@cleartrip/ct-design-calendar 4.0.0 → 5.0.0

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.
Files changed (119) hide show
  1. package/dist/Arrow/LeftArrow.d.ts +3 -0
  2. package/dist/Arrow/LeftArrow.d.ts.map +1 -0
  3. package/dist/Arrow/RightArrow.d.ts +3 -0
  4. package/dist/Arrow/RightArrow.d.ts.map +1 -0
  5. package/dist/BaseCalendar.d.ts +4 -0
  6. package/dist/BaseCalendar.d.ts.map +1 -0
  7. package/dist/Calendar.d.ts +4 -0
  8. package/dist/Calendar.d.ts.map +1 -0
  9. package/dist/Calendar.native.d.ts +4 -0
  10. package/dist/Calendar.native.d.ts.map +1 -0
  11. package/dist/CalendarBody/LazyMonthList.d.ts +4 -0
  12. package/dist/CalendarBody/LazyMonthList.d.ts.map +1 -0
  13. package/dist/CalendarBody/PlaceholderMonth.d.ts +5 -0
  14. package/dist/CalendarBody/PlaceholderMonth.d.ts.map +1 -0
  15. package/dist/CalendarBody/index.d.ts +4 -0
  16. package/dist/CalendarBody/index.d.ts.map +1 -0
  17. package/dist/CalendarDayElements/CalendarDate.d.ts +4 -0
  18. package/dist/CalendarDayElements/CalendarDate.d.ts.map +1 -0
  19. package/dist/CalendarDayElements/CalendarDot.d.ts +4 -0
  20. package/dist/CalendarDayElements/CalendarDot.d.ts.map +1 -0
  21. package/dist/CalendarDayElements/CalendarDotWrapper.d.ts +5 -0
  22. package/dist/CalendarDayElements/CalendarDotWrapper.d.ts.map +1 -0
  23. package/dist/CalendarDayElements/CalendarRange.d.ts +4 -0
  24. package/dist/CalendarDayElements/CalendarRange.d.ts.map +1 -0
  25. package/dist/CalendarDayElements/index.d.ts +4 -0
  26. package/dist/CalendarDayElements/index.d.ts.map +1 -0
  27. package/dist/CalendarDayElements/useForceRerender.d.ts +5 -0
  28. package/dist/CalendarDayElements/useForceRerender.d.ts.map +1 -0
  29. package/dist/CalendarMonth/CalendarMonthBody.d.ts +4 -0
  30. package/dist/CalendarMonth/CalendarMonthBody.d.ts.map +1 -0
  31. package/dist/CalendarMonth/CalendarMonthFooter.d.ts +5 -0
  32. package/dist/CalendarMonth/CalendarMonthFooter.d.ts.map +1 -0
  33. package/dist/CalendarMonth/CalendarMonthHeader.d.ts +4 -0
  34. package/dist/CalendarMonth/CalendarMonthHeader.d.ts.map +1 -0
  35. package/dist/CalendarMonth/index.d.ts +12 -0
  36. package/dist/CalendarMonth/index.d.ts.map +1 -0
  37. package/dist/Caption/index.d.ts +4 -0
  38. package/dist/Caption/index.d.ts.map +1 -0
  39. package/dist/DayPicker.d.ts +62 -0
  40. package/dist/DayPicker.d.ts.map +1 -0
  41. package/dist/Footer/CheckinCheckout.d.ts +11 -0
  42. package/dist/Footer/CheckinCheckout.d.ts.map +1 -0
  43. package/dist/Footer/LongWeekend.d.ts +5 -0
  44. package/dist/Footer/LongWeekend.d.ts.map +1 -0
  45. package/dist/Footer/constants.d.ts +7 -0
  46. package/dist/Footer/constants.d.ts.map +1 -0
  47. package/dist/Footer/index.d.ts +14 -0
  48. package/dist/Footer/index.d.ts.map +1 -0
  49. package/dist/WeekDays.d.ts +3 -0
  50. package/dist/WeekDays.d.ts.map +1 -0
  51. package/dist/constants.d.ts +13 -0
  52. package/dist/constants.d.ts.map +1 -0
  53. package/dist/ct-design-calendar.browser.cjs.js +2 -0
  54. package/dist/ct-design-calendar.browser.cjs.js.map +1 -0
  55. package/dist/ct-design-calendar.browser.esm.js +2 -0
  56. package/dist/ct-design-calendar.browser.esm.js.map +1 -0
  57. package/dist/ct-design-calendar.cjs.js +67 -0
  58. package/dist/ct-design-calendar.cjs.js.map +1 -0
  59. package/dist/ct-design-calendar.esm.js +61 -0
  60. package/dist/ct-design-calendar.esm.js.map +1 -0
  61. package/dist/ct-design-calendar.umd.js +70 -0
  62. package/dist/ct-design-calendar.umd.js.map +1 -0
  63. package/dist/event/EventEmitter/index.d.ts +10 -0
  64. package/dist/event/EventEmitter/index.d.ts.map +1 -0
  65. package/dist/event/EventEmitter/type.d.ts +10 -0
  66. package/dist/event/EventEmitter/type.d.ts.map +1 -0
  67. package/dist/event/constants.d.ts +6 -0
  68. package/dist/event/constants.d.ts.map +1 -0
  69. package/dist/event/index.d.ts +8 -0
  70. package/dist/event/index.d.ts.map +1 -0
  71. package/dist/globalStyle.d.ts +2 -0
  72. package/dist/globalStyle.d.ts.map +1 -0
  73. package/dist/index.d.ts +4 -0
  74. package/dist/index.d.ts.map +1 -0
  75. package/dist/style.d.ts +2 -0
  76. package/dist/style.d.ts.map +1 -0
  77. package/dist/styles.d.ts +570 -0
  78. package/dist/styles.d.ts.map +1 -0
  79. package/dist/type.d.ts +58 -0
  80. package/dist/type.d.ts.map +1 -0
  81. package/dist/util.d.ts +22 -0
  82. package/dist/util.d.ts.map +1 -0
  83. package/package.json +32 -5
  84. package/src/Arrow/LeftArrow.tsx +13 -0
  85. package/src/Arrow/RightArrow.tsx +13 -0
  86. package/src/BaseCalendar.tsx +189 -0
  87. package/src/Calendar.native.tsx +99 -0
  88. package/src/Calendar.tsx +13 -0
  89. package/src/CalendarBody/LazyMonthList.tsx +45 -0
  90. package/src/CalendarBody/PlaceholderMonth.tsx +20 -0
  91. package/src/CalendarBody/index.tsx +159 -0
  92. package/src/CalendarDayElements/CalendarDate.tsx +34 -0
  93. package/src/CalendarDayElements/CalendarDot.tsx +11 -0
  94. package/src/CalendarDayElements/CalendarDotWrapper.tsx +17 -0
  95. package/src/CalendarDayElements/CalendarRange.tsx +54 -0
  96. package/src/CalendarDayElements/index.tsx +77 -0
  97. package/src/CalendarDayElements/useForceRerender.ts +14 -0
  98. package/src/CalendarMonth/CalendarMonthBody.tsx +39 -0
  99. package/src/CalendarMonth/CalendarMonthFooter.tsx +70 -0
  100. package/src/CalendarMonth/CalendarMonthHeader.tsx +15 -0
  101. package/src/CalendarMonth/index.tsx +43 -0
  102. package/src/Caption/index.tsx +39 -0
  103. package/src/DayPicker.tsx +324 -0
  104. package/src/Footer/CheckinCheckout.tsx +196 -0
  105. package/src/Footer/LongWeekend.tsx +98 -0
  106. package/src/Footer/constants.ts +7 -0
  107. package/src/Footer/index.tsx +84 -0
  108. package/src/WeekDays.tsx +20 -0
  109. package/src/constants.ts +54 -0
  110. package/src/event/EventEmitter/index.ts +34 -0
  111. package/src/event/EventEmitter/type.ts +10 -0
  112. package/src/event/constants.ts +5 -0
  113. package/src/event/index.tsx +21 -0
  114. package/src/globalStyle.ts +351 -0
  115. package/src/index.ts +3 -0
  116. package/src/style.ts +333 -0
  117. package/src/styles.ts +167 -0
  118. package/src/type.ts +66 -0
  119. package/src/util.ts +114 -0
