@adiraku/react-native-ui 1.2.8-canary-0 → 1.2.8-canary-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.
Files changed (93) hide show
  1. package/lib/commonjs/components/CheckBoxInput/CheckBoxInput.component.js +3 -1
  2. package/lib/commonjs/components/CheckBoxInput/CheckBoxInput.component.js.map +1 -1
  3. package/lib/commonjs/components/CheckBoxInput/CheckBoxInput.style.js +2 -2
  4. package/lib/commonjs/components/CheckBoxInput/CheckBoxInput.style.js.map +1 -1
  5. package/lib/commonjs/components/RadioInput/RadioInput.component.js +3 -1
  6. package/lib/commonjs/components/RadioInput/RadioInput.component.js.map +1 -1
  7. package/lib/commonjs/components/RadioInput/RadioInput.style.js +2 -2
  8. package/lib/commonjs/components/RadioInput/RadioInput.style.js.map +1 -1
  9. package/lib/commonjs/components/TextArea/TextArea.component.js +6 -4
  10. package/lib/commonjs/components/TextArea/TextArea.component.js.map +1 -1
  11. package/lib/commonjs/components/TextInput/TextInput.component.js +45 -6
  12. package/lib/commonjs/components/TextInput/TextInput.component.js.map +1 -1
  13. package/lib/commonjs/components/calendars/calendars.component.js +215 -0
  14. package/lib/commonjs/components/calendars/calendars.component.js.map +1 -0
  15. package/lib/commonjs/components/calendars/calendars.service.js +68 -0
  16. package/lib/commonjs/components/calendars/calendars.service.js.map +1 -0
  17. package/lib/commonjs/components/calendars/calendars.style.js +126 -0
  18. package/lib/commonjs/components/calendars/calendars.style.js.map +1 -0
  19. package/lib/commonjs/components/calendars/calendars.type.js +14 -0
  20. package/lib/commonjs/components/calendars/calendars.type.js.map +1 -0
  21. package/lib/commonjs/components/calendars/month-picker-modal.component.js +104 -0
  22. package/lib/commonjs/components/calendars/month-picker-modal.component.js.map +1 -0
  23. package/lib/commonjs/components/index.js +7 -0
  24. package/lib/commonjs/components/index.js.map +1 -1
  25. package/lib/commonjs/components/typography/typography.style.js +181 -0
  26. package/lib/commonjs/components/typography/typography.style.js.map +1 -1
  27. package/lib/module/components/CheckBoxInput/CheckBoxInput.component.js +3 -1
  28. package/lib/module/components/CheckBoxInput/CheckBoxInput.component.js.map +1 -1
  29. package/lib/module/components/CheckBoxInput/CheckBoxInput.style.js +2 -2
  30. package/lib/module/components/CheckBoxInput/CheckBoxInput.style.js.map +1 -1
  31. package/lib/module/components/RadioInput/RadioInput.component.js +3 -1
  32. package/lib/module/components/RadioInput/RadioInput.component.js.map +1 -1
  33. package/lib/module/components/RadioInput/RadioInput.style.js +2 -2
  34. package/lib/module/components/RadioInput/RadioInput.style.js.map +1 -1
  35. package/lib/module/components/TextArea/TextArea.component.js +7 -5
  36. package/lib/module/components/TextArea/TextArea.component.js.map +1 -1
  37. package/lib/module/components/TextInput/TextInput.component.js +46 -7
  38. package/lib/module/components/TextInput/TextInput.component.js.map +1 -1
  39. package/lib/module/components/calendars/calendars.component.js +207 -0
  40. package/lib/module/components/calendars/calendars.component.js.map +1 -0
  41. package/lib/module/components/calendars/calendars.service.js +56 -0
  42. package/lib/module/components/calendars/calendars.service.js.map +1 -0
  43. package/lib/module/components/calendars/calendars.style.js +119 -0
  44. package/lib/module/components/calendars/calendars.style.js.map +1 -0
  45. package/lib/module/components/calendars/calendars.type.js +8 -0
  46. package/lib/module/components/calendars/calendars.type.js.map +1 -0
  47. package/lib/module/components/calendars/month-picker-modal.component.js +95 -0
  48. package/lib/module/components/calendars/month-picker-modal.component.js.map +1 -0
  49. package/lib/module/components/index.js +1 -0
  50. package/lib/module/components/index.js.map +1 -1
  51. package/lib/module/components/typography/typography.style.js +181 -0
  52. package/lib/module/components/typography/typography.style.js.map +1 -1
  53. package/lib/typescript/components/CheckBoxInput/CheckBoxInput.component.d.ts.map +1 -1
  54. package/lib/typescript/components/RadioInput/RadioInput.component.d.ts.map +1 -1
  55. package/lib/typescript/components/TextArea/TextArea.component.d.ts.map +1 -1
  56. package/lib/typescript/components/TextInput/TextInput.component.d.ts.map +1 -1
  57. package/lib/typescript/components/TextInput/TextInput.type.d.ts +7 -0
  58. package/lib/typescript/components/TextInput/TextInput.type.d.ts.map +1 -1
  59. package/lib/typescript/components/calendars/calendars.component.d.ts +8 -0
  60. package/lib/typescript/components/calendars/calendars.component.d.ts.map +1 -0
  61. package/lib/typescript/components/calendars/calendars.service.d.ts +9 -0
  62. package/lib/typescript/components/calendars/calendars.service.d.ts.map +1 -0
  63. package/lib/typescript/components/calendars/calendars.style.d.ts +20 -0
  64. package/lib/typescript/components/calendars/calendars.style.d.ts.map +1 -0
  65. package/lib/typescript/components/calendars/calendars.type.d.ts +26 -0
  66. package/lib/typescript/components/calendars/calendars.type.d.ts.map +1 -0
  67. package/lib/typescript/components/calendars/month-picker-modal.component.d.ts +15 -0
  68. package/lib/typescript/components/calendars/month-picker-modal.component.d.ts.map +1 -0
  69. package/lib/typescript/components/index.d.ts +1 -0
  70. package/lib/typescript/components/index.d.ts.map +1 -1
  71. package/lib/typescript/components/information-box/information-box.type.d.ts +13 -2
  72. package/lib/typescript/components/information-box/information-box.type.d.ts.map +1 -1
  73. package/lib/typescript/components/typography/typography.style.d.ts +28 -0
  74. package/lib/typescript/components/typography/typography.style.d.ts.map +1 -1
  75. package/lib/typescript/components/typography/typography.type.d.ts +4 -4
  76. package/lib/typescript/components/typography/typography.type.d.ts.map +1 -1
  77. package/package.json +2 -1
  78. package/src/components/CheckBoxInput/CheckBoxInput.component.tsx +8 -1
  79. package/src/components/CheckBoxInput/CheckBoxInput.style.tsx +2 -2
  80. package/src/components/RadioInput/RadioInput.component.tsx +8 -1
  81. package/src/components/RadioInput/RadioInput.style.tsx +2 -2
  82. package/src/components/TextArea/TextArea.component.tsx +9 -6
  83. package/src/components/TextInput/TextInput.component.tsx +114 -50
  84. package/src/components/TextInput/TextInput.type.ts +11 -0
  85. package/src/components/calendars/calendars.component.tsx +296 -0
  86. package/src/components/calendars/calendars.service.ts +64 -0
  87. package/src/components/calendars/calendars.style.ts +148 -0
  88. package/src/components/calendars/calendars.type.tsx +57 -0
  89. package/src/components/calendars/month-picker-modal.component.tsx +137 -0
  90. package/src/components/index.ts +1 -0
  91. package/src/components/information-box/information-box.type.ts +13 -5
  92. package/src/components/typography/typography.style.tsx +243 -0
  93. package/src/components/typography/typography.type.ts +31 -3
