@vxrn/native 1.12.8-1774390675831

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 (176) hide show
  1. package/.turbo/turbo-build.log +2 -0
  2. package/android/build.gradle +32 -0
  3. package/android/src/main/AndroidManifest.xml +2 -0
  4. package/android/src/main/java/dev/vxrn/native/VxrnNativeModule.kt +117 -0
  5. package/android/src/main/java/dev/vxrn/native/VxrnNativePackage.kt +16 -0
  6. package/dist/cjs/color/android.dynamic.types.cjs +16 -0
  7. package/dist/cjs/color/android.dynamic.types.native.js +19 -0
  8. package/dist/cjs/color/android.dynamic.types.native.js.map +1 -0
  9. package/dist/cjs/color/android.material.types.cjs +16 -0
  10. package/dist/cjs/color/android.material.types.native.js +19 -0
  11. package/dist/cjs/color/android.material.types.native.js.map +1 -0
  12. package/dist/cjs/color/index.cjs +66 -0
  13. package/dist/cjs/color/index.native.js +69 -0
  14. package/dist/cjs/color/index.native.js.map +1 -0
  15. package/dist/cjs/color/ios.types.cjs +16 -0
  16. package/dist/cjs/color/ios.types.native.js +19 -0
  17. package/dist/cjs/color/ios.types.native.js.map +1 -0
  18. package/dist/cjs/color/materialColor.cjs +32 -0
  19. package/dist/cjs/color/materialColor.native.js +43 -0
  20. package/dist/cjs/color/materialColor.native.js.map +1 -0
  21. package/dist/cjs/index.cjs +37 -0
  22. package/dist/cjs/index.native.js +40 -0
  23. package/dist/cjs/index.native.js.map +1 -0
  24. package/dist/cjs/menu/index.cjs +28 -0
  25. package/dist/cjs/menu/index.native.js +47 -0
  26. package/dist/cjs/menu/index.native.js.map +1 -0
  27. package/dist/cjs/menu/types.cjs +16 -0
  28. package/dist/cjs/menu/types.native.js +19 -0
  29. package/dist/cjs/menu/types.native.js.map +1 -0
  30. package/dist/cjs/split-view/index.cjs +26 -0
  31. package/dist/cjs/split-view/index.native.js +29 -0
  32. package/dist/cjs/split-view/index.native.js.map +1 -0
  33. package/dist/cjs/split-view/split-view.cjs +80 -0
  34. package/dist/cjs/split-view/split-view.native.js +88 -0
  35. package/dist/cjs/split-view/split-view.native.js.map +1 -0
  36. package/dist/cjs/toolbar/index.cjs +32 -0
  37. package/dist/cjs/toolbar/index.native.js +60 -0
  38. package/dist/cjs/toolbar/index.native.js.map +1 -0
  39. package/dist/cjs/toolbar/types.cjs +16 -0
  40. package/dist/cjs/toolbar/types.native.js +19 -0
  41. package/dist/cjs/toolbar/types.native.js.map +1 -0
  42. package/dist/cjs/zoom/index.cjs +36 -0
  43. package/dist/cjs/zoom/index.native.js +65 -0
  44. package/dist/cjs/zoom/index.native.js.map +1 -0
  45. package/dist/cjs/zoom/types.cjs +16 -0
  46. package/dist/cjs/zoom/types.native.js +19 -0
  47. package/dist/cjs/zoom/types.native.js.map +1 -0
  48. package/dist/esm/color/android.dynamic.types.mjs +2 -0
  49. package/dist/esm/color/android.dynamic.types.mjs.map +1 -0
  50. package/dist/esm/color/android.dynamic.types.native.js +2 -0
  51. package/dist/esm/color/android.dynamic.types.native.js.map +1 -0
  52. package/dist/esm/color/android.material.types.mjs +2 -0
  53. package/dist/esm/color/android.material.types.mjs.map +1 -0
  54. package/dist/esm/color/android.material.types.native.js +2 -0
  55. package/dist/esm/color/android.material.types.native.js.map +1 -0
  56. package/dist/esm/color/index.mjs +42 -0
  57. package/dist/esm/color/index.mjs.map +1 -0
  58. package/dist/esm/color/index.native.js +42 -0
  59. package/dist/esm/color/index.native.js.map +1 -0
  60. package/dist/esm/color/ios.types.mjs +2 -0
  61. package/dist/esm/color/ios.types.mjs.map +1 -0
  62. package/dist/esm/color/ios.types.native.js +2 -0
  63. package/dist/esm/color/ios.types.native.js.map +1 -0
  64. package/dist/esm/color/materialColor.mjs +8 -0
  65. package/dist/esm/color/materialColor.mjs.map +1 -0
  66. package/dist/esm/color/materialColor.native.js +16 -0
  67. package/dist/esm/color/materialColor.native.js.map +1 -0
  68. package/dist/esm/index.mjs +7 -0
  69. package/dist/esm/index.mjs.map +1 -0
  70. package/dist/esm/index.native.js +7 -0
  71. package/dist/esm/index.native.js.map +1 -0
  72. package/dist/esm/menu/index.mjs +5 -0
  73. package/dist/esm/menu/index.mjs.map +1 -0
  74. package/dist/esm/menu/index.native.js +21 -0
  75. package/dist/esm/menu/index.native.js.map +1 -0
  76. package/dist/esm/menu/types.mjs +2 -0
  77. package/dist/esm/menu/types.mjs.map +1 -0
  78. package/dist/esm/menu/types.native.js +2 -0
  79. package/dist/esm/menu/types.native.js.map +1 -0
  80. package/dist/esm/split-view/index.mjs +3 -0
  81. package/dist/esm/split-view/index.mjs.map +1 -0
  82. package/dist/esm/split-view/index.native.js +3 -0
  83. package/dist/esm/split-view/index.native.js.map +1 -0
  84. package/dist/esm/split-view/split-view.mjs +46 -0
  85. package/dist/esm/split-view/split-view.mjs.map +1 -0
  86. package/dist/esm/split-view/split-view.native.js +51 -0
  87. package/dist/esm/split-view/split-view.native.js.map +1 -0
  88. package/dist/esm/toolbar/index.mjs +8 -0
  89. package/dist/esm/toolbar/index.mjs.map +1 -0
  90. package/dist/esm/toolbar/index.native.js +33 -0
  91. package/dist/esm/toolbar/index.native.js.map +1 -0
  92. package/dist/esm/toolbar/types.mjs +2 -0
  93. package/dist/esm/toolbar/types.mjs.map +1 -0
  94. package/dist/esm/toolbar/types.native.js +2 -0
  95. package/dist/esm/toolbar/types.native.js.map +1 -0
  96. package/dist/esm/zoom/index.mjs +11 -0
  97. package/dist/esm/zoom/index.mjs.map +1 -0
  98. package/dist/esm/zoom/index.native.js +37 -0
  99. package/dist/esm/zoom/index.native.js.map +1 -0
  100. package/dist/esm/zoom/types.mjs +2 -0
  101. package/dist/esm/zoom/types.mjs.map +1 -0
  102. package/dist/esm/zoom/types.native.js +2 -0
  103. package/dist/esm/zoom/types.native.js.map +1 -0
  104. package/ios/Menu/MenuActionView.swift +339 -0
  105. package/ios/Menu/VxrnMenuActionManager.m +47 -0
  106. package/ios/Toolbar/FontUtils.swift +46 -0
  107. package/ios/Toolbar/ToolbarHostView.swift +138 -0
  108. package/ios/Toolbar/ToolbarItemView.swift +334 -0
  109. package/ios/Toolbar/VxrnToolbarHostManager.m +20 -0
  110. package/ios/Toolbar/VxrnToolbarItemManager.m +41 -0
  111. package/ios/VxrnNative-Bridging-Header.h +7 -0
  112. package/ios/VxrnNative.podspec +31 -0
  113. package/ios/ZoomTransition/VxrnZoomAlignmentManager.m +22 -0
  114. package/ios/ZoomTransition/VxrnZoomEnablerManager.m +23 -0
  115. package/ios/ZoomTransition/VxrnZoomSourceManager.m +24 -0
  116. package/ios/ZoomTransition/ZoomTransition.swift +384 -0
  117. package/package.json +82 -0
  118. package/react-native.config.js +14 -0
  119. package/src/color/android.dynamic.types.ts +384 -0
  120. package/src/color/android.material.types.ts +291 -0
  121. package/src/color/index.native.ts +75 -0
  122. package/src/color/index.ts +75 -0
  123. package/src/color/ios.types.ts +156 -0
  124. package/src/color/materialColor.native.ts +15 -0
  125. package/src/color/materialColor.ts +7 -0
  126. package/src/index.ts +20 -0
  127. package/src/menu/index.native.tsx +28 -0
  128. package/src/menu/index.ts +7 -0
  129. package/src/menu/types.ts +32 -0
  130. package/src/split-view/index.ts +2 -0
  131. package/src/split-view/split-view.tsx +80 -0
  132. package/src/toolbar/index.native.tsx +39 -0
  133. package/src/toolbar/index.ts +11 -0
  134. package/src/toolbar/types.ts +39 -0
  135. package/src/zoom/index.native.tsx +56 -0
  136. package/src/zoom/index.ts +28 -0
  137. package/src/zoom/types.ts +30 -0
  138. package/tsconfig.json +7 -0
  139. package/types/color/android.dynamic.types.d.ts +384 -0
  140. package/types/color/android.dynamic.types.d.ts.map +1 -0
  141. package/types/color/android.material.types.d.ts +291 -0
  142. package/types/color/android.material.types.d.ts.map +1 -0
  143. package/types/color/index.d.ts +25 -0
  144. package/types/color/index.d.ts.map +1 -0
  145. package/types/color/index.native.d.ts +25 -0
  146. package/types/color/index.native.d.ts.map +1 -0
  147. package/types/color/ios.types.d.ts +156 -0
  148. package/types/color/ios.types.d.ts.map +1 -0
  149. package/types/color/materialColor.d.ts +3 -0
  150. package/types/color/materialColor.d.ts.map +1 -0
  151. package/types/color/materialColor.native.d.ts +3 -0
  152. package/types/color/materialColor.native.d.ts.map +1 -0
  153. package/types/index.d.ts +10 -0
  154. package/types/index.d.ts.map +1 -0
  155. package/types/menu/index.d.ts +4 -0
  156. package/types/menu/index.d.ts.map +1 -0
  157. package/types/menu/index.native.d.ts +4 -0
  158. package/types/menu/index.native.d.ts.map +1 -0
  159. package/types/menu/types.d.ts +32 -0
  160. package/types/menu/types.d.ts.map +1 -0
  161. package/types/split-view/index.d.ts +3 -0
  162. package/types/split-view/index.d.ts.map +1 -0
  163. package/types/split-view/split-view.d.ts +19 -0
  164. package/types/split-view/split-view.d.ts.map +1 -0
  165. package/types/toolbar/index.d.ts +5 -0
  166. package/types/toolbar/index.d.ts.map +1 -0
  167. package/types/toolbar/index.native.d.ts +5 -0
  168. package/types/toolbar/index.native.d.ts.map +1 -0
  169. package/types/toolbar/types.d.ts +37 -0
  170. package/types/toolbar/types.d.ts.map +1 -0
  171. package/types/zoom/index.d.ts +6 -0
  172. package/types/zoom/index.d.ts.map +1 -0
  173. package/types/zoom/index.native.d.ts +6 -0
  174. package/types/zoom/index.native.d.ts.map +1 -0
  175. package/types/zoom/types.d.ts +26 -0
  176. package/types/zoom/types.d.ts.map +1 -0
