diff --git a/PYLayoutDemo/PYLayoutDemo.xcodeproj/project.pbxproj b/PYLayoutDemo/PYLayoutDemo.xcodeproj/project.pbxproj new file mode 100644 index 0000000..56c1a45 --- /dev/null +++ b/PYLayoutDemo/PYLayoutDemo.xcodeproj/project.pbxproj @@ -0,0 +1,413 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 55; + objects = { + +/* Begin PBXBuildFile section */ + 2F1F7D7128317E0700AA30DB /* CollectionCardExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F1F7D7028317E0700AA30DB /* CollectionCardExample.swift */; }; + 2F1F7D7328318D9900AA30DB /* TextExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F1F7D7228318D9900AA30DB /* TextExample.swift */; }; + 2F1F7D7528318EEE00AA30DB /* ButtonExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F1F7D7428318EEE00AA30DB /* ButtonExample.swift */; }; + 2F9321B3282EE49E003DA929 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F9321B2282EE49E003DA929 /* AppDelegate.swift */; }; + 2F9321B5282EE49E003DA929 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F9321B4282EE49E003DA929 /* SceneDelegate.swift */; }; + 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 */; }; + 2F9321C7282EE4C1003DA929 /* PYLayout in Resources */ = {isa = PBXBuildFile; fileRef = 2F9321C6282EE4C1003DA929 /* PYLayout */; }; + 2F9321CA282EE4F2003DA929 /* PYLayout in Frameworks */ = {isa = PBXBuildFile; productRef = 2F9321C9282EE4F2003DA929 /* PYLayout */; }; + 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 */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 2F1F7D7028317E0700AA30DB /* CollectionCardExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionCardExample.swift; sourceTree = ""; }; + 2F1F7D7228318D9900AA30DB /* TextExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextExample.swift; sourceTree = ""; }; + 2F1F7D7428318EEE00AA30DB /* ButtonExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonExample.swift; sourceTree = ""; }; + 2F9321AF282EE49E003DA929 /* PYLayoutDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PYLayoutDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 2F9321B2282EE49E003DA929 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 2F9321B4282EE49E003DA929 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 2F9321B6282EE49E003DA929 /* MenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuView.swift; sourceTree = ""; }; + 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 = ""; }; + 2F9321C6282EE4C1003DA929 /* PYLayout */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = PYLayout; path = ..; 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 = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 2F9321AC282EE49E003DA929 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2F9321CA282EE4F2003DA929 /* PYLayout in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2F1F7D6F28317DE200AA30DB /* Examples */ = { + isa = PBXGroup; + children = ( + 2F1F7D7028317E0700AA30DB /* CollectionCardExample.swift */, + 2F1F7D7228318D9900AA30DB /* TextExample.swift */, + 2F1F7D7428318EEE00AA30DB /* ButtonExample.swift */, + 2FC004082831AC250037EF10 /* StoryExample.swift */, + 2FA986782837351B000DB409 /* GridExample.swift */, + 2FA9867A28373DD3000DB409 /* SnackbarExample.swift */, + ); + path = Examples; + sourceTree = ""; + }; + 2F9321A6282EE49E003DA929 = { + isa = PBXGroup; + children = ( + 2F9321C6282EE4C1003DA929 /* PYLayout */, + 2F9321B1282EE49E003DA929 /* PYLayoutDemo */, + 2F9321B0282EE49E003DA929 /* Products */, + 2F9321C8282EE4F2003DA929 /* Frameworks */, + ); + sourceTree = ""; + }; + 2F9321B0282EE49E003DA929 /* Products */ = { + isa = PBXGroup; + children = ( + 2F9321AF282EE49E003DA929 /* PYLayoutDemo.app */, + ); + name = Products; + sourceTree = ""; + }; + 2F9321B1282EE49E003DA929 /* PYLayoutDemo */ = { + isa = PBXGroup; + children = ( + 2F1F7D6F28317DE200AA30DB /* Examples */, + 2F9321B2282EE49E003DA929 /* AppDelegate.swift */, + 2F9321B4282EE49E003DA929 /* SceneDelegate.swift */, + 2F9321B6282EE49E003DA929 /* MenuView.swift */, + 2F9321BB282EE49E003DA929 /* Assets.xcassets */, + 2F9321BD282EE49E003DA929 /* LaunchScreen.storyboard */, + 2F9321C0282EE49E003DA929 /* Info.plist */, + ); + path = PYLayoutDemo; + sourceTree = ""; + }; + 2F9321C8282EE4F2003DA929 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 2F9321AE282EE49E003DA929 /* PYLayoutDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2F9321C3282EE49E003DA929 /* Build configuration list for PBXNativeTarget "PYLayoutDemo" */; + buildPhases = ( + 2F9321AB282EE49E003DA929 /* Sources */, + 2F9321AC282EE49E003DA929 /* Frameworks */, + 2F9321AD282EE49E003DA929 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PYLayoutDemo; + packageProductDependencies = ( + 2F9321C9282EE4F2003DA929 /* PYLayout */, + ); + productName = PYLayoutDemo; + productReference = 2F9321AF282EE49E003DA929 /* PYLayoutDemo.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 2F9321A7282EE49E003DA929 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1320; + LastUpgradeCheck = 1320; + TargetAttributes = { + 2F9321AE282EE49E003DA929 = { + CreatedOnToolsVersion = 13.2.1; + }; + }; + }; + buildConfigurationList = 2F9321AA282EE49E003DA929 /* Build configuration list for PBXProject "PYLayoutDemo" */; + compatibilityVersion = "Xcode 13.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 2F9321A6282EE49E003DA929; + packageReferences = ( + ); + productRefGroup = 2F9321B0282EE49E003DA929 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 2F9321AE282EE49E003DA929 /* PYLayoutDemo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 2F9321AD282EE49E003DA929 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2F9321BF282EE49E003DA929 /* LaunchScreen.storyboard in Resources */, + 2F9321BC282EE49E003DA929 /* Assets.xcassets in Resources */, + 2F9321C7282EE4C1003DA929 /* PYLayout in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 2F9321AB282EE49E003DA929 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2FC004092831AC250037EF10 /* StoryExample.swift in Sources */, + 2F1F7D7128317E0700AA30DB /* CollectionCardExample.swift in Sources */, + 2F1F7D7328318D9900AA30DB /* TextExample.swift in Sources */, + 2F9321B7282EE49E003DA929 /* MenuView.swift in Sources */, + 2F9321B3282EE49E003DA929 /* AppDelegate.swift in Sources */, + 2FA9867B28373DD3000DB409 /* SnackbarExample.swift in Sources */, + 2F1F7D7528318EEE00AA30DB /* ButtonExample.swift in Sources */, + 2FA986792837351B000DB409 /* GridExample.swift in Sources */, + 2F9321B5282EE49E003DA929 /* SceneDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 2F9321BD282EE49E003DA929 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 2F9321BE282EE49E003DA929 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 2F9321C1282EE49E003DA929 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.2; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 2F9321C2282EE49E003DA929 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.2; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 2F9321C4282EE49E003DA929 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 9TP4HMDZ7W; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = PYLayoutDemo/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = "Payan Layout"; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 14.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = juandahurt.PYLayoutDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Debug; + }; + 2F9321C5282EE49E003DA929 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 9TP4HMDZ7W; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = PYLayoutDemo/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = "Payan Layout"; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 14.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = juandahurt.PYLayoutDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 2F9321AA282EE49E003DA929 /* Build configuration list for PBXProject "PYLayoutDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2F9321C1282EE49E003DA929 /* Debug */, + 2F9321C2282EE49E003DA929 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2F9321C3282EE49E003DA929 /* Build configuration list for PBXNativeTarget "PYLayoutDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2F9321C4282EE49E003DA929 /* Debug */, + 2F9321C5282EE49E003DA929 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCSwiftPackageProductDependency section */ + 2F9321C9282EE4F2003DA929 /* PYLayout */ = { + isa = XCSwiftPackageProductDependency; + productName = PYLayout; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 2F9321A7282EE49E003DA929 /* Project object */; +} diff --git a/PYLayoutDemo/PYLayoutDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/PYLayoutDemo/PYLayoutDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/PYLayoutDemo/PYLayoutDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/PYLayoutDemo/PYLayoutDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/PYLayoutDemo/PYLayoutDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/PYLayoutDemo/PYLayoutDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/PYLayoutDemo/PYLayoutDemo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/PYLayoutDemo/PYLayoutDemo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..c53243f --- /dev/null +++ b/PYLayoutDemo/PYLayoutDemo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,16 @@ +{ + "object": { + "pins": [ + { + "package": "Kingfisher", + "repositoryURL": "https://github.com/onevcat/Kingfisher.git", + "state": { + "branch": null, + "revision": "59eb199fdb8dd47733624e8b0277822d0232579e", + "version": "7.2.2" + } + } + ] + }, + "version": 1 +} diff --git a/PYLayoutDemo/PYLayoutDemo/AppDelegate.swift b/PYLayoutDemo/PYLayoutDemo/AppDelegate.swift new file mode 100644 index 0000000..431ca82 --- /dev/null +++ b/PYLayoutDemo/PYLayoutDemo/AppDelegate.swift @@ -0,0 +1,37 @@ +// +// AppDelegate.swift +// PYLayoutDemo +// +// Created by Juan Hurtado on 13/05/22. +// + +import UIKit +import PYLayout + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + PYLayoutManager.shared.configure() + return true + } + + // MARK: UISceneSession Lifecycle + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } + + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they will not return. + } + + +} + diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AccentColor.colorset/Contents.json b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..28d9cc7 --- /dev/null +++ b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,158 @@ +{ + "images" : [ + { + "filename" : "notification-icon@2x.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "filename" : "notification-icon@3x.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "filename" : "icon-small.png", + "idiom" : "iphone", + "scale" : "1x", + "size" : "29x29" + }, + { + "filename" : "icon-small@2x.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "icon-small@3x.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "filename" : "icon-40@2x.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "filename" : "icon-40@3x.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "filename" : "icon.png", + "idiom" : "iphone", + "scale" : "1x", + "size" : "57x57" + }, + { + "filename" : "icon@2x.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "57x57" + }, + { + "filename" : "icon-60@2x.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "filename" : "icon-60@3x.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "filename" : "notification-icon~ipad.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "filename" : "notification-icon~ipad@2x.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "filename" : "icon-small.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "filename" : "icon-small@2x.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "icon-40.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "filename" : "icon-40@2x.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "filename" : "icon-small-50.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "50x50" + }, + { + "filename" : "icon-small-50@2x.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "50x50" + }, + { + "filename" : "icon-72.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "72x72" + }, + { + "filename" : "icon-72@2x.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "72x72" + }, + { + "filename" : "icon-76.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "filename" : "icon-76@2x.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "filename" : "icon-83.5@2x.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "filename" : "ios-marketing.png", + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-40.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-40.png new file mode 100644 index 0000000..cd79379 Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-40.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png new file mode 100644 index 0000000..ea0eec0 Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png new file mode 100644 index 0000000..df52622 Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png new file mode 100644 index 0000000..df52622 Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png new file mode 100644 index 0000000..5341396 Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-72.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-72.png new file mode 100644 index 0000000..ae30e9c Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-72.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png new file mode 100644 index 0000000..e733a90 Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-76.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-76.png new file mode 100644 index 0000000..fc60a38 Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-76.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png new file mode 100644 index 0000000..c5017fd Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png new file mode 100644 index 0000000..e2ba4a6 Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-small-50.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-small-50.png new file mode 100644 index 0000000..b7a4a8a Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-small-50.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-small-50@2x.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-small-50@2x.png new file mode 100644 index 0000000..8815771 Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-small-50@2x.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-small.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-small.png new file mode 100644 index 0000000..50a4b73 Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-small.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-small@2x.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-small@2x.png new file mode 100644 index 0000000..628b5fd Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-small@2x.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-small@3x.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-small@3x.png new file mode 100644 index 0000000..513fc15 Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon-small@3x.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon.png new file mode 100644 index 0000000..8cdd884 Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon@2x.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon@2x.png new file mode 100644 index 0000000..9f92ddb Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/icon@2x.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/ios-marketing.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/ios-marketing.png new file mode 100644 index 0000000..94b45bb Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/ios-marketing.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/notification-icon@2x.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/notification-icon@2x.png new file mode 100644 index 0000000..cd79379 Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/notification-icon@2x.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/notification-icon@3x.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/notification-icon@3x.png new file mode 100644 index 0000000..56ec212 Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/notification-icon@3x.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/notification-icon~ipad.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/notification-icon~ipad.png new file mode 100644 index 0000000..224788d Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/notification-icon~ipad.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/notification-icon~ipad@2x.png b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/notification-icon~ipad@2x.png new file mode 100644 index 0000000..cd79379 Binary files /dev/null and b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/AppIcon.appiconset/notification-icon~ipad@2x.png differ diff --git a/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/Contents.json b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/PYLayoutDemo/PYLayoutDemo/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/PYLayoutDemo/PYLayoutDemo/Base.lproj/LaunchScreen.storyboard b/PYLayoutDemo/PYLayoutDemo/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..865e932 --- /dev/null +++ b/PYLayoutDemo/PYLayoutDemo/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PYLayoutDemo/PYLayoutDemo/Examples/ButtonExample.swift b/PYLayoutDemo/PYLayoutDemo/Examples/ButtonExample.swift new file mode 100644 index 0000000..d1b6efa --- /dev/null +++ b/PYLayoutDemo/PYLayoutDemo/Examples/ButtonExample.swift @@ -0,0 +1,26 @@ +// +// ButtonExample.swift +// PYLayoutDemo +// +// Created by Juan Hurtado on 15/05/22. +// + +import Foundation +import SwiftUI +import PYLayout + +struct ButtonExample: View { + var body: some View { + Text("`PYButtonView('title', type: .loud)`") + PYButtonView("Font size: 12", fontSize: 12) + PYButtonView("Font size: 14", fontSize: 14) + PYButtonView("Font size: 16", fontSize: 16) + .padding(.bottom) + + Text("`PYButtonView('title', type: .quiet)`") + PYButtonView("Font size: 12", fontSize: 12, type: .quiet) + PYButtonView("Font size: 14", fontSize: 14, type: .quiet) + PYButtonView("Font size: 16", fontSize: 16, type: .quiet) + Spacer() + } +} diff --git a/PYLayoutDemo/PYLayoutDemo/Examples/CollectionCardExample.swift b/PYLayoutDemo/PYLayoutDemo/Examples/CollectionCardExample.swift new file mode 100644 index 0000000..c5425ad --- /dev/null +++ b/PYLayoutDemo/PYLayoutDemo/Examples/CollectionCardExample.swift @@ -0,0 +1,33 @@ +// +// CollectionCardExample.swift +// PYLayoutDemo +// +// Created by Juan Hurtado on 15/05/22. +// + +import Foundation +import PYLayout +import SwiftUI + +struct CollectionCardExample: View { + var body: some View { + Text("`PYCollectionCardView(cards: ...)`") + .padding() + PYCollectionCardView(cards: [ + MockCard("https://www.biografiasyvidas.com/biografia/c/fotos/caldas_francisco_jose_2.jpg"), + MockCard("https://upload.wikimedia.org/wikipedia/commons/a/ac/Froil%C3%A1n_Largacha_Hurtado.jpg"), + MockCard("https://upload.wikimedia.org/wikipedia/commons/8/86/Camilo_Torres_y_Tenorio.jpg") + ]) + Spacer() + } +} + +struct MockCard: PYCollectionCardData { + var deepLink: String = "" + var backgroundImage: URL? + var title: String = "Froilán Largacha Hurtado" + + init(_ url: String) { + self.backgroundImage = URL(string: url) + } +} diff --git a/PYLayoutDemo/PYLayoutDemo/Examples/GridExample.swift b/PYLayoutDemo/PYLayoutDemo/Examples/GridExample.swift new file mode 100644 index 0000000..57a05ff --- /dev/null +++ b/PYLayoutDemo/PYLayoutDemo/Examples/GridExample.swift @@ -0,0 +1,33 @@ +// +// GridExample.swift +// PYLayoutDemo +// +// Created by Juan Hurtado on 19/05/22. +// + +import Kingfisher +import Foundation +import SwiftUI +import PYLayout + +struct GridExample: View { + var body: some View { + Text("`PYVerticalGridView(...)`") + .padding() + PYVerticalGridView(columns: 2, spacing: 1) { + KFImage(URL(string: "https://www.biografiasyvidas.com/biografia/c/fotos/caldas_francisco_jose_2.jpg")) + .resizable() + .frame(height: 200) + KFImage(URL(string: "https://www.biografiasyvidas.com/biografia/c/fotos/caldas_francisco_jose_2.jpg")) + .resizable() + .frame(height: 200) + KFImage(URL(string: "https://www.biografiasyvidas.com/biografia/c/fotos/caldas_francisco_jose_2.jpg")) + .resizable() + .frame(height: 200) + KFImage(URL(string: "https://www.biografiasyvidas.com/biografia/c/fotos/caldas_francisco_jose_2.jpg")) + .resizable() + .frame(height: 200) + } + Spacer() + } +} diff --git a/PYLayoutDemo/PYLayoutDemo/Examples/SnackbarExample.swift b/PYLayoutDemo/PYLayoutDemo/Examples/SnackbarExample.swift new file mode 100644 index 0000000..746f04a --- /dev/null +++ b/PYLayoutDemo/PYLayoutDemo/Examples/SnackbarExample.swift @@ -0,0 +1,29 @@ +// +// SnackbarExample.swift +// PYLayoutDemo +// +// Created by Juan Hurtado on 19/05/22. +// + +import Foundation +import SwiftUI +import PYLayout + +struct SnackBarExample: View { + @State var showSnackbar = false + + var body: some View { + Text("`PYSnackbarView(title: ...)`") + .padding() + PYButtonView(!showSnackbar ? "Mostrar snackbar" : "Ocultar snackbar", fontSize: 14) { + showSnackbar = !showSnackbar + } + Spacer() + PYSnackbarView( + title: "Hay una actualización disponible", + type: .alert, + isVisible: $showSnackbar, + buttonTitle: "ACTUALIZAR" + ) + } +} diff --git a/PYLayoutDemo/PYLayoutDemo/Examples/StoryExample.swift b/PYLayoutDemo/PYLayoutDemo/Examples/StoryExample.swift new file mode 100644 index 0000000..8f08fad --- /dev/null +++ b/PYLayoutDemo/PYLayoutDemo/Examples/StoryExample.swift @@ -0,0 +1,41 @@ +// +// StoryExample.swift +// PYLayoutDemo +// +// Created by Juan Hurtado on 15/05/22. +// + +import Foundation +import SwiftUI +import PYLayout + +struct StoryExample: View { + var body: some View { + Text("`PYStoryView(stories: [...])`") + .padding() + PYStoryView(stories: [ + MockStory( + image: URL(string: "https://elturismoencolombia.com/wp-content/uploads/2018/06/popayan_iglesia_santo_domingo_colombia_travel.jpg"), + title: "First title", + subtitle: "La Universidad del Cauca es una universidad pública de Colombia, sujeta a inspección y vigilancia por medio de la Ley 1740 de 2014 y la ley 30 de 1992 del Ministerio de Educación de Colombia. Su campus principal se encuentra ubicado en la ciudad de Popayán, " + ), + MockStory( + image: URL(string: "https://media-cdn.tripadvisor.com/media/photo-m/1280/14/3f/03/e8/vista-diurna-de-la-ermita.jpg"), + title: "Second title", + subtitle: "skdjh asDSd Cauca es una universidad pública de Colombia, sujeta a inspección y vigsdljlkjljsd" + ), + MockStory( + image: URL(string: "https://www.cronicadelquindio.com/files/noticias/20100220064229.jpg"), + title: "Third title", + subtitle: "La Ajliyh dlkjsouoy ojsf del Cauca es una universidad pública de Colombia, sujeta a inspección y vigilancia por medio de la Ley 174Sholj ljlih osdfyán, " + ) + ]) + Spacer() + } +} + +struct MockStory: PYStoryData { + var image: URL? + var title: String + var subtitle: String +} diff --git a/PYLayoutDemo/PYLayoutDemo/Examples/TextExample.swift b/PYLayoutDemo/PYLayoutDemo/Examples/TextExample.swift new file mode 100644 index 0000000..f10ba37 --- /dev/null +++ b/PYLayoutDemo/PYLayoutDemo/Examples/TextExample.swift @@ -0,0 +1,25 @@ +// +// TextExample.swift +// PYLayoutDemo +// +// Created by Juan Hurtado on 15/05/22. +// + +import Foundation +import SwiftUI +import PYLayout + +struct TextExample: View { + var body: some View { + Text("`PYTextView('text')`") + .padding() + PYTextView("Size: 12", fontSize: 12) + PYTextView("Size: 14", fontSize: 14) + PYTextView("Size: 16", fontSize: 16) + PYTextView("Size: 18", fontSize: 18) + PYTextView("Size: 20", fontSize: 20) + Text("*note: the color is static*") + .padding() + Spacer() + } +} diff --git a/PYLayoutDemo/PYLayoutDemo/Info.plist b/PYLayoutDemo/PYLayoutDemo/Info.plist new file mode 100644 index 0000000..0eb786d --- /dev/null +++ b/PYLayoutDemo/PYLayoutDemo/Info.plist @@ -0,0 +1,23 @@ + + + + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + + + + + + diff --git a/PYLayoutDemo/PYLayoutDemo/MenuView.swift b/PYLayoutDemo/PYLayoutDemo/MenuView.swift new file mode 100644 index 0000000..422f902 --- /dev/null +++ b/PYLayoutDemo/PYLayoutDemo/MenuView.swift @@ -0,0 +1,42 @@ +// +// MenuView.swift +// PYLayoutDemo +// +// Created by Juan Hurtado on 13/05/22. +// + +import PYLayout +import SwiftUI +import UIKit + +struct MenuView: View { + var body: some View { + NavigationView { + List { + Section(header: Text("Basic")) { + NavigationLink("Text") { + TextExample() + } + NavigationLink("Button") { + ButtonExample() + } + NavigationLink("Snackbar") { + SnackBarExample() + } + } + Section(header: Text("Complex")) { + NavigationLink("Collection card") { + CollectionCardExample() + } + NavigationLink("Story") { + StoryExample() + } + NavigationLink("Grid") { + GridExample() + } + } + } + .navigationTitle("Payan Layout") + } + } +} diff --git a/PYLayoutDemo/PYLayoutDemo/SceneDelegate.swift b/PYLayoutDemo/PYLayoutDemo/SceneDelegate.swift new file mode 100644 index 0000000..a6fd396 --- /dev/null +++ b/PYLayoutDemo/PYLayoutDemo/SceneDelegate.swift @@ -0,0 +1,59 @@ +// +// SceneDelegate.swift +// PYLayoutDemo +// +// Created by Juan Hurtado on 13/05/22. +// + +import UIKit +import SwiftUI + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + guard let windowScene = (scene as? UIWindowScene) else { return } + window = UIWindow(frame: windowScene.coordinateSpace.bounds) + window?.windowScene = windowScene + + let navigationController = UINavigationController() + window?.rootViewController = navigationController + let vc = UIHostingController(rootView: MenuView()) + navigationController.pushViewController(vc, animated: false) + + window?.makeKeyAndVisible() + } + + func sceneDidDisconnect(_ scene: UIScene) { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). + } + + func sceneDidBecomeActive(_ scene: UIScene) { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + } + + func sceneWillResignActive(_ scene: UIScene) { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + } + + func sceneWillEnterForeground(_ scene: UIScene) { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + } + + func sceneDidEnterBackground(_ scene: UIScene) { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. + } + + +} + diff --git a/Package.swift b/Package.swift index abb1312..1921d09 100644 --- a/Package.swift +++ b/Package.swift @@ -1,26 +1,29 @@ // swift-tools-version:5.5 -// The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription let package = Package( name: "PYLayout", + platforms: [ + .iOS(.v14) + ], products: [ - // Products define the executables and libraries a package produces, and make them visible to other packages. .library( name: "PYLayout", targets: ["PYLayout"]), ], dependencies: [ - // Dependencies declare other packages that this package depends on. - // .package(url: /* package url */, from: "1.0.0"), + .package(url: "https://github.com/onevcat/Kingfisher.git", .upToNextMinor(from: "7.2.0")), ], targets: [ - // Targets are the basic building blocks of a package. A target can define a module or a test suite. - // Targets can depend on other targets in this package, and on products in packages this package depends on. .target( name: "PYLayout", - dependencies: []), + dependencies: ["Kingfisher"], + resources: [ + .copy("Resources/Fonts/Poppins/Poppins-Regular.ttf"), + .copy("Resources/Fonts/Poppins/Poppins-Medium.ttf"), + .copy("Resources/Fonts/Poppins/Poppins-SemiBold.ttf") + ]), .testTarget( name: "PYLayoutTests", dependencies: ["PYLayout"]), diff --git a/Sources/PYLayout/Common/Extensions/Color+Hex.swift b/Sources/PYLayout/Common/Extensions/Color+Hex.swift new file mode 100644 index 0000000..4f43862 --- /dev/null +++ b/Sources/PYLayout/Common/Extensions/Color+Hex.swift @@ -0,0 +1,48 @@ +// +// Color+Hex.swift +// +// +// Created by Juan Hurtado on 16/05/22. +// + +import Foundation +import SwiftUI + +extension Color { + /// Creates a color from a hexsadecimal string representation. + init?(_ hex: String) { + var str = hex + if str.hasPrefix("#") { + str.removeFirst() + } + if str.count == 3 { + str = String(repeating: str[str.startIndex], count: 2) + + String(repeating: str[str.index(str.startIndex, offsetBy: 1)], count: 2) + + String(repeating: str[str.index(str.startIndex, offsetBy: 2)], count: 2) + } else if !str.count.isMultiple(of: 2) || str.count > 8 { + return nil + } + guard let color = UInt64(str, radix: 16) else { return nil } + if str.count == 2 { + let gray = Double(Int(color) & 0xFF) / 255 + self.init(.sRGB, red: gray, green: gray, blue: gray, opacity: 1) + } else if str.count == 4 { + let gray = Double(Int(color >> 8) & 0x00FF) / 255 + let alpha = Double(Int(color) & 0x00FF) / 255 + self.init(.sRGB, red: gray, green: gray, blue: gray, opacity: alpha) + } else if str.count == 6 { + let red = Double(Int(color >> 16) & 0x0000FF) / 255 + let green = Double(Int(color >> 8) & 0x0000FF) / 255 + let blue = Double(Int(color) & 0x0000FF) / 255 + self.init(.sRGB, red: red, green: green, blue: blue, opacity: 1) + } else if str.count == 8 { + let red = Double(Int(color >> 24) & 0x000000FF) / 255 + let green = Double(Int(color >> 16) & 0x000000FF) / 255 + let blue = Double(Int(color >> 8) & 0x000000FF) / 255 + let alpha = Double(Int(color) & 0x000000FF) / 255 + self.init(.sRGB, red: red, green: green, blue: blue, opacity: alpha) + } else { + return nil + } + } +} diff --git a/Sources/PYLayout/Common/PYLayoutManager.swift b/Sources/PYLayout/Common/PYLayoutManager.swift new file mode 100644 index 0000000..e5ad021 --- /dev/null +++ b/Sources/PYLayout/Common/PYLayoutManager.swift @@ -0,0 +1,53 @@ +// +// PYLayoutManager.swift +// +// +// Created by Juan Hurtado on 14/05/22. +// + +import UIKit +import Foundation + +public struct PYLayoutManager { + public static let shared = PYLayoutManager() + + private init() {} + + public func configure() { + registerFonts() + } +} + +extension PYLayoutManager { + private func registerFonts() { + let fonts = [ + PYResource(name: "Poppins-Regular", fileExtension: "ttf"), + PYResource(name: "Poppins-Medium", fileExtension: "ttf"), + PYResource(name: "Poppins-SemiBold", fileExtension: "ttf") + ] + fonts.forEach({ try? registerFont(from: $0.url)}) + } + + private func registerFont(from url: URL?) throws { + guard let url = url else { + throw FontRegisteringError.noFontFound + } + guard let fontDataProvider = CGDataProvider(url: url as CFURL) else { + throw FontRegisteringError.noFontDataProvider + } + guard let font = CGFont(fontDataProvider) else { + throw FontRegisteringError.noFontFromFontDataProvider + } + var error: Unmanaged? + guard CTFontManagerRegisterGraphicsFont(font, &error) else { + throw FontRegisteringError.errorInRegisteringFont(font: font, error: error!.takeRetainedValue()) + } + } +} + +enum FontRegisteringError: Error { + case noFontFound + case noFontDataProvider + case noFontFromFontDataProvider + case errorInRegisteringFont(font: CGFont, error: CFError) +} diff --git a/Sources/PYLayout/Common/PYResource.swift b/Sources/PYLayout/Common/PYResource.swift new file mode 100644 index 0000000..02d97a4 --- /dev/null +++ b/Sources/PYLayout/Common/PYResource.swift @@ -0,0 +1,16 @@ +// +// PYResource.swift +// +// +// Created by Juan Hurtado on 14/05/22. +// + +import Foundation + +struct PYResource { + var name: String + var fileExtension: String + var url: URL? { + Bundle.module.url(forResource: name, withExtension: fileExtension) + } +} diff --git a/Sources/PYLayout/Common/Protocols/PYView.swift b/Sources/PYLayout/Common/Protocols/PYView.swift new file mode 100644 index 0000000..73de1cd --- /dev/null +++ b/Sources/PYLayout/Common/Protocols/PYView.swift @@ -0,0 +1,14 @@ +// +// PYView.swift +// +// +// Created by Juan Hurtado on 16/05/22. +// + +import Foundation + +/// Defines a Payan view +protocol PYView { + /// Used by the view factory to know which view must be build. + static var identifier: String { get } +} diff --git a/Sources/PYLayout/PYLayout.swift b/Sources/PYLayout/PYLayout.swift deleted file mode 100644 index ed3d0ff..0000000 --- a/Sources/PYLayout/PYLayout.swift +++ /dev/null @@ -1,6 +0,0 @@ -public struct PYLayout { - public private(set) var text = "Hello, World!" - - public init() { - } -} diff --git a/Sources/PYLayout/Resources/Fonts/Poppins/Poppins-Medium.ttf b/Sources/PYLayout/Resources/Fonts/Poppins/Poppins-Medium.ttf new file mode 100644 index 0000000..6bcdcc2 Binary files /dev/null and b/Sources/PYLayout/Resources/Fonts/Poppins/Poppins-Medium.ttf differ diff --git a/Sources/PYLayout/Resources/Fonts/Poppins/Poppins-Regular.ttf b/Sources/PYLayout/Resources/Fonts/Poppins/Poppins-Regular.ttf new file mode 100644 index 0000000..9f0c71b Binary files /dev/null and b/Sources/PYLayout/Resources/Fonts/Poppins/Poppins-Regular.ttf differ diff --git a/Sources/PYLayout/Resources/Fonts/Poppins/Poppins-SemiBold.ttf b/Sources/PYLayout/Resources/Fonts/Poppins/Poppins-SemiBold.ttf new file mode 100644 index 0000000..74c726e Binary files /dev/null and b/Sources/PYLayout/Resources/Fonts/Poppins/Poppins-SemiBold.ttf differ diff --git a/Sources/PYLayout/Views/Basic/Button/PYButtonType.swift b/Sources/PYLayout/Views/Basic/Button/PYButtonType.swift new file mode 100644 index 0000000..4d68dfe --- /dev/null +++ b/Sources/PYLayout/Views/Basic/Button/PYButtonType.swift @@ -0,0 +1,13 @@ +// +// PYButtonType.swift +// +// +// Created by Juan Hurtado on 14/05/22. +// + +import Foundation +import SwiftUI + +public enum PYButtonType { + case loud, quiet, custom(Color, Color, Color) // 0: background, 1: on pressed, 2: text color +} diff --git a/Sources/PYLayout/Views/Basic/Button/PYButtonView.swift b/Sources/PYLayout/Views/Basic/Button/PYButtonView.swift new file mode 100644 index 0000000..cf1c055 --- /dev/null +++ b/Sources/PYLayout/Views/Basic/Button/PYButtonView.swift @@ -0,0 +1,87 @@ +// +// PYButtonView.swift +// +// +// Created by Juan Hurtado on 14/05/22. +// + +import Foundation +import SwiftUI + +public struct PYButtonView: View { + @State var backgroundColor: Color = .blue + @State var isBeingPressed = false + + let title: String + let fontSize: Int + let type: PYButtonType + let onTap: (() -> Void)? + + public init(_ title: String, fontSize: Int = 12, type: PYButtonType = .loud, onTap: (() -> Void)? = nil) { + self.title = title + self.fontSize = fontSize + self.type = type + self.onTap = onTap + } + + private func getTextColor() -> Color { + switch type { + case .loud: + return .white + case .quiet: + return .init(.sRGB, red: 89/255, green: 136/255, blue: 219/255, opacity: 1) + case .custom(_, _, let textColor): + return textColor + } + } + + private func getBackgroundColor() -> Color { + switch type { + case .loud: + return .init(.sRGB, red: 100/255, green: 145/255, blue: 223/255, opacity: 1) + case .quiet: + return .init(.sRGB, red: 232/255, green: 240/255, blue: 255/255, opacity: 1) + case .custom(let backgroundColor, _, _): + return backgroundColor + } + } + + private func getOnPressedBackgroundColor() -> Color { + switch type { + case .loud: + return .init(.sRGB, red: 89/255, green: 136/255, blue: 219/255, opacity: 1) + case .quiet: + return .init(.sRGB, red: 167/255, green: 195/255, blue: 246/255, opacity: 1) + case .custom(_, let onPressedColor, _): + return onPressedColor + } + } + + public var body: some View { + PYTextView(title, fontSize: fontSize, textColor: getTextColor(), weight: .medium) + .onTapGesture { + onTap?() + } + .simultaneousGesture( + DragGesture(minimumDistance: 0) + .onChanged({ _ in + withAnimation(.easeIn(duration: 0.1)) { + isBeingPressed = true + } + }) + .onEnded({ _ in + isBeingPressed = false + }) + ) + .padding(.horizontal) + .padding(.vertical, 5) + .background(isBeingPressed ? getOnPressedBackgroundColor() : getBackgroundColor()) + .cornerRadius(4) + } +} + +extension PYButtonView: PYView { + static var identifier: String { + "btn" + } +} diff --git a/Sources/PYLayout/Views/Basic/Snackbar/PYSnackbarType.swift b/Sources/PYLayout/Views/Basic/Snackbar/PYSnackbarType.swift new file mode 100644 index 0000000..32622c8 --- /dev/null +++ b/Sources/PYLayout/Views/Basic/Snackbar/PYSnackbarType.swift @@ -0,0 +1,12 @@ +// +// PYSnackbarType.swift +// +// +// Created by Juan Hurtado on 20/05/22. +// + +import Foundation + +public enum PYSnackbarType { + case info, alert +} diff --git a/Sources/PYLayout/Views/Basic/Snackbar/PYSnackbarView.swift b/Sources/PYLayout/Views/Basic/Snackbar/PYSnackbarView.swift new file mode 100644 index 0000000..9ac63f3 --- /dev/null +++ b/Sources/PYLayout/Views/Basic/Snackbar/PYSnackbarView.swift @@ -0,0 +1,62 @@ +// +// PYSnackbarView.swift +// +// +// Created by Juan Hurtado on 19/05/22. +// + +import Foundation +import SwiftUI + +public struct PYSnackbarView: View { + @State var yOffset: CGFloat = 100 + @State var opacity: Double = 0 + + let title: String + let type: PYSnackbarType + @Binding var isVisible: Bool + let buttonTitle: String? + let buttonOnTap: (() -> Void)? + + public init(title: String, type: PYSnackbarType = .info, isVisible: Binding, buttonTitle: String? = nil, buttonOnTap: (() -> Void)? = nil) { + self.title = title + self.type = type + self._isVisible = isVisible + self.buttonTitle = buttonTitle + self.buttonOnTap = buttonOnTap + } + + private func getBackgroundColor() -> Color { + switch type { + case .info: + return .gray + case .alert: + return .blue + } + } + + public var body: some View { + HStack { + PYTextView(title, fontSize: 14, textColor: .white) + Spacer() + if let buttonTitle = buttonTitle { + PYButtonView(buttonTitle, fontSize: 14, type: .custom(.clear, .clear, .white)) { + buttonOnTap?() + } + } + } + .lineLimit(2) + .padding() + .frame(width: UIScreen.main.bounds.width - 40) + .background(getBackgroundColor()) + .cornerRadius(5) + .onChange(of: isVisible, perform: { isPresented in + withAnimation(.spring()) { + yOffset = isPresented ? 0 : 100 + opacity = isPresented ? 1 : 0 + } + }) + .opacity(opacity) + .offset(x: 0, y: yOffset) + } +} diff --git a/Sources/PYLayout/Views/Basic/Text/PYTextView.swift b/Sources/PYLayout/Views/Basic/Text/PYTextView.swift new file mode 100644 index 0000000..7f57402 --- /dev/null +++ b/Sources/PYLayout/Views/Basic/Text/PYTextView.swift @@ -0,0 +1,47 @@ +// +// PYTextView.swift +// +// +// Created by Juan Hurtado on 13/05/22. +// + +import SwiftUI + +public struct PYTextView: View { + let content: String + let fontSize: Int + let textColor: Color + let weight: PYTextWeight + + public init(_ content: String, fontSize: Int = 12, textColor: Color = .black, weight: PYTextWeight = .regular) { + self.content = content + self.fontSize = fontSize + self.textColor = textColor + self.weight = weight + } + + private func getFont() -> Font { + var fontName = "Poppins-" + switch weight { + case .regular: + fontName += "Regular" + case .medium: + fontName += "Medium" + case .semibold: + fontName += "SemiBold" + } + return .custom(fontName, size: CGFloat(fontSize)) + } + + public var body: some View { + Text(content) + .font(getFont()) + .foregroundColor(textColor) + } +} + +extension PYTextView: PYView { + static var identifier: String { + "txt" + } +} diff --git a/Sources/PYLayout/Views/Basic/Text/PYTextWeight.swift b/Sources/PYLayout/Views/Basic/Text/PYTextWeight.swift new file mode 100644 index 0000000..14e012e --- /dev/null +++ b/Sources/PYLayout/Views/Basic/Text/PYTextWeight.swift @@ -0,0 +1,14 @@ +// +// PYTextWeight.swift +// +// +// Created by Juan Hurtado on 14/05/22. +// + +import Foundation + +public enum PYTextWeight: String { + case regular = "regular" + case medium = "medium" + case semibold = "semibold" +} diff --git a/Sources/PYLayout/Views/Complex/Collection Card/PYCollectionCardData.swift b/Sources/PYLayout/Views/Complex/Collection Card/PYCollectionCardData.swift new file mode 100644 index 0000000..db600aa --- /dev/null +++ b/Sources/PYLayout/Views/Complex/Collection Card/PYCollectionCardData.swift @@ -0,0 +1,18 @@ +// +// PYCollectionCardData.swift +// +// +// Created by Juan Hurtado on 14/05/22. +// + +import Foundation + +/// Defines the data that a collection card can show. +public protocol PYCollectionCardData { + /// Card's deep link + var deepLink: String { get } + /// Card's backgrond image + var backgroundImage: URL? { get } + /// Card's title + var title: String { get } +} diff --git a/Sources/PYLayout/Views/Complex/Collection Card/PYCollectionCardHandler.swift b/Sources/PYLayout/Views/Complex/Collection Card/PYCollectionCardHandler.swift new file mode 100644 index 0000000..49c9340 --- /dev/null +++ b/Sources/PYLayout/Views/Complex/Collection Card/PYCollectionCardHandler.swift @@ -0,0 +1,14 @@ +// +// PYCollectionCardHandler.swift +// +// +// Created by Juan Hurtado on 18/05/22. +// + +import Foundation + +/// Defines the `PYCollectionCardView` interaction logic +public protocol PYCollectionCardHandler { + /// It gets called when a user taps on a certain card. + func didSelectCard(_ card: PYCollectionCardData) +} diff --git a/Sources/PYLayout/Views/Complex/Collection Card/PYCollectionCardView.swift b/Sources/PYLayout/Views/Complex/Collection Card/PYCollectionCardView.swift new file mode 100644 index 0000000..bd0a435 --- /dev/null +++ b/Sources/PYLayout/Views/Complex/Collection Card/PYCollectionCardView.swift @@ -0,0 +1,124 @@ +// +// PYCollectionCardView.swift +// +// +// Created by Juan Hurtado on 13/05/22. +// + +import Kingfisher +import SwiftUI + +public struct PYCollectionCardView: View { + @State var image = UIImage() + @State var dragOffset: CGSize = .zero + @State var dragOpacity: Double = 1 + + private let firstCardSize = CGSize(width: 220, height: 300) + + @State var cards: [PYCollectionCardData] + let numberOfCards: Int + + public init(cards: [PYCollectionCardData]) { + self.cards = cards + self.numberOfCards = cards.count + } + + func next() { + let card = cards.popLast()! + cards.insert(card, at: 0) + } + + func getSize(at index: Int) -> CGSize { + guard index != numberOfCards - 1 else { + return firstCardSize + } + return CGSize( + width: firstCardSize.width - CGFloat(numberOfCards - index) * 10, + height: firstCardSize.height - CGFloat(numberOfCards - index) * 10 + ) + } + + func getShadowOpacity(forViewAt index: Int) -> Double { + guard index != numberOfCards - 1 else { + return 0 + } + guard index != numberOfCards - 2 else { + if dragOpacity > 1.0 - 1.0 / Double(numberOfCards - index) { + return 1.0 - 1.0 / Double(numberOfCards - index) + } else { + return dragOpacity + } + } + return 1.0 - 1.0 / Double(numberOfCards - index) + } + + func card(at index: Int) -> some View { + Group { + if cards.isEmpty { + EmptyView() + + } else { + ZStack(alignment: .center) { + KFImage.url(cards[index].backgroundImage) + .resizable() + .frame(width: getSize(at: index).width, height: getSize(at: index).height) + .aspectRatio(contentMode: .fill) + LinearGradient(gradient: Gradient(colors: [.clear, .black.opacity(0.35)]), startPoint: .top, endPoint: .center) + VStack(alignment: .leading) { + Spacer() + HStack { + PYTextView(cards[index].title, fontSize: 12, textColor: .white, weight: .medium) + Spacer(minLength: 0) + } + }.padding() + Color.white.opacity(getShadowOpacity(forViewAt: index)) + } + .frame(width: getSize(at: index).width, height: getSize(at: index).height) + .cornerRadius(5) + .opacity(index == cards.count - 1 ? dragOpacity : 1) + .offset(x: CGFloat(index == numberOfCards - 1 ? 0 : (numberOfCards - index) * 10) , y: 0) + .offset(x: index == numberOfCards - 1 ? dragOffset.width : .zero, y: .zero) + .onTapGesture { + if index == numberOfCards - 1 { + // user can only touch the top card! + + } + } + .simultaneousGesture( + DragGesture(minimumDistance: 0, coordinateSpace: .global) + .onChanged({ value in + if value.translation.width < 0 && index == numberOfCards - 1 { + dragOffset = value.translation + dragOpacity = (-1/value.translation.width) * 20 + } else if value.translation.width >= 0 { + dragOpacity = 1 + } + }) + .onEnded({ value in + if dragOpacity < 0.4 { + next() + } + dragOpacity = 1 + dragOffset = .zero + }) + ) + } + } + } + + public var body: some View { + HStack(alignment: .center) { + ZStack(alignment: .trailing) { + ForEach(0.. 0 else { return } + currentIndex -= 1 + } + + public var body: some View { + ZStack { + KFImage.url(stories[currentIndex].image) + .placeholder({ _ in + ProgressView() + }) + .resizable() + LinearGradient(gradient: Gradient(colors: [.clear, .black.opacity(0.35)]), startPoint: .top, endPoint: .center) + VStack { + Spacer() + HStack { + PYTextView(stories[currentIndex].title, fontSize: 16, textColor: .white, weight: .medium) + Spacer() + } + HStack { + PYTextView(stories[currentIndex].subtitle, fontSize: 12, textColor: .white) + Spacer() + } + }.padding() + VStack { + indicators + Spacer() + } + .padding(5) + GeometryReader { geometry in + HStack { + Color.gray + .opacity(0.001) + .frame(width: geometry.size.width * 0.4) + .onTapGesture { + back() + } + Spacer() + Color.gray // When opacity = 0 or the color is `clear`, tap gesture doesn't work :c + .opacity(0.001) + .frame(width: geometry.size.width * 0.4) + .onTapGesture { + next() + } + } + + } + }.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height * 0.33) + + } +} diff --git a/Sources/PYLayout/Views/Complex/Vertical Grid/PYVerticalGridView.swift b/Sources/PYLayout/Views/Complex/Vertical Grid/PYVerticalGridView.swift new file mode 100644 index 0000000..a55e5f7 --- /dev/null +++ b/Sources/PYLayout/Views/Complex/Vertical Grid/PYVerticalGridView.swift @@ -0,0 +1,30 @@ +// +// PYVerticalGridView.swift +// +// +// Created by Juan Hurtado on 19/05/22. +// + +import Foundation +import SwiftUI + +public struct PYVerticalGridView: View { + private let gridItems: [GridItem] + + let content: Content + let columns: Int + let spacing: Double + + public init(columns: Int, spacing: Double = 10, @ViewBuilder _ content: () -> Content) { + self.content = content() + self.columns = columns + self.spacing = spacing + self.gridItems = [GridItem](repeating: GridItem(spacing: spacing), count: columns) + } + + public var body: some View { + LazyVGrid(columns: gridItems, spacing: spacing) { + content + } + } +} diff --git a/Tests/PYLayoutTests/PYLayoutTests.swift b/Tests/PYLayoutTests/PYLayoutTests.swift index 8f0cbb9..2028530 100644 --- a/Tests/PYLayoutTests/PYLayoutTests.swift +++ b/Tests/PYLayoutTests/PYLayoutTests.swift @@ -6,6 +6,6 @@ final class PYLayoutTests: XCTestCase { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct // results. - XCTAssertEqual(PYLayout().text, "Hello, World!") +// XCTAssertEqual(PYLayout().text, "Hello, World!") } }