@momo-kits/native-kits 0.162.18-debug → 0.162.19-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/compose/build.gradle.kts +1 -1
- package/compose/compose.podspec +1 -1
- package/gradle.properties +1 -1
- package/ios/Application/ApplicationEnvironment.swift +11 -0
- package/ios/Application/Components.swift +34 -44
- package/ios/Application/FloatingButton.swift +10 -9
- package/ios/Application/HeaderRight.swift +79 -45
- package/ios/Application/Navigation/BottomTab/BottomTab.swift +103 -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 +176 -0
- package/ios/Application/Navigation/NavigationOptions.swift +109 -0
- package/ios/Application/Navigation/Navigator.swift +364 -0
- package/ios/Application/Navigation/Overplay/BottomSheet.swift +188 -0
- package/ios/Application/Navigation/Overplay/ModalScreen.swift +68 -0
- package/ios/Application/Navigation/Overplay/SnackBar.swift +144 -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 +453 -0
- package/ios/Avatar/Avatar.swift +193 -0
- package/ios/Badge/Badge.swift +11 -14
- package/ios/Badge/BadgeRibbon.swift +12 -21
- package/ios/BaselineView/BaselineView.swift +163 -0
- package/ios/Button/Button.swift +61 -22
- package/ios/Carousel/Carousel.swift +181 -0
- package/ios/Checkbox/Checkbox.swift +14 -13
- package/ios/Chip/Chip.swift +23 -9
- package/ios/Collapse/Collapse.swift +182 -0
- package/ios/Colors+Radius+Spacing/Colors.swift +12 -12
- package/ios/Colors+Radius+Spacing/Theme.swift +295 -0
- package/ios/DateTimePicker/DateTimePicker.swift +210 -0
- package/ios/DateTimePicker/DateTimePickerTypes.swift +55 -0
- package/ios/DateTimePicker/DateTimePickerUtils.swift +167 -0
- package/ios/DateTimePicker/WheelPicker.swift +161 -0
- package/ios/Divider/Divider.swift +16 -0
- package/ios/Extensions/Color++.swift +32 -0
- package/ios/Icon/Icon.swift +6 -1
- package/ios/IconButton/IconButton.swift +112 -0
- package/ios/Input/Input.swift +41 -25
- package/ios/Input/InputPhoneNumber.swift +20 -19
- package/ios/Input/InputSearch.swift +100 -47
- package/ios/Input/InputTextArea.swift +66 -40
- package/ios/InputDropDown/InputDropDown.swift +198 -0
- package/ios/InputMoney/InputMoney.swift +335 -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 +8 -16
- package/ios/Popup/PopupInput.swift +2 -8
- package/ios/Popup/PopupNotify.swift +219 -0
- package/ios/ProgressInfo/ProgressInfo.swift +294 -0
- package/ios/Radio/Radio.swift +70 -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 +451 -0
- package/ios/SuggestAction/SuggestAction.swift +97 -0
- package/ios/Swipeable/SwipeCell.swift +185 -0
- package/ios/Swipeable/SwipeCellModel.swift +21 -0
- package/ios/TabView/TabView.swift +530 -0
- package/ios/Tag/Tag.swift +98 -0
- package/ios/Title/Title.swift +269 -0
- package/ios/Tooltip/Tooltip.swift +482 -0
- package/ios/Typography/Text.swift +76 -5
- package/ios/Uploader/Uploader.swift +183 -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 +278 -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/NavigationDemo.swift +227 -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/package.json +1 -1
- package/publish.sh +50 -0
- package/scripts/gen-ios-color.mjs +136 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
//
|
|
2
|
+
// PaginationDot.swift
|
|
3
|
+
// MoMoUIKits
|
|
4
|
+
//
|
|
5
|
+
// Native SwiftUI port of Compose's PaginationDot.
|
|
6
|
+
// An active dot is a 12x4 pill in `activeColor`; inactive dots are 4x4
|
|
7
|
+
// rounded squares in the pressed-background token.
|
|
8
|
+
//
|
|
9
|
+
|
|
10
|
+
import SwiftUI
|
|
11
|
+
|
|
12
|
+
// MARK: - Dot
|
|
13
|
+
|
|
14
|
+
/// A single pagination dot, mirroring Compose's `Dot` composable.
|
|
15
|
+
public struct PaginationDotItem: View {
|
|
16
|
+
@Environment(\.appTheme) private var theme
|
|
17
|
+
|
|
18
|
+
private let active: Bool
|
|
19
|
+
private let activeColor: Color
|
|
20
|
+
|
|
21
|
+
public init(active: Bool = false, activeColor: Color) {
|
|
22
|
+
self.active = active
|
|
23
|
+
self.activeColor = activeColor
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public var body: some View {
|
|
27
|
+
if active {
|
|
28
|
+
RoundedRectangle(cornerRadius: 4)
|
|
29
|
+
.fill(activeColor)
|
|
30
|
+
.frame(width: 12, height: 4)
|
|
31
|
+
} else {
|
|
32
|
+
RoundedRectangle(cornerRadius: 4)
|
|
33
|
+
.fill(theme.colors.background.pressed)
|
|
34
|
+
.frame(width: 4, height: 4)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// MARK: - PaginationDot
|
|
40
|
+
|
|
41
|
+
/// Mirrors Compose's `PaginationDot(activeIndex, dataLength)`.
|
|
42
|
+
public struct PaginationDot: View {
|
|
43
|
+
@Environment(\.appTheme) private var theme
|
|
44
|
+
|
|
45
|
+
private let activeIndex: Int
|
|
46
|
+
private let dataLength: Int
|
|
47
|
+
|
|
48
|
+
public init(activeIndex: Int = 0, dataLength: Int = 3) {
|
|
49
|
+
self.activeIndex = activeIndex
|
|
50
|
+
self.dataLength = dataLength
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public var body: some View {
|
|
54
|
+
HStack(spacing: 0) {
|
|
55
|
+
ForEach(0..<max(dataLength, 0), id: \.self) { i in
|
|
56
|
+
PaginationDotItem(active: i == activeIndex, activeColor: theme.colors.primary)
|
|
57
|
+
.padding(.trailing, i != dataLength - 1 ? Spacing.XS : 0)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
//
|
|
2
|
+
// PaginationNumber.swift
|
|
3
|
+
// MoMoUIKits
|
|
4
|
+
//
|
|
5
|
+
// Native SwiftUI port of Compose's PaginationNumber.
|
|
6
|
+
// Renders "current/total" text on a translucent black rounded chip.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
import SwiftUI
|
|
10
|
+
|
|
11
|
+
// MARK: - PaginationNumber
|
|
12
|
+
|
|
13
|
+
/// Mirrors Compose's `PaginationNumber(activeIndex, dataLength)`.
|
|
14
|
+
public struct PaginationNumber: View {
|
|
15
|
+
private let activeIndex: Int
|
|
16
|
+
private let dataLength: Int
|
|
17
|
+
|
|
18
|
+
public init(activeIndex: Int = 0, dataLength: Int = 2) {
|
|
19
|
+
self.activeIndex = activeIndex
|
|
20
|
+
self.dataLength = dataLength
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public var body: some View {
|
|
24
|
+
MomoText(
|
|
25
|
+
"\(1 + activeIndex)/\(dataLength)",
|
|
26
|
+
typography: .labelDefaultMedium,
|
|
27
|
+
color: Colors.black01
|
|
28
|
+
)
|
|
29
|
+
.padding(.horizontal, Spacing.S)
|
|
30
|
+
.background(
|
|
31
|
+
RoundedRectangle(cornerRadius: Radius.L)
|
|
32
|
+
.fill(Color.black.opacity(0.2)) // Color(0x33000000)
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
//
|
|
2
|
+
// PaginationScroll.swift
|
|
3
|
+
// MoMoUIKits
|
|
4
|
+
//
|
|
5
|
+
// Native SwiftUI port of Compose's PaginationScroll.
|
|
6
|
+
// Wraps arbitrary horizontally-scrollable content and renders a
|
|
7
|
+
// progress-bar style indicator whose position tracks the scroll offset.
|
|
8
|
+
//
|
|
9
|
+
|
|
10
|
+
import SwiftUI
|
|
11
|
+
|
|
12
|
+
// MARK: - Constants
|
|
13
|
+
|
|
14
|
+
private let INDICATOR_WIDTH: CGFloat = 24
|
|
15
|
+
private let PROGRESS_WIDTH: CGFloat = 72
|
|
16
|
+
|
|
17
|
+
/// Memoized offset calculation, mirroring Compose's `calculateOffset`.
|
|
18
|
+
private func calculateOffset(currentPosition: CGFloat, maxBound: CGFloat) -> CGFloat {
|
|
19
|
+
guard maxBound > 0 else { return 0 }
|
|
20
|
+
return (PROGRESS_WIDTH - INDICATOR_WIDTH) * (currentPosition / maxBound)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// MARK: - PaginationScroll
|
|
24
|
+
|
|
25
|
+
/// Mirrors Compose's `PaginationScroll(modifier, content)`.
|
|
26
|
+
///
|
|
27
|
+
/// The trailing-closure `content` is laid out in a horizontal scroll view and
|
|
28
|
+
/// the indicator below reflects the current scroll progress.
|
|
29
|
+
public struct PaginationScroll<Content: View>: View {
|
|
30
|
+
@Environment(\.appTheme) private var theme
|
|
31
|
+
|
|
32
|
+
private let content: Content
|
|
33
|
+
|
|
34
|
+
@State private var scrollOffset: CGFloat = 0
|
|
35
|
+
@State private var contentWidth: CGFloat = 0
|
|
36
|
+
@State private var viewportWidth: CGFloat = 0
|
|
37
|
+
|
|
38
|
+
public init(@ViewBuilder content: () -> Content) {
|
|
39
|
+
self.content = content()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private var maxBound: CGFloat {
|
|
43
|
+
max(contentWidth - viewportWidth, 0)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private var indicatorOffset: CGFloat {
|
|
47
|
+
calculateOffset(currentPosition: scrollOffset, maxBound: maxBound)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public var body: some View {
|
|
51
|
+
VStack(spacing: 0) {
|
|
52
|
+
ScrollView(.horizontal, showsIndicators: false) {
|
|
53
|
+
HStack(spacing: 0) {
|
|
54
|
+
content
|
|
55
|
+
}
|
|
56
|
+
.background(
|
|
57
|
+
GeometryReader { proxy in
|
|
58
|
+
Color.clear
|
|
59
|
+
.preference(
|
|
60
|
+
key: ScrollOffsetKey.self,
|
|
61
|
+
value: -proxy.frame(in: .named("paginationScroll")).minX
|
|
62
|
+
)
|
|
63
|
+
.onAppear { contentWidth = proxy.size.width }
|
|
64
|
+
.onChange(of: proxy.size.width) { contentWidth = $0 }
|
|
65
|
+
}
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
.coordinateSpace(name: "paginationScroll")
|
|
69
|
+
.background(
|
|
70
|
+
GeometryReader { viewport in
|
|
71
|
+
Color.clear
|
|
72
|
+
.onAppear { viewportWidth = viewport.size.width }
|
|
73
|
+
.onChange(of: viewport.size.width) { viewportWidth = $0 }
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
.onPreferenceChange(ScrollOffsetKey.self) { scrollOffset = max($0, 0) }
|
|
77
|
+
.padding(.bottom, Spacing.L)
|
|
78
|
+
|
|
79
|
+
// Progress indicator
|
|
80
|
+
ZStack(alignment: .leading) {
|
|
81
|
+
RoundedRectangle(cornerRadius: Spacing.XS)
|
|
82
|
+
.fill(theme.colors.background.pressed)
|
|
83
|
+
.frame(width: PROGRESS_WIDTH, height: 4)
|
|
84
|
+
|
|
85
|
+
RoundedRectangle(cornerRadius: Spacing.XS)
|
|
86
|
+
.fill(theme.colors.primary)
|
|
87
|
+
.frame(width: INDICATOR_WIDTH, height: 4)
|
|
88
|
+
.offset(x: indicatorOffset)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// MARK: - Preference key
|
|
95
|
+
|
|
96
|
+
private struct ScrollOffsetKey: PreferenceKey {
|
|
97
|
+
static var defaultValue: CGFloat = 0
|
|
98
|
+
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
|
|
99
|
+
value = nextValue()
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
//
|
|
2
|
+
// PaginationWhiteDot.swift
|
|
3
|
+
// MoMoUIKits
|
|
4
|
+
//
|
|
5
|
+
// Native SwiftUI port of Compose's PaginationWhiteDot.
|
|
6
|
+
// Same dot layout as PaginationDot, but the active color is white
|
|
7
|
+
// (black_01) and the row sits on a translucent black rounded surface.
|
|
8
|
+
//
|
|
9
|
+
|
|
10
|
+
import SwiftUI
|
|
11
|
+
|
|
12
|
+
// MARK: - PaginationWhiteDot
|
|
13
|
+
|
|
14
|
+
/// Mirrors Compose's `PaginationWhiteDot(activeIndex, dataLength)`.
|
|
15
|
+
public struct PaginationWhiteDot: View {
|
|
16
|
+
private let activeIndex: Int
|
|
17
|
+
private let dataLength: Int
|
|
18
|
+
|
|
19
|
+
public init(activeIndex: Int = 0, dataLength: Int = 3) {
|
|
20
|
+
self.activeIndex = activeIndex
|
|
21
|
+
self.dataLength = dataLength
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public var body: some View {
|
|
25
|
+
HStack(spacing: 0) {
|
|
26
|
+
ForEach(0..<max(dataLength, 0), id: \.self) { i in
|
|
27
|
+
PaginationDotItem(active: i == activeIndex, activeColor: Colors.black01)
|
|
28
|
+
.padding(.trailing, i != dataLength - 1 ? Spacing.XS : 0)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
.padding(Spacing.XS)
|
|
32
|
+
.background(
|
|
33
|
+
RoundedRectangle(cornerRadius: Radius.S)
|
|
34
|
+
.fill(Color.black.opacity(0.2)) // Color(0x33000000)
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -221,17 +221,13 @@ public struct PopupDisplay: View {
|
|
|
221
221
|
var RowTextButtons: some View {
|
|
222
222
|
HStack {
|
|
223
223
|
SwiftUI.Button(action: onPressCloseButton) {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
.ignoreBoldTextSetting()
|
|
227
|
-
}.foregroundColor(Colors.black09)
|
|
224
|
+
MomoText(closeButtonTitle, typography: .actionSBold, color: Colors.black09)
|
|
225
|
+
}
|
|
228
226
|
.padding(.trailing, 12)
|
|
229
227
|
|
|
230
228
|
SwiftUI.Button(action: onPressAction) {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
.ignoreBoldTextSetting()
|
|
234
|
-
}.foregroundColor(Colors.primary)
|
|
229
|
+
MomoText(actionButtonTitle, typography: .actionSBold, color: Colors.primary)
|
|
230
|
+
}
|
|
235
231
|
}
|
|
236
232
|
.frame(maxWidth: .infinity, alignment: .trailing)
|
|
237
233
|
.padding(EdgeInsets(top: 0, leading: 0, bottom: 24, trailing: 24))
|
|
@@ -240,17 +236,13 @@ public struct PopupDisplay: View {
|
|
|
240
236
|
var ColumnTextButtons: some View {
|
|
241
237
|
VStack(alignment: .trailing) {
|
|
242
238
|
SwiftUI.Button(action: onPressAction) {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
.ignoreBoldTextSetting()
|
|
246
|
-
}.foregroundColor(Colors.primary)
|
|
239
|
+
MomoText(actionButtonTitle, typography: .actionSBold, color: Colors.primary)
|
|
240
|
+
}
|
|
247
241
|
.padding(.bottom, 6)
|
|
248
242
|
|
|
249
243
|
SwiftUI.Button(action: onPressCloseButton) {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
.ignoreBoldTextSetting()
|
|
253
|
-
}.foregroundColor(Colors.black09)
|
|
244
|
+
MomoText(closeButtonTitle, typography: .actionSBold, color: Colors.black09)
|
|
245
|
+
}
|
|
254
246
|
}
|
|
255
247
|
.frame(maxWidth: .infinity, alignment: .trailing)
|
|
256
248
|
.padding(EdgeInsets(top: 0, leading: 0, bottom: 24, trailing: 24))
|
|
@@ -35,17 +35,11 @@ public struct PopupInput: View {
|
|
|
35
35
|
|
|
36
36
|
VStack {
|
|
37
37
|
VStack(alignment: .leading) {
|
|
38
|
-
|
|
39
|
-
.foregroundColor(.black)
|
|
40
|
-
.font(.headerText1)
|
|
41
|
-
.ignoreBoldTextSetting()
|
|
38
|
+
MomoText(title, typography: .headerDefaultBold, color: .black)
|
|
42
39
|
.padding(.top, 12)
|
|
43
40
|
.padding(.bottom, 24)
|
|
44
41
|
|
|
45
|
-
|
|
46
|
-
.foregroundColor(.black)
|
|
47
|
-
.font(.paragraph)
|
|
48
|
-
.ignoreBoldTextSetting()
|
|
42
|
+
MomoText(description, typography: .bodyDefaultRegular, color: .black)
|
|
49
43
|
.opacity(0.6)
|
|
50
44
|
.multilineTextAlignment(.leading)
|
|
51
45
|
.padding(.bottom, 20)
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import SDWebImageSwiftUI
|
|
2
|
+
import SwiftUI
|
|
3
|
+
|
|
4
|
+
public typealias PopupActionDirection = PopupButtonDirection
|
|
5
|
+
|
|
6
|
+
public struct PopupNotifyProps {
|
|
7
|
+
public var image: String
|
|
8
|
+
public var title: String
|
|
9
|
+
public var description: String
|
|
10
|
+
public var error: String
|
|
11
|
+
public var primary: PopupAction?
|
|
12
|
+
public var secondary: PopupAction?
|
|
13
|
+
public var buttonDirection: PopupActionDirection
|
|
14
|
+
public var onIconClose: () -> Void
|
|
15
|
+
public var isShowCloseIcon: Bool
|
|
16
|
+
|
|
17
|
+
public init(
|
|
18
|
+
image: String = "",
|
|
19
|
+
title: String = "Title",
|
|
20
|
+
description: String = "Description",
|
|
21
|
+
error: String = "",
|
|
22
|
+
primary: PopupAction? = nil,
|
|
23
|
+
secondary: PopupAction? = nil,
|
|
24
|
+
buttonDirection: PopupActionDirection = .row,
|
|
25
|
+
onIconClose: @escaping () -> Void,
|
|
26
|
+
isShowCloseIcon: Bool = true
|
|
27
|
+
) {
|
|
28
|
+
self.image = image
|
|
29
|
+
self.title = title
|
|
30
|
+
self.description = description
|
|
31
|
+
self.error = error
|
|
32
|
+
self.primary = primary
|
|
33
|
+
self.secondary = secondary
|
|
34
|
+
self.buttonDirection = buttonDirection
|
|
35
|
+
self.onIconClose = onIconClose
|
|
36
|
+
self.isShowCloseIcon = isShowCloseIcon
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public struct PopupNotify: View {
|
|
41
|
+
public let props: PopupNotifyProps
|
|
42
|
+
|
|
43
|
+
@State private var descriptionHeight: CGFloat = 0
|
|
44
|
+
|
|
45
|
+
private var errorCodePrefix: String {
|
|
46
|
+
let language = UserDefaults.standard
|
|
47
|
+
.string(forKey: "language")?
|
|
48
|
+
.replacingOccurrences(of: "\"", with: "") ?? "vi"
|
|
49
|
+
return language == "en" ? "Error code: " : "Mã lỗi: "
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private var maxDescriptionHeight: CGFloat {
|
|
53
|
+
scaleSize(TypographyStyle.bodyDefaultRegular.lineHeight) * 8.5
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private var shouldUseColumnButtons: Bool {
|
|
57
|
+
switch props.buttonDirection {
|
|
58
|
+
case .column:
|
|
59
|
+
return true
|
|
60
|
+
case .row:
|
|
61
|
+
return false
|
|
62
|
+
case .auto:
|
|
63
|
+
return (props.secondary?.title.count ?? 0) > 12 || (props.primary?.title.count ?? 0) > 12
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
public init(props: PopupNotifyProps) {
|
|
68
|
+
self.props = props
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public var body: some View {
|
|
72
|
+
ZStack(alignment: .topTrailing) {
|
|
73
|
+
VStack(spacing: 0) {
|
|
74
|
+
if !props.image.isEmpty {
|
|
75
|
+
popupImage
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
VStack(alignment: .leading, spacing: 0) {
|
|
79
|
+
MomoText(
|
|
80
|
+
props.title,
|
|
81
|
+
typography: .headerDefaultBold,
|
|
82
|
+
maxLines: 2,
|
|
83
|
+
accessibilityId: "title_popup_permission"
|
|
84
|
+
)
|
|
85
|
+
.padding(.bottom, Spacing.S)
|
|
86
|
+
|
|
87
|
+
descriptionContent
|
|
88
|
+
|
|
89
|
+
if !props.error.isEmpty {
|
|
90
|
+
MomoText(
|
|
91
|
+
errorCodePrefix + props.error,
|
|
92
|
+
typography: .descriptionXsRegular,
|
|
93
|
+
color: Colors.black12,
|
|
94
|
+
maxLines: 1
|
|
95
|
+
)
|
|
96
|
+
.padding(.top, Spacing.S)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
.frame(maxWidth: .infinity, alignment: .leading)
|
|
100
|
+
.padding(Spacing.XL)
|
|
101
|
+
|
|
102
|
+
actionButtons
|
|
103
|
+
.padding(.horizontal, Spacing.XL)
|
|
104
|
+
.padding(.bottom, Spacing.XL)
|
|
105
|
+
}
|
|
106
|
+
.background(Colors.black01)
|
|
107
|
+
.clipShape(RoundedRectangle(cornerRadius: Radius.L))
|
|
108
|
+
|
|
109
|
+
if props.isShowCloseIcon {
|
|
110
|
+
closeButton
|
|
111
|
+
.offset(x: 1, y: -11)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
.padding(.horizontal, Spacing.M)
|
|
115
|
+
.accessibilityElement(children: .ignore)
|
|
116
|
+
.accessibilityIdentifier("popup_notify")
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private var popupImage: some View {
|
|
120
|
+
WebImage(url: URL(string: props.image), isAnimating: .constant(true))
|
|
121
|
+
.resizable()
|
|
122
|
+
.placeholder {
|
|
123
|
+
Rectangle()
|
|
124
|
+
.fill(Colors.black03)
|
|
125
|
+
.aspectRatio(1.777, contentMode: .fit)
|
|
126
|
+
.frame(maxWidth: .infinity)
|
|
127
|
+
}
|
|
128
|
+
.aspectRatio(1.777, contentMode: .fit)
|
|
129
|
+
.frame(maxWidth: .infinity)
|
|
130
|
+
.clipShape(RoundedCorner(radius: Radius.L, corners: [.topLeft, .topRight]))
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@ViewBuilder
|
|
134
|
+
private var descriptionContent: some View {
|
|
135
|
+
if descriptionHeight > maxDescriptionHeight {
|
|
136
|
+
ScrollView(.vertical, showsIndicators: false) {
|
|
137
|
+
descriptionText
|
|
138
|
+
}
|
|
139
|
+
.frame(height: maxDescriptionHeight)
|
|
140
|
+
} else {
|
|
141
|
+
descriptionText
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
private var descriptionText: some View {
|
|
146
|
+
MomoText(
|
|
147
|
+
props.description,
|
|
148
|
+
typography: .bodyDefaultRegular,
|
|
149
|
+
accessibilityId: "description_popup_permission"
|
|
150
|
+
)
|
|
151
|
+
.frame(maxWidth: .infinity, alignment: .leading)
|
|
152
|
+
.background(
|
|
153
|
+
GeometryReader { proxy in
|
|
154
|
+
Color.clear
|
|
155
|
+
.onAppear { descriptionHeight = proxy.size.height }
|
|
156
|
+
.onChange(of: props.description) { _ in
|
|
157
|
+
descriptionHeight = proxy.size.height
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
@ViewBuilder
|
|
164
|
+
private var actionButtons: some View {
|
|
165
|
+
if shouldUseColumnButtons {
|
|
166
|
+
VStack(spacing: Spacing.S) {
|
|
167
|
+
primaryButton
|
|
168
|
+
if props.secondary != nil {
|
|
169
|
+
secondaryButton
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
} else {
|
|
173
|
+
HStack(spacing: Spacing.S) {
|
|
174
|
+
if props.secondary != nil {
|
|
175
|
+
secondaryButton
|
|
176
|
+
.frame(maxWidth: .infinity)
|
|
177
|
+
}
|
|
178
|
+
primaryButton
|
|
179
|
+
.frame(maxWidth: .infinity)
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
private var primaryButton: some View {
|
|
185
|
+
Button(
|
|
186
|
+
title: props.primary?.title ?? "",
|
|
187
|
+
action: { props.primary?.onPress?() },
|
|
188
|
+
size: .medium
|
|
189
|
+
)
|
|
190
|
+
.accessibilityIdentifier("btn_popup_allow")
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
private var secondaryButton: some View {
|
|
194
|
+
Button(
|
|
195
|
+
title: props.secondary?.title ?? "",
|
|
196
|
+
action: { props.secondary?.onPress?() },
|
|
197
|
+
type: .text,
|
|
198
|
+
size: .medium
|
|
199
|
+
)
|
|
200
|
+
.accessibilityIdentifier("btn_popup_cancel")
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
private var closeButton: some View {
|
|
204
|
+
SwiftUI.Button(action: props.onIconClose) {
|
|
205
|
+
ZStack {
|
|
206
|
+
Circle()
|
|
207
|
+
.fill(Colors.black17)
|
|
208
|
+
.overlay(
|
|
209
|
+
Circle()
|
|
210
|
+
.stroke(Colors.black01, lineWidth: 2)
|
|
211
|
+
)
|
|
212
|
+
.frame(width: 22, height: 22)
|
|
213
|
+
|
|
214
|
+
Icon(source: "navigation_close", size: 16, color: Colors.black01)
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
.accessibilityIdentifier("ic_popup_close")
|
|
218
|
+
}
|
|
219
|
+
}
|