@expo/ui 55.0.5 → 55.0.6

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 (92) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/android/build.gradle +2 -2
  3. package/android/src/main/java/expo/modules/ui/AlertDialogView.kt +56 -28
  4. package/android/src/main/java/expo/modules/ui/BasicAlertDialogView.kt +9 -1
  5. package/android/src/main/java/expo/modules/ui/DividerView.kt +21 -2
  6. package/android/src/main/java/expo/modules/ui/ExpoUIModule.kt +15 -15
  7. package/android/src/main/java/expo/modules/ui/ModifierRegistry.kt +6 -0
  8. package/android/src/main/java/expo/modules/ui/PullToRefreshBoxView.kt +20 -3
  9. package/android/src/main/java/expo/modules/ui/SlotView.kt +8 -0
  10. package/android/src/main/java/expo/modules/ui/SurfaceView.kt +88 -11
  11. package/android/src/main/java/expo/modules/ui/TextInputView.kt +15 -3
  12. package/android/src/main/java/expo/modules/ui/TextView.kt +145 -12
  13. package/build/jetpack-compose/AlertDialog/index.d.ts +72 -36
  14. package/build/jetpack-compose/AlertDialog/index.d.ts.map +1 -1
  15. package/build/jetpack-compose/BasicAlertDialog/index.d.ts +7 -2
  16. package/build/jetpack-compose/BasicAlertDialog/index.d.ts.map +1 -1
  17. package/build/jetpack-compose/Card/index.d.ts.map +1 -1
  18. package/build/jetpack-compose/Divider/index.d.ts +20 -5
  19. package/build/jetpack-compose/Divider/index.d.ts.map +1 -1
  20. package/build/jetpack-compose/Progress/index.d.ts.map +1 -1
  21. package/build/jetpack-compose/PullToRefreshBox/index.d.ts +34 -9
  22. package/build/jetpack-compose/PullToRefreshBox/index.d.ts.map +1 -1
  23. package/build/jetpack-compose/Surface/index.d.ts +52 -2
  24. package/build/jetpack-compose/Surface/index.d.ts.map +1 -1
  25. package/build/jetpack-compose/Text/index.d.ts +77 -89
  26. package/build/jetpack-compose/Text/index.d.ts.map +1 -1
  27. package/build/jetpack-compose/TextInput/index.d.ts +18 -3
  28. package/build/jetpack-compose/TextInput/index.d.ts.map +1 -1
  29. package/build/jetpack-compose/index.d.ts +2 -2
  30. package/build/jetpack-compose/index.d.ts.map +1 -1
  31. package/build/jetpack-compose/modifiers/index.d.ts +5 -0
  32. package/build/jetpack-compose/modifiers/index.d.ts.map +1 -1
  33. package/build/swift-ui/modifiers/index.d.ts +1 -1
  34. package/build/types.d.ts +26 -0
  35. package/build/types.d.ts.map +1 -1
  36. package/expo-module.config.json +1 -1
  37. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{55.0.5/expo.modules.ui-55.0.5-sources.jar → 55.0.6/expo.modules.ui-55.0.6-sources.jar} +0 -0
  38. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.6/expo.modules.ui-55.0.6-sources.jar.md5 +1 -0
  39. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.6/expo.modules.ui-55.0.6-sources.jar.sha1 +1 -0
  40. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.6/expo.modules.ui-55.0.6-sources.jar.sha256 +1 -0
  41. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.6/expo.modules.ui-55.0.6-sources.jar.sha512 +1 -0
  42. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.6/expo.modules.ui-55.0.6.aar +0 -0
  43. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.6/expo.modules.ui-55.0.6.aar.md5 +1 -0
  44. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.6/expo.modules.ui-55.0.6.aar.sha1 +1 -0
  45. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.6/expo.modules.ui-55.0.6.aar.sha256 +1 -0
  46. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.6/expo.modules.ui-55.0.6.aar.sha512 +1 -0
  47. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{55.0.5/expo.modules.ui-55.0.5.module → 55.0.6/expo.modules.ui-55.0.6.module} +22 -22
  48. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.6/expo.modules.ui-55.0.6.module.md5 +1 -0
  49. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.6/expo.modules.ui-55.0.6.module.sha1 +1 -0
  50. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.6/expo.modules.ui-55.0.6.module.sha256 +1 -0
  51. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.6/expo.modules.ui-55.0.6.module.sha512 +1 -0
  52. package/local-maven-repo/expo/modules/ui/expo.modules.ui/{55.0.5/expo.modules.ui-55.0.5.pom → 55.0.6/expo.modules.ui-55.0.6.pom} +1 -1
  53. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.6/expo.modules.ui-55.0.6.pom.md5 +1 -0
  54. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.6/expo.modules.ui-55.0.6.pom.sha1 +1 -0
  55. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.6/expo.modules.ui-55.0.6.pom.sha256 +1 -0
  56. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.6/expo.modules.ui-55.0.6.pom.sha512 +1 -0
  57. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml +4 -4
  58. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.md5 +1 -1
  59. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha1 +1 -1
  60. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha256 +1 -1
  61. package/local-maven-repo/expo/modules/ui/expo.modules.ui/maven-metadata.xml.sha512 +1 -1
  62. package/package.json +2 -2
  63. package/src/jetpack-compose/AlertDialog/index.tsx +94 -41
  64. package/src/jetpack-compose/BasicAlertDialog/index.tsx +9 -2
  65. package/src/jetpack-compose/Card/index.tsx +4 -2
  66. package/src/jetpack-compose/Divider/index.tsx +34 -14
  67. package/src/jetpack-compose/Progress/index.tsx +4 -2
  68. package/src/jetpack-compose/PullToRefreshBox/index.tsx +35 -18
  69. package/src/jetpack-compose/Surface/index.tsx +75 -4
  70. package/src/jetpack-compose/Text/index.tsx +171 -101
  71. package/src/jetpack-compose/TextInput/index.tsx +38 -8
  72. package/src/jetpack-compose/index.ts +2 -2
  73. package/src/jetpack-compose/modifiers/index.ts +10 -0
  74. package/src/swift-ui/modifiers/index.ts +1 -1
  75. package/src/types.ts +27 -0
  76. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.5/expo.modules.ui-55.0.5-sources.jar.md5 +0 -1
  77. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.5/expo.modules.ui-55.0.5-sources.jar.sha1 +0 -1
  78. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.5/expo.modules.ui-55.0.5-sources.jar.sha256 +0 -1
  79. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.5/expo.modules.ui-55.0.5-sources.jar.sha512 +0 -1
  80. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.5/expo.modules.ui-55.0.5.aar +0 -0
  81. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.5/expo.modules.ui-55.0.5.aar.md5 +0 -1
  82. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.5/expo.modules.ui-55.0.5.aar.sha1 +0 -1
  83. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.5/expo.modules.ui-55.0.5.aar.sha256 +0 -1
  84. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.5/expo.modules.ui-55.0.5.aar.sha512 +0 -1
  85. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.5/expo.modules.ui-55.0.5.module.md5 +0 -1
  86. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.5/expo.modules.ui-55.0.5.module.sha1 +0 -1
  87. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.5/expo.modules.ui-55.0.5.module.sha256 +0 -1
  88. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.5/expo.modules.ui-55.0.5.module.sha512 +0 -1
  89. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.5/expo.modules.ui-55.0.5.pom.md5 +0 -1
  90. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.5/expo.modules.ui-55.0.5.pom.sha1 +0 -1
  91. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.5/expo.modules.ui-55.0.5.pom.sha256 +0 -1
  92. package/local-maven-repo/expo/modules/ui/expo.modules.ui/55.0.5/expo.modules.ui-55.0.5.pom.sha512 +0 -1
