diff --git a/PuraceDemo/PuraceDemo.xcodeproj/project.pbxproj b/PuraceDemo/PuraceDemo.xcodeproj/project.pbxproj index b410159..5f360ba 100644 --- a/PuraceDemo/PuraceDemo.xcodeproj/project.pbxproj +++ b/PuraceDemo/PuraceDemo.xcodeproj/project.pbxproj @@ -24,6 +24,7 @@ 2F9321B7282EE49E003DA929 /* MenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F9321B6282EE49E003DA929 /* MenuView.swift */; }; 2F9321BC282EE49E003DA929 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2F9321BB282EE49E003DA929 /* Assets.xcassets */; }; 2F9321BF282EE49E003DA929 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2F9321BD282EE49E003DA929 /* LaunchScreen.storyboard */; }; + 2FA5850C28A01F7700A8393E /* ScaffoldExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA5850B28A01F7700A8393E /* ScaffoldExample.swift */; }; 2FA986792837351B000DB409 /* GridExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA986782837351B000DB409 /* GridExample.swift */; }; 2FA9867B28373DD3000DB409 /* SnackbarExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA9867A28373DD3000DB409 /* SnackbarExample.swift */; }; 2FC004092831AC250037EF10 /* StoryExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FC004082831AC250037EF10 /* StoryExample.swift */; }; @@ -52,6 +53,7 @@ 2F9321BB282EE49E003DA929 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 2F9321BE282EE49E003DA929 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 2F9321C0282EE49E003DA929 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 2FA5850B28A01F7700A8393E /* ScaffoldExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScaffoldExample.swift; sourceTree = ""; }; 2FA986782837351B000DB409 /* GridExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GridExample.swift; sourceTree = ""; }; 2FA9867A28373DD3000DB409 /* SnackbarExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnackbarExample.swift; sourceTree = ""; }; 2FC004082831AC250037EF10 /* StoryExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoryExample.swift; sourceTree = ""; }; @@ -74,6 +76,7 @@ 2F1F7D6F28317DE200AA30DB /* Examples */ = { isa = PBXGroup; children = ( + 2FA5850A28A01F4800A8393E /* Pages */, 2F27BC9B284814A700B5AC8D /* Complex */, 2F27BC9A2848149900B5AC8D /* Basic */, ); @@ -149,6 +152,14 @@ name = Frameworks; sourceTree = ""; }; + 2FA5850A28A01F4800A8393E /* Pages */ = { + isa = PBXGroup; + children = ( + 2FA5850B28A01F7700A8393E /* ScaffoldExample.swift */, + ); + path = Pages; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -234,6 +245,7 @@ 2F9321B3282EE49E003DA929 /* AppDelegate.swift in Sources */, 2F6267AE2857B6960063A630 /* AccordionExample.swift in Sources */, 2F569939285FB93500F2D4D3 /* ModalExample.swift in Sources */, + 2FA5850C28A01F7700A8393E /* ScaffoldExample.swift in Sources */, 2F77A234283C4AC700F143FB /* ImageExample.swift in Sources */, 2F5EFD3C284D23E3005D130A /* HorizontalGridExample.swift in Sources */, 2FA9867B28373DD3000DB409 /* SnackbarExample.swift in Sources */, diff --git a/PuraceDemo/PuraceDemo/Examples/Basic/ButtonExample.swift b/PuraceDemo/PuraceDemo/Examples/Basic/ButtonExample.swift index 9a9e24b..ac36808 100644 --- a/PuraceDemo/PuraceDemo/Examples/Basic/ButtonExample.swift +++ b/PuraceDemo/PuraceDemo/Examples/Basic/ButtonExample.swift @@ -14,27 +14,27 @@ struct ButtonExample: View { VStack(spacing: 0) { VStack { Text("`PuraceButtonView('title', type: .loud)`") - PuraceButtonView("Font size: 12", fontSize: 12) - PuraceButtonView("Font size: 14", fontSize: 14) - PuraceButtonView("Font size: 16", fontSize: 16) + PuraceButtonView("small", size: .small) + PuraceButtonView("medium") + PuraceButtonView("large", size: .large) .padding(.bottom) } VStack { Text("`PuraceButtonView('title', type: .quiet)`") - PuraceButtonView("Font size: 12", fontSize: 12, type: .quiet) - PuraceButtonView("Font size: 14", fontSize: 14, type: .quiet) - PuraceButtonView("Font size: 16", fontSize: 16, type: .quiet) + PuraceButtonView("small", size: .small, type: .quiet) + PuraceButtonView("medium", type: .quiet) + PuraceButtonView("large", size: .large, type: .quiet) .padding(.bottom) } - - VStack { - Text("`PuraceButtonView('title', type: .transparent)`") - PuraceButtonView("Font size: 12", fontSize: 12, type: .transparent) - PuraceButtonView("Font size: 14", fontSize: 14, type: .transparent) - PuraceButtonView("Font size: 16", fontSize: 16, type: .transparent) - Spacer() - } +// +// VStack { +// Text("`PuraceButtonView('title', type: .transparent)`") +// PuraceButtonView("Font size: 12", fontSize: 12, type: .transparent) +// PuraceButtonView("Font size: 14", fontSize: 14, type: .transparent) +// PuraceButtonView("Font size: 16", fontSize: 16, type: .transparent) +// Spacer() +// } } } } diff --git a/PuraceDemo/PuraceDemo/Examples/Basic/SnackbarExample.swift b/PuraceDemo/PuraceDemo/Examples/Basic/SnackbarExample.swift index 83dbb8e..866c744 100644 --- a/PuraceDemo/PuraceDemo/Examples/Basic/SnackbarExample.swift +++ b/PuraceDemo/PuraceDemo/Examples/Basic/SnackbarExample.swift @@ -44,7 +44,7 @@ struct SnackBarExample: View { Spacer() } - PuraceButtonView("Mostrar snackbar", fontSize: 14) { + PuraceButtonView("Mostrar snackbar") { PuraceSnackbarBuilder() .withTitle("Hubo un error") .withType(getType()) diff --git a/PuraceDemo/PuraceDemo/Examples/Pages/ScaffoldExample.swift b/PuraceDemo/PuraceDemo/Examples/Pages/ScaffoldExample.swift new file mode 100644 index 0000000..e8f5742 --- /dev/null +++ b/PuraceDemo/PuraceDemo/Examples/Pages/ScaffoldExample.swift @@ -0,0 +1,32 @@ +// +// ScaffoldExample.swift +// PuraceDemo +// +// Created by Juan Hurtado on 7/08/22. +// + +import Foundation +import SwiftUI +import Purace + +struct ScaffoldExample: View { + @State var showError = false + @Environment(\.presentationMode) var presentationMode + + var body: some View { + PuraceScaffold(navBar: .init(title: "This is an example", backOnTap: { + presentationMode.wrappedValue.dismiss() + })) { + PuraceScaffoldContent { + VStack { + PuraceButtonView("Toggle error") { + showError.toggle() + } + } + }.genericErrorView(isPresented: $showError) { + print("error retry callback has been called") + } + } + .navigationBarHidden(true) + } +} diff --git a/PuraceDemo/PuraceDemo/MenuView.swift b/PuraceDemo/PuraceDemo/MenuView.swift index b34bb73..c9c81ec 100644 --- a/PuraceDemo/PuraceDemo/MenuView.swift +++ b/PuraceDemo/PuraceDemo/MenuView.swift @@ -65,6 +65,11 @@ struct MenuView: View { AdjustableHStackExample() } } + Section { + NavigationLink("Scaffold") { + ScaffoldExample() + } + } } .navigationTitle("Purace") } diff --git a/Sources/Purace/Pages/Scaffold/PuraceErrorView.swift b/Sources/Purace/Pages/Scaffold/PuraceErrorView.swift new file mode 100644 index 0000000..b9e11ed --- /dev/null +++ b/Sources/Purace/Pages/Scaffold/PuraceErrorView.swift @@ -0,0 +1,67 @@ +// +// PuraceErrorView.swift +// +// +// Created by Juan Hurtado on 15/12/22. +// + +import SwiftUI + +struct PuraceErrorView: View { + var onRetryTap: (() -> Void)? + + var body: some View { + GeometryReader { _ in + VStack(alignment: .center) { + Spacer(minLength: 0) + Image("error", bundle: .module) + VStack(spacing: 17) { + PuraceTextView("Ups", fontSize: 22, weight: .medium) + PuraceTextView("Parece que ha ocurrido un error. No te preocupes, es nuestra culpa.", fontSize: 14, textColor: PuraceStyle.Color.N2) + .multilineTextAlignment(.center) + HStack(spacing: 3) { + PuraceTextView("Código:", textColor: PuraceStyle.Color.N4) + PuraceTextView("12", weight: .medium) + } + .padding(.horizontal, 20) + .padding(.vertical, 4) + .background(Color.white) + .cornerRadius(20) + } + Spacer(minLength: 0) + if let onRetryTap { + PuraceButtonView("Reintentar") { + onRetryTap() + } + } + Spacer(minLength: 0) + } + .padding(.horizontal, 50) + }.background(PuraceStyle.Color.F1) + } +} + +// MARK: - View modifier +struct PuraceErrorViewModifier: ViewModifier { + @Binding var isPresented: Bool + var retryCallback: (() -> Void)? + + func body(content: Content) -> some View { + Group { + if isPresented { + PuraceErrorView(onRetryTap: retryCallback) + } else { + content + } + } + } +} + + +// MARK: - Scaffold extension +public extension PuraceScaffoldContent { + func genericErrorView(isPresented: Binding, retryCallback: (() -> Void)? = nil) -> some View { + let errorModifier = PuraceErrorViewModifier(isPresented: isPresented, retryCallback: retryCallback) + return modifier(errorModifier) + } +} diff --git a/Sources/Purace/Pages/Scaffold/PuraceScaffold.swift b/Sources/Purace/Pages/Scaffold/PuraceScaffold.swift new file mode 100644 index 0000000..a96aacd --- /dev/null +++ b/Sources/Purace/Pages/Scaffold/PuraceScaffold.swift @@ -0,0 +1,41 @@ +// +// PuraceScaffold.swift +// +// +// Created by Juan Hurtado on 7/08/22. +// + +import Foundation +import SwiftUI + +public struct PuraceScaffold: View { + var navBar: PuraceScaffoldNavBar? + var content: () -> Content + + public init(navBar: PuraceScaffoldNavBar? = nil, content: @escaping () -> Content) { + self.navBar = navBar + self.content = content + } + + public var body: some View { + VStack(spacing: 0) { + if let navBar { + navBar + } + content() + Spacer(minLength: 0) + } + } +} + +public struct PuraceScaffoldContent: View { + public var content: () -> Content + + public init(content: @escaping () -> Content) { + self.content = content + } + + public var body: some View { + content() + } +} diff --git a/Sources/Purace/Pages/Scaffold/PuraceScaffoldNavBar.swift b/Sources/Purace/Pages/Scaffold/PuraceScaffoldNavBar.swift new file mode 100644 index 0000000..6fd78fb --- /dev/null +++ b/Sources/Purace/Pages/Scaffold/PuraceScaffoldNavBar.swift @@ -0,0 +1,51 @@ +// +// PuraceScaffoldNavBar.swift +// +// +// Created by Juan Hurtado on 7/08/22. +// + +import Foundation +import SwiftUI + +public struct PuraceScaffoldNavBar: View { + var title: String + var backOnTap: () -> Void + + public init(title: String, backOnTap: @escaping () -> Void) { + self.title = title + self.backOnTap = backOnTap + } + + public var body: some View { + GeometryReader { _ in + VStack(alignment: .center) { + Spacer(minLength: 0) + HStack(alignment: .center) { + Button { + backOnTap() + } label: { + Image("arrow_left", bundle: .module) + .foregroundColor(PuraceStyle.Color.N1) + }.frame(width: 20) + .buttonStyle(.plain) + + Spacer(minLength: 0) + + PuraceTextView(title, fontSize: 14, weight: .medium) + .multilineTextAlignment(.center) + + Spacer(minLength: 0) + + Color.white + .frame(width: 20, height: 20) + .background(Color.white) + } + Spacer(minLength: 0) + } + } + .frame(height: 50) + .padding(.horizontal, 16) + .background(Color.white) + } +} diff --git a/Sources/Purace/Resources/Media.xcassets/arrow_left.imageset/Contents.json b/Sources/Purace/Resources/Media.xcassets/arrow_left.imageset/Contents.json new file mode 100644 index 0000000..5a49b49 --- /dev/null +++ b/Sources/Purace/Resources/Media.xcassets/arrow_left.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "arrow_left.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sources/Purace/Resources/Media.xcassets/arrow_left.imageset/arrow_left.svg b/Sources/Purace/Resources/Media.xcassets/arrow_left.imageset/arrow_left.svg new file mode 100644 index 0000000..6328257 --- /dev/null +++ b/Sources/Purace/Resources/Media.xcassets/arrow_left.imageset/arrow_left.svg @@ -0,0 +1,3 @@ + + + diff --git a/Sources/Purace/Resources/Media.xcassets/error.imageset/Contents.json b/Sources/Purace/Resources/Media.xcassets/error.imageset/Contents.json new file mode 100644 index 0000000..a2f8724 --- /dev/null +++ b/Sources/Purace/Resources/Media.xcassets/error.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "error.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sources/Purace/Resources/Media.xcassets/error.imageset/error.svg b/Sources/Purace/Resources/Media.xcassets/error.imageset/error.svg new file mode 100644 index 0000000..f8f970d --- /dev/null +++ b/Sources/Purace/Resources/Media.xcassets/error.imageset/error.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/Purace/Views/Basic/Button/PuraceButtonSize.swift b/Sources/Purace/Views/Basic/Button/PuraceButtonSize.swift new file mode 100644 index 0000000..a6214a7 --- /dev/null +++ b/Sources/Purace/Views/Basic/Button/PuraceButtonSize.swift @@ -0,0 +1,14 @@ +// +// PuraceButtonSize.swift +// +// +// Created by Juan Hurtado on 15/12/22. +// + +import Foundation + +public enum PuraceButtonSize: Int { + case small = 12 + case medium = 14 + case large = 16 +} diff --git a/Sources/Purace/Views/Basic/Button/PuraceButtonType.swift b/Sources/Purace/Views/Basic/Button/PuraceButtonType.swift index 5c4f3ed..f4899d0 100644 --- a/Sources/Purace/Views/Basic/Button/PuraceButtonType.swift +++ b/Sources/Purace/Views/Basic/Button/PuraceButtonType.swift @@ -9,6 +9,5 @@ import Foundation import SwiftUI public enum PuraceButtonType { - case loud, quiet, transparent - case custom(Color, Color, Color) // 0: background, 1: on pressed, 2: text color + case loud, quiet } diff --git a/Sources/Purace/Views/Basic/Button/PuraceButtonView.swift b/Sources/Purace/Views/Basic/Button/PuraceButtonView.swift index 251aa8d..e707443 100644 --- a/Sources/Purace/Views/Basic/Button/PuraceButtonView.swift +++ b/Sources/Purace/Views/Basic/Button/PuraceButtonView.swift @@ -10,14 +10,14 @@ import SwiftUI public struct PuraceButtonView: View { let title: String - let fontSize: Int let type: PuraceButtonType + let size: PuraceButtonSize let onTap: (() -> Void)? - public init(_ title: String, fontSize: Int = 12, type: PuraceButtonType = .loud, onTap: (() -> Void)? = nil) { + public init(_ title: String, size: PuraceButtonSize = .medium, type: PuraceButtonType = .loud, onTap: (() -> Void)? = nil) { self.title = title - self.fontSize = fontSize self.type = type + self.size = size self.onTap = onTap } @@ -25,7 +25,7 @@ public struct PuraceButtonView: View { Button(title) { onTap?() } - .font(PuraceStyle.Font.get(size: CGFloat(fontSize), weight: .medium)) + .font(PuraceStyle.Font.get(size: CGFloat(size.rawValue), weight: .medium)) .buttonStyle(PuraceButtonStyle(type: type)) } } @@ -36,13 +36,9 @@ struct PuraceButtonStyle: ButtonStyle { private func getBackgroundColor() -> Color { switch type { case .loud: - return PuraceStyle.Color.B2 + return PuraceStyle.Color.N2 case .quiet: - return PuraceStyle.Color.B5 - case .transparent: - return .white.opacity(0.01) - case .custom(let backgroundColor, _, _): - return backgroundColor + return .clear } } @@ -51,33 +47,30 @@ struct PuraceButtonStyle: ButtonStyle { case .loud: return .white case .quiet: - return PuraceStyle.Color.B1 - case .transparent: - return PuraceStyle.Color.B1 - case .custom(_, _, let textColor): - return textColor + return PuraceStyle.Color.N1 } } private func getOnPressedBackgroundColor() -> Color { switch type { case .loud: - return PuraceStyle.Color.B1 + return PuraceStyle.Color.N1 case .quiet: - return PuraceStyle.Color.B4 - case .transparent: - return PuraceStyle.Color.B5 - case .custom(_, let onPressedColor, _): - return onPressedColor + return PuraceStyle.Color.N8 } } func makeBody(configuration: Configuration) -> some View { configuration.label - .padding(.horizontal, 10) - .padding(.vertical, 5) + .padding(.horizontal, 20) + .padding(.vertical, 4) .background(configuration.isPressed ? getOnPressedBackgroundColor() : getBackgroundColor()) .foregroundColor(getTextColor()) - .clipShape(RoundedRectangle(cornerRadius: 5)) + .clipShape(RoundedRectangle(cornerRadius: 20)) + .overlay( + RoundedRectangle(cornerRadius:20) + .stroke(lineWidth: 1) + .foregroundColor(PuraceStyle.Color.N2) + ) } } diff --git a/Sources/Purace/Views/Basic/Snackbar/PuraceSnackbarView.swift b/Sources/Purace/Views/Basic/Snackbar/PuraceSnackbarView.swift index 1dc6819..6faf2d7 100644 --- a/Sources/Purace/Views/Basic/Snackbar/PuraceSnackbarView.swift +++ b/Sources/Purace/Views/Basic/Snackbar/PuraceSnackbarView.swift @@ -40,10 +40,11 @@ struct PuraceSnackbarView: View { PuraceTextView(title, textColor: .white) Spacer() if let buttonTitle = buttonTitle { - PuraceButtonView(buttonTitle, fontSize: 14, type: .custom(.clear, .white.opacity(0.1), .white)) { - buttonOnTap?() - isVisible = false - } + PuraceTextView(buttonTitle, textColor: .white, weight: .medium) + .onTapGesture { + buttonOnTap?() + isVisible = false + } } } .lineLimit(2)