@thelacanians/vue-native-cli 0.4.14 → 0.6.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 (123) hide show
  1. package/dist/cli.js +789 -200
  2. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/NativeBridge.kt +156 -5
  3. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VListFactory.kt +33 -13
  4. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VScrollViewFactory.kt +27 -6
  5. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VSliderFactory.kt +9 -2
  6. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VViewFactory.kt +178 -1
  7. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Helpers/EventThrottle.kt +57 -0
  8. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/GeneratedModuleRegistry.kt +28 -0
  9. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/NativeModuleRegistry.kt +3 -0
  10. package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/ComponentFactoryTest.kt +674 -0
  11. package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/ErrorOverlayViewTest.kt +183 -0
  12. package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/EventThrottleTest.kt +203 -0
  13. package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/HotReloadManagerTest.kt +162 -0
  14. package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/JSPolyfillsTest.kt +153 -0
  15. package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/NativeBridgeTest.kt +6 -3
  16. package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/NativeModuleTest.kt +475 -0
  17. package/native/android/gradle.properties +1 -0
  18. package/native/android/gradlew +1 -1
  19. package/native/ios/VueNativeCore/Package.swift +1 -1
  20. package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/EventThrottle.swift +80 -0
  21. package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/NativeBridge.swift +244 -112
  22. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VListFactory.swift +19 -2
  23. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VScrollViewFactory.swift +9 -4
  24. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VSliderFactory.swift +8 -3
  25. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VTextFactory.swift +43 -0
  26. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VViewFactory.swift +116 -4
  27. package/native/ios/VueNativeCore/Sources/VueNativeCore/Helpers/GestureWrapper.swift +100 -0
  28. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/GeneratedModuleRegistry.swift +28 -0
  29. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NativeModuleRegistry.swift +3 -0
  30. package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/CertificatePinningTests.swift +190 -0
  31. package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/ComponentFactoryTests.swift +585 -0
  32. package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/EventThrottleTests.swift +161 -0
  33. package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/HotReloadManagerTests.swift +88 -0
  34. package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/JSPolyfillsTests.swift +319 -0
  35. package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/NativeModuleTests.swift +400 -0
  36. package/native/macos/VueNativeMacOS/Package.swift +34 -0
  37. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/ErrorOverlayView.swift +112 -0
  38. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/EventThrottle.swift +58 -0
  39. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/HotReloadManager.swift +153 -0
  40. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/JSPolyfills.swift +696 -0
  41. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/JSRuntime.swift +347 -0
  42. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/NativeBridge.swift +877 -0
  43. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/VueNativeWindowController.swift +125 -0
  44. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/ComponentRegistry.swift +209 -0
  45. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VActionSheetFactory.swift +155 -0
  46. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VActivityIndicatorFactory.swift +85 -0
  47. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VAlertDialogFactory.swift +132 -0
  48. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VButtonFactory.swift +83 -0
  49. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VCheckboxFactory.swift +108 -0
  50. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VDropdownFactory.swift +155 -0
  51. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VImageFactory.swift +270 -0
  52. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VInputFactory.swift +257 -0
  53. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VKeyboardAvoidingFactory.swift +22 -0
  54. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VListFactory.swift +324 -0
  55. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VModalFactory.swift +231 -0
  56. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VOutlineViewFactory.swift +276 -0
  57. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VPickerFactory.swift +134 -0
  58. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VPressableFactory.swift +120 -0
  59. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VProgressBarFactory.swift +71 -0
  60. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VRadioFactory.swift +193 -0
  61. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VRefreshControlFactory.swift +25 -0
  62. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSafeAreaFactory.swift +46 -0
  63. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VScrollViewFactory.swift +190 -0
  64. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSectionListFactory.swift +374 -0
  65. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSegmentedControlFactory.swift +125 -0
  66. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSliderFactory.swift +131 -0
  67. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSplitViewFactory.swift +215 -0
  68. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VStatusBarFactory.swift +25 -0
  69. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSwitchFactory.swift +92 -0
  70. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VTextFactory.swift +336 -0
  71. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VToolbarFactory.swift +212 -0
  72. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VVideoFactory.swift +245 -0
  73. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VViewFactory.swift +314 -0
  74. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VWebViewFactory.swift +162 -0
  75. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/NativeComponentFactory.swift +54 -0
  76. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/ClickableView.swift +100 -0
  77. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/Extensions.swift +23 -0
  78. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/GestureWrapper.swift +183 -0
  79. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/NSColor+Hex.swift +78 -0
  80. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Layout/FlippedView.swift +19 -0
  81. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Layout/LayoutNode.swift +493 -0
  82. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/AnimationModule.swift +354 -0
  83. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/AppStateModule.swift +62 -0
  84. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/BiometryModule.swift +60 -0
  85. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/CameraModule.swift +167 -0
  86. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/ClipboardModule.swift +34 -0
  87. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/DeviceInfoModule.swift +49 -0
  88. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/DragDropModule.swift +50 -0
  89. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/FileDialogModule.swift +86 -0
  90. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/HapticsModule.swift +42 -0
  91. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/KeyboardModule.swift +28 -0
  92. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/LinkingModule.swift +49 -0
  93. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/MenuModule.swift +95 -0
  94. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/NativeModuleRegistry.swift +63 -0
  95. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/NotificationsModule.swift +112 -0
  96. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/PermissionsModule.swift +149 -0
  97. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/ShareModule.swift +37 -0
  98. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/WindowModule.swift +71 -0
  99. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Resources/vue-native-placeholder.js +2 -0
  100. package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Styling/StyleEngine.swift +885 -0
  101. package/native/macos/VueNativeMacOS/Tests/VueNativeMacOSTests/ComponentFactoryTests.swift +80 -0
  102. package/native/macos/VueNativeMacOS/Tests/VueNativeMacOSTests/VueNativeMacOSTests.swift +149 -0
  103. package/native/shared/VueNativeShared/AGENTS.md +129 -0
  104. package/native/shared/VueNativeShared/Package.swift +14 -0
  105. package/native/shared/VueNativeShared/Sources/VueNativeShared/CertificatePinning.swift +134 -0
  106. package/native/shared/VueNativeShared/Sources/VueNativeShared/EventThrottle.swift +78 -0
  107. package/native/shared/VueNativeShared/Sources/VueNativeShared/HotReloadManager.swift +162 -0
  108. package/native/shared/VueNativeShared/Sources/VueNativeShared/JSRuntime.swift +412 -0
  109. package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/AsyncStorageModule.swift +68 -0
  110. package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/AudioModule.swift +359 -0
  111. package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/DatabaseModule.swift +259 -0
  112. package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/FileSystemModule.swift +233 -0
  113. package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/GeolocationModule.swift +156 -0
  114. package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/NetworkModule.swift +59 -0
  115. package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/PerformanceModule.swift +113 -0
  116. package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/SecureStorageModule.swift +119 -0
  117. package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/WebSocketModule.swift +212 -0
  118. package/native/shared/VueNativeShared/Sources/VueNativeShared/NativeEventDispatcher.swift +6 -0
  119. package/native/shared/VueNativeShared/Sources/VueNativeShared/NativeModule.swift +26 -0
  120. package/native/shared/VueNativeShared/Sources/VueNativeShared/NativeModuleRegistry.swift +37 -0
  121. package/native/shared/VueNativeShared/Sources/VueNativeShared/SharedJSPolyfills.swift +673 -0
  122. package/native/shared/VueNativeShared/Tests/VueNativeSharedTests/VueNativeSharedTests.swift +44 -0
  123. package/package.json +8 -2