package/dist/util.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ export declare const PAST_DATE = "2000-01-01";
2
+ export declare const DAY_MILLISECONDS: number;
3
+ export declare const TODAY_DATE: string;
4
+ export declare const MONTHS: string[];
5
+ export declare const ELEMENTS_HEIGHT: {
6
+ HEADING: number;
7
+ DATE: number;
8
+ FOOTER: number;
9
+ HOLIDAY: number;
10
+ };
11
+ export declare const DAY_LIST: {
12
+ day: string;
13
+ isWeekend: boolean;
14
+ }[];
15
+ export declare const formattedDate: (year: string, month: string, day: string) => string;
16
+ export declare const getWeekRow: (year: number, month: number) => number[][];
17
+ export declare const getMonthArray: (startMonth: number, startYear: number) => {
18
+ month: string;
19
+ year: string;
20
+ }[];
21
+ export declare const getDateDifference: (date1: string, date2: string) => number;
22
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../packages/components/Calendar/src/util.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,eAAe,CAAC;AAEtC,eAAO,MAAM,gBAAgB,QAAsB,CAAC;AAEpD,eAAO,MAAM,UAAU,QAA4D,CAAC;AAEpF,eAAO,MAAM,MAAM,UAalB,CAAC;AAEF,eAAO,MAAM,eAAe;;;;;CAK3B,CAAC;AAEF,eAAO,MAAM,QAAQ;;;GA6BpB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,EAAE,OAAO,MAAM,EAAE,KAAK,MAAM,WAKrE,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,EAAE,OAAO,MAAM,eAwBrD,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,YAAY,MAAM,EAAE,WAAW,MAAM;WAC1C,MAAM;UAAQ,MAAM;GAc5C,CAAC;AACF,eAAO,MAAM,iBAAiB,GAAI,OAAO,MAAM,EAAE,OAAO,MAAM,WAK7D,CAAC"}
package/package.json CHANGED
@@ -1,21 +1,44 @@
1
1
  {
2
2
  "name": "@cleartrip/ct-design-calendar",
3
- "version": "4.0.0",
3
+ "version": "5.0.0",
4
4
  "description": "Calendar Component",
5
5
  "types": "dist/index.d.ts",
6
- "main": "dist/ct-design-calendar.cjs.js",
6
+ "main": "./dist/ct-design-calendar.cjs.js",
7
7
  "jsnext:main": "dist/ct-design-calendar.esm.js",
8
+ "react-native": "src/index.ts",
8
9
  "module": "dist/ct-design-calendar.esm.js",
9
10
  "sideEffects": false,
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/ct-design-calendar.esm.js",
15
+ "default": "./dist/ct-design-calendar.cjs.js"
16
+ }
17
+ },
10
18
  "browser": {
11
19
  "./dist/ct-design-calendar.esm.js": "./dist/ct-design-calendar.browser.esm.js",
12
20
  "./dist/ct-design-calendar.cjs.js": "./dist/ct-design-calendar.browser.cjs.js"
13
21
  },
