expo-2k-datetime-picker 1.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 (96) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +267 -0
  3. package/android/build.gradle +18 -0
  4. package/android/src/main/AndroidManifest.xml +2 -0
  5. package/android/src/main/java/expo/modules/calendar2k/Calendar2kModule.kt +15 -0
  6. package/android/src/main/java/expo/modules/calendar2k/Calendar2kView.kt +26 -0
  7. package/build/Calendar2k.types.d.ts +38 -0
  8. package/build/Calendar2k.types.js +2 -0
  9. package/build/Calendar2kModule.d.ts +8 -0
  10. package/build/Calendar2kModule.js +10 -0
  11. package/build/Calendar2kModule.web.d.ts +6 -0
  12. package/build/Calendar2kModule.web.js +26 -0
  13. package/build/Calendar2kView.d.ts +4 -0
  14. package/build/Calendar2kView.js +366 -0
  15. package/build/Calendar2kView.web.d.ts +3 -0
  16. package/build/Calendar2kView.web.js +49 -0
  17. package/build/assets/assets/images/calendar.png +0 -0
  18. package/build/assets/assets/images/chevron-left.png +0 -0
  19. package/build/assets/assets/images/chevron-right.png +0 -0
  20. package/build/assets/assets/images/clock.png +0 -0
  21. package/build/assets/assets/images/swipe.png +0 -0
  22. package/build/assets/images/calendar.png +0 -0
  23. package/build/assets/images/chevron-left.png +0 -0
  24. package/build/assets/images/chevron-right.png +0 -0
  25. package/build/assets/images/clock.png +0 -0
  26. package/build/assets/images/swipe.png +0 -0
  27. package/build/components/ArrowButton.d.ts +8 -0
  28. package/build/components/ArrowButton.js +19 -0
  29. package/build/components/Backdrop.d.ts +5 -0
  30. package/build/components/Backdrop.js +25 -0
  31. package/build/components/DayLabel.d.ts +6 -0
  32. package/build/components/DayLabel.js +16 -0
  33. package/build/components/Icon.d.ts +6 -0
  34. package/build/components/Icon.js +16 -0
  35. package/build/components/SwipeIcon.d.ts +5 -0
  36. package/build/components/SwipeIcon.js +8 -0
  37. package/build/components/Time.d.ts +11 -0
  38. package/build/components/Time.js +95 -0
  39. package/build/components/TimeView.d.ts +10 -0
  40. package/build/components/TimeView.js +25 -0
  41. package/build/hooks/useCalendarDisclose.d.ts +4 -0
  42. package/build/hooks/useCalendarDisclose.js +9 -0
  43. package/build/libs/format.d.ts +4 -0
  44. package/build/libs/format.js +52 -0
  45. package/build/libs/formatNb.d.ts +1 -0
  46. package/build/libs/formatNb.js +6 -0
  47. package/build/libs/getDayMatrix.d.ts +1 -0
  48. package/build/libs/getDayMatrix.js +74 -0
  49. package/build/libs/getStatus.d.ts +14 -0
  50. package/build/libs/getStatus.js +37 -0
  51. package/build/libs/getStyle.d.ts +14 -0
  52. package/build/libs/getStyle.js +35 -0
  53. package/build/libs/isActive.d.ts +8 -0
  54. package/build/libs/isActive.js +17 -0
  55. package/build/libs/isToday.d.ts +1 -0
  56. package/build/libs/isToday.js +9 -0
  57. package/build/libs/resetTime.d.ts +1 -0
  58. package/build/libs/resetTime.js +6 -0
  59. package/build/libs/toHexColor.d.ts +1 -0
  60. package/build/libs/toHexColor.js +13 -0
  61. package/build/ui/index.d.ts +15 -0
  62. package/build/ui/index.js +35 -0
  63. package/expo-module.config.json +9 -0
  64. package/ios/Calendar2k.podspec +23 -0
  65. package/ios/Calendar2kModule.swift +12 -0
  66. package/ios/Calendar2kView.swift +18 -0
  67. package/package.json +53 -0
  68. package/src/Calendar2k.types.ts +40 -0
  69. package/src/Calendar2kModule.ts +9 -0
  70. package/src/Calendar2kModule.web.ts +7 -0
  71. package/src/Calendar2kView.tsx +416 -0
  72. package/src/Calendar2kView.web.tsx +19 -0
  73. package/src/assets/images/calendar.png +0 -0
  74. package/src/assets/images/chevron-left.png +0 -0
  75. package/src/assets/images/chevron-right.png +0 -0
  76. package/src/assets/images/clock.png +0 -0
  77. package/src/assets/images/swipe.png +0 -0
  78. package/src/components/ArrowButton.tsx +40 -0
  79. package/src/components/Backdrop.tsx +31 -0
  80. package/src/components/DayLabel.tsx +20 -0
  81. package/src/components/Icon.tsx +24 -0
  82. package/src/components/SwipeIcon.tsx +13 -0
  83. package/src/components/Time.tsx +93 -0
  84. package/src/components/TimeView.tsx +64 -0
  85. package/src/hooks/useCalendarDisclose.ts +9 -0
  86. package/src/libs/format.ts +57 -0
  87. package/src/libs/formatNb.ts +3 -0
  88. package/src/libs/getDayMatrix.ts +73 -0
  89. package/src/libs/getStatus.ts +47 -0
  90. package/src/libs/getStyle.ts +53 -0
  91. package/src/libs/isActive.ts +20 -0
  92. package/src/libs/isToday.ts +9 -0
  93. package/src/libs/resetTime.ts +3 -0
  94. package/src/libs/toHexColor.ts +13 -0
  95. package/src/ui/index.tsx +51 -0
  96. package/tsconfig.json +22 -0
