@momo-kits/calendar 0.168.1-beta.2 → 0.168.1-beta.22

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 CHANGED
@@ -7,18 +7,16 @@ import React, {
7
7
  forwardRef,
8
8
  useImperativeHandle,
9
9
  } from 'react';
10
- import { Platform, ScrollView, View } from 'react-native';
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 './index';
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 today = useMemo(() => moment(), []);
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
@@ -205,7 +193,12 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
205
193
  }
206
194
 
207
195
  return (
208
- <View style={styles.container}>
196
+ <View
197
+ style={[
198
+ styles.container,
199
+ { backgroundColor: theme.colors.background.surface },
200
+ ]}
201
+ >
209
202
  <HeaderControl
210
203
  ref={headerControlRef}
211
204
  selectedDate={propSelectedDate}
@@ -218,11 +211,15 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
218
211
  {[1, 2, 3, 4, 5, 6, 7].map(dayIdx => (
219
212
  <Text
220
213
  key={dayIdx}
221
- color={dayIdx >= 6 ? Colors.red_03 : Colors.black_17}
214
+ color={
215
+ dayIdx >= 6
216
+ ? theme.colors.error.primary
217
+ : theme.colors.text.default
218
+ }
222
219
  typography="label_s_medium"
223
220
  style={[
224
221
  styles.textDay,
225
- { width: (size.width - Spacing.M * 2) / 7 },
222
+ { width: (size.width - Spacing.S * 2) / 7 },
226
223
  ]}
227
224
  >
228
225
  {translate?.(Util.mapWeeKDate(dayIdx))}
@@ -231,7 +228,6 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
231
228
  </View>
232
229
  <MonthList
233
230
  ref={monthListRef}
234
- today={today}
235
231
  minDate={minDate}
236
232
  maxDate={maxDate}
237
233
  startDate={startDate!}
@@ -241,7 +237,6 @@ const CalendarPro = forwardRef<CalendarProRef, CalendarProProps>(
241
237
  isShowLunar={!isOffLunar && showLunar}
242
238
  isDoubleDateMode={isDoubleDateMode}
243
239
  tabSelected={tabSelected}
244
- lunarConverter={converter}
245
240
  holidays={holidays}
246
241
  selectedDate={propSelectedDate}
247
242
  priceList={priceListFormat}
@@ -0,0 +1,3 @@
1
+ import { createContext } from 'react';
2
+
3
+ export const ContainerContext = createContext({ width: 0, height: 0 });
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 './index';
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.M) / 7;
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
  }
@@ -114,7 +113,6 @@ const Day: React.FC<DayProps> = props => {
114
113
  paddingVertical: !!price ? Spacing.XS : Spacing.S,
115
114
  },
116
115
  (isStart || isEnd) && { backgroundColor: theme.colors.primary },
117
- !!price && { height: scaledHeight },
118
116
  { height: size.height },
119
117
  ]}
120
118
  disabled={!(isValid && isInScope)}
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: Moment.Moment}>({
21
+ const [info, setInfo] = useState<{date: moment.Moment}>({
23
22
  date: moment(selectedDate || new Date()),
24
23
  });
25
24
 
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 './index';
7
+ import {ContainerContext} from './ContainerContext';
8
8
 
9
9
  const Month: React.FC<MonthProps> = ({
10
10
  dateList,
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 './index';
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, holidays]);
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
- if (changed.length > 0) {
158
- const { item, key, index } = changed[0];
159
- if (onScrollCalendar && item && currentKey.current !== key) {
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
- (scaledHeight48 * item.dateList.length) / 7 +
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
- onScrollCalendar({ date: item.date, key, currentIndex: index });
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}
package/TabHeader.tsx CHANGED
@@ -1,88 +1,73 @@
1
- import React from 'react';
2
- import {TouchableWithoutFeedback, View} from 'react-native';
1
+ import React, {
2
+ forwardRef,
3
+ useContext,
4
+ useImperativeHandle,
5
+ useState,
6
+ } from 'react';
7
+ import { TouchableWithoutFeedback, View } from 'react-native';
3
8
  import Moment from 'moment';
4
9
  import Util from './Util';
5
10
  import {
6
11
  ApplicationContext,
7
- Colors,
8
12
  Radius,
9
13
  Spacing,
10
14
  Text,
11
15
  } from '@momo-kits/foundation';
12
- import {TabHeaderProps, TabHeaderState} from './types';
16
+ import { TabHeaderProps, TabHeaderRef } from './types';
13
17
 
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;
18
+ const TabHeader = forwardRef<TabHeaderRef, TabHeaderProps>((props, ref) => {
19
+ const { label, disabled, id, onChangeTab } = props;
20
+ const { theme, translate } = useContext(ApplicationContext);
21
+ const [active, setActive] = useState<boolean | undefined>(props.activeTab);
22
+ const [date, setDate] = useState<Moment.Moment | undefined>(
23
+ props.date ? Moment(props.date) : undefined,
24
+ );
22
25
 
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
- }
26
+ useImperativeHandle(ref, () => ({
27
+ updateView: (nextDate, activeTab) => {
28
+ setDate(nextDate ? Moment(nextDate) : undefined);
29
+ setActive(activeTab);
30
+ },
31
+ setActiveTab: setActive,
32
+ }));
31
33
 
32
- onChangeTab = () => {
33
- const {onChangeTab, id} = this.props;
34
- onChangeTab?.(id);
35
- };
34
+ const weekday = (day: Moment.Moment) =>
35
+ translate?.(Util.WEEKDAYSFROMMOMENT[day.day()]);
36
+ const isHighlighted = active && !disabled;
36
37
 
37
- updateView = (date?: Moment.Moment | Date | null, activeTab?: boolean) => {
38
- this.setState({
39
- date: date ? Moment(date) : undefined,
40
- active: activeTab,
41
- });
42
- };
38
+ const formattedDate = date ? date.format('DD/MM/YYYY') : '';
39
+ const dayOfWeek = date ? `${weekday(date)}, ` : '';
43
40
 
44
- setActiveTab = (active: boolean) => {
45
- this.setState({active});
46
- };
41
+ return (
42
+ <TouchableWithoutFeedback
43
+ disabled={disabled}
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
+ });
47
72
 
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
- }
73
+ export default TabHeader;
package/Util.ts CHANGED
@@ -3,50 +3,8 @@ import LunarDateConverter from './LunarDateConverter';
3
3
  import holiday from './holidayData';
4
4
  import {Holidays} from './types';
5
5
 
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
- };
6
+ // @ts-ignore
7
+ const converter = new LunarDateConverter();
50
8
 
51
9
  const Solar = (momentDate: moment.Moment) => ({
52
10
  solarDay: momentDate.date(),
@@ -106,39 +64,8 @@ const sortByDate = (arr: Holidays[]): Holidays[] => {
106
64
  };
107
65
 
108
66
  const Utils = {
109
- WEEKDAYS: ['T2', 'T3', 'T4', 'T5', 'T6', 'T7', 'CN'],
110
-
111
67
  WEEKDAYSFROMMOMENT: ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'],
112
68
 
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
-
142
69
  mapWeeKDate(i: number) {
143
70
  const date = ['', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'];
144
71
  return date[i];
@@ -162,36 +89,11 @@ const Utils = {
162
89
  return month.get(i);
163
90
  },
164
91
 
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
-
188
92
  /**
189
93
  * Get sorted list of holidays within the given month.
190
94
  */
191
95
  getHolidaysInMonth(headerInfo: moment.Moment): Holidays[] {
192
96
  if (headerInfo) {
193
- // @ts-ignore
194
- const converter = new LunarDateConverter();
195
97
  const startDate = moment(headerInfo).startOf('month');
196
98
  const endDate = moment(headerInfo).endOf('month');
197
99
  const minLunarDate = converter.SolarToLunar(Solar(startDate));
@@ -279,7 +181,6 @@ const Utils = {
279
181
  }
280
182
  return [];
281
183
  },
282
- I18N_MAP,
283
184
  };
284
185
 
285
186
  export default Utils;
package/index.tsx CHANGED
@@ -1,11 +1,5 @@
1
1
  /* eslint-disable react-hooks/exhaustive-deps */
2
- import React, {
3
- useState,
4
- useRef,
5
- useEffect,
6
- useContext,
7
- createContext,
8
- } from 'react';
2
+ import React, { useState, useRef, useEffect, useContext } from 'react';
9
3
  import { Dimensions, LayoutChangeEvent, View } from 'react-native';
10
4
  import moment from 'moment';
11
5
  import {
@@ -18,13 +12,12 @@ import {
18
12
  } from '@momo-kits/foundation';
19
13
  import CalendarPro from './CalendarPro';
20
14
  import TabHeader from './TabHeader';
21
- import { CalendarProps, CalendarProRef } from './types';
15
+ import { CalendarProps, CalendarProRef, TabHeaderRef } from './types';
16
+ import { ContainerContext } from './ContainerContext';
22
17
  import styles from './styles';
23
18
 
24
19
  const DOUBLE = 'doubleDate';
25
20
 
26
- export const ContainerContext = createContext({ width: 0, height: 0 });
27
-
28
21
  const Calendar: React.FC<CalendarProps> = props => {
29
22
  const { translate, theme } = useContext(ApplicationContext);
30
23
  const scaledHeight48 = useScaleSize(48);
@@ -49,9 +42,6 @@ const Calendar: React.FC<CalendarProps> = props => {
49
42
  isHideHoliday,
50
43
  isShowLunar,
51
44
  priceList,
52
- labelFrom,
53
- labelTo,
54
- isHideLabel,
55
45
  minDate = minDateDefault,
56
46
  maxDate = maxDateDefault,
57
47
  style,
@@ -85,9 +75,9 @@ const Calendar: React.FC<CalendarProps> = props => {
85
75
 
86
76
  const calendarPicker = useRef<CalendarProRef>(null);
87
77
  // hold refs to TabHeader instances
88
- const cellHeader1 = useRef<TabHeader>(null);
89
- const cellHeader2 = useRef<TabHeader>(null);
90
- const cellHeaderSingle = useRef<TabHeader>(null);
78
+ const cellHeader1 = useRef<TabHeaderRef>(null);
79
+ const cellHeader2 = useRef<TabHeaderRef>(null);
80
+ const cellHeaderSingle = useRef<TabHeaderRef>(null);
91
81
 
92
82
  // Initialize view on mount
93
83
  useEffect(() => {
@@ -217,18 +207,11 @@ const Calendar: React.FC<CalendarProps> = props => {
217
207
  const updateHeaderView = () => {
218
208
  const { onDateChange, onCTAStateChange } = props;
219
209
  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
- );
227
210
  doubleDate.current.first = moment(selectedDate);
228
211
  doubleDate.current.second = null;
229
212
  tabSelected.current = 1;
230
- cellHeader2.current?.setActiveTab(true);
231
- cellHeader1.current?.setActiveTab(false);
213
+ cellHeader1.current?.updateView(selectedDate, false);
214
+ cellHeader2.current?.updateView(null, true);
232
215
  calendarPicker.current?.setDoubleDateAndTabIndex(
233
216
  doubleDate.current.first,
234
217
  doubleDate.current.second,
@@ -237,16 +220,17 @@ const Calendar: React.FC<CalendarProps> = props => {
237
220
  onCTAStateChange?.(false);
238
221
  onDateChange?.({ first: doubleDate.current.first!, second: null });
239
222
  } else {
240
- // Reset second date when switching to single mode
223
+ const date = doubleDate.current.first ?? selectedDate;
241
224
  doubleDate.current.second = null;
242
- props.onCTAStateChange?.(true);
243
- if (doubleDate.current.first) {
244
- cellHeaderSingle.current?.updateView(doubleDate.current.first, true);
245
- setSelectedDate(doubleDate.current.first);
225
+ tabSelected.current = 0;
226
+ calendarPicker.current?.setDoubleDateAndTabIndex(date, null, 0);
227
+ onCTAStateChange?.(true);
228
+ if (date.isSame(selectedDate, 'day')) {
229
+ cellHeaderSingle.current?.updateView(date, true);
230
+ onDateChange?.(date.toDate());
246
231
  } else {
247
- cellHeaderSingle.current?.updateView(selectedDate, true);
232
+ setSelectedDate(date);
248
233
  }
249
- props.onDateChange?.(selectedDate.toDate());
250
234
  }
251
235
  };
252
236
 
@@ -302,7 +286,7 @@ const Calendar: React.FC<CalendarProps> = props => {
302
286
  activeTab
303
287
  date={doubleDate.current.first}
304
288
  />
305
- <View style={{ width: 4, height: '100%' }} />
289
+ <View style={styles.tabGap} />
306
290
  <TabHeader
307
291
  id={1}
308
292
  ref={cellHeader2}
@@ -361,9 +345,6 @@ const Calendar: React.FC<CalendarProps> = props => {
361
345
  selectedDate={selectedDate}
362
346
  isShowLunar={isShowLunar}
363
347
  onCallbackCalendar={onCallbackCalendar}
364
- labelFrom={labelFrom}
365
- labelTo={labelTo}
366
- isHideLabel={isHideLabel}
367
348
  minDate={minDate}
368
349
  maxDate={maxDate}
369
350
  isHideHoliday={isHideHoliday}
@@ -376,4 +357,4 @@ const Calendar: React.FC<CalendarProps> = props => {
376
357
  );
377
358
  };
378
359
 
379
- export { Calendar };
360
+ export { Calendar, ContainerContext };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/calendar",
3
- "version": "0.168.1-beta.2",
3
+ "version": "0.168.1-beta.22",
4
4
  "private": false,
5
5
  "main": "index.tsx",
6
6
  "peerDependencies": {
package/styles.ts CHANGED
@@ -16,6 +16,10 @@ 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
+ },
19
23
  headerContainer: {
20
24
  paddingHorizontal: Spacing.M,
21
25
  marginTop: Spacing.S,
@@ -57,7 +61,6 @@ export default StyleSheet.create({
57
61
  marginTop: Spacing.S,
58
62
  },
59
63
  container: {
60
- backgroundColor: 'white',
61
64
  borderRadius: Radius.XS,
62
65
  },
63
66
  blueSeperator: {
@@ -70,18 +73,6 @@ export default StyleSheet.create({
70
73
  txtHeader: {
71
74
  textAlign: 'center',
72
75
  },
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
- },
85
76
  headerControlContainer: {
86
77
  flexDirection: 'row',
87
78
  justifyContent: 'space-between',
@@ -101,9 +92,6 @@ export default StyleSheet.create({
101
92
  alignItems: 'center',
102
93
  borderRadius: Radius.XS,
103
94
  },
104
- dayText: {
105
- textAlign: 'center',
106
- },
107
95
  dayStartContainer: {
108
96
  borderTopLeftRadius: Radius.XS,
109
97
  borderBottomLeftRadius: Radius.XS,
package/types.ts CHANGED
@@ -42,9 +42,6 @@ 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;
48
45
  isHideHoliday?: boolean;
49
46
  isOffLunar?: boolean;
50
47
  onCallbackCalendar?: (lunar: string, nextStateShowLunar: boolean) => void;
@@ -52,17 +49,6 @@ export type CalendarProProps = {
52
49
  bestPriceColor?: string;
53
50
  };
54
51
 
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
-
66
52
  export type DoubleDate = {
67
53
  first: Moment.Moment;
68
54
  second: Moment.Moment | null;
@@ -102,15 +88,6 @@ export type CalendarProRef = {
102
88
  secondDate?: Moment.Moment | null,
103
89
  tabSelected?: number,
104
90
  ) => 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;
114
91
  };
115
92
 
116
93
  export type HeaderControlRef = {
@@ -134,23 +111,16 @@ export type MonthListProps = {
134
111
  endDate: Moment.Moment;
135
112
  isShowLunar: boolean;
136
113
  tabSelected?: number;
137
- today: Moment.Moment;
138
114
  onChoose: (day: Moment.Moment) => void;
139
115
  onScrollCalendar?: (info: {
140
116
  date: Moment.Moment;
141
117
  key: string;
142
118
  currentIndex: number;
143
119
  }) => void;
144
- lunarConverter: any;
145
120
  disabledDays?: Date[];
146
121
  bestPriceColor?: string;
147
122
  };
148
123
 
149
- export type MonthListState = {
150
- data?: any;
151
- isDoubleDateMode?: boolean;
152
- };
153
-
154
124
  export type MonthListRef = {
155
125
  scrollToMonth: (date: Moment.Moment) => void;
156
126
  };
@@ -168,6 +138,8 @@ export type MonthProps = {
168
138
  isDoubleDateMode: boolean;
169
139
  disabledDays?: Date[];
170
140
  bestPriceColor?: string;
141
+ tabSelected?: number;
142
+ onChoose?: (date: Moment.Moment) => void;
171
143
  };
172
144
 
173
145
  export type DayProps = {
@@ -192,9 +164,9 @@ export type DayProps = {
192
164
  bestPriceColor?: string;
193
165
  };
194
166
 
195
- export type TabHeaderState = {
196
- active?: boolean;
197
- date?: Moment.Moment;
167
+ export type TabHeaderRef = {
168
+ updateView: (date?: Moment.Moment | Date | null, activeTab?: boolean) => void;
169
+ setActiveTab: (active: boolean) => void;
198
170
  };
199
171
 
200
172
  export type TabHeaderProps = {
@@ -205,8 +177,3 @@ export type TabHeaderProps = {
205
177
  id: number;
206
178
  disabled?: boolean;
207
179
  };
208
-
209
- export type TabHeaderRef = {
210
- updateView: (date?: Moment.Moment | null, activeTab?: boolean) => void;
211
- setActiveTab: (active: boolean) => void;
212
- };
package/LunarService.ts DELETED
@@ -1,206 +0,0 @@
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
- };