";
- };
-/* End PBXVariantGroup section */
-
-/* Begin XCBuildConfiguration section */
- F4C33DEB26C92DF9001A28B1 /* 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++14";
- 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 = 14.5;
- 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;
- };
- F4C33DEC26C92DF9001A28B1 /* 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++14";
- 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 = 14.5;
- MTL_ENABLE_DEBUG_INFO = NO;
- MTL_FAST_MATH = YES;
- SDKROOT = iphoneos;
- SWIFT_COMPILATION_MODE = wholemodule;
- SWIFT_OPTIMIZATION_LEVEL = "-O";
- VALIDATE_PRODUCT = YES;
- };
- name = Release;
- };
- F4C33DEE26C92DF9001A28B1 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "";
- CODE_SIGN_STYLE = Automatic;
- DEVELOPMENT_TEAM = 5KKK9SKF79;
- INFOPLIST_FILE = "iOS Example/Info.plist";
- LD_RUNPATH_SEARCH_PATHS = (
- "$(inherited)",
- "@executable_path/Frameworks",
- );
- PRODUCT_BUNDLE_IDENTIFIER = by.ivanvorobei.opensource.nativeuikit.ios;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 5.0;
- TARGETED_DEVICE_FAMILY = "1,2";
- };
- name = Debug;
- };
- F4C33DEF26C92DF9001A28B1 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "";
- CODE_SIGN_STYLE = Automatic;
- DEVELOPMENT_TEAM = 5KKK9SKF79;
- INFOPLIST_FILE = "iOS Example/Info.plist";
- LD_RUNPATH_SEARCH_PATHS = (
- "$(inherited)",
- "@executable_path/Frameworks",
- );
- PRODUCT_BUNDLE_IDENTIFIER = by.ivanvorobei.opensource.nativeuikit.ios;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 5.0;
- TARGETED_DEVICE_FAMILY = "1,2";
- };
- name = Release;
- };
- F4C33E1A26C93160001A28B1 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
- ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "";
- CLANG_ENABLE_MODULES = YES;
- CODE_SIGN_STYLE = Automatic;
- DEVELOPMENT_TEAM = 5KKK9SKF79;
- INFOPLIST_FILE = "tvOS Example/Info.plist";
- LD_RUNPATH_SEARCH_PATHS = (
- "$(inherited)",
- "@executable_path/Frameworks",
- );
- PRODUCT_BUNDLE_IDENTIFIER = by.ivanvorobei.opensource.nativeuikit.tvos;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SDKROOT = appletvos;
- SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- SWIFT_VERSION = 5.0;
- TARGETED_DEVICE_FAMILY = 3;
- TVOS_DEPLOYMENT_TARGET = 14.5;
- };
- name = Debug;
- };
- F4C33E1B26C93160001A28B1 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
- ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "";
- CLANG_ENABLE_MODULES = YES;
- CODE_SIGN_STYLE = Automatic;
- DEVELOPMENT_TEAM = 5KKK9SKF79;
- INFOPLIST_FILE = "tvOS Example/Info.plist";
- LD_RUNPATH_SEARCH_PATHS = (
- "$(inherited)",
- "@executable_path/Frameworks",
- );
- PRODUCT_BUNDLE_IDENTIFIER = by.ivanvorobei.opensource.nativeuikit.tvos;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SDKROOT = appletvos;
- SWIFT_VERSION = 5.0;
- TARGETED_DEVICE_FAMILY = 3;
- TVOS_DEPLOYMENT_TARGET = 14.5;
- };
- name = Release;
- };
- F4C33E4E26C932CB001A28B1 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication;
- CODE_SIGN_STYLE = Automatic;
- DEVELOPMENT_TEAM = 5KKK9SKF79;
- INFOPLIST_FILE = "watchOS Example Extension/Info.plist";
- LD_RUNPATH_SEARCH_PATHS = (
- "$(inherited)",
- "@executable_path/Frameworks",
- "@executable_path/../../Frameworks",
- );
- PRODUCT_BUNDLE_IDENTIFIER = by.ivanvorobei.opensource.nativeuikit.ios.watchkitapp.watchkitextension;
- PRODUCT_NAME = "${TARGET_NAME}";
- SDKROOT = watchos;
- SKIP_INSTALL = YES;
- SWIFT_VERSION = 5.0;
- TARGETED_DEVICE_FAMILY = 4;
- WATCHOS_DEPLOYMENT_TARGET = 7.4;
- };
- name = Debug;
- };
- F4C33E4F26C932CB001A28B1 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication;
- CODE_SIGN_STYLE = Automatic;
- DEVELOPMENT_TEAM = 5KKK9SKF79;
- INFOPLIST_FILE = "watchOS Example Extension/Info.plist";
- LD_RUNPATH_SEARCH_PATHS = (
- "$(inherited)",
- "@executable_path/Frameworks",
- "@executable_path/../../Frameworks",
- );
- PRODUCT_BUNDLE_IDENTIFIER = by.ivanvorobei.opensource.nativeuikit.ios.watchkitapp.watchkitextension;
- PRODUCT_NAME = "${TARGET_NAME}";
- SDKROOT = watchos;
- SKIP_INSTALL = YES;
- SWIFT_VERSION = 5.0;
- TARGETED_DEVICE_FAMILY = 4;
- WATCHOS_DEPLOYMENT_TARGET = 7.4;
- };
- name = Release;
- };
- F4C33E5226C932CB001A28B1 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "";
- CODE_SIGN_STYLE = Automatic;
- DEVELOPMENT_TEAM = 5KKK9SKF79;
- IBSC_MODULE = watchOS_Example_Extension;
- INFOPLIST_FILE = "watchOS Example/Info.plist";
- PRODUCT_BUNDLE_IDENTIFIER = by.ivanvorobei.opensource.nativeuikit.ios.watchkitapp;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SDKROOT = watchos;
- SKIP_INSTALL = YES;
- SWIFT_VERSION = 5.0;
- TARGETED_DEVICE_FAMILY = 4;
- WATCHOS_DEPLOYMENT_TARGET = 7.4;
- };
- name = Debug;
- };
- F4C33E5326C932CB001A28B1 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "";
- CODE_SIGN_STYLE = Automatic;
- DEVELOPMENT_TEAM = 5KKK9SKF79;
- IBSC_MODULE = watchOS_Example_Extension;
- INFOPLIST_FILE = "watchOS Example/Info.plist";
- PRODUCT_BUNDLE_IDENTIFIER = by.ivanvorobei.opensource.nativeuikit.ios.watchkitapp;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SDKROOT = watchos;
- SKIP_INSTALL = YES;
- SWIFT_VERSION = 5.0;
- TARGETED_DEVICE_FAMILY = 4;
- WATCHOS_DEPLOYMENT_TARGET = 7.4;
- };
- name = Release;
- };
-/* End XCBuildConfiguration section */
-
-/* Begin XCConfigurationList section */
- F4C33DD426C92DF8001A28B1 /* Build configuration list for PBXProject "NativeUIKit" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- F4C33DEB26C92DF9001A28B1 /* Debug */,
- F4C33DEC26C92DF9001A28B1 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- F4C33DED26C92DF9001A28B1 /* Build configuration list for PBXNativeTarget "iOS Example" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- F4C33DEE26C92DF9001A28B1 /* Debug */,
- F4C33DEF26C92DF9001A28B1 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- F4C33E1926C93160001A28B1 /* Build configuration list for PBXNativeTarget "tvOS Example" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- F4C33E1A26C93160001A28B1 /* Debug */,
- F4C33E1B26C93160001A28B1 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- F4C33E4D26C932CB001A28B1 /* Build configuration list for PBXNativeTarget "watchOS Example Extension" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- F4C33E4E26C932CB001A28B1 /* Debug */,
- F4C33E4F26C932CB001A28B1 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- F4C33E5126C932CB001A28B1 /* Build configuration list for PBXNativeTarget "watchOS Example" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- F4C33E5226C932CB001A28B1 /* Debug */,
- F4C33E5326C932CB001A28B1 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
-/* End XCConfigurationList section */
-
-/* Begin XCRemoteSwiftPackageReference section */
- F4C33DFE26C92EBB001A28B1 /* XCRemoteSwiftPackageReference "SparrowKit" */ = {
- isa = XCRemoteSwiftPackageReference;
- repositoryURL = "https://github.com/ivanvorobei/SparrowKit";
- requirement = {
- kind = upToNextMajorVersion;
- minimumVersion = 3.4.6;
- };
- };
-/* End XCRemoteSwiftPackageReference section */
-
-/* Begin XCSwiftPackageProductDependency section */
- F4C33DFF26C92EBB001A28B1 /* SparrowKit */ = {
- isa = XCSwiftPackageProductDependency;
- package = F4C33DFE26C92EBB001A28B1 /* XCRemoteSwiftPackageReference "SparrowKit" */;
- productName = SparrowKit;
- };
- F4C33E0226C92EEA001A28B1 /* NativeUIKit */ = {
- isa = XCSwiftPackageProductDependency;
- productName = NativeUIKit;
- };
- F4C33E2626C931BD001A28B1 /* SparrowKit */ = {
- isa = XCSwiftPackageProductDependency;
- package = F4C33DFE26C92EBB001A28B1 /* XCRemoteSwiftPackageReference "SparrowKit" */;
- productName = SparrowKit;
- };
- F4C33E2826C931BF001A28B1 /* NativeUIKit */ = {
- isa = XCSwiftPackageProductDependency;
- productName = NativeUIKit;
- };
-/* End XCSwiftPackageProductDependency section */
- };
- rootObject = F4C33DD126C92DF8001A28B1 /* Project object */;
-}
diff --git a/Example App/NativeUIKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Example App/NativeUIKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata
deleted file mode 100644
index 919434a..0000000
--- a/Example App/NativeUIKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/Example App/NativeUIKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Example App/NativeUIKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
deleted file mode 100644
index 18d9810..0000000
--- a/Example App/NativeUIKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- IDEDidComputeMac32BitWarning
-
-
-
diff --git a/Example App/NativeUIKit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Example App/NativeUIKit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
deleted file mode 100644
index bce3df5..0000000
--- a/Example App/NativeUIKit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "object": {
- "pins": [
- {
- "package": "SparrowKit",
- "repositoryURL": "https://github.com/ivanvorobei/SparrowKit",
- "state": {
- "branch": null,
- "revision": "4a6283d0e5e010a99c038bd103a8c883245aafa5",
- "version": "3.5.4"
- }
- },
- {
- "package": "SPDiffable",
- "repositoryURL": "https://github.com/ivanvorobei/SPDiffable",
- "state": {
- "branch": null,
- "revision": "49d6a86438d0e82efc8da1e0202bceee9b1f5666",
- "version": "4.0.6"
- }
- },
- {
- "package": "SPPerspective",
- "repositoryURL": "https://github.com/ivanvorobei/SPPerspective",
- "state": {
- "branch": null,
- "revision": "580ed06a5daec94c5095379971570289b429fa3d",
- "version": "1.4.1"
- }
- }
- ]
- },
- "version": 1
-}
diff --git a/Example App/NativeUIKit.xcodeproj/project.xcworkspace/xcuserdata/ivanvorobei.xcuserdatad/UserInterfaceState.xcuserstate b/Example App/NativeUIKit.xcodeproj/project.xcworkspace/xcuserdata/ivanvorobei.xcuserdatad/UserInterfaceState.xcuserstate
deleted file mode 100644
index c4086de..0000000
Binary files a/Example App/NativeUIKit.xcodeproj/project.xcworkspace/xcuserdata/ivanvorobei.xcuserdatad/UserInterfaceState.xcuserstate and /dev/null differ
diff --git a/Example App/NativeUIKit.xcodeproj/xcshareddata/xcschemes/iOS Example.xcscheme b/Example App/NativeUIKit.xcodeproj/xcshareddata/xcschemes/iOS Example.xcscheme
deleted file mode 100644
index 9c07ce7..0000000
--- a/Example App/NativeUIKit.xcodeproj/xcshareddata/xcschemes/iOS Example.xcscheme
+++ /dev/null
@@ -1,78 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Example App/NativeUIKit.xcodeproj/xcshareddata/xcschemes/watchOS Example.xcscheme b/Example App/NativeUIKit.xcodeproj/xcshareddata/xcschemes/watchOS Example.xcscheme
deleted file mode 100644
index 23df4a6..0000000
--- a/Example App/NativeUIKit.xcodeproj/xcshareddata/xcschemes/watchOS Example.xcscheme
+++ /dev/null
@@ -1,105 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Example App/NativeUIKit.xcodeproj/xcuserdata/ivanvorobei.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Example App/NativeUIKit.xcodeproj/xcuserdata/ivanvorobei.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
deleted file mode 100644
index f259397..0000000
--- a/Example App/NativeUIKit.xcodeproj/xcuserdata/ivanvorobei.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
diff --git a/Example App/NativeUIKit.xcodeproj/xcuserdata/ivanvorobei.xcuserdatad/xcschemes/xcschememanagement.plist b/Example App/NativeUIKit.xcodeproj/xcuserdata/ivanvorobei.xcuserdatad/xcschemes/xcschememanagement.plist
deleted file mode 100644
index 52d946c..0000000
--- a/Example App/NativeUIKit.xcodeproj/xcuserdata/ivanvorobei.xcuserdatad/xcschemes/xcschememanagement.plist
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
- SchemeUserState
-
- iOS Example.xcscheme_^#shared#^_
-
- orderHint
- 0
-
- tvOS Example.xcscheme_^#shared#^_
-
- orderHint
- 3
-
- watchOS Example.xcscheme_^#shared#^_
-
- orderHint
- 2
-
-
- SuppressBuildableAutocreation
-
- F4C33DD826C92DF8001A28B1
-
- primary
-
-
- F4C33E2F26C932C8001A28B1
-
- primary
-
-
-
-
-
diff --git a/Example App/iOS Example/App/AppDelegate.swift b/Example App/iOS Example/App/AppDelegate.swift
deleted file mode 100644
index 5208746..0000000
--- a/Example App/iOS Example/App/AppDelegate.swift
+++ /dev/null
@@ -1,36 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-import UIKit
-import SparrowKit
-import NativeUIKit
-
-@UIApplicationMain
-class AppDelegate: SPAppWindowDelegate {
-
- func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
- let rootController = RootController()
- let navigationController = NativeNavigationController(rootViewController: rootController)
- makeKeyAndVisible(viewController: navigationController, tint: .systemBlue)
- return true
- }
-}
-
diff --git a/Example App/iOS Example/App/Assets.xcassets/AppIcon.appiconset/Contents.json b/Example App/iOS Example/App/Assets.xcassets/AppIcon.appiconset/Contents.json
deleted file mode 100644
index 9221b9b..0000000
--- a/Example App/iOS Example/App/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ /dev/null
@@ -1,98 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "iphone",
- "scale" : "2x",
- "size" : "20x20"
- },
- {
- "idiom" : "iphone",
- "scale" : "3x",
- "size" : "20x20"
- },
- {
- "idiom" : "iphone",
- "scale" : "2x",
- "size" : "29x29"
- },
- {
- "idiom" : "iphone",
- "scale" : "3x",
- "size" : "29x29"
- },
- {
- "idiom" : "iphone",
- "scale" : "2x",
- "size" : "40x40"
- },
- {
- "idiom" : "iphone",
- "scale" : "3x",
- "size" : "40x40"
- },
- {
- "idiom" : "iphone",
- "scale" : "2x",
- "size" : "60x60"
- },
- {
- "idiom" : "iphone",
- "scale" : "3x",
- "size" : "60x60"
- },
- {
- "idiom" : "ipad",
- "scale" : "1x",
- "size" : "20x20"
- },
- {
- "idiom" : "ipad",
- "scale" : "2x",
- "size" : "20x20"
- },
- {
- "idiom" : "ipad",
- "scale" : "1x",
- "size" : "29x29"
- },
- {
- "idiom" : "ipad",
- "scale" : "2x",
- "size" : "29x29"
- },
- {
- "idiom" : "ipad",
- "scale" : "1x",
- "size" : "40x40"
- },
- {
- "idiom" : "ipad",
- "scale" : "2x",
- "size" : "40x40"
- },
- {
- "idiom" : "ipad",
- "scale" : "1x",
- "size" : "76x76"
- },
- {
- "idiom" : "ipad",
- "scale" : "2x",
- "size" : "76x76"
- },
- {
- "idiom" : "ipad",
- "scale" : "2x",
- "size" : "83.5x83.5"
- },
- {
- "idiom" : "ios-marketing",
- "scale" : "1x",
- "size" : "1024x1024"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/iOS Example/App/Assets.xcassets/Contents.json b/Example App/iOS Example/App/Assets.xcassets/Contents.json
deleted file mode 100644
index 73c0059..0000000
--- a/Example App/iOS Example/App/Assets.xcassets/Contents.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/iOS Example/App/Base.lproj/LaunchScreen.storyboard b/Example App/iOS Example/App/Base.lproj/LaunchScreen.storyboard
deleted file mode 100644
index 865e932..0000000
--- a/Example App/iOS Example/App/Base.lproj/LaunchScreen.storyboard
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Example App/iOS Example/Info.plist b/Example App/iOS Example/Info.plist
deleted file mode 100644
index a8624ed..0000000
--- a/Example App/iOS Example/Info.plist
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- $(PRODUCT_BUNDLE_PACKAGE_TYPE)
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- 1
- LSRequiresIPhoneOS
-
- UIApplicationSupportsIndirectInputEvents
-
- UILaunchStoryboardName
- LaunchScreen
- UIRequiredDeviceCapabilities
-
- armv7
-
- UISupportedInterfaceOrientations
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UISupportedInterfaceOrientations~ipad
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
-
-
diff --git a/Example App/iOS Example/Scenes/RootController.swift b/Example App/iOS Example/Scenes/RootController.swift
deleted file mode 100644
index 7be592b..0000000
--- a/Example App/iOS Example/Scenes/RootController.swift
+++ /dev/null
@@ -1,29 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-import UIKit
-import SparrowKit
-import NativeUIKit
-
-class RootController: UIViewController {
-
-
-}
diff --git a/Example App/tvOS Example/AppDelegate.swift b/Example App/tvOS Example/AppDelegate.swift
deleted file mode 100644
index 01f6b83..0000000
--- a/Example App/tvOS Example/AppDelegate.swift
+++ /dev/null
@@ -1,5 +0,0 @@
-import UIKit
-import SparrowKit
-
-@main
-class AppDelegate: SPAppWindowDelegate {}
diff --git a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json
deleted file mode 100644
index 2e00335..0000000
--- a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "tv"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json b/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json
deleted file mode 100644
index 73c0059..0000000
--- a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json b/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json
deleted file mode 100644
index de59d88..0000000
--- a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "info" : {
- "author" : "xcode",
- "version" : 1
- },
- "layers" : [
- {
- "filename" : "Front.imagestacklayer"
- },
- {
- "filename" : "Middle.imagestacklayer"
- },
- {
- "filename" : "Back.imagestacklayer"
- }
- ]
-}
diff --git a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json
deleted file mode 100644
index 2e00335..0000000
--- a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "tv"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json b/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json
deleted file mode 100644
index 73c0059..0000000
--- a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json
deleted file mode 100644
index 2e00335..0000000
--- a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "tv"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json b/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json
deleted file mode 100644
index 73c0059..0000000
--- a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json
deleted file mode 100644
index 795cce1..0000000
--- a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "tv",
- "scale" : "1x"
- },
- {
- "idiom" : "tv",
- "scale" : "2x"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json b/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json
deleted file mode 100644
index 73c0059..0000000
--- a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json b/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json
deleted file mode 100644
index de59d88..0000000
--- a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "info" : {
- "author" : "xcode",
- "version" : 1
- },
- "layers" : [
- {
- "filename" : "Front.imagestacklayer"
- },
- {
- "filename" : "Middle.imagestacklayer"
- },
- {
- "filename" : "Back.imagestacklayer"
- }
- ]
-}
diff --git a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json
deleted file mode 100644
index 795cce1..0000000
--- a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "tv",
- "scale" : "1x"
- },
- {
- "idiom" : "tv",
- "scale" : "2x"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json b/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json
deleted file mode 100644
index 73c0059..0000000
--- a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json
deleted file mode 100644
index 795cce1..0000000
--- a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "tv",
- "scale" : "1x"
- },
- {
- "idiom" : "tv",
- "scale" : "2x"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json b/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json
deleted file mode 100644
index 73c0059..0000000
--- a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json b/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json
deleted file mode 100644
index f47ba43..0000000
--- a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
- "assets" : [
- {
- "filename" : "App Icon - App Store.imagestack",
- "idiom" : "tv",
- "role" : "primary-app-icon",
- "size" : "1280x768"
- },
- {
- "filename" : "App Icon.imagestack",
- "idiom" : "tv",
- "role" : "primary-app-icon",
- "size" : "400x240"
- },
- {
- "filename" : "Top Shelf Image Wide.imageset",
- "idiom" : "tv",
- "role" : "top-shelf-image-wide",
- "size" : "2320x720"
- },
- {
- "filename" : "Top Shelf Image.imageset",
- "idiom" : "tv",
- "role" : "top-shelf-image",
- "size" : "1920x720"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json b/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json
deleted file mode 100644
index b65f0cd..0000000
--- a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "tv",
- "scale" : "1x"
- },
- {
- "idiom" : "tv",
- "scale" : "2x"
- },
- {
- "idiom" : "tv-marketing",
- "scale" : "1x"
- },
- {
- "idiom" : "tv-marketing",
- "scale" : "2x"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json b/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json
deleted file mode 100644
index b65f0cd..0000000
--- a/Example App/tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "tv",
- "scale" : "1x"
- },
- {
- "idiom" : "tv",
- "scale" : "2x"
- },
- {
- "idiom" : "tv-marketing",
- "scale" : "1x"
- },
- {
- "idiom" : "tv-marketing",
- "scale" : "2x"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/tvOS Example/Assets.xcassets/Contents.json b/Example App/tvOS Example/Assets.xcassets/Contents.json
deleted file mode 100644
index 73c0059..0000000
--- a/Example App/tvOS Example/Assets.xcassets/Contents.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/tvOS Example/Info.plist b/Example App/tvOS Example/Info.plist
deleted file mode 100644
index 25869ef..0000000
--- a/Example App/tvOS Example/Info.plist
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- $(PRODUCT_BUNDLE_PACKAGE_TYPE)
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- 1
- LSRequiresIPhoneOS
-
- UILaunchStoryboardName
- LaunchScreen
- UIMainStoryboardFile
- Main
- UIRequiredDeviceCapabilities
-
- arm64
-
- UIUserInterfaceStyle
- Automatic
-
-
diff --git a/Example App/tvOS Example/LaunchScreen.storyboard b/Example App/tvOS Example/LaunchScreen.storyboard
deleted file mode 100644
index 195dc8c..0000000
--- a/Example App/tvOS Example/LaunchScreen.storyboard
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json b/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json
deleted file mode 100644
index ed7de25..0000000
--- a/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : "<=145"
- },
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">161"
- },
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">145"
- },
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">183"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Contents.json b/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Contents.json
deleted file mode 100644
index e8b3252..0000000
--- a/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Contents.json
+++ /dev/null
@@ -1,53 +0,0 @@
-{
- "assets" : [
- {
- "filename" : "Circular.imageset",
- "idiom" : "watch",
- "role" : "circular"
- },
- {
- "filename" : "Extra Large.imageset",
- "idiom" : "watch",
- "role" : "extra-large"
- },
- {
- "filename" : "Graphic Bezel.imageset",
- "idiom" : "watch",
- "role" : "graphic-bezel"
- },
- {
- "filename" : "Graphic Circular.imageset",
- "idiom" : "watch",
- "role" : "graphic-circular"
- },
- {
- "filename" : "Graphic Corner.imageset",
- "idiom" : "watch",
- "role" : "graphic-corner"
- },
- {
- "filename" : "Graphic Extra Large.imageset",
- "idiom" : "watch",
- "role" : "graphic-extra-large"
- },
- {
- "filename" : "Graphic Large Rectangular.imageset",
- "idiom" : "watch",
- "role" : "graphic-large-rectangular"
- },
- {
- "filename" : "Modular.imageset",
- "idiom" : "watch",
- "role" : "modular"
- },
- {
- "filename" : "Utilitarian.imageset",
- "idiom" : "watch",
- "role" : "utilitarian"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json b/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json
deleted file mode 100644
index ed7de25..0000000
--- a/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : "<=145"
- },
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">161"
- },
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">145"
- },
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">183"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json b/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json
deleted file mode 100644
index 9685a7f..0000000
--- a/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">161"
- },
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">183"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json b/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json
deleted file mode 100644
index 9685a7f..0000000
--- a/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">161"
- },
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">183"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json b/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json
deleted file mode 100644
index 9685a7f..0000000
--- a/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">161"
- },
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">183"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Graphic Extra Large.imageset/Contents.json b/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Graphic Extra Large.imageset/Contents.json
deleted file mode 100644
index ed7de25..0000000
--- a/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Graphic Extra Large.imageset/Contents.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : "<=145"
- },
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">161"
- },
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">145"
- },
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">183"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json b/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json
deleted file mode 100644
index 9685a7f..0000000
--- a/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">161"
- },
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">183"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json b/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json
deleted file mode 100644
index ed7de25..0000000
--- a/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : "<=145"
- },
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">161"
- },
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">145"
- },
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">183"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json b/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json
deleted file mode 100644
index ed7de25..0000000
--- a/Example App/watchOS Example Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : "<=145"
- },
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">161"
- },
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">145"
- },
- {
- "idiom" : "watch",
- "scale" : "2x",
- "screen-width" : ">183"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/watchOS Example Extension/Assets.xcassets/Contents.json b/Example App/watchOS Example Extension/Assets.xcassets/Contents.json
deleted file mode 100644
index 73c0059..0000000
--- a/Example App/watchOS Example Extension/Assets.xcassets/Contents.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/watchOS Example Extension/ExtensionDelegate.swift b/Example App/watchOS Example Extension/ExtensionDelegate.swift
deleted file mode 100644
index 0f219f4..0000000
--- a/Example App/watchOS Example Extension/ExtensionDelegate.swift
+++ /dev/null
@@ -1,3 +0,0 @@
-import WatchKit
-
-class ExtensionDelegate: NSObject, WKExtensionDelegate {}
diff --git a/Example App/watchOS Example Extension/Info.plist b/Example App/watchOS Example Extension/Info.plist
deleted file mode 100644
index ae74f16..0000000
--- a/Example App/watchOS Example Extension/Info.plist
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- $(PRODUCT_BUNDLE_PACKAGE_TYPE)
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- 1
- CLKComplicationPrincipalClass
- $(PRODUCT_MODULE_NAME).ComplicationController
- NSExtension
-
- NSExtensionAttributes
-
- WKAppBundleIdentifier
- by.ivanvorobei.opensource.nativeuikit.ios.watchkitapp
-
- NSExtensionPointIdentifier
- com.apple.watchkit
-
- WKExtensionDelegateClassName
- $(PRODUCT_MODULE_NAME).ExtensionDelegate
-
-
diff --git a/Example App/watchOS Example/Assets.xcassets/AccentColor.colorset/Contents.json b/Example App/watchOS Example/Assets.xcassets/AccentColor.colorset/Contents.json
deleted file mode 100644
index eb87897..0000000
--- a/Example App/watchOS Example/Assets.xcassets/AccentColor.colorset/Contents.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "colors" : [
- {
- "idiom" : "universal"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/watchOS Example/Assets.xcassets/AppIcon.appiconset/Contents.json b/Example App/watchOS Example/Assets.xcassets/AppIcon.appiconset/Contents.json
deleted file mode 100644
index d06b66a..0000000
--- a/Example App/watchOS Example/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ /dev/null
@@ -1,81 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "watch",
- "role" : "notificationCenter",
- "scale" : "2x",
- "size" : "24x24",
- "subtype" : "38mm"
- },
- {
- "idiom" : "watch",
- "role" : "notificationCenter",
- "scale" : "2x",
- "size" : "27.5x27.5",
- "subtype" : "42mm"
- },
- {
- "idiom" : "watch",
- "role" : "companionSettings",
- "scale" : "2x",
- "size" : "29x29"
- },
- {
- "idiom" : "watch",
- "role" : "companionSettings",
- "scale" : "3x",
- "size" : "29x29"
- },
- {
- "idiom" : "watch",
- "role" : "appLauncher",
- "scale" : "2x",
- "size" : "40x40",
- "subtype" : "38mm"
- },
- {
- "idiom" : "watch",
- "role" : "appLauncher",
- "scale" : "2x",
- "size" : "44x44",
- "subtype" : "40mm"
- },
- {
- "idiom" : "watch",
- "role" : "appLauncher",
- "scale" : "2x",
- "size" : "50x50",
- "subtype" : "44mm"
- },
- {
- "idiom" : "watch",
- "role" : "quickLook",
- "scale" : "2x",
- "size" : "86x86",
- "subtype" : "38mm"
- },
- {
- "idiom" : "watch",
- "role" : "quickLook",
- "scale" : "2x",
- "size" : "98x98",
- "subtype" : "42mm"
- },
- {
- "idiom" : "watch",
- "role" : "quickLook",
- "scale" : "2x",
- "size" : "108x108",
- "subtype" : "44mm"
- },
- {
- "idiom" : "watch-marketing",
- "scale" : "1x",
- "size" : "1024x1024"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/watchOS Example/Assets.xcassets/Contents.json b/Example App/watchOS Example/Assets.xcassets/Contents.json
deleted file mode 100644
index 73c0059..0000000
--- a/Example App/watchOS Example/Assets.xcassets/Contents.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Example App/watchOS Example/Base.lproj/Interface.storyboard b/Example App/watchOS Example/Base.lproj/Interface.storyboard
deleted file mode 100644
index cf05d24..0000000
--- a/Example App/watchOS Example/Base.lproj/Interface.storyboard
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Example App/watchOS Example/Info.plist b/Example App/watchOS Example/Info.plist
deleted file mode 100644
index ac58b18..0000000
--- a/Example App/watchOS Example/Info.plist
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- $(PRODUCT_BUNDLE_PACKAGE_TYPE)
- CFBundleShortVersionString
- 1.0
- CFBundleVersion
- 1
- UISupportedInterfaceOrientations
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
-
- WKCompanionAppBundleIdentifier
- by.ivanvorobei.opensource.nativeuikit.ios
- WKWatchKitApp
-
-
-
diff --git a/LICENSE b/LICENSE
index a943a88..a0468ed 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2021 Ivan Vorobei
+Copyright (c) 2022 Sparrow Code
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/Package.swift b/Package.swift
index 457358e..77caa25 100644
--- a/Package.swift
+++ b/Package.swift
@@ -3,34 +3,30 @@
import PackageDescription
let package = Package(
- name: "NativeUIKit",
+ name: "UIKitExtension",
platforms: [
- .iOS(.v12),
- .tvOS(.v12),
- .watchOS(.v6)
+ .iOS(.v14),
+ .tvOS(.v14)
],
products: [
.library(
- name: "NativeUIKit", targets: ["NativeUIKit"]
+ name: "UIKitExtension",
+ targets: ["UIKitExtension"]
)
],
dependencies: [
- .package(url: "https://github.com/ivanvorobei/SparrowKit", .upToNextMajor(from: "3.6.0")),
- .package(url: "https://github.com/ivanvorobei/SPPerspective", .upToNextMajor(from: "1.4.1")),
- .package(url: "https://github.com/ivanvorobei/SPDiffable", .upToNextMajor(from: "4.1.0")),
- .package(url: "https://github.com/ivanvorobei/SPPageController", .upToNextMajor(from: "1.3.2"))
+ .package(url: "https://github.com/sparrowcode/SwiftBoost", .upToNextMajor(from: "4.0.0")),
+ .package(url: "https://github.com/sparrowcode/DiffableKit", .upToNextMajor(from: "5.0.0")),
],
targets: [
.target(
- name: "NativeUIKit",
+ name: "UIKitExtension",
dependencies: [
- .product(name: "SparrowKit", package: "SparrowKit"),
- .product(name: "SPPerspective", package: "SPPerspective"),
- .product(name: "SPDiffable", package: "SPDiffable"),
- .product(name: "SPPageController", package: "SPPageController")
+ .product(name: "SwiftBoost", package: "SwiftBoost"),
+ .product(name: "DiffableKit", package: "DiffableKit")
],
swiftSettings: [
- .define("NATIVEUIKIT_SPM")
+ .define("UIKITEXTENSION_SPM")
]
)
],
diff --git a/README.md b/README.md
index 039e02b..e547cc2 100644
--- a/README.md
+++ b/README.md
@@ -1,30 +1,16 @@
-# NativeUIKit
+# UIKitExtension
-Mimicrated views and controls to native Apple appearance. If you have any ideas of what elements can be added, let me know. Here provided all elements which available, tap for open docs for it.
+### Community
-
-
-
-
-
-
-
+
+
+
-
-
-
+
+
-
-
-
-
-
-
-If you like the project, don't forget to `put star ★`
Check out my other libraries:
-
-
-
-
+
+
@@ -33,183 +19,37 @@ If you like the project, don't forget to `put star ★`
Check out my other li
- [Installation](#installation)
- [Swift Package Manager](#swift-package-manager)
- [Manually](#manually)
-- [Classes](#usage)
- - [NativeLargeActionButton](#NativeLargeActionButton)
- - [NativeSmallActionButton](#NativeSmallActionButton)
- - [NativeAvatarView](#NativeAvatarView)
- - [NativePlayPauseCompactButton](#NativePlayPauseCompactButton)
-- [Сontribution](#сontribution)
-- [Other Projects](#other-projects)
-- [Russian Community](#russian-community)
+- [Apps Using](#apps-using)
## Installation
-Ready for use on iOS 12+, tvOS 12+ & watchOS 6.0+. Works with Swift 5+. Required Xcode 12.0 and higher.
-
-
+Ready to use on iOS 13+, tvOS 13+ & watchOS 6+
### Swift Package Manager
-The [Swift Package Manager](https://swift.org/package-manager/) is a tool for managing the distribution of Swift code. It’s integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies.
-
-To integrate using Xcode 12, specify it in `File > Swift Packages > Add Package Dependency...`:
-
-```ogdl
-https://github.com/ivanvorobei/NativeUIKit
-```
-
-### Manually
-
-If you prefer not to use any of dependency managers, you can integrate manually. Put `Sources/NativeUIKit` folder in your Xcode project. Make sure to enable `Copy items if needed` and `Create groups`.
-
-## Classes
-
-
-### [NativeLargeActionButton](https://github.com/ivanvorobei/NativeUIKit/blob/main/Sources/NativeUIKit/NativeLargeActionButton.swift)
-
-Usually used at the bottom of the screen. You can set an icon. You can set how to change the style when you click. Supports states `disabled` and `dimmed`.
+In Xcode go to `File` -> `Packages` -> `Update to Latest Package Versions` and insert url:
-
-
-
-
-
-
-Next code for usage:
-
-```swift
-// Set Appearance and Content
-let button = NativeLargeActionButton()
-button.setImage(UIImage.init(systemName: "plus.circle.fill")!)
-button.higlightStyle = .background
-button.applyDefaultAppearance(with: .init(content: .custom(.white), background: .tint))
-
-// or use Wrapper
-button.set(
- title: "Large Action",
- icon: UIImage.init(systemName: "plus.circle.fill")!,
- colorise: .init(content: .custom(.white), background: .tint)
-)
```
-
-Button support system layouts by `sizeToFit()`. Next code allow you to layout button with cutom width:
-
-```swift
-button.sizeToFit()
-button.frame = .init(x: 0, y: 0, width: 300, height: button.frame.height)
+https://github.com/sparrowcode/UIKitExtension
```
-### [NativeSmallActionButton](https://github.com/ivanvorobei/NativeUIKit/blob/main/Sources/NativeUIKit/NativeSmallActionButton.swift)
-
-You definitely saw this button in the AppStore. You can use it without the icon.
-Supports states `disabled` and `dimmed`.
-
-
-
-
-
-
-
-Next code for usage:
+or adding it to the `dependencies` value of your `Package.swift`:
```swift
-// Set Appearance and Content
-let button = NativeSmallActionButton()
-button.higlightStyle = .background
-button.applyDefaultAppearance(with: .init(content: .custom(.white), background: .tint))
-
-// or use Wrapper
-button.set(
- title: "Edit",
- icon: nil,
- colorise: .init(content: .custom(.white), background: .tint)
-)
+dependencies: [
+ .package(url: "https://github.com/sparrowcode/UIKitExtension", .upToNextMajor(from: "2.0.0"))
+]
```
-Button support system layouts by `sizeToFit()`. Next code allow you to layout button:
-
-```swift
-button.sizeToFit()
-```
-
-### [NativeAvatarView](https://github.com/ivanvorobei/NativeUIKit/blob/main/Sources/NativeUIKit/NativeAvatarView.swift)
-
-
-
-
-
-Avatar view is container with 3 buttons - placeholder, avatar and indicator. For change avatar set `avatarAppearance`. For show or hide edit button set `isEditable`.
-
-Layout availbe by size to fit for content. In this case change placeholder size to valid SFSymbol for have correct fit. By default font side is 80 point. Or you can set fixed frame and ignore fitting size.
-
-```swift
-let avatarView = NativeAvatarView()
-
-// You can set target, actions or even contex menu like usual button.
-avatarView.placeholderButton.addTarget(self, action: #selector(didTap), for: .touchUpInside)
-avatarView.avatarButton.addTarget(self, action: #selector(didTap), for: .touchUpInside)
-avatarView.indicatorButton.addTarget(self, action: #selector(didTap), for: .touchUpInside)
-
-// For show edit button.
-avatarView.isEditable = true
-
-// Layout.
-// For fit by images.
-avatarView.sizeToFit()
-// By custom frame:
-avatarView.frame = .init(x: 0, y: 0, width: 60, height: 60)
-```
-
-### [NativePlayPauseCompactButton](https://github.com/ivanvorobei/NativeUIKit/blob/main/Sources/NativeUIKit/NativePlayPauseCompactButton.swift)
-
-
-
-
-
-
-
-Simple play/pause button.
-
-```swift
-let button = NativePlayPauseCompactButton()
-// For fit to valid size.
-button.sizeToFit()
-// For change appearance.
-button.appearance = .play //.pause
-```
-
-## Сontribution
-
-My English is very bad. You can see this once you read the documentation. I would really like to have clean and nice documentation. If you see gramatical errors and can help fix the Readme, please contact me hello@ivanvorobei.io or make a Pull Request. Thank you in advance!
-
-## Other Projects
-
-I love being helpful. Here I have provided a list of libraries that I keep up to date. For see `video previews` of libraries without install open [opensource.ivanvorobei.io](https://opensource.ivanvorobei.io) website.
-I have libraries with native interface and managing permissions. Also available pack of useful extensions for boost your development process.
-
-
-
-
-
-
-
-
-
+### Manually
-## Russian Community
+If you prefer not to use any of dependency managers, you can integrate manually. Put `Sources/UIKitExtension` folder in your Xcode project. Make sure to enable `Copy items if needed` and `Create groups`.
-Подписывайся в телеграмм-канал, если хочешь получать уведомления о новых туториалах.
-Со сложными и непонятными задачами помогут в чате.
+## Apps Using
-
-
-
-
-
-
+
+
+
+
-
-Видео-туториалы выклыдываю на [YouTube](https://tutorials.ivanvorobei.io/youtube):
-
-[](https://tutorials.ivanvorobei.io/youtube)
diff --git a/Sources/NativeUIKit/Bars/NativeBorderedView.swift b/Sources/NativeUIKit/Bars/NativeBorderedView.swift
deleted file mode 100644
index 9eb59d5..0000000
--- a/Sources/NativeUIKit/Bars/NativeBorderedView.swift
+++ /dev/null
@@ -1,114 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-/**
- NativeUIKit: View with porder on some position.
- For change position check property.
- */
-open class NativeBorderedView: SPView {
-
- // MARK: - Data
-
- /**
- NativeUIKit: Border Position.
- */
- open var position: Position = .top {
- didSet {
- layoutSubviews()
- }
- }
-
- // MARK: - Views
-
- private let borderView = SPView().do {
- if #available(iOS 13.0, *) {
- $0.backgroundColor = .separator
- } else {
- $0.backgroundColor = .systemGray
- }
- }
-
- // MARK: - Init
-
- public init(position: Position) {
- self.position = position
- super.init()
- }
-
- public required init?(coder aDecoder: NSCoder) {
- super.init(coder: aDecoder)
- }
-
- open override func commonInit() {
- super.commonInit()
- addSubview(borderView)
- }
-
- // MARK: - Actions
-
- /**
- NativeUIKit: Show or hide border.
-
- - parameter visible: New visible state of border.
- - parameter animated: State for apply changes animatable or not.
- */
- open func setBorderVisible(_ visible: Bool, animated: Bool) {
- let work = { [weak self] in
- guard let self = self else { return }
- self.borderView.alpha = visible ? 1 : 0
- }
- if animated {
- UIView.animate(withDuration: 0.3, delay: 0, options: [.beginFromCurrentState, .allowUserInteraction], animations: {
- work()
- })
- } else {
- work()
- }
- }
-
- // MARK: - Layout
-
- open override func layoutSubviews() {
- super.layoutSubviews()
- borderView.frame.setWidth(frame.width)
- borderView.frame.setHeight(0.5)
- borderView.frame.origin.x = 0
- switch position {
- case .top:
- borderView.frame.origin.y = 0
- case .bottom:
- borderView.frame.setMaxY(frame.height)
- }
- }
-
- // MARK: - Models
-
- public enum Position {
-
- case top
- case bottom
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Bars/NativeMimicrateBarView.swift b/Sources/NativeUIKit/Bars/NativeMimicrateBarView.swift
deleted file mode 100644
index 32543f8..0000000
--- a/Sources/NativeUIKit/Bars/NativeMimicrateBarView.swift
+++ /dev/null
@@ -1,78 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-/**
- NativeUIKit: View with mimicrate to navigation and toolbar views.
- */
-open class NativeMimicrateBarView: SPView {
-
- // MARK: - Views
-
- public let borderedView: NativeBorderedView
- public let backgroundView: UIVisualEffectView
-
- // MARK: - Init
-
- public init(borderPosition: NativeBorderedView.Position) {
- self.borderedView = NativeBorderedView(position: borderPosition)
- self.backgroundView = UIVisualEffectView.init(style: .regular)
- super.init()
- }
-
- public required init?(coder aDecoder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- open override func commonInit() {
- super.commonInit()
- addSubview(backgroundView)
- addSubview(borderedView)
- setVisible(progress: 1)
- }
-
- // MARK: - Actions
-
- /**
- NativeUIKit: Show or hide bar.
-
- - parameter progress: Value in range from `0` to `1` to visible or not view.
- */
- open func setVisible(progress: CGFloat) {
- var alpha: CGFloat = progress
- if progress < 0 { alpha = 0 }
- if progress > 1 { alpha = 1 }
- self.borderedView.alpha = alpha
- self.backgroundView.alpha = alpha
- }
-
- // MARK: - Layout
-
- open override func layoutSubviews() {
- super.layoutSubviews()
- backgroundView.setEqualSuperviewBounds()
- borderedView.setEqualSuperviewBounds()
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Bars/NativeMimicrateNavigationBarView.swift b/Sources/NativeUIKit/Bars/NativeMimicrateNavigationBarView.swift
deleted file mode 100644
index b378472..0000000
--- a/Sources/NativeUIKit/Bars/NativeMimicrateNavigationBarView.swift
+++ /dev/null
@@ -1,38 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-open class NativeMimicrateNavigationBarView: NativeMimicrateBarView {
-
- // MARK: - Init
-
- public init() {
- super.init(borderPosition: .bottom)
- }
-
- public required init?(coder aDecoder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Bars/ToolBar/LargeAction/NativeLargeActionToolBarView.swift b/Sources/NativeUIKit/Bars/ToolBar/LargeAction/NativeLargeActionToolBarView.swift
deleted file mode 100644
index 04c77d9..0000000
--- a/Sources/NativeUIKit/Bars/ToolBar/LargeAction/NativeLargeActionToolBarView.swift
+++ /dev/null
@@ -1,100 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-open class NativeLargeActionToolBarView: NativeMimicrateToolBarView {
-
- // MARK: - Views
-
- public let activityIndicatorView = UIActivityIndicatorView()
-
- public let actionButton = NativeLargeActionButton().do {
- $0.applyDefaultAppearance(with: .tintedColorful)
- }
-
- public let footerLabel = SPLabel().do {
- $0.font = .preferredFont(forTextStyle: .footnote)
- $0.numberOfLines = .zero
- if #available(iOS 13.0, *) {
- $0.textColor = .secondaryLabel
- } else {
- $0.textColor = .black.alpha(0.5)
- }
- }
-
- // MARK: - Init
-
- open override func commonInit() {
- super.commonInit()
- addSubview(activityIndicatorView)
- addSubview(actionButton)
- addSubview(footerLabel)
- }
-
- // MARK: - Actions
-
- open func setLoading(_ state: Bool) {
- if state {
- activityIndicatorView.startAnimating()
- actionButton.isHidden = true
- footerLabel.isHidden = true
- } else {
- activityIndicatorView.stopAnimating()
- actionButton.isHidden = false
- footerLabel.isHidden = false
- }
- }
-
- // MARK: - Layout
-
- internal let footerLeftInset: CGFloat = 20
-
- open override func layoutSubviews() {
- super.layoutSubviews()
- actionButton.layout(y: layoutMargins.top)
- if footerLabel.text != nil {
- footerLabel.layoutDynamicHeight(x: layoutMargins.left + footerLeftInset, y: actionButton.frame.maxY + 12, width: layoutWidth - footerLeftInset)
- }
-
- let contentHeight: CGFloat = {
- if footerLabel.text == nil {
- return actionButton.frame.maxY
- } else {
- return footerLabel.frame.maxY
- }
- }()
- activityIndicatorView.setXCenter()
- activityIndicatorView.center.y = contentHeight / 2
- }
-
- open override func sizeThatFits(_ size: CGSize) -> CGSize {
- layoutSubviews()
- if footerLabel.text == nil {
- return .init(width: size.width, height: actionButton.frame.maxY + layoutMargins.bottom)
- } else {
- return .init(width: size.width, height: footerLabel.frame.maxY + layoutMargins.bottom)
- }
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Bars/ToolBar/LargeAction/NativeLargeSmallActionToolBarView.swift b/Sources/NativeUIKit/Bars/ToolBar/LargeAction/NativeLargeSmallActionToolBarView.swift
deleted file mode 100644
index 4043d54..0000000
--- a/Sources/NativeUIKit/Bars/ToolBar/LargeAction/NativeLargeSmallActionToolBarView.swift
+++ /dev/null
@@ -1,63 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-open class NativeLargeSmallActionToolBarView: NativeLargeActionToolBarView {
-
- // MARK: - Views
-
- public let secondActionButton = SPDimmedButton().do {
- $0.applyDefaultAppearance(with: .tintedContent)
- $0.titleLabel?.font = UIFont.preferredFont(forTextStyle: .headline, addPoints: -1)
- }
-
- // MARK: - Init
-
- open override func commonInit() {
- super.commonInit()
- addSubview(secondActionButton)
- }
-
- // MARK: - Actions
-
- open override func setLoading(_ state: Bool) {
- super.setLoading(state)
- secondActionButton.isHidden = state
- }
-
- // MARK: - Layout
-
- open override func layoutSubviews() {
- super.layoutSubviews()
- secondActionButton.setWidthAndFit(width: layoutWidth)
- secondActionButton.frame.origin.y = actionButton.frame.maxY + 12
- secondActionButton.setXCenter()
- }
-
- open override func sizeThatFits(_ size: CGSize) -> CGSize {
- layoutSubviews()
- return .init(width: size.width, height: secondActionButton.frame.maxY + layoutMargins.bottom)
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Bars/ToolBar/LargeAction/NativeSkipableLargeActionToolBarView.swift b/Sources/NativeUIKit/Bars/ToolBar/LargeAction/NativeSkipableLargeActionToolBarView.swift
deleted file mode 100644
index 1a9bdd5..0000000
--- a/Sources/NativeUIKit/Bars/ToolBar/LargeAction/NativeSkipableLargeActionToolBarView.swift
+++ /dev/null
@@ -1,63 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-open class NativeSkipableLargeActionToolBarView: NativeLargeActionToolBarView {
-
- // MARK: - Views
-
- public let skipButton = SPDimmedButton().do {
- $0.applyDefaultAppearance(with: .init(content: .systemGray, background: .clear))
- $0.titleLabel?.font = UIFont.preferredFont(forTextStyle: .body, weight: .semibold)
- }
-
- // MARK: - Init
-
- open override func commonInit() {
- super.commonInit()
- addSubview(skipButton)
- }
-
- // MARK: - Actions
-
- open override func setLoading(_ state: Bool) {
- super.setLoading(state)
- skipButton.isHidden = state
- }
-
- // MARK: - Layout
-
- open override func layoutSubviews() {
- super.layoutSubviews()
- skipButton.setWidthAndFit(width: layoutWidth)
- skipButton.frame.origin.y = actionButton.frame.maxY + 12
- skipButton.setXCenter()
- }
-
- open override func sizeThatFits(_ size: CGSize) -> CGSize {
- layoutSubviews()
- return .init(width: size.width, height: skipButton.frame.maxY + layoutMargins.bottom)
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Bars/ToolBar/NativeAppleAuthToolBarView.swift b/Sources/NativeUIKit/Bars/ToolBar/NativeAppleAuthToolBarView.swift
deleted file mode 100644
index 7607901..0000000
--- a/Sources/NativeUIKit/Bars/ToolBar/NativeAppleAuthToolBarView.swift
+++ /dev/null
@@ -1,75 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && canImport(AuthenticationServices) && (os(iOS))
-import UIKit
-import SparrowKit
-import AuthenticationServices
-
-@available(iOS 13.0, *)
-open class NativeAppleAuthToolBarView: NativeMimicrateToolBarView {
-
- // MARK: - Views
-
- public let authButton = ASAuthorizationAppleIDButton()
-
- public let footerLabel = SPLabel().do {
- $0.font = .preferredFont(forTextStyle: .footnote)
- $0.numberOfLines = .zero
- $0.textColor = .secondaryLabel
- }
-
- // MARK: - Init
-
- open override func commonInit() {
- super.commonInit()
- addSubview(authButton)
- addSubview(footerLabel)
- }
-
- // MARK: - Layout
-
- internal let footerLeftInset: CGFloat = 20
-
- open override func layoutSubviews() {
- super.layoutSubviews()
-
- let authButtonWidth = min(readableWidth, NativeLayout.Sizes.actionable_area_maximum_width)
- authButton.frame.setWidth(authButtonWidth)
- authButton.frame.setHeight(52)
- authButton.setXCenter()
- authButton.frame.origin.y = layoutMargins.top
-
- if footerLabel.text != nil {
- footerLabel.layoutDynamicHeight(x: layoutMargins.left + footerLeftInset, y: authButton.frame.maxY + 12, width: layoutWidth - footerLeftInset)
- }
- }
-
- open override func sizeThatFits(_ size: CGSize) -> CGSize {
- layoutSubviews()
- if footerLabel.text == nil {
- return .init(width: size.width, height: authButton.frame.maxY + layoutMargins.bottom)
- } else {
- return .init(width: size.width, height: footerLabel.frame.maxY + layoutMargins.bottom)
- }
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Bars/ToolBar/NativeMimicrateNavigationToolBarView.swift b/Sources/NativeUIKit/Bars/ToolBar/NativeMimicrateNavigationToolBarView.swift
deleted file mode 100644
index 1878046..0000000
--- a/Sources/NativeUIKit/Bars/ToolBar/NativeMimicrateNavigationToolBarView.swift
+++ /dev/null
@@ -1,55 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-open class NativeMimicrateToolBarView: NativeMimicrateBarView {
-
- // MARK: - Init
-
- public init() {
- super.init(borderPosition: .top)
- }
-
- public required init?(coder aDecoder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- open override func commonInit() {
- super.commonInit()
- insetsLayoutMarginsFromSafeArea = false
- layoutMargins.top = 16
- }
-
- // MARK: - Layout
-
- open override func layoutSubviews() {
- super.layoutSubviews()
- guard let superview = superview else { return }
- let contentWidth = min(440, superview.readableWidth)
- let horizontalMargin = (frame.width - contentWidth) / 2
- layoutMargins.left = horizontalMargin
- layoutMargins.right = horizontalMargin
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Bars/ToolBar/NativeSmallActionToolBarView.swift b/Sources/NativeUIKit/Bars/ToolBar/NativeSmallActionToolBarView.swift
deleted file mode 100644
index 68ab3d8..0000000
--- a/Sources/NativeUIKit/Bars/ToolBar/NativeSmallActionToolBarView.swift
+++ /dev/null
@@ -1,54 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-open class NativeSmallActionToolBarView: NativeMimicrateToolBarView {
-
- public let actionButton = SPDimmedButton().do {
- $0.applyDefaultAppearance(with: .tintedContent)
- $0.titleLabel?.font = UIFont.preferredFont(forTextStyle: .title3, weight: .semibold)
- }
-
- // MARK: - Init
-
- open override func commonInit() {
- super.commonInit()
- addSubview(actionButton)
- }
-
- // MARK: - Layout
-
- open override func layoutSubviews() {
- super.layoutSubviews()
- actionButton.setWidthAndFit(width: layoutWidth)
- actionButton.frame.origin.y = layoutMargins.top + 16
- actionButton.setXCenter()
- }
-
- open override func sizeThatFits(_ size: CGSize) -> CGSize {
- layoutSubviews()
- return .init(width: size.width, height: actionButton.frame.maxY + layoutMargins.bottom)
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Collection/LargeHeader/NativeLargeHeaderCollectionView.swift b/Sources/NativeUIKit/Collection/LargeHeader/NativeLargeHeaderCollectionView.swift
deleted file mode 100644
index 1bf86cb..0000000
--- a/Sources/NativeUIKit/Collection/LargeHeader/NativeLargeHeaderCollectionView.swift
+++ /dev/null
@@ -1,54 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-open class NativeLargeHeaderCollectionView: SPCollectionReusableView {
-
- public let headerView = NativeLargeHeaderView()
-
- open override func commonInit() {
- super.commonInit()
- insetsLayoutMarginsFromSafeArea = false
- layoutMargins = .zero
- addSubview(headerView)
- }
-
- open override func layoutSubviews() {
- super.layoutSubviews()
- headerView.layout(y: layoutMargins.top)
- }
-
- open override func sizeThatFits(_ size: CGSize) -> CGSize {
- let superSize = super.sizeThatFits(size)
- return .init(width: superSize.width, height: headerView.frame.height + layoutMargins.bottom)
- }
-
- static public func size(for item: NativeLargeHeaderItem, in collectionView: UICollectionView) -> CGSize {
- let view = NativeLargeHeaderView()
- view.configure(with: item, section: .zero)
- view.setWidthAndFit(width: collectionView.layoutWidth)
- return .init(width: collectionView.frame.width, height: view.frame.height)
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Collection/LargeHeader/SPDiffableCollectionHeaderFooterProvider+LargeHeader.swift b/Sources/NativeUIKit/Collection/LargeHeader/SPDiffableCollectionHeaderFooterProvider+LargeHeader.swift
deleted file mode 100644
index 67b20bb..0000000
--- a/Sources/NativeUIKit/Collection/LargeHeader/SPDiffableCollectionHeaderFooterProvider+LargeHeader.swift
+++ /dev/null
@@ -1,38 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-import UIKit
-import SPDiffable
-
-@available(iOS 13.0, tvOS 13.0, *)
-extension SPDiffableCollectionDataSource.HeaderFooterProvider {
-
- #if (os(iOS))
- public static var largeHeader: SPDiffableCollectionDataSource.HeaderFooterProvider {
- return SPDiffableCollectionDataSource.HeaderFooterProvider.init { collectionView, kind, indexPath, item in
- guard let header = item as? NativeLargeHeaderItem else { return nil }
- let view = collectionView.dequeueReusableSupplementaryView(withCalss: NativeLargeHeaderCollectionView.self, kind: kind, for: indexPath)
- view.headerView.configure(with: header, section: indexPath.section)
- return view
- }
- }
- #endif
-}
diff --git a/Sources/NativeUIKit/Collection/NativePromoCollectionViewCell.swift b/Sources/NativeUIKit/Collection/NativePromoCollectionViewCell.swift
deleted file mode 100644
index 98366fb..0000000
--- a/Sources/NativeUIKit/Collection/NativePromoCollectionViewCell.swift
+++ /dev/null
@@ -1,59 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-import SPPerspective
-
-open class NativePromoCollectionViewCell: SPCollectionViewCell {
-
- // MARK: - Views
-
- public let promoView = NativePromoView()
-
- // MARK: - Init
-
- open override func commonInit() {
- super.commonInit()
- contentView.layoutMargins = .zero
- contentView.addSubview(promoView)
- }
-
- open override func prepareForReuse() {
- super.prepareForReuse()
- promoView.iconView.resetPerspective()
- }
-
- // MARK: - Layout
-
- open override func layoutSubviews() {
- super.layoutSubviews()
- promoView.layout(y: contentView.layoutMargins.top)
- }
-
- open override func sizeThatFits(_ size: CGSize) -> CGSize {
- let superSize = super.sizeThatFits(size)
- layoutSubviews()
- return .init(width: superSize.width, height: promoView.frame.maxY + contentView.layoutMargins.bottom)
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Controllers/Complex/Onboarding/Actinos/NativeOnbiardingActionButton.swift b/Sources/NativeUIKit/Controllers/Complex/Onboarding/Actinos/NativeOnbiardingActionButton.swift
deleted file mode 100644
index 0bb62f2..0000000
--- a/Sources/NativeUIKit/Controllers/Complex/Onboarding/Actinos/NativeOnbiardingActionButton.swift
+++ /dev/null
@@ -1,151 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-public class NativeOnbiardingActionButton: SPDimmedButton {
-
- // MARK: - Data
-
- private let model: ActionModel
-
- // MARK: - Views
-
- let disclouserIndicator = SPDimmedButton().do {
- if #available(iOS 13, *) {
- $0.setImage(.system("chevron.right", font: .preferredFont(forTextStyle: .body, weight: .medium)).alwaysTemplate)
- $0.tintColor = .tertiaryLabel
- }
- }
-
- let actionIconView = SPImageView().do {
- $0.contentMode = .scaleAspectFit
- }
-
- let actionTitleLabel = SPLabel().do {
- $0.font = .preferredFont(forTextStyle: .body, weight: .semibold)
- if #available(iOS 13.0, *) {
- $0.textColor = .label
- } else {
- $0.textColor = .black
- }
- $0.numberOfLines = .zero
- }
-
- let actionDescriptionLabel = SPLabel().do {
- $0.font = .preferredFont(forTextStyle: .subheadline)
- if #available(iOS 13.0, *) {
- $0.textColor = .secondaryLabel
- } else {
- $0.textColor = .black
- }
- $0.numberOfLines = .zero
- }
-
- // MARK: - Init
-
- init(with model: ActionModel) {
- self.model = model
- super.init()
- actionIconView.image = model.iconImage
- actionTitleLabel.text = model.title
- actionDescriptionLabel.text = model.description
-
- addTarget(self, action: #selector(self.didTap), for: .touchUpInside)
- }
-
- required init?(coder aDecoder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- public override func commonInit() {
- super.commonInit()
- higlightStyle = .background
- if #available(iOS 13.0, *) {
- applyDefaultAppearance(with: .init(content: .label, background: .secondarySystemBackground))
- }
- roundCorners(radius: NativeLayout.Spaces.default_less)
- layoutMargins = .init(horizontal: NativeLayout.Spaces.default_more, vertical: NativeLayout.Spaces.default_more)
- addSubviews(actionIconView, actionTitleLabel, actionDescriptionLabel, disclouserIndicator)
- }
-
- // MARK: - Layout
-
- public override func layoutSubviews() {
- super.layoutSubviews()
- actionIconView.frame = .init(side: 28)
- actionIconView.frame.origin.x = layoutMargins.left
-
- disclouserIndicator.sizeToFit()
- disclouserIndicator.setMaxXToSuperviewRightMargin()
-
- let leftSpace: CGFloat = NativeLayout.Spaces.default_more
- let rightSpace: CGFloat = NativeLayout.Spaces.default
- let labelWidth = layoutWidth - actionIconView.frame.width - disclouserIndicator.frame.width - leftSpace - rightSpace
-
- actionTitleLabel.layoutDynamicHeight(width: labelWidth)
- actionTitleLabel.frame.origin.x = actionIconView.frame.maxX + leftSpace
- actionTitleLabel.frame.origin.y = layoutMargins.top
-
- actionDescriptionLabel.layoutDynamicHeight(width: labelWidth)
- actionDescriptionLabel.frame.origin.x = actionTitleLabel.frame.origin.x
- actionDescriptionLabel.frame.origin.y = actionTitleLabel.frame.maxY + NativeLayout.Spaces.step
-
- disclouserIndicator.setYCenter()
- actionIconView.setYCenter()
- }
-
- public override func sizeThatFits(_ size: CGSize) -> CGSize {
- layoutSubviews()
- return .init(width: size.width, height: actionDescriptionLabel.frame.maxY + layoutMargins.bottom)
- }
-
- // MARK: - Action
-
- @objc func didTap() {
- self.model.action()
- }
-
- // MARK: - Models
-
- /**
- Wrapper of data for action model.
-
- - important: Recomended save app tint color for icons like native.
- */
- public class ActionModel {
-
- let iconImage: UIImage
- let title: String
- let description: String
- let action: ()->Void
-
- public init(iconImage: UIImage, title: String, description: String, action: @escaping ()->Void) {
- self.iconImage = iconImage
- self.title = title
- self.description = description
- self.action = action
- }
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Controllers/Complex/Onboarding/Actinos/NativeOnboardingActionsController.swift b/Sources/NativeUIKit/Controllers/Complex/Onboarding/Actinos/NativeOnboardingActionsController.swift
deleted file mode 100644
index 560a551..0000000
--- a/Sources/NativeUIKit/Controllers/Complex/Onboarding/Actinos/NativeOnboardingActionsController.swift
+++ /dev/null
@@ -1,85 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-open class NativeOnboardingActionsController: NativeHeaderController {
-
- private var views: [NativeOnbiardingActionButton] = []
-
- // MARK: - Init
-
- public init(
- iconImage: UIImage?,
- title: String,
- subtitle: String
- ) {
- super.init(image: iconImage, title: title, subtitle: subtitle)
- }
-
- public required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- // MARK: - Lifecycle
-
- open override func viewDidLoad() {
- super.viewDidLoad()
- if #available(iOS 13.0, *) {
- self.view.backgroundColor = .systemBackground
- } else {
- view.backgroundColor = .white
- }
- scrollView.addSubviews(views)
- }
-
- open func setActions(_ models: [NativeOnbiardingActionButton.ActionModel]) {
- // Clean old
- views.forEach({ $0.removeFromSuperview() })
- views.removeAll()
-
- // Add new
- views = models.map({ NativeOnbiardingActionButton(with: $0) })
-
- // Added like subviews
- if isViewLoaded {
- scrollView.addSubviews(views)
- }
- }
-
- // MARK: - Layout
-
- open override func viewDidLayoutSubviews() {
- super.viewDidLayoutSubviews()
- var currentYPosition = headerView.frame.maxY + NativeLayout.Spaces.default_double
- let elementWidth: CGFloat = min(scrollView.readableWidth, 320)
- for (_, itemView) in views.enumerated() {
- itemView.setWidthAndFit(width: elementWidth)
- itemView.setXCenter()
- itemView.frame.origin.y = currentYPosition
- currentYPosition = itemView.frame.maxY + NativeLayout.Spaces.default_half
- }
- scrollView.contentSize = .init(width: scrollView.frame.width, height: views.last?.frame.maxY ?? .zero)
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Controllers/Complex/Onboarding/Features/NativeOnboardingFeatureView.swift b/Sources/NativeUIKit/Controllers/Complex/Onboarding/Features/NativeOnboardingFeatureView.swift
deleted file mode 100644
index 85368a3..0000000
--- a/Sources/NativeUIKit/Controllers/Complex/Onboarding/Features/NativeOnboardingFeatureView.swift
+++ /dev/null
@@ -1,132 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-public class NativeOnboardingFeatureView: SPView {
-
- // MARK: - Data
-
- let model: FeatureModel
-
- // MARK: - Views
-
- let iconView = SPImageView().do {
- $0.contentMode = .scaleAspectFit
- }
-
- let titleLabel = SPLabel().do {
- $0.font = .preferredFont(forTextStyle: .title3, weight: .semibold)
- if #available(iOS 13.0, *) {
- $0.textColor = .label
- } else {
- $0.textColor = .black
- }
- $0.numberOfLines = .zero
- }
-
- let descriptionLabel = SPLabel().do {
- $0.font = .preferredFont(forTextStyle: .body)
- if #available(iOS 13.0, *) {
- $0.textColor = .secondaryLabel
- } else {
- $0.textColor = .black
- }
- $0.numberOfLines = .zero
- }
-
- // MARK: - Init
-
- init(with model: FeatureModel) {
- self.model = model
- super.init()
- iconView.image = model.iconImage
- titleLabel.text = model.title
- descriptionLabel.text = model.description
- }
-
- required init?(coder aDecoder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- public override func commonInit() {
- super.commonInit()
- backgroundColor = .clear
- roundCorners(radius: NativeLayout.Spaces.default_less)
- layoutMargins = .init(horizontal: NativeLayout.Spaces.default_more, vertical: NativeLayout.Spaces.default_more)
- addSubviews(iconView, titleLabel, descriptionLabel)
- }
-
- // MARK: - Layout
-
- public override func layoutSubviews() {
- super.layoutSubviews()
- iconView.frame = .init(side: 42)
- iconView.frame.origin.y = layoutMargins.top
- iconView.frame.origin.x = layoutMargins.left
-
- let labelWidth = layoutWidth - iconView.frame.width - NativeLayout.Spaces.default
-
- titleLabel.layoutDynamicHeight(width: labelWidth)
- titleLabel.setMaxXToSuperviewRightMargin()
- titleLabel.frame.origin.y = layoutMargins.top
-
- descriptionLabel.layoutDynamicHeight(width: labelWidth)
- descriptionLabel.frame.origin.x = titleLabel.frame.origin.x
- descriptionLabel.frame.origin.y = titleLabel.frame.maxY + NativeLayout.Spaces.step
- }
-
- public override func sizeThatFits(_ size: CGSize) -> CGSize {
- layoutSubviews()
- return .init(width: size.width, height: descriptionLabel.frame.maxY + layoutMargins.bottom)
- }
-
- // MARK: - Actions
-
- func setProgress(_ value: CGFloat) {
- if #available(iOS 13.0, *) {
- self.backgroundColor = .secondarySystemBackground.alpha(1 - value)
- }
- }
-
- // MARK: - Models
-
- /**
- Wrapper of data for feature model.
-
- - important: Recomended use custom tint color for icons like native.
- */
- public class FeatureModel {
-
- let iconImage: UIImage
- let title: String
- let description: String
-
- public init(iconImage: UIImage, title: String, description: String) {
- self.iconImage = iconImage
- self.title = title
- self.description = description
- }
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Controllers/Complex/Onboarding/Features/NativeOnboardingFeaturesController.swift b/Sources/NativeUIKit/Controllers/Complex/Onboarding/Features/NativeOnboardingFeaturesController.swift
deleted file mode 100644
index a3836c1..0000000
--- a/Sources/NativeUIKit/Controllers/Complex/Onboarding/Features/NativeOnboardingFeaturesController.swift
+++ /dev/null
@@ -1,102 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-open class NativeOnboardingFeaturesController: NativeHeaderController {
-
- private var views: [NativeOnboardingFeatureView] = []
-
- // MARK: - Init
-
- public init(
- iconImage: UIImage?,
- title: String,
- subtitle: String
- ) {
- super.init(image: iconImage, title: title, subtitle: subtitle)
- }
-
- public required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- // MARK: - Lifecycle
-
- open override func viewDidLoad() {
- super.viewDidLoad()
- if #available(iOS 13.0, *) {
- self.view.backgroundColor = .systemBackground
- } else {
- view.backgroundColor = .white
- }
- scrollView.addSubviews(views)
- }
-
- open func setFeatures(_ models: [NativeOnboardingFeatureView.FeatureModel]) {
- // Clean old
- views.forEach({ $0.removeFromSuperview() })
- views.removeAll()
-
- // Add new
- views = models.map({ NativeOnboardingFeatureView(with: $0) })
-
- // Added like subviews
- if isViewLoaded {
- scrollView.addSubviews(views)
- }
- }
-
- // MARK: - Layout
-
- open override func viewDidLayoutSubviews() {
- super.viewDidLayoutSubviews()
- var currentYPosition = headerView.frame.maxY + NativeLayout.Spaces.default_double
- for (_, itemView) in views.enumerated() {
- itemView.setWidthAndFit(width: scrollView.readableWidth)
- itemView.setXCenter()
- itemView.frame.origin.y = currentYPosition
- currentYPosition = itemView.frame.maxY + NativeLayout.Spaces.default_half
- }
- scrollView.contentSize = .init(width: scrollView.frame.width, height: views.last?.frame.maxY ?? .zero)
- }
-
- public func scrollViewDidScroll(_ scrollView: UIScrollView) {
- for itemView in views {
- let progress = progressForFeatureView(itemView)
- itemView.setProgress(progress)
- }
- }
-
- private func progressForFeatureView(_ view: NativeOnboardingFeatureView) -> CGFloat {
- let offsetY = scrollView.contentOffset.y + scrollView.safeAreaInsets.top + scrollView.frame.height - scrollView.safeAreaInsets.bottom
- let correction: CGFloat = NativeLayout.Spaces.Scroll.bottom_inset_reach_end
- let topSafeArea = scrollView.safeAreaInsets.top + correction
- let startPosition = view.frame.origin.y + topSafeArea
- let progress = (offsetY - startPosition) / view.frame.height
- if progress < .zero { return .zero }
- if progress > 1 { return 1 }
- return progress
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Controllers/Complex/Onboarding/NativeOnboardingController.swift b/Sources/NativeUIKit/Controllers/Complex/Onboarding/NativeOnboardingController.swift
deleted file mode 100644
index 8837747..0000000
--- a/Sources/NativeUIKit/Controllers/Complex/Onboarding/NativeOnboardingController.swift
+++ /dev/null
@@ -1,86 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-import SPPageController
-
-open class NativeOnboardingController: SPPageController, NativeOnboardingManagerDelegate {
-
- private let controllers: [UIViewController]
- private let completion: SPCompletion
-
- // MARK: - Init
-
- public init(controllers: [UIViewController], completion: @escaping SPCompletion) {
-
- self.controllers = controllers
- self.completion = completion
-
- var childControllers: [UIViewController] = []
- for controller in controllers {
- let navigationController = NativeNavigationController(rootViewController: controller)
- navigationController.inheritLayoutMarginsForСhilds = true
- navigationController.inheritLayoutMarginsForNavigationBar = true
- navigationController.view.preservesSuperviewLayoutMargins = true
- childControllers.append(navigationController)
- }
-
- super.init(childControllers: childControllers, system: .page)
-
- controllers.forEach { controller in
- let onboardingChildController = controller as! NativeOnboardingChildInterface
- onboardingChildController.onboardingManagerDelegate = self
- }
-
- allowScroll = false
- allowDismissWithGester = false
- }
-
- public required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- // MARK: - OnboardingManagerDelegate
-
- public func onboardingActionComplete(for controller: UIViewController) {
- guard let index = controllers.firstIndex(of: controller) else { return }
- if index == (controllers.count - 1) {
- dismiss(animated: true) { [weak self] in
- self?.completion()
- }
- } else {
- safeScrollTo(index: index + 1, animated: true)
- }
- }
-}
-
-public protocol NativeOnboardingManagerDelegate: AnyObject {
-
- func onboardingActionComplete(for controller: UIViewController)
-}
-
-public protocol NativeOnboardingChildInterface: AnyObject {
-
- var onboardingManagerDelegate: NativeOnboardingManagerDelegate? { get set }
-}
-#endif
diff --git a/Sources/NativeUIKit/Controllers/Complex/Profile/NativeAvatarHeaderView.swift b/Sources/NativeUIKit/Controllers/Complex/Profile/NativeAvatarHeaderView.swift
deleted file mode 100644
index 4fe82d7..0000000
--- a/Sources/NativeUIKit/Controllers/Complex/Profile/NativeAvatarHeaderView.swift
+++ /dev/null
@@ -1,79 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-@available(iOS 13.0, *)
-open class NativeAvatarHeaderView: SPView {
-
- // MARK: - Public
-
- public let avatarView = NativeAvatarView().do {
- $0.avatarAppearance = .placeholder
- $0.isEditable = true
- }
-
- // MARK: - Private
-
- private var extendView = SPView()
-
- // MARK: - Init
-
- open override func commonInit() {
- super.commonInit()
- backgroundColor = .clear
- addSubviews([extendView, avatarView])
-
- layoutMargins = .init(
- top: NativeLayout.Spaces.default,
- left: NativeLayout.Spaces.default_double,
- bottom: NativeLayout.Spaces.default_more,
- right: NativeLayout.Spaces.default_double
- )
- }
-
- // MARK: - Ovveride
-
- open override var backgroundColor: UIColor? {
- didSet {
- extendView.backgroundColor = backgroundColor
- }
- }
-
- // MARK: - Layout
-
- open override func layoutSubviews() {
- super.layoutSubviews()
- extendView.frame = .init(x: .zero, maxY: .zero, width: frame.width, height: 1000)
-
- avatarView.sizeToFit()
- avatarView.setXCenter()
- avatarView.frame.origin.y = layoutMargins.top
- }
-
- open override func sizeThatFits(_ size: CGSize) -> CGSize {
- layoutSubviews()
- return .init(width: frame.width, height: avatarView.frame.maxY + layoutMargins.bottom)
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Controllers/Complex/Profile/NativeProfileController.swift b/Sources/NativeUIKit/Controllers/Complex/Profile/NativeProfileController.swift
deleted file mode 100644
index ac748bc..0000000
--- a/Sources/NativeUIKit/Controllers/Complex/Profile/NativeProfileController.swift
+++ /dev/null
@@ -1,51 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-import SPDiffable
-
-@available(iOS 13.0, *)
-open class NativeProfileController: NativeHeaderTableController {
-
- // MARK: - Views
-
- public let headerView = NativeAvatarHeaderView()
-
- // MARK: - Init
-
- public init(style: UITableView.Style = .insetGrouped) {
- super.init(style: style, headerView: headerView)
- }
-
- public required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- // MARK: - Lifecycle
-
- open override func viewDidLoad() {
- super.viewDidLoad()
- navigationItem.title = .empty
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Controllers/Complex/Profile/NativeProfileHeaderView.swift b/Sources/NativeUIKit/Controllers/Complex/Profile/NativeProfileHeaderView.swift
deleted file mode 100644
index c32b701..0000000
--- a/Sources/NativeUIKit/Controllers/Complex/Profile/NativeProfileHeaderView.swift
+++ /dev/null
@@ -1,144 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-@available(iOS 13.0, *)
-open class NativeProfileHeaderView: SPView {
-
- // MARK: - Public
-
- public let avatarView = NativeAvatarView().do {
- $0.avatarAppearance = .placeholder
- $0.isEditable = true
- }
-
- public let nameLabel = SPLabel().do {
- $0.font = UIFont.preferredFont(forTextStyle: .title2, weight: .semibold, addPoints: 2)
- $0.textColor = .label
- $0.numberOfLines = 1
- $0.textAlignment = .center
- // $0.adjustsFontSizeToFitWidth = true
- // $0.minimumScaleFactor = 0.5
- $0.text = nil
- }
-
- public let namePlaceholderLabel = SPLabel().do {
- $0.font = UIFont.preferredFont(forTextStyle: .title2, weight: .semibold, addPoints: 2)
- $0.textColor = .secondaryLabel
- $0.numberOfLines = 1
- $0.textAlignment = .center
- // $0.adjustsFontSizeToFitWidth = true
- // $0.minimumScaleFactor = 0.5
- $0.text = nil
- }
-
- // Add tap to clipboard
- public let emailButton = SPDimmedButton().do {
- $0.titleLabel?.font = UIFont.preferredFont(forTextStyle: .body, weight: .regular, addPoints: -2)
- // $0.titleLabel?.adjustsFontSizeToFitWidth = true
- // $0.titleLabel?.minimumScaleFactor = 0.5
- $0.titleImageInset = 2
- $0.titleLabel?.textAlignment = .center
- }
-
- // MARK: - Private
-
- private var extendView = SPView()
-
- var nameTextObserer: NSKeyValueObservation?
-
- // MARK: - Init
-
- open override func commonInit() {
- super.commonInit()
- backgroundColor = .clear
- addSubviews([extendView, avatarView, nameLabel, namePlaceholderLabel, emailButton])
-
- layoutMargins = .init(
- top: NativeLayout.Spaces.default_half,
- left: NativeLayout.Spaces.default_double,
- bottom: NativeLayout.Spaces.default_half,
- right: NativeLayout.Spaces.default_double
- )
-
- self.nameLabel.isHidden = !(self.nameLabel == self.usingNameLabel)
- self.namePlaceholderLabel.isHidden = !(self.namePlaceholderLabel == self.usingNameLabel)
-
- nameTextObserer = nameLabel.observe(\.text) { [weak self] _, _ in
- guard let self = self else { return }
- self.nameLabel.isHidden = !(self.nameLabel == self.usingNameLabel)
- self.namePlaceholderLabel.isHidden = !(self.namePlaceholderLabel == self.usingNameLabel)
- }
- }
-
- // MARK: - Ovveride
-
- open override var backgroundColor: UIColor? {
- didSet {
- extendView.backgroundColor = backgroundColor
- }
- }
-
- // MARK: - Layout
-
- private var usingNameLabel: SPLabel {
- if nameLabel.text?.isEmptyContent ?? true {
- return namePlaceholderLabel
- } else {
- return nameLabel
- }
- }
-
- open override func layoutSubviews() {
- super.layoutSubviews()
- extendView.frame = .init(x: .zero, maxY: .zero, width: frame.width, height: 1000)
-
- avatarView.sizeToFit()
- avatarView.setXCenter()
- avatarView.frame.origin.y = layoutMargins.top
-
- let textWidth: CGFloat = layoutWidth * 0.8
-
- nameLabel.layoutDynamicHeight(width: textWidth)
- nameLabel.setXCenter()
- nameLabel.frame.origin.y = avatarView.frame.maxY + NativeLayout.Spaces.default_half
-
- namePlaceholderLabel.layoutDynamicHeight(width: textWidth)
- namePlaceholderLabel.setXCenter()
- namePlaceholderLabel.frame.origin.y = nameLabel.frame.origin.y
-
- emailButton.sizeToFit()
- if emailButton.frame.width > textWidth {
- emailButton.frame.setWidth(textWidth)
- }
- emailButton.setXCenter()
- emailButton.frame.origin.y = usingNameLabel.frame.maxY
- }
-
- open override func sizeThatFits(_ size: CGSize) -> CGSize {
- layoutSubviews()
- return .init(width: frame.width, height: emailButton.frame.maxY + layoutMargins.bottom)
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Controllers/Navigation/NativeNavigationController.swift b/Sources/NativeUIKit/Controllers/Navigation/NativeNavigationController.swift
deleted file mode 100644
index 9628476..0000000
--- a/Sources/NativeUIKit/Controllers/Navigation/NativeNavigationController.swift
+++ /dev/null
@@ -1,80 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-open class NativeNavigationController: SPNavigationController {
-
- // MARK: - Views
-
- open var mimicrateToolBarView: NativeMimicrateToolBarView? = nil {
- willSet {
- if let toolBarView = mimicrateToolBarView {
- toolBarView.removeFromSuperview()
- }
- }
- didSet {
- if let toolBarView = mimicrateToolBarView {
- view.addSubview(toolBarView)
- }
- }
- }
-
- open override func setToolbarHidden(_ hidden: Bool, animated: Bool) {
- if let barView = mimicrateToolBarView {
- if animated {
-
- if barView.isHidden && !hidden {
- barView.isHidden = false
- barView.alpha = .zero
- }
-
- UIView.animate(withDuration: 0.12, delay: .zero, options: [.beginFromCurrentState, .curveEaseInOut], animations: {
- barView.alpha = hidden ? .zero : 1
- }) { completed in
- barView.isHidden = hidden
- }
- } else {
- barView.isHidden = hidden
- }
- } else {
- super.setToolbarHidden(hidden, animated: animated)
- }
- }
-
- // MARK: - Layout
-
- open override func viewDidLayoutSubviews() {
- super.viewDidLayoutSubviews()
- if let toolBarView = mimicrateToolBarView {
- toolBarView.layoutMargins.bottom = systemSafeAreaInsets.bottom + 16
- toolBarView.setWidthAndFit(width: view.frame.width)
- toolBarView.frame.setMaxY(view.frame.height)
- let toolBarFrameFitHeight = toolBarView.frame.height - systemSafeAreaInsets.bottom
- if additionalSafeAreaInsets.bottom != toolBarFrameFitHeight {
- additionalSafeAreaInsets.bottom = toolBarFrameFitHeight
- }
- }
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Controllers/Scroll/NativeHeaderController.swift b/Sources/NativeUIKit/Controllers/Scroll/NativeHeaderController.swift
deleted file mode 100644
index 2d7d01a..0000000
--- a/Sources/NativeUIKit/Controllers/Scroll/NativeHeaderController.swift
+++ /dev/null
@@ -1,57 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-open class NativeHeaderController: SPScrollController {
-
- // MARK: - Views
-
- public let headerView: NativeModalHeaderView
-
- // MARK: - Init
-
- public init(image: UIImage?, title: String, subtitle: String) {
- self.headerView = NativeModalHeaderView(image: image, title: title, subtitle: subtitle)
- super.init()
- }
-
- public required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- // MARK: - Lifecycle
-
- open override func viewDidLoad() {
- super.viewDidLoad()
- scrollView.contentInset.bottom = NativeLayout.Spaces.Scroll.bottom_inset_reach_end
- scrollView.addSubview(headerView)
- }
-
- open override func viewDidLayoutSubviews() {
- super.viewDidLayoutSubviews()
- headerView.layout(y: NativeLayout.Spaces.default)
- scrollView.contentSize = .init(width: view.frame.width, height: headerView.frame.maxY)
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Controllers/Scroll/NativeHeaderFullWidthImageController.swift b/Sources/NativeUIKit/Controllers/Scroll/NativeHeaderFullWidthImageController.swift
deleted file mode 100644
index 0b8a579..0000000
--- a/Sources/NativeUIKit/Controllers/Scroll/NativeHeaderFullWidthImageController.swift
+++ /dev/null
@@ -1,60 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-@available(iOS 13.0, *)
-open class NativeHeaderFullWidthImageController: SPScrollController {
-
- // MARK: - Views
-
- public let headerImageView = SPImageView().do {
- $0.backgroundColor = .systemGray.alpha(0.1)
- $0.contentMode = .scaleAspectFill
- }
-
- public let titlesView = NativeModalHeaderView()
-
- // MARK: - Lifecycle
-
- open override func viewDidLoad() {
- super.viewDidLoad()
- view.backgroundColor = .secondarySystemBackground
- scrollView.showsVerticalScrollIndicator = false
- scrollView.addSubviews([headerImageView, titlesView])
- navigationController?.navigationBar.setAppearance(.transparentAlways)
- }
-
- // MARK: - Layout
-
- open override func viewDidLayoutSubviews() {
- super.viewDidLayoutSubviews()
- headerImageView.frame = .init(x: .zero, y: -scrollView.layoutMargins.top, width: view.frame.width, height: view.frame.height * 0.45)
- titlesView.layout(y: headerImageView.frame.maxY + NativeLayout.Spaces.default_double)
- scrollView.contentSize = .init(
- width: view.frame.width,
- height: titlesView.frame.maxY + NativeLayout.Spaces.default_double
- )
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Controllers/Scroll/NativeHeaderTextFieldController.swift b/Sources/NativeUIKit/Controllers/Scroll/NativeHeaderTextFieldController.swift
deleted file mode 100644
index 7274274..0000000
--- a/Sources/NativeUIKit/Controllers/Scroll/NativeHeaderTextFieldController.swift
+++ /dev/null
@@ -1,59 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-open class NativeHeaderTextFieldController: NativeHeaderController {
-
- // MARK: - Views
-
- public let textField = NativeLargeTextField().do {
- $0.returnKeyType = .done
- $0.autocapitalizationType = .words
- }
-
- public let footerView = NativeFooterView()
-
- // MARK: - Lifecycle
-
- open override func viewDidLoad() {
- super.viewDidLoad()
- if #available(iOS 13.0, *) {
- view.backgroundColor = .systemBackground
- }
- scrollView.addSubviews(textField, footerView)
- dismissKeyboardWhenTappedAround()
- }
-
- // MARK: - Layout
-
- open override func viewDidLayoutSubviews() {
- super.viewDidLayoutSubviews()
- textField.layout(y: headerView.frame.maxY + NativeLayout.Spaces.default + NativeLayout.Spaces.default_half)
- footerView.setWidthAndFit(width: textField.frame.width)
- footerView.frame.origin.x = textField.frame.origin.x
- footerView.frame.origin.y = textField.frame.maxY
- scrollView.contentSize = .init(width: view.frame.width, height: footerView.frame.maxY)
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Controllers/Table/Header/NativeHeaderTableController+HeaderContainerView.swift b/Sources/NativeUIKit/Controllers/Table/Header/NativeHeaderTableController+HeaderContainerView.swift
deleted file mode 100644
index e9c702f..0000000
--- a/Sources/NativeUIKit/Controllers/Table/Header/NativeHeaderTableController+HeaderContainerView.swift
+++ /dev/null
@@ -1,71 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-import SPDiffable
-
-@available(iOS 13.0, *)
-extension NativeHeaderTableController {
-
- open class HeaderContainerView: SPView {
-
- // MARK: - Public
-
- public let contentView: UIView
-
- // MARK: - Init
-
- public init(contentView: UIView) {
- self.contentView = contentView
- super.init()
- }
-
- public required init?(coder aDecoder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- public override func commonInit() {
- super.commonInit()
- insetsLayoutMarginsFromSafeArea = false
- contentView.insetsLayoutMarginsFromSafeArea = false
- layoutMargins = .zero
- addSubview(contentView)
- }
-
- // MARK: - Layout
-
- public override func layoutSubviews() {
- super.layoutSubviews()
- contentView.setWidthAndFit(width: layoutWidth)
- contentView.frame.origin.x = layoutMargins.left
- contentView.frame.origin.y = layoutMargins.top
- }
-
- public override func sizeThatFits(_ size: CGSize) -> CGSize {
- frame.setWidth(size.width)
- layoutSubviews()
- return .init(width: size.width, height: contentView.frame.maxY + layoutMargins.bottom)
- }
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Controllers/Table/Header/NativeHeaderTableController.swift b/Sources/NativeUIKit/Controllers/Table/Header/NativeHeaderTableController.swift
deleted file mode 100644
index dce3b98..0000000
--- a/Sources/NativeUIKit/Controllers/Table/Header/NativeHeaderTableController.swift
+++ /dev/null
@@ -1,77 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-import SPDiffable
-
-@available(iOS 13.0, *)
-open class NativeHeaderTableController: SPDiffableTableController {
-
- // MARK: - Public
-
- open var headerContainerView: HeaderContainerView
-
- // MARK: - Init
-
- public init(style: UITableView.Style, headerView: UIView) {
- self.headerContainerView = HeaderContainerView(contentView: headerView)
- super.init(style: style)
- }
-
- public required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- // MARK: - Lifecycle
-
- open override func viewDidLoad() {
- super.viewDidLoad()
- headerContainerView.setWidthAndFit(width: view.frame.width)
- tableView.tableHeaderView = headerContainerView
- }
-
- // MARK: - Layout
-
- open override func viewDidLayoutSubviews() {
- super.viewDidLayoutSubviews()
- headerContainerView.contentView.layoutMargins.left = tableView.layoutMargins.left
- headerContainerView.contentView.layoutMargins.right = tableView.layoutMargins.right
- headerContainerView.setWidthAndFit(width: view.frame.width)
- if cachedHeaderHeight != headerContainerView.frame.height {
- cachedHeaderHeight = headerContainerView.frame.height
- DispatchQueue.main.async { [weak self] in
- guard let self = self else { return }
- self.diffableDataSource?.updateLayout(animated: true, completion: nil)
- }
- }
- }
-
- private var cachedHeaderHeight: CGFloat? = nil
-
- // MARK: - Public
-
- open func setSpaceBetweenHeaderAndCells(_ value: CGFloat) {
- headerContainerView.layoutMargins.bottom = value
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Controls/Buttons/NativeLargeActionButton.swift b/Sources/NativeUIKit/Controls/Buttons/NativeLargeActionButton.swift
deleted file mode 100644
index 6774564..0000000
--- a/Sources/NativeUIKit/Controls/Buttons/NativeLargeActionButton.swift
+++ /dev/null
@@ -1,118 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-/**
- NativeUIKit: Large action button.
- Usually using at bottom of screen.
- */
-open class NativeLargeActionButton: SPDimmedButton {
-
- // MARK: - Init
-
- open override func commonInit() {
- super.commonInit()
- insetsLayoutMarginsFromSafeArea = false
- preservesSuperviewLayoutMargins = false
- titleLabel?.font = UIFont.preferredFont(forTextStyle: .headline, addPoints: 1)
- titleLabel?.numberOfLines = 1
- highlightOpacity = NativeAppearance.actionable_element_highlight_opacity
- titleImageInset = 6
- contentEdgeInsets = .init(horizontal: 10, vertical: 12)
- roundCorners(radius: NativeAppearance.Corners.readable_area)
- }
-
- // MARK: - Public
-
- /**
- NativeUIKit: Wrapper of set content and color of button.
-
- - parameter title: Text which using like title.
- - parameter icon: Object of `UIImage`, using like icon.
- - parameter colorise: Color of button in default state.
- */
- public func set(title: String, icon: UIImage?, colorise: SPDimmedButton.Colorise) {
- setTitle(title)
- if let icon = icon {
- setImage(icon.alwaysTemplate)
- }
- applyDefaultAppearance(with: colorise)
- }
-
- // MARK: - Layout
-
- /**
- NativeUIKit: Layout wrapper. Native way for layout button.
- */
- open func layout(y: CGFloat) {
- guard let superview = self.superview else { return }
- sizeToFit()
- let width = min(superview.readableWidth, NativeLayout.Sizes.actionable_area_maximum_width)
- frame.setWidth(width)
- setXCenter()
- frame.origin.y = y
- }
-
- /**
- NativeUIKit: Layout wrapper. Native way for layout button.
- */
- open func layout(maxY: CGFloat) {
- guard let superview = self.superview else { return }
- sizeToFit()
- let width = min(superview.readableWidth, NativeLayout.Sizes.actionable_area_maximum_width)
- frame.setWidth(width)
- setXCenter()
- frame.setMaxY(maxY)
- }
-
- open override func sizeThatFits(_ size: CGSize) -> CGSize {
- let superSize = super.sizeThatFits(size)
- let width = superSize.width
-
- var height = superSize.height
- if let titleLabel = titleLabel, let imageView = imageView, let _ = imageView.image {
- if titleLabel.frame.height > .zero && imageView.frame.height > .zero {
- let imageCorrection = imageView.frame.height - titleLabel.frame.height
- height -= imageCorrection
- }
- }
-
- return CGSize(width: width, height: height)
- }
-
- // MARK: - Wrappers
-
- public static var defaultCornerRadius: CGFloat {
- let button = NativeLargeActionButton()
- return button.layer.cornerRadius
- }
-
- public static var defaultHeight: CGFloat {
- let button = NativeLargeActionButton()
- button.setTitle(.space)
- button.sizeToFit()
- return button.frame.height
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Controls/Buttons/NativeMediumActionButton.swift b/Sources/NativeUIKit/Controls/Buttons/NativeMediumActionButton.swift
deleted file mode 100644
index a9cd771..0000000
--- a/Sources/NativeUIKit/Controls/Buttons/NativeMediumActionButton.swift
+++ /dev/null
@@ -1,89 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-/**
- NativeUIKit: Medium action button.
- You see it in Apply Music play and shuffle buttons.
- */
-open class NativeMediumActionButton: SPDimmedButton {
-
- // MARK: - Init
-
- open override func commonInit() {
- super.commonInit()
- titleLabel?.font = UIFont.preferredFont(forTextStyle: .body, weight: .semibold, addPoints: .zero)
- titleLabel?.numberOfLines = 1
- titleImageInset = 8
- contentEdgeInsets = .init(horizontal: 15, vertical: 15)
- roundCorners(radius: 12)
- }
-
- // MARK: - Public
-
- /**
- NativeUIKit: Wrapper of set content and color of button.
-
- - parameter title: Text which using like title.
- - parameter icon: Object of `UIImage`, using like icon. Usually Apple doesn't use icon in this button.
- - parameter colorise: Color of button in default state.
- */
- public func set(title: String, icon: UIImage? = nil, colorise: SPDimmedButton.Colorise) {
- setTitle(title)
- if let icon = icon {
- setImage(icon.alwaysTemplate)
- }
- applyDefaultAppearance(with: colorise)
- }
-
- open override func sizeThatFits(_ size: CGSize) -> CGSize {
- let superSize = super.sizeThatFits(size)
- let width = superSize.width
-
- var height = superSize.height
- if let titleLabel = titleLabel, let imageView = imageView, let _ = imageView.image {
- if titleLabel.frame.height > .zero && imageView.frame.height > .zero {
- let imageCorrection = imageView.frame.height - titleLabel.frame.height
- height -= imageCorrection
- }
- }
-
- return CGSize(width: width, height: height)
- }
-
- // MARK: - Wrappers
-
- public static var defaultCornerRadius: CGFloat {
- let button = NativeMediumActionButton()
- return button.layer.cornerRadius
- }
-
- public static var defaultHeight: CGFloat {
- let button = NativeMediumActionButton()
- button.setTitle(.space)
- button.sizeToFit()
- return button.frame.height
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Controls/Buttons/NativeSmallActionButton.swift b/Sources/NativeUIKit/Controls/Buttons/NativeSmallActionButton.swift
deleted file mode 100644
index 2def7eb..0000000
--- a/Sources/NativeUIKit/Controls/Buttons/NativeSmallActionButton.swift
+++ /dev/null
@@ -1,89 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-/**
- NativeUIKit: Small action button.
- Using inside cells.
- */
-open class NativeSmallActionButton: SPDimmedButton {
-
- // MARK: - Init
-
- open override func commonInit() {
- super.commonInit()
- titleLabel?.font = UIFont.preferredFont(forTextStyle: .subheadline, weight: .bold, addPoints: -1)
- titleLabel?.numberOfLines = 1
- titleImageInset = 6
- contentEdgeInsets = .init(horizontal: 10, vertical: 6)
- }
-
- // MARK: - Public
-
- /**
- NativeUIKit: Wrapper of set content and color of button.
-
- - parameter title: Text which using like title.
- - parameter icon: Object of `UIImage`, using like icon. Usually Apple doesn't use icon in this button.
- - parameter colorise: Color of button in default state.
- */
- public func set(title: String, icon: UIImage? = nil, colorise: SPDimmedButton.Colorise) {
- setTitle(title)
- if let icon = icon {
- setImage(icon.alwaysTemplate)
- }
- applyDefaultAppearance(with: colorise)
- }
-
- // MARK: - Layout
-
- open override func layoutSubviews() {
- super.layoutSubviews()
- roundMinimumSide()
- }
-
- open override func sizeThatFits(_ size: CGSize) -> CGSize {
- let superSize = super.sizeThatFits(size)
- var width = superSize.width
- let minimumWidth: CGFloat = 70
- if width < minimumWidth { width = minimumWidth }
-
- var height = superSize.height
- if let titleLabel = titleLabel, let imageView = imageView, let _ = imageView.image {
- if titleLabel.frame.height > .zero && imageView.frame.height > .zero {
- let imageCorrection = imageView.frame.height - titleLabel.frame.height
- height -= imageCorrection
- }
- }
-
- return CGSize(width: width, height: height)
- }
-
- // MARK: - Ovveride
-
- open override func setTitle(_ title: String?, for state: UIControl.State) {
- super.setTitle(title?.uppercased(), for: state)
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Controls/NativeLargeTextField.swift b/Sources/NativeUIKit/Controls/NativeLargeTextField.swift
deleted file mode 100644
index d55dc1b..0000000
--- a/Sources/NativeUIKit/Controls/NativeLargeTextField.swift
+++ /dev/null
@@ -1,80 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-open class NativeLargeTextField: SPInsetsTextField {
-
- // MARK: - Init
-
- open override func commonInit() {
- super.commonInit()
- if #available(iOS 13.0, *) {
- backgroundColor = .secondarySystemBackground
- } else {
- backgroundColor = .white
- }
- layer.cornerRadius = NativeAppearance.Corners.readable_area
- textAlignment = .center
- clearButtonMode = .whileEditing
- contentMode = .scaleAspectFit
- font = .preferredFont(forTextStyle: .title2, weight: .bold, addPoints: .zero)
- adjustsFontSizeToFitWidth = true
- minimumFontSize = 16
- insets = .init(horizontal: 48, vertical: 14)
- }
-
- // MARK: - Lifecycle
-
- open override func tintColorDidChange() {
- super.tintColorDidChange()
- textColor = tintColor
- }
-
- // MARK: - Layout
-
- /**
- NativeUIKit: Layout wrapper. Native way for layout button.
- */
- open func layout(y: CGFloat) {
- guard let superview = self.superview else { return }
- sizeToFit()
- let width = min(superview.readableWidth, NativeLayout.Sizes.actionable_area_maximum_width)
- frame.setWidth(width)
- setXCenter()
- frame.origin.y = y
- }
-
- /**
- NativeUIKit: Layout wrapper. Native way for layout button.
- */
- open func layout(maxY: CGFloat) {
- guard let superview = self.superview else { return }
- sizeToFit()
- let width = min(superview.readableWidth, NativeLayout.Sizes.actionable_area_maximum_width)
- frame.setWidth(width)
- setXCenter()
- frame.setMaxY(maxY)
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Controls/NativePlayPauseCompactButton.swift b/Sources/NativeUIKit/Controls/NativePlayPauseCompactButton.swift
deleted file mode 100644
index 90b9140..0000000
--- a/Sources/NativeUIKit/Controls/NativePlayPauseCompactButton.swift
+++ /dev/null
@@ -1,67 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-@available(iOS 13, *)
-open class NativePlayPauseCompactButton: SPDimmedButton {
-
- // MARK: - Data
-
- open var appearance: Appearance = .play {
- didSet {
- updateAppearance()
- }
- }
- open var playImage = UIImage.system("play.fill", font: .preferredFont(forTextStyle: .body))
- open var pauseImage = UIImage.system("pause.fill", font: .preferredFont(forTextStyle: .body))
-
- // MARK: - Init
-
- open override func commonInit() {
- super.commonInit()
- contentEdgeInsets = .init(side: 8)
- applyDefaultAppearance(with: .tintedContent)
- updateAppearance()
- }
-
- // MARK: - Internal
-
- internal func updateAppearance() {
- switch self.appearance {
- case .play:
- setImage(playImage)
- case .pause:
- setImage(pauseImage)
- }
- }
-
- // MARK: - Models
-
- public enum Appearance {
-
- case play
- case pause
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Labels/NativeFooterView.swift b/Sources/NativeUIKit/Labels/NativeFooterView.swift
deleted file mode 100644
index f599aa6..0000000
--- a/Sources/NativeUIKit/Labels/NativeFooterView.swift
+++ /dev/null
@@ -1,69 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-open class NativeFooterView: SPView {
-
- // MARK: - Views
-
- public let label = SPLabel().do {
- $0.font = .preferredFont(forTextStyle: .footnote, addPoints: 1)
- $0.numberOfLines = .zero
- if #available(iOS 13.0, *) {
- $0.textColor = .secondaryLabel
- } else {
- $0.textColor = .gray
- }
- }
-
- public override init() {
- super.init()
- }
-
- public init(text: String) {
- super.init()
- label.text = text
- }
-
- required public init?(coder aDecoder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- open override func commonInit() {
- super.commonInit()
- layoutMargins = .init(top: NativeLayout.Spaces.default_half, left: 16, bottom: NativeLayout.Spaces.default_half, right: .zero)
- addSubview(label)
- }
-
- open override func layoutSubviews() {
- super.layoutSubviews()
- label.layoutDynamicHeight(x: layoutMargins.left, y: layoutMargins.top, width: layoutWidth)
- }
-
- open override func sizeThatFits(_ size: CGSize) -> CGSize {
- layoutSubviews()
- return .init(width: size.width, height: label.frame.maxY + layoutMargins.bottom)
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Labels/NativeModalHeaderView.swift b/Sources/NativeUIKit/Labels/NativeModalHeaderView.swift
deleted file mode 100644
index 70152d1..0000000
--- a/Sources/NativeUIKit/Labels/NativeModalHeaderView.swift
+++ /dev/null
@@ -1,131 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-/**
- NativeUIKit: Usually use in modal screen with large title and subtitle.
- Image is optional.
- */
-open class NativeModalHeaderView: SPView {
-
- // MARK: - Views
-
- public let iconImageView = SPImageView().do {
- $0.contentMode = .scaleAspectFit
- $0.tintColor = UIColor.tint
- }
-
- public let titleLabel = SPLabel().do {
- $0.numberOfLines = .zero
- $0.font = UIFont.preferredFont(forTextStyle: .largeTitle, weight: .bold)
- if #available(iOS 13.0, *) {
- $0.textColor = .label
- } else {
- $0.textColor = .black
- }
- $0.textAlignment = .center
- }
-
- public let subtitleLabel = SPLabel().do {
- $0.numberOfLines = .zero
- $0.font = UIFont.preferredFont(forTextStyle: .body)
- if #available(iOS 13.0, *) {
- $0.textColor = .secondaryLabel
- } else {
- $0.textColor = .black.alpha(0.5)
- }
- $0.textAlignment = .center
- }
-
- // MARK: - Init
-
- public override init() {
- super.init()
- }
-
- public init(image: UIImage?, title: String, subtitle: String) {
- super.init()
- titleLabel.text = title
- subtitleLabel.text = subtitle
- iconImageView.image = image
- }
-
- public required init?(coder aDecoder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- open override func commonInit() {
- super.commonInit()
- backgroundColor = .clear
- layoutMargins = .zero
- addSubview(titleLabel)
- addSubview(subtitleLabel)
- addSubview(iconImageView)
- }
-
- // MARK: - Layout
-
- /**
- NativeUIKit: Layout wrapper. Native way for layout button.
- */
- open func layout(y: CGFloat) {
- guard let superview = self.superview else { return }
- let width = min(superview.readableWidth, NativeLayout.Sizes.not_actionable_area_maximum_width)
- setWidthAndFit(width: width)
- setXCenter()
- frame.origin.y = y
- }
-
- /**
- NativeUIKit: Layout wrapper. Native way for layout button.
- */
- open func layout(maxY: CGFloat) {
- guard let superview = self.superview else { return }
- let width = min(superview.readableWidth, NativeLayout.Sizes.not_actionable_area_maximum_width)
- setWidthAndFit(width: width)
- setXCenter()
- frame.setMaxY(maxY)
- }
-
- open override func layoutSubviews() {
- super.layoutSubviews()
- iconImageView.frame = .init(side: NativeLayout.Spaces.default_double * 2)
- iconImageView.setXCenter()
- iconImageView.frame.origin.y = layoutMargins.top
-
- if let _ = iconImageView.image {
- titleLabel.layoutDynamicHeight(x: .zero, y: iconImageView.frame.maxY + 12, width: layoutWidth)
- } else {
- titleLabel.layoutDynamicHeight(x: .zero, y: .zero, width: layoutWidth)
- }
-
- subtitleLabel.layoutDynamicHeight(x: .zero, y: titleLabel.frame.maxY + 4, width: titleLabel.frame.width)
- }
-
- open override func sizeThatFits(_ size: CGSize) -> CGSize {
- layoutSubviews()
- return .init(width: size.width, height: subtitleLabel.frame.maxY + layoutMargins.bottom)
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/NativeAppearance.swift b/Sources/NativeUIKit/NativeAppearance.swift
deleted file mode 100644
index 0ee6c9f..0000000
--- a/Sources/NativeUIKit/NativeAppearance.swift
+++ /dev/null
@@ -1,34 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-
-enum NativeAppearance {
-
- enum Corners {
-
- static var readable_area: CGFloat { 15 }
- }
-
- static var actionable_element_highlight_opacity: CGFloat { 0.6 }
-}
-#endif
diff --git a/Sources/NativeUIKit/NativeLayout.swift b/Sources/NativeUIKit/NativeLayout.swift
deleted file mode 100644
index 99a574d..0000000
--- a/Sources/NativeUIKit/NativeLayout.swift
+++ /dev/null
@@ -1,58 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-
-public enum NativeLayout {
-
- public enum Sizes {
-
- public static var actionable_area_maximum_width: CGFloat { 408 }
- public static var not_actionable_area_maximum_width: CGFloat { 382 }
- }
-
- public enum Spaces {
-
- public static var step: CGFloat = 4
-
- public static var default_less: CGFloat { step * 3 }
- public static var `default`: CGFloat { step * 4 }
- public static var default_more: CGFloat { step * 5 }
-
- public static var default_half: CGFloat { self.default / 2 }
- public static var default_double: CGFloat { self.default * 2 }
-
- public enum Margins {
-
- public static var full_screen_horizontal: CGFloat { Spaces.default }
- public static var modal_screen_horizontal: CGFloat { step * 5 }
- }
-
- public enum Scroll {
-
- public static var top_inset_transparent_navigation: CGFloat { step * 2 }
- public static var bottom_inset_reach_end: CGFloat { step * 9 }
- public static var bottom_inset_when_keyboard_can_appear: CGFloat { step * 8 }
- }
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Table/Button/CellProvider+Button.swift b/Sources/NativeUIKit/Table/Button/CellProvider+Button.swift
deleted file mode 100644
index 5605bfb..0000000
--- a/Sources/NativeUIKit/Table/Button/CellProvider+Button.swift
+++ /dev/null
@@ -1,44 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SPDiffable
-
-@available(iOS 13.0, *)
-extension SPDiffableTableDataSource.CellProvider {
-
- public static var button: SPDiffableTableDataSource.CellProvider {
- return SPDiffableTableDataSource.CellProvider() { (tableView, indexPath, item) -> UITableViewCell? in
- guard let item = item as? NativeDiffableLeftButton else { return nil }
- let cell = tableView.dequeueReusableCell(withClass: NativeLeftButtonTableViewCell.self, for: indexPath)
- cell.textLabel?.text = item.text
- cell.textLabel?.textColor = item.textColor
- cell.detailTextLabel?.text = item.detail
- cell.detailTextLabel?.textColor = item.detailColor
- cell.imageView?.image = item.icon
- cell.accessoryType = item.accessoryType
- cell.higlightStyle = item.higlightStyle
- return cell
- }
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Table/Button/NativeDiffableLeftButton.swift b/Sources/NativeUIKit/Table/Button/NativeDiffableLeftButton.swift
deleted file mode 100644
index bf392c5..0000000
--- a/Sources/NativeUIKit/Table/Button/NativeDiffableLeftButton.swift
+++ /dev/null
@@ -1,59 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-import SPDiffable
-
-@available(iOS 13.0, *)
-open class NativeDiffableLeftButton: SPDiffableTableRow {
-
- open var textColor: UIColor
- open var detailColor: UIColor
- open var higlightStyle: SPTableViewCell.HiglightStyle
-
- public init(
- id: String? = nil,
- text: String,
- textColor: UIColor = .label,
- detail: String? = nil,
- detailColor: UIColor = .secondaryLabel,
- icon: UIImage? = nil,
- accessoryType: UITableViewCell.AccessoryType = .none,
- higlightStyle: SPTableViewCell.HiglightStyle = .content,
- action: SPDiffableTableRow.Action? = nil
- ) {
- self.textColor = textColor
- self.detailColor = detailColor
- self.higlightStyle = higlightStyle
-
- super.init(
- id: id,
- text: text,
- detail: detail,
- icon: icon,
- accessoryType: accessoryType,
- action: action
- )
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Table/Button/NativeLeftButtonTableViewCell.swift b/Sources/NativeUIKit/Table/Button/NativeLeftButtonTableViewCell.swift
deleted file mode 100644
index 3d3d4a6..0000000
--- a/Sources/NativeUIKit/Table/Button/NativeLeftButtonTableViewCell.swift
+++ /dev/null
@@ -1,47 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-open class NativeLeftButtonTableViewCell: SPTableViewCell {
-
- public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
- super.init(style: .value1, reuseIdentifier: reuseIdentifier)
- }
-
- required public init?(coder aDecoder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- open override func commonInit() {
- super.commonInit()
- textLabel?.font = .preferredFont(forTextStyle: .body, weight: .medium)
- higlightStyle = .content
- }
-
- open override func sizeThatFits(_ size: CGSize) -> CGSize {
- let superSize = super.sizeThatFits(size)
- return .init(width: superSize.width, height: superSize.height + 6)
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Table/Empty/CellProvider+Empty.swift b/Sources/NativeUIKit/Table/Empty/CellProvider+Empty.swift
deleted file mode 100644
index b3d5549..0000000
--- a/Sources/NativeUIKit/Table/Empty/CellProvider+Empty.swift
+++ /dev/null
@@ -1,40 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SPDiffable
-
-@available(iOS 13.0, *)
-extension SPDiffableTableDataSource.CellProvider {
-
- public static var empty: SPDiffableTableDataSource.CellProvider {
- return SPDiffableTableDataSource.CellProvider() { (tableView, indexPath, item) -> UITableViewCell? in
- guard let item = item as? NativeEmptyRowItem else { return nil }
- let cell = tableView.dequeueReusableCell(withClass: NativeEmptyTableViewCell.self, for: indexPath)
- cell.placeholderView.headerLabel.text = item.text
- cell.placeholderView.descriptionLabel.text = item.detail
- cell.verticalMargins = item.verticalMargins
- return cell
- }
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Table/Empty/NativeEmptyRowItem.swift b/Sources/NativeUIKit/Table/Empty/NativeEmptyRowItem.swift
deleted file mode 100644
index ebb9fd2..0000000
--- a/Sources/NativeUIKit/Table/Empty/NativeEmptyRowItem.swift
+++ /dev/null
@@ -1,37 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-import SPDiffable
-
-@available(iOS 13.0, *)
-open class NativeEmptyRowItem: SPDiffableTableRow {
-
- var verticalMargins: NativeEmptyTableViewCell.Margins
-
- public init(id: String, verticalMargins: NativeEmptyTableViewCell.Margins, text: String, detail: String?) {
- self.verticalMargins = verticalMargins
- super.init(id: id, text: text, detail: detail)
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Table/Empty/NativeEmptyTableViewCell.swift b/Sources/NativeUIKit/Table/Empty/NativeEmptyTableViewCell.swift
deleted file mode 100644
index ce3b6a4..0000000
--- a/Sources/NativeUIKit/Table/Empty/NativeEmptyTableViewCell.swift
+++ /dev/null
@@ -1,113 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-
-open class NativeEmptyTableViewCell: SPTableViewCell {
-
- // MARK: - Data
-
- open var verticalMargins: Margins = .medium {
- didSet {
- contentView.layoutMargins.top = self.verticalMargins.value
- contentView.layoutMargins.bottom = self.verticalMargins.value
- }
- }
-
- // MARK: - Views
-
- public let placeholderView = NativePlaceholderView().do {
- $0.isUserInteractionEnabled = false
- }
-
- // MARK: - Init
-
- open override func commonInit() {
- super.commonInit()
- selectionStyle = .none
- contentView.addSubview(placeholderView)
- updateBackgroundColorByParent()
- }
-
- // MARK: - Lifecycle
-
- open override func tintColorDidChange() {
- super.tintColorDidChange()
- updateBackgroundColorByParent()
- }
-
- // MARK: - Layout
-
- open override func layoutSubviews() {
- super.layoutSubviews()
- placeholderView.frame.origin.y = contentView.layoutMargins.top
- placeholderView.setWidthAndFit(width: contentView.layoutWidth)
- placeholderView.setXCenter()
- }
-
- open override func sizeThatFits(_ size: CGSize) -> CGSize {
- let superSize = super.sizeThatFits(size)
- layoutSubviews()
- let calculatedHeight = placeholderView.frame.maxY + contentView.layoutMargins.bottom
- let bottomInset = calculatedHeight * (1 - 0.94)
- return .init(width: superSize.width, height: calculatedHeight + bottomInset)
- }
-
- // MARK: - Actions
-
- private func updateBackgroundColorByParent() {
- if #available(iOS 13.0, *) {
- backgroundColor = UIColor.systemDownedGroupedBackground
- }
- /*if let superView = self.superview?.superview {
- let superViewBackgroundColor = superView.backgroundColor ?? .clear
- if superViewBackgroundColor == .systemGroupedBackground {
- backgroundColor = UIColor.init(
- light: superViewBackgroundColor.mixWithColor(.darkGray, amount: 0.09).mixWithColor(.systemBlue, amount: 0.01),
- dark: .secondarySystemGroupedBackground.alpha(0.7)
- )
- } else {
- // Here not implemented becouse not using never for now.
- backgroundColor = .red
- }
- }*/
- }
-
- // MARK: - Models
-
- public enum Margins {
-
- case small
- case medium
- case large
-
- var value: CGFloat {
- switch self {
- case .small: return 16
- case .medium: return 32
- case .large: return 48
- }
- }
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Table/LargeHeader/CellProvider+LargeHeader.swift b/Sources/NativeUIKit/Table/LargeHeader/CellProvider+LargeHeader.swift
deleted file mode 100644
index ea99733..0000000
--- a/Sources/NativeUIKit/Table/LargeHeader/CellProvider+LargeHeader.swift
+++ /dev/null
@@ -1,38 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SPDiffable
-
-@available(iOS 13.0, *)
-extension SPDiffableTableDataSource.HeaderFooterProvider {
-
- public static var largeHeader: SPDiffableTableDataSource.HeaderFooterProvider {
- return SPDiffableTableDataSource.HeaderFooterProvider() { (tableView, section, item) -> UIView? in
- guard let header = item as? NativeLargeHeaderItem else { return nil }
- let view = NativeLargeHeaderView()
- view.configure(with: header, section: section)
- return view
- }
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Table/LargeHeader/NativeLargeHeaderItem.swift b/Sources/NativeUIKit/Table/LargeHeader/NativeLargeHeaderItem.swift
deleted file mode 100644
index 496a780..0000000
--- a/Sources/NativeUIKit/Table/LargeHeader/NativeLargeHeaderItem.swift
+++ /dev/null
@@ -1,42 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2020 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS) || os(tvOS))
-import UIKit
-import SPDiffable
-
-/**
- SPDiffable: Native large header with button.
- */
-open class NativeLargeHeaderItem: SPDiffableItem, SPDiffableItemActionable {
-
- open var title: String
- open var actionTitle: String?
- open var action: Action?
-
- public init(id: String? = nil, title: String, actionTitle: String? = nil, action: Action? = nil) {
- self.title = title
- self.actionTitle = actionTitle
- self.action = action
- super.init(id: id ?? title)
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Table/LargeHeader/NativeLargeHeaderViewExtension.swift b/Sources/NativeUIKit/Table/LargeHeader/NativeLargeHeaderViewExtension.swift
deleted file mode 100644
index 4e8ac29..0000000
--- a/Sources/NativeUIKit/Table/LargeHeader/NativeLargeHeaderViewExtension.swift
+++ /dev/null
@@ -1,37 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-
-extension NativeLargeHeaderView {
-
- func configure(with item: NativeLargeHeaderItem, section: Int) {
- titleLabel.text = item.title
- if let actionTitle = item.actionTitle {
- button.setTitle(actionTitle)
- diffableButtonAction = {
- item.action?(item, .init(row: .zero, section: section))
- }
- }
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Views/NativeLargeHeaderView.swift b/Sources/NativeUIKit/Views/NativeLargeHeaderView.swift
deleted file mode 100644
index de07e5a..0000000
--- a/Sources/NativeUIKit/Views/NativeLargeHeaderView.swift
+++ /dev/null
@@ -1,97 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2020 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-import SPDiffable
-
-open class NativeLargeHeaderView: SPView {
-
- // MARK: - Views
-
- public let titleLabel = SPLabel().do {
- $0.font = UIFont.preferredFont(forTextStyle: .title2, weight: .semibold)
- if #available(iOS 13.0, *) {
- $0.textColor = .label
- } else {
- $0.textColor = .black
- }
- }
-
- public let button = SPDimmedButton().do {
- $0.applyDefaultAppearance(with: .tintedContent)
- }
-
- // MARK: - Init
-
- open override func commonInit() {
- super.commonInit()
- layoutMargins = .init(top: NativeLayout.Spaces.default_double, left: .zero, bottom: 14, right: .zero)
- insetsLayoutMarginsFromSafeArea = false
- preservesSuperviewLayoutMargins = false
- addSubviews(titleLabel, button)
- }
-
- // MARK: - Layout
-
- open func layout(y: CGFloat) {
- guard let superview = self.superview else { return }
- setWidthAndFit(width: superview.layoutWidth)
- setXCenter()
- frame.origin.y = y
- }
-
- open override func layoutSubviews() {
- super.layoutSubviews()
- titleLabel.layoutDynamicHeight(
- x: layoutMargins.left,
- y: layoutMargins.top,
- width: layoutWidth
- )
- button.sizeToFit()
- button.setMaxXToSuperviewRightMargin()
- button.center.y = titleLabel.center.y
- }
-
- open override func sizeThatFits(_ size: CGSize) -> CGSize {
- let superSize = super.sizeThatFits(size)
- layoutSubviews()
- return .init(width: superSize.width, height: titleLabel.frame.maxY + layoutMargins.bottom)
- }
-
- // MARK: - Private
-
- var diffableButtonAction: (()->Void)? = nil {
- didSet {
- if let _ = diffableButtonAction {
- self.button.addTarget(self, action: #selector(self.diffableButtonTargetAction), for: .touchUpInside)
- } else {
- self.button.removeTargetsAndActions()
- }
- }
- }
-
- @objc func diffableButtonTargetAction() {
- self.diffableButtonAction?()
- }
-}
-#endif
diff --git a/Sources/NativeUIKit/Views/NativePromoView.swift b/Sources/NativeUIKit/Views/NativePromoView.swift
deleted file mode 100644
index 2288e4a..0000000
--- a/Sources/NativeUIKit/Views/NativePromoView.swift
+++ /dev/null
@@ -1,153 +0,0 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-#if canImport(UIKit) && (os(iOS))
-import UIKit
-import SparrowKit
-import SPPerspective
-
-open class NativePromoView: SPView {
-
- // MARK: - Views
-
- public let titleLabel = SPLabel().do {
- $0.font = UIFont.preferredFont(forTextStyle: .title2, weight: .semibold)
- if #available(iOS 13.0, *) {
- $0.textColor = .label
- } else {
- $0.textColor = .black
- }
- $0.numberOfLines = .zero
- $0.textAlignment = .center
- }
-
- public let descriptionLabel = SPLabel().do {
- $0.font = UIFont.preferredFont(forTextStyle: .body, weight: .regular)
- if #available(iOS 13.0, *) {
- $0.textColor = .secondaryLabel
- } else {
- $0.textColor = .black.alpha(0.5)
- }
- $0.numberOfLines = .zero
- $0.textAlignment = .center
- }
-
- public let iconView = SPImageView().do {
- $0.backgroundColor = .clear
- }
-
- public let button = SPDimmedButton().do {
- $0.applyDefaultAppearance(with: .tintedContent)
- $0.titleLabel?.font = UIFont.preferredFont(forTextStyle: .body, weight: .semibold, addPoints: 2)
- }
-
- public let areaView = SPView().do {
- if #available(iOS 13.0, *) {
- $0.backgroundColor = UIColor.secondarySystemBackground
- }
- $0.layer.cornerRadius = 15
- }
-
- // MARK: - Init
-
- open override func commonInit() {
- super.commonInit()
- layoutMargins = .zero
- addSubview(areaView)
- addSubview(titleLabel)
- addSubview(descriptionLabel)
- addSubview(iconView)
- addSubview(button)
- areaView.layoutMargins = .init(horizontal: 24, vertical: 24)
- iconView.applyPerspective(.iOS14WidgetAnimatable)
- }
-
- // MARK: - Layout
-
- open func layout(y: CGFloat) {
- guard let superview = self.superview else { return }
- var width = min(superview.readableWidth, NativeLayout.Sizes.actionable_area_maximum_width)
- if (width == .zero) && (superview.layoutWidth != .zero) { width = superview.layoutWidth }
- setWidthAndFit(width: width)
- setXCenter()
- frame.origin.y = y
- }
-
- open override func layoutSubviews() {
- super.layoutSubviews()
- areaView.frame = .init(x: layoutMargins.left, y: layoutMargins.top, width: layoutWidth, height: areaView.frame.height)
-
- let labelsWidth = areaView.layoutWidth
-
- titleLabel.layoutDynamicHeight(width: labelsWidth)
- titleLabel.setXCenter()
- titleLabel.frame.origin.y = areaView.frame.origin.y + areaView.layoutMargins.top
-
- descriptionLabel.layoutDynamicHeight(width: labelsWidth)
- descriptionLabel.setXCenter()
- descriptionLabel.frame.origin.y = titleLabel.frame.maxY + 3
-
- let iconSideSize = min(titleLabel.frame.width * 0.5, 120)
- iconView.frame.setWidth(iconSideSize)
- iconView.frame.setHeight(iconSideSize)
- iconView.setXCenter()
- iconView.frame.origin.y = descriptionLabel.frame.maxY + 16
-
- areaView.frame.setHeight(iconView.frame.origin.y + iconView.frame.height / 2)
-
- button.sizeToFit()
- button.setXCenter()
- button.frame.origin.y = iconView.frame.maxY + 24
- }
-
- open override func sizeThatFits(_ size: CGSize) -> CGSize {
- layoutSubviews()
- return .init(width: size.width, height: button.frame.maxY + layoutMargins.bottom)
- }
-}
-
-open class NativePromoContainerView: SPView {
-
- // MARK: - Views
-
- public let promoView = NativePromoView()
-
- // MARK: - Init
-
- open override func commonInit() {
- super.commonInit()
- layoutMargins = .zero
- addSubview(promoView)
- }
-
- // MARK: - Layout
-
- open override func layoutSubviews() {
- super.layoutSubviews()
- promoView.layout(y: layoutMargins.top)
- }
-
- open override func sizeThatFits(_ size: CGSize) -> CGSize {
- layoutSubviews()
- return .init(width: size.width, height: promoView.frame.maxY + layoutMargins.bottom)
- }
-}
-#endif
diff --git a/Sources/UIKitExtension/AppDelegate/Scenes/UICommonWindowSceneDelegate.swift b/Sources/UIKitExtension/AppDelegate/Scenes/UICommonWindowSceneDelegate.swift
new file mode 100644
index 0000000..89a795a
--- /dev/null
+++ b/Sources/UIKitExtension/AppDelegate/Scenes/UICommonWindowSceneDelegate.swift
@@ -0,0 +1,54 @@
+#if canImport(UIKit) && (os(iOS))
+import UIKit
+
+/**
+ UIKitExtension: Basic class for scene.
+
+ Has ready use window property and assets funcs for present window.
+ */
+@available(iOS 13.0, *)
+open class UICommonWindowSceneDelegate: UIResponder, UIWindowSceneDelegate {
+
+ /**
+ UIKitExtension: Ready-use window property.
+
+ For correct configure, call `makeKeyAndVisible`.
+ */
+ open var window: UIWindow?
+
+ /**
+ UIKitExtension: Configure window and make it present.
+
+ This method get controller after apply tint and window scene, in some cases it critical. For example tint of window get before valid tint set. It happen with first window and launch. For solve it use this.
+
+ - parameter scene: Scene which sync to window.
+ - parameter createViewControllerHandler: Handler for get root controller for window.
+ - parameter tint: Tint color for window.
+ */
+ open func makeKeyAndVisible(in scene: UIWindowScene, createViewControllerHandler: () -> UIViewController, tint: UIColor) {
+ window = UIWindow(frame: scene.coordinateSpace.bounds)
+ window?.windowScene = scene
+ window?.tintColor = tint
+ window?.rootViewController = createViewControllerHandler()
+ window?.makeKeyAndVisible()
+ }
+
+ /**
+ UIKitExtension: Configure window and make it present.
+
+ Set scene, tint and already created controller.
+
+ - warning:
+ If you get troubles with tinting, please, check other method `makeKeyAndVisible`.
+
+ - parameter scene: Scene which sync to window.
+ - parameter viewController: Root controller for window.
+ - parameter tint: Tint color for window.
+ */
+ open func makeKeyAndVisible(in scene: UIWindowScene, viewController: UIViewController, tint: UIColor) {
+ makeKeyAndVisible(in: scene, createViewControllerHandler: {
+ return viewController
+ }, tint: tint)
+ }
+}
+#endif
diff --git a/Sources/UIKitExtension/AppDelegate/Scenes/UIScenesApplicationDelegate.swift b/Sources/UIKitExtension/AppDelegate/Scenes/UIScenesApplicationDelegate.swift
new file mode 100644
index 0000000..1e55b36
--- /dev/null
+++ b/Sources/UIKitExtension/AppDelegate/Scenes/UIScenesApplicationDelegate.swift
@@ -0,0 +1,8 @@
+#if canImport(UIKit) && (os(iOS))
+import UIKit
+
+/**
+ UIKitExtension: App class which using with scenes.
+ */
+open class UIScenesApplicationDelegate: UIResponder, UIApplicationDelegate {}
+#endif
diff --git a/Sources/UIKitExtension/AppDelegate/Window/UIWindowApplicationDelegate.swift b/Sources/UIKitExtension/AppDelegate/Window/UIWindowApplicationDelegate.swift
new file mode 100644
index 0000000..654e2b6
--- /dev/null
+++ b/Sources/UIKitExtension/AppDelegate/Window/UIWindowApplicationDelegate.swift
@@ -0,0 +1,52 @@
+#if canImport(UIKit) && (os(iOS) || os(tvOS))
+import UIKit
+
+/**
+ UIKitExtension: App which not using with scenes, only with one window key.
+ */
+open class UIWindowApplicationDelegate: UIResponder, UIApplicationDelegate {
+
+ /**
+ UIKitExtension: Ready-use window property.
+
+ For correct configure, call `makeKeyAndVisible`.
+ */
+ open var window: UIWindow?
+
+ /**
+ UIKitExtension: Configure window and make it present.
+
+ Method init window and configure with your tint and controller.
+
+ - warning:
+ Use it only if none-scene mode.
+
+ - parameter createViewControllerHandler: Handler for get root controller for window.
+ - parameter tint: Tint color for window.
+ */
+ open func makeKeyAndVisible(createViewControllerHandler: () -> UIViewController, tint: UIColor) {
+ let frame = UIScreen.main.bounds
+ window = UIWindow(frame: frame)
+ window?.tintColor = tint
+ window?.rootViewController = createViewControllerHandler()
+ window?.makeKeyAndVisible()
+ }
+
+ /**
+ UIKitExtension: Configure window and make it present.
+
+ Method init window and configure with your tint and controller.
+
+ - warning:
+ Use it only if none-scene mode.
+
+ - parameter viewController: Root controller for window.
+ - parameter tint: Tint color for window.
+ */
+ open func makeKeyAndVisible(viewController: UIViewController, tint: UIColor) {
+ makeKeyAndVisible(createViewControllerHandler: {
+ return viewController
+ }, tint: tint)
+ }
+}
+#endif
diff --git a/Sources/UIKitExtension/Appearance.swift b/Sources/UIKitExtension/Appearance.swift
new file mode 100644
index 0000000..08a7259
--- /dev/null
+++ b/Sources/UIKitExtension/Appearance.swift
@@ -0,0 +1,11 @@
+#if canImport(UIKit) && (os(iOS))
+import UIKit
+
+enum Appearance {
+
+ enum Corners {
+
+ static var readable_area: CGFloat { 16 }
+ }
+}
+#endif
diff --git a/Sources/UIKitExtension/Collection/UILargeHeaderCollectionView.swift b/Sources/UIKitExtension/Collection/UILargeHeaderCollectionView.swift
new file mode 100644
index 0000000..2337369
--- /dev/null
+++ b/Sources/UIKitExtension/Collection/UILargeHeaderCollectionView.swift
@@ -0,0 +1,57 @@
+#if canImport(UIKit) && (os(iOS))
+import UIKit
+import DiffableKit
+import SwiftBoost
+
+open class UILargeHeaderCollectionView: UICommonCollectionReusableView {
+
+ public let headerView = UILargeHeaderView()
+
+ open override func commonInit() {
+ super.commonInit()
+ layoutMargins = .zero
+ layoutMargins.left = Spaces.default_half
+ preservesSuperviewLayoutMargins = false
+ insetsLayoutMarginsFromSafeArea = false
+ addSubview(headerView)
+ }
+
+ open override func prepareForReuse() {
+ super.prepareForReuse()
+ headerView.button.removeTargetsAndActions()
+ }
+
+ open override func layoutSubviews() {
+ super.layoutSubviews()
+ headerView.setWidthAndFit(width: layoutWidth)
+ headerView.frame.origin = .init(x: layoutMargins.left, y: layoutMargins.top)
+ }
+
+ open override func sizeThatFits(_ size: CGSize) -> CGSize {
+ let superSize = super.sizeThatFits(size)
+ layoutSubviews()
+ return .init(width: superSize.width, height: headerView.frame.maxY + layoutMargins.bottom)
+ }
+}
+
+extension DiffableCollectionDataSource.HeaderFooterProvider {
+
+ public static var largeHeader: DiffableCollectionDataSource.HeaderFooterProvider {
+ return DiffableCollectionDataSource.HeaderFooterProvider() { (collectionView, section, item) -> UICollectionReusableView? in
+ guard let header = item as? DiffableLargeHeaderItem else { return nil }
+ let view = collectionView.dequeueReusableSupplementaryView(withCalss: UILargeHeaderCollectionView.self, kind: UICollectionView.elementKindSectionHeader, for: .init(row: .zero, section: section))
+ view.headerView.button.setTitle(header.title)
+ if let action = header.action {
+ view.headerView.showChevron = true
+ view.headerView.button.addAction(.init(handler: { _ in
+ action(item, .init(row: .zero, section: section))
+ }), for: .touchUpInside)
+ } else {
+ view.headerView.showChevron = true
+ }
+ view.layoutSubviews()
+ return view
+ }
+ }
+}
+#endif
diff --git a/Sources/UIKitExtension/Collection/UIPagingCollectionViewLayout.swift b/Sources/UIKitExtension/Collection/UIPagingCollectionViewLayout.swift
new file mode 100644
index 0000000..0e68d65
--- /dev/null
+++ b/Sources/UIKitExtension/Collection/UIPagingCollectionViewLayout.swift
@@ -0,0 +1,48 @@
+import UIKit
+
+/**
+ - warning: Sometimes scroll working not well. Recommended to use composition layout.
+ */
+open class UIPagingCollectionViewFlowLayout: UICollectionViewFlowLayout {
+
+ public enum Behavior {
+
+ case soft
+ case aggresive
+ }
+
+ open var behavior: Behavior = .soft
+
+ open override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
+
+ switch behavior {
+ case .soft:
+ guard let collectionView = self.collectionView else {
+ let latestOffset = super.targetContentOffset(forProposedContentOffset: proposedContentOffset, withScrollingVelocity: velocity)
+ return latestOffset
+ }
+ var offsetAdjustment = CGFloat.greatestFiniteMagnitude
+ let horizontalOffset = proposedContentOffset.x
+ let targetRect = CGRect(origin: CGPoint(x: proposedContentOffset.x, y: 0), size: collectionView.bounds.size)
+ for layoutAttributes in super.layoutAttributesForElements(in: targetRect)! {
+ let itemOffset = layoutAttributes.frame.origin.x
+ if (abs(itemOffset - horizontalOffset) < abs(offsetAdjustment)) {
+ offsetAdjustment = itemOffset - horizontalOffset
+ }
+ }
+ return CGPoint(x: proposedContentOffset.x + offsetAdjustment - collectionView.layoutMargins.left, y: proposedContentOffset.y)
+ case .aggresive:
+ guard let collectionView = self.collectionView else {
+ let latestOffset = super.targetContentOffset(forProposedContentOffset: proposedContentOffset, withScrollingVelocity: velocity)
+ return latestOffset
+ }
+ let pageWidth = self.itemSize.width + self.minimumLineSpacing
+ let approximatePage = collectionView.contentOffset.x / pageWidth
+ let currentPage = velocity.x == 0 ? round(approximatePage) : (velocity.x < 0.0 ? floor(approximatePage) : ceil(approximatePage))
+ let flickVelocity = velocity.x * 0.3
+ let flickedPages = (abs(round(flickVelocity)) <= 1) ? 0 : round(flickVelocity)
+ let newHorizontalOffset = ((currentPage + flickedPages) * pageWidth) - collectionView.contentInset.left
+ return CGPoint(x: newHorizontalOffset, y: proposedContentOffset.y)
+ }
+ }
+}
diff --git a/Sources/UIKitExtension/CommonInit.swift b/Sources/UIKitExtension/CommonInit.swift
new file mode 100644
index 0000000..990ba98
--- /dev/null
+++ b/Sources/UIKitExtension/CommonInit.swift
@@ -0,0 +1,303 @@
+#if canImport(UIKit) && (os(iOS) || os(tvOS))
+import UIKit
+
+public protocol UICommonInit {
+
+ /**
+ UIKitExtension: Wrapper of init.
+ Called in each init and using for configuration.
+
+ No need ovveride init. Using one function for configurate view.
+ */
+ func commonInit()
+}
+
+open class UICommonView: UIView, UICommonInit {
+
+ public init() {
+ super.init(frame: CGRect.zero)
+ commonInit()
+ }
+
+ public override init(frame: CGRect) {
+ super.init(frame: frame)
+ commonInit()
+ }
+
+ public required init?(coder aDecoder: NSCoder) {
+ super.init(coder: aDecoder)
+ commonInit()
+ }
+
+ open func commonInit() {}
+}
+
+open class UICommonScrollView: UIScrollView, UICommonInit {
+
+ public init() {
+ super.init(frame: CGRect.zero)
+ commonInit()
+ }
+
+ public override init(frame: CGRect) {
+ super.init(frame: frame)
+ commonInit()
+ }
+
+ public required init?(coder aDecoder: NSCoder) {
+ super.init(coder: aDecoder)
+ commonInit()
+ }
+
+ open func commonInit() {}
+}
+
+open class UICommonControl: UIControl, UICommonInit {
+
+ public init() {
+ super.init(frame: CGRect.zero)
+ commonInit()
+ }
+
+ public override init(frame: CGRect) {
+ super.init(frame: frame)
+ commonInit()
+ }
+
+ public required init?(coder aDecoder: NSCoder) {
+ super.init(coder: aDecoder)
+ commonInit()
+ }
+
+ open func commonInit() {}
+}
+
+open class UICommonButton: UIButton, UICommonInit {
+
+ public init() {
+ super.init(frame: CGRect.zero)
+ commonInit()
+ }
+
+ public override init(frame: CGRect) {
+ super.init(frame: frame)
+ commonInit()
+ }
+
+ public required init?(coder aDecoder: NSCoder) {
+ super.init(coder: aDecoder)
+ commonInit()
+ }
+
+ open func commonInit() {}
+
+ // MARK: - Layout
+
+ /**
+ UIKitExtension: Inset between image and title.
+
+ No need any additional processing layout.
+ It work automatically in `layoutSubviews` method.
+ */
+ open var titleImageInset: CGFloat? = nil
+
+ open override func layoutSubviews() {
+ super.layoutSubviews()
+ if let inset = titleImageInset {
+ if imageView?.image == nil {
+ imageEdgeInsets.right = .zero
+ titleEdgeInsets.left = .zero
+ } else {
+ if ltr {
+ imageEdgeInsets.right = inset
+ titleEdgeInsets.left = inset
+ } else {
+ imageEdgeInsets.right = -inset
+ titleEdgeInsets.left = -inset
+ }
+ }
+ }
+ }
+}
+
+open class UICommonImageView: UIImageView, UICommonInit {
+
+ public init() {
+ super.init(frame: .zero)
+ commonInit()
+ }
+
+ public init(image: UIImage?, contentMode: UIImageView.ContentMode) {
+ super.init(image: image)
+ self.contentMode = contentMode
+ commonInit()
+ }
+
+ public required init?(coder: NSCoder) {
+ super.init(coder: coder)
+ commonInit()
+ }
+
+ open func commonInit() {}
+}
+
+open class UICommonLabel: UILabel, UICommonInit {
+
+ public init() {
+ super.init(frame: .zero)
+ commonInit()
+ }
+
+ public required init?(coder aDecoder: NSCoder) {
+ super.init(coder: aDecoder)
+ commonInit()
+ }
+
+ open func commonInit() {}
+}
+
+open class UICommonSlider: UISlider, UICommonInit {
+
+ public init() {
+ super.init(frame: .zero)
+ commonInit()
+ }
+
+ public required init?(coder: NSCoder) {
+ super.init(coder: coder)
+ commonInit()
+ }
+
+ open func commonInit() {}
+}
+
+open class UICommonTextField: UITextField, UICommonInit {
+
+ public init() {
+ super.init(frame: CGRect.zero)
+ commonInit()
+ }
+
+ public override init(frame: CGRect) {
+ super.init(frame: frame)
+ commonInit()
+ }
+
+ public required init?(coder aDecoder: NSCoder) {
+ super.init(coder: aDecoder)
+ commonInit()
+ }
+
+ open func commonInit() {}
+}
+
+public class UICommonInitTextView: UITextView, UICommonInit {
+
+ public init() {
+ super.init(frame: .zero, textContainer: nil)
+ commonInit()
+ }
+
+ public required init?(coder aDecoder: NSCoder) {
+ super.init(coder: aDecoder)
+ commonInit()
+ }
+
+ open func commonInit() {}
+}
+
+open class UICommonCollectionView: UICollectionView, UICommonInit {
+
+ public init(collectionViewLayout layout: UICollectionViewLayout) {
+ super.init(frame: .zero, collectionViewLayout: layout)
+ commonInit()
+ }
+
+ public required init?(coder aDecoder: NSCoder) {
+ super.init(coder: aDecoder)
+ commonInit()
+ }
+
+ open func commonInit() {}
+}
+
+open class UICommonCollectionViewCell: UICollectionViewCell, UICommonInit {
+
+ public init() {
+ super.init(frame: .zero)
+ commonInit()
+ }
+
+ public override init(frame: CGRect) {
+ super.init(frame: frame)
+ commonInit()
+ }
+
+ public required init?(coder aDecoder: NSCoder) {
+ super.init(coder: aDecoder)
+ commonInit()
+ }
+
+ open func commonInit() {}
+}
+
+open class UICommonTableView: UITableView, UICommonInit {
+
+ public init(style: UITableView.Style) {
+ super.init(frame: .zero, style: style)
+ commonInit()
+ }
+
+ public required init?(coder aDecoder: NSCoder) {
+ super.init(coder: aDecoder)
+ commonInit()
+ }
+
+ open func commonInit() {}
+}
+
+open class UICommonTableViewCell: UITableViewCell, UICommonInit {
+
+ public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
+ super.init(style: style, reuseIdentifier: reuseIdentifier)
+ commonInit()
+ }
+
+ public required init?(coder aDecoder: NSCoder) {
+ super.init(coder: aDecoder)
+ commonInit()
+ }
+
+ open func commonInit() {}
+}
+
+open class UICommonTableViewHeaderFooterView: UITableViewHeaderFooterView {
+
+ public override init(reuseIdentifier: String?) {
+ super.init(reuseIdentifier: reuseIdentifier)
+ commonInit()
+ }
+
+ public required init?(coder: NSCoder) {
+ super.init(coder: coder)
+ commonInit()
+ }
+
+ open func commonInit() {}
+}
+
+open class UICommonCollectionReusableView: UICollectionReusableView {
+
+ public override init(frame: CGRect) {
+ super.init(frame: frame)
+ commonInit()
+ }
+
+ public required init?(coder: NSCoder) {
+ super.init(coder: coder)
+ commonInit()
+ }
+
+ open func commonInit() {}
+}
+#endif
diff --git a/Sources/UIKitExtension/Controllers/UICommonCollectionViewController.swift b/Sources/UIKitExtension/Controllers/UICommonCollectionViewController.swift
new file mode 100644
index 0000000..f970d93
--- /dev/null
+++ b/Sources/UIKitExtension/Controllers/UICommonCollectionViewController.swift
@@ -0,0 +1,23 @@
+import UIKit
+
+open class UICommonCollectionViewContoller: UICollectionViewController, UICommonInit {
+
+ // MARK: - Init
+
+ public convenience init() {
+ self.init(collectionViewLayout: UICollectionViewFlowLayout())
+ commonInit()
+ }
+
+ public override init(collectionViewLayout layout: UICollectionViewLayout) {
+ super.init(collectionViewLayout: layout)
+ commonInit()
+ }
+
+ public required init?(coder: NSCoder) {
+ super.init(coder: coder)
+ commonInit()
+ }
+
+ open func commonInit() {}
+}
diff --git a/Sources/UIKitExtension/Controllers/UICommonNavigationController.swift b/Sources/UIKitExtension/Controllers/UICommonNavigationController.swift
new file mode 100644
index 0000000..9392a00
--- /dev/null
+++ b/Sources/UIKitExtension/Controllers/UICommonNavigationController.swift
@@ -0,0 +1,78 @@
+import UIKit
+
+open class UICommonNavigationController: UINavigationController, UICommonInit, UINavigationControllerDelegate {
+
+ // MARK: - Init
+
+ public override init(rootViewController: UIViewController) {
+ super.init(rootViewController: rootViewController)
+ commonInit()
+ }
+
+ public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
+ super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
+ commonInit()
+ }
+
+ public required init?(coder aDecoder: NSCoder) {
+ super.init(coder: aDecoder)
+ }
+
+ public override init(navigationBarClass: AnyClass?, toolbarClass: AnyClass?) {
+ super.init(navigationBarClass: navigationBarClass, toolbarClass: toolbarClass)
+ }
+
+ open func commonInit() {
+ delegate = self
+ }
+
+ // MARK: - Layout
+
+ /**
+ UIKitExtension: If set to `true`, navigation bar apply horizontal margins from view of navigation controller.
+ Default is `false`.
+ */
+ open var inheritLayoutMarginsForNavigationBar: Bool = false
+
+ /**
+ UIKitExtension: If set to `true`, child controllers apply horizontal margins from view of navigation controller.
+ Default is `false`.
+ */
+ open var inheritLayoutMarginsForСhilds: Bool = false
+
+ open override func viewDidLayoutSubviews() {
+ super.viewDidLayoutSubviews()
+
+ // Inhert of Navigation Bar
+
+ if inheritLayoutMarginsForNavigationBar {
+
+ let leftMargin = view.layoutMargins.left
+ let rightMargin = view.layoutMargins.right
+
+ if navigationBar.layoutMargins.left != leftMargin {
+ navigationBar.layoutMargins.left = leftMargin
+ }
+ if navigationBar.layoutMargins.right != rightMargin {
+ navigationBar.layoutMargins.right = rightMargin
+ }
+ }
+
+ // Inhert Childs Controllers
+
+ if inheritLayoutMarginsForСhilds {
+
+ let leftMargin = view.layoutMargins.left
+ let rightMargin = view.layoutMargins.right
+
+ for childController in viewControllers {
+ if childController.view.layoutMargins.left != leftMargin {
+ childController.view.layoutMargins.left = leftMargin
+ }
+ if childController.view.layoutMargins.right != rightMargin {
+ childController.view.layoutMargins.right = rightMargin
+ }
+ }
+ }
+ }
+}
diff --git a/Sources/UIKitExtension/Controllers/UICommonScrollViewController.swift b/Sources/UIKitExtension/Controllers/UICommonScrollViewController.swift
new file mode 100644
index 0000000..2cc2e06
--- /dev/null
+++ b/Sources/UIKitExtension/Controllers/UICommonScrollViewController.swift
@@ -0,0 +1,25 @@
+import UIKit
+
+open class UICommonScrollViewController: UICommonViewContoller {
+
+ public lazy var scrollView = UICommonScrollView()
+
+ open override func viewDidLoad() {
+ super.viewDidLoad()
+
+ scrollView.delaysContentTouches = false
+ view.addSubview(scrollView)
+
+ if #available(iOS 15.0, *) {
+ setContentScrollView(scrollView)
+ }
+
+ scrollView.translatesAutoresizingMaskIntoConstraints = false
+ NSLayoutConstraint.activate([
+ scrollView.topAnchor.constraint(equalTo: view.topAnchor),
+ scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
+ scrollView.leftAnchor.constraint(equalTo: view.leftAnchor),
+ scrollView.rightAnchor.constraint(equalTo: view.rightAnchor)
+ ])
+ }
+}
diff --git a/Sources/UIKitExtension/Controllers/UICommonSplitViewController.swift b/Sources/UIKitExtension/Controllers/UICommonSplitViewController.swift
new file mode 100644
index 0000000..27871cc
--- /dev/null
+++ b/Sources/UIKitExtension/Controllers/UICommonSplitViewController.swift
@@ -0,0 +1,22 @@
+import UIKit
+
+open class UICommonSplitViewController: UISplitViewController {
+
+ public init() {
+ super.init(nibName: nil, bundle: nil)
+ commonInit()
+ }
+
+ @available(iOS 14.0, *)
+ public override init(style: UISplitViewController.Style) {
+ super.init(style: style)
+ commonInit()
+ }
+
+ public required init?(coder: NSCoder) {
+ super.init(coder: coder)
+ commonInit()
+ }
+
+ open func commonInit() {}
+}
diff --git a/Sources/UIKitExtension/Controllers/UICommonViewContoller.swift b/Sources/UIKitExtension/Controllers/UICommonViewContoller.swift
new file mode 100644
index 0000000..14bbedf
--- /dev/null
+++ b/Sources/UIKitExtension/Controllers/UICommonViewContoller.swift
@@ -0,0 +1,28 @@
+import UIKit
+
+open class UICommonViewContoller: UIViewController, UICommonInit {
+
+ // MARK: - Init
+
+ public init() {
+ super.init(nibName: nil, bundle: nil)
+ commonInit()
+ }
+
+ public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
+ super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
+ commonInit()
+ }
+
+ public required init?(coder: NSCoder) {
+ super.init(coder: coder)
+ commonInit()
+ }
+
+ open func commonInit() {}
+
+ // MARK: - Toolbar
+
+ //open var extendedToolbarContainerView: UIToolbarContainerView.ContainerView? = nil
+
+}
diff --git a/Sources/UIKitExtension/Controllers/UIPageContainerController/UIPageContainerController.swift b/Sources/UIKitExtension/Controllers/UIPageContainerController/UIPageContainerController.swift
new file mode 100644
index 0000000..22bca28
--- /dev/null
+++ b/Sources/UIKitExtension/Controllers/UIPageContainerController/UIPageContainerController.swift
@@ -0,0 +1,83 @@
+import UIKit
+
+open class UIPageContainerController: UIViewController {
+
+ public var containerController: UIViewController
+
+ // todo clean to
+
+ public func scrollToPage(index: Int, animated: Bool) {
+ if let pageController = containerController as? UIPageScrollSystemController {
+ pageController.safeScrollTo(index: index, animated: animated)
+ }
+ }
+
+ public func getCurrentController() -> UIViewController? {
+ if let pageController = containerController as? UIPageScrollSystemController {
+ return pageController.getCurrentController()
+ }
+ return nil
+ }
+
+ public init(data: UIPageContainerControllerDataSystem, scrollSystem: UIPageContainerControllerScrollSystem) {
+ switch data {
+ case .dataSource(let dataSource):
+ switch scrollSystem {
+ case .page:
+ containerController = UIPageScrollSystemController(dataSource: dataSource)
+ case .scroll:
+ fatalError()
+ }
+ case .array(let viewControllers):
+ switch scrollSystem {
+ case .page:
+ containerController = UIPageScrollSystemController(viewControllers: viewControllers)
+ case .scroll:
+ fatalError()
+ }
+ }
+ super.init(nibName: nil, bundle: nil)
+ }
+
+ public required init?(coder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ // MARK: - Lifecycle
+
+ open override func viewDidLoad() {
+ super.viewDidLoad()
+ //presentationController?.delegate = self
+
+ containerController.view.backgroundColor = .clear
+ addChild(containerController)
+ view.addSubview(containerController.view)
+ containerController.didMove(toParent: self)
+
+ containerController.view.preservesSuperviewLayoutMargins = true
+ containerController.view.translatesAutoresizingMaskIntoConstraints = false
+ NSLayoutConstraint.activate([
+ containerController.view.topAnchor.constraint(equalTo: view.topAnchor),
+ containerController.view.leftAnchor.constraint(equalTo: view.leftAnchor),
+ containerController.view.rightAnchor.constraint(equalTo: view.rightAnchor),
+ containerController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor)
+ ])
+ }
+}
+
+public enum UIPageContainerControllerScrollSystem {
+
+ case page
+ case scroll
+}
+
+public protocol UIPageContainerControllerDataSource {
+
+ func pageContainerViewController(for index: Int) -> UIViewController?
+}
+
+public enum UIPageContainerControllerDataSystem {
+
+ case dataSource(dataSource: UIPageContainerControllerDataSource)
+ case array(viewControllers: [UIViewController])
+}
diff --git a/Sources/UIKitExtension/Controllers/UIPageContainerController/UIPageControllerInterface.swift b/Sources/UIKitExtension/Controllers/UIPageContainerController/UIPageControllerInterface.swift
new file mode 100644
index 0000000..d247452
--- /dev/null
+++ b/Sources/UIKitExtension/Controllers/UIPageContainerController/UIPageControllerInterface.swift
@@ -0,0 +1,10 @@
+import UIKit
+
+protocol UIPageContainerControllerInterface: AnyObject {
+
+ var allowScroll: Bool { get set }
+
+ func safeScrollTo(index: Int, animated: Bool)
+
+ func getCurrentController() -> UIViewController?
+}
diff --git a/Sources/UIKitExtension/Controllers/UIPageContainerController/UIPageScrollSystemController.swift b/Sources/UIKitExtension/Controllers/UIPageContainerController/UIPageScrollSystemController.swift
new file mode 100644
index 0000000..c1ae66f
--- /dev/null
+++ b/Sources/UIKitExtension/Controllers/UIPageContainerController/UIPageScrollSystemController.swift
@@ -0,0 +1,123 @@
+import UIKit
+
+extension UIPageContainerController {
+
+ class UIPageScrollSystemController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate, UIPageContainerControllerInterface {
+
+ private var childControllers: [UIViewController]? = nil
+ private var controllersDataSource: UIPageContainerControllerDataSource?
+
+ // MARK: - Init
+
+ init(dataSource: UIPageContainerControllerDataSource, initialIndex: Int = .zero) {
+ self.controllersDataSource = dataSource
+ super.init(transitionStyle: .scroll, navigationOrientation: .horizontal, options: [:])
+ guard let firstController = getViewController(for: initialIndex) else { return }
+ setViewControllers([firstController], direction: .forward, animated: false)
+ }
+
+ init(viewControllers: [UIViewController]) {
+ self.childControllers = viewControllers
+ super.init(transitionStyle: .scroll, navigationOrientation: .horizontal, options: [:])
+ guard let firstController = self.childControllers?.first else { return }
+ setViewControllers([firstController], direction: .forward, animated: false)
+ }
+
+ required init?(coder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ dataSource = self
+ delegate = self
+
+ view.layoutMargins = .zero
+ view.preservesSuperviewLayoutMargins = true
+ view.insetsLayoutMarginsFromSafeArea = false
+
+ for view in view.subviews {
+ if let scrollView = view as? UIScrollView {
+ scrollView.delaysContentTouches = false
+ scrollView.preservesSuperviewLayoutMargins = true
+ }
+ }
+
+ if #available(iOS 13.0, *) {
+ view.backgroundColor = .systemBackground
+ }
+ }
+
+ // MARK: - Layout
+
+ override func viewDidLayoutSubviews() {
+ super.viewDidLayoutSubviews()
+ // todo add observing margins for controllers
+ /*let margins = view.layoutMargins
+ childControllers.forEach({
+ if $0.view.preservesSuperviewLayoutMargins && $0.view.layoutMargins != margins {
+ $0.view.layoutMargins = margins
+ }
+ })*/
+ }
+
+ // MARK: - SPPageControllerInterface
+
+ // todo complete
+ var allowScroll: Bool = false
+
+ // todo complete
+ func safeScrollTo(index: Int, animated: Bool) {
+ guard let controller = getViewController(for: index) else { return }
+ setViewControllers([controller], direction: .forward, animated: animated)
+
+ }
+
+ func getCurrentController() -> UIViewController? {
+ return viewControllers?.first
+ }
+
+ // MARK: - UIPageViewControllerDataSource
+
+ func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
+ if let childControllers = self.childControllers {
+ guard let index = childControllers.firstIndex(of: viewController) else { return nil }
+ let newIndex = index - 1
+ if newIndex < 0 { return nil }
+ return childControllers[newIndex]
+ } else {
+ print("vv \(viewController)")
+ guard let currentIndex = (viewController as? UIPageContainerControllerIndexProtocol)?.pageControllerIndex else { fatalError() }
+ return getViewController(for: currentIndex - 1)
+ }
+ }
+
+ func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
+ if let childControllers = self.childControllers {
+ guard let index = childControllers.firstIndex(of: viewController) else { return nil }
+ let newIndex = index + 1
+ if newIndex > childControllers.count - 1 { return nil }
+ return childControllers[newIndex]
+ } else {
+ guard let indexBefore = (viewController as? UIPageContainerControllerIndexProtocol)?.pageControllerIndex else { fatalError() }
+ print("currentIndex before \(indexBefore)")
+ return getViewController(for: indexBefore + 1)
+ }
+ }
+
+ // MARK: - Internal
+
+ private func getViewController(for index: Int) -> UIViewController? {
+ print("ask controller for index \(index) in page")
+ guard let controller = controllersDataSource?.pageContainerViewController(for: index) else { return nil }
+ guard var indexController = controller as? UIPageContainerControllerIndexProtocol else { fatalError() }
+ indexController.pageControllerIndex = index
+ return indexController as? UIViewController
+ }
+ }
+}
+
+public protocol UIPageContainerControllerIndexProtocol {
+
+ var pageControllerIndex: Int? { get set }
+}
diff --git a/Sources/UIKitExtension/Controllers/UIPopoverNavigationController.swift b/Sources/UIKitExtension/Controllers/UIPopoverNavigationController.swift
new file mode 100644
index 0000000..460eebe
--- /dev/null
+++ b/Sources/UIKitExtension/Controllers/UIPopoverNavigationController.swift
@@ -0,0 +1,35 @@
+import UIKit
+
+open class UIPopoverNavigationController: UICommonNavigationController, UIPopoverPresentationControllerDelegate {
+
+ public init(rootController: UIViewController, preferredContentSize size: CGSize, sourceView: UIView, direction: UIPopoverArrowDirection) {
+ super.init(rootViewController: rootController)
+
+ modalPresentationStyle = .popover
+ preferredContentSize = size
+ popoverPresentationController?.permittedArrowDirections = [direction]
+ popoverPresentationController?.sourceView = sourceView
+ popoverPresentationController?.sourceRect = sourceView.frame
+ popoverPresentationController?.delegate = self
+ }
+
+ public init(rootController: UIViewController, preferredContentSize size: CGSize, sourceBarButtonItem: UIBarButtonItem, direction: UIPopoverArrowDirection) {
+ super.init(rootViewController: rootController)
+
+ modalPresentationStyle = .popover
+ preferredContentSize = size
+ popoverPresentationController?.permittedArrowDirections = [direction]
+ popoverPresentationController?.barButtonItem = sourceBarButtonItem
+ popoverPresentationController?.delegate = self
+ }
+
+ required public init?(coder aDecoder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ // MARK: - UIPopoverPresentationControllerDelegate
+
+ public func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
+ return .none
+ }
+}
diff --git a/Sources/UIKitExtension/Controllers/UIProfileNavigationController.swift b/Sources/UIKitExtension/Controllers/UIProfileNavigationController.swift
new file mode 100644
index 0000000..324eeee
--- /dev/null
+++ b/Sources/UIKitExtension/Controllers/UIProfileNavigationController.swift
@@ -0,0 +1,90 @@
+import UIKit
+import SwiftBoost
+
+open class UIProfileNavigationController: UICommonNavigationController {
+
+ open lazy var avatarControl = UIAvatarControl()
+
+ open lazy var navigationSubtitleLabel = UILabel().do {
+ $0.font = .preferredFont(forTextStyle: .footnote)
+ $0.textColor = .secondaryLabel
+ $0.numberOfLines = 1
+ $0.text = nil
+ }
+
+ // MARK: - Init
+
+ open override func commonInit() {
+ super.commonInit()
+ }
+
+ // MARK: - UINavigationControllerDelegate
+
+ open func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
+ if !isShowProfile(for: viewController) {
+ removeAvatarControl()
+ }
+ }
+
+ open func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
+ if isShowProfile(for: viewController) {
+ addAvatarControl()
+ }
+ }
+
+ // MARK: - Profile
+
+ private var profileAnimationDuration: TimeInterval { 0.12 }
+
+ open func isShowProfile(for viewController: UIViewController) -> Bool {
+ return (viewController as? UIProfileNavigationControllerDelegate)?.isShowProfile ?? false
+ }
+
+ internal func addAvatarControl() {
+
+ let navBar = navigationBar
+ navBar.subviews.forEach { subview in
+
+ let stringFromClass = NSStringFromClass(subview.classForCoder)
+#if targetEnvironment(macCatalyst)
+ guard stringFromClass.contains("UINavigationBarContentView") else { return }
+#else
+ guard stringFromClass.contains("UINavigationBarLargeTitleView") else { return }
+#endif
+
+ if avatarControl.superview != subview {
+ avatarControl.removeFromSuperview()
+ subview.addSubview(avatarControl)
+ }
+
+ avatarControl.alpha = .zero
+ avatarControl.isUserInteractionEnabled = true
+ UIView.animate(withDuration: profileAnimationDuration, delay: .zero, options: [.beginFromCurrentState, .allowUserInteraction], animations: {
+ self.avatarControl.alpha = 1
+ })
+
+ avatarControl.translatesAutoresizingMaskIntoConstraints = false
+ avatarControl.removeConstraints(avatarControl.constraints)
+ avatarControl.widthAnchor.constraint(equalToConstant: 36).isActive = true
+ avatarControl.heightAnchor.constraint(equalToConstant: 36).isActive = true
+ avatarControl.bottomAnchor.constraint(equalTo: avatarControl.superview!.bottomAnchor, constant: -10).isActive = true
+ avatarControl.trailingAnchor.constraint(equalTo: subview.safeAreaLayoutGuide.trailingAnchor, constant: -16).isActive = true
+ }
+ }
+
+ internal func removeAvatarControl() {
+ self.navigationSubtitleLabel.removeFromSuperview()
+ UIView.animate(withDuration: profileAnimationDuration, delay: .zero, options: [.beginFromCurrentState, .allowUserInteraction, .curveEaseInOut], animations: {
+ self.avatarControl.alpha = .zero
+ }, completion: { finished in
+ if finished {
+ self.avatarControl.removeFromSuperview()
+ }
+ })
+ }
+}
+
+public protocol UIProfileNavigationControllerDelegate {
+
+ var isShowProfile: Bool { get }
+}
diff --git a/Sources/UIKitExtension/Controls/Buttons/UIDimmedButton.swift b/Sources/UIKitExtension/Controls/Buttons/UIDimmedButton.swift
new file mode 100644
index 0000000..99c9838
--- /dev/null
+++ b/Sources/UIKitExtension/Controls/Buttons/UIDimmedButton.swift
@@ -0,0 +1,256 @@
+#if canImport(UIKit) && (os(iOS) || os(tvOS))
+import UIKit
+
+/**
+ UIKitExtension: Button with process dimmed colors.
+
+ Button support color states like `basic`, `dimmed` and `disabled`.
+ For change it using `Colorise` object.
+
+ Also available tinting for all modes.
+ */
+open class UIDimmedButton: UICommonButton {
+
+ open override var isHighlighted: Bool {
+ didSet {
+ updateAppearance()
+ }
+ }
+
+ open override var isEnabled: Bool {
+ didSet {
+ updateAppearance()
+ }
+ }
+
+ open override func tintColorDidChange() {
+ super.tintColorDidChange()
+ updateAppearance()
+ }
+
+ /**
+ UIKitExtension: Higlight style when button pressing.
+
+ If set content, only label and image change opacity.
+ If choosed background, area of button will change opacity.
+ */
+ open var higlightStyle = HiglightStyle.default
+
+ // MARK: - Colorises
+
+ private lazy var defaultColorise = Colorise(content: tintColor, background: .clear)
+ private lazy var disabledColorise = Colorise(content: .dimmedContent, background: .clear)
+ private lazy var dimmedColorise = Colorise(content: .dimmedContent, background: .clear)
+
+ // MARK: - Data
+
+ /**
+ UIKitExtension: Opacity of elements when button higlight.
+ */
+ open var highlightOpacity: CGFloat = 0.7
+
+ // MARK: - Process
+
+ open func setColorise(_ colorise: Colorise, for state: AppearanceState) {
+ switch state {
+ case .default:
+ defaultColorise = colorise
+ case .dimmed:
+ dimmedColorise = colorise
+ case .disabled:
+ disabledColorise = colorise
+ }
+ updateAppearance()
+ }
+
+ open func getColorise(for state: AppearanceState) -> Colorise {
+ switch state {
+ case .default:
+ return defaultColorise
+ case .dimmed:
+ return dimmedColorise
+ case .disabled:
+ return disabledColorise
+ }
+ }
+
+ /**
+ UIKitExtension: Set the color scheme for the default state.
+ `.dimmed` and `.disabled` states calculate automaticaly.
+ */
+ open func applyDefaultAppearance(with colorise: Colorise? = nil) {
+ defaultColorise = colorise ?? Colorise(content: .tint, background: .custom(.clear))
+ let defaultBackgroundColor = colorFromColoriseMode(defaultColorise.background)
+ let dimmedBackground = (defaultBackgroundColor == .clear) ? UIColor.clear : .dimmedBackground
+ dimmedColorise = Colorise(content: .dimmedContent, background: dimmedBackground)
+ disabledColorise = Colorise(content: .dimmedContent, background: dimmedBackground)
+ updateAppearance()
+ }
+
+ private func updateAppearance() {
+ if tintAdjustmentMode == .dimmed {
+ applyColorise(dimmedColorise)
+ } else if isEnabled {
+ let colorise = self.defaultColorise
+ applyColorise(colorise)
+
+ // Image Tint Color
+ var imageTintColor = colorFromColoriseMode(colorise.icon)
+ imageTintColor = imageTintColor.withAlphaComponent(isHighlighted ? imageTintColor.alpha * highlightOpacity : imageTintColor.alpha)
+ imageView?.tintColor = imageTintColor
+
+ // Higlight
+ switch higlightStyle {
+ case .content:
+ break
+ case .background:
+ let color = colorFromColoriseMode(colorise.background)
+ backgroundColor = color.alpha(isHighlighted ? color.alpha * highlightOpacity : color.alpha)
+ }
+ } else {
+ applyColorise(disabledColorise)
+ }
+ }
+
+ private func applyColorise(_ colorise: Colorise) {
+ let titleColor = colorFromColoriseMode(colorise.title)
+ setTitleColor(titleColor, for: .normal)
+ setTitleColor(titleColor.withAlphaComponent(highlightOpacity), for: .highlighted)
+ imageView?.tintColor = colorFromColoriseMode(colorise.icon)
+ backgroundColor = colorFromColoriseMode(colorise.background)
+ }
+
+ /**
+ UIKitExtension: Get valid color by `Colorise.Mode` for this button.
+
+ For example each call can return diffrent color for if changing tint.
+ If mode in custom always return this value.
+
+ - parameter mode: Colorise mode from which need get color.
+ */
+ public func colorFromColoriseMode(_ mode: Colorise.Mode) -> UIColor {
+ switch mode {
+ case .tint: return self.tintColor
+ case .secondaryTint: return self.tintColor.secondary
+ case .custom(let color): return color
+ }
+ }
+
+ // MARK: - Models
+
+ /**
+ UIKitExtension: Represent colors for state of button for elements.
+ */
+ public struct Colorise {
+
+ public var title: Mode
+ public var icon: Mode
+ public var background: Mode
+
+ public init(content: Mode, background: Mode) {
+ self.title = content
+ self.icon = content
+ self.background = background
+ }
+
+ public init(content: UIColor, background: UIColor) {
+ self.title = .custom(content)
+ self.icon = .custom(content)
+ self.background = .custom(background)
+ }
+
+ public init(content: UIColor, icon: UIColor, background: UIColor) {
+ self.title = .custom(content)
+ self.icon = .custom(icon)
+ self.background = .custom(background)
+ }
+
+ /**
+ UIKitExtension: Represent of rendering colors in button.
+
+ It need for have dynamic tint color and fixed custom.
+ */
+ public enum Mode {
+
+ /**
+ UIKitExtension: Always specific color.
+ */
+ case custom(UIColor)
+
+ /**
+ UIKitExtension: Observe and apply tint color of button.
+ */
+ case tint
+
+ /**
+ UIKitExtension: Observe and apply secondary tint color of button.
+ */
+ case secondaryTint
+ }
+
+ // MARK: - Ready Use
+
+ public static var tintedContent: Colorise {
+ return .init(content: .tint, background: .custom(.clear))
+ }
+
+ #if os(iOS)
+ @available(iOS 13.0, *)
+ public static var tintedContentSecondaryBackground : Colorise {
+ return .init(content: .tint, background: .custom(.secondarySystemBackground))
+ }
+
+ @available(iOS 13.0, *)
+ public static var tintedContentTertiaryBackground : Colorise {
+ return .init(content: .tint, background: .custom(.tertiarySystemBackground))
+ }
+
+ @available(iOS 13.0, *)
+ public static var tintedContentSecondaryGroupBackground : Colorise {
+ return .init(content: .tint, background: .custom(.secondarySystemGroupedBackground))
+ }
+
+ @available(iOS 13.0, *)
+ public static var tintedContentTertiaryGroupBackground : Colorise {
+ return .init(content: .tint, background: .custom(.tertiarySystemGroupedBackground))
+ }
+ #endif
+
+ public static var tintedColorful: Colorise {
+ return .init(content: .custom(.white), background: .tint)
+ }
+
+ public static var tinted: Colorise {
+ return .init(content: .tint, background: .secondaryTint)
+ }
+ }
+
+ public enum HiglightStyle {
+
+ case content
+ case background
+
+ static var `default`: HiglightStyle {
+ return .background
+ }
+ }
+
+ public enum AppearanceState {
+
+ /**
+ UIKitExtension: The button is in the normal state.
+ */
+ case `default`
+
+ /**
+ UIKitExtension: The button is in a dimmed state, for example when another `UIViewController` is presented.
+ */
+ case dimmed
+
+ /**
+ UIKitExtension: The button is disabled. Controlled through the `isDisabled` property.
+ */
+ case disabled
+ }
+}
+#endif
diff --git a/Sources/UIKitExtension/Controls/Buttons/UILargeActionButton.swift b/Sources/UIKitExtension/Controls/Buttons/UILargeActionButton.swift
new file mode 100644
index 0000000..a85c758
--- /dev/null
+++ b/Sources/UIKitExtension/Controls/Buttons/UILargeActionButton.swift
@@ -0,0 +1,84 @@
+#if canImport(UIKit) && (os(iOS))
+import UIKit
+
+/**
+ UIKitExtension: Large action button.
+ Usually using at bottom of screen.
+ */
+open class UILargeActionButton: UIDimmedButton {
+
+ // MARK: - Init
+
+ open override func commonInit() {
+ super.commonInit()
+ insetsLayoutMarginsFromSafeArea = false
+ preservesSuperviewLayoutMargins = false
+ titleLabel?.font = UIFont.preferredFont(forTextStyle: .headline, addPoints: 1)
+ titleLabel?.numberOfLines = 1
+ titleImageInset = 6
+ // before was 12, 14 looks little better
+ contentEdgeInsets = .init(horizontal: 10, vertical: 14)
+ roundCorners(curve: .continuous, radius: Appearance.Corners.readable_area)
+ }
+
+ // MARK: - Layout
+
+ /**
+ NativeUIKit: Layout wrapper. Native way for layout button.
+ */
+ open func layout(y: CGFloat) {
+ guard let superview = self.superview else { return }
+ sizeToFit()
+ let width = superview.readableWidth
+ frame.setWidth(width)
+ setXCenter()
+ frame.origin.y = y
+ }
+
+ /**
+ NativeUIKit: Layout wrapper. Native way for layout button.
+ */
+ open func layout(maxY: CGFloat) {
+ guard let superview = self.superview else { return }
+ sizeToFit()
+ let width = superview.readableWidth
+ frame.setWidth(width)
+ setXCenter()
+ frame.setMaxY(maxY)
+ }
+
+ open override func sizeThatFits(_ size: CGSize) -> CGSize {
+ let superSize = super.sizeThatFits(size)
+ let width = superSize.width
+
+ let height = superSize.height
+ /* Disabled image correction becouse
+ returned other values and its confused lauout system.
+ For now disabled.
+
+ // When set image, height may change.
+ // It's allow save height of button.
+ if let titleLabel = titleLabel, let imageView = imageView, let _ = imageView.image {
+ if titleLabel.frame.height > .zero && imageView.frame.height > .zero {
+ let imageCorrection = imageView.frame.height - titleLabel.frame.height
+ height -= imageCorrection
+ }
+ }*/
+ return CGSize(width: width, height: height)
+ }
+
+ // MARK: - Wrappers
+
+ public static var defaultCornerRadius: CGFloat {
+ let button = UILargeActionButton()
+ return button.layer.cornerRadius
+ }
+
+ public static var defaultHeight: CGFloat {
+ let button = UILargeActionButton()
+ button.setTitle(.space)
+ button.sizeToFit()
+ return button.frame.height
+ }
+}
+#endif
diff --git a/Sources/NativeUIKit/Views/NativeAvatarView.swift b/Sources/UIKitExtension/Controls/UIAvatarControl.swift
similarity index 53%
rename from Sources/NativeUIKit/Views/NativeAvatarView.swift
rename to Sources/UIKitExtension/Controls/UIAvatarControl.swift
index b647578..1fac753 100644
--- a/Sources/NativeUIKit/Views/NativeAvatarView.swift
+++ b/Sources/UIKitExtension/Controls/UIAvatarControl.swift
@@ -1,28 +1,190 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
#if canImport(UIKit) && (os(iOS))
import UIKit
-import SparrowKit
+/*
+ // edit buttons
+ open var indicatorAddImage = UIImage.system("plus", font: .preferredFont(forTextStyle: .title3, weight: .bold)) {
+ didSet {
+ updateEditAppearance()
+ }
+ }
+
+ open var indicatorAddColorise = UIDimmedButton.Colorise.init(content: .white, background: .systemGreen) {
+ didSet {
+ updateEditAppearance()
+ }
+ }
+
+ open var indicatorEditImage = UIImage.system("pencil", font: .preferredFont(forTextStyle: .title3, weight: .bold)) {
+ didSet {
+ updateEditAppearance()
+ }
+ }
+
+ open var indicatorEditColorise = UIDimmedButton.Colorise.init(content: .white, background: .systemBlue) {
+ didSet {
+ updateEditAppearance()
+ }
+ }
+ */
+
+open class UIAvatarControl: UICommonControl {
+
+ // MARK: - Views
+
+ public let activityIndicatorView = UIActivityIndicatorView().do {
+ $0.stopAnimating()
+ }
+
+ public let avatarView = UICommonImageView().do {
+ $0.contentMode = .scaleAspectFill
+ $0.layer.masksToBounds = true
+ }
+
+ public let placeholderView = UICommonImageView().do {
+ $0.image = UIImage.system("person.crop.circle.fill")
+ $0.contentMode = .scaleAspectFit
+ $0.tintColor = .init(light: .systemGray3, dark: .systemGray2)
+ }
+
+ public let indicatorButton = UIDimmedButton().do {
+ $0.contentEdgeInsets = .init(side: 4)
+ }
+
+ // MARK: - Public
+
+ open var hasAvatar: Bool {
+ switch avatarAppearance {
+ case .avatar(_): return true
+ default: return false
+ }
+ }
+
+ open var avatarAppearance: AvatarAppearance = .placeholder {
+ didSet {
+ updateAvatarAppearance()
+ updateEditAppearance()
+ }
+ }
+
+ open var isEditable: Bool = false {
+ didSet {
+ updateEditAppearance()
+ }
+ }
+
+ @objc func didTapAction(sender: UITapGestureRecognizer) {
+ self.sendActions(for: .touchUpInside)
+ }
+
+ open override var isHighlighted: Bool {
+ didSet {
+ placeholderView.alpha = isHighlighted ? 0.8 : 1
+ }
+ }
+
+ // MARK: - Init
+
+ open override func commonInit() {
+ super.commonInit()
+ layoutMargins = .zero
+ addSubview(placeholderView)
+ addSubview(avatarView)
+ addSubview(activityIndicatorView)
+
+ updateAvatarAppearance()
+ updateEditAppearance()
+
+ addGestureRecognizer(tapGestureRecognizer)
+ tapGestureRecognizer.addTarget(self, action: #selector(didTapAction(sender: )))
+
+ addSubview(indicatorButton)
+ }
+
+ // MARK: - Layout
+
+ open override func layoutSubviews() {
+ super.layoutSubviews()
+
+ placeholderView.setEqualSuperviewMarginsWithFrames()
+ avatarView.setEqualSuperviewMarginsWithFrames()
+
+ indicatorButton.sizeToFit()
+ indicatorButton.roundMinimumSide()
+ let sqrt2 = CGFloat(sqrt(2))
+ if rtl {
+ let indicatorCenter = ((avatarView.frame.width * (sqrt2 + 1)) / (2 * sqrt2)) * 1.02
+ indicatorButton.center = .init(x: frame.width - indicatorCenter, y: indicatorCenter)
+ } else {
+ let indicatorCenter = ((avatarView.frame.width * (sqrt2 + 1)) / (2 * sqrt2)) * 1.02
+ indicatorButton.center = .init(x: indicatorCenter, y: indicatorCenter)
+ }
+
+ activityIndicatorView.setToCenter()
+ }
+
+ // MARK: - Internal
+
+ let tapGestureRecognizer = UITapGestureRecognizer()
+
+ internal func updateAvatarAppearance() {
+ switch avatarAppearance {
+ case .loading:
+ activityIndicatorView.startAnimating()
+ avatarView.isHidden = true
+ placeholderView.isHidden = true
+ case .placeholder:
+ activityIndicatorView.stopAnimating()
+ avatarView.isHidden = true
+ placeholderView.isHidden = false
+ case .avatar(let image):
+ activityIndicatorView.stopAnimating()
+ avatarView.isHidden = false
+ avatarView.image = image
+ placeholderView.isHidden = true
+ }
+ }
+
+ internal func updateEditAppearance() {
+ if isEditable {
+ switch avatarAppearance {
+ case .loading:
+ indicatorButton.isHidden = true
+ case .placeholder:
+ indicatorButton.isHidden = false
+ //indicatorButton.setImage(indicatorAddImage)
+ //indicatorButton.applyDefaultAppearance(with: indicatorAddColorise)
+ case .avatar(_):
+ indicatorButton.isHidden = false
+ //indicatorButton.setImage(indicatorEditImage)
+ //indicatorButton.applyDefaultAppearance(with: indicatorEditColorise)
+ }
+ } else {
+ indicatorButton.isHidden = true
+ }
+
+ [placeholderView, avatarView, indicatorButton].forEach({ $0.isUserInteractionEnabled = isEditable })
+ }
+
+ // MARK: - Models
+
+ public enum AvatarAppearance {
+
+ case loading
+ case placeholder
+ case avatar(_ image: UIImage)
+ }
+
+ public enum EditAppearance {
+
+ case none
+ case edit
+ case add
+ }
+}
+
+/*
/**
NativeUIKit: Native avatar view.
@@ -31,8 +193,9 @@ import SparrowKit
For change colors or content check images and colorises properties.
For change show edit button set `isEditable` to true.
*/
+#warning("todo redo it")
@available(iOS 13, *)
-open class NativeAvatarView: SPView {
+open class NativeAvatarView22: SPView {
// MARK: - Views
@@ -47,10 +210,10 @@ open class NativeAvatarView: SPView {
$0.contentHorizontalAlignment = .fill
}
- public lazy var placeholderButton = SPDimmedButton().do {
+ public lazy var placeholderButton = SPButton().do {
$0.imageView?.contentMode = .scaleAspectFit
- $0.setImage(placeholderImage)
- $0.applyDefaultAppearance(with: placeholderColorise)
+ $0.setImage(placeholderImage.alwaysTemplate)
+ $0.tintColor = .init(light: .systemGray3, dark: .systemGray2)
}
public lazy var indicatorButton = SPDimmedButton().do {
@@ -97,7 +260,7 @@ open class NativeAvatarView: SPView {
open var placeholderColorise = SPDimmedButton.Colorise.init(content: .init(light: .systemGray3, dark: .systemGray2), background: .clear) {
didSet {
- placeholderButton.applyDefaultAppearance(with: placeholderColorise)
+ //placeholderButton.applyDefaultAppearance(with: placeholderColorise)
}
}
@@ -154,8 +317,15 @@ open class NativeAvatarView: SPView {
indicatorButton.sizeToFit()
indicatorButton.roundMinimumSide()
let sqrt2 = CGFloat(sqrt(2))
- let indicatorCenter = ((avatarButton.frame.width * (sqrt2 + 1)) / (2 * sqrt2)) * 1.02
- indicatorButton.center = .init(x: indicatorCenter, y: indicatorCenter)
+
+
+ if rtl {
+ let indicatorCenter = ((avatarButton.frame.width * (sqrt2 + 1)) / (2 * sqrt2)) * 1.02
+ indicatorButton.center = .init(x: frame.width - indicatorCenter, y: indicatorCenter)
+ } else {
+ let indicatorCenter = ((avatarButton.frame.width * (sqrt2 + 1)) / (2 * sqrt2)) * 1.02
+ indicatorButton.center = .init(x: indicatorCenter, y: indicatorCenter)
+ }
activityIndicatorView.center = placeholderButton.center
}
@@ -251,5 +421,5 @@ open class NativeAvatarView: SPView {
case edit
case add
}
-}
+}*/
#endif
diff --git a/Sources/UIKitExtension/Diffable/DiffableEmptyRowItem.swift b/Sources/UIKitExtension/Diffable/DiffableEmptyRowItem.swift
new file mode 100644
index 0000000..1c7b901
--- /dev/null
+++ b/Sources/UIKitExtension/Diffable/DiffableEmptyRowItem.swift
@@ -0,0 +1,28 @@
+#if canImport(UIKit) && (os(iOS))
+import UIKit
+import DiffableKit
+
+open class DiffableEmptyRowItem: DiffableTableRow {
+
+ var verticalMargins: UIEmptyTableViewCell.Margins
+
+ public init(id: String, verticalMargins: UIEmptyTableViewCell.Margins, text: String, detail: String?) {
+ self.verticalMargins = verticalMargins
+ super.init(id: id, text: text, detail: detail)
+ }
+}
+
+extension DiffableTableDataSource.CellProvider {
+
+ public static var empty: DiffableTableDataSource.CellProvider {
+ return DiffableTableDataSource.CellProvider() { (tableView, indexPath, item) -> UITableViewCell? in
+ guard let item = item as? DiffableEmptyRowItem else { return nil }
+ let cell = tableView.dequeueReusableCell(withClass: UIEmptyTableViewCell.self, for: indexPath)
+ cell.placeholderView.headerLabel.text = item.text
+ cell.placeholderView.descriptionLabel.text = item.detail
+ cell.verticalMargins = item.verticalMargins
+ return cell
+ }
+ }
+}
+#endif
diff --git a/Sources/UIKitExtension/Diffable/DiffableLargeHeaderItem.swift b/Sources/UIKitExtension/Diffable/DiffableLargeHeaderItem.swift
new file mode 100644
index 0000000..54744b7
--- /dev/null
+++ b/Sources/UIKitExtension/Diffable/DiffableLargeHeaderItem.swift
@@ -0,0 +1,14 @@
+#if canImport(UIKit) && (os(iOS))
+import UIKit
+import DiffableKit
+
+open class DiffableLargeHeaderItem: DiffableActionableItem {
+
+ open var title: String
+
+ public init(id: String? = nil, title: String, action: Action? = nil) {
+ self.title = title
+ super.init(id: id ?? title, action: action)
+ }
+}
+#endif
diff --git a/Sources/UIKitExtension/Diffable/DiffableTableTextField.swift b/Sources/UIKitExtension/Diffable/DiffableTableTextField.swift
new file mode 100644
index 0000000..f34d698
--- /dev/null
+++ b/Sources/UIKitExtension/Diffable/DiffableTableTextField.swift
@@ -0,0 +1,39 @@
+#if canImport(UIKit) && (os(iOS))
+import UIKit
+import DiffableKit
+
+open class DiffableTableTextField: DiffableItem {
+
+ open var title: String? = nil
+ open var getTextFieldText: (() -> String?) = { return nil }
+ open var textFieldplaceholder: String? = nil
+ open var action: Action
+
+ public init(
+ id: String,
+ title: String?,
+ getTextFieldText: @escaping (() -> String?),
+ textFieldplaceholder: String?,
+ action: @escaping Action
+ ) {
+ self.title = title
+ self.getTextFieldText = getTextFieldText
+ self.textFieldplaceholder = textFieldplaceholder
+ self.action = action
+ super.init(id: id)
+ }
+
+ open override var hash: Int {
+ var hasher = Hasher()
+ hasher.combine(id)
+ return hasher.finalize()
+ }
+
+ open override func isEqual(_ object: Any?) -> Bool {
+ guard let object = object as? DiffableItem else { return false }
+ return id == object.id
+ }
+
+ public typealias Action = (_ item: DiffableItem, _ indexPath: IndexPath, _ value: String?) -> Void
+}
+#endif
diff --git a/Sources/UIKitExtension/Diffable/DiffableTintTableRow.swift b/Sources/UIKitExtension/Diffable/DiffableTintTableRow.swift
new file mode 100644
index 0000000..f45540d
--- /dev/null
+++ b/Sources/UIKitExtension/Diffable/DiffableTintTableRow.swift
@@ -0,0 +1,22 @@
+#if canImport(UIKit) && (os(iOS))
+import UIKit
+import DiffableKit
+
+open class DiffableTintedTableRow: DiffableTableRow {
+
+ open var color: UIColor
+
+ public init(
+ id: String? = nil,
+ text: String,
+ detail: String? = nil,
+ icon: UIImage? = nil,
+ color: UIColor,
+ accessoryType: UITableViewCell.AccessoryType = .none,
+ action: Action? = nil
+ ) {
+ self.color = color
+ super.init(id: id ?? text, text: text, detail: detail, icon: icon, accessoryType: accessoryType, selectionStyle: .none, action: action)
+ }
+}
+#endif
diff --git a/Sources/UIKitExtension/Extensions/UIColorExtension.swift b/Sources/UIKitExtension/Extensions/UIColorExtension.swift
new file mode 100644
index 0000000..3184fd9
--- /dev/null
+++ b/Sources/UIKitExtension/Extensions/UIColorExtension.swift
@@ -0,0 +1,52 @@
+#if canImport(UIKit)
+import UIKit
+
+extension UIColor {
+
+ public static var secondarySystemGroupedBorder: UIColor {
+ return .init(
+ light: secondarySystemGroupedBackground.darker(by: 0.1),
+ dark: secondarySystemGroupedBackground.lighter(by: 0.1)
+ )
+ }
+
+ /**
+ UIKitExtension: New color to system stack.
+ Its color for empty areas and it usually downed of main background color.
+ */
+ public static var systemDownedBackground: UIColor {
+ let lightColor = UIColor.secondarySystemBackground.mixWithColor(.darkGray, amount: 0.09).mixWithColor(UIColor.systemBlue, amount: 0.01)
+ let darkColor = UIColor.secondarySystemBackground
+ return UIColor.init(light: lightColor, dark: darkColor)
+ }
+
+
+ /**
+ UIKitExtension: New color to system grouped stack.
+ Its color for empty aread and it usually downed of content background color.
+ */
+ public static var systemDownedGroupedBackground: UIColor {
+ return UIColor.init(dynamicProvider: { trait in
+ if trait.userInterfaceStyle == .light {
+ return UIColor.systemGroupedBackground.mixWithColor(.darkGray, amount: 0.09).mixWithColor(UIColor.systemBlue, amount: 0.01)
+ } else {
+ return UIColor.secondarySystemGroupedBackground.alpha(0.7)
+ }
+ })
+ }
+
+ /**
+ UIKitExtension: Dimmed content color.
+ */
+ public static var dimmedContent: UIColor {
+ return UIColor.secondaryLabel
+ }
+
+ /**
+ UIKitExtension: Dimmed background color.
+ */
+ public static var dimmedBackground: UIColor {
+ dimmedContent.alpha(0.1)
+ }
+}
+#endif
diff --git a/Sources/UIKitExtension/Extensions/UIImageExtension.swift b/Sources/UIKitExtension/Extensions/UIImageExtension.swift
new file mode 100644
index 0000000..d57979d
--- /dev/null
+++ b/Sources/UIKitExtension/Extensions/UIImageExtension.swift
@@ -0,0 +1,25 @@
+#if canImport(UIKit)
+import UIKit
+
+public extension UIImage {
+
+ /**
+ UIKitExtension: For iOS version get fill image, for macOS get lines images.
+ */
+ static func adaptive(_ name: String) -> UIImage {
+ var formattedName = name
+ let fillSuffix = ".fill"
+ if UIDevice.current.isMac {
+ if name.hasSuffix(fillSuffix) {
+ formattedName = name.removedSuffix(fillSuffix)
+ }
+ } else {
+ if !name.hasSuffix(fillSuffix) {
+ formattedName = name + fillSuffix
+ }
+ }
+ let image = UIImage.init(systemName: formattedName)
+ return image ?? UIImage.system(name)
+ }
+}
+#endif
diff --git a/Sources/UIKitExtension/Extensions/UIScreenExtension.swift b/Sources/UIKitExtension/Extensions/UIScreenExtension.swift
new file mode 100644
index 0000000..ecf1c23
--- /dev/null
+++ b/Sources/UIKitExtension/Extensions/UIScreenExtension.swift
@@ -0,0 +1,11 @@
+import UIKit
+
+public extension UIScreen {
+
+ var displayCornerRadius: CGFloat {
+ guard let cornerRadius = self.value(forKey: "_displayCornerRadius") as? CGFloat else {
+ return .zero
+ }
+ return cornerRadius
+ }
+}
diff --git a/Sources/UIKitExtension/Import.swift b/Sources/UIKitExtension/Import.swift
new file mode 100644
index 0000000..70e5cf2
--- /dev/null
+++ b/Sources/UIKitExtension/Import.swift
@@ -0,0 +1,2 @@
+import Foundation
+import SwiftBoost
diff --git a/Sources/UIKitExtension/Layout.swift b/Sources/UIKitExtension/Layout.swift
new file mode 100644
index 0000000..fe69e62
--- /dev/null
+++ b/Sources/UIKitExtension/Layout.swift
@@ -0,0 +1,21 @@
+#if canImport(UIKit) && (os(iOS))
+import UIKit
+
+public enum Spaces {
+
+ public static var step: CGFloat = 4
+
+ public static var default_less: CGFloat { step * 3 }
+ public static var `default`: CGFloat { step * 4 }
+ public static var default_more: CGFloat { step * 5 }
+
+ public static var default_half: CGFloat { self.default / 2 }
+ public static var default_double: CGFloat { self.default * 2 }
+}
+
+public enum Margins {
+
+ public static var full_screen_horizontal: CGFloat { Spaces.default }
+ public static var modal_screen_horizontal: CGFloat { Spaces.step * 5 }
+}
+#endif
diff --git a/Sources/UIKitExtension/Ready Use/FooterView/UIFooterCollectionFooterView.swift b/Sources/UIKitExtension/Ready Use/FooterView/UIFooterCollectionFooterView.swift
new file mode 100644
index 0000000..cccabd6
--- /dev/null
+++ b/Sources/UIKitExtension/Ready Use/FooterView/UIFooterCollectionFooterView.swift
@@ -0,0 +1,30 @@
+import UIKit
+
+open class UIFooterCollectionFooterView: UICommonCollectionReusableView {
+
+ public let contentView = UIFooterView()
+
+ open override func commonInit() {
+ super.commonInit()
+ layoutMargins = .zero
+ preservesSuperviewLayoutMargins = false
+ insetsLayoutMarginsFromSafeArea = false
+ addSubview(contentView)
+ }
+
+ open override func prepareForReuse() {
+ super.prepareForReuse()
+ }
+
+ open override func layoutSubviews() {
+ super.layoutSubviews()
+ contentView.setWidthAndFit(width: layoutWidth)
+ contentView.frame.origin = .init(x: layoutMargins.left, y: layoutMargins.top)
+ }
+
+ open override func sizeThatFits(_ size: CGSize) -> CGSize {
+ let superSize = super.sizeThatFits(size)
+ layoutSubviews()
+ return .init(width: superSize.width, height: contentView.frame.maxY + layoutMargins.bottom)
+ }
+}
diff --git a/Sources/UIKitExtension/Ready Use/FooterView/UIFooterView.swift b/Sources/UIKitExtension/Ready Use/FooterView/UIFooterView.swift
new file mode 100644
index 0000000..de0b6b6
--- /dev/null
+++ b/Sources/UIKitExtension/Ready Use/FooterView/UIFooterView.swift
@@ -0,0 +1,47 @@
+#if canImport(UIKit) && (os(iOS))
+import UIKit
+
+open class UIFooterView: UICommonView {
+
+ // MARK: - Views
+
+ public let label = UICommonLabel().do {
+ $0.font = .preferredFont(forTextStyle: .footnote)
+ $0.numberOfLines = .zero
+ if #available(iOS 13.0, *) {
+ $0.textColor = .secondaryLabel
+ } else {
+ $0.textColor = .gray
+ }
+ }
+
+ public override init() {
+ super.init()
+ }
+
+ public init(text: String) {
+ super.init()
+ label.text = text
+ }
+
+ required public init?(coder aDecoder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ open override func commonInit() {
+ super.commonInit()
+ layoutMargins = .init(top: Spaces.default_half, left: 16, bottom: Spaces.default_half, right: .zero)
+ addSubview(label)
+ }
+
+ open override func layoutSubviews() {
+ super.layoutSubviews()
+ label.layoutDynamicHeight(x: layoutMargins.left, y: layoutMargins.top, width: layoutWidth)
+ }
+
+ open override func sizeThatFits(_ size: CGSize) -> CGSize {
+ layoutSubviews()
+ return .init(width: size.width, height: label.frame.maxY + layoutMargins.bottom)
+ }
+}
+#endif
diff --git a/Sources/UIKitExtension/Ready Use/LargeButtonFooterView/UILargeButtonFooterView.swift b/Sources/UIKitExtension/Ready Use/LargeButtonFooterView/UILargeButtonFooterView.swift
new file mode 100644
index 0000000..9fac4a6
--- /dev/null
+++ b/Sources/UIKitExtension/Ready Use/LargeButtonFooterView/UILargeButtonFooterView.swift
@@ -0,0 +1,34 @@
+import UIKit
+
+open class UILargeButtonFooterView: UICommonView {
+
+ public let button = UILargeActionButton().do {
+ $0.applyDefaultAppearance(with: .tinted)
+ }
+
+ public let footerView = UIFooterView()
+
+ // MARK: - Init
+
+ open override func commonInit() {
+ super.commonInit()
+ addSubviews([button, footerView])
+ }
+
+ // MARK: - Layout
+
+ open override func layoutSubviews() {
+ super.layoutSubviews()
+ button.sizeToFit()
+ button.frame.setWidth(frame.width)
+
+ footerView.setWidthAndFit(width: button.frame.width)
+ footerView.frame.origin.x = button.frame.origin.x
+ footerView.frame.origin.y = button.frame.maxY
+ }
+
+ open override func sizeThatFits(_ size: CGSize) -> CGSize {
+ layoutSubviews()
+ return .init(width: size.width, height: footerView.frame.maxY + layoutMargins.bottom)
+ }
+}
diff --git a/Sources/UIKitExtension/Ready Use/LargeButtonFooterView/UILargeButtonFooterViewTableHeaderView.swift b/Sources/UIKitExtension/Ready Use/LargeButtonFooterView/UILargeButtonFooterViewTableHeaderView.swift
new file mode 100644
index 0000000..029c044
--- /dev/null
+++ b/Sources/UIKitExtension/Ready Use/LargeButtonFooterView/UILargeButtonFooterViewTableHeaderView.swift
@@ -0,0 +1,26 @@
+import UIKit
+
+open class UILargeButtonFooterViewTableHeaderView: UICommonView {
+
+ public let contentView = UILargeButtonFooterView()
+
+ open override func commonInit() {
+ super.commonInit()
+ addSubview(contentView)
+ layoutMargins = .zero
+ layoutMargins.top = Spaces.step
+ }
+
+ open override func layoutSubviews() {
+ super.layoutSubviews()
+ contentView.setWidthAndFit(width: readableWidth)
+ contentView.frame.origin.x = .zero
+ contentView.frame.origin.y = layoutMargins.top
+ }
+
+ open override func sizeThatFits(_ size: CGSize) -> CGSize {
+ let superSize = super.sizeThatFits(size)
+ layoutIfNeeded()
+ return .init(width: superSize.width, height: contentView.frame.maxY + layoutMargins.bottom)
+ }
+}
diff --git "a/Sources/UIKitExtension/Ready Use/LargeButtonFooterView/UILargeButtonFooterView\320\241ollectionHeaderView.swift" "b/Sources/UIKitExtension/Ready Use/LargeButtonFooterView/UILargeButtonFooterView\320\241ollectionHeaderView.swift"
new file mode 100644
index 0000000..704b3f5
--- /dev/null
+++ "b/Sources/UIKitExtension/Ready Use/LargeButtonFooterView/UILargeButtonFooterView\320\241ollectionHeaderView.swift"
@@ -0,0 +1,31 @@
+import UIKit
+
+open class UILargeButtonFooterViewСollectionHeaderView: UICommonCollectionReusableView {
+
+ public let contentView = UILargeButtonFooterView()
+
+ open override func commonInit() {
+ super.commonInit()
+ layoutMargins = .zero
+ preservesSuperviewLayoutMargins = false
+ insetsLayoutMarginsFromSafeArea = false
+ addSubview(contentView)
+ }
+
+ open override func prepareForReuse() {
+ super.prepareForReuse()
+ contentView.button.removeTargetsAndActions()
+ }
+
+ open override func layoutSubviews() {
+ super.layoutSubviews()
+ contentView.setWidthAndFit(width: layoutWidth)
+ contentView.frame.origin = .init(x: layoutMargins.left, y: layoutMargins.top)
+ }
+
+ open override func sizeThatFits(_ size: CGSize) -> CGSize {
+ let superSize = super.sizeThatFits(size)
+ layoutSubviews()
+ return .init(width: superSize.width, height: contentView.frame.maxY + layoutMargins.bottom)
+ }
+}
diff --git a/Sources/UIKitExtension/SettingIconGenerator.swift b/Sources/UIKitExtension/SettingIconGenerator.swift
new file mode 100644
index 0000000..abfaddd
--- /dev/null
+++ b/Sources/UIKitExtension/SettingIconGenerator.swift
@@ -0,0 +1,41 @@
+#if canImport(UIKit)
+import UIKit
+
+extension UIImage {
+
+ static var iconFontSize: Int { 16 }
+ static var backgroundFontSize: Int { 32 }
+ static var backgroundSystemName: String { "app.fill" }
+
+ @available(iOS 13, tvOS 13, *)
+ public static func generateSettingIcon(_ systemName: String, backgroundColor: UIColor) -> UIImage? {
+
+ let iconConfiguration = UIImage.SymbolConfiguration(pointSize: CGFloat(iconFontSize), weight: .regular)
+ let iconImage = UIImage(systemName: systemName, withConfiguration: iconConfiguration)?.withTintColor(.white, renderingMode: .alwaysOriginal)
+
+ #warning("bg area symol has border, must drop it")
+ let backgroundConfiguration = UIImage.SymbolConfiguration(pointSize: CGFloat(backgroundFontSize), weight: .regular)
+ let backgroundImage = UIImage(systemName: backgroundSystemName, withConfiguration: backgroundConfiguration)!.withTintColor(backgroundColor, renderingMode: .alwaysOriginal)
+
+ let size = backgroundImage.size
+ UIGraphicsBeginImageContextWithOptions(size, false, .zero)
+
+ backgroundImage.draw(in: CGRect(origin: .zero, size: size))
+
+ if let iconImage = iconImage {
+ let iconSize = iconImage.size
+ iconImage.draw(in: CGRect(
+ origin: .init(
+ x: (size.width - iconSize.width) / 2,
+ y: (size.height - iconSize.height) / 2
+ ),
+ size: iconSize
+ ))
+ }
+
+ let settingsImage = UIGraphicsGetImageFromCurrentImageContext()
+ UIGraphicsEndImageContext()
+ return settingsImage
+ }
+}
+#endif
diff --git a/Sources/UIKitExtension/Table/UIEmptyTableViewCell.swift b/Sources/UIKitExtension/Table/UIEmptyTableViewCell.swift
new file mode 100644
index 0000000..fc8cfbb
--- /dev/null
+++ b/Sources/UIKitExtension/Table/UIEmptyTableViewCell.swift
@@ -0,0 +1,80 @@
+#if canImport(UIKit) && (os(iOS))
+import UIKit
+import DiffableKit
+
+open class UIEmptyTableViewCell: UICommonTableViewCell {
+
+ // MARK: - Data
+
+ open var verticalMargins: Margins = .medium {
+ didSet {
+ contentView.layoutMargins.top = self.verticalMargins.value
+ contentView.layoutMargins.bottom = self.verticalMargins.value
+ }
+ }
+
+ // MARK: - Views
+
+ public let placeholderView = UIPlaceholderView().do {
+ $0.isUserInteractionEnabled = false
+ }
+
+ // MARK: - Init
+
+ open override func commonInit() {
+ super.commonInit()
+ selectionStyle = .none
+ contentView.addSubview(placeholderView)
+ updateBackgroundColorByParent()
+ }
+
+ // MARK: - Lifecycle
+
+ open override func tintColorDidChange() {
+ super.tintColorDidChange()
+ updateBackgroundColorByParent()
+ }
+
+ // MARK: - Layout
+
+ open override func layoutSubviews() {
+ super.layoutSubviews()
+ placeholderView.frame.origin.y = contentView.layoutMargins.top
+ placeholderView.setWidthAndFit(width: contentView.layoutWidth)
+ placeholderView.setXCenter()
+ }
+
+ open override func sizeThatFits(_ size: CGSize) -> CGSize {
+ let superSize = super.sizeThatFits(size)
+ layoutSubviews()
+ let calculatedHeight = placeholderView.frame.maxY + contentView.layoutMargins.bottom
+ let bottomInset = calculatedHeight * (1 - 0.94)
+ return .init(width: superSize.width, height: calculatedHeight + bottomInset)
+ }
+
+ // MARK: - Actions
+
+ private func updateBackgroundColorByParent() {
+ if #available(iOS 13.0, *) {
+ backgroundColor = UIColor.systemDownedGroupedBackground
+ }
+ }
+
+ // MARK: - Models
+
+ public enum Margins {
+
+ case small
+ case medium
+ case large
+
+ var value: CGFloat {
+ switch self {
+ case .small: return Spaces.default
+ case .medium: return Spaces.default * 2
+ case .large: return Spaces.default * 3
+ }
+ }
+ }
+}
+#endif
diff --git a/Sources/UIKitExtension/Table/UIHeaderTableController+HeaderContainerView.swift b/Sources/UIKitExtension/Table/UIHeaderTableController+HeaderContainerView.swift
new file mode 100644
index 0000000..c554090
--- /dev/null
+++ b/Sources/UIKitExtension/Table/UIHeaderTableController+HeaderContainerView.swift
@@ -0,0 +1,45 @@
+import UIKit
+
+extension UIHeaderTableController {
+
+ open class HeaderContainerView: UICommonView {
+
+ // MARK: - Public
+
+ public let contentView: UIView
+
+ // MARK: - Init
+
+ public init(contentView: UIView) {
+ self.contentView = contentView
+ super.init()
+ }
+
+ public required init?(coder aDecoder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ public override func commonInit() {
+ super.commonInit()
+ insetsLayoutMarginsFromSafeArea = false
+ layoutMargins = .zero
+ addSubview(contentView)
+ }
+
+ // MARK: - Layout
+
+ public override func layoutSubviews() {
+ super.layoutSubviews()
+ contentView.setWidthAndFit(width: layoutWidth)
+ contentView.frame.origin.x = layoutMargins.left
+ contentView.frame.origin.y = layoutMargins.top
+ }
+
+ public override func sizeThatFits(_ size: CGSize) -> CGSize {
+ frame.setWidth(size.width)
+ layoutSubviews()
+ //print(size.width, contentView.frame.maxY, layoutMargins.bottom)
+ return .init(width: size.width, height: contentView.frame.maxY + layoutMargins.bottom)
+ }
+ }
+}
diff --git a/Sources/UIKitExtension/Table/UIHeaderTableController.swift b/Sources/UIKitExtension/Table/UIHeaderTableController.swift
new file mode 100644
index 0000000..827efc3
--- /dev/null
+++ b/Sources/UIKitExtension/Table/UIHeaderTableController.swift
@@ -0,0 +1,68 @@
+import UIKit
+import DiffableKit
+
+open class UIHeaderTableController: DiffableTableController {
+
+ // MARK: - Public
+
+ open func setHeaderView(_ view: UIView) {
+ let containerView = HeaderContainerView(contentView: view)
+ //headerContainerView.setWidthAndFit(width: self.view.frame.width)
+ tableView.tableHeaderView = containerView
+ }
+
+ open func setFooterView(_ view: UIView) {
+ let containerView = HeaderContainerView(contentView: view)
+ //headerContainerView.setWidthAndFit(width: self.view.frame.width)
+ tableView.tableFooterView = containerView
+ }
+
+ open func setSpaceBetweenHeaderAndCells(_ value: CGFloat) {
+ tableView.tableHeaderView?.layoutMargins.bottom = value
+ }
+
+ open func setSpaceBetweenFooterAndCells(_ value: CGFloat) {
+ tableView.tableFooterView?.layoutMargins.top = value
+ }
+
+ // MARK: - Layout
+
+ open override func viewDidLayoutSubviews() {
+ super.viewDidLayoutSubviews()
+ for view in [tableView.tableHeaderView, tableView.tableFooterView] {
+ if let containerView = view as? HeaderContainerView {
+ if containerView.layoutMargins.left != tableView.layoutMargins.left {
+ containerView.layoutMargins.left = tableView.layoutMargins.left
+ }
+
+ if containerView.layoutMargins.right != tableView.layoutMargins.right {
+ containerView.layoutMargins.right = tableView.layoutMargins.right
+ }
+
+ containerView.setWidthAndFit(width: self.view.frame.width)
+
+ if view == tableView.tableHeaderView && cachedHeaderHeight != containerView.frame.height {
+ let animated = (cachedHeaderHeight == nil) ? false : true
+ cachedHeaderHeight = containerView.frame.height
+ DispatchQueue.main.async { [weak self] in
+ guard let self = self else { return }
+ self.diffableDataSource?.updateLayout(animated: animated, completion: nil)
+ }
+ }
+
+ if view == tableView.tableFooterView && cachedFooterHeight != containerView.frame.height {
+ let animated = (cachedHeaderHeight == nil) ? false : true
+ cachedFooterHeight = containerView.frame.height
+ DispatchQueue.main.async { [weak self] in
+ guard let self = self else { return }
+ self.diffableDataSource?.updateLayout(animated: animated, completion: nil)
+ }
+ }
+ }
+ }
+
+ }
+
+ private var cachedHeaderHeight: CGFloat? = nil
+ private var cachedFooterHeight: CGFloat? = nil
+}
diff --git a/Sources/UIKitExtension/Table/UILargeHeaderTableView.swift b/Sources/UIKitExtension/Table/UILargeHeaderTableView.swift
new file mode 100644
index 0000000..087ee50
--- /dev/null
+++ b/Sources/UIKitExtension/Table/UILargeHeaderTableView.swift
@@ -0,0 +1,45 @@
+#if canImport(UIKit) && (os(iOS))
+import UIKit
+import DiffableKit
+
+open class UILargeHeaderTableView: UICommonTableViewHeaderFooterView {
+
+ public let headerView = UILargeHeaderView()
+
+ open override func commonInit() {
+ super.commonInit()
+ insetsLayoutMarginsFromSafeArea = false
+ contentView.layoutMargins = .zero
+ contentView.layoutMargins.left = Spaces.default_half
+ contentView.preservesSuperviewLayoutMargins = false
+ contentView.insetsLayoutMarginsFromSafeArea = false
+ contentView.addSubview(headerView)
+ }
+
+ open override func layoutSubviews() {
+ super.layoutSubviews()
+ headerView.setWidthAndFit(width: contentView.layoutWidth)
+ headerView.frame.origin = .init(x: contentView.layoutMargins.left, y: contentView.layoutMargins.top)
+ }
+
+ open override func sizeThatFits(_ size: CGSize) -> CGSize {
+ let superSize = super.sizeThatFits(size)
+ return .init(width: superSize.width, height: headerView.frame.maxY + contentView.layoutMargins.bottom)
+ }
+}
+
+extension DiffableTableDataSource.HeaderFooterProvider {
+
+ public static var largeHeader: DiffableTableDataSource.HeaderFooterProvider {
+ return DiffableTableDataSource.HeaderFooterProvider() { (tableView, section, item) -> UIView? in
+ guard let header = item as? DiffableLargeHeaderItem else { return nil }
+ let view = tableView.dequeueReusableHeaderFooterView(withClass: UILargeHeaderTableView.self)
+ view.headerView.button.setTitle(header.title)
+ view.headerView.button.addAction(.init(handler: { _ in
+ header.action?(item, .init(row: .zero, section: section))
+ }), for: .touchUpInside)
+ return view
+ }
+ }
+}
+#endif
diff --git a/Sources/UIKitExtension/Table/UITextFieldTableViewCell.swift b/Sources/UIKitExtension/Table/UITextFieldTableViewCell.swift
new file mode 100644
index 0000000..a33a14b
--- /dev/null
+++ b/Sources/UIKitExtension/Table/UITextFieldTableViewCell.swift
@@ -0,0 +1,63 @@
+import UIKit
+import DiffableKit
+
+open class UITextFieldTableViewCell: UICommonTableViewCell {
+
+ public static var reuseIdentifier: String { "UITextFieldTableViewCell" }
+
+ public let titleLabel = UICommonLabel()
+ public let textField = UICommonTextField()
+
+ open override func commonInit() {
+ super.commonInit()
+ contentView.addSubviews(titleLabel, textField)
+ selectionStyle = .none
+ }
+
+ open override func layoutSubviews() {
+ super.layoutSubviews()
+ if titleLabel.text == nil {
+ textField.setEqualSuperviewMarginsWithFrames()
+ } else {
+ titleLabel.sizeToFit()
+ titleLabel.frame.origin.x = contentView.layoutMargins.left
+ titleLabel.setYCenter()
+
+ textField.sizeToFit()
+ textField.setYCenter()
+ let space: CGFloat = Spaces.default_half
+ textField.frame.setWidth(contentView.layoutWidth - titleLabel.frame.maxX - space)
+ textField.frame.origin.x = titleLabel.frame.maxX + space
+ }
+ }
+
+ open override func prepareForReuse() {
+ super.prepareForReuse()
+ titleLabel.text = nil
+ textField.text = nil
+ textField.placeholder = nil
+ textField.removeTargetsAndActions()
+ accessoryView = nil
+ textLabel?.text = nil
+ detailTextLabel?.text = nil
+ }
+}
+
+extension DiffableTableDataSource.CellProvider {
+
+ @available(iOS 14.0, *)
+ public static var textField: DiffableTableDataSource.CellProvider {
+ return DiffableTableDataSource.CellProvider() { (tableView, indexPath, item) -> UITableViewCell? in
+ guard let item = item as? DiffableTableTextField else { return nil }
+ let cell = tableView.dequeueReusableCell(withClass: UITextFieldTableViewCell.self, for: indexPath)
+ cell.titleLabel.text = item.title
+ cell.titleLabel.textColor = .secondaryLabel
+ cell.textField.text = item.getTextFieldText()
+ cell.textField.placeholder = item.textFieldplaceholder
+ cell.textField.addAction(.init(handler: { _ in
+ item.action(item, indexPath, cell.textField.text)
+ }), for: .editingChanged)
+ return cell
+ }
+ }
+}
diff --git a/Sources/UIKitExtension/Table/UITintedTableViewCell.swift b/Sources/UIKitExtension/Table/UITintedTableViewCell.swift
new file mode 100644
index 0000000..2efd9aa
--- /dev/null
+++ b/Sources/UIKitExtension/Table/UITintedTableViewCell.swift
@@ -0,0 +1,44 @@
+import UIKit
+import DiffableKit
+
+open class UITintedTableViewCell: DiffableTableViewCell {
+
+ public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
+ super.init(style: .value1, reuseIdentifier: reuseIdentifier)
+ textLabel?.font = UIFont.preferredFont(forTextStyle: .body, weight: .medium)
+ selectionStyle = .none
+ }
+
+ public required init?(coder: NSCoder) {
+ super.init(coder: coder)
+ }
+
+ open override func setHighlighted(_ highlighted: Bool, animated: Bool) {
+ for view in [imageView, textLabel] {
+ #warning("to constant higloight 0.7")
+ view?.alpha = highlighted ? 0.7 : 1
+ }
+ }
+
+ open override func sizeThatFits(_ size: CGSize) -> CGSize {
+ let superSize = super.sizeThatFits(size)
+ return .init(width: superSize.width, height: superSize.height + 4)
+ }
+}
+
+extension DiffableTableDataSource.CellProvider {
+
+ public static var rowTinted: DiffableTableDataSource.CellProvider {
+ return DiffableTableDataSource.CellProvider() { (tableView, indexPath, item) -> UITableViewCell? in
+ guard let item = item as? DiffableTintedTableRow else { return nil }
+ let cell = tableView.dequeueReusableCell(withClass: UITintedTableViewCell.self, for: indexPath)
+ cell.textLabel?.text = item.text
+ cell.detailTextLabel?.text = item.detail
+ cell.imageView?.image = item.icon
+ cell.accessoryType = item.accessoryType
+ cell.imageView?.tintColor = item.color
+ cell.textLabel?.textColor = item.color
+ return cell
+ }
+ }
+}
diff --git a/Sources/UIKitExtension/Views/Gradient/UIGradientView.swift b/Sources/UIKitExtension/Views/Gradient/UIGradientView.swift
new file mode 100644
index 0000000..c73e096
--- /dev/null
+++ b/Sources/UIKitExtension/Views/Gradient/UIGradientView.swift
@@ -0,0 +1,100 @@
+#if canImport(UIKit) && (os(iOS))
+import UIKit
+
+open class UIGradientView: UICommonView {
+
+ open var gradientLayer = CAGradientLayer()
+
+ open var startColor = UIColor.white {
+ didSet {
+ updateGradient()
+ }
+ }
+
+ open var endColor = UIColor.black {
+ didSet {
+ updateGradient()
+ }
+ }
+
+ open var startColorPosition = Position.topLeft {
+ didSet {
+ updateGradient()
+ }
+ }
+
+ open var endColorPosition = Position.bottomRight {
+ didSet {
+ updateGradient()
+ }
+ }
+
+ // MARK: - Init
+
+ open override func commonInit() {
+ super.commonInit()
+ layer.addSublayer(gradientLayer)
+ }
+
+ // MARK: - Lifecycle
+
+ open override func tintColorDidChange() {
+ super.tintColorDidChange()
+ updateGradient()
+ }
+
+ // MARK: - Layout
+
+ open override func layoutSublayers(of layer: CALayer) {
+ gradientLayer.frame = self.bounds
+ super.layoutSublayers(of: layer)
+ }
+
+ // MARK: - Helpers
+
+ private func updateGradient() {
+ gradientLayer.colors = [startColor.cgColor, endColor.cgColor]
+ gradientLayer.locations = [0.0, 1.0]
+ gradientLayer.startPoint = startColorPosition.point
+ gradientLayer.endPoint = endColorPosition.point
+ }
+
+ // MARK: - Models
+
+ public enum Position {
+
+ case topLeft
+ case topCenter
+ case topRight
+ case bottomLeft
+ case bottomCenter
+ case bottomRight
+ case mediumLeft
+ case mediumRight
+ case mediumCenter
+
+ var point: CGPoint {
+ switch self {
+ case .topLeft:
+ return CGPoint.init(x: 0, y: 0)
+ case .topCenter:
+ return CGPoint.init(x: 0.5, y: 0)
+ case .topRight:
+ return CGPoint.init(x: 1, y: 0)
+ case .bottomLeft:
+ return CGPoint.init(x: 0, y: 1)
+ case .bottomCenter:
+ return CGPoint.init(x: 0.5, y: 1)
+ case .bottomRight:
+ return CGPoint.init(x: 1, y: 1)
+ case .mediumLeft:
+ return CGPoint.init(x: 0, y: 0.5)
+ case .mediumRight:
+ return CGPoint.init(x: 1, y: 0.5)
+ case .mediumCenter:
+ return CGPoint.init(x: 0.5, y: 0.5)
+ }
+ }
+ }
+}
+#endif
diff --git a/Sources/UIKitExtension/Views/UIBorderedView.swift b/Sources/UIKitExtension/Views/UIBorderedView.swift
new file mode 100644
index 0000000..511aad1
--- /dev/null
+++ b/Sources/UIKitExtension/Views/UIBorderedView.swift
@@ -0,0 +1,83 @@
+#if canImport(UIKit) && (os(iOS))
+import UIKit
+import SwiftBoost
+
+open class UIBorderedView: UICommonView {
+
+ // MARK: - Data
+
+ open var position: Position = .top {
+ didSet {
+ layoutSubviews()
+ }
+ }
+
+ // MARK: - Views
+
+ private let borderView = UICommonView().do {
+ if #available(iOS 13.0, *) {
+ $0.backgroundColor = .separator
+ } else {
+ $0.backgroundColor = .systemGray
+ }
+ }
+
+ // MARK: - Init
+
+ public init(position: Position) {
+ self.position = position
+ super.init()
+ }
+
+ public required init?(coder aDecoder: NSCoder) {
+ super.init(coder: aDecoder)
+ }
+
+ open override func commonInit() {
+ super.commonInit()
+ layoutMargins = .zero
+ addSubview(borderView)
+ }
+
+ // MARK: - Actions
+
+ public func setBorderVisible(_ visible: Bool, animated: Bool) {
+ let work = { [weak self] in
+ guard let self = self else { return }
+ self.borderView.alpha = visible ? 1 : 0
+ }
+ if animated {
+ UIView.animate(withDuration: 0.3, delay: 0, options: [.beginFromCurrentState, .allowUserInteraction], animations: {
+ work()
+ })
+ } else {
+ work()
+ }
+ }
+
+ // MARK: - Layout
+
+ open override func layoutSubviews() {
+ super.layoutSubviews()
+ let leftMargin = self.layoutMargins.left
+ let rightMargin = self.layoutMargins.right
+ borderView.frame.setWidth(frame.width - leftMargin - rightMargin)
+ borderView.frame.setHeight(0.7)
+ borderView.frame.origin.x = leftMargin
+ switch position {
+ case .top:
+ borderView.frame.origin.y = 0
+ case .bottom:
+ borderView.frame.setMaxY(frame.height)
+ }
+ }
+
+ // MARK: - Models
+
+ public enum Position {
+
+ case top
+ case bottom
+ }
+}
+#endif
diff --git a/Sources/UIKitExtension/Views/UILargeHeaderView.swift b/Sources/UIKitExtension/Views/UILargeHeaderView.swift
new file mode 100644
index 0000000..6d19df5
--- /dev/null
+++ b/Sources/UIKitExtension/Views/UILargeHeaderView.swift
@@ -0,0 +1,106 @@
+#if canImport(UIKit) && (os(iOS))
+import UIKit
+import SwiftBoost
+
+open class UILargeHeaderView: UICommonView {
+
+ // MARK: - Views
+
+ public let button = UIDimmedButton().do {
+ $0.applyDefaultAppearance(with: .init(content: .label, background: .clear))
+ $0.higlightStyle = .content
+ $0.titleLabel?.font = UIFont.preferredFont(forTextStyle: .title2, weight: .bold)
+ }
+
+ public var showChevron: Bool = false {
+ didSet {
+ if showChevron {
+ var image = UIImage(systemName: "chevron.right")
+ let fontConfig = UIImage.SymbolConfiguration(font: UIFont.preferredFont(forTextStyle: .body, weight: .bold))
+ image = image?.applyingSymbolConfiguration(fontConfig)
+ image = image?.withTintColor(.secondaryLabel, renderingMode: .alwaysOriginal)
+ button.setImage(image)
+ } else {
+ button.setImage(nil)
+ }
+ }
+ }
+
+ // MARK: - Init
+
+ open override func commonInit() {
+ super.commonInit()
+ insetsLayoutMarginsFromSafeArea = false
+ preservesSuperviewLayoutMargins = false
+ layoutMargins = .init(top: Spaces.default_double, left: .zero, bottom: 14, right: .zero)
+ addSubviews(button)
+
+ showChevron = true
+ }
+
+ // MARK: - Layout
+
+ public func layout(y: CGFloat) {
+ guard let superview = self.superview else { return }
+ setWidthAndFit(width: superview.layoutWidth)
+ frame.origin = .init(x: superview.layoutMargins.left, y: y)
+ }
+
+ open override func layoutSubviews() {
+ super.layoutSubviews()
+
+ let spacing: CGFloat = Spaces.step
+ button.contentEdgeInsets.left = spacing
+ button.contentEdgeInsets.right = spacing
+
+ button.sizeToFit()
+
+ button.frame.origin.y = layoutMargins.top
+ if ltr {
+ button.frame.origin.x = layoutMargins.left
+ } else {
+ button.frame.setMaxX(frame.width - layoutMargins.right)
+ }
+
+ let buttonWidth = button.frame.width
+ let imageWidth = button.imageView?.frame.width ?? .zero
+
+
+ button.imageEdgeInsets = UIEdgeInsets(
+ top: 1,
+ left: buttonWidth - spacing - imageWidth,
+ bottom: -1,
+ right: -spacing
+ )
+
+ button.titleEdgeInsets = UIEdgeInsets(
+ top: 0,
+ left: -(imageWidth + spacing + spacing + imageWidth),
+ bottom: 0,
+ right: 0
+ )
+ }
+
+ open override func sizeThatFits(_ size: CGSize) -> CGSize {
+ let superSize = super.sizeThatFits(size)
+ layoutSubviews()
+ return .init(width: superSize.width, height: button.frame.maxY + layoutMargins.bottom)
+ }
+
+ // MARK: - Private
+
+ var diffableButtonAction: (()->Void)? = nil {
+ didSet {
+ if let _ = diffableButtonAction {
+ self.button.addTarget(self, action: #selector(self.diffableButtonTargetAction), for: .touchUpInside)
+ } else {
+ self.button.removeTargetsAndActions()
+ }
+ }
+ }
+
+ @objc func diffableButtonTargetAction() {
+ self.diffableButtonAction?()
+ }
+}
+#endif
diff --git a/Sources/NativeUIKit/Views/NativePlaceholderView.swift b/Sources/UIKitExtension/Views/UIPlaceholderView.swift
similarity index 61%
rename from Sources/NativeUIKit/Views/NativePlaceholderView.swift
rename to Sources/UIKitExtension/Views/UIPlaceholderView.swift
index 0278e7e..4983fa8 100644
--- a/Sources/NativeUIKit/Views/NativePlaceholderView.swift
+++ b/Sources/UIKitExtension/Views/UIPlaceholderView.swift
@@ -1,43 +1,21 @@
-// The MIT License (MIT)
-// Copyright © 2021 Ivan Vorobei (hello@ivanvorobei.io)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
#if canImport(UIKit) && (os(iOS))
import UIKit
-import SparrowKit
-open class NativePlaceholderView: SPButton {
+open class UIPlaceholderView: UICommonButton {
// MARK: - Views
- public let iconImageView = SPImageView().do {
+ public let iconImageView = UICommonImageView().do {
$0.contentMode = .scaleAspectFit
}
- public let headerLabel = SPLabel().do {
+ public let headerLabel = UICommonLabel().do {
$0.numberOfLines = .zero
$0.textAlignment = .center
$0.font = UIFont.preferredFont(forTextStyle: .title1, weight: .bold)
}
- public let descriptionLabel = SPLabel().do {
+ public let descriptionLabel = UICommonLabel().do {
$0.numberOfLines = .zero
$0.textAlignment = .center
$0.font = UIFont.preferredFont(forTextStyle: .body, weight: .regular)
@@ -63,18 +41,12 @@ open class NativePlaceholderView: SPButton {
open override func commonInit() {
super.commonInit()
layoutMargins = .zero
- if #available(iOS 13.0, *) {
- tintColor = .tertiaryLabel
- } else {
- tintColor = UIColor.black.alpha(0.3)
- }
+ tintColor = .tertiaryLabel
backgroundColor = .clear
iconImageView.tintColor = tintColor
- addSubview(iconImageView)
headerLabel.textColor = tintColor
- addSubview(headerLabel)
descriptionLabel.textColor = tintColor
- addSubview(descriptionLabel)
+ addSubviews(iconImageView, headerLabel, descriptionLabel)
}
// MARK: - Ovveride
@@ -82,7 +54,7 @@ open class NativePlaceholderView: SPButton {
open override var isHighlighted: Bool {
didSet {
UIView.animate(withDuration: 0.1, delay: 0, options: [.beginFromCurrentState, .allowUserInteraction], animations: {
- self.alpha = self.isHighlighted ? NativeAppearance.actionable_element_highlight_opacity : 1
+ self.alpha = self.isHighlighted ? 0.5 : 1
}, completion: nil)
}
}
@@ -105,24 +77,18 @@ open class NativePlaceholderView: SPButton {
// MARK: - Layout
- /**
- NativeUIKit: Layout wrapper. Native way for layout placeholder.
- */
open func layout(y: CGFloat) {
guard let superview = self.superview else { return }
sizeToFit()
- let width = min(superview.readableWidth, NativeLayout.Sizes.actionable_area_maximum_width)
+ let width = superview.readableWidth
frame.setWidth(width)
setXCenter()
frame.origin.y = y
}
- /**
- NativeUIKit: Layout wrapper. Native way for layout placeholder.
- */
open func layoutCenter() {
guard let superview = self.superview else { return }
- let width = min(superview.readableWidth, NativeLayout.Sizes.actionable_area_maximum_width)
+ let width = superview.readableWidth
setWidthAndFit(width: width)
setXCenter()
switch superview {
diff --git a/TODO.md b/TODO.md
deleted file mode 100644
index 7ae73c8..0000000
--- a/TODO.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# TODO
-
-Here provided ideas or features which will be implemented soon.
-
-- Readme.
-- Example app.
-- Add to list in opensource.
-- Add docs.
-- Added examples of controllers.