@@ -0,0 +1,40 @@
1
+ export type Calendar2kModuleEvents = {
2
+ onChange: (params: ChangeEventPayload) => void;
3
+ };
4
+
5
+ export type ChangeEventPayload = {
6
+ value: string;
7
+ };
8
+
9
+ export type OnTapEventPayload = Record<string, never>;
10
+
11
+ export type Calendar2kViewProps = {
12
+ onChangeDate?: (date: DateValueType) => void;
13
+ value?: DateValueType;
14
+ locales?: Intl.LocalesArgument;
15
+ mode?: "date" | "time" | "datetime";
16
+ color?: string;
17
+ min?: Date;
18
+ max?: Date;
19
+ disableDate?: (date: Date) => boolean;
20
+ placeholder?: string;
21
+ customTrigger?: (onToggle: () => void) => React.ReactNode;
22
+ disabled?: boolean;
23
+ };
24
+
25
+ export type DayColumnProps = {
26
+ label: string;
27
+ dayNumber: number;
28
+ };
29
+
30
+ export type DayProps = {
31
+ date: Date;
32
+ };
33
+
34
+ export type TimeType =
35
+ `${number}${number}:${number}${number}:${number}${number}`;
36
+
37
+ export type TimeRangeType = { start: TimeType; end?: TimeType };
38
+ export type DateRangeType = { start: Date; end?: Date };
39
+ export type DateValueType = Date | DateRangeType | TimeType | TimeRangeType;
40
+ export type DateStateType = Date | DateRangeType;
@@ -0,0 +1,9 @@
1
+ import { NativeModule, requireNativeModule } from "expo";
2
+
3
+ import { Calendar2kModuleEvents } from "./Calendar2k.types";
4
+
5
+ declare class Calendar2kModule extends NativeModule<Calendar2kModuleEvents> {}
6
+
7
+ export default requireNativeModule<Calendar2kModule>("Calendar2k");
8
+ export type { DateValueType } from "./Calendar2k.types";
9
+ export { default as Calendar2kView } from "./Calendar2kView";
@@ -0,0 +1,7 @@
1
+ import { registerWebModule, NativeModule } from 'expo';
2
+
3
+ import { Calendar2kModuleEvents } from './Calendar2k.types';
4
+
5
+ class Calendar2kModule extends NativeModule<Calendar2kModuleEvents> {}
6
+
7
+ export default registerWebModule(Calendar2kModule, 'Calendar2kModule');
@@ -0,0 +1,416 @@
1
+ import * as React from "react";
2
+ import { useMemo, useState } from "react";
3
+ import { Modal, Pressable } from "react-native";
4
+ import { SafeAreaView } from "react-native-safe-area-context";
5
+ import ArrowButton from "./components/ArrowButton";
6
+ import Backdrop from "./components/Backdrop";
7
+ import DayLabel from "./components/DayLabel";
8
+ import Icon from "./components/Icon";
9
+ import SwipeIcon from "./components/SwipeIcon";
10
+ import Time from "./components/Time";
11
+ import TimeView from "./components/TimeView";
12
+ import useCalendarDisclose from "./hooks/useCalendarDisclose";
13
+ import { formatDate, formatMonth, getWeekDay } from "./libs/format";
14
+ import getDayMatrix from "./libs/getDayMatrix";
15
+ import getStyle from "./libs/getStyle";
16
+ import isActive from "./libs/isActive";
17
+ import { toHexColor } from "./libs/toHexColor";
18
+ import { KText, KTouchableOpacity, KView } from "./ui";
19
+
20
+ import {
21
+ DateStateType,
22
+ TimeType,
23
+ type Calendar2kViewProps,
24
+ type DateValueType,
25
+ type DayColumnProps,
26
+ type DayProps,
27
+ } from "./Calendar2k.types";
28
+
29
+ export default function Calendar2kView({
30
+ onChangeDate,
31
+ value,
32
+ locales,
33
+ color,
34
+ min,
35
+ max,
36
+ disableDate,
37
+ placeholder,
38
+ customTrigger,
39
+ mode = "datetime",
40
+ disabled,
41
+ }: Calendar2kViewProps) {
42
+ color = toHexColor(color);
43
+
44
+ const isValueDate = value instanceof Date;
45
+ const isValueTime = typeof value === "string";
46
+ const isValueRange = !!value && !isValueDate && typeof value === "object";
47
+ const isValueDateRange = isValueRange && value.start instanceof Date;
48
+ const isValueTimeRange = isValueRange && typeof value.start === "string";
49
+
50
+ if (isValueTime || isValueTimeRange) mode = "time";
51
+
52
+ const modeHasTime = mode?.includes("time");
53
+ const modeHasDate = mode?.includes("date");
54
+
55
+ const { isOpen, onToggle } = useCalendarDisclose();
56
+
57
+ const [selectedDate, setSelectedDate] = useState<DateStateType>(() => {
58
+ if (!value) return new Date();
59
+
60
+ if (isValueDate) return value;
61
+
62
+ if (isValueTime) return new Date(`2026-05-30 ${value}`);
63
+
64
+ if (isValueTimeRange)
65
+ return {
66
+ start: new Date(`2026-05-30 ${value.start}`),
67
+ end: new Date(`2026-05-30 ${value.end}`),
68
+ };
69
+
70
+ return value as DateStateType;
71
+ });
72
+
73
+ const isStateDate = selectedDate instanceof Date;
74
+ const isDateRange =
75
+ !isStateDate &&
76
+ typeof selectedDate === "object" &&
77
+ selectedDate.start instanceof Date;
78
+
79
+ const [shortDate, setShortDate] = useState(() => {
80
+ if (isStateDate) return selectedDate;
81
+
82
+ return selectedDate.start;
83
+ });
84
+
85
+ const matrix = getDayMatrix(shortDate);
86
+
87
+ const weekDays = Array.from({ length: 7 }).map((_, i) =>
88
+ getWeekDay(new Date(2026, 4, 3 + i), locales),
89
+ );
90
+
91
+ const datetimeOuput = useMemo(() => {
92
+ if (customTrigger) return "";
93
+
94
+ if (!value) {
95
+ if (placeholder) return placeholder;
96
+
97
+ placeholder = "Select date and time";
98
+
99
+ if (mode === "date") return "Select date";
100
+ if (mode === "time") return "Select time";
101
+
102
+ return placeholder;
103
+ }
104
+
105
+ if (isValueDate) return formatDate(value, locales, mode);
106
+
107
+ if (isValueTime) return value;
108
+
109
+ if (isValueTimeRange)
110
+ return `${formatDate(new Date(`2026-05-30 ${value.start}`), locales, mode)} - ${formatDate(new Date(`2026-05-30 ${value.end}`), locales, mode)}`;
111
+
112
+ if (isValueDateRange) {
113
+ let date = formatDate(value.start as Date, locales, mode);
114
+
115
+ if (value.end)
116
+ date = date
117
+ .concat(" - ")
118
+ .concat(formatDate(value.end as Date, locales, mode));
119
+
120
+ return date;
121
+ }
122
+
123
+ return "Invalid date or time";
124
+ }, [value, locales, mode]);
125
+
126
+ const changeYear = async (year: number) =>
127
+ setShortDate((v) => new Date(year, v.getMonth(), v.getDate()));
128
+
129
+ const changeMonth = (nb: number) => async () =>
130
+ setShortDate(
131
+ (v) => new Date(v.getFullYear(), v.getMonth() + nb, v.getDate()),
132
+ );
133
+
134
+ const selectDate = (date: Date) => async () => {
135
+ const newDate = new Date(date);
136
+
137
+ if (isStateDate) {
138
+ if (modeHasTime) {
139
+ newDate.setHours(selectedDate.getHours());
140
+ newDate.setMinutes(selectedDate.getMinutes());
141
+ }
142
+
143
+ setSelectedDate(newDate);
144
+ } else {
145
+ const isBeforeStart = selectedDate.start.getTime() > newDate.getTime();
146
+
147
+ if (selectedDate.end || isBeforeStart) {
148
+ if (modeHasTime) {
149
+ newDate.setHours(selectedDate.start.getHours());
150
+ newDate.setMinutes(selectedDate.start.getMinutes());
151
+ }
152
+
153
+ setSelectedDate({ start: newDate, end: undefined });
154
+ } else {
155
+ if (modeHasTime) {
156
+ newDate.setHours(selectedDate.start.getHours());
157
+ newDate.setMinutes(selectedDate.start.getMinutes());
158
+ }
159
+
160
+ setSelectedDate((v) => ({ ...v, end: newDate }));
161
+ }
162
+ }
163
+ };
164
+
165
+ const changeTime =
166
+ (key: "h" | "min" = "h", endTime?: boolean) =>
167
+ async (time: number) => {
168
+ if (isStateDate) {
169
+ const date = new Date(selectedDate);
170
+
171
+ if (key === "h") date.setHours(time);
172
+ if (key === "min") date.setMinutes(time);
173
+
174
+ setSelectedDate(date);
175
+ } else if (isDateRange) {
176
+ if (selectedDate.end && endTime) {
177
+ const date = new Date(selectedDate.end);
178
+
179
+ if (key === "h") date.setHours(time);
180
+ if (key === "min") date.setMinutes(time);
181
+
182
+ setSelectedDate((v) => ({ ...v, end: date }));
183
+ } else if (selectedDate.start) {
184
+ const date = new Date(selectedDate.start);
185
+
186
+ if (key === "h") date.setHours(time);
187
+ if (key === "min") date.setMinutes(time);
188
+
189
+ setSelectedDate((v) => ({ ...v, start: date }));
190
+ }
191
+ }
192
+ };
193
+
194
+ const save = async () => {
195
+ let data: DateValueType = selectedDate;
196
+
197
+ if (isStateDate && isValueTime)
198
+ data = formatDate(selectedDate, locales, mode) as TimeType;
199
+
200
+ if (isDateRange && isValueTimeRange)
201
+ data = {
202
+ start: formatDate(selectedDate.start, locales, mode) as TimeType,
203
+ end: formatDate(selectedDate.end as Date, locales, mode) as TimeType,
204
+ };
205
+
206
+ onChangeDate?.(data);
207
+
208
+ onToggle();
209
+ };
210
+
211
+ function Day({ date }: DayProps) {
212
+ const active = isActive({ min, max, date, disableDate });
213
+
214
+ const style = getStyle({
215
+ date,
216
+ shortDate,
217
+ selectedDate,
218
+ color,
219
+ active,
220
+ });
221
+
222
+ return (
223
+ <KTouchableOpacity
224
+ paddingHorizontal={16}
225
+ paddingVertical={10}
226
+ alignItems="center"
227
+ justifyContent="center"
228
+ nativeProps={{ onPress: selectDate(date), disabled: !active }}
229
+ {...style.touchableOpacity}
230
+ >
231
+ <KText textAlign="center" fontSize={16} {...style.text}>
232
+ {date.getDate()}
233
+ </KText>
234
+ </KTouchableOpacity>
235
+ );
236
+ }
237
+
238
+ function DayColumn({ label, dayNumber }: DayColumnProps) {
239
+ return (
240
+ <KView rowGap={3} flex={1} alignItems="stretch">
241
+ <DayLabel color={color}>{label}</DayLabel>
242
+ <Day date={matrix[dayNumber][0]} />
243
+ <Day date={matrix[dayNumber][1]} />
244
+ <Day date={matrix[dayNumber][2]} />
245
+ <Day date={matrix[dayNumber][3]} />
246
+ <Day date={matrix[dayNumber][4]} />
247
+ </KView>
248
+ );
249
+ }
250
+
251
+ return (
252
+ <>
253
+ {customTrigger ? (
254
+ customTrigger(onToggle)
255
+ ) : (
256
+ <Pressable
257
+ onPress={onToggle}
258
+ disabled={disabled}
259
+ style={{
260
+ width: "100%",
261
+ borderWidth: 1,
262
+ borderColor: "#0003",
263
+ paddingHorizontal: 16,
264
+ paddingVertical: 10,
265
+ borderRadius: 8,
266
+ backgroundColor: "white",
267
+ flexDirection: "row",
268
+ gap: 10,
269
+ alignItems: "center",
270
+ }}
271
+ >
272
+ <>
273
+ <Icon mode={mode} />
274
+ <KText fontSize={16} color={value ? undefined : "#0007"}>
275
+ {datetimeOuput}
276
+ </KText>
277
+ </>
278
+ </Pressable>
279
+ )}
280
+ <Modal
281
+ animationType="slide"
282
+ visible={isOpen}
283
+ transparent
284
+ onRequestClose={onToggle}
285
+ >
286
+ <KView flex={1} justifyContent="flex-end">
287
+ {isOpen && <Backdrop onPress={onToggle} />}
288
+ <SafeAreaView
289
+ style={{
290
+ minHeight: modeHasDate ? 470 : 200,
291
+ backgroundColor: "white",
292
+ padding: 20,
293
+ gap: 16,
294
+ }}
295
+ >
296
+ <KView
297
+ flexDirection="row"
298
+ justifyContent={modeHasTime ? "space-between" : "flex-end"}
299
+ alignItems="center"
300
+ >
301
+ {modeHasTime && (
302
+ <KView
303
+ flexDirection="row"
304
+ justifyContent="space-between"
305
+ alignItems="center"
306
+ gap={8}
307
+ >
308
+ <TimeView
309
+ date={isStateDate ? selectedDate : selectedDate.start}
310
+ onChangeHours={changeTime("h")}
311
+ onChangeMinutes={changeTime("min")}
312
+ showDate={modeHasDate}
313
+ color={color}
314
+ />
315
+ {(selectedDate as any)?.end && (
316
+ <>
317
+ <KView width={10} borderWidth={2} borderColor={color} />
318
+ <TimeView
319
+ date={(selectedDate as any).end}
320
+ onChangeHours={changeTime("h", true)}
321
+ onChangeMinutes={changeTime("min", true)}
322
+ showDate={modeHasDate}
323
+ color={color}
324
+ />
325
+ </>
326
+ )}
327
+ <SwipeIcon color={color} />
328
+ </KView>
329
+ )}
330
+ <KTouchableOpacity
331
+ nativeProps={{ onPress: save }}
332
+ alignItems="center"
333
+ justifyContent="center"
334
+ borderWidth={3}
335
+ paddingHorizontal={14}
336
+ paddingVertical={14}
337
+ borderColor={color}
338
+ >
339
+ <KText fontSize={20} fontWeight="bold" color={color}>
340
+ OK
341
+ </KText>
342
+ </KTouchableOpacity>
343
+ </KView>
344
+ <KView borderTopWidth={1} width="100%" borderColor={`${color}11`} />
345
+ {modeHasDate && (
346
+ <>
347
+ <KView
348
+ flexDirection="row"
349
+ justifyContent="space-between"
350
+ alignItems="center"
351
+ >
352
+ <ArrowButton
353
+ color={color}
354
+ onPress={changeMonth(-1)}
355
+ direction="left"
356
+ />
357
+ <KView flexDirection="row" alignItems="center" gap={4}>
358
+ <KText
359
+ fontWeight="bold"
360
+ fontSize={16}
361
+ textTransform="capitalize"
362
+ color={color}
363
+ minWidth={100}
364
+ textAlign="right"
365
+ >
366
+ {formatMonth(shortDate, locales)} -
367
+ </KText>
368
+ <KView
369
+ height={40}
370
+ backgroundColor={`${color}11`}
371
+ paddingHorizontal={10}
372
+ borderColor={`${color}11`}
373
+ flexDirection="row"
374
+ alignItems="center"
375
+ >
376
+ <Time
377
+ length={1000}
378
+ index={shortDate.getFullYear()}
379
+ height={40}
380
+ start={new Date().getFullYear() - 500}
381
+ onScrollEnd={changeYear}
382
+ color={color}
383
+ />
384
+ <SwipeIcon color={color} />
385
+ </KView>
386
+ </KView>
387
+ <ArrowButton
388
+ color={color}
389
+ onPress={changeMonth(1)}
390
+ direction="right"
391
+ />
392
+ </KView>
393
+ <KView
394
+ borderTopWidth={1}
395
+ width="100%"
396
+ borderColor={`${color}22`}
397
+ />
398
+ <KView flexDirection="row" flex={1}>
399
+ <DayColumn label={weekDays[0]} dayNumber={6} />
400
+ <DayColumn label={weekDays[1]} dayNumber={0} />
401
+ <DayColumn label={weekDays[2]} dayNumber={1} />
402
+ <DayColumn label={weekDays[3]} dayNumber={2} />
403
+ <DayColumn label={weekDays[4]} dayNumber={3} />
404
+ <DayColumn label={weekDays[5]} dayNumber={4} />
405
+ <DayColumn label={weekDays[6]} dayNumber={5} />
406
+ </KView>
407
+ </>
408
+ )}
409
+ </SafeAreaView>
410
+ </KView>
411
+ </Modal>
412
+ </>
413
+ );
414
+ }
415
+
416
+ export type { Calendar2kViewProps, DateValueType };
@@ -0,0 +1,19 @@
1
+ import * as React from 'react';
2
+
3
+ import { Calendar2kViewProps } from './Calendar2k.types';
4
+
5
+ export default function Calendar2kView(_props: Calendar2kViewProps) {
6
+ return (
7
+ <div
8
+ style={{
9
+ backgroundColor: '#aabbcc',
10
+ flex: 1,
11
+ display: 'flex',
12
+ flexDirection: 'column',
13
+ alignItems: 'center',
14
+ justifyContent: 'center',
15
+ }}>
16
+ <span>Calendar2k - native view</span>
17
+ </div>
18
+ );
19
+ }
Binary file
Binary file
Binary file
@@ -0,0 +1,40 @@
1
+ import { PropsWithChildren } from "react";
2
+ import { Image } from "react-native";
3
+ import { KTouchableOpacity } from "../ui";
4
+
5
+ type Props = {
6
+ onPress: () => void;
7
+ color?: string;
8
+ direction?: "right" | "left";
9
+ } & PropsWithChildren;
10
+ export default function ArrowButton({
11
+ onPress,
12
+ children,
13
+ color,
14
+ direction = "right",
15
+ }: Props) {
16
+ const source = () => {
17
+ switch (direction) {
18
+ case "right":
19
+ return require("../assets/images/chevron-right.png");
20
+ case "left":
21
+ return require("../assets/images/chevron-left.png");
22
+ }
23
+ };
24
+
25
+ return (
26
+ <KTouchableOpacity
27
+ backgroundColor={color}
28
+ width={35}
29
+ height={35}
30
+ alignItems="center"
31
+ justifyContent="center"
32
+ nativeProps={{ onPress }}
33
+ >
34
+ <Image
35
+ source={source()}
36
+ style={{ width: 12, height: 12, tintColor: "white" }}
37
+ />
38
+ </KTouchableOpacity>
39
+ );
40
+ }
@@ -0,0 +1,31 @@
1
+ import { useEffect, useRef } from "react";
2
+ import { Animated } from "react-native";
3
+ import { KTouchableOpacity } from "../ui";
4
+
5
+ type Props = {
6
+ onPress: () => void;
7
+ };
8
+ export default function Backdrop({ onPress }: Props) {
9
+ const fadeAnim = useRef(new Animated.Value(0)).current;
10
+
11
+ useEffect(() => {
12
+ Animated.timing(fadeAnim, {
13
+ toValue: 1,
14
+ duration: 800,
15
+ delay: 100,
16
+ useNativeDriver: true,
17
+ }).start();
18
+ }, []);
19
+
20
+ return (
21
+ <Animated.View
22
+ style={{
23
+ opacity: fadeAnim,
24
+ flex: 1,
25
+ backgroundColor: "#0003",
26
+ }}
27
+ >
28
+ <KTouchableOpacity flex={1} nativeProps={{ onPress }} />
29
+ </Animated.View>
30
+ );
31
+ }
@@ -0,0 +1,20 @@
1
+ import React, { PropsWithChildren } from "react";
2
+ import { KText, KView } from "../ui";
3
+
4
+ type Props = {
5
+ color?: string;
6
+ } & PropsWithChildren;
7
+ export default function DayLabel({ children, color }: Props) {
8
+ return (
9
+ <KView padding={4}>
10
+ <KText
11
+ textAlign="center"
12
+ fontWeight="bold"
13
+ textTransform="uppercase"
14
+ color={color}
15
+ >
16
+ {children}
17
+ </KText>
18
+ </KView>
19
+ );
20
+ }
@@ -0,0 +1,24 @@
1
+ import { Image } from "react-native";
2
+
3
+ type Props = {
4
+ color?: string;
5
+ mode?: "date" | "time" | "datetime";
6
+ };
7
+ export default function Icon({ color, mode }: Props) {
8
+ const source = () => {
9
+ switch (mode) {
10
+ case "time":
11
+ return require("../assets/images/clock.png");
12
+
13
+ default:
14
+ return require("../assets/images/calendar.png");
15
+ }
16
+ };
17
+
18
+ return (
19
+ <Image
20
+ source={source()}
21
+ style={{ width: 25, height: 25, tintColor: "#A1A1A1" }}
22
+ />
23
+ );
24
+ }
@@ -0,0 +1,13 @@
1
+ import { Image } from "react-native";
2
+
3
+ type Props = {
4
+ color?: string;
5
+ };
6
+ export default function SwipeIcon({ color }: Props) {
7
+ return (
8
+ <Image
9
+ source={require("../assets/images/swipe.png")}
10
+ style={{ width: 30, height: 30, tintColor: color }}
11
+ />
12
+ );
13
+ }