├── .all-contributorsrc ├── .auto-changelog ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── documentation.yml │ ├── label-sponsors.yml │ ├── main.yml │ ├── publish-yarn.yaml │ └── stale.yml ├── .gitignore ├── .huskyrc.json ├── .prettierignore ├── .prettierrc.json ├── .release-it.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── babel.config.js ├── commitlint.config.js ├── example ├── app │ ├── package.json │ ├── src │ │ ├── App.tsx │ │ ├── components │ │ │ ├── button │ │ │ │ ├── Button.tsx │ │ │ │ └── index.ts │ │ │ ├── contactItem │ │ │ │ ├── ContactItem.tsx │ │ │ │ └── index.ts │ │ │ ├── contactList │ │ │ │ ├── ContactList.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── styles.ts │ │ │ │ └── styles.web.ts │ │ │ ├── customBackground │ │ │ │ ├── CustomBackground.tsx │ │ │ │ └── index.ts │ │ │ ├── customFooter │ │ │ │ ├── CustomFooter.tsx │ │ │ │ └── index.ts │ │ │ ├── customHandle │ │ │ │ ├── CustomHandle.tsx │ │ │ │ └── index.ts │ │ │ ├── headerHandle │ │ │ │ ├── HeaderHandle.tsx │ │ │ │ └── index.ts │ │ │ └── searchHandle │ │ │ │ ├── SearchHandle.tsx │ │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── screens │ │ │ ├── advanced │ │ │ │ ├── BackdropExample.tsx │ │ │ │ ├── CustomBackgroundExample.tsx │ │ │ │ ├── CustomHandleExample.tsx │ │ │ │ ├── CustomThemeExample.tsx │ │ │ │ ├── DynamicSnapPointExample.tsx │ │ │ │ ├── FooterExample.tsx │ │ │ │ ├── KeyboardHandlingExample.tsx │ │ │ │ ├── PullToRefreshExample.tsx │ │ │ │ ├── ShadowExample.tsx │ │ │ │ └── customGestureHandling │ │ │ │ │ ├── CustomGestureHandling.tsx │ │ │ │ │ ├── GestureTranslationContext.tsx │ │ │ │ │ ├── useCustomGestureEventsHandlers.ts │ │ │ │ │ └── useCustomScrollEventsHandlers.tsx │ │ │ ├── basic │ │ │ │ └── BasicExamples.tsx │ │ │ ├── index.ts │ │ │ └── modal │ │ │ │ ├── BackdropExample.tsx │ │ │ │ ├── DetachedExample.tsx │ │ │ │ ├── DynamicSnapPointExample.tsx │ │ │ │ ├── SimpleExample.tsx │ │ │ │ ├── StackExample.tsx │ │ │ │ └── withModalProvider.tsx │ │ ├── types.d.ts │ │ └── utilities │ │ │ ├── createMockData.ts │ │ │ └── transformOrigin.ts │ └── tsconfig.json ├── bare │ ├── android │ │ ├── .project │ │ ├── .settings │ │ │ └── org.eclipse.buildship.core.prefs │ │ ├── app │ │ │ ├── build.gradle │ │ │ ├── debug.keystore │ │ │ ├── proguard-rules.pro │ │ │ └── src │ │ │ │ ├── debug │ │ │ │ ├── AndroidManifest.xml │ │ │ │ └── java │ │ │ │ │ └── dev │ │ │ │ │ └── gorhom │ │ │ │ │ └── bottomsheet │ │ │ │ │ └── ReactNativeFlipper.java │ │ │ │ └── main │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── ic_launcher-playstore.png │ │ │ │ ├── java │ │ │ │ └── dev │ │ │ │ │ └── gorhom │ │ │ │ │ └── bottomsheet │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ ├── MainApplication.java │ │ │ │ │ ├── MainApplicationReactNativeHost.java │ │ │ │ │ ├── components │ │ │ │ │ └── MainComponentsRegistry.java │ │ │ │ │ └── modules │ │ │ │ │ └── MainApplicationTurboModuleManagerDelegate.java │ │ │ │ ├── jni │ │ │ │ ├── Android.mk │ │ │ │ ├── MainApplicationModuleProvider.cpp │ │ │ │ ├── MainApplicationModuleProvider.h │ │ │ │ ├── MainApplicationTurboModuleManagerDelegate.cpp │ │ │ │ ├── MainApplicationTurboModuleManagerDelegate.h │ │ │ │ ├── MainComponentsRegistry.cpp │ │ │ │ ├── MainComponentsRegistry.h │ │ │ │ └── OnLoad.cpp │ │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ └── rn_edit_text_material.xml │ │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── ic_launcher_foreground.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ └── values │ │ │ │ ├── ic_launcher_background.xml │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ └── gradle-wrapper.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ └── settings.gradle │ ├── app.json │ ├── babel.config.js │ ├── index.ts │ ├── ios │ │ ├── .xcode.env │ │ ├── BottomSheetExample.xcodeproj │ │ │ ├── project.pbxproj │ │ │ └── xcshareddata │ │ │ │ └── xcschemes │ │ │ │ └── BottomSheetExample.xcscheme │ │ ├── BottomSheetExample.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── BottomSheetExample │ │ │ ├── AppDelegate.h │ │ │ ├── AppDelegate.mm │ │ │ ├── Images.xcassets │ │ │ │ ├── AppIcon.appiconset │ │ │ │ │ ├── 100.png │ │ │ │ │ ├── 1024.png │ │ │ │ │ ├── 114.png │ │ │ │ │ ├── 120.png │ │ │ │ │ ├── 144.png │ │ │ │ │ ├── 152.png │ │ │ │ │ ├── 167.png │ │ │ │ │ ├── 180.png │ │ │ │ │ ├── 20.png │ │ │ │ │ ├── 29.png │ │ │ │ │ ├── 40.png │ │ │ │ │ ├── 50.png │ │ │ │ │ ├── 57.png │ │ │ │ │ ├── 58.png │ │ │ │ │ ├── 60.png │ │ │ │ │ ├── 72.png │ │ │ │ │ ├── 76.png │ │ │ │ │ ├── 80.png │ │ │ │ │ ├── 87.png │ │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ │ ├── Info.plist │ │ │ ├── LaunchScreen.storyboard │ │ │ └── main.m │ │ ├── Podfile │ │ └── Podfile.lock │ ├── metro.config.js │ ├── package.json │ ├── patches │ │ ├── @react-native-community+blur+3.6.0.patch │ │ ├── react-native-gesture-handler+1.10.3._patch │ │ └── react-native-gesture-handler+2.1.0.patch │ ├── src │ │ ├── App.tsx │ │ ├── Dev.tsx │ │ ├── Perf.tsx │ │ ├── components │ │ │ ├── blurredBackground │ │ │ │ ├── BlurredBackground.tsx │ │ │ │ └── index.ts │ │ │ ├── locationDetails │ │ │ │ ├── LocationDetails.tsx │ │ │ │ └── index.ts │ │ │ ├── locationDetailsHandle │ │ │ │ ├── LocationDetailsHandle.tsx │ │ │ │ └── index.ts │ │ │ ├── locationItem │ │ │ │ ├── LocationItem.tsx │ │ │ │ └── index.ts │ │ │ └── weather │ │ │ │ ├── Weather.tsx │ │ │ │ └── index.ts │ │ ├── screens │ │ │ ├── DummyScreen.tsx │ │ │ ├── index.ts │ │ │ ├── integrations │ │ │ │ ├── MapExample.tsx │ │ │ │ ├── NativeScreensExample.tsx │ │ │ │ ├── NavigatorExample.tsx │ │ │ │ └── ViewPagerExample.tsx │ │ │ └── screens.ts │ │ ├── types.d.ts │ │ └── utilities │ │ │ ├── createMockData.ts │ │ │ ├── index.ts │ │ │ └── transformOrigin.ts │ └── tsconfig.json └── expo │ ├── .gitignore │ ├── app.json │ ├── assets │ ├── adaptive-icon.png │ ├── favicon.png │ ├── icon.png │ └── splash.png │ ├── babel.config.js │ ├── index.ts │ ├── metro.config.js │ ├── package.json │ ├── src │ └── App.tsx │ ├── tsconfig.json │ └── webpack.config.js ├── lint-staged.config.js ├── mock.js ├── mogorhom-dark.png ├── mogorhom-light.png ├── package.json ├── preview.gif ├── scripts └── auto-changelog.js ├── src ├── components │ ├── bottomSheet │ │ ├── BottomSheet.tsx │ │ ├── constants.ts │ │ ├── index.ts │ │ ├── styles.ts │ │ └── types.d.ts │ ├── bottomSheetBackdrop │ │ ├── BottomSheetBackdrop.tsx │ │ ├── constants.ts │ │ ├── index.ts │ │ ├── styles.ts │ │ └── types.d.ts │ ├── bottomSheetBackdropContainer │ │ ├── BottomSheetBackdropContainer.tsx │ │ ├── index.ts │ │ ├── styles.ts │ │ └── types.d.ts │ ├── bottomSheetBackground │ │ ├── BottomSheetBackground.tsx │ │ ├── index.ts │ │ ├── styles.ts │ │ └── types.d.ts │ ├── bottomSheetBackgroundContainer │ │ ├── BottomSheetBackgroundContainer.tsx │ │ ├── index.ts │ │ ├── styles.ts │ │ └── types.d.ts │ ├── bottomSheetContainer │ │ ├── BottomSheetContainer.tsx │ │ ├── index.ts │ │ ├── styles.ts │ │ ├── styles.web.ts │ │ └── types.d.ts │ ├── bottomSheetDebugView │ │ ├── BottomSheetDebugView.tsx │ │ ├── ReText.tsx │ │ ├── index.ts │ │ └── styles.ts │ ├── bottomSheetDraggableView │ │ ├── BottomSheetDraggableView.tsx │ │ ├── index.ts │ │ └── types.d.ts │ ├── bottomSheetFooter │ │ ├── BottomSheetFooter.tsx │ │ ├── index.ts │ │ ├── styles.ts │ │ └── types.d.ts │ ├── bottomSheetFooterContainer │ │ ├── BottomSheetFooterContainer.tsx │ │ └── types.d.ts │ ├── bottomSheetGestureHandlersProvider │ │ ├── BottomSheetGestureHandlersProvider.tsx │ │ ├── index.ts │ │ └── types.d.ts │ ├── bottomSheetHandle │ │ ├── BottomSheetHandle.tsx │ │ ├── index.ts │ │ ├── styles.ts │ │ └── types.d.ts │ ├── bottomSheetHandleContainer │ │ ├── BottomSheetHandleContainer.tsx │ │ ├── index.ts │ │ └── types.d.ts │ ├── bottomSheetModal │ │ ├── BottomSheetModal.tsx │ │ ├── constants.ts │ │ ├── index.ts │ │ └── types.d.ts │ ├── bottomSheetModalProvider │ │ ├── BottomSheetModalProvider.tsx │ │ ├── index.ts │ │ └── types.d.ts │ ├── bottomSheetRefreshControl │ │ ├── BottomSheetRefreshControl.android.tsx │ │ ├── BottomSheetRefreshControl.tsx │ │ └── index.ts │ ├── bottomSheetScrollable │ │ ├── BottomSheetFlashList.tsx │ │ ├── BottomSheetFlatList.tsx │ │ ├── BottomSheetScrollView.tsx │ │ ├── BottomSheetSectionList.tsx │ │ ├── BottomSheetVirtualizedList.tsx │ │ ├── createBottomSheetScrollableComponent.tsx │ │ ├── index.ts │ │ ├── styles.ts │ │ └── types.d.ts │ ├── bottomSheetTextInput │ │ ├── BottomSheetTextInput.tsx │ │ ├── index.ts │ │ └── types.ts │ ├── bottomSheetView │ │ ├── BottomSheetView.tsx │ │ ├── index.ts │ │ ├── styles.ts │ │ └── types.d.ts │ └── touchables │ │ ├── Touchables.ios.tsx │ │ ├── Touchables.tsx │ │ └── index.ts ├── constants.ts ├── contexts │ ├── external.ts │ ├── gesture.ts │ ├── index.ts │ ├── internal.ts │ └── modal │ │ ├── external.ts │ │ └── internal.ts ├── hooks │ ├── index.ts │ ├── useBottomSheet.ts │ ├── useBottomSheetDynamicSnapPoints.ts │ ├── useBottomSheetGestureHandlers.ts │ ├── useBottomSheetInternal.ts │ ├── useBottomSheetModal.ts │ ├── useBottomSheetModalInternal.ts │ ├── useBottomSheetSpringConfigs.ts │ ├── useBottomSheetTimingConfigs.ts │ ├── useGestureEventsHandlersDefault.tsx │ ├── useGestureHandler.ts │ ├── useKeyboard.ts │ ├── useNormalizedSnapPoints.ts │ ├── usePropsValidator.ts │ ├── useReactiveSharedValue.ts │ ├── useScrollEventsHandlersDefault.ts │ ├── useScrollHandler.ts │ ├── useScrollable.ts │ ├── useScrollableSetter.ts │ └── useStableCallback.ts ├── index.ts ├── types.d.ts └── utilities │ ├── animate.ts │ ├── clamp.ts │ ├── easingExp.ts │ ├── getKeyboardAnimationConfigs.ts │ ├── id.ts │ ├── index.ts │ ├── logger.ts │ ├── noop.ts │ ├── normalizeSnapPoint.ts │ ├── snapPoint.ts │ └── validateSnapPoint.ts ├── templates ├── changelog-template.hbs └── release-template.hbs ├── tsconfig.json └── yarn.lock /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 76, 6 | "commit": false, 7 | "contributors": [ 8 | { 9 | "login": "vonovak", 10 | "name": "Vojtech Novak", 11 | "avatar_url": "https://avatars.githubusercontent.com/u/1566403?v=4", 12 | "profile": "https://react-native-training.eu", 13 | "contributions": [ 14 | "code" 15 | ] 16 | }, 17 | { 18 | "login": "kickbk", 19 | "name": "kickbk", 20 | "avatar_url": "https://avatars.githubusercontent.com/u/31323376?v=4", 21 | "profile": "https://github.com/kickbk", 22 | "contributions": [ 23 | "bug", 24 | "test" 25 | ] 26 | } 27 | ], 28 | "contributorsPerLine": 7, 29 | "projectName": "react-native-bottom-sheet", 30 | "projectOwner": "gorhom", 31 | "repoType": "github", 32 | "repoHost": "https://github.com", 33 | "skipCi": true 34 | } 35 | -------------------------------------------------------------------------------- /.auto-changelog: -------------------------------------------------------------------------------- 1 | { 2 | "handlebarsSetup": "./scripts/auto-changelog.js", 3 | "ignoreCommitPattern": "release v", 4 | "startingVersion": "v4.0.0-alpha.0", 5 | "unreleased": false, 6 | "commitLimit": false, 7 | "replaceText": { 8 | "([bB]reaking: )": "", 9 | "([bB]reaking change: )": "", 10 | "(^[fF]eat: )": "", 11 | "(^[fF]eat\\()": "(", 12 | "(^[fF]ix: )": "", 13 | "(^[fF]ix\\()": "(", 14 | "(^[cC]hore: )": "", 15 | "(^[cC]hore\\()": "(", 16 | "(^[dD]ocs: )": "", 17 | "(^[dD]ocs\\()": "(", 18 | "(^[rR]efactor: )": "", 19 | "(^[rR]efactor\\()": "(", 20 | "(^[tT]est: )": "", 21 | "(^[tT]est\\()": "(", 22 | "(^[sS]tyle: )": "", 23 | "(^[sS]tyle\\()": "(", 24 | "(^[pP]erf: )": "", 25 | "(^[pP]erf\\()": "(" 26 | } 27 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | indent_style = space 10 | indent_size = 2 11 | 12 | end_of_line = lf 13 | charset = utf-8 14 | trim_trailing_whitespace = true 15 | insert_final_newline = true 16 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | 3 | # generated by bob 4 | lib/ 5 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['@react-native-community', 'prettier'], 4 | rules: { 5 | 'no-console': ['error', { allow: ['warn', 'error'] }], 6 | 'prettier/prettier': 'error', 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: gorhom 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '[v4] | [v2] Issue title' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | # Bug 11 | 12 | 20 | 21 | ## Environment info 22 | 23 | 26 | 27 | | Library | Version | 28 | | ------------------------------- | ------- | 29 | | @gorhom/bottom-sheet | x.x.x | 30 | | react-native | x.x.x | 31 | | react-native-reanimated | x.x.x | 32 | | react-native-gesture-handler | x.x.x | 33 | 34 | ## Steps To Reproduce 35 | 36 | 42 | 43 | 1. 44 | 2. 45 | 3. 46 | 47 | Describe what you expected to happen: 48 | 49 | 1. 50 | 2. 51 | 52 | ## Reproducible sample code 53 | 54 | 58 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | # Feature Request 11 | 12 | 15 | 16 | ## Why it is needed 17 | 18 | 21 | 22 | ## Possible implementation 23 | 24 | 27 | 28 | ### Code sample 29 | 30 | 33 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Please provide enough information so that others can review your pull request: 2 | 3 | ## Motivation 4 | 5 | Explain the **motivation** for making this change. What existing problem does the pull request solve? 6 | 7 | -------------------------------------------------------------------------------- /.github/workflows/documentation.yml: -------------------------------------------------------------------------------- 1 | name: documentation 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - website 7 | push: 8 | branches: 9 | - website 10 | 11 | jobs: 12 | checks: 13 | if: github.event_name != 'push' 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v2 17 | - uses: actions/setup-node@v2 18 | with: 19 | node-version: '14' 20 | - name: Test Build 21 | run: | 22 | if [ -e yarn.lock ]; then 23 | yarn install --frozen-lockfile 24 | elif [ -e package-lock.json ]; then 25 | npm ci 26 | else 27 | npm i 28 | fi 29 | npm run build 30 | deploy: 31 | if: github.event_name != 'pull_request' 32 | runs-on: ubuntu-latest 33 | steps: 34 | - uses: actions/checkout@v2 35 | - uses: actions/setup-node@v2 36 | with: 37 | node-version: '14' 38 | - uses: webfactory/ssh-agent@v0.5.0 39 | with: 40 | ssh-private-key: ${{ secrets.GH_PAGES_DEPLOY }} 41 | - name: Release to GitHub Pages 42 | env: 43 | USE_SSH: true 44 | GIT_USER: git 45 | CURRENT_BRANCH: website 46 | run: | 47 | git config --global user.email "gorhom@me.com" 48 | git config --global user.name "gorhom" 49 | if [ -e yarn.lock ]; then 50 | yarn install --frozen-lockfile 51 | elif [ -e package-lock.json ]; then 52 | npm ci 53 | else 54 | npm i 55 | fi 56 | npm run deploy -------------------------------------------------------------------------------- /.github/workflows/label-sponsors.yml: -------------------------------------------------------------------------------- 1 | name: Label sponsors 2 | on: 3 | pull_request: 4 | types: [opened] 5 | issues: 6 | types: [opened] 7 | jobs: 8 | build: 9 | name: is-sponsor-label 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: JasonEtco/is-sponsor-label-action@v1.2.0 13 | with: 14 | label: sponsor 15 | env: 16 | GITHUB_TOKEN: ${{ secrets.ACTIONS_TOKEN }} 17 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | on: 2 | issues: 3 | types: [opened, edited] 4 | 5 | jobs: 6 | auto_close_issues: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Checkout 10 | uses: actions/checkout@v1 11 | - name: Automatically close issues that don't follow the issue template 12 | uses: lucasbento/auto-close-issues@v1.0.2 13 | with: 14 | github-token: ${{ secrets.GITHUB_TOKEN }} 15 | issue-close-message: "@${issue.user.login}: hello! :wave:\n\nThis issue is being automatically closed because it does not follow the issue template." # optional property 16 | closed-issues-label: "not-following-issue-template" -------------------------------------------------------------------------------- /.github/workflows/publish-yarn.yaml: -------------------------------------------------------------------------------- 1 | name: Publish Package to Github Packages 2 | on: 3 | release: 4 | types: [created] 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | permissions: 9 | contents: read 10 | packages: write 11 | steps: 12 | - uses: actions/checkout@v3 13 | - uses: actions/setup-node@v3 14 | with: 15 | node-version: '16.x' 16 | registry-url: 'https://npm.pkg.github.com' 17 | scope: '@discord' 18 | - run: yarn 19 | - run: yarn publish 20 | env: 21 | NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 22 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Mark stale issues and pull requests 2 | 3 | on: 4 | schedule: 5 | - cron: '39 9 * * *' 6 | 7 | jobs: 8 | stale: 9 | 10 | runs-on: ubuntu-latest 11 | permissions: 12 | issues: write 13 | pull-requests: write 14 | 15 | steps: 16 | - uses: actions/stale@v5.0.0 17 | with: 18 | repo-token: ${{ secrets.GITHUB_TOKEN }} 19 | stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.' 20 | stale-pr-message: 'This PR is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 10 days.' 21 | close-issue-message: 'This issue was closed because it has been stalled for 5 days with no activity.' 22 | stale-issue-label: 'no-issue-activity' 23 | stale-pr-label: 'no-pr-activity' 24 | days-before-stale: 30 25 | days-before-pr-stale: 30 26 | days-before-close: 5 27 | days-before-pr-close: 10 28 | exempt-assignees: 'gorhom' 29 | exempt-issue-labels: 'sponsor' 30 | exempt-pr-labels: 'sponsor' 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # XDE 6 | .expo/ 7 | 8 | # VSCode 9 | .vscode/ 10 | jsconfig.json 11 | 12 | # Xcode 13 | # 14 | build/ 15 | *.pbxuser 16 | !default.pbxuser 17 | *.mode1v3 18 | !default.mode1v3 19 | *.mode2v3 20 | !default.mode2v3 21 | *.perspectivev3 22 | !default.perspectivev3 23 | xcuserdata 24 | *.xccheckout 25 | *.moved-aside 26 | DerivedData 27 | *.hmap 28 | *.ipa 29 | *.xcuserstate 30 | project.xcworkspace 31 | 32 | # Android/IJ 33 | # 34 | .idea 35 | .gradle 36 | local.properties 37 | android.iml 38 | 39 | # Cocoapods 40 | # 41 | Pods/ 42 | 43 | # node.js 44 | # 45 | node_modules/ 46 | npm-debug.log 47 | yarn-debug.log 48 | yarn-error.log 49 | yarn.lock 50 | example/yarn.lock 51 | 52 | # BUCK 53 | buck-out/ 54 | \.buckd/ 55 | android/app/libs 56 | android/keystores/debug.keystore 57 | 58 | # generated by bob 59 | lib/ 60 | -------------------------------------------------------------------------------- /.huskyrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "hooks": { 3 | "pre-commit": "lint-staged" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .github 2 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "arrowParens": "avoid", 4 | "singleQuote": true, 5 | "tabWidth": 2, 6 | "trailingComma": "es5", 7 | "useTabs": false 8 | } 9 | -------------------------------------------------------------------------------- /.release-it.json: -------------------------------------------------------------------------------- 1 | { 2 | "git": { 3 | "push": true, 4 | "tagName": "v${version}", 5 | "commitMessage": "chore: release v${version}" 6 | }, 7 | "github": { 8 | "release": true 9 | }, 10 | "npm": { 11 | "publish": false 12 | }, 13 | "plugins": { 14 | "@release-it/conventional-changelog": { 15 | "preset": "angular", 16 | "infile": "CHANGELOG.md" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Mo Gorhom 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | plugins: ['react-native-reanimated/plugin'], 4 | }; 5 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | }; 4 | -------------------------------------------------------------------------------- /example/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@gorhom/bottom-sheet-example-app", 3 | "description": "Example app for @gorhom/bottom-sheet", 4 | "version": "0.0.1", 5 | "main": "./src/index", 6 | "react-native": "./src/index", 7 | "private": true, 8 | "peerDependencies": { 9 | "@gorhom/portal": "^1.0.13", 10 | "@gorhom/showcase-template": "^2.1.0", 11 | "@react-native-community/blur": "^3.6.0", 12 | "@react-native-community/masked-view": "0.1.11", 13 | "@react-navigation/bottom-tabs": "^6.0.9", 14 | "@react-navigation/elements": "^1.2.1", 15 | "@react-navigation/material-top-tabs": "^6.0.6", 16 | "@react-navigation/native": "^6.0.6", 17 | "@react-navigation/native-stack": "^6.2.5", 18 | "@react-navigation/stack": "^6.0.11", 19 | "faker": "^4.1.0", 20 | "nanoid": "^3.3.3", 21 | "react": "17.0.2", 22 | "react-native": "0.68.1", 23 | "react-native-gesture-handler": "^2.5.0", 24 | "react-native-maps": "^0.30.1", 25 | "react-native-pager-view": "^5.4.24", 26 | "react-native-reanimated": "^2.9.1", 27 | "react-native-redash": "^16.0.11", 28 | "react-native-safe-area-context": "4.2.4", 29 | "react-native-screens": "^3.15.0", 30 | "react-native-tab-view": "^3.1.1", 31 | "@babel/core": "^7.13.10", 32 | "@babel/runtime": "^7.13.10", 33 | "@types/faker": "^4.1.12", 34 | "@types/react": "^17.0.35", 35 | "@types/react-native": "^0.66.5", 36 | "metro-react-native-babel-preset": "^0.67.0", 37 | "typescript": "^4.2.4" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /example/app/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React, { useMemo } from 'react'; 2 | import { StyleSheet } from 'react-native'; 3 | import { ShowcaseApp } from '@gorhom/showcase-template'; 4 | import { screens as defaultScreens } from './screens'; 5 | import { version, description } from '../../../package.json'; 6 | import { GestureHandlerRootView } from 'react-native-gesture-handler'; 7 | 8 | const author = { 9 | username: 'Mo Gorhom', 10 | url: 'https://gorhom.dev', 11 | }; 12 | 13 | interface AppProps { 14 | screens?: any[]; 15 | } 16 | 17 | export const App = ({ screens: providedScreens }: AppProps) => { 18 | const screens = useMemo( 19 | () => [...defaultScreens, ...(providedScreens ? providedScreens : [])], 20 | [providedScreens] 21 | ); 22 | return ( 23 | 24 | 31 | 32 | ); 33 | }; 34 | 35 | const styles = StyleSheet.create({ 36 | container: { 37 | flex: 1, 38 | flexGrow: 1, 39 | }, 40 | }); 41 | -------------------------------------------------------------------------------- /example/app/src/components/button/Button.tsx: -------------------------------------------------------------------------------- 1 | import React, { memo } from 'react'; 2 | import { ViewStyle, TextStyle } from 'react-native'; 3 | import { ShowcaseButton, ShowcaseLabel } from '@gorhom/showcase-template'; 4 | 5 | interface ButtonProps { 6 | label: string; 7 | labelStyle?: TextStyle; 8 | style?: ViewStyle; 9 | onPress: () => void; 10 | } 11 | 12 | const ButtonComponent = ({ 13 | label, 14 | labelStyle, 15 | style, 16 | onPress, 17 | }: ButtonProps) => ( 18 | 19 | {label} 20 | 21 | ); 22 | 23 | export const Button = memo(ButtonComponent); 24 | -------------------------------------------------------------------------------- /example/app/src/components/button/index.ts: -------------------------------------------------------------------------------- 1 | export { Button } from './Button'; 2 | -------------------------------------------------------------------------------- /example/app/src/components/contactItem/ContactItem.tsx: -------------------------------------------------------------------------------- 1 | import React, { memo, useMemo } from 'react'; 2 | import { Text, StyleSheet, View, TextStyle, ViewStyle } from 'react-native'; 3 | import { TouchableOpacity } from '@gorhom/bottom-sheet'; 4 | 5 | interface ContactItemProps { 6 | title: string; 7 | subTitle?: string; 8 | titleStyle?: TextStyle; 9 | subTitleStyle?: TextStyle; 10 | thumbnailStyle?: ViewStyle; 11 | iconStyle?: ViewStyle; 12 | onPress?: () => void; 13 | } 14 | 15 | const ContactItemComponent = ({ 16 | title, 17 | subTitle, 18 | titleStyle, 19 | subTitleStyle, 20 | thumbnailStyle, 21 | iconStyle, 22 | onPress, 23 | }: ContactItemProps) => { 24 | const ContentWrapper = useMemo( 25 | () => (onPress ? TouchableOpacity : View), 26 | [onPress] 27 | ); 28 | // render 29 | return ( 30 | 31 | 32 | 33 | {title} 34 | {subTitle && ( 35 | {subTitle} 36 | )} 37 | 38 | 39 | 40 | ); 41 | }; 42 | 43 | const styles = StyleSheet.create({ 44 | container: { 45 | flexDirection: 'row', 46 | alignContent: 'center', 47 | marginVertical: 12, 48 | }, 49 | contentContainer: { 50 | flex: 1, 51 | alignSelf: 'center', 52 | marginLeft: 12, 53 | }, 54 | thumbnail: { 55 | width: 46, 56 | height: 46, 57 | borderRadius: 46, 58 | backgroundColor: 'rgba(0, 0, 0, 0.25)', 59 | }, 60 | icon: { 61 | alignSelf: 'center', 62 | width: 24, 63 | height: 24, 64 | borderRadius: 24, 65 | backgroundColor: 'rgba(0, 0, 0, 0.125)', 66 | }, 67 | title: { 68 | color: '#111', 69 | fontSize: 16, 70 | marginBottom: 4, 71 | textTransform: 'capitalize', 72 | }, 73 | 74 | subtitle: { 75 | color: '#666', 76 | fontSize: 14, 77 | textTransform: 'capitalize', 78 | }, 79 | }); 80 | 81 | export const ContactItem = memo(ContactItemComponent); 82 | -------------------------------------------------------------------------------- /example/app/src/components/contactItem/index.ts: -------------------------------------------------------------------------------- 1 | export { ContactItem } from './ContactItem'; 2 | -------------------------------------------------------------------------------- /example/app/src/components/contactList/index.ts: -------------------------------------------------------------------------------- 1 | export { ContactList } from './ContactList'; 2 | export type { ContactListProps } from './ContactList'; 3 | -------------------------------------------------------------------------------- /example/app/src/components/contactList/styles.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | 3 | export const styles = StyleSheet.create({ 4 | sectionHeaderContainer: { 5 | paddingTop: 24, 6 | paddingBottom: 6, 7 | backgroundColor: 'white', 8 | }, 9 | sectionHeaderTitle: { 10 | fontSize: 16, 11 | textTransform: 'uppercase', 12 | color: 'black', 13 | }, 14 | container: { 15 | overflow: 'visible', 16 | flex: 1, 17 | }, 18 | contentContainer: { 19 | paddingHorizontal: 16, 20 | overflow: 'visible', 21 | }, 22 | }); 23 | -------------------------------------------------------------------------------- /example/app/src/components/contactList/styles.web.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | 3 | export const styles = StyleSheet.create({ 4 | sectionHeaderContainer: { 5 | paddingTop: 24, 6 | paddingBottom: 6, 7 | backgroundColor: 'white', 8 | }, 9 | sectionHeaderTitle: { 10 | fontSize: 16, 11 | textTransform: 'uppercase', 12 | }, 13 | container: { 14 | flex: 1, 15 | paddingHorizontal: 16, 16 | }, 17 | contentContainer: { 18 | paddingHorizontal: 16, 19 | }, 20 | }); 21 | -------------------------------------------------------------------------------- /example/app/src/components/customBackground/CustomBackground.tsx: -------------------------------------------------------------------------------- 1 | import React, { memo, useMemo } from 'react'; 2 | import { StyleSheet } from 'react-native'; 3 | import { BottomSheetBackgroundProps } from '@gorhom/bottom-sheet'; 4 | import Animated, { 5 | useAnimatedStyle, 6 | interpolateColor, 7 | } from 'react-native-reanimated'; 8 | 9 | interface CustomBackgroundProps extends BottomSheetBackgroundProps {} 10 | 11 | const CustomBackgroundComponent: React.FC = ({ 12 | style, 13 | animatedIndex, 14 | }) => { 15 | //#region styles 16 | const containerAnimatedStyle = useAnimatedStyle(() => ({ 17 | // @ts-ignore 18 | backgroundColor: interpolateColor( 19 | animatedIndex.value, 20 | [0, 1], 21 | ['#ffffff', '#a8b5eb'] 22 | ), 23 | })); 24 | const containerStyle = useMemo( 25 | () => [styles.container, style, containerAnimatedStyle], 26 | [style, containerAnimatedStyle] 27 | ); 28 | //#endregion 29 | 30 | // render 31 | return ; 32 | }; 33 | 34 | export const CustomBackground = memo(CustomBackgroundComponent); 35 | 36 | const styles = StyleSheet.create({ 37 | container: { 38 | borderTopLeftRadius: 20, 39 | borderTopRightRadius: 20, 40 | backgroundColor: '#fff', 41 | }, 42 | }); 43 | -------------------------------------------------------------------------------- /example/app/src/components/customBackground/index.ts: -------------------------------------------------------------------------------- 1 | export { CustomBackground } from './CustomBackground'; 2 | -------------------------------------------------------------------------------- /example/app/src/components/customFooter/index.ts: -------------------------------------------------------------------------------- 1 | export { CustomFooter } from './CustomFooter'; 2 | -------------------------------------------------------------------------------- /example/app/src/components/customHandle/index.ts: -------------------------------------------------------------------------------- 1 | export { CustomHandle } from './CustomHandle'; 2 | -------------------------------------------------------------------------------- /example/app/src/components/headerHandle/HeaderHandle.tsx: -------------------------------------------------------------------------------- 1 | import React, { memo } from 'react'; 2 | import { StyleSheet, Text } from 'react-native'; 3 | import { 4 | BottomSheetHandle, 5 | BottomSheetHandleProps, 6 | } from '@gorhom/bottom-sheet'; 7 | 8 | interface HeaderHandleProps extends BottomSheetHandleProps { 9 | children?: string | React.ReactNode | React.ReactNode[]; 10 | } 11 | 12 | const HeaderHandleComponent = ({ children, ...rest }: HeaderHandleProps) => { 13 | return ( 14 | 19 | {typeof children === 'string' ? ( 20 | {children} 21 | ) : ( 22 | children 23 | )} 24 | 25 | ); 26 | }; 27 | 28 | const styles = StyleSheet.create({ 29 | container: { 30 | paddingBottom: 12, 31 | paddingHorizontal: 16, 32 | borderBottomWidth: 1, 33 | borderBottomColor: 'rgba(0,0,0,0.075)', 34 | zIndex: 99999, 35 | }, 36 | title: { 37 | marginTop: 16, 38 | fontSize: 20, 39 | lineHeight: 20, 40 | textAlign: 'center', 41 | fontWeight: 'bold', 42 | color: 'black', 43 | }, 44 | indicator: { 45 | height: 4, 46 | opacity: 0.5, 47 | }, 48 | }); 49 | 50 | export const HeaderHandle = memo(HeaderHandleComponent); 51 | -------------------------------------------------------------------------------- /example/app/src/components/headerHandle/index.ts: -------------------------------------------------------------------------------- 1 | export { HeaderHandle } from './HeaderHandle'; 2 | -------------------------------------------------------------------------------- /example/app/src/components/searchHandle/SearchHandle.tsx: -------------------------------------------------------------------------------- 1 | import React, { memo, useState, useCallback } from 'react'; 2 | import { 3 | View, 4 | StyleSheet, 5 | Dimensions, 6 | NativeSyntheticEvent, 7 | TextInputChangeEventData, 8 | } from 'react-native'; 9 | import { 10 | BottomSheetTextInput, 11 | BottomSheetHandleProps, 12 | } from '@gorhom/bottom-sheet'; 13 | import { useShowcaseTheme } from '@gorhom/showcase-template'; 14 | 15 | const { width: SCREEN_WIDTH } = Dimensions.get('screen'); 16 | export const SEARCH_HANDLE_HEIGHT = 69; 17 | 18 | interface SearchHandleProps extends BottomSheetHandleProps { 19 | initialValue?: string; 20 | onChange?: (text: string) => void; 21 | } 22 | 23 | const SearchHandleComponent = ({ 24 | initialValue = '', 25 | onChange, 26 | }: SearchHandleProps) => { 27 | // state 28 | const [value, setValue] = useState(initialValue); 29 | 30 | // hooks 31 | const { colors } = useShowcaseTheme(); 32 | 33 | // callbacks 34 | const handleInputChange = useCallback( 35 | ({ 36 | nativeEvent: { text }, 37 | }: NativeSyntheticEvent) => { 38 | setValue(text); 39 | 40 | if (onChange) { 41 | onChange(text); 42 | } 43 | }, 44 | [onChange] 45 | ); 46 | 47 | // render 48 | return ( 49 | 50 | 51 | 59 | 60 | ); 61 | }; 62 | 63 | export const styles = StyleSheet.create({ 64 | container: { 65 | paddingHorizontal: 16, 66 | paddingVertical: 5, 67 | }, 68 | indicator: { 69 | alignSelf: 'center', 70 | width: (8 * SCREEN_WIDTH) / 100, 71 | height: 5, 72 | borderRadius: 4, 73 | backgroundColor: 'rgba(0, 0, 0, 0.5)', 74 | }, 75 | input: { 76 | marginTop: 8, 77 | marginBottom: 10, 78 | borderRadius: 10, 79 | fontSize: 16, 80 | lineHeight: 20, 81 | padding: 8, 82 | backgroundColor: 'rgba(151, 151, 151, 0.25)', 83 | }, 84 | }); 85 | 86 | export const SearchHandle = memo(SearchHandleComponent); 87 | -------------------------------------------------------------------------------- /example/app/src/components/searchHandle/index.ts: -------------------------------------------------------------------------------- 1 | export { SearchHandle, SEARCH_HANDLE_HEIGHT } from './SearchHandle'; 2 | -------------------------------------------------------------------------------- /example/app/src/index.ts: -------------------------------------------------------------------------------- 1 | export { App } from './App'; 2 | export { default as ModalBackdropExample } from './screens/modal/BackdropExample'; 3 | export { withModalProvider } from './screens/modal/withModalProvider'; 4 | export { Button } from './components/button'; 5 | export { ContactList } from './components/contactList'; 6 | export { ContactItem } from './components/contactItem'; 7 | export { SearchHandle, SEARCH_HANDLE_HEIGHT } from './components/searchHandle'; 8 | export * from './utilities/createMockData'; 9 | -------------------------------------------------------------------------------- /example/app/src/screens/advanced/CustomBackgroundExample.tsx: -------------------------------------------------------------------------------- 1 | import React, { useCallback, useMemo, useRef } from 'react'; 2 | import { View, StyleSheet } from 'react-native'; 3 | import BottomSheet from '@gorhom/bottom-sheet'; 4 | import { CustomBackground } from '../../components/customBackground'; 5 | import { Button } from '../../components/button'; 6 | import { ContactList } from '../../components/contactList'; 7 | import { HeaderHandle } from '../../components/headerHandle'; 8 | 9 | const CustomBackgroundExample = () => { 10 | // hooks 11 | const bottomSheetRef = useRef(null); 12 | 13 | // variables 14 | const snapPoints = useMemo(() => [150, 450], []); 15 | 16 | // callbacks 17 | const handleSnapPress = useCallback(index => { 18 | bottomSheetRef.current?.snapToIndex(index); 19 | }, []); 20 | const handleExpandPress = useCallback(() => { 21 | bottomSheetRef.current?.expand(); 22 | }, []); 23 | const handleCollapsePress = useCallback(() => { 24 | bottomSheetRef.current?.collapse(); 25 | }, []); 26 | const handleClosePress = useCallback(() => { 27 | bottomSheetRef.current?.close(); 28 | }, []); 29 | 30 | // render 31 | const renderHeaderHandle = useCallback( 32 | props => , 33 | [] 34 | ); 35 | return ( 36 | 37 |