@@ -87,6 +87,51 @@ final class VViewFactory: NativeComponentFactory {
87
87
  view.isUserInteractionEnabled = true
88
88
  GestureStorage.storeObject(pinchWrapper, for: view, event: event)
89
89
 
90
+ // MARK: Rotation
91
+ case "rotate":
92
+ let rotationWrapper = RotationWrapper(handler: handler)
93
+ let rotation = UIRotationGestureRecognizer(
94
+ target: rotationWrapper,
95
+ action: #selector(RotationWrapper.handle(_:))
96
+ )
97
+ view.addGestureRecognizer(rotation)
98
+ view.isUserInteractionEnabled = true
99
+ GestureStorage.storeObject(rotationWrapper, for: view, event: event)
100
+
101
+ // MARK: Double Tap
102
+ case "doubleTap":
103
+ let wrapper = DoubleTapWrapper(handler: handler)
104
+ let tapRecognizer = UITapGestureRecognizer(
105
+ target: wrapper,
106
+ action: #selector(DoubleTapWrapper.handleGesture(_:))
107
+ )
108
+ tapRecognizer.numberOfTapsRequired = 2
109
+ view.addGestureRecognizer(tapRecognizer)
110
+ view.isUserInteractionEnabled = true
111
+ GestureStorage.storeObject(wrapper, for: view, event: event)
112
+
113
+ // MARK: Force Touch (3D Touch)
114
+ case "forceTouch":
115
+ let wrapper = ForceTouchWrapper(handler: handler)
116
+ // Force touch is handled via touch events, not gesture recognizers
117
+ // We store the wrapper and will handle it in a custom touch handler
118
+ GestureStorage.storeObject(wrapper, for: view, event: event)
119
+ // Enable force touch on the view
120
+ view.isUserInteractionEnabled = true
121
+ attachForceTouchHandler(to: view, wrapper: wrapper)
122
+
123
+ // MARK: Hover (iOS 13+)
124
+ case "hover":
125
+ if #available(iOS 13.0, *) {
126
+ let hoverWrapper = HoverWrapper(handler: handler)
127
+ let hover = UIHoverGestureRecognizer(
128
+ target: hoverWrapper,
129
+ action: #selector(HoverWrapper.handleGesture(_:))
130
+ )
131
+ view.addGestureRecognizer(hover)
132
+ GestureStorage.storeObject(hoverWrapper, for: view, event: event)
133
+ }
134
+
90
135
  default:
