@thelacanians/vue-native-cli 0.4.3 → 0.4.5

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 (173) hide show
  1. package/dist/cli.js +102 -32
  2. package/native/android/README.md +205 -0
  3. package/native/android/VueNativeCore/build.gradle.kts +113 -0
  4. package/native/android/VueNativeCore/consumer-rules.pro +12 -0
  5. package/native/android/VueNativeCore/proguard-rules.pro +33 -0
  6. package/native/android/VueNativeCore/src/main/AndroidManifest.xml +17 -0
  7. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/ErrorOverlayView.kt +94 -0
  8. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/HotReloadManager.kt +105 -0
  9. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/JSPolyfills.kt +652 -0
  10. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/JSRuntime.kt +207 -0
  11. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/NativeBridge.kt +417 -0
  12. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/ComponentRegistry.kt +76 -0
  13. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VActionSheetFactory.kt +78 -0
  14. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VActivityIndicatorFactory.kt +46 -0
  15. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VAlertDialogFactory.kt +84 -0
  16. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VButtonFactory.kt +73 -0
  17. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VCheckboxFactory.kt +93 -0
  18. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VDropdownFactory.kt +125 -0
  19. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VImageFactory.kt +75 -0
  20. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VInputFactory.kt +210 -0
  21. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VKeyboardAvoidingFactory.kt +31 -0
  22. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VListFactory.kt +183 -0
  23. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VModalFactory.kt +105 -0
  24. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VPickerFactory.kt +57 -0
  25. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VPressableFactory.kt +109 -0
  26. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VProgressBarFactory.kt +43 -0
  27. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VRadioFactory.kt +103 -0
  28. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VRefreshControlFactory.kt +73 -0
  29. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VRootFactory.kt +39 -0
  30. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VSafeAreaFactory.kt +48 -0
  31. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VScrollViewFactory.kt +105 -0
  32. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VSectionListFactory.kt +144 -0
  33. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VSegmentedControlFactory.kt +77 -0
  34. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VSliderFactory.kt +74 -0
  35. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VStatusBarFactory.kt +52 -0
  36. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VSwitchFactory.kt +62 -0
  37. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VTextFactory.kt +53 -0
  38. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VVideoFactory.kt +191 -0
  39. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VViewFactory.kt +48 -0
  40. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VWebViewFactory.kt +90 -0
  41. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/NativeComponentFactory.kt +40 -0
  42. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/VTextNodeView.kt +23 -0
  43. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Helpers/GestureHelper.kt +16 -0
  44. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Helpers/TouchableView.kt +105 -0
  45. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/AnimationModule.kt +292 -0
  46. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/AppStateModule.kt +41 -0
  47. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/AsyncStorageModule.kt +59 -0
  48. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/AudioModule.kt +331 -0
  49. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/BackgroundTaskModule.kt +166 -0
  50. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/BiometryModule.kt +56 -0
  51. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/BluetoothModule.kt +302 -0
  52. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/CalendarModule.kt +198 -0
  53. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/CameraModule.kt +64 -0
  54. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/ClipboardModule.kt +36 -0
  55. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/ContactsModule.kt +288 -0
  56. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/DatabaseModule.kt +229 -0
  57. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/DeviceInfoModule.kt +39 -0
  58. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/FileSystemModule.kt +193 -0
  59. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/GeolocationModule.kt +68 -0
  60. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/HapticsModule.kt +61 -0
  61. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/HttpModule.kt +111 -0
  62. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/IAPModule.kt +302 -0
  63. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/KeyboardModule.kt +26 -0
  64. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/LinkingModule.kt +43 -0
  65. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/NativeModule.kt +27 -0
  66. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/NativeModuleRegistry.kt +92 -0
  67. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/NetworkModule.kt +75 -0
  68. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/NotificationsModule.kt +181 -0
  69. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/OTAModule.kt +255 -0
  70. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/PerformanceModule.kt +147 -0
  71. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/PermissionsModule.kt +126 -0
  72. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/SecureStorageModule.kt +51 -0
  73. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/SensorsModule.kt +134 -0
  74. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/ShareModule.kt +36 -0
  75. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/SocialAuthModule.kt +163 -0
  76. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/WebSocketModule.kt +155 -0
  77. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Styling/StyleEngine.kt +802 -0
  78. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Tags.kt +43 -0
  79. package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/VueNativeActivity.kt +169 -0
  80. package/native/android/VueNativeCore/src/main/res/values/ids.xml +8 -0
  81. package/native/android/app/build.gradle.kts +45 -0
  82. package/native/android/app/proguard-rules.pro +5 -0
  83. package/native/android/app/src/main/AndroidManifest.xml +25 -0
  84. package/native/android/app/src/main/assets/.gitkeep +0 -0
  85. package/native/android/app/src/main/kotlin/com/vuenative/example/counter/MainActivity.kt +14 -0
  86. package/native/android/app/src/main/res/layout/activity_main.xml +6 -0
  87. package/native/android/app/src/main/res/values/strings.xml +3 -0
  88. package/native/android/app/src/main/res/values/themes.xml +9 -0
  89. package/native/android/app/src/main/res/xml/network_security_config.xml +8 -0
  90. package/native/android/build.gradle.kts +6 -0
  91. package/native/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  92. package/native/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  93. package/native/android/gradle.properties +4 -0
  94. package/native/android/gradlew +87 -0
  95. package/native/android/gradlew.bat +48 -0
  96. package/native/android/settings.gradle.kts +20 -0
  97. package/native/ios/VueNativeCore/Package.resolved +23 -0
  98. package/native/ios/VueNativeCore/Package.swift +32 -0
  99. package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/CertificatePinning.swift +136 -0
  100. package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/ErrorOverlayView.swift +89 -0
  101. package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/HotReloadManager.swift +147 -0
  102. package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/JSPolyfills.swift +711 -0
  103. package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/JSRuntime.swift +421 -0
  104. package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/NativeBridge.swift +906 -0
  105. package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/VueNativeViewController.swift +88 -0
  106. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/ComponentRegistry.swift +193 -0
  107. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VActionSheetFactory.swift +90 -0
  108. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VActivityIndicatorFactory.swift +74 -0
  109. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VAlertDialogFactory.swift +149 -0
  110. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VButtonFactory.swift +93 -0
  111. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VCheckboxFactory.swift +114 -0
  112. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VDropdownFactory.swift +112 -0
  113. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VImageFactory.swift +172 -0
  114. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VInputFactory.swift +357 -0
  115. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VKeyboardAvoidingFactory.swift +99 -0
  116. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VListFactory.swift +250 -0
  117. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VModalFactory.swift +109 -0
  118. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VPickerFactory.swift +96 -0
  119. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VPressableFactory.swift +168 -0
  120. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VProgressBarFactory.swift +39 -0
  121. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VRadioFactory.swift +167 -0
  122. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VRefreshControlFactory.swift +153 -0
  123. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VSafeAreaFactory.swift +56 -0
  124. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VScrollViewFactory.swift +240 -0
  125. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VSectionListFactory.swift +248 -0
  126. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VSegmentedControlFactory.swift +73 -0
  127. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VSliderFactory.swift +63 -0
  128. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VStatusBarFactory.swift +50 -0
  129. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VSwitchFactory.swift +108 -0
  130. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VTextFactory.swift +290 -0
  131. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VVideoFactory.swift +250 -0
  132. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VViewFactory.swift +157 -0
  133. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VWebViewFactory.swift +174 -0
  134. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/NativeComponentFactory.swift +53 -0
  135. package/native/ios/VueNativeCore/Sources/VueNativeCore/Helpers/Extensions.swift +31 -0
  136. package/native/ios/VueNativeCore/Sources/VueNativeCore/Helpers/GestureWrapper.swift +107 -0
  137. package/native/ios/VueNativeCore/Sources/VueNativeCore/Helpers/TouchableView.swift +136 -0
  138. package/native/ios/VueNativeCore/Sources/VueNativeCore/Helpers/UIColor+Hex.swift +80 -0
  139. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/AnimationModule.swift +283 -0
  140. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/AppStateModule.swift +59 -0
  141. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/AsyncStorageModule.swift +68 -0
  142. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/AudioModule.swift +371 -0
  143. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/BackgroundTaskModule.swift +135 -0
  144. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/BiometryModule.swift +61 -0
  145. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/BluetoothModule.swift +379 -0
  146. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/CalendarModule.swift +154 -0
  147. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/CameraModule.swift +315 -0
  148. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/ClipboardModule.swift +33 -0
  149. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/ContactsModule.swift +173 -0
  150. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/DatabaseModule.swift +259 -0
  151. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/DeviceInfoModule.swift +34 -0
  152. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/FileSystemModule.swift +233 -0
  153. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/GeolocationModule.swift +147 -0
  154. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/HapticsModule.swift +50 -0
  155. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/IAPModule.swift +194 -0
  156. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/KeyboardModule.swift +31 -0
  157. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/LinkingModule.swift +42 -0
  158. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NativeModule.swift +28 -0
  159. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NativeModuleRegistry.swift +78 -0
  160. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NetworkModule.swift +62 -0
  161. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NotificationsModule.swift +215 -0
  162. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/OTAModule.swift +281 -0
  163. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/PerformanceModule.swift +141 -0
  164. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/PermissionsModule.swift +190 -0
  165. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/SecureStorageModule.swift +118 -0
  166. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/SensorsModule.swift +103 -0
  167. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/ShareModule.swift +48 -0
  168. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/SocialAuthModule.swift +256 -0
  169. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/WebSocketModule.swift +213 -0
  170. package/native/ios/VueNativeCore/Sources/VueNativeCore/Resources/vue-native-placeholder.js +8 -0
  171. package/native/ios/VueNativeCore/Sources/VueNativeCore/Styling/StyleEngine.swift +885 -0
  172. package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/JSRuntimeTests.swift +362 -0
  173. package/package.json +3 -2
