@momo-kits/calendar 0.167.1-duotest.1 → 0.167.1-rc.2
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/CalendarHeader.tsx +107 -0
- package/CalendarPro.tsx +18 -26
- package/ContainerContext.ts +3 -0
- package/Day.tsx +20 -20
- package/HeaderControl.tsx +1 -2
- package/LunarDateConverter.ts +21 -19
- package/Month.tsx +8 -20
- package/MonthList.tsx +36 -23
- package/TabHeader.tsx +57 -83
- package/Util.ts +6 -108
- package/index.tsx +51 -123
- package/package.json +17 -17
- package/styles.ts +22 -16
- package/types.ts +5 -38
- package/LunarService.ts +0 -206
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import React, { useContext } from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import moment from 'moment';
|
|
4
|
+
import { ApplicationContext, Switch, Text } from '@momo-kits/foundation';
|
|
5
|
+
import TabHeader from './TabHeader';
|
|
6
|
+
import { TabHeaderRef } from './types';
|
|
7
|
+
import styles from './styles';
|
|
8
|
+
|
|
9
|
+
type SwitchReturnSelectionProps = {
|
|
10
|
+
hidden?: boolean;
|
|
11
|
+
title?: string;
|
|
12
|
+
value: boolean;
|
|
13
|
+
onChange: () => void;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const SwitchReturnSelection: React.FC<
|
|
17
|
+
SwitchReturnSelectionProps
|
|
18
|
+
> = props => {
|
|
19
|
+
const { translate, theme } = useContext(ApplicationContext);
|
|
20
|
+
if (props.hidden) return null;
|
|
21
|
+
return (
|
|
22
|
+
<View style={styles.headerContainer}>
|
|
23
|
+
<View
|
|
24
|
+
style={[
|
|
25
|
+
styles.viewSwitch,
|
|
26
|
+
{ backgroundColor: theme.colors.background.surface },
|
|
27
|
+
]}
|
|
28
|
+
>
|
|
29
|
+
<Text typography="label_default_medium">
|
|
30
|
+
{props.title || translate?.('chooseRoundtrip')}
|
|
31
|
+
</Text>
|
|
32
|
+
<Switch value={props.value} onChange={props.onChange} />
|
|
33
|
+
</View>
|
|
34
|
+
</View>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
type HeaderPanelProps = {
|
|
39
|
+
isDoubleDateMode: boolean;
|
|
40
|
+
cellHeader1: React.RefObject<TabHeaderRef | null>;
|
|
41
|
+
cellHeader2: React.RefObject<TabHeaderRef | null>;
|
|
42
|
+
cellHeaderSingle: React.RefObject<TabHeaderRef | null>;
|
|
43
|
+
onChangeTab: (tabId: number) => void;
|
|
44
|
+
headerFrom?: string;
|
|
45
|
+
headerTo?: string;
|
|
46
|
+
firstDate: moment.Moment | null;
|
|
47
|
+
secondDate: moment.Moment | null;
|
|
48
|
+
selectedDate: moment.Moment;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const HeaderPanel: React.FC<HeaderPanelProps> = props => {
|
|
52
|
+
const { theme } = useContext(ApplicationContext);
|
|
53
|
+
const {
|
|
54
|
+
isDoubleDateMode,
|
|
55
|
+
cellHeader1,
|
|
56
|
+
cellHeader2,
|
|
57
|
+
cellHeaderSingle,
|
|
58
|
+
onChangeTab,
|
|
59
|
+
headerFrom,
|
|
60
|
+
headerTo,
|
|
61
|
+
firstDate,
|
|
62
|
+
secondDate,
|
|
63
|
+
selectedDate,
|
|
64
|
+
} = props;
|
|
65
|
+
return isDoubleDateMode ? (
|
|
66
|
+
<View
|
|
67
|
+
style={[
|
|
68
|
+
styles.viewPanel,
|
|
69
|
+
{ backgroundColor: theme.colors.background.default },
|
|
70
|
+
]}
|
|
71
|
+
>
|
|
72
|
+
<TabHeader
|
|
73
|
+
id={0}
|
|
74
|
+
ref={cellHeader1}
|
|
75
|
+
onChangeTab={onChangeTab}
|
|
76
|
+
label={headerFrom || 'depart'}
|
|
77
|
+
activeTab
|
|
78
|
+
date={firstDate}
|
|
79
|
+
/>
|
|
80
|
+
<View style={styles.tabGap} />
|
|
81
|
+
<TabHeader
|
|
82
|
+
id={1}
|
|
83
|
+
ref={cellHeader2}
|
|
84
|
+
onChangeTab={onChangeTab}
|
|
85
|
+
label={headerTo || 'return'}
|
|
86
|
+
activeTab={false}
|
|
87
|
+
date={secondDate}
|
|
88
|
+
/>
|
|
89
|
+
</View>
|
|
90
|
+
) : (
|
|
91
|
+
<View
|
|
92
|
+
style={[
|
|
93
|
+
styles.viewPanel,
|
|
94
|
+
{ backgroundColor: theme.colors.background.default },
|
|
95
|
+
]}
|
|
96
|
+
>
|
|
97
|
+
<TabHeader
|
|
98
|
+
id={0}
|
|
99
|
+
disabled
|
|
100
|
+
ref={cellHeaderSingle}
|
|
101
|
+
label={headerFrom || 'depart'}
|
|
102
|
+
activeTab
|
|
103
|
+
date={selectedDate}
|
|
104
|
+
/>
|
|
105
|
+
</View>
|
|
106
|
+
);
|
|
107
|
+
};
|
package/CalendarPro.tsx
CHANGED
|
@@ -7,18 +7,16 @@ import React, {
|
|
|
7
7
|
forwardRef,
|
|
8
8
|
useImperativeHandle,
|
|
9
9
|
} from 'react';
|
|
10
|
-
import {
|
|
10
|
+
import { ScrollView, View } from 'react-native';
|
|
11
11
|
import moment, { Moment } from 'moment';
|
|
12
12
|
import {
|
|
13
13
|
ApplicationContext,
|
|
14
14
|
CheckBox,
|
|
15
|
-
Colors,
|
|
16
15
|
Spacing,
|
|
17
16
|
Text,
|
|
18
17
|
} from '@momo-kits/foundation';
|
|
19
18
|
import MonthList from './MonthList';
|
|
20
19
|
import HeaderControl from './HeaderControl';
|
|
21
|
-
import LunarDateConverter from './LunarDateConverter';
|
|
22
20
|
import Util from './Util';
|
|
23
21
|
import {
|
|
24
22
|
CalendarProProps,
|
|
@@ -27,7 +25,7 @@ import {
|
|
|
27
25
|
MonthListRef,
|
|
28
26
|
Holidays,
|
|
29
27
|
} from './types';
|
|
30
|
-
import { ContainerContext } from './
|
|
28
|
+
import { ContainerContext } from './ContainerContext';
|
|
31
29
|
import styles from './styles';
|
|
32
30
|
|
|
33
31
|
const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
@@ -53,8 +51,7 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
53
51
|
const { theme, translate } = useContext(ApplicationContext);
|
|
54
52
|
const size = useContext(ContainerContext);
|
|
55
53
|
|
|
56
|
-
const
|
|
57
|
-
const headerRef = useRef<Moment>(today.clone());
|
|
54
|
+
const headerRef = useRef<Moment>(moment());
|
|
58
55
|
const headerControlRef = useRef<HeaderControlRef>(null);
|
|
59
56
|
const monthListRef = useRef<MonthListRef>(null);
|
|
60
57
|
|
|
@@ -84,10 +81,6 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
84
81
|
const [temp, setTemp] = useState<any[]>([]);
|
|
85
82
|
const [headerKey, setHeaderKey] = useState<string>('');
|
|
86
83
|
const [ownUpdate, setOwnUpdate] = useState<boolean>(false);
|
|
87
|
-
const converter: any = useMemo(
|
|
88
|
-
() => (new LunarDateConverter()),
|
|
89
|
-
[],
|
|
90
|
-
);
|
|
91
84
|
|
|
92
85
|
useImperativeHandle(ref, () => ({
|
|
93
86
|
setDoubleDateAndTabIndex: (
|
|
@@ -99,11 +92,6 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
99
92
|
if (firstDate) setStartDate(firstDate);
|
|
100
93
|
if (secondDate !== undefined) setEndDate(secondDate);
|
|
101
94
|
},
|
|
102
|
-
setDateRange: (dateRange: { startDate: any; endDate: any }) => {
|
|
103
|
-
if (monthListRef.current && dateRange.startDate) {
|
|
104
|
-
monthListRef.current.scrollToMonth(moment(dateRange.startDate));
|
|
105
|
-
}
|
|
106
|
-
},
|
|
107
95
|
}));
|
|
108
96
|
|
|
109
97
|
// Sync showLunar prop
|
|
@@ -200,13 +188,17 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
200
188
|
|
|
201
189
|
// Determine price list format
|
|
202
190
|
let priceListFormat = priceList?.outbound;
|
|
203
|
-
if (isDoubleDateMode) {
|
|
204
|
-
priceListFormat =
|
|
205
|
-
tabSelected === 0 ? priceList?.outbound : priceList?.inbound;
|
|
191
|
+
if (isDoubleDateMode && tabSelected !== 0) {
|
|
192
|
+
priceListFormat = priceList?.inbound;
|
|
206
193
|
}
|
|
207
194
|
|
|
208
195
|
return (
|
|
209
|
-
<View
|
|
196
|
+
<View
|
|
197
|
+
style={[
|
|
198
|
+
styles.container,
|
|
199
|
+
{ backgroundColor: theme.colors.background.surface },
|
|
200
|
+
]}
|
|
201
|
+
>
|
|
210
202
|
<HeaderControl
|
|
211
203
|
ref={headerControlRef}
|
|
212
204
|
selectedDate={propSelectedDate}
|
|
@@ -219,11 +211,15 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
219
211
|
{[1, 2, 3, 4, 5, 6, 7].map(dayIdx => (
|
|
220
212
|
<Text
|
|
221
213
|
key={dayIdx}
|
|
222
|
-
color={
|
|
214
|
+
color={
|
|
215
|
+
dayIdx >= 6
|
|
216
|
+
? theme.colors.error.primary
|
|
217
|
+
: theme.colors.text.default
|
|
218
|
+
}
|
|
223
219
|
typography="label_s_medium"
|
|
224
220
|
style={[
|
|
225
221
|
styles.textDay,
|
|
226
|
-
{ width: (size.width - Spacing.
|
|
222
|
+
{ width: (size.width - Spacing.S * 2) / 7 },
|
|
227
223
|
]}
|
|
228
224
|
>
|
|
229
225
|
{translate?.(Util.mapWeeKDate(dayIdx))}
|
|
@@ -232,7 +228,6 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
232
228
|
</View>
|
|
233
229
|
<MonthList
|
|
234
230
|
ref={monthListRef}
|
|
235
|
-
today={today}
|
|
236
231
|
minDate={minDate}
|
|
237
232
|
maxDate={maxDate}
|
|
238
233
|
startDate={startDate!}
|
|
@@ -242,7 +237,6 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
242
237
|
isShowLunar={!isOffLunar && showLunar}
|
|
243
238
|
isDoubleDateMode={isDoubleDateMode}
|
|
244
239
|
tabSelected={tabSelected}
|
|
245
|
-
lunarConverter={converter}
|
|
246
240
|
holidays={holidays}
|
|
247
241
|
selectedDate={propSelectedDate}
|
|
248
242
|
priceList={priceListFormat}
|
|
@@ -274,9 +268,7 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
|
|
|
274
268
|
const labelDate = `${item.day > 9 ? item.day : `0${item.day}`}/${
|
|
275
269
|
item.month > 9 ? item.month : `0${item.month}`
|
|
276
270
|
}`;
|
|
277
|
-
const labelHoliday = showLunar
|
|
278
|
-
? item.mixedLabel || item.label
|
|
279
|
-
: item.label;
|
|
271
|
+
const labelHoliday = (showLunar && item.mixedLabel) || item.label;
|
|
280
272
|
const labelHighlight = showLunar ? item.highlight || '' : '';
|
|
281
273
|
return (
|
|
282
274
|
<View style={styles.row} key={idx.toString()}>
|
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 './ContainerContext';
|
|
13
13
|
import styles from './styles';
|
|
14
14
|
|
|
15
15
|
const Day: React.FC<DayProps> = props => {
|
|
@@ -36,13 +36,12 @@ 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);
|
|
40
39
|
const scaledSpacing = useScaleSize(Spacing.XS);
|
|
41
40
|
const scaledFontSize = useScaleSize(8);
|
|
42
41
|
const scaledLineHeight = useScaleSize(12);
|
|
43
42
|
const lunarFontFamily = exportFontFamily('regular');
|
|
44
43
|
|
|
45
|
-
const itemWidth = (size.width - Spacing.
|
|
44
|
+
const itemWidth = (size.width - Spacing.S * 2) / 7;
|
|
46
45
|
if (isEmpty || !date) {
|
|
47
46
|
return <View style={[styles.dayContainer, { width: itemWidth }]} />;
|
|
48
47
|
}
|
|
@@ -63,9 +62,8 @@ const Day: React.FC<DayProps> = props => {
|
|
|
63
62
|
const isWeekEnd = index === 6 || index === 5;
|
|
64
63
|
const showLunar = isShowLunar;
|
|
65
64
|
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
: true;
|
|
65
|
+
const isEndTab = isDoubleDateMode && tabSelected !== 0;
|
|
66
|
+
const isInScope = !isEndTab || date.isSameOrAfter(startDate, 'day');
|
|
69
67
|
|
|
70
68
|
const chooseDay = () => {
|
|
71
69
|
onChoose && onChoose(date);
|
|
@@ -95,6 +93,9 @@ const Day: React.FC<DayProps> = props => {
|
|
|
95
93
|
lunarTextColor = theme.colors.text.disable;
|
|
96
94
|
}
|
|
97
95
|
|
|
96
|
+
const { lunarDay, lunarMonth } = lunarDate ?? {};
|
|
97
|
+
const lunarLabel = lunarDay === 1 ? `${lunarDay}/${lunarMonth}` : lunarDay;
|
|
98
|
+
|
|
98
99
|
return (
|
|
99
100
|
<View style={[styles.dayContainer, { width: itemWidth }]}>
|
|
100
101
|
<View
|
|
@@ -109,10 +110,9 @@ const Day: React.FC<DayProps> = props => {
|
|
|
109
110
|
styles.day,
|
|
110
111
|
{
|
|
111
112
|
width: itemWidth,
|
|
112
|
-
paddingVertical:
|
|
113
|
+
paddingVertical: price ? Spacing.XS : Spacing.S,
|
|
113
114
|
},
|
|
114
115
|
(isStart || isEnd) && { backgroundColor: theme.colors.primary },
|
|
115
|
-
!!price && { height: scaledHeight },
|
|
116
116
|
{ height: size.height },
|
|
117
117
|
]}
|
|
118
118
|
disabled={!(isValid && isInScope)}
|
|
@@ -121,19 +121,19 @@ const Day: React.FC<DayProps> = props => {
|
|
|
121
121
|
{lunarDate && showLunar && !!date && (
|
|
122
122
|
<RNText
|
|
123
123
|
allowFontScaling={false}
|
|
124
|
-
style={
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
124
|
+
style={[
|
|
125
|
+
styles.lunarText,
|
|
126
|
+
{
|
|
127
|
+
top: scaledSpacing,
|
|
128
|
+
right: scaledSpacing,
|
|
129
|
+
color: lunarTextColor,
|
|
130
|
+
fontSize: scaledFontSize,
|
|
131
|
+
lineHeight: scaledLineHeight,
|
|
132
|
+
fontFamily: lunarFontFamily,
|
|
133
|
+
},
|
|
134
|
+
]}
|
|
133
135
|
>
|
|
134
|
-
{
|
|
135
|
-
? `${lunarDate.lunarDay}/${lunarDate.lunarMonth}`
|
|
136
|
-
: lunarDate.lunarDay}
|
|
136
|
+
{lunarLabel}
|
|
137
137
|
</RNText>
|
|
138
138
|
)}
|
|
139
139
|
<Text typography="body_default_regular" color={textColor}>
|
package/HeaderControl.tsx
CHANGED
|
@@ -7,7 +7,6 @@ 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';
|
|
11
10
|
import {ApplicationContext, Icon, Text} from '@momo-kits/foundation';
|
|
12
11
|
|
|
13
12
|
import Util from './Util';
|
|
@@ -19,7 +18,7 @@ const HeaderControl: ForwardRefRenderFunction<
|
|
|
19
18
|
HeaderControlProps
|
|
20
19
|
> = ({onPressBackArrow, onPressNextArrow, selectedDate}, ref) => {
|
|
21
20
|
const {translate} = useContext(ApplicationContext);
|
|
22
|
-
const [info, setInfo] = useState<{date:
|
|
21
|
+
const [info, setInfo] = useState<{date: moment.Moment}>({
|
|
23
22
|
date: moment(selectedDate || new Date()),
|
|
24
23
|
});
|
|
25
24
|
|
package/LunarDateConverter.ts
CHANGED
|
@@ -77,6 +77,7 @@ function LunarSolarConverter(this: any) {
|
|
|
77
77
|
* @return {number}
|
|
78
78
|
*/
|
|
79
79
|
this.GetBitInt = function (data: number, length: number, shift: number) {
|
|
80
|
+
// eslint-disable-next-line no-bitwise -- unpacks bit-packed lunar table data
|
|
80
81
|
return (data & (((1 << length) - 1) << shift)) >> shift;
|
|
81
82
|
};
|
|
82
83
|
|
|
@@ -86,43 +87,43 @@ function LunarSolarConverter(this: any) {
|
|
|
86
87
|
*/
|
|
87
88
|
this.SolarToInt = function (y: number, m: number, d: number) {
|
|
88
89
|
m = (m + 9) % 12;
|
|
89
|
-
y = parseInt(String(y)) - parseInt(String(m / 10));
|
|
90
|
+
y = parseInt(String(y), 10) - parseInt(String(m / 10), 10);
|
|
90
91
|
return (
|
|
91
92
|
365 * y +
|
|
92
|
-
parseInt(String(y / 4)) -
|
|
93
|
-
parseInt(String(y / 100)) +
|
|
94
|
-
parseInt(String(y / 400)) +
|
|
95
|
-
parseInt(String((m * 306 + 5) / 10)) +
|
|
93
|
+
parseInt(String(y / 4), 10) -
|
|
94
|
+
parseInt(String(y / 100), 10) +
|
|
95
|
+
parseInt(String(y / 400), 10) +
|
|
96
|
+
parseInt(String((m * 306 + 5) / 10), 10) +
|
|
96
97
|
(d - 1)
|
|
97
98
|
);
|
|
98
99
|
};
|
|
99
100
|
|
|
100
101
|
this.SolarFromInt = function (g: number) {
|
|
101
|
-
let y = parseInt(String((10000 * g + 14780) / 3652425));
|
|
102
|
+
let y = parseInt(String((10000 * g + 14780) / 3652425), 10);
|
|
102
103
|
let ddd =
|
|
103
104
|
g -
|
|
104
105
|
(365 * y +
|
|
105
|
-
parseInt(String(y / 4)) -
|
|
106
|
-
parseInt(String(y / 100)) +
|
|
107
|
-
parseInt(String(y / 400)));
|
|
106
|
+
parseInt(String(y / 4), 10) -
|
|
107
|
+
parseInt(String(y / 100), 10) +
|
|
108
|
+
parseInt(String(y / 400), 10));
|
|
108
109
|
if (ddd < 0) {
|
|
109
110
|
y--;
|
|
110
111
|
ddd =
|
|
111
112
|
g -
|
|
112
113
|
(365 * y +
|
|
113
|
-
parseInt(String(y / 4)) -
|
|
114
|
-
parseInt(String(y / 100)) +
|
|
115
|
-
parseInt(String(y / 400)));
|
|
114
|
+
parseInt(String(y / 4), 10) -
|
|
115
|
+
parseInt(String(y / 100), 10) +
|
|
116
|
+
parseInt(String(y / 400), 10));
|
|
116
117
|
}
|
|
117
|
-
const mi = parseInt(String((100 * ddd + 52) / 3060));
|
|
118
|
+
const mi = parseInt(String((100 * ddd + 52) / 3060), 10);
|
|
118
119
|
const mm = ((mi + 2) % 12) + 1;
|
|
119
|
-
y += parseInt(String((mi + 2) / 12));
|
|
120
|
-
const dd = ddd - parseInt(String((mi * 306 + 5) / 10)) + 1;
|
|
120
|
+
y += parseInt(String((mi + 2) / 12), 10);
|
|
121
|
+
const dd = ddd - parseInt(String((mi * 306 + 5) / 10), 10) + 1;
|
|
121
122
|
// @ts-ignore
|
|
122
123
|
const solar = new Solar();
|
|
123
|
-
solar.solarYear = parseInt(String(y));
|
|
124
|
-
solar.solarMonth = parseInt(String(mm));
|
|
125
|
-
solar.solarDay = parseInt(String(dd));
|
|
124
|
+
solar.solarYear = parseInt(String(y), 10);
|
|
125
|
+
solar.solarMonth = parseInt(String(mm), 10);
|
|
126
|
+
solar.solarDay = parseInt(String(dd), 10);
|
|
126
127
|
return solar;
|
|
127
128
|
};
|
|
128
129
|
|
|
@@ -181,6 +182,7 @@ function LunarSolarConverter(this: any) {
|
|
|
181
182
|
const lunar = new Lunar();
|
|
182
183
|
let index = solar.solarYear - this.solar_1_1[0];
|
|
183
184
|
const data =
|
|
185
|
+
// eslint-disable-next-line no-bitwise -- packs date to compare with solar_1_1 table
|
|
184
186
|
(solar.solarYear << 9) | (solar.solarMonth << 5) | solar.solarDay;
|
|
185
187
|
if (this.solar_1_1[index] > data) {
|
|
186
188
|
index--;
|
|
@@ -209,7 +211,7 @@ function LunarSolarConverter(this: any) {
|
|
|
209
211
|
break;
|
|
210
212
|
}
|
|
211
213
|
}
|
|
212
|
-
const lunarD = parseInt(String(offset));
|
|
214
|
+
const lunarD = parseInt(String(offset), 10);
|
|
213
215
|
lunar.lunarYear = lunarY;
|
|
214
216
|
lunar.lunarMonth = lunarM;
|
|
215
217
|
lunar.isleap = false;
|
package/Month.tsx
CHANGED
|
@@ -2,9 +2,10 @@ import React, {useContext, useMemo} from 'react';
|
|
|
2
2
|
import {View} from 'react-native';
|
|
3
3
|
import moment, {Moment} from 'moment';
|
|
4
4
|
import Day from './Day';
|
|
5
|
-
import {useScaleSize
|
|
5
|
+
import {useScaleSize} from '@momo-kits/foundation';
|
|
6
6
|
import {MonthProps} from './types';
|
|
7
|
-
import {ContainerContext} from './
|
|
7
|
+
import {ContainerContext} from './ContainerContext';
|
|
8
|
+
import styles from './styles';
|
|
8
9
|
|
|
9
10
|
const Month: React.FC<MonthProps> = ({
|
|
10
11
|
dateList,
|
|
@@ -60,31 +61,18 @@ const Month: React.FC<MonthProps> = ({
|
|
|
60
61
|
|
|
61
62
|
return (
|
|
62
63
|
<View style={{width: size.width}}>
|
|
63
|
-
<View
|
|
64
|
-
style={{
|
|
65
|
-
paddingHorizontal: Spacing.S,
|
|
66
|
-
width: '100%',
|
|
67
|
-
alignItems: 'center',
|
|
68
|
-
}}>
|
|
64
|
+
<View style={styles.monthRows}>
|
|
69
65
|
{rows.map((dayList, rowIndex) => (
|
|
70
66
|
<View
|
|
71
67
|
key={`row${rowIndex}`}
|
|
72
|
-
style={{
|
|
73
|
-
flexDirection: 'row',
|
|
74
|
-
alignItems: 'center',
|
|
75
|
-
marginBottom: Spacing.XS,
|
|
76
|
-
height: scaledHeight,
|
|
77
|
-
}}>
|
|
68
|
+
style={[styles.monthRow, {height: scaledHeight}]}>
|
|
78
69
|
{dayList.map((item, i) => {
|
|
79
70
|
const {isEmpty, date: dateMoment, lunarDate} = item;
|
|
80
71
|
// compute key for price/disabled only if not empty
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
: '';
|
|
72
|
+
const hasDate = !isEmpty && dateMoment;
|
|
73
|
+
const keyDay = hasDate ? dateMoment.format('YYYY-MM-DD') : '';
|
|
84
74
|
const priceInfo = keyDay ? priceListDate?.[keyDay] : undefined;
|
|
85
|
-
const isDisabled = keyDay
|
|
86
|
-
? disabledSet.has(keyDay)
|
|
87
|
-
: false;
|
|
75
|
+
const isDisabled = keyDay ? disabledSet.has(keyDay) : false;
|
|
88
76
|
|
|
89
77
|
return (
|
|
90
78
|
<Day
|
package/MonthList.tsx
CHANGED
|
@@ -5,7 +5,6 @@ import React, {
|
|
|
5
5
|
useImperativeHandle,
|
|
6
6
|
useCallback,
|
|
7
7
|
useContext,
|
|
8
|
-
useEffect,
|
|
9
8
|
useLayoutEffect,
|
|
10
9
|
useMemo,
|
|
11
10
|
useRef,
|
|
@@ -17,7 +16,7 @@ import {
|
|
|
17
16
|
NativeSyntheticEvent,
|
|
18
17
|
Platform,
|
|
19
18
|
} from 'react-native';
|
|
20
|
-
import { ContainerContext } from './
|
|
19
|
+
import { ContainerContext } from './ContainerContext';
|
|
21
20
|
import LunarDateConverter from './LunarDateConverter';
|
|
22
21
|
import Month from './Month';
|
|
23
22
|
import { MonthListProps, MonthListRef } from './types';
|
|
@@ -39,15 +38,22 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
39
38
|
isShowLunar,
|
|
40
39
|
isDoubleDateMode,
|
|
41
40
|
disabledDays,
|
|
41
|
+
tabSelected,
|
|
42
|
+
onChoose,
|
|
43
|
+
bestPriceColor,
|
|
42
44
|
onScrollCalendar,
|
|
43
|
-
...restProps
|
|
44
45
|
} = props;
|
|
45
46
|
|
|
46
47
|
const size = useContext(ContainerContext);
|
|
47
48
|
const scaledHeight48 = useScaleSize(48);
|
|
48
49
|
const listRef = useRef<FlatList>(null);
|
|
49
50
|
const currentKey = useRef<string | null>(null);
|
|
51
|
+
const targetIndex = useRef<number | null>(null);
|
|
50
52
|
const [heightStyle, setHeightStyle] = useState({});
|
|
53
|
+
const onScrollCalendarRef = useRef(onScrollCalendar);
|
|
54
|
+
onScrollCalendarRef.current = onScrollCalendar;
|
|
55
|
+
const scaledHeight48Ref = useRef(scaledHeight48);
|
|
56
|
+
scaledHeight48Ref.current = scaledHeight48;
|
|
51
57
|
|
|
52
58
|
const data = useMemo(() => {
|
|
53
59
|
const months: { date: Moment; dateList: any[] }[] = [];
|
|
@@ -69,9 +75,6 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
69
75
|
}
|
|
70
76
|
while (cursor.month() === monthIdx) {
|
|
71
77
|
const cloned = cursor.clone();
|
|
72
|
-
const hol = holidays.find(
|
|
73
|
-
h => h.day === cloned.date() && h.month === cloned.month() + 1,
|
|
74
|
-
);
|
|
75
78
|
dayList.push({
|
|
76
79
|
isEmpty: false,
|
|
77
80
|
date: cloned,
|
|
@@ -80,8 +83,6 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
80
83
|
solarMonth: cloned.month() + 1,
|
|
81
84
|
solarYear: cloned.year(),
|
|
82
85
|
}),
|
|
83
|
-
isSolarHoliday: !!(hol && !hol.lunar),
|
|
84
|
-
isLunarHoliday: !!(hol && hol.lunar),
|
|
85
86
|
});
|
|
86
87
|
cursor.add(1, 'days');
|
|
87
88
|
}
|
|
@@ -96,7 +97,7 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
96
97
|
mMin.add(1, 'month');
|
|
97
98
|
}
|
|
98
99
|
return months;
|
|
99
|
-
}, [minDate, maxDate
|
|
100
|
+
}, [minDate, maxDate]);
|
|
100
101
|
|
|
101
102
|
const getIndexOfMonth = useCallback(
|
|
102
103
|
(date: Moment) => data.findIndex(item => item.date.isSame(date, 'month')),
|
|
@@ -138,6 +139,9 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
138
139
|
(month: Moment) => {
|
|
139
140
|
const idx = getIndexOfMonth(month);
|
|
140
141
|
if (listRef.current && idx !== -1) {
|
|
142
|
+
const offset = idx * pageWidth.current;
|
|
143
|
+
targetIndex.current =
|
|
144
|
+
Math.abs(offset - scrollOffset.current) < 1 ? null : idx;
|
|
141
145
|
listRef.current.scrollToIndex({ index: idx, animated: true });
|
|
142
146
|
}
|
|
143
147
|
},
|
|
@@ -146,29 +150,31 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
146
150
|
|
|
147
151
|
useImperativeHandle(ref, () => ({ scrollToMonth }));
|
|
148
152
|
|
|
149
|
-
useEffect(() => {
|
|
150
|
-
const timer = setTimeout(() => {
|
|
151
|
-
scrollToMonth(selectedDate);
|
|
152
|
-
}, 500);
|
|
153
|
-
return () => clearTimeout(timer);
|
|
154
|
-
}, []);
|
|
155
|
-
|
|
156
153
|
const onViewableItemsChanged = useRef(({ changed }: { changed: any[] }) => {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
154
|
+
const visible = changed.find(token => token.isViewable);
|
|
155
|
+
if (targetIndex.current !== null && visible?.index !== targetIndex.current) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
targetIndex.current = null;
|
|
159
|
+
if (visible) {
|
|
160
|
+
const { item, key, index } = visible;
|
|
161
|
+
if (onScrollCalendarRef.current && item && currentKey.current !== key) {
|
|
160
162
|
currentKey.current = key;
|
|
161
163
|
try {
|
|
162
164
|
setHeightStyle({
|
|
163
165
|
height:
|
|
164
|
-
(
|
|
166
|
+
(scaledHeight48Ref.current * item.dateList.length) / 7 +
|
|
165
167
|
Spacing.L * 2 +
|
|
166
168
|
Spacing.XS,
|
|
167
169
|
});
|
|
168
170
|
} catch {
|
|
169
171
|
setHeightStyle({});
|
|
170
172
|
}
|
|
171
|
-
|
|
173
|
+
onScrollCalendarRef.current({
|
|
174
|
+
date: item.date,
|
|
175
|
+
key,
|
|
176
|
+
currentIndex: index,
|
|
177
|
+
});
|
|
172
178
|
}
|
|
173
179
|
}
|
|
174
180
|
}).current;
|
|
@@ -201,7 +207,6 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
201
207
|
const priceListDate = priceList?.[keyMonth]?.day;
|
|
202
208
|
return (
|
|
203
209
|
<Month
|
|
204
|
-
{...restProps}
|
|
205
210
|
key={index}
|
|
206
211
|
month={item.date}
|
|
207
212
|
dateList={item.dateList}
|
|
@@ -214,11 +219,13 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
214
219
|
isShowLunar={isShowLunar}
|
|
215
220
|
isDoubleDateMode={isDoubleDateMode}
|
|
216
221
|
disabledDays={disabledDays}
|
|
222
|
+
tabSelected={tabSelected}
|
|
223
|
+
onChoose={onChoose}
|
|
224
|
+
bestPriceColor={bestPriceColor}
|
|
217
225
|
/>
|
|
218
226
|
);
|
|
219
227
|
},
|
|
220
228
|
[
|
|
221
|
-
restProps,
|
|
222
229
|
priceList,
|
|
223
230
|
holidays,
|
|
224
231
|
minDate,
|
|
@@ -228,6 +235,9 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
228
235
|
isShowLunar,
|
|
229
236
|
isDoubleDateMode,
|
|
230
237
|
disabledDays,
|
|
238
|
+
tabSelected,
|
|
239
|
+
onChoose,
|
|
240
|
+
bestPriceColor,
|
|
231
241
|
],
|
|
232
242
|
);
|
|
233
243
|
|
|
@@ -244,6 +254,9 @@ const MonthList = forwardRef<MonthListRef, MonthListProps>((props, ref) => {
|
|
|
244
254
|
keyExtractor={keyExtractor}
|
|
245
255
|
onScrollToIndexFailed={() => {}}
|
|
246
256
|
onScroll={onScroll}
|
|
257
|
+
onScrollBeginDrag={() => {
|
|
258
|
+
targetIndex.current = null;
|
|
259
|
+
}}
|
|
247
260
|
scrollEnabled
|
|
248
261
|
initialNumToRender={3}
|
|
249
262
|
maxToRenderPerBatch={MAX_RENDER_PER_BATCH}
|