91
136
  break
92
137
  }
@@ -97,24 +142,91 @@ final class VViewFactory: NativeComponentFactory {
97
142
  // Remove matching gesture recognizers
98
143
  view.gestureRecognizers?.forEach { recognizer in
99
144
  switch event {
100
- case "press" where recognizer is UITapGestureRecognizer:
101
- view.removeGestureRecognizer(recognizer)
145
+ case "press":
146
+ if let tap = recognizer as? UITapGestureRecognizer, tap.numberOfTapsRequired == 1 {
147
+ view.removeGestureRecognizer(recognizer)
148
+ }
102
149
  case "longpress" where recognizer is UILongPressGestureRecognizer:
103
150
  view.removeGestureRecognizer(recognizer)
104
151
  case "pan" where recognizer is UIPanGestureRecognizer:
105
152
  view.removeGestureRecognizer(recognizer)
106
- case "swipeLeft", "swipeRight", "swipeUp", "swipeDown"
107
- where recognizer is UISwipeGestureRecognizer:
153
+ case "swipeLeft" where recognizer is UISwipeGestureRecognizer:
154
+ view.removeGestureRecognizer(recognizer)
155
+ case "swipeRight" where recognizer is UISwipeGestureRecognizer:
156
+ view.removeGestureRecognizer(recognizer)
157
+ case "swipeUp" where recognizer is UISwipeGestureRecognizer:
158
+ view.removeGestureRecognizer(recognizer)
159
+ case "swipeDown" where recognizer is UISwipeGestureRecognizer:
108
160
  view.removeGestureRecognizer(recognizer)
109
161
  case "pinch" where recognizer is UIPinchGestureRecognizer:
110
162
  view.removeGestureRecognizer(recognizer)
163
+ case "rotate" where recognizer is UIRotationGestureRecognizer:
164
+ view.removeGestureRecognizer(recognizer)
165
+ case "doubleTap":
166
+ if let tap = recognizer as? UITapGestureRecognizer, tap.numberOfTapsRequired == 2 {
167
+ view.removeGestureRecognizer(recognizer)
168
+ }
169
+ case "hover":
170
+ if #available(iOS 13.0, *) {
171
+ if recognizer is UIHoverGestureRecognizer {
172
+ view.removeGestureRecognizer(recognizer)
173
+ }
174
+ }
111
175
  default:
112
176
  break
113
177
  }
114
178
  }
