@momo-kits/calendar 0.168.1-beta.18 → 0.168.1-beta.19
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 +20 -15
- package/Day.tsx +4 -2
- package/HeaderControl.tsx +2 -1
- package/LunarService.ts +206 -0
- package/Month.tsx +1 -1
- package/MonthList.tsx +23 -36
- package/TabHeader.tsx +74 -59
- package/Util.ts +101 -2
- package/index.tsx +37 -18
- package/package.json +1 -1
- package/styles.ts +16 -4
- package/types.ts +38 -5
- package/ContainerContext.ts +0 -3
package/CalendarPro.tsx
CHANGED
|
@@ -7,16 +7,18 @@ import React, {
|
|
|
7
7
|
forwardRef,
|
|
8
8
|
useImperativeHandle,
|
|
9
9
|
} from 'react';
|
|
10
|
-
import { ScrollView, View } from 'react-native';
|
|
10
|
+
import { Platform, ScrollView, View } from 'react-native';
|
|
11
11
|
import moment, { Moment } from 'moment';
|
|
12
12
|
import {
|
|
13
13
|
ApplicationContext,
|
|
14
14
|
CheckBox,
|
|
15
|
+
Colors,
|
|
15
16
|
Spacing,
|
|
16
17
|
Text,
|
|
17
18
|
} from '@momo-kits/foundation';
|
|
18
19
|
import MonthList from './MonthList';
|
|
19
20
|
import HeaderControl from './HeaderControl';
|
|
21
|
+
import LunarDateConverter from './LunarDateConverter';
|
|
20
22
|
import Util from './Util';
|
|
21
23
|
import {
|
|
22
24
|
CalendarProProps,
|
|
@@ -25,7 +27,7 @@ import {
|
|
|
25
27
|
MonthListRef,
|
|
26
28
|
Holidays,
|
|
27
29
|
} from './types';
|
|
28
|
-
import { ContainerContext } from './
|
|
30
|
+
import { ContainerContext } from './index';
|
|
29
31
|
import styles from './styles';
|
|
30
32
|
|
|
31
33
|
const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
@@ -51,7 +53,8 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
51
53
|
const { theme, translate } = useContext(ApplicationContext);
|
|
52
54
|
const size = useContext(ContainerContext);
|
|
53
55
|
|
|
54
|
-
const
|
|
56
|
+
const today = useMemo(() => moment(), []);
|
|
57
|
+
const headerRef = useRef<Moment>(today.clone());
|
|
55
58
|
const headerControlRef = useRef<HeaderControlRef>(null);
|
|
56
59
|
const monthListRef = useRef<MonthListRef>(null);
|
|
57
60
|
|
|
@@ -81,6 +84,10 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
81
84
|
const [temp, setTemp] = useState<any[]>([]);
|
|
82
85
|
const [headerKey, setHeaderKey] = useState<string>('');
|
|
83
86
|
const [ownUpdate, setOwnUpdate] = useState<boolean>(false);
|
|
87
|
+
const converter: any = useMemo(
|
|
88
|
+
() => (new LunarDateConverter()),
|
|
89
|
+
[],
|
|
90
|
+
);
|
|
84
91
|
|
|
85
92
|
useImperativeHandle(ref, () => ({
|
|
86
93
|
setDoubleDateAndTabIndex: (
|
|
@@ -92,6 +99,11 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
92
99
|
if (firstDate) setStartDate(firstDate);
|
|
93
100
|
if (secondDate !== undefined) setEndDate(secondDate);
|
|
94
101
|
},
|
|
102
|
+
setDateRange: (dateRange: { startDate: any; endDate: any }) => {
|
|
103
|
+
if (monthListRef.current && dateRange.startDate) {
|
|
104
|
+
monthListRef.current.scrollToMonth(moment(dateRange.startDate));
|
|
105
|
+
}
|
|
106
|
+
},
|
|
95
107
|
}));
|
|
96
108
|
|
|
97
109
|
// Sync showLunar prop
|
|
@@ -193,12 +205,7 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
193
205
|
}
|
|
194
206
|
|
|
195
207
|
return (
|
|
196
|
-
<View
|
|
197
|
-
style={[
|
|
198
|
-
styles.container,
|
|
199
|
-
{ backgroundColor: theme.colors.background.surface },
|
|
200
|
-
]}
|
|
201
|
-
>
|
|
208
|
+
<View style={styles.container}>
|
|
202
209
|
<HeaderControl
|
|
203
210
|
ref={headerControlRef}
|
|
204
211
|
selectedDate={propSelectedDate}
|
|
@@ -211,15 +218,11 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
211
218
|
{[1, 2, 3, 4, 5, 6, 7].map(dayIdx => (
|
|
212
219
|
<Text
|
|
213
220
|
key={dayIdx}
|
|
214
|
-
color={
|
|
215
|
-
dayIdx >= 6
|
|
216
|
-
? theme.colors.error.primary
|
|
217
|
-
: theme.colors.text.default
|
|
218
|
-
}
|
|
221
|
+
color={dayIdx >= 6 ? Colors.red_03 : Colors.black_17}
|
|
219
222
|
typography="label_s_medium"
|
|
220
223
|
style={[
|
|
221
224
|
styles.textDay,
|
|
222
|
-
{ width: (size.width - Spacing.
|
|
225
|
+
{ width: (size.width - Spacing.M * 2) / 7 },
|
|
223
226
|
]}
|
|
224
227
|
>
|
|
225
228
|
{translate?.(Util.mapWeeKDate(dayIdx))}
|
|
@@ -228,6 +231,7 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
228
231
|
</View>
|
|
229
232
|
<MonthList
|
|
230
233
|
ref={monthListRef}
|
|
234
|
+
today={today}
|
|
231
235
|
minDate={minDate}
|
|
232
236
|
maxDate={maxDate}
|
|
233
237
|
startDate={startDate!}
|
|
@@ -237,6 +241,7 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
237
241
|
isShowLunar={!isOffLunar && showLunar}
|
|
238
242
|
isDoubleDateMode={isDoubleDateMode}
|
|
239
243
|
tabSelected={tabSelected}
|
|
244
|
+
lunarConverter={converter}
|
|
240
245
|
holidays={holidays}
|
|
241
246
|
selectedDate={propSelectedDate}
|
|
242
247
|
priceList={priceListFormat}
|
package/Day.tsx
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
exportFontFamily,
|
|
10
10
|
} from '@momo-kits/foundation';
|
|
11
11
|
import { DayProps } from './types';
|
|
12
|
-
import { ContainerContext } from './
|
|
12
|
+
import { ContainerContext } from './index';
|
|
13
13
|
import styles from './styles';
|
|
14
14
|
|
|
15
15
|
const Day: React.FC<DayProps> = props => {
|
|
@@ -36,12 +36,13 @@ const Day: React.FC<DayProps> = props => {
|
|
|
36
36
|
|
|
37
37
|
const { theme } = useContext(ApplicationContext);
|
|
38
38
|
const size = useContext(ContainerContext);
|
|
39
|
+
const scaledHeight = useScaleSize(48);
|
|
39
40
|
const scaledSpacing = useScaleSize(Spacing.XS);
|
|
40
41
|
const scaledFontSize = useScaleSize(8);
|
|
41
42
|
const scaledLineHeight = useScaleSize(12);
|
|
42
43
|
const lunarFontFamily = exportFontFamily('regular');
|
|
43
44
|
|
|
44
|
-
const itemWidth = (size.width - Spacing.
|
|
45
|
+
const itemWidth = (size.width - Spacing.M) / 7;
|
|
45
46
|
if (isEmpty || !date) {
|
|
46
47
|
return <View style={[styles.dayContainer, { width: itemWidth }]} />;
|
|
47
48
|
}
|
|
@@ -113,6 +114,7 @@ const Day: React.FC<DayProps> = props => {
|
|
|
113
114
|
paddingVertical: !!price ? Spacing.XS : Spacing.S,
|
|
114
115
|
},
|
|
115
116
|
(isStart || isEnd) && { backgroundColor: theme.colors.primary },
|
|
117
|
+
!!price && { height: scaledHeight },
|
|
116
118
|
{ height: size.height },
|
|
117
119
|
]}
|
|
118
120
|
disabled={!(isValid && isInScope)}
|
package/HeaderControl.tsx
CHANGED
|
@@ -7,6 +7,7 @@ import React, {
|
|
|
7
7
|
} from 'react';
|
|
8
8
|
import {TouchableOpacity, View} from 'react-native';
|
|
9
9
|
import moment from 'moment';
|
|
10
|
+
import Moment from 'moment';
|
|
10
11
|
import {ApplicationContext, Icon, Text} from '@momo-kits/foundation';
|
|
11
12
|
|
|
12
13
|
import Util from './Util';
|
|
@@ -18,7 +19,7 @@ const HeaderControl: ForwardRefRenderFunction<
|
|
|
18
19
|
HeaderControlProps
|
|
19
20
|
> = ({onPressBackArrow, onPressNextArrow, selectedDate}, ref) => {
|
|
20
21
|
const {translate} = useContext(ApplicationContext);
|
|
21
|
-
const [info, setInfo] = useState<{date:
|
|
22
|
+
const [info, setInfo] = useState<{date: Moment.Moment}>({
|
|
22
23
|
date: moment(selectedDate || new Date()),
|
|
23
24
|
});
|
|
24
25
|
|
package/LunarService.ts
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
const removeFractionalPart = (number: string | number) =>
|
|
2
|
+
parseInt(String(number));
|
|
3
|
+
|
|
4
|
+
/* Compute the (integral) Julian day number of day dd/mm/yyyy, i.e., the number
|
|
5
|
+
* of days between 1/1/4713 BC (Julian calendar) and dd/mm/yyyy.
|
|
6
|
+
* Formula from http://www.tondering.dk/claus/calendar.html
|
|
7
|
+
*/
|
|
8
|
+
const jdFromDate = (dd: number, mm: number, yy: number) => {
|
|
9
|
+
let a, y, m, jd;
|
|
10
|
+
a = removeFractionalPart((14 - mm) / 12);
|
|
11
|
+
y = yy + 4800 - a;
|
|
12
|
+
m = mm + 12 * a - 3;
|
|
13
|
+
jd =
|
|
14
|
+
dd +
|
|
15
|
+
removeFractionalPart((153 * m + 2) / 5) +
|
|
16
|
+
365 * y +
|
|
17
|
+
removeFractionalPart(y / 4) -
|
|
18
|
+
removeFractionalPart(y / 100) +
|
|
19
|
+
removeFractionalPart(y / 400) -
|
|
20
|
+
32045;
|
|
21
|
+
if (jd < 2299161) {
|
|
22
|
+
jd =
|
|
23
|
+
dd +
|
|
24
|
+
removeFractionalPart((153 * m + 2) / 5) +
|
|
25
|
+
365 * y +
|
|
26
|
+
removeFractionalPart(y / 4) -
|
|
27
|
+
32083;
|
|
28
|
+
}
|
|
29
|
+
return jd;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/* Compute the time of the k-th new moon after the new moon of 1/1/1900 13:52 UCT
|
|
33
|
+
* (measured as the number of days since 1/1/4713 BC noon UCT, e.g., 2451545.125 is 1/1/2000 15:00 UTC).
|
|
34
|
+
* Returns a floating number, e.g., 2415079.9758617813 for k=2 or 2414961.935157746 for k=-2
|
|
35
|
+
* Algorithm from: "Astronomical Algorithms" by Jean Meeus, 1998
|
|
36
|
+
*/
|
|
37
|
+
const NewMoon = (k: number) => {
|
|
38
|
+
let T, T2, T3, dr, Jd1, M, Mpr, F, C1, deltat, JdNew;
|
|
39
|
+
T = k / 1236.85; // Time in Julian centuries from 1900 January 0.5
|
|
40
|
+
T2 = T * T;
|
|
41
|
+
T3 = T2 * T;
|
|
42
|
+
dr = Math.PI / 180;
|
|
43
|
+
Jd1 = 2415020.75933 + 29.53058868 * k + 0.0001178 * T2 - 0.000000155 * T3;
|
|
44
|
+
Jd1 = Jd1 + 0.00033 * Math.sin((166.56 + 132.87 * T - 0.009173 * T2) * dr); // Mean new moon
|
|
45
|
+
M = 359.2242 + 29.10535608 * k - 0.0000333 * T2 - 0.00000347 * T3; // Sun's mean anomaly
|
|
46
|
+
Mpr = 306.0253 + 385.81691806 * k + 0.0107306 * T2 + 0.00001236 * T3; // Moon's mean anomaly
|
|
47
|
+
F = 21.2964 + 390.67050646 * k - 0.0016528 * T2 - 0.00000239 * T3; // Moon's argument of latitude
|
|
48
|
+
C1 =
|
|
49
|
+
(0.1734 - 0.000393 * T) * Math.sin(M * dr) + 0.0021 * Math.sin(2 * dr * M);
|
|
50
|
+
C1 = C1 - 0.4068 * Math.sin(Mpr * dr) + 0.0161 * Math.sin(dr * 2 * Mpr);
|
|
51
|
+
C1 = C1 - 0.0004 * Math.sin(dr * 3 * Mpr);
|
|
52
|
+
C1 = C1 + 0.0104 * Math.sin(dr * 2 * F) - 0.0051 * Math.sin(dr * (M + Mpr));
|
|
53
|
+
C1 =
|
|
54
|
+
C1 -
|
|
55
|
+
0.0074 * Math.sin(dr * (M - Mpr)) +
|
|
56
|
+
0.0004 * Math.sin(dr * (2 * F + M));
|
|
57
|
+
C1 =
|
|
58
|
+
C1 -
|
|
59
|
+
0.0004 * Math.sin(dr * (2 * F - M)) -
|
|
60
|
+
0.0006 * Math.sin(dr * (2 * F + Mpr));
|
|
61
|
+
C1 =
|
|
62
|
+
C1 +
|
|
63
|
+
0.001 * Math.sin(dr * (2 * F - Mpr)) +
|
|
64
|
+
0.0005 * Math.sin(dr * (2 * Mpr + M));
|
|
65
|
+
if (T < -11) {
|
|
66
|
+
deltat =
|
|
67
|
+
0.001 +
|
|
68
|
+
0.000839 * T +
|
|
69
|
+
0.0002261 * T2 -
|
|
70
|
+
0.00000845 * T3 -
|
|
71
|
+
0.000000081 * T * T3;
|
|
72
|
+
} else {
|
|
73
|
+
deltat = -0.000278 + 0.000265 * T + 0.000262 * T2;
|
|
74
|
+
}
|
|
75
|
+
JdNew = Jd1 + C1 - deltat;
|
|
76
|
+
return JdNew;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
/* Compute the longitude of the sun at any time.
|
|
80
|
+
* Parameter: floating number jdn, the number of days since 1/1/4713 BC noon
|
|
81
|
+
* Algorithm from: "Astronomical Algorithms" by Jean Meeus, 1998
|
|
82
|
+
*/
|
|
83
|
+
const SunLongitude = (jdn: number) => {
|
|
84
|
+
let T, T2, dr, M, L0, DL, L;
|
|
85
|
+
T = (jdn - 2451545.0) / 36525; // Time in Julian centuries from 2000-01-01 12:00:00 GMT
|
|
86
|
+
T2 = T * T;
|
|
87
|
+
dr = Math.PI / 180; // degree to radian
|
|
88
|
+
M = 357.5291 + 35999.0503 * T - 0.0001559 * T2 - 0.00000048 * T * T2; // mean anomaly, degree
|
|
89
|
+
L0 = 280.46645 + 36000.76983 * T + 0.0003032 * T2; // mean longitude, degree
|
|
90
|
+
DL = (1.9146 - 0.004817 * T - 0.000014 * T2) * Math.sin(dr * M);
|
|
91
|
+
DL =
|
|
92
|
+
DL +
|
|
93
|
+
(0.019993 - 0.000101 * T) * Math.sin(dr * 2 * M) +
|
|
94
|
+
0.00029 * Math.sin(dr * 3 * M);
|
|
95
|
+
L = L0 + DL; // true longitude, degree
|
|
96
|
+
L = L * dr;
|
|
97
|
+
L = L - Math.PI * 2 * Math.sin(L / (Math.PI * 2)); // Normalize to (0, 2*PI)
|
|
98
|
+
return L;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
/* Compute sun position at midnight of the day with the given Julian day number.
|
|
102
|
+
* The time zone if the time difference between local time and UTC: 7.0 for UTC+7:00.
|
|
103
|
+
* The returns a number between 0 and 11.
|
|
104
|
+
* From the day after March equinox and the 1st major term after March equinox, 0 is returned.
|
|
105
|
+
* After that, return 1, 2, 3 ...
|
|
106
|
+
*/
|
|
107
|
+
const getSunLongitude = (dayNumber: number, timeZone: number) => {
|
|
108
|
+
return removeFractionalPart(
|
|
109
|
+
(SunLongitude(dayNumber - 0.5 - timeZone / 24) / Math.PI) * 6
|
|
110
|
+
);
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/* Compute the day of the k-th new moon in the given time zone.
|
|
114
|
+
* The time zone if the time difference between local time and UTC: 7.0 for UTC+7:00
|
|
115
|
+
*/
|
|
116
|
+
const getNewMoonDay = (k: number, timeZone: number) => {
|
|
117
|
+
return removeFractionalPart(NewMoon(k) + 0.5 + timeZone / 24);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/* Find the day that starts the luner month 11 of the given year for the given time zone */
|
|
121
|
+
const getLunarMonth11 = (yy: number, timeZone: number) => {
|
|
122
|
+
let k, off, nm, sunLong;
|
|
123
|
+
//off = jdFromDate(31, 12, yy) - 2415021.076998695;
|
|
124
|
+
off = jdFromDate(31, 12, yy) - 2415021;
|
|
125
|
+
k = removeFractionalPart(off / 29.530588853);
|
|
126
|
+
nm = getNewMoonDay(k, timeZone);
|
|
127
|
+
sunLong = getSunLongitude(nm, timeZone); // sun longitude at local midnight
|
|
128
|
+
if (sunLong >= 9) {
|
|
129
|
+
nm = getNewMoonDay(k - 1, timeZone);
|
|
130
|
+
}
|
|
131
|
+
return nm;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
/* Find the index of the leap month after the month starting on the day a11. */
|
|
135
|
+
const getLeapMonthOffset = (a11: number, timeZone: number) => {
|
|
136
|
+
let k, last, arc, i;
|
|
137
|
+
k = removeFractionalPart((a11 - 2415021.076998695) / 29.530588853 + 0.5);
|
|
138
|
+
last = 0;
|
|
139
|
+
i = 1; // We start with the month following lunar month 11
|
|
140
|
+
arc = getSunLongitude(getNewMoonDay(k + i, timeZone), timeZone);
|
|
141
|
+
do {
|
|
142
|
+
last = arc;
|
|
143
|
+
i++;
|
|
144
|
+
arc = getSunLongitude(getNewMoonDay(k + i, timeZone), timeZone);
|
|
145
|
+
} while (arc !== last && i < 14);
|
|
146
|
+
return i - 1;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
/* Comvert solar date dd/mm/yyyy to the corresponding lunar date */
|
|
150
|
+
export const convertSolar2Lunar = (
|
|
151
|
+
dd: number,
|
|
152
|
+
mm: number,
|
|
153
|
+
yy: number,
|
|
154
|
+
timeZone: number
|
|
155
|
+
) => {
|
|
156
|
+
let k,
|
|
157
|
+
dayNumber,
|
|
158
|
+
monthStart,
|
|
159
|
+
a11,
|
|
160
|
+
b11,
|
|
161
|
+
lunarDay,
|
|
162
|
+
lunarMonth,
|
|
163
|
+
lunarYear,
|
|
164
|
+
lunarLeap;
|
|
165
|
+
dayNumber = jdFromDate(dd, mm, yy);
|
|
166
|
+
k = removeFractionalPart((dayNumber - 2415021.076998695) / 29.530588853);
|
|
167
|
+
monthStart = getNewMoonDay(k + 1, timeZone);
|
|
168
|
+
if (monthStart > dayNumber) {
|
|
169
|
+
monthStart = getNewMoonDay(k, timeZone);
|
|
170
|
+
}
|
|
171
|
+
//alert(dayNumber+" -> "+monthStart);
|
|
172
|
+
a11 = getLunarMonth11(yy, timeZone);
|
|
173
|
+
b11 = a11;
|
|
174
|
+
if (a11 >= monthStart) {
|
|
175
|
+
lunarYear = yy;
|
|
176
|
+
a11 = getLunarMonth11(yy - 1, timeZone);
|
|
177
|
+
} else {
|
|
178
|
+
lunarYear = yy + 1;
|
|
179
|
+
b11 = getLunarMonth11(yy + 1, timeZone);
|
|
180
|
+
}
|
|
181
|
+
lunarDay = dayNumber - monthStart + 1;
|
|
182
|
+
let diff = removeFractionalPart((monthStart - a11) / 29);
|
|
183
|
+
lunarLeap = 0;
|
|
184
|
+
lunarMonth = diff + 10;
|
|
185
|
+
if (b11 - a11 > 365) {
|
|
186
|
+
let leapMonthDiff = getLeapMonthOffset(a11, timeZone);
|
|
187
|
+
if (diff >= leapMonthDiff) {
|
|
188
|
+
lunarMonth = diff + 10;
|
|
189
|
+
if (diff === leapMonthDiff) {
|
|
190
|
+
lunarLeap = 1;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (lunarMonth > 12) {
|
|
195
|
+
lunarMonth = lunarMonth - 12;
|
|
196
|
+
}
|
|
197
|
+
if (lunarMonth >= 11 && diff < 4) {
|
|
198
|
+
lunarYear -= 1;
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
lunarDay,
|
|
202
|
+
lunarMonth: lunarMonth,
|
|
203
|
+
lunarYear,
|
|
204
|
+
isleap: lunarLeap,
|
|
205
|
+
};
|
|
206
|
+
};
|
package/Month.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import moment, {Moment} from 'moment';
|
|
|
4
4
|
import Day from './Day';
|
|
5
5
|
import {useScaleSize, Spacing} from '@momo-kits/foundation';
|
|
6
6
|
import {MonthProps} from './types';
|
|
7
|
-
import {ContainerContext} from './
|
|
7
|
+
import {ContainerContext} from './index';
|
|
8
8
|
|
|
9
9
|
const Month: React.FC<MonthProps> = ({
|
|
10
10
|
dateList,
|
package/MonthList.tsx
CHANGED
|
@@ -5,6 +5,7 @@ import React, {
|
|
|
5
5
|
useImperativeHandle,
|
|
6
6
|
useCallback,
|
|
7
7
|
useContext,
|
|
8
|
+
useEffect,
|
|
8
9
|
useLayoutEffect,
|
|
9
10
|
useMemo,
|
|
10
11
|
useRef,
|
|
@@ -16,7 +17,7 @@ import {
|
|
|
16
17
|
NativeSyntheticEvent,
|
|
17
18
|
Platform,
|
|
18
19
|
} from 'react-native';
|
|
19
|
-
import { ContainerContext } from './
|
|
20
|
+
import { ContainerContext } from './index';
|
|
20
21
|
import LunarDateConverter from './LunarDateConverter';
|
|
21
22
|
import Month from './Month';
|
|
22
23
|
import { MonthListProps, MonthListRef } from './types';
|
|
@@ -38,22 +39,15 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
38
39
|
isShowLunar,
|
|
39
40
|
isDoubleDateMode,
|
|
40
41
|
disabledDays,
|
|
41
|
-
tabSelected,
|
|
42
|
-
onChoose,
|
|
43
|
-
bestPriceColor,
|
|
44
42
|
onScrollCalendar,
|
|
43
|
+
...restProps
|
|
45
44
|
} = props;
|
|
46
45
|
|
|
47
46
|
const size = useContext(ContainerContext);
|
|
48
47
|
const scaledHeight48 = useScaleSize(48);
|
|
49
48
|
const listRef = useRef<FlatList>(null);
|
|
50
49
|
const currentKey = useRef<string | null>(null);
|
|
51
|
-
const targetIndex = useRef<number | null>(null);
|
|
52
50
|
const [heightStyle, setHeightStyle] = useState({});
|
|
53
|
-
const onScrollCalendarRef = useRef(onScrollCalendar);
|
|
54
|
-
onScrollCalendarRef.current = onScrollCalendar;
|
|
55
|
-
const scaledHeight48Ref = useRef(scaledHeight48);
|
|
56
|
-
scaledHeight48Ref.current = scaledHeight48;
|
|
57
51
|
|
|
58
52
|
const data = useMemo(() => {
|
|
59
53
|
const months: { date: Moment; dateList: any[] }[] = [];
|
|
@@ -75,6 +69,9 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
75
69
|
}
|
|
76
70
|
while (cursor.month() === monthIdx) {
|
|
77
71
|
const cloned = cursor.clone();
|
|
72
|
+
const hol = holidays.find(
|
|
73
|
+
h => h.day === cloned.date() && h.month === cloned.month() + 1,
|
|
74
|
+
);
|
|
78
75
|
dayList.push({
|
|
79
76
|
isEmpty: false,
|
|
80
77
|
date: cloned,
|
|
@@ -83,6 +80,8 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
83
80
|
solarMonth: cloned.month() + 1,
|
|
84
81
|
solarYear: cloned.year(),
|
|
85
82
|
}),
|
|
83
|
+
isSolarHoliday: !!(hol && !hol.lunar),
|
|
84
|
+
isLunarHoliday: !!(hol && hol.lunar),
|
|
86
85
|
});
|
|
87
86
|
cursor.add(1, 'days');
|
|
88
87
|
}
|
|
@@ -97,7 +96,7 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
97
96
|
mMin.add(1, 'month');
|
|
98
97
|
}
|
|
99
98
|
return months;
|
|
100
|
-
}, [minDate, maxDate]);
|
|
99
|
+
}, [minDate, maxDate, holidays]);
|
|
101
100
|
|
|
102
101
|
const getIndexOfMonth = useCallback(
|
|
103
102
|
(date: Moment) => data.findIndex(item => item.date.isSame(date, 'month')),
|
|
@@ -139,9 +138,6 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
139
138
|
(month: Moment) => {
|
|
140
139
|
const idx = getIndexOfMonth(month);
|
|
141
140
|
if (listRef.current && idx !== -1) {
|
|
142
|
-
const offset = idx * pageWidth.current;
|
|
143
|
-
targetIndex.current =
|
|
144
|
-
Math.abs(offset - scrollOffset.current) < 1 ? null : idx;
|
|
145
141
|
listRef.current.scrollToIndex({ index: idx, animated: true });
|
|
146
142
|
}
|
|
147
143
|
},
|
|
@@ -150,31 +146,29 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
150
146
|
|
|
151
147
|
useImperativeHandle(ref, () => ({ scrollToMonth }));
|
|
152
148
|
|
|
149
|
+
useEffect(() => {
|
|
150
|
+
const timer = setTimeout(() => {
|
|
151
|
+
scrollToMonth(selectedDate);
|
|
152
|
+
}, 500);
|
|
153
|
+
return () => clearTimeout(timer);
|
|
154
|
+
}, []);
|
|
155
|
+
|
|
153
156
|
const onViewableItemsChanged = useRef(({ changed }: { changed: any[] }) => {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
targetIndex.current = null;
|
|
159
|
-
if (visible) {
|
|
160
|
-
const { item, key, index } = visible;
|
|
161
|
-
if (onScrollCalendarRef.current && item && currentKey.current !== key) {
|
|
157
|
+
if (changed.length > 0) {
|
|
158
|
+
const { item, key, index } = changed[0];
|
|
159
|
+
if (onScrollCalendar && item && currentKey.current !== key) {
|
|
162
160
|
currentKey.current = key;
|
|
163
161
|
try {
|
|
164
162
|
setHeightStyle({
|
|
165
163
|
height:
|
|
166
|
-
(
|
|
164
|
+
(scaledHeight48 * item.dateList.length) / 7 +
|
|
167
165
|
Spacing.L * 2 +
|
|
168
166
|
Spacing.XS,
|
|
169
167
|
});
|
|
170
168
|
} catch {
|
|
171
169
|
setHeightStyle({});
|
|
172
170
|
}
|
|
173
|
-
|
|
174
|
-
date: item.date,
|
|
175
|
-
key,
|
|
176
|
-
currentIndex: index,
|
|
177
|
-
});
|
|
171
|
+
onScrollCalendar({ date: item.date, key, currentIndex: index });
|
|
178
172
|
}
|
|
179
173
|
}
|
|
180
174
|
}).current;
|
|
@@ -207,6 +201,7 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
207
201
|
const priceListDate = priceList?.[keyMonth]?.day;
|
|
208
202
|
return (
|
|
209
203
|
<Month
|
|
204
|
+
{...restProps}
|
|
210
205
|
key={index}
|
|
211
206
|
month={item.date}
|
|
212
207
|
dateList={item.dateList}
|
|
@@ -219,13 +214,11 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
219
214
|
isShowLunar={isShowLunar}
|
|
220
215
|
isDoubleDateMode={isDoubleDateMode}
|
|
221
216
|
disabledDays={disabledDays}
|
|
222
|
-
tabSelected={tabSelected}
|
|
223
|
-
onChoose={onChoose}
|
|
224
|
-
bestPriceColor={bestPriceColor}
|
|
225
217
|
/>
|
|
226
218
|
);
|
|
227
219
|
},
|
|
228
220
|
[
|
|
221
|
+
restProps,
|
|
229
222
|
priceList,
|
|
230
223
|
holidays,
|
|
231
224
|
minDate,
|
|
@@ -235,9 +228,6 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
235
228
|
isShowLunar,
|
|
236
229
|
isDoubleDateMode,
|
|
237
230
|
disabledDays,
|
|
238
|
-
tabSelected,
|
|
239
|
-
onChoose,
|
|
240
|
-
bestPriceColor,
|
|
241
231
|
],
|
|
242
232
|
);
|
|
243
233
|
|
|
@@ -254,9 +244,6 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
254
244
|
keyExtractor={keyExtractor}
|
|
255
245
|
onScrollToIndexFailed={() => {}}
|
|
256
246
|
onScroll={onScroll}
|
|
257
|
-
onScrollBeginDrag={() => {
|
|
258
|
-
targetIndex.current = null;
|
|
259
|
-
}}
|
|
260
247
|
scrollEnabled
|
|
261
248
|
initialNumToRender={3}
|
|
262
249
|
maxToRenderPerBatch={MAX_RENDER_PER_BATCH}
|
package/TabHeader.tsx
CHANGED
|
@@ -1,73 +1,88 @@
|
|
|
1
|
-
import React
|
|
2
|
-
|
|
3
|
-
useContext,
|
|
4
|
-
useImperativeHandle,
|
|
5
|
-
useState,
|
|
6
|
-
} from 'react';
|
|
7
|
-
import { TouchableWithoutFeedback, View } from 'react-native';
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {TouchableWithoutFeedback, View} from 'react-native';
|
|
8
3
|
import Moment from 'moment';
|
|
9
4
|
import Util from './Util';
|
|
10
5
|
import {
|
|
11
6
|
ApplicationContext,
|
|
7
|
+
Colors,
|
|
12
8
|
Radius,
|
|
13
9
|
Spacing,
|
|
14
10
|
Text,
|
|
15
11
|
} from '@momo-kits/foundation';
|
|
16
|
-
import {
|
|
12
|
+
import {TabHeaderProps, TabHeaderState} from './types';
|
|
17
13
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
14
|
+
export default class TabHeader extends React.Component<
|
|
15
|
+
TabHeaderProps,
|
|
16
|
+
TabHeaderState
|
|
17
|
+
> {
|
|
18
|
+
static contextType = ApplicationContext;
|
|
19
|
+
context: React.ContextType<typeof ApplicationContext> = {} as React.ContextType<typeof ApplicationContext>;
|
|
20
|
+
label;
|
|
21
|
+
defaultDate: Moment.Moment | null;
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
23
|
+
constructor(props: TabHeaderProps) {
|
|
24
|
+
super(props);
|
|
25
|
+
this.state = {
|
|
26
|
+
active: props.activeTab,
|
|
27
|
+
};
|
|
28
|
+
this.label = props.label;
|
|
29
|
+
this.defaultDate = props.date ? Moment(props.date) : null;
|
|
30
|
+
}
|
|
33
31
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
onChangeTab = () => {
|
|
33
|
+
const {onChangeTab, id} = this.props;
|
|
34
|
+
onChangeTab?.(id);
|
|
35
|
+
};
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
updateView = (date?: Moment.Moment | Date | null, activeTab?: boolean) => {
|
|
38
|
+
this.setState({
|
|
39
|
+
date: date ? Moment(date) : undefined,
|
|
40
|
+
active: activeTab,
|
|
41
|
+
});
|
|
42
|
+
};
|
|
40
43
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
onPress={() => onChangeTab?.(id)}
|
|
45
|
-
>
|
|
46
|
-
<View
|
|
47
|
-
style={[
|
|
48
|
-
{
|
|
49
|
-
flex: 1,
|
|
50
|
-
padding: Spacing.S,
|
|
51
|
-
borderRadius: Radius.S,
|
|
52
|
-
},
|
|
53
|
-
isHighlighted && {
|
|
54
|
-
backgroundColor: theme.colors.background.surface,
|
|
55
|
-
},
|
|
56
|
-
]}
|
|
57
|
-
>
|
|
58
|
-
<Text
|
|
59
|
-
typography={'description_default_regular'}
|
|
60
|
-
color={theme.colors.text.hint}
|
|
61
|
-
>
|
|
62
|
-
{translate?.(label)}
|
|
63
|
-
</Text>
|
|
64
|
-
<Text typography={'header_s_semibold'}>
|
|
65
|
-
{`${dayOfWeek || '--'} `}
|
|
66
|
-
{formattedDate || '--/--/----'}
|
|
67
|
-
</Text>
|
|
68
|
-
</View>
|
|
69
|
-
</TouchableWithoutFeedback>
|
|
70
|
-
);
|
|
71
|
-
});
|
|
44
|
+
setActiveTab = (active: boolean) => {
|
|
45
|
+
this.setState({active});
|
|
46
|
+
};
|
|
72
47
|
|
|
73
|
-
|
|
48
|
+
render() {
|
|
49
|
+
const {label, disabled} = this.props;
|
|
50
|
+
const {date, active} = this.state;
|
|
51
|
+
const {theme, translate} = this.context;
|
|
52
|
+
const defaultDate = this.defaultDate;
|
|
53
|
+
const weekday = (day: Moment.Moment) =>
|
|
54
|
+
translate?.(Util.WEEKDAYSFROMMOMENT[day.day()]);
|
|
55
|
+
const isHighlighted = active && !disabled;
|
|
56
|
+
|
|
57
|
+
const formattedDateFromState = date ? date.format('DD/MM/YYYY') : '';
|
|
58
|
+
const formattedDateFromDefault = defaultDate?.format('DD/MM/YYYY') ?? '';
|
|
59
|
+
const dayOfWeekFromState = date ? `${weekday(date)}, ` : '';
|
|
60
|
+
const dayOfWeekFromDefault = defaultDate ? `${weekday(defaultDate)},` : '';
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<TouchableWithoutFeedback disabled={disabled} onPress={this.onChangeTab}>
|
|
64
|
+
<View
|
|
65
|
+
style={[
|
|
66
|
+
{
|
|
67
|
+
flex: 1,
|
|
68
|
+
padding: Spacing.S,
|
|
69
|
+
borderRadius: Radius.S,
|
|
70
|
+
},
|
|
71
|
+
isHighlighted && {
|
|
72
|
+
backgroundColor: theme.colors.background.surface,
|
|
73
|
+
},
|
|
74
|
+
]}>
|
|
75
|
+
<Text
|
|
76
|
+
typography={'description_default_regular'}
|
|
77
|
+
color={Colors.black_12}>
|
|
78
|
+
{translate?.(label)}
|
|
79
|
+
</Text>
|
|
80
|
+
<Text typography={'header_s_semibold'}>
|
|
81
|
+
{`${dayOfWeekFromState || dayOfWeekFromDefault || '--'} `}
|
|
82
|
+
{formattedDateFromState || formattedDateFromDefault || '--/--/----'}
|
|
83
|
+
</Text>
|
|
84
|
+
</View>
|
|
85
|
+
</TouchableWithoutFeedback>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
}
|
package/Util.ts
CHANGED
|
@@ -3,8 +3,50 @@ import LunarDateConverter from './LunarDateConverter';
|
|
|
3
3
|
import holiday from './holidayData';
|
|
4
4
|
import {Holidays} from './types';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const I18N_MAP = {
|
|
7
|
+
en: {
|
|
8
|
+
w: ['', 'Mon', 'Tues', 'Wed', 'Thur', 'Fri', 'Sat', 'Sun'],
|
|
9
|
+
weekday: [
|
|
10
|
+
'',
|
|
11
|
+
'Monday',
|
|
12
|
+
'Tuesday',
|
|
13
|
+
'Wednesday',
|
|
14
|
+
'Thursday',
|
|
15
|
+
'Friday',
|
|
16
|
+
'Saturday',
|
|
17
|
+
'Sunday',
|
|
18
|
+
],
|
|
19
|
+
text: {
|
|
20
|
+
start: 'Start',
|
|
21
|
+
end: 'End',
|
|
22
|
+
date: 'Date',
|
|
23
|
+
save: 'Save',
|
|
24
|
+
clear: 'Reset',
|
|
25
|
+
},
|
|
26
|
+
date: 'DD / MM',
|
|
27
|
+
},
|
|
28
|
+
vi: {
|
|
29
|
+
w: ['', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7', 'CN'],
|
|
30
|
+
weekday: [
|
|
31
|
+
'',
|
|
32
|
+
'Thứ hai',
|
|
33
|
+
'Thứ ba',
|
|
34
|
+
'Thứ tư',
|
|
35
|
+
'Thứ năm',
|
|
36
|
+
'Thứ sáu',
|
|
37
|
+
'Thứ bảy',
|
|
38
|
+
'Chủ nhật',
|
|
39
|
+
],
|
|
40
|
+
text: {
|
|
41
|
+
start: 'Start',
|
|
42
|
+
end: 'End',
|
|
43
|
+
date: 'Date',
|
|
44
|
+
save: 'Save',
|
|
45
|
+
clear: 'Reset',
|
|
46
|
+
},
|
|
47
|
+
date: 'DD / MM',
|
|
48
|
+
},
|
|
49
|
+
};
|
|
8
50
|
|
|
9
51
|
const Solar = (momentDate: moment.Moment) => ({
|
|
10
52
|
solarDay: momentDate.date(),
|
|
@@ -64,8 +106,39 @@ const sortByDate = (arr: Holidays[]): Holidays[] => {
|
|
|
64
106
|
};
|
|
65
107
|
|
|
66
108
|
const Utils = {
|
|
109
|
+
WEEKDAYS: ['T2', 'T3', 'T4', 'T5', 'T6', 'T7', 'CN'],
|
|
110
|
+
|
|
67
111
|
WEEKDAYSFROMMOMENT: ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'],
|
|
68
112
|
|
|
113
|
+
WEEKDAYSNAME: [
|
|
114
|
+
'Thứ 2',
|
|
115
|
+
'Thứ 3',
|
|
116
|
+
'Thứ 4',
|
|
117
|
+
'Thứ 5',
|
|
118
|
+
'Thứ 6',
|
|
119
|
+
'Thứ 7',
|
|
120
|
+
'Chủ nhật',
|
|
121
|
+
],
|
|
122
|
+
|
|
123
|
+
MONTHS: [
|
|
124
|
+
'Tháng 1',
|
|
125
|
+
'Tháng 2',
|
|
126
|
+
'Tháng 3',
|
|
127
|
+
'Tháng 4',
|
|
128
|
+
'Tháng 5',
|
|
129
|
+
'Tháng 6',
|
|
130
|
+
'Tháng 7',
|
|
131
|
+
'Tháng 8',
|
|
132
|
+
'Tháng 9',
|
|
133
|
+
'Tháng 10',
|
|
134
|
+
'Tháng 11',
|
|
135
|
+
'Tháng 12',
|
|
136
|
+
],
|
|
137
|
+
|
|
138
|
+
MAX_ROWS: 7,
|
|
139
|
+
|
|
140
|
+
MAX_COLUMNS: 7,
|
|
141
|
+
|
|
69
142
|
mapWeeKDate(i: number) {
|
|
70
143
|
const date = ['', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'];
|
|
71
144
|
return date[i];
|
|
@@ -89,11 +162,36 @@ const Utils = {
|
|
|
89
162
|
return month.get(i);
|
|
90
163
|
},
|
|
91
164
|
|
|
165
|
+
mapMonthShorten(i: number) {
|
|
166
|
+
const month = new Map([
|
|
167
|
+
[1, 'Jan'],
|
|
168
|
+
[2, 'Feb'],
|
|
169
|
+
[3, 'Mar'],
|
|
170
|
+
[4, 'Apr'],
|
|
171
|
+
[5, 'May'],
|
|
172
|
+
[6, 'Jun'],
|
|
173
|
+
[7, 'Jul'],
|
|
174
|
+
[8, 'Aug'],
|
|
175
|
+
[9, 'Sep'],
|
|
176
|
+
[10, 'Oct'],
|
|
177
|
+
[11, 'Nov'],
|
|
178
|
+
[12, 'Dec'],
|
|
179
|
+
]);
|
|
180
|
+
return month.get(i);
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
getDaysInMonth(month: number, year: number) {
|
|
184
|
+
const lastDayOfMonth = new Date(year, month + 1, 0);
|
|
185
|
+
return lastDayOfMonth.getDate();
|
|
186
|
+
},
|
|
187
|
+
|
|
92
188
|
/**
|
|
93
189
|
* Get sorted list of holidays within the given month.
|
|
94
190
|
*/
|
|
95
191
|
getHolidaysInMonth(headerInfo: moment.Moment): Holidays[] {
|
|
96
192
|
if (headerInfo) {
|
|
193
|
+
// @ts-ignore
|
|
194
|
+
const converter = new LunarDateConverter();
|
|
97
195
|
const startDate = moment(headerInfo).startOf('month');
|
|
98
196
|
const endDate = moment(headerInfo).endOf('month');
|
|
99
197
|
const minLunarDate = converter.SolarToLunar(Solar(startDate));
|
|
@@ -181,6 +279,7 @@ const Utils = {
|
|
|
181
279
|
}
|
|
182
280
|
return [];
|
|
183
281
|
},
|
|
282
|
+
I18N_MAP,
|
|
184
283
|
};
|
|
185
284
|
|
|
186
285
|
export default Utils;
|
package/index.tsx
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
/* eslint-disable react-hooks/exhaustive-deps */
|
|
2
|
-
import React, {
|
|
2
|
+
import React, {
|
|
3
|
+
useState,
|
|
4
|
+
useRef,
|
|
5
|
+
useEffect,
|
|
6
|
+
useContext,
|
|
7
|
+
createContext,
|
|
8
|
+
} from 'react';
|
|
3
9
|
import { Dimensions, LayoutChangeEvent, View } from 'react-native';
|
|
4
10
|
import moment from 'moment';
|
|
5
11
|
import {
|
|
@@ -12,12 +18,13 @@ import {
|
|
|
12
18
|
} from '@momo-kits/foundation';
|
|
13
19
|
import CalendarPro from './CalendarPro';
|
|
14
20
|
import TabHeader from './TabHeader';
|
|
15
|
-
import { CalendarProps, CalendarProRef
|
|
16
|
-
import { ContainerContext } from './ContainerContext';
|
|
21
|
+
import { CalendarProps, CalendarProRef } from './types';
|
|
17
22
|
import styles from './styles';
|
|
18
23
|
|
|
19
24
|
const DOUBLE = 'doubleDate';
|
|
20
25
|
|
|
26
|
+
export const ContainerContext = createContext({ width: 0, height: 0 });
|
|
27
|
+
|
|
21
28
|
const Calendar: React.FC<CalendarProps> = props => {
|
|
22
29
|
const { translate, theme } = useContext(ApplicationContext);
|
|
23
30
|
const scaledHeight48 = useScaleSize(48);
|
|
@@ -42,6 +49,9 @@ const Calendar: React.FC<CalendarProps> = props => {
|
|
|
42
49
|
isHideHoliday,
|
|
43
50
|
isShowLunar,
|
|
44
51
|
priceList,
|
|
52
|
+
labelFrom,
|
|
53
|
+
labelTo,
|
|
54
|
+
isHideLabel,
|
|
45
55
|
minDate = minDateDefault,
|
|
46
56
|
maxDate = maxDateDefault,
|
|
47
57
|
style,
|
|
@@ -75,9 +85,9 @@ const Calendar: React.FC<CalendarProps> = props => {
|
|
|
75
85
|
|
|
76
86
|
const calendarPicker = useRef<CalendarProRef>(null);
|
|
77
87
|
// hold refs to TabHeader instances
|
|
78
|
-
const cellHeader1 = useRef<
|
|
79
|
-
const cellHeader2 = useRef<
|
|
80
|
-
const cellHeaderSingle = useRef<
|
|
88
|
+
const cellHeader1 = useRef<TabHeader>(null);
|
|
89
|
+
const cellHeader2 = useRef<TabHeader>(null);
|
|
90
|
+
const cellHeaderSingle = useRef<TabHeader>(null);
|
|
81
91
|
|
|
82
92
|
// Initialize view on mount
|
|
83
93
|
useEffect(() => {
|
|
@@ -207,11 +217,18 @@ const Calendar: React.FC<CalendarProps> = props => {
|
|
|
207
217
|
const updateHeaderView = () => {
|
|
208
218
|
const { onDateChange, onCTAStateChange } = props;
|
|
209
219
|
if (isDoubleDateMode) {
|
|
220
|
+
cellHeader1.current?.updateView(selectedDate, true);
|
|
221
|
+
cellHeader2.current?.updateView(null, false);
|
|
222
|
+
calendarPicker.current?.setDoubleDateAndTabIndex(
|
|
223
|
+
selectedDate,
|
|
224
|
+
null,
|
|
225
|
+
tabSelected.current,
|
|
226
|
+
);
|
|
210
227
|
doubleDate.current.first = moment(selectedDate);
|
|
211
228
|
doubleDate.current.second = null;
|
|
212
229
|
tabSelected.current = 1;
|
|
213
|
-
|
|
214
|
-
|
|
230
|
+
cellHeader2.current?.setActiveTab(true);
|
|
231
|
+
cellHeader1.current?.setActiveTab(false);
|
|
215
232
|
calendarPicker.current?.setDoubleDateAndTabIndex(
|
|
216
233
|
doubleDate.current.first,
|
|
217
234
|
doubleDate.current.second,
|
|
@@ -220,17 +237,16 @@ const Calendar: React.FC<CalendarProps> = props => {
|
|
|
220
237
|
onCTAStateChange?.(false);
|
|
221
238
|
onDateChange?.({ first: doubleDate.current.first!, second: null });
|
|
222
239
|
} else {
|
|
223
|
-
|
|
240
|
+
// Reset second date when switching to single mode
|
|
224
241
|
doubleDate.current.second = null;
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
cellHeaderSingle.current?.updateView(date, true);
|
|
230
|
-
onDateChange?.(date.toDate());
|
|
242
|
+
props.onCTAStateChange?.(true);
|
|
243
|
+
if (doubleDate.current.first) {
|
|
244
|
+
cellHeaderSingle.current?.updateView(doubleDate.current.first, true);
|
|
245
|
+
setSelectedDate(doubleDate.current.first);
|
|
231
246
|
} else {
|
|
232
|
-
|
|
247
|
+
cellHeaderSingle.current?.updateView(selectedDate, true);
|
|
233
248
|
}
|
|
249
|
+
props.onDateChange?.(selectedDate.toDate());
|
|
234
250
|
}
|
|
235
251
|
};
|
|
236
252
|
|
|
@@ -286,7 +302,7 @@ const Calendar: React.FC<CalendarProps> = props => {
|
|
|
286
302
|
activeTab
|
|
287
303
|
date={doubleDate.current.first}
|
|
288
304
|
/>
|
|
289
|
-
<View style={
|
|
305
|
+
<View style={{ width: 4, height: '100%' }} />
|
|
290
306
|
<TabHeader
|
|
291
307
|
id={1}
|
|
292
308
|
ref={cellHeader2}
|
|
@@ -345,6 +361,9 @@ const Calendar: React.FC<CalendarProps> = props => {
|
|
|
345
361
|
selectedDate={selectedDate}
|
|
346
362
|
isShowLunar={isShowLunar}
|
|
347
363
|
onCallbackCalendar={onCallbackCalendar}
|
|
364
|
+
labelFrom={labelFrom}
|
|
365
|
+
labelTo={labelTo}
|
|
366
|
+
isHideLabel={isHideLabel}
|
|
348
367
|
minDate={minDate}
|
|
349
368
|
maxDate={maxDate}
|
|
350
369
|
isHideHoliday={isHideHoliday}
|
|
@@ -357,4 +376,4 @@ const Calendar: React.FC<CalendarProps> = props => {
|
|
|
357
376
|
);
|
|
358
377
|
};
|
|
359
378
|
|
|
360
|
-
export { Calendar
|
|
379
|
+
export { Calendar };
|
package/package.json
CHANGED
package/styles.ts
CHANGED
|
@@ -16,10 +16,6 @@ export default StyleSheet.create({
|
|
|
16
16
|
alignItems: 'center',
|
|
17
17
|
marginBottom: Spacing.XS,
|
|
18
18
|
},
|
|
19
|
-
tabGap: {
|
|
20
|
-
width: Spacing.XS,
|
|
21
|
-
height: '100%',
|
|
22
|
-
},
|
|
23
19
|
headerContainer: {
|
|
24
20
|
paddingHorizontal: Spacing.M,
|
|
25
21
|
marginTop: Spacing.S,
|
|
@@ -61,6 +57,7 @@ export default StyleSheet.create({
|
|
|
61
57
|
marginTop: Spacing.S,
|
|
62
58
|
},
|
|
63
59
|
container: {
|
|
60
|
+
backgroundColor: 'white',
|
|
64
61
|
borderRadius: Radius.XS,
|
|
65
62
|
},
|
|
66
63
|
blueSeperator: {
|
|
@@ -73,6 +70,18 @@ export default StyleSheet.create({
|
|
|
73
70
|
txtHeader: {
|
|
74
71
|
textAlign: 'center',
|
|
75
72
|
},
|
|
73
|
+
btnRight: {
|
|
74
|
+
width: 36,
|
|
75
|
+
height: 36,
|
|
76
|
+
justifyContent: 'center',
|
|
77
|
+
alignItems: 'center',
|
|
78
|
+
},
|
|
79
|
+
btnLeft: {
|
|
80
|
+
width: 36,
|
|
81
|
+
height: 36,
|
|
82
|
+
justifyContent: 'center',
|
|
83
|
+
alignItems: 'center',
|
|
84
|
+
},
|
|
76
85
|
headerControlContainer: {
|
|
77
86
|
flexDirection: 'row',
|
|
78
87
|
justifyContent: 'space-between',
|
|
@@ -92,6 +101,9 @@ export default StyleSheet.create({
|
|
|
92
101
|
alignItems: 'center',
|
|
93
102
|
borderRadius: Radius.XS,
|
|
94
103
|
},
|
|
104
|
+
dayText: {
|
|
105
|
+
textAlign: 'center',
|
|
106
|
+
},
|
|
95
107
|
dayStartContainer: {
|
|
96
108
|
borderTopLeftRadius: Radius.XS,
|
|
97
109
|
borderBottomLeftRadius: Radius.XS,
|
package/types.ts
CHANGED
|
@@ -42,6 +42,9 @@ export type CalendarProProps = {
|
|
|
42
42
|
isDoubleDateMode: boolean;
|
|
43
43
|
onDateChange: (day: Moment.Moment) => void;
|
|
44
44
|
priceList?: PriceListData;
|
|
45
|
+
labelFrom?: string;
|
|
46
|
+
labelTo?: string;
|
|
47
|
+
isHideLabel?: boolean;
|
|
45
48
|
isHideHoliday?: boolean;
|
|
46
49
|
isOffLunar?: boolean;
|
|
47
50
|
onCallbackCalendar?: (lunar: string, nextStateShowLunar: boolean) => void;
|
|
@@ -49,6 +52,17 @@ export type CalendarProProps = {
|
|
|
49
52
|
bestPriceColor?: string;
|
|
50
53
|
};
|
|
51
54
|
|
|
55
|
+
export type CalendarProState = {
|
|
56
|
+
startDate: Moment.Moment;
|
|
57
|
+
endDate: Moment.Moment;
|
|
58
|
+
showLunar?: boolean;
|
|
59
|
+
tabSelected?: number;
|
|
60
|
+
holidays: Holidays[];
|
|
61
|
+
ownUpdate?: boolean;
|
|
62
|
+
temp?: any;
|
|
63
|
+
headerKey?: string;
|
|
64
|
+
};
|
|
65
|
+
|
|
52
66
|
export type DoubleDate = {
|
|
53
67
|
first: Moment.Moment;
|
|
54
68
|
second: Moment.Moment | null;
|
|
@@ -88,6 +102,15 @@ export type CalendarProRef = {
|
|
|
88
102
|
secondDate?: Moment.Moment | null,
|
|
89
103
|
tabSelected?: number,
|
|
90
104
|
) => void;
|
|
105
|
+
setDateRange: (
|
|
106
|
+
dateRange: { startDate: any; endDate: any },
|
|
107
|
+
isScrollToStartDate: any,
|
|
108
|
+
) => void;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export type CalendarState = {
|
|
112
|
+
isDoubleDateMode: boolean;
|
|
113
|
+
containerWidth: number;
|
|
91
114
|
};
|
|
92
115
|
|
|
93
116
|
export type HeaderControlRef = {
|
|
@@ -111,16 +134,23 @@ export type MonthListProps = {
|
|
|
111
134
|
endDate: Moment.Moment;
|
|
112
135
|
isShowLunar: boolean;
|
|
113
136
|
tabSelected?: number;
|
|
137
|
+
today: Moment.Moment;
|
|
114
138
|
onChoose: (day: Moment.Moment) => void;
|
|
115
139
|
onScrollCalendar?: (info: {
|
|
116
140
|
date: Moment.Moment;
|
|
117
141
|
key: string;
|
|
118
142
|
currentIndex: number;
|
|
119
143
|
}) => void;
|
|
144
|
+
lunarConverter: any;
|
|
120
145
|
disabledDays?: Date[];
|
|
121
146
|
bestPriceColor?: string;
|
|
122
147
|
};
|
|
123
148
|
|
|
149
|
+
export type MonthListState = {
|
|
150
|
+
data?: any;
|
|
151
|
+
isDoubleDateMode?: boolean;
|
|
152
|
+
};
|
|
153
|
+
|
|
124
154
|
export type MonthListRef = {
|
|
125
155
|
scrollToMonth: (date: Moment.Moment) => void;
|
|
126
156
|
};
|
|
@@ -138,8 +168,6 @@ export type MonthProps = {
|
|
|
138
168
|
isDoubleDateMode: boolean;
|
|
139
169
|
disabledDays?: Date[];
|
|
140
170
|
bestPriceColor?: string;
|
|
141
|
-
tabSelected?: number;
|
|
142
|
-
onChoose?: (date: Moment.Moment) => void;
|
|
143
171
|
};
|
|
144
172
|
|
|
145
173
|
export type DayProps = {
|
|
@@ -164,9 +192,9 @@ export type DayProps = {
|
|
|
164
192
|
bestPriceColor?: string;
|
|
165
193
|
};
|
|
166
194
|
|
|
167
|
-
export type
|
|
168
|
-
|
|
169
|
-
|
|
195
|
+
export type TabHeaderState = {
|
|
196
|
+
active?: boolean;
|
|
197
|
+
date?: Moment.Moment;
|
|
170
198
|
};
|
|
171
199
|
|
|
172
200
|
export type TabHeaderProps = {
|
|
@@ -177,3 +205,8 @@ export type TabHeaderProps = {
|
|
|
177
205
|
id: number;
|
|
178
206
|
disabled?: boolean;
|
|
179
207
|
};
|
|
208
|
+
|
|
209
|
+
export type TabHeaderRef = {
|
|
210
|
+
updateView: (date?: Moment.Moment | null, activeTab?: boolean) => void;
|
|
211
|
+
setActiveTab: (active: boolean) => void;
|
|
212
|
+
};
|
package/ContainerContext.ts
DELETED