@@ -0,0 +1,107 @@
1
+ #if canImport(UIKit)
2
+ import UIKit
3
+
4
+ /// ObjC-compatible wrapper for gesture recognizer action handlers.
5
+ /// Allows attaching Swift closure-based event handlers to UIGestureRecognizers
6
+ /// that require an @objc selector target.
7
+ @objc final class GestureWrapper: NSObject {
8
+
9
+ private let handler: (Any?) -> Void
10
+
11
+ init(handler: @escaping (Any?) -> Void) {
12
+ self.handler = handler
13
+ super.init()
14
+ }
15
+
16
+ @objc func handleGesture(_ gesture: UIGestureRecognizer) {
17
+ handler(nil)
18
+ }
19
+
20
+ @objc func handleGestureWithState(_ gesture: UIGestureRecognizer) {
21
+ let payload: [String: Any] = [
22
+ "state": gesture.state.rawValue,
23
+ "locationX": gesture.location(in: gesture.view).x,
24
+ "locationY": gesture.location(in: gesture.view).y
25
+ ]
26
+ handler(payload)
27
+ }
28
+ }
29
+
30
+ // MARK: - PanWrapper
31
+
32
+ /// ObjC-compatible wrapper for UIPanGestureRecognizer action handlers.
33
+ @objc final class PanWrapper: NSObject {
34
+ private let handler: (Any?) -> Void
35
+
36
+ init(handler: @escaping (Any?) -> Void) {
37
+ self.handler = handler
38
+ super.init()
39
+ }
40
+
41
+ @objc func handle(_ recognizer: UIPanGestureRecognizer) {
42
+ guard let view = recognizer.view else { return }
43
+ let translation = recognizer.translation(in: view.superview)
44
+ let velocity = recognizer.velocity(in: view.superview)
45
+ let stateStr: String
46
+ switch recognizer.state {
47
+ case .began: stateStr = "began"
48
+ case .changed: stateStr = "changed"
49
+ case .ended: stateStr = "ended"
50
+ case .cancelled, .failed: stateStr = "cancelled"
51
+ default: stateStr = "unknown"
52
+ }
53
+ handler([
54
+ "translationX": translation.x,
55
+ "translationY": translation.y,
56
+ "velocityX": velocity.x,
57
+ "velocityY": velocity.y,
58
+ "state": stateStr
59
+ ] as [String: Any])
60
+ }
61
+ }
62
+
63
+ // MARK: - SwipeWrapper
64
+
65
+ /// ObjC-compatible wrapper for UISwipeGestureRecognizer action handlers.
66
+ @objc final class SwipeWrapper: NSObject {
67
+ private let handler: (Any?) -> Void
68
+ private let direction: String
69
+
70
+ init(handler: @escaping (Any?) -> Void, direction: String) {
71
+ self.handler = handler
72
+ self.direction = direction
73
+ super.init()
74
+ }
75
+
76
+ @objc func handle(_ recognizer: UISwipeGestureRecognizer) {
77
+ handler(["direction": direction] as [String: Any])
78
+ }
79
+ }
80
+
81
+ // MARK: - PinchWrapper
82
+
83
+ /// ObjC-compatible wrapper for UIPinchGestureRecognizer action handlers.
84
+ @objc final class PinchWrapper: NSObject {
85
+ private let handler: (Any?) -> Void
86
+
87
+ init(handler: @escaping (Any?) -> Void) {
88
+ self.handler = handler
89
+ super.init()
90
+ }
91
+
92
+ @objc func handle(_ recognizer: UIPinchGestureRecognizer) {
93
+ let stateStr: String
94
+ switch recognizer.state {
95
+ case .began: stateStr = "began"
96
+ case .changed: stateStr = "changed"
97
+ case .ended: stateStr = "ended"
98
+ default: stateStr = "cancelled"
99
+ }
100
+ handler([
101
+ "scale": recognizer.scale,
102
+ "velocity": recognizer.velocity,
103
+ "state": stateStr
104
+ ] as [String: Any])
105
+ }
106
+ }
107
+ #endif
@@ -0,0 +1,136 @@
1
+ #if canImport(UIKit)
2
+ import UIKit
3
+
4
+ /// Custom UIView subclass that provides button-like touch behavior
5
+ /// with configurable active opacity and support for press and long press events.
6
+ class TouchableView: UIView {
7
+
8
+ // MARK: - Public properties
9
+
10
+ /// The opacity to apply when the user is pressing the view.
11
+ var activeOpacity: CGFloat = 0.7
12
+
13
+ /// Called when a tap completes within the view bounds.
14
+ var onPress: (() -> Void)?
15
+
16
+ /// Called when a long press gesture is recognized.
17
+ var onLongPress: (() -> Void)?
18
+
19
+ /// Whether touch interactions are disabled.
20
+ var isDisabled: Bool = false {
21
+ didSet {
22
+ isUserInteractionEnabled = !isDisabled
23
+ alpha = isDisabled ? 0.4 : 1.0
24
+ }
25
+ }
26
+
27
+ // MARK: - Private properties
28
+
29
+ private var longPressRecognizer: UILongPressGestureRecognizer?
30
+ private var isTouchInside: Bool = false
31
+
32
+ // MARK: - Initialization
33
+
34
+ override init(frame: CGRect) {
35
+ super.init(frame: frame)
36
+ setupLongPressRecognizer()
37
+ }
38
+
39
+ required init?(coder: NSCoder) {
40
+ super.init(coder: coder)
41
+ setupLongPressRecognizer()
42
+ }
43
+
44
+ // MARK: - Touch handling
45
+
46
+ override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
47
+ super.touchesBegan(touches, with: event)
48
+ guard !isDisabled else { return }
49
+
50
+ isTouchInside = true
51
+ UIView.animate(
52
+ withDuration: 0.1,
53
+ delay: 0,
54
+ options: [.beginFromCurrentState, .allowUserInteraction],
55
+ animations: { [weak self] in
56
+ guard let self = self else { return }
57
+ self.alpha = self.activeOpacity
58
+ }
59
+ )
60
+ }
61
+
62
+ override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
63
+ super.touchesMoved(touches, with: event)
64
+ guard !isDisabled, let touch = touches.first else { return }
65
+
66
+ let location = touch.location(in: self)
67
+ let wasInside = isTouchInside
68
+ isTouchInside = bounds.contains(location)
69
+
70
+ if wasInside != isTouchInside {
71
+ UIView.animate(
72
+ withDuration: 0.1,
73
+ delay: 0,
74
+ options: [.beginFromCurrentState, .allowUserInteraction],
75
+ animations: { [weak self] in
76
+ guard let self = self else { return }
77
+ self.alpha = self.isTouchInside ? self.activeOpacity : 1.0
78
+ }
79
+ )
80
+ }
81
+ }
82
+
83
+ override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
84
+ super.touchesEnded(touches, with: event)
85
+ guard !isDisabled else { return }
86
+
87
+ UIView.animate(
88
+ withDuration: 0.15,
89
+ delay: 0,
90
+ options: [.beginFromCurrentState, .allowUserInteraction],
91
+ animations: { [weak self] in
92
+ self?.alpha = 1.0
93
+ }
94
+ )
95
+
96
+ if isTouchInside {
97
+ onPress?()
98
+ }
99
+ isTouchInside = false
100
+ }
101
+
102
+ override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
103
+ super.touchesCancelled(touches, with: event)
104
+ guard !isDisabled else { return }
105
+
106
+ UIView.animate(
107
+ withDuration: 0.15,
108
+ delay: 0,
109
+ options: [.beginFromCurrentState, .allowUserInteraction],
110
+ animations: { [weak self] in
111
+ self?.alpha = 1.0
112
+ }
113
+ )
114
+ isTouchInside = false
115
+ }
116
+
117
+ // MARK: - Long press
118
+
119
+ private func setupLongPressRecognizer() {
120
+ let recognizer = UILongPressGestureRecognizer(
121
+ target: self,
122
+ action: #selector(handleLongPress(_:))
123
+ )
124
+ recognizer.minimumPressDuration = 0.5
125
+ addGestureRecognizer(recognizer)
126
+ longPressRecognizer = recognizer
127
+ }
128
+
129
+ @objc private func handleLongPress(_ recognizer: UILongPressGestureRecognizer) {
130
+ guard !isDisabled else { return }
131
+ if recognizer.state == .began {
132
+ onLongPress?()
133
+ }
134
+ }
135
+ }
136
+ #endif
@@ -0,0 +1,80 @@
1
+ #if canImport(UIKit)
2
+ import UIKit
3
+
4
+ extension UIColor {
5
+
6
+ // MARK: - Named color lookup
7
+
8
+ private static let namedColors: [String: UIColor] = [
9
+ "transparent": .clear,
10
+ "black": .black,
11
+ "white": .white,
12
+ "red": .red,
13
+ "green": .green,
14
+ "blue": .blue,
15
+ "gray": .gray,
16
+ "grey": .gray,
17
+ "orange": .orange,
18
+ "yellow": .yellow,
19
+ "purple": .purple,
20
+ "cyan": .cyan,
21
+ "magenta": .magenta,
22
+ "brown": .brown
23
+ ]
24
+
25
+ // MARK: - Hex initializer
26
+
27
+ /// Creates a UIColor from a hex string.
28
+ /// Supports formats: "#RGB", "#RRGGBB", "#RRGGBBAA"
29
+ /// Also supports named colors: "transparent", "black", "white", "red", "green", "blue", "gray"
30
+ /// Returns .clear for invalid input.
31
+ static func fromHex(_ hex: String) -> UIColor {
32
+ let trimmed = hex.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
33
+
34
+ // Check named colors first
35
+ if let named = namedColors[trimmed] {
36
+ return named
37
+ }
38
+
39
+ // Must start with '#'
40
+ guard trimmed.hasPrefix("#") else {
41
+ return .clear
42
+ }
43
+
44
+ let hexString = String(trimmed.dropFirst())
45
+ let scanner = Scanner(string: hexString)
46
+ var hexNumber: UInt64 = 0
47
+
48
+ guard scanner.scanHexInt64(&hexNumber) else {
49
+ return .clear
50
+ }
51
+
52
+ switch hexString.count {
53
+ case 3:
54
+ // #RGB -> #RRGGBB
55
+ let r = CGFloat((hexNumber & 0xF00) >> 8) / 15.0
56
+ let g = CGFloat((hexNumber & 0x0F0) >> 4) / 15.0
57
+ let b = CGFloat(hexNumber & 0x00F) / 15.0
58
+ return UIColor(red: r, green: g, blue: b, alpha: 1.0)
59
+
60
+ case 6:
61
+ // #RRGGBB
62
+ let r = CGFloat((hexNumber & 0xFF0000) >> 16) / 255.0
63
+ let g = CGFloat((hexNumber & 0x00FF00) >> 8) / 255.0
64
+ let b = CGFloat(hexNumber & 0x0000FF) / 255.0
65
+ return UIColor(red: r, green: g, blue: b, alpha: 1.0)
66
+
67
+ case 8:
68
+ // #RRGGBBAA
69
+ let r = CGFloat((hexNumber & 0xFF000000) >> 24) / 255.0
70
+ let g = CGFloat((hexNumber & 0x00FF0000) >> 16) / 255.0
71
+ let b = CGFloat((hexNumber & 0x0000FF00) >> 8) / 255.0
72
+ let a = CGFloat(hexNumber & 0x000000FF) / 255.0
73
+ return UIColor(red: r, green: g, blue: b, alpha: a)
74
+
75
+ default:
76
+ return .clear
77
+ }
78
+ }
79
+ }
80
+ #endif
@@ -0,0 +1,283 @@
1
+ #if canImport(UIKit)
2
+ import UIKit
3
+
4
+ /// Native module for UIView animations.
5
+ /// Exposes timing, spring, keyframe, sequence, and parallel animations to JS composables.
6
+ final class AnimationModule: NativeModule {
7
+
8
+ let moduleName = "Animation"
9
+
10
+ func invoke(method: String, args: [Any], callback: @escaping (Any?, String?) -> Void) {
11
+ switch method {
12
+ case "timing":
13
+ handleTiming(args: args, callback: callback)
14
+ case "spring":
15
+ handleSpring(args: args, callback: callback)
16
+ case "keyframe":
17
+ guard let viewId = args[safe: 0] as? Int,
18
+ let keyframesData = args[safe: 1] as? [[String: Any]],
19
+ let options = args[safe: 2] as? [String: Any] else {
20
+ callback(nil, "Invalid args"); return
21
+ }
22
+ let duration = options["duration"] as? Double ?? 300
23
+ animateKeyframes(viewId: viewId, keyframes: keyframesData, duration: duration / 1000.0, callback: callback)
24
+ case "sequence":
25
+ guard let animationsData = args[safe: 0] as? [[String: Any]] else {
26
+ callback(nil, "Invalid args"); return
27
+ }
28
+ runSequence(animationsData: animationsData, index: 0, callback: callback)
29
+ case "parallel":
30
+ guard let animationsData = args[safe: 0] as? [[String: Any]] else {
31
+ callback(nil, "Invalid args"); return
32
+ }
33
+ runParallel(animationsData: animationsData, callback: callback)
34
+ default:
35
+ callback(nil, "AnimationModule: unknown method '\(method)'")
36
+ }
37
+ }
38
+
39
+ func invokeSync(method: String, args: [Any]) -> Any? {
40
+ return nil
41
+ }
42
+
43
+ // MARK: - timing(viewId, styles, options)
44
+ // args[0]: Int (viewId)
45
+ // args[1]: [String: Any] (target styles, only numeric values like opacity, transform offsets)
46
+ // args[2]: [String: Any] (options: duration, delay, easing)
47
+
48
+ private func handleTiming(args: [Any], callback: @escaping (Any?, String?) -> Void) {
49
+ guard let viewId = args.first.flatMap({ $0 as? Int ?? ($0 as? Double).map(Int.init) }),
50
+ let styles = args.count > 1 ? args[1] as? [String: Any] : [:] else {
51
+ callback(nil, "timing: invalid arguments")
52
+ return
53
+ }
54
+
55
+ let options = args.count > 2 ? (args[2] as? [String: Any] ?? [:]) : [:]
56
+ let duration = (options["duration"] as? Double ?? 300) / 1000.0
57
+ let delay = (options["delay"] as? Double ?? 0) / 1000.0
58
+ let easing = options["easing"] as? String ?? "ease"
59
+
60
+ let curve: UIView.AnimationOptions
61
+ switch easing {
62
+ case "linear": curve = .curveLinear
63
+ case "ease-in", "easeIn": curve = .curveEaseIn
64
+ case "ease-out", "easeOut": curve = .curveEaseOut
65
+ default: curve = .curveEaseInOut
66
+ }
67
+
68
+ DispatchQueue.main.async {
69
+ MainActor.assumeIsolated {
70
+ guard let view = NativeBridge.shared.view(forId: viewId) else {
71
+ callback(nil, "timing: view \(viewId) not found")
72
+ return
73
+ }
74
+
75
+ UIView.animate(
76
+ withDuration: duration,
77
+ delay: delay,
78
+ options: [curve],
79
+ animations: { [styles] in
80
+ MainActor.assumeIsolated {
81
+ for (key, value) in styles {
82
+ StyleEngine.apply(key: key, value: value, to: view)
83
+ }
84
+ }
85
+ },
86
+ completion: { _ in
87
+ callback(true, nil)
88
+ }
89
+ )
90
+ }
91
+ }
92
+ }
93
+
94
+ // MARK: - spring(viewId, styles, options)
95
+ // args[0]: Int (viewId)
96
+ // args[1]: [String: Any] (target styles)
97
+ // args[2]: [String: Any] (options: damping, stiffness/duration, mass)
98
+
99
+ private func handleSpring(args: [Any], callback: @escaping (Any?, String?) -> Void) {
100
+ guard let viewId = args.first.flatMap({ $0 as? Int ?? ($0 as? Double).map(Int.init) }),
101
+ let styles = args.count > 1 ? args[1] as? [String: Any] : [:] else {
102
+ callback(nil, "spring: invalid arguments")
103
+ return
104
+ }
105
+
106
+ let options = args.count > 2 ? (args[2] as? [String: Any] ?? [:]) : [:]
107
+ let damping = CGFloat(options["damping"] as? Double ?? 0.7)
108
+ let duration = (options["duration"] as? Double ?? 500) / 1000.0
109
+ let delay = (options["delay"] as? Double ?? 0) / 1000.0
110
+
111
+ DispatchQueue.main.async {
112
+ MainActor.assumeIsolated {
113
+ guard let view = NativeBridge.shared.view(forId: viewId) else {
114
+ callback(nil, "spring: view \(viewId) not found")
115
+ return
116
+ }
117
+
118
+ UIView.animate(
119
+ withDuration: duration,
120
+ delay: delay,
121
+ usingSpringWithDamping: damping,
122
+ initialSpringVelocity: 0,
123
+ options: [],
124
+ animations: { [styles] in
125
+ MainActor.assumeIsolated {
126
+ for (key, value) in styles {
127
+ StyleEngine.apply(key: key, value: value, to: view)
128
+ }
129
+ }
130
+ },
131
+ completion: { _ in
132
+ callback(true, nil)
133
+ }
134
+ )
135
+ }
136
+ }
137
+ }
138
+
139
+ // MARK: - keyframe(viewId, keyframes, options)
140
+
141
+ private func animateKeyframes(viewId: Int, keyframes: [[String: Any]], duration: TimeInterval, callback: @escaping (Any?, String?) -> Void) {
142
+ DispatchQueue.main.async {
143
+ guard let view = NativeBridge.shared.view(forId: viewId) else {
144
+ callback(nil, "View not found for id \(viewId)"); return
145
+ }
146
+
147
+ // Build CAKeyframeAnimation for each animated property
148
+ // Group them with CAAnimationGroup
149
+ let group = CAAnimationGroup()
150
+ group.duration = duration
151
+ group.fillMode = .forwards
152
+ group.isRemovedOnCompletion = false
153
+
154
+ var animations: [CAAnimation] = []
155
+
156
+ // Collect all property names from keyframes
157
+ var propertyKeys = Set<String>()
158
+ for kf in keyframes { propertyKeys.formUnion(kf.keys.filter { $0 != "offset" }) }
159
+
160
+ for propKey in propertyKeys {
161
+ let keyPath: String
162
+ var values: [Any] = []
163
+ var keyTimes: [NSNumber] = []
164
+
165
+ switch propKey {
166
+ case "opacity":
167
+ keyPath = "opacity"
168
+ for kf in keyframes {
169
+ if let v = kf[propKey] as? Double {
170
+ values.append(v)
171
+ keyTimes.append(NSNumber(value: kf["offset"] as? Double ?? 0))
172
+ }
173
+ }
174
+ case "translateX":
175
+ keyPath = "transform.translation.x"
176
+ for kf in keyframes {
177
+ if let v = kf[propKey] as? Double {
178
+ values.append(v)
179
+ keyTimes.append(NSNumber(value: kf["offset"] as? Double ?? 0))
180
+ }
181
+ }
182
+ case "translateY":
183
+ keyPath = "transform.translation.y"
184
+ for kf in keyframes {
185
+ if let v = kf[propKey] as? Double {
186
+ values.append(v)
187
+ keyTimes.append(NSNumber(value: kf["offset"] as? Double ?? 0))
188
+ }
189
+ }
190
+ case "scale", "scaleX":
191
+ keyPath = "transform.scale.x"
192
+ for kf in keyframes {
193
+ if let v = kf[propKey] as? Double {
194
+ values.append(v)
195
+ keyTimes.append(NSNumber(value: kf["offset"] as? Double ?? 0))
196
+ }
197
+ }
198
+ case "scaleY":
199
+ keyPath = "transform.scale.y"
200
+ for kf in keyframes {
201
+ if let v = kf[propKey] as? Double {
202
+ values.append(v)
203
+ keyTimes.append(NSNumber(value: kf["offset"] as? Double ?? 0))
204
+ }
205
+ }
206
+ default:
207
+ continue
208
+ }
209
+
210
+ if !values.isEmpty {
211
+ let anim = CAKeyframeAnimation(keyPath: keyPath)
212
+ anim.values = values
213
+ anim.keyTimes = keyTimes
214
+ anim.duration = duration
215
+ animations.append(anim)
216
+ }
217
+ }
218
+
219
+ if animations.isEmpty { callback(nil, nil); return }
220
+ group.animations = animations
221
+
222
+ CATransaction.begin()
223
+ CATransaction.setCompletionBlock { callback(nil, nil) }
224
+ view.layer.add(group, forKey: "keyframeAnimation")
225
+ CATransaction.commit()
226
+ }
227
+ }
228
+
229
+ // MARK: - sequence([animData])
230
+
231
+ private func runSequence(animationsData: [[String: Any]], index: Int, callback: @escaping (Any?, String?) -> Void) {
232
+ guard index < animationsData.count else { callback(nil, nil); return }
233
+ let animData = animationsData[index]
234
+ let method = animData["type"] as? String ?? "timing"
235
+ let viewId = animData["viewId"] as? Int ?? 0
236
+ let toStyles = animData["toStyles"] as? [String: Any] ?? [:]
237
+ let options = animData["options"] as? [String: Any] ?? [:]
238
+
239
+ runSingleAnimation(method: method, viewId: viewId, toStyles: toStyles, options: options) { [weak self] _, error in
240
+ if let error = error { callback(nil, error); return }
241
+ self?.runSequence(animationsData: animationsData, index: index + 1, callback: callback)
242
+ }
243
+ }
244
+
245
+ private func runSingleAnimation(method: String, viewId: Int, toStyles: [String: Any], options: [String: Any], callback: @escaping (Any?, String?) -> Void) {
246
+ switch method {
247
+ case "timing":
248
+ let argsArr: [Any] = [viewId, toStyles, options]
249
+ invoke(method: "timing", args: argsArr, callback: callback)
250
+ case "spring":
251
+ let argsArr: [Any] = [viewId, toStyles, options]
252
+ invoke(method: "spring", args: argsArr, callback: callback)
253
+ default:
254
+ callback(nil, "Unknown animation type: \(method)")
255
+ }
256
+ }
257
+
258
+ // MARK: - parallel([animData])
259
+
260
+ private func runParallel(animationsData: [[String: Any]], callback: @escaping (Any?, String?) -> Void) {
261
+ guard !animationsData.isEmpty else { callback(nil, nil); return }
262
+ let total = animationsData.count
263
+ var completed = 0
264
+ let lock = NSLock()
265
+
266
+ for animData in animationsData {
267
+ let method = animData["type"] as? String ?? "timing"
268
+ let viewId = animData["viewId"] as? Int ?? 0
269
+ let toStyles = animData["toStyles"] as? [String: Any] ?? [:]
270
+ let options = animData["options"] as? [String: Any] ?? [:]
271
+
272
+ runSingleAnimation(method: method, viewId: viewId, toStyles: toStyles, options: options) { _, _ in
273
+ lock.lock()
274
+ completed += 1
275
+ let allDone = completed == total
276
+ lock.unlock()
277
+ if allDone { callback(nil, nil) }
278
+ }
279
+ }
280
+ }
281
+ }
282
+
283
+ #endif
@@ -0,0 +1,59 @@
1
+ #if canImport(UIKit)
2
+ import UIKit
3
+
4
+ final class AppStateModule: NSObject, NativeModule {
5
+ var moduleName: String { "AppState" }
6
+ private weak var bridge: NativeBridge?
7
+ private var observers: [NSObjectProtocol] = []
8
+
9
+ init(bridge: NativeBridge) {
10
+ self.bridge = bridge
11
+ super.init()
12
+ setupObservers()
13
+ }
14
+
15
+ private func setupObservers() {
16
+ observers.append(NotificationCenter.default.addObserver(
17
+ forName: UIApplication.didBecomeActiveNotification, object: nil, queue: .main
18
+ ) { [weak self] _ in
19
+ self?.bridge?.dispatchGlobalEvent("appState:change", payload: ["state": "active"])
20
+ })
21
+ observers.append(NotificationCenter.default.addObserver(
22
+ forName: UIApplication.willResignActiveNotification, object: nil, queue: .main
23
+ ) { [weak self] _ in
24
+ self?.bridge?.dispatchGlobalEvent("appState:change", payload: ["state": "inactive"])
25
+ })
26
+ observers.append(NotificationCenter.default.addObserver(
27
+ forName: UIApplication.didEnterBackgroundNotification, object: nil, queue: .main
28
+ ) { [weak self] _ in
29
+ self?.bridge?.dispatchGlobalEvent("appState:change", payload: ["state": "background"])
30
+ })
31
+ }
32
+
33
+ deinit {
34
+ observers.forEach { NotificationCenter.default.removeObserver($0) }
35
+ }
36
+
37
+ func invoke(method: String, args: [Any], callback: @escaping (Any?, String?) -> Void) {
38
+ switch method {
39
+ case "getState":
40
+ let bridge = bridge
41
+ DispatchQueue.main.async {
42
+ let state: String
43
+ switch UIApplication.shared.applicationState {
44
+ case .active: state = "active"
45
+ case .inactive: state = "inactive"
46
+ case .background: state = "background"
47
+ @unknown default: state = "unknown"
48
+ }
49
+ bridge?.dispatchGlobalEvent("appState:change", payload: ["state": state])
50
+ callback(state, nil)
51
+ }
52
+ default:
53
+ callback(nil, "Unknown method: \(method)")
54
+ }
55
+ }
56
+
57
+ func invokeSync(method: String, args: [Any]) -> Any? { nil }
58
+ }
59
+ #endif