@momo-kits/native-kits 0.163.1-beta.8-debug → 0.163.1-beta.9-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.
- package/CLAUDE.md +1 -1
- package/compose/build.gradle.kts +1 -1
- package/compose/compose.podspec +1 -1
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +7 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +30 -3
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +5 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +3 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +56 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +4 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +22 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +8 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +63 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +32 -19
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +49 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +3 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +93 -75
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +26 -7
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +3 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +23 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +9 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +11 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +66 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +26 -3
- package/gradle.properties +1 -1
- package/ios/Application/ApplicationEnvironment.swift +15 -2
- package/ios/Application/Components.swift +50 -44
- package/ios/Application/FloatingButton.swift +10 -9
- package/ios/Application/HeaderRight.swift +79 -45
- package/ios/Application/Localize.swift +277 -0
- package/ios/Application/MaxApi.swift +18 -0
- package/ios/Application/Navigation/BottomTab/BottomTab.swift +104 -0
- package/ios/Application/Navigation/BottomTab/BottomTabBar.swift +215 -0
- package/ios/Application/Navigation/BottomTab/CurvedContainer.swift +65 -0
- package/ios/Application/Navigation/HeaderBackProps.swift +66 -0
- package/ios/Application/Navigation/HeaderTitle.swift +57 -0
- package/ios/Application/Navigation/HeaderUser.swift +209 -0
- package/ios/Application/Navigation/NavigationContainer.swift +200 -0
- package/ios/Application/Navigation/NavigationOptions.swift +109 -0
- package/ios/Application/Navigation/Navigator.swift +385 -0
- package/ios/Application/Navigation/Overplay/BottomSheet.swift +256 -0
- package/ios/Application/Navigation/Overplay/ModalScreen.swift +74 -0
- package/ios/Application/Navigation/Overplay/SnackBar.swift +144 -0
- package/ios/Application/Navigation/Tracking/ScreenTracker.swift +117 -0
- package/ios/Application/Navigation/component/Header.swift +178 -0
- package/ios/Application/Navigation/component/HeaderBackground.swift +83 -0
- package/ios/Application/Navigation/component/HeaderColor.swift +65 -0
- package/ios/Application/Screen.swift +2 -1
- package/ios/Application/StackScreen.swift +501 -0
- package/ios/Avatar/Avatar.swift +193 -0
- package/ios/Badge/Badge.swift +11 -14
- package/ios/Badge/BadgeRibbon.swift +92 -21
- package/ios/BaselineView/BaselineView.swift +163 -0
- package/ios/Button/Button.swift +124 -29
- package/ios/Carousel/Carousel.swift +196 -0
- package/ios/Checkbox/Checkbox.swift +23 -28
- package/ios/Chip/Chip.swift +56 -33
- package/ios/Collapse/Collapse.swift +192 -0
- package/ios/Colors+Radius+Spacing/Colors.swift +20 -17
- package/ios/Colors+Radius+Spacing/Spacing.swift +3 -1
- package/ios/Colors+Radius+Spacing/Theme.swift +295 -0
- package/ios/DateTimePicker/DateTimePicker.swift +212 -0
- package/ios/DateTimePicker/DateTimePickerTypes.swift +55 -0
- package/ios/DateTimePicker/DateTimePickerUtils.swift +167 -0
- package/ios/DateTimePicker/WheelPicker.swift +165 -0
- package/ios/Divider/Divider.swift +16 -0
- package/ios/Extensions/ActiveOpacityButtonStyle.swift +14 -0
- package/ios/Extensions/Color++.swift +32 -0
- package/ios/Icon/Icon.swift +10 -1
- package/ios/IconButton/IconButton.swift +140 -0
- package/ios/Image/Image.swift +16 -3
- package/ios/Information/Information.swift +3 -1
- package/ios/Input/ErrorView.swift +3 -1
- package/ios/Input/Input.swift +72 -33
- package/ios/Input/InputPhoneNumber.swift +33 -21
- package/ios/Input/InputSearch.swift +107 -48
- package/ios/Input/InputTextArea.swift +134 -64
- package/ios/InputDropDown/InputDropDown.swift +201 -0
- package/ios/InputMoney/InputMoney.swift +347 -0
- package/ios/InputOTP/InputOTP.swift +210 -0
- package/ios/Loader/Loader.swift +113 -0
- package/ios/MoMoUIKits.podspec +5 -0
- package/ios/Pagination/PaginationDot.swift +61 -0
- package/ios/Pagination/PaginationNumber.swift +35 -0
- package/ios/Pagination/PaginationScroll.swift +101 -0
- package/ios/Pagination/PaginationWhiteDot.swift +37 -0
- package/ios/Popup/PopupDisplay.swift +11 -20
- package/ios/Popup/PopupInput.swift +2 -8
- package/ios/Popup/PopupNotify.swift +218 -0
- package/ios/Popup/PopupPromotion.swift +16 -8
- package/ios/ProgressInfo/ProgressInfo.swift +296 -0
- package/ios/Radio/Radio.swift +69 -0
- package/ios/Rating/Rating.swift +82 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/AccentColor.colorset/Contents.json +11 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Background.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Border.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Card.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Contents.json +6 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Error.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Primary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/PrimaryDark.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/PrimaryLight.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Secondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Success.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Text.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/TextSecondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/Contents.json +9 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-default.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-disable.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-pressed.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-selected.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-surface.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-tonal.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-default.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-disable.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/gradient.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/primary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/secondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-container.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-primary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-secondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-default.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-disable.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-hint.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-secondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Warning.colorset/Contents.json +38 -0
- package/ios/Skeleton/Skeleton.swift +99 -0
- package/ios/Slider/Slider.swift +237 -0
- package/ios/Stepper/Stepper.swift +220 -0
- package/ios/Steps/Steps.swift +467 -0
- package/ios/SuggestAction/SuggestAction.swift +99 -0
- package/ios/Swipeable/SwipeCell.swift +187 -0
- package/ios/Swipeable/SwipeCellModel.swift +21 -0
- package/ios/Switch/Switch.swift +53 -28
- package/ios/TabView/TabView.swift +534 -0
- package/ios/Tag/Tag.swift +98 -0
- package/ios/Template/TrustBanner/TrustBanner.swift +6 -7
- package/ios/Title/Title.swift +269 -0
- package/ios/Tooltip/Tooltip.swift +485 -0
- package/ios/Typography/FontScaleStore.swift +19 -0
- package/ios/Typography/Text.swift +79 -5
- package/ios/Typography/Typography.swift +3 -0
- package/ios/Uploader/Uploader.swift +174 -0
- package/ios/native-kits.podspec +61 -8
- package/ios-demo/MoMoUIKitsDemo.podspec +20 -0
- package/ios-demo/README.md +120 -0
- package/ios-demo/Resources/dot_loading.json +558 -0
- package/ios-demo/Resources/icon.json +4052 -0
- package/ios-demo/Resources/lottie_circle_loader.json +1 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/DemoScaffold.swift +48 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsBadgeDemoView.swift +25 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsButtonDemoView.swift +26 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsCheckboxDemoView.swift +19 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsChipDemoView.swift +33 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsInputDemoView.swift +48 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsPopupDemoView.swift +21 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsRadioDemoView.swift +17 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsTypographyDemoView.swift +28 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/MoMoUIKitsDemoContext.swift +31 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/MoMoUIKitsDemoFactory.swift +24 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AnimatedHeaderDemo.swift +110 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AvatarDemo.swift +93 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BadgeDemo.swift +269 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BaselineView.swift +117 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BottomTabDemo.swift +89 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ButtonDemo.swift +100 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CarouselDemo.swift +126 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CheckboxDemo.swift +63 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ChipDemo.swift +20 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CollapseDemo.swift +93 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ContentView.swift +107 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DateTimePickerDemo.swift +124 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DividerDemo.swift +14 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/HeaderUserDemo.swift +49 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +279 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconButtonDemo.swift +58 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ImageDemo.swift +78 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InformationDemo.swift +138 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDemo.swift +111 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDropDownDemo.swift +136 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputMoneyDemo.swift +107 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputOTPDemo.swift +73 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputPhoneNumberDemo.swift +100 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputSearchDemo.swift +32 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputTextAreaDemo.swift +57 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LoaderDemo.swift +70 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LocalizeDemo.swift +188 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +229 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PaginationDemo.swift +72 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupDisplayDemo.swift +175 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupNotifyDemo.swift +121 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupPromotionDemo.swift +76 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ProgressInfoDemo.swift +89 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RadioDemo.swift +32 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RatingDemo.swift +56 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SkeletonDemo.swift +32 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SliderDemo.swift +150 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SnackBarDemo.swift +138 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepperDemo.swift +103 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepsDemo.swift +94 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SuggestActionDemo.swift +79 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwipeDemo.swift +152 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwitchDemo.swift +33 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TabViewDemo.swift +190 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TagDemo.swift +34 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ThemeDemo.swift +182 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TitleDemo.swift +109 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TooltipDemo.swift +187 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TypographyDemo.swift +87 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/UploaderDemo.swift +131 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SwiftUIDemoBrowserView.swift +51 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/UIKitsDemoModels.swift +15 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/UIKitsDemoRegistry.swift +73 -0
- package/local.properties +2 -2
- package/package.json +1 -1
- package/publish.sh +53 -0
- package/scripts/gen-ios-color.mjs +136 -0
- package/.claude/settings.local.json +0 -62
package/CLAUDE.md
CHANGED
|
@@ -40,7 +40,7 @@ Publishing is automated (`publish.sh` + GitLab CI on `[ci build]` / `main`). Do
|
|
|
40
40
|
## Architecture essentials
|
|
41
41
|
|
|
42
42
|
- **Entry point:** wrap content in `NavigationContainer(...)` from `navigation/`. It builds the `Navigator`, takes a host-supplied `Localize` (falls back to an empty one), and provides the CompositionLocals below. **Do not use** `ApplicationContainer` (`application/NavigationContainer.kt`) — deprecated and does **not** wire `LocalLocalize` / `LocalNavigator` / `LocalMaxApi`.
|
|
43
|
-
- **Configuration flows via CompositionLocals**, not params. Public ones: `AppTheme`, `AppStatusBar`, `AppNavigationBar` (`const/Theme.kt`); `ApplicationContext`, `AppConfig`, `AppLanguage`, `LocalLocalize
|
|
43
|
+
- **Configuration flows via CompositionLocals**, not params. Public ones: `AppTheme`, `AppStatusBar`, `AppNavigationBar` (`const/Theme.kt`); `ApplicationContext`, `AppConfig`, `AppLanguage`, `LocalLocalize` (`application/`); `LocalNavigator`, `LocalMaxApi` (`navigation/`). Read with `X.current`.
|
|
44
44
|
- **Platform code** goes through `expect`/`actual` in `platform/` — never reference Android/iOS APIs from `commonMain` directly.
|
|
45
45
|
- **Native bridge:** `IMaxApi` (`vn.momo.maxapi`, exposed as `LocalMaxApi`) is the host-app bridge (dismiss, tracking, device info, language).
|
|
46
46
|
- Navigation uses a runtime `DynamicScreenRegistry`; overlays (modal/bottom-sheet/snackbar) go through `Navigator` + `OverplayComponentRegistry`.
|
package/compose/build.gradle.kts
CHANGED
package/compose/compose.podspec
CHANGED
|
@@ -8,7 +8,10 @@ import android.graphics.PorterDuffColorFilter
|
|
|
8
8
|
import android.os.Build
|
|
9
9
|
import androidx.compose.foundation.layout.Box
|
|
10
10
|
import androidx.compose.runtime.Composable
|
|
11
|
+
import androidx.compose.runtime.LaunchedEffect
|
|
11
12
|
import androidx.compose.runtime.getValue
|
|
13
|
+
import androidx.compose.runtime.rememberUpdatedState
|
|
14
|
+
import androidx.compose.runtime.snapshotFlow
|
|
12
15
|
import androidx.compose.ui.Modifier
|
|
13
16
|
import androidx.compose.ui.graphics.Color
|
|
14
17
|
import androidx.compose.ui.graphics.NativePaint
|
|
@@ -21,7 +24,7 @@ import androidx.compose.ui.unit.dp
|
|
|
21
24
|
import com.airbnb.lottie.LottieProperty
|
|
22
25
|
import com.airbnb.lottie.compose.LottieAnimation
|
|
23
26
|
import com.airbnb.lottie.compose.LottieCompositionSpec
|
|
24
|
-
import com.airbnb.lottie.compose.
|
|
27
|
+
import com.airbnb.lottie.compose.animateLottieCompositionAsState
|
|
25
28
|
import com.airbnb.lottie.compose.rememberLottieComposition
|
|
26
29
|
import com.airbnb.lottie.compose.rememberLottieDynamicProperties
|
|
27
30
|
import com.airbnb.lottie.compose.rememberLottieDynamicProperty
|
|
@@ -78,11 +81,14 @@ actual fun LottieAnimation(
|
|
|
78
81
|
tintColor: Color?,
|
|
79
82
|
bgColor: Color?,
|
|
80
83
|
placedAsOverlay: Boolean,
|
|
84
|
+
iterations: Int,
|
|
85
|
+
isPlaying: Boolean,
|
|
86
|
+
onEvent: ((String) -> Unit)?,
|
|
81
87
|
modifier: Modifier,
|
|
82
88
|
useCompose: Boolean
|
|
83
89
|
) {
|
|
84
90
|
if (useCompose) {
|
|
85
|
-
ComposeLottieAnimation(path, tintColor, bgColor, modifier)
|
|
91
|
+
ComposeLottieAnimation(path, tintColor, bgColor, iterations, isPlaying, onEvent, modifier)
|
|
86
92
|
return
|
|
87
93
|
}
|
|
88
94
|
|
|
@@ -110,9 +116,30 @@ actual fun LottieAnimation(
|
|
|
110
116
|
)
|
|
111
117
|
)
|
|
112
118
|
|
|
119
|
+
val lottieState = animateLottieCompositionAsState(
|
|
120
|
+
composition = composition,
|
|
121
|
+
iterations = iterations,
|
|
122
|
+
isPlaying = isPlaying,
|
|
123
|
+
restartOnPlay = false,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
val currentOnEvent by rememberUpdatedState(onEvent)
|
|
127
|
+
|
|
128
|
+
LaunchedEffect(isPlaying) {
|
|
129
|
+
currentOnEvent?.invoke(if (isPlaying) LottieEvent.Start else LottieEvent.Pause)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
LaunchedEffect(lottieState) {
|
|
133
|
+
var armed = false
|
|
134
|
+
snapshotFlow { lottieState.isAtEnd }.collect { atEnd ->
|
|
135
|
+
if (!atEnd) armed = true
|
|
136
|
+
else if (armed) { armed = false; currentOnEvent?.invoke(LottieEvent.Finish) }
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
113
140
|
LottieAnimation(
|
|
114
141
|
composition = composition,
|
|
115
|
-
|
|
142
|
+
progress = { lottieState.progress },
|
|
116
143
|
dynamicProperties = if (tintColor != null) dynamicProperties else null,
|
|
117
144
|
modifier = modifier
|
|
118
145
|
)
|
|
@@ -29,6 +29,8 @@ data class MiniAppContext(
|
|
|
29
29
|
val permissions: List<Map<String, Any>>? = emptyList(),
|
|
30
30
|
val features: FeatureFlags? = null,
|
|
31
31
|
val scaleSizeMaxRate: Float? = null,
|
|
32
|
+
val userScaleRate: Float? = null,
|
|
33
|
+
val useOSScaleRate: Boolean? = null,
|
|
32
34
|
) {
|
|
33
35
|
companion object {
|
|
34
36
|
|
|
@@ -61,6 +63,8 @@ data class MiniAppContext(
|
|
|
61
63
|
permissions = if (!parent.permissions.isNullOrEmpty()) parent.permissions else child.permissions,
|
|
62
64
|
features = mergeFeatureFlags(parent.features, child.features),
|
|
63
65
|
scaleSizeMaxRate = parent.scaleSizeMaxRate ?: child.scaleSizeMaxRate,
|
|
66
|
+
userScaleRate = parent.userScaleRate ?: child.userScaleRate,
|
|
67
|
+
useOSScaleRate = parent.useOSScaleRate ?: child.useOSScaleRate,
|
|
64
68
|
)
|
|
65
69
|
}
|
|
66
70
|
|
|
@@ -98,4 +102,5 @@ val LocalComponentInformation = staticCompositionLocalOf<ComponentInformation?>
|
|
|
98
102
|
null
|
|
99
103
|
}
|
|
100
104
|
|
|
105
|
+
@Deprecated("Max font scale is fixed at MAX_FONT_SCALE (1.5); this CompositionLocal is no longer read.")
|
|
101
106
|
val ScaleSizeMaxRate = staticCompositionLocalOf<Float?> { null }
|
|
@@ -7,6 +7,7 @@ import androidx.compose.ui.Modifier
|
|
|
7
7
|
import androidx.compose.ui.unit.Dp
|
|
8
8
|
import vn.momo.kits.const.*
|
|
9
9
|
import vn.momo.kits.modifier.DeprecatedModifier
|
|
10
|
+
import vn.momo.kits.platform.ProvideOsFontScale
|
|
10
11
|
import vn.momo.kits.platform.getStatusBarHeight
|
|
11
12
|
|
|
12
13
|
@Deprecated("Use IMaxApi instead", ReplaceWith("IMaxApi"))
|
|
@@ -93,6 +94,7 @@ fun ApplicationContainer(
|
|
|
93
94
|
|
|
94
95
|
val appStatusBarHeight = statusBarHeight ?: getStatusBarHeight()
|
|
95
96
|
|
|
97
|
+
ProvideOsFontScale {
|
|
96
98
|
CompositionLocalProvider(
|
|
97
99
|
AppTheme provides appTheme,
|
|
98
100
|
PlatformApi provides composeApi,
|
|
@@ -103,5 +105,6 @@ fun ApplicationContainer(
|
|
|
103
105
|
content()
|
|
104
106
|
}
|
|
105
107
|
}
|
|
108
|
+
}
|
|
106
109
|
|
|
107
110
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
package vn.momo.kits.application
|
|
2
|
+
|
|
3
|
+
import androidx.compose.runtime.Composable
|
|
4
|
+
import androidx.compose.runtime.CompositionLocalProvider
|
|
5
|
+
import androidx.compose.runtime.LaunchedEffect
|
|
6
|
+
import androidx.compose.runtime.remember
|
|
7
|
+
import vn.momo.kits.const.AppTheme
|
|
8
|
+
import vn.momo.kits.const.Theme
|
|
9
|
+
import vn.momo.kits.navigation.LocalMaxApi
|
|
10
|
+
import vn.momo.kits.platform.ProvideOsFontScale
|
|
11
|
+
import vn.momo.maxapi.IMaxApi
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@Composable
|
|
15
|
+
fun WidgetContainer(
|
|
16
|
+
theme: Theme? = null,
|
|
17
|
+
miniAppContext: MiniAppContext? = null,
|
|
18
|
+
maxApi: IMaxApi? = null,
|
|
19
|
+
localize: Localize? = null,
|
|
20
|
+
content: @Composable () -> Unit,
|
|
21
|
+
) {
|
|
22
|
+
val parentContext = LocalContext.current
|
|
23
|
+
val mergedContext = remember(parentContext, miniAppContext) {
|
|
24
|
+
MiniAppContext.merge(parentContext, miniAppContext)
|
|
25
|
+
}
|
|
26
|
+
val resolvedTheme = theme ?: AppTheme.current
|
|
27
|
+
val resolvedLocalize = localize ?: LocalLocalize.current
|
|
28
|
+
val resolvedMaxApi = maxApi ?: LocalMaxApi.current
|
|
29
|
+
|
|
30
|
+
LaunchedEffect(resolvedMaxApi, localize) {
|
|
31
|
+
val api = resolvedMaxApi ?: return@LaunchedEffect
|
|
32
|
+
val target = localize ?: return@LaunchedEffect
|
|
33
|
+
runCatching {
|
|
34
|
+
api.getLanguage(callback = { data ->
|
|
35
|
+
if (parseLanguage(data) == Localize.EN) target.changeLanguage(Localize.EN)
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
ProvideOsFontScale {
|
|
41
|
+
CompositionLocalProvider(
|
|
42
|
+
AppTheme provides resolvedTheme,
|
|
43
|
+
LocalContext provides mergedContext,
|
|
44
|
+
LocalLocalize provides resolvedLocalize,
|
|
45
|
+
LocalMaxApi provides resolvedMaxApi,
|
|
46
|
+
) {
|
|
47
|
+
content()
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private fun parseLanguage(raw: Map<String, Any?>?): String? {
|
|
53
|
+
val code = (raw?.get("response") as? String)?.trim()?.lowercase()
|
|
54
|
+
if (code.isNullOrEmpty()) return null
|
|
55
|
+
return if (code.startsWith(Localize.EN)) Localize.EN else Localize.VI
|
|
56
|
+
}
|
|
@@ -4,6 +4,10 @@ import androidx.compose.runtime.Composable
|
|
|
4
4
|
import androidx.compose.runtime.CompositionLocalProvider
|
|
5
5
|
import vn.momo.kits.application.ScaleSizeMaxRate
|
|
6
6
|
|
|
7
|
+
@Deprecated(
|
|
8
|
+
"Max font scale is fixed at MAX_FONT_SCALE (1.5); this override is no longer applied. Remove the wrapper.",
|
|
9
|
+
ReplaceWith("content()"),
|
|
10
|
+
)
|
|
7
11
|
@Composable
|
|
8
12
|
fun ScaleSizeScope(
|
|
9
13
|
scaleSizeMaxRate: Float? = null,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
package vn.momo.kits.const
|
|
2
|
+
|
|
3
|
+
import androidx.compose.runtime.getValue
|
|
4
|
+
import androidx.compose.runtime.mutableStateOf
|
|
5
|
+
import androidx.compose.runtime.setValue
|
|
6
|
+
|
|
7
|
+
// App-wide font-scale holder. The kit is sandboxed and can't read the host cache directly, so the
|
|
8
|
+
// host (which sees both core and this kit) seeds this once at startup and pushes runtime updates into
|
|
9
|
+
// it. scaleSize() reads it as the fallback, so every screen — including direct NavigationContainer
|
|
10
|
+
// screens with no host-pushed MiniAppContext — scales with no per-render prop and no async flicker.
|
|
11
|
+
// Backed by snapshot state: writes recompose text automatically.
|
|
12
|
+
object KitFontScale {
|
|
13
|
+
var userScaleRate by mutableStateOf(1f)
|
|
14
|
+
private set
|
|
15
|
+
var useOSScaleRate by mutableStateOf(true)
|
|
16
|
+
private set
|
|
17
|
+
|
|
18
|
+
fun update(userScaleRate: Float, useOSScaleRate: Boolean) {
|
|
19
|
+
this.userScaleRate = userScaleRate
|
|
20
|
+
this.useOSScaleRate = useOSScaleRate
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -11,7 +11,7 @@ import androidx.compose.ui.unit.*
|
|
|
11
11
|
import org.jetbrains.compose.resources.Font
|
|
12
12
|
import org.jetbrains.compose.resources.FontResource
|
|
13
13
|
import org.jetbrains.compose.resources.InternalResourceApi
|
|
14
|
-
import vn.momo.kits.application.
|
|
14
|
+
import vn.momo.kits.application.LocalContext
|
|
15
15
|
import vn.momo.kits.platform.getScreenDimensions
|
|
16
16
|
import vn.momo.uikits.resources.*
|
|
17
17
|
import kotlin.math.max
|
|
@@ -23,7 +23,13 @@ const val MAX_DEVICE_SCALE = 5
|
|
|
23
23
|
|
|
24
24
|
@Composable
|
|
25
25
|
fun scaleSize(size: Float): Float {
|
|
26
|
-
val
|
|
26
|
+
val context = LocalContext.current
|
|
27
|
+
// Host-pushed context wins; otherwise fall back to the app-wide KitFontScale holder.
|
|
28
|
+
val useOsScale = context?.useOSScaleRate ?: KitFontScale.useOSScaleRate
|
|
29
|
+
if (!useOsScale) {
|
|
30
|
+
return size * (context?.userScaleRate ?: KitFontScale.userScaleRate)
|
|
31
|
+
}
|
|
32
|
+
val scaleSizeMaxRate: Float = MAX_FONT_SCALE
|
|
27
33
|
val deviceWidth = getScreenDimensions().width
|
|
28
34
|
val deviceScale = deviceWidth / DEFAULT_SCREEN_SIZE
|
|
29
35
|
|
|
@@ -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:
|
|
12
|
-
val
|
|
13
|
-
val sizePerSpan:
|
|
14
|
-
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
content: @Composable () -> Unit,
|
|
36
|
+
widthSpan: Int = 12,
|
|
37
|
+
heightSpan: Int = 0,
|
|
22
38
|
modifier: Modifier = Modifier,
|
|
23
|
-
|
|
39
|
+
content: @Composable () -> Unit,
|
|
24
40
|
) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
+
}
|
|
@@ -85,7 +85,9 @@ data class NavigationOptions(
|
|
|
85
85
|
val footerComponent: @Composable (() -> Unit)? = null,
|
|
86
86
|
val floatingButtonProps: FloatingButtonProps? = null,
|
|
87
87
|
val keyboardOptions: KeyboardOptions = KeyboardOptions()
|
|
88
|
-
)
|
|
88
|
+
) {
|
|
89
|
+
internal fun hasFooter() : Boolean = footerComponent != null
|
|
90
|
+
}
|
|
89
91
|
|
|
90
92
|
data class KeyboardOptions(
|
|
91
93
|
val keyboardShouldPersistTaps: Boolean = false,
|