react-native-nitro-modal 0.2.0 → 0.3.1-rc

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 (83) hide show
  1. package/README.md +52 -4
  2. package/android/src/main/java/com/margelo/nitro/nitromodal/BottomSheetPresenter.kt +399 -34
  3. package/android/src/main/java/com/margelo/nitro/nitromodal/HybridNitroModal.kt +67 -22
  4. package/android/src/main/java/com/margelo/nitro/nitromodal/ModalConfig.kt +35 -1
  5. package/android/src/main/java/com/margelo/nitro/nitromodal/ModalContentRoot.kt +48 -5
  6. package/android/src/main/java/com/margelo/nitro/nitromodal/ModalPresenter.kt +63 -4
  7. package/android/src/main/java/com/margelo/nitro/nitromodal/NitroModalHostView.kt +68 -8
  8. package/ios/HybridNitroModal.swift +115 -20
  9. package/ios/ModalConfig.swift +48 -2
  10. package/ios/NitroModalHostView.swift +73 -8
  11. package/ios/SheetView.swift +647 -0
  12. package/ios/SheetViewController.swift +19 -450
  13. package/lib/module/NitroModal.js +54 -6
  14. package/lib/module/NitroModal.js.map +1 -1
  15. package/lib/module/NitroModalView.web.js +86 -26
  16. package/lib/module/NitroModalView.web.js.map +1 -1
  17. package/lib/module/index.js.map +1 -1
  18. package/lib/module/web/AnimatedValue.js +3 -0
  19. package/lib/module/web/AnimatedValue.js.map +1 -1
  20. package/lib/module/web/ModalConfig.js +10 -4
  21. package/lib/module/web/ModalConfig.js.map +1 -1
  22. package/lib/module/web/ModalController.js +29 -2
  23. package/lib/module/web/ModalController.js.map +1 -1
  24. package/lib/module/web/ModalPresenter.js +47 -12
  25. package/lib/module/web/ModalPresenter.js.map +1 -1
  26. package/lib/module/web/SheetPresenter.js +118 -34
  27. package/lib/module/web/SheetPresenter.js.map +1 -1
  28. package/lib/module/web/dom.js +16 -0
  29. package/lib/module/web/dom.js.map +1 -1
  30. package/lib/typescript/src/NitroModal.d.ts +42 -2
  31. package/lib/typescript/src/NitroModal.d.ts.map +1 -1
  32. package/lib/typescript/src/NitroModal.nitro.d.ts +37 -2
  33. package/lib/typescript/src/NitroModal.nitro.d.ts.map +1 -1
  34. package/lib/typescript/src/NitroModalView.web.d.ts.map +1 -1
  35. package/lib/typescript/src/index.d.ts +2 -2
  36. package/lib/typescript/src/index.d.ts.map +1 -1
  37. package/lib/typescript/src/web/AnimatedValue.d.ts +1 -0
  38. package/lib/typescript/src/web/AnimatedValue.d.ts.map +1 -1
  39. package/lib/typescript/src/web/ModalConfig.d.ts +10 -0
  40. package/lib/typescript/src/web/ModalConfig.d.ts.map +1 -1
  41. package/lib/typescript/src/web/ModalController.d.ts +5 -0
  42. package/lib/typescript/src/web/ModalController.d.ts.map +1 -1
  43. package/lib/typescript/src/web/ModalPresenter.d.ts +13 -0
  44. package/lib/typescript/src/web/ModalPresenter.d.ts.map +1 -1
  45. package/lib/typescript/src/web/SheetPresenter.d.ts +13 -2
  46. package/lib/typescript/src/web/SheetPresenter.d.ts.map +1 -1
  47. package/lib/typescript/src/web/dom.d.ts +4 -0
  48. package/lib/typescript/src/web/dom.d.ts.map +1 -1
  49. package/nitrogen/generated/android/c++/JHybridNitroModalSpec.cpp +78 -6
  50. package/nitrogen/generated/android/c++/JHybridNitroModalSpec.hpp +14 -2
  51. package/nitrogen/generated/android/c++/JNamedSheetDetent.hpp +64 -0
  52. package/nitrogen/generated/android/c++/JSheetDetent.cpp +26 -0
  53. package/nitrogen/generated/android/c++/JSheetDetent.hpp +42 -37
  54. package/nitrogen/generated/android/c++/views/JHybridNitroModalStateUpdater.cpp +30 -0
  55. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromodal/HybridNitroModalSpec.kt +52 -0
  56. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromodal/NamedSheetDetent.kt +25 -0
  57. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromodal/SheetDetent.kt +47 -10
  58. package/nitrogen/generated/android/nitromodal+autolinking.cmake +1 -0
  59. package/nitrogen/generated/ios/NitroModal-Swift-Cxx-Bridge.hpp +68 -8
  60. package/nitrogen/generated/ios/NitroModal-Swift-Cxx-Umbrella.hpp +4 -3
  61. package/nitrogen/generated/ios/c++/HybridNitroModalSpecSwift.hpp +46 -5
  62. package/nitrogen/generated/ios/c++/views/HybridNitroModalComponent.mm +36 -0
  63. package/nitrogen/generated/ios/swift/HybridNitroModalSpec.swift +6 -0
  64. package/nitrogen/generated/ios/swift/HybridNitroModalSpec_cxx.swift +158 -5
  65. package/nitrogen/generated/ios/swift/NamedSheetDetent.swift +48 -0
  66. package/nitrogen/generated/ios/swift/SheetDetent.swift +15 -33
  67. package/nitrogen/generated/shared/c++/HybridNitroModalSpec.cpp +12 -0
  68. package/nitrogen/generated/shared/c++/HybridNitroModalSpec.hpp +18 -5
  69. package/nitrogen/generated/shared/c++/{SheetDetent.hpp → NamedSheetDetent.hpp} +17 -17
  70. package/nitrogen/generated/shared/c++/views/HybridNitroModalComponent.cpp +13 -1
  71. package/nitrogen/generated/shared/c++/views/HybridNitroModalComponent.hpp +21 -2
  72. package/nitrogen/generated/shared/json/NitroModalConfig.json +6 -0
  73. package/package.json +1 -1
  74. package/src/NitroModal.nitro.ts +38 -2
  75. package/src/NitroModal.tsx +93 -4
  76. package/src/NitroModalView.web.tsx +79 -12
  77. package/src/index.tsx +2 -0
  78. package/src/web/AnimatedValue.ts +4 -0
  79. package/src/web/ModalConfig.ts +19 -3
  80. package/src/web/ModalController.ts +35 -2
  81. package/src/web/ModalPresenter.ts +50 -11
  82. package/src/web/SheetPresenter.ts +169 -37
  83. package/src/web/dom.ts +20 -0
