@lodev09/react-native-true-sheet 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +53 -0
  3. package/TrueSheet.podspec +42 -0
  4. package/android/build.gradle +94 -0
  5. package/android/gradle.properties +5 -0
  6. package/android/src/main/AndroidManifest.xml +3 -0
  7. package/android/src/main/AndroidManifestNew.xml +2 -0
  8. package/android/src/main/java/com/lodev09/truesheet/TrueSheetPackage.kt +17 -0
  9. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +20 -0
  10. package/ios/Extensions/UIView+pinTo.swift +25 -0
  11. package/ios/Extensions/UIViewController+detentForSize.swift +112 -0
  12. package/ios/TrueSheet-Bridging-Header.h +9 -0
  13. package/ios/TrueSheetView.swift +249 -0
  14. package/ios/TrueSheetViewController.swift +98 -0
  15. package/ios/TrueSheetViewManager.m +38 -0
  16. package/ios/TrueSheetViewManager.swift +46 -0
  17. package/ios/Utils/Logger.swift +43 -0
  18. package/ios/Utils/Promise.swift +25 -0
  19. package/lib/commonjs/TrueSheet.js +104 -0
  20. package/lib/commonjs/TrueSheet.js.map +1 -0
  21. package/lib/commonjs/TrueSheetModule.js +17 -0
  22. package/lib/commonjs/TrueSheetModule.js.map +1 -0
  23. package/lib/commonjs/index.js +28 -0
  24. package/lib/commonjs/index.js.map +1 -0
  25. package/lib/commonjs/types.js +6 -0
  26. package/lib/commonjs/types.js.map +1 -0
  27. package/lib/module/TrueSheet.js +95 -0
  28. package/lib/module/TrueSheet.js.map +1 -0
  29. package/lib/module/TrueSheetModule.js +11 -0
  30. package/lib/module/TrueSheetModule.js.map +1 -0
  31. package/lib/module/index.js +3 -0
  32. package/lib/module/index.js.map +1 -0
  33. package/lib/module/types.js +2 -0
  34. package/lib/module/types.js.map +1 -0
  35. package/lib/typescript/src/TrueSheet.d.ts +31 -0
  36. package/lib/typescript/src/TrueSheet.d.ts.map +1 -0
  37. package/lib/typescript/src/TrueSheetModule.d.ts +2 -0
  38. package/lib/typescript/src/TrueSheetModule.d.ts.map +1 -0
  39. package/lib/typescript/src/index.d.ts +3 -0
  40. package/lib/typescript/src/index.d.ts.map +1 -0
  41. package/lib/typescript/src/types.d.ts +94 -0
  42. package/lib/typescript/src/types.d.ts.map +1 -0
  43. package/package.json +183 -0
  44. package/src/TrueSheet.tsx +162 -0
  45. package/src/TrueSheetModule.ts +18 -0
  46. package/src/index.ts +2 -0
  47. package/src/types.ts +107 -0
