@expo/ui 58.0.7 → 58.0.9

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 (135) hide show
  1. package/CHANGELOG.md +12 -5
  2. package/android/build.gradle +2 -2
  3. package/android/src/main/java/expo/modules/ui/AnimatedVisibilityView.kt +40 -8
  4. package/android/src/main/java/expo/modules/ui/ComposeViews.kt +21 -3
  5. package/android/src/main/java/expo/modules/ui/DatePickerView.kt +12 -4
  6. package/android/src/main/java/expo/modules/ui/ExpoUIModule.kt +5 -1
  7. package/android/src/main/java/expo/modules/ui/HorizontalPagerView.kt +3 -1
  8. package/android/src/main/java/expo/modules/ui/HostView.kt +64 -12
  9. package/android/src/main/java/expo/modules/ui/LazyItemsView.kt +14 -2
  10. package/android/src/main/java/expo/modules/ui/ModalBottomSheetView.kt +5 -1
  11. package/android/src/main/java/expo/modules/ui/ModifierRegistry.kt +40 -7
  12. package/android/src/main/java/expo/modules/ui/RNHostView.kt +3 -1
  13. package/android/src/main/java/expo/modules/ui/SemanticsModifier.kt +2 -1
  14. package/android/src/main/java/expo/modules/ui/ShapeView.kt +3 -1
  15. package/android/src/main/java/expo/modules/ui/SlotView.kt +3 -1
  16. package/android/src/main/java/expo/modules/ui/SnackbarView.kt +5 -1
  17. package/android/src/main/java/expo/modules/ui/TextView.kt +3 -1
  18. package/android/src/main/java/expo/modules/ui/Utils.kt +3 -1
  19. package/android/src/main/java/expo/modules/ui/colors/MaterialColors.kt +5 -1
  20. package/android/src/main/java/expo/modules/ui/convertibles/AnimationSpecParams.kt +3 -1
  21. package/android/src/main/java/expo/modules/ui/graphics/ImageLoader.kt +6 -2
  22. package/android/src/main/java/expo/modules/ui/icon/IconView.kt +5 -1
  23. package/android/src/main/java/expo/modules/ui/state/ObservableState.kt +3 -1
  24. package/android/src/main/java/expo/modules/ui/textfield/BasicTextField.kt +10 -2
  25. package/android/src/main/java/expo/modules/ui/textfield/TextField.kt +20 -4
  26. package/android/src/main/java/expo/modules/ui/textfield/TextFieldShared.kt +3 -1
  27. package/build/jetpack-compose/LazyColumn/index.d.ts +2 -1
  28. package/build/jetpack-compose/LazyColumn/index.js +1 -0
  29. package/build/jetpack-compose/LazyColumn/index.js.map +1 -1
  30. package/build/jetpack-compose/LazyItems/index.d.ts +19 -18
  31. package/build/jetpack-compose/LazyItems/index.js +1 -2
  32. package/build/jetpack-compose/LazyItems/index.js.map +1 -1
  33. package/build/jetpack-compose/LazyRow/index.d.ts +2 -1
  34. package/build/jetpack-compose/LazyRow/index.js +1 -0
  35. package/build/jetpack-compose/LazyRow/index.js.map +1 -1
  36. package/build/jetpack-compose/index.d.ts +0 -1
  37. package/build/jetpack-compose/index.js.map +1 -1
  38. package/build/jetpack-compose/modifiers/index.d.ts +33 -6
  39. package/build/jetpack-compose/modifiers/index.js +15 -2
  40. package/build/jetpack-compose/modifiers/index.js.map +1 -1
  41. package/build/swift-ui/LazyHStack/index.d.ts +45 -0
  42. package/build/swift-ui/LazyHStack/index.js +9 -0
  43. package/build/swift-ui/LazyHStack/index.js.map +1 -1
  44. package/build/swift-ui/LazyStackForEach/index.d.ts +44 -0
  45. package/build/swift-ui/LazyStackForEach/index.js +54 -0
  46. package/build/swift-ui/LazyStackForEach/index.js.map +1 -0
  47. package/build/swift-ui/LazyVStack/index.d.ts +45 -0
  48. package/build/swift-ui/LazyVStack/index.js +9 -0
  49. package/build/swift-ui/LazyVStack/index.js.map +1 -1
  50. package/build/swift-ui/List/DataListForEach.d.ts +6 -7
  51. package/build/swift-ui/List/DataListForEach.js.map +1 -1
  52. package/build/swift-ui/List/ListForEach.d.ts +7 -1
  53. package/build/swift-ui/List/ListForEach.js +1 -5
  54. package/build/swift-ui/List/ListForEach.js.map +1 -1
  55. package/build/swift-ui/index.d.ts +1 -0
  56. package/build/swift-ui/index.js.map +1 -1
  57. package/build/swift-ui/modifiers/index.d.ts +5 -1
  58. package/build/swift-ui/modifiers/index.js.map +1 -1
  59. package/build/universal/State.android.d.ts +1 -3
  60. package/build/universal/State.d.ts +2 -3
  61. package/build/universal/State.ios.d.ts +1 -3
  62. package/build/universal/State.js +10 -4
  63. package/build/universal/State.js.map +1 -1
  64. package/build/universal/Switch/index.android.js +5 -1
  65. package/build/universal/Switch/index.android.js.map +1 -1
  66. package/build/universal/types.d.ts +24 -0
  67. package/build/universal/types.js +8 -2
  68. package/build/universal/types.js.map +1 -1
  69. package/expo-module.config.json +0 -1
  70. package/ios/DataListForEachView.swift +65 -28
  71. package/ios/LazyHStackView.swift +3 -0
  72. package/ios/LazyVStackView.swift +3 -0
  73. package/ios/ListView.swift +8 -0
  74. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.7/expo.modules.ui-58.0.7-sources.jar → 58.0.9/expo.modules.ui-58.0.9-sources.jar} +0 -0
  75. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.9/expo.modules.ui-58.0.9-sources.jar.md5 +1 -0
  76. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.9/expo.modules.ui-58.0.9-sources.jar.sha1 +1 -0
  77. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.9/expo.modules.ui-58.0.9-sources.jar.sha256 +1 -0
  78. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.9/expo.modules.ui-58.0.9-sources.jar.sha512 +1 -0
  79. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.9/expo.modules.ui-58.0.9.aar +0 -0
  80. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.9/expo.modules.ui-58.0.9.aar.md5 +1 -0
  81. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.9/expo.modules.ui-58.0.9.aar.sha1 +1 -0
  82. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.9/expo.modules.ui-58.0.9.aar.sha256 +1 -0
  83. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.9/expo.modules.ui-58.0.9.aar.sha512 +1 -0
  84. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.7/expo.modules.ui-58.0.7.module → 58.0.9/expo.modules.ui-58.0.9.module} +23 -23
  85. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.9/expo.modules.ui-58.0.9.module.md5 +1 -0
  86. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.9/expo.modules.ui-58.0.9.module.sha1 +1 -0
  87. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.9/expo.modules.ui-58.0.9.module.sha256 +1 -0
  88. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.9/expo.modules.ui-58.0.9.module.sha512 +1 -0
  89. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{58.0.7/expo.modules.ui-58.0.7.pom → 58.0.9/expo.modules.ui-58.0.9.pom} +2 -2
  90. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.9/expo.modules.ui-58.0.9.pom.md5 +1 -0
  91. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.9/expo.modules.ui-58.0.9.pom.sha1 +1 -0
  92. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.9/expo.modules.ui-58.0.9.pom.sha256 +1 -0
  93. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.9/expo.modules.ui-58.0.9.pom.sha512 +1 -0
  94. package/package.json +3 -3
  95. package/prebuilds/output/debug/xcframeworks/ExpoUI.tar.gz +0 -0
  96. package/prebuilds/output/release/xcframeworks/ExpoUI.tar.gz +0 -0
  97. package/src/jetpack-compose/LazyColumn/index.tsx +2 -0
  98. package/src/jetpack-compose/LazyItems/index.tsx +18 -21
  99. package/src/jetpack-compose/LazyRow/index.tsx +2 -0
  100. package/src/jetpack-compose/index.ts +0 -1
  101. package/src/jetpack-compose/modifiers/index.ts +32 -4
  102. package/src/swift-ui/LazyHStack/index.tsx +45 -0
  103. package/src/swift-ui/LazyStackForEach/index.tsx +110 -0
  104. package/src/swift-ui/LazyVStack/index.tsx +45 -0
  105. package/src/swift-ui/List/DataListForEach.tsx +7 -8
  106. package/src/swift-ui/List/ListForEach.tsx +10 -3
  107. package/src/swift-ui/index.tsx +1 -0
  108. package/src/swift-ui/modifiers/index.ts +5 -1
  109. package/src/universal/State.android.ts +1 -1
  110. package/src/universal/State.ios.ts +1 -1
  111. package/src/universal/State.ts +12 -4
  112. package/src/universal/Switch/index.android.tsx +11 -2
  113. package/src/universal/types.ts +27 -0
  114. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.7/expo.modules.ui-58.0.7-sources.jar.md5 +0 -1
  115. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.7/expo.modules.ui-58.0.7-sources.jar.sha1 +0 -1
  116. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.7/expo.modules.ui-58.0.7-sources.jar.sha256 +0 -1
  117. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.7/expo.modules.ui-58.0.7-sources.jar.sha512 +0 -1
  118. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.7/expo.modules.ui-58.0.7.aar +0 -0
  119. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.7/expo.modules.ui-58.0.7.aar.md5 +0 -1
  120. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.7/expo.modules.ui-58.0.7.aar.sha1 +0 -1
  121. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.7/expo.modules.ui-58.0.7.aar.sha256 +0 -1
  122. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.7/expo.modules.ui-58.0.7.aar.sha512 +0 -1
  123. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.7/expo.modules.ui-58.0.7.module.md5 +0 -1
  124. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.7/expo.modules.ui-58.0.7.module.sha1 +0 -1
  125. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.7/expo.modules.ui-58.0.7.module.sha256 +0 -1
  126. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.7/expo.modules.ui-58.0.7.module.sha512 +0 -1
  127. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.7/expo.modules.ui-58.0.7.pom.md5 +0 -1
  128. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.7/expo.modules.ui-58.0.7.pom.sha1 +0 -1
  129. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.7/expo.modules.ui-58.0.7.pom.sha256 +0 -1
  130. package/local-maven-repo/expo/modules/ui/expo.modules.ui/58.0.7/expo.modules.ui-58.0.7.pom.sha512 +0 -1
  131. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml +0 -13
  132. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.md5 +0 -1
  133. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha1 +0 -1
  134. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha256 +0 -1
  135. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha512 +0 -1
