@thelacanians/vue-native-cli 0.4.12 → 0.4.14
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.
- package/dist/cli.js +6 -1
- package/native/android/.editorconfig +25 -0
- package/native/android/VueNativeCore/build.gradle.kts +25 -1
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/JSPolyfills.kt +17 -10
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/JSRuntime.kt +5 -5
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/NativeBridge.kt +13 -13
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/ComponentRegistry.kt +27 -27
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VActionSheetFactory.kt +6 -4
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VActivityIndicatorFactory.kt +1 -1
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VAlertDialogFactory.kt +24 -12
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VButtonFactory.kt +5 -2
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VImageFactory.kt +7 -7
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VInputFactory.kt +12 -12
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VKeyboardAvoidingFactory.kt +0 -1
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VListFactory.kt +5 -2
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VModalFactory.kt +5 -2
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VPickerFactory.kt +3 -2
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VPressableFactory.kt +5 -3
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VRootFactory.kt +5 -2
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VScrollViewFactory.kt +5 -2
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VSectionListFactory.kt +5 -2
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VSegmentedControlFactory.kt +3 -3
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VStatusBarFactory.kt +3 -3
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VSwitchFactory.kt +0 -1
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VViewFactory.kt +9 -3
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VWebViewFactory.kt +7 -5
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/NativeComponentFactory.kt +5 -2
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Helpers/GestureHelper.kt +4 -1
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/AnimationModule.kt +77 -21
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/AsyncStorageModule.kt +20 -5
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/BackgroundTaskModule.kt +12 -3
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/BiometryModule.kt +5 -2
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/BluetoothModule.kt +88 -23
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/CalendarModule.kt +24 -11
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/ClipboardModule.kt +7 -2
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/ContactsModule.kt +24 -12
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/DeviceInfoModule.kt +14 -11
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/FileSystemModule.kt +79 -24
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/GeolocationModule.kt +10 -7
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/HapticsModule.kt +5 -5
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/HttpModule.kt +17 -8
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/IAPModule.kt +20 -5
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/KeyboardModule.kt +4 -1
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/LinkingModule.kt +12 -3
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/NetworkModule.kt +4 -1
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/NotificationsModule.kt +24 -6
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/OTAModule.kt +13 -5
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/PerformanceModule.kt +8 -2
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/PermissionsModule.kt +17 -8
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/SecureStorageModule.kt +20 -5
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/SensorsModule.kt +16 -4
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/ShareModule.kt +6 -3
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/SocialAuthModule.kt +4 -2
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/WebSocketModule.kt +26 -8
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Styling/StyleEngine.kt +127 -84
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Tags.kt +26 -26
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/VueNativeActivity.kt +1 -1
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/ComponentRegistryTest.kt +173 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/NativeBridgeTest.kt +436 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/NativeModuleRegistryTest.kt +251 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/StyleEngineTest.kt +482 -0
- package/native/android/build.gradle.kts +1 -0
- package/native/ios/.swiftlint.yml +62 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/JSPolyfills.swift +15 -2
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/NativeBridge.swift +4 -1
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/ComponentRegistryTests.swift +237 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/NativeBridgeOperationTests.swift +398 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/NativeModuleRegistryTests.swift +203 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/StyleEngineTests.swift +381 -0
- package/package.json +1 -1
package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Styling/StyleEngine.kt
CHANGED
|
@@ -62,10 +62,22 @@ object StyleEngine {
|
|
|
62
62
|
val bg = ensureBackground(view)
|
|
63
63
|
val radii = bg.cornerRadii ?: FloatArray(8) { 0f }
|
|
64
64
|
when (key) {
|
|
65
|
-
"borderTopLeftRadius"
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
"borderTopLeftRadius" -> {
|
|
66
|
+
radii[0] = px
|
|
67
|
+
radii[1] = px
|
|
68
|
+
}
|
|
69
|
+
"borderTopRightRadius" -> {
|
|
70
|
+
radii[2] = px
|
|
71
|
+
radii[3] = px
|
|
72
|
+
}
|
|
73
|
+
"borderBottomRightRadius" -> {
|
|
74
|
+
radii[4] = px
|
|
75
|
+
radii[5] = px
|
|
76
|
+
}
|
|
77
|
+
"borderBottomLeftRadius" -> {
|
|
78
|
+
radii[6] = px
|
|
79
|
+
radii[7] = px
|
|
80
|
+
}
|
|
69
81
|
}
|
|
70
82
|
bg.cornerRadii = radii
|
|
71
83
|
view.background = view.background
|
|
@@ -124,37 +136,52 @@ object StyleEngine {
|
|
|
124
136
|
}
|
|
125
137
|
|
|
126
138
|
// --- Margin (stored in FlexProps, applied when inserted into parent) ---
|
|
127
|
-
"margin" -> updateFlexProps(view) { fp ->
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
"
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
"
|
|
139
|
+
"margin" -> updateFlexProps(view) { fp ->
|
|
140
|
+
val px = dpToPx(ctx, toFloat(value, 0f)).toInt()
|
|
141
|
+
fp.copy(marginLeft = px, marginTop = px, marginRight = px, marginBottom = px)
|
|
142
|
+
}
|
|
143
|
+
"marginHorizontal" -> updateFlexProps(view) { fp ->
|
|
144
|
+
val px = dpToPx(ctx, toFloat(value, 0f)).toInt()
|
|
145
|
+
fp.copy(marginLeft = px, marginRight = px)
|
|
146
|
+
}
|
|
147
|
+
"marginVertical" -> updateFlexProps(view) { fp ->
|
|
148
|
+
val px = dpToPx(ctx, toFloat(value, 0f)).toInt()
|
|
149
|
+
fp.copy(marginTop = px, marginBottom = px)
|
|
150
|
+
}
|
|
151
|
+
"marginLeft" -> updateFlexProps(view) { fp -> fp.copy(marginLeft = dpToPx(ctx, toFloat(value, 0f)).toInt()) }
|
|
152
|
+
"marginRight" -> updateFlexProps(view) { fp -> fp.copy(marginRight = dpToPx(ctx, toFloat(value, 0f)).toInt()) }
|
|
153
|
+
"marginTop" -> updateFlexProps(view) { fp -> fp.copy(marginTop = dpToPx(ctx, toFloat(value, 0f)).toInt()) }
|
|
154
|
+
"marginBottom" -> updateFlexProps(view) { fp -> fp.copy(marginBottom = dpToPx(ctx, toFloat(value, 0f)).toInt()) }
|
|
155
|
+
"marginStart" -> updateFlexProps(view) { fp -> fp.copy(marginStart = dpToPx(ctx, toFloat(value, 0f)).toInt()) }
|
|
156
|
+
"marginEnd" -> updateFlexProps(view) { fp -> fp.copy(marginEnd = dpToPx(ctx, toFloat(value, 0f)).toInt()) }
|
|
136
157
|
|
|
137
158
|
// --- Dimensions ---
|
|
138
159
|
"width" -> {
|
|
139
160
|
val pct = parsePercent(value)
|
|
140
|
-
if (pct != null)
|
|
141
|
-
|
|
161
|
+
if (pct != null) {
|
|
162
|
+
updateFlexProps(view) { fp -> fp.copy(width = ViewGroup.LayoutParams.WRAP_CONTENT, widthPercent = pct) }
|
|
163
|
+
} else {
|
|
164
|
+
updateFlexProps(view) { fp -> fp.copy(width = parseDimension(ctx, value), widthPercent = -1f) }
|
|
165
|
+
}
|
|
142
166
|
}
|
|
143
167
|
"height" -> {
|
|
144
168
|
val pct = parsePercent(value)
|
|
145
|
-
if (pct != null)
|
|
146
|
-
|
|
169
|
+
if (pct != null) {
|
|
170
|
+
updateFlexProps(view) { fp -> fp.copy(height = ViewGroup.LayoutParams.WRAP_CONTENT, heightPercent = pct) }
|
|
171
|
+
} else {
|
|
172
|
+
updateFlexProps(view) { fp -> fp.copy(height = parseDimension(ctx, value), heightPercent = -1f) }
|
|
173
|
+
}
|
|
147
174
|
}
|
|
148
|
-
"minWidth"
|
|
175
|
+
"minWidth" -> updateFlexProps(view) { fp -> fp.copy(minWidth = dpToPx(ctx, toFloat(value, 0f)).toInt()) }
|
|
149
176
|
"minHeight" -> updateFlexProps(view) { fp -> fp.copy(minHeight = dpToPx(ctx, toFloat(value, 0f)).toInt()) }
|
|
150
|
-
"maxWidth"
|
|
177
|
+
"maxWidth" -> updateFlexProps(view) { fp -> fp.copy(maxWidth = dpToPx(ctx, toFloat(value, 0f)).toInt()) }
|
|
151
178
|
|
|
152
179
|
// --- Flex props (stored in FlexProps, applied when inserted) ---
|
|
153
180
|
"flex" -> {
|
|
154
181
|
val f = toFloat(value, 0f)
|
|
155
182
|
updateFlexProps(view) { fp -> fp.copy(flexGrow = f, flexShrink = 1f, width = 0, height = 0) }
|
|
156
183
|
}
|
|
157
|
-
"flexGrow"
|
|
184
|
+
"flexGrow" -> updateFlexProps(view) { fp -> fp.copy(flexGrow = toFloat(value, 0f)) }
|
|
158
185
|
"flexShrink" -> updateFlexProps(view) { fp -> fp.copy(flexShrink = toFloat(value, 1f)) }
|
|
159
186
|
"flexBasis" -> {
|
|
160
187
|
if (value == "auto" || value == null) {
|
|
@@ -170,8 +197,8 @@ object StyleEngine {
|
|
|
170
197
|
}
|
|
171
198
|
}
|
|
172
199
|
}
|
|
173
|
-
"alignSelf"
|
|
174
|
-
"order"
|
|
200
|
+
"alignSelf" -> updateFlexProps(view) { fp -> fp.copy(alignSelf = parseAlignSelf(value)) }
|
|
201
|
+
"order" -> updateFlexProps(view) { fp -> fp.copy(order = toInt(value, 1)) }
|
|
175
202
|
|
|
176
203
|
// --- Parent Flex props (applied to FlexboxLayout itself) ---
|
|
177
204
|
"flexDirection" -> {
|
|
@@ -281,8 +308,11 @@ object StyleEngine {
|
|
|
281
308
|
view.visibility = if (value == "none") View.GONE else View.VISIBLE
|
|
282
309
|
}
|
|
283
310
|
"visible" -> {
|
|
284
|
-
if (value == false || value == "false")
|
|
285
|
-
|
|
311
|
+
if (value == false || value == "false") {
|
|
312
|
+
view.visibility = View.INVISIBLE
|
|
313
|
+
} else {
|
|
314
|
+
view.visibility = View.VISIBLE
|
|
315
|
+
}
|
|
286
316
|
}
|
|
287
317
|
"hidden" -> {
|
|
288
318
|
view.visibility = if (value == true || value == "true") View.INVISIBLE else View.VISIBLE
|
|
@@ -332,15 +362,15 @@ object StyleEngine {
|
|
|
332
362
|
override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfoCompat) {
|
|
333
363
|
super.onInitializeAccessibilityNodeInfo(host, info)
|
|
334
364
|
when (role) {
|
|
335
|
-
"button"
|
|
336
|
-
"link"
|
|
337
|
-
"header"
|
|
338
|
-
"image"
|
|
339
|
-
"text"
|
|
340
|
-
"search"
|
|
365
|
+
"button" -> info.className = "android.widget.Button"
|
|
366
|
+
"link" -> info.addAction(AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_CLICK)
|
|
367
|
+
"header" -> info.isHeading = true
|
|
368
|
+
"image" -> info.className = "android.widget.ImageView"
|
|
369
|
+
"text" -> info.className = "android.widget.TextView"
|
|
370
|
+
"search" -> info.className = "android.widget.EditText"
|
|
341
371
|
"adjustable" -> info.className = "android.widget.SeekBar"
|
|
342
|
-
"tab"
|
|
343
|
-
"none"
|
|
372
|
+
"tab" -> info.roleDescription = "tab"
|
|
373
|
+
"none" -> { /* no special role */ }
|
|
344
374
|
}
|
|
345
375
|
}
|
|
346
376
|
})
|
|
@@ -363,13 +393,16 @@ object StyleEngine {
|
|
|
363
393
|
view.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES
|
|
364
394
|
}
|
|
365
395
|
"accessible" -> view.importantForAccessibility =
|
|
366
|
-
if (value == true)
|
|
367
|
-
|
|
396
|
+
if (value == true) {
|
|
397
|
+
View.IMPORTANT_FOR_ACCESSIBILITY_YES
|
|
398
|
+
} else {
|
|
399
|
+
View.IMPORTANT_FOR_ACCESSIBILITY_NO
|
|
400
|
+
}
|
|
368
401
|
"importantForAccessibility" -> {
|
|
369
402
|
view.importantForAccessibility = when (value) {
|
|
370
403
|
"auto" -> View.IMPORTANT_FOR_ACCESSIBILITY_AUTO
|
|
371
|
-
"yes"
|
|
372
|
-
"no"
|
|
404
|
+
"yes" -> View.IMPORTANT_FOR_ACCESSIBILITY_YES
|
|
405
|
+
"no" -> View.IMPORTANT_FOR_ACCESSIBILITY_NO
|
|
373
406
|
"no-hide-descendants" -> View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
|
|
374
407
|
else -> View.IMPORTANT_FOR_ACCESSIBILITY_AUTO
|
|
375
408
|
}
|
|
@@ -390,23 +423,28 @@ object StyleEngine {
|
|
|
390
423
|
"fontWeight" -> {
|
|
391
424
|
val current = tv.typeface ?: android.graphics.Typeface.DEFAULT
|
|
392
425
|
tv.setTypeface(current,
|
|
393
|
-
if (value == "bold" || (value as? Number)?.toInt() ?: 0 >= 600)
|
|
426
|
+
if (value == "bold" || (value as? Number)?.toInt() ?: 0 >= 600) {
|
|
394
427
|
android.graphics.Typeface.BOLD
|
|
395
|
-
else
|
|
428
|
+
} else {
|
|
429
|
+
android.graphics.Typeface.NORMAL
|
|
430
|
+
}
|
|
396
431
|
)
|
|
397
432
|
}
|
|
398
433
|
"fontStyle" -> {
|
|
399
434
|
val current = tv.typeface ?: android.graphics.Typeface.DEFAULT
|
|
400
435
|
tv.setTypeface(current,
|
|
401
|
-
if (value == "italic")
|
|
402
|
-
|
|
436
|
+
if (value == "italic") {
|
|
437
|
+
android.graphics.Typeface.ITALIC
|
|
438
|
+
} else {
|
|
439
|
+
android.graphics.Typeface.NORMAL
|
|
440
|
+
}
|
|
403
441
|
)
|
|
404
442
|
}
|
|
405
443
|
"textAlign" -> tv.textAlignment = when (value) {
|
|
406
444
|
"center" -> View.TEXT_ALIGNMENT_CENTER
|
|
407
|
-
"right"
|
|
408
|
-
"left"
|
|
409
|
-
else
|
|
445
|
+
"right" -> View.TEXT_ALIGNMENT_VIEW_END
|
|
446
|
+
"left" -> View.TEXT_ALIGNMENT_VIEW_START
|
|
447
|
+
else -> View.TEXT_ALIGNMENT_INHERIT
|
|
410
448
|
}
|
|
411
449
|
"lineHeight" -> {
|
|
412
450
|
val px = dpToPx(ctx, toFloat(value, 0f))
|
|
@@ -419,20 +457,20 @@ object StyleEngine {
|
|
|
419
457
|
}
|
|
420
458
|
"textDecorationLine" -> {
|
|
421
459
|
tv.paintFlags = when (value) {
|
|
422
|
-
"underline"
|
|
460
|
+
"underline" -> tv.paintFlags or android.graphics.Paint.UNDERLINE_TEXT_FLAG
|
|
423
461
|
"line-through" -> tv.paintFlags or android.graphics.Paint.STRIKE_THRU_TEXT_FLAG
|
|
424
|
-
"none"
|
|
462
|
+
"none" -> (tv.paintFlags and android.graphics.Paint.UNDERLINE_TEXT_FLAG.inv()
|
|
425
463
|
and android.graphics.Paint.STRIKE_THRU_TEXT_FLAG.inv())
|
|
426
|
-
else
|
|
464
|
+
else -> tv.paintFlags
|
|
427
465
|
}
|
|
428
466
|
}
|
|
429
467
|
"textTransform" -> {
|
|
430
468
|
val t = tv.text?.toString() ?: ""
|
|
431
469
|
tv.text = when (value) {
|
|
432
|
-
"uppercase"
|
|
433
|
-
"lowercase"
|
|
470
|
+
"uppercase" -> t.uppercase()
|
|
471
|
+
"lowercase" -> t.lowercase()
|
|
434
472
|
"capitalize" -> t.split(" ").joinToString(" ") { it.replaceFirstChar(Char::uppercase) }
|
|
435
|
-
else
|
|
473
|
+
else -> t
|
|
436
474
|
}
|
|
437
475
|
}
|
|
438
476
|
"numberOfLines" -> {
|
|
@@ -528,7 +566,9 @@ object StyleEngine {
|
|
|
528
566
|
s == "gray" || s == "grey" -> Color.GRAY
|
|
529
567
|
else -> Color.parseColor(s)
|
|
530
568
|
}
|
|
531
|
-
} catch (e: Exception) {
|
|
569
|
+
} catch (e: Exception) {
|
|
570
|
+
null
|
|
571
|
+
}
|
|
532
572
|
}
|
|
533
573
|
|
|
534
574
|
// -- Dimension helpers --------------------------------------------------------
|
|
@@ -546,8 +586,11 @@ object StyleEngine {
|
|
|
546
586
|
value is String && value.endsWith("%") -> {
|
|
547
587
|
// 100% maps to MATCH_PARENT; other percentages are handled via widthPercent/heightPercent
|
|
548
588
|
// in the "width"/"height" cases above — this fallback covers minWidth/minHeight
|
|
549
|
-
if (value == "100%")
|
|
550
|
-
|
|
589
|
+
if (value == "100%") {
|
|
590
|
+
ViewGroup.LayoutParams.MATCH_PARENT
|
|
591
|
+
} else {
|
|
592
|
+
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
593
|
+
}
|
|
551
594
|
}
|
|
552
595
|
value == "auto" || value == null -> ViewGroup.LayoutParams.WRAP_CONTENT
|
|
553
596
|
else -> dpToPx(context, toFloat(value, 0f)).toInt()
|
|
@@ -564,20 +607,20 @@ object StyleEngine {
|
|
|
564
607
|
|
|
565
608
|
fun toFloat(value: Any?, default: Float): Float = when (value) {
|
|
566
609
|
is Double -> value.toFloat()
|
|
567
|
-
is Float
|
|
568
|
-
is Int
|
|
569
|
-
is Long
|
|
610
|
+
is Float -> value
|
|
611
|
+
is Int -> value.toFloat()
|
|
612
|
+
is Long -> value.toFloat()
|
|
570
613
|
is String -> value.toFloatOrNull() ?: default
|
|
571
|
-
else
|
|
614
|
+
else -> default
|
|
572
615
|
}
|
|
573
616
|
|
|
574
617
|
fun toInt(value: Any?, default: Int): Int = when (value) {
|
|
575
|
-
is Int
|
|
618
|
+
is Int -> value
|
|
576
619
|
is Double -> value.toInt()
|
|
577
|
-
is Float
|
|
578
|
-
is Long
|
|
620
|
+
is Float -> value.toInt()
|
|
621
|
+
is Long -> value.toInt()
|
|
579
622
|
is String -> value.toIntOrNull() ?: default
|
|
580
|
-
else
|
|
623
|
+
else -> default
|
|
581
624
|
}
|
|
582
625
|
|
|
583
626
|
// -- GradientDrawable management ----------------------------------------------
|
|
@@ -593,51 +636,51 @@ object StyleEngine {
|
|
|
593
636
|
// -- Flex enum parsing --------------------------------------------------------
|
|
594
637
|
|
|
595
638
|
private fun parseFlexDirection(value: Any?) = when (value) {
|
|
596
|
-
"row"
|
|
597
|
-
"row-reverse"
|
|
639
|
+
"row" -> FlexDirection.ROW
|
|
640
|
+
"row-reverse" -> FlexDirection.ROW_REVERSE
|
|
598
641
|
"column-reverse" -> FlexDirection.COLUMN_REVERSE
|
|
599
|
-
else
|
|
642
|
+
else -> FlexDirection.COLUMN
|
|
600
643
|
}
|
|
601
644
|
|
|
602
645
|
private fun parseFlexWrap(value: Any?) = when (value) {
|
|
603
|
-
"wrap"
|
|
646
|
+
"wrap" -> FlexWrap.WRAP
|
|
604
647
|
"wrap-reverse" -> FlexWrap.WRAP_REVERSE
|
|
605
|
-
else
|
|
648
|
+
else -> FlexWrap.NOWRAP
|
|
606
649
|
}
|
|
607
650
|
|
|
608
651
|
private fun parseAlignItems(value: Any?) = when (value) {
|
|
609
652
|
"flex-start" -> AlignItems.FLEX_START
|
|
610
|
-
"flex-end"
|
|
611
|
-
"center"
|
|
612
|
-
"baseline"
|
|
613
|
-
else
|
|
653
|
+
"flex-end" -> AlignItems.FLEX_END
|
|
654
|
+
"center" -> AlignItems.CENTER
|
|
655
|
+
"baseline" -> AlignItems.BASELINE
|
|
656
|
+
else -> AlignItems.STRETCH
|
|
614
657
|
}
|
|
615
658
|
|
|
616
659
|
private fun parseAlignContent(value: Any?) = when (value) {
|
|
617
|
-
"flex-start"
|
|
618
|
-
"flex-end"
|
|
619
|
-
"center"
|
|
660
|
+
"flex-start" -> AlignContent.FLEX_START
|
|
661
|
+
"flex-end" -> AlignContent.FLEX_END
|
|
662
|
+
"center" -> AlignContent.CENTER
|
|
620
663
|
"space-between" -> AlignContent.SPACE_BETWEEN
|
|
621
|
-
"space-around"
|
|
622
|
-
else
|
|
664
|
+
"space-around" -> AlignContent.SPACE_AROUND
|
|
665
|
+
else -> AlignContent.STRETCH
|
|
623
666
|
}
|
|
624
667
|
|
|
625
668
|
private fun parseJustifyContent(value: Any?) = when (value) {
|
|
626
|
-
"flex-end"
|
|
627
|
-
"center"
|
|
669
|
+
"flex-end" -> JustifyContent.FLEX_END
|
|
670
|
+
"center" -> JustifyContent.CENTER
|
|
628
671
|
"space-between" -> JustifyContent.SPACE_BETWEEN
|
|
629
|
-
"space-around"
|
|
630
|
-
"space-evenly"
|
|
631
|
-
else
|
|
672
|
+
"space-around" -> JustifyContent.SPACE_AROUND
|
|
673
|
+
"space-evenly" -> JustifyContent.SPACE_EVENLY
|
|
674
|
+
else -> JustifyContent.FLEX_START
|
|
632
675
|
}
|
|
633
676
|
|
|
634
677
|
private fun parseAlignSelf(value: Any?) = when (value) {
|
|
635
678
|
"flex-start" -> AlignSelf.FLEX_START
|
|
636
|
-
"flex-end"
|
|
637
|
-
"center"
|
|
638
|
-
"baseline"
|
|
639
|
-
"stretch"
|
|
640
|
-
else
|
|
679
|
+
"flex-end" -> AlignSelf.FLEX_END
|
|
680
|
+
"center" -> AlignSelf.CENTER
|
|
681
|
+
"baseline" -> AlignSelf.BASELINE
|
|
682
|
+
"stretch" -> AlignSelf.STRETCH
|
|
683
|
+
else -> AlignSelf.AUTO
|
|
641
684
|
}
|
|
642
685
|
|
|
643
686
|
private val FLEX_LAYOUT_KEYS = setOf(
|
|
@@ -2,42 +2,42 @@ package com.vuenative.core
|
|
|
2
2
|
|
|
3
3
|
/** View tag IDs used with View.setTag(id, value) */
|
|
4
4
|
object Tags {
|
|
5
|
-
const val FLEX_PROPS
|
|
5
|
+
const val FLEX_PROPS = 0x7F_FF_0001
|
|
6
6
|
const val EVENT_HANDLER = 0x7F_FF_0002
|
|
7
|
-
const val NODE_ID
|
|
8
|
-
const val FACTORY
|
|
9
|
-
const val BORDER_COLOR
|
|
10
|
-
const val BORDER_WIDTH
|
|
11
|
-
const val GAP
|
|
12
|
-
const val SHADOW_COLOR
|
|
13
|
-
const val SHADOW_OPACITY= 0x7F_FF_0014
|
|
7
|
+
const val NODE_ID = 0x7F_FF_0003
|
|
8
|
+
const val FACTORY = 0x7F_FF_0004
|
|
9
|
+
const val BORDER_COLOR = 0x7F_FF_0010
|
|
10
|
+
const val BORDER_WIDTH = 0x7F_FF_0011
|
|
11
|
+
const val GAP = 0x7F_FF_0012
|
|
12
|
+
const val SHADOW_COLOR = 0x7F_FF_0013
|
|
13
|
+
const val SHADOW_OPACITY = 0x7F_FF_0014
|
|
14
14
|
const val SHADOW_RADIUS = 0x7F_FF_0015
|
|
15
15
|
const val SHADOW_OFFSET_X = 0x7F_FF_0016
|
|
16
16
|
const val SHADOW_OFFSET_Y = 0x7F_FF_0017
|
|
17
|
-
const val POSITION
|
|
18
|
-
const val POSITION_TOP
|
|
19
|
-
const val POSITION_LEFT
|
|
17
|
+
const val POSITION = 0x7F_FF_0020
|
|
18
|
+
const val POSITION_TOP = 0x7F_FF_0021
|
|
19
|
+
const val POSITION_LEFT = 0x7F_FF_0022
|
|
20
20
|
const val POSITION_RIGHT = 0x7F_FF_0023
|
|
21
|
-
const val POSITION_BOTTOM= 0x7F_FF_0024
|
|
21
|
+
const val POSITION_BOTTOM = 0x7F_FF_0024
|
|
22
22
|
const val INTERNAL_PROPS = 0x7F_FF_0030
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
/** Alias used throughout the codebase */
|
|
26
|
-
const val TAG_FLEX_PROPS
|
|
26
|
+
const val TAG_FLEX_PROPS = Tags.FLEX_PROPS
|
|
27
27
|
const val TAG_EVENT_HANDLER = Tags.EVENT_HANDLER
|
|
28
|
-
const val TAG_NODE_ID
|
|
29
|
-
const val TAG_FACTORY
|
|
30
|
-
const val TAG_BORDER_COLOR
|
|
31
|
-
const val TAG_BORDER_WIDTH
|
|
32
|
-
const val TAG_GAP
|
|
33
|
-
const val TAG_SHADOW_COLOR
|
|
34
|
-
const val TAG_SHADOW_OPACITY
|
|
35
|
-
const val TAG_SHADOW_RADIUS
|
|
28
|
+
const val TAG_NODE_ID = Tags.NODE_ID
|
|
29
|
+
const val TAG_FACTORY = Tags.FACTORY
|
|
30
|
+
const val TAG_BORDER_COLOR = Tags.BORDER_COLOR
|
|
31
|
+
const val TAG_BORDER_WIDTH = Tags.BORDER_WIDTH
|
|
32
|
+
const val TAG_GAP = Tags.GAP
|
|
33
|
+
const val TAG_SHADOW_COLOR = Tags.SHADOW_COLOR
|
|
34
|
+
const val TAG_SHADOW_OPACITY = Tags.SHADOW_OPACITY
|
|
35
|
+
const val TAG_SHADOW_RADIUS = Tags.SHADOW_RADIUS
|
|
36
36
|
const val TAG_SHADOW_OFFSET_X = Tags.SHADOW_OFFSET_X
|
|
37
37
|
const val TAG_SHADOW_OFFSET_Y = Tags.SHADOW_OFFSET_Y
|
|
38
|
-
const val TAG_POSITION
|
|
39
|
-
const val TAG_POSITION_TOP
|
|
40
|
-
const val TAG_POSITION_LEFT
|
|
41
|
-
const val TAG_POSITION_RIGHT
|
|
38
|
+
const val TAG_POSITION = Tags.POSITION
|
|
39
|
+
const val TAG_POSITION_TOP = Tags.POSITION_TOP
|
|
40
|
+
const val TAG_POSITION_LEFT = Tags.POSITION_LEFT
|
|
41
|
+
const val TAG_POSITION_RIGHT = Tags.POSITION_RIGHT
|
|
42
42
|
const val TAG_POSITION_BOTTOM = Tags.POSITION_BOTTOM
|
|
43
|
-
const val TAG_INTERNAL_PROPS
|
|
43
|
+
const val TAG_INTERNAL_PROPS = Tags.INTERNAL_PROPS
|
package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/VueNativeActivity.kt
CHANGED
|
@@ -4,10 +4,10 @@ import android.content.Intent
|
|
|
4
4
|
import android.graphics.Color
|
|
5
5
|
import android.os.Build
|
|
6
6
|
import android.os.Bundle
|
|
7
|
+
import android.util.Log
|
|
7
8
|
import android.view.View
|
|
8
9
|
import android.view.ViewGroup
|
|
9
10
|
import android.widget.FrameLayout
|
|
10
|
-
import android.util.Log
|
|
11
11
|
import androidx.appcompat.app.AppCompatActivity
|
|
12
12
|
|
|
13
13
|
/**
|
package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/ComponentRegistryTest.kt
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
package com.vuenative.core
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.view.View
|
|
5
|
+
import android.widget.TextView
|
|
6
|
+
import androidx.test.core.app.ApplicationProvider
|
|
7
|
+
import com.google.android.flexbox.FlexboxLayout
|
|
8
|
+
import org.junit.Assert.assertEquals
|
|
9
|
+
import org.junit.Assert.assertNotNull
|
|
10
|
+
import org.junit.Assert.assertNull
|
|
11
|
+
import org.junit.Assert.assertTrue
|
|
12
|
+
import org.junit.Before
|
|
13
|
+
import org.junit.Test
|
|
14
|
+
import org.junit.runner.RunWith
|
|
15
|
+
import org.robolectric.RobolectricTestRunner
|
|
16
|
+
import org.robolectric.annotation.Config
|
|
17
|
+
|
|
18
|
+
@RunWith(RobolectricTestRunner::class)
|
|
19
|
+
@Config(sdk = [34])
|
|
20
|
+
class ComponentRegistryTest {
|
|
21
|
+
|
|
22
|
+
private lateinit var context: Context
|
|
23
|
+
private lateinit var registry: ComponentRegistry
|
|
24
|
+
|
|
25
|
+
@Before
|
|
26
|
+
fun setUp() {
|
|
27
|
+
// Reset singleton via reflection for test isolation
|
|
28
|
+
val field = ComponentRegistry::class.java.getDeclaredField("instance")
|
|
29
|
+
field.isAccessible = true
|
|
30
|
+
field.set(null, null)
|
|
31
|
+
|
|
32
|
+
context = ApplicationProvider.getApplicationContext()
|
|
33
|
+
registry = ComponentRegistry.getInstance(context)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// -------------------------------------------------------------------------
|
|
37
|
+
// All 28 default component types should be registered
|
|
38
|
+
// -------------------------------------------------------------------------
|
|
39
|
+
|
|
40
|
+
@Test
|
|
41
|
+
fun testAllComponentsRegistered() {
|
|
42
|
+
val expectedTypes = listOf(
|
|
43
|
+
"VView", "VText", "VButton", "VInput", "VSwitch",
|
|
44
|
+
"VActivityIndicator", "VScrollView", "VImage",
|
|
45
|
+
"VKeyboardAvoiding", "VSafeArea", "VSlider", "VList",
|
|
46
|
+
"VModal", "VAlertDialog", "VStatusBar", "VWebView",
|
|
47
|
+
"VProgressBar", "VPicker", "VSegmentedControl", "VActionSheet",
|
|
48
|
+
"VRefreshControl", "VPressable", "VSectionList", "VCheckbox",
|
|
49
|
+
"VRadio", "VDropdown", "VVideo", "__ROOT__"
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
for (type in expectedTypes) {
|
|
53
|
+
val view = registry.createView(type)
|
|
54
|
+
assertNotNull("createView('$type') should return non-null", view)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// -------------------------------------------------------------------------
|
|
59
|
+
// Unknown type returns null
|
|
60
|
+
// -------------------------------------------------------------------------
|
|
61
|
+
|
|
62
|
+
@Test
|
|
63
|
+
fun testUnknownTypeReturnsNull() {
|
|
64
|
+
val view = registry.createView("NonExistent")
|
|
65
|
+
assertNull("Unknown type should return null", view)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// -------------------------------------------------------------------------
|
|
69
|
+
// Factory is stored on view via tag
|
|
70
|
+
// -------------------------------------------------------------------------
|
|
71
|
+
|
|
72
|
+
@Test
|
|
73
|
+
fun testFactoryStoredOnView() {
|
|
74
|
+
val view = registry.createView("VView")!!
|
|
75
|
+
val factory = registry.factoryForView(view)
|
|
76
|
+
assertNotNull("factoryForView should return non-null after createView", factory)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// -------------------------------------------------------------------------
|
|
80
|
+
// factoryForType
|
|
81
|
+
// -------------------------------------------------------------------------
|
|
82
|
+
|
|
83
|
+
@Test
|
|
84
|
+
fun testFactoryForType() {
|
|
85
|
+
val factory = registry.factoryForType("VView")
|
|
86
|
+
assertNotNull("factoryForType('VView') should return non-null", factory)
|
|
87
|
+
assertTrue("VView factory should be VViewFactory", factory is VViewFactory)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@Test
|
|
91
|
+
fun testFactoryForTypeUnknown() {
|
|
92
|
+
val factory = registry.factoryForType("NonExistent")
|
|
93
|
+
assertNull("factoryForType for unknown type should return null", factory)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// -------------------------------------------------------------------------
|
|
97
|
+
// Register a custom factory
|
|
98
|
+
// -------------------------------------------------------------------------
|
|
99
|
+
|
|
100
|
+
@Test
|
|
101
|
+
fun testRegisterCustomFactory() {
|
|
102
|
+
val customFactory = object : NativeComponentFactory {
|
|
103
|
+
override fun createView(context: Context): View = View(context)
|
|
104
|
+
override fun updateProp(view: View, key: String, value: Any?) {}
|
|
105
|
+
override fun addEventListener(view: View, event: String, handler: (Any?) -> Unit) {}
|
|
106
|
+
override fun removeEventListener(view: View, event: String) {}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
registry.register("CustomComponent", customFactory)
|
|
110
|
+
val view = registry.createView("CustomComponent")
|
|
111
|
+
assertNotNull("Custom component should be created", view)
|
|
112
|
+
|
|
113
|
+
val retrievedFactory = registry.factoryForType("CustomComponent")
|
|
114
|
+
assertEquals("Retrieved factory should be the custom factory", customFactory, retrievedFactory)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// -------------------------------------------------------------------------
|
|
118
|
+
// VText creates a TextView
|
|
119
|
+
// -------------------------------------------------------------------------
|
|
120
|
+
|
|
121
|
+
@Test
|
|
122
|
+
fun testVTextCreatesTextView() {
|
|
123
|
+
val view = registry.createView("VText")
|
|
124
|
+
assertNotNull(view)
|
|
125
|
+
assertTrue("VText should create a TextView", view is TextView)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// -------------------------------------------------------------------------
|
|
129
|
+
// VView creates a FlexboxLayout
|
|
130
|
+
// -------------------------------------------------------------------------
|
|
131
|
+
|
|
132
|
+
@Test
|
|
133
|
+
fun testVViewCreatesFlexboxLayout() {
|
|
134
|
+
val view = registry.createView("VView")
|
|
135
|
+
assertNotNull(view)
|
|
136
|
+
assertTrue("VView should create a FlexboxLayout", view is FlexboxLayout)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// -------------------------------------------------------------------------
|
|
140
|
+
// Singleton behavior
|
|
141
|
+
// -------------------------------------------------------------------------
|
|
142
|
+
|
|
143
|
+
@Test
|
|
144
|
+
fun testSingletonReturnsSameInstance() {
|
|
145
|
+
val instance1 = ComponentRegistry.getInstance(context)
|
|
146
|
+
val instance2 = ComponentRegistry.getInstance(context)
|
|
147
|
+
assertTrue("getInstance should return the same instance", instance1 === instance2)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// -------------------------------------------------------------------------
|
|
151
|
+
// Register overwrites existing factory
|
|
152
|
+
// -------------------------------------------------------------------------
|
|
153
|
+
|
|
154
|
+
@Test
|
|
155
|
+
fun testRegisterOverwritesExistingFactory() {
|
|
156
|
+
val customFactory = object : NativeComponentFactory {
|
|
157
|
+
override fun createView(context: Context): View = TextView(context)
|
|
158
|
+
override fun updateProp(view: View, key: String, value: Any?) {}
|
|
159
|
+
override fun addEventListener(view: View, event: String, handler: (Any?) -> Unit) {}
|
|
160
|
+
override fun removeEventListener(view: View, event: String) {}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Overwrite the default VView factory
|
|
164
|
+
registry.register("VView", customFactory)
|
|
165
|
+
|
|
166
|
+
val factory = registry.factoryForType("VView")
|
|
167
|
+
assertEquals("Factory should be the newly registered one", customFactory, factory)
|
|
168
|
+
|
|
169
|
+
// The view created should now be a TextView (from custom factory), not FlexboxLayout
|
|
170
|
+
val view = registry.createView("VView")
|
|
171
|
+
assertTrue("Overwritten VView should create a TextView", view is TextView)
|
|
172
|
+
}
|
|
173
|
+
}
|