@onekeyfe/react-native-native-overlay 3.0.162-alpha.268

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 (163) hide show
  1. package/LICENSE +21 -0
  2. package/NativeOverlay.podspec +30 -0
  3. package/README.md +35 -0
  4. package/android/build.gradle +82 -0
  5. package/android/src/main/AndroidManifest.xml +2 -0
  6. package/android/src/main/java/com/onekey/nativeoverlay/NativeOverlayAnimation.kt +176 -0
  7. package/android/src/main/java/com/onekey/nativeoverlay/NativeOverlayEntryRootView.kt +415 -0
  8. package/android/src/main/java/com/onekey/nativeoverlay/NativeOverlayEvents.kt +38 -0
  9. package/android/src/main/java/com/onekey/nativeoverlay/NativeOverlayHost.kt +174 -0
  10. package/android/src/main/java/com/onekey/nativeoverlay/NativeOverlayPackage.kt +16 -0
  11. package/android/src/main/java/com/onekey/nativeoverlay/NativeOverlayPageHostView.kt +122 -0
  12. package/android/src/main/java/com/onekey/nativeoverlay/NativeOverlayPageHostViewManager.kt +40 -0
  13. package/android/src/main/java/com/onekey/nativeoverlay/NativeOverlayView.kt +465 -0
  14. package/android/src/main/java/com/onekey/nativeoverlay/NativeOverlayViewManager.kt +156 -0
  15. package/android/src/main/jni/CMakeLists.txt +44 -0
  16. package/android/src/main/jni/RNCNativeOverlay.h +19 -0
  17. package/common/cpp/react/renderer/components/RNCNativeOverlay/NativeOverlayComponentDescriptor.h +12 -0
  18. package/common/cpp/react/renderer/components/RNCNativeOverlay/NativeOverlayShadowNode.cpp +12 -0
  19. package/common/cpp/react/renderer/components/RNCNativeOverlay/NativeOverlayShadowNode.h +41 -0
  20. package/common/cpp/react/renderer/components/RNCNativeOverlay/NativeOverlayState.h +40 -0
  21. package/docs/SPEC.md +693 -0
  22. package/ios/NativeOverlayAnimation.swift +160 -0
  23. package/ios/NativeOverlayContainerView.swift +688 -0
  24. package/ios/NativeOverlayKeyboard.swift +88 -0
  25. package/ios/NativeOverlayPageHostView.swift +98 -0
  26. package/ios/NativeOverlaySheetController.swift +391 -0
  27. package/ios/NativeOverlayWindowManager.swift +194 -0
  28. package/ios/RCTNativeOverlayComponentView.h +11 -0
  29. package/ios/RCTNativeOverlayComponentView.mm +193 -0
  30. package/ios/RCTNativeOverlayPageHostComponentView.h +11 -0
  31. package/ios/RCTNativeOverlayPageHostComponentView.mm +64 -0
  32. package/lib/module/NativeOverlayNativeComponent.ts +61 -0
  33. package/lib/module/NativeOverlayPageHostNativeComponent.ts +13 -0
  34. package/lib/module/OverlayErrors.js +6 -0
  35. package/lib/module/OverlayErrors.js.map +1 -0
  36. package/lib/module/OverlayLevelContext.js +27 -0
  37. package/lib/module/OverlayLevelContext.js.map +1 -0
  38. package/lib/module/OverlayLevels.js +33 -0
  39. package/lib/module/OverlayLevels.js.map +1 -0
  40. package/lib/module/OverlayPageHost.js +24 -0
  41. package/lib/module/OverlayPageHost.js.map +1 -0
  42. package/lib/module/OverlayPageHost.web.js +49 -0
  43. package/lib/module/OverlayPageHost.web.js.map +1 -0
  44. package/lib/module/OverlayPageScope.js +41 -0
  45. package/lib/module/OverlayPageScope.js.map +1 -0
  46. package/lib/module/OverlayStore.js +305 -0
  47. package/lib/module/OverlayStore.js.map +1 -0
  48. package/lib/module/OverlayView.js +141 -0
  49. package/lib/module/OverlayView.js.map +1 -0
  50. package/lib/module/OverlayView.web.js +290 -0
  51. package/lib/module/OverlayView.web.js.map +1 -0
  52. package/lib/module/OverlayViewTypes.js +4 -0
  53. package/lib/module/OverlayViewTypes.js.map +1 -0
  54. package/lib/module/animation/motionPresets.js +57 -0
  55. package/lib/module/animation/motionPresets.js.map +1 -0
  56. package/lib/module/animation/platformMotionPresets.js +4 -0
  57. package/lib/module/animation/platformMotionPresets.js.map +1 -0
  58. package/lib/module/animation/platformMotionPresets.web.js +4 -0
  59. package/lib/module/animation/platformMotionPresets.web.js.map +1 -0
  60. package/lib/module/animation/resolveAnimation.js +80 -0
  61. package/lib/module/animation/resolveAnimation.js.map +1 -0
  62. package/lib/module/animation/spring.js +69 -0
  63. package/lib/module/animation/spring.js.map +1 -0
  64. package/lib/module/animation/types.js +2 -0
  65. package/lib/module/animation/types.js.map +1 -0
  66. package/lib/module/index.js +16 -0
  67. package/lib/module/index.js.map +1 -0
  68. package/lib/module/package.json +1 -0
  69. package/lib/module/types.js +2 -0
  70. package/lib/module/types.js.map +1 -0
  71. package/lib/module/useOverlayController.js +127 -0
  72. package/lib/module/useOverlayController.js.map +1 -0
  73. package/lib/module/useSuspendedPageOwners.js +16 -0
  74. package/lib/module/useSuspendedPageOwners.js.map +1 -0
  75. package/lib/module/web/animateTransition.js +115 -0
  76. package/lib/module/web/animateTransition.js.map +1 -0
  77. package/lib/module/web/overlayLayers.js +147 -0
  78. package/lib/module/web/overlayLayers.js.map +1 -0
  79. package/lib/module/web/useKeyboardShift.js +110 -0
  80. package/lib/module/web/useKeyboardShift.js.map +1 -0
  81. package/lib/module/web/useSheetDrag.js +126 -0
  82. package/lib/module/web/useSheetDrag.js.map +1 -0
  83. package/lib/typescript/package.json +1 -0
  84. package/lib/typescript/src/NativeOverlayNativeComponent.d.ts +41 -0
  85. package/lib/typescript/src/NativeOverlayNativeComponent.d.ts.map +1 -0
  86. package/lib/typescript/src/NativeOverlayPageHostNativeComponent.d.ts +9 -0
  87. package/lib/typescript/src/NativeOverlayPageHostNativeComponent.d.ts.map +1 -0
  88. package/lib/typescript/src/OverlayErrors.d.ts +4 -0
  89. package/lib/typescript/src/OverlayErrors.d.ts.map +1 -0
  90. package/lib/typescript/src/OverlayLevelContext.d.ts +12 -0
  91. package/lib/typescript/src/OverlayLevelContext.d.ts.map +1 -0
  92. package/lib/typescript/src/OverlayLevels.d.ts +13 -0
  93. package/lib/typescript/src/OverlayLevels.d.ts.map +1 -0
  94. package/lib/typescript/src/OverlayPageHost.d.ts +9 -0
  95. package/lib/typescript/src/OverlayPageHost.d.ts.map +1 -0
  96. package/lib/typescript/src/OverlayPageHost.web.d.ts +11 -0
  97. package/lib/typescript/src/OverlayPageHost.web.d.ts.map +1 -0
  98. package/lib/typescript/src/OverlayPageScope.d.ts +17 -0
  99. package/lib/typescript/src/OverlayPageScope.d.ts.map +1 -0
  100. package/lib/typescript/src/OverlayStore.d.ts +72 -0
  101. package/lib/typescript/src/OverlayStore.d.ts.map +1 -0
  102. package/lib/typescript/src/OverlayView.d.ts +3 -0
  103. package/lib/typescript/src/OverlayView.d.ts.map +1 -0
  104. package/lib/typescript/src/OverlayView.web.d.ts +3 -0
  105. package/lib/typescript/src/OverlayView.web.d.ts.map +1 -0
  106. package/lib/typescript/src/OverlayViewTypes.d.ts +68 -0
  107. package/lib/typescript/src/OverlayViewTypes.d.ts.map +1 -0
  108. package/lib/typescript/src/animation/motionPresets.d.ts +13 -0
  109. package/lib/typescript/src/animation/motionPresets.d.ts.map +1 -0
  110. package/lib/typescript/src/animation/platformMotionPresets.d.ts +2 -0
  111. package/lib/typescript/src/animation/platformMotionPresets.d.ts.map +1 -0
  112. package/lib/typescript/src/animation/platformMotionPresets.web.d.ts +2 -0
  113. package/lib/typescript/src/animation/platformMotionPresets.web.d.ts.map +1 -0
  114. package/lib/typescript/src/animation/resolveAnimation.d.ts +23 -0
  115. package/lib/typescript/src/animation/resolveAnimation.d.ts.map +1 -0
  116. package/lib/typescript/src/animation/spring.d.ts +24 -0
  117. package/lib/typescript/src/animation/spring.d.ts.map +1 -0
  118. package/lib/typescript/src/animation/types.d.ts +56 -0
  119. package/lib/typescript/src/animation/types.d.ts.map +1 -0
  120. package/lib/typescript/src/index.d.ts +18 -0
  121. package/lib/typescript/src/index.d.ts.map +1 -0
  122. package/lib/typescript/src/types.d.ts +59 -0
  123. package/lib/typescript/src/types.d.ts.map +1 -0
  124. package/lib/typescript/src/useOverlayController.d.ts +29 -0
  125. package/lib/typescript/src/useOverlayController.d.ts.map +1 -0
  126. package/lib/typescript/src/useSuspendedPageOwners.d.ts +7 -0
  127. package/lib/typescript/src/useSuspendedPageOwners.d.ts.map +1 -0
  128. package/lib/typescript/src/web/animateTransition.d.ts +18 -0
  129. package/lib/typescript/src/web/animateTransition.d.ts.map +1 -0
  130. package/lib/typescript/src/web/overlayLayers.d.ts +10 -0
  131. package/lib/typescript/src/web/overlayLayers.d.ts.map +1 -0
  132. package/lib/typescript/src/web/useKeyboardShift.d.ts +29 -0
  133. package/lib/typescript/src/web/useKeyboardShift.d.ts.map +1 -0
  134. package/lib/typescript/src/web/useSheetDrag.d.ts +13 -0
  135. package/lib/typescript/src/web/useSheetDrag.d.ts.map +1 -0
  136. package/package.json +188 -0
  137. package/react-native.config.js +16 -0
  138. package/src/NativeOverlayNativeComponent.ts +61 -0
  139. package/src/NativeOverlayPageHostNativeComponent.ts +13 -0
  140. package/src/OverlayErrors.ts +3 -0
  141. package/src/OverlayLevelContext.tsx +32 -0
  142. package/src/OverlayLevels.ts +40 -0
  143. package/src/OverlayPageHost.tsx +21 -0
  144. package/src/OverlayPageHost.web.tsx +53 -0
  145. package/src/OverlayPageScope.tsx +42 -0
  146. package/src/OverlayStore.ts +401 -0
  147. package/src/OverlayView.tsx +165 -0
  148. package/src/OverlayView.web.tsx +356 -0
  149. package/src/OverlayViewTypes.ts +81 -0
  150. package/src/animation/motionPresets.ts +52 -0
  151. package/src/animation/platformMotionPresets.ts +1 -0
  152. package/src/animation/platformMotionPresets.web.ts +1 -0
  153. package/src/animation/resolveAnimation.ts +103 -0
  154. package/src/animation/spring.ts +80 -0
  155. package/src/animation/types.ts +71 -0
  156. package/src/index.ts +55 -0
  157. package/src/types.ts +79 -0
  158. package/src/useOverlayController.ts +199 -0
  159. package/src/useSuspendedPageOwners.ts +26 -0
  160. package/src/web/animateTransition.ts +137 -0
  161. package/src/web/overlayLayers.ts +182 -0
  162. package/src/web/useKeyboardShift.ts +130 -0
  163. package/src/web/useSheetDrag.ts +143 -0
