{"id":28259223,"url":"https://github.com/troberts-28/react-native-timer-picker","last_synced_at":"2026-04-02T10:38:52.668Z","repository":{"id":188222789,"uuid":"676934681","full_name":"troberts-28/react-native-timer-picker","owner":"troberts-28","description":"A simple, flexible, performant duration picker for React Native apps (Expo \u0026 Bare Workflow). Great for timers, alarms and duration inputs. Includes iOS-style haptic and audio feedback.","archived":false,"fork":false,"pushed_at":"2026-02-08T20:10:28.000Z","size":29406,"stargazers_count":216,"open_issues_count":2,"forks_count":24,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-09T01:17:50.598Z","etag":null,"topics":["duration-picker","react","react-native","react-native-component","react-native-components","react-native-picker"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/react-native-timer-picker","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/troberts-28.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-08-10T10:55:24.000Z","updated_at":"2026-02-08T20:10:08.000Z","dependencies_parsed_at":"2023-12-26T15:58:51.382Z","dependency_job_id":"a4d8a186-bec6-42c7-b4b1-79b281132c4e","html_url":"https://github.com/troberts-28/react-native-timer-picker","commit_stats":null,"previous_names":["troberts-28/react-native-duration-picker","troberts-28/react-native-timer-picker"],"tags_count":50,"template":false,"template_full_name":null,"purl":"pkg:github/troberts-28/react-native-timer-picker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/troberts-28%2Freact-native-timer-picker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/troberts-28%2Freact-native-timer-picker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/troberts-28%2Freact-native-timer-picker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/troberts-28%2Freact-native-timer-picker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/troberts-28","download_url":"https://codeload.github.com/troberts-28/react-native-timer-picker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/troberts-28%2Freact-native-timer-picker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29839947,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-25T20:42:33.054Z","status":"ssl_error","status_checked_at":"2026-02-25T20:42:21.322Z","response_time":61,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["duration-picker","react","react-native","react-native-component","react-native-components","react-native-picker"],"created_at":"2025-05-20T02:16:39.868Z","updated_at":"2026-02-25T23:07:36.223Z","avatar_url":"https://github.com/troberts-28.png","language":"TypeScript","readme":"# React Native Timer Picker ⏰🕰️⏳\n\n[![license](https://img.shields.io/github/license/mashape/apistatus.svg?style=for-the-badge)]()\n![platforms](https://img.shields.io/badge/platforms-Android%20%7C%20iOS-brightgreen.svg?style=for-the-badge\u0026colorB=191A17)\n[![Version](https://img.shields.io/npm/v/react-native-timer-picker.svg?style=for-the-badge)](https://www.npmjs.com/package/react-native-timer-picker)\n[![npm](https://img.shields.io/npm/dt/react-native-timer-picker.svg?style=for-the-badge\u0026cacheSeconds=86400)](https://www.npmjs.com/package/react-native-timer-picker)\n\nA simple, flexible, performant duration picker component for React Native apps 🔥\n\nGreat for timers, alarms and duration inputs.\n\nWorks with Expo and bare React Native apps ✅\n\nIncludes iOS-style haptic and audio feedback 🍏\n\n- [React Native Timer Picker ⏰🕰️⏳](#react-native-timer-picker-️)\n  - [Demos 📱](#demos-)\n  - [Installation 🚀](#installation-)\n    - [Peer Dependencies 👶](#peer-dependencies-)\n      - [Linear Gradient](#linear-gradient)\n      - [Masked View](#masked-view)\n  - [Examples 😎](#examples-)\n    - [Timer Picker Modal (Dark Mode) 🌚](#timer-picker-modal-dark-mode-)\n    - [Timer Picker Modal (Light Mode) 🌞](#timer-picker-modal-light-mode-)\n    - [Timer Picker Modal with Custom Buttons 🎨](#timer-picker-modal-with-custom-buttons-)\n    - [Timer Picker with Transparent Fade-Out (Dark Mode) 🌒](#timer-picker-with-transparent-fade-out-dark-mode-)\n    - [Timer Picker with Customisation (Light Mode) 🌔](#timer-picker-with-customisation-light-mode-)\n  - [Props 💅](#props-)\n    - [TimerPicker ⏲️](#timerpicker-️)\n      - [Custom Styles 👗](#custom-styles-)\n      - [Performance](#performance)\n      - [Custom FlatList](#custom-flatlist)\n    - [TimerPickerModal ⏰](#timerpickermodal-)\n      - [Custom Styles 👕](#custom-styles--1)\n  - [Methods 🔄](#methods-)\n    - [TimerPicker](#timerpicker)\n    - [TimerPickerModal](#timerpickermodal)\n  - [Picker Feedback 📳🔉](#picker-feedback-)\n    - [Audio Feedack](#audio-feedack)\n    - [Haptic Feedback](#haptic-feedback)\n    - [Feedback Example](#feedback-example)\n    - [Expo-Specific Audio/Haptic Feedback (DEPRECATED)](#expo-specific-audiohaptic-feedback-deprecated)\n  - [Contributing 🧑‍🤝‍🧑](#contributing-)\n    - [Dev Setup](#dev-setup)\n    - [GitHub Guidelines](#github-guidelines)\n  - [Limitations ⚠](#limitations-)\n  - [License 📝](#license-)\n\n\u003cbr\u003e\n\n## Demos 📱\n\n**Try it out for yourself on [Expo Snack](https://snack.expo.dev/@nuumi/react-native-timer-picker-demo)!** Make sure to run it on a mobile to see it working properly.\n\n\u003cp\u003e\n    \u003cimg src=\"demos/example1.gif\" width=\"250\" height=\"550\" style=\"margin-right:50px\"/\u003e\n    \u003cimg src=\"demos/example2.gif\" width=\"250\" height=\"550\" style=\"margin-right:50px\"/\u003e\n    \u003cimg src=\"demos/example3.gif\" width=\"250\" height=\"550\" /\u003e\n\u003c/p\u003e\n\u003cp\u003e\n    \u003cimg src=\"demos/example4.gif\" width=\"250\" height=\"550\" style=\"margin-right:50px\"/\u003e\n    \u003cimg src=\"demos/example5.gif\" width=\"250\" height=\"550\"/\u003e\n\u003c/p\u003e\n\n\u003cbr\u003e\n\n## Installation 🚀\n\nSupports React Native \u003e= 0.72.0 and React \u003e= 18.2.0.\n\nJust run:\n\n```bash\nnpm install react-native-timer-picker\n```\n\nor\n\n```bash\nyarn add react-native-timer-picker\n```\n\n### Peer Dependencies 👶\n\nThis component will work in your React Native Project **_without any peer dependencies_**. However, to enable certain additional features (e.g. fade-out) you will need to supply various libraries as props. These are detailed below.\n\n#### Linear Gradient\n\nIf you want the numbers to fade in/out at the top and bottom of the picker, you will need to install either:\n\n-   [expo-linear-gradient](https://www.npmjs.com/package/expo-linear-gradient) (if using Expo)\n-   [react-native-linear-gradient](https://www.npmjs.com/package/react-native-linear-gradient) (if using in a bare React Native project)\n\n**To enable the linear gradient, you need to supply the component as a prop to either TimerPickerModal or TimerPicker.**\n\n#### Masked View\n\nTo make the numbers fade in/out on a transparent background (e.g. if the picker is rendered on top of a gradient or image), you will need to install the [@react-native-masked-view/masked-view\n](https://www.npmjs.com/package/@react-native-masked-view/masked-view) component. This is as the standard LinearGradient implementation relies on there being a solid background colour. You then just need to set `backgroundColor: \"transparent` on the `TimerPicker` styles prop.\n\n`import MaskedView from \"@react-native-masked-view/masked-view\";`\n\n**To enable the fade-out on a transparent background, you need to supply the imported `MaskedView` component AND one of the LinearGradient components as props to either TimerPickerModal or TimerPicker (see [this example](#timer-picker-with-transparent-fade-out-dark-mode-)).**\n\n\u003cbr\u003e\n\n## Examples 😎\n\n### Timer Picker Modal (Dark Mode) 🌚\n\n\u003cimg src=\"demos/example1.gif\" width=\"250\" height=\"550\"/\u003e\n\n```jsx\nimport { TimerPickerModal } from \"react-native-timer-picker\";\nimport { LinearGradient } from \"expo-linear-gradient\"; // or `import LinearGradient from \"react-native-linear-gradient\"`\n\n....\nconst [showPicker, setShowPicker] = useState(false);\nconst [alarmString, setAlarmString] = useState\u003c\n        string | null\n    \u003e(null);\n\nconst formatTime = ({\n    hours,\n    minutes,\n    seconds,\n}: {\n    hours?: number;\n    minutes?: number;\n    seconds?: number;\n}) =\u003e {\n    const timeParts = [];\n\n    if (hours !== undefined) {\n        timeParts.push(hours.toString().padStart(2, \"0\"));\n    }\n    if (minutes !== undefined) {\n        timeParts.push(minutes.toString().padStart(2, \"0\"));\n    }\n    if (seconds !== undefined) {\n        timeParts.push(seconds.toString().padStart(2, \"0\"));\n    }\n\n    return timeParts.join(\":\");\n};\n\nreturn (\n    \u003cView style={{backgroundColor: \"#514242\", alignItems: \"center\", justifyContent: \"center\"}}\u003e\n        \u003cText style={{fontSize: 18, color: \"#F1F1F1\"}}\u003e\n            {alarmString !== null\n                ? \"Alarm set for\"\n                : \"No alarm set\"}\n        \u003c/Text\u003e\n        \u003cTouchableOpacity\n            activeOpacity={0.7}\n            onPress={() =\u003e setShowPicker(true)}\u003e\n            \u003cView style={{alignItems: \"center\"}}\u003e\n                {alarmString !== null ? (\n                    \u003cText style={{color: \"#F1F1F1\", fontSize: 48}}\u003e\n                        {alarmString}\n                    \u003c/Text\u003e\n                ) : null}\n                \u003cTouchableOpacity\n                    activeOpacity={0.7}\n                    onPress={() =\u003e setShowPicker(true)}\u003e\n                    \u003cView style={{marginTop: 30}}\u003e\n                        \u003cText\n                            style={{\n                                paddingVertical: 10,\n                                paddingHorizontal: 18,\n                                borderWidth: 1,\n                                borderRadius: 10,\n                                fontSize: 16,\n                                overflow: \"hidden\",\n                                borderColor: \"#C2C2C2\",\n                                color: \"#C2C2C2\"\n                                }}\u003e\n                            {\"Set Alarm 🔔\"}\n                        \u003c/Text\u003e\n                    \u003c/View\u003e\n                \u003c/TouchableOpacity\u003e\n            \u003c/View\u003e\n        \u003c/TouchableOpacity\u003e\n        \u003cTimerPickerModal\n            closeOnOverlayPress\n            LinearGradient={LinearGradient}\n            modalProps={{\n                overlayOpacity: 0.2,\n            }}\n            modalTitle=\"Set Alarm\"\n            onCancel={() =\u003e setShowPicker(false)}\n            onConfirm={(pickedDuration) =\u003e {\n                setAlarmString(formatTime(pickedDuration));\n                setShowPicker(false);\n            }}\n            setIsVisible={setShowPicker}\n            styles={{\n                theme: \"dark\",\n            }}\n            visible={showPicker}\n        /\u003e\n    \u003c/View\u003e\n)\n\n```\n\n### Timer Picker Modal (Light Mode) 🌞\n\n\u003cimg src=\"demos/example2.gif\" width=\"250\" height=\"550\"/\u003e\n\n```jsx\nimport { TimerPickerModal } from \"react-native-timer-picker\";\nimport { LinearGradient } from \"expo-linear-gradient\"; // or `import LinearGradient from \"react-native-linear-gradient\"`\n\n....\nconst [showPicker, setShowPicker] = useState(false);\nconst [alarmString, setAlarmString] = useState\u003c\n        string | null\n    \u003e(null);\n\nconst formatTime = ({\n    hours,\n    minutes,\n    seconds,\n}: {\n    hours?: number;\n    minutes?: number;\n    seconds?: number;\n}) =\u003e {\n    const timeParts = [];\n\n    if (hours !== undefined) {\n        timeParts.push(hours.toString().padStart(2, \"0\"));\n    }\n    if (minutes !== undefined) {\n        timeParts.push(minutes.toString().padStart(2, \"0\"));\n    }\n    if (seconds !== undefined) {\n        timeParts.push(seconds.toString().padStart(2, \"0\"));\n    }\n\n    return timeParts.join(\":\");\n};\n\nreturn (\n    \u003cView style={{backgroundColor: \"#F1F1F1\", alignItems: \"center\", justifyContent: \"center\"}}\u003e\n        \u003cText style={{fontSize: 18, color: \"#202020\"}}\u003e\n            {alarmString !== null\n                ? \"Alarm set for\"\n                : \"No alarm set\"}\n        \u003c/Text\u003e\n        \u003cTouchableOpacity\n            activeOpacity={0.7}\n            onPress={() =\u003e setShowPicker(true)}\u003e\n            \u003cView style={{alignItems: \"center\"}}\u003e\n                {alarmString !== null ? (\n                    \u003cText style={{color: \"#202020\", fontSize: 48}}\u003e\n                        {alarmString}\n                    \u003c/Text\u003e\n                ) : null}\n                \u003cTouchableOpacity\n                    activeOpacity={0.7}\n                    onPress={() =\u003e setShowPicker(true)}\u003e\n                    \u003cView style={{marginTop: 30}}\u003e\n                        \u003cText\n                            style={{paddingVertical: 10,\n                            paddingHorizontal: 18,\n                            borderWidth: 1,\n                            borderRadius: 10,\n                            fontSize: 16,\n                            overflow: \"hidden\",\n                            borderColor: \"#8C8C8C\",\n                            color: \"#8C8C8C\"\n                            }}\u003e\n                            {\"Set Alarm 🔔\"}\n                        \u003c/Text\u003e\n                    \u003c/View\u003e\n                \u003c/TouchableOpacity\u003e\n            \u003c/View\u003e\n        \u003c/TouchableOpacity\u003e\n        \u003cTimerPickerModal\n            closeOnOverlayPress\n            LinearGradient={LinearGradient}\n            modalTitle=\"Set Alarm\"\n            onCancel={() =\u003e setShowPicker(false)}\n            onConfirm={(pickedDuration) =\u003e {\n                setAlarmString(formatTime(pickedDuration));\n                setShowPicker(false);\n            }}\n            setIsVisible={setShowPicker}\n            styles={{\n                theme: \"light\",\n                pickerColumnWidth: {\n                    hours: 90,\n                },\n            }}\n            use12HourPicker\n            visible={showPicker}\n        /\u003e\n    \u003c/View\u003e\n)\n\n```\n\n### Timer Picker Modal with Custom Buttons 🎨\n\n\u003cimg src=\"demos/example3.gif\" width=\"250\" height=\"550\"/\u003e\n\n```jsx\nimport { TimerPickerModal } from \"react-native-timer-picker\";\nimport { LinearGradient } from \"expo-linear-gradient\"; // or `import LinearGradient from \"react-native-linear-gradient\"`\nimport { TouchableOpacity, Text, StyleSheet } from \"react-native\";\n\n// Custom Button Component\ninterface CustomButtonProps {\n    label: string;\n    onPress?: () =\u003e void;\n}\n\nconst CustomButton: React.FC\u003cCustomButtonProps\u003e = ({ label, onPress }) =\u003e {\n    return (\n        \u003cTouchableOpacity onPress={onPress} style={styles.customButtonContainer}\u003e\n            \u003cLinearGradient\n                style={styles.customButtonGradient}\n                colors={['#bb2649', '#6c35de']}\n                start={{ x: 0, y: 0 }}\n                end={{ x: 1, y: 1 }}\n            \u003e\n                \u003cText style={styles.customButtonText}\u003e{label}\u003c/Text\u003e\n            \u003c/LinearGradient\u003e\n        \u003c/TouchableOpacity\u003e\n    );\n};\n\n// Styles\nconst styles = StyleSheet.create({\n    customButtonContainer: {\n        marginHorizontal: 5,\n    },\n    customButtonGradient: {\n        borderRadius: 15,\n        paddingVertical: 12,\n        paddingHorizontal: 20,\n        alignItems: 'center',\n        justifyContent: 'center',\n    },\n    customButtonText: {\n        color: '#FFFFFF',\n        fontSize: 16,\n        fontWeight: '600',\n    },\n});\n\n....\nconst [showPicker, setShowPicker] = useState(false);\nconst [alarmString, setAlarmString] = useState\u003cstring\u003e(\"00:00:00\");\n\nconst formatTime = ({\n    hours,\n    minutes,\n    seconds,\n}: {\n    hours?: number;\n    minutes?: number;\n    seconds?: number;\n}) =\u003e {\n    const timeParts = [];\n\n    if (hours !== undefined) {\n        timeParts.push(hours.toString().padStart(2, \"0\"));\n    }\n    if (minutes !== undefined) {\n        timeParts.push(minutes.toString().padStart(2, \"0\"));\n    }\n    if (seconds !== undefined) {\n        timeParts.push(seconds.toString().padStart(2, \"0\"));\n    }\n\n    return timeParts.join(\":\");\n};\n\nreturn (\n    \u003cView style={{backgroundColor: \"#F1F1F1\", alignItems: \"center\", justifyContent: \"center\"}}\u003e\n        \u003cText style={{fontSize: 18, color: \"#202020\"}}\u003e\n            {alarmString !== null ? \"Alarm set for\" : \"No alarm set\"}\n        \u003c/Text\u003e\n        \u003cTouchableOpacity\n            activeOpacity={0.7}\n            onPress={() =\u003e setShowPicker(true)}\u003e\n            \u003cView style={{alignItems: \"center\"}}\u003e\n                {alarmString !== null ? (\n                    \u003cText style={{color: \"#202020\", fontSize: 48}}\u003e\n                        {alarmString}\n                    \u003c/Text\u003e\n                ) : null}\n                \u003cTouchableOpacity\n                    activeOpacity={0.7}\n                    onPress={() =\u003e setShowPicker(true)}\u003e\n                    \u003cView style={{marginTop: 30}}\u003e\n                        \u003cText\n                            style={{paddingVertical: 10,\n                            paddingHorizontal: 18,\n                            borderWidth: 1,\n                            borderRadius: 10,\n                            fontSize: 16,\n                            overflow: \"hidden\",\n                            borderColor: \"#8C8C8C\",\n                            color: \"#8C8C8C\"\n                            }}\u003e\n                            Set Alarm 🔔\n                        \u003c/Text\u003e\n                    \u003c/View\u003e\n                \u003c/TouchableOpacity\u003e\n            \u003c/View\u003e\n        \u003c/TouchableOpacity\u003e\n        \u003cTimerPickerModal\n            cancelButton={\u003cCustomButton label=\"Cancel\" /\u003e}\n            closeOnOverlayPress\n            confirmButton={\u003cCustomButton label=\"Confirm\" /\u003e}\n            LinearGradient={LinearGradient}\n            modalProps={{\n                overlayOpacity: 0.2,\n            }}\n            modalTitle=\"Set Alarm\"\n            onCancel={() =\u003e setShowPicker(false)}\n            onConfirm={(pickedDuration) =\u003e {\n                setAlarmString(formatTime(pickedDuration));\n                setShowPicker(false);\n            }}\n            setIsVisible={setShowPicker}\n            styles={{\n                theme: \"dark\",\n                pickerLabelGap: 10,\n                text: { fontSize: 18 },\n            }}\n            visible={showPicker}\n        /\u003e\n    \u003c/View\u003e\n)\n\n```\n\n### Timer Picker with Transparent Fade-Out (Dark Mode) 🌒\n\n\u003cimg src=\"demos/example4.gif\" width=\"250\" height=\"550\"/\u003e\n\n```jsx\nimport { TimerPicker } from \"react-native-timer-picker\";\nimport MaskedView from \"@react-native-masked-view/masked-view\"; // for transparent fade-out\nimport { LinearGradient } from \"expo-linear-gradient\"; // or `import LinearGradient from \"react-native-linear-gradient\"`\n\n....\n\nreturn (\n    \u003cLinearGradient\n        colors={[\"#202020\", \"#220578\"]}\n        end={{ x: 1, y: 1 }}\n        start={{ x: 0, y: 0 }}\n        style={{alignItems: \"center\", justifyContent: \"center\"}}\u003e\n        \u003cTimerPicker\n            hourLabel=\":\"\n            LinearGradient={LinearGradient}\n            MaskedView={MaskedView}\n            minuteLabel=\":\"\n            padWithNItems={2}\n            secondLabel=\"\"\n            styles={{\n                theme: \"dark\",\n                backgroundColor: \"transparent\",\n                pickerItem: {\n                    fontSize: 34,\n                },\n                pickerLabel: {\n                    fontSize: 32,\n                },\n                pickerLabelContainer: {\n                    marginTop: -4,\n                },\n                pickerLabelGap: 23,\n                pickerContainer: {\n                    paddingHorizontal: 50,\n                },\n            }}\n        /\u003e\n    \u003c/LinearGradient\u003e\n)\n\n```\n\n### Timer Picker with Customisation (Light Mode) 🌔\n\n\u003cimg src=\"demos/example5.gif\" width=\"250\" height=\"550\"/\u003e\n\n```jsx\nimport { TimerPicker } from \"react-native-timer-picker\";\nimport { LinearGradient } from \"expo-linear-gradient\"; // or `import LinearGradient from \"react-native-linear-gradient\"`\n\n....\n\nreturn (\n    \u003cView style={{backgroundColor: \"#F1F1F1\", alignItems: \"center\", justifyContent: \"center\"}}\u003e\n        \u003cTimerPicker\n            hideHours\n            LinearGradient={LinearGradient}\n            minuteLabel=\"min\"\n            padWithNItems={3}\n            secondLabel=\"sec\"\n            styles={{\n                theme: \"light\",\n                pickerLabelGap: 8,\n                pickerItem: {\n                    fontSize: 34,\n                },\n                pickerLabel: {\n                    fontSize: 26,\n                },\n                pickerContainer: {\n                    paddingHorizontal: 50,\n                },\n            }}\n        /\u003e\n    \u003c/View\u003e\n)\n\n```\n\n\u003cbr\u003e\n\n## Props 💅\n\n### TimerPicker ⏲️\n\n|             Prop              | Description                                                                                                                                                                                                              |                                                                                              Type                                                                                               |            Default             | Required |\n| :---------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------: | :------: |\n|       onDurationChange        | Callback when the duration changes                                                                                                                                                                                       |                                                     `(duration: { days: number, hours: number, minutes: number, seconds: number }) =\u003e void`                                                     |               -                |  false   |\n|         initialValue          | Initial value for the picker                                                                                                                                                                                             |                                                             `{ days?: number, hours?: number, minutes?: number, seconds?: number }`                                                             |               -                |  false   |\n|           hideDays            | Hide the days picker                                                                                                                                                                                                     |                                                                                             Boolean                                                                                             |              true              |  false   |\n|           hideHours           | Hide the hours picker                                                                                                                                                                                                    |                                                                                             Boolean                                                                                             |             false              |  false   |\n|          hideMinutes          | Hide the minutes picker                                                                                                                                                                                                  |                                                                                             Boolean                                                                                             |             false              |  false   |\n|          hideSeconds          | Hide the seconds picker                                                                                                                                                                                                  |                                                                                             Boolean                                                                                             |             false              |  false   |\n|     daysPickerIsDisabled      | Disable the days picker                                                                                                                                                                                                  |                                                                                             Boolean                                                                                             |             false              |  false   |\n|     hoursPickerIsDisabled     | Disable the hours picker                                                                                                                                                                                                 |                                                                                             Boolean                                                                                             |             false              |  false   |\n|    minutesPickerIsDisabled    | Disable the minutes picker                                                                                                                                                                                               |                                                                                             Boolean                                                                                             |             false              |  false   |\n|    secondsPickerIsDisabled    | Disable the seconds picker                                                                                                                                                                                               |                                                                                             Boolean                                                                                             |             false              |  false   |\n|           dayLimit            | Limit on the days it is possible to select                                                                                                                                                                               |                                                                                `{ max?: Number, min?: Number }`                                                                                 |               -                |  false   |\n|           hourLimit           | Limit on the hours it is possible to select                                                                                                                                                                              |                                                                                `{ max?: Number, min?: Number }`                                                                                 |               -                |  false   |\n|          minuteLimit          | Limit on the minutes it is possible to select                                                                                                                                                                            |                                                                                `{ max?: Number, min?: Number }`                                                                                 |               -                |  false   |\n|          secondLimit          | Limit on the seconds it is possible to select                                                                                                                                                                            |                                                                                `{ max?: Number, min?: Number }`                                                                                 |               -                |  false   |\n|          maximumDays          | The highest value on the days picker                                                                                                                                                                                     |                                                                                             Number                                                                                              |               23               |  false   |\n|         maximumHours          | The highest value on the hours picker                                                                                                                                                                                    |                                                                                             Number                                                                                              |               23               |  false   |\n|        maximumMinutes         | The highest value on the minutes picker                                                                                                                                                                                  |                                                                                             Number                                                                                              |               59               |  false   |\n|        maximumSeconds         | The highest value on the seconds picker                                                                                                                                                                                  |                                                                                             Number                                                                                              |               59               |  false   |\n|          dayInterval          | The interval between values on the days picker                                                                                                                                                                           |                                                                                             Number                                                                                              |               1                |  false   |\n|         hourInterval          | The interval between values on the hours picker                                                                                                                                                                          |                                                                                             Number                                                                                              |               1                |  false   |\n|        minuteInterval         | The interval between values on the minutes picker                                                                                                                                                                        |                                                                                             Number                                                                                              |               1                |  false   |\n|        secondInterval         | The interval between values on the seconds picker                                                                                                                                                                        |                                                                                             Number                                                                                              |               1                |  false   |\n|           dayLabel            | Label for the days picker                                                                                                                                                                                                |                                                                                  String \\| React.ReactElement                                                                                   |               d                |  false   |\n|           hourLabel           | Label for the hours picker                                                                                                                                                                                               |                                                                                  String \\| React.ReactElement                                                                                   |               h                |  false   |\n|          minuteLabel          | Label for the minutes picker                                                                                                                                                                                             |                                                                                  String \\| React.ReactElement                                                                                   |               m                |  false   |\n|          secondLabel          | Label for the seconds picker                                                                                                                                                                                             |                                                                                  String \\| React.ReactElement                                                                                   |               s                |  false   |\n|        padDaysWithZero        | Pad single-digit days in the picker with a zero                                                                                                                                                                          |                                                                                             Boolean                                                                                             |             false              |  false   |\n|       padHoursWithZero        | Pad single-digit hours in the picker with a zero                                                                                                                                                                         |                                                                                             Boolean                                                                                             |             false              |  false   |\n|      padMinutesWithZero       | Pad single-digit minutes in the picker with a zero                                                                                                                                                                       |                                                                                             Boolean                                                                                             |              true              |  false   |\n|      padSecondsWithZero       | Pad single-digit seconds in the picker with a zero                                                                                                                                                                       |                                                                                             Boolean                                                                                             |              true              |  false   |\n|         padWithNItems         | Number of items to pad the picker with on either side                                                                                                                                                                    |                                                                                             Number                                                                                              |               1                |  false   |\n| aggressivelyGetLatestDuration | Set to True to ask DurationScroll to aggressively update the latestDuration ref                                                                                                                                          |                                                                                             Boolean                                                                                             |             false              |  false   |\n|       allowFontScaling        | Allow font in the picker to scale with accessibility settings                                                                                                                                                            |                                                                                             Boolean                                                                                             |             false              |  false   |\n|        use12HourPicker        | Switch the hour picker to 12-hour format with an AM / PM label                                                                                                                                                           |                                                                                             Boolean                                                                                             |             false              |  false   |\n|            amLabel            | Set the AM label if using the 12-hour picker                                                                                                                                                                             |                                                                                             String                                                                                              |               am               |  false   |\n|            pmLabel            | Set the PM label if using the 12-hour picker                                                                                                                                                                             |                                                                                             String                                                                                              |               pm               |  false   |\n|    repeatDayNumbersNTimes     | Set the number of times the list of days is repeated in the picker                                                                                                                                                       |                                                                                             Number                                                                                              |               3                |  false   |\n|    repeatHourNumbersNTimes    | Set the number of times the list of hours is repeated in the picker                                                                                                                                                      |                                                                                             Number                                                                                              |               7                |  false   |\n|   repeatMinuteNumbersNTimes   | Set the number of times the list of minutes is repeated in the picker                                                                                                                                                    |                                                                                             Number                                                                                              |               3                |  false   |\n|   repeatSecondNumbersNTimes   | Set the number of times the list of seconds is repeated in the picker                                                                                                                                                    |                                                                                             Number                                                                                              |               3                |  false   |\n|     disableInfiniteScroll     | Disable the infinite scroll feature                                                                                                                                                                                      |                                                                                             Boolean                                                                                             |             false              |  false   |\n|        LinearGradient         | [Linear Gradient Component (required for picker fade-out)](#linear-gradient)                                                                                                                                             | [expo-linear-gradient](https://www.npmjs.com/package/expo-linear-gradient).LinearGradient or [react-native-linear-gradient](https://www.npmjs.com/package/react-native-linear-gradient).default |               -                |  false   |\n|          MaskedView           | [Masked View Component (required for picker fade-out on transparent background)](#masked-view)                                                                                                                           |                                      [@react-native-masked-view/masked-view](https://www.npmjs.com/package/@react-native-masked-view/masked-view).default                                       |               -                |  false   |\n|           FlatList            | FlatList component used internally to implement each picker (day, hour, minutes and seconds). More info [below](#custom-flatlist)                                                                                        |                                                                 [react-native](https://reactnative.dev/docs/flatlist).FlatList                                                                  | `FlatList` from `react-native` |  false   |\n|        pickerFeedback         | [Callback for providing audio/haptic feedback](#picker-feedback-) (fired whenever the picker ticks over a value)                                                                                                         |                                                                                 `() =\u003e void \\| Promise\u003cvoid\u003e `                                                                                  |               -                |  false   |\n|     Haptics (DEPRECATED)      | [Expo Haptics Namespace](#expo-specific-audiohaptic-feedback-deprecated) (please use pickerFeedback instead)                                                                                                             |                                                                   [expo-haptics](https://www.npmjs.com/package/expo-haptics)                                                                    |               -                |  false   |\n|      Audio (DEPRECATED)       | [Expo AV Audio Class](#expo-specific-audiohaptic-feedback-deprecated)                                                                                                                                                    |                                                   [expo-av](https://www.npmjs.com/package/expo-av).Audio (please use pickerFeedback instead)                                                    |               -                |  false   |\n| clickSoundAsset (DEPRECATED)  | Custom sound asset for click sound (please use pickerFeedback instead), was required for offline click sound - download default [here](https://drive.google.com/uc?export=download\u0026id=10e1YkbNsRh-vGx1jmS1Nntz8xzkBp4_I) |                                                                        require(.../somefolderpath) or {uri: www.someurl}                                                                        |               -                |  false   |\n|     pickerContainerProps      | Props for the picker container                                                                                                                                                                                           |                                                                               `React.ComponentProps\u003ctypeof View\u003e`                                                                               |               -                |  false   |\n|  pickerGradientOverlayProps   | Props for the gradient overlay (supply a different `locations` array to adjust its position) overlays                                                                                                                    |                                                                                 `Partial\u003cLinearGradientProps\u003e`                                                                                  |               -                |  false   |\n|            styles             | Custom styles for the timer picker                                                                                                                                                                                       |                                                                           [CustomTimerPickerStyles](#custom-styles-)                                                                            |               -                |  false   |\n|       decelerationRate        | Set how quickly the picker decelerates after the user lifts their finger                                                                                                                                                 |                                                                                   'fast', 'normal', or Number                                                                                   |              0.88              |  false   |\n\n#### Custom Styles 👗\n\nThe component should look good straight out of the box, but you can use these easy styles to make it fit in with your App's theme:\n\n|                Style Prop                 | Description                                                                                                                                              |        Type        |\n| :---------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------: |\n|                   theme                   | Theme of the component                                                                                                                                   | \"light\" \\| \"dark\"  |\n|              backgroundColor              | Main background color                                                                                                                                    |       string       |\n|                   text                    | Base text style                                                                                                                                          |     TextStyle      |\n|              pickerLabelGap               | Pixel gap between the label and the picker number column. Can be a single number or a per-column object (e.g. `{ hours: 10, minutes: 8 }`). Default: `6` | `PerColumnValue`\\* |\n|             pickerColumnWidth             | Width of individual picker columns in pixels. Can be a single number or a per-column object. Overrides default flex-based sizing when set                 | `PerColumnValue`\\* |\n| labelOffsetPercentage **(DEPRECATED)**    | Percentage offset for horizontal label positioning relative to the picker (use `pickerLabelGap` instead)                                                 |       number       |\n\n**\\*`PerColumnValue` type:** `number | { days?: number, hours?: number, minutes?: number, seconds?: number }` — pass a single number for all columns, or an object to set values per column. Omitted columns use the default.\n\nFor deeper style customization, you can supply the following custom styles to adjust the component in any way. These are applied on top of the default styling so take a look at those [styles](src/components/TimerPicker/styles.ts) if something isn't adjusting in the way you'd expect.\n\n|               Style Prop               | Description                                                          |                   Type                   |\n| :------------------------------------: | :------------------------------------------------------------------- | :--------------------------------------: |\n|            pickerContainer             | Main container for the picker                                        | ViewStyle \u0026 { backgroundColor?: string } |\n|          pickerLabelContainer          | Container for the picker's labels                                    |                ViewStyle                 |\n|              pickerLabel               | Style for the picker's labels                                        |                TextStyle                 |\n|          pickerAmPmContainer           | Style for the picker's labels                                        |                ViewStyle                 |\n|            pickerAmPmLabel             | Style for the picker's labels                                        |                TextStyle                 |\n|          pickerItemContainer           | Container for each number in the picker                              |     ViewStyle \u0026 { height?: number }      |\n|               pickerItem               | Style for each number                                                |                TextStyle                 |\n|           disabledPickerItem           | Style for any numbers outside any set limits                         |                TextStyle                 |\n|           selectedPickerItem           | Style for the currently selected number                              |                TextStyle                 |\n|        disabledPickerContainer         | Style for disabled pickers                                           |                ViewStyle                 |\n|         pickerGradientOverlay          | Style for the gradient overlay (fade out)                            |                ViewStyle                 |\n|         durationScrollFlatList         | Style for the Flatlist in each picker                                |                ViewStyle                 |\n|    durationScrollFlatListContainer     | Style for the View that contains the Flatlist in each picker         |                ViewStyle                 |\n| durationScrollFlatListContentContainer | Style for the Flatlist's `contentContainerStyle` prop in each picker |                ViewStyle                 |\n\n**Note:** There are minor limitations on `pickerContainer.backgroundColor` and `pickerItemContainer.height`. These properties must be simple values (string and number respectively) as they are used in internal calculations for scroll positioning, gradient overlays, and snap behavior. Complex computed values or union types are not supported for these specific properties.\n\n#### Performance\n\nWhen the `disableInfiniteScroll` prop is not set, the picker gives the appearance of an infinitely scrolling picker by auto-scrolling forward/back when you near the start/end of the list. When the picker auto-scrolls, a momentary flicker is visible if you are scrolling very slowly.\n\nTo mitigate for this, the list of numbers in each picker is repeated a given number of times based on the length of the list (7 times for the hours picker, and 3 times for the days/minutes/seconds picker). These have a performance trade-off: higher values mean the picker has to auto-scroll less to maintain the infinite scroll, but has to render a longer list of numbers. The number of repetitions automatically adjusts if the number of items in the picker changes (e.g. if an interval is included, or the maximum value is modified), balancing the trade-off. You can also manually adjust the number of repetitions in each picker with the `repeatHourNumbersNTimes`, `repeatMinuteNumbersNTimes` and `repeatSecondNumbersNTimes` props.\n\nNote that you can avoid the auto-scroll flickering entirely by disabling infinite scroll. You could then set the above props to high values, so that a user has to scroll far down/up the list to reach the end of the list.\n\n#### Custom FlatList\n\nThe library offers the ability to provide a custom component for the `\u003cFlatList /\u003e`, instead of the default React Native component. This allows for more flexibility and integration with libraries like [react-native-gesture-handler](react-native-gesture-handler) or other components built on top of it, like [https://ui.gorhom.dev/components/bottom-sheet](https://ui.gorhom.dev/components/bottom-sheet).\n\nE.g. if you want to place the timer picker within that bottom-sheet component, the scrolling detection from the bottom-sheet [would interfere](https://ui.gorhom.dev/components/bottom-sheet/troubleshooting#adding-horizontal-flatlist-or-scrollview-is-not-working-properly-on-android) with the one inside the timer picker, but it can be easily solved by providing the `FlatList` component from `react-native-gesture-handler` like this:\n\n```Jsx\nimport { FlatList } from 'react-native-gesture-handler';\nimport { TimerPicker } from \"react-native-timer-picker\";\n\n// ...\n\n\u003cTimerPicker\n    {...props}\n    FlatList={FlatList}\n/\u003e\n\n```\n\nPlease note that this solution does not work for all bottom-sheet components (e.g. `@tamagui/sheet`) as it depends on the implementation of each component.\n\n**Important**:\nThe custom component needs to have the same interface as React Native's `\u003cFlatList /\u003e` in order for it to work as expected. A complete reference of the current usage can be found [here](/src/components/DurationScroll/index.tsx).\n\n### TimerPickerModal ⏰\n\nThe TimerPickerModal component accepts all [TimerPicker props](#timerpicker-️), and the below additional props.\n\n|            Prop             | Description                                           |                                             Type                                             | Default | Required |\n| :-------------------------: | :---------------------------------------------------- | :------------------------------------------------------------------------------------------: | :-----: | :------: |\n|           visible           | Determines if the modal is visible                    |                                           Boolean                                            |    -    |   true   |\n|        setIsVisible         | Callback to set modal visibility                      |                                `(isVisible: boolean) =\u003e void`                                |    -    |   true   |\n|          onConfirm          | Callback when the user confirms the selected time     | `({ hours, minutes, seconds }: { hours: number, minutes: number, seconds: number }) =\u003e void` |    -    |   true   |\n|          onCancel           | Callback when the user cancels the selection          |                                         `() =\u003e void`                                         |    -    |  false   |\n|     closeOnOverlayPress     | Determines if the modal should close on overlay press |                                           Boolean                                            |  false  |  false   |\n|      hideCancelButton       | Hide the cancel button within the modal               |                                           Boolean                                            |  false  |  false   |\n|      confirmButtonText      | Text for the confirm button                           |                                            String                                            | Confirm |  false   |\n|      cancelButtonText       | Text for the cancel button                            |                                            String                                            | Cancel  |  false   |\n|        confirmButton        | Custom confirm button component                       |                           `ReactElement\u003c{ onPress?: () =\u003e void }\u003e`                           |    -    |  false   |\n|        cancelButton         | Custom cancel button component                        |                           `ReactElement\u003c{ onPress?: () =\u003e void }\u003e`                           |    -    |  false   |\n|         modalTitle          | Title text for the modal                              |                                            String                                            |    -    |  false   |\n|         modalProps          | Props for the main modal component                    |                             `React.ComponentProps\u003ctypeof Modal\u003e`                             |    -    |  false   |\n|       containerProps        | Props for the main container                          |                             `React.ComponentProps\u003ctypeof View\u003e`                              |    -    |  false   |\n|    contentContainerProps    | Props for the content container                       |                             `React.ComponentProps\u003ctypeof View\u003e`                              |    -    |  false   |\n|    buttonContainerProps     | Props for the button containers                       |                             `React.ComponentProps\u003ctypeof View\u003e`                              |    -    |  false   |\n| buttonTouchableOpacityProps | Props for the button touchable opacities              |                       `React.ComponentProps\u003ctypeof TouchableOpacity\u003e`                        |    -    |  false   |\n|       modalTitleProps       | Props for the modal title text component              |                             `React.ComponentProps\u003ctypeof Text\u003e`                              |    -    |  false   |\n|           styles            | Custom styles for the timer picker modal              |                      [CustomTimerPickerModalStyles](#custom-styles--1)                       |    -    |  false   |\n\n#### Custom Styles 👕\n\nThe following custom styles can be supplied to re-style the component in any way. You can also supply all of the styles specified in [CustomTimerPickerStyles](#custom-styles-). These are applied on top of the default styling so take a look at those [styles](src/components/TimerPickerModal/styles.ts) if something isn't adjusting in the way you'd expect.\n\n|    Style Prop    | Description                                                      |   Type    |\n| :--------------: | :--------------------------------------------------------------- | :-------: |\n|    container     | Style for the modal container                                    | ViewStyle |\n| contentContainer | Style for the modal content's container                          | ViewStyle |\n| buttonContainer  | Style for the container for the buttons                          | ViewStyle |\n|      button      | General style for both buttons                                   | TextStyle |\n|   cancelButton   | Style for the cancel button                                      | TextStyle |\n|  confirmButton   | Style for the confirm button                                     | TextStyle |\n|    modalTitle    | Style for the title of the modal                                 | TextStyle |\n|       ...        | Supply any of [TimerPicker's custom styles](\u003c(#custom-styles-)\u003e) |     -     |\n\n\u003cbr\u003e\n\n## Methods 🔄\n\n### TimerPicker\n\nThe library exposes a TimerPickerRef type, which can be used to type your ref to the picker:\n\n```javascript\nconst timerPickerRef = useRef \u003c TimerPickerRef \u003e null;\n```\n\nIt has the following available methods:\n\n`reset` - imperative method to reset the selected duration to their initial values.\n\n```javascript\ntimerPickerRef.current.reset(options?: { animated: boolean });\n```\n\n`setValue` - imperative method to set the selected duration to a particular value\n\n```javascript\ntimerPickerRef.current.setValue({ days?: number, hours?: number, minutes?: number, seconds?: number }, options?: { animated: boolean });\n```\n\nIt also exposes the following ref object:\n\n`latestDuration` - provides access to the latest duration (even during scrolls). **This only works if `aggressivelyGetLatestDuration` is set to True (as in TimerPickerModal).** It is used internally to ensure that the latest duration is returned in `TimerPickerModal` on pressing the confirm button, even if the inputs are still scrolling.\n\n```javascript\nconst latestDuration = timerPickerRef.current?.latestDuration;\nconst newDuration = {\n    days: latestDuration?.days?.current,\n    hours: latestDuration?.hours?.current,\n    minutes: latestDuration?.minutes?.current,\n    seconds: latestDuration?.seconds?.current,\n};\n```\n\n### TimerPickerModal\n\nAn identical ref is also exposed for the TimerPickerModal component.\n\n\u003cbr\u003e\n\n## Picker Feedback 📳🔉\n\nYou can use the picker feedback callback prop `pickerFeedback` to provide any form of audio/haptic feedback for the picker. This function is called whenever any of the pickers tick onto a new number.\n\nNote that this prop should be used in lieu of the now deprecated expo-specific audio/haptic feedback props.\n\n### Audio Feedack\n\nThere is a challenge here with audio latency as we need to be able to play the click-sound repeatedly and rapidly when a user scrolls fast. Most React Native sound libraries are designed for playing audio tracks and the latency is too high for this application.\n\nRecommended libraries:\n\n-   [react-native-audio-api](https://www.npmjs.com/package/react-native-audio-api): this is a new library but it's built by Software Mansion and has strong potential for our application with low-latency audio. It is not currently straightforward to use a local sound asset with this library; please check out the [Expo example](./examples/example-expo/App.tsx) and [Bare React Native example](./examples/example-bare//App.tsx) for a guide on how to do that. Note that this library will not work in Expo Go (you must create a development build).\n\nLibraries to avoid:\n\n-   [react-native-sound](https://www.npmjs.com/package/react-native-sound): this likely has low enough latency to work but has not been maintained for 3+ years.\n-   [expo-av](https://docs.expo.dev/versions/latest/sdk/av/): the latency is too high to work well. Expo are developing a new audio module [expo-audio](https://docs.expo.dev/versions/latest/sdk/audio/) that may be better, but at the time of writing (May 2025) it does not have the capability to repeatedly play the same sound.\n\n### Haptic Feedback\n\nRecommended libraries:\n\n-   [expo-haptics](https://www.npmjs.com/package/expo-haptics): for Expo apps.\n-   [react-native-haptic-feedback](https://github.com/mkuczera/react-native-haptic-feedback): for bare React Native apps.\n\n### Feedback Example\n\n```Jsx\nimport { useCallback, useRef } from \"react\";\nimport { TimerPicker } from \"react-native-timer-picker\";\n\nimport { AudioContext, type AudioBuffer } from \"react-native-audio-api\";\nimport * as Haptics from 'expo-haptics'; // Expo apps\nimport { trigger } from 'react-native-haptic-feedback'; // Bare RN apps\n\n// see examples/example-expo and examples/example-bare for how to load a local sound\nimport { getClickSound } from \"./utils/getClickSound\";\n\n// ...\n\nconst audioContextRef = useRef\u003cAudioContext | null\u003e(null);\nconst audioBufferRef = useRef\u003cAudioBuffer | null\u003e(null);\n\nuseEffect(() =\u003e {\n    const setupAudio = async () =\u003e {\n        try {\n            const context = new AudioContext();\n            const arrayBuffer = await getClickSound();\n            const buffer = await context.decodeAudioData(arrayBuffer);\n\n            audioContextRef.current = context;\n            audioBufferRef.current = buffer;\n        } catch (error) {\n            console.warn(\"Audio setup failed:\", error);\n        }\n    };\n\n    setupAudio();\n\n    return () =\u003e {\n        audioContextRef.current?.close();\n    };\n}, []);\n\nconst pickerFeedback = useCallback(() =\u003e {\n    try {\n        // Audio\n        const context = audioContextRef.current;\n        const buffer = audioBufferRef.current;\n\n        if (!context || !buffer) {\n            console.warn(\"Audio not initialized\");\n            return;\n        }\n\n        const playerNode = context.createBufferSource();\n        playerNode.buffer = buffer;\n        playerNode.connect(context.destination);\n        playerNode.start(context.currentTime);\n\n        // Haptics (Expo apps)\n        Haptics.selectionAsync();\n        // Hatpics (Bare RN apps)\n        trigger('selection');\n    } catch {\n        console.warn(\"Picker feedback failed\");\n    }\n}, [])\n\n\u003cTimerPicker\n    {...props}\n    pickerFeedback={pickerFeedback}\n/\u003e\n\n```\n\n### Expo-Specific Audio/Haptic Feedback (DEPRECATED)\n\n**⚠️ This was deprecated in v2.2.0 - please use the [picker feedback](#generic-feedback) prop instead.**\n\nEnable haptic feedback with the [expo-haptics](https://www.npmjs.com/package/expo-haptics) module:\n\n`import * as Haptics from \"expo-haptics\";`\n\nTo enable haptic feedback, you need to supply the imported `Haptics` namespace as a prop to either TimerPickerModal or TimerPicker.\n\n\u003cbr\u003e\n\nEnable audio feedback with the [expo-av](https://www.npmjs.com/package/expo-av) module:\n\n`import { Audio } from \"expo-av\";`\n\nTo enable audio feedback, you need to supply the imported `Audio` class as a prop to either TimerPickerModal or TimerPicker.\n\nPlease note that the default click sound uses a hosted mp3 file. To make the click sound work offline, you need to supply your own\nsound asset through the `clickSoundAsset` prop. You can download the default click sound [here](https://drive.google.com/uc?export=download\u0026id=10e1YkbNsRh-vGx1jmS1Nntz8xzkBp4_I).\n\n\u003cbr\u003e\n\n## Contributing 🧑‍🤝‍🧑\n\nContributions to this project are more than welcome.\n\n**N.B. Please submit PRs into `develop`, not `main`.**\n\n### Dev Setup\n\nTo get this project running locally:\n\n1. Clone the Git repo.\n2. Run `yarn setup` from the project root (this installs the project dependencies and the examples' additional dependencies)\n\nYou can then start either the Expo example or the bare React Native example:\n\n-   For Expo, run `yarn start` to start the Expo example in Expo Go. For audio feedback, uncomment the relevant lines in `examples/example-expo/App.tsx` and create a development build with `yarn build:android` or `yarn build:ios`.\n-   For bare React Native, run `yarn start-bare:android` or `start-bare:ios` to start the project on an emulator/device (you have to refresh the app once on startup for it to work).\n\n### GitHub Guidelines\n\nThere are two permenant branches: `main` and `develop`. You should never work directly on either of these branches.\n\n1. Create a new branch off `develop` for your work using the pattern `feature/{DESCRIPTION}`.\n2. When you think your work is ready for review, submit a PR from your branch back to `develop`.\n3. Once the PR is resolved, your work will be merged into `develop`, and will be included in the next major/minor release.\n\n\u003cbr\u003e\n\n## Limitations ⚠\n\n-   The project is not compatibile with React Native versions prior to `v0.72.0` due to this [React Native issue](https://github.com/facebook/react-native/issues/36329).\n-   The audio feedback provided by the `Audio` prop with `expo-av` suffers from high latency and doesn't work well when a user scrolls quickly. This has now been deprecated in place of the `pickerFeedback` prop. Please try `react-native-audio-api` instead.\n\n\u003cbr\u003e\n\n## License 📝\n\nThis project is licensed under the [MIT License](LICENSE).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftroberts-28%2Freact-native-timer-picker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftroberts-28%2Freact-native-timer-picker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftroberts-28%2Freact-native-timer-picker/lists"}