pytech-ui 1.0.21 → 1.0.23

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 (151) hide show
  1. package/android/.gradle/8.9/checksums/checksums.lock +0 -0
  2. package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
  3. package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
  4. package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
  5. package/android/.gradle/8.9/gc.properties +0 -0
  6. package/android/.gradle/9.3.0/checksums/checksums.lock +0 -0
  7. package/android/.gradle/9.3.0/fileChanges/last-build.bin +0 -0
  8. package/android/.gradle/9.3.0/fileHashes/fileHashes.bin +0 -0
  9. package/android/.gradle/9.3.0/fileHashes/fileHashes.lock +0 -0
  10. package/android/.gradle/9.3.0/gc.properties +0 -0
  11. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  12. package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  13. package/android/.gradle/nb-cache/trust/8732A504261C070E1F639E78DF65F8E6DC6FFC865B3D7178A7609BB57105805F +1 -0
  14. package/android/.gradle/vcs-1/gc.properties +0 -0
  15. package/android/build.gradle +47 -0
  16. package/android/src/main/AndroidManifest.xml +2 -0
  17. package/android/src/main/java/expo/modules/myui/Dialog.kt +39 -0
  18. package/android/src/main/java/expo/modules/myui/ForEach/ForEachRecords.kt +23 -0
  19. package/android/src/main/java/expo/modules/myui/ForEach/index.kt +82 -0
  20. package/android/src/main/java/expo/modules/myui/Gradient/GradientView.kt +124 -0
  21. package/android/src/main/java/expo/modules/myui/Icon/index.kt +36 -0
  22. package/android/src/main/java/expo/modules/myui/Icon/utils.kt +43 -0
  23. package/android/src/main/java/expo/modules/myui/ListItem/Data/ListItemDataRecords.kt +84 -0
  24. package/android/src/main/java/expo/modules/myui/ListItem/Data/ListItemFromData.kt +127 -0
  25. package/android/src/main/java/expo/modules/myui/ListItem/Slots/ListItemFromSlots.kt +60 -0
  26. package/android/src/main/java/expo/modules/myui/ListItem/Slots/types.kt +42 -0
  27. package/android/src/main/java/expo/modules/myui/ListItem/_shared/Decorator/Decorator.kt +79 -0
  28. package/android/src/main/java/expo/modules/myui/ListItem/_shared/Decorator/Divider.kt +36 -0
  29. package/android/src/main/java/expo/modules/myui/ListItem/_shared/Decorator/utilsDecorator.kt +19 -0
  30. package/android/src/main/java/expo/modules/myui/ListItem/_shared/Dynamic/Dynamic.kt +163 -0
  31. package/android/src/main/java/expo/modules/myui/ListItem/_shared/Dynamic/Row.kt +136 -0
  32. package/android/src/main/java/expo/modules/myui/Menu/DropdownMenu.kt +48 -0
  33. package/android/src/main/java/expo/modules/myui/Menu/DropdownMenuRecords.kt +20 -0
  34. package/android/src/main/java/expo/modules/myui/MyUiModifiers.kt +94 -0
  35. package/android/src/main/java/expo/modules/myui/MyUiModule.kt +168 -0
  36. package/android/src/main/java/expo/modules/myui/SearchBar.kt +213 -0
  37. package/android/src/main/java/expo/modules/myui/Section/SectionHost.kt +81 -0
  38. package/android/src/main/java/expo/modules/myui/Section/SectionHostView.kt +65 -0
  39. package/android/src/main/java/expo/modules/myui/TextField.kt +251 -0
  40. package/android/src/main/java/expo/modules/myui/TypographySlot/TypographySlotBridge.kt +120 -0
  41. package/android/src/main/java/expo/modules/myui/TypographySlot/constants.kt +47 -0
  42. package/android/src/main/java/expo/modules/myui/TypographySlot/index.kt +43 -0
  43. package/android/src/main/java/expo/modules/myui/extended-theme/ExtendedThemeView.kt +19 -0
  44. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Colors/ExtendedColorBridge.kt +77 -0
  45. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Colors/index.kt +148 -0
  46. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Constants/Constants.kt +11 -0
  47. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/AppBarLargeFlexibleTokens.kt +20 -0
  48. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/AppBarLargeTokens.kt +19 -0
  49. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/AppBarMediumFlexibleTokens.kt +20 -0
  50. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/AppBarMediumTokens.kt +19 -0
  51. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/AppBarSmallTokens.kt +19 -0
  52. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/AppBarTokens.kt +23 -0
  53. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/AssistChipTokens.kt +25 -0
  54. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/BadgeTokens.kt +20 -0
  55. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/BaselineButtonTokens.kt +26 -0
  56. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/BottomAppBarTokens.kt +19 -0
  57. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/ButtonGroupSmallTokens.kt +20 -0
  58. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/ButtonLargeTokens.kt +24 -0
  59. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/ButtonMediumTokens.kt +24 -0
  60. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/ButtonSmallTokens.kt +24 -0
  61. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/ButtonXLargeTokens.kt +24 -0
  62. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/ButtonXSmallTokens.kt +24 -0
  63. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/CheckboxTokens.kt +35 -0
  64. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/CircularProgressIndicatorTokens.kt +25 -0
  65. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/ConnectedButtonGroupSmallTokens.kt +21 -0
  66. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/DateInputModalTokens.kt +22 -0
  67. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/DatePickerModalTokens.kt +33 -0
  68. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/DialogTokens.kt +19 -0
  69. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/DividerTokens.kt +19 -0
  70. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/DockedToolbarTokens.kt +23 -0
  71. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/DragHandleTokens.kt +25 -0
  72. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/ElevatedButtonTokens.kt +19 -0
  73. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/ElevatedCardTokens.kt +20 -0
  74. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/ElevationTokens.kt +24 -0
  75. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/ExpressiveMotionTokens.kt +28 -0
  76. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/ExtendedFabLargeTokens.kt +23 -0
  77. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/ExtendedFabMediumTokens.kt +24 -0
  78. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/ExtendedFabPrimaryTokens.kt +20 -0
  79. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/ExtendedFabSmallTokens.kt +23 -0
  80. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/FabBaselineTokens.kt +21 -0
  81. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/FabLargeTokens.kt +21 -0
  82. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/FabMediumTokens.kt +22 -0
  83. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/FabMenuBaselineTokens.kt +28 -0
  84. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/FabSmallTokens.kt +21 -0
  85. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/FilledAutocompleteTokens.kt +31 -0
  86. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/FilledButtonTokens.kt +19 -0
  87. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/FilledCardTokens.kt +20 -0
  88. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/FilledIconButtonTokens.kt +18 -0
  89. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/FilledTextFieldTokens.kt +31 -0
  90. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/FilledTonalButtonTokens.kt +23 -0
  91. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/FilledTonalIconButtonTokens.kt +18 -0
  92. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/FilterChipTokens.kt +28 -0
  93. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/FloatingToolbarTokens.kt +23 -0
  94. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/IconButtonTokens.kt +17 -0
  95. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/InputChipTokens.kt +30 -0
  96. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/LargeIconButtonTokens.kt +27 -0
  97. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/LinearProgressIndicatorTokens.kt +28 -0
  98. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/ListTokens.kt +57 -0
  99. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/LoadingIndicatorTokens.kt +21 -0
  100. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/MediumIconButtonTokens.kt +27 -0
  101. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/MotionTokens.kt +44 -0
  102. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/NavigationBarHorizontalItemTokens.kt +22 -0
  103. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/NavigationBarTokens.kt +23 -0
  104. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/NavigationBarVerticalItemTokens.kt +22 -0
  105. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/NavigationDrawerTokens.kt +23 -0
  106. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/NavigationRailBaselineItemTokens.kt +25 -0
  107. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/NavigationRailCollapsedTokens.kt +23 -0
  108. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/NavigationRailExpandedTokens.kt +22 -0
  109. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/NavigationRailHorizontalItemTokens.kt +24 -0
  110. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/NavigationRailVerticalItemTokens.kt +24 -0
  111. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/OutlinedAutocompleteTokens.kt +30 -0
  112. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/OutlinedButtonTokens.kt +19 -0
  113. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/OutlinedCardTokens.kt +21 -0
  114. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/OutlinedIconButtonTokens.kt +18 -0
  115. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/OutlinedSegmentedButtonTokens.kt +24 -0
  116. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/OutlinedTextFieldTokens.kt +31 -0
  117. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/PrimaryNavigationTabTokens.kt +24 -0
  118. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/RadioButtonTokens.kt +22 -0
  119. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/ScrimTokens.kt +17 -0
  120. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/SearchBarTokens.kt +20 -0
  121. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/SearchViewTokens.kt +20 -0
  122. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/SecondaryNavigationTabTokens.kt +21 -0
  123. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/SegmentedMenuTokens.kt +42 -0
  124. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/ShapeTokens.kt +74 -0
  125. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/SheetBottomTokens.kt +20 -0
  126. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/SliderTokens.kt +39 -0
  127. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/SmallIconButtonTokens.kt +27 -0
  128. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/SnackbarTokens.kt +21 -0
  129. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/SplitButtonLargeTokens.kt +26 -0
  130. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/SplitButtonMediumTokens.kt +26 -0
  131. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/SplitButtonSmallTokens.kt +26 -0
  132. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/SplitButtonXLargeTokens.kt +26 -0
  133. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/SplitButtonXSmallTokens.kt +27 -0
  134. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/StandardMenuTokens.kt +25 -0
  135. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/StandardMotionTokens.kt +27 -0
  136. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/StateTokens.kt +20 -0
  137. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/SuggestionChipTokens.kt +25 -0
  138. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/SwitchTokens.kt +37 -0
  139. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/TextButtonTokens.kt +18 -0
  140. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/TimeInputTokens.kt +24 -0
  141. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/TimePickerTokens.kt +30 -0
  142. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/TonalButtonTokens.kt +19 -0
  143. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/TypeScaleTokens.kt +72 -0
  144. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/VibrantMenuTokens.kt +26 -0
  145. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/XLargeIconButtonTokens.kt +27 -0
  146. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/assets/XSmallIconButtonTokens.kt +27 -0
  147. package/android/src/main/java/expo/modules/myui/extended-theme/assets/Tokens/index.kt +217 -0
  148. package/android/src/main/java/expo/modules/myui/extended-theme/index.kt +39 -0
  149. package/android/src/main/java/expo/modules/myui/utils/children.kt +127 -0
  150. package/android/src/main/java/expo/modules/myui/utils/modifiers.kt +45 -0
  151. package/package.json +2 -1
