@momo-kits/calendar 0.79.6 → 0.80.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/index.tsx CHANGED
@@ -1,3 +1,482 @@
1
- import Calendar from './src/Calendar';
1
+ import React, {Component, createContext, RefObject} from 'react';
2
+ import {Dimensions, LayoutChangeEvent, ScrollView, View} from 'react-native';
3
+ import moment from 'moment';
4
+ import {
5
+ ApplicationContext,
6
+ Radius,
7
+ scaleSize,
8
+ Spacing,
9
+ Switch,
10
+ Text,
11
+ } from '@momo-kits/foundation';
12
+ import CalendarPro from './CalendarPro';
13
+ import TabHeader from './TabHeader';
14
+ import {
15
+ CalendarProps,
16
+ CalendarProRef,
17
+ CalendarState,
18
+ TabHeaderRef,
19
+ } from './types';
20
+ import styles from './styles';
2
21
 
3
- export {Calendar};
22
+ const DOUBLE = 'doubleDate';
23
+ const SINGLE = 'singleDate';
24
+
25
+ export const ContainerContext = createContext({width: 0, height: 0});
26
+
27
+ class Calendar extends Component<CalendarProps, CalendarState> {
28
+ static contextType = ApplicationContext;
29
+ doubleDate;
30
+ tabSelected;
31
+ selectedDate;
32
+ calendarPicker: RefObject<CalendarProRef>;
33
+ cellHeader1: RefObject<TabHeaderRef>;
34
+ cellHeader2: RefObject<TabHeaderRef>;
35
+ cellHeaderSingle: RefObject<TabHeaderRef>;
36
+ constructor(props: CalendarProps) {
37
+ super(props);
38
+ this.doubleDate = props.doubleDate
39
+ ? {
40
+ first: props.doubleDate.first ? moment(props.doubleDate.first) : null,
41
+ second: props.doubleDate.second
42
+ ? moment(props.doubleDate.second)
43
+ : null,
44
+ }
45
+ : {};
46
+ this.tabSelected = 0;
47
+
48
+ this.selectedDate = props.selectedDate
49
+ ? moment(props.selectedDate)
50
+ : moment();
51
+
52
+ this.state = {
53
+ isDoubleDateMode: props.mode === DOUBLE,
54
+ containerWidth: Dimensions.get('window').width,
55
+ };
56
+ this.calendarPicker = React.createRef<CalendarProRef>();
57
+ this.cellHeader1 = React.createRef();
58
+ this.cellHeader2 = React.createRef();
59
+ this.cellHeaderSingle = React.createRef();
60
+ }
61
+
62
+ componentDidMount() {
63
+ const {id} = this.props;
64
+ this.tabSelected = id || 0;
65
+ this.viewInit();
66
+ }
67
+
68
+ viewInit() {
69
+ const {mode} = this.props;
70
+ if (mode === DOUBLE) {
71
+ if (
72
+ this.cellHeader1.current &&
73
+ this.cellHeader2.current &&
74
+ this.calendarPicker.current
75
+ ) {
76
+ const start = this.doubleDate.first ? this.doubleDate.first : null;
77
+ const end = this.doubleDate.second ? this.doubleDate.second : null;
78
+ this.cellHeader1.current.updateView(start, this.tabSelected === 0);
79
+ this.cellHeader2.current.updateView(end, this.tabSelected === 1);
80
+ this.calendarPicker.current.setDoubleDateAndTabIndex(
81
+ this.doubleDate.first,
82
+ this.doubleDate.second,
83
+ this.tabSelected,
84
+ );
85
+ }
86
+ } else if (this.calendarPicker.current) {
87
+ this.calendarPicker.current.setDoubleDateAndTabIndex(this.selectedDate);
88
+ }
89
+ }
90
+
91
+ onChangeTab = (idTab: number) => {
92
+ this.props.onChangeTab?.(idTab);
93
+ this.tabSelected = idTab;
94
+
95
+ if (this.cellHeader1.current && this.cellHeader2.current) {
96
+ this.cellHeader1.current.setActiveTab(idTab === 0);
97
+ this.cellHeader2.current.setActiveTab(idTab === 1);
98
+ }
99
+ this.updateViewFlowPicker();
100
+ };
101
+
102
+ updateViewFlowPicker() {
103
+ if (this.calendarPicker.current) {
104
+ this.calendarPicker.current.setDoubleDateAndTabIndex(
105
+ this.doubleDate.first,
106
+ this.doubleDate.second,
107
+ this.tabSelected,
108
+ );
109
+ }
110
+ }
111
+
112
+ processDateFirst() {
113
+ const {onDateChange, onCTAStateChange} = this.props;
114
+ if (
115
+ this.cellHeader1.current &&
116
+ this.cellHeader2.current &&
117
+ this.calendarPicker.current
118
+ ) {
119
+ if (
120
+ this.doubleDate.first &&
121
+ this.doubleDate.second &&
122
+ this.selectedDate <= this.doubleDate.first
123
+ ) {
124
+ this.doubleDate.first = this.selectedDate;
125
+ this.doubleDate.second = null;
126
+ this.tabSelected = 1;
127
+ this.cellHeader1.current.updateView(
128
+ this.selectedDate,
129
+ this.tabSelected === 0,
130
+ );
131
+ this.cellHeader2.current.updateView(
132
+ this.doubleDate.second,
133
+ this.tabSelected === 1,
134
+ );
135
+ this.cellHeader2.current.setActiveTab(this.tabSelected === 1);
136
+ this.calendarPicker.current.setDoubleDateAndTabIndex(
137
+ this.doubleDate.first,
138
+ this.doubleDate.second,
139
+ this.tabSelected,
140
+ );
141
+ if (onDateChange) {
142
+ onDateChange({
143
+ first: this.doubleDate.first
144
+ ? this.doubleDate.first.toDate()
145
+ : null,
146
+ second: this.doubleDate.second
147
+ ? this.doubleDate.second.toDate()
148
+ : null,
149
+ });
150
+ }
151
+ } else {
152
+ this.doubleDate.first = this.selectedDate;
153
+ this.doubleDate.second = null;
154
+ this.cellHeader1.current.updateView(this.selectedDate, false);
155
+ this.cellHeader2.current.updateView(null, true);
156
+ this.tabSelected = 1;
157
+ this.calendarPicker.current.setDoubleDateAndTabIndex(
158
+ this.doubleDate.first,
159
+ this.doubleDate.second,
160
+ this.tabSelected,
161
+ );
162
+ if (onDateChange) {
163
+ onDateChange({
164
+ first: this.doubleDate.first
165
+ ? this.doubleDate.first.toDate()
166
+ : null,
167
+ second: this.doubleDate.second
168
+ ? this.doubleDate.second.toDate()
169
+ : null,
170
+ });
171
+ }
172
+ }
173
+ }
174
+ if (onCTAStateChange) {
175
+ onCTAStateChange(!!this.doubleDate.second);
176
+ }
177
+ }
178
+
179
+ processDateSecond() {
180
+ const {onDateChange, onCTAStateChange} = this.props;
181
+ if (
182
+ this.cellHeader2.current &&
183
+ this.selectedDate >= this.doubleDate.first
184
+ ) {
185
+ this.doubleDate.second = this.selectedDate;
186
+ this.cellHeader2.current.updateView(this.selectedDate, false);
187
+ this.cellHeader1?.current?.setActiveTab(true);
188
+ this.tabSelected = 0;
189
+ this.calendarPicker?.current?.setDoubleDateAndTabIndex(
190
+ this.doubleDate.first,
191
+ this.doubleDate.second,
192
+ this.tabSelected,
193
+ );
194
+ if (onCTAStateChange) {
195
+ onCTAStateChange(!!this.doubleDate.second);
196
+ }
197
+ if (onDateChange) {
198
+ onDateChange({
199
+ first: this.doubleDate.first ? this.doubleDate.first.toDate() : null,
200
+ second: this.doubleDate.second
201
+ ? this.doubleDate.second.toDate()
202
+ : null,
203
+ });
204
+ }
205
+ } else {
206
+ this.doubleDate.first = this.selectedDate;
207
+ this.doubleDate.second = null;
208
+
209
+ this.cellHeader1?.current?.updateView(this.selectedDate, false);
210
+ this.cellHeader2?.current?.updateView(null, false);
211
+ }
212
+ }
213
+
214
+ processDoubleDate() {
215
+ if (this.tabSelected === 0) {
216
+ this.processDateFirst();
217
+ } else {
218
+ this.processDateSecond();
219
+ }
220
+ }
221
+
222
+ updateView() {
223
+ const {onDateChange} = this.props;
224
+ const {isDoubleDateMode} = this.state;
225
+
226
+ if (isDoubleDateMode) {
227
+ this.processDoubleDate();
228
+ } else {
229
+ if (this.cellHeaderSingle.current) {
230
+ this.cellHeaderSingle.current.updateView(this.selectedDate, true);
231
+ }
232
+ if (onDateChange) {
233
+ const date = new Date(this.selectedDate.toDate());
234
+ onDateChange(date);
235
+ }
236
+ }
237
+ }
238
+
239
+ onDateChange = (date: moment.Moment) => {
240
+ this.selectedDate = date;
241
+ this.updateView();
242
+ };
243
+
244
+ updateHeaderView = () => {
245
+ const {onDateChange, onCTAStateChange} = this.props;
246
+ const {isDoubleDateMode} = this.state;
247
+ if (isDoubleDateMode) {
248
+ if (this.cellHeader1.current && this.cellHeader2.current) {
249
+ this.cellHeader1.current.updateView(this.selectedDate, true);
250
+ this.cellHeader2.current.updateView(null, false);
251
+ this.calendarPicker.current?.setDoubleDateAndTabIndex(
252
+ this.selectedDate,
253
+ null,
254
+ this.tabSelected,
255
+ );
256
+ this.doubleDate.first = moment(this.selectedDate);
257
+ this.doubleDate.second = null;
258
+
259
+ this.tabSelected = 1;
260
+ this.cellHeader2.current?.setActiveTab(true);
261
+ this.cellHeader1.current?.setActiveTab(false);
262
+ this.calendarPicker?.current?.setDoubleDateAndTabIndex(
263
+ this.doubleDate.first,
264
+ this.doubleDate.second,
265
+ this.tabSelected,
266
+ );
267
+
268
+ if (onCTAStateChange) {
269
+ onCTAStateChange(false);
270
+ }
271
+ if (onDateChange) {
272
+ onDateChange({
273
+ first: this.doubleDate.first
274
+ ? this.doubleDate.first.toDate()
275
+ : null,
276
+ second: this.doubleDate.second
277
+ ? this.doubleDate.second.toDate()
278
+ : null,
279
+ });
280
+ }
281
+ }
282
+ } else {
283
+ if (onCTAStateChange) {
284
+ onCTAStateChange(true);
285
+ }
286
+ if (this.cellHeaderSingle.current) {
287
+ if (this.doubleDate.first) {
288
+ this.cellHeaderSingle.current.updateView(this.doubleDate.first, true);
289
+ this.selectedDate = this.doubleDate.first;
290
+ } else {
291
+ this.cellHeaderSingle.current.updateView(this.selectedDate, true);
292
+ }
293
+ if (onDateChange) {
294
+ onDateChange(this.selectedDate.toDate());
295
+ }
296
+ }
297
+ }
298
+ };
299
+
300
+ toggleSelectionDateMode = () => {
301
+ const {onCallbackCalendar} = this.props;
302
+ this.setState(
303
+ preState => ({isDoubleDateMode: !preState.isDoubleDateMode}),
304
+ () => {
305
+ const {isDoubleDateMode} = this.state;
306
+ this.updateHeaderView();
307
+ if (onCallbackCalendar && typeof onCallbackCalendar === 'function') {
308
+ onCallbackCalendar('switch', isDoubleDateMode);
309
+ }
310
+ },
311
+ );
312
+ };
313
+
314
+ renderSwitchReturnSelection = () => {
315
+ const {isDoubleDateMode} = this.state;
316
+ const {translate, theme} = this.context;
317
+ return (
318
+ <View style={styles.headerContainer}>
319
+ <View
320
+ style={[
321
+ styles.viewSwitch,
322
+ {backgroundColor: theme.colors.background.surface},
323
+ ]}>
324
+ <Text typography={'label_default'}>
325
+ {translate('chooseRoundtrip')}
326
+ </Text>
327
+ <Switch
328
+ value={isDoubleDateMode}
329
+ onChange={this.toggleSelectionDateMode}
330
+ />
331
+ </View>
332
+ </View>
333
+ );
334
+ };
335
+
336
+ renderHeaderPanel = (theme: {colors: {background: {default: string}}}) => {
337
+ const {isDoubleDateMode} = this.state;
338
+ const {headerFrom, headerTo} = this.props;
339
+ return isDoubleDateMode ? (
340
+ <View
341
+ style={[
342
+ styles.viewPanel,
343
+ {backgroundColor: theme.colors.background.default},
344
+ ]}>
345
+ <TabHeader
346
+ id={0}
347
+ ref={this.cellHeader1}
348
+ onChangeTab={this.onChangeTab}
349
+ label={headerFrom || 'depart'}
350
+ activeTab
351
+ date={this.doubleDate.first}
352
+ />
353
+ <View style={{width: 4, height: '100%'}} />
354
+ <TabHeader
355
+ id={1}
356
+ ref={this.cellHeader2}
357
+ onChangeTab={this.onChangeTab}
358
+ label={headerTo || 'return'}
359
+ activeTab={false}
360
+ date=""
361
+ />
362
+ </View>
363
+ ) : (
364
+ <View
365
+ style={[
366
+ styles.viewPanel,
367
+ {backgroundColor: theme.colors.background.default},
368
+ ]}>
369
+ <TabHeader
370
+ id={0}
371
+ disabled
372
+ ref={this.cellHeaderSingle}
373
+ label={headerFrom || 'depart'}
374
+ activeTab
375
+ date={this.selectedDate}
376
+ />
377
+ </View>
378
+ );
379
+ };
380
+
381
+ setDateRange = (
382
+ dateRange: {
383
+ startDate: moment.Moment | undefined;
384
+ endDate: moment.Moment | undefined;
385
+ },
386
+ isScrollToStartDate: any,
387
+ ) => {
388
+ const {mode, doubleDate = {}} = this.props;
389
+ if (mode === 'doubleDate') {
390
+ this.cellHeader1?.current?.updateView(
391
+ dateRange.startDate,
392
+ this.tabSelected === 0,
393
+ );
394
+ this.cellHeader2?.current?.updateView(
395
+ dateRange.endDate,
396
+ this.tabSelected === 1,
397
+ );
398
+ this.calendarPicker?.current?.setDateRange(
399
+ dateRange,
400
+ isScrollToStartDate,
401
+ );
402
+ this.doubleDate = doubleDate
403
+ ? {
404
+ first: dateRange.startDate ? moment(dateRange.startDate) : null,
405
+ second: dateRange.endDate ? moment(dateRange.endDate) : null,
406
+ }
407
+ : {};
408
+ }
409
+ };
410
+
411
+ onLayout = (e: LayoutChangeEvent) => {
412
+ this.setState({containerWidth: e.nativeEvent.layout.width});
413
+ };
414
+
415
+ render() {
416
+ const currentDate = new Date();
417
+ const minDateDefault = new Date(currentDate);
418
+ const maxDateDefault = new Date(currentDate);
419
+ minDateDefault.setFullYear(minDateDefault.getFullYear() - 1);
420
+ maxDateDefault.setFullYear(maxDateDefault.getFullYear() + 1);
421
+
422
+ const {
423
+ isOffLunar,
424
+ isHideHoliday,
425
+ isHiddenSwitch,
426
+ isShowLunar,
427
+ onCallbackCalendar,
428
+ priceList,
429
+ labelFrom,
430
+ labelTo,
431
+ isHideLabel,
432
+ minDate,
433
+ maxDate,
434
+ doubleDate,
435
+ isHideHeaderPanel,
436
+ style,
437
+ disabledDays = [],
438
+ } = this.props;
439
+ const {isDoubleDateMode, containerWidth} = this.state;
440
+ const {theme} = this.context;
441
+ return (
442
+ <ContainerContext.Provider
443
+ value={{
444
+ width: containerWidth,
445
+ height: priceList ? scaleSize(48) : scaleSize(34),
446
+ }}>
447
+ <View onLayout={this.onLayout} style={[style, styles.scrollView]}>
448
+ <View
449
+ style={{
450
+ backgroundColor: theme.colors.background.surface,
451
+ borderRadius: Radius.XS,
452
+ marginBottom: Spacing.S,
453
+ }}>
454
+ {!isHiddenSwitch && this.renderSwitchReturnSelection()}
455
+ {!isHideHeaderPanel && this.renderHeaderPanel(theme)}
456
+ </View>
457
+ <CalendarPro
458
+ priceList={priceList}
459
+ ref={this.calendarPicker}
460
+ startDate={doubleDate?.first}
461
+ endDate={doubleDate?.second}
462
+ onDateChange={this.onDateChange}
463
+ isDoubleDateMode={isDoubleDateMode}
464
+ selectedDate={this.selectedDate}
465
+ isShowLunar={isShowLunar}
466
+ onCallbackCalendar={onCallbackCalendar}
467
+ labelFrom={labelFrom}
468
+ labelTo={labelTo}
469
+ isHideLabel={isHideLabel}
470
+ minDate={minDate}
471
+ maxDate={maxDate}
472
+ isHideHoliday={isHideHoliday}
473
+ isOffLunar={isOffLunar}
474
+ disabledDays={disabledDays}
475
+ />
476
+ </View>
477
+ </ContainerContext.Provider>
478
+ );
479
+ }
480
+ }
481
+
482
+ export default Calendar;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/calendar",
3
- "version": "0.79.6",
3
+ "version": "0.80.2",
4
4
  "private": false,