115
179
  }
180
+
181
+ // MARK: - Force Touch Helper
182
+
183
+ private func attachForceTouchHandler(to view: UIView, wrapper: ForceTouchWrapper) {
184
+ // ForceTouchHandler is attached via associated object
185
+ let handler = ForceTouchHandlerView(wrapper: wrapper)
186
+ objc_setAssociatedObject(view, &forceTouchHandlerKey, handler, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
187
+ handler.attach(to: view)
188
+ }
116
189
  }
117
190
 
191
+ // MARK: - ForceTouchHandlerView
192
+
193
+ /// Custom UIView subclass that monitors force touch events
194
+ private class ForceTouchHandlerView: UIView {
195
+ private let wrapper: ForceTouchWrapper
196
+ private weak var targetView: UIView?
197
+
198
+ init(wrapper: ForceTouchWrapper) {
199
+ self.wrapper = wrapper
200
+ super.init(frame: .zero)
201
+ }
202
+
203
+ required init?(coder: NSCoder) {
204
+ fatalError("init(coder:) has not been implemented")
205
+ }
206
+
207
+ func attach(to view: UIView) {
208
+ targetView = view
209
+ }
210
+
211
+ override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
212
+ super.touchesMoved(touches, with: event)
213
+ guard let touch = touches.first else { return }
214
+ let force = touch.force
215
+ let location = touch.location(in: targetView)
216
+ wrapper.handleTouch(force: force, location: location)
217
+ }
218
+
219
+ override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
220
+ super.touchesBegan(touches, with: event)
221
+ guard let touch = touches.first else { return }
222
+ let force = touch.force
223
+ let location = touch.location(in: targetView)
224
+ wrapper.handleTouch(force: force, location: location)
225
+ }
226
+ }
227
+
228
+ private var forceTouchHandlerKey: UInt8 = 0
229
+
118
230
  // MARK: - GestureStorage
119
231
 
120
232
  /// Stores gesture wrapper references as associated objects on views to prevent deallocation.
@@ -104,4 +104,104 @@ import UIKit
104
104
  ] as [String: Any])
105
105
  }
106
106
  }