@@ -0,0 +1,94 @@
1
+ import type { Component, ComponentType, RefObject } from 'react';
2
+ import type { ColorValue, ViewProps } from 'react-native';
3
+ export interface SizeChangeEvent {
4
+ index: number;
5
+ value: number;
6
+ }
7
+ /**
8
+ * Supported Sheet size.
9
+ * Requires IOS 15+
10
+ */
11
+ export type SheetSize =
12
+ /**
13
+ * Auto resize based on content height
14
+ *
15
+ * @platform android
16
+ * @platform ios 16+
17
+ */
18
+ 'auto'
19
+ /**
20
+ * Fixed height
21
+ *
22
+ * @platform android
23
+ * @platform ios 16+
24
+ */
25
+ | number
26
+ /**
27
+ * Fixed height in %
28
+ *
29
+ * @platform android
30
+ * @platform ios 16+
31
+ */
32
+ | `${number}%`
33
+ /**
34
+ * Translates to 25%
35
+ *
36
+ * @platform android
37
+ * @platform ios 16+
38
+ */
39
+ | 'small'
40
+ /**
41
+ * Translates to 50%
42
+ *
43
+ * @platform android
44
+ * @platform ios 15+
45
+ */
46
+ | 'medium'
47
+ /**
48
+ * Translates to 100%
49
+ *
50
+ * @platform android
51
+ * @platform ios 15+
52
+ */
53
+ | 'large';
54
+ export interface TrueSheetProps extends ViewProps {
55
+ /**
56
+ * Main sheet background color
57
+ */
58
+ backgroundColor?: ColorValue;
59
+ /**
60
+ * The main scrollable ref that Sheet should handle.
61
+ */
62
+ scrollRef?: RefObject<Component<unknown>>;
63
+ /**
64
+ * The sizes you want the Sheet to support.
65
+ * IMPORTANT! Sort them in ascending order
66
+ *
67
+ * Example:
68
+ * ```ts
69
+ * size={['auto', 400, '80%', 'large']}
70
+ * ```
71
+ *
72
+ * @default ['medium', 'large']
73
+ */
74
+ sizes?: SheetSize[];
75
+ /**
76
+ * A component that floats at the bottom of the Sheet.
77
+ */
78
+ FooterComponent?: ComponentType<unknown>;
79
+ /**
80
+ * Called when the Sheet has been presented.
81
+ * Comes with the size index.
82
+ */
83
+ onPresent?: () => void;
84
+ /**
85
+ * Called when the Sheet has been dismissed
86
+ */
87
+ onDismiss?: () => void;
88
+ /**
89
+ * Called when the size of the sheet has changed.
90
+ * Either by dragging or programatically.
91
+ */
92
+ onSizeChange?: (event: SizeChangeEvent) => void;
93
+ }
94
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAEzD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;GAGG;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;;OAEG;IACH,eAAe,CAAC,EAAE,UAAU,CAAA;IAE5B;;OAEG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAA;IAEzC;;;;;;;;;;OAUG;IACH,KAAK,CAAC,EAAE,SAAS,EAAE,CAAA;IAEnB;;OAEG;IACH,eAAe,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAA;IAExC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IAEtB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IAEtB;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAA;CAChD"}
package/package.json ADDED
@@ -0,0 +1,183 @@
1
+ {
2
+ "name": "@lodev09/react-native-true-sheet",
3
+ "version": "0.1.0",
4
+ "description": "The true native bottom sheet. 💩",
5
+ "main": "lib/commonjs/index",
6
+ "module": "lib/module/index",
7
+ "types": "lib/typescript/src/index.d.ts",
8
+ "react-native": "src/index",
9
+ "source": "src/index",
10
+ "files": [
11
+ "src",
12
+ "lib",
13
+ "android",
14
+ "ios",
15
+ "cpp",
16
+ "*.podspec",
17
+ "!ios/build",
18
+ "!android/build",
19
+ "!android/gradle",
20
+ "!android/gradlew",
21
+ "!android/gradlew.bat",
22
+ "!android/local.properties",
23
+ "!**/__tests__",
24
+ "!**/__fixtures__",
25
+ "!**/__mocks__",
26
+ "!**/.*"
27
+ ],
28
+ "scripts": {
29
+ "example": "yarn workspace true-sheet-example",
30
+ "test": "jest",
31
+ "typecheck": "tsc --noEmit",
32
+ "lint": "eslint --fix \"**/*.{js,ts,tsx}\"",
33
+ "format": "prettier --write \"**/*.{js,ts,tsx}\"",
34
+ "tidy": "yarn typecheck && yarn lint && yarn format && scripts/swiftlint.sh && scripts/swiftformat.sh",
35
+ "clean": "del-cli android/build lib && yarn workspace true-sheet-example clean",
36
+ "prepare": "bob build",
37
+ "release": "release-it"
38
+ },
39
+ "keywords": [
40
+ "react-native",
41
+ "ios",
42
+ "android"
43
+ ],
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "git+https://github.com/lodev09/react-native-true-sheet.git"
47
+ },
48
+ "author": "lodev09 <lodev09@gmail.com> (https://github.com/lodev09)",
49
+ "license": "MIT",
50
+ "bugs": {
51
+ "url": "https://github.com/lodev09/react-native-true-sheet/issues"
52
+ },
53
+ "homepage": "https://github.com/lodev09/react-native-true-sheet#readme",
54
+ "publishConfig": {
55
+ "registry": "https://registry.npmjs.org/"
56
+ },
57
+ "devDependencies": {
58
+ "@commitlint/config-conventional": "^19.0.3",
59
+ "@evilmartians/lefthook": "^1.6.5",
60
+ "@react-native/eslint-config": "^0.73.2",
61
+ "@release-it/conventional-changelog": "^8.0.1",
62
+ "@types/jest": "^29.5.12",
63
+ "@types/react": "^18.2.64",
64
+ "@typescript-eslint/eslint-plugin": "^7.1.1",
65
+ "@typescript-eslint/parser": "^7.1.1",
66
+ "commitlint": "^19.0.3",
67
+ "del-cli": "^5.1.0",
68
+ "eslint": "^8.57.0",
69
+ "eslint-config-prettier": "^9.1.0",
70
+ "eslint-config-standard": "^17.1.0",
71
+ "eslint-plugin-import": "^2.29.1",
72
+ "eslint-plugin-n": "^16.6.2",
73
+ "eslint-plugin-prettier": "^5.1.3",
74
+ "eslint-plugin-promise": "^6.1.1",
75
+ "jest": "^29.7.0",
76
+ "prettier": "^3.2.5",
77
+ "react": "^18.2.0",
78
+ "react-native": "^0.73.5",
79
+ "react-native-builder-bob": "^0.23.2",
80
+ "release-it": "^17.1.1",
81
+ "turbo": "^1.12.5",
82
+ "typescript": "~5.3.3"
83
+ },
84
+ "resolutions": {
85
+ "@types/react": "^18.2.44"
86
+ },
87
+ "peerDependencies": {
88
+ "react": "*",
89
+ "react-native": "*"
90
+ },
91
+ "workspaces": [
92
+ "example"
93
+ ],
94
+ "packageManager": "yarn@4.1.1",
95
+ "jest": {
96
+ "preset": "react-native",
97
+ "modulePathIgnorePatterns": [
98
+ "<rootDir>/example/node_modules",
99
+ "<rootDir>/lib/"
100
+ ]
101
+ },
102
+ "commitlint": {
103
+ "extends": [
104
+ "@commitlint/config-conventional"
105
+ ]
106
+ },
107
+ "release-it": {
108
+ "git": {
109
+ "commitMessage": "chore: release ${version}",
110
+ "tagName": "v${version}"
111
+ },
112
+ "npm": {
113
+ "publish": true
114
+ },
115
+ "github": {
116
+ "release": true,
117
+ "comments": {
118
+ "submit": true,
119
+ "issue": ":rocket: _This issue has been resolved in v${version}. See [${releaseName}](${releaseUrl}) for release notes._",
120
+ "pr": ":rocket: _This pull request is included in v${version}. See [${releaseName}](${releaseUrl}) for release notes._"
121
+ }
122
+ },
123
+ "plugins": {
124
+ "@release-it/conventional-changelog": {
125
+ "preset": "angular"
126
+ }
127
+ }
128
+ },
129
+ "eslintConfig": {
130
+ "root": true,
131
+ "extends": [
132
+ "plugin:@typescript-eslint/recommended",
133
+ "eslint:recommended",
134
+ "plugin:react/recommended",
135
+ "plugin:react-native/all",
136
+ "standard",
137
+ "prettier"
138
+ ],
139
+ "globals": {
140
+ "it": false
141
+ },
142
+ "rules": {
143
+ "@typescript-eslint/no-var-requires": 0,
144
+ "@typescript-eslint/no-unused-vars": [
145
+ "error",
146
+ {
147
+ "argsIgnorePattern": "^_",
148
+ "varsIgnorePattern": "^_"
149
+ }
150
+ ],
151
+ "no-unused-vars": 0
152
+ },
153
+ "settings": {
154
+ "react": {
155
+ "pragma": "React",
156
+ "version": "detect"
157
+ }
158
+ }
159
+ },
160
+ "prettier": {
161
+ "quoteProps": "consistent",
162
+ "singleQuote": true,
163
+ "tabWidth": 2,
164
+ "trailingComma": "es5",
165
+ "useTabs": false,
166
+ "printWidth": 100,
167
+ "semi": false
168
+ },
169
+ "react-native-builder-bob": {
170
+ "source": "src",
171
+ "output": "lib",
172
+ "targets": [
173
+ "commonjs",
174
+ "module",
175
+ [
176
+ "typescript",
177
+ {
178
+ "project": "tsconfig.build.json"
179
+ }
180
+ ]
181
+ ]
182
+ }
183
+ }
@@ -0,0 +1,162 @@
1
+ import React, { PureComponent, Component, type RefObject, createRef, type ReactNode } from 'react'
2
+ import {
3
+ requireNativeComponent,
4
+ Platform,
5
+ findNodeHandle,
6
+ type NativeMethods,
7
+ type ViewStyle,
8
+ View,
9
+ type ViewProps,
10
+ type NativeSyntheticEvent,
11
+ type StyleProp,
12
+ type ColorValue,
13
+ } from 'react-native'
14
+
15
+ import type { TrueSheetProps, SizeChangeEvent } from './types'
16
+ import { TrueSheetModule } from './TrueSheetModule'
17
+
18
+ const LINKING_ERROR =
19
+ `The package '@lodev09/react-native-true-sheet' doesn't seem to be linked. Make sure: \n\n` +
20
+ Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
21
+ '- You rebuilt the app after installing the package\n' +
22
+ '- You are not using Expo Go\n'
23
+
24
+ const ComponentName = 'TrueSheetView'
25
+
26
+ interface TrueSheetNativeViewProps {
27
+ scrollableHandle: number | null
28
+ footerHandle: number | null
29
+ onDismiss: () => void
30
+ onPresent: (event: NativeSyntheticEvent<{ index: number }>) => void
31
+ onSizeChange: (event: NativeSyntheticEvent<SizeChangeEvent>) => void
32
+ children: ReactNode
33
+ backgroundColor?: ColorValue
34
+ style: StyleProp<ViewStyle>
35
+ sizes: TrueSheetProps['sizes']
36
+ }
37
+
38
+ const TrueSheetNativeView = requireNativeComponent<TrueSheetNativeViewProps>(ComponentName)
39
+
40
+ if (!TrueSheetNativeView) {
41
+ throw new Error(LINKING_ERROR)
42
+ }
43
+
44
+ type NativeRef = Component<TrueSheetNativeViewProps> & Readonly<NativeMethods>
45
+ type FooterRef = Component<ViewProps> & Readonly<NativeMethods>
46
+
47
+ interface TrueSheetState {
48
+ scrollableHandle: number | null
49
+ footerHandle: number | null
50
+ }
51
+
52
+ export class TrueSheet extends PureComponent<TrueSheetProps, TrueSheetState> {
53
+ displayName = 'TrueSheet'
54
+
55
+ private readonly ref: RefObject<NativeRef>
56
+ private readonly footerRef: RefObject<FooterRef>
57
+
58
+ constructor(props: TrueSheetProps) {
59
+ super(props)
60
+
61
+ this.ref = createRef<NativeRef>()
62
+ this.footerRef = createRef<FooterRef>()
63
+
64
+ this.onDismiss = this.onDismiss.bind(this)
65
+ this.onPresent = this.onPresent.bind(this)
66
+ this.onSizeChange = this.onSizeChange.bind(this)
67
+
68
+ this.state = {
69
+ scrollableHandle: null,
70
+ footerHandle: null,
71
+ }
72
+ }
73
+
74
+ private get handle(): number {
75
+ const nodeHandle = findNodeHandle(this.ref.current)
76
+ if (nodeHandle == null || nodeHandle === -1) {
77
+ throw new Error(`Could not get native view tag`)
78
+ }
79
+
80
+ return nodeHandle
81
+ }
82
+
83
+ private updateHandles() {
84
+ const scrollableHandle = this.props.scrollRef?.current
85
+ ? findNodeHandle(this.props.scrollRef.current)
86
+ : null
87
+
88
+ const footerHandle = findNodeHandle(this.footerRef.current)
89
+
90
+ this.setState({
91
+ footerHandle,
92
+ scrollableHandle,
93
+ })
94
+ }
95
+
96
+ private onSizeChange(event: NativeSyntheticEvent<SizeChangeEvent>) {
97
+ this.props.onSizeChange?.(event.nativeEvent)
98
+ }
99
+
100
+ private onPresent(): void {
101
+ this.props.onPresent?.()
102
+ }
103
+
104
+ private onDismiss(): void {
105
+ this.props.onDismiss?.()
106
+ }
107
+
108
+ componentDidMount(): void {
109
+ this.updateHandles()
110
+ }
111
+
112
+ componentDidUpdate(): void {
113
+ this.updateHandles()
114
+ }
115
+
116
+ /**
117
+ * Present the modal sheet at size index.
118
+ * See `sizes` prop
119
+ */
120
+ public async present(index: number = 0) {
121
+ await TrueSheetModule.present(this.handle, index)
122
+ }
123
+
124
+ /**
125
+ * Dismiss the Sheet
126
+ */
127
+ public async dismiss() {
128
+ await TrueSheetModule.dismiss(this.handle)
129
+ }
130
+
131
+ render(): ReactNode {
132
+ const FooterComponent = this.props.FooterComponent
133
+
134
+ return (
135
+ <TrueSheetNativeView
136
+ ref={this.ref}
137
+ style={$nativeSheet}
138
+ scrollableHandle={this.state.scrollableHandle}
139
+ footerHandle={this.state.footerHandle}
140
+ sizes={this.props.sizes ?? ['medium', 'large']}
141
+ backgroundColor={this.props.backgroundColor}
142
+ onPresent={this.onPresent}
143
+ onDismiss={this.onDismiss}
144
+ onSizeChange={this.onSizeChange}
145
+ >
146
+ <View>
147
+ <View style={this.props.style}>{this.props.children}</View>
148
+ {!!FooterComponent && (
149
+ <View ref={this.footerRef}>
150
+ <FooterComponent />
151
+ </View>
152
+ )}
153
+ </View>
154
+ </TrueSheetNativeView>
155
+ )
156
+ }
157
+ }
158
+
159
+ const $nativeSheet: ViewStyle = {
160
+ position: 'absolute',
161
+ zIndex: -99,
162
+ }
@@ -0,0 +1,18 @@
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
+ export const TrueSheetModule = NativeModules.TrueSheetViewManager
10
+ ? NativeModules.TrueSheetViewManager
11
+ : new Proxy(
12
+ {},
13
+ {
14
+ get() {
15
+ throw new Error(LINKING_ERROR)
16
+ },
17
+ }
18
+ )
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './types'
2
+ export * from './TrueSheet'
package/src/types.ts ADDED
@@ -0,0 +1,107 @@
1
+ import type { Component, ComponentType, RefObject } from 'react'
2
+ import type { ColorValue, ViewProps } from 'react-native'
3
+
4
+ export interface SizeChangeEvent {
5
+ index: number
6
+ value: number
7
+ }
8
+
9
+ /**
10
+ * Supported Sheet size.
11
+ * Requires IOS 15+
12
+ */
13
+ export type SheetSize =
14
+ /**
15
+ * Auto resize based on content height
16
+ *
17
+ * @platform android
18
+ * @platform ios 16+
19
+ */
20
+ | 'auto'
21
+
22
+ /**
23
+ * Fixed height
24
+ *
25
+ * @platform android
26
+ * @platform ios 16+
27
+ */
28
+ | number
29
+
30
+ /**
31
+ * Fixed height in %
32
+ *
33
+ * @platform android
34
+ * @platform ios 16+
35
+ */
36
+ | `${number}%`
37
+
38
+ /**
39
+ * Translates to 25%
40
+ *
41
+ * @platform android
42
+ * @platform ios 16+
43
+ */
44
+ | 'small'
45
+
46
+ /**
47
+ * Translates to 50%
48
+ *
49
+ * @platform android
50
+ * @platform ios 15+
51
+ */
52
+ | 'medium'
53
+
54
+ /**
55
+ * Translates to 100%
56
+ *
57
+ * @platform android
58
+ * @platform ios 15+
59
+ */
60
+ | 'large'
61
+
62
+ export interface TrueSheetProps extends ViewProps {
63
+ /**
64
+ * Main sheet background color
65
+ */
66
+ backgroundColor?: ColorValue
67
+
68
+ /**
69
+ * The main scrollable ref that Sheet should handle.
70
+ */
71
+ scrollRef?: RefObject<Component<unknown>>
72
+
73
+ /**
74
+ * The sizes you want the Sheet to support.
75
+ * IMPORTANT! Sort them in ascending order
76
+ *
77
+ * Example:
78
+ * ```ts
79
+ * size={['auto', 400, '80%', 'large']}
80
+ * ```
81
+ *
82
+ * @default ['medium', 'large']
83
+ */
84
+ sizes?: SheetSize[]
85
+
86
+ /**
87
+ * A component that floats at the bottom of the Sheet.
88
+ */
89
+ FooterComponent?: ComponentType<unknown>
90
+
91
+ /**
92
+ * Called when the Sheet has been presented.
93
+ * Comes with the size index.
94
+ */
95
+ onPresent?: () => void
96
+
97
+ /**
98
+ * Called when the Sheet has been dismissed
99
+ */
100
+ onDismiss?: () => void
101
+
102
+ /**
103
+ * Called when the size of the sheet has changed.
104
+ * Either by dragging or programatically.
105
+ */
106
+ onSizeChange?: (event: SizeChangeEvent) => void
107
+ }