package/CHANGELOG.md CHANGED
@@ -1,14 +1,21 @@
1
1
  # Changelog
2
2
 
3
- ## Unpublished
3
+ ## 58.0.9
4
4
 
5
- ### 🛠 Breaking changes
5
+ ### Patch Changes
6
6
 
7
- ### 🎉 New features
7
+ - Force-bump all packages, due to migration to changesets. ([#50762](https://github.com/expo/expo/pull/50762) by [@kitten](https://github.com/kitten))
8
+ - [iOS] Added `LazyVStack.ForEach` and `LazyHStack.ForEach`, which render rows from `data` and `keyExtractor` with a `children` function: `{({ item, index }) => <Row item={item} />}`. Rows are recycled from a small pool around the visible range, so large stacks only render the rows near the viewport. Set `recycling={false}` to render every row. ([#50579](https://github.com/expo/expo/pull/50579) by [@intergalacticspacehighway](https://github.com/intergalacticspacehighway))
9
+ - [android] Fix `Switch` label rendering one letter per line inside a `Host` with `matchContents`. ([#50693](https://github.com/expo/expo/pull/50693) by [@janicduplessis](https://github.com/janicduplessis))
10
+ - [android] Added `IntrinsicSize` support to the `width` modifier. ([#50693](https://github.com/expo/expo/pull/50693) by [@janicduplessis](https://github.com/janicduplessis))
8
11
 
9
- ### 🐛 Bug fixes
12
+ ## 58.0.8 — 2026-09-28
10
13
 
11
- ### 💡 Others
14
+ ### 🎉 New features
15
+
16
+ - [iOS] Export the `FrameAlignment` type for the `alignment` parameter of `frame()`. ([#50702](https://github.com/expo/expo/pull/50702) by [@amandeepmittal](https://github.com/amandeepmittal))
17
+ - [Android] Add `contentDescription` to the `semantics` modifier, so TalkBack can announce a label other than the visible content. ([#50688](https://github.com/expo/expo/pull/50688) by [@enavermate](https://github.com/enavermate))
18
+ - Added `get()` and `set()` to the universal `ObservableState` type and to the web implementation of `useNativeState`, as React Compiler-compliant alternatives to `.value`. ([#50684](https://github.com/expo/expo/pull/50684) by [@Den1Marshall](https://github.com/Den1Marshall))
12
19
 
13
20
  ## 58.0.7 — 2026-09-25
14
21
 
@@ -12,13 +12,13 @@ apply plugin: 'expo-module-gradle-plugin'
12
12
  apply plugin: 'org.jetbrains.kotlin.plugin.compose'
13
13
 
14
14
  group = 'expo.modules.ui'
15
- version = '58.0.7'
15
+ version = '58.0.9'
16
16
 
17
17
  android {
18
18
  namespace "expo.modules.ui"
19
19
  defaultConfig {
20
20
  versionCode 1
21
- versionName "58.0.7"
21
+ versionName "58.0.9"
22
22
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
23
23
  }
24
24
  buildFeatures {
@@ -73,32 +73,64 @@ data class ExitTransitionRecord(
73
73
  // TODO(@ubax): expose animationSpec parameter (tween, spring, duration) for all transitions
74
74
  private fun EnterTransitionRecord.toComposeTransition(): EnterTransition = when (type) {
75
75
  EnterTransitionType.FADE_IN ->
76
- if (initialAlpha != null) fadeIn(initialAlpha = initialAlpha) else fadeIn()
76
+ if (initialAlpha != null) {
77
+ fadeIn(initialAlpha = initialAlpha)
78
+ } else {
79
+ fadeIn()
80
+ }
77
81
  EnterTransitionType.SLIDE_IN_HORIZONTALLY ->
78
- if (initialOffsetX != null) slideInHorizontally { (it * initialOffsetX).toInt() } else slideInHorizontally()
82
+ if (initialOffsetX != null) {
83
+ slideInHorizontally { (it * initialOffsetX).toInt() }
84
+ } else {
85
+ slideInHorizontally()
86
+ }
79
87
  EnterTransitionType.SLIDE_IN_VERTICALLY ->
80
- if (initialOffsetY != null) slideInVertically { (it * initialOffsetY).toInt() } else slideInVertically()
88
+ if (initialOffsetY != null) {
89
+ slideInVertically { (it * initialOffsetY).toInt() }
90
+ } else {
91
+ slideInVertically()
92
+ }
81
93
  // TODO(@ubax): expose expandFrom (Alignment) and initialSize parameters for expand transitions
82
94
  EnterTransitionType.EXPAND_IN -> expandIn()
83
95
  EnterTransitionType.EXPAND_HORIZONTALLY -> expandHorizontally()
84
96
  EnterTransitionType.EXPAND_VERTICALLY -> expandVertically()
85
97
  EnterTransitionType.SCALE_IN ->
86
- if (initialScale != null) scaleIn(initialScale = initialScale) else scaleIn()
98
+ if (initialScale != null) {
99
+ scaleIn(initialScale = initialScale)
100
+ } else {
101
+ scaleIn()
102
+ }
87
103
  }
88
104
 
89
105
  private fun ExitTransitionRecord.toComposeTransition(): ExitTransition = when (type) {
90
106
  ExitTransitionType.FADE_OUT ->
91
- if (targetAlpha != null) fadeOut(targetAlpha = targetAlpha) else fadeOut()
107
+ if (targetAlpha != null) {
108
+ fadeOut(targetAlpha = targetAlpha)
109
+ } else {
110
+ fadeOut()
111
+ }
92
112
  ExitTransitionType.SLIDE_OUT_HORIZONTALLY ->
93
- if (targetOffsetX != null) slideOutHorizontally { (it * targetOffsetX).toInt() } else slideOutHorizontally()
113
+ if (targetOffsetX != null) {
114
+ slideOutHorizontally { (it * targetOffsetX).toInt() }
115
+ } else {
116
+ slideOutHorizontally()
117
+ }
94
118
  ExitTransitionType.SLIDE_OUT_VERTICALLY ->
95
- if (targetOffsetY != null) slideOutVertically { (it * targetOffsetY).toInt() } else slideOutVertically()
119
+ if (targetOffsetY != null) {
120
+ slideOutVertically { (it * targetOffsetY).toInt() }
121
+ } else {
122
+ slideOutVertically()
123
+ }
96
124
  // TODO(@ubax): expose shrinkTowards (Alignment) and targetSize parameters for shrink transitions
97
125
  ExitTransitionType.SHRINK_OUT -> shrinkOut()
98
126
  ExitTransitionType.SHRINK_HORIZONTALLY -> shrinkHorizontally()
99
127
  ExitTransitionType.SHRINK_VERTICALLY -> shrinkVertically()
100
128
  ExitTransitionType.SCALE_OUT ->
101
- if (targetScale != null) scaleOut(targetScale = targetScale) else scaleOut()
129
+ if (targetScale != null) {
130
+ scaleOut(targetScale = targetScale)
131
+ } else {
132
+ scaleOut()
133
+ }
102
134
  }
103
135
 
104
136
  private fun List<EnterTransitionRecord>.toComposedEnterTransition(): EnterTransition? =
@@ -65,7 +65,13 @@ internal fun FunctionalComposableScope.RowContent(props: LayoutProps) {
65
65
  verticalAlignment = props.verticalAlignment?.toComposeAlignment() ?: Alignment.Top,
66
66
  modifier = ModifierRegistry
67
67
  .applyModifiers(props.modifiers, appContext, composableScope, globalEventDispatcher)
68
- .then(if (scrollBehavior != null) Modifier.nestedScroll(scrollBehavior) else Modifier)
68
+ .then(
69
+ if (scrollBehavior != null) {
70
+ Modifier.nestedScroll(scrollBehavior)
71
+ } else {
72
+ Modifier
73
+ }
74
+ )
69
75
  ) {
70
76
  Children(UIComposableScope(rowScope = this@Row, nestedScrollConnection = scrollBehavior))
71
77
  }
@@ -95,7 +101,13 @@ internal fun FunctionalComposableScope.ColumnContent(props: LayoutProps) {
95
101
  horizontalAlignment = props.horizontalAlignment?.toComposeAlignment() ?: Alignment.Start,
96
102
  modifier = ModifierRegistry
97
103
  .applyModifiers(props.modifiers, appContext, composableScope, globalEventDispatcher)
98
- .then(if (scrollBehavior != null) Modifier.nestedScroll(scrollBehavior) else Modifier)
104
+ .then(
105
+ if (scrollBehavior != null) {
106
+ Modifier.nestedScroll(scrollBehavior)
107
+ } else {
108
+ Modifier
109
+ }
110
+ )
99
111
  ) {
100
112
  Children(UIComposableScope(columnScope = this@Column, nestedScrollConnection = scrollBehavior))
101
113
  }
@@ -112,7 +124,13 @@ fun FunctionalComposableScope.BoxContent(props: LayoutProps) {
112
124
  contentAlignment = props.contentAlignment?.toComposeAlignment() ?: Alignment.TopStart,
113
125
  modifier = ModifierRegistry
114
126
  .applyModifiers(props.modifiers, appContext, composableScope, globalEventDispatcher)
115
- .then(if (scrollBehavior != null) Modifier.nestedScroll(scrollBehavior) else Modifier)
127
+ .then(
128
+ if (scrollBehavior != null) {
129
+ Modifier.nestedScroll(scrollBehavior)
130
+ } else {
131
+ Modifier
132
+ }
133
+ )
116
134
  ) {
117
135
  Children(UIComposableScope(boxScope = this@Box, nestedScrollConnection = scrollBehavior))
118
136
  }
@@ -219,14 +219,22 @@ fun rememberSelectableDates(selectableDatesRecord: SelectableDatesRecord?): Sele
219
219
 
220
220
  object : SelectableDates {
221
221
  override fun isSelectableDate(utcTimeMillis: Long): Boolean {
222
- if (startUtcDayMillis != null && utcTimeMillis < startUtcDayMillis) return false
223
- if (endUtcDayMillis != null && utcTimeMillis > endUtcDayMillis) return false
222
+ if (startUtcDayMillis != null && utcTimeMillis < startUtcDayMillis) {
223
+ return false
224
+ }
225
+ if (endUtcDayMillis != null && utcTimeMillis > endUtcDayMillis) {
226
+ return false
227
+ }
224
228
  return true
225
229
  }
226
230
 
227
231
  override fun isSelectableYear(year: Int): Boolean {
228
- if (startYear != null && year < startYear) return false
229
- if (endYear != null && year > endYear) return false
232
+ if (startYear != null && year < startYear) {
233
+ return false
234
+ }
235
+ if (endYear != null && year > endYear) {
236
+ return false
237
+ }
230
238
  return true
231
239
  }
232
240
  }
@@ -167,7 +167,11 @@ class ExpoUIModule : Module() {
167
167
  ?: appContext.reactContext
168
168
  ?: throw Exceptions.ReactContextLost()
169
169
  val resolvedScheme = options?.scheme
170
- ?: if (context.isSystemInDarkTheme()) ExpoColorScheme.DARK else ExpoColorScheme.LIGHT
170
+ ?: if (context.isSystemInDarkTheme()) {
171
+ ExpoColorScheme.DARK
172
+ } else {
173
+ ExpoColorScheme.LIGHT
174
+ }
171
175
  val isDark = resolvedScheme == ExpoColorScheme.DARK
172
176
  val seedArgb = options?.seedColor?.composeOrNull?.toArgb()
173
177
  val colorScheme = if (seedArgb != null) {
@@ -125,7 +125,9 @@ fun FunctionalComposableScope.HorizontalPagerContent(
125
125
  }
126
126
 
127
127
  val pageCount = pageCountState.intValue
128
- if (pageCount == 0) return
128
+ if (pageCount == 0) {
129
+ return
130
+ }
129
131
 
130
132
  // Mirror Compose's PagerState observable fields to JS callbacks. Each
131
133
  // state-backed snapshotFlow drops its first emission so we don't echo the
@@ -81,17 +81,33 @@ internal enum class ExpoColorScheme(val value: String) : Enumerable {
81
81
 
82
82
  fun toColorScheme(context: Context): ColorScheme {
83
83
  return when (this) {
84
- LIGHT -> if (isDynamicColorSupported) dynamicLightColorScheme(context) else lightColorScheme()
85
- DARK -> if (isDynamicColorSupported) dynamicDarkColorScheme(context) else darkColorScheme()
84
+ LIGHT -> if (isDynamicColorSupported) {
85
+ dynamicLightColorScheme(context)
86
+ } else {
87
+ lightColorScheme()
88
+ }
89
+ DARK -> if (isDynamicColorSupported) {
90
+ dynamicDarkColorScheme(context)
91
+ } else {
92
+ darkColorScheme()
93
+ }
86
94
  }
87
95
  }
88
96
 
89
97
  companion object {
90
98
  fun defaultColorScheme(context: Context, isSystemInDarkTheme: Boolean): ColorScheme {
91
99
  return if (isDynamicColorSupported) {
92
- if (isSystemInDarkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
100
+ if (isSystemInDarkTheme) {
101
+ dynamicDarkColorScheme(context)
102
+ } else {
103
+ dynamicLightColorScheme(context)
104
+ }
93
105
  } else {
94
- if (isSystemInDarkTheme) darkColorScheme() else lightColorScheme()
106
+ if (isSystemInDarkTheme) {
107
+ darkColorScheme()
108
+ } else {
109
+ lightColorScheme()
110
+ }
95
111
  }
96
112
  }
97
113
  }
@@ -159,8 +175,20 @@ internal class HostView(context: Context, appContext: AppContext) :
159
175
 
160
176
  Layout(
161
177
  modifier = Modifier
162
- .then(if (props.matchContentsHorizontal.value == true) Modifier.wrapContentWidth() else Modifier)
163
- .then(if (props.matchContentsVertical.value == true) Modifier.wrapContentHeight() else Modifier)
178
+ .then(
179
+ if (props.matchContentsHorizontal.value == true) {
180
+ Modifier.wrapContentWidth()
181
+ } else {
182
+ Modifier
183
+ }
184
+ )
185
+ .then(
186
+ if (props.matchContentsVertical.value == true) {
187
+ Modifier.wrapContentHeight()
188
+ } else {
189
+ Modifier
190
+ }
191
+ )
164
192
  .onSizeChanged { size -> dispatchOnLayoutContent(size, density) },
165
193
  content = content
166
194
  ) { measurables, constraints ->
@@ -199,8 +227,16 @@ internal class HostView(context: Context, appContext: AppContext) :
199
227
  val heightDp = contentHeightPx.toDp().value.toDouble()
200
228
 
201
229
  shadowNodeProxy.setViewSize(
202
- if (constraints.maxWidth == 0) widthDp else Double.NaN,
203
- if (constraints.maxHeight == 0) heightDp else Double.NaN
230
+ if (constraints.maxWidth == 0) {
231
+ widthDp
232
+ } else {
233
+ Double.NaN
234
+ },
235
+ if (constraints.maxHeight == 0) {
236
+ heightDp
237
+ } else {
238
+ Double.NaN
239
+ }
204
240
  )
205
241
  }
206
242
  }
@@ -227,8 +263,16 @@ internal class HostView(context: Context, appContext: AppContext) :
227
263
  val height = size.height.toDp().value
228
264
 
229
265
  if (matchContentsHorizontal == true || matchContentsVertical == true) {
230
- val styleWidth = if (matchContentsHorizontal == true && width > 0) width else null
231
- val styleHeight = if (matchContentsVertical == true && height > 0) height else null
266
+ val styleWidth = if (matchContentsHorizontal == true && width > 0) {
267
+ width
268
+ } else {
269
+ null
270
+ }
271
+ val styleHeight = if (matchContentsVertical == true && height > 0) {
272
+ height
273
+ } else {
274
+ null
275
+ }
232
276
  shadowNodeProxy.setStyleSize(styleWidth?.toDouble(), styleHeight?.toDouble())
233
277
  }
234
278
 
@@ -263,8 +307,16 @@ internal class HostView(context: Context, appContext: AppContext) :
263
307
  val matchContentsVertical = props.matchContentsVertical.value
264
308
  val composeView = findComposeView()
265
309
  composeView.layoutParams = LayoutParams(
266
- if (matchContentsHorizontal == true) LayoutParams.WRAP_CONTENT else LayoutParams.MATCH_PARENT,
267
- if (matchContentsVertical == true) LayoutParams.WRAP_CONTENT else LayoutParams.MATCH_PARENT
310
+ if (matchContentsHorizontal == true) {
311
+ LayoutParams.WRAP_CONTENT
312
+ } else {
313
+ LayoutParams.MATCH_PARENT
314
+ },
315
+ if (matchContentsVertical == true) {
316
+ LayoutParams.WRAP_CONTENT
317
+ } else {
318
+ LayoutParams.MATCH_PARENT
319
+ }
268
320
  )
269
321
  }
270
322
 
@@ -176,7 +176,15 @@ internal fun LazyListScope.lazyRecycledItems(
176
176
  Box(
177
177
  modifier = Modifier.onSizeChanged { size ->
178
178
  if (content != null) {
179
- window.measure(itemKey, if (isVertical) size.height else size.width, revision)
179
+ window.measure(
180
+ itemKey,
181
+ if (isVertical) {
182
+ size.height
183
+ } else {
184
+ size.width
185
+ },
186
+ revision
187
+ )
180
188
  }
181
189
  }
182
190
  ) {
@@ -205,7 +213,11 @@ internal fun LazyListScope.lazyRecycledItems(
205
213
  */
206
214
  internal fun Modifier.lazyRecycledItemsCrossAxis(list: ViewGroup, isVertical: Boolean): Modifier =
207
215
  layout { measurable, constraints ->
208
- val crossAxisSize = if (isVertical) constraints.maxWidth else constraints.maxHeight
216
+ val crossAxisSize = if (isVertical) {
217
+ constraints.maxWidth
218
+ } else {
219
+ constraints.maxHeight
220
+ }
209
221
  for (index in 0..<list.childCount) {
210
222
  (list.getChildAt(index) as? LazyItemsView)?.window?.updateCrossAxisSize(crossAxisSize)
211
223
  }
@@ -145,7 +145,11 @@ fun FunctionalComposableScope.ModalBottomSheetContent(
145
145
  // then asked for light system bars, which turned the navigation bar white.
146
146
  val resolvedContentColor = props.contentColor.composeOrNull
147
147
  ?: MaterialTheme.colorScheme.contentColorFor(resolvedContainerColor).takeOrElse {
148
- if (resolvedContainerColor.luminance() > 0.5f) ComposeColor.Black else ComposeColor.White
148
+ if (resolvedContainerColor.luminance() > 0.5f) {
149
+ ComposeColor.Black
150
+ } else {
151
+ ComposeColor.White
152
+ }
149
153
  }
150
154
  val resolvedScrimColor = props.scrimColor.composeOrNull ?: BottomSheetDefaults.ScrimColor
151
155
  val dragHandleSlotView = findChildSlotView(view, "dragHandle")
@@ -21,6 +21,7 @@ import androidx.compose.foundation.border
21
21
  import androidx.compose.foundation.clickable
22
22
  import androidx.compose.foundation.combinedClickable
23
23
  import androidx.compose.foundation.horizontalScroll
24
+ import androidx.compose.foundation.layout.IntrinsicSize
24
25
  import androidx.compose.foundation.layout.defaultMinSize
25
26
  import androidx.compose.foundation.layout.fillMaxHeight
26
27
  import androidx.compose.foundation.layout.fillMaxSize
@@ -67,6 +68,7 @@ import androidx.compose.ui.layout.onVisibilityChanged
67
68
  import androidx.compose.ui.layout.positionInWindow
68
69
  import androidx.compose.ui.platform.LocalDensity
69
70
  import androidx.compose.ui.semantics.Role
71
+ import androidx.compose.ui.semantics.contentDescription
70
72
  import androidx.compose.ui.semantics.contentType
71
73
  import androidx.compose.ui.semantics.semantics
72
74
  import androidx.compose.ui.unit.DpOffset
@@ -78,6 +80,7 @@ import expo.modules.kotlin.records.Field
78
80
  import expo.modules.kotlin.records.Record
79
81
  import expo.modules.kotlin.records.recordFromMap
80
82
  import expo.modules.kotlin.types.ConverterContext
83
+ import expo.modules.kotlin.types.Either
81
84
  import expo.modules.kotlin.types.Enumerable
82
85
  import expo.modules.kotlin.types.OptimizedRecord
83
86
  import expo.modules.kotlin.views.ComposableScope
@@ -132,6 +135,21 @@ data class WidthParams(
132
135
  @Field val width: Int = 0
133
136
  ) : Record
134
137
 
138
+ internal enum class IntrinsicSizeType(val value: String) : Enumerable {
139
+ MIN("min"),
140
+ MAX("max");
141
+
142
+ fun toComposeIntrinsicSize(): IntrinsicSize = when (this) {
143
+ MIN -> IntrinsicSize.Min
144
+ MAX -> IntrinsicSize.Max
145
+ }
146
+ }
147
+
148
+ @OptimizedRecord
149
+ internal data class ComposeWidthParams(
150
+ @Field val width: Either<Int, IntrinsicSizeType>? = null
151
+ ) : Record
152
+
135
153
  @OptimizedRecord
136
154
  data class HeightParams(
137
155
  @Field val height: Int = 0
@@ -167,7 +185,9 @@ data class BackgroundParams(
167
185
  // Color animation specs reuse the JS `$type` shape from `@expo/ui/jetpack-compose/modifiers/animation` (spring / tween / snap).
168
186
  // Keyframes are float-only and aren't supported for colors.
169
187
  private fun parseColorAnimationSpec(raw: Any?): AnimationSpec<androidx.compose.ui.graphics.Color>? {
170
- if (raw !is Map<*, *>) return null
188
+ if (raw !is Map<*, *>) {
189
+ return null
190
+ }
171
191
  return when (raw["\$type"]) {
172
192
  "spring" -> spring(
173
193
  dampingRatio = (raw["dampingRatio"] as? Number)?.toFloat() ?: Spring.DampingRatioNoBouncy,
@@ -408,7 +428,9 @@ object ModifierRegistry {
408
428
  scope: ComposableScope,
409
429
  eventDispatcher: ModifierEventDispatcher
410
430
  ): Modifier {
411
- if (modifiers.isNullOrEmpty()) return Modifier
431
+ if (modifiers.isNullOrEmpty()) {
432
+ return Modifier
433
+ }
412
434
  return modifiers.fold(Modifier as Modifier) { acc, config ->
413
435
  val type = config["\$type"]?.asString() ?: return@fold acc
414
436
  val modifier = modifierFactories[type]?.invoke(config, scope, appContext, eventDispatcher)
@@ -470,8 +492,12 @@ object ModifierRegistry {
470
492
  }
471
493
 
472
494
  register("width") { map, _, appContext, _ ->
473
- val params = recordFromMap<WidthParams>(map, appContext)
474
- Modifier.width(params.width.dp)
495
+ val width = recordFromMap<ComposeWidthParams>(map, appContext).width
496
+ if (width?.`is`(IntrinsicSizeType::class) == true) {
497
+ Modifier.width(width.second().toComposeIntrinsicSize())
498
+ } else {
499
+ Modifier.width((width?.first() ?: 0).dp)
500
+ }
475
501
  }
476
502
 
477
503
  register("height") { map, _, appContext, _ ->
@@ -681,9 +707,16 @@ object ModifierRegistry {
681
707
 
682
708
  register("semantics") { map, _, appContext, _ ->
683
709
  val params = recordFromMap<SemanticsParams>(map, appContext)
684
- params.contentType.toContentType()?.let { ct ->
685
- Modifier.semantics { contentType = ct }
686
- } ?: Modifier
710
+ val type = params.contentType.toContentType()
711
+ val description = params.contentDescription
712
+ if (type == null && description == null) {
713
+ Modifier
714
+ } else {
715
+ Modifier.semantics {
716
+ type?.let { contentType = it }
717
+ description?.let { contentDescription = it }
718
+ }
719
+ }
687
720
  }
688
721
 
689
722
  register("clip") { map, _, appContext, _ ->
@@ -498,7 +498,9 @@ private class TouchDispatchingRootViewGroup(
498
498
  // Use the (…, type, consumed) variant so we can read how much the sheet ate (consumed[1]).
499
499
  val consumed = IntArray(2)
500
500
  dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, null, ViewCompat.TYPE_TOUCH, consumed)
501
- if (consumed[1] != 0) sheetMovingOnLastDragFrame = true
501
+ if (consumed[1] != 0) {
502
+ sheetMovingOnLastDragFrame = true
503
+ }
502
504
  }
503
505
 
504
506
  override fun onNestedPreFling(target: View, velocityX: Float, velocityY: Float): Boolean {
@@ -7,7 +7,8 @@ import expo.modules.kotlin.types.OptimizedRecord
7
7
 
8
8
  @OptimizedRecord
9
9
  internal data class SemanticsParams(
10
- @Field val contentType: String? = null
10
+ @Field val contentType: String? = null,
11
+ @Field val contentDescription: String? = null
11
12
  ) : Record
12
13
 
13
14
  internal fun String?.toContentType(): ContentType? = when (this) {
@@ -179,7 +179,9 @@ fun pathFromShapeRecord(record: ShapeRecord, size: Size, density: Density): Path
179
179
  }
180
180
 
181
181
  fun shapeFromShapeRecord(shapeRecord: ShapeRecord?): Shape? {
182
- if (shapeRecord == null) return null
182
+ if (shapeRecord == null) {
183
+ return null
184
+ }
183
185
  return object : Shape {
184
186
  override fun createOutline(size: Size, layoutDirection: LayoutDirection, density: Density): Outline {
185
187
  val path = pathFromShapeRecord(shapeRecord, size, density)
@@ -65,7 +65,9 @@ fun findChildSlotView(viewGroup: ViewGroup, slotName: String): SlotView? {
65
65
  inline fun <reified T> findChildOfType(viewGroup: ViewGroup): T? {
66
66
  for (index in 0..<viewGroup.size) {
67
67
  val child = viewGroup.getChildAt(index)
68
- if (child is T) return child
68
+ if (child is T) {
69
+ return child
70
+ }
69
71
  }
70
72
  return null
71
73
  }
@@ -83,7 +83,11 @@ fun FunctionalComposableScope.SnackbarHostContent(
83
83
  "long" -> SnackbarDuration.Long
84
84
  "indefinite" -> SnackbarDuration.Indefinite
85
85
  // M3 default: indefinite when there's an action label, else short.
86
- else -> if (options.actionLabel == null) SnackbarDuration.Short else SnackbarDuration.Indefinite
86
+ else -> if (options.actionLabel == null) {
87
+ SnackbarDuration.Short
88
+ } else {
89
+ SnackbarDuration.Indefinite
90
+ }
87
91
  }
88
92
  val result = try {
89
93
  withContext(scope.coroutineContext) {
@@ -134,7 +134,9 @@ enum class TextLineBreakType(val value: String) : Enumerable {
134
134
  }
135
135
 
136
136
  fun resolveFontFamily(name: String?, context: Context): FontFamily? {
137
- if (name == null) return null
137
+ if (name == null) {
138
+ return null
139
+ }
138
140
  return when (name) {
139
141
  "default" -> FontFamily.Default
140
142
  "sansSerif" -> FontFamily.SansSerif
@@ -32,7 +32,9 @@ val Color?.composeOrNull: androidx.compose.ui.graphics.Color?
32
32
  * Gets the ImageVector for a given icon name using reflection.
33
33
  */
34
34
  fun getImageVector(icon: String?): ImageVector? {
35
- if (icon.isNullOrEmpty()) return null
35
+ if (icon.isNullOrEmpty()) {
36
+ return null
37
+ }
36
38
  return try {
37
39
  val (theme, name) = icon.split(".")
38
40
  val clazz = Class.forName("androidx.compose.material.icons.$theme.${name}Kt")
@@ -38,7 +38,11 @@ internal fun Context.isSystemInDarkTheme(): Boolean {
38
38
  * Allows `expo-widgets` to back `getMaterialColors` inside the widgets JS runtime.
39
39
  */
40
40
  fun getMaterialColorTokens(context: Context, isDark: Boolean): Map<String, String> {
41
- val scheme = if (isDark) ExpoColorScheme.DARK else ExpoColorScheme.LIGHT
41
+ val scheme = if (isDark) {
42
+ ExpoColorScheme.DARK
43
+ } else {
44
+ ExpoColorScheme.LIGHT
45
+ }
42
46
  return scheme.toColorScheme(context).toTokenMap()
43
47
  }
44
48
 
@@ -87,7 +87,9 @@ internal data class KeyframesSpecParams(
87
87
 
88
88
  @Suppress("UNCHECKED_CAST")
89
89
  internal fun parseAnimationSpec(raw: Any?, converterContext: ConverterContext): AnimationSpec<Float>? {
90
- if (raw !is Map<*, *>) return null
90
+ if (raw !is Map<*, *>) {
91
+ return null
92
+ }
91
93
  val map = raw as Map<String, Any?>
92
94
  return when (raw["\$type"]) {
93
95
  "spring" -> recordFromMap<SpringSpecParams>(map, converterContext).toAnimationSpec()
@@ -199,7 +199,9 @@ class ImageLoader(
199
199
  * Detect if byte array contains XML content.
200
200
  */
201
201
  private fun isXmlContent(bytes: ByteArray): Boolean {
202
- if (bytes.size < 5) return false
202
+ if (bytes.size < 5) {
203
+ return false
204
+ }
203
205
 
204
206
  // Check for UTF-8 BOM
205
207
  var offset = 0
@@ -211,7 +213,9 @@ class ImageLoader(
211
213
  // Check if content starts with '<' (possibly with leading whitespace)
212
214
  for (i in offset until minOf(offset + 10, bytes.size)) {
213
215
  val b = bytes[i]
214
- if (b == '<'.code.toByte()) return true
216
+ if (b == '<'.code.toByte()) {
217
+ return true
218
+ }
215
219
  if (b != ' '.code.toByte() && b != '\t'.code.toByte() &&
216
220
  b != '\n'.code.toByte() && b != '\r'.code.toByte()
217
221
  ) {
@@ -83,7 +83,11 @@ class IconView(context: Context, appContext: AppContext) :
83
83
  // Render icon if painter available
84
84
  if (painter != null) {
85
85
  val resolvedTint = tint?.compose
86
- ?: if (inheritTint) LocalContentColor.current else androidx.compose.ui.graphics.Color.Unspecified
86
+ ?: if (inheritTint) {
87
+ LocalContentColor.current
88
+ } else {
89
+ androidx.compose.ui.graphics.Color.Unspecified
90
+ }
87
91
  Icon(
88
92
  painter = painter,
89
93
  contentDescription = contentDescription,
@@ -19,7 +19,9 @@ class ObservableState(initialValue: Any? = null) : SharedObject() {
19
19
  set(v) {
20
20
  _state.value = v
21
21
  // Skip re-invoking onChange if state.value was written from inside onChange.
22
- if (isNotifying) return
22
+ if (isNotifying) {
23
+ return
24
+ }
23
25
  isNotifying = true
24
26
  try {
25
27
  onChange?.invoke(v)