107
+
108
+ // MARK: - RotationWrapper
109
+
110
+ /// ObjC-compatible wrapper for UIRotationGestureRecognizer action handlers.
111
+ @objc final class RotationWrapper: NSObject {
112
+ private let handler: (Any?) -> Void
113
+
114
+ init(handler: @escaping (Any?) -> Void) {
115
+ self.handler = handler
116
+ super.init()
117
+ }
118
+
119
+ @objc func handle(_ recognizer: UIRotationGestureRecognizer) {
120
+ let stateStr: String
121
+ switch recognizer.state {
122
+ case .began: stateStr = "began"
123
+ case .changed: stateStr = "changed"
124
+ case .ended: stateStr = "ended"
125
+ default: stateStr = "cancelled"
126
+ }
127
+ handler([
128
+ "rotation": recognizer.rotation,
129
+ "velocity": recognizer.velocity,
130
+ "state": stateStr
131
+ ] as [String: Any])
132
+ }
133
+ }
134
+
135
+ // MARK: - ForceTouchWrapper
136
+
137
+ /// Wrapper for 3D Touch / Force Touch gesture handlers.
138
+ @objc final class ForceTouchWrapper: NSObject {
139
+ private let handler: (Any?) -> Void
140
+ private var lastForce: CGFloat = 0
141
+
142
+ init(handler: @escaping (Any?) -> Void) {
143
+ self.handler = handler
144
+ super.init()
145
+ }
146
+
147
+ func handleTouch(force: CGFloat, location: CGPoint) {
148
+ let payload: [String: Any] = [
149
+ "force": force,
150
+ "locationX": location.x,
151
+ "locationY": location.y
152
+ ]
153
+ handler(payload)
154
+ }
155
+ }
156
+
157
+ // MARK: - DoubleTapWrapper
158
+
159
+ /// ObjC-compatible wrapper for double-tap gesture handlers.
160
+ @objc final class DoubleTapWrapper: NSObject {
161
+ private let handler: (Any?) -> Void
162
+
163
+ init(handler: @escaping (Any?) -> Void) {
164
+ self.handler = handler
165
+ super.init()
166
+ }
167
+
168
+ @objc func handleGesture(_ gesture: UITapGestureRecognizer) {
169
+ let location = gesture.location(in: gesture.view)
170
+ let payload: [String: Any] = [
171
+ "locationX": location.x,
172
+ "locationY": location.y
173
+ ]
174
+ handler(payload)
175
+ }
176
+ }
177
+
178
+ // MARK: - HoverWrapper
179
+
180
+ /// Wrapper for hover gesture handlers (iOS 13+).
181
+ @objc final class HoverWrapper: NSObject {
182
+ private let handler: (Any?) -> Void
183
+
184
+ init(handler: @escaping (Any?) -> Void) {
185
+ self.handler = handler
186
+ super.init()
187
+ }
188
+
189
+ @objc func handleGesture(_ gesture: UIHoverGestureRecognizer) {
190
+ guard let view = gesture.view else { return }
191
+ let location = gesture.location(in: view)
192
+ let stateStr: String
193
+ switch gesture.state {
194
+ case .began: stateStr = "began"
195
+ case .changed: stateStr = "changed"
196
+ case .ended: stateStr = "ended"
197
+ default: stateStr = "cancelled"
198
+ }
199
+ let payload: [String: Any] = [
200
+ "locationX": location.x,
201
+ "locationY": location.y,
202
+ "state": stateStr
203
+ ]
204
+ handler(payload)
205
+ }
206
+ }
107
207
  #endif
@@ -0,0 +1,28 @@
1
+ // ────────────────────────────────────────────────────────────────────────────────
2
+ // Auto-Generated Module Registration
3
+ // ────────────────────────────────────────────────────────────────────────────────
4
+ //
5
+ // ⚠️ WARNING: This file is auto-generated. DO NOT EDIT MANUALLY.
6
+ // Changes will be overwritten by the vue-native-codegen tool.
7
+ //
8
+ // Generated: {{GENERATED_DATE}}
9
+ //
10
+ // This file registers all native modules generated from <native> blocks
11
+ // in Vue SFC files.
12
+ //
13
+ // ────────────────────────────────────────────────────────────────────────────────
14
+
15
+ import Foundation
16
+
17
+ @MainActor
18
+ extension NativeModuleRegistry {
19
+ /// Register all generated native modules from <native> blocks
20
+ func registerGeneratedModules() {
21
+ // Generated modules will be registered here
22
+ // Example:
23
+ // register(HapticsModule())
24
+ // register(CameraModule())
25
+
26
+ // This function is called automatically after registerDefaults()
27
+ }
28
+ }
@@ -55,6 +55,9 @@ final class NativeModuleRegistry {
55
55
  register(BluetoothModule(bridge: bridge))
56
56
  register(CalendarModule())
57
57
  register(ContactsModule())
58
+
59
+ // Register generated modules from <native> blocks
60
+ registerGeneratedModules()
58
61
  }