@@ -0,0 +1,60 @@
1
+ package expo.modules.myui.ListItem
2
+
3
+ import androidx.compose.foundation.layout.fillMaxWidth
4
+ import androidx.compose.runtime.Composable
5
+ import androidx.compose.ui.Modifier
6
+ import expo.modules.kotlin.views.ExpoComposeView
7
+ import expo.modules.kotlin.views.FunctionalComposableScope
8
+ import expo.modules.ui.SlotView
9
+
10
+ import expo.modules.myui.getModifier
11
+ import expo.modules.myui.section.sectionItemPosition
12
+ import expo.modules.myui.ListItem.ListItemDynamic
13
+ import expo.modules.myui.ListItem.Decorator
14
+ import expo.modules.myui.ListItem.RenderSlot
15
+ import expo.modules.myui.findChildBySlotName
16
+
17
+
18
+
19
+
20
+ // Crea el ListItem desde los slots
21
+
22
+ @Composable
23
+ internal fun FunctionalComposableScope.ListItemFromSlots(props: ListItemProps) {
24
+ val composeView = view as ExpoComposeView<*>
25
+ val sectionPosition = composeView.sectionItemPosition(props)
26
+
27
+ val isFirst = sectionPosition?.isFirst ?: (props.isFirst ?: true)
28
+ val isLast = sectionPosition?.isLast ?: (props.isLast ?: true)
29
+
30
+ val headlineSlot = findChildBySlotName("headlineContent")
31
+ val overlineSlot = findChildBySlotName("overlineContent")
32
+ val supportingSlot = findChildBySlotName("supportingContent")
33
+ val leadingSlot = findChildBySlotName("leadingContent")
34
+ val trailingSlot = findChildBySlotName("trailingContent")
35
+ Decorator(
36
+ isFirst = isFirst,
37
+ isLast = isLast,
38
+ showDivider = props.showDivider,
39
+ modifier = getModifier(props.modifiers),
40
+ ) { innerProps ->
41
+ ListItemDynamic(
42
+ props = props,
43
+ modifier = Modifier.fillMaxWidth(),
44
+ innerProps = innerProps,
45
+ leadingContent = leadingSlot?.let { slot -> { RenderSlot(slot) } },
46
+ overlineContent = overlineSlot?.let { slot -> { RenderSlot(slot) } },
47
+ supportingContent = supportingSlot?.let { slot -> { RenderSlot(slot) } },
48
+ headlineContent = headlineSlot?.let { slot -> { RenderSlot(slot) } },
49
+ trailingContent = trailingSlot?.let { slot -> { RenderSlot(slot) } },
50
+ )
51
+ }
52
+ }
53
+
54
+
55
+ @Composable
56
+ internal fun FunctionalComposableScope.RenderSlot(slot: SlotView) {
57
+ with(composableScope) {
58
+ with(slot) { Content() }
59
+ }
60
+ }
@@ -0,0 +1,42 @@
1
+ package expo.modules.myui.ListItem
2
+
3
+ import android.graphics.Color
4
+ import androidx.compose.ui.unit.Dp
5
+ import expo.modules.kotlin.records.Field
6
+ import expo.modules.kotlin.records.Record
7
+ import expo.modules.kotlin.types.OptimizedRecord
8
+ import expo.modules.kotlin.views.ComposeProps
9
+ import expo.modules.kotlin.views.OptimizedComposeProps
10
+ import expo.modules.ui.ModifierList
11
+
12
+
13
+
14
+ @OptimizedRecord
15
+ data class ListItemColorsRecord(
16
+ @Field val containerColor: Color? = null,
17
+ @Field val contentColor: Color? = null,
18
+ @Field val leadingContentColor: Color? = null,
19
+ @Field val trailingContentColor: Color? = null,
20
+ @Field val supportingContentColor: Color? = null,
21
+ @Field val overlineContentColor: Color? = null,
22
+ ) : Record
23
+
24
+ @OptimizedComposeProps
25
+ data class ListItemProps(
26
+
27
+ val showDivider: Boolean = true,
28
+ val isFirst: Boolean? = null,
29
+ val isLast: Boolean? = null,
30
+ val hasNavigationLink: Boolean? = null,
31
+
32
+ val tonalElevation: Float? = null,
33
+ val shadowElevation: Float? = null,
34
+ val colors: ListItemColorsRecord? = null,
35
+ val modifiers: ModifierList = emptyList(),
36
+
37
+ ) : ComposeProps
38
+
39
+ /** Props internas de Kotlin; el callback no puede venir del bridge JS. */
40
+ internal data class ListItemInnerProps(
41
+ val onLeadingWidthChanged: ((Dp) -> Unit)? = null,
42
+ )
@@ -0,0 +1,79 @@
1
+ package expo.modules.myui.ListItem
2
+
3
+ import androidx.compose.foundation.background
4
+ import androidx.compose.foundation.layout.Column
5
+ import androidx.compose.foundation.layout.fillMaxWidth
6
+ import androidx.compose.runtime.Composable
7
+ import androidx.compose.runtime.getValue
8
+ import androidx.compose.runtime.mutableStateOf
9
+ import androidx.compose.runtime.remember
10
+ import androidx.compose.runtime.setValue
11
+ import androidx.compose.ui.Modifier
12
+ import androidx.compose.ui.draw.clip
13
+ import androidx.compose.ui.unit.dp
14
+
15
+ import expo.modules.myui.theme.ExtendedTheme
16
+
17
+
18
+
19
+ /*
20
+
21
+ Decorator para el ListItem
22
+
23
+ Agrega:
24
+
25
+ - Background
26
+ - Shape
27
+ - Divider
28
+
29
+ Tiene la logica interna del LeadingWidth
30
+
31
+ */
32
+
33
+ @Composable
34
+ internal fun Decorator(
35
+ isFirst: Boolean,
36
+ isLast: Boolean,
37
+ showDivider: Boolean = true,
38
+ modifier: Modifier = Modifier,
39
+ content: @Composable (ListItemInnerProps) -> Unit,
40
+
41
+ ) {
42
+
43
+ val shouldShowDivider = showDivider && !isLast
44
+ val backgroundColor = ExtendedTheme.colorScheme.secondarySystemGroupedBackground
45
+ val shape =
46
+ if (isFirst || isLast) {
47
+ itemClipShape(isFirst, isLast)
48
+ } else {
49
+ null
50
+ }
51
+
52
+ var leadingWidth by remember { mutableStateOf(0.dp) }
53
+ val shapeModifier = if (shape != null) {
54
+ Modifier.clip(shape).background(backgroundColor, shape)
55
+ } else {
56
+ Modifier.background(backgroundColor)
57
+ }
58
+
59
+ // clickable debe ir después de clip para que el ripple respete las esquinas
60
+ val rowModifier = Modifier
61
+ .fillMaxWidth()
62
+ .then(shapeModifier)
63
+ .then(modifier)
64
+
65
+ Column(modifier = rowModifier) {
66
+ content(
67
+ ListItemInnerProps(
68
+ onLeadingWidthChanged =
69
+ if (shouldShowDivider) {
70
+ { width -> if (width != leadingWidth) { leadingWidth = width } }
71
+ } else {
72
+ null
73
+ },
74
+ ),
75
+ )
76
+
77
+ if (shouldShowDivider) { ListItemDivider(leadingWidth = leadingWidth) }
78
+ }
79
+ }
@@ -0,0 +1,36 @@
1
+ package expo.modules.myui.ListItem
2
+
3
+ import androidx.compose.foundation.layout.fillMaxWidth
4
+ import androidx.compose.foundation.layout.padding
5
+ import androidx.compose.material3.HorizontalDivider
6
+ import androidx.compose.runtime.Composable
7
+ import androidx.compose.ui.Modifier
8
+ import androidx.compose.ui.unit.Dp
9
+ import androidx.compose.ui.unit.dp
10
+
11
+ import expo.modules.myui.theme.ExtendedTheme
12
+ import expo.modules.myui.theme.tokens.ListTokens
13
+
14
+
15
+
16
+ /* Crea el divider segun el leadingWidth */
17
+
18
+ @Composable
19
+ internal fun ListItemDivider(leadingWidth: Dp) {
20
+ val leadingInset = if (leadingWidth > 0.dp) {
21
+ leadingWidth + ListTokens.ItemBetweenSpace + 4.dp // +4.dp porque tiene que dar 16.dp
22
+ } else {
23
+ 0.dp
24
+ }
25
+
26
+ HorizontalDivider(
27
+ modifier = Modifier
28
+ .fillMaxWidth()
29
+ .padding(
30
+ start = ListTokens.DividerLeadingSpace + leadingInset,
31
+ end = ListTokens.DividerTrailingSpace,
32
+ ),
33
+ color = ExtendedTheme.colorScheme.separator.copy(alpha = 0.4f),
34
+ thickness = 1.dp,
35
+ )
36
+ }
@@ -0,0 +1,19 @@
1
+ package expo.modules.myui.ListItem
2
+
3
+ import androidx.compose.foundation.shape.RoundedCornerShape
4
+ import androidx.compose.ui.unit.dp
5
+
6
+ import expo.modules.myui.theme.tokens.ShapeTokens
7
+
8
+
9
+
10
+ private val GroupCornerRadius = ShapeTokens.CornerValueExtraLarge
11
+
12
+ internal fun itemClipShape(isFirst: Boolean, isLast: Boolean): RoundedCornerShape {
13
+ return RoundedCornerShape(
14
+ topStart = if (isFirst) GroupCornerRadius else 0.dp,
15
+ topEnd = if (isFirst) GroupCornerRadius else 0.dp,
16
+ bottomStart = if (isLast) GroupCornerRadius else 0.dp,
17
+ bottomEnd = if (isLast) GroupCornerRadius else 0.dp,
18
+ )
19
+ }
@@ -0,0 +1,163 @@
1
+ package expo.modules.myui.ListItem
2
+
3
+ import androidx.compose.foundation.layout.Box
4
+ import androidx.compose.foundation.layout.fillMaxWidth
5
+ import androidx.compose.foundation.layout.size
6
+ import androidx.compose.material.icons.Icons
7
+ import androidx.compose.material.icons.rounded.ArrowForwardIos
8
+ import androidx.compose.material3.Icon
9
+ import androidx.compose.material3.ListItem as ListItemMaterial
10
+ import androidx.compose.material3.ListItemDefaults
11
+ import androidx.compose.material3.Surface
12
+ import androidx.compose.runtime.Composable
13
+ import androidx.compose.ui.Alignment
14
+ import androidx.compose.ui.Modifier
15
+ import androidx.compose.ui.graphics.Color
16
+ import androidx.compose.ui.graphics.Color as ComposeColor
17
+ import androidx.compose.ui.layout.onSizeChanged
18
+ import androidx.compose.ui.platform.LocalDensity
19
+ import androidx.compose.ui.unit.dp
20
+ import expo.modules.ui.composeOrNull
21
+
22
+ import expo.modules.myui.TypographySlot.SlotTypography
23
+ import expo.modules.myui.theme.ExtendedTheme
24
+
25
+
26
+
27
+ /*
28
+
29
+ ListItemDynamic es el componente que se encarga de la logica interna del ListItem
30
+
31
+ Se encarga de poner visualmente:
32
+
33
+ - LeadingContent
34
+ - HeadlineContent
35
+ - TrailingContent
36
+ - OverlineContent
37
+ - SupportingContent
38
+
39
+ */
40
+
41
+ @Composable
42
+ internal fun ListItemDynamic(
43
+ props: ListItemProps = ListItemProps(),
44
+ modifier: Modifier = Modifier,
45
+ innerProps: ListItemInnerProps = ListItemInnerProps(),
46
+ leadingContent: (@Composable () -> Unit)? = null,
47
+ headlineContent: (@Composable () -> Unit)? = null,
48
+ trailingContent: (@Composable () -> Unit)? = null,
49
+ overlineContent: (@Composable () -> Unit)? = null,
50
+ supportingContent: (@Composable () -> Unit)? = null,
51
+ ) {
52
+ val density = LocalDensity.current
53
+
54
+ val colors = listItemColors(props)
55
+
56
+ ListItemMaterial(
57
+ modifier = modifier,
58
+ colors = colors,
59
+ tonalElevation = props.tonalElevation?.dp ?: ListItemDefaults.Elevation,
60
+ shadowElevation = props.shadowElevation?.dp ?: ListItemDefaults.Elevation,
61
+ supportingContent = supportingContent?.let { content ->
62
+ { StyledSlotContent("supportingcontent", colors.supportingContentColor, content) }
63
+ },
64
+ leadingContent = leadingContent?.let { content ->
65
+ {
66
+ val styledContent: @Composable () -> Unit = {
67
+ StyledSlotContent("leadingcontent", colors.leadingContentColor, content)
68
+ }
69
+ val onLeadingWidthChanged = innerProps.onLeadingWidthChanged
70
+ if (onLeadingWidthChanged != null) {
71
+ Box(
72
+ modifier = Modifier.onSizeChanged { size ->
73
+ onLeadingWidthChanged(with(density) { size.width.toDp() })
74
+ },
75
+ ) {
76
+ styledContent()
77
+ }
78
+ } else {
79
+ styledContent()
80
+ }
81
+ }
82
+ },
83
+ overlineContent = overlineContent?.let { content ->
84
+ { StyledSlotContent("overlinecontent", colors.overlineContentColor, content) }
85
+ },
86
+ headlineContent = {
87
+ when {
88
+ headlineContent == null && trailingContent == null -> Unit
89
+ trailingContent == null -> {
90
+ Box(modifier = Modifier.fillMaxWidth()) {
91
+ headlineContent?.let { content ->
92
+ StyledSlotContent("headlinecontent", colors.contentColor, content)
93
+ }
94
+ }
95
+ }
96
+ headlineContent == null -> {
97
+ Box(
98
+ modifier = Modifier.fillMaxWidth(),
99
+ contentAlignment = Alignment.CenterEnd,
100
+ ) {
101
+ StyledSlotContent("trailingcontent", colors.trailingContentColor, trailingContent)
102
+ }
103
+ }
104
+ else -> {
105
+ DynamicRow(
106
+ first = { StyledSlotContent("headlinecontent", colors.contentColor, headlineContent) },
107
+ second = { StyledSlotContent("trailingcontent", colors.trailingContentColor, trailingContent) },
108
+ )
109
+ }
110
+ }
111
+ },
112
+ trailingContent = if (props.hasNavigationLink == true) {
113
+ {
114
+ Icon(
115
+ imageVector = Icons.Rounded.ArrowForwardIos,
116
+ contentDescription = null,
117
+ tint = ExtendedTheme.colorScheme.tertiaryLabel,
118
+ modifier = Modifier.size(17.dp),
119
+ )
120
+ }
121
+ } else {
122
+ null
123
+ },
124
+ )
125
+ }
126
+
127
+
128
+ @Composable
129
+ internal fun listItemColors(props: ListItemProps) = ListItemDefaults.colors(
130
+ containerColor = props.colors?.containerColor.composeOrNull ?: ComposeColor.Transparent,
131
+ contentColor = props.colors?.contentColor.composeOrNull ?: ExtendedTheme.colorScheme.label,
132
+ leadingContentColor = props.colors?.leadingContentColor.composeOrNull ?: ExtendedTheme.colorScheme.link,
133
+ trailingContentColor = props.colors?.trailingContentColor.composeOrNull ?: ExtendedTheme.colorScheme.secondaryLabel,
134
+ supportingContentColor = props.colors?.supportingContentColor.composeOrNull ?: ExtendedTheme.colorScheme.secondaryLabel,
135
+ overlineContentColor = props.colors?.overlineContentColor.composeOrNull ?: ExtendedTheme.colorScheme.secondaryLabel,
136
+ )
137
+
138
+ @Composable
139
+ private fun SlotContentColor(
140
+ contentColor: Color?,
141
+ content: @Composable () -> Unit,
142
+ ) {
143
+ if (contentColor != null) {
144
+ Surface(color = Color.Transparent, contentColor = contentColor) {
145
+ content()
146
+ }
147
+ } else {
148
+ content()
149
+ }
150
+ }
151
+
152
+ @Composable
153
+ private fun StyledSlotContent(
154
+ slotName: String,
155
+ contentColor: Color?,
156
+ content: @Composable () -> Unit,
157
+ ) {
158
+ SlotContentColor(contentColor) {
159
+ SlotTypography(slotName) {
160
+ content()
161
+ }
162
+ }
163
+ }
@@ -0,0 +1,136 @@
1
+ package expo.modules.myui.ListItem
2
+
3
+ import androidx.compose.foundation.layout.Box
4
+ import androidx.compose.foundation.layout.fillMaxWidth
5
+ import androidx.compose.foundation.layout.wrapContentWidth
6
+ import androidx.compose.runtime.Composable
7
+ import androidx.compose.ui.Alignment
8
+ import androidx.compose.ui.Modifier
9
+ import androidx.compose.ui.layout.SubcomposeLayout
10
+ import androidx.compose.ui.unit.Constraints
11
+ import androidx.compose.ui.unit.Dp
12
+ import kotlin.math.max
13
+
14
+ import expo.modules.myui.theme.tokens.ListTokens
15
+
16
+
17
+
18
+ /**
19
+ * Headline + trailing en una fila.
20
+ *
21
+ * - Caben con ancho natural: headline al inicio, trailing al final.
22
+ * - No caben: el que no supera la mitad queda en su ancho natural; el otro ocupa el resto.
23
+ * - Si ambos superan la mitad: reparto 50/50.
24
+ */
25
+
26
+ @Composable
27
+ internal fun DynamicRow(
28
+ modifier: Modifier = Modifier,
29
+ spacing: Dp = ListTokens.ItemBetweenSpace,
30
+ first: @Composable () -> Unit,
31
+ second: @Composable () -> Unit,
32
+ ) {
33
+ SubcomposeLayout(
34
+ modifier = modifier.fillMaxWidth(),
35
+ ) { constraints ->
36
+ val spacingPx = spacing.roundToPx()
37
+ val maxWidth = constraints.maxWidth
38
+
39
+ val naturalConstraints = Constraints(
40
+ minWidth = 0,
41
+ maxWidth = maxWidth,
42
+ minHeight = 0,
43
+ maxHeight = constraints.maxHeight,
44
+ )
45
+
46
+ val firstNatural = subcompose(Slot.FirstMeasure) {
47
+ Box(Modifier.wrapContentWidth(Alignment.Start)) { first() }
48
+ }.first().measure(naturalConstraints)
49
+
50
+ val secondNatural = subcompose(Slot.SecondMeasure) {
51
+ Box(Modifier.wrapContentWidth(Alignment.End)) { second() }
52
+ }.first().measure(naturalConstraints)
53
+
54
+ val needsSplit = firstNatural.width + spacingPx + secondNatural.width > maxWidth
55
+
56
+ if (needsSplit) {
57
+ val available = max(0, maxWidth - spacingPx)
58
+ val halfWidth = available / 2
59
+ val firstExceedsHalf = firstNatural.width > halfWidth
60
+ val secondExceedsHalf = secondNatural.width > halfWidth
61
+
62
+ val firstWidth: Int
63
+ val secondWidth: Int
64
+ when {
65
+ firstExceedsHalf && !secondExceedsHalf -> {
66
+ secondWidth = secondNatural.width
67
+ firstWidth = available - secondWidth
68
+ }
69
+ secondExceedsHalf && !firstExceedsHalf -> {
70
+ firstWidth = firstNatural.width
71
+ secondWidth = available - firstWidth
72
+ }
73
+ else -> {
74
+ firstWidth = halfWidth
75
+ secondWidth = halfWidth
76
+ }
77
+ }
78
+
79
+ val firstConstraints = Constraints(
80
+ minWidth = firstWidth,
81
+ maxWidth = firstWidth,
82
+ minHeight = 0,
83
+ maxHeight = constraints.maxHeight,
84
+ )
85
+ val secondConstraints = Constraints(
86
+ minWidth = secondWidth,
87
+ maxWidth = secondWidth,
88
+ minHeight = 0,
89
+ maxHeight = constraints.maxHeight,
90
+ )
91
+
92
+ val firstSplit = subcompose(Slot.FirstSplit) {
93
+ Box(
94
+ modifier = Modifier.fillMaxWidth(),
95
+ contentAlignment = Alignment.CenterStart,
96
+ ) {
97
+ first()
98
+ }
99
+ }.first().measure(firstConstraints)
100
+
101
+ val secondSplit = subcompose(Slot.SecondSplit) {
102
+ Box(
103
+ modifier = Modifier.fillMaxWidth(),
104
+ contentAlignment = Alignment.CenterEnd,
105
+ ) {
106
+ second()
107
+ }
108
+ }.first().measure(secondConstraints)
109
+
110
+ val height = max(firstSplit.height, secondSplit.height).coerceAtLeast(constraints.minHeight)
111
+
112
+ layout(maxWidth, height) {
113
+ val firstY = (height - firstSplit.height) / 2
114
+ val secondY = (height - secondSplit.height) / 2
115
+ firstSplit.placeRelative(0, firstY)
116
+ secondSplit.placeRelative(firstWidth + spacingPx, secondY)
117
+ }
118
+ } else {
119
+ val height = max(firstNatural.height, secondNatural.height).coerceAtLeast(constraints.minHeight)
120
+
121
+ layout(maxWidth, height) {
122
+ val firstY = (height - firstNatural.height) / 2
123
+ val secondY = (height - secondNatural.height) / 2
124
+ firstNatural.placeRelative(0, firstY)
125
+ secondNatural.placeRelative(maxWidth - secondNatural.width, secondY)
126
+ }
127
+ }
128
+ }
129
+ }
130
+
131
+ private enum class Slot {
132
+ FirstMeasure,
133
+ SecondMeasure,
134
+ FirstSplit,
135
+ SecondSplit,
136
+ }
@@ -0,0 +1,48 @@
1
+ package expo.modules.myui.menu
2
+
3
+ import androidx.compose.foundation.layout.Box
4
+ import androidx.compose.foundation.layout.widthIn
5
+ import androidx.compose.material3.DropdownMenu
6
+ import androidx.compose.material3.MenuDefaults
7
+ import androidx.compose.runtime.Composable
8
+ import androidx.compose.ui.Modifier
9
+ import androidx.compose.ui.platform.LocalConfiguration
10
+ import androidx.compose.ui.unit.dp
11
+ import expo.modules.kotlin.views.FunctionalComposableScope
12
+ import expo.modules.myui.theme.tokens.ShapeTokens
13
+ import expo.modules.ui.ModifierRegistry
14
+ import expo.modules.ui.UIComposableScope
15
+ import expo.modules.ui.composeOrNull
16
+ import expo.modules.ui.findChildSlotView
17
+ import expo.modules.ui.isSlotView
18
+
19
+ private val HorizontalScreenInset = 16.dp
20
+
21
+ @Composable
22
+ fun FunctionalComposableScope.DropdownMenuContent(
23
+ props: DropdownMenuProps,
24
+ onDismissRequest: () -> Unit
25
+ ) {
26
+ val itemsSlotView = findChildSlotView(view, "items")
27
+ val maxMenuWidth = LocalConfiguration.current.screenWidthDp.dp - HorizontalScreenInset * 2
28
+
29
+ Box(modifier = ModifierRegistry.applyModifiers(props.modifiers, appContext, composableScope, globalEventDispatcher)) {
30
+ Children(UIComposableScope(), filter = { !isSlotView(it) })
31
+
32
+ DropdownMenu(
33
+ containerColor = props.color?.composeOrNull ?: MenuDefaults.containerColor,
34
+ expanded = props.expanded,
35
+ onDismissRequest = onDismissRequest,
36
+ shape = ShapeTokens.CornerExtraLarge,
37
+ modifier = Modifier.widthIn(max = maxMenuWidth),
38
+ ) {
39
+ itemsSlotView?.let {
40
+ with(UIComposableScope()) {
41
+ with(it) {
42
+ Content()
43
+ }
44
+ }
45
+ }
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,20 @@
1
+ package expo.modules.myui.menu
2
+
3
+ import android.graphics.Color
4
+ import expo.modules.kotlin.types.Enumerable
5
+ import expo.modules.kotlin.views.ComposeProps
6
+ import expo.modules.ui.ModifierList
7
+ import expo.modules.kotlin.views.OptimizedComposeProps
8
+
9
+ enum class ActivationMethod(val value: String) : Enumerable {
10
+ SINGLE_PRESS("singlePress"),
11
+ LONG_PRESS("longPress")
12
+ }
13
+
14
+ @OptimizedComposeProps
15
+ data class DropdownMenuProps(
16
+ val activationMethod: ActivationMethod = ActivationMethod.SINGLE_PRESS,
17
+ val expanded: Boolean = false,
18
+ val color: Color? = null,
19
+ val modifiers: ModifierList = emptyList()
20
+ ) : ComposeProps
@@ -0,0 +1,94 @@
1
+ package expo.modules.myui
2
+
3
+ import android.graphics.Color as AndroidColor
4
+ import androidx.compose.foundation.layout.heightIn
5
+ import androidx.compose.ui.Modifier
6
+ import androidx.compose.ui.draw.drawBehind
7
+ import androidx.compose.ui.geometry.Offset
8
+ import androidx.compose.ui.graphics.Brush
9
+ import androidx.compose.ui.graphics.Color as ComposeColor
10
+ import androidx.compose.ui.platform.LocalConfiguration
11
+ import androidx.compose.ui.unit.Dp
12
+ import androidx.compose.ui.unit.dp
13
+ import expo.modules.ui.ModifierRegistry
14
+ import expo.modules.ui.columnScope
15
+ import expo.modules.ui.rowScope
16
+
17
+ private fun normalizeColorString(s: String): String {
18
+ val t = s.trim()
19
+ return if (t.startsWith("#")) t else "#$t"
20
+ }
21
+
22
+ /**
23
+ * Registra modificadores extra para Jetpack Compose (p. ej. degradados con [Brush]).
24
+ * Debe llamarse al crear el módulo nativo; [ModifierRegistry] es el mismo que usa @expo/ui.
25
+ */
26
+ fun registerModifiers() {
27
+
28
+ // --------------------------- backgroundLinearGradient---------------------------
29
+
30
+ ModifierRegistry.register("backgroundLinearGradient") { map, _, _, _ ->
31
+ val raw = map["colors"] as? List<*> ?: return@register Modifier
32
+ val composeColors = raw.mapNotNull { item ->
33
+ val hex = (item as? String)?.trim()?.takeIf { it.isNotEmpty() } ?: return@mapNotNull null
34
+ runCatching {
35
+ val argb = AndroidColor.parseColor(normalizeColorString(hex))
36
+ ComposeColor(argb)
37
+ }.getOrNull()
38
+ }
39
+ if (composeColors.size < 2) return@register Modifier
40
+
41
+ val sx = (map["startX"] as? Number)?.toFloat() ?: 0f
42
+ val sy = (map["startY"] as? Number)?.toFloat() ?: 0f
43
+ val ex = (map["endX"] as? Number)?.toFloat() ?: 0f
44
+ val ey = (map["endY"] as? Number)?.toFloat() ?: 1f
45
+
46
+ Modifier.drawBehind {
47
+ val brush = Brush.linearGradient(
48
+ colors = composeColors,
49
+ start = Offset(size.width * sx, size.height * sy),
50
+ end = Offset(size.width * ex, size.height * ey)
51
+ )
52
+ drawRect(brush = brush, size = size)
53
+ }
54
+ }
55
+
56
+ // --------------------------- heightIn ------------------------------------------
57
+
58
+ ModifierRegistry.register("heightIn") { map, _, _, _ ->
59
+ val minDp = (map["min"] as? Number)?.toFloat()
60
+ val maxDp = (map["max"] as? Number)?.toFloat()
61
+ val minFraction = (map["minFraction"] as? Number)?.toFloat()
62
+ val maxFraction = (map["maxFraction"] as? Number)?.toFloat()
63
+
64
+ val screenHeightDp = LocalConfiguration.current.screenHeightDp.toFloat()
65
+
66
+ val resolvedMin = when {
67
+ minDp != null -> minDp.dp
68
+ minFraction != null -> (screenHeightDp * minFraction).dp
69
+ else -> Dp.Unspecified
70
+ }
71
+ val resolvedMax = when {
72
+ maxFraction != null -> (screenHeightDp * maxFraction).dp
73
+ maxDp != null -> maxDp.dp
74
+ else -> Dp.Unspecified
75
+ }
76
+
77
+ Modifier.heightIn(min = resolvedMin, max = resolvedMax)
78
+ }
79
+
80
+ // --------------------------- flexWeight ----------------------------------------
81
+
82
+ ModifierRegistry.register("flexWeight") { map, scope, _, _ ->
83
+ val weight = (map["weight"] as? Number)?.toFloat() ?: 1f
84
+ val fill = map["fill"] as? Boolean ?: false
85
+
86
+ scope?.rowScope?.run {
87
+ Modifier.weight(weight, fill = fill)
88
+ } ?: scope?.columnScope?.run {
89
+ Modifier.weight(weight, fill = fill)
90
+ } ?: Modifier
91
+ }
92
+
93
+ // -------------------------------------------------------------------------------
94
+ }