@@ -0,0 +1,194 @@
1
+ import UIKit
2
+
3
+ /// Levels mirror `OVERLAY_LEVEL_ORDER`. Each active level gets its own
4
+ /// window so that order between levels never depends on show order.
5
+ enum NativeOverlayLevel: String, CaseIterable {
6
+ case modal
7
+ case hardware
8
+ case secure
9
+ case toast
10
+ case lock
11
+ case debug
12
+
13
+ /// Mirrors `OVERLAY_LEVEL_ORDER`.
14
+ var order: Int {
15
+ switch self {
16
+ case .modal: return 100
17
+ case .hardware: return 200
18
+ case .secure: return 300
19
+ case .toast: return 400
20
+ case .lock: return 500
21
+ case .debug: return 900
22
+ }
23
+ }
24
+
25
+ var windowLevel: UIWindow.Level {
26
+ switch self {
27
+ // Above the app window (and every VC it presents), below system alerts.
28
+ case .modal: return UIWindow.Level(rawValue: UIWindow.Level.normal.rawValue + 10)
29
+ case .hardware: return UIWindow.Level(rawValue: UIWindow.Level.normal.rawValue + 20)
30
+ case .secure: return UIWindow.Level(rawValue: UIWindow.Level.normal.rawValue + 30)
31
+ case .toast: return UIWindow.Level(rawValue: UIWindow.Level.normal.rawValue + 40)
32
+ // Above React Native's Alert window (alert + 1) and perf overlays.
33
+ case .lock: return UIWindow.Level(rawValue: UIWindow.Level.alert.rawValue + 10)
34
+ case .debug: return UIWindow.Level(rawValue: UIWindow.Level.alert.rawValue + 20)
35
+ }
36
+ }
37
+ }
38
+
39
+ /// Lets touches that miss every overlay fall through to lower windows.
40
+ final class NativeOverlayPassthroughWindow: UIWindow {
41
+ override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
42
+ let hit = super.hitTest(point, with: event)
43
+ if hit === self || hit === rootViewController?.view {
44
+ return nil
45
+ }
46
+ return hit
47
+ }
48
+
49
+ // React Native reads the window dimensions from the key window, and a
50
+ // touched level window becomes key. A rotation reported while it is key
51
+ // (or while it is hidden with a stale frame) leaves JS with the wrong
52
+ // window size. Once the sizes settle, re-report through the frame
53
+ // observer React Native keeps on the app window.
54
+ override var frame: CGRect {
55
+ didSet {
56
+ if isKeyWindow && oldValue.size != frame.size {
57
+ refreshReactNativeDimensions()
58
+ }
59
+ }
60
+ }
61
+
62
+ override func resignKey() {
63
+ super.resignKey()
64
+ refreshReactNativeDimensions()
65
+ }
66
+
67
+ private func refreshReactNativeDimensions() {
68
+ guard let appWindow = (rootViewController as? NativeOverlayRootViewController)?.appWindow
69
+ else { return }
70
+ DispatchQueue.main.async { [weak appWindow] in
71
+ guard let appWindow else { return }
72
+ // Assigning the frame fires React Native's KVO, which recomputes the
73
+ // dimensions from the current key window.
74
+ let frame = appWindow.frame
75
+ appWindow.frame = frame
76
+ }
77
+ }
78
+ }
79
+
80
+ /// Status bar and orientation follow the app window underneath, because
81
+ /// `childForStatusBarStyle` cannot reach across windows.
82
+ final class NativeOverlayRootViewController: UIViewController {
83
+ weak var appWindow: UIWindow?
84
+
85
+ private var appTopController: UIViewController? {
86
+ var controller = appWindow?.rootViewController
87
+ while let presented = controller?.presentedViewController, !presented.isBeingDismissed {
88
+ controller = presented
89
+ }
90
+ // Never answer with ourselves: asking it would recurse forever.
91
+ return controller === self ? nil : controller
92
+ }
93
+
94
+ override func loadView() {
95
+ let root = UIView()
96
+ root.backgroundColor = .clear
97
+ view = root
98
+ }
99
+
100
+ /// Apps without view-controller-based status bar appearance set one
101
+ /// app-wide style (React Native's StatusBar does). Level windows above the
102
+ /// status bar (`lock`, `debug`) still get asked, so answer with that style.
103
+ private static let viewControllerBasedAppearance =
104
+ (Bundle.main.object(forInfoDictionaryKey: "UIViewControllerBasedStatusBarAppearance") as? Bool) ?? true
105
+
106
+ override var preferredStatusBarStyle: UIStatusBarStyle {
107
+ if !Self.viewControllerBasedAppearance {
108
+ return UIApplication.shared.statusBarStyle
109
+ }
110
+ return appTopController?.preferredStatusBarStyle ?? .default
111
+ }
112
+
113
+ override var prefersStatusBarHidden: Bool {
114
+ appTopController?.prefersStatusBarHidden ?? false
115
+ }
116
+
117
+ override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
118
+ appTopController?.supportedInterfaceOrientations ?? .all
119
+ }
120
+ }
121
+
122
+ final class NativeOverlayWindowManager {
123
+ static let shared = NativeOverlayWindowManager()
124
+
125
+ private struct SceneKey: Hashable {
126
+ let id: ObjectIdentifier
127
+ }
128
+
129
+ private var windows: [SceneKey: [NativeOverlayLevel: NativeOverlayPassthroughWindow]] = [:]
130
+
131
+ /// The level window for `level` in the scene of `appWindow`, shown on demand.
132
+ /// Non-sheet entries are added directly to it so they interleave by insertion
133
+ /// order with UIKit presentation containers of sheets in the same level.
134
+ func window(for level: NativeOverlayLevel, appWindow hostWindow: UIWindow) -> UIWindow? {
135
+ // An overlay opened from inside another overlay (a popover in a password
136
+ // prompt) is hosted in a level window; follow it back to the app window.
137
+ let appWindow =
138
+ ((hostWindow as? NativeOverlayPassthroughWindow)?.rootViewController
139
+ as? NativeOverlayRootViewController)?.appWindow ?? hostWindow
140
+ guard let scene = appWindow.windowScene else { return nil }
141
+ let key = SceneKey(id: ObjectIdentifier(scene))
142
+ pruneDisconnectedScenes()
143
+ var sceneWindows = windows[key] ?? [:]
144
+ let window: NativeOverlayPassthroughWindow
145
+ if let existing = sceneWindows[level] {
146
+ window = existing
147
+ } else {
148
+ window = NativeOverlayPassthroughWindow(windowScene: scene)
149
+ window.windowLevel = level.windowLevel
150
+ window.backgroundColor = .clear
151
+ window.rootViewController = NativeOverlayRootViewController()
152
+ sceneWindows[level] = window
153
+ windows[key] = sceneWindows
154
+ }
155
+ (window.rootViewController as? NativeOverlayRootViewController)?.appWindow = appWindow
156
+ if window.isHidden {
157
+ window.frame = scene.coordinateSpace.bounds
158
+ window.isHidden = false
159
+ window.rootViewController?.setNeedsStatusBarAppearanceUpdate()
160
+ }
161
+ return window
162
+ }
163
+
164
+ /// Top of the level window's presentation chain; sheets of one level stack here.
165
+ func presenter(in window: UIWindow) -> UIViewController? {
166
+ var controller = window.rootViewController
167
+ while let presented = controller?.presentedViewController, !presented.isBeingDismissed {
168
+ controller = presented
169
+ }
170
+ return controller
171
+ }
172
+
173
+ /// Hides a level window once nothing is shown in it, and hands key status
174
+ /// back to the app window if an input in the overlay had taken it.
175
+ func entryRemoved(from window: UIWindow?) {
176
+ guard let window = window as? NativeOverlayPassthroughWindow,
177
+ let root = window.rootViewController else { return }
178
+ let hasEntries = window.subviews.contains { $0 is NativeOverlayEntryView }
179
+ let presented = root.presentedViewController
180
+ guard !hasEntries, presented == nil || presented?.isBeingDismissed == true else { return }
181
+ let wasKey = window.isKeyWindow
182
+ window.isHidden = true
183
+ if wasKey {
184
+ (root as? NativeOverlayRootViewController)?.appWindow?.makeKey()
185
+ }
186
+ }
187
+
188
+ private func pruneDisconnectedScenes() {
189
+ let connected = Set(
190
+ UIApplication.shared.connectedScenes.map { SceneKey(id: ObjectIdentifier($0)) }
191
+ )
192
+ windows = windows.filter { connected.contains($0.key) }
193
+ }
194
+ }
@@ -0,0 +1,11 @@
1
+ #ifdef RCT_NEW_ARCH_ENABLED
2
+ #import <React/RCTViewComponentView.h>
3
+ #import <UIKit/UIKit.h>
4
+
5
+ NS_ASSUME_NONNULL_BEGIN
6
+
7
+ @interface RCTNativeOverlayComponentView : RCTViewComponentView
8
+ @end
9
+
10
+ NS_ASSUME_NONNULL_END
11
+ #endif
@@ -0,0 +1,193 @@
1
+ #import "RCTNativeOverlayComponentView.h"
2
+
3
+ #include <cmath>
4
+
5
+ #import <react/renderer/components/RNCNativeOverlay/NativeOverlayComponentDescriptor.h>
6
+ #import <react/renderer/components/RNCNativeOverlay/EventEmitters.h>
7
+ #import <react/renderer/components/RNCNativeOverlay/Props.h>
8
+ #import <react/renderer/components/RNCNativeOverlay/RCTComponentViewHelpers.h>
9
+
10
+ #import <React/RCTComponent.h>
11
+ #import <React/RCTConversions.h>
12
+ #import <React/RCTFabricComponentsPlugins.h>
13
+ #import <React/RCTSurfaceTouchHandler.h>
14
+
15
+ #if __has_include(<NativeOverlay/NativeOverlay-Swift.h>)
16
+ #import <NativeOverlay/NativeOverlay-Swift.h>
17
+ #elif __has_include("NativeOverlay/NativeOverlay-Swift.h")
18
+ #import "NativeOverlay/NativeOverlay-Swift.h"
19
+ #else
20
+ #import "NativeOverlay-Swift.h"
21
+ #endif
22
+
23
+ using namespace facebook::react;
24
+
25
+ static NSString *RNCNativeOverlayLevelString(RNCNativeOverlayLevel level)
26
+ {
27
+ switch (level) {
28
+ case RNCNativeOverlayLevel::Hardware:
29
+ return @"hardware";
30
+ case RNCNativeOverlayLevel::Secure:
31
+ return @"secure";
32
+ case RNCNativeOverlayLevel::Toast:
33
+ return @"toast";
34
+ case RNCNativeOverlayLevel::Lock:
35
+ return @"lock";
36
+ case RNCNativeOverlayLevel::Debug:
37
+ return @"debug";
38
+ case RNCNativeOverlayLevel::Modal:
39
+ default:
40
+ return @"modal";
41
+ }
42
+ }
43
+
44
+ static NSString *RNCNativeOverlayPresentationString(RNCNativeOverlayPresentation presentation)
45
+ {
46
+ switch (presentation) {
47
+ case RNCNativeOverlayPresentation::Toast:
48
+ return @"toast";
49
+ case RNCNativeOverlayPresentation::Fullscreen:
50
+ return @"fullscreen";
51
+ case RNCNativeOverlayPresentation::Sheet:
52
+ return @"sheet";
53
+ case RNCNativeOverlayPresentation::Anchored:
54
+ return @"anchored";
55
+ case RNCNativeOverlayPresentation::Center:
56
+ default:
57
+ return @"center";
58
+ }
59
+ }
60
+
61
+ @implementation RCTNativeOverlayComponentView {
62
+ NativeOverlayContainerView *_containerView;
63
+ RCTSurfaceTouchHandler *_touchHandler;
64
+ RNCNativeOverlayShadowNode::ConcreteState::Shared _state;
65
+ CGPoint _contentOffset;
66
+ }
67
+
68
+ + (ComponentDescriptorProvider)componentDescriptorProvider
69
+ {
70
+ return concreteComponentDescriptorProvider<RNCNativeOverlayComponentDescriptor>();
71
+ }
72
+
73
+ - (instancetype)initWithFrame:(CGRect)frame
74
+ {
75
+ if (self = [super initWithFrame:frame]) {
76
+ static const auto defaultProps = std::make_shared<const RNCNativeOverlayProps>();
77
+ _props = defaultProps;
78
+
79
+ _containerView = [NativeOverlayContainerView new];
80
+ _touchHandler = [RCTSurfaceTouchHandler new];
81
+ _containerView.touchHandler = _touchHandler;
82
+ self.contentView = _containerView;
83
+
84
+ __weak auto weakSelf = self;
85
+ _containerView.onContentOffsetChanged = ^(CGPoint offset) {
86
+ auto strongSelf = weakSelf;
87
+ if (!strongSelf) return;
88
+ strongSelf->_contentOffset = offset;
89
+ [strongSelf pushContentOffset];
90
+ };
91
+ _containerView.onPresented = ^(NSDictionary *body) {
92
+ auto strongSelf = weakSelf;
93
+ if (!strongSelf) return;
94
+ auto emitter = std::static_pointer_cast<const RNCNativeOverlayEventEmitter>(strongSelf->_eventEmitter);
95
+ if (!emitter) return;
96
+ NSNumber *stackOrder = body[@"stackOrder"] ?: @0;
97
+ emitter->onPresented({.stackOrder = stackOrder.intValue});
98
+ };
99
+ _containerView.onDismissed = ^(NSDictionary *body) {
100
+ auto strongSelf = weakSelf;
101
+ if (!strongSelf) return;
102
+ auto emitter = std::static_pointer_cast<const RNCNativeOverlayEventEmitter>(strongSelf->_eventEmitter);
103
+ if (!emitter) return;
104
+ NSString *reason = body[@"reason"] ?: @"system";
105
+ emitter->onDismissed({.reason = std::string(reason.UTF8String)});
106
+ };
107
+ _containerView.onRequestDismiss = ^(NSDictionary *body) {
108
+ auto strongSelf = weakSelf;
109
+ if (!strongSelf) return;
110
+ auto emitter = std::static_pointer_cast<const RNCNativeOverlayEventEmitter>(strongSelf->_eventEmitter);
111
+ if (!emitter) return;
112
+ NSString *reason = body[@"reason"] ?: @"back";
113
+ emitter->onRequestDismiss({.reason = std::string(reason.UTF8String)});
114
+ };
115
+ }
116
+ return self;
117
+ }
118
+
119
+ + (BOOL)shouldBeRecycled
120
+ {
121
+ return NO;
122
+ }
123
+
124
+ - (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView
125
+ index:(NSInteger)index
126
+ {
127
+ [_containerView insertChild:childComponentView atIndex:index];
128
+ }
129
+
130
+ - (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView
131
+ index:(NSInteger)index
132
+ {
133
+ [_containerView removeChild:childComponentView];
134
+ [childComponentView removeFromSuperview];
135
+ }
136
+
137
+ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
138
+ {
139
+ const auto &newProps = *std::static_pointer_cast<RNCNativeOverlayProps const>(props);
140
+
141
+ _containerView.level = RNCNativeOverlayLevelString(newProps.level);
142
+ _containerView.presentation = RNCNativeOverlayPresentationString(newProps.presentation);
143
+ _containerView.scope = newProps.scope == RNCNativeOverlayScope::Page ? @"page" : @"global";
144
+ _containerView.hostKey = [NSString stringWithUTF8String:newProps.hostKey.c_str()];
145
+ _containerView.ownerKey = [NSString stringWithUTF8String:newProps.ownerKey.c_str()];
146
+ _containerView.stackOrder = newProps.stackOrder;
147
+ _containerView.blocking = newProps.blocking;
148
+ _containerView.dismissOnBackPress = newProps.dismissOnBackPress;
149
+ _containerView.dismissOnBackdropPress = newProps.dismissOnBackdropPress;
150
+ _containerView.backdropColor = RCTUIColorFromSharedColor(newProps.backdropColor);
151
+ _containerView.sheetHeight = newProps.sheetHeight;
152
+ _containerView.sheetCornerRadius = newProps.sheetCornerRadius;
153
+ _containerView.showHandle = newProps.showHandle;
154
+ _containerView.sheetBackgroundColor = RCTUIColorFromSharedColor(newProps.sheetBackgroundColor);
155
+ _containerView.dismissOnPanDown = newProps.dismissOnPanDown;
156
+ _containerView.animationConfig = [NSString stringWithUTF8String:newProps.animationConfig.c_str()];
157
+ _containerView.visible = newProps.visible;
158
+ [_containerView commitConfiguration];
159
+
160
+ [super updateProps:props oldProps:oldProps];
161
+ }
162
+
163
+ - (void)updateState:(State::Shared const &)state oldState:(State::Shared const &)oldState
164
+ {
165
+ _state = std::static_pointer_cast<RNCNativeOverlayShadowNode::ConcreteState const>(state);
166
+ [self pushContentOffset];
167
+ }
168
+
169
+ // Keeps the shadow node's measurement origin at the content's window origin.
170
+ - (void)pushContentOffset
171
+ {
172
+ if (!_state) {
173
+ return;
174
+ }
175
+ const auto current = _state->getData().contentOffset;
176
+ if (std::abs(current.x - _contentOffset.x) < 0.5 && std::abs(current.y - _contentOffset.y) < 0.5) {
177
+ return;
178
+ }
179
+ _state->updateState(NativeOverlayState{facebook::react::Point{.x = _contentOffset.x, .y = _contentOffset.y}});
180
+ }
181
+
182
+ - (void)invalidate
183
+ {
184
+ [_containerView invalidate];
185
+ [super invalidate];
186
+ }
187
+
188
+ @end
189
+
190
+ Class<RCTComponentViewProtocol> RNCNativeOverlayCls(void)
191
+ {
192
+ return RCTNativeOverlayComponentView.class;
193
+ }
@@ -0,0 +1,11 @@
1
+ #ifdef RCT_NEW_ARCH_ENABLED
2
+ #import <React/RCTViewComponentView.h>
3
+ #import <UIKit/UIKit.h>
4
+
5
+ NS_ASSUME_NONNULL_BEGIN
6
+
7
+ @interface RCTNativeOverlayPageHostComponentView : RCTViewComponentView
8
+ @end
9
+
10
+ NS_ASSUME_NONNULL_END
11
+ #endif
@@ -0,0 +1,64 @@
1
+ #import "RCTNativeOverlayPageHostComponentView.h"
2
+
3
+ #import <react/renderer/components/RNCNativeOverlay/ComponentDescriptors.h>
4
+ #import <react/renderer/components/RNCNativeOverlay/Props.h>
5
+ #import <react/renderer/components/RNCNativeOverlay/RCTComponentViewHelpers.h>
6
+
7
+ #import <React/RCTComponent.h>
8
+ #import <React/RCTFabricComponentsPlugins.h>
9
+
10
+ #if __has_include(<NativeOverlay/NativeOverlay-Swift.h>)
11
+ #import <NativeOverlay/NativeOverlay-Swift.h>
12
+ #elif __has_include("NativeOverlay/NativeOverlay-Swift.h")
13
+ #import "NativeOverlay/NativeOverlay-Swift.h"
14
+ #else
15
+ #import "NativeOverlay-Swift.h"
16
+ #endif
17
+
18
+ using namespace facebook::react;
19
+
20
+ @implementation RCTNativeOverlayPageHostComponentView {
21
+ NativeOverlayPageHostView *_hostView;
22
+ }
23
+
24
+ + (ComponentDescriptorProvider)componentDescriptorProvider
25
+ {
26
+ return concreteComponentDescriptorProvider<RNCNativeOverlayPageHostComponentDescriptor>();
27
+ }
28
+
29
+ - (instancetype)initWithFrame:(CGRect)frame
30
+ {
31
+ if (self = [super initWithFrame:frame]) {
32
+ static const auto defaultProps = std::make_shared<const RNCNativeOverlayPageHostProps>();
33
+ _props = defaultProps;
34
+ _hostView = [NativeOverlayPageHostView new];
35
+ self.contentView = _hostView;
36
+ }
37
+ return self;
38
+ }
39
+
40
+ + (BOOL)shouldBeRecycled
41
+ {
42
+ return NO;
43
+ }
44
+
45
+ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
46
+ {
47
+ const auto &newProps = *std::static_pointer_cast<RNCNativeOverlayPageHostProps const>(props);
48
+ _hostView.hostKey = [NSString stringWithUTF8String:newProps.hostKey.c_str()];
49
+ [_hostView setSuspendedOwners:[NSString stringWithUTF8String:newProps.suspendedOwners.c_str()]];
50
+ [super updateProps:props oldProps:oldProps];
51
+ }
52
+
53
+ - (void)invalidate
54
+ {
55
+ [_hostView invalidate];
56
+ [super invalidate];
57
+ }
58
+
59
+ @end
60
+
61
+ Class<RCTComponentViewProtocol> RNCNativeOverlayPageHostCls(void)
62
+ {
63
+ return RCTNativeOverlayPageHostComponentView.class;
64
+ }
@@ -0,0 +1,61 @@
1
+ import { codegenNativeComponent } from 'react-native';
2
+
3
+ import type {
4
+ CodegenTypes,
5
+ ColorValue,
6
+ HostComponent,
7
+ ViewProps,
8
+ } from 'react-native';
9
+ type INativeOverlayDismissedEvent = Readonly<{
10
+ reason: string;
11
+ }>;
12
+
13
+ type INativeOverlayRequestDismissEvent = Readonly<{
14
+ reason: string;
15
+ }>;
16
+
17
+ type INativeOverlayPresentedEvent = Readonly<{
18
+ stackOrder: CodegenTypes.Int32;
19
+ }>;
20
+
21
+ export interface INativeOverlayNativeProps extends ViewProps {
22
+ /** Present when true; play the exit animation and emit onDismissed when it turns false. */
23
+ visible: boolean;
24
+ level?: CodegenTypes.WithDefault<
25
+ 'modal' | 'hardware' | 'secure' | 'toast' | 'lock' | 'debug',
26
+ 'modal'
27
+ >;
28
+ presentation?: CodegenTypes.WithDefault<
29
+ 'center' | 'toast' | 'fullscreen' | 'sheet' | 'anchored',
30
+ 'center'
31
+ >;
32
+ scope?: CodegenTypes.WithDefault<'global' | 'page', 'global'>;
33
+ /** `page` scope: the `OverlayPageHost` to render in and the owning page. */
34
+ hostKey?: CodegenTypes.WithDefault<string, ''>;
35
+ ownerKey?: CodegenTypes.WithDefault<string, ''>;
36
+ /** Order inside the level; higher renders above. */
37
+ stackOrder?: CodegenTypes.WithDefault<CodegenTypes.Int32, 0>;
38
+ /** Swallow touches that miss the content instead of passing them through. */
39
+ blocking?: CodegenTypes.WithDefault<boolean, true>;
40
+ dismissOnBackPress?: CodegenTypes.WithDefault<boolean, true>;
41
+ dismissOnBackdropPress?: CodegenTypes.WithDefault<boolean, false>;
42
+ backdropColor?: ColorValue;
43
+ /** `sheet` presentation: resolved content height in points. */
44
+ sheetHeight?: CodegenTypes.WithDefault<CodegenTypes.Double, 0>;
45
+ sheetCornerRadius?: CodegenTypes.WithDefault<CodegenTypes.Double, 24>;
46
+ showHandle?: CodegenTypes.WithDefault<boolean, false>;
47
+ sheetBackgroundColor?: ColorValue;
48
+ dismissOnPanDown?: CodegenTypes.WithDefault<boolean, true>;
49
+ /** JSON of the resolved animation (`IResolvedOverlayAnimation`). */
50
+ animationConfig?: CodegenTypes.WithDefault<string, ''>;
51
+ onPresented?: CodegenTypes.DirectEventHandler<INativeOverlayPresentedEvent>;
52
+ onDismissed?: CodegenTypes.DirectEventHandler<INativeOverlayDismissedEvent>;
53
+ onRequestDismiss?: CodegenTypes.DirectEventHandler<INativeOverlayRequestDismissEvent>;
54
+ }
55
+
56
+ // The shadow node is hand-written (common/cpp): it carries the on-screen
57
+ // content offset so `measure` reports where native presented the content.
58
+ export default codegenNativeComponent<INativeOverlayNativeProps>(
59
+ 'RNCNativeOverlay',
60
+ { interfaceOnly: true }
61
+ ) as HostComponent<INativeOverlayNativeProps>;
@@ -0,0 +1,13 @@
1
+ import { codegenNativeComponent } from 'react-native';
2
+
3
+ import type { HostComponent, ViewProps } from 'react-native';
4
+
5
+ export interface INativeOverlayPageHostNativeProps extends ViewProps {
6
+ hostKey: string;
7
+ /** Owners whose entries are hidden, newline separated. */
8
+ suspendedOwners?: string;
9
+ }
10
+
11
+ export default codegenNativeComponent<INativeOverlayPageHostNativeProps>(
12
+ 'RNCNativeOverlayPageHost'
13
+ ) as HostComponent<INativeOverlayPageHostNativeProps>;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+
3
+ export class OverlayRequestError extends Error {
4
+ name = 'OverlayRequestError';
5
+ }
6
+ //# sourceMappingURL=OverlayErrors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["OverlayRequestError","Error","name"],"sourceRoot":"../../src","sources":["OverlayErrors.ts"],"mappings":";;AAAA,OAAO,MAAMA,mBAAmB,SAASC,KAAK,CAAC;EACpCC,IAAI,GAAG,qBAAqB;AACvC","ignoreList":[]}
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+
3
+ import { createContext, useContext } from 'react';
4
+ import { OVERLAY_LEVEL_ORDER } from "./OverlayLevels.js";
5
+ const OverlayLevelContext = /*#__PURE__*/createContext(undefined);
6
+
7
+ /** Provided by `OverlayView` to its content. */
8
+ export const OverlayLevelProvider = OverlayLevelContext.Provider;
9
+
10
+ /** The level of the overlay this component renders in, if any. */
11
+ export function useEnclosingOverlayLevel() {
12
+ return useContext(OverlayLevelContext);
13
+ }
14
+
15
+ /**
16
+ * The level for an overlay opened from inside another one (a popover in a
17
+ * password prompt, a tooltip on the lock screen): never below the overlay it
18
+ * is opened from, or it would render underneath it.
19
+ */
20
+ export function useNestedOverlayLevel(minimum = 'modal') {
21
+ const enclosing = useEnclosingOverlayLevel();
22
+ if (!enclosing) {
23
+ return minimum;
24
+ }
25
+ return OVERLAY_LEVEL_ORDER[enclosing] > OVERLAY_LEVEL_ORDER[minimum] ? enclosing : minimum;
26
+ }
27
+ //# sourceMappingURL=OverlayLevelContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createContext","useContext","OVERLAY_LEVEL_ORDER","OverlayLevelContext","undefined","OverlayLevelProvider","Provider","useEnclosingOverlayLevel","useNestedOverlayLevel","minimum","enclosing"],"sourceRoot":"../../src","sources":["OverlayLevelContext.tsx"],"mappings":";;AAAA,SAASA,aAAa,EAAEC,UAAU,QAAQ,OAAO;AAEjD,SAASC,mBAAmB,QAAQ,oBAAiB;AAIrD,MAAMC,mBAAmB,gBAAGH,aAAa,CAA4BI,SAAS,CAAC;;AAE/E;AACA,OAAO,MAAMC,oBAAoB,GAAGF,mBAAmB,CAACG,QAAQ;;AAEhE;AACA,OAAO,SAASC,wBAAwBA,CAAA,EAA8B;EACpE,OAAON,UAAU,CAACE,mBAAmB,CAAC;AACxC;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASK,qBAAqBA,CACnCC,OAAsB,GAAG,OAAO,EACjB;EACf,MAAMC,SAAS,GAAGH,wBAAwB,CAAC,CAAC;EAC5C,IAAI,CAACG,SAAS,EAAE;IACd,OAAOD,OAAO;EAChB;EACA,OAAOP,mBAAmB,CAACQ,SAAS,CAAC,GAAGR,mBAAmB,CAACO,OAAO,CAAC,GAChEC,SAAS,GACTD,OAAO;AACb","ignoreList":[]}
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+
3
+ export const OVERLAY_LEVEL_ORDER = {
4
+ modal: 100,
5
+ hardware: 200,
6
+ secure: 300,
7
+ toast: 400,
8
+ lock: 500,
9
+ debug: 900
10
+ };
11
+ export const OVERLAY_LEVELS = Object.keys(OVERLAY_LEVEL_ORDER).toSorted((a, b) => OVERLAY_LEVEL_ORDER[a] - OVERLAY_LEVEL_ORDER[b]);
12
+ const NON_BLOCKING_LEVELS = new Set(['toast', 'debug']);
13
+ export function isBlockingLevel(level) {
14
+ return !NON_BLOCKING_LEVELS.has(level);
15
+ }
16
+
17
+ /**
18
+ * Web z-index bands of the level layer roots (`document.body` children). In-page
19
+ * content that must rise above a level (a drag clone over a dialog) uses a
20
+ * value just above that level's base.
21
+ */
22
+ export const OVERLAY_WEB_Z_INDEX_BASE = {
23
+ modal: 100_000,
24
+ hardware: 120_000,
25
+ secure: 160_000,
26
+ toast: 1_000_000,
27
+ lock: 100_000_000,
28
+ debug: 100_000_005
29
+ };
30
+
31
+ /** Page-scope entries always render below every global entry. */
32
+ export const OVERLAY_WEB_PAGE_Z_INDEX_BASE = 1000;
33
+ //# sourceMappingURL=OverlayLevels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["OVERLAY_LEVEL_ORDER","modal","hardware","secure","toast","lock","debug","OVERLAY_LEVELS","Object","keys","toSorted","a","b","NON_BLOCKING_LEVELS","Set","isBlockingLevel","level","has","OVERLAY_WEB_Z_INDEX_BASE","OVERLAY_WEB_PAGE_Z_INDEX_BASE"],"sourceRoot":"../../src","sources":["OverlayLevels.ts"],"mappings":";;AAEA,OAAO,MAAMA,mBAAkD,GAAG;EAChEC,KAAK,EAAE,GAAG;EACVC,QAAQ,EAAE,GAAG;EACbC,MAAM,EAAE,GAAG;EACXC,KAAK,EAAE,GAAG;EACVC,IAAI,EAAE,GAAG;EACTC,KAAK,EAAE;AACT,CAAC;AAED,OAAO,MAAMC,cAAwC,GACnDC,MAAM,CAACC,IAAI,CAACT,mBAAmB,CAAC,CAChCU,QAAQ,CAAC,CAACC,CAAC,EAAEC,CAAC,KAAKZ,mBAAmB,CAACW,CAAC,CAAC,GAAGX,mBAAmB,CAACY,CAAC,CAAC,CAAC;AAErE,MAAMC,mBAA+C,GAAG,IAAIC,GAAG,CAAC,CAC9D,OAAO,EACP,OAAO,CACR,CAAC;AAEF,OAAO,SAASC,eAAeA,CAACC,KAAoB,EAAW;EAC7D,OAAO,CAACH,mBAAmB,CAACI,GAAG,CAACD,KAAK,CAAC;AACxC;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAME,wBAAuD,GAAG;EACrEjB,KAAK,EAAE,OAAO;EACdC,QAAQ,EAAE,OAAO;EACjBC,MAAM,EAAE,OAAO;EACfC,KAAK,EAAE,SAAS;EAChBC,IAAI,EAAE,WAAW;EACjBC,KAAK,EAAE;AACT,CAAC;;AAED;AACA,OAAO,MAAMa,6BAA6B,GAAG,IAAI","ignoreList":[]}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+
3
+ import { StyleSheet } from 'react-native';
4
+ import NativeOverlayPageHost from './NativeOverlayPageHostNativeComponent';
5
+ import { useSuspendedPageOwners } from "./useSuspendedPageOwners.js";
6
+
7
+ /**
8
+ * Renders page-scope overlays of one root route. Place it as the last child
9
+ * of the root-route screen, after its navigator, so page overlays cover the
10
+ * native header and tab bar of every page in that route.
11
+ */
12
+ import { jsx as _jsx } from "react/jsx-runtime";
13
+ export function OverlayPageHost({
14
+ hostKey
15
+ }) {
16
+ const suspendedOwners = useSuspendedPageOwners(hostKey);
17
+ return /*#__PURE__*/_jsx(NativeOverlayPageHost, {
18
+ hostKey: hostKey,
19
+ suspendedOwners: suspendedOwners.join('\n'),
20
+ pointerEvents: "box-none",
21
+ style: StyleSheet.absoluteFill
22
+ });
23
+ }
24
+ //# sourceMappingURL=OverlayPageHost.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["StyleSheet","NativeOverlayPageHost","useSuspendedPageOwners","jsx","_jsx","OverlayPageHost","hostKey","suspendedOwners","join","pointerEvents","style","absoluteFill"],"sourceRoot":"../../src","sources":["OverlayPageHost.tsx"],"mappings":";;AAAA,SAASA,UAAU,QAAQ,cAAc;AAEzC,OAAOC,qBAAqB,MAAM,wCAAwC;AAC1E,SAASC,sBAAsB,QAAQ,6BAA0B;;AAEjE;AACA;AACA;AACA;AACA;AAJA,SAAAC,GAAA,IAAAC,IAAA;AAKA,OAAO,SAASC,eAAeA,CAAC;EAAEC;AAA6B,CAAC,EAAE;EAChE,MAAMC,eAAe,GAAGL,sBAAsB,CAACI,OAAO,CAAC;EACvD,oBACEF,IAAA,CAACH,qBAAqB;IACpBK,OAAO,EAAEA,OAAQ;IACjBC,eAAe,EAAEA,eAAe,CAACC,IAAI,CAAC,IAAI,CAAE;IAC5CC,aAAa,EAAC,UAAU;IACxBC,KAAK,EAAEV,UAAU,CAACW;EAAa,CAChC,CAAC;AAEN","ignoreList":[]}