@momo-kits/native-kits 0.162.2-test.23-debug → 0.162.2-test.24-debug

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.
@@ -40,7 +40,7 @@ kotlin {
40
40
  }
41
41
 
42
42
  cocoapods {
43
- version = "0.162.2-test.23-debug"
43
+ version = "0.162.2-test.24-debug"
44
44
  summary = "IOS Shared module"
45
45
  homepage = "https://momo.vn"
46
46
  ios.deploymentTarget = "15.0"
@@ -129,8 +129,6 @@ actual fun LottieAnimation(
129
129
  currentOnEvent?.invoke(if (isPlaying) LottieEvent.Start else LottieEvent.Pause)
130
130
  }
131
131
 
132
- // Only fire finish once the animation has actually advanced (armed by a not-at-end frame) then
133
- // reaches the end, so a transient isAtEnd at init can't produce a spurious callback.
134
132
  LaunchedEffect(lottieState) {
135
133
  var armed = false
136
134
  snapshotFlow { lottieState.isAtEnd }.collect { atEnd ->
@@ -1,2 +1,65 @@
1
1
  package vn.momo.kits.layout
2
2
 
3
+ import androidx.compose.foundation.background
4
+ import androidx.compose.foundation.layout.Arrangement
5
+ import androidx.compose.foundation.layout.Box
6
+ import androidx.compose.foundation.layout.BoxWithConstraints
7
+ import androidx.compose.foundation.layout.ExperimentalLayoutApi
8
+ import androidx.compose.foundation.layout.FlowRow
9
+ import androidx.compose.foundation.layout.fillMaxWidth
10
+ import androidx.compose.foundation.layout.padding
11
+ import androidx.compose.foundation.shape.RoundedCornerShape
12
+ import androidx.compose.runtime.Composable
13
+ import androidx.compose.runtime.CompositionLocalProvider
14
+ import androidx.compose.ui.Modifier
15
+ import androidx.compose.ui.draw.clip
16
+ import androidx.compose.ui.draw.shadow
17
+ import androidx.compose.ui.unit.dp
18
+ import vn.momo.kits.components.Image
19
+ import vn.momo.kits.const.AppTheme
20
+ import vn.momo.kits.const.Radius
21
+
22
+ /**
23
+ * A white rounded surface card that lays its [Item]s on a 12-column grid
24
+ * (React kit foundations/Layout/Card). 8dp gutter, 12dp padding, 12dp
25
+ * horizontal margin, Radius.M corners, background = theme surface, optional
26
+ * shadow or [backgroundImage]. Items flow left-to-right and wrap.
27
+ */
28
+ @OptIn(ExperimentalLayoutApi::class)
29
+ @Composable
30
+ fun Card(
31
+ useShadow: Boolean = false,
32
+ backgroundImage: String? = null,
33
+ modifier: Modifier = Modifier,
34
+ content: @Composable () -> Unit,
35
+ ) {
36
+ val columns = 12
37
+ val gutter = 8.dp
38
+ val shape = RoundedCornerShape(Radius.M)
39
+ var surface = modifier.fillMaxWidth().padding(horizontal = 12.dp)
40
+ if (useShadow) surface = surface.shadow(4.dp, shape)
41
+ surface = surface.clip(shape)
42
+ // The React kit drops the surface colour when a backgroundImage is supplied
43
+ // (`!!backgroundImage && { backgroundColor: undefined }`).
44
+ if (backgroundImage == null) surface = surface.background(AppTheme.current.colors.background.surface)
45
+ Box(modifier = surface) {
46
+ // React renders this as an absolutely-filled child BEHIND the content
47
+ // (styles.imageBackground: position absolute, inset 0) — matchParentSize
48
+ // fills the card without contributing to its measured size.
49
+ if (backgroundImage != null) {
50
+ Image(source = backgroundImage, modifier = Modifier.matchParentSize())
51
+ }
52
+ BoxWithConstraints(modifier = Modifier.fillMaxWidth().padding(12.dp)) {
53
+ // `- 1.dp / columns` mirrors the React kit's `- 1 / numberOfColumns`
54
+ // nudge: it keeps a full 12-span Item ~1dp narrower than the content
55
+ // box so sub-pixel rounding can never overflow and wrap the FlowRow.
56
+ val sizePerSpan = (maxWidth - gutter * (columns - 1)) / columns - 1.dp / columns
57
+ CompositionLocalProvider(LocalGridContext provides GridContext(columns, gutter, sizePerSpan)) {
58
+ FlowRow(
59
+ horizontalArrangement = Arrangement.spacedBy(gutter),
60
+ verticalArrangement = Arrangement.spacedBy(gutter),
61
+ ) { content() }
62
+ }
63
+ }
64
+ }
65
+ }
@@ -4,32 +4,45 @@ import androidx.compose.foundation.layout.Box
4
4
  import androidx.compose.foundation.layout.height
5
5
  import androidx.compose.foundation.layout.width
6
6
  import androidx.compose.runtime.Composable
7
+ import androidx.compose.runtime.compositionLocalOf
7
8
  import androidx.compose.ui.Modifier
8
9
  import androidx.compose.ui.unit.Dp
10
+ import androidx.compose.ui.unit.dp
9
11
 
12
+ /**
13
+ * Grid context supplied by [Section] / [Card]: the per-span cell size + gutter,
14
+ * so an [Item] can resolve its pixel width from a 1-12 `widthSpan`. Mirrors the
15
+ * React kit's GridContext (foundations/Layout/GridSystem).
16
+ */
10
17
  data class GridContext(
11
- val numberOfColumns: Number,
12
- val gutterSize: Number,
13
- val sizePerSpan: Number,
14
- val getSizeSpan: (Number) -> Number
15
- )
18
+ val numberOfColumns: Int = 12,
19
+ val gutter: Dp = 12.dp,
20
+ val sizePerSpan: Dp = 0.dp,
21
+ ) {
22
+ /** Width covering `span` columns + the (span-1) gutters between them. */
23
+ fun sizeForSpan(span: Int): Dp = sizePerSpan * span + gutter * (span - 1)
24
+ }
25
+
26
+ /** Provided by Section/Card; null when an Item is rendered outside a grid. */
27
+ val LocalGridContext = compositionLocalOf<GridContext?> { null }
16
28
 
29
+ /**
30
+ * A grid cell. `widthSpan` (1-12) sets the width as a fraction of the parent
31
+ * Section/Card; the parent's flex-wrap flows the cells into rows. Rendered
32
+ * outside a grid it just wraps its content at its natural size.
33
+ */
17
34
  @Composable
18
35
  fun Item(
19
- heightSpan: Number = 1,
20
- widthSpan: Number = 1,
21
- content: @Composable () -> Unit,
36
+ widthSpan: Int = 12,
37
+ heightSpan: Int = 0,
22
38
  modifier: Modifier = Modifier,
23
- grid: GridContext
39
+ content: @Composable () -> Unit,
24
40
  ) {
25
-
26
- val widthItem = grid.getSizeSpan(widthSpan)
27
- val heightItem = grid.getSizeSpan(heightSpan)
28
-
29
- Box(
30
- modifier = modifier.width(width = Dp(widthItem.toFloat()))
31
- .height(height = Dp(heightItem.toFloat()))
32
- ) {
33
- content()
41
+ val grid = LocalGridContext.current
42
+ var m = modifier
43
+ if (grid != null) {
44
+ m = m.width(grid.sizeForSpan(widthSpan))
45
+ if (heightSpan > 0) m = m.height(grid.sizeForSpan(heightSpan))
34
46
  }
35
- }
47
+ Box(modifier = m) { content() }
48
+ }
@@ -1,2 +1,51 @@
1
1
  package vn.momo.kits.layout
2
2
 
3
+ import androidx.compose.foundation.layout.Arrangement
4
+ import androidx.compose.foundation.layout.Box
5
+ import androidx.compose.foundation.layout.BoxWithConstraints
6
+ import androidx.compose.foundation.layout.ExperimentalLayoutApi
7
+ import androidx.compose.foundation.layout.FlowRow
8
+ import androidx.compose.foundation.layout.fillMaxWidth
9
+ import androidx.compose.foundation.layout.padding
10
+ import androidx.compose.runtime.Composable
11
+ import androidx.compose.runtime.CompositionLocalProvider
12
+ import androidx.compose.ui.Modifier
13
+ import androidx.compose.ui.unit.dp
14
+ import vn.momo.kits.components.Image
15
+
16
+ /**
17
+ * A transparent 12-column grid row that wraps its [Item]s (React kit
18
+ * foundations/Layout/Section). 12dp gutter; 12dp horizontal margin when
19
+ * `useMargin`; optional [backgroundImage]. Items flow left-to-right and wrap.
20
+ */
21
+ @OptIn(ExperimentalLayoutApi::class)
22
+ @Composable
23
+ fun Section(
24
+ useMargin: Boolean = true,
25
+ backgroundImage: String? = null,
26
+ modifier: Modifier = Modifier,
27
+ content: @Composable () -> Unit,
28
+ ) {
29
+ val columns = 12
30
+ val gutter = 12.dp
31
+ val margin = if (useMargin) 12.dp else 0.dp
32
+ Box(modifier = modifier.fillMaxWidth().padding(horizontal = margin)) {
33
+ // React renders this as an absolutely-filled child behind the content
34
+ // (styles.imageBackground: position absolute, inset 0).
35
+ if (backgroundImage != null) {
36
+ Image(source = backgroundImage, modifier = Modifier.matchParentSize())
37
+ }
38
+ BoxWithConstraints(modifier = Modifier.fillMaxWidth()) {
39
+ // `- 1.dp / columns` mirrors the React kit's `- 1 / numberOfColumns`
40
+ // nudge — keeps a full 12-span Item ~1dp inside the content box so
41
+ // sub-pixel rounding can never overflow and wrap the FlowRow.
42
+ val sizePerSpan = (maxWidth - gutter * (columns - 1)) / columns - 1.dp / columns
43
+ CompositionLocalProvider(LocalGridContext provides GridContext(columns, gutter, sizePerSpan)) {
44
+ FlowRow(
45
+ horizontalArrangement = Arrangement.spacedBy(gutter),
46
+ verticalArrangement = Arrangement.spacedBy(gutter),
47
+ ) { content() }
48
+ }
49
+ }
50
+ }
51
+ }
@@ -24,6 +24,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
24
24
  import androidx.compose.runtime.Composable
25
25
  import androidx.compose.runtime.DisposableEffect
26
26
  import androidx.compose.runtime.LaunchedEffect
27
+ import androidx.compose.runtime.mutableStateOf
27
28
  import androidx.compose.runtime.remember
28
29
  import androidx.compose.runtime.rememberCoroutineScope
29
30
  import androidx.compose.ui.Alignment
@@ -101,7 +102,11 @@ internal fun BottomSheet(
101
102
  )
102
103
  }
103
104
 
105
+ val isClosing = remember { mutableStateOf(false) }
106
+
104
107
  fun closeEvent(){
108
+ if (isClosing.value) return
109
+ isClosing.value = true
105
110
  coroutineScope.launch {
106
111
  sheetOffset.animateTo(
107
112
  targetValue = screenHeightPx,
@@ -71,7 +71,11 @@ internal fun ModalScreen(
71
71
  }
72
72
  }
73
73
 
74
+ val isClosing = remember { mutableStateOf(false) }
75
+
74
76
  fun closeEvent() {
77
+ if (isClosing.value) return
78
+ isClosing.value = true
75
79
  coroutineScope.launch {
76
80
  alpha.animateTo(
77
81
  targetValue = 0f,
package/gradle.properties CHANGED
@@ -18,7 +18,7 @@ kotlin.apple.xcodeCompatibility.nowarn=true
18
18
  name="ComposeKits"
19
19
  group=vn.momo.kits
20
20
  artifact.id=kits
21
- version=0.162.2-test.23
21
+ version=0.162.2-test.24
22
22
 
23
23
  repo=GitLab
24
24
  url=https://gitlab.mservice.com.vn/api/v4/projects/5400/packages/maven
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/native-kits",
3
- "version": "0.162.2-test.23-debug",
3
+ "version": "0.162.2-test.24-debug",
4
4
  "private": false,
5
5
  "dependencies": {},
6
6
  "devDependencies": {},
package/publish.sh CHANGED
@@ -251,6 +251,9 @@ phase_publish_maven() {
251
251
 
252
252
  # Temporarily remove composeResources and compose { resources { ... } } block
253
253
  echo "📦 Backing up sample/shared composeResources and build.gradle.kts..."
254
+ # mv into an existing dir nests instead of renaming, so a backup left behind by a
255
+ # crashed run must be cleared first or the restore below puts back the wrong tree.
256
+ rm -rf sample/shared/src/commonMain/composeResources.backup
254
257
  if [ -d "sample/shared/src/commonMain/composeResources" ]; then
255
258
  mv sample/shared/src/commonMain/composeResources sample/shared/src/commonMain/composeResources.backup
256
259
  fi