@momo-kits/native-kits 0.167.1-duo.8 → 0.167.1-duo.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 +4 -1
- package/build.gradle.kts +11 -0
- package/compose/build.gradle.kts +204 -0
- package/compose/build.gradle.kts.backup +204 -0
- package/compose/compose.podspec +47 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/const/HostFont.android.kt +19 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/navigation/ScrollToTop.android.kt +6 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/BackGesture.android.kt +12 -0
- 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 +153 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/ReservedRegions.android.kt +6 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +52 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +124 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +183 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +207 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +39 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +86 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +76 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +76 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +293 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +33 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +831 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +269 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +110 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +378 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +56 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +69 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +157 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +81 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +32 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +338 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +175 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +357 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +115 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +89 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +128 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +209 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +542 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +49 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +76 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +125 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +231 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +189 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +478 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +114 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +265 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +235 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +223 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +265 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +185 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +343 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +108 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +56 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +41 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +84 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +40 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +361 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +108 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +308 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +59 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +87 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +21 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +90 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +330 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +220 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +473 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +122 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +207 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +92 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +560 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +86 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +125 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +207 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +501 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +176 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +182 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +193 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +29 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +236 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +180 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +325 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/HostFont.kt +16 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitDesignSystem.kt +18 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +22 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +12 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +16 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +188 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +297 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +54 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +50 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/ScreenLayout.kt +232 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +41 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +52 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +66 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +11 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +104 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +48 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +51 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +338 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/HostBackGestureBridge.kt +58 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +137 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +106 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +205 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +393 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScrollToTop.kt +8 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +708 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackTransition.kt +148 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/SwipeBackHaptic.kt +35 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +209 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +231 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +86 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoBarCompression.kt +98 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoTabBar.kt +312 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +169 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +408 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +92 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderJourney.kt +106 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderLocation.kt +74 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +366 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +37 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +363 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SideBar.kt +185 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +133 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +127 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/BackGesture.kt +12 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +91 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +9 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +74 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ReservedRegions.kt +13 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +1329 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +55 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +15 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +118 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/const/HostFont.ios.kt +40 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/HostBackGesture.ios.kt +45 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +32 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/BackGesture.ios.kt +38 -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 +217 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/ReservedRegions.ios.kt +86 -0
- package/gradle/libs.versions.toml +69 -0
- package/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/gradle/wrapper/gradle-wrapper.properties +8 -0
- package/gradle.properties +26 -0
- package/gradlew +252 -0
- package/gradlew.bat +94 -0
- package/ios/Application/ApplicationEnvironment.swift +11 -0
- package/ios/Application/ComposeApi.swift +2 -1
- package/ios/Application/{Components.swift → LegacyHeader.swift} +6 -62
- package/ios/Application/Screen.swift +3 -2
- package/ios/Avatar/Avatar.swift +4 -3
- package/ios/Badge/Badge.swift +6 -4
- package/ios/Badge/BadgeDot.swift +1 -1
- package/ios/Badge/BadgeRibbon.swift +0 -1
- package/ios/Button/Button.swift +15 -12
- package/ios/CalculatorKeyboard/CalculatorKeyboard.swift +12 -20
- package/ios/Carousel/Carousel.swift +29 -12
- package/ios/Checkbox/Checkbox.swift +7 -3
- package/ios/Chip/Chip.swift +5 -4
- package/ios/Collapse/Collapse.swift +70 -19
- package/ios/Colors+Radius+Spacing/Colors.swift +9 -0
- package/ios/DateTimePicker/DateTimePicker.swift +54 -20
- package/ios/DateTimePicker/WheelPicker.swift +103 -105
- package/ios/Divider/Divider.swift +37 -4
- package/ios/Extensions/Color++.swift +18 -0
- package/ios/Icon/Icon.swift +7 -1
- package/ios/IconButton/IconButton.swift +15 -7
- package/ios/Image/Image.swift +7 -34
- package/ios/Information/Information.swift +27 -9
- package/ios/Input/ErrorView.swift +2 -2
- package/ios/Input/Input.swift +160 -147
- package/ios/Input/InputPhoneNumber.swift +12 -9
- package/ios/Input/InputSearch.swift +102 -75
- package/ios/Input/InputTextArea.swift +128 -145
- package/ios/InputDropDown/InputDropDown.swift +10 -7
- package/ios/InputMoney/InputMoney.swift +33 -11
- package/ios/InputOTP/InputOTP.swift +22 -12
- package/ios/Layout/Card.swift +50 -0
- package/ios/Layout/GridContext.swift +123 -3
- package/ios/Layout/Item.swift +5 -4
- package/ios/Layout/Section.swift +4 -100
- package/ios/Loader/Loader.swift +5 -9
- package/ios/Lottie/LottieView.swift +10 -0
- package/ios/{Application/Navigation/Overplay → Navigation}/BottomSheet.swift +61 -9
- package/ios/{Application/Navigation → Navigation}/BottomTab/BottomTab.swift +60 -34
- package/ios/{Application/Navigation → Navigation}/BottomTab/BottomTabBar.swift +11 -6
- package/ios/{Application → Navigation/Component}/FloatingButton.swift +14 -3
- package/ios/Navigation/Component/Header.swift +493 -0
- package/ios/Navigation/Component/HeaderBackground.swift +134 -0
- package/ios/Navigation/Component/HeaderJourney.swift +73 -0
- package/ios/Navigation/Component/HeaderLocation.swift +48 -0
- package/ios/Navigation/Component/HeaderRight.swift +386 -0
- package/ios/Navigation/Component/HeaderTitle.swift +36 -0
- package/ios/{Application/Navigation → Navigation/Component}/HeaderUser.swift +20 -23
- package/ios/{Application/Navigation/component → Navigation/Component}/SideBar.swift +49 -28
- package/ios/{Application/Navigation/Overplay → Navigation/Component}/SnackBar.swift +5 -5
- package/ios/Navigation/HostBackGestureBridge.swift +57 -0
- package/ios/Navigation/Navigation.swift +190 -0
- package/ios/{Application/Navigation → Navigation}/NavigationContainer.swift +46 -41
- package/ios/{Application/Navigation → Navigation}/Navigator.swift +65 -9
- package/ios/{Application → Navigation}/StackScreen.swift +236 -103
- package/ios/{Application/Navigation → Navigation}/Tracking/ScreenTracker.swift +12 -5
- package/ios/OTPKeyboard/OTPKeyboard.swift +8 -11
- package/ios/Pagination/PaginationScroll.swift +2 -2
- package/ios/Popup/PopupDisplay.swift +79 -159
- package/ios/Popup/PopupInput.swift +10 -13
- package/ios/Popup/PopupLayout.swift +97 -2
- package/ios/Popup/PopupNotify.swift +27 -55
- package/ios/Popup/PopupPromotion.swift +22 -50
- package/ios/PopupView/FullscreenPopup.swift +13 -19
- package/ios/PopupView/PopupView.swift +1 -1
- package/ios/PopupView/Utils++.swift +0 -8
- package/ios/ProgressInfo/ProgressInfo.swift +4 -2
- package/ios/Radio/Radio.swift +2 -1
- package/ios/Rating/Rating.swift +9 -1
- package/ios/ScrollIndicator/ScrollIndicator.swift +11 -10
- package/ios/Skeleton/Skeleton.swift +22 -27
- package/ios/Slider/Slider.swift +16 -18
- package/ios/Stepper/Stepper.swift +6 -1
- package/ios/Steps/Steps.swift +8 -6
- package/ios/SuggestAction/SuggestAction.swift +5 -0
- package/ios/Swipeable/SwipeCell.swift +10 -6
- package/ios/Switch/Switch.swift +22 -20
- package/ios/TabView/TabView.swift +102 -21
- package/ios/Tag/Tag.swift +15 -4
- package/ios/Template/Logo/Logo.swift +2 -1
- package/ios/Template/TrustBanner/TrustBanner.swift +41 -27
- package/ios/Title/Title.swift +6 -17
- package/ios/Tooltip/Tooltip.swift +29 -14
- package/ios/Typography/Text.swift +61 -19
- package/ios/Uploader/Uploader.swift +3 -1
- package/ios/native-kits.podspec +1 -0
- package/ios-demo/README.md +120 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ContentView.swift +1 -1
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +77 -1
- package/package.json +1 -1
- package/settings.gradle.kts +64 -0
- package/ios/Application/HeaderRight.swift +0 -324
- package/ios/Application/Navigation/HeaderBackProps.swift +0 -66
- package/ios/Application/Navigation/HeaderTitle.swift +0 -57
- package/ios/Application/Navigation/NavigationOptions.swift +0 -109
- package/ios/Application/Navigation/NavigatorManager.swift +0 -29
- package/ios/Application/Navigation/component/DuoScrollGradient.swift +0 -54
- package/ios/Application/Navigation/component/Header.swift +0 -183
- package/ios/Application/Navigation/component/HeaderBackground.swift +0 -84
- package/ios/Application/Navigation/component/HeaderColor.swift +0 -65
- package/ios/Application/Navigation/component/HeaderRightWidthKey.swift +0 -11
- package/ios/Application/Navigation/component/NavigationFooter.swift +0 -90
- package/ios/Application/Navigation/component/NavigationHeaderRight.swift +0 -280
- /package/ios/{Application/Layout → Layout}/ScreenLayout.swift +0 -0
- /package/ios/{Application/Navigation → Navigation}/BottomTab/CurvedContainer.swift +0 -0
- /package/ios/{Application/Navigation → Navigation}/BottomTab/DuoBarCompression.swift +0 -0
- /package/ios/{Application/Navigation → Navigation}/BottomTab/DuoTabBar.swift +0 -0
- /package/ios/{Application/Navigation/Overplay → Navigation}/ModalScreen.swift +0 -0
|
@@ -10,9 +10,8 @@ private let wheelPickerBorderWidth: CGFloat = 1
|
|
|
10
10
|
|
|
11
11
|
/// A reusable single-column wheel picker, mirroring Compose `WheelPicker.kt`.
|
|
12
12
|
///
|
|
13
|
-
///
|
|
14
|
-
///
|
|
15
|
-
/// `onChange(name, value)`.
|
|
13
|
+
/// Five rows tall with the selection in the middle row. A drag always settles on a row
|
|
14
|
+
/// (Compose snaps once the scroll stops) and then reports it via `onChange(name, value)`.
|
|
16
15
|
public struct WheelPicker: View {
|
|
17
16
|
@Environment(\.appTheme) private var theme
|
|
18
17
|
|
|
@@ -28,68 +27,50 @@ public struct WheelPicker: View {
|
|
|
28
27
|
self.data = data
|
|
29
28
|
self.selectedData = selectedData
|
|
30
29
|
self.onChange = onChange
|
|
30
|
+
_restIndex = State(initialValue: Self.index(of: selectedData, in: data))
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
// MARK: Public
|
|
34
34
|
|
|
35
35
|
public var body: some View {
|
|
36
|
-
let
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
.id(index)
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
.background(
|
|
56
|
-
GeometryReader { inner in
|
|
57
|
-
Color.clear.preference(
|
|
58
|
-
key: WheelOffsetKey.self,
|
|
59
|
-
value: inner.frame(in: .named(scrollSpace)).minY
|
|
60
|
-
)
|
|
61
|
-
}
|
|
62
|
-
)
|
|
63
|
-
}
|
|
64
|
-
.coordinateSpace(name: scrollSpace)
|
|
65
|
-
.onPreferenceChange(WheelOffsetKey.self) { value in
|
|
66
|
-
scrollOffset = value
|
|
67
|
-
updateSelection(paddedData: paddedData, viewportHeight: height)
|
|
68
|
-
}
|
|
69
|
-
.onAppear {
|
|
70
|
-
let initial = max(paddedData.firstIndex(of: selectedData) ?? 2, 2)
|
|
71
|
-
selectedIndex = initial
|
|
72
|
-
DispatchQueue.main.async {
|
|
73
|
-
proxy.scrollTo(initial, anchor: .center)
|
|
36
|
+
let position = self.position
|
|
37
|
+
let centerSlot = CGFloat(wheelVisibleCount / 2)
|
|
38
|
+
|
|
39
|
+
return Rectangle()
|
|
40
|
+
.fill(theme.colors.background.surface)
|
|
41
|
+
.overlay(
|
|
42
|
+
// Compose draws the selection band behind the rows.
|
|
43
|
+
Rectangle()
|
|
44
|
+
.fill(Colors.blue10)
|
|
45
|
+
.opacity(0.2)
|
|
46
|
+
.frame(height: wheelItemHeight)
|
|
47
|
+
)
|
|
48
|
+
.overlay(
|
|
49
|
+
VStack(spacing: 0) {
|
|
50
|
+
ForEach(Array(data.enumerated()), id: \.offset) { index, text in
|
|
51
|
+
WheelPickerItem(text: text, distance: abs(CGFloat(index) - position))
|
|
74
52
|
}
|
|
75
53
|
}
|
|
54
|
+
.offset(y: (centerSlot - position) * wheelItemHeight),
|
|
55
|
+
alignment: .top
|
|
56
|
+
)
|
|
57
|
+
.frame(maxWidth: .infinity)
|
|
58
|
+
.frame(height: wheelItemHeight * CGFloat(wheelVisibleCount))
|
|
59
|
+
.clipShape(RoundedRectangle(cornerRadius: Radius.S))
|
|
60
|
+
.overlay(
|
|
61
|
+
RoundedRectangle(cornerRadius: Radius.S)
|
|
62
|
+
.strokeBorder(theme.colors.border.default, lineWidth: wheelPickerBorderWidth)
|
|
63
|
+
)
|
|
64
|
+
.contentShape(Rectangle())
|
|
65
|
+
.gesture(dragGesture)
|
|
66
|
+
.onAppear { reportIfUnlisted() }
|
|
67
|
+
.onChange(of: selectedData) { _ in syncToSelection() }
|
|
68
|
+
.onChange(of: data) { _ in syncToSelection() }
|
|
69
|
+
.accessibilityElement()
|
|
70
|
+
.accessibilityValue(data.indices.contains(restIndex) ? data[restIndex] : "")
|
|
71
|
+
.accessibilityAdjustableAction { direction in
|
|
72
|
+
settle(at: restIndex + (direction == .increment ? 1 : -1))
|
|
76
73
|
}
|
|
77
|
-
}
|
|
78
|
-
.frame(height: wheelItemHeight * CGFloat(wheelVisibleCount))
|
|
79
|
-
.overlay(
|
|
80
|
-
RoundedRectangle(cornerRadius: Radius.S)
|
|
81
|
-
.stroke(theme.colors.border.default, lineWidth: wheelPickerBorderWidth)
|
|
82
|
-
)
|
|
83
|
-
.background(theme.colors.background.surface.clipShape(RoundedRectangle(cornerRadius: Radius.S)))
|
|
84
|
-
.overlay(
|
|
85
|
-
// Centered translucent selection band.
|
|
86
|
-
Rectangle()
|
|
87
|
-
.fill(Colors.blue10)
|
|
88
|
-
.opacity(0.2)
|
|
89
|
-
.frame(height: wheelItemHeight)
|
|
90
|
-
.allowsHitTesting(false)
|
|
91
|
-
)
|
|
92
|
-
.clipShape(RoundedRectangle(cornerRadius: Radius.S))
|
|
93
74
|
}
|
|
94
75
|
|
|
95
76
|
// MARK: Internal
|
|
@@ -99,24 +80,60 @@ public struct WheelPicker: View {
|
|
|
99
80
|
let selectedData: String
|
|
100
81
|
let onChange: (String, String) -> Void
|
|
101
82
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
private
|
|
106
|
-
|
|
107
|
-
///
|
|
108
|
-
private
|
|
109
|
-
|
|
110
|
-
let
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
83
|
+
// MARK: Private
|
|
84
|
+
|
|
85
|
+
@State private var restIndex: Int
|
|
86
|
+
@State private var dragTranslation: CGFloat = 0
|
|
87
|
+
|
|
88
|
+
/// Fractional row index under the band; past either end the drag meets resistance.
|
|
89
|
+
private var position: CGFloat {
|
|
90
|
+
let raw = CGFloat(restIndex) - dragTranslation / wheelItemHeight
|
|
91
|
+
let last = CGFloat(max(0, data.count - 1))
|
|
92
|
+
if raw < 0 { return raw * 0.3 }
|
|
93
|
+
if raw > last { return last + (raw - last) * 0.3 }
|
|
94
|
+
return raw
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
private var dragGesture: some Gesture {
|
|
98
|
+
DragGesture(minimumDistance: 4)
|
|
99
|
+
.onChanged { value in
|
|
100
|
+
dragTranslation = value.translation.height
|
|
101
|
+
}
|
|
102
|
+
.onEnded { value in
|
|
103
|
+
let predicted = CGFloat(restIndex) - value.predictedEndTranslation.height / wheelItemHeight
|
|
104
|
+
settle(at: Int(predicted.rounded()))
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/// Like Compose `paddedData.indexOf(selectedData).coerceAtLeast(2)`: an unknown value shows the first row.
|
|
109
|
+
private static func index(of value: String, in data: [String]) -> Int {
|
|
110
|
+
data.firstIndex(of: value) ?? 0
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private func settle(at index: Int) {
|
|
114
|
+
let target = min(max(index, 0), max(0, data.count - 1))
|
|
115
|
+
let rows = Double(abs(CGFloat(target) - position))
|
|
116
|
+
withAnimation(.easeOut(duration: min(0.5, 0.2 + 0.03 * rows))) {
|
|
117
|
+
restIndex = target
|
|
118
|
+
dragTranslation = 0
|
|
119
119
|
}
|
|
120
|
+
guard data.indices.contains(target), data[target] != selectedData else { return }
|
|
121
|
+
onChange(name, data[target])
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/// The parent may coerce the value (e.g. day 31 → 28) or swap the list; jump without animation
|
|
125
|
+
/// like Compose `scrollToItem`.
|
|
126
|
+
private func syncToSelection() {
|
|
127
|
+
restIndex = Self.index(of: selectedData, in: data)
|
|
128
|
+
dragTranslation = 0
|
|
129
|
+
reportIfUnlisted()
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/// Compose reports the row the wheel lands on, so a value missing from `data` (minute 07 with a
|
|
133
|
+
/// 5-minute interval, an unset AM/PM) takes the shown row's value instead of drifting from it.
|
|
134
|
+
private func reportIfUnlisted() {
|
|
135
|
+
guard data.indices.contains(restIndex), !data.contains(selectedData) else { return }
|
|
136
|
+
onChange(name, data[restIndex])
|
|
120
137
|
}
|
|
121
138
|
}
|
|
122
139
|
|
|
@@ -126,40 +143,21 @@ private struct WheelPickerItem: View {
|
|
|
126
143
|
@Environment(\.appTheme) private var theme
|
|
127
144
|
|
|
128
145
|
let text: String
|
|
129
|
-
|
|
130
|
-
let
|
|
131
|
-
let scrollOffset: CGFloat
|
|
132
|
-
let viewportHeight: CGFloat
|
|
146
|
+
/// Rows between this one and the band.
|
|
147
|
+
let distance: CGFloat
|
|
133
148
|
|
|
134
149
|
var body: some View {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
switch distanceFromCenter {
|
|
141
|
-
case ..<1: alpha = 1.0
|
|
142
|
-
case ..<2: alpha = 0.8
|
|
143
|
-
default: alpha = 0.4
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
let scale: CGFloat = isSelected ? 1.0 : 0.87
|
|
147
|
-
|
|
148
|
-
return ZStack {
|
|
149
|
-
MomoText(text, typography: .actionSBold, color: theme.colors.text.default)
|
|
150
|
-
.scaleEffect(scale)
|
|
151
|
-
}
|
|
152
|
-
.frame(maxWidth: .infinity)
|
|
153
|
-
.frame(height: wheelItemHeight)
|
|
154
|
-
.opacity(alpha)
|
|
150
|
+
MomoText(text, typography: .actionSBold, color: theme.colors.text.default)
|
|
151
|
+
.scaleEffect(1 - 0.13 * min(distance, 1))
|
|
152
|
+
.frame(maxWidth: .infinity)
|
|
153
|
+
.frame(height: wheelItemHeight)
|
|
154
|
+
.opacity(Self.opacity(distance))
|
|
155
155
|
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// MARK: - WheelOffsetKey
|
|
159
156
|
|
|
160
|
-
|
|
161
|
-
static
|
|
162
|
-
|
|
163
|
-
|
|
157
|
+
// RN parity: 1 on the band, 0.8 one row away, 0.4 from two rows on.
|
|
158
|
+
private static func opacity(_ distance: CGFloat) -> Double {
|
|
159
|
+
if distance <= 1 { return Double(1 - 0.2 * distance) }
|
|
160
|
+
if distance <= 2 { return Double(0.8 - 0.4 * (distance - 1)) }
|
|
161
|
+
return 0.4
|
|
164
162
|
}
|
|
165
163
|
}
|
|
@@ -1,16 +1,49 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
import SwiftUI
|
|
3
3
|
|
|
4
|
+
public enum DividerType {
|
|
5
|
+
case `default`
|
|
6
|
+
case dash
|
|
7
|
+
}
|
|
8
|
+
|
|
4
9
|
public struct MomoDivider: View {
|
|
5
10
|
@Environment(\.appTheme) private var theme
|
|
6
11
|
|
|
7
|
-
|
|
12
|
+
private let useMargin: Bool
|
|
13
|
+
private let type: DividerType
|
|
14
|
+
|
|
15
|
+
public init(useMargin: Bool = false, type: DividerType = .default) {
|
|
16
|
+
self.useMargin = useMargin
|
|
17
|
+
self.type = type
|
|
18
|
+
}
|
|
8
19
|
|
|
9
20
|
public var body: some View {
|
|
10
|
-
|
|
11
|
-
.fill(theme.colors.border.default)
|
|
21
|
+
line
|
|
12
22
|
.frame(maxWidth: .infinity)
|
|
13
23
|
.frame(height: 1)
|
|
14
|
-
.padding(.vertical, Spacing.XS)
|
|
24
|
+
.padding(.vertical, useMargin ? Spacing.XS : 0)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@ViewBuilder
|
|
28
|
+
private var line: some View {
|
|
29
|
+
switch type {
|
|
30
|
+
case .default:
|
|
31
|
+
Rectangle().fill(theme.colors.border.default)
|
|
32
|
+
case .dash:
|
|
33
|
+
DividerDashLine()
|
|
34
|
+
.stroke(
|
|
35
|
+
theme.colors.border.default,
|
|
36
|
+
style: StrokeStyle(lineWidth: 1, lineCap: .round, dash: [4, 4])
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private struct DividerDashLine: Shape {
|
|
43
|
+
func path(in rect: CGRect) -> Path {
|
|
44
|
+
var path = Path()
|
|
45
|
+
path.move(to: CGPoint(x: rect.minX, y: rect.midY))
|
|
46
|
+
path.addLine(to: CGPoint(x: rect.maxX, y: rect.midY))
|
|
47
|
+
return path
|
|
15
48
|
}
|
|
16
49
|
}
|
|
@@ -66,3 +66,21 @@ public extension Color {
|
|
|
66
66
|
)
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
+
|
|
70
|
+
extension Color {
|
|
71
|
+
/// Compose's `lerp(start, stop, fraction)`, in sRGB; `Color.mix` needs iOS 18.
|
|
72
|
+
func lerp(to other: Color, _ fraction: CGFloat) -> Color {
|
|
73
|
+
let t = min(max(fraction, 0), 1)
|
|
74
|
+
var (r1, g1, b1, a1): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)
|
|
75
|
+
var (r2, g2, b2, a2): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)
|
|
76
|
+
UIColor(self).getRed(&r1, green: &g1, blue: &b1, alpha: &a1)
|
|
77
|
+
UIColor(other).getRed(&r2, green: &g2, blue: &b2, alpha: &a2)
|
|
78
|
+
return Color(
|
|
79
|
+
.sRGB,
|
|
80
|
+
red: r1 + (r2 - r1) * t,
|
|
81
|
+
green: g1 + (g2 - g1) * t,
|
|
82
|
+
blue: b1 + (b2 - b1) * t,
|
|
83
|
+
opacity: a1 + (a2 - a1) * t
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
}
|
package/ios/Icon/Icon.swift
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import SDWebImageSwiftUI
|
|
1
2
|
import SwiftUI
|
|
2
3
|
|
|
3
4
|
struct IconSource: Codable {
|
|
@@ -47,7 +48,12 @@ public struct Icon: View {
|
|
|
47
48
|
let requestedColor = color == iconThemeColor ? theme.colors.text.default : color
|
|
48
49
|
// Mirror Compose: certain icons (e.g. branded glyphs) are never tinted
|
|
49
50
|
let resolvedColor = noThemeIcons.contains(source) ? nil : requestedColor
|
|
50
|
-
|
|
51
|
+
// Bare WebImage like Compose's AsyncImage: no skeleton while loading, nothing on failure.
|
|
52
|
+
WebImage(url: URL(string: uri), isAnimating: .constant(true))
|
|
53
|
+
.resizable()
|
|
54
|
+
.renderingMode(resolvedColor != nil ? .template : .original)
|
|
55
|
+
.scaledToFit()
|
|
56
|
+
.foregroundColor(resolvedColor)
|
|
51
57
|
.frame(width: size, height: size)
|
|
52
58
|
// Mirrors Compose's auto-generated `contentDescription = "img|$iconUrl"`
|
|
53
59
|
// when no explicit label is provided.
|
|
@@ -28,7 +28,7 @@ public enum IconSize {
|
|
|
28
28
|
|
|
29
29
|
// MARK: - IconShape
|
|
30
30
|
|
|
31
|
-
public enum IconShape {
|
|
31
|
+
public enum IconShape: Sendable {
|
|
32
32
|
case circle
|
|
33
33
|
case square
|
|
34
34
|
}
|
|
@@ -68,8 +68,7 @@ public struct IconButton: View {
|
|
|
68
68
|
public var body: some View {
|
|
69
69
|
let bg = backgroundColor
|
|
70
70
|
let fg = contentColor
|
|
71
|
-
|
|
72
|
-
let border: Color? = type == .outline ? (color ?? theme.colors.primary) : borderColor
|
|
71
|
+
let border = borderColor
|
|
73
72
|
let borderWidth = type.borderWidth
|
|
74
73
|
|
|
75
74
|
SwiftUI.Button(action: {
|
|
@@ -82,9 +81,11 @@ public struct IconButton: View {
|
|
|
82
81
|
.background(bg)
|
|
83
82
|
.clipShape(IconButtonShape(shape))
|
|
84
83
|
.overlay(
|
|
84
|
+
// Inside the bounds, like Compose `border`.
|
|
85
85
|
IconButtonShape(shape)
|
|
86
|
-
.
|
|
86
|
+
.strokeBorder(border ?? .clear, lineWidth: border != nil ? borderWidth : 0)
|
|
87
87
|
)
|
|
88
|
+
.contentShape(IconButtonShape(shape))
|
|
88
89
|
}
|
|
89
90
|
.buttonStyle(.plain)
|
|
90
91
|
.disabled(!isEnabled)
|
|
@@ -122,8 +123,9 @@ public struct IconButton: View {
|
|
|
122
123
|
/// Type-erased shape switch (`Circle` vs a fixed `Radius.S` rounded rect) — mirrors
|
|
123
124
|
/// Compose's `IconShape.toShape()`. `AnyShape` needs iOS 17+, so this hand-rolls the same
|
|
124
125
|
/// erasure at the deployment target's iOS 15 floor.
|
|
125
|
-
private struct IconButtonShape:
|
|
126
|
+
private struct IconButtonShape: InsettableShape {
|
|
126
127
|
let shape: IconShape
|
|
128
|
+
var insetAmount: CGFloat = 0
|
|
127
129
|
|
|
128
130
|
init(_ shape: IconShape) {
|
|
129
131
|
self.shape = shape
|
|
@@ -132,9 +134,15 @@ private struct IconButtonShape: Shape {
|
|
|
132
134
|
func path(in rect: CGRect) -> Path {
|
|
133
135
|
switch shape {
|
|
134
136
|
case .circle:
|
|
135
|
-
return Circle().path(in: rect)
|
|
137
|
+
return Circle().inset(by: insetAmount).path(in: rect)
|
|
136
138
|
case .square:
|
|
137
|
-
return RoundedRectangle(cornerRadius: Radius.S).path(in: rect)
|
|
139
|
+
return RoundedRectangle(cornerRadius: Radius.S).inset(by: insetAmount).path(in: rect)
|
|
138
140
|
}
|
|
139
141
|
}
|
|
142
|
+
|
|
143
|
+
func inset(by amount: CGFloat) -> IconButtonShape {
|
|
144
|
+
var shape = self
|
|
145
|
+
shape.insetAmount += amount
|
|
146
|
+
return shape
|
|
147
|
+
}
|
|
140
148
|
}
|
package/ios/Image/Image.swift
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import Foundation
|
|
4
4
|
import SDWebImageSwiftUI
|
|
5
|
-
import SkeletonUI
|
|
6
5
|
import SwiftUI
|
|
7
6
|
|
|
8
7
|
public enum ImageState {
|
|
@@ -39,22 +38,23 @@ public struct ImageView: View {
|
|
|
39
38
|
.resizable()
|
|
40
39
|
.renderingMode(color != nil ? .template : .original)
|
|
41
40
|
.placeholder {
|
|
42
|
-
VStack(alignment: .center
|
|
41
|
+
VStack(alignment: .center) {
|
|
43
42
|
if error {
|
|
44
|
-
|
|
45
|
-
} else if placeholder
|
|
43
|
+
Icon(source: "media_fail", color: theme.colors.text.disable)
|
|
44
|
+
} else if let placeholder {
|
|
46
45
|
placeholder
|
|
46
|
+
} else if loading {
|
|
47
|
+
Skeleton()
|
|
47
48
|
}
|
|
48
|
-
}
|
|
49
|
+
}
|
|
49
50
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
50
|
-
.skeleton(with: loading && !error && placeholder == nil)
|
|
51
|
-
.shape(type: .rectangle)
|
|
52
51
|
}
|
|
53
52
|
.scaledToFit()
|
|
54
53
|
.transition(.fade)
|
|
55
54
|
.aspectRatio(aspectRatio, contentMode: contentMode)
|
|
56
55
|
.foregroundColor(color)
|
|
57
56
|
.onAppear { onStateChanged?(.loading) }
|
|
57
|
+
.onChange(of: url) { _ in error = false }
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
// MARK: Internal
|
|
@@ -69,30 +69,3 @@ public struct ImageView: View {
|
|
|
69
69
|
@State var error: Bool = false
|
|
70
70
|
var url: String
|
|
71
71
|
}
|
|
72
|
-
|
|
73
|
-
// A bare WebImage on purpose: going through `Icon` nests another `ImageView`, whose own
|
|
74
|
-
// failure would render this placeholder again, without end while offline.
|
|
75
|
-
private struct ImageErrorIcon: View {
|
|
76
|
-
let color: Color
|
|
77
|
-
|
|
78
|
-
var body: some View {
|
|
79
|
-
WebImage(url: URL(string: iconSources["media_fail"] ?? ""))
|
|
80
|
-
.resizable()
|
|
81
|
-
.renderingMode(.template)
|
|
82
|
-
.scaledToFit()
|
|
83
|
-
.foregroundColor(color)
|
|
84
|
-
.frame(width: 24, height: 24)
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
private struct ColorMultiplyModifier: ViewModifier {
|
|
89
|
-
let color: Color?
|
|
90
|
-
|
|
91
|
-
func body(content: Content) -> some View {
|
|
92
|
-
if let color {
|
|
93
|
-
content.colorMultiply(color)
|
|
94
|
-
} else {
|
|
95
|
-
content
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
@@ -19,6 +19,7 @@ public struct Information: View {
|
|
|
19
19
|
private let showIconClose: Bool
|
|
20
20
|
private let onPressClose: (() -> Void)?
|
|
21
21
|
private let highlightText: [String]
|
|
22
|
+
private let accessibilityLabel: String?
|
|
22
23
|
|
|
23
24
|
public init(
|
|
24
25
|
title: String? = nil,
|
|
@@ -30,7 +31,8 @@ public struct Information: View {
|
|
|
30
31
|
action: String? = nil,
|
|
31
32
|
showIconClose: Bool = true,
|
|
32
33
|
onPressClose: (() -> Void)? = nil,
|
|
33
|
-
highlightText: [String] = []
|
|
34
|
+
highlightText: [String] = [],
|
|
35
|
+
accessibilityLabel: String? = nil
|
|
34
36
|
) {
|
|
35
37
|
self.title = title
|
|
36
38
|
self.description = description
|
|
@@ -42,6 +44,11 @@ public struct Information: View {
|
|
|
42
44
|
self.showIconClose = showIconClose
|
|
43
45
|
self.onPressClose = onPressClose
|
|
44
46
|
self.highlightText = highlightText
|
|
47
|
+
self.accessibilityLabel = accessibilityLabel
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private var automationId: String {
|
|
51
|
+
accessibilityLabel ?? "Information\(title.map { "/\($0)" } ?? "")"
|
|
45
52
|
}
|
|
46
53
|
|
|
47
54
|
private var borderColor: Color {
|
|
@@ -80,20 +87,23 @@ public struct Information: View {
|
|
|
80
87
|
VStack(alignment: .leading, spacing: 0) {
|
|
81
88
|
HStack(alignment: .top, spacing: 0) {
|
|
82
89
|
if let image {
|
|
83
|
-
ImageView(image)
|
|
90
|
+
ImageView(image, contentMode: .fill)
|
|
84
91
|
.frame(width: 40, height: 40)
|
|
85
92
|
.clipShape(RoundedRectangle(cornerRadius: Radius.S))
|
|
93
|
+
.accessibilityIdentifier("\(automationId)|img")
|
|
86
94
|
.padding(.trailing, Spacing.S)
|
|
87
95
|
} else if showIcon {
|
|
88
96
|
Icon(source: iconSource, size: 16, color: accentColor)
|
|
97
|
+
.accessibilityIdentifier("\(automationId)|icon")
|
|
89
98
|
.padding(.trailing, Spacing.S)
|
|
90
99
|
}
|
|
91
100
|
|
|
92
101
|
VStack(alignment: .leading, spacing: 0) {
|
|
93
102
|
if let title {
|
|
94
|
-
MomoText(title, typography: .labelDefaultMedium)
|
|
103
|
+
MomoText(title, typography: .labelDefaultMedium, accessibilityId: "\(automationId)|title-text")
|
|
95
104
|
}
|
|
96
105
|
MomoText(description, typography: .descriptionDefaultRegular, highlightText: highlightText)
|
|
106
|
+
.accessibilityIdentifier("\(automationId)|description-text")
|
|
97
107
|
}
|
|
98
108
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
99
109
|
|
|
@@ -101,15 +111,21 @@ public struct Information: View {
|
|
|
101
111
|
Icon(source: "navigation_close", size: 16, color: theme.colors.text.default)
|
|
102
112
|
.contentShape(Rectangle())
|
|
103
113
|
.onTapGesture(perform: onPressClose)
|
|
114
|
+
.accessibilityAddTraits(.isButton)
|
|
115
|
+
.accessibilityIdentifier("\(automationId)|close-icon-touch")
|
|
104
116
|
}
|
|
105
117
|
}
|
|
106
118
|
|
|
107
119
|
if let action, let onPressAction {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
120
|
+
HStack(spacing: 0) {
|
|
121
|
+
MomoText(action, typography: .actionXsBold, color: accentColor, accessibilityId: "\(automationId)|cta-text")
|
|
122
|
+
}
|
|
123
|
+
.frame(maxWidth: .infinity, alignment: .trailing)
|
|
124
|
+
.contentShape(Rectangle())
|
|
125
|
+
.onTapGesture(perform: onPressAction)
|
|
126
|
+
.accessibilityElement(children: .contain)
|
|
127
|
+
.accessibilityIdentifier("\(automationId)|cta-touch")
|
|
128
|
+
.padding(.top, Spacing.S)
|
|
113
129
|
}
|
|
114
130
|
}
|
|
115
131
|
.padding(Spacing.M)
|
|
@@ -119,8 +135,10 @@ public struct Information: View {
|
|
|
119
135
|
)
|
|
120
136
|
.overlay(
|
|
121
137
|
RoundedRectangle(cornerRadius: Radius.S)
|
|
122
|
-
.
|
|
138
|
+
.strokeBorder(borderColor, lineWidth: 0.5)
|
|
123
139
|
)
|
|
140
|
+
.accessibilityElement(children: .contain)
|
|
141
|
+
.accessibilityIdentifier(automationId)
|
|
124
142
|
}
|
|
125
143
|
}
|
|
126
144
|
|