@craft-native/android 0.0.209 → 0.0.211

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/README.md CHANGED
@@ -102,7 +102,8 @@ stx native compile --config ../screens/native.config.json --format bundle --outp
102
102
  craft android build --native-bundle ../native-screen.js
103
103
  ```
104
104
 
105
- Native mode maps STX `View`, `SafeAreaView`, `Text`, `Button`, `Link`, `Icon`,
105
+ Native mode maps STX `View`, `SafeAreaView`, `KeyboardAvoidingView`, `StatusBar`,
106
+ `RefreshControl`, `Text`, `Button`, `Link`, `Icon`,
106
107
  `Pressable`, `TouchableOpacity`, `TouchableHighlight`, `Checkbox`, `TextInput`, `Picker`, `DatePicker`, `Modal`, `Switch`, `Slider`, `ActivityIndicator`, `Image`, `ImageBackground`, `Video`, `Svg`, `G`, `SvgText`, `ScrollView`,
107
108
  `Map`, `SectionList`, and `FlatList` to Android views. `Map` uses the Google
108
109
  Maps SDK for trail polylines and marker taps; its overlays carry flat
@@ -199,7 +200,12 @@ JavaScriptSandbox process. Enable `enableLocalDatabase`,
199
200
  `enableLocalNotifications`, and `enableDeepLinks` explicitly. Disabled or
200
201
  malformed calls reject with stable capability/error codes, and in-flight calls
201
202
  have a deadline and cancellation path. The broader browser bridge remains
202
- specific to WebView mode. Native `TextInput` applies `placeholderTextColor`,
203
+ specific to WebView mode. JavaScriptSandbox has no DOM `window`; Craft aliases
204
+ `globalThis.window` to `globalThis` before installing the native bridge so
205
+ browser-safe SDK calls such as `window.craft.dialog.actionSheet()` reach the
206
+ native capability host. This does not add `document` or DOM rendering; routes
207
+ that do not opt into `native` continue using the WebView renderer. Native
208
+ `TextInput` applies `placeholderTextColor`,
203
209
  `selectionColor`, positive `maxLength`, `multiline`, and `numberOfLines` values.
204
210
  Native views include
205
211
  `ActivityIndicator` and expose
@@ -248,7 +254,7 @@ configured start path against `nativeScreens`; invalid native route tables are
248
254
  rejected before a project is generated.
249
255
 
250
256
  - a tab bar and a navigation bar (`craft.navigation.setOptions`: title, large
251
- title, right buttons with badges, `tabBarHidden`), a stack per tab, Android's
257
+ title, right buttons with badges, `tabAccessory`, `tabBarHidden`), a stack per tab, Android's
252
258
  Back key popping it; completed left/right swipes switch between tab roots
253
259
  interactively, yield to a horizontal scroll view, and can be disabled per
254
260
  screen with `craft.navigation.setOptions({ tabSwipeEnabled: false })`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@craft-native/android",
3
- "version": "0.0.209",
3
+ "version": "0.0.211",
4
4
  "homepage": "https://github.com/craft-native/craft/tree/main/packages/android#readme",
5
5
  "repository": {
6
6
  "type": "git",
@@ -389,6 +389,10 @@ internal object CraftNativePrelude {
389
389
  routePrelude: String,
390
390
  ): String = """
391
391
  $routePrelude
392
+ // JavaScriptSandbox has no DOM window, but browser-safe SDK bridges
393
+ // address the host through `window.craft`. Keep native screens
394
+ // compatible without pretending a document exists.
395
+ if (typeof globalThis.window === 'undefined') globalThis.window = globalThis;
392
396
  (function() {
393
397
  var forward = null;
394
398
  var queued = [];
@@ -567,7 +571,7 @@ internal object CraftNativePrelude {
567
571
  * The bar above a screen (back, title, the screen's buttons) and the tab bar
568
572
  * below it, in plain Android views. A screen sets its bar with
569
573
  * `craft.navigation.setOptions` (title, largeTitle, hidden, rightButtons,
570
- * tabBarHidden); the tabs come from the app's `tabs`.
574
+ * tabAccessory, tabBarHidden); the tabs come from the app's `tabs`.
571
575
  */
572
576
  internal class CraftNativeChrome(context: Context, private val tabs: List<CraftNativeTab>) : LinearLayout(context) {
573
577
  val content = FrameLayout(context)
@@ -142,7 +142,7 @@ import kotlin.math.pow
142
142
 
143
143
  private const val CRAFT_NATIVE_CAPABILITY_TIMEOUT_MS = 30_000L
144
144
 
145
- private fun craftNativeOptionalString(value: Any?): String? = value
145
+ internal fun craftNativeOptionalString(value: Any?): String? = value
146
146
  ?.takeUnless { it == JSONObject.NULL }
147
147
  ?.toString()
148
148
  ?.takeUnless { it == "null" || it == "undefined" }
@@ -718,12 +718,15 @@ private class CraftNativeMapView(context: Context) : FrameLayout(context), OnMap
718
718
  val explicitRegion = region(pendingProps.optJSONObject("region"))
719
719
  val initialRegion = region(pendingProps.optJSONObject("initialRegion"))
720
720
  if (explicitRegion != null) {
721
- moveCamera(explicitRegion)
721
+ // A controlled region is an exact camera request. The padding
722
+ // used for fitToBounds is framing chrome, not part of the region
723
+ // contract, and would otherwise zoom every Android screen out.
724
+ moveCamera(explicitRegion, padding = 0)
722
725
  initialCameraKey = null
723
726
  } else if (initialRegion != null) {
724
727
  val key = "region:${pendingProps.optJSONObject("initialRegion")}"
725
728
  if (initialCameraKey != key) {
726
- moveCamera(initialRegion)
729
+ moveCamera(initialRegion, padding = 0)
727
730
  initialCameraKey = key
728
731
  }
729
732
  } else if (craftNativeBoolean(pendingProps.opt("fitToBounds"))) {
@@ -745,9 +748,9 @@ private class CraftNativeMapView(context: Context) : FrameLayout(context), OnMap
745
748
  }
746
749
  }
747
750
 
748
- private fun moveCamera(bounds: LatLngBounds) {
751
+ private fun moveCamera(bounds: LatLngBounds, padding: Int = 24) {
749
752
  post {
750
- if (width > 0 && height > 0) googleMap?.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 24))
753
+ if (width > 0 && height > 0) googleMap?.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, padding))
751
754
  }
752
755
  }
753
756
 
@@ -2512,7 +2515,7 @@ private class CraftNativeScrollView(context: Context) : SwipeRefreshLayout(conte
2512
2515
  }
2513
2516
 
2514
2517
  scroller.setOnScrollChangeListener { _, x, y, _, _ ->
2515
- if (!horizontal) updateStickyHeaders()
2518
+ if (horizontalMode != true) updateStickyHeaders()
2516
2519
  onScroll?.invoke(x, y)
2517
2520
  }
2518
2521
  scroller.setOnTouchListener { _, event ->
@@ -6219,7 +6222,7 @@ class MainActivity : AppCompatActivity() {
6219
6222
  else -> 400
6220
6223
  }
6221
6224
  view.typeface = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
6222
- Typeface.create("sans-serif", weight, false)
6225
+ Typeface.create(Typeface.create("sans-serif", Typeface.NORMAL), weight, false)
6223
6226
  } else {
6224
6227
  Typeface.create("sans-serif", if (weight >= 600) Typeface.BOLD else Typeface.NORMAL)
6225
6228
  }
@@ -6275,7 +6278,7 @@ class MainActivity : AppCompatActivity() {
6275
6278
  private fun configureTextStyle(view: TextView, style: JSONObject) {
6276
6279
  view.setTextColor(color(craftNativeOptionalString(style.opt("color")).orEmpty(), defaultTextColor))
6277
6280
  view.setTextSize(TypedValue.COMPLEX_UNIT_SP, craftNativeFiniteFloat(style, "fontSize", 16f))
6278
- val fontWeight = style.opt("fontWeight") as? String
6281
+ val fontWeight = craftNativeFontWeight(style.opt("fontWeight"))
6279
6282
  val weight = when (fontWeight) {
6280
6283
  "bold" -> 700
6281
6284
  "100", "200", "300", "400", "500", "600", "700", "800", "900" -> style.optInt("fontWeight")