package/README.md CHANGED
@@ -17,7 +17,9 @@
17
17
 
18
18
  ## Features
19
19
 
20
- - 📄 **Native bottom sheets** with multiple detents (`small`, `medium`, `large`, `fitContent`) and swipe-to-dismiss
20
+ - 📄 **Native bottom sheets** with multiple detents (`small`, `medium`, `large`, `fitContent` or a height) and swipe-to-dismiss
21
+ - 📌 **Inline sheets** — a persistent sheet that is part of your screen, with the views behind it still usable
22
+ - 🔄 **Pull to refresh** — pulling a sheet down past its lowest detent, with a native activity indicator
21
23
  - 🪟 **Centered popups** with native `scale` / `fade` transitions
22
24
  - 📏 **Content-sized sheets** — `fitContent` measures your React content and grows with it
23
25
  - ⌨️ **Keyboard aware** — the sheet or card follows the keyboard animation (`pan` or `resize`)
@@ -111,6 +113,40 @@ Detents are listed smallest first. `initialDetentIndex` selects where the sheet
111
113
  </NitroModal>
112
114
  ```
113
115
 
116
+ ### Inline (persistent) bottom sheet
117
+
118
+ `presentation="inline"` keeps the sheet inside the component's own frame instead of presenting it over the app — like a sheet that is part of the screen. There is no backdrop, the views behind it stay interactive, it moves with your screen during navigation, and the user can't dismiss it. Position the frame with `style` (it fills its parent by default); the sheet rests against its bottom edge and its largest detent reaches its top edge.
119
+
120
+ ```tsx
121
+ <View style={{ flex: 1 }}>
122
+ <ScreenContent />
123
+
124
+ <NitroModal
125
+ isOpen
126
+ presentation="inline"
127
+ style={{ top: headerHeight }}
128
+ detents={[320, 'large']}
129
+ refreshing={isRefreshing}
130
+ onPullToRefresh={refresh}
131
+ >
132
+ <FlatList data={rows} renderItem={renderRow} nestedScrollEnabled />
133
+ </NitroModal>
134
+ </View>
135
+ ```
136
+
137
+ A number in `detents` is the content height in dp/pt above the bottom safe area.
138
+
139
+ ### Scrolling content and pull to refresh
140
+
141
+ A sheet hands drags off to the scroll view under the finger:
142
+
143
+ - Dragging up expands the sheet first, then scrolls the content.
144
+ - Dragging down scrolls the content back to its top. Once the content has scrolled during a drag, that drag never moves the sheet; the next drag collapses it.
145
+ - With `onPullToRefresh` set, a drag that starts with the sheet resting on its lowest detent can pull it further down. Letting go past the threshold calls `onPullToRefresh` (with haptic feedback when it is crossed). This needs a sheet that can't be swiped away: inline, or `dismissOnSwipe={false}`.
146
+ - With `refreshing` set too, an activity indicator shows in the gap the pull uncovers, and the sheet stays pulled down while `refreshing` is `true`, like `RefreshControl`. Set it to `true` in `onPullToRefresh` and back to `false` when the refresh is done. Setting it to `true` yourself shows the indicator without a pull.
147
+
148
+ On Android, scrollable content takes part through nested scrolling, so set `nestedScrollEnabled` on it.
149
+
114
150
  ### Popup
115
151
 
116
152
  ```tsx
