@thelacanians/vue-native-cli 0.4.3 → 0.4.4

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 (172) hide show
  1. package/dist/cli.js +34 -17
  2. package/native/android/README.md +205 -0
  3. package/native/android/VueNativeCore/build.gradle.kts +100 -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 +160 -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 +132 -0
  100. package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/ErrorOverlayView.swift +92 -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 +891 -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 +91 -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 +150 -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 +112 -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 +246 -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 +172 -0
  134. package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/NativeComponentFactory.swift +53 -0
  135. package/native/ios/VueNativeCore/Sources/VueNativeCore/Helpers/GestureWrapper.swift +107 -0
  136. package/native/ios/VueNativeCore/Sources/VueNativeCore/Helpers/TouchableView.swift +136 -0
  137. package/native/ios/VueNativeCore/Sources/VueNativeCore/Helpers/UIColor+Hex.swift +80 -0
  138. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/AnimationModule.swift +291 -0
  139. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/AppStateModule.swift +65 -0
  140. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/AsyncStorageModule.swift +68 -0
  141. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/AudioModule.swift +366 -0
  142. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/BackgroundTaskModule.swift +135 -0
  143. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/BiometryModule.swift +61 -0
  144. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/BluetoothModule.swift +387 -0
  145. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/CalendarModule.swift +161 -0
  146. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/CameraModule.swift +318 -0
  147. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/ClipboardModule.swift +33 -0
  148. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/ContactsModule.swift +173 -0
  149. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/DatabaseModule.swift +259 -0
  150. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/DeviceInfoModule.swift +34 -0
  151. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/FileSystemModule.swift +233 -0
  152. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/GeolocationModule.swift +147 -0
  153. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/HapticsModule.swift +50 -0
  154. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/IAPModule.swift +194 -0
  155. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/KeyboardModule.swift +31 -0
  156. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/LinkingModule.swift +42 -0
  157. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NativeModule.swift +28 -0
  158. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NativeModuleRegistry.swift +78 -0
  159. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NetworkModule.swift +62 -0
  160. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NotificationsModule.swift +215 -0
  161. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/OTAModule.swift +281 -0
  162. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/PerformanceModule.swift +138 -0
  163. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/PermissionsModule.swift +190 -0
  164. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/SecureStorageModule.swift +118 -0
  165. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/SensorsModule.swift +103 -0
  166. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/ShareModule.swift +49 -0
  167. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/SocialAuthModule.swift +240 -0
  168. package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/WebSocketModule.swift +213 -0
  169. package/native/ios/VueNativeCore/Sources/VueNativeCore/Resources/vue-native-placeholder.js +8 -0
  170. package/native/ios/VueNativeCore/Sources/VueNativeCore/Styling/StyleEngine.swift +885 -0
  171. package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/JSRuntimeTests.swift +362 -0
  172. package/package.json +3 -2