package/CHANGELOG.md CHANGED
@@ -10,6 +10,18 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 55.0.6 — 2026-03-27
14
+
15
+ ### 🛠 Breaking changes
16
+
17
+ - [android] Refactored `PullToRefreshBox` indicator props: replaced `loadingIndicatorModifiers` with nested `indicator` prop containing `color`, `containerColor`, and `modifiers`. Added `contentAlignment` prop. ([#44079](https://github.com/expo/expo/pull/44079) by [@nishan](https://github.com/intergalacticspacehighway))
18
+ - [android] Split `Divider` into `HorizontalDivider` and `VerticalDivider` matching native Compose components. Added `thickness` and `color` props. ([#44035](https://github.com/expo/expo/pull/44035) by [@nishan](https://github.com/intergalacticspacehighway))
19
+ - [android] Match `AlertDialog` API to native Compose: replaced string props (`title`, `text`, `confirmButtonText`, `dismissButtonText`) with slot sub-components (`AlertDialog.Title`, `AlertDialog.Text`, `AlertDialog.ConfirmButton`, `AlertDialog.DismissButton`, `AlertDialog.Icon`). Removed `visible` prop (use conditional rendering), `onConfirmPressed`/`onDismissPressed` (renamed to `onDismissRequest`), and `confirmButtonColors`/`dismissButtonColors` (replaced with dialog-level `colors`). ([#43997](https://github.com/expo/expo/pull/43997) by [@nishan](https://github.com/intergalacticspacehighway))
20
+
21
+ ### 🎉 New features
22
+
23
+ - [android] add `imePadding` modifier ([#43652](https://github.com/expo/expo/pull/43652) by [@Ubax](https://github.com/Ubax))
24
+
13
25
  ## 55.0.5 — 2026-03-19
14
26
 
15
27
  ### 🛠 Breaking changes
@@ -43,6 +55,8 @@
43
55
 
44
56
  ### 🎉 New features
45
57
 
58
+ - [android] Added `shape`, `border`, `selected`, `checked`, `onClick`, and `onCheckedChange` props to `Surface`, supporting clickable, selectable, and toggleable variants. ([#44079](https://github.com/expo/expo/pull/44079) by [@nishan](https://github.com/intergalacticspacehighway))
59
+ - [android] Added nested text support for Compose `Text` with style inheritance, custom fonts via `expo-font`, `background`, `shadow`, and `lineBreak` properties. ([#44094](https://github.com/expo/expo/pull/44094) by [@nishan](https://github.com/intergalacticspacehighway))
46
60
  - [android] Added `outlined` variant to `TextInput` component. ([#43719](https://github.com/expo/expo/pull/43719) by [@benjaminkomen](https://github.com/benjaminkomen))
47
61
  - Added `@expo/ui/datetimepicker` — a cross-platform `DateTimePicker` drop-in replacement for `@react-native-community/datetimepicker`. ([#44014](https://github.com/expo/expo/pull/44014) by [@vonovak](https://github.com/vonovak))
48
62
  - [iOS] Added `locale` and `timeZone` support to `modifiers`. ([#44013](https://github.com/expo/expo/pull/44013) by [@vonovak](https://github.com/vonovak))
@@ -244,6 +258,7 @@ _This version does not introduce any user-facing changes._
244
258
 
245
259
  ### 🎉 New features
246
260
 
261
+ - [Android] Add `label`, and `placeholder` props to TextField component. ([#40452](https://github.com/expo/expo/pull/40452) by [@akshayjadhav4](https://github.com/akshayjadhav4))
247
262
  - [iOS] Add `refreshable` modifier. ([#40201](https://github.com/expo/expo/pull/40201) by [@christianwooldridge](https://github.com/christianwooldridge))
248
263
  - [iOS] Add RTL support in swiftui. ([#40335](https://github.com/expo/expo/pull/40335) by [@kfirfitousi](https://github.com/kfirfitousi))
249
264
  - [Android] Add Carousel component. ([#40325](https://github.com/expo/expo/pull/40325) by [@aleqsio](https://github.com/aleqsio))
@@ -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 = '55.0.5'
15
+ version = '55.0.6'
16
16
 
17
17
  android {
18
18
  namespace "expo.modules.ui"
19
19
  defaultConfig {
20
20
  versionCode 1
21
- versionName "55.0.5"
21
+ versionName "55.0.6"
22
22
  testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
23
23
  }
24
24
  buildFeatures {
@@ -1,52 +1,80 @@
1
1
  package expo.modules.ui
2
2
 
3
+ import android.graphics.Color
3
4
  import androidx.compose.material3.AlertDialog
4
- import androidx.compose.material3.Text
5
- import androidx.compose.material3.TextButton
5
+ import androidx.compose.material3.AlertDialogDefaults
6
6
  import androidx.compose.runtime.Composable
7
+ import androidx.compose.ui.unit.dp
8
+ import androidx.compose.ui.window.DialogProperties
9
+ import expo.modules.kotlin.records.Field
7
10
  import expo.modules.kotlin.records.Record
8
11
  import expo.modules.kotlin.views.ComposeProps
9
12
  import expo.modules.kotlin.views.FunctionalComposableScope
10
- import java.io.Serializable
11
13
 
12
- open class AlertDialogButtonPressedEvent() : Record, Serializable
14
+ data class AlertDialogColors(
15
+ @Field val containerColor: Color? = null,
16
+ @Field val iconContentColor: Color? = null,
17
+ @Field val titleContentColor: Color? = null,
18
+ @Field val textContentColor: Color? = null
19
+ ) : Record
20
+
21
+ data class ExpoDialogProperties(
22
+ @Field val dismissOnBackPress: Boolean = true,
23
+ @Field val dismissOnClickOutside: Boolean = true,
24
+ @Field val usePlatformDefaultWidth: Boolean = true,
25
+ @Field val decorFitsSystemWindows: Boolean = true
26
+ ) : Record
13
27
 
14
28
  data class AlertDialogProps(
15
- val title: String? = null,
16
- val text: String? = null,
17
- val confirmButtonText: String? = null,
18
- val dismissButtonText: String? = null,
19
- val visible: Boolean = false,
29
+ val colors: AlertDialogColors = AlertDialogColors(),
30
+ val tonalElevation: Double? = null,
31
+ val properties: ExpoDialogProperties = ExpoDialogProperties(),
20
32
  val modifiers: ModifierList = emptyList()
21
33
  ) : ComposeProps
22
34
 
23
35
  @Composable
24
36
  fun FunctionalComposableScope.AlertDialogContent(
25
37
  props: AlertDialogProps,
26
- onDismissPressed: (AlertDialogButtonPressedEvent) -> Unit,
27
- onConfirmPressed: (AlertDialogButtonPressedEvent) -> Unit
38
+ onDismissRequest: () -> Unit
28
39
  ) {
29
- if (!props.visible) {
30
- return
31
- }
40
+ val titleSlotView = findChildSlotView(view, "title")
41
+ val textSlotView = findChildSlotView(view, "text")
42
+ val confirmButtonSlotView = findChildSlotView(view, "confirmButton")
43
+ val dismissButtonSlotView = findChildSlotView(view, "dismissButton")
44
+ val iconSlotView = findChildSlotView(view, "icon")
32
45
 
33
46
  AlertDialog(
47
+ onDismissRequest = { onDismissRequest() },
34
48
  confirmButton = {
35
- props.confirmButtonText?.let {
36
- TextButton(onClick = { onConfirmPressed(AlertDialogButtonPressedEvent()) }) {
37
- Text(it)
38
- }
39
- }
49
+ confirmButtonSlotView?.renderSlot()
50
+ },
51
+ modifier = ModifierRegistry.applyModifiers(props.modifiers, appContext, composableScope, globalEventDispatcher),
52
+ dismissButton = dismissButtonSlotView?.let {
53
+ { it.renderSlot() }
54
+ },
55
+ title = titleSlotView?.let {
56
+ { it.renderSlot() }
57
+ },
58
+ text = textSlotView?.let {
59
+ { it.renderSlot() }
40
60
  },
41
- dismissButton = {
42
- props.dismissButtonText?.let {
43
- TextButton(onClick = { onDismissPressed(AlertDialogButtonPressedEvent()) }) {
44
- Text(it)
45
- }
46
- }
61
+ icon = iconSlotView?.let {
62
+ { it.renderSlot() }
47
63
  },
48
- onDismissRequest = { onDismissPressed(AlertDialogButtonPressedEvent()) },
49
- title = { props.title?.let { Text(it) } },
50
- text = { props.text?.let { Text(it) } }
64
+ containerColor = props.colors.containerColor.composeOrNull
65
+ ?: AlertDialogDefaults.containerColor,
66
+ iconContentColor = props.colors.iconContentColor.composeOrNull
67
+ ?: AlertDialogDefaults.iconContentColor,
68
+ titleContentColor = props.colors.titleContentColor.composeOrNull
69
+ ?: AlertDialogDefaults.titleContentColor,
70
+ textContentColor = props.colors.textContentColor.composeOrNull
71
+ ?: AlertDialogDefaults.textContentColor,
72
+ tonalElevation = props.tonalElevation?.dp ?: AlertDialogDefaults.TonalElevation,
73
+ properties = DialogProperties(
74
+ dismissOnBackPress = props.properties.dismissOnBackPress,
75
+ dismissOnClickOutside = props.properties.dismissOnClickOutside,
76
+ usePlatformDefaultWidth = props.properties.usePlatformDefaultWidth,
77
+ decorFitsSystemWindows = props.properties.decorFitsSystemWindows
78
+ )
51
79
  )
52
80
  }
@@ -3,11 +3,13 @@ package expo.modules.ui
3
3
  import androidx.compose.material3.BasicAlertDialog
4
4
  import androidx.compose.material3.ExperimentalMaterial3Api
5
5
  import androidx.compose.runtime.Composable
6
+ import androidx.compose.ui.window.DialogProperties
6
7
  import expo.modules.kotlin.views.ComposableScope
7
8
  import expo.modules.kotlin.views.ComposeProps
8
9
  import expo.modules.kotlin.views.FunctionalComposableScope
9
10
 
10
11
  data class BasicAlertDialogProps(
12
+ val properties: ExpoDialogProperties = ExpoDialogProperties(),
11
13
  val modifiers: ModifierList = emptyList()
12
14
  ) : ComposeProps
13
15
 
@@ -19,7 +21,13 @@ fun FunctionalComposableScope.BasicAlertDialogContent(
19
21
  ) {
20
22
  BasicAlertDialog(
21
23
  onDismissRequest = { onDismissRequest() },
22
- modifier = ModifierRegistry.applyModifiers(props.modifiers, appContext, composableScope, globalEventDispatcher)
24
+ modifier = ModifierRegistry.applyModifiers(props.modifiers, appContext, composableScope, globalEventDispatcher),
25
+ properties = DialogProperties(
26
+ dismissOnBackPress = props.properties.dismissOnBackPress,
27
+ dismissOnClickOutside = props.properties.dismissOnClickOutside,
28
+ usePlatformDefaultWidth = props.properties.usePlatformDefaultWidth,
29
+ decorFitsSystemWindows = props.properties.decorFitsSystemWindows
30
+ )
23
31
  ) {
24
32
  Children(ComposableScope())
25
33
  }
@@ -1,15 +1,34 @@
1
1
  package expo.modules.ui
2
2
 
3
+ import android.graphics.Color
4
+ import androidx.compose.material3.DividerDefaults
3
5
  import androidx.compose.material3.HorizontalDivider
6
+ import androidx.compose.material3.VerticalDivider
4
7
  import androidx.compose.runtime.Composable
8
+ import androidx.compose.ui.unit.dp
5
9
  import expo.modules.kotlin.views.ComposeProps
6
10
  import expo.modules.kotlin.views.FunctionalComposableScope
7
11
 
8
12
  data class DividerProps(
13
+ val thickness: Float? = null,
14
+ val color: Color? = null,
9
15
  val modifiers: ModifierList = emptyList()
10
16
  ) : ComposeProps
11
17
 
12
18
  @Composable
13
- fun FunctionalComposableScope.DividerContent(props: DividerProps) {
14
- HorizontalDivider(modifier = ModifierRegistry.applyModifiers(props.modifiers, appContext, composableScope, globalEventDispatcher))
19
+ fun FunctionalComposableScope.HorizontalDividerContent(props: DividerProps) {
20
+ HorizontalDivider(
21
+ modifier = ModifierRegistry.applyModifiers(props.modifiers, appContext, composableScope, globalEventDispatcher),
22
+ thickness = props.thickness?.dp ?: DividerDefaults.Thickness,
23
+ color = props.color.composeOrNull ?: DividerDefaults.color
24
+ )
25
+ }
26
+
27
+ @Composable
28
+ fun FunctionalComposableScope.VerticalDividerContent(props: DividerProps) {
29
+ VerticalDivider(
30
+ modifier = ModifierRegistry.applyModifiers(props.modifiers, appContext, composableScope, globalEventDispatcher),
31
+ thickness = props.thickness?.dp ?: DividerDefaults.Thickness,
32
+ color = props.color.composeOrNull ?: DividerDefaults.color
33
+ )
15
34
  }
@@ -210,8 +210,12 @@ class ExpoUIModule : Module() {
210
210
  ShapeContent(props)
211
211
  }
212
212
 
213
- ExpoUIView("DividerView") { props: DividerProps ->
214
- DividerContent(props)
213
+ ExpoUIView("HorizontalDividerView") { props: DividerProps ->
214
+ HorizontalDividerContent(props)
215
+ }
216
+
217
+ ExpoUIView("VerticalDividerView") { props: DividerProps ->
218
+ VerticalDividerContent(props)
215
219
  }
216
220
 
217
221
  ExpoUIView("DateTimePickerView", events = {
@@ -325,18 +329,10 @@ class ExpoUIModule : Module() {
325
329
  }
326
330
 
327
331
  ExpoUIView("AlertDialogView", events = {
328
- Events(
329
- "onDismissPressed",
330
- "onConfirmPressed"
331
- )
332
+ Events("onDismissRequest")
332
333
  }) { props: AlertDialogProps ->
333
- val onDismissPressed by remember { EventDispatcher<AlertDialogButtonPressedEvent>() }
334
- val onConfirmPressed by remember { EventDispatcher<AlertDialogButtonPressedEvent>() }
335
- AlertDialogContent(
336
- props,
337
- { onDismissPressed(it) },
338
- { onConfirmPressed(it) }
339
- )
334
+ val onDismissRequest by remember { EventDispatcher<Unit>() }
335
+ AlertDialogContent(props) { onDismissRequest(Unit) }
340
336
  }
341
337
 
342
338
  ExpoUIView("AssistChipView", events = {
@@ -422,8 +418,12 @@ class ExpoUIModule : Module() {
422
418
  BasicAlertDialogContent(props) { onDismissRequest(Unit) }
423
419
  }
424
420
 
425
- ExpoUIView("SurfaceView") { props: SurfaceProps ->
426
- SurfaceContent(props)
421
+ ExpoUIView("SurfaceView", events = {
422
+ Events("onSurfaceClick", "onCheckedChange")
423
+ }) { props: SurfaceProps ->
424
+ val onSurfaceClick by remember { EventDispatcher<Unit>() }
425
+ val onCheckedChange by remember { EventDispatcher<GenericEventPayload1<Boolean>>() }
426
+ SurfaceContent(props, onClick = { onSurfaceClick(Unit) }, onCheckedChange = { onCheckedChange(GenericEventPayload1(it)) })
427
427
  }
428
428
 
429
429
  ExpoUIView("AnimatedVisibilityView") { props: AnimatedVisibilityProps ->
@@ -14,6 +14,7 @@ import androidx.compose.foundation.layout.fillMaxHeight
14
14
  import androidx.compose.foundation.layout.fillMaxSize
15
15
  import androidx.compose.foundation.layout.fillMaxWidth
16
16
  import androidx.compose.foundation.layout.height
17
+ import androidx.compose.foundation.layout.imePadding
17
18
  import androidx.compose.foundation.layout.offset
18
19
  import androidx.compose.foundation.layout.padding
19
20
  import androidx.compose.foundation.layout.size
@@ -365,6 +366,11 @@ object ModifierRegistry {
365
366
  } ?: Modifier.wrapContentHeight()
366
367
  }
367
368
 
369
+ // Inset modifiers
370
+ register("imePadding") { _, _, _, _ ->
371
+ Modifier.imePadding()
372
+ }
373
+
368
374
  // Position modifiers
369
375
  register("offset") { map, _, _, _ ->
370
376
  val params = recordFromMap<OffsetParams>(map)
@@ -2,19 +2,33 @@
2
2
 
3
3
  package expo.modules.ui
4
4
 
5
+ import android.graphics.Color
5
6
  import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
7
+ import androidx.compose.material3.MaterialTheme
6
8
  import androidx.compose.material3.pulltorefresh.PullToRefreshBox
7
9
  import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults
8
10
  import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
9
11
  import androidx.compose.runtime.Composable
12
+ import androidx.compose.ui.Alignment
13
+ import androidx.compose.ui.Modifier
10
14
  import expo.modules.kotlin.views.ComposableScope
11
15
  import expo.modules.kotlin.views.ComposeProps
12
16
  import expo.modules.kotlin.views.FunctionalComposableScope
17
+ import expo.modules.kotlin.records.Field
18
+ import expo.modules.kotlin.records.Record
19
+ import expo.modules.ui.convertibles.ContentAlignment
20
+
21
+ data class PullToRefreshIndicatorProps(
22
+ @Field val color: Color? = null,
23
+ @Field val containerColor: Color? = null,
24
+ @Field val modifiers: ModifierList = emptyList()
25
+ ) : Record
13
26
 
14
27
  data class PullToRefreshBoxProps(
15
28
  val isRefreshing: Boolean = false,
16
- val modifiers: ModifierList = emptyList(),
17
- val loadingIndicatorModifiers: ModifierList = emptyList()
29
+ val contentAlignment: ContentAlignment? = null,
30
+ val indicator: PullToRefreshIndicatorProps = PullToRefreshIndicatorProps(),
31
+ val modifiers: ModifierList = emptyList()
18
32
  ) : ComposeProps
19
33
 
20
34
  @Composable
@@ -26,11 +40,14 @@ fun FunctionalComposableScope.PullToRefreshBoxContent(props: PullToRefreshBoxPro
26
40
  isRefreshing = isRefreshing,
27
41
  onRefresh = { onRefresh() },
28
42
  state = pullToRefreshState,
43
+ contentAlignment = props.contentAlignment?.toComposeAlignment() ?: Alignment.TopStart,
29
44
  indicator = {
30
45
  PullToRefreshDefaults.LoadingIndicator(
31
46
  isRefreshing = isRefreshing,
32
47
  state = pullToRefreshState,
33
- modifier = ModifierRegistry.applyModifiers(props.loadingIndicatorModifiers, appContext, composableScope, globalEventDispatcher)
48
+ modifier = ModifierRegistry.applyModifiers(props.indicator.modifiers, appContext, composableScope, globalEventDispatcher),
49
+ color = props.indicator.color.composeOrNull ?: MaterialTheme.colorScheme.primary,
50
+ containerColor = props.indicator.containerColor.composeOrNull ?: MaterialTheme.colorScheme.surfaceContainerHigh
34
51
  )
35
52
  },
36
53
  modifier = ModifierRegistry.applyModifiers(props.modifiers, appContext, composableScope, globalEventDispatcher)
@@ -34,6 +34,14 @@ class SlotView(context: Context, appContext: AppContext) :
34
34
  }
35
35
  }
36
36
 
37
+ /**
38
+ * Renders the slot content within a new [ComposableScope].
39
+ */
40
+ @Composable
41
+ fun SlotView.renderSlot() {
42
+ with(ComposableScope()) { with(this@renderSlot) { Content() } }
43
+ }
44
+
37
45
  fun isSlotWithName(view: ExpoComposeView<*>, slotName: String): Boolean {
38
46
  return view is SlotView && view.props.slotName.value == slotName
39
47
  }
@@ -5,32 +5,109 @@ import androidx.compose.material3.MaterialTheme
5
5
  import androidx.compose.material3.Surface
6
6
  import androidx.compose.material3.contentColorFor
7
7
  import androidx.compose.runtime.Composable
8
+ import androidx.compose.runtime.remember
9
+ import androidx.compose.ui.graphics.RectangleShape
8
10
  import androidx.compose.ui.unit.dp
11
+ import expo.modules.kotlin.records.Field
12
+ import expo.modules.kotlin.records.Record
9
13
  import expo.modules.kotlin.views.ComposableScope
10
14
  import expo.modules.kotlin.views.ComposeProps
11
15
  import expo.modules.kotlin.views.FunctionalComposableScope
12
16
 
17
+
18
+ data class SurfaceBorder(
19
+ @Field val width: Float = 1f,
20
+ @Field val color: Color? = null
21
+ ) : Record
22
+
13
23
  data class SurfaceProps(
14
24
  val color: Color? = null,
15
25
  val contentColor: Color? = null,
16
- val tonalElevation: Float = 0f,
17
- val shadowElevation: Float = 0f,
26
+ val tonalElevation: Float? = null,
27
+ val shadowElevation: Float? = null,
28
+ val shape: ShapeRecord? = null,
29
+ val border: SurfaceBorder? = null,
30
+ val clickable: Boolean = false,
31
+ val enabled: Boolean = true,
32
+ val selected: Boolean? = null,
33
+ val checked: Boolean? = null,
18
34
  val modifiers: ModifierList = emptyList()
19
35
  ) : ComposeProps
20
36
 
21
37
  @Composable
22
- fun FunctionalComposableScope.SurfaceContent(props: SurfaceProps) {
38
+ fun FunctionalComposableScope.SurfaceContent(
39
+ props: SurfaceProps,
40
+ onClick: () -> Unit,
41
+ onCheckedChange: (Boolean) -> Unit
42
+ ) {
23
43
  val modifier = ModifierRegistry.applyModifiers(props.modifiers, appContext, composableScope, globalEventDispatcher)
24
44
  val color = props.color?.compose ?: MaterialTheme.colorScheme.surface
25
45
  val contentColor = props.contentColor?.compose ?: contentColorFor(color)
46
+ val shape = remember(props.shape) { shapeFromShapeRecord(props.shape) ?: RectangleShape }
47
+ val tonalElevation = (props.tonalElevation ?: 0f).dp
48
+ val shadowElevation = (props.shadowElevation ?: 0f).dp
49
+ val outlineColor = MaterialTheme.colorScheme.outline
50
+ val border = remember(props.border, outlineColor) {
51
+ props.border?.let { b ->
52
+ val bColor = b.color.composeOrNull ?: outlineColor
53
+ androidx.compose.foundation.BorderStroke(b.width.dp, bColor)
54
+ }
55
+ }
56
+
57
+ val content: @Composable () -> Unit = { Children(ComposableScope()) }
26
58
 
27
- Surface(
28
- modifier = modifier,
29
- color = color,
30
- contentColor = contentColor,
31
- tonalElevation = props.tonalElevation.dp,
32
- shadowElevation = props.shadowElevation.dp
33
- ) {
34
- Children(ComposableScope())
59
+ when {
60
+ // Toggleable variant
61
+ props.checked != null -> Surface(
62
+ checked = props.checked,
63
+ onCheckedChange = { onCheckedChange(it) },
64
+ modifier = modifier,
65
+ enabled = props.enabled,
66
+ shape = shape,
67
+ color = color,
68
+ contentColor = contentColor,
69
+ tonalElevation = tonalElevation,
70
+ shadowElevation = shadowElevation,
71
+ border = border,
72
+ content = content
73
+ )
74
+ // Selectable variant
75
+ props.selected != null -> Surface(
76
+ selected = props.selected,
77
+ onClick = { onClick() },
78
+ modifier = modifier,
79
+ enabled = props.enabled,
80
+ shape = shape,
81
+ color = color,
82
+ contentColor = contentColor,
83
+ tonalElevation = tonalElevation,
84
+ shadowElevation = shadowElevation,
85
+ border = border,
86
+ content = content
87
+ )
88
+ // Clickable variant
89
+ props.clickable -> Surface(
90
+ onClick = { onClick() },
91
+ modifier = modifier,
92
+ enabled = props.enabled,
93
+ shape = shape,
94
+ color = color,
95
+ contentColor = contentColor,
96
+ tonalElevation = tonalElevation,
97
+ shadowElevation = shadowElevation,
98
+ border = border,
99
+ content = content
100
+ )
101
+ // Basic (non-interactive) variant
102
+ else -> Surface(
103
+ modifier = modifier,
104
+ shape = shape,
105
+ color = color,
106
+ contentColor = contentColor,
107
+ tonalElevation = tonalElevation,
108
+ shadowElevation = shadowElevation,
109
+ border = border,
110
+ content = content
111
+ )
35
112
  }
36
113
  }
@@ -12,21 +12,27 @@ import androidx.compose.runtime.mutableStateOf
12
12
  import androidx.compose.ui.text.input.KeyboardCapitalization
13
13
  import androidx.compose.ui.text.input.KeyboardType
14
14
  import expo.modules.kotlin.AppContext
15
+ import expo.modules.kotlin.types.Enumerable
15
16
  import expo.modules.kotlin.viewevent.EventDispatcher
16
17
  import expo.modules.kotlin.views.ComposableScope
17
18
  import expo.modules.kotlin.views.ComposeProps
18
19
  import expo.modules.kotlin.views.ExpoComposeView
19
20
 
21
+ enum class TextInputViewVariant(val value: String) : Enumerable {
22
+ FILLED("filled"),
23
+ OUTLINED("outlined"),
24
+ }
25
+
20
26
  data class TextInputProps(
21
27
  val defaultValue: MutableState<String> = mutableStateOf(""),
22
28
  val placeholder: MutableState<String> = mutableStateOf(""),
23
- val variant: MutableState<String> = mutableStateOf("filled"),
29
+ val variant: MutableState<TextInputViewVariant> = mutableStateOf(TextInputViewVariant.FILLED),
24
30
  val multiline: MutableState<Boolean> = mutableStateOf(false),
25
31
  val numberOfLines: MutableState<Int?> = mutableStateOf(null),
26
32
  val keyboardType: MutableState<String> = mutableStateOf("default"),
27
33
  val autocorrection: MutableState<Boolean> = mutableStateOf(true),
28
34
  val autoCapitalize: MutableState<String> = mutableStateOf("none"),
29
- val modifiers: MutableState<ModifierList> = mutableStateOf(emptyList())
35
+ val modifiers: MutableState<ModifierList> = mutableStateOf(emptyList()),
30
36
  ) : ComposeProps
31
37
 
32
38
  private fun String.keyboardType(): KeyboardType {
@@ -85,9 +91,13 @@ class TextInputView(context: Context, appContext: AppContext) :
85
91
  autoCorrectEnabled = props.autocorrection.value,
86
92
  capitalization = props.autoCapitalize.value.autoCapitalize()
87
93
  )
94
+ val labelSlotView = findChildSlotView(this@TextInputView, "label")
95
+ val label: (@Composable () -> Unit)? = labelSlotView?.let {
96
+ { with(ComposableScope()) { with(it) { Content() } } }
97
+ }
88
98
  val modifier = ModifierRegistry.applyModifiers(props.modifiers.value, appContext, this@Content, globalEventDispatcher)
89
99
 
90
- if (props.variant.value == "outlined") {
100
+ if (props.variant.value == TextInputViewVariant.OUTLINED) {
91
101
  OutlinedTextField(
92
102
  value = value,
93
103
  onValueChange = onValueChange,
@@ -95,6 +105,7 @@ class TextInputView(context: Context, appContext: AppContext) :
95
105
  maxLines = maxLines,
96
106
  singleLine = singleLine,
97
107
  keyboardOptions = keyboardOptions,
108
+ label = label,
98
109
  modifier = modifier
99
110
  )
100
111
  } else {
@@ -105,6 +116,7 @@ class TextInputView(context: Context, appContext: AppContext) :
105
116
  maxLines = maxLines,
106
117
  singleLine = singleLine,
107
118
  keyboardOptions = keyboardOptions,
119
+ label = label,
108
120
  modifier = modifier
109
121
  )
110
122
  }