@momo-kits/native-kits 0.162.2-sp.1 → 0.162.2-sp.10-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/settings.local.json +15 -1
- package/CLAUDE.md +78 -0
- package/build.gradle.kts +11 -0
- package/compose/build.gradle.kts +190 -0
- package/compose/build.gradle.kts.backup +190 -0
- package/compose/compose.podspec +47 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/navigation/ScrollToTop.android.kt +6 -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 +123 -0
- package/compose/src/commonMain/composeResources/font/momosignature.otf +0 -0
- package/compose/src/commonMain/composeResources/font/momotrustdisplay.otf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_black.otf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_black.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_bold.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_heavy.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_light.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_medium.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_regular.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_semibold.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_thin.otf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_thin.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.otf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.ttf +0 -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 +106 -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 +294 -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 +826 -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 +82 -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 +356 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +113 -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 +543 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +23 -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 +112 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +477 -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 +214 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +240 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +216 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +259 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +182 -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 +328 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +97 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +310 -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 +323 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +217 -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 +199 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +91 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +470 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +88 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +131 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +203 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +498 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +175 -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 +234 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +188 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +306 -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 +276 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +2 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +35 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +2 -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 +253 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +129 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +100 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +172 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +360 -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 +581 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +156 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +225 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +86 -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 +320 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +81 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +309 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +34 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +360 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +132 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +128 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +70 -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 +58 -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 +105 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +32 -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 +184 -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 +15 -2
- package/ios/Application/Components.swift +16 -0
- 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 +3 -1
- package/ios/Application/Navigation/NavigationContainer.swift +53 -4
- package/ios/Application/Navigation/Navigator.swift +54 -29
- package/ios/Application/Navigation/Overplay/BottomSheet.swift +98 -18
- package/ios/Application/Navigation/Overplay/ModalScreen.swift +6 -0
- package/ios/Application/Navigation/Tracking/ScreenTracker.swift +117 -0
- package/ios/Application/Screen.swift +2 -1
- package/ios/Application/StackScreen.swift +55 -3
- package/ios/Badge/BadgeRibbon.swift +80 -0
- package/ios/Button/Button.swift +67 -11
- package/ios/Carousel/Carousel.swift +16 -1
- package/ios/Checkbox/Checkbox.swift +14 -20
- package/ios/Chip/Chip.swift +35 -26
- package/ios/Collapse/Collapse.swift +11 -1
- 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 +15 -15
- package/ios/DateTimePicker/DateTimePicker.swift +4 -2
- package/ios/DateTimePicker/WheelPicker.swift +7 -3
- package/ios/Extensions/ActiveOpacityButtonStyle.swift +14 -0
- package/ios/Extensions/Color++.swift +32 -0
- package/ios/Icon/Icon.swift +5 -1
- package/ios/IconButton/IconButton.swift +35 -7
- 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 +31 -8
- package/ios/Input/InputPhoneNumber.swift +14 -3
- package/ios/Input/InputSearch.swift +7 -1
- package/ios/Input/InputTextArea.swift +78 -34
- package/ios/InputDropDown/InputDropDown.swift +4 -1
- package/ios/InputMoney/InputMoney.swift +16 -4
- package/ios/Popup/PopupDisplay.swift +3 -4
- package/ios/Popup/PopupNotify.swift +3 -4
- package/ios/ProgressInfo/ProgressInfo.swift +4 -2
- package/ios/Radio/Radio.swift +12 -13
- package/ios/Rating/Rating.swift +1 -1
- 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/Stepper/Stepper.swift +2 -2
- package/ios/Steps/Steps.swift +22 -6
- package/ios/SuggestAction/SuggestAction.swift +5 -3
- package/ios/Swipeable/SwipeCell.swift +5 -3
- package/ios/Switch/Switch.swift +53 -28
- package/ios/TabView/TabView.swift +18 -14
- package/ios/Template/TrustBanner/TrustBanner.swift +6 -7
- package/ios/Tooltip/Tooltip.swift +3 -0
- package/ios/Typography/FontScaleStore.swift +19 -0
- package/ios/Typography/Text.swift +3 -0
- package/ios/Typography/Typography.swift +8 -5
- package/ios/Uploader/Uploader.swift +0 -9
- package/ios/native-kits.podspec +6 -3
- package/ios-demo/MoMoUIKitsDemo.podspec +5 -3
- package/ios-demo/README.md +120 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/MoMoUIKitsDemoFactory.swift +9 -57
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +21 -3
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LocalizeDemo.swift +188 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +2 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SwiftUIDemoBrowserView.swift +5 -4
- package/local.properties +8 -0
- package/package.json +1 -1
- package/settings.gradle.kts +64 -0
|
@@ -94,12 +94,27 @@ public struct Carousel<Content: View>: View {
|
|
|
94
94
|
// Offset so the current page is centered within the viewport padding.
|
|
95
95
|
let baseOffset = -CGFloat(currentPage) * step + contentPadding
|
|
96
96
|
|
|
97
|
+
// Windows the rendered range around `currentPage` instead of instantiating all
|
|
98
|
+
// `virtualPageCount` slides up front — with `loop=true`, that's `itemCount * 1000`
|
|
99
|
+
// eager views, a real memory/perf regression versus Compose's lazy `HorizontalPager`.
|
|
100
|
+
// Clear spacers of the skipped width keep the HStack's total layout size (and thus
|
|
101
|
+
// the existing `baseOffset` math) unchanged.
|
|
102
|
+
let windowRadius = 3
|
|
103
|
+
let windowStart = max(0, currentPage - windowRadius)
|
|
104
|
+
let windowEnd = min(virtualPageCount - 1, currentPage + windowRadius)
|
|
105
|
+
|
|
97
106
|
ZStack {
|
|
98
107
|
HStack(spacing: 0) {
|
|
99
|
-
|
|
108
|
+
if windowStart > 0 {
|
|
109
|
+
Color.clear.frame(width: CGFloat(windowStart) * step)
|
|
110
|
+
}
|
|
111
|
+
ForEach(windowStart...windowEnd, id: \.self) { page in
|
|
100
112
|
slide(page: page, step: step, viewportWidth: viewportWidth)
|
|
101
113
|
.frame(width: pageWidth)
|
|
102
114
|
}
|
|
115
|
+
if windowEnd < virtualPageCount - 1 {
|
|
116
|
+
Color.clear.frame(width: CGFloat(virtualPageCount - 1 - windowEnd) * step)
|
|
117
|
+
}
|
|
103
118
|
}
|
|
104
119
|
.offset(x: baseOffset + dragOffset)
|
|
105
120
|
.animation(isDragging ? nil : .easeInOut(duration: 0.25), value: currentPage)
|
|
@@ -28,29 +28,23 @@ public struct Checkbox: View{
|
|
|
28
28
|
public var body: some View {
|
|
29
29
|
HStack(spacing: Spacing.S) {
|
|
30
30
|
// Checkbox
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
SwiftUI.Button(action: onCheck) {
|
|
32
|
+
ZStack {
|
|
33
|
+
RoundedRectangle(cornerRadius: Radius.XS)
|
|
34
|
+
.fill(backgroundColor)
|
|
35
|
+
.frame(width: 20, height: 20)
|
|
36
|
+
.overlay(
|
|
37
|
+
RoundedRectangle(cornerRadius: Radius.XS)
|
|
38
|
+
.stroke(borderColor, lineWidth: Spacing.XXS)
|
|
39
|
+
)
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
.scaledToFit()
|
|
44
|
-
.foregroundColor(Colors.black01)
|
|
45
|
-
.frame(width: 12, height: 12)
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
.onTapGesture {
|
|
50
|
-
if !disabled {
|
|
51
|
-
onCheck()
|
|
41
|
+
if checked {
|
|
42
|
+
Icon(source: indeterminate ? "navigation_minus" : "ic_checked", size: 20, color: Colors.black01)
|
|
43
|
+
}
|
|
52
44
|
}
|
|
53
45
|
}
|
|
46
|
+
.buttonStyle(ActiveOpacityButtonStyle(activeOpacity: 0.8))
|
|
47
|
+
.disabled(disabled)
|
|
54
48
|
|
|
55
49
|
// Title
|
|
56
50
|
if !title.isEmpty {
|
package/ios/Chip/Chip.swift
CHANGED
|
@@ -52,6 +52,13 @@ public struct Chip: View {
|
|
|
52
52
|
|
|
53
53
|
public var body: some View {
|
|
54
54
|
let dims = (size == .small) ? Self.Small : Self.Large
|
|
55
|
+
// Mirrors Compose's `scaleSize(...)` on every chip dimension so it responds
|
|
56
|
+
// to Dynamic Type scaling the same way the rest of the kit does.
|
|
57
|
+
let height = scaleSize(dims.height)
|
|
58
|
+
let horizontal = scaleSize(dims.horizontal)
|
|
59
|
+
let iconSize = scaleSize(dims.iconSize)
|
|
60
|
+
let iconSpacing = scaleSize(dims.iconSpacing)
|
|
61
|
+
let radius = scaleSize(Radius.L)
|
|
55
62
|
|
|
56
63
|
let bg: Color = {
|
|
57
64
|
if selected { return theme.colors.background.selected }
|
|
@@ -63,36 +70,38 @@ public struct Chip: View {
|
|
|
63
70
|
let leftTint: Color = selected ? theme.colors.primary : iconLeftTint ?? theme.colors.text.default
|
|
64
71
|
let rightTint: Color = selected ? theme.colors.primary : iconRightTint ?? theme.colors.text.default
|
|
65
72
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
73
|
+
SwiftUI.Button(action: onClick) {
|
|
74
|
+
HStack(spacing: iconSpacing) {
|
|
75
|
+
if let iconLeft {
|
|
76
|
+
Icon(source: iconLeft, size: iconSize, color: leftTint)
|
|
77
|
+
}
|
|
70
78
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
79
|
+
if let text = label, !text.isEmpty {
|
|
80
|
+
MomoText(text, typography: (size == .large) ? .labelDefaultMedium : .labelSMedium, color: textColor)
|
|
81
|
+
.lineLimit(1)
|
|
82
|
+
}
|
|
75
83
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
.padding(.horizontal, dims.horizontal)
|
|
81
|
-
.frame(height: dims.height)
|
|
82
|
-
.background(
|
|
83
|
-
RoundedRectangle(cornerRadius: Radius.L, style: .continuous)
|
|
84
|
-
.fill(bg)
|
|
85
|
-
)
|
|
86
|
-
.overlay(
|
|
87
|
-
Group {
|
|
88
|
-
if selected {
|
|
89
|
-
RoundedRectangle(cornerRadius: Radius.L, style: .continuous)
|
|
90
|
-
.stroke(theme.colors.secondary, lineWidth: 2)
|
|
84
|
+
if let iconRight {
|
|
85
|
+
Icon(source: iconRight, size: iconSize, color: rightTint)
|
|
91
86
|
}
|
|
92
87
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
88
|
+
.padding(.horizontal, horizontal)
|
|
89
|
+
.frame(height: height)
|
|
90
|
+
.background(
|
|
91
|
+
RoundedRectangle(cornerRadius: radius, style: .continuous)
|
|
92
|
+
.fill(bg)
|
|
93
|
+
)
|
|
94
|
+
.overlay(
|
|
95
|
+
Group {
|
|
96
|
+
if selected {
|
|
97
|
+
RoundedRectangle(cornerRadius: radius, style: .continuous)
|
|
98
|
+
.stroke(theme.colors.secondary, lineWidth: 2)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
.contentShape(RoundedRectangle(cornerRadius: radius, style: .continuous))
|
|
103
|
+
}
|
|
104
|
+
.buttonStyle(ActiveOpacityButtonStyle())
|
|
96
105
|
.modifier(ChipAccessibilityModifier(accessibilityLabel: accessibilityLabel))
|
|
97
106
|
}
|
|
98
107
|
}
|
|
@@ -30,6 +30,7 @@ public struct Collapse<Content: View>: View {
|
|
|
30
30
|
private let useBackgroundCollapseButton: Bool
|
|
31
31
|
private let backgroundColor: Color?
|
|
32
32
|
private let titleColor: Color?
|
|
33
|
+
private let accessibilityId: String?
|
|
33
34
|
private let onPress: ((Bool) -> Void)?
|
|
34
35
|
private let content: (() -> Content)?
|
|
35
36
|
|
|
@@ -49,6 +50,7 @@ public struct Collapse<Content: View>: View {
|
|
|
49
50
|
useBackgroundCollapseButton: Bool = false,
|
|
50
51
|
backgroundColor: Color? = nil,
|
|
51
52
|
titleColor: Color? = nil,
|
|
53
|
+
accessibilityId: String? = nil,
|
|
52
54
|
onPress: ((Bool) -> Void)? = nil,
|
|
53
55
|
@ViewBuilder content: @escaping () -> Content
|
|
54
56
|
) {
|
|
@@ -65,11 +67,17 @@ public struct Collapse<Content: View>: View {
|
|
|
65
67
|
self.useBackgroundCollapseButton = useBackgroundCollapseButton
|
|
66
68
|
self.backgroundColor = backgroundColor
|
|
67
69
|
self.titleColor = titleColor
|
|
70
|
+
self.accessibilityId = accessibilityId
|
|
68
71
|
self.onPress = onPress
|
|
69
72
|
self.content = content
|
|
70
73
|
_expanded = State(initialValue: expandDefault)
|
|
71
74
|
}
|
|
72
75
|
|
|
76
|
+
// Mirrors Kotlin's `accessibilityId ?: "Collapse/$title"`.
|
|
77
|
+
private var automationId: String {
|
|
78
|
+
accessibilityId ?? "Collapse/\(title)"
|
|
79
|
+
}
|
|
80
|
+
|
|
73
81
|
private var resolvedBackgroundColor: Color {
|
|
74
82
|
backgroundColor ?? theme.colors.background.surface
|
|
75
83
|
}
|
|
@@ -97,6 +105,7 @@ public struct Collapse<Content: View>: View {
|
|
|
97
105
|
.frame(maxWidth: .infinity)
|
|
98
106
|
.background(resolvedBackgroundColor)
|
|
99
107
|
.clipShape(RoundedRectangle(cornerRadius: Radius.S, style: .continuous))
|
|
108
|
+
.accessibilityIdentifier(automationId)
|
|
100
109
|
.overlay(
|
|
101
110
|
showBorder
|
|
102
111
|
? RoundedRectangle(cornerRadius: Radius.S, style: .continuous)
|
|
@@ -159,7 +168,8 @@ public struct Collapse<Content: View>: View {
|
|
|
159
168
|
.frame(maxWidth: .infinity)
|
|
160
169
|
.contentShape(Rectangle())
|
|
161
170
|
}
|
|
162
|
-
.buttonStyle(
|
|
171
|
+
.buttonStyle(ActiveOpacityButtonStyle())
|
|
172
|
+
.accessibilityIdentifier("\(automationId)|touch")
|
|
163
173
|
}
|
|
164
174
|
|
|
165
175
|
private var chevron: some View {
|
|
@@ -3,18 +3,18 @@ import Foundation
|
|
|
3
3
|
import SwiftUI
|
|
4
4
|
|
|
5
5
|
public enum Colors {
|
|
6
|
-
public static let primary = Color("Primary")
|
|
7
|
-
public static let primaryDark = Color("PrimaryDark")
|
|
8
|
-
public static let primaryLight = Color("PrimaryLight")
|
|
9
|
-
public static let secondary = Color("Secondary")
|
|
10
|
-
public static let background = Color("Background")
|
|
11
|
-
public static let border = Color("Border")
|
|
12
|
-
public static let text = Color("ThemeColors/text-default")
|
|
13
|
-
public static let textSecondary = Color("TextSecondary")
|
|
14
|
-
public static let card = Color("Card")
|
|
15
|
-
public static let error = Color("Error")
|
|
16
|
-
public static let info =
|
|
17
|
-
public static let success = Color("Success")
|
|
6
|
+
public static let primary = Color.momoAsset("Primary")
|
|
7
|
+
public static let primaryDark = Color.momoAsset("PrimaryDark")
|
|
8
|
+
public static let primaryLight = Color.momoAsset("PrimaryLight")
|
|
9
|
+
public static let secondary = Color.momoAsset("Secondary")
|
|
10
|
+
public static let background = Color.momoAsset("Background")
|
|
11
|
+
public static let border = Color.momoAsset("Border")
|
|
12
|
+
public static let text = Color.momoAsset("ThemeColors/text-default")
|
|
13
|
+
public static let textSecondary = Color.momoAsset("TextSecondary")
|
|
14
|
+
public static let card = Color.momoAsset("Card")
|
|
15
|
+
public static let error = Color.momoAsset("Error")
|
|
16
|
+
public static let info = blue03
|
|
17
|
+
public static let success = Color.momoAsset("Success")
|
|
18
18
|
|
|
19
19
|
public static let black20 = Color(hex: "000000")
|
|
20
20
|
public static let black19 = Color(hex: "18191a")
|
|
@@ -49,15 +49,18 @@ public enum Colors {
|
|
|
49
49
|
public static let pink03 = Color(hex: "eb2f96")
|
|
50
50
|
public static let pink02 = Color(hex: "d42a87")
|
|
51
51
|
public static let pink01 = Color(hex: "bc2678")
|
|
52
|
+
public static let pinkMoMoBranding = Color(hex: "a50064")
|
|
52
53
|
|
|
53
54
|
|
|
54
|
-
public static let
|
|
55
|
-
public static let
|
|
55
|
+
public static let violet11 = Color(hex: "fcf8fe")
|
|
56
|
+
public static let violet11Stroke = Color(hex: "dfe1e5")
|
|
57
|
+
public static let violet10 = Color(hex: "faf4fe")
|
|
58
|
+
public static let violet09 = Color(hex: "f4e9fd")
|
|
56
59
|
public static let violet08 = Color(hex: "ead4fc")
|
|
57
60
|
public static let violet07 = Color(hex: "d5aaf9")
|
|
58
|
-
public static let violet06 = Color(hex: "
|
|
59
|
-
public static let violet05 = Color(hex: "
|
|
60
|
-
public static let violet04 = Color(hex: "
|
|
61
|
+
public static let violet06 = Color(hex: "c07ff6")
|
|
62
|
+
public static let violet05 = Color(hex: "ab55f3")
|
|
63
|
+
public static let violet04 = Color(hex: "a03ff1")
|
|
61
64
|
public static let violet03 = Color(hex: "962af0")
|
|
62
65
|
public static let violet02 = Color(hex: "8726d8")
|
|
63
66
|
public static let violet01 = Color(hex: "7822c0")
|
|
@@ -8,5 +8,7 @@ public enum Spacing {
|
|
|
8
8
|
public static let L: CGFloat = 16
|
|
9
9
|
public static let XL: CGFloat = 24
|
|
10
10
|
public static let XXL: CGFloat = 32
|
|
11
|
-
public static let
|
|
11
|
+
public static let Size3XL: CGFloat = 48
|
|
12
|
+
public static let Size4XL: CGFloat = 56
|
|
13
|
+
public static let Size5XL: CGFloat = 64
|
|
12
14
|
}
|
|
@@ -174,26 +174,26 @@ public struct Theme {
|
|
|
174
174
|
public let defaultTheme = Theme(
|
|
175
175
|
dark: false,
|
|
176
176
|
colors: ColorScheme(
|
|
177
|
-
primary: Color("ThemeColors/primary"),
|
|
178
|
-
secondary: Color("ThemeColors/secondary"),
|
|
179
|
-
gradient: Color("ThemeColors/gradient"),
|
|
177
|
+
primary: Color.momoAsset("ThemeColors/primary"),
|
|
178
|
+
secondary: Color.momoAsset("ThemeColors/secondary"),
|
|
179
|
+
gradient: Color.momoAsset("ThemeColors/gradient"),
|
|
180
180
|
background: Background(
|
|
181
|
-
default: Color("ThemeColors/background-default"),
|
|
182
|
-
surface: Color("ThemeColors/background-surface"),
|
|
183
|
-
tonal: Color("ThemeColors/background-tonal"),
|
|
184
|
-
pressed: Color("ThemeColors/background-pressed"),
|
|
185
|
-
selected: Color("ThemeColors/background-selected"),
|
|
186
|
-
disable: Color("ThemeColors/background-disable")
|
|
181
|
+
default: Color.momoAsset("ThemeColors/background-default"),
|
|
182
|
+
surface: Color.momoAsset("ThemeColors/background-surface"),
|
|
183
|
+
tonal: Color.momoAsset("ThemeColors/background-tonal"),
|
|
184
|
+
pressed: Color.momoAsset("ThemeColors/background-pressed"),
|
|
185
|
+
selected: Color.momoAsset("ThemeColors/background-selected"),
|
|
186
|
+
disable: Color.momoAsset("ThemeColors/background-disable")
|
|
187
187
|
),
|
|
188
188
|
text: TextColors(
|
|
189
|
-
default: Color("ThemeColors/text-default"),
|
|
190
|
-
secondary: Color("ThemeColors/text-secondary"),
|
|
191
|
-
hint: Color("ThemeColors/text-hint"),
|
|
192
|
-
disable: Color("ThemeColors/text-disable")
|
|
189
|
+
default: Color.momoAsset("ThemeColors/text-default"),
|
|
190
|
+
secondary: Color.momoAsset("ThemeColors/text-secondary"),
|
|
191
|
+
hint: Color.momoAsset("ThemeColors/text-hint"),
|
|
192
|
+
disable: Color.momoAsset("ThemeColors/text-disable")
|
|
193
193
|
),
|
|
194
194
|
border: BorderColors(
|
|
195
|
-
default: Color("ThemeColors/border-default"),
|
|
196
|
-
disable: Color("ThemeColors/border-disable")
|
|
195
|
+
default: Color.momoAsset("ThemeColors/border-default"),
|
|
196
|
+
disable: Color.momoAsset("ThemeColors/border-disable")
|
|
197
197
|
),
|
|
198
198
|
success: ColorSet(
|
|
199
199
|
primary: Colors.green03,
|
|
@@ -14,6 +14,8 @@ private let datePickerWithLabelsHeight: CGFloat = 238
|
|
|
14
14
|
/// - `"HH:mm"` shows hour + minute; a lone `"HH"` switches the hour wheel to a
|
|
15
15
|
/// 12-hour clock with an AM/PM column.
|
|
16
16
|
public struct DateTimePicker: View {
|
|
17
|
+
@Environment(\.appTheme) private var theme
|
|
18
|
+
|
|
17
19
|
// MARK: Lifecycle
|
|
18
20
|
|
|
19
21
|
public init(
|
|
@@ -84,7 +86,7 @@ public struct DateTimePicker: View {
|
|
|
84
86
|
|
|
85
87
|
VStack(spacing: 0) {
|
|
86
88
|
if hasLabel {
|
|
87
|
-
MomoText(arrayLabelTime[index], typography: .actionSBold, color:
|
|
89
|
+
MomoText(arrayLabelTime[index], typography: .actionSBold, color: theme.colors.text.default)
|
|
88
90
|
.padding(.bottom, Spacing.S)
|
|
89
91
|
}
|
|
90
92
|
|
|
@@ -100,7 +102,7 @@ public struct DateTimePicker: View {
|
|
|
100
102
|
}
|
|
101
103
|
.frame(maxWidth: .infinity)
|
|
102
104
|
.frame(height: pickerHeight)
|
|
103
|
-
.background(
|
|
105
|
+
.background(theme.colors.background.surface)
|
|
104
106
|
.padding(.horizontal, Spacing.M)
|
|
105
107
|
.onAppear { emitIfValid() }
|
|
106
108
|
}
|
|
@@ -14,6 +14,8 @@ private let wheelPickerBorderWidth: CGFloat = 1
|
|
|
14
14
|
/// real value can be centered. The currently centered row is reported back via
|
|
15
15
|
/// `onChange(name, value)`.
|
|
16
16
|
public struct WheelPicker: View {
|
|
17
|
+
@Environment(\.appTheme) private var theme
|
|
18
|
+
|
|
17
19
|
// MARK: Lifecycle
|
|
18
20
|
|
|
19
21
|
public init(
|
|
@@ -76,9 +78,9 @@ public struct WheelPicker: View {
|
|
|
76
78
|
.frame(height: wheelItemHeight * CGFloat(wheelVisibleCount))
|
|
77
79
|
.overlay(
|
|
78
80
|
RoundedRectangle(cornerRadius: Radius.S)
|
|
79
|
-
.stroke(
|
|
81
|
+
.stroke(theme.colors.border.default, lineWidth: wheelPickerBorderWidth)
|
|
80
82
|
)
|
|
81
|
-
.background(
|
|
83
|
+
.background(theme.colors.background.surface.clipShape(RoundedRectangle(cornerRadius: Radius.S)))
|
|
82
84
|
.overlay(
|
|
83
85
|
// Centered translucent selection band.
|
|
84
86
|
Rectangle()
|
|
@@ -121,6 +123,8 @@ public struct WheelPicker: View {
|
|
|
121
123
|
// MARK: - WheelPickerItem
|
|
122
124
|
|
|
123
125
|
private struct WheelPickerItem: View {
|
|
126
|
+
@Environment(\.appTheme) private var theme
|
|
127
|
+
|
|
124
128
|
let text: String
|
|
125
129
|
let isSelected: Bool
|
|
126
130
|
let index: Int
|
|
@@ -142,7 +146,7 @@ private struct WheelPickerItem: View {
|
|
|
142
146
|
let scale: CGFloat = isSelected ? 1.0 : 0.87
|
|
143
147
|
|
|
144
148
|
return ZStack {
|
|
145
|
-
MomoText(text, typography: .actionSBold, color:
|
|
149
|
+
MomoText(text, typography: .actionSBold, color: theme.colors.text.default)
|
|
146
150
|
.scaleEffect(scale)
|
|
147
151
|
}
|
|
148
152
|
.frame(maxWidth: .infinity)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import SwiftUI
|
|
2
|
+
|
|
3
|
+
/// Mirrors Compose's `Modifier.activeOpacityClickable(activeOpacity:)` (modifier/Clickable.kt):
|
|
4
|
+
/// fades the whole tappable subtree to `activeOpacity` while pressed, animated, instead of
|
|
5
|
+
/// relying on a platform-default press indication.
|
|
6
|
+
struct ActiveOpacityButtonStyle: ButtonStyle {
|
|
7
|
+
var activeOpacity: Double = 0.2
|
|
8
|
+
|
|
9
|
+
func makeBody(configuration: Configuration) -> some View {
|
|
10
|
+
configuration.label
|
|
11
|
+
.opacity(configuration.isPressed ? activeOpacity : 1)
|
|
12
|
+
.animation(.default, value: configuration.isPressed)
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -1,6 +1,38 @@
|
|
|
1
1
|
import SwiftUI
|
|
2
|
+
import Foundation
|
|
3
|
+
|
|
4
|
+
private final class MoMoUIKitsBundleToken {}
|
|
5
|
+
|
|
6
|
+
enum MoMoUIKitsResources {
|
|
7
|
+
static let bundle: Bundle = {
|
|
8
|
+
let bundleName = "MoMoUIKitsResources"
|
|
9
|
+
let tokenBundle = Bundle(for: MoMoUIKitsBundleToken.self)
|
|
10
|
+
let frameworkBundle = Bundle(identifier: "org.cocoapods.MoMoUIKits")
|
|
11
|
+
let candidates = [
|
|
12
|
+
Bundle.main.resourceURL,
|
|
13
|
+
tokenBundle.resourceURL,
|
|
14
|
+
tokenBundle.bundleURL,
|
|
15
|
+
frameworkBundle?.resourceURL,
|
|
16
|
+
frameworkBundle?.bundleURL
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
for candidate in candidates {
|
|
20
|
+
guard let bundleURL = candidate?.appendingPathComponent("\(bundleName).bundle"),
|
|
21
|
+
let bundle = Bundle(url: bundleURL) else {
|
|
22
|
+
continue
|
|
23
|
+
}
|
|
24
|
+
return bundle
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return Bundle.main
|
|
28
|
+
}()
|
|
29
|
+
}
|
|
2
30
|
|
|
3
31
|
public extension Color {
|
|
32
|
+
static func momoAsset(_ name: String) -> Color {
|
|
33
|
+
Color(name, bundle: MoMoUIKitsResources.bundle)
|
|
34
|
+
}
|
|
35
|
+
|
|
4
36
|
init(hex: UInt, alpha: Double = 1) {
|
|
5
37
|
self.init(
|
|
6
38
|
.sRGB,
|
package/ios/Icon/Icon.swift
CHANGED
|
@@ -49,7 +49,11 @@ public struct Icon: View {
|
|
|
49
49
|
if let uri = iconSources[source]?.uri {
|
|
50
50
|
// Mirror Compose: certain icons (e.g. branded glyphs) are never tinted
|
|
51
51
|
let resolvedColor = noThemeIcons.contains(source) ? nil : color
|
|
52
|
-
ImageView(uri, color: resolvedColor)
|
|
52
|
+
ImageView(uri, color: resolvedColor)
|
|
53
|
+
.frame(width: size, height: size)
|
|
54
|
+
// Mirrors Compose's auto-generated `contentDescription = "img|$iconUrl"`
|
|
55
|
+
// when no explicit label is provided.
|
|
56
|
+
.accessibilityLabel(accessibilityLabel ?? "img|\(uri)")
|
|
53
57
|
}
|
|
54
58
|
}
|
|
55
59
|
}
|
|
@@ -5,13 +5,15 @@ import SwiftUI
|
|
|
5
5
|
|
|
6
6
|
public enum IconSize {
|
|
7
7
|
case large
|
|
8
|
+
case medium
|
|
8
9
|
case small
|
|
9
10
|
|
|
10
11
|
/// Container width/height of the button.
|
|
11
12
|
var containerSize: CGFloat {
|
|
12
13
|
switch self {
|
|
13
14
|
case .large: return 48
|
|
14
|
-
case .
|
|
15
|
+
case .medium: return 36
|
|
16
|
+
case .small: return 28
|
|
15
17
|
}
|
|
16
18
|
}
|
|
17
19
|
|
|
@@ -19,13 +21,16 @@ public enum IconSize {
|
|
|
19
21
|
var iconSize: CGFloat {
|
|
20
22
|
switch self {
|
|
21
23
|
case .large: return 24
|
|
22
|
-
case .small: return 16
|
|
24
|
+
case .medium, .small: return 16
|
|
23
25
|
}
|
|
24
26
|
}
|
|
27
|
+
}
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
// MARK: - IconShape
|
|
30
|
+
|
|
31
|
+
public enum IconShape {
|
|
32
|
+
case circle
|
|
33
|
+
case square
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
// MARK: - IconButton
|
|
@@ -37,6 +42,7 @@ public struct IconButton: View {
|
|
|
37
42
|
var onClick: () -> Void
|
|
38
43
|
var type: ButtonType
|
|
39
44
|
var size: IconSize
|
|
45
|
+
var shape: IconShape
|
|
40
46
|
var color: Color?
|
|
41
47
|
|
|
42
48
|
public init(
|
|
@@ -44,12 +50,14 @@ public struct IconButton: View {
|
|
|
44
50
|
onClick: @escaping () -> Void,
|
|
45
51
|
type: ButtonType = .primary,
|
|
46
52
|
size: IconSize = .small,
|
|
53
|
+
shape: IconShape = .circle,
|
|
47
54
|
color: Color? = nil
|
|
48
55
|
) {
|
|
49
56
|
self.icon = icon
|
|
50
57
|
self.onClick = onClick
|
|
51
58
|
self.type = type
|
|
52
59
|
self.size = size
|
|
60
|
+
self.shape = shape
|
|
53
61
|
self.color = color
|
|
54
62
|
}
|
|
55
63
|
|
|
@@ -72,9 +80,9 @@ public struct IconButton: View {
|
|
|
72
80
|
Icon(source: icon, size: size.iconSize, color: fg)
|
|
73
81
|
.frame(width: size.containerSize, height: size.containerSize)
|
|
74
82
|
.background(bg)
|
|
75
|
-
.clipShape(
|
|
83
|
+
.clipShape(IconButtonShape(shape))
|
|
76
84
|
.overlay(
|
|
77
|
-
|
|
85
|
+
IconButtonShape(shape)
|
|
78
86
|
.stroke(border ?? .clear, lineWidth: border != nil ? borderWidth : 0)
|
|
79
87
|
)
|
|
80
88
|
}
|
|
@@ -110,3 +118,23 @@ public struct IconButton: View {
|
|
|
110
118
|
}
|
|
111
119
|
}
|
|
112
120
|
}
|
|
121
|
+
|
|
122
|
+
/// Type-erased shape switch (`Circle` vs a fixed `Radius.S` rounded rect) — mirrors
|
|
123
|
+
/// Compose's `IconShape.toShape()`. `AnyShape` needs iOS 17+, so this hand-rolls the same
|
|
124
|
+
/// erasure at the deployment target's iOS 15 floor.
|
|
125
|
+
private struct IconButtonShape: Shape {
|
|
126
|
+
let shape: IconShape
|
|
127
|
+
|
|
128
|
+
init(_ shape: IconShape) {
|
|
129
|
+
self.shape = shape
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
func path(in rect: CGRect) -> Path {
|
|
133
|
+
switch shape {
|
|
134
|
+
case .circle:
|
|
135
|
+
return Circle().path(in: rect)
|
|
136
|
+
case .square:
|
|
137
|
+
return RoundedRectangle(cornerRadius: Radius.S).path(in: rect)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
package/ios/Image/Image.swift
CHANGED
|
@@ -5,15 +5,23 @@ import SDWebImageSwiftUI
|
|
|
5
5
|
import SkeletonUI
|
|
6
6
|
import SwiftUI
|
|
7
7
|
|
|
8
|
+
public enum ImageState {
|
|
9
|
+
case loading, success, error
|
|
10
|
+
}
|
|
11
|
+
|
|
8
12
|
public struct ImageView: View {
|
|
13
|
+
@Environment(\.appTheme) private var theme
|
|
14
|
+
|
|
9
15
|
// MARK: Lifecycle
|
|
10
16
|
|
|
11
|
-
public init(_ url: String, aspectRatio: CGFloat? = nil, contentMode: ContentMode = ContentMode.fit, placeholder: AnyView? = nil, color: Color? = nil) {
|
|
17
|
+
public init(_ url: String, aspectRatio: CGFloat? = nil, contentMode: ContentMode = ContentMode.fit, placeholder: AnyView? = nil, color: Color? = nil, loading: Bool = true, onStateChanged: ((ImageState) -> Void)? = nil) {
|
|
12
18
|
self.url = url
|
|
13
19
|
self.aspectRatio = aspectRatio
|
|
14
20
|
self.contentMode = contentMode
|
|
15
21
|
self.placeholder = placeholder
|
|
16
22
|
self.color = color
|
|
23
|
+
self.loading = loading
|
|
24
|
+
self.onStateChanged = onStateChanged
|
|
17
25
|
}
|
|
18
26
|
|
|
19
27
|
// MARK: Public
|
|
@@ -22,9 +30,11 @@ public struct ImageView: View {
|
|
|
22
30
|
return WebImage(url: URL(string: url), isAnimating: .constant(true))
|
|
23
31
|
.onFailure { _ in
|
|
24
32
|
error = true
|
|
33
|
+
onStateChanged?(.error)
|
|
25
34
|
}
|
|
26
35
|
.onSuccess { _, _, _ in
|
|
27
36
|
error = false
|
|
37
|
+
onStateChanged?(.success)
|
|
28
38
|
}
|
|
29
39
|
.resizable()
|
|
30
40
|
.renderingMode(color != nil ? .template : .original)
|
|
@@ -34,20 +44,21 @@ public struct ImageView: View {
|
|
|
34
44
|
Image("media_fail")
|
|
35
45
|
.resizable()
|
|
36
46
|
.renderingMode(.template)
|
|
37
|
-
.foregroundColor(
|
|
47
|
+
.foregroundColor(theme.colors.text.disable)
|
|
38
48
|
.frame(width: 24, height: 24)
|
|
39
49
|
} else if placeholder != nil {
|
|
40
50
|
placeholder
|
|
41
51
|
}
|
|
42
52
|
})
|
|
43
53
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
44
|
-
.skeleton(with: !error && placeholder == nil)
|
|
54
|
+
.skeleton(with: loading && !error && placeholder == nil)
|
|
45
55
|
.shape(type: .rectangle)
|
|
46
56
|
}
|
|
47
57
|
.scaledToFit()
|
|
48
58
|
.transition(.fade)
|
|
49
59
|
.aspectRatio(aspectRatio, contentMode: contentMode)
|
|
50
60
|
.foregroundColor(color)
|
|
61
|
+
.onAppear { onStateChanged?(.loading) }
|
|
51
62
|
}
|
|
52
63
|
|
|
53
64
|
// MARK: Internal
|
|
@@ -56,6 +67,8 @@ public struct ImageView: View {
|
|
|
56
67
|
var contentMode: ContentMode
|
|
57
68
|
var placeholder: AnyView?
|
|
58
69
|
var color: Color?
|
|
70
|
+
var loading: Bool
|
|
71
|
+
var onStateChanged: ((ImageState) -> Void)?
|
|
59
72
|
|
|
60
73
|
@State var error: Bool = false
|
|
61
74
|
var url: String
|
|
@@ -7,6 +7,8 @@ public enum InformationState {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
public struct Information: View {
|
|
10
|
+
@Environment(\.appTheme) private var theme
|
|
11
|
+
|
|
10
12
|
private let title: String?
|
|
11
13
|
private let description: String
|
|
12
14
|
private let state: InformationState
|
|
@@ -93,7 +95,7 @@ public struct Information: View {
|
|
|
93
95
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
94
96
|
|
|
95
97
|
if let onPressClose, showIconClose {
|
|
96
|
-
Icon(source: "navigation_close", size: 16, color:
|
|
98
|
+
Icon(source: "navigation_close", size: 16, color: theme.colors.text.default)
|
|
97
99
|
.contentShape(Rectangle())
|
|
98
100
|
.onTapGesture(perform: onPressClose)
|
|
99
101
|
}
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
import SwiftUI
|
|
9
9
|
|
|
10
10
|
public struct ErrorView: View {
|
|
11
|
+
@Environment(\.appTheme) private var theme
|
|
12
|
+
|
|
11
13
|
public var errorMessage: String
|
|
12
14
|
public var errorSpacing: Bool
|
|
13
15
|
public var hintText: String
|
|
@@ -43,7 +45,7 @@ public struct ErrorView: View {
|
|
|
43
45
|
// MARK: - Helpers
|
|
44
46
|
|
|
45
47
|
private func displayColor() -> Color {
|
|
46
|
-
!errorMessage.isEmpty ?
|
|
48
|
+
!errorMessage.isEmpty ? theme.colors.error.primary : theme.colors.text.hint
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
private func displayText() -> String {
|