14
22
  "files": [
15
- "dist"
23
+ "dist",
24
+ "src"
16
25
  ],
17
26
  "dependencies": {
18
- "@cleartrip/ct-design-container": "4.0.0"
27
+ "react-day-picker": "8.8.1",
28
+ "react-tiny-virtual-list": "2.2.0",
29
+ "@cleartrip/ct-design-container": "5.0.0",
30
+ "@cleartrip/ct-design-theme": "5.0.0",
31
+ "@cleartrip/ct-design-accordion": "5.0.0",
32
+ "@cleartrip/ct-design-button": "5.0.0",
33
+ "@cleartrip/ct-design-badge": "5.0.0",
34
+ "@cleartrip/ct-design-typography": "5.0.0",
35
+ "@cleartrip/ct-design-icons": "5.0.0",
36
+ "@cleartrip/ct-design-common-utils": "5.0.0",
37
+ "@cleartrip/ct-design-style-manager": "5.0.0",
38
+ "@cleartrip/ct-design-types": "5.0.0",
39
+ "@cleartrip/ct-design-use-isomorphic-effect": "5.0.0",
40
+ "@cleartrip/ct-design-common-constants": "5.0.0",
41
+ "@cleartrip/ct-design-spacer": "5.0.0"
19
42
  },
20
43
  "devDependencies": {},
21
44
  "peerDependencies": {
@@ -30,6 +53,10 @@
30
53
  "license": "ISC",
31
54
  "scripts": {
32
55
  "test": "echo \"Error: no test specified\" && exit 1",
33
- "build-package-p": "echo \"TODO: Need to fix calendar\""
56
+ "watch-package": "rollup -c -w",
57
+ "build-package": "rollup -c",
58
+ "build-package:clean": "rm -rf dist && rollup -c",
59
+ "publish-package:local": "yalc publish --no-scripts",
60
+ "publish-package:local:registry": "pnpm publish --registry http://localhost:4873 --no-git-checks --access public"
34
61
  }
35
62
  }