@@ -1,14 +1,20 @@
1
1
  import * as React from 'react';
2
2
  import { View } from 'react-native';
3
- import { getStyle } from './TextInput.style';
4
- import type { TextInputProps } from './TextInput.type';
3
+ import { Animated } from 'react-native';
4
+ import type {
5
+ GestureResponderEvent,
6
+ LayoutChangeEvent,
7
+ NativeSyntheticEvent,
8
+ TextInputFocusEventData,
9
+ } from 'react-native';
5
10
  import MaskInput from 'react-native-mask-input';
11
+
12
+ import { getStyle } from './TextInput.style';
6
13
  import { Typography } from '../typography/typography.component';
7
- import { Animated } from 'react-native';
14
+ import { Calendars } from '../calendars/calendars.component';
15
+
8
16
  import { Palettes } from '../../themes';
9
- import type { LayoutChangeEvent } from 'react-native';
10
- import type { NativeSyntheticEvent } from 'react-native';
11
- import type { TextInputFocusEventData } from 'react-native';
17
+ import type { TextInputProps } from './TextInput.type';
12
18
 
13
19
  const TextInput: React.FunctionComponent<TextInputProps> = (props) => {
14
20
  const {
@@ -22,12 +28,20 @@ const TextInput: React.FunctionComponent<TextInputProps> = (props) => {
22
28
  isError,
23
29
  counter = 0,
24
30
  inputIcon = null,
31
+ onTouchStart,
32
+ showSoftInputOnFocus = true,
33
+ inputType = 'text',
34
+ calendarProps,
35
+ onChangeDate: onDateChange,
25
36
  ...rest
26
37
  } = props;
27
38
 
28
39
  const [labelWidth, setLabelWidth] = React.useState(0);
29
40
  const [focused, setFocused] = React.useState(false);
30
41
 
42
+ // for date input
43
+ const [isModalDateVisible, setIsModalDateVisible] = React.useState(false);
44
+
31
45
  const computedStyle = getStyle(props, focused);
32
46
 
33
47
  const animation = React.useRef(new Animated.Value(0));
@@ -76,53 +90,103 @@ const TextInput: React.FunctionComponent<TextInputProps> = (props) => {
76
90
  setLabelWidth(width + 24);
77
91
  };
78
92
 
93
+ const computedValue = React.useMemo(() => {
94
+ if (inputType === 'date' && typeof value === 'object') {
95
+ const options: Intl.DateTimeFormatOptions = {
96
+ weekday: 'long',
97
+ day: '2-digit',
98
+ month: 'short',
99
+ year: 'numeric',
100
+ };
101
+
102
+ const formattedDate = new Intl.DateTimeFormat('id-ID', options).format(
103
+ value
104
+ );
105
+
106
+ // Capitalize the first letter of the weekday and month for consistency with the example format.
107
+ return formattedDate.replace(/(^\w{1})|(\s\w{1})/g, (letter) =>
108
+ letter.toUpperCase()
109
+ );
110
+ }
111
+ return value;
112
+ }, [value, inputType]);
113
+
114
+ const handleOnTouchStart = (e: GestureResponderEvent) => {
115
+ if (inputType === 'date') {
116
+ setIsModalDateVisible(true);
117
+ }
118
+
119
+ onTouchStart?.(e);
120
+ };
121
+
122
+ const handleOnDateChangeSave = (date: Date) => {
123
+ onDateChange?.(date);
124
+ };
125
+
79
126
  return (
80
- <View style={computedStyle.fieldWrapper}>
81
- <View style={computedStyle.fieldContainer}>
82
- {!!label && (
83
- <Animated.View
84
- style={[
85
- computedStyle.labelContainer,
86
- {
87
- transform: [{ scale }, { translateY }, { translateX }],
88
- },
89
- ]}
90
- onLayout={getLabelWidth}
91
- pointerEvents="none"
92
- >
93
- <Typography variant="body2" style={computedStyle.label}>
94
- {label}
95
- </Typography>
96
- </Animated.View>
97
- )}
98
- <View style={computedStyle.inputWrapper}>
99
- <MaskInput
100
- value={value}
101
- style={[computedStyle.textField]}
102
- onFocus={handleOnFocus}
103
- onBlur={handleOnBlur}
104
- placeholderTextColor={focused ? Palettes.black[500] : 'transparent'}
105
- {...rest}
106
- />
107
- {inputIcon || counter > 0
108
- ? inputIcon || (
109
- <Typography style={computedStyle.counter} variant="caption">
110
- {`${value?.length}/${counter}`}
111
- </Typography>
112
- )
113
- : null}
127
+ <>
128
+ <View style={computedStyle.fieldWrapper}>
129
+ <View style={computedStyle.fieldContainer}>
130
+ {!!label && (
131
+ <Animated.View
132
+ style={[
133
+ computedStyle.labelContainer,
134
+ {
135
+ transform: [{ scale }, { translateY }, { translateX }],
136
+ },
137
+ ]}
138
+ onLayout={getLabelWidth}
139
+ pointerEvents="none"
140
+ >
141
+ <Typography variant="body2" style={computedStyle.label}>
142
+ {label}
143
+ </Typography>
144
+ </Animated.View>
145
+ )}
146
+ <View style={computedStyle.inputWrapper}>
147
+ <MaskInput
148
+ value={computedValue}
149
+ style={[computedStyle.textField]}
150
+ onFocus={handleOnFocus}
151
+ onBlur={handleOnBlur}
152
+ placeholderTextColor={
153
+ focused ? Palettes.black[500] : 'transparent'
154
+ }
155
+ showSoftInputOnFocus={
156
+ inputType === 'date' ? false : showSoftInputOnFocus
157
+ }
158
+ onTouchStart={handleOnTouchStart}
159
+ {...rest}
160
+ />
161
+ {inputIcon || counter > 0
162
+ ? inputIcon || (
163
+ <Typography style={computedStyle.counter} variant="caption">
164
+ {`${computedValue?.length}/${counter}`}
165
+ </Typography>
166
+ )
167
+ : null}
168
+ </View>
114
169
  </View>
170
+ {errorMessage || helperMessage ? (
171
+ <Typography
172
+ variant="caption"
173
+ style={computedStyle.messageHelper}
174
+ {...helperMessageProps}
175
+ >
176
+ {errorMessage || ((!isError && helperMessage) as string)}
177
+ </Typography>
178
+ ) : null}
115
179
  </View>
116
- {errorMessage || helperMessage ? (
117
- <Typography
118
- variant="caption"
119
- style={computedStyle.messageHelper}
120
- {...helperMessageProps}
121
- >
122
- {errorMessage || ((!isError && helperMessage) as string)}
123
- </Typography>
124
- ) : null}
125
- </View>
180
+
181
+ {inputType === 'date' && (
182
+ <Calendars
183
+ isVisible={isModalDateVisible}
184
+ onDateSave={handleOnDateChangeSave}
185
+ onDismiss={() => setIsModalDateVisible(false)}
186
+ {...calendarProps}
187
+ />
188
+ )}
189
+ </>
126
190
  );
127
191
  };
128
192
 
@@ -1,6 +1,7 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import { MaskInputProps } from 'react-native-mask-input';
3
3
  import { TypographyProps } from '../typography/typography.type';
4
+ import { CalendarPropsAleph } from '../calendars/calendars.type';
4
5
 
5
6
  export interface TextInputProps extends MaskInputProps {
6
7
  /**
@@ -37,4 +38,14 @@ export interface TextInputProps extends MaskInputProps {
37
38
  * Show Icon at the end of TextInput.
38
39
  */
39
40
  inputIcon?: ReactNode;
41
+
42
+ /**
43
+ * Type of the input. won't show keyboard if value set to 'date'
44
+ */
45
+ inputType?: 'text' | 'date';
46
+
47
+ // handler which get executed when the save button on calendar pressed. Usable only when inputType='date'
48
+ onChangeDate?: (date: Date) => void;
49
+
50
+ calendarProps?: Omit<CalendarPropsAleph, 'isVisible' | 'onDateSave'>;
40
51
  }
@@ -0,0 +1,296 @@
1
+ import React, {
2
+ memo,
3
+ useCallback,
4
+ useMemo,
5
+ useState,
6
+ } from 'react';
7
+ import { TouchableHighlight, View } from 'react-native';
8
+ import {
9
+ Calendar,
10
+ LocaleConfig,
11
+ } from 'react-native-calendars';
12
+ import { DateData, MarkedDates } from 'react-native-calendars/src/types';
13
+ import ReactNativeModal from 'react-native-modal';
14
+
15
+ import { Palettes, Spacing } from '../../themes';
16
+ import {
17
+ adjustDate,
18
+ findYearPairIndex,
19
+ generateYearPairs,
20
+ getFullDate,
21
+ getMonth,
22
+ getYear,
23
+ } from './calendars.service';
24
+ import { calendarTheme, getStyle } from './calendars.style';
25
+ import { CalendarPropsAleph, ModeSelect, MonthID } from './calendars.type';
26
+
27
+ import { IconChevronLeft, IconChevronRight } from '../../icons';
28
+ import { Typography } from '../typography/typography.component';
29
+ import { Button } from '../button/button.component';
30
+ import { MonthPickerModal, YearPicker } from './month-picker-modal.component';
31
+
32
+ // localization for calendar component
33
+ LocaleConfig.locales['id'] = MonthID;
34
+ LocaleConfig.defaultLocale = 'id';
35
+
36
+ export type OnMonthChange = (data: { num: number }) => void;
37
+
38
+ export type OnArrowChange = (direction: 'left' | 'right') => void;
39
+
40
+ export function Calendars({
41
+ isVisible,
42
+ initialDate = new Date(),
43
+ onDismiss = () => {},
44
+ minDate,
45
+ maxDate,
46
+ onDateSave,
47
+ selectedDate,
48
+ ...rest
49
+ }: CalendarPropsAleph) {
50
+ const computedStyle = getStyle();
51
+
52
+ const [dateindicator, setDateIndicator] = useState(
53
+ selectedDate || initialDate
54
+ );
55
+ const [markedDate, setMarkedDate] = useState<MarkedDates>({});
56
+ const [selectMode, setSelectMode] = useState<ModeSelect>('calendar');
57
+
58
+ const yearIntervalPair = useMemo(() => {
59
+ let minYear = 1900;
60
+ let maxYear = new Date().getFullYear();
61
+ if (minDate) {
62
+ minYear = new Date(minDate).getFullYear();
63
+ }
64
+
65
+ if (maxDate) {
66
+ maxYear = new Date(maxDate).getFullYear();
67
+ }
68
+
69
+ console.log({ minYear, maxYear, minDate, maxDate });
70
+
71
+ return generateYearPairs(minYear, maxYear, 12);
72
+ }, [minDate, maxDate]);
73
+
74
+ const initYearPairIndex = findYearPairIndex(
75
+ yearIntervalPair,
76
+ initialDate?.getFullYear() || 0
77
+ );
78
+
79
+ const [yearPairSelectIndex, setYearPairSelectIndex] =
80
+ useState(initYearPairIndex);
81
+
82
+ const handleOnMonthChange: OnMonthChange = ({ num }) => {
83
+ setDateIndicator(adjustDate(dateindicator, num));
84
+ setSelectMode('calendar');
85
+ };
86
+
87
+ const handleOnArrowPress: OnArrowChange = (direction) => {
88
+ if (selectMode === 'calendar') {
89
+ setDateIndicator(
90
+ adjustDate(dateindicator, direction === 'left' ? -1 : 1)
91
+ );
92
+ } else if (selectMode === 'month') {
93
+ setDateIndicator(
94
+ adjustDate(dateindicator, direction === 'left' ? -12 : 12)
95
+ );
96
+ } else {
97
+ if (yearPairSelectIndex <= 0 && direction === 'right') return;
98
+ if (
99
+ yearPairSelectIndex >= yearIntervalPair.length - 1 &&
100
+ direction === 'left'
101
+ )
102
+ return;
103
+
104
+ // don't ask what i'm doing, I know it's crazy T_T
105
+ setYearPairSelectIndex((e) => (direction === 'left' ? e + 1 : e - 1));
106
+ }
107
+ };
108
+
109
+ const onDayPress = useCallback((dates: DateData) => {
110
+ if (!dates) return;
111
+
112
+ setDateIndicator(new Date(dates.timestamp));
113
+ setMarkedDate({
114
+ [dates.dateString]: { selected: true, ...dates },
115
+ });
116
+ }, []);
117
+
118
+ const handleSelectModeChange = (mode: ModeSelect) => {
119
+ setSelectMode(mode);
120
+ };
121
+
122
+ const handleOnDismiss = () => {
123
+ onDismiss();
124
+
125
+ // reset back to initial state
126
+ setSelectMode('calendar');
127
+ setDateIndicator(initialDate);
128
+ setYearPairSelectIndex(initYearPairIndex);
129
+ setMarkedDate({});
130
+ };
131
+
132
+ const handleOnDateSubmit = () => {
133
+ const keys = Object.keys(markedDate)
134
+
135
+ if (keys.length <= 0) return;
136
+
137
+ const testDate = markedDate[keys[0] || ''] as MarkedDates[number] & {
138
+ timestamp: number;
139
+ };
140
+
141
+ const selectedDate = new Date(testDate?.timestamp);
142
+ onDateSave?.(selectedDate);
143
+ onDismiss();
144
+ }
145
+
146
+ return (
147
+ <ReactNativeModal
148
+ isVisible={isVisible}
149
+ onBackdropPress={handleOnDismiss}
150
+ onBackButtonPress={handleOnDismiss}
151
+ backdropTransitionOutTiming={0}
152
+ needsOffscreenAlphaCompositing={true}
153
+ animationIn="zoomInDown"
154
+ animationOut="zoomOut"
155
+ style={computedStyle.modalContainer}
156
+ >
157
+ <View style={computedStyle.container}>
158
+ <CalendarHeader
159
+ initialDate={dateindicator}
160
+ mode={selectMode}
161
+ handleOnArrowPress={handleOnArrowPress}
162
+ handleSelectMode={handleSelectModeChange}
163
+ yearPairSelectIndex={yearPairSelectIndex}
164
+ yearIntervalPair={yearIntervalPair}
165
+ />
166
+
167
+ <View
168
+ style={[
169
+ computedStyle.calendarContainer,
170
+ {
171
+ paddingHorizontal:
172
+ selectMode === 'calendar' ? Spacing[4] : Spacing[4],
173
+ },
174
+ ]}
175
+ >
176
+ {selectMode === 'calendar' ? (
177
+ <>
178
+ <Calendar
179
+ markedDates={markedDate}
180
+ initialDate={getFullDate(dateindicator)}
181
+ style={{ marginHorizontal: Spacing[12] }}
182
+ theme={calendarTheme}
183
+ renderHeader={() => null}
184
+ onDayPress={onDayPress}
185
+ enableSwipeMonths
186
+ minDate={minDate}
187
+ maxDate={maxDate}
188
+ {...rest}
189
+ />
190
+
191
+ <View style={computedStyle.calendarBottomContainer}>
192
+ <View style={{ flex: 1 }}>
193
+ <Button
194
+ label="Batal"
195
+ variant="secondary"
196
+ onPress={handleOnDismiss}
197
+ />
198
+ </View>
199
+ <View style={{ width: 16 }} />
200
+ <View style={{ flex: 1 }}>
201
+ <Button
202
+ label="Simpan"
203
+ onPress={handleOnDateSubmit}
204
+ disabled={Object.keys(markedDate).length <= 0}
205
+ />
206
+ </View>
207
+ </View>
208
+ </>
209
+ ) : selectMode === 'month' ? (
210
+ <MonthPickerModal
211
+ initialDate={dateindicator}
212
+ onMonthChange={handleOnMonthChange}
213
+ />
214
+ ) : (
215
+ <YearPicker
216
+ initialDate={dateindicator}
217
+ yearPairSelectIndex={yearPairSelectIndex}
218
+ yearIntervalPair={yearIntervalPair}
219
+ onYearChange={handleOnMonthChange}
220
+ />
221
+ )}
222
+ </View>
223
+ </View>
224
+ </ReactNativeModal>
225
+ );
226
+ }
227
+
228
+ type CalendarHeaderProps = {
229
+ mode: ModeSelect;
230
+ handleSelectMode: (mode: ModeSelect) => void;
231
+ handleOnArrowPress: OnArrowChange;
232
+ yearPairSelectIndex: number;
233
+ yearIntervalPair: [number, number][];
234
+ } & Pick<CalendarPropsAleph, 'initialDate'>;
235
+
236
+ const CalendarHeader = memo(function ({
237
+ mode = 'calendar',
238
+ initialDate = new Date(),
239
+ yearIntervalPair,
240
+ yearPairSelectIndex,
241
+ handleSelectMode,
242
+ handleOnArrowPress,
243
+ }: CalendarHeaderProps) {
244
+ const computedStyle = getStyle();
245
+
246
+ return (
247
+ <View style={computedStyle.headerContainer}>
248
+ <TouchableHighlight
249
+ onPress={() => handleOnArrowPress('left')}
250
+ style={computedStyle.headerArrowWrapper}
251
+ underlayColor={Palettes.black[900] + '33'}
252
+ >
253
+ <IconChevronLeft />
254
+ </TouchableHighlight>
255
+
256
+ <View style={computedStyle.headerCenterWrapper}>
257
+ {mode === 'calendar' || mode === 'month' ? (
258
+ <>
259
+ <TouchableHighlight
260
+ onPress={() => handleSelectMode('month')}
261
+ style={computedStyle.headerCenterItem}
262
+ underlayColor={Palettes.black[900] + '33'}
263
+ >
264
+ <Typography variant="button">{getMonth(initialDate)}</Typography>
265
+ </TouchableHighlight>
266
+ <TouchableHighlight
267
+ onPress={() => handleSelectMode('year')}
268
+ style={computedStyle.headerCenterItem}
269
+ underlayColor={Palettes.black[900] + '33'}
270
+ >
271
+ <Typography variant="button">{getYear(initialDate)}</Typography>
272
+ </TouchableHighlight>
273
+ </>
274
+ ) : (
275
+ <TouchableHighlight
276
+ style={computedStyle.headerCenterItem}
277
+ underlayColor={Palettes.black[900] + '33'}
278
+ >
279
+ <Typography variant="button">
280
+ {yearIntervalPair[yearPairSelectIndex]?.[1]} -{' '}
281
+ {yearIntervalPair[yearPairSelectIndex]?.[0]}
282
+ </Typography>
283
+ </TouchableHighlight>
284
+ )}
285
+ </View>
286
+
287
+ <TouchableHighlight
288
+ onPress={() => handleOnArrowPress('right')}
289
+ style={computedStyle.headerArrowWrapper}
290
+ underlayColor={Palettes.black[900] + '33'}
291
+ >
292
+ <IconChevronRight />
293
+ </TouchableHighlight>
294
+ </View>
295
+ );
296
+ });
@@ -0,0 +1,64 @@
1
+ export const getMonth = (date: Date) => {
2
+ return new Intl.DateTimeFormat('id-ID', { month: 'long' }).format(date);
3
+ };
4
+
5
+ export const getYear = (date: Date) => {
6
+ return new Intl.DateTimeFormat('id-ID', { year: 'numeric' }).format(date);
7
+ };
8
+
9
+ export const getFullDate = (date: Date) => {
10
+ const formatter = new Intl.DateTimeFormat('en-CA', {
11
+ year: 'numeric',
12
+ month: '2-digit',
13
+ day: '2-digit',
14
+ });
15
+
16
+ // Format the date
17
+ const formattedDate = formatter.format(date);
18
+
19
+ // Since the formatter returns a date in the format of "YYYY/MM/DD",
20
+ // we need to replace the slashes with dashes
21
+ return formattedDate.replace(/\//g, '-');
22
+ };
23
+
24
+ export function adjustDate(date: Date, number: number) {
25
+ // Ensure the input date is a Date object
26
+ const newDate = new Date(date);
27
+
28
+ // Adjust the date by the specified number of days
29
+ newDate.setMonth(newDate.getMonth() + number);
30
+
31
+ return newDate;
32
+ }
33
+
34
+ type YearPair = [number, number];
35
+
36
+ // endYear < startYear
37
+ export function generateYearPairs(endYear: number, startYear: number, interval: number): YearPair[] {
38
+ const yearPairs: YearPair[] = [];
39
+ let currentYear = startYear;
40
+
41
+ while (currentYear - interval >= endYear) {
42
+ yearPairs.push([currentYear, currentYear - interval + 1]);
43
+ currentYear -= interval;
44
+ }
45
+
46
+ yearPairs.push([currentYear, endYear])
47
+
48
+ return yearPairs;
49
+ }
50
+ export function findYearPairIndex(
51
+ years: [number, number][],
52
+ targetYear: number
53
+ ): number {
54
+ for (let i = 0; i < years.length; i++) {
55
+ const pair = years[i];
56
+ if (!pair) continue; // Skip if the pair is undefined
57
+
58
+ const [startYear, endYear] = pair;
59
+ if (targetYear >= endYear && targetYear <= startYear) {
60
+ return i;
61
+ }
62
+ }
63
+ return -1; // Return -1 if the target year is not found in any pair
64
+ }