@expo/ui 0.0.1 → 0.0.2

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 (64) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/android/build.gradle +5 -13
  3. package/android/src/main/java/expo/modules/ui/ExpoUIModule.kt +24 -1
  4. package/android/src/main/java/expo/modules/ui/PickerView.kt +108 -0
  5. package/android/src/main/java/expo/modules/ui/SliderView.kt +73 -0
  6. package/android/src/main/java/expo/modules/ui/SwitchView.kt +118 -0
  7. package/android/src/main/java/expo/modules/ui/Utils.kt +52 -0
  8. package/android/src/main/java/expo/modules/ui/button/Button.kt +140 -0
  9. package/android/src/main/java/expo/modules/ui/menu/ContextMenu.kt +160 -0
  10. package/android/src/main/java/expo/modules/ui/menu/ContextMenuRecords.kt +55 -0
  11. package/build/components/Button/index.d.ts +81 -0
  12. package/build/components/Button/index.d.ts.map +1 -0
  13. package/build/components/ContextMenu/index.d.ts +80 -0
  14. package/build/components/ContextMenu/index.d.ts.map +1 -0
  15. package/build/components/ContextMenu/utils.d.ts +24 -0
  16. package/build/components/ContextMenu/utils.d.ts.map +1 -0
  17. package/build/components/Picker/index.d.ts +65 -0
  18. package/build/components/Picker/index.d.ts.map +1 -0
  19. package/build/components/Section/index.d.ts +12 -0
  20. package/build/components/Section/index.d.ts.map +1 -0
  21. package/build/components/Section/index.ios.d.ts +8 -0
  22. package/build/components/Section/index.ios.d.ts.map +1 -0
  23. package/build/components/Slider/index.d.ts +54 -0
  24. package/build/components/Slider/index.d.ts.map +1 -0
  25. package/build/components/Switch/index.d.ts +101 -0
  26. package/build/components/Switch/index.d.ts.map +1 -0
  27. package/build/src/index.d.ts +13 -0
  28. package/build/src/index.d.ts.map +1 -0
  29. package/components/Button/index.tsx +132 -0
  30. package/components/ContextMenu/index.tsx +147 -0
  31. package/components/ContextMenu/utils.ts +139 -0
  32. package/components/Picker/index.tsx +83 -0
  33. package/components/Section/index.ios.tsx +58 -0
  34. package/components/Section/index.tsx +56 -0
  35. package/components/Slider/index.tsx +85 -0
  36. package/components/Switch/index.tsx +144 -0
  37. package/expo-module.config.json +3 -10
  38. package/ios/Button/Button.swift +54 -0
  39. package/ios/Button/ButtonProps.swift +43 -0
  40. package/ios/ContextMenu/ContextMenu.swift +106 -0
  41. package/ios/ContextMenu/ContextMenuRecords.swift +29 -0
  42. package/ios/ExpoUI.podspec +2 -1
  43. package/ios/ExpoUIModule.swift +6 -1
  44. package/ios/PickerView.swift +52 -0
  45. package/ios/SectionView.swift +27 -0
  46. package/ios/SliderView.swift +51 -0
  47. package/ios/SwitchView.swift +74 -0
  48. package/package.json +2 -2
  49. package/src/index.ts +22 -3
  50. package/tsconfig.json +1 -1
  51. package/android/src/main/java/expo/modules/ui/SingleChoiceSegmentedControlView.kt +0 -47
  52. package/build/ExpoUI.types.d.ts +0 -13
  53. package/build/ExpoUI.types.d.ts.map +0 -1
  54. package/build/ExpoUIModule.d.ts +0 -6
  55. package/build/ExpoUIModule.d.ts.map +0 -1
  56. package/build/ExpoUIView.d.ts +0 -4
  57. package/build/ExpoUIView.d.ts.map +0 -1
  58. package/build/index.d.ts +0 -4
  59. package/build/index.d.ts.map +0 -1
  60. package/ios/SingleChoiceSegmentedControlProps.swift +0 -10
  61. package/ios/SingleChoiceSegmentedControlView.swift +0 -29
  62. package/src/ExpoUI.types.ts +0 -8
  63. package/src/ExpoUIModule.ts +0 -5
  64. package/src/ExpoUIView.tsx +0 -10