@@ -0,0 +1,384 @@
1
+ // adapted from expo-router (MIT license) - https://github.com/expo/expo
2
+ import React
3
+
4
+ // RNSScreen accessed via NSClassFromString without direct import
5
+ import UIKit
6
+
7
+ // MARK: - singleton manager for zoom transition repositories
8
+
9
+ class VxrnNativeZoomManager {
10
+ static let shared = VxrnNativeZoomManager()
11
+ let sourceRepository = ZoomTransitionsSourceRepository()
12
+ let alignmentViewRepository = ZoomTransitionsAlignmentViewRepository()
13
+ private init() {}
14
+ }
15
+
16
+ // MARK: - source info
17
+
18
+ class SourceInfo {
19
+ var alignment: CGRect?
20
+ var animateAspectRatioChange: Bool
21
+ weak var view: UIView?
22
+
23
+ init(view: UIView, alignment: CGRect?, animateAspectRatioChange: Bool) {
24
+ self.view = view
25
+ self.alignment = alignment
26
+ self.animateAspectRatioChange = animateAspectRatioChange
27
+ }
28
+ }
29
+
30
+ // MARK: - repositories
31
+
32
+ class ZoomTransitionsSourceRepository {
33
+ private var sources: [String: SourceInfo] = [:]
34
+ private let lock = NSLock()
35
+
36
+ func registerSource(identifier: String, source: SourceInfo) {
37
+ lock.lock()
38
+ defer { lock.unlock() }
39
+ if sources[identifier] != nil {
40
+ NSLog("[@vxrn/native] ZoomSource with identifier %@ is already registered.", identifier)
41
+ }
42
+ if !identifier.isEmpty {
43
+ sources[identifier] = source
44
+ }
45
+ }
46
+
47
+ func unregisterSource(identifier: String) {
48
+ lock.lock()
49
+ defer { lock.unlock() }
50
+ sources.removeValue(forKey: identifier)
51
+ }
52
+
53
+ func getSource(identifier: String) -> SourceInfo? {
54
+ lock.lock()
55
+ defer { lock.unlock() }
56
+ return sources[identifier]
57
+ }
58
+
59
+ func updateIdentifier(oldIdentifier: String, newIdentifier: String) {
60
+ lock.lock()
61
+ defer { lock.unlock() }
62
+ if let source = sources[oldIdentifier] {
63
+ if !newIdentifier.isEmpty {
64
+ sources[newIdentifier] = source
65
+ }
66
+ sources.removeValue(forKey: oldIdentifier)
67
+ }
68
+ }
69
+
70
+ func updateAlignment(identifier: String, alignment: CGRect?) {
71
+ lock.lock()
72
+ defer { lock.unlock() }
73
+ if let source = sources[identifier], !identifier.isEmpty {
74
+ source.alignment = alignment
75
+ }
76
+ }
77
+
78
+ func updateAnimateAspectRatioChange(identifier: String, animateAspectRatioChange: Bool) {
79
+ lock.lock()
80
+ defer { lock.unlock() }
81
+ if let source: SourceInfo = sources[identifier], !identifier.isEmpty {
82
+ source.animateAspectRatioChange = animateAspectRatioChange
83
+ }
84
+ }
85
+ }
86
+
87
+ class ZoomTransitionsAlignmentViewRepository {
88
+ private var alignmentViews: [String: WeakUIView] = [:]
89
+ private let lock = NSLock()
90
+
91
+ func addIfNotExists(identifier: String, alignmentView: UIView) {
92
+ lock.lock()
93
+ defer { lock.unlock() }
94
+ if alignmentViews[identifier] == nil && !identifier.isEmpty {
95
+ alignmentViews[identifier] = WeakUIView(view: alignmentView)
96
+ }
97
+ }
98
+
99
+ func removeIfSame(identifier: String, alignmentView: UIView) {
100
+ lock.lock()
101
+ defer { lock.unlock() }
102
+ if let existing = alignmentViews[identifier], existing.view === alignmentView {
103
+ alignmentViews.removeValue(forKey: identifier)
104
+ }
105
+ }
106
+
107
+ func get(identifier: String) -> UIView? {
108
+ lock.lock()
109
+ defer { lock.unlock() }
110
+ return alignmentViews[identifier]?.view
111
+ }
112
+
113
+ private class WeakUIView {
114
+ weak var view: UIView?
115
+ init(view: UIView) {
116
+ self.view = view
117
+ }
118
+ }
119
+ }
120
+
121
+ // MARK: - dismissal bounds rect (plain struct, no Expo Record)
122
+
123
+ struct DismissalBoundsRect {
124
+ var minX: Double?
125
+ var maxX: Double?
126
+ var minY: Double?
127
+ var maxY: Double?
128
+
129
+ init(dict: NSDictionary?) {
130
+ guard let dict = dict else { return }
131
+ minX = dict["minX"] as? Double
132
+ maxX = dict["maxX"] as? Double
133
+ minY = dict["minY"] as? Double
134
+ maxY = dict["maxY"] as? Double
135
+ }
136
+ }
137
+
138
+ // MARK: - zoom transition source view
139
+
140
+ @objc(ZoomTransitionSourceView) public
141
+ class ZoomTransitionSourceView: RCTView {
142
+ private var child: UIView?
143
+ private var sourceRepository: ZoomTransitionsSourceRepository { VxrnNativeZoomManager.shared.sourceRepository }
144
+
145
+ private var _identifier: String = ""
146
+ @objc var identifier: NSString = "" {
147
+ didSet {
148
+ let newId = identifier as String
149
+ let oldId = _identifier
150
+ _identifier = newId
151
+ guard newId != oldId else { return }
152
+ if let child = child {
153
+ if oldId.isEmpty {
154
+ sourceRepository.registerSource(
155
+ identifier: newId,
156
+ source: SourceInfo(
157
+ view: child, alignment: _alignment,
158
+ animateAspectRatioChange: _animateAspectRatioChange))
159
+ } else {
160
+ sourceRepository.updateIdentifier(oldIdentifier: oldId, newIdentifier: newId)
161
+ }
162
+ } else {
163
+ sourceRepository.unregisterSource(identifier: oldId)
164
+ }
165
+ }
166
+ }
167
+
168
+ private var _alignment: CGRect?
169
+ @objc var alignment: NSDictionary? {
170
+ didSet {
171
+ if let dict = alignment {
172
+ let x = dict["x"] as? Double ?? 0
173
+ let y = dict["y"] as? Double ?? 0
174
+ let width = dict["width"] as? Double ?? 0
175
+ let height = dict["height"] as? Double ?? 0
176
+ _alignment = CGRect(x: x, y: y, width: width, height: height)
177
+ } else {
178
+ _alignment = nil
179
+ }
180
+ if child != nil {
181
+ sourceRepository.updateAlignment(identifier: _identifier, alignment: _alignment)
182
+ }
183
+ }
184
+ }
185
+
186
+ private var _animateAspectRatioChange: Bool = false
187
+ @objc var animateAspectRatioChange: Bool = false {
188
+ didSet {
189
+ _animateAspectRatioChange = animateAspectRatioChange
190
+ if child != nil {
191
+ sourceRepository.updateAnimateAspectRatioChange(
192
+ identifier: _identifier, animateAspectRatioChange: animateAspectRatioChange)
193
+ }
194
+ }
195
+ }
196
+
197
+ public override func insertReactSubview(_ subview: UIView!, at atIndex: Int) {
198
+ guard child == nil else {
199
+ NSLog("[@vxrn/native] ZoomSource can only have a single native child.")
200
+ return
201
+ }
202
+ child = subview
203
+ sourceRepository.registerSource(
204
+ identifier: _identifier,
205
+ source: SourceInfo(
206
+ view: subview, alignment: _alignment,
207
+ animateAspectRatioChange: _animateAspectRatioChange))
208
+ super.insertReactSubview(subview, at: atIndex)
209
+ }
210
+
211
+ public override func removeReactSubview(_ subview: UIView!) {
212
+ guard subview === self.child else { return }
213
+ self.child = nil
214
+ sourceRepository.unregisterSource(identifier: _identifier)
215
+ super.removeReactSubview(subview)
216
+ }
217
+ }
218
+
219
+ // MARK: - zoom transition alignment rect detector view
220
+
221
+ @objc(ZoomTransitionAlignmentRectDetectorView) public
222
+ class ZoomTransitionAlignmentRectDetectorView: RCTView {
223
+ private var child: UIView?
224
+ private var alignmentViewRepository: ZoomTransitionsAlignmentViewRepository { VxrnNativeZoomManager.shared.alignmentViewRepository }
225
+
226
+ private var _identifier: String = ""
227
+ @objc var identifier: NSString = "" {
228
+ didSet {
229
+ let newId = identifier as String
230
+ let oldId = _identifier
231
+ if oldId != newId && !oldId.isEmpty {
232
+ NSLog("[@vxrn/native] AlignmentRectDetector does not support changing identifier.")
233
+ return
234
+ }
235
+ _identifier = newId
236
+ if let child = child {
237
+ alignmentViewRepository.addIfNotExists(identifier: newId, alignmentView: child)
238
+ }
239
+ }
240
+ }
241
+
242
+ public override func insertReactSubview(_ subview: UIView!, at atIndex: Int) {
243
+ guard child == nil else {
244
+ NSLog("[@vxrn/native] ZoomTarget can only have a single native child.")
245
+ return
246
+ }
247
+ if !_identifier.isEmpty {
248
+ alignmentViewRepository.addIfNotExists(identifier: _identifier, alignmentView: subview)
249
+ }
250
+ self.child = subview
251
+ super.insertReactSubview(subview, at: atIndex)
252
+ }
253
+
254
+ public override func removeReactSubview(_ subview: UIView!) {
255
+ guard subview === self.child else { return }
256
+ self.child = nil
257
+ alignmentViewRepository.removeIfSame(identifier: _identifier, alignmentView: subview)
258
+ super.removeReactSubview(subview)
259
+ }
260
+ }
261
+
262
+ // MARK: - zoom transition enabler view
263
+
264
+ @objc(ZoomTransitionEnablerView) public
265
+ class ZoomTransitionEnablerView: RCTView {
266
+ private var sourceRepository: ZoomTransitionsSourceRepository { VxrnNativeZoomManager.shared.sourceRepository }
267
+ private var alignmentViewRepository: ZoomTransitionsAlignmentViewRepository { VxrnNativeZoomManager.shared.alignmentViewRepository }
268
+
269
+ private var _zoomTransitionSourceIdentifier: String = ""
270
+ @objc var zoomTransitionSourceIdentifier: NSString = "" {
271
+ didSet {
272
+ _zoomTransitionSourceIdentifier = zoomTransitionSourceIdentifier as String
273
+ }
274
+ }
275
+
276
+ private var _dismissalBoundsRect: DismissalBoundsRect?
277
+ @objc var dismissalBoundsRect: NSDictionary? {
278
+ didSet {
279
+ _dismissalBoundsRect = DismissalBoundsRect(dict: dismissalBoundsRect)
280
+ if superview != nil {
281
+ DispatchQueue.main.async { self.setupZoomTransition() }
282
+ }
283
+ }
284
+ }
285
+
286
+ public override func didMoveToSuperview() {
287
+ super.didMoveToSuperview()
288
+ if superview != nil {
289
+ DispatchQueue.main.async { self.setupZoomTransition() }
290
+ }
291
+ }
292
+
293
+ private func setupZoomTransition() {
294
+ if _zoomTransitionSourceIdentifier.isEmpty {
295
+ NSLog("[@vxrn/native] No zoomTransitionSourceIdentifier passed to ZoomTransitionEnabler.")
296
+ return
297
+ }
298
+ if let controller = self.findViewController() {
299
+ NSLog("[@vxrn/native] Found VC: %@ (class: %@) for zoom id: %@", controller.description, String(describing: type(of: controller)), _zoomTransitionSourceIdentifier)
300
+ if #available(iOS 18.0, *) {
301
+ let options = UIViewController.Transition.ZoomOptions()
302
+
303
+ options.alignmentRectProvider = { context in
304
+ guard let sourceInfo = self.sourceRepository.getSource(
305
+ identifier: self._zoomTransitionSourceIdentifier)
306
+ else { return nil }
307
+ guard let alignmentView = self.alignmentViewRepository.get(
308
+ identifier: self._zoomTransitionSourceIdentifier)
309
+ else { return sourceInfo.alignment }
310
+
311
+ let rect = alignmentView.convert(
312
+ alignmentView.bounds, to: context.zoomedViewController.view)
313
+ if sourceInfo.animateAspectRatioChange, let sourceView = sourceInfo.view {
314
+ return self.calculateAdjustedRect(rect, toMatch: sourceView.bounds.size)
315
+ }
316
+ return rect
317
+ }
318
+
319
+ if let rect = _dismissalBoundsRect {
320
+ options.interactiveDismissShouldBegin = { context in
321
+ let location = context.location
322
+ if let minX = rect.minX, location.x < minX { return false }
323
+ if let maxX = rect.maxX, location.x > maxX { return false }
324
+ if let minY = rect.minY, location.y < minY { return false }
325
+ if let maxY = rect.maxY, location.y > maxY { return false }
326
+ return true
327
+ }
328
+ }
329
+
330
+ controller.preferredTransition = .zoom(options: options) { _ in
331
+ let sourceInfo = self.sourceRepository.getSource(
332
+ identifier: self._zoomTransitionSourceIdentifier)
333
+ guard let view = sourceInfo?.view else {
334
+ NSLog("[@vxrn/native] No source view found for identifier %@.", self._zoomTransitionSourceIdentifier)
335
+ return nil
336
+ }
337
+ NSLog("[@vxrn/native] Zoom source view found: %@ for id: %@", view.description, self._zoomTransitionSourceIdentifier)
338
+ return view
339
+ }
340
+ NSLog("[@vxrn/native] preferredTransition set to .zoom for VC: %@", controller.description)
341
+ return
342
+ }
343
+ } else {
344
+ NSLog("[@vxrn/native] No navigation controller found to enable zoom transition.")
345
+ }
346
+ }
347
+
348
+ private func calculateAdjustedRect(_ rect: CGRect, toMatch sourceSize: CGSize) -> CGRect {
349
+ guard sourceSize.width > 0, sourceSize.height > 0, rect.width > 0, rect.height > 0 else {
350
+ return rect
351
+ }
352
+ let sourceAspectRatio = sourceSize.width / sourceSize.height
353
+ let rectAspectRatio = rect.width / rect.height
354
+ if abs(sourceAspectRatio - rectAspectRatio) < 0.001 { return rect }
355
+ if rectAspectRatio > sourceAspectRatio {
356
+ let adjustedWidth = rect.height * sourceAspectRatio
357
+ return CGRect(x: rect.midX - (adjustedWidth / 2), y: rect.origin.y, width: adjustedWidth, height: rect.height)
358
+ }
359
+ let adjustedHeight = rect.width / sourceAspectRatio
360
+ return CGRect(x: rect.origin.x, y: rect.midY - (adjustedHeight / 2), width: rect.width, height: adjustedHeight)
361
+ }
362
+
363
+ private func findViewController() -> UIViewController? {
364
+ // find RNSScreen (react-native-screens VC) via class name to avoid import
365
+ let rnsScreenClass: AnyClass? = NSClassFromString("RNSScreen")
366
+ var responder: UIResponder? = self
367
+ while let r = responder {
368
+ if let vc = r as? UIViewController {
369
+ // prefer RNSScreen if available, otherwise fall back to any VC
370
+ if let rnsClass = rnsScreenClass, vc.isKind(of: rnsClass) {
371
+ return vc
372
+ }
373
+ }
374
+ responder = r.next
375
+ }
376
+ // fallback: return first VC found
377
+ responder = self
378
+ while let r = responder {
379
+ if let vc = r as? UIViewController { return vc }
380
+ responder = r.next
381
+ }
382
+ return nil
383
+ }
384
+ }
package/package.json ADDED
@@ -0,0 +1,82 @@
1
+ {
2
+ "name": "@vxrn/native",
3
+ "version": "1.12.8-1774390675831",
4
+ "type": "module",
5
+ "description": "Native navigation features for One - zoom transitions, toolbar, color API, split view",
6
+ "license": "MIT",
7
+ "main": "dist/cjs/index.cjs",
8
+ "module": "dist/esm/index.mjs",
9
+ "types": "types/index.d.ts",
10
+ "sideEffects": false,
11
+ "scripts": {
12
+ "build": "tamagui-build",
13
+ "clean": "tamagui-build clean"
14
+ },
15
+ "exports": {
16
+ ".": {
17
+ "react-native": {
18
+ "import": "./dist/esm/index.native.js",
19
+ "require": "./dist/cjs/index.native.js"
20
+ },
21
+ "import": "./dist/esm/index.mjs",
22
+ "require": "./dist/cjs/index.cjs"
23
+ },
24
+ "./color": {
25
+ "react-native": {
26
+ "import": "./dist/esm/color/index.native.js",
27
+ "require": "./dist/cjs/color/index.native.js"
28
+ },
29
+ "import": "./dist/esm/color/index.mjs",
30
+ "require": "./dist/cjs/color/index.cjs"
31
+ },
32
+ "./zoom": {
33
+ "react-native": {
34
+ "import": "./dist/esm/zoom/index.native.js",
35
+ "require": "./dist/cjs/zoom/index.native.js"
36
+ },
37
+ "import": "./dist/esm/zoom/index.mjs",
38
+ "require": "./dist/cjs/zoom/index.cjs"
39
+ },
40
+ "./toolbar": {
41
+ "react-native": {
42
+ "import": "./dist/esm/toolbar/index.native.js",
43
+ "require": "./dist/cjs/toolbar/index.native.js"
44
+ },
45
+ "import": "./dist/esm/toolbar/index.mjs",
46
+ "require": "./dist/cjs/toolbar/index.cjs"
47
+ },
48
+ "./menu": {
49
+ "react-native": {
50
+ "import": "./dist/esm/menu/index.native.js",
51
+ "require": "./dist/cjs/menu/index.native.js"
52
+ },
53
+ "import": "./dist/esm/menu/index.mjs",
54
+ "require": "./dist/cjs/menu/index.cjs"
55
+ },
56
+ "./split-view": {
57
+ "react-native": {
58
+ "import": "./dist/esm/split-view/index.native.js",
59
+ "require": "./dist/cjs/split-view/index.native.js"
60
+ },
61
+ "import": "./dist/esm/split-view/index.mjs",
62
+ "require": "./dist/cjs/split-view/index.cjs"
63
+ }
64
+ },
65
+ "publishConfig": {
66
+ "access": "public"
67
+ },
68
+ "peerDependencies": {
69
+ "react": "*",
70
+ "react-native": "*",
71
+ "react-native-screens": "~4.24.0",
72
+ "react-native-safe-area-context": ">=5.4.0"
73
+ },
74
+ "peerDependenciesMeta": {
75
+ "react-native-safe-area-context": {
76
+ "optional": true
77
+ }
78
+ },
79
+ "devDependencies": {
80
+ "@tamagui/build": "2.0.0-rc.31"
81
+ }
82
+ }
@@ -0,0 +1,14 @@
1
+ module.exports = {
2
+ dependency: {
3
+ platforms: {
4
+ ios: {
5
+ podspecPath: './ios/VxrnNative.podspec',
6
+ },
7
+ android: {
8
+ sourceDir: './android',
9
+ packageImportPath: 'import dev.vxrn.native.VxrnNativePackage;',
10
+ packageInstance: 'new VxrnNativePackage()',
11
+ },
12
+ },
13
+ },
14
+ }