5
5
  "main": "index.tsx",
6
6
  "peerDependencies": {
package/styles.ts ADDED
@@ -0,0 +1,115 @@
1
+ import {StyleSheet} from 'react-native';
2
+ import {Colors, Radius, scaleSize, Spacing} from '@momo-kits/foundation';
3
+
4
+ export default StyleSheet.create({
5
+ //calendar
6
+ viewPanel: {
7
+ flexDirection: 'row',
8
+ marginHorizontal: Spacing.M,
9
+ marginVertical: Spacing.S,
10
+ borderRadius: Radius.S,
11
+ padding: Spacing.XXS,
12
+ },
13
+ viewSwitch: {
14
+ flexDirection: 'row',
15
+ justifyContent: 'space-between',
16
+ alignItems: 'center',
17
+ marginBottom: Spacing.XS,
18
+ },
19
+ headerContainer: {
20
+ paddingHorizontal: Spacing.M,
21
+ marginTop: Spacing.S,
22
+ },
23
+ scrollView: {
24
+ backgroundColor: 'transparent',
25
+ alignSelf: 'center',
26
+ width: '100%',
27
+ },
28
+
29
+ //calendar pro
30
+ row: {flexDirection: 'row'},
31
+ txtMonthLunar: {
32
+ marginRight: Spacing.S,
33
+ },
34
+ subTextLunar: {
35
+ marginRight: Spacing.XS,
36
+ },
37
+ contentScroll: {
38
+ paddingHorizontal: Spacing.M,
39
+ paddingTop: Spacing.S,
40
+ paddingBottom: Spacing.M,
41
+ },
42
+ viewLunar: {
43
+ flexDirection: 'row',
44
+ alignItems: 'center',
45
+ marginHorizontal: Spacing.M,
46
+ borderTopWidth: 1,
47
+ paddingVertical: Spacing.S,
48
+ },
49
+ textDay: {
50
+ textAlign: 'center',
51
+ },
52
+ viewDay: {
53
+ flexDirection: 'row',
54
+ justifyContent: 'space-between',
55
+ paddingHorizontal: Spacing.S,
56
+ paddingVertical: Spacing.S,
57
+ marginTop: Spacing.S,
58
+ },
59
+ container: {
60
+ backgroundColor: 'white',
61
+ borderRadius: Radius.XS,
62
+ },
63
+ blueSeperator: {
64
+ height: 1,
65
+ width: '100%',
66
+ backgroundColor: Colors.blue_05,
67
+ },
68
+
69
+ //headerControl
70
+ txtHeader: {
71
+ textAlign: 'center',
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
+ },
85
+ headerControlContainer: {
86
+ flexDirection: 'row',
87
+ justifyContent: 'space-between',
88
+ backgroundColor: Colors.blue_10,
89
+ alignItems: 'center',
90
+ borderRadius: Radius.XS,
91
+ padding: Spacing.S,
92
+ },
93
+
94
+ //day
95
+ dayContainer: {
96
+ borderRadius: Radius.XS,
97
+ alignItems: 'center',
98
+ },
99
+ day: {
100
+ justifyContent: 'center',
101
+ alignItems: 'center',
102
+ borderRadius: Radius.XS,
103
+ },
104
+ dayText: {
105
+ textAlign: 'center',
106
+ },
107
+ dayStartContainer: {
108
+ borderTopLeftRadius: Radius.XS,
109
+ borderBottomLeftRadius: Radius.XS,
110
+ },
111
+ dayEndContainer: {
112
+ borderTopRightRadius: Radius.XS,
113
+ borderBottomRightRadius: Radius.XS,
114
+ },
115
+ });