react-native-timer-picker 1.2.11 → 1.4.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.
- package/README.md +22 -2
- package/dist/commonjs/components/Modal/index.js +13 -14
- package/dist/commonjs/components/Modal/index.js.map +1 -1
- package/dist/commonjs/components/TimerPicker/DurationScroll.js +72 -34
- package/dist/commonjs/components/TimerPicker/DurationScroll.js.map +1 -1
- package/dist/commonjs/components/TimerPicker/TimerPicker.styles.js +23 -3
- package/dist/commonjs/components/TimerPicker/TimerPicker.styles.js.map +1 -1
- package/dist/commonjs/components/TimerPicker/index.js +64 -47
- package/dist/commonjs/components/TimerPicker/index.js.map +1 -1
- package/dist/commonjs/components/index.js +90 -69
- package/dist/commonjs/components/index.js.map +1 -1
- package/dist/commonjs/tests/Modal.test.js +3 -1
- package/dist/commonjs/tests/Modal.test.js.map +1 -1
- package/dist/commonjs/utils/generateNumbers.js +33 -10
- package/dist/commonjs/utils/generateNumbers.js.map +1 -1
- package/dist/commonjs/utils/padNumber.js +15 -0
- package/dist/commonjs/utils/padNumber.js.map +1 -0
- package/dist/module/components/Modal/index.js +13 -14
- package/dist/module/components/Modal/index.js.map +1 -1
- package/dist/module/components/TimerPicker/DurationScroll.js +73 -35
- package/dist/module/components/TimerPicker/DurationScroll.js.map +1 -1
- package/dist/module/components/TimerPicker/TimerPicker.styles.js +23 -3
- package/dist/module/components/TimerPicker/TimerPicker.styles.js.map +1 -1
- package/dist/module/components/TimerPicker/index.js +64 -47
- package/dist/module/components/TimerPicker/index.js.map +1 -1
- package/dist/module/components/index.js +90 -69
- package/dist/module/components/index.js.map +1 -1
- package/dist/module/tests/Modal.test.js +3 -1
- package/dist/module/tests/Modal.test.js.map +1 -1
- package/dist/module/utils/generateNumbers.js +31 -9
- package/dist/module/utils/generateNumbers.js.map +1 -1
- package/dist/module/utils/padNumber.js +8 -0
- package/dist/module/utils/padNumber.js.map +1 -0
- package/dist/typescript/components/TimerPicker/DurationScroll.d.ts +6 -1
- package/dist/typescript/components/TimerPicker/TimerPicker.styles.d.ts +4 -0
- package/dist/typescript/components/TimerPicker/index.d.ts +10 -1
- package/dist/typescript/components/index.d.ts +6 -1
- package/dist/typescript/utils/generateNumbers.d.ts +7 -2
- package/dist/typescript/utils/padNumber.d.ts +3 -0
- package/package.json +2 -2
- package/src/components/Modal/index.tsx +2 -2
- package/src/components/TimerPicker/DurationScroll.tsx +95 -12
- package/src/components/TimerPicker/TimerPicker.styles.ts +32 -1
- package/src/components/TimerPicker/index.tsx +39 -6
- package/src/components/index.tsx +45 -15
- package/src/tests/Modal.test.tsx +1 -1
- package/src/utils/generateNumbers.ts +40 -10
- package/src/utils/padNumber.ts +10 -0
- package/dist/commonjs/utils/padWithZero.js +0 -15
- package/dist/commonjs/utils/padWithZero.js.map +0 -1
- package/dist/module/utils/padWithZero.js +0 -8
- package/dist/module/utils/padWithZero.js.map +0 -1
- package/dist/typescript/utils/padWithZero.d.ts +0 -1
- package/src/utils/padWithZero.ts +0 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["padNumber","generateNumbers","numberOfItems","options","numbers","i","push","padWithZero","padNumbersWithZero","repeatNTimes","Array","fill","flat","disableInfiniteScroll","padWithNItems","unshift","generate12HourNumbers","hour"],"sources":["generateNumbers.ts"],"sourcesContent":["import { padNumber } from \"./padNumber\";\n\nexport const generateNumbers = (\n numberOfItems: number,\n options: {\n repeatNTimes?: number;\n padNumbersWithZero?: boolean;\n disableInfiniteScroll?: boolean;\n padWithNItems: number;\n }\n) => {\n if (numberOfItems <= 0) {\n return [];\n }\n\n let numbers: string[] = [];\n for (let i = 0; i <= numberOfItems; i++) {\n numbers.push(padNumber(i, { padWithZero: options.padNumbersWithZero }));\n }\n\n if ((options.repeatNTimes ?? 1) > 1) {\n numbers = Array(options.repeatNTimes).fill(numbers).flat();\n }\n if (options.disableInfiniteScroll) {\n numbers.push(...Array(options.padWithNItems).fill(\"\"));\n numbers.unshift(...Array(options.padWithNItems).fill(\"\"));\n }\n return numbers;\n};\n\nexport const generate12HourNumbers = (options: {\n repeatNTimes?: number;\n padNumbersWithZero?: boolean;\n disableInfiniteScroll?: boolean;\n padWithNItems: number;\n}) => {\n let numbers: string[] = [];\n\n // Generate numbers from 0 to 11 for AM\n for (let i = 0; i <= 11; i++) {\n numbers.push(\n `${padNumber(i, { padWithZero: options.padNumbersWithZero })} AM`\n );\n }\n\n // Generate numbers from 12 to 11 for PM\n for (let i = 12; i <= 23; i++) {\n const hour = i > 12 ? i - 12 : i;\n numbers.push(\n `${padNumber(hour, { padWithZero: options.padNumbersWithZero })} PM`\n );\n }\n\n if ((options.repeatNTimes ?? 1) > 1) {\n numbers = Array(options.repeatNTimes).fill(numbers).flat();\n }\n\n if (options.disableInfiniteScroll) {\n numbers.push(...Array(options.padWithNItems).fill(\"\"));\n numbers.unshift(...Array(options.padWithNItems).fill(\"\"));\n }\n\n return numbers;\n};\n"],"mappings":"AAAA,SAASA,SAAS,QAAQ,aAAa;AAEvC,OAAO,MAAMC,eAAe,GAAGA,CAC3BC,aAAqB,EACrBC,OAKC,KACA;EACD,IAAID,aAAa,IAAI,CAAC,EAAE;IACpB,OAAO,EAAE;EACb;EAEA,IAAIE,OAAiB,GAAG,EAAE;EAC1B,KAAK,IAAIC,CAAC,GAAG,CAAC,EAAEA,CAAC,IAAIH,aAAa,EAAEG,CAAC,EAAE,EAAE;IACrCD,OAAO,CAACE,IAAI,CAACN,SAAS,CAACK,CAAC,EAAE;MAAEE,WAAW,EAAEJ,OAAO,CAACK;IAAmB,CAAC,CAAC,CAAC;EAC3E;EAEA,IAAI,CAACL,OAAO,CAACM,YAAY,IAAI,CAAC,IAAI,CAAC,EAAE;IACjCL,OAAO,GAAGM,KAAK,CAACP,OAAO,CAACM,YAAY,CAAC,CAACE,IAAI,CAACP,OAAO,CAAC,CAACQ,IAAI,CAAC,CAAC;EAC9D;EACA,IAAIT,OAAO,CAACU,qBAAqB,EAAE;IAC/BT,OAAO,CAACE,IAAI,CAAC,GAAGI,KAAK,CAACP,OAAO,CAACW,aAAa,CAAC,CAACH,IAAI,CAAC,EAAE,CAAC,CAAC;IACtDP,OAAO,CAACW,OAAO,CAAC,GAAGL,KAAK,CAACP,OAAO,CAACW,aAAa,CAAC,CAACH,IAAI,CAAC,EAAE,CAAC,CAAC;EAC7D;EACA,OAAOP,OAAO;AAClB,CAAC;AAED,OAAO,MAAMY,qBAAqB,GAAIb,OAKrC,IAAK;EACF,IAAIC,OAAiB,GAAG,EAAE;;EAE1B;EACA,KAAK,IAAIC,CAAC,GAAG,CAAC,EAAEA,CAAC,IAAI,EAAE,EAAEA,CAAC,EAAE,EAAE;IAC1BD,OAAO,CAACE,IAAI,CACP,GAAEN,SAAS,CAACK,CAAC,EAAE;MAAEE,WAAW,EAAEJ,OAAO,CAACK;IAAmB,CAAC,CAAE,KACjE,CAAC;EACL;;EAEA;EACA,KAAK,IAAIH,CAAC,GAAG,EAAE,EAAEA,CAAC,IAAI,EAAE,EAAEA,CAAC,EAAE,EAAE;IAC3B,MAAMY,IAAI,GAAGZ,CAAC,GAAG,EAAE,GAAGA,CAAC,GAAG,EAAE,GAAGA,CAAC;IAChCD,OAAO,CAACE,IAAI,CACP,GAAEN,SAAS,CAACiB,IAAI,EAAE;MAAEV,WAAW,EAAEJ,OAAO,CAACK;IAAmB,CAAC,CAAE,KACpE,CAAC;EACL;EAEA,IAAI,CAACL,OAAO,CAACM,YAAY,IAAI,CAAC,IAAI,CAAC,EAAE;IACjCL,OAAO,GAAGM,KAAK,CAACP,OAAO,CAACM,YAAY,CAAC,CAACE,IAAI,CAACP,OAAO,CAAC,CAACQ,IAAI,CAAC,CAAC;EAC9D;EAEA,IAAIT,OAAO,CAACU,qBAAqB,EAAE;IAC/BT,OAAO,CAACE,IAAI,CAAC,GAAGI,KAAK,CAACP,OAAO,CAACW,aAAa,CAAC,CAACH,IAAI,CAAC,EAAE,CAAC,CAAC;IACtDP,OAAO,CAACW,OAAO,CAAC,GAAGL,KAAK,CAACP,OAAO,CAACW,aAAa,CAAC,CAACH,IAAI,CAAC,EAAE,CAAC,CAAC;EAC7D;EAEA,OAAOP,OAAO;AAClB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["padNumber","value","options","padWithZero","String"],"sources":["padNumber.ts"],"sourcesContent":["export const padNumber = (\n value: number,\n options?: { padWithZero?: boolean }\n): string => {\n if (value < 10) {\n return (options?.padWithZero ? \"0\" : \" \") + value;\n } else {\n return String(value);\n }\n};\n"],"mappings":"AAAA,OAAO,MAAMA,SAAS,GAAGA,CACrBC,KAAa,EACbC,OAAmC,KAC1B;EACT,IAAID,KAAK,GAAG,EAAE,EAAE;IACZ,OAAO,CAACC,OAAO,aAAPA,OAAO,eAAPA,OAAO,CAAEC,WAAW,GAAG,GAAG,GAAG,GAAG,IAAIF,KAAK;EACrD,CAAC,MAAM;IACH,OAAOG,MAAM,CAACH,KAAK,CAAC;EACxB;AACJ,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { MutableRefObject } from "react";
|
|
2
2
|
import { View } from "react-native";
|
|
3
3
|
import { generateStyles } from "./TimerPicker.styles";
|
|
4
4
|
export interface DurationScrollRef {
|
|
@@ -8,6 +8,7 @@ export interface DurationScrollRef {
|
|
|
8
8
|
setValue: (value: number, options?: {
|
|
9
9
|
animated?: boolean;
|
|
10
10
|
}) => void;
|
|
11
|
+
latestDuration: MutableRefObject<number>;
|
|
11
12
|
}
|
|
12
13
|
type LinearGradientPoint = {
|
|
13
14
|
x: number;
|
|
@@ -31,6 +32,10 @@ interface DurationScrollProps {
|
|
|
31
32
|
padNumbersWithZero?: boolean;
|
|
32
33
|
disableInfiniteScroll?: boolean;
|
|
33
34
|
limit?: LimitType;
|
|
35
|
+
aggressivelyGetLatestDuration: boolean;
|
|
36
|
+
is12HourPicker?: boolean;
|
|
37
|
+
amLabel?: string;
|
|
38
|
+
pmLabel?: string;
|
|
34
39
|
padWithNItems: number;
|
|
35
40
|
pickerGradientOverlayProps?: Partial<LinearGradientProps>;
|
|
36
41
|
topPickerGradientOverlayProps?: Partial<LinearGradientProps>;
|
|
@@ -5,6 +5,8 @@ export interface CustomTimerPickerStyles {
|
|
|
5
5
|
pickerContainer?: any;
|
|
6
6
|
pickerLabelContainer?: any;
|
|
7
7
|
pickerLabel?: any;
|
|
8
|
+
pickerAmPmContainer?: any;
|
|
9
|
+
pickerAmPmLabel?: any;
|
|
8
10
|
pickerItemContainer?: any;
|
|
9
11
|
pickerItem?: any;
|
|
10
12
|
disabledPickerItem?: any;
|
|
@@ -18,6 +20,8 @@ export declare const generateStyles: (customStyles: CustomTimerPickerStyles | un
|
|
|
18
20
|
pickerLabel: any;
|
|
19
21
|
pickerItemContainer: any;
|
|
20
22
|
pickerItem: any;
|
|
23
|
+
pickerAmPmContainer: any;
|
|
24
|
+
pickerAmPmLabel: any;
|
|
21
25
|
disabledPickerItem: any;
|
|
22
26
|
pickerGradientOverlay: any;
|
|
23
27
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { MutableRefObject } from "react";
|
|
2
2
|
import { View } from "react-native";
|
|
3
3
|
import { LimitType } from "./DurationScroll";
|
|
4
4
|
import { CustomTimerPickerStyles } from "./TimerPicker.styles";
|
|
@@ -14,6 +14,11 @@ export interface TimerPickerRef {
|
|
|
14
14
|
}, options?: {
|
|
15
15
|
animated?: boolean;
|
|
16
16
|
}) => void;
|
|
17
|
+
latestDuration: {
|
|
18
|
+
hours: MutableRefObject<number> | undefined;
|
|
19
|
+
minutes: MutableRefObject<number> | undefined;
|
|
20
|
+
seconds: MutableRefObject<number> | undefined;
|
|
21
|
+
};
|
|
17
22
|
}
|
|
18
23
|
export interface TimerPickerProps {
|
|
19
24
|
onDurationChange?: (duration: {
|
|
@@ -24,6 +29,10 @@ export interface TimerPickerProps {
|
|
|
24
29
|
initialHours?: number;
|
|
25
30
|
initialMinutes?: number;
|
|
26
31
|
initialSeconds?: number;
|
|
32
|
+
aggressivelyGetLatestDuration?: boolean;
|
|
33
|
+
use12HourPicker?: boolean;
|
|
34
|
+
amLabel?: string;
|
|
35
|
+
pmLabel?: string;
|
|
27
36
|
hideHours?: boolean;
|
|
28
37
|
hideMinutes?: boolean;
|
|
29
38
|
hideSeconds?: boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { MutableRefObject } from "react";
|
|
2
2
|
import { View, Text, TouchableOpacity } from "react-native";
|
|
3
3
|
import { TimerPickerProps } from "./TimerPicker";
|
|
4
4
|
import Modal from "./Modal";
|
|
@@ -14,6 +14,11 @@ export interface TimerPickerModalRef {
|
|
|
14
14
|
}, options?: {
|
|
15
15
|
animated?: boolean;
|
|
16
16
|
}) => void;
|
|
17
|
+
latestDuration: {
|
|
18
|
+
hours: MutableRefObject<number> | undefined;
|
|
19
|
+
minutes: MutableRefObject<number> | undefined;
|
|
20
|
+
seconds: MutableRefObject<number> | undefined;
|
|
21
|
+
};
|
|
17
22
|
}
|
|
18
23
|
export interface TimerPickerModalProps extends TimerPickerProps {
|
|
19
24
|
visible: boolean;
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import { padWithZero } from "./padWithZero";
|
|
2
1
|
export declare const generateNumbers: (numberOfItems: number, options: {
|
|
3
2
|
repeatNTimes?: number;
|
|
4
|
-
|
|
3
|
+
padNumbersWithZero?: boolean;
|
|
4
|
+
disableInfiniteScroll?: boolean;
|
|
5
|
+
padWithNItems: number;
|
|
6
|
+
}) => string[];
|
|
7
|
+
export declare const generate12HourNumbers: (options: {
|
|
8
|
+
repeatNTimes?: number;
|
|
9
|
+
padNumbersWithZero?: boolean;
|
|
5
10
|
disableInfiniteScroll?: boolean;
|
|
6
11
|
padWithNItems: number;
|
|
7
12
|
}) => string[];
|
package/package.json
CHANGED
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
"url": "https://github.com/troberts-28"
|
|
7
7
|
},
|
|
8
8
|
"license": "MIT",
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.4.0",
|
|
10
10
|
"main": "dist/commonjs/index.js",
|
|
11
11
|
"types": "dist/typescript/src/index.d.ts",
|
|
12
12
|
"scripts": {
|
|
13
13
|
"test": "jest --forceExit --silent",
|
|
14
14
|
"build": "bob build",
|
|
15
15
|
"clean": "rm yarn.lock && rm -rf ./node_modules && yarn install",
|
|
16
|
-
"start": "cp -Rf src example && cd example &&
|
|
16
|
+
"start": "cp -Rf src example && cd example && npx expo install && npx expo start",
|
|
17
17
|
"lint": "eslint --ext .ts,.tsx .",
|
|
18
18
|
"lint:fix": "eslint --ext .ts,.tsx . --fix",
|
|
19
19
|
"prepare": "yarn build"
|
|
@@ -33,7 +33,7 @@ export const Modal = ({
|
|
|
33
33
|
modalProps,
|
|
34
34
|
contentStyle,
|
|
35
35
|
overlayStyle,
|
|
36
|
-
testID,
|
|
36
|
+
testID = "modal",
|
|
37
37
|
}: ModalProps): React.ReactElement => {
|
|
38
38
|
const { width: screenWidth, height: screenHeight } = useWindowDimensions();
|
|
39
39
|
|
|
@@ -109,7 +109,7 @@ export const Modal = ({
|
|
|
109
109
|
animationType="fade"
|
|
110
110
|
visible={isVisible}
|
|
111
111
|
{...modalProps}
|
|
112
|
-
testID={testID
|
|
112
|
+
testID={testID}>
|
|
113
113
|
<TouchableWithoutFeedback
|
|
114
114
|
onPress={onOverlayPress}
|
|
115
115
|
testID="modal-backdrop">
|
|
@@ -3,6 +3,7 @@ import React, {
|
|
|
3
3
|
useCallback,
|
|
4
4
|
forwardRef,
|
|
5
5
|
useImperativeHandle,
|
|
6
|
+
MutableRefObject,
|
|
6
7
|
} from "react";
|
|
7
8
|
import {
|
|
8
9
|
View,
|
|
@@ -14,7 +15,10 @@ import {
|
|
|
14
15
|
NativeScrollEvent,
|
|
15
16
|
} from "react-native";
|
|
16
17
|
|
|
17
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
generate12HourNumbers,
|
|
20
|
+
generateNumbers,
|
|
21
|
+
} from "../../utils/generateNumbers";
|
|
18
22
|
import { colorToRgba } from "../../utils/colorToRgba";
|
|
19
23
|
import { generateStyles } from "./TimerPicker.styles";
|
|
20
24
|
import { getAdjustedLimit } from "../../utils/getAdjustedLimit";
|
|
@@ -23,6 +27,7 @@ import { getScrollIndex } from "../../utils/getScrollIndex";
|
|
|
23
27
|
export interface DurationScrollRef {
|
|
24
28
|
reset: (options?: { animated?: boolean }) => void;
|
|
25
29
|
setValue: (value: number, options?: { animated?: boolean }) => void;
|
|
30
|
+
latestDuration: MutableRefObject<number>;
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
type LinearGradientPoint = {
|
|
@@ -50,6 +55,10 @@ interface DurationScrollProps {
|
|
|
50
55
|
padNumbersWithZero?: boolean;
|
|
51
56
|
disableInfiniteScroll?: boolean;
|
|
52
57
|
limit?: LimitType;
|
|
58
|
+
aggressivelyGetLatestDuration: boolean;
|
|
59
|
+
is12HourPicker?: boolean;
|
|
60
|
+
amLabel?: string;
|
|
61
|
+
pmLabel?: string;
|
|
53
62
|
padWithNItems: number;
|
|
54
63
|
pickerGradientOverlayProps?: Partial<LinearGradientProps>;
|
|
55
64
|
topPickerGradientOverlayProps?: Partial<LinearGradientProps>;
|
|
@@ -73,6 +82,10 @@ const DurationScroll = forwardRef<DurationScrollRef, DurationScrollProps>(
|
|
|
73
82
|
padNumbersWithZero = false,
|
|
74
83
|
disableInfiniteScroll = false,
|
|
75
84
|
limit,
|
|
85
|
+
aggressivelyGetLatestDuration,
|
|
86
|
+
is12HourPicker,
|
|
87
|
+
amLabel,
|
|
88
|
+
pmLabel,
|
|
76
89
|
padWithNItems,
|
|
77
90
|
pickerGradientOverlayProps,
|
|
78
91
|
topPickerGradientOverlayProps,
|
|
@@ -83,14 +96,19 @@ const DurationScroll = forwardRef<DurationScrollRef, DurationScrollProps>(
|
|
|
83
96
|
},
|
|
84
97
|
ref
|
|
85
98
|
): React.ReactElement => {
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
99
|
+
const data = !is12HourPicker
|
|
100
|
+
? generateNumbers(numberOfItems, {
|
|
101
|
+
padNumbersWithZero,
|
|
102
|
+
repeatNTimes: 3,
|
|
103
|
+
disableInfiniteScroll,
|
|
104
|
+
padWithNItems,
|
|
105
|
+
})
|
|
106
|
+
: generate12HourNumbers({
|
|
107
|
+
padNumbersWithZero,
|
|
108
|
+
repeatNTimes: 3,
|
|
109
|
+
disableInfiniteScroll,
|
|
110
|
+
padWithNItems,
|
|
111
|
+
});
|
|
94
112
|
|
|
95
113
|
const numberOfItemsToShow = 1 + padWithNItems * 2;
|
|
96
114
|
|
|
@@ -103,6 +121,10 @@ const DurationScroll = forwardRef<DurationScrollRef, DurationScrollProps>(
|
|
|
103
121
|
disableInfiniteScroll,
|
|
104
122
|
});
|
|
105
123
|
|
|
124
|
+
const latestDuration = useRef(0);
|
|
125
|
+
|
|
126
|
+
const flatListRef = useRef<FlatList | null>(null);
|
|
127
|
+
|
|
106
128
|
useImperativeHandle(ref, () => ({
|
|
107
129
|
reset: (options) => {
|
|
108
130
|
flatListRef.current?.scrollToIndex({
|
|
@@ -121,11 +143,22 @@ const DurationScroll = forwardRef<DurationScrollRef, DurationScrollProps>(
|
|
|
121
143
|
}),
|
|
122
144
|
});
|
|
123
145
|
},
|
|
146
|
+
latestDuration: latestDuration,
|
|
124
147
|
}));
|
|
125
148
|
|
|
126
149
|
const renderItem = useCallback(
|
|
127
150
|
({ item }: { item: string }) => {
|
|
128
|
-
|
|
151
|
+
let stringItem = item;
|
|
152
|
+
let intItem: number;
|
|
153
|
+
let isAm: boolean | undefined;
|
|
154
|
+
|
|
155
|
+
if (!is12HourPicker) {
|
|
156
|
+
intItem = parseInt(item);
|
|
157
|
+
} else {
|
|
158
|
+
isAm = item.includes("AM");
|
|
159
|
+
stringItem = item.replace(/\s[AP]M/g, "");
|
|
160
|
+
intItem = parseInt(stringItem);
|
|
161
|
+
}
|
|
129
162
|
|
|
130
163
|
return (
|
|
131
164
|
<View
|
|
@@ -140,20 +173,67 @@ const DurationScroll = forwardRef<DurationScrollRef, DurationScrollProps>(
|
|
|
140
173
|
? styles.disabledPickerItem
|
|
141
174
|
: {},
|
|
142
175
|
]}>
|
|
143
|
-
{
|
|
176
|
+
{stringItem}
|
|
144
177
|
</Text>
|
|
178
|
+
{is12HourPicker ? (
|
|
179
|
+
<View
|
|
180
|
+
style={styles.pickerAmPmContainer}
|
|
181
|
+
pointerEvents="none">
|
|
182
|
+
<Text style={[styles.pickerAmPmLabel]}>
|
|
183
|
+
{isAm ? amLabel : pmLabel}
|
|
184
|
+
</Text>
|
|
185
|
+
</View>
|
|
186
|
+
) : null}
|
|
145
187
|
</View>
|
|
146
188
|
);
|
|
147
189
|
},
|
|
148
190
|
[
|
|
149
191
|
adjustedLimited.max,
|
|
150
192
|
adjustedLimited.min,
|
|
193
|
+
amLabel,
|
|
194
|
+
is12HourPicker,
|
|
195
|
+
pmLabel,
|
|
151
196
|
styles.disabledPickerItem,
|
|
197
|
+
styles.pickerAmPmContainer,
|
|
198
|
+
styles.pickerAmPmLabel,
|
|
152
199
|
styles.pickerItem,
|
|
153
200
|
styles.pickerItemContainer,
|
|
154
201
|
]
|
|
155
202
|
);
|
|
156
203
|
|
|
204
|
+
const onScroll = useCallback(
|
|
205
|
+
(e: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
206
|
+
// this function is only used when the picker is in a modal
|
|
207
|
+
// it is used to ensure that the modal gets the latest duration on clicking
|
|
208
|
+
// the confirm button, even if the scrollview is still scrolling
|
|
209
|
+
const newIndex = Math.round(
|
|
210
|
+
e.nativeEvent.contentOffset.y /
|
|
211
|
+
styles.pickerItemContainer.height
|
|
212
|
+
);
|
|
213
|
+
let newDuration =
|
|
214
|
+
(disableInfiniteScroll
|
|
215
|
+
? newIndex
|
|
216
|
+
: newIndex + padWithNItems) %
|
|
217
|
+
(numberOfItems + 1);
|
|
218
|
+
|
|
219
|
+
// check limits
|
|
220
|
+
if (newDuration > adjustedLimited.max) {
|
|
221
|
+
newDuration = adjustedLimited.max;
|
|
222
|
+
} else if (newDuration < adjustedLimited.min) {
|
|
223
|
+
newDuration = adjustedLimited.min;
|
|
224
|
+
}
|
|
225
|
+
latestDuration.current = newDuration;
|
|
226
|
+
},
|
|
227
|
+
[
|
|
228
|
+
adjustedLimited.max,
|
|
229
|
+
adjustedLimited.min,
|
|
230
|
+
disableInfiniteScroll,
|
|
231
|
+
numberOfItems,
|
|
232
|
+
padWithNItems,
|
|
233
|
+
styles.pickerItemContainer.height,
|
|
234
|
+
]
|
|
235
|
+
);
|
|
236
|
+
|
|
157
237
|
const onMomentumScrollEnd = useCallback(
|
|
158
238
|
(e: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
159
239
|
const newIndex = Math.round(
|
|
@@ -264,7 +344,7 @@ const DurationScroll = forwardRef<DurationScrollRef, DurationScrollProps>(
|
|
|
264
344
|
renderItem={renderItem}
|
|
265
345
|
keyExtractor={KEY_EXTRACTOR}
|
|
266
346
|
showsVerticalScrollIndicator={false}
|
|
267
|
-
decelerationRate={0.
|
|
347
|
+
decelerationRate={0.88}
|
|
268
348
|
scrollEventThrottle={16}
|
|
269
349
|
snapToAlignment="start"
|
|
270
350
|
// used in place of snapToOffset due to bug on Android
|
|
@@ -277,6 +357,9 @@ const DurationScroll = forwardRef<DurationScrollRef, DurationScrollProps>(
|
|
|
277
357
|
: undefined
|
|
278
358
|
}
|
|
279
359
|
onMomentumScrollEnd={onMomentumScrollEnd}
|
|
360
|
+
onScroll={
|
|
361
|
+
aggressivelyGetLatestDuration ? onScroll : undefined
|
|
362
|
+
}
|
|
280
363
|
testID="duration-scroll-flatlist"
|
|
281
364
|
/>
|
|
282
365
|
<View style={styles.pickerLabelContainer} pointerEvents="none">
|
|
@@ -8,6 +8,8 @@ export interface CustomTimerPickerStyles {
|
|
|
8
8
|
pickerContainer?: any;
|
|
9
9
|
pickerLabelContainer?: any;
|
|
10
10
|
pickerLabel?: any;
|
|
11
|
+
pickerAmPmContainer?: any;
|
|
12
|
+
pickerAmPmLabel?: any;
|
|
11
13
|
pickerItemContainer?: any;
|
|
12
14
|
pickerItem?: any;
|
|
13
15
|
disabledPickerItem?: any;
|
|
@@ -40,12 +42,19 @@ export const generateStyles = (
|
|
|
40
42
|
top: 0,
|
|
41
43
|
bottom: 0,
|
|
42
44
|
justifyContent: "center",
|
|
45
|
+
minWidth:
|
|
46
|
+
(customStyles?.pickerLabel?.fontSize ??
|
|
47
|
+
customStyles?.text?.fontSize ??
|
|
48
|
+
25) * 0.65,
|
|
43
49
|
...customStyles?.pickerLabelContainer,
|
|
44
50
|
},
|
|
45
51
|
pickerLabel: {
|
|
46
52
|
fontSize: 18,
|
|
47
53
|
fontWeight: "bold",
|
|
48
|
-
marginTop:
|
|
54
|
+
marginTop:
|
|
55
|
+
(customStyles?.pickerItem?.fontSize ??
|
|
56
|
+
customStyles?.text?.fontSize ??
|
|
57
|
+
25) / 6,
|
|
49
58
|
color:
|
|
50
59
|
customStyles?.theme === "dark"
|
|
51
60
|
? DARK_MODE_TEXT_COLOR
|
|
@@ -54,6 +63,7 @@ export const generateStyles = (
|
|
|
54
63
|
...customStyles?.pickerLabel,
|
|
55
64
|
},
|
|
56
65
|
pickerItemContainer: {
|
|
66
|
+
flexDirection: "row",
|
|
57
67
|
height: 50,
|
|
58
68
|
justifyContent: "center",
|
|
59
69
|
alignItems: "center",
|
|
@@ -70,6 +80,27 @@ export const generateStyles = (
|
|
|
70
80
|
...customStyles?.text,
|
|
71
81
|
...customStyles?.pickerItem,
|
|
72
82
|
},
|
|
83
|
+
pickerAmPmContainer: {
|
|
84
|
+
position: "absolute",
|
|
85
|
+
right: 0,
|
|
86
|
+
top: 0,
|
|
87
|
+
bottom: 0,
|
|
88
|
+
justifyContent: "center",
|
|
89
|
+
...customStyles?.pickerLabelContainer,
|
|
90
|
+
...customStyles?.pickerAmPmContainer,
|
|
91
|
+
},
|
|
92
|
+
pickerAmPmLabel: {
|
|
93
|
+
fontSize: 18,
|
|
94
|
+
fontWeight: "bold",
|
|
95
|
+
marginTop: (customStyles?.pickerItem?.fontSize ?? 25) / 6,
|
|
96
|
+
color:
|
|
97
|
+
customStyles?.theme === "dark"
|
|
98
|
+
? DARK_MODE_TEXT_COLOR
|
|
99
|
+
: LIGHT_MODE_TEXT_COLOR,
|
|
100
|
+
...customStyles?.text,
|
|
101
|
+
...customStyles?.pickerLabel,
|
|
102
|
+
...customStyles?.pickerAmPmLabel,
|
|
103
|
+
},
|
|
73
104
|
disabledPickerItem: {
|
|
74
105
|
opacity: 0.2,
|
|
75
106
|
...customStyles?.disabledPickerItem,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, {
|
|
2
|
+
MutableRefObject,
|
|
2
3
|
forwardRef,
|
|
3
4
|
useEffect,
|
|
4
5
|
useImperativeHandle,
|
|
@@ -23,6 +24,11 @@ export interface TimerPickerRef {
|
|
|
23
24
|
},
|
|
24
25
|
options?: { animated?: boolean }
|
|
25
26
|
) => void;
|
|
27
|
+
latestDuration: {
|
|
28
|
+
hours: MutableRefObject<number> | undefined;
|
|
29
|
+
minutes: MutableRefObject<number> | undefined;
|
|
30
|
+
seconds: MutableRefObject<number> | undefined;
|
|
31
|
+
};
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
export interface TimerPickerProps {
|
|
@@ -34,6 +40,10 @@ export interface TimerPickerProps {
|
|
|
34
40
|
initialHours?: number;
|
|
35
41
|
initialMinutes?: number;
|
|
36
42
|
initialSeconds?: number;
|
|
43
|
+
aggressivelyGetLatestDuration?: boolean;
|
|
44
|
+
use12HourPicker?: boolean;
|
|
45
|
+
amLabel?: string;
|
|
46
|
+
pmLabel?: string;
|
|
37
47
|
hideHours?: boolean;
|
|
38
48
|
hideMinutes?: boolean;
|
|
39
49
|
hideSeconds?: boolean;
|
|
@@ -67,11 +77,15 @@ const TimerPicker = forwardRef<TimerPickerRef, TimerPickerProps>(
|
|
|
67
77
|
hourLimit,
|
|
68
78
|
minuteLimit,
|
|
69
79
|
secondLimit,
|
|
70
|
-
hourLabel
|
|
71
|
-
minuteLabel
|
|
72
|
-
secondLabel
|
|
80
|
+
hourLabel,
|
|
81
|
+
minuteLabel,
|
|
82
|
+
secondLabel,
|
|
73
83
|
padWithNItems = 1,
|
|
74
84
|
disableInfiniteScroll = false,
|
|
85
|
+
aggressivelyGetLatestDuration = false,
|
|
86
|
+
use12HourPicker = false,
|
|
87
|
+
amLabel = "am",
|
|
88
|
+
pmLabel = "pm",
|
|
75
89
|
LinearGradient,
|
|
76
90
|
pickerContainerProps,
|
|
77
91
|
pickerGradientOverlayProps,
|
|
@@ -133,6 +147,11 @@ const TimerPicker = forwardRef<TimerPickerRef, TimerPickerProps>(
|
|
|
133
147
|
options
|
|
134
148
|
);
|
|
135
149
|
},
|
|
150
|
+
latestDuration: {
|
|
151
|
+
hours: hoursDurationScrollRef.current?.latestDuration,
|
|
152
|
+
minutes: minutesDurationScrollRef.current?.latestDuration,
|
|
153
|
+
seconds: secondsDurationScrollRef.current?.latestDuration,
|
|
154
|
+
},
|
|
136
155
|
}));
|
|
137
156
|
|
|
138
157
|
return (
|
|
@@ -144,8 +163,13 @@ const TimerPicker = forwardRef<TimerPickerRef, TimerPickerProps>(
|
|
|
144
163
|
<DurationScroll
|
|
145
164
|
ref={hoursDurationScrollRef}
|
|
146
165
|
numberOfItems={23}
|
|
147
|
-
label={
|
|
166
|
+
label={
|
|
167
|
+
hourLabel ?? (!use12HourPicker ? "h" : undefined)
|
|
168
|
+
}
|
|
148
169
|
initialValue={initialHours}
|
|
170
|
+
aggressivelyGetLatestDuration={
|
|
171
|
+
aggressivelyGetLatestDuration
|
|
172
|
+
}
|
|
149
173
|
onDurationChange={setSelectedHours}
|
|
150
174
|
pickerGradientOverlayProps={pickerGradientOverlayProps}
|
|
151
175
|
topPickerGradientOverlayProps={
|
|
@@ -158,6 +182,9 @@ const TimerPicker = forwardRef<TimerPickerRef, TimerPickerProps>(
|
|
|
158
182
|
padWithNItems={checkedPadWithNItems}
|
|
159
183
|
limit={hourLimit}
|
|
160
184
|
LinearGradient={LinearGradient}
|
|
185
|
+
is12HourPicker={use12HourPicker}
|
|
186
|
+
amLabel={amLabel}
|
|
187
|
+
pmLabel={pmLabel}
|
|
161
188
|
styles={styles}
|
|
162
189
|
testID="duration-scroll-hour"
|
|
163
190
|
/>
|
|
@@ -166,8 +193,11 @@ const TimerPicker = forwardRef<TimerPickerRef, TimerPickerProps>(
|
|
|
166
193
|
<DurationScroll
|
|
167
194
|
ref={minutesDurationScrollRef}
|
|
168
195
|
numberOfItems={59}
|
|
169
|
-
label={minuteLabel}
|
|
196
|
+
label={minuteLabel ?? "m"}
|
|
170
197
|
initialValue={initialMinutes}
|
|
198
|
+
aggressivelyGetLatestDuration={
|
|
199
|
+
aggressivelyGetLatestDuration
|
|
200
|
+
}
|
|
171
201
|
onDurationChange={setSelectedMinutes}
|
|
172
202
|
padNumbersWithZero
|
|
173
203
|
pickerGradientOverlayProps={pickerGradientOverlayProps}
|
|
@@ -189,8 +219,11 @@ const TimerPicker = forwardRef<TimerPickerRef, TimerPickerProps>(
|
|
|
189
219
|
<DurationScroll
|
|
190
220
|
ref={secondsDurationScrollRef}
|
|
191
221
|
numberOfItems={59}
|
|
192
|
-
label={secondLabel}
|
|
222
|
+
label={secondLabel ?? "s"}
|
|
193
223
|
initialValue={initialSeconds}
|
|
224
|
+
aggressivelyGetLatestDuration={
|
|
225
|
+
aggressivelyGetLatestDuration
|
|
226
|
+
}
|
|
194
227
|
onDurationChange={setSelectedSeconds}
|
|
195
228
|
padNumbersWithZero
|
|
196
229
|
pickerGradientOverlayProps={pickerGradientOverlayProps}
|