@momo-kits/native-kits 0.300.3-debug → 0.300.4-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 +51 -7
- package/README.md +2 -2
- package/compose/build.gradle.kts +10 -2
- package/compose/build.gradle.kts.backup +8 -0
- package/compose/compose.podspec +1 -3
- package/compose/src/androidMain/kotlin/vn/momo/kits/const/HostFont.android.kt +4 -3
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +2 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/ReservedRegions.android.kt +6 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +0 -14
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/DesignSystemKits.kt +62 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +351 -111
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +20 -21
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +2 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +4 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +9 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +11 -12
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +4 -9
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +2 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +10 -9
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +6 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +55 -22
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +12 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +7 -9
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +13 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +13 -5
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +3 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +14 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +19 -21
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +2 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +5 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +3 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +7 -15
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/HostFont.kt +2 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +20 -15
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +1 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/ScreenLayout.kt +306 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +43 -4
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +8 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +10 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +6 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +6 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +197 -60
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +132 -83
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +54 -62
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoBarCompression.kt +97 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoTabBar.kt +377 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +122 -24
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +34 -14
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderJourney.kt +3 -3
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderLocation.kt +1 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +113 -26
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +2 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +1 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HelpCenterRequest.kt +37 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SideBar.kt +192 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +2 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/ToolkitRequests.kt +8 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +3 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ReservedRegions.kt +20 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +13 -0
- package/compose/src/commonTest/kotlin/vn/momo/kits/navigation/component/HelpCenterRequestTest.kt +44 -0
- package/compose/src/commonTest/kotlin/vn/momo/kits/navigation/component/ToolkitRequestsTest.kt +15 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/const/HostFont.ios.kt +3 -1
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +4 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/ReservedRegions.ios.kt +138 -0
- package/gradle/libs.versions.toml +3 -14
- package/gradle/wrapper/gradle-wrapper.properties +0 -2
- package/gradle.properties +3 -5
- package/ios/Application/ApplicationEnvironment.swift +24 -6
- package/ios/Application/DesignSystemKits.swift +100 -0
- package/ios/Application/DesignSystemKitsPayload.swift +68 -0
- package/ios/Application/MaxApi.swift +30 -3
- 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 +8 -2
- package/ios/Button/Button.swift +15 -12
- package/ios/CalculatorKeyboard/CalculatorKeyboard.swift +64 -18
- 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 +10 -1
- package/ios/Colors+Radius+Spacing/Radius.swift +6 -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 +38 -9
- package/ios/Extensions/OptionalEnvironmentObject.swift +12 -0
- package/ios/Extensions/SkeletonUICompat.swift +11 -0
- package/ios/Icon/Icon.swift +21 -23
- package/ios/Icon/Icons.swift +1329 -0
- package/ios/IconButton/IconButton.swift +15 -7
- package/ios/Image/Image.swift +7 -23
- package/ios/Information/Information.swift +27 -9
- package/ios/Input/ErrorView.swift +2 -2
- package/ios/Input/Input.swift +171 -148
- package/ios/Input/InputPhoneNumber.swift +10 -9
- package/ios/Input/InputSearch.swift +107 -78
- package/ios/Input/InputTextArea.swift +133 -148
- package/ios/InputDropDown/InputDropDown.swift +10 -7
- package/ios/InputMoney/InputMoney.swift +32 -11
- package/ios/InputOTP/InputOTP.swift +22 -12
- package/ios/Layout/Card.swift +50 -0
- package/ios/Layout/GridContext.swift +187 -3
- package/ios/Layout/Item.swift +5 -4
- package/ios/Layout/ScreenLayout.swift +415 -0
- package/ios/Layout/Section.swift +4 -100
- package/ios/Loader/Loader.swift +5 -9
- package/ios/Lottie/LottieView.swift +14 -2
- package/ios/{Application/Navigation/Overplay → Navigation}/BottomSheet.swift +169 -29
- package/ios/Navigation/BottomTab/BottomTab.swift +332 -0
- package/ios/{Application/Navigation → Navigation}/BottomTab/BottomTabBar.swift +18 -7
- package/ios/Navigation/BottomTab/DuoBarCompression.swift +104 -0
- package/ios/Navigation/BottomTab/DuoTabBar.swift +329 -0
- package/ios/{Application → Navigation/Component}/FloatingButton.swift +43 -54
- package/ios/Navigation/Component/Header.swift +545 -0
- package/ios/Navigation/Component/HeaderBackground.swift +154 -0
- package/ios/Navigation/Component/HeaderJourney.swift +73 -0
- package/ios/Navigation/Component/HeaderLocation.swift +48 -0
- package/ios/Navigation/Component/HeaderRight.swift +425 -0
- package/ios/Navigation/Component/HeaderTitle.swift +36 -0
- package/ios/{Application/Navigation → Navigation/Component}/HeaderUser.swift +21 -24
- package/ios/Navigation/Component/SideBar.swift +183 -0
- package/ios/{Application/Navigation/Overplay → Navigation/Component}/SnackBar.swift +8 -8
- package/ios/Navigation/HostBackGestureBridge.swift +78 -0
- package/ios/{Application/Navigation/Overplay → Navigation}/ModalScreen.swift +9 -2
- package/ios/Navigation/Navigation.swift +204 -0
- package/ios/Navigation/NavigationContainer.swift +195 -0
- package/ios/{Application/Navigation → Navigation}/Navigator.swift +207 -107
- package/ios/Navigation/StackScreen.swift +930 -0
- package/ios/Navigation/StackTransition.swift +400 -0
- package/ios/Navigation/SwipeBackHaptic.swift +33 -0
- 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 +72 -135
- package/ios/Popup/PopupInput.swift +10 -13
- package/ios/Popup/PopupLayout.swift +138 -0
- package/ios/Popup/PopupNotify.swift +59 -69
- package/ios/Popup/PopupPromotion.swift +31 -47
- 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/Resources/dot_loading.json +558 -0
- package/ios/Resources/lottie_circle_loader.json +1 -0
- 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 +7 -3
- 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 +109 -55
- package/ios/Title/Title.swift +6 -17
- package/ios/Tooltip/Tooltip.swift +29 -14
- package/ios/Typography/FontScale.swift +17 -14
- package/ios/Typography/Text.swift +156 -20
- package/ios/Typography/Typography.swift +2 -2
- package/ios/Uploader/Uploader.swift +3 -1
- package/ios/native-kits.podspec +2 -3
- package/ios-demo/MoMoUIKitsDemo.podspec +1 -3
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ContentView.swift +1 -1
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DuoTabDemo.swift +80 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +2 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IPhoneDuoDemo.swift +173 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +77 -1
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupDisplayDemo.swift +1 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupNotifyDemo.swift +2 -2
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupPromotionDemo.swift +2 -0
- package/package.json +1 -1
- package/publish.sh +19 -2
- package/scripts/gen-ios-icons.mjs +36 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +0 -52
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +0 -183
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +0 -207
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +0 -39
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +0 -86
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +0 -76
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +0 -76
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +0 -293
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +0 -33
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +0 -110
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +0 -378
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +0 -69
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitDesignSystem.kt +0 -18
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +0 -22
- package/ios/Application/Components.swift +0 -270
- package/ios/Application/ComposeApi.swift +0 -22
- package/ios/Application/HeaderRight.swift +0 -306
- package/ios/Application/Navigation/BottomTab/BottomTab.swift +0 -104
- package/ios/Application/Navigation/HeaderBackProps.swift +0 -66
- package/ios/Application/Navigation/HeaderTitle.swift +0 -57
- package/ios/Application/Navigation/NavigationContainer.swift +0 -213
- package/ios/Application/Navigation/NavigationOptions.swift +0 -109
- package/ios/Application/Navigation/NavigatorManager.swift +0 -22
- package/ios/Application/Navigation/component/Header.swift +0 -178
- package/ios/Application/Navigation/component/HeaderBackground.swift +0 -83
- 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 -196
- package/ios/Application/Screen.swift +0 -250
- package/ios/Application/StackScreen.swift +0 -492
- package/ios/Typography/FontScaleStore.swift +0 -58
- package/ios/Typography/KitDesignSystem.swift +0 -17
- /package/ios/{Application/Navigation → Navigation}/BottomTab/CurvedContainer.swift +0 -0
package/ios/Avatar/Avatar.swift
CHANGED
|
@@ -74,12 +74,12 @@ public struct Avatar: View {
|
|
|
74
74
|
.clipShape(RoundedRectangle(cornerRadius: cornerRadius))
|
|
75
75
|
.overlay(
|
|
76
76
|
RoundedRectangle(cornerRadius: cornerRadius)
|
|
77
|
-
.
|
|
77
|
+
.strokeBorder(theme.colors.border.default, lineWidth: 1)
|
|
78
78
|
)
|
|
79
79
|
|
|
80
80
|
// Badge icons — outside clip so they are not cut by border
|
|
81
81
|
if shouldShowIconTop {
|
|
82
|
-
ImageView(LOGO_MOMO_URL)
|
|
82
|
+
ImageView(LOGO_MOMO_URL, contentMode: .fill)
|
|
83
83
|
.frame(width: badgeSizeDp, height: badgeSizeDp)
|
|
84
84
|
.clipShape(RoundedRectangle(cornerRadius: badgeCornerRadius))
|
|
85
85
|
.offset(x: 1, y: -1)
|
|
@@ -92,7 +92,7 @@ public struct Avatar: View {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
if shouldShowIconBottom {
|
|
95
|
-
ImageView(iconSupport)
|
|
95
|
+
ImageView(iconSupport, contentMode: .fill)
|
|
96
96
|
.frame(width: badgeSizeDp, height: badgeSizeDp)
|
|
97
97
|
.clipShape(RoundedRectangle(cornerRadius: badgeCornerRadius))
|
|
98
98
|
.offset(x: 1, y: 1)
|
|
@@ -107,6 +107,7 @@ public struct Avatar: View {
|
|
|
107
107
|
.frame(width: size.sizeDp, height: size.sizeDp)
|
|
108
108
|
.accessibilityElement(children: .ignore)
|
|
109
109
|
.accessibilityLabel(automationId)
|
|
110
|
+
.accessibilityIdentifier(automationId)
|
|
110
111
|
}
|
|
111
112
|
|
|
112
113
|
// MARK: Internal
|
package/ios/Badge/Badge.swift
CHANGED
|
@@ -33,7 +33,8 @@ public struct Badge: View {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
private func formatTitle(_ text: String) -> String {
|
|
36
|
-
|
|
36
|
+
// Digits too long for Int are well over 99.
|
|
37
|
+
if isNumber(text), (Int(text) ?? .max) > 99 {
|
|
37
38
|
return "99+"
|
|
38
39
|
}
|
|
39
40
|
return text
|
|
@@ -54,14 +55,15 @@ public struct Badge: View {
|
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
public var body: some View {
|
|
57
|
-
MomoText(formatTitle(label), typography: .actionXxsBold, color: Colors.black01)
|
|
58
|
+
MomoText(formatTitle(label), typography: .actionXxsBold, color: Colors.black01, maxLines: 1)
|
|
58
59
|
.padding(.horizontal, Spacing.XS)
|
|
59
|
-
.frame(minWidth: fontScale(16)
|
|
60
|
+
.frame(minWidth: fontScale(16))
|
|
61
|
+
.frame(height: fontScale(16))
|
|
60
62
|
.background(badgeColor)
|
|
61
63
|
.cornerRadius(Radius.M)
|
|
62
64
|
.overlay(
|
|
63
65
|
RoundedRectangle(cornerRadius: Radius.M)
|
|
64
|
-
.
|
|
66
|
+
.strokeBorder(Colors.black01, lineWidth: 1)
|
|
65
67
|
)
|
|
66
68
|
}
|
|
67
69
|
}
|
package/ios/Badge/BadgeDot.swift
CHANGED
|
@@ -160,7 +160,6 @@ public struct BadgeRibbon: View {
|
|
|
160
160
|
MomoText(label, typography: .labelXsMedium, color: Colors.black01, maxLines: 1)
|
|
161
161
|
.rotationEffect(rotation)
|
|
162
162
|
.frame(height: RibbonConstants.skewBodyHeight)
|
|
163
|
-
.padding(.horizontal, 8)
|
|
164
163
|
.background(backgroundColor)
|
|
165
164
|
|
|
166
165
|
rightTail
|
|
@@ -204,7 +203,9 @@ public struct BadgeRibbon: View {
|
|
|
204
203
|
/// rotation) — the label gets the same scale applied a second time so it stays right-reading
|
|
205
204
|
/// while only the ribbon shape flips.
|
|
206
205
|
public struct RoundedBadgeRibbon: View {
|
|
206
|
+
@Environment(\.appTheme) private var theme
|
|
207
207
|
@Environment(\.momoFontScale) private var fontScale
|
|
208
|
+
@Environment(\.designSystemKitsConfigs) private var designSystemKitsConfigs
|
|
208
209
|
let text: String
|
|
209
210
|
let position: RibbonPosition
|
|
210
211
|
|
|
@@ -224,7 +225,12 @@ public struct RoundedBadgeRibbon: View {
|
|
|
224
225
|
|
|
225
226
|
private var measuredTextSize: CGSize {
|
|
226
227
|
let fontSize = fontScale(TypographyStyle.labelXsMedium.fontSize)
|
|
227
|
-
let font =
|
|
228
|
+
let font = momoUIFont(
|
|
229
|
+
size: fontSize,
|
|
230
|
+
weight: .medium,
|
|
231
|
+
family: theme.font,
|
|
232
|
+
isWhiteList: designSystemKitsConfigs.isWhiteList
|
|
233
|
+
)
|
|
228
234
|
return text.size(withAttributes: [.font: font])
|
|
229
235
|
}
|
|
230
236
|
|
package/ios/Button/Button.swift
CHANGED
|
@@ -51,15 +51,17 @@ public extension ButtonType {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
func contentColor(loading: Bool, theme: Theme) -> Color {
|
|
54
|
+
let color: Color
|
|
54
55
|
switch self {
|
|
55
|
-
case .disabled:
|
|
56
|
-
case .primary:
|
|
57
|
-
case .secondary:
|
|
58
|
-
case .outline:
|
|
59
|
-
case .tonal:
|
|
60
|
-
case .danger:
|
|
61
|
-
case .text:
|
|
56
|
+
case .disabled: color = theme.colors.text.disable
|
|
57
|
+
case .primary: color = Colors.black01
|
|
58
|
+
case .secondary: color = theme.colors.text.default
|
|
59
|
+
case .outline: color = theme.colors.primary
|
|
60
|
+
case .tonal: color = theme.colors.primary
|
|
61
|
+
case .danger: color = Colors.black01
|
|
62
|
+
case .text: color = theme.colors.primary
|
|
62
63
|
}
|
|
64
|
+
return color.opacity(loading ? 0.75 : 1)
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
var borderColor: Color? {
|
|
@@ -219,9 +221,8 @@ public struct Button: View {
|
|
|
219
221
|
let color: Color? = useTintColor ? textColor : nil
|
|
220
222
|
|
|
221
223
|
if forceLoading {
|
|
222
|
-
LottieView(name: "lottie_circle_loader", loopMode: .loop)
|
|
224
|
+
LottieView(name: "lottie_circle_loader", loopMode: .loop, tintColor: color.map { UIColor($0) })
|
|
223
225
|
.frame(width: size.iconSize, height: size.iconSize)
|
|
224
|
-
.colorMultiply(color ?? Colors.black01)
|
|
225
226
|
} else if !icon.isEmpty {
|
|
226
227
|
Icon(source: icon, size: size.iconSize, color: color)
|
|
227
228
|
}
|
|
@@ -229,8 +230,8 @@ public struct Button: View {
|
|
|
229
230
|
}
|
|
230
231
|
|
|
231
232
|
/// Mirrors Compose's press feedback: the background shrinks via an animated
|
|
232
|
-
/// horizontal inset
|
|
233
|
-
///
|
|
233
|
+
/// horizontal inset and the whole button (background included) fades to 0.5,
|
|
234
|
+
/// matching `animatedPadding`/`alpha` in Button.kt.
|
|
234
235
|
private struct ButtonPressFeedbackStyle: ButtonStyle {
|
|
235
236
|
let isEnabled: Bool
|
|
236
237
|
let background: Color
|
|
@@ -245,7 +246,6 @@ private struct ButtonPressFeedbackStyle: ButtonStyle {
|
|
|
245
246
|
|
|
246
247
|
configuration.label
|
|
247
248
|
.modifier(HugContentOnLegacyOS(isFull: isFull))
|
|
248
|
-
.opacity(pressed ? 0.5 : 1)
|
|
249
249
|
.background(
|
|
250
250
|
RoundedRectangle(cornerRadius: radius)
|
|
251
251
|
.fill(background)
|
|
@@ -257,6 +257,9 @@ private struct ButtonPressFeedbackStyle: ButtonStyle {
|
|
|
257
257
|
)
|
|
258
258
|
.frame(height: height)
|
|
259
259
|
.clipShape(RoundedRectangle(cornerRadius: radius))
|
|
260
|
+
// `.text` has a clear background, which SwiftUI does not hit-test.
|
|
261
|
+
.contentShape(RoundedRectangle(cornerRadius: radius))
|
|
262
|
+
.opacity(pressed ? 0.5 : 1)
|
|
260
263
|
.animation(.easeInOut(duration: 0.1), value: pressed)
|
|
261
264
|
}
|
|
262
265
|
}
|
|
@@ -16,55 +16,101 @@ extension String {
|
|
|
16
16
|
public struct CalculatorKeyboard: View {
|
|
17
17
|
// MARK: Lifecycle
|
|
18
18
|
@Binding var value: String
|
|
19
|
-
@State var tempValue: String = ""
|
|
20
19
|
|
|
21
20
|
public init(_ value: Binding<String>) {
|
|
22
21
|
self._value = value
|
|
23
22
|
}
|
|
23
|
+
|
|
24
|
+
// Derived from `value` so a host write to the binding (prefill, reset after submit) is honoured.
|
|
25
|
+
private var expression: String {
|
|
26
|
+
value.replacingOccurrences(of: "x", with: "*").replacingOccurrences(of: "÷", with: "/")
|
|
27
|
+
}
|
|
24
28
|
|
|
25
29
|
func onPressBack(){
|
|
26
30
|
if (value.count > 0 ){
|
|
27
31
|
value.removeLast()
|
|
28
32
|
}
|
|
29
|
-
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
func onPressClear(key: String){
|
|
33
36
|
value = ""
|
|
34
|
-
tempValue = ""
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
func onPressEqual(key: String){
|
|
38
|
-
|
|
40
|
+
var expression = self.expression
|
|
41
|
+
if (expression == "") {
|
|
39
42
|
return
|
|
40
43
|
}
|
|
41
|
-
if (
|
|
42
|
-
|
|
44
|
+
if (expression.last?.isNumber == false){
|
|
45
|
+
expression.removeLast()
|
|
43
46
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
// Overflow and division by zero are treated like a negative result: cleared.
|
|
48
|
+
if let result = Self.evaluate(expression), result >= 0 {
|
|
49
|
+
value = String(result)
|
|
50
|
+
} else {
|
|
48
51
|
value = ""
|
|
49
52
|
}
|
|
50
53
|
}
|
|
54
|
+
|
|
55
|
+
/// Integer `+ - * /` with the usual precedence, as NSExpression did, but nil instead of a
|
|
56
|
+
/// crash when a number or result leaves `Int` range.
|
|
57
|
+
static func evaluate(_ expression: String) -> Int? {
|
|
58
|
+
var numbers: [Int] = []
|
|
59
|
+
var operators: [Character] = []
|
|
60
|
+
var digits = ""
|
|
61
|
+
for char in expression {
|
|
62
|
+
if ("0"..."9").contains(char) {
|
|
63
|
+
digits.append(char)
|
|
64
|
+
continue
|
|
65
|
+
}
|
|
66
|
+
guard let number = Int(digits) else { return nil }
|
|
67
|
+
numbers.append(number)
|
|
68
|
+
operators.append(char)
|
|
69
|
+
digits = ""
|
|
70
|
+
}
|
|
71
|
+
guard let last = Int(digits) else { return nil }
|
|
72
|
+
numbers.append(last)
|
|
73
|
+
|
|
74
|
+
var terms = [numbers[0]]
|
|
75
|
+
var signs: [Character] = []
|
|
76
|
+
for (op, number) in zip(operators, numbers.dropFirst()) {
|
|
77
|
+
switch op {
|
|
78
|
+
case "*":
|
|
79
|
+
let (product, overflow) = terms[terms.count - 1].multipliedReportingOverflow(by: number)
|
|
80
|
+
if overflow { return nil }
|
|
81
|
+
terms[terms.count - 1] = product
|
|
82
|
+
case "/":
|
|
83
|
+
guard number != 0 else { return nil }
|
|
84
|
+
terms[terms.count - 1] /= number
|
|
85
|
+
case "+", "-":
|
|
86
|
+
terms.append(number)
|
|
87
|
+
signs.append(op)
|
|
88
|
+
default:
|
|
89
|
+
return nil
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
var result = terms[0]
|
|
94
|
+
for (sign, term) in zip(signs, terms.dropFirst()) {
|
|
95
|
+
let (next, overflow) = sign == "+"
|
|
96
|
+
? result.addingReportingOverflow(term)
|
|
97
|
+
: result.subtractingReportingOverflow(term)
|
|
98
|
+
if overflow { return nil }
|
|
99
|
+
result = next
|
|
100
|
+
}
|
|
101
|
+
return result
|
|
102
|
+
}
|
|
51
103
|
|
|
52
104
|
func onPressKey(key:String){
|
|
53
|
-
if (
|
|
105
|
+
if (value.last?.isNumber == false){
|
|
54
106
|
if (key.isNumber == false){
|
|
55
107
|
return
|
|
56
108
|
}
|
|
57
109
|
}
|
|
58
|
-
var convertedKey = key
|
|
59
|
-
if (key == "x") {convertedKey = "*"}
|
|
60
|
-
if (key == "÷") {convertedKey = "/"}
|
|
61
110
|
if (value == "" && (key == "0" || key == "000" || key.isNumber == false)) {
|
|
62
111
|
return
|
|
63
112
|
}
|
|
64
|
-
|
|
65
|
-
value.append(key)
|
|
66
|
-
tempValue.append(convertedKey)
|
|
67
|
-
}
|
|
113
|
+
value.append(key)
|
|
68
114
|
}
|
|
69
115
|
|
|
70
116
|
// MARK: Public
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import Combine
|
|
2
1
|
import SwiftUI
|
|
3
2
|
|
|
4
3
|
/// Native SwiftUI port of the Compose `Carousel` component.
|
|
@@ -10,9 +9,9 @@ import SwiftUI
|
|
|
10
9
|
/// snap behavior, and scroll enable/disable. Snap / scroll-index callbacks
|
|
11
10
|
/// report the real item index.
|
|
12
11
|
///
|
|
13
|
-
///
|
|
12
|
+
/// Uses a custom drag-driven pager (not a ScrollView) so behavior is identical
|
|
14
13
|
/// across versions and supports the loop virtualization + transform effects
|
|
15
|
-
/// that `TabView(.page)` cannot express
|
|
14
|
+
/// that `TabView(.page)` cannot express.
|
|
16
15
|
public struct Carousel<Content: View>: View {
|
|
17
16
|
// MARK: Lifecycle
|
|
18
17
|
|
|
@@ -82,7 +81,7 @@ public struct Carousel<Content: View>: View {
|
|
|
82
81
|
@State private var currentPage: Int
|
|
83
82
|
@State private var dragOffset: CGFloat = 0
|
|
84
83
|
@State private var isDragging: Bool = false
|
|
85
|
-
@
|
|
84
|
+
@GestureState private var dragActive = false
|
|
86
85
|
|
|
87
86
|
private func realIndex(_ page: Int) -> Int {
|
|
88
87
|
((page % itemCount) + itemCount) % itemCount
|
|
@@ -124,9 +123,20 @@ public struct Carousel<Content: View>: View {
|
|
|
124
123
|
}
|
|
125
124
|
.frame(width: viewportWidth)
|
|
126
125
|
.clipped()
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
126
|
+
// Restarts on drag like Compose's LaunchedEffect(autoplayInterval, isUserScrolling).
|
|
127
|
+
.task(id: AutoplayKey(enabled: autoplay && itemCount > 1 && !isDragging, interval: autoplayInterval)) { @MainActor in
|
|
128
|
+
guard autoplay, itemCount > 1, !isDragging, autoplayInterval > 0 else { return }
|
|
129
|
+
while !Task.isCancelled {
|
|
130
|
+
try? await Task.sleep(nanoseconds: UInt64(autoplayInterval * 1_000_000_000))
|
|
131
|
+
guard !Task.isCancelled else { return }
|
|
132
|
+
advance()
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// A drag stolen by a parent scroll view never reaches `onEnded`; settle on the current page.
|
|
136
|
+
.onChange(of: dragActive) { active in
|
|
137
|
+
guard !active, isDragging else { return }
|
|
138
|
+
isDragging = false
|
|
139
|
+
withAnimation(.easeInOut(duration: 0.25)) { dragOffset = 0 }
|
|
130
140
|
}
|
|
131
141
|
}
|
|
132
142
|
|
|
@@ -147,9 +157,14 @@ public struct Carousel<Content: View>: View {
|
|
|
147
157
|
|
|
148
158
|
private func dragGesture(step: CGFloat) -> some Gesture {
|
|
149
159
|
DragGesture(minimumDistance: 5)
|
|
160
|
+
.updating($dragActive) { _, active, _ in active = true }
|
|
150
161
|
.onChanged { value in
|
|
151
162
|
isDragging = true
|
|
152
|
-
|
|
163
|
+
var offset = value.translation.width
|
|
164
|
+
// No slide exists past either end, as with HorizontalPager bounds.
|
|
165
|
+
if currentPage == 0 { offset = min(offset, 0) }
|
|
166
|
+
if currentPage == virtualPageCount - 1 { offset = max(offset, 0) }
|
|
167
|
+
dragOffset = offset
|
|
153
168
|
}
|
|
154
169
|
.onEnded { value in
|
|
155
170
|
isDragging = false
|
|
@@ -167,7 +182,8 @@ public struct Carousel<Content: View>: View {
|
|
|
167
182
|
let moved = step > 0 ? Int((-dragOffset / step).rounded()) : 0
|
|
168
183
|
target = min(max(currentPage + moved, 0), virtualPageCount - 1)
|
|
169
184
|
}
|
|
170
|
-
|
|
185
|
+
// Animated so a drag that stays on the same page eases back too.
|
|
186
|
+
withAnimation(.easeInOut(duration: 0.25)) { dragOffset = 0 }
|
|
171
187
|
setPage(target)
|
|
172
188
|
}
|
|
173
189
|
}
|
|
@@ -189,8 +205,9 @@ public struct Carousel<Content: View>: View {
|
|
|
189
205
|
onScrollIndexChanged(real)
|
|
190
206
|
}
|
|
191
207
|
}
|
|
208
|
+
}
|
|
192
209
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
210
|
+
private struct AutoplayKey: Equatable {
|
|
211
|
+
let enabled: Bool
|
|
212
|
+
let interval: TimeInterval
|
|
196
213
|
}
|
|
@@ -21,8 +21,10 @@ public struct Checkbox: View{
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
func onCheck(){
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
// Not re-read from the binding: a `.constant` / one-way binding would report the stale value.
|
|
25
|
+
let newValue = !checked
|
|
26
|
+
checked = newValue
|
|
27
|
+
onChange?(newValue)
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
public var body: some View {
|
|
@@ -35,13 +37,15 @@ public struct Checkbox: View{
|
|
|
35
37
|
.frame(width: 20, height: 20)
|
|
36
38
|
.overlay(
|
|
37
39
|
RoundedRectangle(cornerRadius: Radius.XS)
|
|
38
|
-
.
|
|
40
|
+
.strokeBorder(borderColor, lineWidth: Spacing.XXS)
|
|
39
41
|
)
|
|
40
42
|
|
|
41
43
|
if checked {
|
|
42
44
|
Icon(source: indeterminate ? "navigation_minus" : "ic_checked", size: 20, color: Colors.black01)
|
|
43
45
|
}
|
|
44
46
|
}
|
|
47
|
+
// The unchecked fill is clear, which SwiftUI does not hit-test.
|
|
48
|
+
.contentShape(RoundedRectangle(cornerRadius: Radius.XS))
|
|
45
49
|
}
|
|
46
50
|
.buttonStyle(ActiveOpacityButtonStyle(activeOpacity: 0.8))
|
|
47
51
|
.disabled(disabled)
|
package/ios/Chip/Chip.swift
CHANGED
|
@@ -89,18 +89,19 @@ public struct Chip: View {
|
|
|
89
89
|
.padding(.horizontal, horizontal)
|
|
90
90
|
.frame(height: height)
|
|
91
91
|
.background(
|
|
92
|
-
RoundedRectangle(cornerRadius: radius
|
|
92
|
+
RoundedRectangle(cornerRadius: radius)
|
|
93
93
|
.fill(bg)
|
|
94
94
|
)
|
|
95
95
|
.overlay(
|
|
96
96
|
Group {
|
|
97
97
|
if selected {
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
// Inside the bounds, like Compose `border`.
|
|
99
|
+
RoundedRectangle(cornerRadius: radius)
|
|
100
|
+
.strokeBorder(theme.colors.secondary, lineWidth: 2)
|
|
100
101
|
}
|
|
101
102
|
}
|
|
102
103
|
)
|
|
103
|
-
.contentShape(RoundedRectangle(cornerRadius: radius
|
|
104
|
+
.contentShape(RoundedRectangle(cornerRadius: radius))
|
|
104
105
|
}
|
|
105
106
|
.buttonStyle(ActiveOpacityButtonStyle())
|
|
106
107
|
.modifier(ChipAccessibilityModifier(accessibilityLabel: accessibilityLabel))
|
|
@@ -32,7 +32,7 @@ public struct Collapse<Content: View>: View {
|
|
|
32
32
|
private let titleColor: Color?
|
|
33
33
|
private let accessibilityId: String?
|
|
34
34
|
private let onPress: ((Bool) -> Void)?
|
|
35
|
-
private
|
|
35
|
+
private var content: (() -> Content)?
|
|
36
36
|
|
|
37
37
|
@State private var expanded: Bool
|
|
38
38
|
|
|
@@ -87,31 +87,36 @@ public struct Collapse<Content: View>: View {
|
|
|
87
87
|
header
|
|
88
88
|
|
|
89
89
|
if let content {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
// Compose's expandVertically: the clip grows with the panel while it slides in from the top.
|
|
91
|
+
VStack(spacing: 0) {
|
|
92
|
+
if expanded {
|
|
93
|
+
VStack(spacing: 0) {
|
|
94
|
+
content()
|
|
95
|
+
}
|
|
96
|
+
.frame(maxWidth: .infinity)
|
|
97
|
+
.overlay(
|
|
98
|
+
showBorder
|
|
99
|
+
? Rectangle().strokeBorder(theme.colors.border.default, lineWidth: 1)
|
|
100
|
+
: nil
|
|
101
|
+
)
|
|
102
|
+
.transition(.move(edge: .top))
|
|
93
103
|
}
|
|
94
|
-
.frame(maxWidth: .infinity)
|
|
95
|
-
.overlay(
|
|
96
|
-
showBorder
|
|
97
|
-
? RoundedRectangle(cornerRadius: 0)
|
|
98
|
-
.stroke(theme.colors.border.default, lineWidth: 1)
|
|
99
|
-
: nil
|
|
100
|
-
)
|
|
101
|
-
.transition(.move(edge: .top).combined(with: .opacity))
|
|
102
104
|
}
|
|
105
|
+
.clipped()
|
|
103
106
|
}
|
|
104
107
|
}
|
|
105
108
|
.frame(maxWidth: .infinity)
|
|
106
109
|
.background(resolvedBackgroundColor)
|
|
107
110
|
.clipShape(RoundedRectangle(cornerRadius: Radius.S, style: .continuous))
|
|
108
|
-
.accessibilityIdentifier(automationId)
|
|
109
111
|
.overlay(
|
|
110
112
|
showBorder
|
|
111
113
|
? RoundedRectangle(cornerRadius: Radius.S, style: .continuous)
|
|
112
|
-
.
|
|
114
|
+
.strokeBorder(theme.colors.border.default, lineWidth: 1)
|
|
113
115
|
: nil
|
|
114
116
|
)
|
|
117
|
+
// `.contain` keeps the children's own identifiers instead of overriding them.
|
|
118
|
+
.accessibilityElement(children: .contain)
|
|
119
|
+
.accessibilityIdentifier(automationId)
|
|
115
120
|
}
|
|
116
121
|
|
|
117
122
|
private var header: some View {
|
|
@@ -126,6 +131,7 @@ public struct Collapse<Content: View>: View {
|
|
|
126
131
|
ImageView(image, contentMode: .fill)
|
|
127
132
|
.frame(width: imageSize, height: imageSize)
|
|
128
133
|
.clipShape(RoundedRectangle(cornerRadius: Radius.XS, style: .continuous))
|
|
134
|
+
.accessibilityIdentifier("\(automationId)|img")
|
|
129
135
|
Spacer().frame(width: Spacing.S)
|
|
130
136
|
}
|
|
131
137
|
|
|
@@ -133,15 +139,17 @@ public struct Collapse<Content: View>: View {
|
|
|
133
139
|
MomoText(
|
|
134
140
|
title,
|
|
135
141
|
typography: titleSize.typography,
|
|
136
|
-
color: titleColor ?? theme.colors.text.default
|
|
142
|
+
color: titleColor ?? theme.colors.text.default,
|
|
143
|
+
accessibilityId: "\(automationId)|text"
|
|
137
144
|
)
|
|
138
145
|
if let description {
|
|
139
146
|
MomoText(
|
|
140
147
|
description,
|
|
141
148
|
typography: .bodyDefaultRegular,
|
|
142
|
-
color: theme.colors.text.secondary
|
|
149
|
+
color: theme.colors.text.secondary,
|
|
150
|
+
maxLines: 2,
|
|
151
|
+
accessibilityId: "\(automationId)|description-text"
|
|
143
152
|
)
|
|
144
|
-
.lineLimit(2)
|
|
145
153
|
}
|
|
146
154
|
}
|
|
147
155
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
@@ -152,9 +160,10 @@ public struct Collapse<Content: View>: View {
|
|
|
152
160
|
MomoText(
|
|
153
161
|
subTitle,
|
|
154
162
|
typography: .bodyDefaultRegular,
|
|
155
|
-
color: theme.colors.text.secondary
|
|
163
|
+
color: theme.colors.text.secondary,
|
|
164
|
+
maxLines: 1,
|
|
165
|
+
accessibilityId: "\(automationId)|sub-title-text"
|
|
156
166
|
)
|
|
157
|
-
.lineLimit(1)
|
|
158
167
|
} else if let tagLabel {
|
|
159
168
|
Tag(label: tagLabel, color: tagColor)
|
|
160
169
|
}
|
|
@@ -187,6 +196,48 @@ public struct Collapse<Content: View>: View {
|
|
|
187
196
|
.rotationEffect(.degrees(expanded ? 180 : 0))
|
|
188
197
|
}
|
|
189
198
|
}
|
|
199
|
+
.accessibilityIdentifier("\(automationId)|icon")
|
|
190
200
|
.animation(.easeInOut(duration: 0.3), value: expanded)
|
|
191
201
|
}
|
|
192
202
|
}
|
|
203
|
+
|
|
204
|
+
public extension Collapse where Content == EmptyView {
|
|
205
|
+
/// Header-only collapse, mirroring Compose's `content = null`.
|
|
206
|
+
init(
|
|
207
|
+
title: String,
|
|
208
|
+
description: String? = nil,
|
|
209
|
+
image: String? = nil,
|
|
210
|
+
imageSize: CGFloat = 24,
|
|
211
|
+
subTitle: String? = nil,
|
|
212
|
+
tagLabel: String? = nil,
|
|
213
|
+
tagColor: Tag.TagColor = .default,
|
|
214
|
+
showBorder: Bool = false,
|
|
215
|
+
expandDefault: Bool = false,
|
|
216
|
+
titleSize: CollapseTitleSize = .medium,
|
|
217
|
+
useBackgroundCollapseButton: Bool = false,
|
|
218
|
+
backgroundColor: Color? = nil,
|
|
219
|
+
titleColor: Color? = nil,
|
|
220
|
+
accessibilityId: String? = nil,
|
|
221
|
+
onPress: ((Bool) -> Void)? = nil
|
|
222
|
+
) {
|
|
223
|
+
self.init(
|
|
224
|
+
title: title,
|
|
225
|
+
description: description,
|
|
226
|
+
image: image,
|
|
227
|
+
imageSize: imageSize,
|
|
228
|
+
subTitle: subTitle,
|
|
229
|
+
tagLabel: tagLabel,
|
|
230
|
+
tagColor: tagColor,
|
|
231
|
+
showBorder: showBorder,
|
|
232
|
+
expandDefault: expandDefault,
|
|
233
|
+
titleSize: titleSize,
|
|
234
|
+
useBackgroundCollapseButton: useBackgroundCollapseButton,
|
|
235
|
+
backgroundColor: backgroundColor,
|
|
236
|
+
titleColor: titleColor,
|
|
237
|
+
accessibilityId: accessibilityId,
|
|
238
|
+
onPress: onPress,
|
|
239
|
+
content: { EmptyView() }
|
|
240
|
+
)
|
|
241
|
+
self.content = nil
|
|
242
|
+
}
|
|
243
|
+
}
|
|
@@ -133,7 +133,7 @@ public enum Colors {
|
|
|
133
133
|
public static let yellow06 = Color(hex: "ffe066")
|
|
134
134
|
public static let yellow05 = Color(hex: "ffd633")
|
|
135
135
|
public static let yellow04 = Color(hex: "ffd119")
|
|
136
|
-
public static let yellow03 = Color(hex: "
|
|
136
|
+
public static let yellow03 = Color(hex: "ffcc00")
|
|
137
137
|
public static let yellow02 = Color(hex: "e6b800")
|
|
138
138
|
public static let yellow01 = Color(hex: "cca300")
|
|
139
139
|
|
|
@@ -172,4 +172,13 @@ public enum Colors {
|
|
|
172
172
|
public static let red03 = Color(hex: "f5222d")
|
|
173
173
|
public static let red02 = Color(hex: "dd1f29")
|
|
174
174
|
public static let red01 = Color(hex: "c41b24")
|
|
175
|
+
|
|
176
|
+
public static let opacityBlack20 = Color(hex: "00000033")
|
|
177
|
+
public static let opacityBlack40 = Color(hex: "00000066")
|
|
178
|
+
public static let opacityBlack60 = Color(hex: "00000099")
|
|
179
|
+
public static let opacityBlack80 = Color(hex: "000000cc")
|
|
180
|
+
public static let opacityWhite20 = Color(hex: "ffffff33")
|
|
181
|
+
public static let opacityWhite40 = Color(hex: "ffffff66")
|
|
182
|
+
public static let opacityWhite60 = Color(hex: "ffffff99")
|
|
183
|
+
public static let opacityWhite80 = Color(hex: "ffffffcc")
|
|
175
184
|
}
|
|
@@ -15,6 +15,12 @@ public struct RoundedCorner: Shape {
|
|
|
15
15
|
var radius: CGFloat = .infinity
|
|
16
16
|
var corners: UIRectCorner = .allCorners
|
|
17
17
|
|
|
18
|
+
/// iOS 15 stand-in for `UnevenRoundedRectangle`.
|
|
19
|
+
public init(radius: CGFloat = .infinity, corners: UIRectCorner = .allCorners) {
|
|
20
|
+
self.radius = radius
|
|
21
|
+
self.corners = corners
|
|
22
|
+
}
|
|
23
|
+
|
|
18
24
|
public func path(in rect: CGRect) -> Path {
|
|
19
25
|
let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
|
|
20
26
|
return Path(path.cgPath)
|