diff --git a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/.swiftpm/xcode/package.xcworkspace/xcuserdata/macintoshi.xcuserdatad/UserInterfaceState.xcuserstate b/.swiftpm/xcode/package.xcworkspace/xcuserdata/macintoshi.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..21acd0e Binary files /dev/null and b/.swiftpm/xcode/package.xcworkspace/xcuserdata/macintoshi.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/.swiftpm/xcode/xcuserdata/macintoshi.xcuserdatad/xcschemes/xcschememanagement.plist b/.swiftpm/xcode/xcuserdata/macintoshi.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..5e8c333 --- /dev/null +++ b/.swiftpm/xcode/xcuserdata/macintoshi.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + ToastKit.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/Sources/ToastKit/ToastKit.swift b/Sources/ToastKit/ToastKit.swift index d79d9c5..444d962 100644 --- a/Sources/ToastKit/ToastKit.swift +++ b/Sources/ToastKit/ToastKit.swift @@ -32,6 +32,7 @@ public struct CustomToast: View { let innerVpadding: CGFloat let outterHpadding: CGFloat let stackAligment: Alignment + let isStackMaxHeight: Bool let cornerRadius: CGFloat @@ -83,6 +84,7 @@ public struct CustomToast: View { innerVpadding: CGFloat = 10, outterHpadding: CGFloat = 20, stackAligment: Alignment = .top, + isStackMaxHeight: Bool = true, cornerRadius: CGFloat = 12, @@ -132,6 +134,7 @@ public struct CustomToast: View { self.innerVpadding = innerVpadding self.outterHpadding = outterHpadding self.stackAligment = stackAligment + self.isStackMaxHeight = isStackMaxHeight self.cornerRadius = cornerRadius @@ -232,7 +235,8 @@ public struct CustomToast: View { .padding(.horizontal, outterHpadding) } } - .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: stackAligment) + .frame(maxWidth: .infinity, alignment: stackAligment) + .if(isStackMaxHeight) { $0.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: stackAligment)} .onChange(of: isVisible) { _, newValue in if newValue { if autoDisappear { @@ -261,5 +265,3 @@ public struct CustomToast: View { } } } - - diff --git a/Sources/ToastKit/ToastStack/ToastStackManager.swift b/Sources/ToastKit/ToastStack/ToastStackManager.swift new file mode 100644 index 0000000..0065f58 --- /dev/null +++ b/Sources/ToastKit/ToastStack/ToastStackManager.swift @@ -0,0 +1,47 @@ +// +// ToastStackManager.swift +// ToastKit +// +// Created by Despo on 18.04.25. +// +import SwiftUI + +@available(macOS 14.0, *) +@available(iOS 17, *) +struct ToastItemModel: Identifiable, Equatable { + let id = UUID() + let title: String + let toastColor: ToastColorTypes + let autoDisappearDuration: TimeInterval + let isStackMaxHeight: Bool = false + + static func == (lhs: ToastItemModel, rhs: ToastItemModel) -> Bool { + return lhs.id == rhs.id + } +} + +@available(macOS 14.0, *) +@available(iOS 17, *) + +@MainActor +class ToastStackManager: ObservableObject { + @Published var toasts: [ToastItemModel] = [] + + func show(title: String, toastColor: ToastColorTypes, autoDisappearDuration: TimeInterval = 2.0) { + let toast = ToastItemModel( + title: title, + toastColor: toastColor, + autoDisappearDuration: autoDisappearDuration + ) + + toasts.insert(toast, at: 0) + + DispatchQueue.main.asyncAfter(deadline: .now() + autoDisappearDuration) { [weak self] in + self?.removeToast(toast) + } + } + + private func removeToast(_ toast: ToastItemModel) { + toasts.removeAll { $0.id == toast.id } + } +} diff --git a/Sources/ToastKit/ToastStack/ToastStackView.swift b/Sources/ToastKit/ToastStack/ToastStackView.swift new file mode 100644 index 0000000..cb24063 --- /dev/null +++ b/Sources/ToastKit/ToastStack/ToastStackView.swift @@ -0,0 +1,41 @@ +// +// ToastStackView.swift +// ToastKit +// +// Created by Despo on 18.04.25. +// + +import SwiftUI + +@available(macOS 14.0, *) +@available(iOS 17, *) +struct ToastStackView: View { + @StateObject var vm: ToastStackManager + let transitionType: AnyTransition + + init( + vm: ToastStackManager, + transitionType: AnyTransition = .move(edge: .top).combined(with: .opacity) + ) { + _vm = StateObject(wrappedValue: vm) + self.transitionType = transitionType + } + + var body: some View { + VStack { + ForEach(vm.toasts, id: \.id) { toast in + ZStack { + CustomToast( + isVisible: .constant(true), + title: toast.title, + toastColor: toast.toastColor, + isStackMaxHeight: toast.isStackMaxHeight + ) + } + .transition(transitionType) + } + } + .frame(maxWidth: .infinity, maxHeight: .infinity,alignment: .top) + .animation(.bouncy, value: vm.toasts) + } +}