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.
Files changed (101) hide show
  1. package/README.md +227 -152
  2. package/dist/commonjs/components/DurationScroll/DurationScroll.js +417 -0
  3. package/dist/commonjs/components/DurationScroll/DurationScroll.js.map +1 -0
  4. package/dist/commonjs/components/DurationScroll/index.js +20 -392
  5. package/dist/commonjs/components/DurationScroll/index.js.map +1 -1
  6. package/dist/commonjs/components/DurationScroll/types.js.map +1 -1
  7. package/dist/commonjs/components/Modal/Modal.js +107 -0
  8. package/dist/commonjs/components/Modal/Modal.js.map +1 -0
  9. package/dist/commonjs/components/Modal/index.js +20 -101
  10. package/dist/commonjs/components/Modal/index.js.map +1 -1
  11. package/dist/commonjs/components/TimerPicker/TimerPicker.js +225 -0
  12. package/dist/commonjs/components/TimerPicker/TimerPicker.js.map +1 -0
  13. package/dist/commonjs/components/TimerPicker/index.js +29 -166
  14. package/dist/commonjs/components/TimerPicker/index.js.map +1 -1
  15. package/dist/commonjs/components/TimerPicker/styles.js +1 -1
  16. package/dist/commonjs/components/TimerPicker/styles.js.map +1 -1
  17. package/dist/commonjs/components/TimerPicker/types.js.map +1 -1
  18. package/dist/commonjs/components/TimerPickerModal/TimerPickerModal.js +143 -0
  19. package/dist/commonjs/components/TimerPickerModal/TimerPickerModal.js.map +1 -0
  20. package/dist/commonjs/components/TimerPickerModal/index.js +30 -131
  21. package/dist/commonjs/components/TimerPickerModal/index.js.map +1 -1
  22. package/dist/commonjs/components/TimerPickerModal/types.js.map +1 -1
  23. package/dist/commonjs/index.js +9 -13
  24. package/dist/commonjs/index.js.map +1 -1
  25. package/dist/commonjs/tests/TimerPicker.test.js +4 -1
  26. package/dist/commonjs/tests/TimerPicker.test.js.map +1 -1
  27. package/dist/commonjs/utils/colorToRgba.js +35 -4
  28. package/dist/commonjs/utils/colorToRgba.js.map +1 -1
  29. package/dist/commonjs/utils/generateNumbers.js +67 -0
  30. package/dist/commonjs/utils/generateNumbers.js.map +1 -1
  31. package/dist/commonjs/utils/getAdjustedLimit.js +25 -0
  32. package/dist/commonjs/utils/getAdjustedLimit.js.map +1 -1
  33. package/dist/commonjs/utils/getDurationAndIndexFromScrollOffset.js +38 -0
  34. package/dist/commonjs/utils/getDurationAndIndexFromScrollOffset.js.map +1 -1
  35. package/dist/commonjs/utils/getInitialScrollIndex.js +38 -0
  36. package/dist/commonjs/utils/getInitialScrollIndex.js.map +1 -1
  37. package/dist/commonjs/utils/getSafeInitialValue.js +28 -0
  38. package/dist/commonjs/utils/getSafeInitialValue.js.map +1 -1
  39. package/dist/commonjs/utils/padNumber.js +25 -0
  40. package/dist/commonjs/utils/padNumber.js.map +1 -1
  41. package/dist/module/components/DurationScroll/DurationScroll.js +410 -0
  42. package/dist/module/components/DurationScroll/DurationScroll.js.map +1 -0
  43. package/dist/module/components/DurationScroll/index.js +2 -390
  44. package/dist/module/components/DurationScroll/index.js.map +1 -1
  45. package/dist/module/components/DurationScroll/types.js.map +1 -1
  46. package/dist/module/components/Modal/Modal.js +99 -0
  47. package/dist/module/components/Modal/Modal.js.map +1 -0
  48. package/dist/module/components/Modal/index.js +2 -98
  49. package/dist/module/components/Modal/index.js.map +1 -1
  50. package/dist/module/components/TimerPicker/TimerPicker.js +217 -0
  51. package/dist/module/components/TimerPicker/TimerPicker.js.map +1 -0
  52. package/dist/module/components/TimerPicker/index.js +3 -166
  53. package/dist/module/components/TimerPicker/index.js.map +1 -1
  54. package/dist/module/components/TimerPicker/styles.js +1 -1
  55. package/dist/module/components/TimerPicker/styles.js.map +1 -1
  56. package/dist/module/components/TimerPicker/types.js.map +1 -1
  57. package/dist/module/components/TimerPickerModal/TimerPickerModal.js +135 -0
  58. package/dist/module/components/TimerPickerModal/TimerPickerModal.js.map +1 -0
  59. package/dist/module/components/TimerPickerModal/index.js +3 -130
  60. package/dist/module/components/TimerPickerModal/index.js.map +1 -1
  61. package/dist/module/components/TimerPickerModal/types.js.map +1 -1
  62. package/dist/module/index.js +2 -6
  63. package/dist/module/index.js.map +1 -1
  64. package/dist/module/tests/TimerPicker.test.js +4 -1
  65. package/dist/module/tests/TimerPicker.test.js.map +1 -1
  66. package/dist/module/utils/colorToRgba.js +35 -4
  67. package/dist/module/utils/colorToRgba.js.map +1 -1
  68. package/dist/module/utils/generateNumbers.js +68 -0
  69. package/dist/module/utils/generateNumbers.js.map +1 -1
  70. package/dist/module/utils/getAdjustedLimit.js +25 -0
  71. package/dist/module/utils/getAdjustedLimit.js.map +1 -1
  72. package/dist/module/utils/getDurationAndIndexFromScrollOffset.js +38 -0
  73. package/dist/module/utils/getDurationAndIndexFromScrollOffset.js.map +1 -1
  74. package/dist/module/utils/getInitialScrollIndex.js +38 -0
  75. package/dist/module/utils/getInitialScrollIndex.js.map +1 -1
  76. package/dist/module/utils/getSafeInitialValue.js +28 -0
  77. package/dist/module/utils/getSafeInitialValue.js.map +1 -1
  78. package/dist/module/utils/padNumber.js +25 -0
  79. package/dist/module/utils/padNumber.js.map +1 -1
  80. package/dist/typescript/components/DurationScroll/DurationScroll.d.ts +4 -0
  81. package/dist/typescript/components/DurationScroll/index.d.ts +2 -4
  82. package/dist/typescript/components/DurationScroll/types.d.ts +13 -9
  83. package/dist/typescript/components/Modal/Modal.d.ts +5 -0
  84. package/dist/typescript/components/Modal/index.d.ts +2 -5
  85. package/dist/typescript/components/TimerPicker/TimerPicker.d.ts +4 -0
  86. package/dist/typescript/components/TimerPicker/index.d.ts +3 -4
  87. package/dist/typescript/components/TimerPicker/styles.d.ts +1169 -771
  88. package/dist/typescript/components/TimerPicker/types.d.ts +26 -10
  89. package/dist/typescript/components/TimerPickerModal/TimerPickerModal.d.ts +4 -0
  90. package/dist/typescript/components/TimerPickerModal/index.d.ts +3 -4
  91. package/dist/typescript/components/TimerPickerModal/styles.d.ts +722 -474
  92. package/dist/typescript/components/TimerPickerModal/types.d.ts +8 -5
  93. package/dist/typescript/index.d.ts +2 -6
  94. package/dist/typescript/utils/colorToRgba.d.ts +34 -0
  95. package/dist/typescript/utils/generateNumbers.d.ts +66 -0
  96. package/dist/typescript/utils/getAdjustedLimit.d.ts +27 -2
  97. package/dist/typescript/utils/getDurationAndIndexFromScrollOffset.d.ts +38 -0
  98. package/dist/typescript/utils/getInitialScrollIndex.d.ts +38 -0
  99. package/dist/typescript/utils/getSafeInitialValue.d.ts +29 -0
  100. package/dist/typescript/utils/padNumber.d.ts +25 -0
  101. 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":["export 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":";;;;;;AAAO,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":[]}
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":["export 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":";;;;;;AAAO,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":[]}
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","hours","isNaN","minutes","seconds","exports"],"sources":["getSafeInitialValue.ts"],"sourcesContent":["export const getSafeInitialValue = (\n initialValue:\n | {\n hours?: number;\n minutes?: number;\n seconds?: number;\n }\n | undefined\n) => ({\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":";;;;;;AAAO,MAAMA,mBAAmB,GAC5BC,YAMe,KACb;EACFC,KAAK,EACD,QAAOD,YAAY,aAAZA,YAAY,uBAAZA,YAAY,CAAEC,KAAK,MAAK,QAAQ,IAAI,CAACC,KAAK,CAACF,YAAY,aAAZA,YAAY,uBAAZA,YAAY,CAAEC,KAAK,CAAC,GAChED,YAAY,CAACC,KAAK,GAClB,CAAC;EACXE,OAAO,EACH,QAAOH,YAAY,aAAZA,YAAY,uBAAZA,YAAY,CAAEG,OAAO,MAAK,QAAQ,IACzC,CAACD,KAAK,CAACF,YAAY,aAAZA,YAAY,uBAAZA,YAAY,CAAEG,OAAO,CAAC,GACvBH,YAAY,CAACG,OAAO,GACpB,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;AACd,CAAC,CAAC;AAACC,OAAA,CAAAN,mBAAA,GAAAA,mBAAA","ignoreList":[]}
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":["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":";;;;;;AAAO,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":[]}
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