├── .editorconfig ├── .eslintignore ├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ └── config.yml ├── actions │ └── setup │ │ └── action.yml └── workflows │ └── ci.yml ├── .gitignore ├── .nvmrc ├── .prettierignore ├── .watchmanconfig ├── .yarn ├── plugins │ └── @yarnpkg │ │ ├── plugin-interactive-tools.cjs │ │ └── plugin-workspace-tools.cjs └── releases │ └── yarn-3.6.1.cjs ├── .yarnrc.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── TrueSheet.podspec ├── android ├── .editorconfig ├── build.gradle ├── gradle.properties └── src │ └── main │ ├── AndroidManifest.xml │ ├── AndroidManifestNew.xml │ └── java │ └── com │ └── lodev09 │ └── truesheet │ ├── TrueSheetDialog.kt │ ├── TrueSheetEvent.kt │ ├── TrueSheetPackage.kt │ ├── TrueSheetView.kt │ ├── TrueSheetViewManager.kt │ ├── TrueSheetViewModule.kt │ └── core │ ├── KeyboardManager.kt │ ├── RootSheetView.kt │ └── Utils.kt ├── babel.config.js ├── docs ├── .gitattributes ├── .gitignore ├── README.md ├── babel.config.js ├── blog │ ├── 2024 │ │ ├── img │ │ │ └── auto-sizing.gif │ │ ├── release-0-10.mdx │ │ └── welcome.mdx │ └── authors.yml ├── docs │ ├── guides │ │ ├── _category_.json │ │ ├── dimming │ │ │ ├── dimming.gif │ │ │ └── dimming.mdx │ │ ├── edge2edge.mdx │ │ ├── footer.mdx │ │ ├── global-methods.mdx │ │ ├── jest.mdx │ │ ├── onmount │ │ │ ├── onmount.gif │ │ │ └── onmount.mdx │ │ ├── reanimated │ │ │ ├── reanimated.gif │ │ │ └── reanimated.mdx │ │ ├── resizing │ │ │ ├── resizing.gif │ │ │ └── resizing.mdx │ │ ├── scrolling.mdx │ │ └── stacking │ │ │ ├── stacking.gif │ │ │ └── stacking.mdx │ ├── install.mdx │ ├── intro.mdx │ ├── reference │ │ ├── 01-props.mdx │ │ ├── 02-methods.mdx │ │ ├── 03-types.mdx │ │ └── _category_.json │ ├── troubleshooting.mdx │ └── usage.mdx ├── docusaurus.config.ts ├── package.json ├── sidebars.ts ├── src │ ├── css │ │ └── custom.css │ ├── pages │ │ └── contributing.mdx │ └── theme │ │ └── DocSidebar │ │ └── Desktop │ │ └── Content │ │ └── index.tsx ├── static │ ├── .nojekyll │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ ├── img │ │ ├── logo.png │ │ ├── logo.svg │ │ ├── preview-2.gif │ │ └── preview.gif │ ├── robots.txt │ └── site.webmanifest └── tsconfig.json ├── example ├── .bundle │ └── config ├── .watchmanconfig ├── Gemfile ├── README.md ├── android │ ├── app │ │ ├── build.gradle │ │ ├── debug.keystore │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── truesheet │ │ │ │ └── example │ │ │ │ ├── MainActivity.kt │ │ │ │ └── MainApplication.kt │ │ │ └── res │ │ │ ├── drawable │ │ │ └── rn_edit_text_material.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ └── values │ │ │ ├── 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.js ├── ios │ ├── .xcode.env │ ├── Podfile │ ├── Podfile.lock │ ├── TrueSheetExample.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── TrueSheetExample.xcscheme │ ├── TrueSheetExample.xcworkspace │ │ └── contents.xcworkspacedata │ └── TrueSheetExample │ │ ├── AppDelegate.swift │ │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ │ ├── Info.plist │ │ ├── LaunchScreen.storyboard │ │ └── PrivacyInfo.xcprivacy ├── jest.config.js ├── metro.config.js ├── package.json ├── react-native.config.js └── src │ ├── App.tsx │ ├── components │ ├── Button.tsx │ ├── DemoContent.tsx │ ├── Footer.tsx │ ├── Input.tsx │ ├── Spacer.tsx │ ├── index.ts │ └── sheets │ │ ├── BasicSheet.tsx │ │ ├── BlankSheet.tsx │ │ ├── FlatListSheet.tsx │ │ ├── GestureSheet.tsx │ │ ├── PromptSheet.tsx │ │ ├── ScrollViewSheet.tsx │ │ └── index.ts │ ├── hooks │ ├── index.ts │ ├── useAppNavigation.ts │ └── useDragChangeHandler.ts │ ├── screens │ ├── ChildScreen.tsx │ ├── MapScreen.tsx │ ├── NavigationScreen.tsx │ └── index.ts │ ├── types.ts │ └── utils │ ├── constants.ts │ ├── index.ts │ ├── random.ts │ └── times.ts ├── ios ├── .swift-version ├── .swiftformat ├── .swiftlint.yml ├── Extensions │ ├── UIBlurEffect+withTint.swift │ ├── UIView+pinTo.swift │ └── UIViewController+detentForSize.swift ├── TrueSheet-Bridging-Header.h ├── TrueSheetEvent.swift ├── TrueSheetView.swift ├── TrueSheetViewController.swift ├── TrueSheetViewManager.m ├── TrueSheetViewManager.swift └── Utils │ ├── Logger.swift │ └── Promise.swift ├── lefthook.yml ├── lib ├── commonjs │ ├── TrueSheet.js │ ├── TrueSheet.js.map │ ├── TrueSheet.types.js │ ├── TrueSheet.types.js.map │ ├── TrueSheetFooter.js │ ├── TrueSheetFooter.js.map │ ├── TrueSheetGrabber.js │ ├── TrueSheetGrabber.js.map │ ├── TrueSheetModule.js │ ├── TrueSheetModule.js.map │ ├── __mocks__ │ │ ├── index.js │ │ └── index.js.map │ ├── index.js │ └── index.js.map ├── module │ ├── TrueSheet.js │ ├── TrueSheet.js.map │ ├── TrueSheet.types.js │ ├── TrueSheet.types.js.map │ ├── TrueSheetFooter.js │ ├── TrueSheetFooter.js.map │ ├── TrueSheetGrabber.js │ ├── TrueSheetGrabber.js.map │ ├── TrueSheetModule.js │ ├── TrueSheetModule.js.map │ ├── __mocks__ │ │ ├── index.js │ │ └── index.js.map │ ├── index.js │ └── index.js.map └── typescript │ ├── commonjs │ ├── package.json │ └── src │ │ ├── TrueSheet.d.ts │ │ ├── TrueSheet.d.ts.map │ │ ├── TrueSheet.types.d.ts │ │ ├── TrueSheet.types.d.ts.map │ │ ├── TrueSheetFooter.d.ts │ │ ├── TrueSheetFooter.d.ts.map │ │ ├── TrueSheetGrabber.d.ts │ │ ├── TrueSheetGrabber.d.ts.map │ │ ├── TrueSheetModule.d.ts │ │ ├── TrueSheetModule.d.ts.map │ │ ├── __tests__ │ │ ├── index.test.d.ts │ │ └── index.test.d.ts.map │ │ ├── index.d.ts │ │ └── index.d.ts.map │ └── module │ ├── package.json │ └── src │ ├── TrueSheet.d.ts │ ├── TrueSheet.d.ts.map │ ├── TrueSheet.types.d.ts │ ├── TrueSheet.types.d.ts.map │ ├── TrueSheetFooter.d.ts │ ├── TrueSheetFooter.d.ts.map │ ├── TrueSheetGrabber.d.ts │ ├── TrueSheetGrabber.d.ts.map │ ├── TrueSheetModule.d.ts │ ├── TrueSheetModule.d.ts.map │ ├── __tests__ │ ├── index.test.d.ts │ └── index.test.d.ts.map │ ├── index.d.ts │ └── index.d.ts.map ├── package.json ├── scripts ├── clean.sh ├── ktlint.sh └── swiftlint.sh ├── src ├── TrueSheet.tsx ├── TrueSheet.types.ts ├── TrueSheetFooter.tsx ├── TrueSheetGrabber.tsx ├── TrueSheetModule.ts ├── __mocks__ │ └── index.js ├── __tests__ │ └── index.test.tsx └── index.ts ├── tsconfig.build.json ├── tsconfig.json ├── turbo.json └── yarn.lock /.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 | lib 2 | build 3 | src/__mocks__ 4 | docs/build 5 | docs/.docusaurus 6 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | # specific for windows script files 3 | *.bat text eol=crlf -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: lodev09 4 | buy_me_a_coffee: lodev09 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: 🐛 Bug report 2 | description: Report a reproducible bug or regression in this library. 3 | labels: [bug] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | # Bug report 9 | 10 | 👋 Hi! 11 | 12 | **Please fill the following carefully before opening a new issue ❗** 13 | *(Your issue may be closed if it doesn't provide the required pieces of information)* 14 | - type: checkboxes 15 | attributes: 16 | label: Before submitting a new issue 17 | description: Please perform simple checks first. 18 | options: 19 | - label: I tested using the latest version of the library, as the bug might be already fixed. 20 | required: true 21 | - label: I tested using a [supported version](https://github.com/reactwg/react-native-releases/blob/main/docs/support.md) of react native. 22 | required: true 23 | - label: I checked for possible duplicate issues, with possible answers. 24 | required: true 25 | - type: textarea 26 | id: summary 27 | attributes: 28 | label: Bug summary 29 | description: | 30 | Provide a clear and concise description of what the bug is. 31 | If needed, you can also provide other samples: error messages / stack traces, screenshots, gifs, etc. 32 | validations: 33 | required: true 34 | - type: input 35 | id: library-version 36 | attributes: 37 | label: Library version 38 | description: What version of the library are you using? 39 | placeholder: "x.x.x" 40 | validations: 41 | required: true 42 | - type: textarea 43 | id: react-native-info 44 | attributes: 45 | label: Environment info 46 | description: Run `react-native info` in your terminal and paste the results here. 47 | validations: 48 | required: true 49 | - type: textarea 50 | id: steps-to-reproduce 51 | attributes: 52 | label: Steps to reproduce 53 | description: | 54 | You must provide a clear list of steps and code to reproduce the problem. 55 | value: | 56 | 1. … 57 | 2. … 58 | validations: 59 | required: true 60 | - type: input 61 | id: reproducible-example 62 | attributes: 63 | label: Reproducible example repository 64 | description: Please provide a link to a repository on GitHub with a reproducible example. 65 | validations: 66 | required: true 67 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Feature Request 💡 4 | url: https://github.com/lodev09/react-native-true-sheet/discussions/new?category=ideas 5 | about: If you have a feature request, please create a new discussion on GitHub. 6 | - name: Discussions on GitHub 💬 7 | url: https://github.com/lodev09/react-native-true-sheet/discussions 8 | about: If this library works as promised but you need help, please ask questions there. 9 | -------------------------------------------------------------------------------- /.github/actions/setup/action.yml: -------------------------------------------------------------------------------- 1 | name: Setup 2 | description: Setup Node.js and install dependencies 3 | 4 | runs: 5 | using: composite 6 | steps: 7 | - name: Setup Node.js 8 | uses: actions/setup-node@v4 9 | with: 10 | node-version-file: .nvmrc 11 | 12 | - name: Restore dependencies 13 | id: yarn-cache 14 | uses: actions/cache/restore@v4 15 | with: 16 | path: | 17 | **/node_modules 18 | .yarn/install-state.gz 19 | key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}-${{ hashFiles('**/package.json', '!node_modules/**') }} 20 | restore-keys: | 21 | ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} 22 | ${{ runner.os }}-yarn- 23 | 24 | - name: Install dependencies 25 | if: steps.yarn-cache.outputs.cache-hit != 'true' 26 | run: yarn install --immutable 27 | shell: bash 28 | 29 | - name: Cache dependencies 30 | if: steps.yarn-cache.outputs.cache-hit != 'true' 31 | uses: actions/cache/save@v4 32 | with: 33 | path: | 34 | **/node_modules 35 | .yarn/install-state.gz 36 | key: ${{ steps.yarn-cache.outputs.cache-primary-key }} 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # XDE 6 | .expo/ 7 | 8 | # Editors 9 | *.sublime-* 10 | .vscode/ 11 | jsconfig.json 12 | 13 | # Xcode 14 | # 15 | build/ 16 | *.pbxuser 17 | !default.pbxuser 18 | *.mode1v3 19 | !default.mode1v3 20 | *.mode2v3 21 | !default.mode2v3 22 | *.perspectivev3 23 | !default.perspectivev3 24 | xcuserdata 25 | *.xccheckout 26 | *.moved-aside 27 | DerivedData 28 | *.hmap 29 | *.ipa 30 | *.xcuserstate 31 | project.xcworkspace 32 | 33 | # Android/IJ 34 | # 35 | .classpath 36 | .cxx 37 | .gradle 38 | .idea 39 | .project 40 | .settings 41 | local.properties 42 | android.iml 43 | 44 | # Cocoapods 45 | # 46 | example/ios/Pods 47 | 48 | # Ruby 49 | example/vendor/ 50 | 51 | # node.js 52 | # 53 | node_modules/ 54 | npm-debug.log 55 | yarn-debug.log 56 | yarn-error.log 57 | 58 | # BUCK 59 | buck-out/ 60 | \.buckd/ 61 | android/app/libs 62 | android/keystores/debug.keystore 63 | 64 | # Yarn 65 | .yarn/* 66 | !.yarn/patches 67 | !.yarn/plugins 68 | !.yarn/releases 69 | !.yarn/sdks 70 | !.yarn/versions 71 | 72 | # Expo 73 | .expo/ 74 | 75 | # Turborepo 76 | .turbo/ 77 | 78 | # React Native Codegen 79 | ios/generated 80 | android/generated 81 | 82 | # Docs 83 | .vercel 84 | 85 | # Misc 86 | .xcode.env.local 87 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v18 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | lib 2 | build 3 | src/__mocks__ 4 | docs/build 5 | docs/.docusaurus 6 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | nmHoistingLimits: workspaces 3 | 4 | plugins: 5 | - path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs 6 | spec: "@yarnpkg/plugin-interactive-tools" 7 | - path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs 8 | spec: "@yarnpkg/plugin-workspace-tools" 9 | 10 | yarnPath: .yarn/releases/yarn-3.6.1.cjs 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 lodev09 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Native True Sheet 2 | 3 | [![CI](https://github.com/lodev09/react-native-true-sheet/actions/workflows/ci.yml/badge.svg)](https://github.com/lodev09/react-native-true-sheet/actions/workflows/ci.yml) 4 | [![Maintainability](https://api.codeclimate.com/v1/badges/0bd49973c6c61d85e2be/maintainability)](https://codeclimate.com/github/lodev09/react-native-true-sheet/maintainability) 5 | [![NPM Downloads](https://img.shields.io/npm/d18m/%40lodev09%2Freact-native-true-sheet)](https://www.npmjs.com/package/@lodev09/react-native-true-sheet) 6 | 7 | The true native bottom sheet experience for your React Native Apps. 💩 8 | 9 | React Native True Sheet - IOSReact Native True Sheet - Android 10 | 11 | ## Features 12 | 13 | * Implemented in the native realm. 14 | * Clean, fast, and lightweight. 15 | * Asynchronus `ref` [methods](https://sheet.lodev09.com/reference/methods#ref-methods). 16 | * Bonus! [Blur](https://sheet.lodev09.com/reference/types#blurtint) support on IOS 😎 17 | 18 | ## Installation 19 | 20 | You can install the package by using either `yarn` or `npm`. 21 | 22 | ```sh 23 | yarn add @lodev09/react-native-true-sheet 24 | ``` 25 | ```sh 26 | npm i @lodev09/react-native-true-sheet 27 | ``` 28 | 29 | Next, run the following to install it on IOS. 30 | 31 | ```sh 32 | cd ios && pod install 33 | ``` 34 | 35 | ## Documentation 36 | 37 | - [Example](example) 38 | - [Guides](https://sheet.lodev09.com/category/guides) 39 | - [Reference](https://sheet.lodev09.com/category/reference) 40 | - [Troubleshooting](https://sheet.lodev09.com/troubleshooting) 41 | 42 | ## Usage 43 | 44 | ```tsx 45 | import { TrueSheet } from "@lodev09/react-native-true-sheet" 46 | 47 | export const App = () => { 48 | const sheet = useRef(null) 49 | 50 | // Present the sheet ✅ 51 | const present = async () => { 52 | await sheet.current?.present() 53 | console.log('horray! sheet has been presented 💩') 54 | } 55 | 56 | // Dismiss the sheet ✅ 57 | const dismiss = async () => { 58 | await sheet.current?.dismiss() 59 | console.log('Bye bye 👋') 60 | } 61 | 62 | return ( 63 | 64 |