package/CHANGELOG.md CHANGED
@@ -10,6 +10,24 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 0.0.2 — 2025-02-11
14
+
15
+ ### 🎉 New features
16
+
17
+ - Add `color` and `elementColors` props. ([#34666](https://github.com/expo/expo/pull/34666) by [@aleqsio](https://github.com/aleqsio))
18
+ - Add Button component.([#34340](https://github.com/expo/expo/pull/34340) by [@behenate](https://github.com/behenate))
19
+ - Apple TV support and source restructure. ([#34532](https://github.com/expo/expo/pull/34532) by [@douglowder](https://github.com/douglowder))
20
+ - Add `ContextMenu` component. ([#34553](https://github.com/expo/expo/pull/34553) by [@behenate](https://github.com/behenate))
21
+
22
+ ### 🐛 Bug fixes
23
+
24
+ - Fix tvOS compilation. ([#34730](https://github.com/expo/expo/pull/34730) by [@douglowder](https://github.com/douglowder))
25
+
26
+ ### 💡 Others
27
+
28
+ - [apple] Migrate remaining `expo-module.config.json` to unified platform syntax. ([#34445](https://github.com/expo/expo/pull/34445) by [@reichhartd](https://github.com/reichhartd))
29
+ - Rename the events for the `Switch` component. ([#34577](https://github.com/expo/expo/pull/34577) by [@behenate](https://github.com/behenate))
30
+
13
31
  ## 0.0.1 — 2025-01-21
14
32
 
15
33
  ### 💡 Others
@@ -1,12 +1,3 @@
1
- apply plugin: 'com.android.library'
2
-
3
- group = 'expo.modules.ui'
4
- version = '0.0.1'
5
-
6
- def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
7
- apply from: expoModulesCorePlugin
8
- applyKotlinExpoModulesCorePlugin()
9
-
10
1
  buildscript {
11
2
  repositories {
12
3
  mavenCentral()
@@ -16,17 +7,18 @@ buildscript {
16
7
  }
17
8
  }
18
9
 
10
+ apply plugin: 'com.android.library'
11
+ apply plugin: 'expo-module-gradle-plugin'
19
12
  apply plugin: 'org.jetbrains.kotlin.plugin.compose'
20
13
 
21
- useCoreDependencies()
22
- useExpoPublishing()
23
- useDefaultAndroidSdkVersions()
14
+ group = 'expo.modules.ui'
15
+ version = '0.0.2'
24
16
 
25
17
  android {
26
18
  namespace "expo.modules.ui"
27
19
  defaultConfig {
28
20
  versionCode 1
29
- versionName "0.0.1"
21
+ versionName "0.0.2"
30
22
  }
31
23
  buildFeatures {
32
24
  compose true
@@ -2,14 +2,37 @@ package expo.modules.ui
2
2
 
3
3
  import expo.modules.kotlin.modules.Module
4
4
  import expo.modules.kotlin.modules.ModuleDefinition
5
+ import expo.modules.ui.button.Button
6
+ import expo.modules.ui.menu.ContextMenu
5
7
 
6
8
  class ExpoUIModule : Module() {
7
9
  override fun definition() = ModuleDefinition {
8
10
  Name("ExpoUI")
9
11
 
10
12
  // Defines a single view for now – a single choice segmented control
11
- View(SingleChoiceSegmentedControlView::class) {
13
+ View(PickerView::class) {
12
14
  Events("onOptionSelected")
13
15
  }
16
+
17
+ View(SwitchView::class) {
18
+ Events("onValueChange")
19
+ }
20
+
21
+ View(Button::class) {
22
+ Events("onButtonPressed")
23
+ }
24
+
25
+ View(SliderView::class) {
26
+ Events("onValueChanged")
27
+ }
28
+
29
+ View(ContextMenu::class) {
30
+ Events(
31
+ "onContextMenuButtonPressed",
32
+ "onContextMenuPickerOptionSelected",
33
+ "onContextMenuSwitchValueChanged",
34
+ "onExpandedChanged"
35
+ )
36
+ }
14
37
  }
15
38
  }
@@ -0,0 +1,108 @@
1
+ package expo.modules.ui
2
+
3
+ import android.content.Context
4
+ import android.graphics.Color
5
+ import androidx.compose.material3.SegmentedButton
6
+ import androidx.compose.material3.SegmentedButtonDefaults
7
+ import expo.modules.kotlin.viewevent.EventDispatcher
8
+ import expo.modules.kotlin.views.ExpoComposeView
9
+ import androidx.compose.material3.SingleChoiceSegmentedButtonRow
10
+ import androidx.compose.material3.Text
11
+ import androidx.compose.runtime.MutableState
12
+ import androidx.compose.runtime.getValue
13
+ import androidx.compose.runtime.mutableStateOf
14
+ import expo.modules.kotlin.AppContext
15
+ import expo.modules.kotlin.views.AutoSizingComposable
16
+ import expo.modules.kotlin.records.Field
17
+ import expo.modules.kotlin.records.Record
18
+ import expo.modules.kotlin.views.ComposeProps
19
+
20
+ class PickerColors : Record {
21
+ @Field
22
+ val activeBorderColor: Color? = null
23
+
24
+ @Field
25
+ val activeContentColor: Color? = null
26
+
27
+ @Field
28
+ val inactiveBorderColor: Color? = null
29
+
30
+ @Field
31
+ val inactiveContentColor: Color? = null
32
+
33
+ @Field
34
+ val disabledActiveBorderColor: Color? = null
35
+
36
+ @Field
37
+ val disabledActiveContentColor: Color? = null
38
+
39
+ @Field
40
+ val disabledInactiveBorderColor: Color? = null
41
+
42
+ @Field
43
+ val disabledInactiveContentColor: Color? = null
44
+
45
+ @Field
46
+ val activeContainerColor: Color? = null
47
+
48
+ @Field
49
+ val inactiveContainerColor: Color? = null
50
+
51
+ @Field
52
+ val disabledActiveContainerColor: Color? = null
53
+
54
+ @Field
55
+ val disabledInactiveContainerColor: Color? = null
56
+ }
57
+
58
+ data class PickerProps(
59
+ val options: MutableState<Array<String>> = mutableStateOf(emptyArray()),
60
+ val selectedIndex: MutableState<Int?> = mutableStateOf(null),
61
+ val elementColors: MutableState<PickerColors> = mutableStateOf(PickerColors())
62
+ ) : ComposeProps
63
+
64
+ class PickerView(context: Context, appContext: AppContext) : ExpoComposeView<PickerProps>(context, appContext) {
65
+ override val props = PickerProps()
66
+ private val onOptionSelected by EventDispatcher()
67
+
68
+ init {
69
+ setContent {
70
+ val (selectedIndex) = props.selectedIndex
71
+ val (options) = props.options
72
+ val (colors) = props.elementColors
73
+ DynamicTheme {
74
+ AutoSizingComposable(shadowNodeProxy) {
75
+ SingleChoiceSegmentedButtonRow {
76
+ options.forEachIndexed { index, label ->
77
+ SegmentedButton(
78
+ shape = SegmentedButtonDefaults.itemShape(
79
+ index = index,
80
+ count = options.size
81
+ ),
82
+ onClick = {
83
+ onOptionSelected(mapOf("index" to index, "label" to label))
84
+ },
85
+ selected = index == selectedIndex,
86
+ label = { Text(label) },
87
+ colors = SegmentedButtonDefaults.colors(
88
+ activeBorderColor = colors.activeBorderColor.compose,
89
+ activeContentColor = colors.activeContentColor.compose,
90
+ inactiveBorderColor = colors.inactiveBorderColor.compose,
91
+ inactiveContentColor = colors.inactiveContentColor.compose,
92
+ disabledActiveBorderColor = colors.disabledActiveBorderColor.compose,
93
+ disabledActiveContentColor = colors.disabledActiveContentColor.compose,
94
+ disabledInactiveBorderColor = colors.disabledInactiveBorderColor.compose,
95
+ disabledInactiveContentColor = colors.disabledInactiveContentColor.compose,
96
+ activeContainerColor = colors.activeContainerColor.compose,
97
+ inactiveContainerColor = colors.inactiveContainerColor.compose,
98
+ disabledActiveContainerColor = colors.disabledActiveContainerColor.compose,
99
+ disabledInactiveContainerColor = colors.disabledInactiveContainerColor.compose
100
+ )
101
+ )
102
+ }
103
+ }
104
+ }
105
+ }
106
+ }
107
+ }
108
+ }
@@ -0,0 +1,73 @@
1
+ package expo.modules.ui
2
+
3
+ import android.content.Context
4
+ import android.graphics.Color
5
+ import expo.modules.kotlin.viewevent.EventDispatcher
6
+ import expo.modules.kotlin.views.ExpoComposeView
7
+ import androidx.compose.material3.Slider
8
+ import androidx.compose.material3.SliderDefaults
9
+ import androidx.compose.runtime.MutableState
10
+ import androidx.compose.runtime.mutableFloatStateOf
11
+ import androidx.compose.runtime.mutableIntStateOf
12
+ import androidx.compose.runtime.mutableStateOf
13
+ import expo.modules.kotlin.AppContext
14
+ import expo.modules.kotlin.records.Field
15
+ import expo.modules.kotlin.records.Record
16
+ import expo.modules.kotlin.views.ComposeProps
17
+
18
+ class SliderColors : Record {
19
+ @Field
20
+ val thumbColor: Color? = null
21
+
22
+ @Field
23
+ val activeTrackColor: Color? = null
24
+
25
+ @Field
26
+ val inactiveTrackColor: Color? = null
27
+
28
+ @Field
29
+ val activeTickColor: Color? = null
30
+
31
+ @Field
32
+ val inactiveTickColor: Color? = null
33
+ }
34
+
35
+ data class SliderProps(
36
+ val value: MutableState<Float> = mutableFloatStateOf(0.0f),
37
+ val min: MutableState<Float> = mutableFloatStateOf(0.0f),
38
+ val max: MutableState<Float> = mutableFloatStateOf(1.0f),
39
+ val steps: MutableState<Int> = mutableIntStateOf(0),
40
+ val elementColors: MutableState<SliderColors> = mutableStateOf(SliderColors())
41
+ ) : ComposeProps
42
+
43
+ class SliderView(context: Context, appContext: AppContext) : ExpoComposeView<SliderProps>(context, appContext) {
44
+ override val props = SliderProps()
45
+ private val onValueChanged by EventDispatcher()
46
+
47
+ init {
48
+ setContent {
49
+ val (value) = props.value
50
+ val (min) = props.min
51
+ val (max) = props.max
52
+ val (steps) = props.steps
53
+ val (colors) = props.elementColors
54
+ DynamicTheme {
55
+ Slider(
56
+ value = value.coerceAtLeast(min).coerceAtMost(max),
57
+ valueRange = min..max,
58
+ steps = steps,
59
+ onValueChange = {
60
+ onValueChanged(mapOf("value" to it))
61
+ },
62
+ colors = SliderDefaults.colors(
63
+ thumbColor = colors.thumbColor.compose,
64
+ activeTrackColor = colors.activeTrackColor.compose,
65
+ inactiveTrackColor = colors.inactiveTrackColor.compose,
66
+ activeTickColor = colors.activeTickColor.compose,
67
+ inactiveTickColor = colors.inactiveTickColor.compose
68
+ )
69
+ )
70
+ }
71
+ }
72
+ }
73
+ }
@@ -0,0 +1,118 @@
1
+ package expo.modules.ui
2
+
3
+ import android.content.Context
4
+ import android.graphics.Color
5
+ import androidx.compose.material3.Checkbox
6
+ import androidx.compose.material3.CheckboxDefaults
7
+ import expo.modules.kotlin.viewevent.EventDispatcher
8
+ import expo.modules.kotlin.views.ExpoComposeView
9
+ import androidx.compose.material3.Switch
10
+ import androidx.compose.material3.SwitchDefaults
11
+ import androidx.compose.runtime.Composable
12
+ import androidx.compose.runtime.MutableState
13
+ import androidx.compose.runtime.mutableStateOf
14
+ import expo.modules.kotlin.AppContext
15
+ import expo.modules.kotlin.views.AutoSizingComposable
16
+ import expo.modules.kotlin.views.ComposeProps
17
+ import expo.modules.kotlin.records.Field
18
+ import expo.modules.kotlin.records.Record
19
+ import java.io.Serializable
20
+
21
+ open class ValueChangeEvent(
22
+ @Field open val value: Boolean = false
23
+ ) : Record, Serializable
24
+
25
+ class SwitchColors : Record {
26
+ @Field
27
+ val checkedThumbColor: Color? = null
28
+
29
+ @Field
30
+ val checkedTrackColor: Color? = null
31
+
32
+ @Field
33
+ val uncheckedThumbColor: Color? = null
34
+
35
+ @Field
36
+ val uncheckedTrackColor: Color? = null
37
+
38
+ @Field
39
+ val checkedColor: Color? = null
40
+
41
+ @Field
42
+ val disabledCheckedColor: Color? = null
43
+
44
+ @Field
45
+ val uncheckedColor: Color? = null
46
+
47
+ @Field
48
+ val disabledUncheckedColor: Color? = null
49
+
50
+ @Field
51
+ val checkmarkColor: Color? = null
52
+
53
+ @Field
54
+ val disabledIndeterminateColor: Color? = null
55
+ }
56
+
57
+ data class SwitchProps(
58
+ val value: MutableState<Boolean> = mutableStateOf(false),
59
+ val variant: MutableState<String> = mutableStateOf("switch"),
60
+ val elementColors: MutableState<SwitchColors> = mutableStateOf(SwitchColors())
61
+ ) : ComposeProps
62
+
63
+ class SwitchView(context: Context, appContext: AppContext) : ExpoComposeView<SwitchProps>(context, appContext) {
64
+ override val props = SwitchProps()
65
+ private val onValueChange by EventDispatcher<ValueChangeEvent>()
66
+
67
+ init {
68
+ setContent {
69
+ val (checked) = props.value
70
+ val (variant) = props.variant
71
+ val (colors) = props.elementColors
72
+ val onCheckedChange = { checked: Boolean ->
73
+ onValueChange(ValueChangeEvent(checked))
74
+ }
75
+
76
+ @Composable
77
+ fun SwitchComposable() {
78
+ Switch(
79
+ checked = checked,
80
+ onCheckedChange = onCheckedChange,
81
+ colors = SwitchDefaults.colors(
82
+ // For some reason the default way of passing colors using `compose` results in a transparent view
83
+ checkedThumbColor = colors.checkedThumbColor.composeOrNull ?: SwitchDefaults.colors().checkedThumbColor,
84
+ checkedTrackColor = colors.checkedTrackColor.composeOrNull ?: SwitchDefaults.colors().checkedTrackColor,
85
+ uncheckedThumbColor = colors.uncheckedThumbColor.composeOrNull ?: SwitchDefaults.colors().uncheckedThumbColor,
86
+ uncheckedTrackColor = colors.uncheckedTrackColor.composeOrNull ?: SwitchDefaults.colors().uncheckedTrackColor
87
+ )
88
+ )
89
+ }
90
+
91
+ @Composable
92
+ fun CheckboxComposable() {
93
+ Checkbox(
94
+ checked = checked,
95
+ onCheckedChange = onCheckedChange,
96
+ colors = CheckboxDefaults.colors(
97
+ checkedColor = colors.checkedColor.compose,
98
+ disabledCheckedColor = colors.disabledCheckedColor.compose,
99
+ uncheckedColor = colors.uncheckedColor.compose,
100
+ disabledUncheckedColor = colors.disabledUncheckedColor.compose,
101
+ checkmarkColor = colors.checkmarkColor.compose,
102
+ disabledIndeterminateColor = colors.disabledIndeterminateColor.compose
103
+ )
104
+ )
105
+ }
106
+
107
+ DynamicTheme {
108
+ AutoSizingComposable(shadowNodeProxy) {
109
+ if (variant == "switch") {
110
+ SwitchComposable()
111
+ } else {
112
+ CheckboxComposable()
113
+ }
114
+ }
115
+ }
116
+ }
117
+ }
118
+ }
@@ -0,0 +1,52 @@
1
+ package expo.modules.ui
2
+
3
+ import android.graphics.Color
4
+ import android.os.Build
5
+ import androidx.compose.foundation.isSystemInDarkTheme
6
+ import androidx.compose.material3.MaterialTheme
7
+ import androidx.compose.material3.darkColorScheme
8
+ import androidx.compose.material3.dynamicDarkColorScheme
9
+ import androidx.compose.material3.dynamicLightColorScheme
10
+ import androidx.compose.material3.lightColorScheme
11
+ import androidx.compose.runtime.Composable
12
+ import androidx.compose.ui.platform.LocalContext
13
+
14
+ @Composable
15
+ fun DynamicTheme(content: @Composable (() -> Unit)) {
16
+ val context = LocalContext.current
17
+ val colors = when {
18
+ (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) -> {
19
+ if (isSystemInDarkTheme()) {
20
+ dynamicDarkColorScheme(context)
21
+ } else {
22
+ dynamicLightColorScheme(context)
23
+ }
24
+ }
25
+
26
+ isSystemInDarkTheme() -> darkColorScheme()
27
+ else -> lightColorScheme()
28
+ }
29
+ MaterialTheme(colorScheme = colors) {
30
+ content()
31
+ }
32
+ }
33
+
34
+ fun colorToComposeColorOrNull(color: Color?): androidx.compose.ui.graphics.Color? {
35
+ return color?.let {
36
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
37
+ androidx.compose.ui.graphics.Color(it.red(), it.green(), it.blue(), it.alpha())
38
+ } else {
39
+ null
40
+ }
41
+ }
42
+ }
43
+
44
+ fun colorToComposeColor(color: Color?): androidx.compose.ui.graphics.Color {
45
+ return colorToComposeColorOrNull(color) ?: androidx.compose.ui.graphics.Color.Unspecified
46
+ }
47
+
48
+ val Color?.compose: androidx.compose.ui.graphics.Color
49
+ get() = colorToComposeColor(this)
50
+
51
+ val Color?.composeOrNull: androidx.compose.ui.graphics.Color?
52
+ get() = colorToComposeColorOrNull(this)
@@ -0,0 +1,140 @@
1
+ package expo.modules.ui.button
2
+
3
+ import android.content.Context
4
+ import android.graphics.Color
5
+ import androidx.compose.foundation.layout.RowScope
6
+ import androidx.compose.material3.ButtonDefaults
7
+ import androidx.compose.material3.ElevatedButton
8
+ import androidx.compose.material3.FilledTonalButton
9
+ import androidx.compose.material3.OutlinedButton
10
+ import expo.modules.kotlin.viewevent.EventDispatcher
11
+ import expo.modules.kotlin.views.ExpoComposeView
12
+ import androidx.compose.material3.Text
13
+ import androidx.compose.material3.TextButton
14
+ import androidx.compose.runtime.Composable
15
+ import androidx.compose.runtime.MutableState
16
+ import androidx.compose.runtime.mutableStateOf
17
+ import expo.modules.kotlin.AppContext
18
+ import expo.modules.kotlin.records.Field
19
+ import expo.modules.kotlin.records.Record
20
+ import expo.modules.kotlin.views.ComposeProps
21
+ import java.io.Serializable
22
+ import expo.modules.kotlin.types.Enumerable
23
+ import expo.modules.ui.DynamicTheme
24
+ import expo.modules.ui.compose
25
+
26
+ open class ButtonPressedEvent() : Record, Serializable
27
+
28
+ enum class ButtonVariant(val value: String) : Enumerable {
29
+ DEFAULT("default"),
30
+ BORDERED("bordered"),
31
+ BORDERLESS("borderless"),
32
+ OUTLINED("outlined"),
33
+ ELEVATED("elevated")
34
+ }
35
+
36
+ class ButtonColors : Record {
37
+ @Field
38
+ val containerColor: Color? = null
39
+
40
+ @Field
41
+ val contentColor: Color? = null
42
+
43
+ @Field
44
+ val disabledContainerColor: Color? = null
45
+
46
+ @Field
47
+ val disabledContentColor: Color? = null
48
+ }
49
+
50
+ data class ButtonProps(
51
+ val text: MutableState<String> = mutableStateOf(""),
52
+ val variant: MutableState<ButtonVariant?> = mutableStateOf(ButtonVariant.DEFAULT),
53
+ val elementColors: MutableState<ButtonColors> = mutableStateOf(ButtonColors())
54
+
55
+ ) : ComposeProps
56
+
57
+ @Composable
58
+ fun StyledButton(variant: ButtonVariant, colors: ButtonColors, onPress: () -> Unit, content: @Composable (RowScope.() -> Unit)) {
59
+ when (variant) {
60
+ ButtonVariant.BORDERED -> FilledTonalButton(
61
+ onPress,
62
+ content = content,
63
+ colors = ButtonDefaults.filledTonalButtonColors(
64
+ containerColor = colors.containerColor.compose,
65
+ contentColor = colors.contentColor.compose,
66
+ disabledContainerColor = colors.disabledContainerColor.compose,
67
+ disabledContentColor = colors.disabledContentColor.compose
68
+ )
69
+ )
70
+
71
+ ButtonVariant.BORDERLESS -> TextButton(
72
+ onPress,
73
+ content = content,
74
+ colors = ButtonDefaults.textButtonColors(
75
+ containerColor = colors.containerColor.compose,
76
+ contentColor = colors.contentColor.compose,
77
+ disabledContainerColor = colors.disabledContainerColor.compose,
78
+ disabledContentColor = colors.disabledContentColor.compose
79
+ )
80
+ )
81
+
82
+ ButtonVariant.OUTLINED -> OutlinedButton(
83
+ onPress,
84
+ content = content,
85
+ colors = ButtonDefaults.outlinedButtonColors(
86
+ containerColor = colors.containerColor.compose,
87
+ contentColor = colors.contentColor.compose,
88
+ disabledContainerColor = colors.disabledContainerColor.compose,
89
+ disabledContentColor = colors.disabledContentColor.compose
90
+ )
91
+ )
92
+
93
+ ButtonVariant.ELEVATED -> ElevatedButton(
94
+ onPress,
95
+ content = content,
96
+ colors = ButtonDefaults.elevatedButtonColors(
97
+ containerColor = colors.containerColor.compose,
98
+ contentColor = colors.contentColor.compose,
99
+ disabledContainerColor = colors.disabledContainerColor.compose,
100
+ disabledContentColor = colors.disabledContentColor.compose
101
+ )
102
+ )
103
+
104
+ else -> androidx.compose.material3.Button(
105
+ onPress,
106
+ content = content,
107
+ colors = ButtonDefaults.buttonColors(
108
+ containerColor = colors.containerColor.compose,
109
+ contentColor = colors.contentColor.compose,
110
+ disabledContainerColor = colors.disabledContainerColor.compose,
111
+ disabledContentColor = colors.disabledContentColor.compose
112
+ )
113
+ )
114
+ }
115
+ }
116
+
117
+ class Button(context: Context, appContext: AppContext) : ExpoComposeView<ButtonProps>(context, appContext) {
118
+ override val props = ButtonProps()
119
+ private val onButtonPressed by EventDispatcher<ButtonPressedEvent>()
120
+
121
+ init {
122
+ clipToPadding = false // needed for elevated buttons to work
123
+ clipChildren = false
124
+
125
+ setContent {
126
+ val (variant) = props.variant
127
+ val (text) = props.text
128
+ val (colors) = props.elementColors
129
+ DynamicTheme {
130
+ StyledButton(
131
+ variant ?: ButtonVariant.DEFAULT,
132
+ colors,
133
+ { onButtonPressed.invoke(ButtonPressedEvent()) }
134
+ ) {
135
+ Text(text)
136
+ }
137
+ }
138
+ }
139
+ }
140
+ }