59
62
 
60
63
  // MARK: - Invocation
@@ -0,0 +1,190 @@
1
+ #if canImport(UIKit)
2
+ import XCTest
3
+ import UIKit
4
+ @testable import VueNativeCore
5
+
6
+ @MainActor
7
+ final class CertificatePinningTests: XCTestCase {
8
+
9
+ // MARK: - Properties
10
+
11
+ private var pinning: CertificatePinning!
12
+
13
+ // MARK: - Setup / Teardown
14
+
15
+ override func setUp() {
16
+ super.setUp()
17
+ pinning = CertificatePinning.shared
18
+ pinning.clearPins()
19
+ }
20
+
21
+ override func tearDown() {
22
+ pinning.clearPins()
23
+ pinning = nil
24
+ super.tearDown()
25
+ }
26
+
27
+ // MARK: - Singleton Tests
28
+
29
+ func testSharedInstanceIsSingleton() {
30
+ let instance1 = CertificatePinning.shared
31
+ let instance2 = CertificatePinning.shared
32
+ XCTAssertTrue(instance1 === instance2, "CertificatePinning.shared should always return the same instance")
33
+ }
34
+
35
+ // MARK: - configurePins Tests
36
+
37
+ func testConfigurePinsStoresHashesForDomain() {
38
+ pinning.configurePins([
39
+ "api.example.com": ["sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="]
40
+ ])
41
+
42
+ XCTAssertTrue(pinning.hasPins(for: "api.example.com"), "Should have pins for configured domain")
43
+ }
44
+
45
+ func testConfigurePinsMultipleDomains() {
46
+ pinning.configurePins([
47
+ "api.example.com": ["sha256/AAA="],
48
+ "cdn.example.com": ["sha256/BBB="]
49
+ ])
50
+
51
+ XCTAssertTrue(pinning.hasPins(for: "api.example.com"), "Should have pins for api.example.com")
52
+ XCTAssertTrue(pinning.hasPins(for: "cdn.example.com"), "Should have pins for cdn.example.com")
53
+ }
54
+
55
+ func testConfigurePinsMultipleHashesPerDomain() {
56
+ pinning.configurePins([
57
+ "api.example.com": ["sha256/PrimaryHash=", "sha256/BackupHash="]
58
+ ])
59
+
60
+ XCTAssertTrue(pinning.hasPins(for: "api.example.com"),
61
+ "Should have pins with multiple hashes")
62
+ }
63
+
64
+ func testConfigurePinsIgnoresMalformedPins() {
65
+ // Pins without "sha256/" prefix should be ignored
66
+ pinning.configurePins([
67
+ "api.example.com": ["md5/NotSupported"]
68
+ ])
69
+
70
+ XCTAssertFalse(pinning.hasPins(for: "api.example.com"),
71
+ "Malformed pins (without sha256/ prefix) should not register")
72
+ }
73
+
74
+ func testConfigurePinsIsCaseInsensitiveForDomain() {
75
+ pinning.configurePins([
76
+ "API.Example.COM": ["sha256/TestHash="]
77
+ ])
78
+
79
+ XCTAssertTrue(pinning.hasPins(for: "api.example.com"),
80
+ "Domain lookup should be case-insensitive")
81
+ }
82
+
83
+ // MARK: - hasPins Tests
84
+
85
+ func testHasPinsReturnsFalseForUnconfiguredDomain() {
86
+ XCTAssertFalse(pinning.hasPins(for: "unknown.com"),
87
+ "Should return false for domains without pins")
88
+ }
89
+
90
+ func testHasPinsReturnsTrueForConfiguredDomain() {
91
+ pinning.configurePins([
92
+ "example.com": ["sha256/TestHash="]
93
+ ])
94
+
95
+ XCTAssertTrue(pinning.hasPins(for: "example.com"),
96
+ "Should return true for configured domain")
97
+ }
98
+
99
+ func testHasPinsIsCaseInsensitive() {
100
+ pinning.configurePins([
101
+ "example.com": ["sha256/TestHash="]
102
+ ])
103
+
104
+ XCTAssertTrue(pinning.hasPins(for: "EXAMPLE.COM"),
105
+ "hasPins lookup should be case-insensitive")
106
+ }
107
+
108
+ // MARK: - clearPins Tests
109
+
110
+ func testClearPinsRemovesAllPins() {
111
+ pinning.configurePins([
112
+ "api.example.com": ["sha256/AAA="],
113
+ "cdn.example.com": ["sha256/BBB="]
114
+ ])
115
+
116
+ pinning.clearPins()
117
+
118
+ XCTAssertFalse(pinning.hasPins(for: "api.example.com"),
119
+ "clearPins should remove all configured pins")
120
+ XCTAssertFalse(pinning.hasPins(for: "cdn.example.com"),
121
+ "clearPins should remove all configured pins")
122
+ }
123
+
124
+ func testClearPinsOnEmptyDoesNotCrash() {
125
+ // Should not crash when called with no pins configured
126
+ pinning.clearPins()
127
+ }
128
+
129
+ // MARK: - Session Tests
130
+
131
+ func testSessionIsURLSession() {
132
+ let session = pinning.session
133
+ XCTAssertNotNil(session, "session should return a valid URLSession")
134
+ }
135
+
136
+ func testSessionIsSameInstance() {
137
+ let session1 = pinning.session
138
+ let session2 = pinning.session
139
+ XCTAssertTrue(session1 === session2, "session should return the same URLSession instance")
140
+ }
141
+
142
+ // MARK: - URLSessionDelegate Conformance
143
+
144
+ func testConformsToURLSessionDelegate() {
145
+ XCTAssertTrue(pinning is URLSessionDelegate,
146
+ "CertificatePinning should conform to URLSessionDelegate")
147
+ }
148
+
149
+ // MARK: - Empty Pins Allows Default Handling
150
+
151
+ func testNoPinsConfiguredAllowsDefaultHandling() {
152
+ // With no pins configured, hasPins should return false for any domain
153
+ XCTAssertFalse(pinning.hasPins(for: "anything.com"),
154
+ "Without pins configured, all domains should use default handling")
155
+ }
156
+
157
+ // MARK: - Backup Pin Support
158
+
159
+ func testBackupPinConfigured() {
160
+ // Configure primary + backup pins for a domain
161
+ pinning.configurePins([
162
+ "api.example.com": ["sha256/PrimaryHash=", "sha256/BackupHash="]
163
+ ])
164
+
165
+ // Both pins should be stored
166
+ XCTAssertTrue(pinning.hasPins(for: "api.example.com"),
167
+ "Domain should have pins configured including backup")
168
+ }
169
+
170
+ // MARK: - Additive Configuration
171
+
172
+ func testConfigurePinsIsAdditive() {
173
+ pinning.configurePins(["api.example.com": ["sha256/AAA="]])
174
+ pinning.configurePins(["cdn.example.com": ["sha256/BBB="]])
175
+
176
+ // First domain's pins may be overwritten or preserved depending on implementation.
177
+ // At minimum, the second domain should be configured.
178
+ XCTAssertTrue(pinning.hasPins(for: "cdn.example.com"),
179
+ "Adding pins for a new domain should work")
180
+ }
181
+
182
+ func testConfigurePinsSameDomainOverwrites() {
183
+ pinning.configurePins(["api.example.com": ["sha256/OldHash="]])
184
+ pinning.configurePins(["api.example.com": ["sha256/NewHash="]])
185
+
186
+ XCTAssertTrue(pinning.hasPins(for: "api.example.com"),
187
+ "Reconfiguring the same domain should still have pins")
188
+ }
189
+ }
190
+ #endif