diff --git a/Sources/OversizeUI/Controls/HUD/HUD.swift b/Sources/OversizeUI/Controls/HUD/HUD.swift index 96c5f30..0f31dbb 100644 --- a/Sources/OversizeUI/Controls/HUD/HUD.swift +++ b/Sources/OversizeUI/Controls/HUD/HUD.swift @@ -1,52 +1,50 @@ // // Copyright © 2023 Alexander Romanov // File.swift, created on 22.05.2023 -// +// import SwiftUI public struct HUD: View where Title: View, Icon: View { - @Environment(\.screenSize) var screenSize - + private let text: String? - + private let title: Title? private let icon: Icon? - + private let isAutoHide: Bool - + @Binding private var isPresented: Bool - + @State private var bottomOffset: CGFloat = 0 @State private var opacity: CGFloat = 0 - + // MARK: Initializers + public init( autoHide: Bool = true, isPresented: Binding, @ViewBuilder title: () -> Title, @ViewBuilder icon: () -> Icon ) { - self._isPresented = isPresented - self.text = nil + _isPresented = isPresented + text = nil self.title = title() self.icon = icon() - self.isAutoHide = autoHide + isAutoHide = autoHide } - - + public var body: some View { HStack(spacing: .xSmall) { if icon != nil { icon } if let text { - Text(text) .body(.medium) .foregroundColor(.onSurfaceHighEmphasis) - + } else if let title { title } @@ -70,7 +68,7 @@ public struct HUD: View where Title: View, Icon: View { } }) } - + private func presentAnimated() { withAnimation { bottomOffset = 0 @@ -84,7 +82,7 @@ public struct HUD: View where Title: View, Icon: View { } } } - + private func dismissAnimated() { withAnimation { bottomOffset = -200 @@ -99,11 +97,11 @@ public extension HUD where Title == EmptyView, Icon == EmptyView { autoHide: Bool = true, isPresented: Binding ) { - self._isPresented = isPresented + _isPresented = isPresented self.text = text - self.title = nil - self.icon = nil - self.isAutoHide = autoHide + title = nil + icon = nil + isAutoHide = autoHide } } @@ -114,10 +112,10 @@ public extension HUD where Title == EmptyView { isPresented: Binding, @ViewBuilder icon: () -> Icon ) { - self._isPresented = isPresented + _isPresented = isPresented self.text = text - self.title = nil - self.isAutoHide = autoHide + title = nil + isAutoHide = autoHide self.icon = icon() } } @@ -128,41 +126,41 @@ public extension HUD where Icon == EmptyView { isPresented: Binding, @ViewBuilder title: () -> Title ) { - self._isPresented = isPresented - self.text = nil + _isPresented = isPresented + text = nil self.title = title() - self.icon = nil - self.isAutoHide = autoHide + icon = nil + isAutoHide = autoHide } } public extension View { func hud(_ text: String, isPresented: Binding) -> some View { - self.overlay(alignment: .top) { + overlay(alignment: .top) { HUD(text, isPresented: isPresented) } } - - func hud(_ text: String, isPresented: Binding, @ViewBuilder icon: () -> Icon) -> some View { - self.overlay(alignment: .top) { + + func hud(_ text: String, isPresented: Binding, @ViewBuilder icon: () -> some View) -> some View { + overlay(alignment: .top) { HUD(text, isPresented: isPresented, icon: icon) } } - - func hud(isPresented: Binding, @ViewBuilder title: () -> Title) -> some View { - self.overlay(alignment: .top) { + + func hud(isPresented: Binding, @ViewBuilder title: () -> some View) -> some View { + overlay(alignment: .top) { HUD(isPresented: isPresented, title: title) } } - - func hud(isPresented: Binding, @ViewBuilder title: () -> Title, @ViewBuilder icon: () -> Icon) -> some View { - self.overlay(alignment: .top) { + + func hud(isPresented: Binding, @ViewBuilder title: () -> some View, @ViewBuilder icon: () -> some View) -> some View { + overlay(alignment: .top) { HUD(isPresented: isPresented, title: title, icon: icon) } } - + func hudLoader(_ text: String = "Loading", isPresented: Binding) -> some View { - self.overlay(alignment: .top) { + overlay(alignment: .top) { HUD(text, autoHide: false, isPresented: isPresented) { ProgressView() } diff --git a/Sources/OversizeUI/Controls/Loader/LoaderOverlayView.swift b/Sources/OversizeUI/Controls/Loader/LoaderOverlayView.swift index 7375ad6..cc9d37d 100644 --- a/Sources/OversizeUI/Controls/Loader/LoaderOverlayView.swift +++ b/Sources/OversizeUI/Controls/Loader/LoaderOverlayView.swift @@ -18,7 +18,6 @@ public struct LoaderOverlayView: View { private let isShowBackground: Bool @Binding var isLoading: Bool - @State private var jump = false @State private var rotationImage = false @@ -48,28 +47,11 @@ public struct LoaderOverlayView: View { } public var body: some View { + VStack { + Spacer() - - VStack { - Spacer() - - if surface { - Surface { - VStack(spacing: 20) { - containedView() - - if showText { - Text(text.isEmpty ? "Loading" : text) - .headline(.semibold) - .onSurfaceDisabledForegroundColor() - .offset(y: 8) - } - } - .padding() - } - .surfaceStyle(.primary) - .elevation(.z4) - } else { + if surface { + Surface { VStack(spacing: 20) { containedView() @@ -81,24 +63,39 @@ public struct LoaderOverlayView: View { } } .padding() - .background { - Capsule() - .fillSurfaceSecondary() + } + .surfaceStyle(.primary) + .elevation(.z4) + } else { + VStack(spacing: 20) { + containedView() + + if showText { + Text(text.isEmpty ? "Loading" : text) + .headline(.semibold) + .onSurfaceDisabledForegroundColor() + .offset(y: 8) } } - - Spacer() + .padding() + .background { + Capsule() + .fillSurfaceSecondary() + } } - .frame( - maxWidth: .infinity, - maxHeight: .infinity, - alignment: .center - ) - .background( - .ultraThinMaterial.opacity(isShowBackground ? 1 : 0), - ignoresSafeAreaEdges: .all - ) - .opacity(isLoading ? 1 : 0) + + Spacer() + } + .frame( + maxWidth: .infinity, + maxHeight: .infinity, + alignment: .center + ) + .background( + .ultraThinMaterial.opacity(isShowBackground ? 1 : 0), + ignoresSafeAreaEdges: .all + ) + .opacity(isLoading ? 1 : 0) } @ViewBuilder @@ -134,7 +131,7 @@ public struct LoaderOverlayView: View { public extension View { func loader(_ text: String? = nil, isPresented: Binding) -> some View { - self.overlay { + overlay { LoaderOverlayView(text: text ?? "", isLoading: isPresented) } } diff --git a/Sources/OversizeUI/Controls/Row/Row.swift b/Sources/OversizeUI/Controls/Row/Row.swift index efc0e2d..8d7c67a 100644 --- a/Sources/OversizeUI/Controls/Row/Row.swift +++ b/Sources/OversizeUI/Controls/Row/Row.swift @@ -7,14 +7,13 @@ import SwiftUI public protocol RowLeadingContentProtocol: View {} -public struct RowLeadingContent: View {// where Content: View { - +public struct RowLeadingContent: View { // where Content: View { private let content: Content - + public init(@ViewBuilder content: () -> Content) { self.content = content() } - + public var body: some View { content } @@ -35,7 +34,7 @@ public struct Row: View where LeadingLabel: View, T private let title: String private let subtitle: String? - + private let leadingSize: CGSize? private let leadingRadius: CGFloat? @@ -149,8 +148,6 @@ public struct Row: View where LeadingLabel: View, T } .padding(controlPadding) } - - private var text: some View { VStack(alignment: textAlignment, spacing: .zero) { @@ -204,9 +201,62 @@ public struct Row: View where LeadingLabel: View, T } } +// MARK: - Modificators + +public extension Row { + func premium(_ premium: Bool = true) -> Row { + var control = self + control.isPremiumOption = premium + return control + } + + func rowArrow(_ showArrowIcon: Bool = true) -> Row { + var control = self + control.isShowArrowIcon = showArrowIcon + return control + } + + func rowIconBackgroundColor(_ color: Color?) -> Row { + var control = self + control.iconBackgroundColor = color + return control + } + + func rowClearButton(style: RowClearIconStyle = .default, action: (() -> Void)?) -> Row { + var control = self + control.сlearButtonStyle = style + control.сlearAction = action + return control + } + + @available(*, deprecated, message: "Use leading: {} and tralling: {}") + func rowLeading(_ leading: RowLeadingType?) -> Row { + var control = self + control.leadingType = leading + return control + } + + @available(*, deprecated, message: "Use leading: {} and tralling: {}") + func rowTrailing(_ trailing: RowTrailingType?) -> Row { + var control = self + control.trallingType = trailing + return control + } +} + +public extension View { + func rowOnSurface(_ elevation: Elevation = .z4, backgroundColor: Color? = nil) -> some View { + Surface { + self.rowContentInset(.zero) + } + .surfaceBackgroundColor(backgroundColor) + .elevation(elevation) + } +} + // MARK: - Icon init -public extension Row where LeadingLabel == Icon { +public extension Row where LeadingLabel == Icon, TrailingLabel: View { init(_ title: String, subtitle: String? = nil, action: (() -> Void)? = nil, @@ -251,7 +301,7 @@ public extension Row where LeadingLabel == Image, TrailingLabel == EmptyView { { self.title = title self.subtitle = subtitle - self.action = nil + action = nil leadingLabel = leading().resizable() trailingLabel = nil leadingSize = .init( @@ -270,7 +320,7 @@ public extension Row where LeadingLabel == Image { { self.title = title self.subtitle = subtitle - self.action = nil + action = nil leadingLabel = leading() .resizable() trailingLabel = trailing() @@ -294,7 +344,7 @@ public extension Row where LeadingLabel == Image { self.action = action leadingLabel = leading() .resizable() - //.renderingMode(.template) + // .renderingMode(.template) trailingLabel = trailing() leadingSize = .init( width: subtitle == nil ? 24 : 48, @@ -366,59 +416,6 @@ public extension Row where LeadingLabel == EmptyView { } } -// MARK: - Modificators - -public extension Row { - func premium(_ premium: Bool = true) -> Row { - var control = self - control.isPremiumOption = premium - return control - } - - func rowArrow(_ showArrowIcon: Bool = true) -> Row { - var control = self - control.isShowArrowIcon = showArrowIcon - return control - } - - func rowIconBackgroundColor(_ color: Color?) -> Row { - var control = self - control.iconBackgroundColor = color - return control - } - - func rowClearButton(style: RowClearIconStyle = .default, action: (() -> Void)?) -> Row { - var control = self - control.сlearButtonStyle = style - control.сlearAction = action - return control - } - - @available(*, deprecated, message: "Use leading: {} and tralling: {}") - func rowLeading(_ leading: RowLeadingType?) -> Row { - var control = self - control.leadingType = leading - return control - } - - @available(*, deprecated, message: "Use leading: {} and tralling: {}") - func rowTrailing(_ trailing: RowTrailingType?) -> Row { - var control = self - control.trallingType = trailing - return control - } -} - -public extension View { - func rowOnSurface(_ elevation: Elevation = .z4, backgroundColor: Color? = nil) -> some View { - Surface { - self.rowContentInset(.zero) - } - .surfaceBackgroundColor(backgroundColor) - .elevation(elevation) - } -} - // MARK: - Preview // swiftlint:disable all diff --git a/Sources/OversizeUI/Controls/Surface/Surface.swift b/Sources/OversizeUI/Controls/Surface/Surface.swift index d327803..6babfa4 100644 --- a/Sources/OversizeUI/Controls/Surface/Surface.swift +++ b/Sources/OversizeUI/Controls/Surface/Surface.swift @@ -20,6 +20,8 @@ public struct Surface: View { @Environment(\.surfaceContentInsets) var contentInsets: EdgeSpaceInsets @Environment(\.isAccent) private var isAccent: Bool + let forceContentInsets: EdgeSpaceInsets? + private enum Constants { /// Colors static var colorPrimary: Color { Color.surfacePrimary } @@ -39,45 +41,8 @@ public struct Surface: View { { self.label = label() self.action = action + forceContentInsets = nil } - - - public init( - action: (() -> Void)? = nil, - @ViewBuilder label: () -> Label) where Label == Row, LeadingLabel: View, TrailingLabel: View { - self.label = label() - self.action = action - self.backgroundColor = .red - } - - public init( - @ViewBuilder label: () -> Label) where Label == Row, LeadingLabel: View, TrailingLabel: View { - self.label = label() - self.action = nil - self.backgroundColor = .red - } - -// public init( -// @ViewBuilder label: () -> Label) where Label == Row, LeadingLabel: View, TrailingLabel: Never { -// self.label = label() -// self.action = nil -// self.backgroundColor = .red -// } - -// public init( -// action: (() -> Void)? = nil, -// @ViewBuilder label: () -> Label) where Label == Row, LeadingLabel: View, TrailingLabel: View -// { -// self.label = label() -// self.action = action -// self.backgroundColor = .red -// } - -// public init( -// url: URL?, -// scale: CGFloat = 1, -// @ViewBuilder content: @escaping (Image) -> I, -// @ViewBuilder placeholder: @escaping () -> P) where Content == _ConditionalContent, I : View, P : View public var body: some View { if action != nil { @@ -98,10 +63,10 @@ public struct Surface: View { private var surface: some View { label - .padding(.top, contentInsets.top) - .padding(.bottom, contentInsets.bottom) - .padding(.leading, contentInsets.leading) - .padding(.trailing, contentInsets.trailing) + .padding(.top, forceContentInsets?.top ?? contentInsets.top) + .padding(.bottom, forceContentInsets?.bottom ?? contentInsets.bottom) + .padding(.leading, forceContentInsets?.leading ?? contentInsets.leading) + .padding(.trailing, forceContentInsets?.trailing ?? contentInsets.trailing) .background( RoundedRectangle(cornerRadius: surfaceRadius, style: .continuous) .fill(surfaceBackgroundColor) @@ -189,138 +154,6 @@ public struct SurfaceButtonStyle: ButtonStyle { } } -// extension Optional : View where Wrapped : View { -//Anchor : Hashable where Value : Hashable { - -// where Content == PresentedWindowContent, D : Decodable, D : Encodable, D : Hashable, C : View -// public init(id: String, for type: D.Type, @ViewBuilder content: @escaping (Binding) -> C) where Content == PresentedWindowContent, D : Decodable, D : Encodable, D : Hashable, C : View -//public extension Surface where Label == Row { - -//extension ExclusiveGesture.Value : Equatable where First.Value : Equatable, Second.Value : Equatable { - -// init( -// action: (() -> Void)? = nil, -// @ViewBuilder label: @escaping () -> (LeadingLabel, TrailingLabel)) where Label == Row, LeadingLabel: View, TrailingLabel : View - -//public extension Surface where Label == Row: View, LeadingLabel: View, TrailingLabel: View { -//extension ForEach where Data == Range, ID == Int, Content : View { -// -// -// extension ForEach where Data == Range, ID == Int, Content : View { -// -// /// Creates an instance that computes views on demand over a given constant -// /// range. -// /// -// /// The instance only reads the initial value of the provided `data` and -// /// doesn't need to identify views across updates. To compute views on -// /// demand over a dynamic range, use ``ForEach/init(_:id:content:)``. -// /// -// /// - Parameters: -// /// - data: A constant range. -// /// - content: The view builder that creates views dynamically. -// public init(_ data: Range, @ViewBuilder content: @escaping (Int) -> Content) -// } - -////extension Surface where Label == Row: View, TrailingLabel: View> { -// -//extension Surface where Label == Row { -// -// public init( -// action: (() -> Void)? = nil, -// @ViewBuilder label: () -> Label) where Label == Row, LeadingLabel : View, TrailingLabel : View { -// self.label = label() -// self.action = action -// self.backgroundColor = .red -// } -//} - -//extension Surface: View where Label == VStack> { -// -// public init(action: (() -> Void)? = nil, -// @ViewBuilder label: () -> Label) -// { -// self.label = label() -// self.action = action -// self.backgroundColor = .red -// } -//} - - -//extension Surface where Label == VStack> { -// -// public init(action: (() -> Void)? = nil, -// @ViewBuilder label: () -> Label) -// { -// self.label = label() -// self.action = action -// self.backgroundColor = .red -// } -//} - -//extension Surface where Label == Row, LeadingLabel: View, TrailingLabel: View { -// public init( -// @ViewBuilder label: () -> Label) where Label == Row, LeadingLabel: View, TrailingLabel: View { -// self.label = label() -// self.action = nil -// self.backgroundColor = .red -// } -//} - -//extension Surface where Label == Row { -// -// public init(action: (() -> Void)? = nil, -// @ViewBuilder label: () -> Label) -// { -// self.label = label() -// self.action = action -// self.backgroundColor = .red -// } -// -//} - -//extension Surface where Label == Row, A: View, B: View { -// -//} - -//extension Surface where Label == Row { -// -// public init(_ title: String, -// subtitle: String? = nil, -// action: (() -> Void)? = nil, -// @ViewBuilder leading: () -> LeadingLabel, -// @ViewBuilder trailing: () -> TrailingLabel) -// { -// self.title = title -// self.subtitle = subtitle -// self.action = action -// leadingLabel = leading() -// trailingLabel = trailing() -// leadingSize = nil -// leadingRadius = nil -// -//} - - -//public struct Row: View where LeadingLabel: View, TrailingLabel: View { - -//public init(_ title: String, -// subtitle: String? = nil, -// action: (() -> Void)? = nil, -// @ViewBuilder leading: () -> LeadingLabel, -// @ViewBuilder trailing: () -> TrailingLabel) -//{ -// self.title = title -// self.subtitle = subtitle -// self.action = action -// leadingLabel = leading() -// trailingLabel = trailing() -// leadingSize = nil -// leadingRadius = nil -//} - -//extension TableColumn where RowValue == Sort.Compared, Label == Text { - -// swiftlint:disable opening_brace public extension View { func surface() -> some View { Surface { self } @@ -364,6 +197,26 @@ public extension View { } } +public extension Surface where Label == VStack, Row)>> { + init(action: (() -> Void)? = nil, + @ViewBuilder label: () -> Label) + { + self.label = label() + self.action = action + forceContentInsets = .init(horizontal: .zero, vertical: .small) + } +} + +public extension Surface where Label == Row { + init(action: (() -> Void)? = nil, + @ViewBuilder label: () -> Label) + { + self.label = label() + self.action = action + forceContentInsets = .init(horizontal: .zero, vertical: .small) + } +} + struct Surface_Previews: PreviewProvider { static var previews: some View { VStack { diff --git a/Sources/OversizeUI/Controls/Toast/Snackbar.swift b/Sources/OversizeUI/Controls/Toast/Snackbar.swift index 9fb08d7..391a529 100644 --- a/Sources/OversizeUI/Controls/Toast/Snackbar.swift +++ b/Sources/OversizeUI/Controls/Toast/Snackbar.swift @@ -1,52 +1,49 @@ // // Copyright © 2023 Alexander Romanov // Snackbar.swift, created on 21.05.2023 -// +// import SwiftUI public struct Snackbar: View where Label: View, Actions: View { - @Environment(\.screenSize) var screenSize - + private let text: String? - + private let label: Label? private let actions: Group? - + @Binding private var isPresented: Bool - + @State private var bottomOffset: CGFloat = 0 @State private var opacity: CGFloat = 0 - + // MARK: Initializers + public init( isPresented: Binding, @ViewBuilder label: () -> Label, @ViewBuilder actions: () -> Actions ) { - self._isPresented = isPresented - self.text = nil + _isPresented = isPresented + text = nil self.label = label() self.actions = Group { actions() } } - - + public var body: some View { - HStack { if let text { - Text(text) .body(.medium) .foregroundColor(.onPrimaryHighEmphasis) - + } else if let label { label } - + Spacer() - + if actions != nil { HStack(spacing: .xxSmall) { actions @@ -56,7 +53,7 @@ public struct Snackbar: View where Label: View, Actions: View { } } } - + .padding(.leading, .medium) .padding(.trailing, .xSmall) .padding(.vertical, .xSmall) @@ -78,7 +75,7 @@ public struct Snackbar: View where Label: View, Actions: View { } }) } - + private func presentAnimated() { withAnimation { bottomOffset = 0 @@ -90,7 +87,7 @@ public struct Snackbar: View where Label: View, Actions: View { } } } - + private func dismissAnimated() { withAnimation { bottomOffset = 200 @@ -104,10 +101,10 @@ public extension Snackbar where Label == EmptyView, Actions == EmptyView { _ text: String, isPresented: Binding ) { - self._isPresented = isPresented + _isPresented = isPresented self.text = text - self.label = nil - self.actions = nil + label = nil + actions = nil } } @@ -116,10 +113,10 @@ public extension Snackbar where Label == Text, Actions == EmptyView { isPresented: Binding, @ViewBuilder label: () -> Label ) { - self._isPresented = isPresented - self.text = nil + _isPresented = isPresented + text = nil self.label = label() - self.actions = nil + actions = nil } } @@ -128,22 +125,21 @@ public extension Snackbar where Actions == EmptyView { isPresented: Binding, @ViewBuilder label: () -> Label ) { - self._isPresented = isPresented - self.text = nil + _isPresented = isPresented + text = nil self.label = label() - self.actions = nil + actions = nil } } - public extension Snackbar where Label == Text, Actions == Button { init( isPresented: Binding, @ViewBuilder label: () -> Label, @ViewBuilder actions: () -> Actions ) { - self._isPresented = isPresented - self.text = nil + _isPresented = isPresented + text = nil self.label = label() self.actions = Group { actions() } } @@ -155,8 +151,8 @@ public extension Snackbar where Label == Text, Actions == Button { @ViewBuilder label: () -> Label, @ViewBuilder actions: () -> Actions ) { - self._isPresented = isPresented - self.text = nil + _isPresented = isPresented + text = nil self.label = label() self.actions = Group { actions() } } @@ -168,8 +164,8 @@ public extension Snackbar where Label == Text, Actions == Button Label, @ViewBuilder actions: () -> Actions ) { - self._isPresented = isPresented - self.text = nil + _isPresented = isPresented + text = nil self.label = label() self.actions = Group { actions() } } @@ -181,8 +177,8 @@ public extension Snackbar where Actions == Button Label, @ViewBuilder actions: () -> Actions ) { - self._isPresented = isPresented - self.text = nil + _isPresented = isPresented + text = nil self.label = label() self.actions = Group { actions() } } @@ -194,8 +190,8 @@ public extension Snackbar where Actions == Button { @ViewBuilder label: () -> Label, @ViewBuilder actions: () -> Actions ) { - self._isPresented = isPresented - self.text = nil + _isPresented = isPresented + text = nil self.label = label() self.actions = Group { actions() } } @@ -207,9 +203,9 @@ public extension Snackbar where Label == EmptyView, Actions == Button { isPresented: Binding, @ViewBuilder actions: () -> Actions ) { - self._isPresented = isPresented + _isPresented = isPresented self.text = text - self.label = nil + label = nil self.actions = Group { actions() } } } @@ -220,9 +216,9 @@ public extension Snackbar where Label == EmptyView, Actions == Button { isPresented: Binding, @ViewBuilder actions: () -> Actions ) { - self._isPresented = isPresented + _isPresented = isPresented self.text = text - self.label = nil + label = nil self.actions = Group { actions() } } } @@ -233,9 +229,9 @@ public extension Snackbar where Label == EmptyView, Actions == Button, @ViewBuilder actions: () -> Actions ) { - self._isPresented = isPresented + _isPresented = isPresented self.text = text - self.label = nil + label = nil self.actions = Group { actions() } } } @@ -246,36 +242,35 @@ public extension Snackbar where Label == EmptyView { isPresented: Binding, @ViewBuilder actions: () -> Actions ) { - self._isPresented = isPresented + _isPresented = isPresented self.text = text - self.label = nil + label = nil self.actions = Group { actions() } } } public extension View { func snackbar(_ text: String, isPresented: Binding) -> some View { - self.overlay(alignment: .bottom) { + overlay(alignment: .bottom) { Snackbar(text, isPresented: isPresented) } } - - func snackbar(_ text: String, isPresented: Binding, @ViewBuilder actions: () -> Actions) -> some View { - self.overlay(alignment: .bottom) { + + func snackbar(_ text: String, isPresented: Binding, @ViewBuilder actions: () -> some View) -> some View { + overlay(alignment: .bottom) { Snackbar(text, isPresented: isPresented, actions: actions) } } - - func snackbar(isPresented: Binding, @ViewBuilder label: () -> Label) -> some View { - self.overlay(alignment: .bottom) { + + func snackbar(isPresented: Binding, @ViewBuilder label: () -> some View) -> some View { + overlay(alignment: .bottom) { Snackbar(isPresented: isPresented, label: label) } } - - func snackbar(isPresented: Binding, @ViewBuilder label: () -> Label, @ViewBuilder actions: () -> Actions) -> some View { - self.overlay(alignment: .bottom) { + + func snackbar(isPresented: Binding, @ViewBuilder label: () -> some View, @ViewBuilder actions: () -> some View) -> some View { + overlay(alignment: .bottom) { Snackbar(isPresented: isPresented, label: label, actions: actions) } } } - diff --git a/Sources/OversizeUI/Controls/Toast/Toast.swift b/Sources/OversizeUI/Controls/Toast/Toast.swift deleted file mode 100644 index 7d71cf1..0000000 --- a/Sources/OversizeUI/Controls/Toast/Toast.swift +++ /dev/null @@ -1,196 +0,0 @@ -// -// Copyright © 2023 Alexander Romanov -// Toast.swift, created on 20.05.2023 -// - -import SwiftUI - - - - -public struct Toast: View { - - private let text: String - private let presentHandler: (() -> Void)? - private let dismissHandler: (() -> Void)? - - @Binding private var isInternallyPresented: Bool - - // MARK: Initializers - public init( - text: String, - isPresented: Binding, - onPresent presentHandler: (() -> Void)?, - onDismiss dismissHandler: (() -> Void)? - ) { - self.text = text - self.presentHandler = presentHandler - self.dismissHandler = dismissHandler - self._isInternallyPresented = isPresented - } - - - public var body: some View { - ZStack(alignment: .bottom, content: { - //dimmingView - contentView - }) - } - - private var dimmingView: some View { - Color.backgroundPrimary.opacity(0.01) - .ignoresSafeArea() - } - - private var contentView: some View { - Surface { - HStack { - Text(text) - .lineLimit(2) - .foregroundColor(.onSurfaceHighEmphasis) - .font(.body) - - Spacer() - - Button("Close") { - isInternallyPresented = false - } - } - - } - .padding(.medium) - .elevation(.z4) - .opacity(isInternallyPresented ? 1 : 0) - //.offset(y: isInternallyPresented ? -300 : 0) - } -} - -public extension View { - - func presentToast(isPresented: Binding, - isBlocking: Bool = true, - @ViewBuilder notification: @escaping () -> Toast) -> some View { - self.presentingView(isPresented: isPresented, - isBlocking: isBlocking) { - notification() - } - } -} - -public extension View { - - @ViewBuilder - func presentingView(isPresented: Binding, - dimmedBackgroundColor: Color = Color.black, - dimmedBackgroundColorOpacity: Double = 0.1, - hasDimmedBackground: Bool = false, - isBlocking: Bool = false, - @ViewBuilder presentedView: @escaping () -> PresentedView) -> some View { - modifier(PresentationModifier(hasDimmedBackground: hasDimmedBackground, - dimmedBackgroundColor: dimmedBackgroundColor, - dimmedBackgroundColorOpacity: dimmedBackgroundColorOpacity, - isBlocking: isBlocking, - isPresented: isPresented, - presentedView: presentedView)) - } -} - - -struct PresentationModifier: ViewModifier { - func body(content: Content) -> some View { - ZStack { - content - - Rectangle() - .frame(maxWidth: .infinity, - maxHeight: .infinity, - alignment: .center) - .foregroundColor(isPresented ? backgroundColor : Color.clear) - .allowsHitTesting(isPresented && isBlocking) - - presentedView - } - .frame(maxWidth: .infinity, - maxHeight: .infinity, - alignment: .center) - .clipped() - } - - var hasDimmedBackground: Bool - var dimmedBackgroundColor: Color - var dimmedBackgroundColorOpacity: Double - var isBlocking: Bool - @Binding var isPresented: Bool - @ViewBuilder var presentedView: PresentedView - - var backgroundColor: Color { - if hasDimmedBackground { - return dimmedBackgroundColor.opacity(dimmedBackgroundColorOpacity) - } else if isBlocking { - // A clear color won't allow the background - // view to block the underlying view - return Color.black.opacity(Double.ulpOfOne) - } - - return Color.clear - } -} - -// func border(width: CGFloat, -// edges: [Edge], -// color: Color) -> some View { -// overlay(EdgeBorder(width: width, -// edges: edges) -// .foregroundColor(color)) -// } -//} - -//extension View { -// -// public func toast( -// isPresented: Binding, -// text: String, -// onPresent presentHandler: (() -> Void)? = nil, -// onDismiss dismissHandler: (() -> Void)? = nil, -// ) -> some View { -// self -// .presentationHost( -// id: id, -// allowsHitTests: false, -// isPresented: isPresented, -// content: { -// VToast( -// uiModel: uiModel, -// onPresent: presentHandler, -// onDismiss: dismissHandler, -// text: text -// ) -// } -// ) -// } -// -// @ViewBuilder public func presentationHost( -// id: String, -// allowsHitTests: Bool = true, -// isPresented: Binding, -// content: @escaping () -> Content -// ) -> some View -// where Content: View -// { -//#if os(iOS) -// self -// .onDisappear(perform: { _PresentationHostViewController.forceDismiss(id: id) }) -// .background(PresentationHostView( -// id: id, -// allowsHitTests: allowsHitTests, -// isPresented: isPresented, -// content: content -// )) -// } -//} - -//struct Toast_Previews: PreviewProvider { -// static var previews: some View { -// Toast() -// } -//} diff --git a/Sources/OversizeUI/Deprecated/HUDDeprecated.swift b/Sources/OversizeUI/Deprecated/HUDDeprecated.swift index 691e4d4..8335b52 100644 --- a/Sources/OversizeUI/Deprecated/HUDDeprecated.swift +++ b/Sources/OversizeUI/Deprecated/HUDDeprecated.swift @@ -62,8 +62,8 @@ public class HUDDeprecated: ObservableObject { public extension View { func hudDeprecated(isPresented: Binding, - type: Binding, - @ViewBuilder content: () -> some View) -> some View + type: Binding, + @ViewBuilder content: () -> some View) -> some View { ZStack(alignment: type.wrappedValue == .hud ? .top : .center) { self diff --git a/Sources/OversizeUI/Generated/GeneratedIcons.swift b/Sources/OversizeUI/Generated/GeneratedIcons.swift index 1bcaa92..27aec00 100644 --- a/Sources/OversizeUI/Generated/GeneratedIcons.swift +++ b/Sources/OversizeUI/Generated/GeneratedIcons.swift @@ -113,32 +113,35 @@ public enum Icons { } } - public struct IconSymbol { - public let path: String public init(path: String) { self.path = path } + public var outline: SwiftUI.Image { - return SwiftUI.Image(path, bundle: Bundle.module) + SwiftUI.Image(path, bundle: Bundle.module) } + public var solid: SwiftUI.Image { - return SwiftUI.Image("Solid/" + path, bundle: Bundle.module) + SwiftUI.Image("Solid/" + path, bundle: Bundle.module) } + public var bulk: SwiftUI.Image { - return SwiftUI.Image("Bulk/" + path, bundle: Bundle.module) + SwiftUI.Image("Bulk/" + path, bundle: Bundle.module) } + public var twoTone: SwiftUI.Image { - return SwiftUI.Image("TwoTone/" + path, bundle: Bundle.module) + SwiftUI.Image("TwoTone/" + path, bundle: Bundle.module) } + public var categoryName: String? { - return path.components(separatedBy: "/").first + path.components(separatedBy: "/").first } public var name: String { - return path.components(separatedBy: "/").last ?? "" + path.components(separatedBy: "/").last ?? "" } } @@ -148,6 +151,7 @@ public struct Icon: View { public init(_ icon: IconSymbol) { self.icon = icon } + public var body: some View { switch iconStyle { case .line: icon.outline diff --git a/Sources/OversizeUI/Generated/GeneratedImages.swift b/Sources/OversizeUI/Generated/GeneratedImages.swift index e53b12d..568a4ec 100644 --- a/Sources/OversizeUI/Generated/GeneratedImages.swift +++ b/Sources/OversizeUI/Generated/GeneratedImages.swift @@ -3,7 +3,6 @@ import SwiftUI - // swiftlint:disable superfluous_disable_command file_length implicit_return // MARK: - Asset Catalogs @@ -11,72 +10,73 @@ import SwiftUI // swiftlint:disable identifier_name line_length nesting type_body_length type_name public enum Images { public static let allImages: [Image] = [ - Appearance.dark, - Appearance.light, - Appearance.system, - avatar, - Status.error, - Status.success, - Status.warning, - ] - public static let allNames: [String] = [ - "", - "Avatar", - "", - ] - public enum Appearance { - public static let allImages: [Image] = [ - dark, - light, - system, - ] - public static let allNames: [String] = [ - "Dark", - "Light", - "System", + Appearance.dark, + Appearance.light, + Appearance.system, + avatar, + Status.error, + Status.success, + Status.warning, ] - public static let dark: Image = .init("Dark", bundle: .module) - public static let darkName: String = "Dark" - public static let light: Image = .init("Light", bundle: .module) - public static let lightName: String = "Light" - public static let system: Image = .init("System", bundle: .module) - public static let systemName: String = "System" - } -public static let avatar: Image = .init("Avatar", bundle: .module) -public static let avatarName: String = "Avatar" - public enum Status { - public static let allImages: [Image] = [ - error, - success, - warning, - ] public static let allNames: [String] = [ - "Error", - "Success", - "Warning", + "", + "Avatar", + "", ] - public static let error: Image = .init("Error", bundle: .module) - public static let errorName: String = "Error" - public static let success: Image = .init("Success", bundle: .module) - public static let successName: String = "Success" - public static let warning: Image = .init("Warning", bundle: .module) - public static let warningName: String = "Warning" - } + public enum Appearance { + public static let allImages: [Image] = [ + dark, + light, + system, + ] + public static let allNames: [String] = [ + "Dark", + "Light", + "System", + ] + public static let dark: Image = .init("Dark", bundle: .module) + public static let darkName: String = "Dark" + public static let light: Image = .init("Light", bundle: .module) + public static let lightName: String = "Light" + public static let system: Image = .init("System", bundle: .module) + public static let systemName: String = "System" + } + + public static let avatar: Image = .init("Avatar", bundle: .module) + public static let avatarName: String = "Avatar" + public enum Status { + public static let allImages: [Image] = [ + error, + success, + warning, + ] + public static let allNames: [String] = [ + "Error", + "Success", + "Warning", + ] + public static let error: Image = .init("Error", bundle: .module) + public static let errorName: String = "Error" + public static let success: Image = .init("Success", bundle: .module) + public static let successName: String = "Success" + public static let warning: Image = .init("Warning", bundle: .module) + public static let warningName: String = "Warning" + } } + // swiftlint:enable identifier_name line_length nesting type_body_length type_name // MARK: - Implementation Details - - // swiftlint:disable convenience_type private final class BundleToken { - static let bundle: Bundle = { - #if SWIFT_PACKAGE - return Bundle.module - #else - return Bundle(for: BundleToken.self) - #endif - }() + static let bundle: Bundle = { + #if SWIFT_PACKAGE + return Bundle.module + #else + return Bundle(for: BundleToken.self) + #endif + }() } + // swiftlint:enable convenience_type