@@ -0,0 +1,13 @@
1
+ import { SVGProps } from 'react';
2
+
3
+ export function LeftArrow(props: SVGProps<SVGSVGElement>) {
4
+ return (
5
+ <svg viewBox='0 0 20 20' {...props}>
6
+ <path
7
+ d='M9.131 2L2.215 9.446a.821.821 0 00-.077 1.01l.077.098L9.131 18l1.106-1.108-5.67-6.106 13.43.02L18 9.21 4.586 9.19l5.65-6.082L9.132 2z'
8
+ fill='currentColor'
9
+ fillRule='nonzero'
10
+ />
11
+ </svg>
12
+ );
13
+ }
@@ -0,0 +1,13 @@
1
+ import { SVGProps } from 'react';
2
+
3
+ export function RightArrow(props: SVGProps<SVGSVGElement>) {
4
+ return (
5
+ <svg viewBox='0 0 20 20' {...props}>
6
+ <path
7
+ d='M10.869 2l6.916 7.446a.821.821 0 01.077 1.01l-.077.098L10.869 18l-1.106-1.108 5.67-6.106-13.43.02L2 9.21l13.414-.02-5.65-6.082L10.868 2z'
8
+ fill='currentColor'
9
+ fillRule='nonzero'
10
+ />
11
+ </svg>
12
+ );
13
+ }
@@ -0,0 +1,189 @@
1
+ import { useLayoutEffect, useRef, useState } from 'react';
2
+ import dayjs from 'dayjs';
3
+ import { WEEK_DAY_LABEL } from '@cleartrip/ct-design-common-constants';
4
+ import { Container } from '@cleartrip/ct-design-container';
5
+ import { makeStyles, useStyles } from '@cleartrip/ct-design-style-manager';
6
+
7
+ import MobileCalendar, { DateRangeProps } from './DayPicker';
8
+
9
+ import useIsomorphicEffect from '@cleartrip/ct-design-use-isomorphic-effect';
10
+ import { ViewStyle } from '@cleartrip/ct-design-types';
11
+
12
+ const staticStyles = makeStyles((theme) => ({
13
+ outerWrapper: {
14
+ display: 'flex',
15
+ flexWrap: 'wrap',
16
+ },
17
+ weekDayHeader: {
18
+ display: 'flex',
19
+ alignItems: 'center',
20
+ justifyContent: 'center',
21
+ top: -1,
22
+ zIndex: 999,
23
+ paddingTop: theme.spacing[4],
24
+ paddingBottom: theme.spacing[4],
25
+ position: 'sticky' as ViewStyle['position'],
26
+ backgroundColor: theme.color.background.neutral,
27
+ height: 26,
28
+ borderBottom: `1px dotted ${theme.color.border.default}`,
29
+ },
30
+ weekDayItem: {
31
+ display: 'flex',
32
+ justifyContent: 'center',
33
+ },
34
+ weekendColor: {
35
+ // Add weekend specific styling if needed
36
+ // This can be enhanced based on design requirements
37
+ },
38
+ }));
39
+
40
+ const Calendar = ({
41
+ onDateSelect,
42
+ noOfMonths,
43
+ mode,
44
+ customHeader,
45
+ onDayClick,
46
+ selectedDays,
47
+ disabledDays: disabledDaysProp,
48
+ defaultMonth,
49
+ modifiers,
50
+ modifierStyles,
51
+ footer,
52
+ customDay,
53
+ customSelectedDayProps,
54
+ asyncInitialScroll = false,
55
+ }: DateRangeProps) => {
56
+ const today = new Date();
57
+
58
+ const disabledDays = disabledDaysProp ?? [{ before: today }];
59
+
60
+ const elementRef = useRef<HTMLDivElement>(null);
61
+
62
+ const [width, setWidth] = useState(0);
63
+
64
+ const containerRef = useRef<HTMLDivElement>(null);
65
+
66
+ const isInitialViewScrolled = useRef(false);
67
+
68
+ const getInitialDefaultDate = () => {
69
+ if (selectedDays && 'from' in selectedDays) {
70
+ const { from, to } = selectedDays;
71
+ if (from !== to) {
72
+ return from;
73
+ }
74
+ return undefined;
75
+ }
76
+ return selectedDays;
77
+ };
78
+
79
+ const initialDate = getInitialDefaultDate();
80
+
81
+ useIsomorphicEffect(() => {
82
+ let scrollTimeout: NodeJS.Timeout;
83
+ const scrollToSelectedRange = () => {
84
+ if (initialDate && containerRef.current) {
85
+ const targetMonthNode = containerRef.current.querySelector(`#Calendar${initialDate.getMonth()}`);
86
+ // Scroll the target month into view
87
+ if (targetMonthNode) {
88
+ targetMonthNode.scrollIntoView({
89
+ block: 'center',
90
+ });
91
+ isInitialViewScrolled.current = true;
92
+ }
93
+ }
94
+ };
95
+ // Scroll to view only once when component is loaded
96
+ if (!isInitialViewScrolled.current) {
97
+ if (asyncInitialScroll) {
98
+ scrollTimeout = setTimeout(scrollToSelectedRange);
99
+ } else {
100
+ scrollToSelectedRange();
101
+ }
102
+ }
103
+ return () => {
104
+ if (scrollTimeout) {
105
+ clearTimeout(scrollTimeout);
106
+ }
107
+ };
108
+ }, [selectedDays, containerRef.current]);
109
+
110
+ useLayoutEffect(() => {
111
+ if (elementRef?.current) {
112
+ setWidth(elementRef.current.clientWidth);
113
+ }
114
+ }, []);
115
+
116
+ const dayDimension = width / 7;
117
+
118
+ const dynamicStyles = useStyles(
119
+ () => ({
120
+ weekDayItem: {
121
+ maxWidth: dayDimension,
122
+ width: width / 7,
123
+ },
124
+ weekendItem: {
125
+ maxWidth: dayDimension,
126
+ width: width / 7,
127
+ // Add weekend specific styling here if needed
128
+ // color: theme.color.text.secondary, // example
129
+ },
130
+ }),
131
+ [dayDimension, width],
132
+ );
133
+
134
+ /**
135
+ * @todo Om To get the MobileCalendar component render here itself
136
+ *
137
+ */
138
+
139
+ return (
140
+ <div ref={elementRef}>
141
+ {width > 0 && (
142
+ <Container styleConfig={{ root: [staticStyles.outerWrapper] }}>
143
+ <Container styleConfig={{ root: [staticStyles.weekDayHeader] }}>
144
+ {Object.keys(WEEK_DAY_LABEL).map((itm, key) => {
145
+ const isWeekend = key > 4;
146
+ return (
147
+ <Container
148
+ key={key}
149
+ styleConfig={{
150
+ root: [
151
+ staticStyles.weekDayItem,
152
+ ...(isWeekend ? [staticStyles.weekendColor] : []),
153
+ isWeekend ? dynamicStyles.weekendItem : dynamicStyles.weekDayItem,
154
+ ],
155
+ }}
156
+ >
157
+ {WEEK_DAY_LABEL[(key + 1) % 7]}
158
+ </Container>
159
+ );
160
+ })}
161
+ </Container>
162
+ <div ref={containerRef}>
163
+ <MobileCalendar
164
+ mode={mode}
165
+ noOfMonths={noOfMonths}
166
+ onDateSelect={onDateSelect}
167
+ onDayClick={onDayClick}
168
+ selectedDays={selectedDays}
169
+ disabledDays={disabledDays}
170
+ cellWidth={dayDimension}
171
+ cellHeight={dayDimension}
172
+ daySize={dayDimension}
173
+ defaultMonth={dayjs(initialDate).toDate()}
174
+ fromMonth={defaultMonth}
175
+ customHeader={customHeader}
176
+ modifiers={modifiers}
177
+ modifierStyles={modifierStyles}
178
+ footer={footer}
179
+ customDay={customDay}
180
+ customSelectedDayProps={customSelectedDayProps}
181
+ />
182
+ </div>
183
+ </Container>
184
+ )}
185
+ </div>
186
+ );
187
+ };
188
+
189
+ export default Calendar;
@@ -0,0 +1,99 @@
1
+ import { memo, useCallback, useEffect, useRef } from 'react';
2
+
3
+ import { usePubEvent } from './event';
4
+ import { makeStyles } from '@cleartrip/ct-design-style-manager';
5
+ import { View } from 'react-native';
6
+
7
+ import { ICalendarProps } from './type';
8
+ import CalendarBody from './CalendarBody';
9
+ import WeekDays from './WeekDays';
10
+
11
+ const staticCalendarStyles = makeStyles((theme) => {
12
+ return {
13
+ calendarContainer: {
14
+ backgroundColor: theme?.color.background.neutral,
15
+ },
16
+ };
17
+ });
18
+
19
+ const Calendar: React.FC<ICalendarProps> = ({
20
+ selectedDates: selectedDatesList,
21
+ handleCalendarDateClicked,
22
+ calendarDotsList,
23
+ holidayList,
24
+ }) => {
25
+ const selectedDates = [selectedDatesList[0]?.toString() || '', selectedDatesList[1]?.toString() || ''];
26
+ const selectedDatesRef = useRef<string[]>(selectedDates);
27
+
28
+ const publishDatesSelection = usePubEvent('SELECTED_DATES');
29
+
30
+ const getSelectedDates = useCallback(() => {
31
+ return selectedDatesRef.current;
32
+ }, []);
33
+
34
+ const setSelectedDate = useCallback((dates: string[]) => {
35
+ publishDatesSelection({
36
+ oldDates: selectedDatesRef.current,
37
+ newDates: dates,
38
+ });
39
+ selectedDatesRef.current = dates ?? [];
40
+ // eslint-disable-next-line react-hooks/exhaustive-deps
41
+ }, []);
42
+
43
+ const handleDateClicked = useCallback((date: string) => {
44
+ let response: string[] = [];
45
+ const reformattedDate = date.replace(/\//g, '-');
46
+ const prev = getSelectedDates();
47
+ switch (prev.filter((x) => x).length) {
48
+ case 0:
49
+ response = [date];
50
+ handleCalendarDateClicked({
51
+ checkInDate: new Date(reformattedDate),
52
+ stateDateType: 'checkOut',
53
+ });
54
+ break;
55
+ case 1:
56
+ if (date <= prev[0]) return;
57
+ response = [prev[0], date];
58
+ handleCalendarDateClicked({
59
+ checkInDate: new Date(prev[0].replace(/\//g, '-')),
60
+ checkOutDate: new Date(reformattedDate),
61
+ stateDateType: 'checkIn',
62
+ });
63
+ break;
64
+ case 2:
65
+ response = [date];
66
+ handleCalendarDateClicked({
67
+ checkInDate: new Date(reformattedDate),
68
+ stateDateType: 'checkOut',
69
+ });
70
+ break;
71
+ }
72
+ setSelectedDate(response);
73
+ // eslint-disable-next-line react-hooks/exhaustive-deps
74
+ }, []);
75
+
76
+ useEffect(() => {
77
+ const [startDate = '', endDate = ''] = selectedDatesList;
78
+ const [currStartDate = '', currEndDate = ''] = selectedDatesRef.current;
79
+ if (startDate === currStartDate && endDate === currEndDate) return;
80
+ if (!startDate) return setSelectedDate([]);
81
+ if (!endDate) return setSelectedDate([startDate]);
82
+ setSelectedDate([startDate, endDate]);
83
+ // eslint-disable-next-line react-hooks/exhaustive-deps
84
+ }, [selectedDatesList]);
85
+
86
+ return (
87
+ <View style={staticCalendarStyles?.calendarContainer}>
88
+ <WeekDays />
89
+ <CalendarBody
90
+ calendarDotsList={calendarDotsList}
91
+ getSelectedDates={getSelectedDates}
92
+ handleDateClicked={handleDateClicked}
93
+ holidayList={holidayList}
94
+ />
95
+ </View>
96
+ );
97
+ };
98
+
99
+ export default memo(Calendar);
@@ -0,0 +1,13 @@
1
+ import { Container } from '@cleartrip/ct-design-container';
2
+ import { ICalendarProps } from './type';
3
+
4
+ const CalendarComponent: React.FC<ICalendarProps> = () => {
5
+ return (
6
+ <Container>
7
+ {/* Well what you need is to to migrate src/components/home/hotelCalendarContainer/calendar.tsx
8
+ biggest challenge is mapping types from aldenui to ct-design-system*/}
9
+ </Container>
10
+ );
11
+ };
12
+
13
+ export default CalendarComponent;
@@ -0,0 +1,45 @@
1
+ import { memo, useState } from 'react';
2
+
3
+ import { InteractionManager } from 'react-native';
4
+
5
+ import PlaceholderMonth from './PlaceholderMonth';
6
+ import CalendarMonth from '../CalendarMonth';
7
+ import { ILazyMonthListProps } from '../type';
8
+
9
+ const LazyMonthList: React.FC<ILazyMonthListProps> = ({
10
+ monthList,
11
+ handleDateClicked,
12
+ getSelectedDates,
13
+ calendarDotsList,
14
+ holidayList,
15
+ monthHeightRef,
16
+ }) => {
17
+ const [rendered, setRendered] = useState(0);
18
+ return monthList.map((item, index) => {
19
+ if (index > rendered)
20
+ return (
21
+ <PlaceholderMonth
22
+ key={`lazyPlaceholderMonth-${index}`}
23
+ height={monthHeightRef.current[`${item.year}/${item.month}`]}
24
+ />
25
+ );
26
+ return (
27
+ <CalendarMonth
28
+ onLayout={() => {
29
+ InteractionManager.runAfterInteractions(() => {
30
+ if (rendered < monthList.length) setRendered((prev) => prev + 1);
31
+ });
32
+ }}
33
+ key={`preceedingMonths-${index}`}
34
+ handleDateClicked={handleDateClicked}
35
+ getSelectedDates={getSelectedDates}
36
+ month={item.month}
37
+ year={item.year}
38
+ calendarDotsList={calendarDotsList}
39
+ holidayList={holidayList}
40
+ />
41
+ );
42
+ });
43
+ };
44
+
45
+ export default memo(LazyMonthList);
@@ -0,0 +1,20 @@
1
+ import { memo } from 'react';
2
+
3
+ import { View } from 'react-native';
4
+
5
+ import { staticCalendarBodyStyle } from '../styles';
6
+
7
+ const PlaceholderMonth = ({ height }: { height: number }) => {
8
+ return (
9
+ <View
10
+ style={[
11
+ staticCalendarBodyStyle?.placeholderMonthContainer,
12
+ {
13
+ height: height,
14
+ },
15
+ ]}
16
+ />
17
+ );
18
+ };
19
+
20
+ export default memo(PlaceholderMonth);
@@ -0,0 +1,159 @@
1
+ import { memo, useEffect, useRef, useState } from 'react';
2
+
3
+ import { InteractionManager, ScrollView, View } from 'react-native';
4
+ import { useSubEvent } from '../event';
5
+
6
+ import CalendarMonth from '../CalendarMonth';
7
+ import { ELEMENTS_HEIGHT, formattedDate, getMonthArray, getWeekRow } from '../util';
8
+ import { ICalendarBodyProps, IMonthListObj } from '../type';
9
+ import { staticCalendarBodyStyle } from '../styles';
10
+ import LazyMonthList from './LazyMonthList';
11
+ import PlaceholderMonth from './PlaceholderMonth';
12
+
13
+ const CalendarBody: React.FC<ICalendarBodyProps> = ({
14
+ getSelectedDates,
15
+ handleDateClicked,
16
+ calendarDotsList,
17
+ holidayList,
18
+ }) => {
19
+ const [show, setShow] = useState(false);
20
+ const [isScrollAnimated, setIsScrollAnimated] = useState<boolean>(false);
21
+ const monthHeightRef = useRef<Record<string, number>>({});
22
+ const scrollViewRef = useRef<ScrollView>(null);
23
+ const currentDate = new Date();
24
+ const currentDay = currentDate.getDate();
25
+ const currentMonth = currentDate.getMonth() + 1;
26
+ const currentYear = currentDate.getFullYear();
27
+ const allMonths: IMonthListObj[] = getMonthArray(currentMonth, currentYear);
28
+
29
+ const getCalendarParts = () => {
30
+ const startDate =
31
+ getSelectedDates() && getSelectedDates().length > 0
32
+ ? getSelectedDates()[0]
33
+ : formattedDate(currentYear.toString(), currentMonth.toString(), currentDay.toString());
34
+ let preceedingMonths: IMonthListObj[] = [];
35
+ let activeMonths: IMonthListObj[] = [];
36
+ let followingMonths: IMonthListObj[] = [];
37
+
38
+ if (getSelectedDates() && getSelectedDates().length > 0) {
39
+ const startMonthIndex = (12 + parseInt(startDate.split('/')[1]) - currentMonth) % 12;
40
+ preceedingMonths = allMonths.slice(0, startMonthIndex);
41
+ activeMonths = allMonths.slice(startMonthIndex, startMonthIndex + 2);
42
+ followingMonths = allMonths.slice(startMonthIndex + 2);
43
+ } else {
44
+ activeMonths = allMonths.slice(0, 2);
45
+ followingMonths = allMonths.slice(2);
46
+ }
47
+ return { preceedingMonths, activeMonths, followingMonths };
48
+ };
49
+
50
+ const { preceedingMonths, activeMonths, followingMonths } = getCalendarParts();
51
+ const [renderedMonths, setRenderedMonths] = useState(0);
52
+
53
+ const storeMonthHeights = () => {
54
+ allMonths.forEach((item) => {
55
+ const rowCount = getWeekRow(parseInt(item.year), parseInt(item.month)).length;
56
+ monthHeightRef.current[`${item.year}/${item.month}`] =
57
+ rowCount * ELEMENTS_HEIGHT.DATE + ELEMENTS_HEIGHT.HEADING + ELEMENTS_HEIGHT.FOOTER;
58
+ });
59
+ };
60
+
61
+ function getWeekOfMonth(dateString: string) {
62
+ const [year, month, day] = dateString.split(/[-/]/).map(Number);
63
+ const date = new Date(year, month - 1, day);
64
+ const firstDay = new Date(date.getFullYear(), date.getMonth(), 1).getDay();
65
+ const mondayBasedOffset = (firstDay + 6) % 7;
66
+ return Math.ceil((date.getDate() + mondayBasedOffset) / 7);
67
+ }
68
+
69
+ const getScrollDelta = (fullDate: string[]) => {
70
+ const startDate = fullDate[0];
71
+ const [startYear, startMonth, _] = startDate.split('/');
72
+ const refStartKey = `${startYear}/${startMonth}`;
73
+ const startDateWeek = getWeekOfMonth(startDate);
74
+ let startDelta = startDateWeek > 3 ? startDateWeek * ELEMENTS_HEIGHT.DATE : 0;
75
+ Object.entries(monthHeightRef.current).forEach(([key, value]) => {
76
+ if (refStartKey > key) {
77
+ startDelta += value;
78
+ }
79
+ });
80
+ return startDelta;
81
+ };
82
+
83
+ storeMonthHeights();
84
+
85
+ const scrollToSelectedDates = (newDates: string[]) => {
86
+ if (scrollViewRef.current && newDates.length > 0) {
87
+ const scrollOffset = getScrollDelta(newDates);
88
+ setTimeout(() => {
89
+ if (scrollViewRef.current) scrollViewRef.current.scrollTo({ y: scrollOffset, animated: isScrollAnimated });
90
+ setIsScrollAnimated(true);
91
+ }, 0);
92
+ }
93
+ };
94
+
95
+ useEffect(() => {
96
+ scrollToSelectedDates(getSelectedDates());
97
+ // eslint-disable-next-line react-hooks/exhaustive-deps
98
+ }, [getSelectedDates]);
99
+
100
+ useSubEvent('SELECTED_DATES', ({ newDates }: { newDates: string[] }) => {
101
+ scrollToSelectedDates(newDates);
102
+ });
103
+
104
+ return (
105
+ <ScrollView showsVerticalScrollIndicator={false} ref={scrollViewRef} nestedScrollEnabled>
106
+ <LazyMonthList
107
+ show={show}
108
+ monthList={preceedingMonths}
109
+ handleDateClicked={handleDateClicked}
110
+ getSelectedDates={getSelectedDates}
111
+ calendarDotsList={calendarDotsList}
112
+ holidayList={holidayList}
113
+ monthHeightRef={monthHeightRef}
114
+ />
115
+ {activeMonths.map((item, index) => {
116
+ if (index > renderedMonths)
117
+ return (
118
+ <PlaceholderMonth
119
+ key={`placeholderMonth-${index}`}
120
+ height={monthHeightRef.current[`${item.year}/${item.month}`]}
121
+ />
122
+ );
123
+ return (
124
+ <CalendarMonth
125
+ onLayout={() => {
126
+ InteractionManager.runAfterInteractions(() => {
127
+ if (renderedMonths < activeMonths.length) setRenderedMonths((prev) => prev + 1);
128
+ });
129
+ if (index === activeMonths.length - 1) {
130
+ InteractionManager.runAfterInteractions(() => {
131
+ setShow(true);
132
+ });
133
+ }
134
+ }}
135
+ key={`activeMonths-${index}`}
136
+ handleDateClicked={handleDateClicked}
137
+ getSelectedDates={getSelectedDates}
138
+ month={item.month}
139
+ year={item.year}
140
+ calendarDotsList={calendarDotsList}
141
+ holidayList={holidayList}
142
+ />
143
+ );
144
+ })}
145
+ <LazyMonthList
146
+ show={show}
147
+ monthList={followingMonths}
148
+ handleDateClicked={handleDateClicked}
149
+ getSelectedDates={getSelectedDates}
150
+ calendarDotsList={calendarDotsList}
151
+ holidayList={holidayList}
152
+ monthHeightRef={monthHeightRef}
153
+ />
154
+ <View style={staticCalendarBodyStyle?.spacer} />
155
+ </ScrollView>
156
+ );
157
+ };
158
+
159
+ export default memo(CalendarBody);
@@ -0,0 +1,34 @@
1
+ import { memo } from 'react';
2
+
3
+ import { useStyles } from '@cleartrip/ct-design-style-manager';
4
+ import { View } from 'react-native';
5
+
6
+ import CalendarDotWrapper from './CalendarDotWrapper';
7
+ import { getSelectedDateRootStyles, staticCalendarDateStyle } from '../styles';
8
+ import { ICalendarDateProp } from '../type';
9
+ import { Typography, TypographyColor, TypographyVariant } from '@cleartrip/ct-design-typography';
10
+
11
+ const CalendarDate: React.FC<ICalendarDateProp> = ({ day, date, isSelected, calendarDotsList }) => {
12
+ const dynamicCalendarDateStyles = useStyles(
13
+ (theme) => {
14
+ return {
15
+ root: getSelectedDateRootStyles(theme, isSelected),
16
+ };
17
+ },
18
+ [isSelected],
19
+ );
20
+ if (!day) return null;
21
+
22
+ const showDot = calendarDotsList.includes(date);
23
+
24
+ return (
25
+ <View style={[staticCalendarDateStyle.root, dynamicCalendarDateStyles?.root]}>
26
+ <CalendarDotWrapper showDot={showDot} />
27
+ <Typography variant={TypographyVariant.P1} color={isSelected ? TypographyColor.NEUTRAL : TypographyColor.PRIMARY}>
28
+ {day}
29
+ </Typography>
30
+ </View>
31
+ );
32
+ };
33
+
34
+ export default memo(CalendarDate);