react-native-timer-picker 2.1.0 → 2.2.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 +227 -152
- package/dist/commonjs/components/DurationScroll/DurationScroll.js +417 -0
- package/dist/commonjs/components/DurationScroll/DurationScroll.js.map +1 -0
- package/dist/commonjs/components/DurationScroll/index.js +20 -392
- package/dist/commonjs/components/DurationScroll/index.js.map +1 -1
- package/dist/commonjs/components/DurationScroll/types.js.map +1 -1
- package/dist/commonjs/components/Modal/Modal.js +107 -0
- package/dist/commonjs/components/Modal/Modal.js.map +1 -0
- package/dist/commonjs/components/Modal/index.js +20 -101
- package/dist/commonjs/components/Modal/index.js.map +1 -1
- package/dist/commonjs/components/TimerPicker/TimerPicker.js +225 -0
- package/dist/commonjs/components/TimerPicker/TimerPicker.js.map +1 -0
- package/dist/commonjs/components/TimerPicker/index.js +29 -166
- package/dist/commonjs/components/TimerPicker/index.js.map +1 -1
- package/dist/commonjs/components/TimerPicker/styles.js +1 -1
- package/dist/commonjs/components/TimerPicker/styles.js.map +1 -1
- package/dist/commonjs/components/TimerPicker/types.js.map +1 -1
- package/dist/commonjs/components/TimerPickerModal/TimerPickerModal.js +143 -0
- package/dist/commonjs/components/TimerPickerModal/TimerPickerModal.js.map +1 -0
- package/dist/commonjs/components/TimerPickerModal/index.js +30 -131
- package/dist/commonjs/components/TimerPickerModal/index.js.map +1 -1
- package/dist/commonjs/components/TimerPickerModal/types.js.map +1 -1
- package/dist/commonjs/index.js +9 -13
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/tests/TimerPicker.test.js +4 -1
- package/dist/commonjs/tests/TimerPicker.test.js.map +1 -1
- package/dist/commonjs/utils/colorToRgba.js +35 -4
- package/dist/commonjs/utils/colorToRgba.js.map +1 -1
- package/dist/commonjs/utils/generateNumbers.js +67 -0
- package/dist/commonjs/utils/generateNumbers.js.map +1 -1
- package/dist/commonjs/utils/getAdjustedLimit.js +25 -0
- package/dist/commonjs/utils/getAdjustedLimit.js.map +1 -1
- package/dist/commonjs/utils/getDurationAndIndexFromScrollOffset.js +38 -0
- package/dist/commonjs/utils/getDurationAndIndexFromScrollOffset.js.map +1 -1
- package/dist/commonjs/utils/getInitialScrollIndex.js +38 -0
- package/dist/commonjs/utils/getInitialScrollIndex.js.map +1 -1
- package/dist/commonjs/utils/getSafeInitialValue.js +28 -0
- package/dist/commonjs/utils/getSafeInitialValue.js.map +1 -1
- package/dist/commonjs/utils/padNumber.js +25 -0
- package/dist/commonjs/utils/padNumber.js.map +1 -1
- package/dist/module/components/DurationScroll/DurationScroll.js +410 -0
- package/dist/module/components/DurationScroll/DurationScroll.js.map +1 -0
- package/dist/module/components/DurationScroll/index.js +2 -390
- package/dist/module/components/DurationScroll/index.js.map +1 -1
- package/dist/module/components/DurationScroll/types.js.map +1 -1
- package/dist/module/components/Modal/Modal.js +99 -0
- package/dist/module/components/Modal/Modal.js.map +1 -0
- package/dist/module/components/Modal/index.js +2 -98
- package/dist/module/components/Modal/index.js.map +1 -1
- package/dist/module/components/TimerPicker/TimerPicker.js +217 -0
- package/dist/module/components/TimerPicker/TimerPicker.js.map +1 -0
- package/dist/module/components/TimerPicker/index.js +3 -166
- package/dist/module/components/TimerPicker/index.js.map +1 -1
- package/dist/module/components/TimerPicker/styles.js +1 -1
- package/dist/module/components/TimerPicker/styles.js.map +1 -1
- package/dist/module/components/TimerPicker/types.js.map +1 -1
- package/dist/module/components/TimerPickerModal/TimerPickerModal.js +135 -0
- package/dist/module/components/TimerPickerModal/TimerPickerModal.js.map +1 -0
- package/dist/module/components/TimerPickerModal/index.js +3 -130
- package/dist/module/components/TimerPickerModal/index.js.map +1 -1
- package/dist/module/components/TimerPickerModal/types.js.map +1 -1
- package/dist/module/index.js +2 -6
- package/dist/module/index.js.map +1 -1
- package/dist/module/tests/TimerPicker.test.js +4 -1
- package/dist/module/tests/TimerPicker.test.js.map +1 -1
- package/dist/module/utils/colorToRgba.js +35 -4
- package/dist/module/utils/colorToRgba.js.map +1 -1
- package/dist/module/utils/generateNumbers.js +68 -0
- package/dist/module/utils/generateNumbers.js.map +1 -1
- package/dist/module/utils/getAdjustedLimit.js +25 -0
- package/dist/module/utils/getAdjustedLimit.js.map +1 -1
- package/dist/module/utils/getDurationAndIndexFromScrollOffset.js +38 -0
- package/dist/module/utils/getDurationAndIndexFromScrollOffset.js.map +1 -1
- package/dist/module/utils/getInitialScrollIndex.js +38 -0
- package/dist/module/utils/getInitialScrollIndex.js.map +1 -1
- package/dist/module/utils/getSafeInitialValue.js +28 -0
- package/dist/module/utils/getSafeInitialValue.js.map +1 -1
- package/dist/module/utils/padNumber.js +25 -0
- package/dist/module/utils/padNumber.js.map +1 -1
- package/dist/typescript/components/DurationScroll/DurationScroll.d.ts +4 -0
- package/dist/typescript/components/DurationScroll/index.d.ts +2 -4
- package/dist/typescript/components/DurationScroll/types.d.ts +13 -9
- package/dist/typescript/components/Modal/Modal.d.ts +5 -0
- package/dist/typescript/components/Modal/index.d.ts +2 -5
- package/dist/typescript/components/TimerPicker/TimerPicker.d.ts +4 -0
- package/dist/typescript/components/TimerPicker/index.d.ts +3 -4
- package/dist/typescript/components/TimerPicker/styles.d.ts +1169 -771
- package/dist/typescript/components/TimerPicker/types.d.ts +26 -10
- package/dist/typescript/components/TimerPickerModal/TimerPickerModal.d.ts +4 -0
- package/dist/typescript/components/TimerPickerModal/index.d.ts +3 -4
- package/dist/typescript/components/TimerPickerModal/styles.d.ts +722 -474
- package/dist/typescript/components/TimerPickerModal/types.d.ts +8 -5
- package/dist/typescript/index.d.ts +2 -6
- package/dist/typescript/utils/colorToRgba.d.ts +34 -0
- package/dist/typescript/utils/generateNumbers.d.ts +66 -0
- package/dist/typescript/utils/getAdjustedLimit.d.ts +27 -2
- package/dist/typescript/utils/getDurationAndIndexFromScrollOffset.d.ts +38 -0
- package/dist/typescript/utils/getInitialScrollIndex.d.ts +38 -0
- package/dist/typescript/utils/getSafeInitialValue.d.ts +29 -0
- package/dist/typescript/utils/padNumber.d.ts +25 -0
- package/package.json +10 -27
|
@@ -4,6 +4,44 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.getDurationAndIndexFromScrollOffset = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Calculates the duration value and index from a scroll offset in a number picker.
|
|
9
|
+
* Handles both infinite and non-infinite scroll modes, taking into account padding and item height.
|
|
10
|
+
*
|
|
11
|
+
* @param {Object} variables - Configuration object for scroll offset calculation
|
|
12
|
+
* @param {boolean} variables.disableInfiniteScroll - Whether infinite scroll is disabled
|
|
13
|
+
* @param {number} variables.interval - The interval between consecutive numbers
|
|
14
|
+
* @param {number} variables.itemHeight - Height of each item in the picker
|
|
15
|
+
* @param {number} variables.numberOfItems - Total number of items in the picker
|
|
16
|
+
* @param {number} variables.padWithNItems - Number of empty items to pad with
|
|
17
|
+
* @param {number} variables.yContentOffset - The vertical scroll offset
|
|
18
|
+
*
|
|
19
|
+
* @returns {{ duration: number; index: number }} Object containing the calculated duration and index
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // With infinite scroll enabled
|
|
23
|
+
* getDurationAndIndexFromScrollOffset({
|
|
24
|
+
* disableInfiniteScroll: false,
|
|
25
|
+
* interval: 1,
|
|
26
|
+
* itemHeight: 50,
|
|
27
|
+
* numberOfItems: 24,
|
|
28
|
+
* padWithNItems: 2,
|
|
29
|
+
* yContentOffset: 100
|
|
30
|
+
* })
|
|
31
|
+
* // Returns: { duration: 2, index: 2 }
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* // With infinite scroll disabled
|
|
35
|
+
* getDurationAndIndexFromScrollOffset({
|
|
36
|
+
* disableInfiniteScroll: true,
|
|
37
|
+
* interval: 1,
|
|
38
|
+
* itemHeight: 50,
|
|
39
|
+
* numberOfItems: 24,
|
|
40
|
+
* padWithNItems: 2,
|
|
41
|
+
* yContentOffset: 100
|
|
42
|
+
* })
|
|
43
|
+
* // Returns: { duration: 2, index: 2 }
|
|
44
|
+
*/
|
|
7
45
|
const getDurationAndIndexFromScrollOffset = variables => {
|
|
8
46
|
const {
|
|
9
47
|
disableInfiniteScroll,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["getDurationAndIndexFromScrollOffset","variables","disableInfiniteScroll","interval","itemHeight","numberOfItems","padWithNItems","yContentOffset","index","Math","round","duration","exports"],"sources":["getDurationAndIndexFromScrollOffset.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"names":["getDurationAndIndexFromScrollOffset","variables","disableInfiniteScroll","interval","itemHeight","numberOfItems","padWithNItems","yContentOffset","index","Math","round","duration","exports"],"sources":["getDurationAndIndexFromScrollOffset.ts"],"sourcesContent":["/**\n * Calculates the duration value and index from a scroll offset in a number picker.\n * Handles both infinite and non-infinite scroll modes, taking into account padding and item height.\n *\n * @param {Object} variables - Configuration object for scroll offset calculation\n * @param {boolean} variables.disableInfiniteScroll - Whether infinite scroll is disabled\n * @param {number} variables.interval - The interval between consecutive numbers\n * @param {number} variables.itemHeight - Height of each item in the picker\n * @param {number} variables.numberOfItems - Total number of items in the picker\n * @param {number} variables.padWithNItems - Number of empty items to pad with\n * @param {number} variables.yContentOffset - The vertical scroll offset\n *\n * @returns {{ duration: number; index: number }} Object containing the calculated duration and index\n *\n * @example\n * // With infinite scroll enabled\n * getDurationAndIndexFromScrollOffset({\n * disableInfiniteScroll: false,\n * interval: 1,\n * itemHeight: 50,\n * numberOfItems: 24,\n * padWithNItems: 2,\n * yContentOffset: 100\n * })\n * // Returns: { duration: 2, index: 2 }\n *\n * @example\n * // With infinite scroll disabled\n * getDurationAndIndexFromScrollOffset({\n * disableInfiniteScroll: true,\n * interval: 1,\n * itemHeight: 50,\n * numberOfItems: 24,\n * padWithNItems: 2,\n * yContentOffset: 100\n * })\n * // Returns: { duration: 2, index: 2 }\n */\nexport const getDurationAndIndexFromScrollOffset = (variables: {\n disableInfiniteScroll: boolean;\n interval: number;\n itemHeight: number;\n numberOfItems: number;\n padWithNItems: number;\n yContentOffset: number;\n}) => {\n const {\n disableInfiniteScroll,\n interval,\n itemHeight,\n numberOfItems,\n padWithNItems,\n yContentOffset,\n } = variables;\n\n const index = Math.round(yContentOffset / itemHeight);\n\n const duration =\n ((disableInfiniteScroll ? index : index + padWithNItems) %\n numberOfItems) *\n interval;\n\n return {\n duration,\n index,\n };\n};\n"],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMA,mCAAmC,GAAIC,SAOnD,IAAK;EACF,MAAM;IACFC,qBAAqB;IACrBC,QAAQ;IACRC,UAAU;IACVC,aAAa;IACbC,aAAa;IACbC;EACJ,CAAC,GAAGN,SAAS;EAEb,MAAMO,KAAK,GAAGC,IAAI,CAACC,KAAK,CAACH,cAAc,GAAGH,UAAU,CAAC;EAErD,MAAMO,QAAQ,GACT,CAACT,qBAAqB,GAAGM,KAAK,GAAGA,KAAK,GAAGF,aAAa,IACnDD,aAAa,GACjBF,QAAQ;EAEZ,OAAO;IACHQ,QAAQ;IACRH;EACJ,CAAC;AACL,CAAC;AAACI,OAAA,CAAAZ,mCAAA,GAAAA,mCAAA","ignoreList":[]}
|
|
@@ -4,6 +4,44 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.getInitialScrollIndex = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Calculates the initial scroll index for a number picker based on the desired value and configuration.
|
|
9
|
+
* Handles both infinite and non-infinite scroll modes, taking into account padding and repetition.
|
|
10
|
+
*
|
|
11
|
+
* @param {Object} variables - Configuration object for scroll index calculation
|
|
12
|
+
* @param {boolean} variables.disableInfiniteScroll - Whether infinite scroll is disabled
|
|
13
|
+
* @param {number} variables.interval - The interval between consecutive numbers
|
|
14
|
+
* @param {number} variables.numberOfItems - Total number of items in the picker
|
|
15
|
+
* @param {number} variables.padWithNItems - Number of empty items to pad with
|
|
16
|
+
* @param {number} variables.repeatNumbersNTimes - How many times to repeat the number sequence
|
|
17
|
+
* @param {number} variables.value - The desired initial value
|
|
18
|
+
*
|
|
19
|
+
* @returns {number} The calculated initial scroll index
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // With infinite scroll enabled
|
|
23
|
+
* getInitialScrollIndex({
|
|
24
|
+
* disableInfiniteScroll: false,
|
|
25
|
+
* interval: 1,
|
|
26
|
+
* numberOfItems: 24,
|
|
27
|
+
* padWithNItems: 2,
|
|
28
|
+
* repeatNumbersNTimes: 3,
|
|
29
|
+
* value: 12
|
|
30
|
+
* })
|
|
31
|
+
* // Returns: 38
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* // With infinite scroll disabled
|
|
35
|
+
* getInitialScrollIndex({
|
|
36
|
+
* disableInfiniteScroll: true,
|
|
37
|
+
* interval: 1,
|
|
38
|
+
* numberOfItems: 24,
|
|
39
|
+
* padWithNItems: 2,
|
|
40
|
+
* repeatNumbersNTimes: 1,
|
|
41
|
+
* value: 12
|
|
42
|
+
* })
|
|
43
|
+
* // Returns: 12
|
|
44
|
+
*/
|
|
7
45
|
const getInitialScrollIndex = variables => {
|
|
8
46
|
const {
|
|
9
47
|
disableInfiniteScroll,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["getInitialScrollIndex","variables","disableInfiniteScroll","interval","numberOfItems","padWithNItems","repeatNumbersNTimes","value","Math","max","floor","exports"],"sources":["getInitialScrollIndex.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"names":["getInitialScrollIndex","variables","disableInfiniteScroll","interval","numberOfItems","padWithNItems","repeatNumbersNTimes","value","Math","max","floor","exports"],"sources":["getInitialScrollIndex.ts"],"sourcesContent":["/**\n * Calculates the initial scroll index for a number picker based on the desired value and configuration.\n * Handles both infinite and non-infinite scroll modes, taking into account padding and repetition.\n * \n * @param {Object} variables - Configuration object for scroll index calculation\n * @param {boolean} variables.disableInfiniteScroll - Whether infinite scroll is disabled\n * @param {number} variables.interval - The interval between consecutive numbers\n * @param {number} variables.numberOfItems - Total number of items in the picker\n * @param {number} variables.padWithNItems - Number of empty items to pad with\n * @param {number} variables.repeatNumbersNTimes - How many times to repeat the number sequence\n * @param {number} variables.value - The desired initial value\n * \n * @returns {number} The calculated initial scroll index\n * \n * @example\n * // With infinite scroll enabled\n * getInitialScrollIndex({\n * disableInfiniteScroll: false,\n * interval: 1,\n * numberOfItems: 24,\n * padWithNItems: 2,\n * repeatNumbersNTimes: 3,\n * value: 12\n * })\n * // Returns: 38\n * \n * @example\n * // With infinite scroll disabled\n * getInitialScrollIndex({\n * disableInfiniteScroll: true,\n * interval: 1,\n * numberOfItems: 24,\n * padWithNItems: 2,\n * repeatNumbersNTimes: 1,\n * value: 12\n * })\n * // Returns: 12\n */\nexport const getInitialScrollIndex = (variables: {\n disableInfiniteScroll: boolean;\n interval: number;\n numberOfItems: number;\n padWithNItems: number;\n repeatNumbersNTimes: number;\n value: number;\n}) => {\n const {\n disableInfiniteScroll,\n interval,\n numberOfItems,\n padWithNItems,\n repeatNumbersNTimes,\n value,\n } = variables;\n\n return Math.max(\n numberOfItems * Math.floor(repeatNumbersNTimes / 2) +\n ((value / interval + numberOfItems) % numberOfItems) -\n (!disableInfiniteScroll ? padWithNItems : 0),\n 0\n );\n};\n"],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMA,qBAAqB,GAAIC,SAOrC,IAAK;EACF,MAAM;IACFC,qBAAqB;IACrBC,QAAQ;IACRC,aAAa;IACbC,aAAa;IACbC,mBAAmB;IACnBC;EACJ,CAAC,GAAGN,SAAS;EAEb,OAAOO,IAAI,CAACC,GAAG,CACXL,aAAa,GAAGI,IAAI,CAACE,KAAK,CAACJ,mBAAmB,GAAG,CAAC,CAAC,GAC9C,CAACC,KAAK,GAAGJ,QAAQ,GAAGC,aAAa,IAAIA,aAAc,IACnD,CAACF,qBAAqB,GAAGG,aAAa,GAAG,CAAC,CAAC,EAChD,CACJ,CAAC;AACL,CAAC;AAACM,OAAA,CAAAX,qBAAA,GAAAA,qBAAA","ignoreList":[]}
|
|
@@ -4,7 +4,35 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.getSafeInitialValue = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Safely extracts and validates initial duration values, ensuring all values are valid numbers.
|
|
9
|
+
* Returns a duration object with safe default values (0) for any invalid or missing inputs.
|
|
10
|
+
*
|
|
11
|
+
* @param {Object} [initialValue] - Optional initial duration values
|
|
12
|
+
* @param {number} [initialValue.days] - Initial days value
|
|
13
|
+
* @param {number} [initialValue.hours] - Initial hours value
|
|
14
|
+
* @param {number} [initialValue.minutes] - Initial minutes value
|
|
15
|
+
* @param {number} [initialValue.seconds] - Initial seconds value
|
|
16
|
+
*
|
|
17
|
+
* @returns {{ days: number; hours: number; minutes: number; seconds: number }} An object containing safe duration values
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // With valid values
|
|
21
|
+
* getSafeInitialValue({ days: 1, hours: 2, minutes: 30, seconds: 45 })
|
|
22
|
+
* // Returns: { days: 1, hours: 2, minutes: 30, seconds: 45 }
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* // With invalid values
|
|
26
|
+
* getSafeInitialValue({ days: NaN, hours: 'invalid', minutes: undefined })
|
|
27
|
+
* // Returns: { days: 0, hours: 0, minutes: 0, seconds: 0 }
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* // With undefined input
|
|
31
|
+
* getSafeInitialValue(undefined)
|
|
32
|
+
* // Returns: { days: 0, hours: 0, minutes: 0, seconds: 0 }
|
|
33
|
+
*/
|
|
7
34
|
const getSafeInitialValue = initialValue => ({
|
|
35
|
+
days: typeof (initialValue === null || initialValue === void 0 ? void 0 : initialValue.days) === "number" && !isNaN(initialValue === null || initialValue === void 0 ? void 0 : initialValue.days) ? initialValue.days : 0,
|
|
8
36
|
hours: typeof (initialValue === null || initialValue === void 0 ? void 0 : initialValue.hours) === "number" && !isNaN(initialValue === null || initialValue === void 0 ? void 0 : initialValue.hours) ? initialValue.hours : 0,
|
|
9
37
|
minutes: typeof (initialValue === null || initialValue === void 0 ? void 0 : initialValue.minutes) === "number" && !isNaN(initialValue === null || initialValue === void 0 ? void 0 : initialValue.minutes) ? initialValue.minutes : 0,
|
|
10
38
|
seconds: typeof (initialValue === null || initialValue === void 0 ? void 0 : initialValue.seconds) === "number" && !isNaN(initialValue === null || initialValue === void 0 ? void 0 : initialValue.seconds) ? initialValue.seconds : 0
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["getSafeInitialValue","initialValue","
|
|
1
|
+
{"version":3,"names":["getSafeInitialValue","initialValue","days","isNaN","hours","minutes","seconds","exports"],"sources":["getSafeInitialValue.ts"],"sourcesContent":["/**\n * Safely extracts and validates initial duration values, ensuring all values are valid numbers.\n * Returns a duration object with safe default values (0) for any invalid or missing inputs.\n * \n * @param {Object} [initialValue] - Optional initial duration values\n * @param {number} [initialValue.days] - Initial days value\n * @param {number} [initialValue.hours] - Initial hours value\n * @param {number} [initialValue.minutes] - Initial minutes value\n * @param {number} [initialValue.seconds] - Initial seconds value\n * \n * @returns {{ days: number; hours: number; minutes: number; seconds: number }} An object containing safe duration values\n * \n * @example\n * // With valid values\n * getSafeInitialValue({ days: 1, hours: 2, minutes: 30, seconds: 45 })\n * // Returns: { days: 1, hours: 2, minutes: 30, seconds: 45 }\n * \n * @example\n * // With invalid values\n * getSafeInitialValue({ days: NaN, hours: 'invalid', minutes: undefined })\n * // Returns: { days: 0, hours: 0, minutes: 0, seconds: 0 }\n * \n * @example\n * // With undefined input\n * getSafeInitialValue(undefined)\n * // Returns: { days: 0, hours: 0, minutes: 0, seconds: 0 }\n */\nexport const getSafeInitialValue = (\n initialValue:\n | {\n days?: number;\n hours?: number;\n minutes?: number;\n seconds?: number;\n }\n | undefined\n) => ({\n days:\n typeof initialValue?.days === \"number\" && !isNaN(initialValue?.days)\n ? initialValue.days\n : 0,\n hours:\n typeof initialValue?.hours === \"number\" && !isNaN(initialValue?.hours)\n ? initialValue.hours\n : 0,\n minutes:\n typeof initialValue?.minutes === \"number\" &&\n !isNaN(initialValue?.minutes)\n ? initialValue.minutes\n : 0,\n seconds:\n typeof initialValue?.seconds === \"number\" &&\n !isNaN(initialValue?.seconds)\n ? initialValue.seconds\n : 0,\n});\n"],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMA,mBAAmB,GAC5BC,YAOe,KACb;EACFC,IAAI,EACA,QAAOD,YAAY,aAAZA,YAAY,uBAAZA,YAAY,CAAEC,IAAI,MAAK,QAAQ,IAAI,CAACC,KAAK,CAACF,YAAY,aAAZA,YAAY,uBAAZA,YAAY,CAAEC,IAAI,CAAC,GAC9DD,YAAY,CAACC,IAAI,GACjB,CAAC;EACXE,KAAK,EACD,QAAOH,YAAY,aAAZA,YAAY,uBAAZA,YAAY,CAAEG,KAAK,MAAK,QAAQ,IAAI,CAACD,KAAK,CAACF,YAAY,aAAZA,YAAY,uBAAZA,YAAY,CAAEG,KAAK,CAAC,GAChEH,YAAY,CAACG,KAAK,GAClB,CAAC;EACXC,OAAO,EACH,QAAOJ,YAAY,aAAZA,YAAY,uBAAZA,YAAY,CAAEI,OAAO,MAAK,QAAQ,IACzC,CAACF,KAAK,CAACF,YAAY,aAAZA,YAAY,uBAAZA,YAAY,CAAEI,OAAO,CAAC,GACvBJ,YAAY,CAACI,OAAO,GACpB,CAAC;EACXC,OAAO,EACH,QAAOL,YAAY,aAAZA,YAAY,uBAAZA,YAAY,CAAEK,OAAO,MAAK,QAAQ,IACzC,CAACH,KAAK,CAACF,YAAY,aAAZA,YAAY,uBAAZA,YAAY,CAAEK,OAAO,CAAC,GACvBL,YAAY,CAACK,OAAO,GACpB;AACd,CAAC,CAAC;AAACC,OAAA,CAAAP,mBAAA,GAAAA,mBAAA","ignoreList":[]}
|
|
@@ -4,6 +4,31 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.padNumber = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Formats a number by optionally padding it with a leading zero or space.
|
|
9
|
+
* Numbers less than 10 are padded based on the options provided.
|
|
10
|
+
*
|
|
11
|
+
* @param {number} value - The number to format
|
|
12
|
+
* @param {Object} [options] - Optional formatting options
|
|
13
|
+
* @param {boolean} [options.padWithZero] - Whether to pad with zero (true) or space (false)
|
|
14
|
+
*
|
|
15
|
+
* @returns {string} The formatted number string
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* // Pad with zero
|
|
19
|
+
* padNumber(5, { padWithZero: true })
|
|
20
|
+
* // Returns: '05'
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* // Pad with space
|
|
24
|
+
* padNumber(5, { padWithZero: false })
|
|
25
|
+
* // Returns: ' 5'
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* // No padding needed
|
|
29
|
+
* padNumber(15)
|
|
30
|
+
* // Returns: '15'
|
|
31
|
+
*/
|
|
7
32
|
const padNumber = (value, options) => {
|
|
8
33
|
if (value < 10) {
|
|
9
34
|
return (options !== null && options !== void 0 && options.padWithZero ? "0" : " ") + value;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["padNumber","value","options","padWithZero","String","exports"],"sources":["padNumber.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"names":["padNumber","value","options","padWithZero","String","exports"],"sources":["padNumber.ts"],"sourcesContent":["/**\n * Formats a number by optionally padding it with a leading zero or space.\n * Numbers less than 10 are padded based on the options provided.\n * \n * @param {number} value - The number to format\n * @param {Object} [options] - Optional formatting options\n * @param {boolean} [options.padWithZero] - Whether to pad with zero (true) or space (false)\n * \n * @returns {string} The formatted number string\n * \n * @example\n * // Pad with zero\n * padNumber(5, { padWithZero: true })\n * // Returns: '05'\n * \n * @example\n * // Pad with space\n * padNumber(5, { padWithZero: false })\n * // Returns: ' 5'\n * \n * @example\n * // No padding needed\n * padNumber(15)\n * // Returns: '15'\n */\nexport 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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,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;AAACI,OAAA,CAAAL,SAAA,GAAAA,SAAA","ignoreList":[]}
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
2
|
+
import React, { useRef, useCallback, forwardRef, useImperativeHandle, useState, useEffect, useMemo } from "react";
|
|
3
|
+
import { View, Text, FlatList as RNFlatList } from "react-native";
|
|
4
|
+
import { colorToRgba } from "../../utils/colorToRgba";
|
|
5
|
+
import { generate12HourNumbers, generateNumbers } from "../../utils/generateNumbers";
|
|
6
|
+
import { getAdjustedLimit } from "../../utils/getAdjustedLimit";
|
|
7
|
+
import { getDurationAndIndexFromScrollOffset } from "../../utils/getDurationAndIndexFromScrollOffset";
|
|
8
|
+
import { getInitialScrollIndex } from "../../utils/getInitialScrollIndex";
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
+
const keyExtractor = (item, index) => index.toString();
|
|
11
|
+
const DurationScroll = /*#__PURE__*/forwardRef((props, ref) => {
|
|
12
|
+
const {
|
|
13
|
+
aggressivelyGetLatestDuration,
|
|
14
|
+
allowFontScaling = false,
|
|
15
|
+
amLabel,
|
|
16
|
+
Audio,
|
|
17
|
+
clickSoundAsset,
|
|
18
|
+
decelerationRate = 0.88,
|
|
19
|
+
disableInfiniteScroll = false,
|
|
20
|
+
FlatList = RNFlatList,
|
|
21
|
+
Haptics,
|
|
22
|
+
initialValue = 0,
|
|
23
|
+
interval,
|
|
24
|
+
is12HourPicker,
|
|
25
|
+
isDisabled,
|
|
26
|
+
label,
|
|
27
|
+
limit,
|
|
28
|
+
LinearGradient,
|
|
29
|
+
MaskedView,
|
|
30
|
+
maximumValue,
|
|
31
|
+
onDurationChange,
|
|
32
|
+
padNumbersWithZero = false,
|
|
33
|
+
padWithNItems,
|
|
34
|
+
pickerFeedback,
|
|
35
|
+
pickerGradientOverlayProps,
|
|
36
|
+
pmLabel,
|
|
37
|
+
repeatNumbersNTimes = 3,
|
|
38
|
+
repeatNumbersNTimesNotExplicitlySet,
|
|
39
|
+
styles,
|
|
40
|
+
testID
|
|
41
|
+
} = props;
|
|
42
|
+
const numberOfItems = useMemo(() => {
|
|
43
|
+
// guard against negative maximum values
|
|
44
|
+
if (maximumValue < 0) {
|
|
45
|
+
return 1;
|
|
46
|
+
}
|
|
47
|
+
return Math.floor(maximumValue / interval) + 1;
|
|
48
|
+
}, [interval, maximumValue]);
|
|
49
|
+
const safeRepeatNumbersNTimes = useMemo(() => {
|
|
50
|
+
// do not repeat numbers if there is only one option
|
|
51
|
+
if (numberOfItems === 1) {
|
|
52
|
+
return 1;
|
|
53
|
+
}
|
|
54
|
+
if (!disableInfiniteScroll && repeatNumbersNTimes < 2) {
|
|
55
|
+
return 2;
|
|
56
|
+
} else if (repeatNumbersNTimes < 1 || isNaN(repeatNumbersNTimes)) {
|
|
57
|
+
return 1;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// if this variable is not explicitly set, we calculate a reasonable value based on
|
|
61
|
+
// the number of items in the picker, avoiding regular jumps up/down the list
|
|
62
|
+
// whilst avoiding rendering too many items in the picker
|
|
63
|
+
if (repeatNumbersNTimesNotExplicitlySet) {
|
|
64
|
+
return Math.max(Math.round(180 / numberOfItems), 1);
|
|
65
|
+
}
|
|
66
|
+
return Math.round(repeatNumbersNTimes);
|
|
67
|
+
}, [disableInfiniteScroll, numberOfItems, repeatNumbersNTimes, repeatNumbersNTimesNotExplicitlySet]);
|
|
68
|
+
const numbersForFlatList = useMemo(() => {
|
|
69
|
+
if (is12HourPicker) {
|
|
70
|
+
return generate12HourNumbers({
|
|
71
|
+
padNumbersWithZero,
|
|
72
|
+
repeatNTimes: safeRepeatNumbersNTimes,
|
|
73
|
+
disableInfiniteScroll,
|
|
74
|
+
padWithNItems,
|
|
75
|
+
interval
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return generateNumbers(numberOfItems, {
|
|
79
|
+
padNumbersWithZero,
|
|
80
|
+
repeatNTimes: safeRepeatNumbersNTimes,
|
|
81
|
+
disableInfiniteScroll,
|
|
82
|
+
padWithNItems,
|
|
83
|
+
interval
|
|
84
|
+
});
|
|
85
|
+
}, [disableInfiniteScroll, is12HourPicker, interval, numberOfItems, padNumbersWithZero, padWithNItems, safeRepeatNumbersNTimes]);
|
|
86
|
+
const initialScrollIndex = useMemo(() => getInitialScrollIndex({
|
|
87
|
+
disableInfiniteScroll,
|
|
88
|
+
interval,
|
|
89
|
+
numberOfItems,
|
|
90
|
+
padWithNItems,
|
|
91
|
+
repeatNumbersNTimes: safeRepeatNumbersNTimes,
|
|
92
|
+
value: initialValue
|
|
93
|
+
}), [disableInfiniteScroll, initialValue, interval, numberOfItems, padWithNItems, safeRepeatNumbersNTimes]);
|
|
94
|
+
const adjustedLimited = useMemo(() => getAdjustedLimit(limit, numberOfItems, interval), [interval, limit, numberOfItems]);
|
|
95
|
+
const numberOfItemsToShow = 1 + padWithNItems * 2;
|
|
96
|
+
|
|
97
|
+
// keep track of the latest duration as it scrolls
|
|
98
|
+
const latestDuration = useRef(0);
|
|
99
|
+
// keep track of the last index scrolled past for haptic/audio feedback
|
|
100
|
+
const lastFeedbackIndex = useRef(0);
|
|
101
|
+
const flatListRef = useRef(null);
|
|
102
|
+
const [clickSound, setClickSound] = useState(null);
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
// Audio prop deprecated in v2.2.0 (use pickerFeedback instead) - will be removed in a future version
|
|
105
|
+
|
|
106
|
+
// preload the sound when the component mounts
|
|
107
|
+
let soundInstance = null;
|
|
108
|
+
const loadSound = async () => {
|
|
109
|
+
if (!Audio) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
const {
|
|
114
|
+
sound: newSound
|
|
115
|
+
} = await Audio.Sound.createAsync(clickSoundAsset ?? {
|
|
116
|
+
// use a hosted sound as a fallback (do not use local asset due to loader issues
|
|
117
|
+
// in some environments when including mp3 in library)
|
|
118
|
+
uri: "https://drive.google.com/uc?export=download&id=10e1YkbNsRh-vGx1jmS1Nntz8xzkBp4_I"
|
|
119
|
+
}, {
|
|
120
|
+
shouldPlay: false
|
|
121
|
+
});
|
|
122
|
+
soundInstance = newSound;
|
|
123
|
+
setClickSound(newSound);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
console.warn("Failed to load click sound:", error);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
loadSound();
|
|
129
|
+
return () => {
|
|
130
|
+
var _soundInstance;
|
|
131
|
+
// unload sound when component unmounts
|
|
132
|
+
(_soundInstance = soundInstance) === null || _soundInstance === void 0 || _soundInstance.unloadAsync();
|
|
133
|
+
};
|
|
134
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
135
|
+
}, [Audio]);
|
|
136
|
+
const playClickSound = useCallback(async () => {
|
|
137
|
+
if (!clickSound) return;
|
|
138
|
+
try {
|
|
139
|
+
await clickSound.replayAsync();
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.warn("Failed to play click sound:", error);
|
|
142
|
+
}
|
|
143
|
+
}, [clickSound]);
|
|
144
|
+
const renderItem = useCallback(({
|
|
145
|
+
item
|
|
146
|
+
}) => {
|
|
147
|
+
let stringItem = item;
|
|
148
|
+
let intItem;
|
|
149
|
+
let isAm;
|
|
150
|
+
if (!is12HourPicker) {
|
|
151
|
+
intItem = parseInt(item);
|
|
152
|
+
} else {
|
|
153
|
+
isAm = item.includes("AM");
|
|
154
|
+
stringItem = item.replace(/\s[AP]M/g, "");
|
|
155
|
+
intItem = parseInt(stringItem);
|
|
156
|
+
}
|
|
157
|
+
return /*#__PURE__*/React.createElement(View, {
|
|
158
|
+
key: item,
|
|
159
|
+
style: styles.pickerItemContainer,
|
|
160
|
+
testID: "picker-item"
|
|
161
|
+
}, /*#__PURE__*/React.createElement(Text, {
|
|
162
|
+
allowFontScaling: allowFontScaling,
|
|
163
|
+
style: [styles.pickerItem, intItem > adjustedLimited.max || intItem < adjustedLimited.min ? styles.disabledPickerItem : {}]
|
|
164
|
+
}, stringItem), is12HourPicker ? /*#__PURE__*/React.createElement(View, {
|
|
165
|
+
pointerEvents: "none",
|
|
166
|
+
style: styles.pickerAmPmContainer
|
|
167
|
+
}, /*#__PURE__*/React.createElement(Text, {
|
|
168
|
+
allowFontScaling: allowFontScaling,
|
|
169
|
+
style: [styles.pickerAmPmLabel]
|
|
170
|
+
}, isAm ? amLabel : pmLabel)) : null);
|
|
171
|
+
}, [adjustedLimited.max, adjustedLimited.min, allowFontScaling, amLabel, is12HourPicker, pmLabel, styles.disabledPickerItem, styles.pickerAmPmContainer, styles.pickerAmPmLabel, styles.pickerItem, styles.pickerItemContainer]);
|
|
172
|
+
const onScroll = useCallback(e => {
|
|
173
|
+
// this function is only used when the picker is in a modal and/or has Haptic/Audio feedback
|
|
174
|
+
// it is used to ensure that the modal gets the latest duration on clicking
|
|
175
|
+
// the confirm button, even if the scrollview is still scrolling
|
|
176
|
+
if (!aggressivelyGetLatestDuration && !Haptics && !Audio && !pickerFeedback) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if (aggressivelyGetLatestDuration) {
|
|
180
|
+
const newValues = getDurationAndIndexFromScrollOffset({
|
|
181
|
+
disableInfiniteScroll,
|
|
182
|
+
interval,
|
|
183
|
+
itemHeight: styles.pickerItemContainer.height,
|
|
184
|
+
numberOfItems,
|
|
185
|
+
padWithNItems,
|
|
186
|
+
yContentOffset: e.nativeEvent.contentOffset.y
|
|
187
|
+
});
|
|
188
|
+
if (newValues.duration !== latestDuration.current) {
|
|
189
|
+
// check limits
|
|
190
|
+
if (newValues.duration > adjustedLimited.max) {
|
|
191
|
+
newValues.duration = adjustedLimited.max;
|
|
192
|
+
} else if (newValues.duration < adjustedLimited.min) {
|
|
193
|
+
newValues.duration = adjustedLimited.min;
|
|
194
|
+
}
|
|
195
|
+
latestDuration.current = newValues.duration;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (pickerFeedback || Haptics || Audio) {
|
|
199
|
+
const feedbackIndex = Math.round((e.nativeEvent.contentOffset.y + styles.pickerItemContainer.height / 2) / styles.pickerItemContainer.height);
|
|
200
|
+
if (feedbackIndex !== lastFeedbackIndex.current) {
|
|
201
|
+
// this check stops the feedback firing when the component mounts
|
|
202
|
+
if (lastFeedbackIndex.current) {
|
|
203
|
+
// fire haptic feedback if available
|
|
204
|
+
try {
|
|
205
|
+
Haptics === null || Haptics === void 0 || Haptics.selectionAsync();
|
|
206
|
+
} catch {
|
|
207
|
+
// do nothing
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// play click sound if available
|
|
211
|
+
try {
|
|
212
|
+
playClickSound();
|
|
213
|
+
} catch {
|
|
214
|
+
// do nothing
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// fire custom feedback if available
|
|
218
|
+
try {
|
|
219
|
+
pickerFeedback === null || pickerFeedback === void 0 || pickerFeedback();
|
|
220
|
+
} catch {
|
|
221
|
+
// do nothing
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
lastFeedbackIndex.current = feedbackIndex;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
229
|
+
[adjustedLimited.max, adjustedLimited.min, aggressivelyGetLatestDuration, playClickSound, disableInfiniteScroll, interval, numberOfItems, padWithNItems, styles.pickerItemContainer.height]);
|
|
230
|
+
const onMomentumScrollEnd = useCallback(e => {
|
|
231
|
+
const newValues = getDurationAndIndexFromScrollOffset({
|
|
232
|
+
disableInfiniteScroll,
|
|
233
|
+
interval,
|
|
234
|
+
itemHeight: styles.pickerItemContainer.height,
|
|
235
|
+
numberOfItems,
|
|
236
|
+
padWithNItems,
|
|
237
|
+
yContentOffset: e.nativeEvent.contentOffset.y
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// check limits
|
|
241
|
+
if (newValues.duration > adjustedLimited.max) {
|
|
242
|
+
var _flatListRef$current;
|
|
243
|
+
const targetScrollIndex = newValues.index - (newValues.duration - adjustedLimited.max);
|
|
244
|
+
(_flatListRef$current = flatListRef.current) === null || _flatListRef$current === void 0 || _flatListRef$current.scrollToIndex({
|
|
245
|
+
animated: true,
|
|
246
|
+
index:
|
|
247
|
+
// guard against scrolling beyond end of list
|
|
248
|
+
targetScrollIndex >= 0 ? targetScrollIndex : adjustedLimited.max - 1
|
|
249
|
+
}); // scroll down to max
|
|
250
|
+
newValues.duration = adjustedLimited.max;
|
|
251
|
+
} else if (newValues.duration < adjustedLimited.min) {
|
|
252
|
+
var _flatListRef$current2;
|
|
253
|
+
const targetScrollIndex = newValues.index + (adjustedLimited.min - newValues.duration);
|
|
254
|
+
(_flatListRef$current2 = flatListRef.current) === null || _flatListRef$current2 === void 0 || _flatListRef$current2.scrollToIndex({
|
|
255
|
+
animated: true,
|
|
256
|
+
index:
|
|
257
|
+
// guard against scrolling beyond end of list
|
|
258
|
+
targetScrollIndex <= numbersForFlatList.length - 1 ? targetScrollIndex : adjustedLimited.min
|
|
259
|
+
}); // scroll up to min
|
|
260
|
+
newValues.duration = adjustedLimited.min;
|
|
261
|
+
}
|
|
262
|
+
onDurationChange(newValues.duration);
|
|
263
|
+
}, [disableInfiniteScroll, interval, styles.pickerItemContainer.height, numberOfItems, padWithNItems, adjustedLimited.max, adjustedLimited.min, onDurationChange, numbersForFlatList.length]);
|
|
264
|
+
const onViewableItemsChanged = useCallback(({
|
|
265
|
+
viewableItems
|
|
266
|
+
}) => {
|
|
267
|
+
var _viewableItems$, _viewableItems$2;
|
|
268
|
+
if (numberOfItems === 1) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
if ((_viewableItems$ = viewableItems[0]) !== null && _viewableItems$ !== void 0 && _viewableItems$.index && viewableItems[0].index < numberOfItems * 0.5) {
|
|
272
|
+
var _flatListRef$current3;
|
|
273
|
+
(_flatListRef$current3 = flatListRef.current) === null || _flatListRef$current3 === void 0 || _flatListRef$current3.scrollToIndex({
|
|
274
|
+
animated: false,
|
|
275
|
+
index: viewableItems[0].index + numberOfItems
|
|
276
|
+
});
|
|
277
|
+
} else if ((_viewableItems$2 = viewableItems[0]) !== null && _viewableItems$2 !== void 0 && _viewableItems$2.index && viewableItems[0].index >= numberOfItems * (safeRepeatNumbersNTimes - 0.5)) {
|
|
278
|
+
var _flatListRef$current4;
|
|
279
|
+
(_flatListRef$current4 = flatListRef.current) === null || _flatListRef$current4 === void 0 || _flatListRef$current4.scrollToIndex({
|
|
280
|
+
animated: false,
|
|
281
|
+
index: viewableItems[0].index - numberOfItems
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
}, [numberOfItems, safeRepeatNumbersNTimes]);
|
|
285
|
+
const [viewabilityConfigCallbackPairs, setViewabilityConfigCallbackPairs] = useState(!disableInfiniteScroll ? [{
|
|
286
|
+
viewabilityConfig: {
|
|
287
|
+
viewAreaCoveragePercentThreshold: 0
|
|
288
|
+
},
|
|
289
|
+
onViewableItemsChanged: onViewableItemsChanged
|
|
290
|
+
}] : undefined);
|
|
291
|
+
const [flatListRenderKey, setFlatListRenderKey] = useState(0);
|
|
292
|
+
const initialRender = useRef(true);
|
|
293
|
+
useEffect(() => {
|
|
294
|
+
// don't run on first render
|
|
295
|
+
if (initialRender.current) {
|
|
296
|
+
initialRender.current = false;
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// if the onViewableItemsChanged callback changes, we need to update viewabilityConfigCallbackPairs
|
|
301
|
+
// which requires the FlatList to be remounted, hence the increase of the FlatList key
|
|
302
|
+
setFlatListRenderKey(prev => prev + 1);
|
|
303
|
+
setViewabilityConfigCallbackPairs(!disableInfiniteScroll ? [{
|
|
304
|
+
viewabilityConfig: {
|
|
305
|
+
viewAreaCoveragePercentThreshold: 0
|
|
306
|
+
},
|
|
307
|
+
onViewableItemsChanged: onViewableItemsChanged
|
|
308
|
+
}] : undefined);
|
|
309
|
+
}, [disableInfiniteScroll, onViewableItemsChanged]);
|
|
310
|
+
const getItemLayout = useCallback((_, index) => ({
|
|
311
|
+
length: styles.pickerItemContainer.height,
|
|
312
|
+
offset: styles.pickerItemContainer.height * index,
|
|
313
|
+
index
|
|
314
|
+
}), [styles.pickerItemContainer.height]);
|
|
315
|
+
useImperativeHandle(ref, () => ({
|
|
316
|
+
reset: options => {
|
|
317
|
+
var _flatListRef$current5;
|
|
318
|
+
(_flatListRef$current5 = flatListRef.current) === null || _flatListRef$current5 === void 0 || _flatListRef$current5.scrollToIndex({
|
|
319
|
+
animated: (options === null || options === void 0 ? void 0 : options.animated) ?? false,
|
|
320
|
+
index: initialScrollIndex
|
|
321
|
+
});
|
|
322
|
+
},
|
|
323
|
+
setValue: (value, options) => {
|
|
324
|
+
var _flatListRef$current6;
|
|
325
|
+
(_flatListRef$current6 = flatListRef.current) === null || _flatListRef$current6 === void 0 || _flatListRef$current6.scrollToIndex({
|
|
326
|
+
animated: (options === null || options === void 0 ? void 0 : options.animated) ?? false,
|
|
327
|
+
index: getInitialScrollIndex({
|
|
328
|
+
disableInfiniteScroll,
|
|
329
|
+
interval,
|
|
330
|
+
numberOfItems,
|
|
331
|
+
padWithNItems,
|
|
332
|
+
repeatNumbersNTimes: safeRepeatNumbersNTimes,
|
|
333
|
+
value: value
|
|
334
|
+
})
|
|
335
|
+
});
|
|
336
|
+
},
|
|
337
|
+
latestDuration: latestDuration
|
|
338
|
+
}));
|
|
339
|
+
const renderContent = useMemo(() => {
|
|
340
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(FlatList, {
|
|
341
|
+
key: flatListRenderKey,
|
|
342
|
+
ref: flatListRef,
|
|
343
|
+
contentContainerStyle: styles.durationScrollFlatListContentContainer,
|
|
344
|
+
data: numbersForFlatList,
|
|
345
|
+
decelerationRate: decelerationRate,
|
|
346
|
+
getItemLayout: getItemLayout,
|
|
347
|
+
initialScrollIndex: initialScrollIndex,
|
|
348
|
+
keyExtractor: keyExtractor,
|
|
349
|
+
nestedScrollEnabled: true,
|
|
350
|
+
onMomentumScrollEnd: onMomentumScrollEnd,
|
|
351
|
+
onScroll: onScroll,
|
|
352
|
+
renderItem: renderItem,
|
|
353
|
+
scrollEnabled: !isDisabled,
|
|
354
|
+
scrollEventThrottle: 16,
|
|
355
|
+
showsVerticalScrollIndicator: false,
|
|
356
|
+
snapToAlignment: "start"
|
|
357
|
+
// used in place of snapToInterval due to bug on Android
|
|
358
|
+
,
|
|
359
|
+
snapToOffsets: [...Array(numbersForFlatList.length)].map((_, i) => i * styles.pickerItemContainer.height),
|
|
360
|
+
style: styles.durationScrollFlatList,
|
|
361
|
+
testID: "duration-scroll-flatlist",
|
|
362
|
+
viewabilityConfigCallbackPairs: viewabilityConfigCallbackPairs,
|
|
363
|
+
windowSize: numberOfItemsToShow
|
|
364
|
+
}), /*#__PURE__*/React.createElement(View, {
|
|
365
|
+
pointerEvents: "none",
|
|
366
|
+
style: styles.pickerLabelContainer
|
|
367
|
+
}, typeof label === "string" ? /*#__PURE__*/React.createElement(Text, {
|
|
368
|
+
allowFontScaling: allowFontScaling,
|
|
369
|
+
style: styles.pickerLabel
|
|
370
|
+
}, label) : label ?? null));
|
|
371
|
+
}, [FlatList, allowFontScaling, flatListRenderKey, getItemLayout, initialScrollIndex, isDisabled, label, numberOfItemsToShow, numbersForFlatList, onMomentumScrollEnd, onScroll, renderItem, styles.durationScrollFlatList, styles.durationScrollFlatListContentContainer, styles.pickerItemContainer.height, styles.pickerLabel, styles.pickerLabelContainer, viewabilityConfigCallbackPairs, decelerationRate]);
|
|
372
|
+
const renderLinearGradient = useMemo(() => {
|
|
373
|
+
if (!LinearGradient) {
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
376
|
+
let colors;
|
|
377
|
+
if (MaskedView) {
|
|
378
|
+
// if using masked view, we only care about the opacity
|
|
379
|
+
colors = ["rgba(0,0,0,0)", "rgba(0,0,0,1)", "rgba(0,0,0,1)", "rgba(0,0,0,0)"];
|
|
380
|
+
} else {
|
|
381
|
+
const backgroundColor = styles.pickerContainer.backgroundColor ?? "white";
|
|
382
|
+
const transparentBackgroundColor = colorToRgba({
|
|
383
|
+
color: backgroundColor,
|
|
384
|
+
opacity: 0
|
|
385
|
+
});
|
|
386
|
+
colors = [backgroundColor, transparentBackgroundColor, transparentBackgroundColor, backgroundColor];
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// calculate the gradient height to cover the top item and bottom item
|
|
390
|
+
const gradientHeight = padWithNItems > 0 ? 1 / (padWithNItems * 2 + 1) : 0.3;
|
|
391
|
+
return /*#__PURE__*/React.createElement(LinearGradient, _extends({
|
|
392
|
+
colors: colors,
|
|
393
|
+
locations: [0, gradientHeight, 1 - gradientHeight, 1],
|
|
394
|
+
pointerEvents: "none",
|
|
395
|
+
style: styles.pickerGradientOverlay
|
|
396
|
+
}, pickerGradientOverlayProps));
|
|
397
|
+
}, [LinearGradient, MaskedView, padWithNItems, pickerGradientOverlayProps, styles.pickerContainer.backgroundColor, styles.pickerGradientOverlay]);
|
|
398
|
+
return /*#__PURE__*/React.createElement(View, {
|
|
399
|
+
pointerEvents: isDisabled ? "none" : undefined,
|
|
400
|
+
style: [styles.durationScrollFlatListContainer, {
|
|
401
|
+
height: styles.pickerItemContainer.height * numberOfItemsToShow
|
|
402
|
+
}, isDisabled && styles.disabledPickerContainer],
|
|
403
|
+
testID: testID
|
|
404
|
+
}, MaskedView ? /*#__PURE__*/React.createElement(MaskedView, {
|
|
405
|
+
maskElement: renderLinearGradient,
|
|
406
|
+
style: [styles.maskedView]
|
|
407
|
+
}, renderContent) : /*#__PURE__*/React.createElement(React.Fragment, null, renderContent, renderLinearGradient));
|
|
408
|
+
});
|
|
409
|
+
export default /*#__PURE__*/React.memo(DurationScroll);
|
|
410
|
+
//# sourceMappingURL=DurationScroll.js.map
|