@@ -0,0 +1,210 @@
1
+ package com.vuenative.core
2
+
3
+ import android.content.Context
4
+ import android.graphics.Color
5
+ import android.text.Editable
6
+ import android.text.InputFilter
7
+ import android.text.InputType
8
+ import android.text.TextWatcher
9
+ import android.view.View
10
+ import android.view.ViewGroup
11
+ import android.view.inputmethod.EditorInfo
12
+ import android.widget.EditText
13
+
14
+ class VInputFactory : NativeComponentFactory {
15
+ private val changeHandlers = mutableMapOf<EditText, (Any?) -> Unit>()
16
+ private val submitHandlers = mutableMapOf<EditText, (Any?) -> Unit>()
17
+ private val focusHandlers = mutableMapOf<EditText, (Any?) -> Unit>()
18
+ private val blurHandlers = mutableMapOf<EditText, (Any?) -> Unit>()
19
+ private val textWatchers = mutableMapOf<EditText, TextWatcher>()
20
+
21
+ override fun createView(context: Context): View {
22
+ return EditText(context).apply {
23
+ setBackgroundColor(Color.TRANSPARENT)
24
+ setPadding(0, 0, 0, 0)
25
+ textSize = 16f
26
+ setTextColor(Color.BLACK)
27
+ layoutParams = ViewGroup.LayoutParams(
28
+ ViewGroup.LayoutParams.WRAP_CONTENT,
29
+ ViewGroup.LayoutParams.WRAP_CONTENT
30
+ )
31
+ }
32
+ }
33
+
34
+ override fun updateProp(view: View, key: String, value: Any?) {
35
+ val et = view as? EditText ?: return
36
+ when (key) {
37
+ "text", "value" -> {
38
+ val newText = value?.toString() ?: ""
39
+ if (et.text.toString() != newText) {
40
+ et.setText(newText)
41
+ et.setSelection(newText.length)
42
+ }
43
+ }
44
+ "placeholder" -> et.hint = value?.toString()
45
+ "placeholderColor", "placeholderTextColor" -> {
46
+ val color = StyleEngine.parseColor(value)
47
+ if (color != null) et.setHintTextColor(color)
48
+ }
49
+ "editable" -> et.isEnabled = value != false && value != "false"
50
+ "keyboardType" -> {
51
+ et.inputType = when (value) {
52
+ "numeric", "number-pad", "decimal-pad" ->
53
+ InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
54
+ "email-address", "email" ->
55
+ InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
56
+ "phone-pad", "phone" -> InputType.TYPE_CLASS_PHONE
57
+ "url" -> InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_URI
58
+ else -> InputType.TYPE_CLASS_TEXT
59
+ }
60
+ }
61
+ "secureTextEntry" -> {
62
+ if (value == true || value == "true") {
63
+ et.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
64
+ }
65
+ }
66
+ "multiline" -> {
67
+ if (value == true || value == "true") {
68
+ et.inputType = et.inputType or InputType.TYPE_TEXT_FLAG_MULTI_LINE
69
+ et.isSingleLine = false
70
+ }
71
+ }
72
+ "returnKeyType" -> {
73
+ et.imeOptions = when (value) {
74
+ "done" -> EditorInfo.IME_ACTION_DONE
75
+ "go" -> EditorInfo.IME_ACTION_GO
76
+ "next" -> EditorInfo.IME_ACTION_NEXT
77
+ "search" -> EditorInfo.IME_ACTION_SEARCH
78
+ "send" -> EditorInfo.IME_ACTION_SEND
79
+ else -> EditorInfo.IME_ACTION_DONE
80
+ }
81
+ }
82
+ "maxLength" -> {
83
+ val n = StyleEngine.toInt(value, 0)
84
+ if (n > 0) {
85
+ et.filters = arrayOf(InputFilter.LengthFilter(n))
86
+ } else {
87
+ // Remove length filter
88
+ et.filters = et.filters.filter { it !is InputFilter.LengthFilter }.toTypedArray()
89
+ }
90
+ }
91
+ "autoCapitalize", "autocapitalize" -> {
92
+ // Clear existing cap flags first
93
+ val baseType = et.inputType and
94
+ (InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS or
95
+ InputType.TYPE_TEXT_FLAG_CAP_WORDS or
96
+ InputType.TYPE_TEXT_FLAG_CAP_SENTENCES).inv()
97
+ et.inputType = when (value) {
98
+ "characters", "allCharacters" -> baseType or InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS
99
+ "words" -> baseType or InputType.TYPE_TEXT_FLAG_CAP_WORDS
100
+ "sentences" -> baseType or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
101
+ "none" -> baseType
102
+ else -> baseType or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
103
+ }
104
+ }
105
+ "autoCorrect", "autocorrect" -> {
106
+ if (value == true || value == "true") {
107
+ et.inputType = et.inputType or InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
108
+ } else if (value == false || value == "false") {
109
+ et.inputType = et.inputType and InputType.TYPE_TEXT_FLAG_AUTO_CORRECT.inv()
110
+ }
111
+ }
112
+ "textAlign", "textAlignment" -> {
113
+ et.textAlignment = when (value) {
114
+ "left" -> View.TEXT_ALIGNMENT_TEXT_START
115
+ "center" -> View.TEXT_ALIGNMENT_CENTER
116
+ "right" -> View.TEXT_ALIGNMENT_TEXT_END
117
+ else -> View.TEXT_ALIGNMENT_TEXT_START
118
+ }
119
+ }
120
+ "color" -> {
121
+ val color = StyleEngine.parseColor(value)
122
+ if (color != null) et.setTextColor(color)
123
+ }
124
+ "fontSize" -> {
125
+ val size = when (value) {
126
+ is Number -> value.toFloat()
127
+ is String -> value.toFloatOrNull()
128
+ else -> null
129
+ }
130
+ if (size != null) et.textSize = size
131
+ }
132
+ else -> StyleEngine.apply(key, value, view)
133
+ }
134
+ }
135
+
136
+ override fun addEventListener(view: View, event: String, handler: (Any?) -> Unit) {
137
+ val et = view as? EditText ?: return
138
+ when (event) {
139
+ "change", "input", "changetext" -> {
140
+ changeHandlers[et] = handler
141
+ // Remove old watcher if any
142
+ textWatchers[et]?.let { et.removeTextChangedListener(it) }
143
+ val watcher = object : TextWatcher {
144
+ override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
145
+ override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
146
+ override fun afterTextChanged(s: Editable?) {
147
+ changeHandlers[et]?.invoke(mapOf("value" to (s?.toString() ?: "")))
148
+ }
149
+ }
150
+ textWatchers[et] = watcher
151
+ et.addTextChangedListener(watcher)
152
+ }
153
+ "submit" -> {
154
+ submitHandlers[et] = handler
155
+ et.setOnEditorActionListener { _, _, _ ->
156
+ submitHandlers[et]?.invoke(mapOf("value" to et.text.toString()))
157
+ true
158
+ }
159
+ }
160
+ "focus" -> {
161
+ focusHandlers[et] = handler
162
+ ensureFocusListener(et)
163
+ }
164
+ "blur" -> {
165
+ blurHandlers[et] = handler
166
+ ensureFocusListener(et)
167
+ }
168
+ }
169
+ }
170
+
171
+ override fun removeEventListener(view: View, event: String) {
172
+ val et = view as? EditText ?: return
173
+ when (event) {
174
+ "change", "input", "changetext" -> {
175
+ changeHandlers.remove(et)
176
+ textWatchers.remove(et)?.let { et.removeTextChangedListener(it) }
177
+ }
178
+ "submit" -> {
179
+ submitHandlers.remove(et)
180
+ et.setOnEditorActionListener(null)
181
+ }
182
+ "focus" -> {
183
+ focusHandlers.remove(et)
184
+ if (blurHandlers[et] == null) {
185
+ et.onFocusChangeListener = null
186
+ }
187
+ }
188
+ "blur" -> {
189
+ blurHandlers.remove(et)
190
+ if (focusHandlers[et] == null) {
191
+ et.onFocusChangeListener = null
192
+ }
193
+ }
194
+ }
195
+ }
196
+
197
+ /**
198
+ * Sets a single OnFocusChangeListener that dispatches to both focus and blur handlers.
199
+ * This avoids the problem of one listener overwriting the other.
200
+ */
201
+ private fun ensureFocusListener(et: EditText) {
202
+ et.onFocusChangeListener = View.OnFocusChangeListener { _, hasFocus ->
203
+ if (hasFocus) {
204
+ focusHandlers[et]?.invoke(null)
205
+ } else {
206
+ blurHandlers[et]?.invoke(null)
207
+ }
208
+ }
209
+ }
210
+ }
@@ -0,0 +1,31 @@
1
+ package com.vuenative.core
2
+
3
+ import android.content.Context
4
+ import android.view.View
5
+ import android.view.ViewGroup
6
+ import android.view.ViewTreeObserver
7
+ import com.google.android.flexbox.FlexDirection
8
+ import com.google.android.flexbox.FlexboxLayout
9
+
10
+ class VKeyboardAvoidingFactory : NativeComponentFactory {
11
+ override fun createView(context: Context): View {
12
+ val flex = FlexboxLayout(context).apply {
13
+ flexDirection = FlexDirection.COLUMN
14
+ layoutParams = ViewGroup.LayoutParams(
15
+ ViewGroup.LayoutParams.MATCH_PARENT,
16
+ ViewGroup.LayoutParams.MATCH_PARENT
17
+ )
18
+ }
19
+ // The Activity sets android:windowSoftInputMode="adjustResize" which
20
+ // makes the system handle keyboard avoidance automatically on Android.
21
+ return flex
22
+ }
23
+ override fun updateProp(view: View, key: String, value: Any?) = StyleEngine.apply(key, value, view)
24
+ override fun addEventListener(view: View, event: String, handler: (Any?) -> Unit) {}
25
+ override fun removeEventListener(view: View, event: String) {}
26
+ override fun insertChild(parent: View, child: View, index: Int) {
27
+ val flex = parent as? FlexboxLayout ?: return
28
+ val lp = StyleEngine.buildFlexLayoutParams(child)
29
+ if (index >= flex.childCount) flex.addView(child, lp) else flex.addView(child, index, lp)
30
+ }
31
+ }
@@ -0,0 +1,183 @@
1
+ package com.vuenative.core
2
+
3
+ import android.content.Context
4
+ import android.view.View
5
+ import android.view.ViewGroup
6
+ import androidx.recyclerview.widget.LinearLayoutManager
7
+ import androidx.recyclerview.widget.RecyclerView
8
+
9
+ class VListFactory : NativeComponentFactory {
10
+ // For each RecyclerView, store child views managed by the bridge.
11
+ // All maps are cleaned up in cleanupRecyclerView() when the view is removed.
12
+ private val childViews = mutableMapOf<RecyclerView, MutableList<View>>()
13
+ private val scrollHandlers = mutableMapOf<RecyclerView, (Any?) -> Unit>()
14
+ private val endReachedHandlers = mutableMapOf<RecyclerView, (Any?) -> Unit>()
15
+ private val scrollListeners = mutableMapOf<RecyclerView, RecyclerView.OnScrollListener>()
16
+ private val firedEndReached = mutableMapOf<RecyclerView, Boolean>()
17
+ private val estimatedItemHeights = mutableMapOf<RecyclerView, Int>()
18
+
19
+ override fun createView(context: Context): View {
20
+ val rv = RecyclerView(context).apply {
21
+ layoutManager = LinearLayoutManager(context)
22
+ layoutParams = ViewGroup.LayoutParams(
23
+ ViewGroup.LayoutParams.MATCH_PARENT,
24
+ ViewGroup.LayoutParams.MATCH_PARENT
25
+ )
26
+ }
27
+ childViews[rv] = mutableListOf()
28
+ firedEndReached[rv] = false
29
+ rv.adapter = VListAdapter(childViews[rv]!!)
30
+ return rv
31
+ }
32
+
33
+ override fun updateProp(view: View, key: String, value: Any?) {
34
+ val rv = view as? RecyclerView ?: return
35
+ when (key) {
36
+ "horizontal" -> {
37
+ if (value == true) {
38
+ rv.layoutManager = LinearLayoutManager(rv.context, LinearLayoutManager.HORIZONTAL, false)
39
+ }
40
+ }
41
+ "bounces" -> {
42
+ rv.overScrollMode = if (value == false || value == "false")
43
+ View.OVER_SCROLL_NEVER else View.OVER_SCROLL_ALWAYS
44
+ }
45
+ "showsScrollIndicator" -> {
46
+ val show = value != false && value != "false"
47
+ rv.isVerticalScrollBarEnabled = show
48
+ rv.isHorizontalScrollBarEnabled = show
49
+ }
50
+ "estimatedItemHeight" -> {
51
+ val h = when (value) {
52
+ is Number -> value.toInt()
53
+ is String -> value.toIntOrNull() ?: 44
54
+ else -> 44
55
+ }
56
+ estimatedItemHeights[rv] = h
57
+ }
58
+ else -> StyleEngine.apply(key, value, view)
59
+ }
60
+ }
61
+
62
+ override fun addEventListener(view: View, event: String, handler: (Any?) -> Unit) {
63
+ val rv = view as? RecyclerView ?: return
64
+ when (event) {
65
+ "scroll" -> {
66
+ scrollHandlers[rv] = handler
67
+ ensureScrollListener(rv)
68
+ }
69
+ "endReached" -> {
70
+ endReachedHandlers[rv] = handler
71
+ ensureScrollListener(rv)
72
+ }
73
+ }
74
+ }
75
+
76
+ override fun removeEventListener(view: View, event: String) {
77
+ val rv = view as? RecyclerView ?: return
78
+ when (event) {
79
+ "scroll" -> scrollHandlers.remove(rv)
80
+ "endReached" -> endReachedHandlers.remove(rv)
81
+ }
82
+ // Remove listener if neither handler is registered
83
+ if (!scrollHandlers.containsKey(rv) && !endReachedHandlers.containsKey(rv)) {
84
+ scrollListeners.remove(rv)?.let { rv.removeOnScrollListener(it) }
85
+ }
86
+ }
87
+
88
+ private fun ensureScrollListener(rv: RecyclerView) {
89
+ if (scrollListeners.containsKey(rv)) return
90
+ // Track cumulative scroll position
91
+ var cumulativeX = 0
92
+ var cumulativeY = 0
93
+ val listener = object : RecyclerView.OnScrollListener() {
94
+ override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
95
+ cumulativeX += dx
96
+ cumulativeY += dy
97
+
98
+ // Dispatch scroll event with cumulative position
99
+ scrollHandlers[recyclerView]?.invoke(
100
+ mapOf("x" to cumulativeX, "y" to cumulativeY)
101
+ )
102
+
103
+ // endReached detection (threshold = 20% from bottom)
104
+ val lm = recyclerView.layoutManager as? LinearLayoutManager ?: return
105
+ val totalItems = lm.itemCount
106
+ if (totalItems == 0) return
107
+ val lastVisible = lm.findLastVisibleItemPosition()
108
+ val threshold = (totalItems * 0.2).toInt().coerceAtLeast(1)
109
+
110
+ if (lastVisible >= totalItems - threshold) {
111
+ if (firedEndReached[recyclerView] != true) {
112
+ firedEndReached[recyclerView] = true
113
+ endReachedHandlers[recyclerView]?.invoke(null)
114
+ }
115
+ } else {
116
+ // Reset when scrolled back up significantly
117
+ firedEndReached[recyclerView] = false
118
+ }
119
+ }
120
+ }
121
+ scrollListeners[rv] = listener
122
+ rv.addOnScrollListener(listener)
123
+ }
124
+
125
+ override fun insertChild(parent: View, child: View, index: Int) {
126
+ val rv = parent as? RecyclerView ?: return
127
+ val list = childViews[rv] ?: return
128
+ val insertIdx = if (index >= list.size) list.size else index
129
+ list.add(insertIdx, child)
130
+ rv.adapter?.notifyItemInserted(insertIdx)
131
+ }
132
+
133
+ override fun removeChild(parent: View, child: View) {
134
+ val rv = parent as? RecyclerView ?: return
135
+ val list = childViews[rv] ?: return
136
+ val idx = list.indexOf(child)
137
+ if (idx >= 0) {
138
+ list.removeAt(idx)
139
+ rv.adapter?.notifyItemRemoved(idx)
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Clean up all state associated with a RecyclerView when it is removed from the tree.
145
+ * Prevents memory leaks by clearing all map entries that reference the view.
146
+ */
147
+ fun cleanupRecyclerView(rv: RecyclerView) {
148
+ scrollListeners.remove(rv)?.let { rv.removeOnScrollListener(it) }
149
+ scrollHandlers.remove(rv)
150
+ endReachedHandlers.remove(rv)
151
+ firedEndReached.remove(rv)
152
+ estimatedItemHeights.remove(rv)
153
+ childViews.remove(rv)
154
+ rv.adapter = null
155
+ }
156
+
157
+ /**
158
+ * Called when the parent view is being destroyed. Cleans up the RecyclerView.
159
+ */
160
+ fun destroyView(view: View) {
161
+ val rv = view as? RecyclerView ?: return
162
+ cleanupRecyclerView(rv)
163
+ }
164
+ }
165
+
166
+ class VListAdapter(private val items: List<View>) : RecyclerView.Adapter<VListAdapter.VH>() {
167
+ class VH(val view: View) : RecyclerView.ViewHolder(view)
168
+
169
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
170
+ val v = items.getOrNull(viewType) ?: android.widget.FrameLayout(parent.context)
171
+ // Remove from any existing parent
172
+ (v.parent as? ViewGroup)?.removeView(v)
173
+ v.layoutParams = RecyclerView.LayoutParams(
174
+ RecyclerView.LayoutParams.MATCH_PARENT,
175
+ RecyclerView.LayoutParams.WRAP_CONTENT
176
+ )
177
+ return VH(v)
178
+ }
179
+
180
+ override fun onBindViewHolder(holder: VH, position: Int) {}
181
+ override fun getItemCount(): Int = items.size
182
+ override fun getItemViewType(position: Int): Int = position
183
+ }
@@ -0,0 +1,105 @@
1
+ package com.vuenative.core
2
+
3
+ import android.app.Dialog
4
+ import android.content.Context
5
+ import android.graphics.Color
6
+ import android.graphics.drawable.ColorDrawable
7
+ import android.view.View
8
+ import android.view.ViewGroup
9
+ import android.view.Window
10
+ import com.google.android.flexbox.FlexDirection
11
+ import com.google.android.flexbox.FlexboxLayout
12
+
13
+ class VModalFactory : NativeComponentFactory {
14
+ private val dialogs = mutableMapOf<View, Dialog>()
15
+ private val contentContainers = mutableMapOf<View, FlexboxLayout>()
16
+ private val dismissHandlers = mutableMapOf<View, (Any?) -> Unit>()
17
+
18
+ override fun createView(context: Context): View {
19
+ // Return a zero-size placeholder view
20
+ return View(context).apply {
21
+ layoutParams = ViewGroup.LayoutParams(0, 0)
22
+ visibility = View.GONE
23
+ }
24
+ }
25
+
26
+ override fun updateProp(view: View, key: String, value: Any?) {
27
+ when (key) {
28
+ "visible" -> {
29
+ val show = value == true || value == "true"
30
+ if (show) showModal(view) else dismissModal(view)
31
+ }
32
+ "animationType" -> {} // TODO: dialog animation
33
+ "transparent" -> {
34
+ if (value == true) {
35
+ dialogs[view]?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
36
+ }
37
+ }
38
+ }
39
+ }
40
+
41
+ private fun showModal(view: View) {
42
+ val ctx = view.context
43
+ if (dialogs[view]?.isShowing == true) return
44
+ val dialog = Dialog(ctx, android.R.style.Theme_Translucent_NoTitleBar_Fullscreen)
45
+ dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
46
+ dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
47
+
48
+ val content = contentContainers.getOrPut(view) {
49
+ FlexboxLayout(ctx).apply {
50
+ flexDirection = FlexDirection.COLUMN
51
+ layoutParams = ViewGroup.LayoutParams(
52
+ ViewGroup.LayoutParams.MATCH_PARENT,
53
+ ViewGroup.LayoutParams.MATCH_PARENT
54
+ )
55
+ }
56
+ }
57
+ (content.parent as? ViewGroup)?.removeView(content)
58
+ dialog.setContentView(content)
59
+ dialog.setOnDismissListener { dismissHandlers[view]?.invoke(null) }
60
+ dialog.show()
61
+ dialogs[view] = dialog
62
+ }
63
+
64
+ private fun dismissModal(view: View) {
65
+ dialogs[view]?.dismiss()
66
+ dialogs.remove(view)
67
+ }
68
+
69
+ override fun addEventListener(view: View, event: String, handler: (Any?) -> Unit) {
70
+ if (event == "dismiss") dismissHandlers[view] = handler
71
+ }
72
+
73
+ override fun removeEventListener(view: View, event: String) {
74
+ if (event == "dismiss") dismissHandlers.remove(view)
75
+ }
76
+
77
+ override fun insertChild(parent: View, child: View, index: Int) {
78
+ val container = contentContainers.getOrPut(parent) {
79
+ FlexboxLayout(parent.context).apply {
80
+ flexDirection = FlexDirection.COLUMN
81
+ }
82
+ }
83
+ val lp = StyleEngine.buildFlexLayoutParams(child)
84
+ if (index >= container.childCount) container.addView(child, lp)
85
+ else container.addView(child, index, lp)
86
+ }
87
+
88
+ override fun removeChild(parent: View, child: View) {
89
+ contentContainers[parent]?.removeView(child)
90
+ }
91
+
92
+ /**
93
+ * Clean up all state associated with a modal view when it is removed from the tree.
94
+ * Dismisses the dialog and clears all map entries that reference the view,
95
+ * preventing memory leaks.
96
+ */
97
+ fun destroyView(view: View) {
98
+ dialogs[view]?.let { dialog ->
99
+ if (dialog.isShowing) dialog.dismiss()
100
+ }
101
+ dialogs.remove(view)
102
+ contentContainers.remove(view)
103
+ dismissHandlers.remove(view)
104
+ }
105
+ }
@@ -0,0 +1,57 @@
1
+ package com.vuenative.core
2
+
3
+ import android.content.Context
4
+ import android.view.View
5
+ import android.view.ViewGroup
6
+ import android.widget.DatePicker
7
+ import android.widget.TimePicker
8
+ import java.util.Calendar
9
+
10
+ class VPickerFactory : NativeComponentFactory {
11
+ private val changeHandlers = mutableMapOf<View, (Any?) -> Unit>()
12
+
13
+ override fun createView(context: Context): View {
14
+ return DatePicker(context).apply {
15
+ layoutParams = ViewGroup.LayoutParams(
16
+ ViewGroup.LayoutParams.WRAP_CONTENT,
17
+ ViewGroup.LayoutParams.WRAP_CONTENT
18
+ )
19
+ }
20
+ }
21
+
22
+ override fun updateProp(view: View, key: String, value: Any?) {
23
+ val dp = view as? DatePicker ?: return
24
+ when (key) {
25
+ "value" -> {
26
+ val ms = StyleEngine.toFloat(value, 0f).toLong()
27
+ val cal = Calendar.getInstance().apply { timeInMillis = ms }
28
+ dp.updateDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH))
29
+ }
30
+ "minimumDate" -> {
31
+ val ms = StyleEngine.toFloat(value, 0f).toLong()
32
+ dp.minDate = ms
33
+ }
34
+ "maximumDate" -> {
35
+ val ms = StyleEngine.toFloat(value, 0f).toLong()
36
+ dp.maxDate = ms
37
+ }
38
+ "mode" -> {} // DatePicker handles date mode; TimePicker for time
39
+ else -> StyleEngine.apply(key, value, view)
40
+ }
41
+ }
42
+
43
+ override fun addEventListener(view: View, event: String, handler: (Any?) -> Unit) {
44
+ val dp = view as? DatePicker ?: return
45
+ if (event == "change") {
46
+ changeHandlers[view] = handler
47
+ dp.init(
48
+ dp.year, dp.month, dp.dayOfMonth
49
+ ) { _, year, month, day ->
50
+ val cal = Calendar.getInstance().apply { set(year, month, day) }
51
+ changeHandlers[view]?.invoke(mapOf("value" to cal.timeInMillis.toDouble()))
52
+ }
53
+ }
54
+ }
55
+
56
+ override fun removeEventListener(view: View, event: String) { changeHandlers.remove(view) }
57
+ }