@@ -168,7 +204,9 @@ const sheet = useRef<NitroModalRef>(null);
168
204
  | ------------------------ | ---------------------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------- |
169
205
  | `isOpen` | `boolean` | — | Controls visibility. Leave undefined to use the [ref API](#nitromodalref) instead. |
170
206
  | `mode` | `'bottomSheet' \| 'popup'` | `'bottomSheet'` | How the modal is presented. |
171
- | `detents` | `SheetDetent[]` | `['fitContent']` | Sheet heights, smallest first. Android uses at most three. |
207
+ | `presentation` | `'modal' \| 'inline'` | `'modal'` | `inline` keeps a bottom sheet inside the component's frame, as part of the screen. See [Inline](#inline-persistent-bottom-sheet). |
208
+ | `style` | `StyleProp<ViewStyle>` | `absoluteFill` | Inline only: the frame the sheet lives in. |
209
+ | `detents` | `SheetDetent[]` | `['fitContent']` | Sheet heights, smallest first: named sizes or a content height in dp/pt. Android uses at most three. |
172
210
  | `initialDetentIndex` | `number` | `0` | Index into `detents` the sheet opens at. |
173
211
  | `backdropColor` | `ColorValue` | `'black'` | Backdrop color. |
174
212
  | `backdropOpacity` | `number` | `0.4` | Backdrop opacity, `0`–`1`. |
@@ -181,6 +219,8 @@ const sheet = useRef<NitroModalRef>(null);
181
219
  | `backgroundColor` | `ColorValue` | system surface | Background of the sheet/card. |
182
220
  | `keyboardBehavior` | `'pan' \| 'resize' \| 'none'` | `'pan'` | How the modal reacts to the software keyboard. |
183
221
  | `popupAnimation` | `'scale' \| 'fade' \| 'none'` | `'scale'` | Enter/exit transition of a popup. |
222
+ | `refreshing` | `boolean` | — | A refresh is in progress: the sheet stays pulled down with an activity indicator. See [pull to refresh](#scrolling-content-and-pull-to-refresh). |
223
+ | `refreshIndicatorColor` | `ColorValue` | platform default | Color of the refresh indicator. |
184
224
  | `contentContainerStyle` | `StyleProp<ViewStyle>` | — | Style of the view that wraps `children` inside the modal. |
185
225
  | `testID` | `string` | — | Applied to the content container. |
186
226
  | `ref` | `Ref<NitroModalRef>` | — | Imperative handle. |
@@ -194,6 +234,7 @@ const sheet = useRef<NitroModalRef>(null);
194
234
  | `onDetentChange` | `(index: number) => void` | A bottom sheet settled on a different detent. |
195
235
  | `onBackdropPress` | `() => void` | The backdrop was tapped (fires even when `dismissOnBackdropPress` is `false`). |
196
236
  | `onBackButtonPress` | `() => void` | The Android hardware/gesture back (Escape on web) was pressed. |
237
+ | `onPullToRefresh` | `() => void` | The sheet was pulled down past its lowest detent and released. See [pull to refresh](#scrolling-content-and-pull-to-refresh). |
197
238
 
198
239
  ### `NitroModalRef`
199
240
 
@@ -208,12 +249,17 @@ const sheet = useRef<NitroModalRef>(null);
208
249
  ```ts
209
250
  type ModalMode = 'bottomSheet' | 'popup';
210
251
 
211
- type SheetDetent =
252
+ type ModalPresentation = 'modal' | 'inline';
253
+
254
+ type NamedSheetDetent =
212
255
  | 'small' // ~25% of the available height
213
256
  | 'medium' // ~50% of the available height
214
257
  | 'large' // the full available height
215
258
  | 'fitContent'; // the measured height of your content
216
259
 
260
+ // A named height, or the content height in dp/pt above the bottom safe area.
261
+ type SheetDetent = NamedSheetDetent | number;
262
+
217
263
  type KeyboardBehavior = 'pan' | 'resize' | 'none';
218
264
 
219
265
  type PopupAnimation = 'scale' | 'fade' | 'none';
@@ -228,6 +274,8 @@ import type {
228
274
  DismissReason,
229
275
  KeyboardBehavior,
230
276
  ModalMode,
277
+ ModalPresentation,
278
+ NamedSheetDetent,
231
279
  NitroModalProps,
232
280
  NitroModalRef,
233
281
  PopupAnimation,
@@ -237,7 +285,7 @@ import type {
237
285
 
238
286
  ## How it works
239
287
 
240
- `<NitroModal>` mounts a zero-size placeholder in your React tree. When opened, the native side presents a real view controller (iOS) or window (Android) and hosts your React children inside it. Children mount when the modal opens and stay mounted until the native exit animation completes, so content never disappears mid-transition. The native side also reports the exact area available to the content (accounting for rotation, keyboard and sheet size), and the content container is sized accordingly.
288
+ `<NitroModal>` mounts a zero-size placeholder in your React tree. When opened, the native side presents a real view controller (iOS) or window (Android) and hosts your React children inside it. An inline sheet instead lives in a view laid out with `style`, in your screen's own hierarchy: touches that miss the sheet go to the views behind it, and `keyboardBehavior` doesn't apply (the screen's own keyboard handling does). Children mount when the modal opens and stay mounted until the native exit animation completes, so content never disappears mid-transition. The native side also reports the exact area available to the content (accounting for rotation, keyboard and sheet size), and the content container is sized accordingly.
241
289
 
242
290
  ## Platform notes
243
291