diff --git a/Layers.xcodeproj/project.pbxproj b/Layers.xcodeproj/project.pbxproj new file mode 100644 index 0000000..bb46185 --- /dev/null +++ b/Layers.xcodeproj/project.pbxproj @@ -0,0 +1,421 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + 111150222AC8CCDF00C0D356 /* LayersApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111150212AC8CCDF00C0D356 /* LayersApp.swift */; }; + 111150242AC8CCDF00C0D356 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111150232AC8CCDF00C0D356 /* ContentView.swift */; }; + 111150262AC8CCE100C0D356 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 111150252AC8CCE100C0D356 /* Assets.xcassets */; }; + 111150292AC8CCE100C0D356 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 111150282AC8CCE100C0D356 /* Preview Assets.xcassets */; }; + 111150412AC8CD5A00C0D356 /* LayerStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111150302AC8CD5A00C0D356 /* LayerStack.swift */; }; + 111150422AC8CD5A00C0D356 /* LayerImagePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111150312AC8CD5A00C0D356 /* LayerImagePicker.swift */; }; + 111150432AC8CD5A00C0D356 /* LayerButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111150322AC8CD5A00C0D356 /* LayerButton.swift */; }; + 111150442AC8CD5A00C0D356 /* LayerHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111150332AC8CD5A00C0D356 /* LayerHeader.swift */; }; + 111150452AC8CD5A00C0D356 /* LayerTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111150342AC8CD5A00C0D356 /* LayerTextField.swift */; }; + 111150462AC8CD5A00C0D356 /* LayerIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111150352AC8CD5A00C0D356 /* LayerIcon.swift */; }; + 111150472AC8CD5A00C0D356 /* LayerText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111150362AC8CD5A00C0D356 /* LayerText.swift */; }; + 111150482AC8CD5A00C0D356 /* LayerContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111150372AC8CD5A00C0D356 /* LayerContent.swift */; }; + 111150492AC8CD5A00C0D356 /* LayerBackground.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111150382AC8CD5A00C0D356 /* LayerBackground.swift */; }; + 1111504A2AC8CD5A00C0D356 /* LayerActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 111150392AC8CD5A00C0D356 /* LayerActions.swift */; }; + 1111504B2AC8CD5A00C0D356 /* Layer+Example.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1111503A2AC8CD5A00C0D356 /* Layer+Example.swift */; }; + 1111504C2AC8CD5A00C0D356 /* Layer+Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1111503C2AC8CD5A00C0D356 /* Layer+Constants.swift */; }; + 1111504D2AC8CD5A00C0D356 /* Layer+Animations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1111503D2AC8CD5A00C0D356 /* Layer+Animations.swift */; }; + 1111504E2AC8CD5A00C0D356 /* Layer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1111503E2AC8CD5A00C0D356 /* Layer+Extensions.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1111501E2AC8CCDF00C0D356 /* Layers.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Layers.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 111150212AC8CCDF00C0D356 /* LayersApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayersApp.swift; sourceTree = ""; }; + 111150232AC8CCDF00C0D356 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + 111150252AC8CCE100C0D356 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 111150282AC8CCE100C0D356 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 111150302AC8CD5A00C0D356 /* LayerStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LayerStack.swift; sourceTree = ""; }; + 111150312AC8CD5A00C0D356 /* LayerImagePicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LayerImagePicker.swift; sourceTree = ""; }; + 111150322AC8CD5A00C0D356 /* LayerButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LayerButton.swift; sourceTree = ""; }; + 111150332AC8CD5A00C0D356 /* LayerHeader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LayerHeader.swift; sourceTree = ""; }; + 111150342AC8CD5A00C0D356 /* LayerTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LayerTextField.swift; sourceTree = ""; }; + 111150352AC8CD5A00C0D356 /* LayerIcon.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LayerIcon.swift; sourceTree = ""; }; + 111150362AC8CD5A00C0D356 /* LayerText.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LayerText.swift; sourceTree = ""; }; + 111150372AC8CD5A00C0D356 /* LayerContent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LayerContent.swift; sourceTree = ""; }; + 111150382AC8CD5A00C0D356 /* LayerBackground.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LayerBackground.swift; sourceTree = ""; }; + 111150392AC8CD5A00C0D356 /* LayerActions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LayerActions.swift; sourceTree = ""; }; + 1111503A2AC8CD5A00C0D356 /* Layer+Example.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Layer+Example.swift"; sourceTree = ""; }; + 1111503C2AC8CD5A00C0D356 /* Layer+Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Layer+Constants.swift"; sourceTree = ""; }; + 1111503D2AC8CD5A00C0D356 /* Layer+Animations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Layer+Animations.swift"; sourceTree = ""; }; + 1111503E2AC8CD5A00C0D356 /* Layer+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Layer+Extensions.swift"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1111501B2AC8CCDF00C0D356 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 111150152AC8CCDF00C0D356 = { + isa = PBXGroup; + children = ( + 111150202AC8CCDF00C0D356 /* Layers */, + 1111501F2AC8CCDF00C0D356 /* Products */, + ); + sourceTree = ""; + }; + 1111501F2AC8CCDF00C0D356 /* Products */ = { + isa = PBXGroup; + children = ( + 1111501E2AC8CCDF00C0D356 /* Layers.app */, + ); + name = Products; + sourceTree = ""; + }; + 111150202AC8CCDF00C0D356 /* Layers */ = { + isa = PBXGroup; + children = ( + 1111502F2AC8CD5A00C0D356 /* Components */, + 1111503B2AC8CD5A00C0D356 /* Utilities */, + 111150212AC8CCDF00C0D356 /* LayersApp.swift */, + 111150232AC8CCDF00C0D356 /* ContentView.swift */, + 111150252AC8CCE100C0D356 /* Assets.xcassets */, + 111150272AC8CCE100C0D356 /* Preview Content */, + ); + path = Layers; + sourceTree = ""; + }; + 111150272AC8CCE100C0D356 /* Preview Content */ = { + isa = PBXGroup; + children = ( + 111150282AC8CCE100C0D356 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + 1111502F2AC8CD5A00C0D356 /* Components */ = { + isa = PBXGroup; + children = ( + 111150302AC8CD5A00C0D356 /* LayerStack.swift */, + 111150312AC8CD5A00C0D356 /* LayerImagePicker.swift */, + 111150322AC8CD5A00C0D356 /* LayerButton.swift */, + 111150332AC8CD5A00C0D356 /* LayerHeader.swift */, + 111150342AC8CD5A00C0D356 /* LayerTextField.swift */, + 111150352AC8CD5A00C0D356 /* LayerIcon.swift */, + 111150362AC8CD5A00C0D356 /* LayerText.swift */, + 111150372AC8CD5A00C0D356 /* LayerContent.swift */, + 111150382AC8CD5A00C0D356 /* LayerBackground.swift */, + 111150392AC8CD5A00C0D356 /* LayerActions.swift */, + ); + path = Components; + sourceTree = ""; + }; + 1111503B2AC8CD5A00C0D356 /* Utilities */ = { + isa = PBXGroup; + children = ( + 1111503A2AC8CD5A00C0D356 /* Layer+Example.swift */, + 1111503C2AC8CD5A00C0D356 /* Layer+Constants.swift */, + 1111503D2AC8CD5A00C0D356 /* Layer+Animations.swift */, + 1111503E2AC8CD5A00C0D356 /* Layer+Extensions.swift */, + ); + path = Utilities; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1111501D2AC8CCDF00C0D356 /* Layers */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1111502C2AC8CCE100C0D356 /* Build configuration list for PBXNativeTarget "Layers" */; + buildPhases = ( + 1111501A2AC8CCDF00C0D356 /* Sources */, + 1111501B2AC8CCDF00C0D356 /* Frameworks */, + 1111501C2AC8CCDF00C0D356 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Layers; + productName = Layers; + productReference = 1111501E2AC8CCDF00C0D356 /* Layers.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 111150162AC8CCDF00C0D356 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1500; + LastUpgradeCheck = 1500; + TargetAttributes = { + 1111501D2AC8CCDF00C0D356 = { + CreatedOnToolsVersion = 15.0; + }; + }; + }; + buildConfigurationList = 111150192AC8CCDF00C0D356 /* Build configuration list for PBXProject "Layers" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 111150152AC8CCDF00C0D356; + productRefGroup = 1111501F2AC8CCDF00C0D356 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 1111501D2AC8CCDF00C0D356 /* Layers */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1111501C2AC8CCDF00C0D356 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 111150292AC8CCE100C0D356 /* Preview Assets.xcassets in Resources */, + 111150262AC8CCE100C0D356 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1111501A2AC8CCDF00C0D356 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 111150492AC8CD5A00C0D356 /* LayerBackground.swift in Sources */, + 111150462AC8CD5A00C0D356 /* LayerIcon.swift in Sources */, + 111150482AC8CD5A00C0D356 /* LayerContent.swift in Sources */, + 111150412AC8CD5A00C0D356 /* LayerStack.swift in Sources */, + 1111504B2AC8CD5A00C0D356 /* Layer+Example.swift in Sources */, + 111150472AC8CD5A00C0D356 /* LayerText.swift in Sources */, + 111150242AC8CCDF00C0D356 /* ContentView.swift in Sources */, + 111150222AC8CCDF00C0D356 /* LayersApp.swift in Sources */, + 1111504A2AC8CD5A00C0D356 /* LayerActions.swift in Sources */, + 1111504E2AC8CD5A00C0D356 /* Layer+Extensions.swift in Sources */, + 1111504C2AC8CD5A00C0D356 /* Layer+Constants.swift in Sources */, + 111150432AC8CD5A00C0D356 /* LayerButton.swift in Sources */, + 111150442AC8CD5A00C0D356 /* LayerHeader.swift in Sources */, + 111150422AC8CD5A00C0D356 /* LayerImagePicker.swift in Sources */, + 111150452AC8CD5A00C0D356 /* LayerTextField.swift in Sources */, + 1111504D2AC8CD5A00C0D356 /* Layer+Animations.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1111502A2AC8CCE100C0D356 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + 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; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + 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 = 17.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 1111502B2AC8CCE100C0D356 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + 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; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + 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 = 17.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 1111502D2AC8CCE100C0D356 /* 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_ASSET_PATHS = "\"Layers/Preview Content\""; + DEVELOPMENT_TEAM = 7VFLYD5292; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.app.packages.Layers; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 1111502E2AC8CCE100C0D356 /* 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_ASSET_PATHS = "\"Layers/Preview Content\""; + DEVELOPMENT_TEAM = 7VFLYD5292; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.app.packages.Layers; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 111150192AC8CCDF00C0D356 /* Build configuration list for PBXProject "Layers" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1111502A2AC8CCE100C0D356 /* Debug */, + 1111502B2AC8CCE100C0D356 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1111502C2AC8CCE100C0D356 /* Build configuration list for PBXNativeTarget "Layers" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1111502D2AC8CCE100C0D356 /* Debug */, + 1111502E2AC8CCE100C0D356 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 111150162AC8CCDF00C0D356 /* Project object */; +} diff --git a/Layers.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Layers.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/Layers.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Layers.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Layers.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Layers.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Layers.xcodeproj/xcuserdata/raphaelsalaja.xcuserdatad/xcschemes/xcschememanagement.plist b/Layers.xcodeproj/xcuserdata/raphaelsalaja.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..a5c6808 --- /dev/null +++ b/Layers.xcodeproj/xcuserdata/raphaelsalaja.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + Layers.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/Layers/Assets.xcassets/AccentColor.colorset/Contents.json b/Layers/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/Layers/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Layers/Assets.xcassets/AppIcon.appiconset/Contents.json b/Layers/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..13613e3 --- /dev/null +++ b/Layers/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Layers/Assets.xcassets/Contents.json b/Layers/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Layers/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Layers/Components/LayerActions.swift b/Layers/Components/LayerActions.swift new file mode 100644 index 0000000..27f918f --- /dev/null +++ b/Layers/Components/LayerActions.swift @@ -0,0 +1,22 @@ +// +// LayerActions.swift +// Eyedee +// +// Created by Raphael Salaja on 29/09/2023. +// + +import SwiftUI + +struct LayerActions: View { + @State var content: AnyView + + public init(@ViewBuilder content: @escaping () -> Content) where Content: View { + self.content = AnyView(content()) + } + + var body: some View { + HStack { + content + } + } +} diff --git a/Layers/Components/LayerBackground.swift b/Layers/Components/LayerBackground.swift new file mode 100644 index 0000000..efd84a8 --- /dev/null +++ b/Layers/Components/LayerBackground.swift @@ -0,0 +1,30 @@ +// +// LayerBackground.swift +// Eyedee +// +// Created by Raphael Salaja on 29/09/2023. +// + +import SwiftUI + +struct LayerBackground: View { + @State var content: AnyView + + public init(@ViewBuilder content: @escaping () -> Content) where Content: View { + self.content = AnyView(content()) + } + + var body: some View { + ZStack { + Color(.black.opacity(0.25)).ignoresSafeArea() + + content + } + } +} + +#Preview { + LayerBackground { + LayerPlayground() + } +} diff --git a/Layers/Components/LayerButton.swift b/Layers/Components/LayerButton.swift new file mode 100644 index 0000000..3ba6753 --- /dev/null +++ b/Layers/Components/LayerButton.swift @@ -0,0 +1,211 @@ +// +// LayerButton.swift +// Eyedee +// +// Created by Raphael Salaja on 19/09/2023. +// + +import SwiftUI + +/// A custom button control with text, an optional icon, and various styling options. +/// +/// The `LayerButton` allows you to create buttons with customizable text, icons, and visual appearance. +/// It provides options to specify the button's action, background color, and disabled state. +/// +/// Example usage: +/// ```swift +/// struct ContentView: View { +/// var body: some View { +/// LayerButton(text: "Submit", action: { +/// // Perform button action here +/// }) +/// } +/// } +/// ``` +/// +/// - Parameters: +/// - id: The unique identifier for the button, used in animations +/// - text: The text displayed on the button. +/// - action: The closure to execute when the button is tapped. +/// - color: The background color of the button. +/// - icon: The name of the system image to display as an icon (optional). +/// - disabled: A boolean indicating whether the button should be disabled (default is `false`). +/// +/// The `LayerButton` supports various styling options, including font size, text alignment, +/// padding, background color, and the option to display an icon alongside the text. +/// +struct LayerButton: View { + enum LayerButtonType { + case single + case select + } + + @State var id: String + @State var text: String + @State var action: () -> Void + @State var color: Color + @State var icon: String + @State var disabled: Bool + @State var type: LayerButtonType + + @State var selected: Bool = false + + internal init( + id: String = UUID().uuidString, + text: String = "Button", + color: Color = Color(.systemBlue), + icon: String = "", + disabled: Bool = false, + type: LayerButtonType = .single, + action: @escaping () -> Void = {} + ) { + self.id = id + self.text = text + self.action = action + self.color = color + self.icon = icon + self.disabled = disabled + self.type = type + } + + func selectOperation() { + action + + withAnimation(.snappy(duration: 0.25)) { + selected.toggle() + } + } + + var body: some View { + if type == .single { + single + } else { + select + } + } + + var single: some View { + Button(action: action) { + VStack(alignment: .center) { + HStack(alignment: .center) { + Spacer(minLength: 0) + + if icon != "" { + Image(systemName: icon) + .font(.body) + .fontWeight(.bold) + .foregroundColor(color.isDark ? Color.white : Color.black) + } + + Text(text) + .font(.body) + .fontWeight(.bold) + .fontDesign(.rounded) + .transition(.scale(scale: 1.0)) + .matchedGeometryEffect( + id: "layer.button.text.\(id)", + in: LayerConstants.Animations.Namespaces.namespace + ) + .foregroundColor(color.isDark ? Color.white : Color.black) + + Spacer(minLength: 0) + } + } + .padding(16) + .frame(maxWidth: .infinity) + .background(disabled ? color.opacity(0.5) : color) + .clipShape(RoundedRectangle(cornerRadius: 100, style: .continuous)) + } + .disabled(disabled) + .buttonStyle(ScaleButtonStyle()) + } + + var select: some View { + Button(action: selectOperation) { + VStack(alignment: .center) { + HStack(alignment: .center) { + if icon != "" { + Image(systemName: icon) + .font(.body) + .fontWeight(.bold) + .foregroundColor(Color(.systemGray)) + } + + HStack { + Text(text) + .font(.body) + .fontWeight(.bold) + .multilineTextAlignment(.leading) + .fontDesign(.rounded) + .foregroundColor(Color.black) + .transition(.slide) + .minimumScaleFactor(0.1) + + Spacer(minLength: 0) + } + .matchedGeometryEffect( + id: "layer.button.select.\(id)", + in: LayerConstants.Animations.Namespaces.namespace + ) + + if selected { + Image(systemName: "checkmark.circle.fill") + .font(.title3) + .frame(width: 16, height: 16) + .fontWeight(.black) + .foregroundColor(color) + .transition( + .asymmetric( + insertion: + .scale(scale: 1.0) + .combined(with: .offset(x: 32)), + removal: + .scale(scale: 1.0) + .combined(with: .offset(x: 48)) + ) + ) + .matchedGeometryEffect( + id: "layer.button.select.icon.\(id)", + in: LayerConstants.Animations.Namespaces.namespace + ) + } + } + } + .padding(16) + .frame(maxWidth: .infinity) + .background(selected ? Color(.systemGray6) : Color.white) + .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous)) + } + .transition(.scale(scale: 1.0)) + .buttonStyle(.plain) + } +} + +#Preview("Select", traits: .sizeThatFitsLayout) { + VStack { + LayerButton( + icon: "plus", + type: .select + ) + LayerButton( + icon: "plus", + type: .select + ) + LayerButton( + icon: "plus", + type: .select + ) + LayerButton( + icon: "plus", + type: .select + ) + LayerButton( + icon: "plus", + type: .select + ) + }.padding() +} + +#Preview("Action", traits: .sizeThatFitsLayout) { + LayerButton().padding() +} diff --git a/Layers/Components/LayerContent.swift b/Layers/Components/LayerContent.swift new file mode 100644 index 0000000..a4da186 --- /dev/null +++ b/Layers/Components/LayerContent.swift @@ -0,0 +1,24 @@ +// +// LayerContent.swift +// Eyedee +// +// Created by Raphael Salaja on 29/09/2023. +// + +import SwiftUI + +struct LayerContent: View { + @State var content: AnyView + + init() { + self.content = AnyView(EmptyView()) + } + + internal init(@ViewBuilder content: @escaping () -> Content) where Content: View { + self.content = AnyView(content()) + } + + var body: some View { + content + } +} diff --git a/Layers/Components/LayerHeader.swift b/Layers/Components/LayerHeader.swift new file mode 100644 index 0000000..420a780 --- /dev/null +++ b/Layers/Components/LayerHeader.swift @@ -0,0 +1,28 @@ +// +// LayerHeader.swift +// Eyedee +// +// Created by Raphael Salaja on 29/09/2023. +// + +import SwiftUI + +struct LayerHeader: View { + @State var content: AnyView + + public init(@ViewBuilder content: @escaping () -> Content) where Content: View { + self.content = AnyView(content()) + } + + var body: some View { + HStack { + content + } + } +} + +#Preview { + LayerHeader { + Text("Hello, World!") + } +} diff --git a/Layers/Components/LayerIcon.swift b/Layers/Components/LayerIcon.swift new file mode 100644 index 0000000..370e04c --- /dev/null +++ b/Layers/Components/LayerIcon.swift @@ -0,0 +1,43 @@ +// +// LayerIcon.swift +// Eyedee +// +// Created by Raphael Salaja on 19/09/2023. +// + +import SwiftUI + +enum IconStyle { + case native + case button +} + +struct LayerIcon: View { + @State public var icon: String + + @State public var action: (() -> Void)? + + internal init(icon: String, action: (() -> Void)? = nil) { + self.icon = icon + self.action = action + } + + var body: some View { + Button(action: {}) { + Image(systemName: icon) + .resizable() + .scaledToFit() + .frame(width: 24, height: 24) + .fontWeight(.black) + .fontDesign(.rounded) + .scaleEffect(0.416) + .foregroundColor(Color(.systemGray)) + .background(Color(.systemGray6)) + .clipShape(Circle()) + } + } +} + +#Preview { + LayerIcon(icon: "xmark") +} diff --git a/Layers/Components/LayerImagePicker.swift b/Layers/Components/LayerImagePicker.swift new file mode 100644 index 0000000..431bf16 --- /dev/null +++ b/Layers/Components/LayerImagePicker.swift @@ -0,0 +1,48 @@ +// +// Layer.swift +// Eyedee +// +// Created by Raphael Salaja on 19/09/2023. +// + +import PhotosUI +import SwiftUI + +struct LayerImagePicker: View { +// @State var namespace: Namespace.ID + + var body: some View { + VStack(alignment: .center) { + ZStack { + Text("Tap to add an image") + .font(.headline) + .fontWeight(.bold) + .multilineTextAlignment(.center) + .fontDesign(.rounded) + .foregroundColor(Color(.systemGray)) + } + } + .frame(maxHeight: 300) + .frame(maxWidth: .infinity) + .background(Color(.systemGray6)) + .cornerRadius(20) + .shadow(color: Color(.systemGray4), radius: 10, x: 0, y: 5) +// .matchedGeometryEffect( +// id: "layer.image.picker", +// in: namespace +// ) +// .transition( +// .asymmetric( +// insertion: +// .opacity.animation(.default.delay(0.30)) +// .combined( +// with: .scale(scale: 0.9).animation(.default.delay(0.30))), +// removal: .opacity +// ) +// ) + } +} + +#Preview("Image Picker") { + LayerImagePicker() +} diff --git a/Layers/Components/LayerStack.swift b/Layers/Components/LayerStack.swift new file mode 100644 index 0000000..21d2c48 --- /dev/null +++ b/Layers/Components/LayerStack.swift @@ -0,0 +1,57 @@ +// +// LayerStack.swift +// Eyedee +// +// Created by Raphael Salaja on 29/09/2023. +// + +import SwiftUI + +struct LayerStack: View { + @Namespace private var layer + + var content: AnyView + + public init(@ViewBuilder content: @escaping () -> Content) where Content: View { + self.content = AnyView(content()) + } + + var body: some View { + VStack { + Spacer() + ZStack { + VStack(alignment: .leading, spacing: 24) { + content + } + .padding(32) + .background( + Color(.layerBackground) + .matchedGeometryEffect( + id: LayerConstants.Animations.Namespaces.background, + in: LayerConstants.Animations.Namespaces.namespace + ) + ) + .mask { + RoundedRectangle(cornerRadius: 32, style: .continuous) + .matchedGeometryEffect( + id: LayerConstants.Animations.Namespaces.mask, + in: LayerConstants.Animations.Namespaces.namespace + ) + } + } + } + .layerPadding() + } +} + +#Preview { + ZStack { + Color(.black.opacity(0.25)).ignoresSafeArea() + + LayerStack { + VStack { + Text("Hello, World!") + } + } + } +} diff --git a/Layers/Components/LayerText.swift b/Layers/Components/LayerText.swift new file mode 100644 index 0000000..a9a88b2 --- /dev/null +++ b/Layers/Components/LayerText.swift @@ -0,0 +1,67 @@ +// +// LayerTitle.swift +// Eyedee +// +// Created by Raphael Salaja on 19/09/2023. +// + +import SwiftUI + +private struct FullWidthText: View { + @State var text: AnyView + + public init(@ViewBuilder text: @escaping () -> Content) where Content: View { + self.text = AnyView(text()) + } + + var body: some View { + HStack { + text + + Spacer() + } + .frame(maxWidth: .infinity) + } +} + +struct LayerTitle: View { + @State public var title: String + + var body: some View { + FullWidthText { + Text(title).layerTitleStyle() + } + .matchedGeometryEffect( + id: LayerConstants.Animations.Namespaces.title, + in: LayerConstants.Animations.Namespaces.namespace + ) + .transition(.opacity.combined(with: .scale(scale: 1.0))) + } +} + +struct LayerDescription: View { + @State var description: String + + var body: some View { + FullWidthText { + Text(description).layerDescriptionStyle() + } + .matchedGeometryEffect( + id: LayerConstants.Animations.Namespaces.description, + in: LayerConstants.Animations.Namespaces.namespace + ) + .transition(.opacity.combined(with: .scale(scale: 1.0))) + } +} + +#Preview("Title", traits: .sizeThatFitsLayout) { + LayerTitle(title: "Heading") +} + +#Preview("Description", traits: .sizeThatFitsLayout) { + LayerDescription(description: + """ + Consequat cillum amet sint elit ut ut exercitation. Excepteur consectetur pariatur nisi. + """ + ) +} diff --git a/Layers/Components/LayerTextField.swift b/Layers/Components/LayerTextField.swift new file mode 100644 index 0000000..a47f57a --- /dev/null +++ b/Layers/Components/LayerTextField.swift @@ -0,0 +1,125 @@ +// +// LayerTextfield.swift +// Eyedee +// +// Created by Raphael Salaja on 22/09/2023. +// + +import SwiftUI + +/// The size variations for a `LayerTextField`. +/// +/// The `LayerTextField` provides five size variations, ranging from extra small to extra large. +/// These affect the maximum number of lines of text that can be displayed in the text field. +enum LayerTextFieldSize: Int { + /// The extra small variation for a `LayerTextField`. + case extraSmall = 1 + + /// The small variation for a `LayerTextField`. + case small = 2 + + /// The medium variation for a `LayerTextField`. + case medium = 3 + + /// The large variation for a `LayerTextField`. + case large = 4 + + /// The extra large variation for a `LayerTextField`. + case extraLarge = 5 +} + +/// A custom text field control with various size variations and styling options. +/// +/// The `LayerTextField` allows you to create text fields with different sizes and styles. +/// It provides options to customize the input text, placeholder text, and visual appearance. +/// +/// ```swift +/// struct ContentView: View { +/// @State private var username: String = "" +/// +/// var body: some View { +/// LayerTextField(input: $username, placeholder: "Username", variation: .medium) +/// } +/// } +/// ``` +/// +/// - Parameters: +/// - input: A binding to the input text displayed in the text field. +/// - placeholder: The placeholder text displayed when the text field is empty. +/// - variation: The size variation for the text field, ranging from extra small to extra large. +/// +struct LayerTextField: View { + @State var input: String + @State var placeholder: String + @State var variation: LayerTextFieldSize + + internal init( + input: String, + placeholder: String, + variation: LayerTextFieldSize + ) { + self.input = input + self.placeholder = placeholder + self.variation = variation + } + + var body: some View { + TextField(placeholder, text: $input, axis: .vertical) + .font(.system(.body, design: .rounded).weight(.medium)) + .multilineTextAlignment(.leading) + .padding(20) + .foregroundColor(Color(.label)) + .background(Color(.systemGray6)) + .clipShape(RoundedRectangle(cornerRadius: 20, style: .continuous)) + .lineLimit(variation.rawValue, reservesSpace: true) + } +} + +#Preview("Extra Small", traits: .sizeThatFitsLayout) { + LayerTextField( + input: "", + placeholder: "Placeholder", + variation: .extraSmall + ) + .padding() +} + +#Preview("Small", traits: .sizeThatFitsLayout) { + LayerTextField( + input: "", + placeholder: "Placeholder", + variation: .small + ) + .padding() + .previewLayout(.sizeThatFits) +} + +#Preview("Medium", traits: .sizeThatFitsLayout) { + LayerTextField( + input: "", + placeholder: "Placeholder", + variation: .medium + ) + .padding() + .previewLayout(.sizeThatFits) +} + +#Preview("Large", traits: .sizeThatFitsLayout) { + LayerTextField( + input: "", + placeholder: "Placeholder", + variation: .large + ) + .padding() + .previewLayout(.sizeThatFits) +} + +#Preview("Extra Large", traits: .sizeThatFitsLayout) { + LayerTextField( + input: "", + placeholder: "Placeholder", + variation: .extraLarge + ) + .padding() + .previewLayout(.sizeThatFits) +} diff --git a/Layers/ContentView.swift b/Layers/ContentView.swift new file mode 100644 index 0000000..390b4a9 --- /dev/null +++ b/Layers/ContentView.swift @@ -0,0 +1,102 @@ +// +// ContentView.swift +// Layers +// +// Created by Raphael Salaja on 30/09/2023. +// + +import SwiftUI + +struct ContentView: View { + var body: some View { + @Namespace private var namespace + + @State var index = 0 + + let headers: [String] = [ + "Heading 1", + "Heading 2", + "Heading 3", + "Heading 4" + ] + + let descriptions: [String] = [ + """ + Ad elit do deserunt elit Lorem consectetur ipsum cillum labore id. + """, + """ + Consequat cillum amet sint elit ut ut exercitation. + """, + """ + Excepteur nostrud anim mollit magna sunt aliqua aliqua do esse. + """, + """ + Eu laborum consequat laboris eiusmod dolor. + """ + ] + + let contents: [LayerContent] = [ + LayerContent(), + LayerContent(), + LayerContent { + LayerImagePicker() + }, + LayerContent() + ] + + var body: some View { + LayerStack { + HStack { + LayerTitle(title: headers[index]).id(headers[index]) + + LayerIcon(icon: "xmark") + } + + LayerDescription(description: descriptions[index]).id(descriptions[index]) + + ForEach(contents.indices) { position in + if position == self.index { + self.contents[index] + .matchedGeometryEffect( + id: LayerConstants.Animations.Namespaces.content + String(index), + in: namespace + ) + .transition( + .asymmetric( + insertion: + .opacity.combined(with: .scale(scale: 0.9)), + + removal: + .opacity.combined(with: .scale(scale: 1.0)) + ) + ) + } + } + + LayerActions { + LayerButton( + id: "cancel", + text: "Cancel", + color: Color(.systemOrange) + ) + + LayerButton( + id: "continue", + text: "Continue", + color: Color(.systemBlue) + ) { + withAnimation(.snappy) { + index = (index + 1) % 4 + } + } + } + } + } + } +} + +#Preview { + LayerBackground { + ContentView() + } +} diff --git a/Layers/LayersApp.swift b/Layers/LayersApp.swift new file mode 100644 index 0000000..641acd8 --- /dev/null +++ b/Layers/LayersApp.swift @@ -0,0 +1,17 @@ +// +// LayersApp.swift +// Layers +// +// Created by Raphael Salaja on 30/09/2023. +// + +import SwiftUI + +@main +struct LayersApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} diff --git a/Layers/Preview Content/Preview Assets.xcassets/Contents.json b/Layers/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Layers/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Layers/Utilities/Layer+Animations.swift b/Layers/Utilities/Layer+Animations.swift new file mode 100644 index 0000000..7bbe48f --- /dev/null +++ b/Layers/Utilities/Layer+Animations.swift @@ -0,0 +1,18 @@ +// +// Layer+Animations.swift +// Eyedee +// +// Created by Raphael Salaja on 29/09/2023. +// + +import SwiftUI + +struct Layer_Animations: View { + var body: some View { + Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) + } +} + +#Preview { + Layer_Animations() +} diff --git a/Layers/Utilities/Layer+Constants.swift b/Layers/Utilities/Layer+Constants.swift new file mode 100644 index 0000000..7d2d25c --- /dev/null +++ b/Layers/Utilities/Layer+Constants.swift @@ -0,0 +1,33 @@ +// +// Layer+Constants.swift +// Eyedee +// +// Created by Raphael Salaja on 29/09/2023. +// + +import SwiftUI + +public enum LayerConstants { + enum Styling { + static let padding: EdgeInsets = .init(top: 0, leading: 16, bottom: 0, trailing: 16) + } + + enum Animations { + enum Namespaces { + static let namespace: Namespace.ID = Namespace().wrappedValue + static let background = "layer.background" + static let mask = "layer.mask" + static let title = "layer.title" + static let description = "layer.description" + static let content = "layer.content" + } + + enum Transitions { + static let imagePicker: AnyTransition = + .asymmetric( + insertion: .opacity.animation(.default.delay(0.30)).combined(with: .scale(scale: 0.9).animation(.default.delay(0.30))), + removal: .opacity + ) + } + } +} diff --git a/Layers/Utilities/Layer+Example.swift b/Layers/Utilities/Layer+Example.swift new file mode 100644 index 0000000..7771d1f --- /dev/null +++ b/Layers/Utilities/Layer+Example.swift @@ -0,0 +1,290 @@ +// +// LayerExample.swift +// Eyedee +// +// Created by Raphael Salaja on 21/09/2023. +// + +import SwiftUI + +struct Layer_Example: View { + @Environment(\.colorScheme) var colorScheme + + enum Layers { + case start + case middle + case select + case end + } + + @State var opacity: CGFloat = 0.0 + @State var layer: Layers = .start + @State var index: Int = 0 + + @Namespace private var _default + + var titles: [String] = [ + "Heading 1", + "Heading 2", + "Heading 3", + "Heading 4" + ] + + var texts: [String] = [ + """ + Ad elit do deserunt elit Lorem consectetur ipsum cillum labore id. + """, + """ + Consequat cillum amet sint elit ut ut exercitation. + """, + """ + Excepteur nostrud anim mollit magna sunt aliqua aliqua do esse. + """, + """ + Eu laborum consequat laboris eiusmod dolor. + """ + ] + + @State var text: String = "Ad elit do deserunt elit Lorem consectetur ipsum cillum labore id." + @State var title: String = "Heading 1" + + var padding: EdgeInsets = .init( + top: 0, + leading: 16, + bottom: 0, + trailing: 16 + ) + + func change() { + withAnimation(.snappy) { + index += 1 + + if index > 3 { + index = 0 + } + + updateLayers(index: index) + + title = titles[index] + text = texts[index] + } + } + + func updateLayers(index: Int) { + self.index = index + + print(index) + + switch index { + case 0: + layer = .start + case 1: + layer = .middle + case 2: + layer = .select + case 3: + layer = .end + default: + layer = .start + } + } + + init() { + title = titles[index] + text = texts[index] + } + + var body: some View { + VStack { + Spacer() + /* + ZStack { + VStack(alignment: .leading, spacing: 24) { + HStack { + LayerTitle(title: title) + .id(title) + .matchedGeometryEffect( + id: "layer.title", + in: _default + ) + .transition( + .asymmetric( + insertion: + .opacity.combined(with: .scale(scale: 1.0)), + + removal: + .opacity.combined(with: .scale(scale: 1.0)) + ) + ) + + Spacer() + + LayerIcon(icon: "xmark") + } + + LayerDescription(description: text) + .id(text) + .matchedGeometryEffect( + id: "layer.text", + in: _default + ) + .transition( + .asymmetric( + insertion: + .opacity.combined(with: .scale(scale: 0.9)), + + removal: + .opacity.combined(with: .scale(scale: 1.0)) + ) + ) + + if layer == .middle { + // LayerImagePicker(namespace: _default) + } + + if layer == .select { + VStack(spacing: 8) { + LayerButton( + color: Color(.green), + icon: "plus", + namespace: _default, + type: .select + ) + + LayerButton( + color: Color(.green), + icon: "plus", + namespace: _default, + type: .select + ) + + LayerButton( + color: Color(.green), + icon: "plus", + namespace: _default, + type: .select + ) + + LayerButton( + color: Color(.green), + icon: "plus", + namespace: _default, + type: .select + ) + } + .transition( + .asymmetric( + insertion: + .opacity.animation(.default.delay(0.30)) + .combined( + with: .scale(scale: 0.9).animation(.default.delay(0.30))), + removal: .opacity + ) + ) + } + + if layer == .end { + LayerTextField( + input: "", + placeholder: "Placeholder", + variation: .small + ) + .matchedGeometryEffect( + id: "layer.textfield", + in: _default + ) + .transition( + .opacity.combined(with: .scale(scale: 1.00)) + ) + } + HStack { + switch layer { + case .start: + LayerButton( + id: "cancel", + text: "Cancel", + action: change, + color: Color(.systemGray6), + namespace: _default + ) + + LayerButton( + id: "continue", + text: "Continue", + action: change, + color: Color(.green), + namespace: _default + ) + + case .middle: + LayerButton( + id: "cancel", + text: "Cancel", + action: change, + color: Color(.systemGray6), + namespace: _default + ) + + LayerButton( + id: "continue", + text: "Continue", + action: change, + color: Color(.green), + namespace: _default + ) + + case .select: + LayerButton( + id: "cancel", + text: "Cancel", + action: change, + color: Color(.systemGray6), + namespace: _default + ) + + LayerButton( + id: "continue", + text: "Continue", + action: change, + color: Color(.green), + namespace: _default + ) + case .end: + LayerButton( + id: "cancel", + text: "Cancel", + action: change, + color: Color(.systemGray6), + namespace: _default + ) + } + } + } + .padding(32) + .background( + Color(.layerBackground) + .matchedGeometryEffect( + id: "layer.container", + in: _default + ) + ) + .mask { + RoundedRectangle(cornerRadius: 32, style: .continuous) + .matchedGeometryEffect( + id: "layer.mask", + in: _default + ) + } + } + */ + } + .padding(padding) + } +} + +#Preview("Example") { + ZStack { + Color(.black.opacity(0.25)).ignoresSafeArea() + Layer_Example() + } +} diff --git a/Layers/Utilities/Layer+Extensions.swift b/Layers/Utilities/Layer+Extensions.swift new file mode 100644 index 0000000..3414d47 --- /dev/null +++ b/Layers/Utilities/Layer+Extensions.swift @@ -0,0 +1,44 @@ +// +// LayerPadding.swift +// Eyedee +// +// Created by Raphael Salaja on 29/09/2023. +// + +import SwiftUI + +struct LayerPadding: ViewModifier { + func body(content: Content) -> some View { + content + .padding(LayerConstants.Styling.padding) + } +} + +struct LayerTitleStyle: ViewModifier { + func body(content: Content) -> some View { + content + .font(.system(.title3, design: .rounded, weight: .bold)) + } +} + +struct LayerDescriptionStyle: ViewModifier { + func body(content: Content) -> some View { + content + .font(.system(.headline, design: .rounded, weight: .medium)) + .foregroundColor(Color(.systemGray)) + } +} + +extension View { + func layerPadding() -> some View { + modifier(LayerPadding()) + } + + func layerTitleStyle() -> some View { + modifier(LayerTitleStyle()) + } + + func layerDescriptionStyle() -> some View { + modifier(LayerDescriptionStyle()) + } +}