├── .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 | [](https://github.com/lodev09/react-native-true-sheet/actions/workflows/ci.yml)
4 | [](https://codeclimate.com/github/lodev09/react-native-true-sheet/maintainability)
5 | [](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 | 
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 |
65 |
70 |
71 |
72 |
73 | )
74 | }
75 | ```
76 |
77 | ## Contributing
78 |
79 | See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
80 |
81 | ## License
82 |
83 | [MIT](LICENSE)
84 |
85 | ---
86 |
87 | Made with ❤️ by [@lodev09](http://linkedin.com/in/lodev09/)
88 |
--------------------------------------------------------------------------------
/TrueSheet.podspec:
--------------------------------------------------------------------------------
1 | require "json"
2 |
3 | package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4 | folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
5 |
6 | Pod::Spec.new do |s|
7 | s.name = "TrueSheet"
8 | s.version = package["version"]
9 | s.summary = package["description"]
10 | s.homepage = package["homepage"]
11 | s.license = package["license"]
12 | s.authors = package["author"]
13 |
14 | s.platforms = { :ios => "13.4" }
15 | s.source = { :git => "https://github.com/lodev09/react-native-true-sheet.git", :tag => "#{s.version}" }
16 |
17 | s.source_files = "ios/**/*.{h,m,mm,swift}"
18 |
19 | if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
20 | s.pod_target_xcconfig = {
21 | # Detect if new arch is enabled in Swift code
22 | "OTHER_SWIFT_FLAGS" => "-DRCT_NEW_ARCH_ENABLED"
23 | }
24 | end
25 |
26 | # Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
27 | # See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
28 | if respond_to?(:install_modules_dependencies, true)
29 | install_modules_dependencies(s)
30 | else
31 | s.dependency "React-Core"
32 |
33 | # Don't install the dependencies when we run `pod install` in the old architecture.
34 | if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
35 | s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
36 | s.pod_target_xcconfig = s.pod_target_xcconfig | {
37 | "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
38 | "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
39 | "CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
40 | }
41 | s.dependency "React-RCTFabric"
42 | s.dependency "React-Codegen"
43 | s.dependency "RCT-Folly"
44 | s.dependency "RCTRequired"
45 | s.dependency "RCTTypeSafety"
46 | s.dependency "ReactCommon/turbomodule/core"
47 | end
48 | end
49 | end
50 |
--------------------------------------------------------------------------------
/android/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.{kt,kts}]
2 | indent_style=space
3 | indent_size=2
4 | continuation_indent_size=4
5 | insert_final_newline=true
6 | max_line_length=140
7 | ktlint_code_style=android_studio
8 | ktlint_standard=enabled
9 | ktlint_experimental=enabled
10 | ktlint_standard_filename=disabled # dont require PascalCase filenames
11 | ktlint_standard_no-wildcard-imports=disabled # allow .* imports
12 | ktlint_function_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than=5
13 | ktlint_function_signature_body_expression_wrapping=multiline
14 | ij_kotlin_allow_trailing_comma_on_call_site=false
15 | ij_kotlin_allow_trailing_comma=false
16 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.getExtOrDefault = {name ->
3 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['TrueSheet_' + name]
4 | }
5 |
6 | repositories {
7 | google()
8 | mavenCentral()
9 | }
10 |
11 | dependencies {
12 | classpath "com.android.tools.build:gradle:8.7.2"
13 | // noinspection DifferentKotlinGradleVersion
14 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
15 | }
16 | }
17 |
18 |
19 | def isNewArchitectureEnabled() {
20 | return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
21 | }
22 |
23 | apply plugin: "com.android.library"
24 | apply plugin: "kotlin-android"
25 |
26 | // TODO:
27 | // When running example, comment this block!
28 | // Not sure what's going on but we are getting multiple definition error when this is enabled.
29 | if (isNewArchitectureEnabled()) {
30 | apply plugin: "com.facebook.react"
31 | }
32 |
33 | def getExtOrIntegerDefault(name) {
34 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["TrueSheet_" + name]).toInteger()
35 | }
36 |
37 | def supportsNamespace() {
38 | def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
39 | def major = parsed[0].toInteger()
40 | def minor = parsed[1].toInteger()
41 |
42 | // Namespace support was added in 7.3.0
43 | return (major == 7 && minor >= 3) || major >= 8
44 | }
45 |
46 | android {
47 | if (supportsNamespace()) {
48 | namespace "com.lodev09.truesheet"
49 |
50 | sourceSets {
51 | main {
52 | manifest.srcFile "src/main/AndroidManifestNew.xml"
53 | }
54 | }
55 | }
56 |
57 | compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
58 |
59 | defaultConfig {
60 | minSdkVersion getExtOrIntegerDefault("minSdkVersion")
61 | targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
62 |
63 | }
64 |
65 | buildTypes {
66 | release {
67 | minifyEnabled false
68 | }
69 | }
70 |
71 | lintOptions {
72 | disable "GradleCompatible"
73 | }
74 |
75 | compileOptions {
76 | sourceCompatibility JavaVersion.VERSION_1_8
77 | targetCompatibility JavaVersion.VERSION_1_8
78 | }
79 | }
80 |
81 | repositories {
82 | mavenCentral()
83 | google()
84 | }
85 |
86 | def kotlin_version = getExtOrDefault("kotlinVersion")
87 |
88 | dependencies {
89 | implementation "com.facebook.react:react-android"
90 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
91 | implementation "com.google.android.material:material:1.12.0"
92 | }
93 |
94 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | TrueSheet_kotlinVersion=2.0.21
2 | TrueSheet_minSdkVersion=24
3 | TrueSheet_targetSdkVersion=34
4 | TrueSheet_compileSdkVersion=35
5 | TrueSheet_ndkVersion=27.1.12297006
6 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifestNew.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/android/src/main/java/com/lodev09/truesheet/TrueSheetEvent.kt:
--------------------------------------------------------------------------------
1 | package com.lodev09.truesheet
2 |
3 | import com.facebook.react.bridge.Arguments
4 | import com.facebook.react.bridge.WritableMap
5 | import com.facebook.react.uimanager.events.Event
6 |
7 | class TrueSheetEvent(surfaceId: Int, viewId: Int, private val name: String, private val data: WritableMap?) :
8 | Event(surfaceId, viewId) {
9 | override fun getEventName() = name
10 | override fun getEventData(): WritableMap = data ?: Arguments.createMap()
11 |
12 | companion object {
13 | const val MOUNT = "topMount"
14 | const val PRESENT = "topPresent"
15 | const val DISMISS = "topDismiss"
16 | const val SIZE_CHANGE = "topSizeChange"
17 | const val DRAG_BEGIN = "topDragBegin"
18 | const val DRAG_CHANGE = "topDragChange"
19 | const val DRAG_END = "topDragEnd"
20 | const val CONTAINER_SIZE_CHANGE = "topContainerSizeChange"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/android/src/main/java/com/lodev09/truesheet/TrueSheetPackage.kt:
--------------------------------------------------------------------------------
1 | package com.lodev09.truesheet
2 |
3 | import com.facebook.react.ReactPackage
4 | import com.facebook.react.bridge.NativeModule
5 | import com.facebook.react.bridge.ReactApplicationContext
6 | import com.facebook.react.uimanager.ViewManager
7 |
8 | class TrueSheetPackage : ReactPackage {
9 | override fun createNativeModules(reactContext: ReactApplicationContext): List = listOf(TrueSheetViewModule(reactContext))
10 |
11 | override fun createViewManagers(reactContext: ReactApplicationContext): List> = listOf(TrueSheetViewManager())
12 | }
13 |
--------------------------------------------------------------------------------
/android/src/main/java/com/lodev09/truesheet/TrueSheetViewModule.kt:
--------------------------------------------------------------------------------
1 | package com.lodev09.truesheet
2 |
3 | import android.util.Log
4 | import com.facebook.react.bridge.Promise
5 | import com.facebook.react.bridge.ReactApplicationContext
6 | import com.facebook.react.bridge.ReactContextBaseJavaModule
7 | import com.facebook.react.bridge.ReactMethod
8 | import com.facebook.react.bridge.UiThreadUtil
9 | import com.facebook.react.module.annotations.ReactModule
10 | import com.facebook.react.uimanager.UIManagerHelper
11 | import com.lodev09.truesheet.core.Utils
12 |
13 | @ReactModule(name = TrueSheetViewModule.TAG)
14 | class TrueSheetViewModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
15 | override fun getName(): String = TAG
16 |
17 | private fun withTrueSheetView(tag: Int, closure: (trueSheetView: TrueSheetView) -> Unit) {
18 | UiThreadUtil.runOnUiThread {
19 | try {
20 | val manager = UIManagerHelper.getUIManagerForReactTag(reactApplicationContext, tag)
21 | val view = manager?.resolveView(tag)
22 | if (view == null) {
23 | Log.d(TAG, "Tag $tag not found")
24 | return@runOnUiThread
25 | }
26 |
27 | if (view is TrueSheetView) {
28 | closure(view)
29 | } else {
30 | Log.d(TAG, "Tag $tag does not match")
31 | }
32 | } catch (e: Exception) {
33 | e.printStackTrace()
34 | }
35 | }
36 | }
37 |
38 | @ReactMethod
39 | fun present(tag: Int, index: Int, promise: Promise) {
40 | withTrueSheetView(tag) {
41 | it.present(index) {
42 | Utils.withPromise(promise) {
43 | return@withPromise null
44 | }
45 | }
46 | }
47 | }
48 |
49 | @ReactMethod
50 | fun dismiss(tag: Int, promise: Promise) {
51 | withTrueSheetView(tag) {
52 | it.dismiss {
53 | Utils.withPromise(promise) {
54 | return@withPromise null
55 | }
56 | }
57 | }
58 | }
59 |
60 | companion object {
61 | const val TAG = "TrueSheetView"
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/android/src/main/java/com/lodev09/truesheet/core/KeyboardManager.kt:
--------------------------------------------------------------------------------
1 | package com.lodev09.truesheet.core
2 |
3 | import android.content.Context
4 | import android.view.View
5 | import android.view.ViewTreeObserver.OnGlobalLayoutListener
6 | import android.view.inputmethod.InputMethodManager
7 | import com.facebook.react.bridge.ReactContext
8 |
9 | class KeyboardManager(reactContext: ReactContext) {
10 | interface OnKeyboardChangeListener {
11 | fun onKeyboardStateChange(isVisible: Boolean, visibleHeight: Int?)
12 | }
13 |
14 | private var contentView: View? = null
15 | private var onGlobalLayoutListener: OnGlobalLayoutListener? = null
16 | private var isKeyboardVisible = false
17 |
18 | init {
19 | val activity = reactContext.currentActivity
20 | contentView = activity?.findViewById(android.R.id.content)
21 | }
22 |
23 | fun registerKeyboardListener(listener: OnKeyboardChangeListener?) {
24 | contentView?.apply {
25 | unregisterKeyboardListener()
26 |
27 | onGlobalLayoutListener = object : OnGlobalLayoutListener {
28 | private var previousHeight = 0
29 |
30 | override fun onGlobalLayout() {
31 | val heightDiff = rootView.height - height
32 | if (heightDiff > Utils.toPixel(200.0)) {
33 | // Will ask InputMethodManager.isAcceptingText() to detect if keyboard appeared or not.
34 | val inputManager = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
35 | if (height != previousHeight && inputManager.isAcceptingText()) {
36 | listener?.onKeyboardStateChange(true, height)
37 |
38 | previousHeight = height
39 | isKeyboardVisible = true
40 | }
41 | } else if (isKeyboardVisible) {
42 | listener?.onKeyboardStateChange(false, null)
43 | previousHeight = 0
44 | isKeyboardVisible = false
45 | }
46 | }
47 | }
48 |
49 | getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener)
50 | }
51 | }
52 |
53 | fun unregisterKeyboardListener() {
54 | onGlobalLayoutListener?.let {
55 | contentView?.getViewTreeObserver()?.removeOnGlobalLayoutListener(onGlobalLayoutListener)
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/android/src/main/java/com/lodev09/truesheet/core/RootSheetView.kt:
--------------------------------------------------------------------------------
1 | package com.lodev09.truesheet.core
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Context
5 | import android.view.MotionEvent
6 | import android.view.View
7 | import com.facebook.react.config.ReactFeatureFlags
8 | import com.facebook.react.uimanager.JSPointerDispatcher
9 | import com.facebook.react.uimanager.JSTouchDispatcher
10 | import com.facebook.react.uimanager.RootView
11 | import com.facebook.react.uimanager.ThemedReactContext
12 | import com.facebook.react.uimanager.events.EventDispatcher
13 | import com.facebook.react.views.view.ReactViewGroup
14 |
15 | /**
16 | * RootSheetView is the ViewGroup which contains all the children of a Modal. It gets all
17 | * child information forwarded from TrueSheetView and uses that to create children. It is
18 | * also responsible for acting as a RootView and handling touch events. It does this the same way
19 | * as ReactRootView.
20 | *
21 | *
22 | * To get layout to work properly, we need to layout all the elements within the Modal as if
23 | * they can fill the entire window. To do that, we need to explicitly set the styleWidth and
24 | * styleHeight on the LayoutShadowNode to be the window size. This is done through the
25 | * UIManagerModule, and will then cause the children to layout as if they can fill the window.
26 | */
27 | class RootSheetView(private val context: Context?) :
28 | ReactViewGroup(context),
29 | RootView {
30 | private var viewWidth = 0
31 | private var viewHeight = 0
32 |
33 | private val jSTouchDispatcher = JSTouchDispatcher(this)
34 | private var jSPointerDispatcher: JSPointerDispatcher? = null
35 |
36 | var sizeChangeListener: ((w: Int, h: Int) -> Unit)? = null
37 | var eventDispatcher: EventDispatcher? = null
38 |
39 | private val reactContext: ThemedReactContext
40 | get() = context as ThemedReactContext
41 |
42 | init {
43 | if (ReactFeatureFlags.dispatchPointerEvents) {
44 | jSPointerDispatcher = JSPointerDispatcher(this)
45 | }
46 | }
47 |
48 | override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
49 | super.onSizeChanged(w, h, oldw, oldh)
50 |
51 | viewWidth = w
52 | viewHeight = h
53 |
54 | sizeChangeListener?.let { it(viewWidth, viewHeight) }
55 | }
56 |
57 | override fun handleException(t: Throwable) {
58 | reactContext.reactApplicationContext.handleException(RuntimeException(t))
59 | }
60 |
61 | override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
62 | eventDispatcher?.let { eventDispatcher ->
63 | jSTouchDispatcher.handleTouchEvent(event, eventDispatcher, reactContext)
64 | jSPointerDispatcher?.handleMotionEvent(event, eventDispatcher, true)
65 | }
66 | return super.onInterceptTouchEvent(event)
67 | }
68 |
69 | @SuppressLint("ClickableViewAccessibility")
70 | override fun onTouchEvent(event: MotionEvent): Boolean {
71 | eventDispatcher?.let { eventDispatcher ->
72 | jSTouchDispatcher.handleTouchEvent(event, eventDispatcher, reactContext)
73 | jSPointerDispatcher?.handleMotionEvent(event, eventDispatcher, false)
74 | }
75 | super.onTouchEvent(event)
76 | // In case when there is no children interested in handling touch event, we return true from
77 | // the root view in order to receive subsequent events related to that gesture
78 | return true
79 | }
80 |
81 | override fun onInterceptHoverEvent(event: MotionEvent): Boolean {
82 | eventDispatcher?.let { jSPointerDispatcher?.handleMotionEvent(event, it, true) }
83 | return super.onHoverEvent(event)
84 | }
85 |
86 | override fun onHoverEvent(event: MotionEvent): Boolean {
87 | eventDispatcher?.let { jSPointerDispatcher?.handleMotionEvent(event, it, false) }
88 | return super.onHoverEvent(event)
89 | }
90 |
91 | override fun onChildStartedNativeGesture(childView: View?, ev: MotionEvent) {
92 | eventDispatcher?.let { eventDispatcher ->
93 | jSTouchDispatcher.onChildStartedNativeGesture(ev, eventDispatcher)
94 | jSPointerDispatcher?.onChildStartedNativeGesture(childView, ev, eventDispatcher)
95 | }
96 | }
97 |
98 | override fun onChildEndedNativeGesture(childView: View, ev: MotionEvent) {
99 | eventDispatcher?.let { jSTouchDispatcher.onChildEndedNativeGesture(ev, it) }
100 | jSPointerDispatcher?.onChildEndedNativeGesture()
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/android/src/main/java/com/lodev09/truesheet/core/Utils.kt:
--------------------------------------------------------------------------------
1 | package com.lodev09.truesheet.core
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Context
5 | import android.os.Build
6 | import android.util.DisplayMetrics
7 | import android.view.WindowInsets
8 | import android.view.WindowManager
9 | import com.facebook.react.bridge.Promise
10 | import com.facebook.react.bridge.ReactContext
11 | import com.facebook.react.uimanager.PixelUtil
12 |
13 | object Utils {
14 | @SuppressLint("DiscouragedApi")
15 | private fun getIdentifierHeight(context: ReactContext, name: String): Int =
16 | context.resources.getDimensionPixelSize(
17 | context.resources.getIdentifier(name, "dimen", "android")
18 | ).takeIf { it > 0 } ?: 0
19 |
20 | @SuppressLint("InternalInsetResource", "DiscouragedApi")
21 | fun screenHeight(context: ReactContext, edgeToEdge: Boolean): Int {
22 | val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
23 | val displayMetrics = DisplayMetrics()
24 |
25 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
26 | context.display?.getRealMetrics(displayMetrics)
27 | } else {
28 | windowManager.defaultDisplay.getMetrics(displayMetrics)
29 | }
30 |
31 | val screenHeight = displayMetrics.heightPixels
32 | val statusBarHeight = getIdentifierHeight(context, "status_bar_height")
33 | val hasNavigationBar = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
34 | context.getSystemService(WindowManager::class.java)
35 | ?.currentWindowMetrics
36 | ?.windowInsets
37 | ?.isVisible(WindowInsets.Type.navigationBars()) ?: false
38 | } else {
39 | context.resources.getIdentifier("navigation_bar_height", "dimen", "android") > 0
40 | }
41 |
42 | val navigationBarHeight = if (hasNavigationBar) {
43 | getIdentifierHeight(context, "navigation_bar_height")
44 | } else {
45 | 0
46 | }
47 |
48 | return if (edgeToEdge) {
49 | // getRealMetrics includes navigation bar height
50 | // windowManager.defaultDisplay.getMetrics doesn't
51 | when (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
52 | true -> screenHeight
53 | false -> screenHeight + navigationBarHeight
54 | }
55 | } else {
56 | screenHeight - statusBarHeight - navigationBarHeight
57 | }
58 | }
59 |
60 | fun toDIP(value: Float): Float = PixelUtil.toDIPFromPixel(value)
61 | fun toPixel(value: Double): Float = PixelUtil.toPixelFromDIP(value)
62 |
63 | fun withPromise(promise: Promise, closure: () -> Any?) {
64 | try {
65 | val result = closure()
66 | promise.resolve(result)
67 | } catch (e: Throwable) {
68 | e.printStackTrace()
69 | promise.reject("Error", e.message, e.cause)
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['module:react-native-builder-bob/babel-preset'],
3 | };
4 |
--------------------------------------------------------------------------------
/docs/.gitattributes:
--------------------------------------------------------------------------------
1 | # Mark the docs/ directory as documentation only, so it doesn't show up as JS code.
2 | **/* linguist-documentation
3 |
--------------------------------------------------------------------------------
/docs/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependencies
2 | /node_modules
3 |
4 | # Production
5 | /build
6 |
7 | # Generated files
8 | .docusaurus
9 | .cache-loader
10 |
11 | # Misc
12 | .DS_Store
13 | .env.local
14 | .env.development.local
15 | .env.test.local
16 | .env.production.local
17 |
18 | npm-debug.log*
19 | yarn-debug.log*
20 | yarn-error.log*
21 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Website
2 |
3 | This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.
4 |
5 | ### Installation
6 |
7 | ```
8 | $ yarn
9 | ```
10 |
11 | ### Local Development
12 |
13 | ```
14 | $ yarn start
15 | ```
16 |
17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
18 |
19 | ### Build
20 |
21 | ```
22 | $ yarn build
23 | ```
24 |
25 | This command generates static content into the `build` directory and can be served using any static contents hosting service.
26 |
--------------------------------------------------------------------------------
/docs/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
3 | }
4 |
--------------------------------------------------------------------------------
/docs/blog/2024/img/auto-sizing.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/docs/blog/2024/img/auto-sizing.gif
--------------------------------------------------------------------------------
/docs/blog/2024/release-0-10.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | date: 2024-04-22
3 | slug: release-0-10
4 | title: Version 0.10 Release
5 | authors: [lodev09]
6 | tags: [release]
7 | ---
8 |
9 | import sizing from './img/auto-sizing.gif'
10 |
11 | ## Version 0.10 🎉
12 |
13 | True Sheet is getting better with every update! This latest version introduces some exciting new features to enhance your experience.
14 |
15 | {/* truncate */}
16 |
17 | ### Global Static Methods
18 |
19 | Many users have asked about presenting the sheet from anywhere within their applications. While there are multiple solutions, we've chosen the simplest approach.
20 |
21 | Introducing [static methods](/reference/methods#global-methods)!
22 |
23 | With this update, you can now present the sheet from any part of your code by providing a [`name`](/reference/props#name) to your sheet instance. This streamlines the process and makes it easier to manage your sheets across your application.
24 |
25 | Here's an example:
26 |
27 | ```tsx {3}
28 | const App = () => {
29 | return (
30 |
31 |
32 |
33 | )
34 | }
35 | ```
36 |
37 |
38 | ```tsx {5}
39 | import { TrueSheet } from '@lodev09/react-native-true-sheet'
40 |
41 | const SomeComponent = () => {
42 | const presentMySheet = () => {
43 | TrueSheet.present('my-sheet') // 🎉
44 | }
45 |
46 | return (
47 |
48 | )
49 | }
50 | ```
51 |
52 | Check out our [guide](/guides/global-methods) on global static methods for examples and detailed usage instructions.
53 |
54 | ### Truly Automatic `auto` Sizing
55 |
56 | True Sheet has long supported [`auto`](/reference/types#sheetsize) sizing, where the sheet's height adjusts dynamically based on its content. However, in previous versions, this feature had some limitations and required re-presenting the sheet to update the size after content changes.
57 |
58 | With version `0.10`, `auto` sizing is now truly automatic. Whenever the content within the sheet changes, the sheet's height will adjust seamlessly without the need for re-presenting. 😎
59 |
60 |
61 |
62 | This enhancement ensures a smooth and responsive experience, keeping your sheets sized appropriately at all times without any extra effort on your part.
63 |
64 | Check out [this example](https://github.com/lodev09/react-native-true-sheet/blob/main/example/src/sheets/PromptSheet.tsx) to see it in action!
65 |
66 | ## That's All
67 |
68 | We're constantly working to improve True Sheet and bring you the features you need. Stay tuned for more exciting updates in the future!
69 |
--------------------------------------------------------------------------------
/docs/blog/2024/welcome.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | date: 2024-04-21
3 | slug: welcome
4 | title: Welcome
5 | authors: [lodev09]
6 | tags: [bottom-sheet, true-sheet, native-sheet]
7 | ---
8 |
9 | ## Hello World!
10 |
11 | {/* truncate */}
12 |
--------------------------------------------------------------------------------
/docs/blog/authors.yml:
--------------------------------------------------------------------------------
1 | lodev09:
2 | name: Jovanni Lo
3 | title: Lead Mobile Developer
4 | url: https://github.com/lodev09
5 | image_url: https://github.com/lodev09.png
6 |
--------------------------------------------------------------------------------
/docs/docs/guides/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Guides",
3 | "position": 4,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "Guides on how to use True Native Bottom Sheet on your React Native app.",
7 | "keywords": ["bottom sheet guides", "how to add bottom sheet", "bottom sheet recipes", "bottom sheet getting started", "using native bottom sheet"]
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/docs/docs/guides/dimming/dimming.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/docs/docs/guides/dimming/dimming.gif
--------------------------------------------------------------------------------
/docs/docs/guides/dimming/dimming.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Dimming the Background
3 | description: Control the bottom sheet's dimming behavior.
4 | keywords: [bottom sheet dimming, bottom sheet background, inline bottom sheet, maps bottom sheet]
5 | ---
6 |
7 | import dimming from './dimming.gif'
8 |
9 | One of the most common use cases for a Bottom Sheet is to present it while still allowing users to interact with background components, such as in a Maps app.
10 |
11 | In this guide, you can configure `TrueSheet` to achieve this exact functionality.
12 |
13 |
14 |
15 | ## How?
16 |
17 | You can easily disable the dimmed background of the sheet by setting [`dimmed`](/reference/props#dimmed) to `false`.
18 |
19 | ```tsx {5}
20 | export const App = () => {
21 | return (
22 |
26 |
27 |
28 | )
29 | }
30 | ```
31 |
32 | ### Dimmed by Size Index
33 |
34 | To further customize the dimming behavior, [`dimmedIndex`](/reference/props#dimmedindex) is also available. Set the [size](/reference/props#sizes) `index` at which you want the sheet to start dimming.
35 |
36 | ```tsx {5}
37 | export const App = () => {
38 | return (
39 |
43 |
44 |
45 | )
46 | }
47 | ```
48 |
49 | :::info
50 | `dimmedIndex` is ignored if `dimmed` is set to `false`.
51 | :::
52 |
--------------------------------------------------------------------------------
/docs/docs/guides/edge2edge.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Enable edge-to-edge
3 | description: Turning on edge-to-edge support for Android.
4 | keywords: [bottom sheet edge-to-edge, edge-to-edge, android]
5 | ---
6 |
7 | Yes! TrueSheet does support [`edge-to-edge`](https://developer.android.com/develop/ui/views/layout/edge-to-edge).
8 |
9 | ## How?
10 |
11 | It's easy, just set [`edgeToEdge`](/reference/props#edgetoedge) to `true`.
12 |
13 | ```tsx {3}
14 | const App = () => {
15 | return (
16 |
17 |
18 |
19 | )
20 | }
21 | ```
22 |
23 | ## react-native-edge-to-edge
24 |
25 | [`react-native-edge-to-edge`](https://github.com/zoontek/react-native-edge-to-edge) is a cool tiny package that lets you effortlessly enable `edge-to-edge` display for your app. Go check it out!
26 |
--------------------------------------------------------------------------------
/docs/docs/guides/footer.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Adding Footer
3 | description: Add a floating footer component to the bottom sheet.
4 | keywords: [bottom sheet footer, bottom sheet floating footer, bottom sheet sticky footer]
5 | ---
6 |
7 | Do you need a FAB (Floating Action Button) on the sheet? Or perhaps a small banner at the bottom? We've got you covered!
8 |
9 | `TrueSheet` provides first-class support for a `Footer` component. This component will float at the bottom of the sheet.
10 |
11 | ## How?
12 |
13 | Define your footer component.
14 |
15 | ```tsx
16 | const SomeFooter = () => {
17 | return (
18 |
19 | My Foot-er is Awesome.
20 |
21 | )
22 | }
23 | ```
24 |
25 | Stick it in the [`FooterComponent`](/reference/props#footercomponent).
26 |
27 | ```tsx {3}
28 | const App = () => {
29 | return (
30 |
31 |
32 |
33 | )
34 | }
35 | ```
36 |
37 | :::tip
38 | For best performance, use `ReactElement` instead!
39 |
40 | ```tsx {5-9}
41 | const App = () => {
42 | return (
43 |
47 | My Foot-er is more awesome.
48 |
49 | }
50 | >
51 |
52 |
53 | )
54 | }
55 | ```
56 | :::
57 |
--------------------------------------------------------------------------------
/docs/docs/guides/global-methods.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Global Methods
3 | description: Bottom sheet's global methods that you can invoke from anywhere.
4 | keywords: [bottom sheet global methods, bottom sheet static methods, bottom sheet invoking anywhere]
5 | ---
6 |
7 | `TrueSheet` relies heavily on [component methods](/reference/methods) to present and dismiss the sheet. However, this becomes challenging when the button is deep within the component tree.
8 |
9 | To resolve this issue, `TrueSheet` provides [global methods](/reference/methods#global-methods) that allow you to present or dismiss any sheet from anywhere!
10 |
11 | ## How?
12 |
13 | Somewhere in your App, define the sheet with a [`name`](/reference/props#name).
14 |
15 | ```tsx {3}
16 | const App = () => {
17 | return (
18 |
19 |
20 |
21 | )
22 | }
23 | ```
24 |
25 | In your component, present the sheet using the `present` global method.
26 |
27 | ```tsx {5}
28 | import { TrueSheet } from '@lodev09/react-native-true-sheet'
29 |
30 | const SomeComponent = () => {
31 | const presentMySheet = () => {
32 | TrueSheet.present('my-sheet') // 🎉
33 | }
34 |
35 | return (
36 |
37 | )
38 | }
39 | ```
40 |
41 | Guess what? You can also `dismiss` it globally 🤩.
42 |
43 | ```tsx
44 | TrueSheet.dismiss('my-sheet') // ✅
45 | ```
46 |
--------------------------------------------------------------------------------
/docs/docs/guides/jest.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Testing with Jest
3 | description: Mocking the bottom sheet component using Jest.
4 | keywords: [bottom sheet jest, testing bottom sheet, mocking bottom sheet]
5 | ---
6 |
7 | When using `jest`, simply mock the entire package.
8 |
9 | ```tsx
10 | jest.mock('@lodev09/react-native-true-sheet')
11 | ```
12 |
--------------------------------------------------------------------------------
/docs/docs/guides/onmount/onmount.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/docs/docs/guides/onmount/onmount.gif
--------------------------------------------------------------------------------
/docs/docs/guides/onmount/onmount.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Presenting During Mount
3 | description: Present the bottom sheet on mount.
4 | keywords: [bottom sheet on mount, bottom sheet initialIndex]
5 | ---
6 |
7 | import onmount from './onmount.gif'
8 |
9 | Sometimes, you may want to present the sheet directly during mount. For example, you might want to present the sheet when a screen is opened through a deep link.
10 |
11 |
12 |
13 | ## How?
14 |
15 | You can do this by setting [`initialIndex`](/reference/props#initialindex) prop. It accepts the [`size`](/reference/types#sheetsize) `index` that your sheet is configured with. See [sizes](/reference/props#sizes) prop for more information.
16 |
17 | ```tsx {5-6}
18 | const App = () => {
19 | return (
20 |
25 |
26 |
27 | )
28 | }
29 | ```
30 |
31 | ### Disabling Animation
32 |
33 | You may want to disable the present animation. To do this, simply set [`initialIndexAnimated`](/reference/props#initialindexanimated) to `false`.
34 |
35 | ### Using with React Navigation
36 |
37 | Using this with [`react-navigation`](https://reactnavigation.org) can cause render issue. Check out the [troubleshooting guide](/troubleshooting#present-during-mount) for the fix 😉.
38 |
--------------------------------------------------------------------------------
/docs/docs/guides/reanimated/reanimated.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/docs/docs/guides/reanimated/reanimated.gif
--------------------------------------------------------------------------------
/docs/docs/guides/reanimated/reanimated.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Integrating Reanimated
3 | description: Integrate Reanimated while dragging your sheet.
4 | keywords: [bottom sheet dragging, react-native-reanimated, reanimated]
5 | ---
6 |
7 | import reanimated from './reanimated.gif'
8 |
9 | Yes! `TrueSheet` does support [react-native-reanimated](https://docs.swmansion.com/react-native-reanimated/). One use case would be a floating action button (FAB) to the sheet's movement, adjusting its position, opacity, or scale as the Sheet is being dragged.
10 |
11 |
12 |
13 | ## How?
14 |
15 | In this example, we will use the [`onDragChange`](/reference/props#ondragchange) event to listen to size changes while dragging.
16 |
17 | You can checkout [example](https://github.com/lodev09/react-native-true-sheet/tree/main/example) for the complete implementation.
18 |
19 | ### 1. Define a handler hook
20 |
21 | ```tsx
22 | import { useEvent, useHandler } from 'react-native-reanimated'
23 |
24 | type DragChangeHandler = (sizeInfo: SizeInfo, context: unknown) => void
25 |
26 | export const useDragChangeHandler = (
27 | handler: DragChangeHandler,
28 | dependencies: DependencyList = []
29 | ) => {
30 | const handlers = {
31 | onDragChange: handler,
32 | }
33 |
34 | const { context, doDependenciesDiffer } = useHandler(handlers, dependencies)
35 |
36 | return useEvent(
37 | (event) => {
38 | 'worklet'
39 | const { onDragChange } = handlers
40 | if (onDragChange && event.eventName.endsWith('onDragChange')) {
41 | onDragChange(event, context)
42 | }
43 | },
44 | ['onDragChange'],
45 | doDependenciesDiffer
46 | )
47 | }
48 | ```
49 |
50 | ### 2. Attach the event handler
51 |
52 | ```tsx {3-4,9-12,23}
53 | import Animated, { useSharedValue, useAnimatedStyle } from 'react-native-reanimated'
54 |
55 | const AnimatedButton = Animated.createAnimatedComponent(TouchableOpacity)
56 | const AnimatedTrueSheet = Animated.createAnimatedComponent(TrueSheet)
57 |
58 | const App = () => {
59 | const buttonY = useSharedValue(0)
60 |
61 | const dragChangeHandler = useDragChangeHandler((sizeInfo: SizeInfo) => {
62 | 'worklet'
63 | buttonY.value = -sizeInfo.value
64 | })
65 |
66 | const $animatedStyle: ViewStyle = useAnimatedStyle(() => ({
67 | transform: [{ translateY: buttonY.value }],
68 | }))
69 |
70 | return (
71 |
72 |
73 |
77 |
78 |
79 |
80 | )
81 | }
82 | ```
83 |
--------------------------------------------------------------------------------
/docs/docs/guides/resizing/resizing.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/docs/docs/guides/resizing/resizing.gif
--------------------------------------------------------------------------------
/docs/docs/guides/resizing/resizing.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Resizing Programmatically
3 | description: Programmatically resize the bottom sheet and listen for size changes.
4 | keywords: [bottom sheet resizing, bottom sheet sizes, bottom sheet auto resizing]
5 | ---
6 |
7 | import resizing from './resizing.gif'
8 |
9 | `TrueSheet` has a main prop called [`sizes`](/reference/props#sizes) which allows you to define the sizes that the sheet can support. This is an array of [`SheetSize`](/reference/types#sheetsize) that supports sizes like `"auto"`, `"medium"`, `"large"`, etc.
10 |
11 | In some cases, you may want to resize the sheet programmatically for a better experience.
12 |
13 |
14 |
15 | ## How?
16 |
17 | ### Resize Programmatically
18 |
19 | Define the sheet and use the [`resize`](/reference/methods#resize) method.
20 |
21 | ```tsx {2-2,6-6,11-13}
22 | const App = () => {
23 | const sheet = useRef(null)
24 |
25 | const resize = async () => {
26 | // Resize to 69%
27 | await sheet.current?.resize(1)
28 | console.log('Yay, we are now at 69% 💦')
29 | }
30 |
31 | return (
32 |
33 |
34 |
35 | )
36 | }
37 | ```
38 |
39 | :::tip
40 | You can also do it globally using the related [global method](/reference/methods#global-methods).
41 |
42 | ```tsx
43 | TrueSheet.resize('resizing-sheet', 1)
44 | ```
45 | :::
46 |
47 | :::info
48 | `sizes` can only support up to 3 sizes. **_collapsed_**, **_half-expanded_**, and **_expanded_**.
49 | :::
50 |
51 |
52 | ### Listening to Size Change
53 |
54 | For some reason, if you want to get the resolved size, you can listen to size changes by providing the [`onSizeChange`](/reference/props#onsizechange) event.
55 |
56 | The event comes with the [`SizeInfo`](/reference/types#sizeinfo) that you can use to get the size `value`.
57 |
58 | ```tsx {9-11,17-17}
59 | const App = () => {
60 | const sheet = useRef(null)
61 |
62 | const resize = async () => {
63 | // Resize to 69%
64 | await sheet.current?.resize(1)
65 | }
66 |
67 | const handleSizeChange = (e: SizeChangeEvent) => {
68 | console.log(e.nativeEvent.index, e.nativeEvent.value) // Do whatever you need from this size ✅
69 | }
70 |
71 | return (
72 |
77 |
78 |
79 | )
80 | }
81 | ```
82 |
83 | :::info
84 | The event will also trigger when the user drags the sheet into a size.
85 | :::
86 |
--------------------------------------------------------------------------------
/docs/docs/guides/scrolling.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Scrolling Content
3 | description: Handle scrolling content within the bottom sheet.
4 | keywords: [bottom sheet scrolling, bottom sheet scrollview, bottom sheet flatlist]
5 | ---
6 |
7 | Scrolling content within the sheet requires some special configuration on both iOS and Android. Let's admit, some things just don't work out of the box.
8 |
9 | Follow the guide below so you can scroll your content using `TrueSheet`.
10 |
11 | ## How?
12 |
13 | ### IOS
14 |
15 | On iOS, use [`scrollRef`](/reference/props#scrollref) to reference the scrollable component, allowing iOS to handle it automatically.
16 |
17 | This works for `FlatList` as well.
18 |
19 | ```tsx {6-7}
20 | const App = () => {
21 | const sheet = useRef(null)
22 | const scrollview = useRef(null)
23 |
24 | return (
25 |
26 |
27 |
28 |
29 |
30 | )
31 | }
32 | ```
33 |
34 | ### Android
35 |
36 | On Android, `nestedScrollEnabled` needs to be enabled so that scrolling works when the sheet is expanded to its `maxHeight`.
37 |
38 | ```tsx {6}
39 | const App = () => {
40 | const sheet = useRef(null)
41 |
42 | return (
43 |
44 |
45 |
46 |
47 |
48 | )
49 | }
50 | ```
51 |
--------------------------------------------------------------------------------
/docs/docs/guides/stacking/stacking.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/docs/docs/guides/stacking/stacking.gif
--------------------------------------------------------------------------------
/docs/docs/guides/stacking/stacking.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Stacking Sheets
3 | description: Guide on how to present bottom sheet on top of an existing sheet.
4 | keywords: [bottom sheet stacking, multiple bottom sheets, parent bottom sheet, child bottom sheet]
5 | ---
6 |
7 | import stacking from './stacking.gif'
8 |
9 | Sometimes you want to stack the sheets one after another. On iOS, this can cause issues. There are _**two**_ ways to resolve this.
10 |
11 |
12 |
13 | ## How?
14 |
15 | ### 1. Dismiss the "parent" sheet first
16 |
17 | ```tsx {2-3,9-9}
18 | const presentSheet2 = async () => {
19 | await sheet1.current?.dismiss() // Wait for sheet 1 to dismiss ✅
20 | await sheet2.current?.present() // Sheet 2 will now present 🎉
21 | }
22 |
23 | return (
24 | <>
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | >
33 | )
34 | ```
35 | ### 2. Define the 2nd sheet within the "parent" sheet.
36 |
37 | IOS handles this automatically by default 😎.
38 |
39 | ```tsx {2-2,7-7}
40 | const presentSheet2 = async () => {
41 | await sheet2.current?.present() // Sheet 2 will now present 🎉
42 | }
43 |
44 | return (
45 |
46 |
47 |
48 |
49 |
50 |
51 | )
52 | ```
53 |
54 | :::tip
55 | You can do the same with **Android** for a more consistent user experience.
56 | :::
57 |
--------------------------------------------------------------------------------
/docs/docs/install.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 2
3 | description: Installation of the React Native True Bottom Sheet component.
4 | keywords: [bottom sheet installation, bottom sheet yarn, bottom sheet npm, ios bottom sheet, android bottom sheet, expo bottom sheet]
5 | ---
6 |
7 | # Installation
8 |
9 | You can install the package by using either `yarn` or `npm`.
10 |
11 | ```sh
12 | yarn add @lodev09/react-native-true-sheet
13 | ```
14 | ```sh
15 | npm i @lodev09/react-native-true-sheet
16 | ```
17 |
18 | Next, run the following to install it on IOS.
19 |
20 | ```sh
21 | cd ios && pod install
22 | ```
23 |
24 | :::info
25 | This package is not compatible with [Expo Go](https://docs.expo.dev/get-started/expo-go/). Use this with [Expo CNG](https://docs.expo.dev/workflow/continuous-native-generation/) instead.
26 | :::
27 |
--------------------------------------------------------------------------------
/docs/docs/intro.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 1
3 | description: The true native bottom sheet experience for your React Native Apps.
4 | slug: /
5 | ---
6 |
7 | import preview from '/img/preview.gif'
8 | import preview2 from '/img/preview-2.gif'
9 |
10 | # Introduction
11 |
12 | The **_true_** native bottom sheet experience for your [React Native](https://reactnative.dev) Apps.
13 |
14 |
15 |
16 |
17 | ## Features
18 |
19 | - Implemented in the native realm.
20 | - Clean, fast, and lightweight.
21 | - Asynchronus `ref` [methods](/reference/methods).
22 | - Bonus! [Blur](/reference/props#blurtint) support on IOS 😎
23 |
--------------------------------------------------------------------------------
/docs/docs/reference/02-methods.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Methods
3 | description: True Native Bottom Sheet component methods.
4 | keywords: [bottom sheet methods, preseting bottom sheet, dimissing bottom sheet, showing bottom sheet, closing bottom sheet, resizing bottom sheet]
5 | ---
6 |
7 | ## Component Methods
8 |
9 | `TrueSheet` has a couple of core methods that you'll be using most of the time. These methods are asynchronous so you can use `async` and `await` on them.
10 |
11 | Define the sheet and provide a `ref`. We will be using the `sheet` to access these methods.
12 | ```tsx {4}
13 | const sheet = useRef(null)
14 |
15 | return (
16 |
17 |
18 |
19 | )
20 | ```
21 |
22 | ### `present`
23 |
24 | Present the sheet. Optionally accepts a size `index`. See [`sizes`](/reference/props#sizes) prop.
25 |
26 | | Parameters | Required |
27 | | - | - |
28 | | `index: number = 0` | No |
29 |
30 | ```tsx
31 | await sheet.current?.present()
32 | ```
33 |
34 |
35 | ### `dismiss`
36 |
37 | Dismisses the sheet.
38 |
39 | ```tsx
40 | await sheet.current?.dismiss()
41 | ```
42 |
43 | ### `resize`
44 |
45 | Resizes the sheet programmatically by `index`. This is an alias of the [`present(index)`](#present) method.
46 |
47 | | Parameters | Required |
48 | | - | - |
49 | | `index: number` | Yes
50 |
51 | ```tsx
52 | // Resize to 80%
53 | await sheet.current?.resize(1)
54 | ```
55 |
56 | ## Global Methods
57 |
58 | You can also call the above methods statically without having access to a sheet's `ref`. This is particularly useful when you want to present a sheet from anywhere.
59 |
60 | The API is similar to the component methods except for the required [`name`](/reference/props#name) prop. See [this guide](/guides/global-methods) for example.
61 |
62 | In the example below, we provide `"my-sheet"` as the `name` of our sheet.
63 | ```tsx {4}
64 | const sheet = useRef(null)
65 |
66 | return (
67 |
68 |
69 |
70 | )
71 | ```
72 |
73 | You can then use these methods globally.
74 |
75 | ```tsx
76 | await TrueSheet.present('my-sheet')
77 | ```
78 | ```tsx
79 | await TrueSheet.dismiss('my-sheet')
80 | ```
81 | ```tsx
82 | // Resize to 80%
83 | await TrueSheet.resize('my-sheet', 1)
84 | ```
85 |
--------------------------------------------------------------------------------
/docs/docs/reference/03-types.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Types
3 | description: True Native Bottom Sheet type reference.
4 | keywords: [bottom sheet types, bottom sheet typescript, bottom sheet definitions]
5 | ---
6 |
7 | ## `SheetSize`
8 |
9 | ```tsx
10 |
11 |
12 |
13 | ```
14 |
15 | | Value | Description | 🍎 | 🤖 |
16 | | - | - | - | - |
17 | | `"auto"` | Auto resize based on content height. | **_16+_** | ✅ |
18 | | `"small"` | Translates to 25% | **_16+_** | ✅ |
19 | | `"medium"` | Translates to 50% | **_15+_** | ✅ |
20 | | `"large"` | Translates to 100% | ✅ | ✅ |
21 | | `"${number}%"` | Fixed height in % | **_16+_** | ✅ |
22 | | `number` | Fixed height | **_16+_** | ✅ |
23 |
24 | ## `TrueSheetGrabberProps`
25 |
26 | Grabber props to be used for android grabber or handle.
27 |
28 | | Prop | Type | Default | Description |
29 | | - | - | - | - |
30 | | visible | `boolean` | `true` | Is grabber visible. |
31 | | color | `ColorValue` | `"rgba(73,69,79,0.4)"` | Grabber color according to M3 specs. |
32 | | height | `number` | `4` | Grabber height according to M3 specs. |
33 | | width | `number` | `32` | Grabber width according to M3 specs. |
34 | | topOffset | `number` | `0` | Grabber top position offset. |
35 |
36 | ## `BlurTint`
37 |
38 | Blur tint that is mapped into native values in IOS.
39 |
40 | ```tsx
41 |
42 |
43 |
44 | ```
45 |
46 | | Value |
47 | | - |
48 | | `"light"` |
49 | | `"dark"` |
50 | | `"default"` |
51 | | `"extraLight"` |
52 | | `"regular"` |
53 | | `"prominent"` |
54 | | `"systemUltraThinMaterial"` |
55 | | `"systemThinMaterial"` |
56 | | `"systemMaterial"` |
57 | | `"systemThickMaterial"` |
58 | | `"systemChromeMaterial"` |
59 | | `"systemUltraThinMaterialLight"` |
60 | | `"systemThinMaterialLight"` |
61 | | `"systemMaterialLight"` |
62 | | `"systemThickMaterialLight"` |
63 | | `"systemChromeMaterialLight"` |
64 | | `"systemUltraThinMaterialDark"` |
65 | | `"systemThinMaterialDark"` |
66 | | `"systemMaterialDark"` |
67 | | `"systemThickMaterialDark"` |
68 | | `"systemChromeMaterialDark"` |
69 |
70 | ## `SizeInfo`
71 |
72 | `Object` that comes with some events.
73 |
74 | ```tsx
75 | {
76 | index: 1,
77 | value: 69
78 | }
79 | ```
80 |
81 | | Property | Type | Description |
82 | | - | - | - |
83 | | index | `number` | The size index from the provided sizes. See `sizes` prop. |
84 | | value | `number` | The actual height value of the size. |
85 |
--------------------------------------------------------------------------------
/docs/docs/reference/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Reference",
3 | "position": 5,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "True Native Bottom Sheet API reference.",
7 | "keywords": ["bottom sheet api reference", "bottom sheet api", "bottom sheet documentation"]
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/docs/docs/troubleshooting.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 6
3 | description: Fix common issues when using True Native Bottom Sheet.
4 | keywords: [bottom sheet troubleshooting, fixing bottom sheet, debugging bottom sheet]
5 | ---
6 |
7 | # Troubleshooting
8 |
9 | ## React Native Gesture Handler
10 |
11 | [`react-native-gesture-handler`](https://docs.swmansion.com/react-native-gesture-handler/docs/)
12 |
13 | On Android, [RNGH does not work](https://docs.swmansion.com/react-native-gesture-handler/docs/fundamentals/installation/#usage-with-modals-on-android) by default because modals are not located under React Native Root view in native hierarchy. To fix that, components need to be wrapped with `GestureHandlerRootView`.
14 |
15 | ```tsx
16 | import { GestureHandlerRootView } from 'react-native-gesture-handler'
17 | ```
18 |
19 | ```tsx {3-5}
20 | return (
21 |
22 |
23 |
24 |
25 |
26 | )
27 | ```
28 |
29 | :::info
30 | Note that we are using `flexGrow` instead of `flex` here. For some weird reason, `flex` does not work correctly. See [below](#weird-layout-render).
31 | :::
32 |
33 | ## React Navigation
34 |
35 | [`react-navigation`](https://reactnavigation.org)
36 |
37 | ### Navigation Crash
38 |
39 | On IOS, navigating to a screen from within the Sheet can cause issues. To resolve this, dismiss the sheet before navigating!
40 |
41 | Example:
42 | ```tsx {4-5}
43 | const sheet = useRef(null)
44 |
45 | const navigate = async () => {
46 | await sheet.current?.dismiss() // wait for the sheet to dismiss ✅
47 | navigation.navigate('SomeScreen') // navigate to the screen 🎉
48 | }
49 |
50 | return (
51 |
52 |
53 |
54 |
55 | )
56 | ```
57 |
58 | ### Present during Mount
59 |
60 | On iOS, when setting [`initialIndex`](/reference/props#initialindex) and enabling `initialIndexAnimated` (default is `true`) to present during mount, the presentation animation becomes weird. This happens because RNN is not yet finished when the sheet is trying to present.
61 |
62 | To solve this, you can do the following:
63 |
64 | 1. Set `initialIndexAnimated` to `false`. Disables animation during mount.
65 |
66 | ```tsx
67 | return (
68 |
69 |
70 |
71 | )
72 | ```
73 |
74 | 2. Wait for the screen to fully transition. See [`transitionEnd`](https://reactnavigation.org/docs/native-stack-navigator/#transitionend) event.
75 |
76 | ```tsx
77 | const navigation = useNavigation()
78 | const [isScreenShown, setIsScreenShown] = useState(false)
79 |
80 | // Subscribe to the transitionEnd event ✅
81 | useEffect(() => {
82 | const unsubscribe = navigation.addListener("transitionEnd", ({ data }) => {
83 | if (!data.closing) {
84 | setIsScreenShown(true)
85 | }
86 | })
87 |
88 | return unsubscribe
89 | }, [])
90 |
91 | // Wait for the screen to finish transitioning ✅
92 | if (!isScreenShown) return null
93 |
94 | // Finally show the sheet 🎉
95 | return (
96 |
97 |
98 |
99 | )
100 | ```
101 |
102 | ## Weird layout render
103 |
104 | The sheet does not have control over how React Native renders components and may lead to rendering issues. To resolve this, try to minimize the use of `flex=1` in your content styles. Instead, use fixed `height` or employ `flexGrow`, `flexBasis`, etc., to manage your layout requirements.
105 |
--------------------------------------------------------------------------------
/docs/docs/usage.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 3
3 | description: How to use the React Native True Bottom Sheet component.
4 | keywords: [bottom sheet usage, bottom sheet getting started, bottom sheet setup, import bottom sheet]
5 | ---
6 |
7 | # Usage
8 |
9 | 1. Import `TrueSheet`.
10 |
11 | ```tsx
12 | import { TrueSheet } from "@lodev09/react-native-true-sheet"
13 | ```
14 |
15 | 2. Define `TrueSheet` inside any component and attach a `ref` to it.
16 | 3. Control the sheet by invoking the available `ref` [methods](/reference/methods).
17 |
18 | ```tsx {2-2,5-8,11-14,18-25}
19 | export const App = () => {
20 | const sheet = useRef(null)
21 |
22 | // Present the sheet ✅
23 | const present = async () => {
24 | await sheet.current?.present()
25 | console.log('horray! sheet has been presented 💩')
26 | }
27 |
28 | // Dismiss the sheet ✅
29 | const dismiss = async () => {
30 | await sheet.current?.dismiss()
31 | console.log('Bye bye 👋')
32 | }
33 |
34 | return (
35 |
36 |
37 |
42 |
43 |
44 |
45 | )
46 | }
47 | ```
48 |
49 | Simple, right? Head over to [`props`](/reference/props) to learn more about configuring your sheet.
50 |
--------------------------------------------------------------------------------
/docs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "docs",
3 | "version": "1.0.0",
4 | "private": true,
5 | "scripts": {
6 | "docusaurus": "docusaurus",
7 | "start": "docusaurus start",
8 | "build": "docusaurus build",
9 | "swizzle": "docusaurus swizzle",
10 | "clear": "docusaurus clear",
11 | "serve": "docusaurus serve",
12 | "write-translations": "docusaurus write-translations",
13 | "write-heading-ids": "docusaurus write-heading-ids",
14 | "typecheck": "tsc"
15 | },
16 | "dependencies": {
17 | "@docusaurus/core": "^3.4.0",
18 | "@docusaurus/plugin-google-gtag": "^3.4.0",
19 | "@docusaurus/plugin-vercel-analytics": "^3.4.0",
20 | "@docusaurus/preset-classic": "^3.4.0",
21 | "@mdx-js/react": "^3.0.0",
22 | "clsx": "^2.0.0",
23 | "prism-react-renderer": "^2.3.0",
24 | "react": "^18.0.0",
25 | "react-dom": "^18.0.0"
26 | },
27 | "devDependencies": {
28 | "@docusaurus/module-type-aliases": "^3.4.0",
29 | "@docusaurus/tsconfig": "^3.4.0",
30 | "@docusaurus/types": "^3.4.0",
31 | "typescript": "~5.2.2"
32 | },
33 | "browserslist": {
34 | "production": [
35 | ">0.5%",
36 | "not dead",
37 | "not op_mini all"
38 | ],
39 | "development": [
40 | "last 3 chrome version",
41 | "last 3 firefox version",
42 | "last 5 safari version"
43 | ]
44 | },
45 | "engines": {
46 | "node": ">=18.0"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/docs/sidebars.ts:
--------------------------------------------------------------------------------
1 | import type { SidebarsConfig } from '@docusaurus/plugin-content-docs'
2 |
3 | const sidebars: SidebarsConfig = {
4 | trueSheetSidebar: [
5 | {
6 | type: 'autogenerated',
7 | dirName: '.',
8 | },
9 | ],
10 | }
11 |
12 | export default sidebars
13 |
--------------------------------------------------------------------------------
/docs/src/css/custom.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --ifm-color-primary: #1f64ae;
3 | --ifm-color-primary-dark: #1c5a9d;
4 | --ifm-color-primary-darker: #1a5594;
5 | --ifm-color-primary-darkest: #16467a;
6 | --ifm-color-primary-light: #226ebf;
7 | --ifm-color-primary-lighter: #2473c8;
8 | --ifm-color-primary-lightest: #3082da;
9 |
10 | --ifm-code-font-size: 95%;
11 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
12 | }
13 |
14 | [data-theme='dark'] {
15 | --ifm-color-primary: #8bb8e8;
16 | --ifm-color-primary-dark: #6ca5e2;
17 | --ifm-color-primary-darker: #5d9cdf;
18 | --ifm-color-primary-darkest: #2e7fd6;
19 | --ifm-color-primary-light: #aacbee;
20 | --ifm-color-primary-lighter: #b9d4f1;
21 | --ifm-color-primary-lightest: #e8f1fa;
22 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.2);
23 |
24 | --ifm-color-success: #47d995;
25 | --ifm-color-success-dark: #2fd487;
26 | --ifm-color-success-darker: #2acb80;
27 | --ifm-color-success-darkest: #23a769;
28 | --ifm-color-success-light: #5fdea3;
29 | --ifm-color-success-lighter: #6be0aa;
30 | --ifm-color-success-lightest: #8fe8be;
31 |
32 | --ifm-color-success-contrast-background: blue;
33 | }
34 |
35 | [data-theme='dark'] .alert--success {
36 | --ifm-alert-background-color: #11663f;
37 | }
38 |
39 | .padding-top--md {
40 | padding: 1.5rem !important;
41 | }
42 |
43 | .doc-sidebar-content {
44 | padding: 1.5rem !important;
45 | }
46 |
47 | .theme-doc-sidebar-container {
48 | border-right-width: 0 !important;
49 | }
50 |
51 | .pagination-nav__link {
52 | background-color: var(--ifm-menu-color-background-active);
53 | border-width: 0;
54 | }
55 |
56 | img {
57 | border-radius: var(--ifm-pre-border-radius);
58 | }
59 |
--------------------------------------------------------------------------------
/docs/src/theme/DocSidebar/Desktop/Content/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Content from '@theme-original/DocSidebar/Desktop/Content'
3 | import type ContentType from '@theme/DocSidebar/Desktop/Content'
4 | import type { WrapperProps } from '@docusaurus/types'
5 |
6 | type Props = WrapperProps
7 |
8 | export default function ContentWrapper(props: Props): React.ReactElement {
9 | return (
10 | <>
11 |
12 | >
13 | )
14 | }
15 |
--------------------------------------------------------------------------------
/docs/static/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/docs/static/.nojekyll
--------------------------------------------------------------------------------
/docs/static/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/docs/static/android-chrome-192x192.png
--------------------------------------------------------------------------------
/docs/static/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/docs/static/android-chrome-512x512.png
--------------------------------------------------------------------------------
/docs/static/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/docs/static/apple-touch-icon.png
--------------------------------------------------------------------------------
/docs/static/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/docs/static/favicon-16x16.png
--------------------------------------------------------------------------------
/docs/static/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/docs/static/favicon-32x32.png
--------------------------------------------------------------------------------
/docs/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/docs/static/favicon.ico
--------------------------------------------------------------------------------
/docs/static/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/docs/static/img/logo.png
--------------------------------------------------------------------------------
/docs/static/img/logo.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/docs/static/img/preview-2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/docs/static/img/preview-2.gif
--------------------------------------------------------------------------------
/docs/static/img/preview.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/docs/static/img/preview.gif
--------------------------------------------------------------------------------
/docs/static/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Allow: /
3 |
4 | # Host
5 | Host: https://sheet.lodev09.com
6 |
7 | # Sitemaps
8 | Sitemap: https://sheet.lodev09.com/sitemap.xml
9 |
--------------------------------------------------------------------------------
/docs/static/site.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "TrueSheet",
3 | "short_name": "TrueSheet",
4 | "icons": [
5 | {
6 | "src": "/android-chrome-192x192.png",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | },
10 | {
11 | "src": "/android-chrome-512x512.png",
12 | "sizes": "512x512",
13 | "type": "image/png"
14 | }
15 | ],
16 | "theme_color": "#ffffff",
17 | "background_color": "#ffffff",
18 | "display": "standalone"
19 | }
20 |
--------------------------------------------------------------------------------
/docs/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | // This file is not used in compilation. It is here just for a nice editor experience.
3 | "extends": "@docusaurus/tsconfig",
4 | "compilerOptions": {
5 | "baseUrl": "."
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/example/.bundle/config:
--------------------------------------------------------------------------------
1 | BUNDLE_PATH: "vendor/bundle"
2 | BUNDLE_FORCE_RUBY_PLATFORM: 1
3 |
--------------------------------------------------------------------------------
/example/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/example/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
4 | ruby ">= 2.6.10"
5 |
6 | # Exclude problematic versions of cocoapods and activesupport that causes build failures.
7 | gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1'
8 | gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0'
9 | gem 'xcodeproj', '< 1.26.0'
10 | gem 'concurrent-ruby', '< 1.3.4'
11 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | > **Note**: Make sure you have completed the [Set Up Your Environment](https://reactnative.dev/docs/set-up-your-environment) guide before proceeding.
4 |
5 | ## Step 1: Start Metro
6 |
7 | First, you will need to run **Metro**, the JavaScript build tool for React Native.
8 |
9 | To start the Metro dev server, run the following command from the root of your React Native project:
10 |
11 | ```sh
12 | # Using npm
13 | npm start
14 |
15 | # OR using Yarn
16 | yarn start
17 | ```
18 |
19 | ## Step 2: Build and run your app
20 |
21 | With Metro running, open a new terminal window/pane from the root of your React Native project, and use one of the following commands to build and run your Android or iOS app:
22 |
23 | ### Android
24 |
25 | ```sh
26 | # Using npm
27 | npm run android
28 |
29 | # OR using Yarn
30 | yarn android
31 | ```
32 |
33 | ### iOS
34 |
35 | For iOS, remember to install CocoaPods dependencies (this only needs to be run on first clone or after updating native deps).
36 |
37 | The first time you create a new project, run the Ruby bundler to install CocoaPods itself:
38 |
39 | ```sh
40 | bundle install
41 | ```
42 |
43 | Then, and every time you update your native dependencies, run:
44 |
45 | ```sh
46 | bundle exec pod install
47 | ```
48 |
49 | For more information, please visit [CocoaPods Getting Started guide](https://guides.cocoapods.org/using/getting-started.html).
50 |
51 | ```sh
52 | # Using npm
53 | npm run ios
54 |
55 | # OR using Yarn
56 | yarn ios
57 | ```
58 |
59 | If everything is set up correctly, you should see your new app running in the Android Emulator, iOS Simulator, or your connected device.
60 |
61 | This is one way to run your app — you can also build it directly from Android Studio or Xcode.
62 |
63 | ## Step 3: Modify your app
64 |
65 | Now that you have successfully run the app, let's make changes!
66 |
67 | Open `App.tsx` in your text editor of choice and make some changes. When you save, your app will automatically update and reflect these changes — this is powered by [Fast Refresh](https://reactnative.dev/docs/fast-refresh).
68 |
69 | When you want to forcefully reload, for example to reset the state of your app, you can perform a full reload:
70 |
71 | - **Android**: Press the R key twice or select **"Reload"** from the **Dev Menu**, accessed via Ctrl + M (Windows/Linux) or Cmd ⌘ + M (macOS).
72 | - **iOS**: Press R in iOS Simulator.
73 |
74 | ## Congratulations! :tada:
75 |
76 | You've successfully run and modified your React Native App. :partying_face:
77 |
78 | ### Now what?
79 |
80 | - If you want to add this new React Native code to an existing application, check out the [Integration guide](https://reactnative.dev/docs/integration-with-existing-apps).
81 | - If you're curious to learn more about React Native, check out the [docs](https://reactnative.dev/docs/getting-started).
82 |
83 | # Troubleshooting
84 |
85 | If you're having issues getting the above steps to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page.
86 |
87 | # Learn More
88 |
89 | To learn more about React Native, take a look at the following resources:
90 |
91 | - [React Native Website](https://reactnative.dev) - learn more about React Native.
92 | - [Getting Started](https://reactnative.dev/docs/environment-setup) - an **overview** of React Native and how setup your environment.
93 | - [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**.
94 | - [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts.
95 | - [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for React Native.
96 |
--------------------------------------------------------------------------------
/example/android/app/debug.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/example/android/app/debug.keystore
--------------------------------------------------------------------------------
/example/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
13 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/truesheet/example/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package truesheet.example
2 |
3 | import com.facebook.react.ReactActivity
4 | import com.facebook.react.ReactActivityDelegate
5 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
6 | import com.facebook.react.defaults.DefaultReactActivityDelegate
7 |
8 | class MainActivity : ReactActivity() {
9 |
10 | /**
11 | * Returns the name of the main component registered from JavaScript. This is used to schedule
12 | * rendering of the component.
13 | */
14 | override fun getMainComponentName(): String = "TrueSheetExample"
15 |
16 | /**
17 | * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
18 | * which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
19 | */
20 | override fun createReactActivityDelegate(): ReactActivityDelegate =
21 | DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
22 | }
23 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/truesheet/example/MainApplication.kt:
--------------------------------------------------------------------------------
1 | package truesheet.example
2 |
3 | import android.app.Application
4 | import com.facebook.react.PackageList
5 | import com.facebook.react.ReactApplication
6 | import com.facebook.react.ReactHost
7 | import com.facebook.react.ReactNativeHost
8 | import com.facebook.react.ReactPackage
9 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
10 | import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
11 | import com.facebook.react.defaults.DefaultReactNativeHost
12 | import com.facebook.react.soloader.OpenSourceMergedSoMapping
13 | import com.facebook.soloader.SoLoader
14 |
15 | class MainApplication : Application(), ReactApplication {
16 |
17 | override val reactNativeHost: ReactNativeHost =
18 | object : DefaultReactNativeHost(this) {
19 | override fun getPackages(): List =
20 | PackageList(this).packages.apply {
21 | // Packages that cannot be autolinked yet can be added manually here, for example:
22 | // add(MyReactNativePackage())
23 | }
24 |
25 | override fun getJSMainModuleName(): String = "index"
26 |
27 | override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
28 |
29 | override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
30 | override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
31 | }
32 |
33 | override val reactHost: ReactHost
34 | get() = getDefaultReactHost(applicationContext, reactNativeHost)
35 |
36 | override fun onCreate() {
37 | super.onCreate()
38 | SoLoader.init(this, OpenSourceMergedSoMapping)
39 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
40 | // If you opted-in for the New Architecture, we load the native entry point for this app.
41 | load()
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable/rn_edit_text_material.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
22 |
23 |
24 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | TrueSheetExample
3 |
4 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext {
3 | buildToolsVersion = "35.0.0"
4 | minSdkVersion = 24
5 | compileSdkVersion = 35
6 | targetSdkVersion = 35
7 | ndkVersion = "27.1.12297006"
8 | kotlinVersion = "2.0.21"
9 | }
10 | repositories {
11 | google()
12 | mavenCentral()
13 | }
14 | dependencies {
15 | classpath("com.android.tools.build:gradle")
16 | classpath("com.facebook.react:react-native-gradle-plugin")
17 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin")
18 | }
19 | }
20 |
21 | apply plugin: "com.facebook.react.rootproject"
22 |
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m
13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | # AndroidX package structure to make it clearer which packages are bundled with the
21 | # Android operating system, and which are packaged with your app's APK
22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
23 | android.useAndroidX=true
24 |
25 | # Use this property to specify which architecture you want to build.
26 | # You can also override it from the CLI using
27 | # ./gradlew -PreactNativeArchitectures=x86_64
28 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
29 |
30 | # Use this property to enable support to the new architecture.
31 | # This will allow you to use TurboModules and the Fabric render in
32 | # your application. You should enable this flag either if you want
33 | # to write custom TurboModules/Fabric components OR use libraries that
34 | # are providing them.
35 | newArchEnabled=false
36 |
37 | # Use this property to enable or disable the Hermes JS engine.
38 | # If set to false, you will be using JSC instead.
39 | hermesEnabled=true
40 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lodev09/react-native-true-sheet/798a1f0ba562268a5d49731425bcdb94cda97a7a/example/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/example/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 | @rem SPDX-License-Identifier: Apache-2.0
17 | @rem
18 |
19 | @if "%DEBUG%"=="" @echo off
20 | @rem ##########################################################################
21 | @rem
22 | @rem Gradle startup script for Windows
23 | @rem
24 | @rem ##########################################################################
25 |
26 | @rem Set local scope for the variables with windows NT shell
27 | if "%OS%"=="Windows_NT" setlocal
28 |
29 | set DIRNAME=%~dp0
30 | if "%DIRNAME%"=="" set DIRNAME=.
31 | @rem This is normally unused
32 | set APP_BASE_NAME=%~n0
33 | set APP_HOME=%DIRNAME%
34 |
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
37 |
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
40 |
41 | @rem Find java.exe
42 | if defined JAVA_HOME goto findJavaFromJavaHome
43 |
44 | set JAVA_EXE=java.exe
45 | %JAVA_EXE% -version >NUL 2>&1
46 | if %ERRORLEVEL% equ 0 goto execute
47 |
48 | echo. 1>&2
49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
50 | echo. 1>&2
51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
52 | echo location of your Java installation. 1>&2
53 |
54 | goto fail
55 |
56 | :findJavaFromJavaHome
57 | set JAVA_HOME=%JAVA_HOME:"=%
58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
59 |
60 | if exist "%JAVA_EXE%" goto execute
61 |
62 | echo. 1>&2
63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
64 | echo. 1>&2
65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
66 | echo location of your Java installation. 1>&2
67 |
68 | goto fail
69 |
70 | :execute
71 | @rem Setup the command line
72 |
73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
74 |
75 |
76 | @rem Execute Gradle
77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
78 |
79 | :end
80 | @rem End local scope for the variables with windows NT shell
81 | if %ERRORLEVEL% equ 0 goto mainEnd
82 |
83 | :fail
84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
85 | rem the _cmd.exe /c_ return code!
86 | set EXIT_CODE=%ERRORLEVEL%
87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
89 | exit /b %EXIT_CODE%
90 |
91 | :mainEnd
92 | if "%OS%"=="Windows_NT" endlocal
93 |
94 | :omega
95 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") }
2 | plugins { id("com.facebook.react.settings") }
3 | extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() }
4 | rootProject.name = 'truesheet.example'
5 | include ':app'
6 | includeBuild('../node_modules/@react-native/gradle-plugin')
7 |
--------------------------------------------------------------------------------
/example/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "TrueSheetExample",
3 | "displayName": "TrueSheetExample"
4 | }
5 |
--------------------------------------------------------------------------------
/example/babel.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const { getConfig } = require('react-native-builder-bob/babel-config')
3 | const pkg = require('../package.json')
4 |
5 | const root = path.resolve(__dirname, '..')
6 |
7 | module.exports = getConfig(
8 | {
9 | presets: ['module:@react-native/babel-preset'],
10 | plugins: ['react-native-reanimated/plugin'],
11 | },
12 | { root, pkg }
13 | )
14 |
--------------------------------------------------------------------------------
/example/index.js:
--------------------------------------------------------------------------------
1 | import { AppRegistry } from 'react-native'
2 | import App from './src/App'
3 | import { name as appName } from './app.json'
4 |
5 | AppRegistry.registerComponent(appName, () => App)
6 |
--------------------------------------------------------------------------------
/example/ios/.xcode.env:
--------------------------------------------------------------------------------
1 | # This `.xcode.env` file is versioned and is used to source the environment
2 | # used when running script phases inside Xcode.
3 | # To customize your local environment, you can create an `.xcode.env.local`
4 | # file that is not versioned.
5 |
6 | # NODE_BINARY variable contains the PATH to the node executable.
7 | #
8 | # Customize the NODE_BINARY variable here.
9 | # For example, to use nvm with brew, add the following line
10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use
11 | export NODE_BINARY=$(command -v node)
12 |
--------------------------------------------------------------------------------
/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | ENV['RCT_NEW_ARCH_ENABLED'] = '0'
2 |
3 | # Resolve react_native_pods.rb with node to allow for hoisting
4 | require Pod::Executable.execute_command('node', ['-p',
5 | 'require.resolve(
6 | "react-native/scripts/react_native_pods.rb",
7 | {paths: [process.argv[1]]},
8 | )', __dir__]).strip
9 |
10 | platform :ios, min_ios_version_supported
11 | prepare_react_native_project!
12 |
13 | linkage = ENV['USE_FRAMEWORKS']
14 | if linkage != nil
15 | Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
16 | use_frameworks! :linkage => linkage.to_sym
17 | end
18 |
19 | target 'TrueSheetExample' do
20 | config = use_native_modules!
21 |
22 | use_react_native!(
23 | :path => config[:reactNativePath],
24 | # An absolute path to your application root.
25 | :app_path => "#{Pod::Config.instance.installation_root}/.."
26 | )
27 |
28 | post_install do |installer|
29 | # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
30 | react_native_post_install(
31 | installer,
32 | config[:reactNativePath],
33 | :mac_catalyst_enabled => false,
34 | # :ccache_enabled => true
35 | )
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/example/ios/TrueSheetExample.xcodeproj/xcshareddata/xcschemes/TrueSheetExample.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
55 |
61 |
62 |
63 |
64 |
70 |
72 |
78 |
79 |
80 |
81 |
83 |
84 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/example/ios/TrueSheetExample.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/ios/TrueSheetExample/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import React
3 | import React_RCTAppDelegate
4 | import ReactAppDependencyProvider
5 |
6 | @main
7 | class AppDelegate: RCTAppDelegate {
8 | override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
9 | self.moduleName = "TrueSheetExample"
10 | self.dependencyProvider = RCTAppDependencyProvider()
11 |
12 | // You can add your custom initial props in the dictionary below.
13 | // They will be passed down to the ViewController used by React Native.
14 | self.initialProps = [:]
15 |
16 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
17 | }
18 |
19 | override func sourceURL(for bridge: RCTBridge) -> URL? {
20 | self.bundleURL()
21 | }
22 |
23 | override func bundleURL() -> URL? {
24 | #if DEBUG
25 | RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
26 | #else
27 | Bundle.main.url(forResource: "main", withExtension: "jsbundle")
28 | #endif
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/example/ios/TrueSheetExample/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "scale" : "2x",
36 | "size" : "60x60"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "scale" : "3x",
41 | "size" : "60x60"
42 | },
43 | {
44 | "idiom" : "ios-marketing",
45 | "scale" : "1x",
46 | "size" : "1024x1024"
47 | }
48 | ],
49 | "info" : {
50 | "author" : "xcode",
51 | "version" : 1
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/example/ios/TrueSheetExample/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/example/ios/TrueSheetExample/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | TrueSheetExample
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(MARKETING_VERSION)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(CURRENT_PROJECT_VERSION)
25 | LSRequiresIPhoneOS
26 |
27 | NSAppTransportSecurity
28 |
29 |
30 | NSAllowsArbitraryLoads
31 |
32 | NSAllowsLocalNetworking
33 |
34 |
35 | NSLocationWhenInUseUsageDescription
36 |
37 | UILaunchStoryboardName
38 | LaunchScreen
39 | UIRequiredDeviceCapabilities
40 |
41 | arm64
42 |
43 | UISupportedInterfaceOrientations
44 |
45 | UIInterfaceOrientationPortrait
46 | UIInterfaceOrientationLandscapeLeft
47 | UIInterfaceOrientationLandscapeRight
48 |
49 | UIViewControllerBasedStatusBarAppearance
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/example/ios/TrueSheetExample/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
24 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/example/ios/TrueSheetExample/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSPrivacyAccessedAPITypes
6 |
7 |
8 | NSPrivacyAccessedAPIType
9 | NSPrivacyAccessedAPICategoryFileTimestamp
10 | NSPrivacyAccessedAPITypeReasons
11 |
12 | C617.1
13 |
14 |
15 |
16 | NSPrivacyAccessedAPIType
17 | NSPrivacyAccessedAPICategoryUserDefaults
18 | NSPrivacyAccessedAPITypeReasons
19 |
20 | CA92.1
21 |
22 |
23 |
24 | NSPrivacyAccessedAPIType
25 | NSPrivacyAccessedAPICategorySystemBootTime
26 | NSPrivacyAccessedAPITypeReasons
27 |
28 | 35F9.1
29 |
30 |
31 |
32 | NSPrivacyCollectedDataTypes
33 |
34 | NSPrivacyTracking
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/example/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'react-native',
3 | }
4 |
--------------------------------------------------------------------------------
/example/metro.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const { getDefaultConfig } = require('@react-native/metro-config')
3 | const { getConfig } = require('react-native-builder-bob/metro-config')
4 | const { wrapWithReanimatedMetroConfig } = require('react-native-reanimated/metro-config')
5 | const pkg = require('../package.json')
6 |
7 | const root = path.resolve(__dirname, '..')
8 |
9 | const config = getConfig(getDefaultConfig(__dirname), {
10 | root,
11 | pkg,
12 | project: __dirname,
13 | })
14 |
15 | /**
16 | * Metro configuration
17 | * https://facebook.github.io/metro/docs/configuration
18 | *
19 | * @type {import('metro-config').MetroConfig}
20 | */
21 | module.exports = wrapWithReanimatedMetroConfig(config)
22 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-true-sheet-example",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "android": "react-native run-android",
7 | "ios": "react-native run-ios",
8 | "start": "react-native start",
9 | "build:android": "react-native build-android --extra-params \"--no-daemon --console=plain -PreactNativeArchitectures=arm64-v8a\"",
10 | "build:ios": "react-native build-ios --scheme TrueSheetExample --mode Debug --extra-params \"-sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO\""
11 | },
12 | "dependencies": {
13 | "@react-navigation/native": "^7.0.14",
14 | "@react-navigation/native-stack": "^7.2.0",
15 | "react": "19.0.0",
16 | "react-native": "0.78.0",
17 | "react-native-edge-to-edge": "^1.4.3",
18 | "react-native-gesture-handler": "^2.24.0",
19 | "react-native-maps": "^1.20.1",
20 | "react-native-reanimated": "^3.17.1",
21 | "react-native-safe-area-context": "^5.3.0",
22 | "react-native-screens": "^4.9.1"
23 | },
24 | "devDependencies": {
25 | "@babel/core": "^7.25.2",
26 | "@babel/preset-env": "^7.25.3",
27 | "@babel/runtime": "^7.25.0",
28 | "@react-native-community/cli": "15.0.1",
29 | "@react-native-community/cli-platform-android": "15.0.1",
30 | "@react-native-community/cli-platform-ios": "15.0.1",
31 | "@react-native/babel-preset": "0.78.0",
32 | "@react-native/metro-config": "0.78.0",
33 | "@react-native/typescript-config": "0.78.0",
34 | "react-native-builder-bob": "^0.36.0"
35 | },
36 | "engines": {
37 | "node": ">=18"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/example/react-native.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const pkg = require('../package.json')
3 |
4 | module.exports = {
5 | project: {
6 | ios: {
7 | automaticPodsInstallation: true,
8 | },
9 | },
10 | dependencies: {
11 | [pkg.name]: {
12 | root: path.join(__dirname, '..'),
13 | platforms: {
14 | // Codegen script incorrectly fails without this
15 | // So we explicitly specify the platforms with empty object
16 | ios: {},
17 | android: {},
18 | },
19 | },
20 | },
21 | }
22 |
--------------------------------------------------------------------------------
/example/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { NavigationContainer } from '@react-navigation/native'
2 | import { createNativeStackNavigator } from '@react-navigation/native-stack'
3 |
4 | import { MapScreen, NavigationScreen, ChildScreen } from './screens'
5 | import type { AppStackParamList } from './types'
6 |
7 | const Stack = createNativeStackNavigator()
8 |
9 | const App = () => {
10 | return (
11 |
12 |
16 |
17 |
22 |
23 |
24 |
25 | )
26 | }
27 |
28 | export default App
29 |
--------------------------------------------------------------------------------
/example/src/components/Button.tsx:
--------------------------------------------------------------------------------
1 | import { Text, TouchableOpacity, type TouchableOpacityProps, type ViewStyle } from 'react-native'
2 |
3 | import { $WHITE_TEXT, BORDER_RADIUS, DARK_BLUE } from '../utils'
4 |
5 | interface ButtonProps extends TouchableOpacityProps {
6 | text: string
7 | }
8 |
9 | export const Button = (props: ButtonProps) => {
10 | const { text, style: $styleOverride, ...rest } = props
11 | return (
12 |
13 | {text}
14 |
15 | )
16 | }
17 |
18 | const $button: ViewStyle = {
19 | height: 40,
20 | padding: 12,
21 | borderRadius: BORDER_RADIUS,
22 | backgroundColor: DARK_BLUE,
23 | marginBottom: 12,
24 | alignItems: 'center',
25 | }
26 |
--------------------------------------------------------------------------------
/example/src/components/DemoContent.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | View,
3 | type ColorValue,
4 | type ViewProps,
5 | Text,
6 | type ViewStyle,
7 | type TextStyle,
8 | } from 'react-native'
9 | import { BORDER_RADIUS, SPACING } from '../utils'
10 |
11 | interface DemoContentProps extends ViewProps {
12 | radius?: number
13 | color?: ColorValue
14 | text?: string
15 | }
16 |
17 | export const DemoContent = (props: DemoContentProps) => {
18 | const { text, radius = BORDER_RADIUS, style: $style, color = 'rgba(0,0,0,0.2)', ...rest } = props
19 | return (
20 |
21 | {text && {text}}
22 |
23 | )
24 | }
25 |
26 | const $content: ViewStyle = {
27 | height: 100,
28 | marginBottom: 16,
29 | padding: SPACING / 2,
30 | alignItems: 'center',
31 | }
32 |
33 | const $text: TextStyle = {
34 | fontSize: 16,
35 | lineHeight: 20,
36 | color: 'white',
37 | }
38 |
--------------------------------------------------------------------------------
/example/src/components/Footer.tsx:
--------------------------------------------------------------------------------
1 | import { Text, View, type ViewStyle } from 'react-native'
2 |
3 | import { $WHITE_TEXT, DARK_GRAY, FOOTER_HEIGHT } from '../utils'
4 |
5 | export const Footer = () => {
6 | return (
7 |
8 | FOOTER
9 |
10 | )
11 | }
12 |
13 | const $footer: ViewStyle = {
14 | height: FOOTER_HEIGHT,
15 | backgroundColor: DARK_GRAY,
16 | alignItems: 'center',
17 | justifyContent: 'center',
18 | }
19 |
--------------------------------------------------------------------------------
/example/src/components/Input.tsx:
--------------------------------------------------------------------------------
1 | import { TextInput, View, type TextStyle, type ViewStyle } from 'react-native'
2 |
3 | import { BORDER_RADIUS, GRAY, INPUT_HEIGHT, SPACING } from '../utils'
4 |
5 | export const Input = () => {
6 | return (
7 |
8 |
9 |
10 | )
11 | }
12 |
13 | const $inputContainer: ViewStyle = {
14 | backgroundColor: 'white',
15 | paddingHorizontal: SPACING,
16 | height: INPUT_HEIGHT,
17 | borderRadius: BORDER_RADIUS,
18 | justifyContent: 'center',
19 | marginBottom: SPACING,
20 | }
21 |
22 | const $input: TextStyle = {
23 | fontSize: 16,
24 | height: INPUT_HEIGHT,
25 | }
26 |
--------------------------------------------------------------------------------
/example/src/components/Spacer.tsx:
--------------------------------------------------------------------------------
1 | import { View, type ViewProps } from 'react-native'
2 |
3 | import { SPACING } from '../utils'
4 |
5 | interface SpacerProps extends ViewProps {
6 | space?: number
7 | }
8 |
9 | export const Spacer = (props: SpacerProps) => {
10 | const { space = SPACING, style: $styleOverride, ...rest } = props
11 | return
12 | }
13 |
--------------------------------------------------------------------------------
/example/src/components/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Footer'
2 | export * from './DemoContent'
3 | export * from './Button'
4 | export * from './Spacer'
5 | export * from './Input'
6 |
--------------------------------------------------------------------------------
/example/src/components/sheets/BasicSheet.tsx:
--------------------------------------------------------------------------------
1 | import { forwardRef, useRef, type Ref, useImperativeHandle } from 'react'
2 | import { type ViewStyle } from 'react-native'
3 | import { TrueSheet, type TrueSheetProps } from '@lodev09/react-native-true-sheet'
4 |
5 | import { DARK, DARK_BLUE, GRABBER_COLOR, SPACING } from '../../utils'
6 | import { DemoContent } from '../DemoContent'
7 | import { Footer } from '../Footer'
8 | import { Button } from '../Button'
9 | import { Spacer } from '../Spacer'
10 |
11 | interface BasicSheetProps extends TrueSheetProps {}
12 |
13 | export const BasicSheet = forwardRef((props: BasicSheetProps, ref: Ref) => {
14 | const sheetRef = useRef(null)
15 | const childSheet = useRef(null)
16 |
17 | const resize = async (index: number) => {
18 | await sheetRef.current?.resize(index)
19 | console.log(`Basic sheet resize to ${index} async`)
20 | }
21 |
22 | const dismiss = async () => {
23 | await sheetRef.current?.dismiss()
24 | console.log('Basic sheet dismiss asynced')
25 | }
26 |
27 | const presentChild = async () => {
28 | // Note: no need to dismiss this sheet 😎
29 | await childSheet.current?.present()
30 |
31 | console.log('Child sheet presented!')
32 | }
33 |
34 | const presentPromptSheet = async () => {
35 | // Note: we need to dismiss this sheet first
36 | await sheetRef.current?.dismiss()
37 |
38 | await TrueSheet.present('prompt-sheet')
39 | }
40 |
41 | useImperativeHandle(ref, () => sheetRef.current)
42 |
43 | return (
44 |
54 | console.log(
55 | `drag changed with size of ${e.nativeEvent.value} at index: ${e.nativeEvent.index}`
56 | )
57 | }
58 | onDragBegin={(e) =>
59 | console.log(
60 | `drag began with size of ${e.nativeEvent.value} at index: ${e.nativeEvent.index}`
61 | )
62 | }
63 | onDragEnd={(e) =>
64 | console.log(
65 | `drag ended with size of ${e.nativeEvent.value} at index: ${e.nativeEvent.index}`
66 | )
67 | }
68 | onDismiss={() => console.log('Basic sheet dismissed!')}
69 | onPresent={(e) =>
70 | console.log(
71 | `Basic sheet presented with size of ${e.nativeEvent.value} at index: ${e.nativeEvent.index}`
72 | )
73 | }
74 | onSizeChange={(e) =>
75 | console.log(`Resized to:`, e.nativeEvent.value, 'at index:', e.nativeEvent.index)
76 | }
77 | FooterComponent={}
78 | {...props}
79 | >
80 |
81 |
103 |
104 | )
105 | })
106 |
107 | const $content: ViewStyle = {
108 | padding: SPACING,
109 | }
110 |
111 | BasicSheet.displayName = 'BasicSheet'
112 |
--------------------------------------------------------------------------------
/example/src/components/sheets/BlankSheet.tsx:
--------------------------------------------------------------------------------
1 | import { forwardRef, type Ref } from 'react'
2 | import { Text, type ViewStyle } from 'react-native'
3 | import { TrueSheet, type TrueSheetProps } from '@lodev09/react-native-true-sheet'
4 |
5 | import { $WHITE_TEXT, DARK, SPACING } from '../../utils'
6 |
7 | interface BlankSheetProps extends TrueSheetProps {}
8 |
9 | export const BlankSheet = forwardRef((props: BlankSheetProps, ref: Ref) => {
10 | return (
11 |
22 | Blank Sheet
23 |
24 | )
25 | })
26 |
27 | const $content: ViewStyle = {
28 | padding: SPACING,
29 | }
30 |
31 | BlankSheet.displayName = 'BlankSheet'
32 |
--------------------------------------------------------------------------------
/example/src/components/sheets/FlatListSheet.tsx:
--------------------------------------------------------------------------------
1 | import { forwardRef, useRef, type Ref } from 'react'
2 | import { FlatList, View, type ViewStyle } from 'react-native'
3 | import { TrueSheet, type TrueSheetProps } from '@lodev09/react-native-true-sheet'
4 |
5 | import { DARK, DARK_GRAY, INPUT_HEIGHT, SPACING, times } from '../../utils'
6 | import { Input } from '../Input'
7 | import { DemoContent } from '../DemoContent'
8 |
9 | interface FlatListSheetProps extends TrueSheetProps {}
10 |
11 | export const FlatListSheet = forwardRef((props: FlatListSheetProps, ref: Ref) => {
12 | const flatListRef = useRef(null)
13 |
14 | return (
15 | console.log('Sheet FlatList dismissed!')}
25 | onPresent={() => console.log(`Sheet FlatList presented!`)}
26 | {...props}
27 | >
28 |
29 |
30 |
31 |
32 | ref={flatListRef}
33 | nestedScrollEnabled
34 | data={times(50, (i) => i)}
35 | contentContainerStyle={$content}
36 | indicatorStyle="black"
37 | renderItem={() => }
38 | />
39 |
40 | )
41 | })
42 |
43 | FlatListSheet.displayName = 'FlatListSheet'
44 |
45 | const $content: ViewStyle = {
46 | padding: SPACING,
47 | paddingTop: INPUT_HEIGHT + SPACING * 4,
48 | }
49 |
50 | const $header: ViewStyle = {
51 | position: 'absolute',
52 | left: 0,
53 | right: 0,
54 | top: 0,
55 | backgroundColor: DARK,
56 | paddingTop: SPACING * 2,
57 | paddingHorizontal: SPACING,
58 | zIndex: 1,
59 | }
60 |
--------------------------------------------------------------------------------
/example/src/components/sheets/GestureSheet.tsx:
--------------------------------------------------------------------------------
1 | import { forwardRef, useRef, type Ref, useImperativeHandle } from 'react'
2 | import { useWindowDimensions, type ViewStyle } from 'react-native'
3 | import { TrueSheet, type TrueSheetProps } from '@lodev09/react-native-true-sheet'
4 | import Animated, { useAnimatedStyle, useSharedValue, withDecay } from 'react-native-reanimated'
5 | import { Gesture, GestureDetector, GestureHandlerRootView } from 'react-native-gesture-handler'
6 |
7 | import { DARK, DARK_GRAY, GRABBER_COLOR, SPACING, times } from '../../utils'
8 | import { Footer } from '../Footer'
9 | import { Button } from '../Button'
10 | import { DemoContent } from '../DemoContent'
11 |
12 | const BOXES_COUNT = 20
13 | const CONTAINER_HEIGHT = 200
14 | const BOX_GAP = SPACING
15 | const BOX_SIZE = CONTAINER_HEIGHT - SPACING * 2
16 |
17 | interface GestureSheetProps extends TrueSheetProps {}
18 |
19 | export const GestureSheet = forwardRef((props: GestureSheetProps, ref: Ref) => {
20 | const sheetRef = useRef(null)
21 |
22 | const scrollX = useSharedValue(0)
23 | const dimensions = useWindowDimensions()
24 |
25 | const dismiss = async () => {
26 | await sheetRef.current?.dismiss()
27 | }
28 |
29 | const $animatedContainer: ViewStyle = useAnimatedStyle(() => ({
30 | transform: [{ translateX: scrollX.value }],
31 | }))
32 |
33 | const pan = Gesture.Pan()
34 | .onChange((e) => {
35 | scrollX.value += e.changeX
36 | })
37 | .onFinalize((e) => {
38 | scrollX.value = withDecay({
39 | velocity: e.velocityX,
40 | rubberBandEffect: true,
41 | clamp: [-((BOX_SIZE + BOX_GAP) * BOXES_COUNT) + dimensions.width - SPACING, 0],
42 | })
43 | })
44 | .activeOffsetX([-10, 10])
45 |
46 | useImperativeHandle(ref, () => sheetRef.current)
47 |
48 | return (
49 | console.log('Gesture sheet dismissed!')}
59 | onPresent={(e) =>
60 | console.log(
61 | `Gesture sheet presented with size of ${e.nativeEvent.value} at index: ${e.nativeEvent.index}`
62 | )
63 | }
64 | onSizeChange={(e) =>
65 | console.log(`Resized to:`, e.nativeEvent.value, 'at index:', e.nativeEvent.index)
66 | }
67 | FooterComponent={}
68 | {...props}
69 | >
70 |
71 |
72 |
73 | {times(BOXES_COUNT, (i) => (
74 |
75 | ))}
76 |
77 |
78 |
79 |
80 |
81 | )
82 | })
83 |
84 | const $gestureRoot: ViewStyle = {
85 | flexGrow: 1,
86 | }
87 |
88 | const $box: ViewStyle = {
89 | alignItems: 'center',
90 | backgroundColor: DARK_GRAY,
91 | height: BOX_SIZE,
92 | justifyContent: 'center',
93 | width: BOX_SIZE,
94 | }
95 |
96 | const $content: ViewStyle = {
97 | padding: SPACING,
98 | }
99 |
100 | const $panContainer: ViewStyle = {
101 | flexDirection: 'row',
102 | gap: BOX_GAP,
103 | height: CONTAINER_HEIGHT,
104 | marginBottom: SPACING,
105 | paddingVertical: SPACING,
106 | }
107 |
108 | GestureSheet.displayName = 'GestureSheet'
109 |
--------------------------------------------------------------------------------
/example/src/components/sheets/PromptSheet.tsx:
--------------------------------------------------------------------------------
1 | import { forwardRef, useRef, type Ref, useImperativeHandle, useState } from 'react'
2 | import type { ViewStyle } from 'react-native'
3 | import { TrueSheet, type TrueSheetProps } from '@lodev09/react-native-true-sheet'
4 |
5 | import { DARK, DARK_BLUE, GRABBER_COLOR, SPACING } from '../../utils'
6 | import { DemoContent } from '../DemoContent'
7 | import { Input } from '../Input'
8 | import { Button } from '../Button'
9 | import { Footer } from '../Footer'
10 |
11 | interface PromptSheetProps extends TrueSheetProps {}
12 |
13 | export const PromptSheet = forwardRef((props: PromptSheetProps, ref: Ref) => {
14 | const sheetRef = useRef(null)
15 |
16 | const [isSubmitted, setIsSubmitted] = useState(false)
17 |
18 | const handleDismiss = () => {
19 | setIsSubmitted(false)
20 | console.log('Sheet prompt dismissed!')
21 | }
22 |
23 | const dismiss = async () => {
24 | await sheetRef.current?.dismiss()
25 | console.log('Sheet prompt dismiss asynced')
26 | }
27 |
28 | const submit = async () => {
29 | setIsSubmitted(true)
30 | }
31 |
32 | useImperativeHandle(ref, () => sheetRef.current)
33 |
34 | return (
35 |
49 | console.log(
50 | `Sheet prompt presented with size of ${e.nativeEvent.value} at index: ${e.nativeEvent.index}`
51 | )
52 | }
53 | onSizeChange={(e) =>
54 | console.log(`Resized to:`, e.nativeEvent.value, 'at index:', e.nativeEvent.index)
55 | }
56 | FooterComponent={}
57 | {...props}
58 | >
59 |
60 |
61 | {isSubmitted && }
62 |
63 |
64 |
65 | )
66 | })
67 |
68 | PromptSheet.displayName = 'PromptSheet'
69 |
70 | const $content: ViewStyle = {
71 | padding: SPACING,
72 | }
73 |
--------------------------------------------------------------------------------
/example/src/components/sheets/ScrollViewSheet.tsx:
--------------------------------------------------------------------------------
1 | import { forwardRef, useRef, type Ref } from 'react'
2 | import { ScrollView, type ViewStyle } from 'react-native'
3 | import { TrueSheet, type TrueSheetProps } from '@lodev09/react-native-true-sheet'
4 |
5 | import { FOOTER_HEIGHT, SPACING, times } from '../../utils'
6 | import { Footer } from '../Footer'
7 | import { DemoContent } from '../DemoContent'
8 |
9 | interface ScrollViewSheetProps extends TrueSheetProps {}
10 |
11 | export const ScrollViewSheet = forwardRef((props: ScrollViewSheetProps, ref: Ref) => {
12 | const scrollViewRef = useRef(null)
13 |
14 | return (
15 | console.log('Sheet ScrollView dismissed!')}
21 | onPresent={() => console.log(`Sheet ScrollView presented!`)}
22 | FooterComponent={}
23 | edgeToEdge
24 | {...props}
25 | >
26 |
32 | {times(25, (i) => (
33 |
34 | ))}
35 |
36 |
37 | )
38 | })
39 |
40 | ScrollViewSheet.displayName = 'ScrollViewSheet'
41 |
42 | const $content: ViewStyle = {
43 | padding: SPACING,
44 | paddingBottom: FOOTER_HEIGHT + SPACING,
45 | }
46 |
--------------------------------------------------------------------------------
/example/src/components/sheets/index.ts:
--------------------------------------------------------------------------------
1 | export * from './BasicSheet'
2 | export * from './PromptSheet'
3 | export * from './ScrollViewSheet'
4 | export * from './FlatListSheet'
5 | export * from './GestureSheet'
6 | export * from './BlankSheet'
7 |
--------------------------------------------------------------------------------
/example/src/hooks/index.ts:
--------------------------------------------------------------------------------
1 | export * from './useAppNavigation'
2 | export * from './useDragChangeHandler'
3 |
--------------------------------------------------------------------------------
/example/src/hooks/useAppNavigation.ts:
--------------------------------------------------------------------------------
1 | import type { NativeStackNavigationProp } from '@react-navigation/native-stack'
2 | import { useNavigation } from '@react-navigation/native'
3 |
4 | import type { AppStackParamList } from '../types'
5 |
6 | export const useAppNavigation = () =>
7 | useNavigation>()
8 |
--------------------------------------------------------------------------------
/example/src/hooks/useDragChangeHandler.ts:
--------------------------------------------------------------------------------
1 | import { useEvent, useHandler } from 'react-native-reanimated'
2 | import type { DependencyList } from 'react-native-reanimated/lib/typescript/hook'
3 | import type { DragChangeEvent, SizeInfo } from '@lodev09/react-native-true-sheet'
4 |
5 | type DragChangeHandler = (sizeInfo: SizeInfo, context: unknown) => void
6 |
7 | export const useDragChangeHandler = (
8 | handler: DragChangeHandler,
9 | dependencies: DependencyList = []
10 | ) => {
11 | const handlers = {
12 | onDragChange: handler,
13 | }
14 |
15 | const { context, doDependenciesDiffer } = useHandler(handlers, dependencies)
16 |
17 | return useEvent(
18 | (event) => {
19 | 'worklet'
20 | const { onDragChange } = handlers
21 | if (onDragChange && event.eventName.endsWith('onDragChange')) {
22 | onDragChange(event, context)
23 | }
24 | },
25 | ['onDragChange'],
26 | doDependenciesDiffer
27 | )
28 | }
29 |
--------------------------------------------------------------------------------
/example/src/screens/ChildScreen.tsx:
--------------------------------------------------------------------------------
1 | import { useRef } from 'react'
2 | import { View, type ViewStyle } from 'react-native'
3 | import type { TrueSheet } from '@lodev09/react-native-true-sheet'
4 |
5 | import { BLUE, SPACING } from '../utils'
6 | import { Button } from '../components'
7 | import { BasicSheet, PromptSheet, ScrollViewSheet } from '../components/sheets'
8 |
9 | export const ChildScreen = () => {
10 | const basicSheet = useRef(null)
11 | const promptSheet = useRef(null)
12 | const scrollViewSheet = useRef(null)
13 |
14 | return (
15 |
16 | basicSheet.current?.present()} />
17 | promptSheet.current?.present()} />
18 | scrollViewSheet.current?.present()} />
19 |
20 |
21 |
22 |
23 |
24 | )
25 | }
26 |
27 | const $container: ViewStyle = {
28 | backgroundColor: BLUE,
29 | justifyContent: 'center',
30 | flex: 1,
31 | padding: SPACING,
32 | }
33 |
--------------------------------------------------------------------------------
/example/src/screens/NavigationScreen.tsx:
--------------------------------------------------------------------------------
1 | import { useRef } from 'react'
2 | import { Text, View, type TextStyle, type ViewStyle } from 'react-native'
3 | import { TrueSheet } from '@lodev09/react-native-true-sheet'
4 |
5 | import {
6 | BasicSheet,
7 | BlankSheet,
8 | FlatListSheet,
9 | GestureSheet,
10 | PromptSheet,
11 | ScrollViewSheet,
12 | } from '../components/sheets'
13 | import { Button, Spacer } from '../components'
14 | import { BLUE, LIGHT_GRAY, SPACING } from '../utils'
15 | import { useAppNavigation } from '../hooks'
16 |
17 | export const NavigationScreen = () => {
18 | const basicSheet = useRef(null)
19 | const promptSheet = useRef(null)
20 | const scrollViewSheet = useRef(null)
21 | const flatListSheet = useRef(null)
22 | const gestureSheet = useRef(null)
23 | const blankSheet = useRef(null)
24 |
25 | const navigation = useAppNavigation()
26 |
27 | const presentBasicSheet = async (index = 0) => {
28 | await basicSheet.current?.present(index)
29 | console.log('Sheet 1 present async')
30 | }
31 |
32 | return (
33 |
34 |
35 | True Sheet 💩
36 | The true native bottom sheet experience.
37 |
38 |
39 | navigation.navigate('Child')} />
40 |
41 |
42 | presentBasicSheet(0)} />
43 | promptSheet.current?.present()} />
44 | scrollViewSheet.current?.present()} />
45 | flatListSheet.current?.present()} />
46 | gestureSheet.current?.present()} />
47 | blankSheet.current?.present()} />
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | )
57 | }
58 |
59 | const $container: ViewStyle = {
60 | backgroundColor: BLUE,
61 | justifyContent: 'center',
62 | flex: 1,
63 | padding: SPACING,
64 | }
65 |
66 | const $heading: ViewStyle = {
67 | marginBottom: SPACING * 2,
68 | }
69 |
70 | const $title: TextStyle = {
71 | fontSize: 24,
72 | lineHeight: 30,
73 | fontWeight: 500,
74 | color: 'white',
75 | }
76 |
77 | const $subtitle: TextStyle = {
78 | lineHeight: 24,
79 | color: LIGHT_GRAY,
80 | }
81 |
--------------------------------------------------------------------------------
/example/src/screens/index.ts:
--------------------------------------------------------------------------------
1 | export * from './MapScreen'
2 | export * from './NavigationScreen'
3 | export * from './ChildScreen'
4 |
--------------------------------------------------------------------------------
/example/src/types.ts:
--------------------------------------------------------------------------------
1 | export type AppStackParamList = {
2 | Map: undefined
3 | Navigation: undefined
4 | Child: undefined
5 | }
6 |
--------------------------------------------------------------------------------
/example/src/utils/constants.ts:
--------------------------------------------------------------------------------
1 | import type { TextStyle } from 'react-native'
2 | import type { WithSpringConfig } from 'react-native-reanimated'
3 |
4 | export const SPACING = 16
5 | export const INPUT_HEIGHT = SPACING * 3
6 | export const FOOTER_HEIGHT = SPACING * 6
7 | export const BORDER_RADIUS = 4
8 | export const GRABBER_COLOR = 'rgba(121, 135, 160, 0.5)'
9 |
10 | export const DARK = '#282e37'
11 | export const GRAY = '#b2bac8'
12 | export const DARK_GRAY = '#333b48'
13 | export const LIGHT_GRAY = '#ebedf1'
14 | export const BLUE = '#3784d7'
15 | export const DARK_BLUE = '#1f64ae'
16 |
17 | export const $WHITE_TEXT: TextStyle = { color: 'white' }
18 |
19 | export const SPRING_CONFIG: WithSpringConfig = {
20 | damping: 500,
21 | stiffness: 1000,
22 | mass: 3,
23 | overshootClamping: true,
24 | restDisplacementThreshold: 10,
25 | restSpeedThreshold: 10,
26 | }
27 |
--------------------------------------------------------------------------------
/example/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from './constants'
2 | export * from './times'
3 | export * from './random'
4 |
--------------------------------------------------------------------------------
/example/src/utils/random.ts:
--------------------------------------------------------------------------------
1 | export const random = (items: T[]) => items[Math.floor(Math.random() * items.length)]
2 |
--------------------------------------------------------------------------------
/example/src/utils/times.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Invokes the iteratee n times, returning an array of the results of each invocation.
3 | * The iteratee is invoked with one argument; (index).
4 | */
5 | export const times = (length: number, iteratee: (index: number) => T): T[] =>
6 | Array.from({ length }, (_, k) => k).map(iteratee)
7 |
--------------------------------------------------------------------------------
/ios/.swift-version:
--------------------------------------------------------------------------------
1 | 5.2
2 |
--------------------------------------------------------------------------------
/ios/.swiftformat:
--------------------------------------------------------------------------------
1 | --allman false
2 | --indent 2
3 | --exclude Pods,Generated
4 |
5 | --disable andOperator
6 | --disable redundantReturn
7 | --disable wrapMultilineStatementBraces
8 | --disable organizeDeclarations
9 |
10 | --enable markTypes
11 |
12 | --enable isEmpty
13 |
--------------------------------------------------------------------------------
/ios/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | disabled_rules:
2 | - identifier_name
3 | - trailing_comma
4 | - todo
5 | - type_body_length
6 | - cyclomatic_complexity
7 | - function_body_length
8 | - for_where
9 | opt_in_rules:
10 | - contains_over_filter_count
11 | - contains_over_filter_is_empty
12 | - contains_over_first_not_nil
13 | - contains_over_range_nil_comparison
14 | - empty_collection_literal
15 | - empty_count
16 | - empty_string
17 | - first_where
18 | - flatmap_over_map_reduce
19 | - last_where
20 | - reduce_boolean
21 | - reduce_into
22 | - yoda_condition
23 | - vertical_whitespace_opening_braces
24 | - vertical_whitespace_closing_braces
25 | - vertical_parameter_alignment_on_call
26 | - untyped_error_in_catch
27 | - unowned_variable_capture
28 | - unavailable_function
29 | - switch_case_on_newline
30 | - static_operator
31 | - strict_fileprivate
32 | - sorted_imports
33 | - sorted_first_last
34 | - required_enum_case
35 | - redundant_type_annotation
36 | - redundant_nil_coalescing
37 | - attributes
38 | - convenience_type
39 | analyzer_rules:
40 | - explicit_self
41 | - unused_declaration
42 | - unused_import
43 |
44 | excluded: # paths to ignore during linting. Takes precedence over `included`.
45 | - Pods
46 |
47 | # Adjust rule numbers
48 | line_length: 160
49 | file_length: 500
50 |
51 | # reporter type (xcode, json, csv, checkstyle, codeclimate, junit, html, emoji, sonarqube, markdown, github-actions-logging)
52 | reporter: "xcode"
53 |
--------------------------------------------------------------------------------
/ios/Extensions/UIBlurEffect+withTint.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jovanni Lo (@lodev09)
3 | // Copyright (c) 2024-present. All rights reserved.
4 | //
5 | // This source code is licensed under the MIT license found in the
6 | // LICENSE file in the root directory of this source tree.
7 | //
8 |
9 | extension UIBlurEffect {
10 | convenience init(with tint: String) {
11 | var blurStyle: Style
12 |
13 | switch tint {
14 | case "default":
15 | blurStyle = .regular
16 | case "extraLight":
17 | blurStyle = .extraLight
18 | case "light":
19 | blurStyle = .light
20 | case "regular":
21 | blurStyle = .regular
22 | case "dark":
23 | blurStyle = .dark
24 | case "prominent":
25 | blurStyle = .prominent
26 | case "systemUltraThinMaterial":
27 | blurStyle = .systemUltraThinMaterial
28 | case "systemThinMaterial":
29 | blurStyle = .systemThinMaterial
30 | case "systemMaterial":
31 | blurStyle = .systemMaterial
32 | case "systemThickMaterial":
33 | blurStyle = .systemThickMaterial
34 | case "systemChromeMaterial":
35 | blurStyle = .systemChromeMaterial
36 | case "systemUltraThinMaterialLight":
37 | blurStyle = .systemUltraThinMaterialLight
38 | case "systemThickMaterialLight":
39 | blurStyle = .systemThickMaterialLight
40 | case "systemThinMaterialLight":
41 | blurStyle = .systemThinMaterialLight
42 | case "systemMaterialLight":
43 | blurStyle = .systemMaterialLight
44 | case "systemChromeMaterialLight":
45 | blurStyle = .systemChromeMaterialLight
46 | case "systemUltraThinMaterialDark":
47 | blurStyle = .systemUltraThinMaterialDark
48 | case "systemThinMaterialDark":
49 | blurStyle = .systemThinMaterialDark
50 | case "systemMaterialDark":
51 | blurStyle = .systemMaterialDark
52 | case "systemThickMaterialDark":
53 | blurStyle = .systemThickMaterialDark
54 | case "systemChromeMaterialDark":
55 | blurStyle = .systemChromeMaterialDark
56 | default:
57 | blurStyle = .light
58 | }
59 |
60 | self.init(style: blurStyle)
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/ios/Extensions/UIView+pinTo.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jovanni Lo (@lodev09)
3 | // Copyright (c) 2024-present. All rights reserved.
4 | //
5 | // This source code is licensed under the MIT license found in the
6 | // LICENSE file in the root directory of this source tree.
7 | //
8 |
9 | // MARK: - Constraints
10 |
11 | struct Constraints {
12 | var top: NSLayoutConstraint?
13 | var bottom: NSLayoutConstraint?
14 | var left: NSLayoutConstraint?
15 | var right: NSLayoutConstraint?
16 | var height: NSLayoutConstraint?
17 | }
18 |
19 | extension UIView {
20 | /// Pin a view to the given view.
21 | /// Optionally accepts a completion handler for the resulting constraints
22 | func pinTo(
23 | view: UIView,
24 | from edges: UIRectEdge = .all,
25 | with height: CGFloat? = nil,
26 | constraints: ((Constraints) -> Void)?
27 | ) {
28 | translatesAutoresizingMaskIntoConstraints = false
29 |
30 | var topConstraint: NSLayoutConstraint?
31 | var bottomConstraint: NSLayoutConstraint?
32 | var leftConstraint: NSLayoutConstraint?
33 | var rightConstraint: NSLayoutConstraint?
34 | var heightConstraint: NSLayoutConstraint?
35 |
36 | if edges.contains(.top) {
37 | topConstraint = topAnchor.constraint(equalTo: view.topAnchor)
38 | topConstraint?.isActive = true
39 | }
40 |
41 | if edges.contains(.bottom) {
42 | bottomConstraint = bottomAnchor.constraint(equalTo: view.bottomAnchor)
43 | bottomConstraint?.isActive = true
44 | }
45 |
46 | if edges.contains(.left) {
47 | leftConstraint = leadingAnchor.constraint(equalTo: view.leadingAnchor)
48 | leftConstraint?.isActive = true
49 | }
50 |
51 | if edges.contains(.right) {
52 | rightConstraint = trailingAnchor.constraint(equalTo: view.trailingAnchor)
53 | rightConstraint?.isActive = true
54 | }
55 |
56 | if let height {
57 | heightConstraint = heightAnchor.constraint(equalToConstant: height)
58 | heightConstraint?.isActive = true
59 | }
60 |
61 | constraints?(Constraints(
62 | top: topConstraint,
63 | bottom: bottomConstraint,
64 | left: leftConstraint,
65 | right: rightConstraint,
66 | height: heightConstraint
67 | ))
68 | }
69 |
70 | func unpin() {
71 | translatesAutoresizingMaskIntoConstraints = true
72 | removeConstraints(constraints)
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/ios/TrueSheet-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jovanni Lo (@lodev09)
3 | // Copyright (c) 2024-present. All rights reserved.
4 | //
5 | // This source code is licensed under the MIT license found in the
6 | // LICENSE file in the root directory of this source tree.
7 | //
8 |
9 | #import
10 | #import
11 | #import
12 | #import
13 | #import
14 | #import
15 |
--------------------------------------------------------------------------------
/ios/TrueSheetEvent.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jovanni Lo (@lodev09)
3 | // Copyright (c) 2024-present. All rights reserved.
4 | //
5 | // This source code is licensed under the MIT license found in the
6 | // LICENSE file in the root directory of this source tree.
7 | //
8 |
9 | class TrueSheetEvent: NSObject, RCTEvent {
10 | var viewTag: NSNumber
11 |
12 | private var name: String
13 | private var data: [String: Any]?
14 |
15 | var eventName: String {
16 | return name
17 | }
18 |
19 | var coalescingKey: UInt16 {
20 | return 0
21 | }
22 |
23 | init(viewTag: NSNumber, name: String, data: [String: Any]?) {
24 | self.name = name
25 | self.viewTag = viewTag
26 | self.data = data
27 | }
28 |
29 | static func moduleDotMethod() -> String {
30 | return "RCTEventEmitter.receiveEvent"
31 | }
32 |
33 | func arguments() -> [Any] {
34 | return [
35 | viewTag,
36 | RCTNormalizeInputEventName(eventName)!,
37 | data ?? [:],
38 | ]
39 | }
40 |
41 | func canCoalesce() -> Bool {
42 | return true
43 | }
44 |
45 | func coalesce(with newEvent: RCTEvent) -> RCTEvent {
46 | return newEvent
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/ios/TrueSheetViewManager.m:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jovanni Lo (@lodev09)
3 | // Copyright (c) 2024-present. All rights reserved.
4 | //
5 | // This source code is licensed under the MIT license found in the
6 | // LICENSE file in the root directory of this source tree.
7 | //
8 |
9 | #import
10 |
11 | @interface RCT_EXTERN_REMAP_MODULE (TrueSheetView, TrueSheetViewManager, RCTViewManager)
12 |
13 | // Module Functions
14 |
15 | /// Presents the sheet controller
16 | RCT_EXTERN_METHOD(present:(nonnull NSNumber*)tag
17 | index:(int)index
18 | resolve:(RCTPromiseResolveBlock)resolve
19 | reject:(RCTPromiseRejectBlock)reject)
20 |
21 | RCT_EXTERN_METHOD(dismiss:(nonnull NSNumber*)tag
22 | resolve:(RCTPromiseResolveBlock)resolve
23 | reject:(RCTPromiseRejectBlock)reject)
24 |
25 | // Events
26 | RCT_EXPORT_VIEW_PROPERTY(onMount, RCTDirectEventBlock)
27 | RCT_EXPORT_VIEW_PROPERTY(onPresent, RCTDirectEventBlock)
28 | RCT_EXPORT_VIEW_PROPERTY(onDismiss, RCTDirectEventBlock)
29 | RCT_EXPORT_VIEW_PROPERTY(onSizeChange, RCTDirectEventBlock)
30 | RCT_EXPORT_VIEW_PROPERTY(onDragBegin, RCTDirectEventBlock)
31 | RCT_EXPORT_VIEW_PROPERTY(onDragChange, RCTDirectEventBlock)
32 | RCT_EXPORT_VIEW_PROPERTY(onDragEnd, RCTDirectEventBlock)
33 | RCT_EXPORT_VIEW_PROPERTY(onContainerSizeChange, RCTDirectEventBlock)
34 |
35 | // Properties
36 | RCT_EXPORT_VIEW_PROPERTY(scrollableHandle, NSNumber)
37 | RCT_EXPORT_VIEW_PROPERTY(maxHeight, NSNumber)
38 | RCT_EXPORT_VIEW_PROPERTY(sizes, NSArray)
39 | RCT_EXPORT_VIEW_PROPERTY(blurTint, NSString)
40 | RCT_EXPORT_VIEW_PROPERTY(background, NSNumber)
41 | RCT_EXPORT_VIEW_PROPERTY(cornerRadius, NSNumber)
42 | RCT_EXPORT_VIEW_PROPERTY(grabber, BOOL)
43 | RCT_EXPORT_VIEW_PROPERTY(dismissible, BOOL)
44 | RCT_EXPORT_VIEW_PROPERTY(dimmed, BOOL)
45 | RCT_EXPORT_VIEW_PROPERTY(dimmedIndex, NSNumber)
46 | RCT_EXPORT_VIEW_PROPERTY(initialIndex, NSNumber)
47 | RCT_EXPORT_VIEW_PROPERTY(initialIndexAnimated, BOOL)
48 |
49 | // Internal properties
50 | RCT_EXPORT_VIEW_PROPERTY(contentHeight, NSNumber)
51 | RCT_EXPORT_VIEW_PROPERTY(footerHeight, NSNumber)
52 |
53 | @end
54 |
--------------------------------------------------------------------------------
/ios/TrueSheetViewManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jovanni Lo (@lodev09)
3 | // Copyright (c) 2024-present. All rights reserved.
4 | //
5 | // This source code is licensed under the MIT license found in the
6 | // LICENSE file in the root directory of this source tree.
7 | //
8 |
9 | @objc(TrueSheetViewManager)
10 | class TrueSheetViewManager: RCTViewManager {
11 | // MARK: - properties
12 |
13 | override var methodQueue: DispatchQueue! {
14 | return DispatchQueue.main
15 | }
16 |
17 | override static func requiresMainQueueSetup() -> Bool {
18 | return true
19 | }
20 |
21 | override func view() -> UIView? {
22 | return TrueSheetView(with: bridge)
23 | }
24 |
25 | // MARK: - Private
26 |
27 | private func getTrueSheetView(_ tag: NSNumber) -> TrueSheetView? {
28 | guard let uiManager = bridge?.uiManager else { return nil }
29 | guard let viewForTag = uiManager.view(forReactTag: tag) else { return nil }
30 | // swiftlint:disable force_cast
31 | return viewForTag as! TrueSheetView
32 | // swiftlint:enable force_cast
33 | }
34 |
35 | // MARK: - React Functions
36 |
37 | @objc
38 | func present(_ tag: NSNumber, index: Int, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
39 | let trueSheetView = getTrueSheetView(tag)
40 | trueSheetView?.present(at: index, promise: Promise(resolver: resolve, rejecter: reject))
41 | }
42 |
43 | @objc
44 | func dismiss(_ tag: NSNumber, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
45 | let trueSheetView = getTrueSheetView(tag)
46 | trueSheetView?.dismiss(promise: Promise(resolver: resolve, rejecter: reject))
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/ios/Utils/Logger.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jovanni Lo (@lodev09)
3 | // Copyright (c) 2024-present. All rights reserved.
4 | //
5 | // This source code is licensed under the MIT license found in the
6 | // LICENSE file in the root directory of this source tree.
7 | //
8 |
9 | import Foundation
10 |
11 | // MARK: - Logger
12 |
13 | enum Logger {
14 | /**
15 | Log a message to the console in the format of `TrueSheet.[caller-function-name]: [message]`
16 |
17 | @discussion
18 | If the global ConsoleLogFunction is set, this function also logs to the JavaScript console (console.log, console.trace, console.warn or console.error)
19 | This function also always logs to [RCTDefaultLogFunction].
20 | In non-DEBUG builds, this function is no-op.
21 | */
22 | static func log(level: RCTLogLevel, _ message: String) {
23 | #if DEBUG
24 | RCTDefaultLogFunction(level, RCTLogSource.javaScript, nil, nil, "TrueSheet: \(message)")
25 | #endif
26 | }
27 |
28 | static func info(_ message: String) {
29 | log(level: .info, message)
30 | }
31 |
32 | static func warning(_ message: String) {
33 | log(level: .warning, message)
34 | }
35 |
36 | static func error(_ message: String) {
37 | log(level: .error, message)
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/ios/Utils/Promise.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jovanni Lo (@lodev09)
3 | // Copyright (c) 2024-present. All rights reserved.
4 | //
5 | // This source code is licensed under the MIT license found in the
6 | // LICENSE file in the root directory of this source tree.
7 | //
8 |
9 | class Promise {
10 | private let resolver: RCTPromiseResolveBlock
11 | private let rejecter: RCTPromiseRejectBlock
12 |
13 | init(resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
14 | self.resolver = resolver
15 | self.rejecter = rejecter
16 | }
17 |
18 | func reject(message: String) {
19 | rejecter("Error", message, nil)
20 | }
21 |
22 | func resolve(_ value: Any?) {
23 | resolver(value)
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lefthook.yml:
--------------------------------------------------------------------------------
1 | pre-commit:
2 | parallel: true
3 | commands:
4 | lint:
5 | glob: "*.{ts,tsx}"
6 | run: npx eslint --fix {staged_files}
7 | types:
8 | glob: "*.{ts, tsx}"
9 | run: npx tsc
10 | prettier:
11 | glob: "*.{ts,tsx}"
12 | run: npx prettier --write {staged_files}
13 | commit-msg:
14 | parallel: true
15 | commands:
16 | commitlint:
17 | run: npx commitlint --edit
18 |
--------------------------------------------------------------------------------
/lib/commonjs/TrueSheet.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | //# sourceMappingURL=TrueSheet.types.js.map
--------------------------------------------------------------------------------
/lib/commonjs/TrueSheet.types.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"names":[],"sourceRoot":"../../src","sources":["TrueSheet.types.ts"],"mappings":"","ignoreList":[]}
2 |
--------------------------------------------------------------------------------
/lib/commonjs/TrueSheetFooter.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.TrueSheetFooter = void 0;
7 | var _jsxRuntime = require("react/jsx-runtime");
8 | const TrueSheetFooter = props => {
9 | const {
10 | Component
11 | } = props;
12 | if (!Component) return null;
13 | if (typeof Component !== 'function') {
14 | return Component;
15 | }
16 | return /*#__PURE__*/(0, _jsxRuntime.jsx)(Component, {});
17 | };
18 | exports.TrueSheetFooter = TrueSheetFooter;
19 | //# sourceMappingURL=TrueSheetFooter.js.map
--------------------------------------------------------------------------------
/lib/commonjs/TrueSheetFooter.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"names":["TrueSheetFooter","props","Component","_jsxRuntime","jsx","exports"],"sourceRoot":"../../src","sources":["TrueSheetFooter.tsx"],"mappings":";;;;;;;AAMO,MAAMA,eAAe,GAAIC,KAA2B,IAAK;EAC9D,MAAM;IAAEC;EAAU,CAAC,GAAGD,KAAK;EAE3B,IAAI,CAACC,SAAS,EAAE,OAAO,IAAI;EAE3B,IAAI,OAAOA,SAAS,KAAK,UAAU,EAAE;IACnC,OAAOA,SAAS;EAClB;EAEA,oBAAO,IAAAC,WAAA,CAAAC,GAAA,EAACF,SAAS,IAAE,CAAC;AACtB,CAAC;AAAAG,OAAA,CAAAL,eAAA,GAAAA,eAAA","ignoreList":[]}
2 |
--------------------------------------------------------------------------------
/lib/commonjs/TrueSheetGrabber.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.TrueSheetGrabber = void 0;
7 | var _reactNative = require("react-native");
8 | var _jsxRuntime = require("react/jsx-runtime");
9 | const GRABBER_DEFAULT_HEIGHT = 4;
10 | const GRABBER_DEFAULT_WIDTH = 32;
11 |
12 | // M3 spec: #49454F 0.4 alpha
13 | const GRABBER_DEFAULT_COLOR = 'rgba(73,69,79,0.4)';
14 | /**
15 | * Grabber component.
16 | * Used by defualt for Android but feel free to re-use.
17 | */
18 | const TrueSheetGrabber = props => {
19 | const {
20 | visible = true,
21 | color = GRABBER_DEFAULT_COLOR,
22 | width = GRABBER_DEFAULT_WIDTH,
23 | height = GRABBER_DEFAULT_HEIGHT,
24 | topOffset = 0,
25 | style
26 | } = props;
27 | if (!visible) return null;
28 | return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
29 | style: [$wrapper, style, {
30 | height: GRABBER_DEFAULT_HEIGHT * 4,
31 | top: topOffset
32 | }],
33 | children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
34 | style: [$grabber, {
35 | height,
36 | width,
37 | backgroundColor: color
38 | }]
39 | })
40 | });
41 | };
42 | exports.TrueSheetGrabber = TrueSheetGrabber;
43 | const $wrapper = {
44 | position: 'absolute',
45 | alignSelf: 'center',
46 | paddingHorizontal: 12,
47 | alignItems: 'center',
48 | justifyContent: 'center',
49 | zIndex: 9999
50 | };
51 | const $grabber = {
52 | borderRadius: GRABBER_DEFAULT_HEIGHT / 2
53 | };
54 | //# sourceMappingURL=TrueSheetGrabber.js.map
--------------------------------------------------------------------------------
/lib/commonjs/TrueSheetGrabber.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"names":["_reactNative","require","_jsxRuntime","GRABBER_DEFAULT_HEIGHT","GRABBER_DEFAULT_WIDTH","GRABBER_DEFAULT_COLOR","TrueSheetGrabber","props","visible","color","width","height","topOffset","style","jsx","View","$wrapper","top","children","$grabber","backgroundColor","exports","position","alignSelf","paddingHorizontal","alignItems","justifyContent","zIndex","borderRadius"],"sourceRoot":"../../src","sources":["TrueSheetGrabber.tsx"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAAoF,IAAAC,WAAA,GAAAD,OAAA;AAEpF,MAAME,sBAAsB,GAAG,CAAC;AAChC,MAAMC,qBAAqB,GAAG,EAAE;;AAEhC;AACA,MAAMC,qBAAqB,GAAG,oBAAoB;AAwClD;AACA;AACA;AACA;AACO,MAAMC,gBAAgB,GAAIC,KAA4B,IAAK;EAChE,MAAM;IACJC,OAAO,GAAG,IAAI;IACdC,KAAK,GAAGJ,qBAAqB;IAC7BK,KAAK,GAAGN,qBAAqB;IAC7BO,MAAM,GAAGR,sBAAsB;IAC/BS,SAAS,GAAG,CAAC;IACbC;EACF,CAAC,GAAGN,KAAK;EAET,IAAI,CAACC,OAAO,EAAE,OAAO,IAAI;EAEzB,oBACE,IAAAN,WAAA,CAAAY,GAAA,EAACd,YAAA,CAAAe,IAAI;IAACF,KAAK,EAAE,CAACG,QAAQ,EAAEH,KAAK,EAAE;MAAEF,MAAM,EAAER,sBAAsB,GAAG,CAAC;MAAEc,GAAG,EAAEL;IAAU,CAAC,CAAE;IAAAM,QAAA,eACrF,IAAAhB,WAAA,CAAAY,GAAA,EAACd,YAAA,CAAAe,IAAI;MAACF,KAAK,EAAE,CAACM,QAAQ,EAAE;QAAER,MAAM;QAAED,KAAK;QAAEU,eAAe,EAAEX;MAAM,CAAC;IAAE,CAAE;EAAC,CAClE,CAAC;AAEX,CAAC;AAAAY,OAAA,CAAAf,gBAAA,GAAAA,gBAAA;AAED,MAAMU,QAAmB,GAAG;EAC1BM,QAAQ,EAAE,UAAU;EACpBC,SAAS,EAAE,QAAQ;EACnBC,iBAAiB,EAAE,EAAE;EACrBC,UAAU,EAAE,QAAQ;EACpBC,cAAc,EAAE,QAAQ;EACxBC,MAAM,EAAE;AACV,CAAC;AAED,MAAMR,QAAmB,GAAG;EAC1BS,YAAY,EAAEzB,sBAAsB,GAAG;AACzC,CAAC","ignoreList":[]}
2 |
--------------------------------------------------------------------------------
/lib/commonjs/TrueSheetModule.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.TrueSheetModule = void 0;
7 | var _reactNative = require("react-native");
8 | const LINKING_ERROR = `The package '@lodev09/react-native-true-sheet' doesn't seem to be linked. Make sure: \n\n` + _reactNative.Platform.select({
9 | ios: "- You have run 'pod install'\n",
10 | default: ''
11 | }) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo Go\n';
12 |
13 | // NativeModules automatically resolves 'TrueSheetView' to 'TrueSheetViewModule'
14 | const TrueSheetModule = exports.TrueSheetModule = _reactNative.NativeModules.TrueSheetView ? _reactNative.NativeModules.TrueSheetView : new Proxy({}, {
15 | get() {
16 | throw new Error(LINKING_ERROR);
17 | }
18 | });
19 | //# sourceMappingURL=TrueSheetModule.js.map
--------------------------------------------------------------------------------
/lib/commonjs/TrueSheetModule.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"names":["_reactNative","require","LINKING_ERROR","Platform","select","ios","default","TrueSheetModule","exports","NativeModules","TrueSheetView","Proxy","get","Error"],"sourceRoot":"../../src","sources":["TrueSheetModule.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAEA,MAAMC,aAAa,GACjB,2FAA2F,GAC3FC,qBAAQ,CAACC,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;;AAEjC;AACO,MAAMC,eAAe,GAAAC,OAAA,CAAAD,eAAA,GAAGE,0BAAa,CAACC,aAAa,GACtDD,0BAAa,CAACC,aAAa,GAC3B,IAAIC,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACX,aAAa,CAAC;EAChC;AACF,CACF,CAAC","ignoreList":[]}
2 |
--------------------------------------------------------------------------------
/lib/commonjs/__mocks__/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | var _exportNames = {
7 | TrueSheet: true
8 | };
9 | exports.TrueSheet = void 0;
10 | var _react = _interopRequireDefault(require("react"));
11 | var _reactNative = require("react-native");
12 | var _jsxRuntime = require("react/jsx-runtime");
13 | var _TrueSheetGrabber = require("../TrueSheetGrabber.js");
14 | Object.keys(_TrueSheetGrabber).forEach(function (key) {
15 | if (key === "default" || key === "__esModule") return;
16 | if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
17 | if (key in exports && exports[key] === _TrueSheetGrabber[key]) return;
18 | Object.defineProperty(exports, key, {
19 | enumerable: true,
20 | get: function () {
21 | return _TrueSheetGrabber[key];
22 | }
23 | });
24 | });
25 | var _TrueSheetFooter = require("../TrueSheetFooter.js");
26 | Object.keys(_TrueSheetFooter).forEach(function (key) {
27 | if (key === "default" || key === "__esModule") return;
28 | if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
29 | if (key in exports && exports[key] === _TrueSheetFooter[key]) return;
30 | Object.defineProperty(exports, key, {
31 | enumerable: true,
32 | get: function () {
33 | return _TrueSheetFooter[key];
34 | }
35 | });
36 | });
37 | function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
38 | class TrueSheet extends _react.default.Component {
39 | static dismiss = jest.fn();
40 | static present = jest.fn();
41 | static resize = jest.fn();
42 | dismiss = jest.fn();
43 | present = jest.fn();
44 | resize = jest.fn();
45 | render() {
46 | return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
47 | ...this.props
48 | });
49 | }
50 | }
51 | exports.TrueSheet = TrueSheet;
52 | //# sourceMappingURL=index.js.map
--------------------------------------------------------------------------------
/lib/commonjs/__mocks__/index.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"names":["_react","_interopRequireDefault","require","_reactNative","_jsxRuntime","_TrueSheetGrabber","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get","_TrueSheetFooter","e","__esModule","default","TrueSheet","React","Component","dismiss","jest","fn","present","resize","render","jsx","View","props"],"sourceRoot":"../../../src","sources":["__mocks__/index.js"],"mappings":";;;;;;;;;AAAA,IAAAA,MAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,YAAA,GAAAD,OAAA;AAAmC,IAAAE,WAAA,GAAAF,OAAA;AAEnC,IAAAG,iBAAA,GAAAH,OAAA;AAAAI,MAAA,CAAAC,IAAA,CAAAF,iBAAA,EAAAG,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAC,YAAA,EAAAJ,GAAA;EAAA,IAAAA,GAAA,IAAAK,OAAA,IAAAA,OAAA,CAAAL,GAAA,MAAAJ,iBAAA,CAAAI,GAAA;EAAAH,MAAA,CAAAS,cAAA,CAAAD,OAAA,EAAAL,GAAA;IAAAO,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAZ,iBAAA,CAAAI,GAAA;IAAA;EAAA;AAAA;AACA,IAAAS,gBAAA,GAAAhB,OAAA;AAAAI,MAAA,CAAAC,IAAA,CAAAW,gBAAA,EAAAV,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAC,YAAA,EAAAJ,GAAA;EAAA,IAAAA,GAAA,IAAAK,OAAA,IAAAA,OAAA,CAAAL,GAAA,MAAAS,gBAAA,CAAAT,GAAA;EAAAH,MAAA,CAAAS,cAAA,CAAAD,OAAA,EAAAL,GAAA;IAAAO,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAC,gBAAA,CAAAT,GAAA;IAAA;EAAA;AAAA;AAAkC,SAAAR,uBAAAkB,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAE3B,MAAMG,SAAS,SAASC,cAAK,CAACC,SAAS,CAAC;EAC7C,OAAOC,OAAO,GAAGC,IAAI,CAACC,EAAE,CAAC,CAAC;EAC1B,OAAOC,OAAO,GAAGF,IAAI,CAACC,EAAE,CAAC,CAAC;EAC1B,OAAOE,MAAM,GAAGH,IAAI,CAACC,EAAE,CAAC,CAAC;EAEzBF,OAAO,GAAGC,IAAI,CAACC,EAAE,CAAC,CAAC;EACnBC,OAAO,GAAGF,IAAI,CAACC,EAAE,CAAC,CAAC;EACnBE,MAAM,GAAGH,IAAI,CAACC,EAAE,CAAC,CAAC;EAElBG,MAAMA,CAAA,EAAG;IACP,oBAAO,IAAA1B,WAAA,CAAA2B,GAAA,EAAC5B,YAAA,CAAA6B,IAAI;MAAA,GAAK,IAAI,CAACC;IAAK,CAAG,CAAC;EACjC;AACF;AAACnB,OAAA,CAAAQ,SAAA,GAAAA,SAAA","ignoreList":[]}
2 |
--------------------------------------------------------------------------------
/lib/commonjs/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | var _TrueSheet = require("./TrueSheet.js");
7 | Object.keys(_TrueSheet).forEach(function (key) {
8 | if (key === "default" || key === "__esModule") return;
9 | if (key in exports && exports[key] === _TrueSheet[key]) return;
10 | Object.defineProperty(exports, key, {
11 | enumerable: true,
12 | get: function () {
13 | return _TrueSheet[key];
14 | }
15 | });
16 | });
17 | var _TrueSheetTypes = require("./TrueSheet.types.js");
18 | Object.keys(_TrueSheetTypes).forEach(function (key) {
19 | if (key === "default" || key === "__esModule") return;
20 | if (key in exports && exports[key] === _TrueSheetTypes[key]) return;
21 | Object.defineProperty(exports, key, {
22 | enumerable: true,
23 | get: function () {
24 | return _TrueSheetTypes[key];
25 | }
26 | });
27 | });
28 | var _TrueSheetGrabber = require("./TrueSheetGrabber.js");
29 | Object.keys(_TrueSheetGrabber).forEach(function (key) {
30 | if (key === "default" || key === "__esModule") return;
31 | if (key in exports && exports[key] === _TrueSheetGrabber[key]) return;
32 | Object.defineProperty(exports, key, {
33 | enumerable: true,
34 | get: function () {
35 | return _TrueSheetGrabber[key];
36 | }
37 | });
38 | });
39 | //# sourceMappingURL=index.js.map
--------------------------------------------------------------------------------
/lib/commonjs/index.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"names":["_TrueSheet","require","Object","keys","forEach","key","exports","defineProperty","enumerable","get","_TrueSheetTypes","_TrueSheetGrabber"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;AAAA,IAAAA,UAAA,GAAAC,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAH,UAAA,EAAAI,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAL,UAAA,CAAAK,GAAA;EAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA;IAAAG,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAT,UAAA,CAAAK,GAAA;IAAA;EAAA;AAAA;AACA,IAAAK,eAAA,GAAAT,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAO,eAAA,EAAAN,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAK,eAAA,CAAAL,GAAA;EAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA;IAAAG,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAC,eAAA,CAAAL,GAAA;IAAA;EAAA;AAAA;AACA,IAAAM,iBAAA,GAAAV,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAQ,iBAAA,EAAAP,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAM,iBAAA,CAAAN,GAAA;EAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA;IAAAG,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAE,iBAAA,CAAAN,GAAA;IAAA;EAAA;AAAA","ignoreList":[]}
2 |
--------------------------------------------------------------------------------
/lib/module/TrueSheet.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | export {};
4 | //# sourceMappingURL=TrueSheet.types.js.map
--------------------------------------------------------------------------------
/lib/module/TrueSheet.types.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"names":[],"sourceRoot":"../../src","sources":["TrueSheet.types.ts"],"mappings":"","ignoreList":[]}
2 |
--------------------------------------------------------------------------------
/lib/module/TrueSheetFooter.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import { jsx as _jsx } from "react/jsx-runtime";
4 | export const TrueSheetFooter = props => {
5 | const {
6 | Component
7 | } = props;
8 | if (!Component) return null;
9 | if (typeof Component !== 'function') {
10 | return Component;
11 | }
12 | return /*#__PURE__*/_jsx(Component, {});
13 | };
14 | //# sourceMappingURL=TrueSheetFooter.js.map
--------------------------------------------------------------------------------
/lib/module/TrueSheetFooter.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"names":["TrueSheetFooter","props","Component","_jsx"],"sourceRoot":"../../src","sources":["TrueSheetFooter.tsx"],"mappings":";;;AAMA,OAAO,MAAMA,eAAe,GAAIC,KAA2B,IAAK;EAC9D,MAAM;IAAEC;EAAU,CAAC,GAAGD,KAAK;EAE3B,IAAI,CAACC,SAAS,EAAE,OAAO,IAAI;EAE3B,IAAI,OAAOA,SAAS,KAAK,UAAU,EAAE;IACnC,OAAOA,SAAS;EAClB;EAEA,oBAAOC,IAAA,CAACD,SAAS,IAAE,CAAC;AACtB,CAAC","ignoreList":[]}
2 |
--------------------------------------------------------------------------------
/lib/module/TrueSheetGrabber.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import { View } from 'react-native';
4 | import { jsx as _jsx } from "react/jsx-runtime";
5 | const GRABBER_DEFAULT_HEIGHT = 4;
6 | const GRABBER_DEFAULT_WIDTH = 32;
7 |
8 | // M3 spec: #49454F 0.4 alpha
9 | const GRABBER_DEFAULT_COLOR = 'rgba(73,69,79,0.4)';
10 | /**
11 | * Grabber component.
12 | * Used by defualt for Android but feel free to re-use.
13 | */
14 | export const TrueSheetGrabber = props => {
15 | const {
16 | visible = true,
17 | color = GRABBER_DEFAULT_COLOR,
18 | width = GRABBER_DEFAULT_WIDTH,
19 | height = GRABBER_DEFAULT_HEIGHT,
20 | topOffset = 0,
21 | style
22 | } = props;
23 | if (!visible) return null;
24 | return /*#__PURE__*/_jsx(View, {
25 | style: [$wrapper, style, {
26 | height: GRABBER_DEFAULT_HEIGHT * 4,
27 | top: topOffset
28 | }],
29 | children: /*#__PURE__*/_jsx(View, {
30 | style: [$grabber, {
31 | height,
32 | width,
33 | backgroundColor: color
34 | }]
35 | })
36 | });
37 | };
38 | const $wrapper = {
39 | position: 'absolute',
40 | alignSelf: 'center',
41 | paddingHorizontal: 12,
42 | alignItems: 'center',
43 | justifyContent: 'center',
44 | zIndex: 9999
45 | };
46 | const $grabber = {
47 | borderRadius: GRABBER_DEFAULT_HEIGHT / 2
48 | };
49 | //# sourceMappingURL=TrueSheetGrabber.js.map
--------------------------------------------------------------------------------
/lib/module/TrueSheetGrabber.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"names":["View","jsx","_jsx","GRABBER_DEFAULT_HEIGHT","GRABBER_DEFAULT_WIDTH","GRABBER_DEFAULT_COLOR","TrueSheetGrabber","props","visible","color","width","height","topOffset","style","$wrapper","top","children","$grabber","backgroundColor","position","alignSelf","paddingHorizontal","alignItems","justifyContent","zIndex","borderRadius"],"sourceRoot":"../../src","sources":["TrueSheetGrabber.tsx"],"mappings":";;AAAA,SAASA,IAAI,QAAyD,cAAc;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAEpF,MAAMC,sBAAsB,GAAG,CAAC;AAChC,MAAMC,qBAAqB,GAAG,EAAE;;AAEhC;AACA,MAAMC,qBAAqB,GAAG,oBAAoB;AAwClD;AACA;AACA;AACA;AACA,OAAO,MAAMC,gBAAgB,GAAIC,KAA4B,IAAK;EAChE,MAAM;IACJC,OAAO,GAAG,IAAI;IACdC,KAAK,GAAGJ,qBAAqB;IAC7BK,KAAK,GAAGN,qBAAqB;IAC7BO,MAAM,GAAGR,sBAAsB;IAC/BS,SAAS,GAAG,CAAC;IACbC;EACF,CAAC,GAAGN,KAAK;EAET,IAAI,CAACC,OAAO,EAAE,OAAO,IAAI;EAEzB,oBACEN,IAAA,CAACF,IAAI;IAACa,KAAK,EAAE,CAACC,QAAQ,EAAED,KAAK,EAAE;MAAEF,MAAM,EAAER,sBAAsB,GAAG,CAAC;MAAEY,GAAG,EAAEH;IAAU,CAAC,CAAE;IAAAI,QAAA,eACrFd,IAAA,CAACF,IAAI;MAACa,KAAK,EAAE,CAACI,QAAQ,EAAE;QAAEN,MAAM;QAAED,KAAK;QAAEQ,eAAe,EAAET;MAAM,CAAC;IAAE,CAAE;EAAC,CAClE,CAAC;AAEX,CAAC;AAED,MAAMK,QAAmB,GAAG;EAC1BK,QAAQ,EAAE,UAAU;EACpBC,SAAS,EAAE,QAAQ;EACnBC,iBAAiB,EAAE,EAAE;EACrBC,UAAU,EAAE,QAAQ;EACpBC,cAAc,EAAE,QAAQ;EACxBC,MAAM,EAAE;AACV,CAAC;AAED,MAAMP,QAAmB,GAAG;EAC1BQ,YAAY,EAAEtB,sBAAsB,GAAG;AACzC,CAAC","ignoreList":[]}
2 |
--------------------------------------------------------------------------------
/lib/module/TrueSheetModule.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import { NativeModules, Platform } from 'react-native';
4 | const LINKING_ERROR = `The package '@lodev09/react-native-true-sheet' doesn't seem to be linked. Make sure: \n\n` + Platform.select({
5 | ios: "- You have run 'pod install'\n",
6 | default: ''
7 | }) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo Go\n';
8 |
9 | // NativeModules automatically resolves 'TrueSheetView' to 'TrueSheetViewModule'
10 | export const TrueSheetModule = NativeModules.TrueSheetView ? NativeModules.TrueSheetView : new Proxy({}, {
11 | get() {
12 | throw new Error(LINKING_ERROR);
13 | }
14 | });
15 | //# sourceMappingURL=TrueSheetModule.js.map
--------------------------------------------------------------------------------
/lib/module/TrueSheetModule.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"names":["NativeModules","Platform","LINKING_ERROR","select","ios","default","TrueSheetModule","TrueSheetView","Proxy","get","Error"],"sourceRoot":"../../src","sources":["TrueSheetModule.ts"],"mappings":";;AAAA,SAASA,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AAEtD,MAAMC,aAAa,GACjB,2FAA2F,GAC3FD,QAAQ,CAACE,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;;AAEjC;AACA,OAAO,MAAMC,eAAe,GAAGN,aAAa,CAACO,aAAa,GACtDP,aAAa,CAACO,aAAa,GAC3B,IAAIC,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACR,aAAa,CAAC;EAChC;AACF,CACF,CAAC","ignoreList":[]}
2 |
--------------------------------------------------------------------------------
/lib/module/__mocks__/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import React from 'react';
4 | import { View } from 'react-native';
5 | import { jsx as _jsx } from "react/jsx-runtime";
6 | export * from "../TrueSheetGrabber.js";
7 | export * from "../TrueSheetFooter.js";
8 | export class TrueSheet extends React.Component {
9 | static dismiss = jest.fn();
10 | static present = jest.fn();
11 | static resize = jest.fn();
12 | dismiss = jest.fn();
13 | present = jest.fn();
14 | resize = jest.fn();
15 | render() {
16 | return /*#__PURE__*/_jsx(View, {
17 | ...this.props
18 | });
19 | }
20 | }
21 | //# sourceMappingURL=index.js.map
--------------------------------------------------------------------------------
/lib/module/__mocks__/index.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"names":["React","View","jsx","_jsx","TrueSheet","Component","dismiss","jest","fn","present","resize","render","props"],"sourceRoot":"../../../src","sources":["__mocks__/index.js"],"mappings":";;AAAA,OAAOA,KAAK,MAAM,OAAO;AACzB,SAASC,IAAI,QAAQ,cAAc;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAEnC,cAAc,wBAAqB;AACnC,cAAc,uBAAoB;AAElC,OAAO,MAAMC,SAAS,SAASJ,KAAK,CAACK,SAAS,CAAC;EAC7C,OAAOC,OAAO,GAAGC,IAAI,CAACC,EAAE,CAAC,CAAC;EAC1B,OAAOC,OAAO,GAAGF,IAAI,CAACC,EAAE,CAAC,CAAC;EAC1B,OAAOE,MAAM,GAAGH,IAAI,CAACC,EAAE,CAAC,CAAC;EAEzBF,OAAO,GAAGC,IAAI,CAACC,EAAE,CAAC,CAAC;EACnBC,OAAO,GAAGF,IAAI,CAACC,EAAE,CAAC,CAAC;EACnBE,MAAM,GAAGH,IAAI,CAACC,EAAE,CAAC,CAAC;EAElBG,MAAMA,CAAA,EAAG;IACP,oBAAOR,IAAA,CAACF,IAAI;MAAA,GAAK,IAAI,CAACW;IAAK,CAAG,CAAC;EACjC;AACF","ignoreList":[]}
2 |
--------------------------------------------------------------------------------
/lib/module/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | export * from "./TrueSheet.js";
4 | export * from "./TrueSheet.types.js";
5 | export * from "./TrueSheetGrabber.js";
6 | //# sourceMappingURL=index.js.map
--------------------------------------------------------------------------------
/lib/module/index.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"names":[],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA,cAAc,gBAAa;AAC3B,cAAc,sBAAmB;AACjC,cAAc,uBAAoB","ignoreList":[]}
2 |
--------------------------------------------------------------------------------
/lib/typescript/commonjs/package.json:
--------------------------------------------------------------------------------
1 | {"type":"commonjs"}
2 |
--------------------------------------------------------------------------------
/lib/typescript/commonjs/src/TrueSheet.d.ts:
--------------------------------------------------------------------------------
1 | import { PureComponent, type ReactNode } from 'react';
2 | import { type NativeSyntheticEvent } from 'react-native';
3 | import type { TrueSheetProps } from './TrueSheet.types';
4 | export type ContainerSizeChangeEvent = NativeSyntheticEvent<{
5 | width: number;
6 | height: number;
7 | }>;
8 | interface TrueSheetState {
9 | containerWidth?: number;
10 | containerHeight?: number;
11 | contentHeight?: number;
12 | footerHeight?: number;
13 | scrollableHandle: number | null;
14 | }
15 | export declare class TrueSheet extends PureComponent {
16 | displayName: string;
17 | private readonly ref;
18 | /**
19 | * Map of sheet names against their handle.
20 | */
21 | private static readonly handles;
22 | constructor(props: TrueSheetProps);
23 | private static getHandle;
24 | /**
25 | * Present the sheet by given `name`.
26 | * See `name` prop.
27 | */
28 | static present(name: string, index?: number): Promise;
29 | /**
30 | * Dismiss the sheet by given `name`.
31 | * See `name` prop.
32 | */
33 | static dismiss(name: string): Promise;
34 | /**
35 | * Resize the sheet by given `name`.
36 | * See `name` prop.
37 | */
38 | static resize(name: string, index: number): Promise;
39 | private get handle();
40 | private updateState;
41 | private onSizeChange;
42 | private onContainerSizeChange;
43 | private onPresent;
44 | private onFooterLayout;
45 | private onContentLayout;
46 | private onDismiss;
47 | private onMount;
48 | private onDragBegin;
49 | private onDragChange;
50 | private onDragEnd;
51 | /**
52 | * Present the sheet. Optionally accepts a size `index`.
53 | * See `sizes` prop
54 | */
55 | present(index?: number): Promise;
56 | /**
57 | * Resizes the Sheet programmatically by `index`.
58 | * This is an alias of the `present(index)` method.
59 | */
60 | resize(index: number): Promise;
61 | /**
62 | * Dismisses the Sheet
63 | */
64 | dismiss(): Promise;
65 | componentDidMount(): void;
66 | componentDidUpdate(): void;
67 | render(): ReactNode;
68 | }
69 | export {};
70 | //# sourceMappingURL=TrueSheet.d.ts.map
--------------------------------------------------------------------------------
/lib/typescript/commonjs/src/TrueSheet.d.ts.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"TrueSheet.d.ts","sourceRoot":"","sources":["../../../../src/TrueSheet.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAwC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAC3F,OAAO,EAOL,KAAK,oBAAoB,EAI1B,MAAM,cAAc,CAAA;AAErB,OAAO,KAAK,EACV,cAAc,EAMf,MAAM,mBAAmB,CAAA;AAY1B,MAAM,MAAM,wBAAwB,GAAG,oBAAoB,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAY9F,UAAU,cAAc;IACtB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;CAChC;AAQD,qBAAa,SAAU,SAAQ,aAAa,CAAC,cAAc,EAAE,cAAc,CAAC;IAC1E,WAAW,SAAc;IAEzB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAsB;IAE1C;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAiC;gBAEpD,KAAK,EAAE,cAAc;IAyBjC,OAAO,CAAC,MAAM,CAAC,SAAS;IAUxB;;;OAGG;WACiB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU;IAO3D;;;OAGG;WACiB,OAAO,CAAC,IAAI,EAAE,MAAM;IAOxC;;;OAGG;WACiB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAItD,OAAO,KAAK,MAAM,GAOjB;IAED,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,qBAAqB;IAO7B,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,SAAS;IAIjB;;;OAGG;IACU,OAAO,CAAC,KAAK,GAAE,MAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAItD;;;OAGG;IACU,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjD;;OAEG;IACU,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrC,iBAAiB,IAAI,IAAI;IAUzB,kBAAkB,IAAI,IAAI;IAI1B,MAAM,IAAI,SAAS;CA8EpB"}
--------------------------------------------------------------------------------
/lib/typescript/commonjs/src/TrueSheet.types.d.ts.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"TrueSheet.types.d.ts","sourceRoot":"","sources":["../../../../src/TrueSheet.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAC9E,OAAO,KAAK,EACV,UAAU,EACV,oBAAoB,EACpB,SAAS,EACT,SAAS,EACT,SAAS,EACV,MAAM,cAAc,CAAA;AAErB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAE/D,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,MAAM,eAAe,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAA;AAC5D,MAAM,MAAM,YAAY,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAA;AACzD,MAAM,MAAM,cAAc,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAA;AAC3D,MAAM,MAAM,eAAe,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAA;AAC5D,MAAM,MAAM,YAAY,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAA;AAEzD;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAChB,OAAO,GACP,MAAM,GACN,SAAS,GACT,YAAY,GACZ,SAAS,GACT,WAAW,GACX,yBAAyB,GACzB,oBAAoB,GACpB,gBAAgB,GAChB,qBAAqB,GACrB,sBAAsB,GACtB,8BAA8B,GAC9B,yBAAyB,GACzB,qBAAqB,GACrB,0BAA0B,GAC1B,2BAA2B,GAC3B,6BAA6B,GAC7B,wBAAwB,GACxB,oBAAoB,GACpB,yBAAyB,GACzB,0BAA0B,CAAA;AAE9B;;;;;GAKG;AACH,MAAM,MAAM,SAAS;AACnB;;;;;GAKG;AACD,MAAM;AAER;;;;;GAKG;GACD,MAAM;AAER;;;;;GAKG;GACD,GAAG,MAAM,GAAG;AAEd;;;;;GAKG;GACD,OAAO;AAET;;;;;GAKG;GACD,QAAQ;AAEV;;;;;GAKG;GACD,OAAO,CAAA;AAEX,MAAM,WAAW,cAAe,SAAQ,SAAS;IAC/C;;;;;;;;;;;;;OAaG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;;;;;;;OAUG;IACH,KAAK,CAAC,EAAE,SAAS,EAAE,CAAA;IAEnB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAEhB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IAErB;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAE9B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IAErB;;;;OAIG;IACH,eAAe,CAAC,EAAE,UAAU,CAAA;IAE5B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IAErB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB;;;;OAIG;IACH,YAAY,CAAC,EAAE,qBAAqB,CAAA;IAEpC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAA;IAEnB;;OAEG;IACH,qBAAqB,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;IAE5C;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAA;IAEzC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;OAEG;IACH,eAAe,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,GAAG,YAAY,CAAA;IAEvD;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAA;IAE/B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IAEpB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IAEpB;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAA;IAEzC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IAEtB;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAA;IAE/C;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAA;IAE7C;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAA;IAE/C;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAA;CAC1C"}
--------------------------------------------------------------------------------
/lib/typescript/commonjs/src/TrueSheetFooter.d.ts:
--------------------------------------------------------------------------------
1 | import type { TrueSheetProps } from './TrueSheet.types';
2 | interface TrueSheetFooterProps {
3 | Component?: TrueSheetProps['FooterComponent'];
4 | }
5 | export declare const TrueSheetFooter: (props: TrueSheetFooterProps) => import("react/jsx-runtime").JSX.Element | null;
6 | export {};
7 | //# sourceMappingURL=TrueSheetFooter.d.ts.map
--------------------------------------------------------------------------------
/lib/typescript/commonjs/src/TrueSheetFooter.d.ts.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"TrueSheetFooter.d.ts","sourceRoot":"","sources":["../../../../src/TrueSheetFooter.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAEvD,UAAU,oBAAoB;IAC5B,SAAS,CAAC,EAAE,cAAc,CAAC,iBAAiB,CAAC,CAAA;CAC9C;AAED,eAAO,MAAM,eAAe,UAAW,oBAAoB,mDAU1D,CAAA"}
--------------------------------------------------------------------------------
/lib/typescript/commonjs/src/TrueSheetGrabber.d.ts:
--------------------------------------------------------------------------------
1 | import { type ColorValue, type ViewStyle, type StyleProp } from 'react-native';
2 | export interface TrueSheetGrabberProps {
3 | /**
4 | * Is grabber visible.
5 | * @default true
6 | */
7 | visible?: boolean;
8 | /**
9 | * Optional style that overrides the default style.
10 | */
11 | style?: StyleProp;
12 | /**
13 | * Grabber color according to M3 specs.
14 | * @default rgba(73,69,79,0.4)
15 | */
16 | color?: ColorValue;
17 | /**
18 | * Grabber height according to M3 specs.
19 | * @default 4
20 | */
21 | height?: number;
22 | /**
23 | * Grabber top position offset.
24 | *
25 | * @default 6
26 | */
27 | topOffset?: number;
28 | /**
29 | * Grabber width according to M3 specs.
30 | * @default 32
31 | */
32 | width?: number;
33 | }
34 | /**
35 | * Grabber component.
36 | * Used by defualt for Android but feel free to re-use.
37 | */
38 | export declare const TrueSheetGrabber: (props: TrueSheetGrabberProps) => import("react/jsx-runtime").JSX.Element | null;
39 | //# sourceMappingURL=TrueSheetGrabber.d.ts.map
--------------------------------------------------------------------------------
/lib/typescript/commonjs/src/TrueSheetGrabber.d.ts.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"TrueSheetGrabber.d.ts","sourceRoot":"","sources":["../../../../src/TrueSheetGrabber.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA;AAQpF,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB;;OAEG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;IAE5B;;;OAGG;IACH,KAAK,CAAC,EAAE,UAAU,CAAA;IAElB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,UAAW,qBAAqB,mDAiB5D,CAAA"}
--------------------------------------------------------------------------------
/lib/typescript/commonjs/src/TrueSheetModule.d.ts:
--------------------------------------------------------------------------------
1 | export declare const TrueSheetModule: any;
2 | //# sourceMappingURL=TrueSheetModule.d.ts.map
--------------------------------------------------------------------------------
/lib/typescript/commonjs/src/TrueSheetModule.d.ts.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"TrueSheetModule.d.ts","sourceRoot":"","sources":["../../../../src/TrueSheetModule.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,eAAe,KASvB,CAAA"}
--------------------------------------------------------------------------------
/lib/typescript/commonjs/src/__tests__/index.test.d.ts:
--------------------------------------------------------------------------------
1 | //# sourceMappingURL=index.test.d.ts.map
--------------------------------------------------------------------------------
/lib/typescript/commonjs/src/__tests__/index.test.d.ts.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../../../src/__tests__/index.test.tsx"],"names":[],"mappings":""}
--------------------------------------------------------------------------------
/lib/typescript/commonjs/src/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from './TrueSheet';
2 | export * from './TrueSheet.types';
3 | export * from './TrueSheetGrabber';
4 | //# sourceMappingURL=index.d.ts.map
--------------------------------------------------------------------------------
/lib/typescript/commonjs/src/index.d.ts.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA"}
--------------------------------------------------------------------------------
/lib/typescript/module/package.json:
--------------------------------------------------------------------------------
1 | {"type":"module"}
2 |
--------------------------------------------------------------------------------
/lib/typescript/module/src/TrueSheet.d.ts:
--------------------------------------------------------------------------------
1 | import { PureComponent, type ReactNode } from 'react';
2 | import { type NativeSyntheticEvent } from 'react-native';
3 | import type { TrueSheetProps } from './TrueSheet.types';
4 | export type ContainerSizeChangeEvent = NativeSyntheticEvent<{
5 | width: number;
6 | height: number;
7 | }>;
8 | interface TrueSheetState {
9 | containerWidth?: number;
10 | containerHeight?: number;
11 | contentHeight?: number;
12 | footerHeight?: number;
13 | scrollableHandle: number | null;
14 | }
15 | export declare class TrueSheet extends PureComponent {
16 | displayName: string;
17 | private readonly ref;
18 | /**
19 | * Map of sheet names against their handle.
20 | */
21 | private static readonly handles;
22 | constructor(props: TrueSheetProps);
23 | private static getHandle;
24 | /**
25 | * Present the sheet by given `name`.
26 | * See `name` prop.
27 | */
28 | static present(name: string, index?: number): Promise;
29 | /**
30 | * Dismiss the sheet by given `name`.
31 | * See `name` prop.
32 | */
33 | static dismiss(name: string): Promise;
34 | /**
35 | * Resize the sheet by given `name`.
36 | * See `name` prop.
37 | */
38 | static resize(name: string, index: number): Promise;
39 | private get handle();
40 | private updateState;
41 | private onSizeChange;
42 | private onContainerSizeChange;
43 | private onPresent;
44 | private onFooterLayout;
45 | private onContentLayout;
46 | private onDismiss;
47 | private onMount;
48 | private onDragBegin;
49 | private onDragChange;
50 | private onDragEnd;
51 | /**
52 | * Present the sheet. Optionally accepts a size `index`.
53 | * See `sizes` prop
54 | */
55 | present(index?: number): Promise;
56 | /**
57 | * Resizes the Sheet programmatically by `index`.
58 | * This is an alias of the `present(index)` method.
59 | */
60 | resize(index: number): Promise;
61 | /**
62 | * Dismisses the Sheet
63 | */
64 | dismiss(): Promise;
65 | componentDidMount(): void;
66 | componentDidUpdate(): void;
67 | render(): ReactNode;
68 | }
69 | export {};
70 | //# sourceMappingURL=TrueSheet.d.ts.map
--------------------------------------------------------------------------------
/lib/typescript/module/src/TrueSheet.d.ts.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"TrueSheet.d.ts","sourceRoot":"","sources":["../../../../src/TrueSheet.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAwC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAC3F,OAAO,EAOL,KAAK,oBAAoB,EAI1B,MAAM,cAAc,CAAA;AAErB,OAAO,KAAK,EACV,cAAc,EAMf,MAAM,mBAAmB,CAAA;AAY1B,MAAM,MAAM,wBAAwB,GAAG,oBAAoB,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAY9F,UAAU,cAAc;IACtB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;CAChC;AAQD,qBAAa,SAAU,SAAQ,aAAa,CAAC,cAAc,EAAE,cAAc,CAAC;IAC1E,WAAW,SAAc;IAEzB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAsB;IAE1C;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAiC;gBAEpD,KAAK,EAAE,cAAc;IAyBjC,OAAO,CAAC,MAAM,CAAC,SAAS;IAUxB;;;OAGG;WACiB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU;IAO3D;;;OAGG;WACiB,OAAO,CAAC,IAAI,EAAE,MAAM;IAOxC;;;OAGG;WACiB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAItD,OAAO,KAAK,MAAM,GAOjB;IAED,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,qBAAqB;IAO7B,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,SAAS;IAIjB;;;OAGG;IACU,OAAO,CAAC,KAAK,GAAE,MAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAItD;;;OAGG;IACU,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjD;;OAEG;IACU,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrC,iBAAiB,IAAI,IAAI;IAUzB,kBAAkB,IAAI,IAAI;IAI1B,MAAM,IAAI,SAAS;CA8EpB"}
--------------------------------------------------------------------------------
/lib/typescript/module/src/TrueSheet.types.d.ts.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"TrueSheet.types.d.ts","sourceRoot":"","sources":["../../../../src/TrueSheet.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAC9E,OAAO,KAAK,EACV,UAAU,EACV,oBAAoB,EACpB,SAAS,EACT,SAAS,EACT,SAAS,EACV,MAAM,cAAc,CAAA;AAErB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAE/D,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,MAAM,eAAe,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAA;AAC5D,MAAM,MAAM,YAAY,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAA;AACzD,MAAM,MAAM,cAAc,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAA;AAC3D,MAAM,MAAM,eAAe,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAA;AAC5D,MAAM,MAAM,YAAY,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAA;AAEzD;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAChB,OAAO,GACP,MAAM,GACN,SAAS,GACT,YAAY,GACZ,SAAS,GACT,WAAW,GACX,yBAAyB,GACzB,oBAAoB,GACpB,gBAAgB,GAChB,qBAAqB,GACrB,sBAAsB,GACtB,8BAA8B,GAC9B,yBAAyB,GACzB,qBAAqB,GACrB,0BAA0B,GAC1B,2BAA2B,GAC3B,6BAA6B,GAC7B,wBAAwB,GACxB,oBAAoB,GACpB,yBAAyB,GACzB,0BAA0B,CAAA;AAE9B;;;;;GAKG;AACH,MAAM,MAAM,SAAS;AACnB;;;;;GAKG;AACD,MAAM;AAER;;;;;GAKG;GACD,MAAM;AAER;;;;;GAKG;GACD,GAAG,MAAM,GAAG;AAEd;;;;;GAKG;GACD,OAAO;AAET;;;;;GAKG;GACD,QAAQ;AAEV;;;;;GAKG;GACD,OAAO,CAAA;AAEX,MAAM,WAAW,cAAe,SAAQ,SAAS;IAC/C;;;;;;;;;;;;;OAaG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;;;;;;;OAUG;IACH,KAAK,CAAC,EAAE,SAAS,EAAE,CAAA;IAEnB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAEhB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IAErB;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAE9B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IAErB;;;;OAIG;IACH,eAAe,CAAC,EAAE,UAAU,CAAA;IAE5B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IAErB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB;;;;OAIG;IACH,YAAY,CAAC,EAAE,qBAAqB,CAAA;IAEpC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAA;IAEnB;;OAEG;IACH,qBAAqB,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;IAE5C;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAA;IAEzC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;OAEG;IACH,eAAe,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,GAAG,YAAY,CAAA;IAEvD;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAA;IAE/B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IAEpB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IAEpB;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAA;IAEzC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IAEtB;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAA;IAE/C;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAA;IAE7C;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAA;IAE/C;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAA;CAC1C"}
--------------------------------------------------------------------------------
/lib/typescript/module/src/TrueSheetFooter.d.ts:
--------------------------------------------------------------------------------
1 | import type { TrueSheetProps } from './TrueSheet.types';
2 | interface TrueSheetFooterProps {
3 | Component?: TrueSheetProps['FooterComponent'];
4 | }
5 | export declare const TrueSheetFooter: (props: TrueSheetFooterProps) => import("react/jsx-runtime").JSX.Element | null;
6 | export {};
7 | //# sourceMappingURL=TrueSheetFooter.d.ts.map
--------------------------------------------------------------------------------
/lib/typescript/module/src/TrueSheetFooter.d.ts.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"TrueSheetFooter.d.ts","sourceRoot":"","sources":["../../../../src/TrueSheetFooter.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAEvD,UAAU,oBAAoB;IAC5B,SAAS,CAAC,EAAE,cAAc,CAAC,iBAAiB,CAAC,CAAA;CAC9C;AAED,eAAO,MAAM,eAAe,UAAW,oBAAoB,mDAU1D,CAAA"}
--------------------------------------------------------------------------------
/lib/typescript/module/src/TrueSheetGrabber.d.ts:
--------------------------------------------------------------------------------
1 | import { type ColorValue, type ViewStyle, type StyleProp } from 'react-native';
2 | export interface TrueSheetGrabberProps {
3 | /**
4 | * Is grabber visible.
5 | * @default true
6 | */
7 | visible?: boolean;
8 | /**
9 | * Optional style that overrides the default style.
10 | */
11 | style?: StyleProp;
12 | /**
13 | * Grabber color according to M3 specs.
14 | * @default rgba(73,69,79,0.4)
15 | */
16 | color?: ColorValue;
17 | /**
18 | * Grabber height according to M3 specs.
19 | * @default 4
20 | */
21 | height?: number;
22 | /**
23 | * Grabber top position offset.
24 | *
25 | * @default 6
26 | */
27 | topOffset?: number;
28 | /**
29 | * Grabber width according to M3 specs.
30 | * @default 32
31 | */
32 | width?: number;
33 | }
34 | /**
35 | * Grabber component.
36 | * Used by defualt for Android but feel free to re-use.
37 | */
38 | export declare const TrueSheetGrabber: (props: TrueSheetGrabberProps) => import("react/jsx-runtime").JSX.Element | null;
39 | //# sourceMappingURL=TrueSheetGrabber.d.ts.map
--------------------------------------------------------------------------------
/lib/typescript/module/src/TrueSheetGrabber.d.ts.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"TrueSheetGrabber.d.ts","sourceRoot":"","sources":["../../../../src/TrueSheetGrabber.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA;AAQpF,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB;;OAEG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;IAE5B;;;OAGG;IACH,KAAK,CAAC,EAAE,UAAU,CAAA;IAElB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,UAAW,qBAAqB,mDAiB5D,CAAA"}
--------------------------------------------------------------------------------
/lib/typescript/module/src/TrueSheetModule.d.ts:
--------------------------------------------------------------------------------
1 | export declare const TrueSheetModule: any;
2 | //# sourceMappingURL=TrueSheetModule.d.ts.map
--------------------------------------------------------------------------------
/lib/typescript/module/src/TrueSheetModule.d.ts.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"TrueSheetModule.d.ts","sourceRoot":"","sources":["../../../../src/TrueSheetModule.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,eAAe,KASvB,CAAA"}
--------------------------------------------------------------------------------
/lib/typescript/module/src/__tests__/index.test.d.ts:
--------------------------------------------------------------------------------
1 | //# sourceMappingURL=index.test.d.ts.map
--------------------------------------------------------------------------------
/lib/typescript/module/src/__tests__/index.test.d.ts.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../../../src/__tests__/index.test.tsx"],"names":[],"mappings":""}
--------------------------------------------------------------------------------
/lib/typescript/module/src/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from './TrueSheet';
2 | export * from './TrueSheet.types';
3 | export * from './TrueSheetGrabber';
4 | //# sourceMappingURL=index.d.ts.map
--------------------------------------------------------------------------------
/lib/typescript/module/src/index.d.ts.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA"}
--------------------------------------------------------------------------------
/scripts/clean.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | echo "[Installing dependencies]"
4 | yarn
5 |
6 | echo "[Cleaning android]"
7 | cd example/android
8 | ./gradlew clean
9 | cd ../..
10 |
11 | echo "[Removing temp directories]"
12 | del-cli android/build example/android/build example/android/app/build example/ios/build
13 |
14 | echo "[Installing pods]"
15 | npx pod-install example
16 | bob build
17 |
--------------------------------------------------------------------------------
/scripts/ktlint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if which ktlint >/dev/null; then
4 | cd android && ktlint --color --relative --editorconfig=./.editorconfig -F ./**/*.kt*
5 | else
6 | echo "error: KTLint not installed, install with 'brew install ktlint' (or manually from https://github.com/pinterest/ktlint)"
7 | exit 1
8 | fi
9 |
--------------------------------------------------------------------------------
/scripts/swiftlint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if which swiftlint >/dev/null; then
4 | cd ios && swiftlint --quiet --fix && swiftlint --quiet && swiftformat --quiet .
5 | else
6 | echo "error: SwiftLint or SwiftFormat not installed, install with 'brew install swiftlint' (or manually from https://github.com/realm/SwiftLint)"
7 | exit 1
8 | fi
9 |
--------------------------------------------------------------------------------
/src/TrueSheetFooter.tsx:
--------------------------------------------------------------------------------
1 | import type { TrueSheetProps } from './TrueSheet.types'
2 |
3 | interface TrueSheetFooterProps {
4 | Component?: TrueSheetProps['FooterComponent']
5 | }
6 |
7 | export const TrueSheetFooter = (props: TrueSheetFooterProps) => {
8 | const { Component } = props
9 |
10 | if (!Component) return null
11 |
12 | if (typeof Component !== 'function') {
13 | return Component
14 | }
15 |
16 | return
17 | }
18 |
--------------------------------------------------------------------------------
/src/TrueSheetGrabber.tsx:
--------------------------------------------------------------------------------
1 | import { View, type ColorValue, type ViewStyle, type StyleProp } from 'react-native'
2 |
3 | const GRABBER_DEFAULT_HEIGHT = 4
4 | const GRABBER_DEFAULT_WIDTH = 32
5 |
6 | // M3 spec: #49454F 0.4 alpha
7 | const GRABBER_DEFAULT_COLOR = 'rgba(73,69,79,0.4)'
8 |
9 | export interface TrueSheetGrabberProps {
10 | /**
11 | * Is grabber visible.
12 | * @default true
13 | */
14 | visible?: boolean
15 |
16 | /**
17 | * Optional style that overrides the default style.
18 | */
19 | style?: StyleProp
20 |
21 | /**
22 | * Grabber color according to M3 specs.
23 | * @default rgba(73,69,79,0.4)
24 | */
25 | color?: ColorValue
26 |
27 | /**
28 | * Grabber height according to M3 specs.
29 | * @default 4
30 | */
31 | height?: number
32 |
33 | /**
34 | * Grabber top position offset.
35 | *
36 | * @default 6
37 | */
38 | topOffset?: number
39 |
40 | /**
41 | * Grabber width according to M3 specs.
42 | * @default 32
43 | */
44 | width?: number
45 | }
46 |
47 | /**
48 | * Grabber component.
49 | * Used by defualt for Android but feel free to re-use.
50 | */
51 | export const TrueSheetGrabber = (props: TrueSheetGrabberProps) => {
52 | const {
53 | visible = true,
54 | color = GRABBER_DEFAULT_COLOR,
55 | width = GRABBER_DEFAULT_WIDTH,
56 | height = GRABBER_DEFAULT_HEIGHT,
57 | topOffset = 0,
58 | style,
59 | } = props
60 |
61 | if (!visible) return null
62 |
63 | return (
64 |
65 |
66 |
67 | )
68 | }
69 |
70 | const $wrapper: ViewStyle = {
71 | position: 'absolute',
72 | alignSelf: 'center',
73 | paddingHorizontal: 12,
74 | alignItems: 'center',
75 | justifyContent: 'center',
76 | zIndex: 9999,
77 | }
78 |
79 | const $grabber: ViewStyle = {
80 | borderRadius: GRABBER_DEFAULT_HEIGHT / 2,
81 | }
82 |
--------------------------------------------------------------------------------
/src/TrueSheetModule.ts:
--------------------------------------------------------------------------------
1 | import { NativeModules, Platform } from 'react-native'
2 |
3 | const LINKING_ERROR =
4 | `The package '@lodev09/react-native-true-sheet' doesn't seem to be linked. Make sure: \n\n` +
5 | Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
6 | '- You rebuilt the app after installing the package\n' +
7 | '- You are not using Expo Go\n'
8 |
9 | // NativeModules automatically resolves 'TrueSheetView' to 'TrueSheetViewModule'
10 | export const TrueSheetModule = NativeModules.TrueSheetView
11 | ? NativeModules.TrueSheetView
12 | : new Proxy(
13 | {},
14 | {
15 | get() {
16 | throw new Error(LINKING_ERROR)
17 | },
18 | }
19 | )
20 |
--------------------------------------------------------------------------------
/src/__mocks__/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { View } from 'react-native'
3 |
4 | export * from '../TrueSheetGrabber'
5 | export * from '../TrueSheetFooter'
6 |
7 | export class TrueSheet extends React.Component {
8 | static dismiss = jest.fn()
9 | static present = jest.fn()
10 | static resize = jest.fn()
11 |
12 | dismiss = jest.fn()
13 | present = jest.fn()
14 | resize = jest.fn()
15 |
16 | render() {
17 | return
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/__tests__/index.test.tsx:
--------------------------------------------------------------------------------
1 | it.todo('write a test')
2 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './TrueSheet'
2 | export * from './TrueSheet.types'
3 | export * from './TrueSheetGrabber'
4 |
--------------------------------------------------------------------------------
/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig",
3 | "exclude": ["example", "lib", "docs"]
4 | }
5 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "rootDir": ".",
4 | "paths": {
5 | "@lodev09/react-native-true-sheet": ["./src/index"]
6 | },
7 | "allowUnreachableCode": false,
8 | "allowUnusedLabels": false,
9 | "esModuleInterop": true,
10 | "forceConsistentCasingInFileNames": true,
11 | "jsx": "react-jsx",
12 | "lib": ["ESNext"],
13 | "module": "ESNext",
14 | "moduleResolution": "Bundler",
15 | "noEmit": true,
16 | "noFallthroughCasesInSwitch": true,
17 | "noImplicitReturns": true,
18 | "noImplicitUseStrict": false,
19 | "noStrictGenericChecks": false,
20 | "noUncheckedIndexedAccess": true,
21 | "noUnusedLocals": true,
22 | "noUnusedParameters": true,
23 | "resolveJsonModule": true,
24 | "resolvePackageJsonImports": false,
25 | "skipLibCheck": true,
26 | "strict": true,
27 | "target": "ESNext",
28 | "verbatimModuleSyntax": true
29 | },
30 | "exclude": ["lib", "build", "src/__mocks__", "docs/.docusaurus"]
31 | }
32 |
--------------------------------------------------------------------------------
/turbo.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://turbo.build/schema.json",
3 | "pipeline": {
4 | "build:android": {
5 | "env": ["ORG_GRADLE_PROJECT_newArchEnabled"],
6 | "inputs": [
7 | "package.json",
8 | "android",
9 | "!android/build",
10 | "src/*.ts",
11 | "src/*.tsx",
12 | "example/package.json",
13 | "example/android",
14 | "!example/android/.gradle",
15 | "!example/android/build",
16 | "!example/android/app/build"
17 | ],
18 | "outputs": []
19 | },
20 | "build:ios": {
21 | "env": ["RCT_NEW_ARCH_ENABLED"],
22 | "inputs": [
23 | "package.json",
24 | "*.podspec",
25 | "ios",
26 | "src/*.ts",
27 | "src/*.tsx",
28 | "example/package.json",
29 | "example/ios",
30 | "!example/ios/build",
31 | "!example/ios/Pods"
32 | ],
33 | "outputs": []
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------