├── .circleci
└── config.yml
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── workflows
│ ├── PrepareRelaseVersionForDelivery.yml
│ ├── PrepareSimulatorVersionForDelivery.yml
│ ├── Test.yml
│ └── TestFrameworks.yml
├── .gitignore
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ └── contents.xcworkspacedata
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Content
├── CustomViewModels.md
└── Images
│ ├── ListGridGallery.png
│ ├── LiveCoding.png
│ ├── Logo.png
│ ├── Project.png
│ └── XCodeTemplate.png
├── DSKitExplorer
├── DSKitExplorer.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── swiftpm
│ │ │ └── Package.resolved
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── DSKitExplorer.xcscheme
└── DSKitExplorer
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AccentColor.colorset
│ │ └── Contents.json
│ ├── Add Frameworks.imageset
│ │ ├── Add Frameworks.png
│ │ └── Contents.json
│ ├── AllApps-demo.imageset
│ │ ├── AllApps-demo.png
│ │ └── Contents.json
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-60.png
│ │ ├── Icon-60@2x.png
│ │ ├── Icon-60@3x.png
│ │ ├── Icon-Small@2x.png
│ │ ├── Icon-Small@3x.png
│ │ ├── Icon-Spotlight-40.png
│ │ ├── Icon-Spotlight-40@2x.png
│ │ ├── Icon-Spotlight-40@3x.png
│ │ └── Icon.png
│ ├── Contents.json
│ ├── Copy items if need.imageset
│ │ ├── Contents.json
│ │ └── Copy items if need.png
│ ├── CoverAppearance.imageset
│ │ ├── Contents.json
│ │ └── CoverAppearance.jpg
│ ├── CoverCodeExampleHome.imageset
│ │ ├── Contents.json
│ │ └── CoverCodeExample.jpg
│ ├── CoverGetStarted.imageset
│ │ ├── Contents.json
│ │ └── CoverGetStarted.jpg
│ ├── CoverLayout.imageset
│ │ ├── Contents.json
│ │ └── CoverLayout.jpg
│ ├── Embed frameworks.imageset
│ │ ├── Contents.json
│ │ └── Embed frameworks.png
│ ├── Home.imageset
│ │ ├── Contents.json
│ │ └── Home.png
│ ├── Icon.imageset
│ │ ├── Contents.json
│ │ └── Icon.png
│ ├── LayoutExample.imageset
│ │ ├── Contents.json
│ │ └── LayoutExample.png
│ ├── LightDarkModes.imageset
│ │ ├── Contents.json
│ │ └── LightDarkModes.png
│ ├── Welcome.imageset
│ │ ├── Contents.json
│ │ └── DSKit_home.png
│ ├── barbershop.imageset
│ │ ├── Contents.json
│ │ └── barbershop.jpg
│ ├── beautysaloon.imageset
│ │ ├── Contents.json
│ │ ├── Screen Shot 2021-03-09 at 10.jpg
│ │ └── beautysaloon.png
│ ├── dskitIcon.imageset
│ │ ├── Contents.json
│ │ └── dskitIcon.pdf
│ ├── ecommerce.imageset
│ │ ├── Contents.json
│ │ └── ecommerce.jpg
│ ├── facebook.imageset
│ │ ├── Contents.json
│ │ └── facebook.pdf
│ ├── flowerstore.imageset
│ │ ├── Contents.json
│ │ ├── flowerstore-1.jpg
│ │ └── flowerstore_light.jpg
│ ├── foodDelivery.imageset
│ │ ├── Contents.json
│ │ └── pexels-photo-1600711.jpeg
│ ├── glasses.imageset
│ │ ├── Contents.json
│ │ └── glasses.jpg
│ ├── grocerystore.imageset
│ │ ├── Contents.json
│ │ ├── grocerystore.jpg
│ │ └── grocerystore_dark.jpg
│ ├── instagram.imageset
│ │ ├── Contents.json
│ │ └── instagram.pdf
│ ├── picture-1.imageset
│ │ ├── Contents.json
│ │ └── picture-1.jpg
│ ├── picture-10.imageset
│ │ ├── Contents.json
│ │ └── picture-10.jpg
│ ├── picture-11.imageset
│ │ ├── Contents.json
│ │ └── picture-11.jpg
│ ├── picture-12.imageset
│ │ ├── Contents.json
│ │ └── picture-12.jpg
│ ├── picture-13.imageset
│ │ ├── Contents.json
│ │ └── picture-13.jpg
│ ├── picture-2.imageset
│ │ ├── Contents.json
│ │ └── picture-2.jpg
│ ├── picture-3.imageset
│ │ ├── Contents.json
│ │ └── picture-3.jpg
│ ├── picture-4.imageset
│ │ ├── Contents.json
│ │ └── picture-4.jpg
│ ├── picture-5.imageset
│ │ ├── Contents.json
│ │ └── picture-5.jpg
│ ├── picture-6.imageset
│ │ ├── Contents.json
│ │ └── picture-6.jpg
│ ├── picture-7.imageset
│ │ ├── Contents.json
│ │ └── picture-7.jpg
│ ├── picture-8.imageset
│ │ ├── Contents.json
│ │ └── picture-8.jpg
│ ├── picture-9.imageset
│ │ ├── Contents.json
│ │ └── picture-9.jpg
│ ├── twitter.imageset
│ │ ├── Contents.json
│ │ └── twitter.pdf
│ └── visa-card-bg.imageset
│ │ ├── Contents.json
│ │ └── visa-card-bg.png
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── CustomViewModels
│ └── Code
│ │ ├── DSCodeUIView.swift
│ │ ├── DSCodeUIView.xib
│ │ └── DSCodeVM.swift
│ ├── Documentation
│ ├── Layout
│ │ ├── Gallery
│ │ │ ├── GalleryAbsoluteWidthLayoutVC.swift
│ │ │ ├── GalleryFractional1GroupedLayoutVC.swift
│ │ │ ├── GalleryFractional1LayoutVC.swift
│ │ │ ├── GalleryFractionalWidthLayoutVC.swift
│ │ │ ├── GalleryFullWidthLayoutVC.swift
│ │ │ ├── GalleryLayoutViewController.swift
│ │ │ ├── GalleryPageControlFractional1LayoutVC.swift
│ │ │ ├── GalleryPageControlLayoutVC.swift
│ │ │ └── GalleryWithSupplementaryItemsLayoutVC.swift
│ │ ├── Grid
│ │ │ ├── GridGrouped3RowsLayoutVC.swift
│ │ │ ├── GridGrouped5RowsHeaderFooterLayoutVC.swift
│ │ │ ├── GridLayoutViewController.swift
│ │ │ ├── GridSimpleHeaderFooterLayoutVC.swift
│ │ │ ├── GridSimpleLayoutVC.swift
│ │ │ └── GridWithSupplementaryItemsLayoutVC.swift
│ │ └── Lists
│ │ │ ├── ListGroupedAndSeparatorLayoutVC.swift
│ │ │ ├── ListGroupedLayoutVC.swift
│ │ │ ├── ListGroupedSeparatorHeaderFooterLayoutVC.swift
│ │ │ ├── ListLayoutViewController.swift
│ │ │ ├── ListSeparatorLayoutVC.swift
│ │ │ ├── ListSimpleLayoutVC.swift
│ │ │ ├── ListWithAdditionalViewModelsLayoutVC.swift
│ │ │ └── ListWithSupplementaryItemsLayoutVC.swift
│ ├── Show
│ │ ├── ShowBottomContentVC.md
│ │ ├── ShowBottomContentVC.swift
│ │ ├── ShowContentVC.md
│ │ ├── ShowContentVC.swift
│ │ ├── ShowContentViewController.swift
│ │ ├── ShowTopBottomContentVC.md
│ │ ├── ShowTopBottomContentVC.swift
│ │ ├── ShowTopContentVC.md
│ │ └── ShowTopContentVC.swift
│ ├── SourceCodeViewController.swift
│ ├── Style
│ │ ├── StyleVC.md
│ │ ├── StyleVC.swift
│ │ └── StyleViewController.swift
│ ├── Typography
│ │ ├── TypographyActiveTextVC.swift
│ │ ├── TypographyHtmlVC.md
│ │ ├── TypographyTextComposerActionVC.swift
│ │ ├── TypographyTextComposerTextVC.swift
│ │ ├── TypographyTextGalleryVC.swift
│ │ ├── TypographyTextGridVC.swift
│ │ ├── TypographyTextListVC.swift
│ │ ├── TypographyTextTypesVC.md
│ │ ├── TypographyTextTypesVC.swift
│ │ └── TypographyViewController.swift
│ ├── ViewModels
│ │ ├── Actions
│ │ │ ├── ActionGalleryVC.swift
│ │ │ ├── ActionGridVC.swift
│ │ │ ├── ActionGroupedListVC.swift
│ │ │ ├── ActionLeftIconVC.swift
│ │ │ ├── ActionLeftImageVC.swift
│ │ │ ├── ActionLeftRoundImageSizeVC.swift
│ │ │ ├── ActionLeftRoundImageVC.swift
│ │ │ ├── ActionListVC.swift
│ │ │ ├── ActionRightButtonVC.swift
│ │ │ ├── ActionRightIconVC.swift
│ │ │ ├── ActionRightImageVC.swift
│ │ │ ├── ActionRightRoundImageSizeVC.swift
│ │ │ ├── ActionRightRoundImageVC.swift
│ │ │ ├── ActionTopImageVC.swift
│ │ │ └── ActionViewController.swift
│ │ ├── Buttons
│ │ │ ├── ButtonGalleryVC.swift
│ │ │ ├── ButtonGridVC.swift
│ │ │ ├── ButtonListVC.swift
│ │ │ ├── ButtonViewController.swift
│ │ │ └── ButtonsVC.swift
│ │ ├── Cards
│ │ │ └── CardViewController.swift
│ │ ├── Images
│ │ │ ├── ImageGalleryHandleDidTapVC.swift
│ │ │ ├── ImageGalleryVC.swift
│ │ │ ├── ImageGridVC.swift
│ │ │ ├── ImageListVC.swift
│ │ │ ├── ImageViewController.swift
│ │ │ └── ImagesVC.swift
│ │ ├── Maps
│ │ │ └── MapViewController.swift
│ │ ├── Page
│ │ │ ├── PageSimplePageVC.swift
│ │ │ ├── PageSimplePageWithInsetsVC.swift
│ │ │ └── PageViewController.swift
│ │ ├── PageControl
│ │ │ └── PageControlViewController.swift
│ │ ├── QuantityPicker
│ │ │ ├── QuantityPickerVC.swift
│ │ │ └── QuantityPickerViewController.swift
│ │ ├── Segments
│ │ │ └── SegmentViewController.swift
│ │ ├── TextFields
│ │ │ ├── TextFieldBuiltInValidationVC.md
│ │ │ ├── TextFieldBuiltInValidationVC.swift
│ │ │ ├── TextFieldCustomInvalidPlaceHolderMessageVC.md
│ │ │ ├── TextFieldCustomInvalidPlaceHolderMessageVC.swift
│ │ │ ├── TextFieldCustomValidationVC.md
│ │ │ ├── TextFieldCustomValidationVC.swift
│ │ │ ├── TextFieldIconsVC.md
│ │ │ ├── TextFieldIconsVC.swift
│ │ │ ├── TextFieldInvalidDataVC.md
│ │ │ ├── TextFieldInvalidDataVC.swift
│ │ │ ├── TextFieldShortcutsVC.md
│ │ │ ├── TextFieldShortcutsVC.swift
│ │ │ ├── TextFieldValidDataVC.md
│ │ │ ├── TextFieldValidDataVC.swift
│ │ │ ├── TextFieldViewController.swift
│ │ │ ├── TextFieldsGridVC.md
│ │ │ ├── TextFieldsGridVC.swift
│ │ │ ├── TextFieldsGroupedGridVC.md
│ │ │ ├── TextFieldsGroupedGridVC.swift
│ │ │ ├── TextFieldsGroupedVC.md
│ │ │ ├── TextFieldsGroupedVC.swift
│ │ │ ├── TextFieldsVC.md
│ │ │ └── TextFieldsVC.swift
│ │ └── TextView
│ │ │ ├── TextViewSimpleVC.swift
│ │ │ └── TextViewViewController.swift
│ └── WebsiteGenerator
│ │ ├── Documentable.swift
│ │ ├── DocumentsGroup.swift
│ │ ├── DocumentsGroups+Sections.swift
│ │ └── DocumentsGroups.swift
│ ├── Extensions
│ ├── DSActionVM+SourceCode.swift
│ ├── DSTextVM+Description.swift
│ ├── DSViewController+PoweredBy.swift
│ ├── DSViewController+SourceCode.swift
│ └── DSViewController+ViewModels.swift
│ ├── Info.plist
│ ├── SceneDelegate.swift
│ └── ViewController.swift
├── Gemfile.lock
├── LICENSE
├── Package.resolved
├── Package.swift
├── README.md
├── Sources
├── DSKit
│ ├── Appearance
│ │ ├── Colors
│ │ │ ├── ColorSpaces.swift
│ │ │ ├── DSColor.swift
│ │ │ ├── DSColorScheme+Color.swift
│ │ │ └── UIColorExtension.swift
│ │ ├── DSAppearance.swift
│ │ ├── DSKitAppearance.swift
│ │ ├── DSNewsAppearance.swift
│ │ ├── Designable
│ │ │ ├── DSDesignable.swift
│ │ │ ├── DSDesignableButtonColor.swift
│ │ │ ├── DSDesignableFonts.swift
│ │ │ ├── DSDesignableNavigationBarColor.swift
│ │ │ ├── DSDesignablePriceColor.swift
│ │ │ ├── DSDesignableTabbarColor.swift
│ │ │ ├── DSDesignableTextColor.swift
│ │ │ ├── DSDesignableTextFieldColor.swift
│ │ │ ├── DSDesignableViewColors.swift
│ │ │ └── DSDesignableViewController.swift
│ │ ├── Fonts
│ │ │ ├── DSScaledFont.swift
│ │ │ ├── HoeflerText.plist
│ │ │ └── Noteworthy.plist
│ │ ├── MintAppearance.swift
│ │ ├── SystemAppearance.swift
│ │ └── UIColor+String.swift
│ ├── CollectionView
│ │ ├── DSCollectionView.swift
│ │ ├── DSCollectionViewPosition.swift
│ │ ├── Data
│ │ │ ├── DSCollectionView+DataSource.swift
│ │ │ └── DSCollectionView+SuplimentaryViewDataSource.swift
│ │ ├── Helpers
│ │ │ ├── DSCollectionView+AdditionalSpace.swift
│ │ │ ├── DSCollectionView+Config.swift
│ │ │ ├── DSCollectionView+Forms.swift
│ │ │ ├── DSCollectionView+Identifiers.swift
│ │ │ ├── DSCollectionView+Keyboard.swift
│ │ │ ├── DSCollectionView+Register.swift
│ │ │ ├── DSCollectionView+Reload.swift
│ │ │ └── DSCollectionView+Show.swift
│ │ └── Layout
│ │ │ ├── DSCollectionView+GalleryLayout.swift
│ │ │ ├── DSCollectionView+GridLayout.swift
│ │ │ ├── DSCollectionView+Layout.swift
│ │ │ ├── DSCollectionView+ListLayout.swift
│ │ │ └── DSCollectionView+SupplementaryViewLayout.swift
│ ├── ContentModels
│ │ ├── Button
│ │ │ └── DSButton.swift
│ │ ├── Image
│ │ │ ├── DSImage+DSViewable.swift
│ │ │ ├── DSImage.swift
│ │ │ ├── DSImageContent.swift
│ │ │ ├── DSImageContentMode.swift
│ │ │ ├── DSImageDisplayStyle.swift
│ │ │ ├── DSImageHeight.swift
│ │ │ ├── DSImageSize.swift
│ │ │ └── DSImageTintColor.swift
│ │ ├── Price
│ │ │ ├── DSPrice+Random.swift
│ │ │ ├── DSPrice+Viewable.swift
│ │ │ └── DSPrice.swift
│ │ ├── Text
│ │ │ ├── DSTextColor.swift
│ │ │ ├── DSTextComposer+Add.swift
│ │ │ ├── DSTextComposer+AttributedString.swift
│ │ │ ├── DSTextComposer+DSViewable.swift
│ │ │ ├── DSTextComposer+ViewModels.swift
│ │ │ ├── DSTextComposer.swift
│ │ │ ├── DSTextFont.swift
│ │ │ ├── DSTextParagraph.swift
│ │ │ ├── DSTextParagraphType.swift
│ │ │ └── DSTextType.swift
│ │ └── View
│ │ │ ├── DSView.swift
│ │ │ └── DSViewPosition.swift
│ ├── Extensions
│ │ ├── CGFloat+UIEdgeInsets.swift
│ │ ├── Double+Rounded.swift
│ │ ├── Int+Cents.swift
│ │ ├── Int+Plural.swift
│ │ ├── Int+TimeString.swift
│ │ ├── NSAttributedString+Badge.swift
│ │ ├── NSAttributedString+Size.swift
│ │ ├── NSNumber+Cents.swift
│ │ ├── Notification+FrameAndDuration.swift
│ │ ├── String+Amount.swift
│ │ ├── String+AppName.swift
│ │ ├── String+Currency.swift
│ │ ├── String+EstimatedHeight.swift
│ │ ├── String+OpenURL.swift
│ │ ├── String+Random.swift
│ │ ├── String+Size.swift
│ │ ├── UIApplication+KeyWindow.swift
│ │ ├── UIApplication+TopViewController.swift
│ │ ├── UIButton+Colors.swift
│ │ ├── UIButton+EdgeInsets.swift
│ │ ├── UIColor+Equtable.swift
│ │ ├── UIColor+IsLight.swift
│ │ ├── UIDeviceExtension.swift
│ │ ├── UIEdgeInsets+Add.swift
│ │ ├── UIEdgeInsets+NSDirectionalEdgeInsets.swift
│ │ ├── UIEdgeInsetsExtension.swift
│ │ ├── UIImage+AverageColor.swift
│ │ ├── UIImage+ResizeCrop.swift
│ │ ├── UIImage+SFSymbol.swift
│ │ ├── UIImageViewExtension.swift
│ │ ├── UILabelExtension.swift
│ │ ├── UIPageControl+Appearance.swift
│ │ ├── UIView+Border.swift
│ │ ├── UIView+Bounce.swift
│ │ ├── UIView+Constraints.swift
│ │ ├── UIView+Corners.swift
│ │ ├── UIView+DSViewModelDisplayStyle.swift
│ │ ├── UIView+EdgeInsets.swift
│ │ └── UIViewExtension.swift
│ ├── Helpers
│ │ ├── AmountFormatter.swift
│ │ ├── DSMaterialSpinner.swift
│ │ ├── DSMessageHUD.swift
│ │ ├── DSSFSymbolConfig.swift
│ │ ├── Date+StringFormatting.swift
│ │ ├── DispatchQueue.swift
│ │ ├── IAKCacheManager.swift
│ │ ├── NonEquatable.swift
│ │ ├── PasswordValidator.swift
│ │ ├── PreviewContainer.swift
│ │ ├── ProgressHUD.swift
│ │ ├── Rescale.swift
│ │ ├── URLOpener.swift
│ │ └── Validator.swift
│ ├── Images.xcassets
│ │ ├── Contents.json
│ │ ├── mapPlaceholder.imageset
│ │ │ ├── Contents.json
│ │ │ └── mapPlaceholder.pdf
│ │ └── placeholder.imageset
│ │ │ ├── Contents.json
│ │ │ └── placeholder.pdf
│ ├── ReusableCollectionViewCells
│ │ ├── DSReusableCollectionSupplementaryView.swift
│ │ ├── DSReusableCollectionViewCell+SupplementaryViews.swift
│ │ ├── DSReusableCollectionViewCell.swift
│ │ ├── DSReusableCollectionViewsHeightManager.swift
│ │ └── UIView+LayoutAttributes.swift
│ ├── Sections
│ │ ├── DSDiffableSection.swift
│ │ ├── DSGallerySection.swift
│ │ ├── DSGridSection.swift
│ │ ├── DSListSection.swift
│ │ ├── DSSection+Count.swift
│ │ ├── DSSection+DisplayStyle.swift
│ │ ├── DSSection+Footer.swift
│ │ ├── DSSection+Hash.swift
│ │ ├── DSSection+Header.swift
│ │ ├── DSSection+Identifiers.swift
│ │ ├── DSSection+Insets.swift
│ │ ├── DSSection+Width.swift
│ │ ├── DSSection.swift
│ │ ├── DSSectionBackgroundColorPrimaryDecorationView.swift
│ │ ├── DSSectionBackgroundColorSecondaryDecorationView.swift
│ │ ├── DSSectionBackgroundDecorationView.swift
│ │ ├── DSSectionBackgroundType.swift
│ │ ├── DSSectionGalleryType.swift
│ │ └── DSSectionType.swift
│ ├── ViewControllers
│ │ ├── BaseViewController
│ │ │ ├── DSBaseViewController+Loading.swift
│ │ │ ├── DSBaseViewController+MessageHUD.swift
│ │ │ ├── DSBaseViewController+NavigationStyle.swift
│ │ │ └── DSBaseViewController.swift
│ │ ├── DSCollectionViewController
│ │ │ ├── DSCollectionViewController+BottomContent.swift
│ │ │ ├── DSCollectionViewController+Shadows.swift
│ │ │ ├── DSCollectionViewController+TopContent.swift
│ │ │ └── DSCollectionViewController.swift
│ │ ├── DSNavigationViewController
│ │ │ └── DSNavigationViewController.swift
│ │ ├── DSViewController
│ │ │ ├── DSViewController+DecorationIcon.swift
│ │ │ ├── DSViewController+Forms.swift
│ │ │ ├── DSViewController+Placeholder.swift
│ │ │ ├── DSViewController+ShowBottomContent.swift
│ │ │ ├── DSViewController+ShowContent.swift
│ │ │ ├── DSViewController+ShowTopContent.swift
│ │ │ └── DSViewController.swift
│ │ └── TabBarViewController
│ │ │ └── DSTabBarViewController.swift
│ ├── ViewModelProtocol
│ │ ├── DSPageControlable.swift
│ │ ├── DSReusableUIView.swift
│ │ ├── DSSideView.swift
│ │ ├── DSSupplementaryView.swift
│ │ ├── DSViewModel.swift
│ │ ├── DSViewModelBorderStyle.swift
│ │ ├── DSViewModelColorStyle.swift
│ │ ├── DSViewModelCornersStyle.swift
│ │ ├── DSViewModelDataSource.swift
│ │ ├── DSViewModelDisplayStyle.swift
│ │ ├── DSViewModelHeight.swift
│ │ ├── DSViewModelShadowStyle.swift
│ │ ├── DSViewModelStyle.swift
│ │ ├── DSViewModelWidth.swift
│ │ ├── DefaultReusableUIViewView.swift
│ │ └── Extensions
│ │ │ ├── DSViewModel+Default.swift
│ │ │ ├── DSViewModel+PrepareToDisplay.swift
│ │ │ ├── DSViewModel+Sections.swift
│ │ │ ├── DSViewModel+SideViews.swift
│ │ │ ├── DSViewModel+ViewColors.swift
│ │ │ ├── DSViewModel+didTap.swift
│ │ │ ├── DSViewModel+isEqual.swift
│ │ │ └── DSViewModelDisplayStyle+UIEdgeInsets.swift
│ └── ViewModels
│ │ ├── Action
│ │ ├── DSActionUIView.swift
│ │ ├── DSActionUIView.xib
│ │ ├── DSActionVM+LeftContent.swift
│ │ ├── DSActionVM+RightContent.swift
│ │ ├── DSActionVM+TopContent.swift
│ │ └── DSActionVM.swift
│ │ ├── ActiveText
│ │ ├── DSActiveTextUIView.swift
│ │ ├── DSActiveTextUIView.xib
│ │ └── DSActiveTextVM.swift
│ │ ├── Button
│ │ ├── DSButtonUIView.swift
│ │ ├── DSButtonUIView.xib
│ │ ├── DSButtonVM.swift
│ │ ├── ImoButton.swift
│ │ └── ImoUIButton.swift
│ │ ├── Card
│ │ ├── DSCardUIView.swift
│ │ ├── DSCardUIView.xib
│ │ └── DSCardVM.swift
│ │ ├── Color
│ │ ├── DSColorUIView.swift
│ │ ├── DSColorUIView.xib
│ │ └── DSColorVM.swift
│ │ ├── Image
│ │ ├── DSImageUIView.swift
│ │ ├── DSImageUIView.xib
│ │ └── DSImageVM.swift
│ │ ├── Label
│ │ ├── DSLabelUIView.swift
│ │ ├── DSLabelUIView.xib
│ │ └── DSLabelVM.swift
│ │ ├── Map
│ │ ├── DSMapUIView.swift
│ │ ├── DSMapUIView.xib
│ │ └── DSMapVM.swift
│ │ ├── Page
│ │ ├── DSPageUIView.swift
│ │ ├── DSPageUIView.xib
│ │ └── DSPageVM.swift
│ │ ├── PageControl
│ │ ├── DSPageControlUIView.swift
│ │ ├── DSPageControlUIView.xib
│ │ └── DSPageControlViewModel.swift
│ │ ├── QuantityPicker
│ │ ├── DSQuantityPicker+RightContent.swift
│ │ ├── DSQuantityPickerUIView.swift
│ │ ├── DSQuantityPickerUIView.xib
│ │ ├── DSQuantityPickerVM+LeftContent.swift
│ │ └── DSQuantityPickerVM.swift
│ │ ├── Segment
│ │ ├── DSSegmentUIView.swift
│ │ ├── DSSegmentUIView.xib
│ │ └── DSSegmentViewModel.swift
│ │ ├── Separator
│ │ ├── DSSeparatorUIView.swift
│ │ ├── DSSeparatorUIView.xib
│ │ └── DSSeparatorVM.swift
│ │ ├── Slider
│ │ ├── DSSliderUIView.swift
│ │ ├── DSSliderUIView.xib
│ │ └── DSSliderVM.swift
│ │ ├── Space
│ │ ├── DSSpaceUIView.swift
│ │ ├── DSSpaceUIView.xib
│ │ └── DSSpaceVM.swift
│ │ ├── Switch
│ │ ├── DSSwitchUIView.swift
│ │ ├── DSSwitchUIView.xib
│ │ └── DSSwitchVM.swift
│ │ ├── TextField
│ │ ├── DSTextFieldUIView.swift
│ │ ├── DSTextFieldUIView.xib
│ │ ├── DSTextFieldVM+Shortcuts.swift
│ │ ├── DSTextFieldVM+Validations.swift
│ │ └── DSTextFieldVM.swift
│ │ └── TextView
│ │ ├── DSTextViewUIView.swift
│ │ ├── DSTextViewUIView.xib
│ │ └── DSTextViewVM.swift
├── DSKitCalendar
│ ├── DSCalendarViewController.swift
│ ├── DSDayLabel.swift
│ ├── DSDayOfWeekLabel.swift
│ ├── DSDayRangeIndicatorView.swift
│ ├── DSMonthLabel.swift
│ └── DSTooltipView.swift
└── DSKitFakery
│ ├── DSFaker.swift
│ ├── Models
│ ├── DSAddress.swift
│ └── DSPerson.swift
│ ├── URL+AdditionalProducts.swift
│ ├── URL+Cards.swift
│ ├── URL+Echeveria.swift
│ ├── URL+Flowers.swift
│ ├── URL+Gifts.swift
│ ├── URL+Hydrangea.swift
│ ├── URL+Jeans.swift
│ ├── URL+Profile.swift
│ ├── URL+Roses.swift
│ ├── URL+Shirts.swift
│ ├── URL+Shoes.swift
│ ├── URL+Sneakers.swift
│ ├── URL+TShirts.swift
│ ├── URL+TopFlowers.swift
│ ├── URL+Tulips.swift
│ ├── URL+Watches.swift
│ └── URLExtension.swift
├── Templates
└── ViewModelTemplates
│ ├── ViewModel.xctemplate
│ ├── DS___FILEBASENAME___UIView.swift
│ ├── DS___FILEBASENAME___UIView.xib
│ ├── DS___FILEBASENAME___VM.swift
│ ├── TemplateIcon.png
│ ├── TemplateIcon@2x.png
│ └── TemplateInfo.plist
│ └── install.sh
└── Tests
└── DSKitTests
└── DSKitTests.swift
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/workflows/PrepareRelaseVersionForDelivery.yml:
--------------------------------------------------------------------------------
1 | name: Archive Release version of DSKit
2 | on:
3 | push:
4 | paths:
5 | - 'DSKit/**'
6 | - 'DSKitFramework/**'
7 | - 'fastlane/**'
8 | jobs:
9 | test:
10 | runs-on: self-hosted
11 | if: "contains(github.event.head_commit.message, 'archive')"
12 | steps:
13 | - uses: actions/checkout@v1
14 | - name: Build all frameworks, test, and archive
15 | run: fastlane prepareForDeliveryReleaseVersion
16 | - name: Upload report result
17 | continue-on-error: true
18 | uses: actions/upload-artifact@v2
19 | with:
20 | name: Release version of DSKit
21 | path: DSKitFramework
22 |
--------------------------------------------------------------------------------
/.github/workflows/PrepareSimulatorVersionForDelivery.yml:
--------------------------------------------------------------------------------
1 | name: Archive Simulator version of DSKit
2 | on:
3 | push:
4 | paths:
5 | - 'DSKit/**'
6 | - 'DSKitFramework/**'
7 | - 'fastlane/**'
8 | jobs:
9 | test:
10 | runs-on: self-hosted
11 | if: "contains(github.event.head_commit.message, 'archive')"
12 | steps:
13 | - uses: actions/checkout@v1
14 | - name: Build all frameworks, test, and archive
15 | run: fastlane prepareForDeliverySimulatorVersion
16 | - name: Upload report result
17 | continue-on-error: true
18 | uses: actions/upload-artifact@v2
19 | with:
20 | name: Simulator version of DSKit
21 | path: DSKitFramework
22 |
--------------------------------------------------------------------------------
/.github/workflows/Test.yml:
--------------------------------------------------------------------------------
1 | name: Run DSKit Tests
2 | on:
3 | push:
4 | paths:
5 | - 'DSKit/**'
6 | - 'fastlane/**'
7 | jobs:
8 | test:
9 | runs-on: self-hosted
10 | if: "!contains(github.event.head_commit.message, 'skip ci')"
11 | steps:
12 | - uses: actions/checkout@v1
13 | - name: Test
14 | run: cd 'DSKit' && fastlane scan --device "iPhone 8" --scheme "DSKit Explorer" --clean
15 |
--------------------------------------------------------------------------------
/.github/workflows/TestFrameworks.yml:
--------------------------------------------------------------------------------
1 | name: Run Frameworks Tests
2 | on:
3 | push:
4 | paths:
5 | - 'DSKit/**'
6 | - 'DSKitFramework/**'
7 | - 'fastlane/**'
8 | jobs:
9 | test:
10 | runs-on: self-hosted
11 | if: "!contains(github.event.head_commit.message, 'skip ci')"
12 | steps:
13 | - uses: actions/checkout@v1
14 | - name: Build all frameworks for simulator and copy to DSKit Framework folder
15 | run: fastlane buildAllFrameworksForSimulatorAndCopyToDSKitFrameworkTestDSKitFrameworks
16 |
17 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | DSKit is developed completely in the open, and your contributions are more than welcome.
2 |
3 | Before you start using DSKit in any of your projects, it’s highly recommended that you spend a few minutes familiarizing yourself with its documentation and internal implementation, so that you’ll be ready to tackle any issues or edge cases that you might encounter.
4 |
5 | Since this is a very young project, it’s likely to have many limitations and missing features, which is something that can really only be discovered and addressed as more people start using it.
6 |
7 | This project does not come with GitHub Issues-based support, and users are instead encouraged to become active participants in its continued development — by fixing any bugs that they encounter, or by improving the documentation wherever it’s found to be lacking.
8 |
9 | If you wish to make a change, open a Pull Request — even if it just contains a draft of the changes you’re planning, or a test that reproduces an issue — and we can discuss it further from there.
10 |
11 | Hope you’ll enjoy using DSKit!
12 |
--------------------------------------------------------------------------------
/Content/Images/ListGridGallery.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/Content/Images/ListGridGallery.png
--------------------------------------------------------------------------------
/Content/Images/LiveCoding.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/Content/Images/LiveCoding.png
--------------------------------------------------------------------------------
/Content/Images/Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/Content/Images/Logo.png
--------------------------------------------------------------------------------
/Content/Images/Project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/Content/Images/Project.png
--------------------------------------------------------------------------------
/Content/Images/XCodeTemplate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/Content/Images/XCodeTemplate.png
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // DSKitExplorer
4 | //
5 | // Created by Ivan Borinschi on 08.02.2022.
6 | //
7 |
8 | import UIKit
9 | import DSKit
10 |
11 | @main
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
15 | DSAppearance.shared.main = DSKitAppearance()
16 | DSAppearance.shared.userInterfaceStyle = .unspecified
17 | return true
18 | }
19 |
20 | // MARK: UISceneSession Lifecycle
21 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
22 | // Called when a new scene session is being created.
23 | // Use this method to select a configuration to create the new scene with.
24 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
25 | }
26 |
27 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
28 | // Called when the user discards a scene session.
29 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
30 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/Add Frameworks.imageset/Add Frameworks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/Add Frameworks.imageset/Add Frameworks.png
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/Add Frameworks.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "Add Frameworks.png",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/AllApps-demo.imageset/AllApps-demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/AllApps-demo.imageset/AllApps-demo.png
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/AllApps-demo.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AllApps-demo.png",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "Icon-Spotlight-40.png",
5 | "idiom" : "iphone",
6 | "scale" : "2x",
7 | "size" : "20x20"
8 | },
9 | {
10 | "filename" : "Icon-60.png",
11 | "idiom" : "iphone",
12 | "scale" : "3x",
13 | "size" : "20x20"
14 | },
15 | {
16 | "filename" : "Icon-Small@2x.png",
17 | "idiom" : "iphone",
18 | "scale" : "2x",
19 | "size" : "29x29"
20 | },
21 | {
22 | "filename" : "Icon-Small@3x.png",
23 | "idiom" : "iphone",
24 | "scale" : "3x",
25 | "size" : "29x29"
26 | },
27 | {
28 | "filename" : "Icon-Spotlight-40@2x.png",
29 | "idiom" : "iphone",
30 | "scale" : "2x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "filename" : "Icon-Spotlight-40@3x.png",
35 | "idiom" : "iphone",
36 | "scale" : "3x",
37 | "size" : "40x40"
38 | },
39 | {
40 | "filename" : "Icon-60@2x.png",
41 | "idiom" : "iphone",
42 | "scale" : "2x",
43 | "size" : "60x60"
44 | },
45 | {
46 | "filename" : "Icon-60@3x.png",
47 | "idiom" : "iphone",
48 | "scale" : "3x",
49 | "size" : "60x60"
50 | },
51 | {
52 | "filename" : "Icon.png",
53 | "idiom" : "ios-marketing",
54 | "scale" : "1x",
55 | "size" : "1024x1024"
56 | }
57 | ],
58 | "info" : {
59 | "author" : "xcode",
60 | "version" : 1
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/AppIcon.appiconset/Icon-60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/AppIcon.appiconset/Icon-60.png
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/AppIcon.appiconset/Icon-Spotlight-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/AppIcon.appiconset/Icon-Spotlight-40.png
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/AppIcon.appiconset/Icon-Spotlight-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/AppIcon.appiconset/Icon-Spotlight-40@2x.png
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/AppIcon.appiconset/Icon-Spotlight-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/AppIcon.appiconset/Icon-Spotlight-40@3x.png
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/AppIcon.appiconset/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/AppIcon.appiconset/Icon.png
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/Copy items if need.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "Copy items if need.png",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/Copy items if need.imageset/Copy items if need.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/Copy items if need.imageset/Copy items if need.png
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/CoverAppearance.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "CoverAppearance.jpg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/CoverAppearance.imageset/CoverAppearance.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/CoverAppearance.imageset/CoverAppearance.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/CoverCodeExampleHome.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "CoverCodeExample.jpg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/CoverCodeExampleHome.imageset/CoverCodeExample.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/CoverCodeExampleHome.imageset/CoverCodeExample.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/CoverGetStarted.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "CoverGetStarted.jpg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/CoverGetStarted.imageset/CoverGetStarted.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/CoverGetStarted.imageset/CoverGetStarted.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/CoverLayout.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "CoverLayout.jpg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/CoverLayout.imageset/CoverLayout.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/CoverLayout.imageset/CoverLayout.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/Embed frameworks.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "Embed frameworks.png",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/Embed frameworks.imageset/Embed frameworks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/Embed frameworks.imageset/Embed frameworks.png
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/Home.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "Home.png",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/Home.imageset/Home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/Home.imageset/Home.png
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/Icon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "Icon.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/Icon.imageset/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/Icon.imageset/Icon.png
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/LayoutExample.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "LayoutExample.png",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/LayoutExample.imageset/LayoutExample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/LayoutExample.imageset/LayoutExample.png
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/LightDarkModes.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "LightDarkModes.png",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/LightDarkModes.imageset/LightDarkModes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/LightDarkModes.imageset/LightDarkModes.png
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/Welcome.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "DSKit_home.png",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/Welcome.imageset/DSKit_home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/Welcome.imageset/DSKit_home.png
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/barbershop.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "barbershop.jpg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/barbershop.imageset/barbershop.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/barbershop.imageset/barbershop.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/beautysaloon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "Screen Shot 2021-03-09 at 10.jpg",
5 | "idiom" : "universal"
6 | },
7 | {
8 | "appearances" : [
9 | {
10 | "appearance" : "luminosity",
11 | "value" : "dark"
12 | }
13 | ],
14 | "filename" : "beautysaloon.png",
15 | "idiom" : "universal"
16 | }
17 | ],
18 | "info" : {
19 | "author" : "xcode",
20 | "version" : 1
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/beautysaloon.imageset/Screen Shot 2021-03-09 at 10.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/beautysaloon.imageset/Screen Shot 2021-03-09 at 10.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/beautysaloon.imageset/beautysaloon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/beautysaloon.imageset/beautysaloon.png
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/dskitIcon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "dskitIcon.pdf",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/dskitIcon.imageset/dskitIcon.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/dskitIcon.imageset/dskitIcon.pdf
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/ecommerce.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "ecommerce.jpg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/ecommerce.imageset/ecommerce.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/ecommerce.imageset/ecommerce.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/facebook.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "facebook.pdf",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "template"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/facebook.imageset/facebook.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/facebook.imageset/facebook.pdf
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/flowerstore.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "flowerstore_light.jpg",
5 | "idiom" : "universal"
6 | },
7 | {
8 | "appearances" : [
9 | {
10 | "appearance" : "luminosity",
11 | "value" : "dark"
12 | }
13 | ],
14 | "filename" : "flowerstore-1.jpg",
15 | "idiom" : "universal"
16 | }
17 | ],
18 | "info" : {
19 | "author" : "xcode",
20 | "version" : 1
21 | },
22 | "properties" : {
23 | "template-rendering-intent" : "original"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/flowerstore.imageset/flowerstore-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/flowerstore.imageset/flowerstore-1.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/flowerstore.imageset/flowerstore_light.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/flowerstore.imageset/flowerstore_light.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/foodDelivery.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "pexels-photo-1600711.jpeg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/foodDelivery.imageset/pexels-photo-1600711.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/foodDelivery.imageset/pexels-photo-1600711.jpeg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/glasses.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "glasses.jpg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/glasses.imageset/glasses.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/glasses.imageset/glasses.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/grocerystore.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "grocerystore.jpg",
5 | "idiom" : "universal"
6 | },
7 | {
8 | "appearances" : [
9 | {
10 | "appearance" : "luminosity",
11 | "value" : "dark"
12 | }
13 | ],
14 | "filename" : "grocerystore_dark.jpg",
15 | "idiom" : "universal"
16 | }
17 | ],
18 | "info" : {
19 | "author" : "xcode",
20 | "version" : 1
21 | },
22 | "properties" : {
23 | "template-rendering-intent" : "original"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/grocerystore.imageset/grocerystore.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/grocerystore.imageset/grocerystore.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/grocerystore.imageset/grocerystore_dark.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/grocerystore.imageset/grocerystore_dark.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/instagram.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "instagram.pdf",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "template"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/instagram.imageset/instagram.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/instagram.imageset/instagram.pdf
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-1.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "picture-1.jpg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-1.imageset/picture-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-1.imageset/picture-1.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-10.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "picture-10.jpg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-10.imageset/picture-10.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-10.imageset/picture-10.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-11.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "picture-11.jpg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-11.imageset/picture-11.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-11.imageset/picture-11.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-12.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "picture-12.jpg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-12.imageset/picture-12.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-12.imageset/picture-12.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-13.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "picture-13.jpg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-13.imageset/picture-13.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-13.imageset/picture-13.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-2.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "picture-2.jpg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-2.imageset/picture-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-2.imageset/picture-2.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-3.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "picture-3.jpg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-3.imageset/picture-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-3.imageset/picture-3.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-4.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "picture-4.jpg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-4.imageset/picture-4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-4.imageset/picture-4.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-5.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "picture-5.jpg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-5.imageset/picture-5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-5.imageset/picture-5.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-6.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "picture-6.jpg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-6.imageset/picture-6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-6.imageset/picture-6.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-7.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "picture-7.jpg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-7.imageset/picture-7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-7.imageset/picture-7.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-8.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "picture-8.jpg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-8.imageset/picture-8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-8.imageset/picture-8.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-9.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "picture-9.jpg",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "original"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-9.imageset/picture-9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/picture-9.imageset/picture-9.jpg
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/twitter.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "twitter.pdf",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "template"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/twitter.imageset/twitter.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/twitter.imageset/twitter.pdf
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/visa-card-bg.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "visa-card-bg.png",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Assets.xcassets/visa-card-bg.imageset/visa-card-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/DSKitExplorer/DSKitExplorer/Assets.xcassets/visa-card-bg.imageset/visa-card-bg.png
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/CustomViewModels/Code/DSCodeUIView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSCodeUIView.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 01.02.2021.
6 | //
7 | //
8 |
9 | import UIKit
10 | import DSKit
11 | import Splash
12 |
13 | final class DSCodeUIView: UIView, DSReusableUIView {
14 |
15 | @IBOutlet weak var label: UILabel!
16 | var appearance = DSAppearance.shared.main
17 |
18 | public var view: UIView { self }
19 |
20 | public func setUpWith(viewModel: DSViewModel) {
21 | guard let viewModel = viewModel as? DSCodeVM else { return }
22 | update(viewModel: viewModel)
23 | }
24 |
25 | func update(viewModel: DSCodeVM) {
26 | let isLightColor = DSAppearance.shared.main.secondaryView.background.isLight()
27 | let theme: Theme = (isLightColor ?? false) ? .sunset(withFont: Font(size: 10)) : .midnight(withFont: Font(size: 10))
28 | let output = AttributedStringOutputFormat(theme: theme)
29 |
30 | let highlighter = SyntaxHighlighter(format: output)
31 | let attributedText = highlighter.highlight(viewModel.code)
32 |
33 | label.attributedText = attributedText
34 | label.textAlignment = .left
35 | label.numberOfLines = 0
36 | }
37 |
38 | override func awakeFromNib() {
39 | super.awakeFromNib()
40 | backgroundColor = .clear
41 | }
42 |
43 | class func instanceFromNib() -> DSCodeUIView {
44 | let view: DSCodeUIView = initFromNib()
45 | return view
46 | }
47 | }
48 |
49 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/Layout/Grid/GridSimpleLayoutVC.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GridSimpleLayoutVC.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | //
7 |
8 | import UIKit
9 | import DSKit
10 |
11 | class GridSimpleLayoutVC: DSViewController {
12 |
13 | override func viewDidLoad() {
14 |
15 | super.viewDidLoad()
16 | title = documentSubtitle
17 | showDemo()
18 | showCode(code: documentCode)
19 | }
20 |
21 | func showDemo() {
22 |
23 | // Demo begin
24 | let viewModels = [1,2,3,4,5].map { (index) -> DSViewModel in
25 | var viewModel = DSImageVM(image: UIImage(named: "picture-\(index)"))
26 | viewModel.height = .absolute(150)
27 | return viewModel
28 | }
29 |
30 | show(content: viewModels.grid())
31 | // Demo end
32 | }
33 | }
34 |
35 | extension GridSimpleLayoutVC: Documentable {
36 |
37 | var documentViewController: UIViewController? {
38 | return self.viewController
39 | }
40 |
41 |
42 | var documentTitle: String {
43 | "Gird"
44 | }
45 |
46 | var documentSubtitle: String {
47 | "Simple layout"
48 | }
49 |
50 | var documentCode: String {
51 | """
52 | let viewModels = [1,2,3,4,5].map { (index) -> DSViewModel in
53 | DSBoxVM(text: index.string())
54 | }
55 |
56 | show(content: viewModels.grid())
57 | """
58 | }
59 |
60 | var documentMarkdownFileName: String? {
61 | return nil
62 | }
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/Layout/Lists/ListGroupedLayoutVC.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListGroupedLayoutVC.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | //
7 |
8 | import UIKit
9 | import DSKit
10 |
11 | class ListGroupedLayoutVC: DSViewController {
12 |
13 | override func viewDidLoad() {
14 |
15 | super.viewDidLoad()
16 | title = documentTitle
17 | showDemo()
18 | showCode(code: documentCode)
19 | }
20 |
21 | func showDemo() {
22 |
23 | // Demo begin
24 |
25 | let texts = ["Aurora","Inure","Mellifluous","Euphoria","Serendipity"]
26 |
27 | let viewModels: [DSViewModel] = texts.map { (text) -> DSLabelVM in
28 | DSLabelVM(.body, text: text)
29 | }
30 |
31 | show(content: viewModels.list(grouped: true))
32 | // Demo end
33 | }
34 | }
35 |
36 | extension ListGroupedLayoutVC: Documentable {
37 |
38 | var documentViewController: UIViewController? {
39 | return self.viewController
40 | }
41 |
42 |
43 | var documentTitle: String {
44 | "List"
45 | }
46 |
47 | var documentSubtitle: String {
48 | "Grouped List"
49 | }
50 |
51 | var documentCode: String {
52 | """
53 | let texts = ["Aurora","Inure","Mellifluous","Euphoria","Serendipity"]
54 |
55 | let viewModels: [DSViewModel] = texts.map { (text) -> DSTextVM in
56 | DSTextVM(.body, text: text)
57 | }
58 |
59 | show(content: viewModels.list())
60 | """
61 | }
62 |
63 | var documentMarkdownFileName: String? {
64 | return nil
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/Layout/Lists/ListSeparatorLayoutVC.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListSeparatorLayoutVC.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | //
7 |
8 | import UIKit
9 | import DSKit
10 |
11 | class ListSeparatorLayoutVC: DSViewController {
12 |
13 | override func viewDidLoad() {
14 |
15 | super.viewDidLoad()
16 | title = "List"
17 | showDemo()
18 | showCode(code: documentCode)
19 | }
20 |
21 | func showDemo() {
22 |
23 | // Demo begin
24 |
25 | let texts = ["Miraculous","Lassitude","Gossamer","Bungalow","Scintilla"]
26 |
27 | let viewModels: [DSViewModel] = texts.map { (text) -> DSLabelVM in
28 | DSLabelVM(.body, text: text)
29 | }
30 |
31 | show(content: viewModels.list(separator: true))
32 | // Demo end
33 | }
34 | }
35 |
36 | extension ListSeparatorLayoutVC: Documentable {
37 |
38 | var documentViewController: UIViewController? {
39 | return self.viewController
40 | }
41 |
42 |
43 | var documentTitle: String {
44 | "Content"
45 | }
46 |
47 | var documentSubtitle: String {
48 | "Show list with separator"
49 | }
50 |
51 | var documentCode: String {
52 | """
53 | let texts = ["Miraculous","Lassitude","Gossamer","Bungalow","Scintilla"]
54 |
55 | let viewModels: [DSViewModel] = texts.map { (text) -> DSTextVM in
56 | DSTextVM(.body, text: text)
57 | }
58 |
59 | show(content: viewModels.list())
60 | """
61 | }
62 |
63 | var documentMarkdownFileName: String? {
64 | return nil
65 | }
66 | }
67 |
68 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/Layout/Lists/ListSimpleLayoutVC.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ListSimpleLayoutVC.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | //
7 |
8 | import UIKit
9 | import DSKit
10 |
11 | class ListSimpleLayoutVC: DSViewController {
12 |
13 | override func viewDidLoad() {
14 |
15 | super.viewDidLoad()
16 | title = documentTitle
17 | showDemo()
18 | showCode(code: documentCode)
19 | }
20 |
21 | func showDemo() {
22 |
23 | // Demo begin
24 |
25 | let texts = ["Petrichor","Sumptuous","Angst","Aesthete","Nadir"]
26 |
27 | let viewModels = texts.map { (text) -> DSViewModel in
28 | DSLabelVM(.body, text: text)
29 | }
30 |
31 | show(content: viewModels.list())
32 | // Demo end
33 | }
34 | }
35 |
36 | extension ListSimpleLayoutVC: Documentable {
37 |
38 | var documentViewController: UIViewController? {
39 | return self.viewController
40 | }
41 |
42 |
43 | var documentTitle: String {
44 | "List"
45 | }
46 |
47 | var documentSubtitle: String {
48 | "Simple list"
49 | }
50 |
51 | var documentCode: String {
52 | """
53 | let texts = ["Petrichor","Sumptuous","Angst","Aesthete","Nadir"]
54 |
55 | let viewModels = texts.map { (text) -> DSViewModel in
56 | DSLabel(.body, text: text)
57 | }
58 |
59 | show(content: viewModels.list())
60 | """
61 | }
62 |
63 | var documentMarkdownFileName: String? {
64 | return nil
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/Show/ShowBottomContentVC.md:
--------------------------------------------------------------------------------
1 | As for the center content of the screen you can easily show content on the bottom of the screen, all you have to do is just call
2 |
3 | ```swift
4 | showBottom(content: [YOUR_SECTION])
5 | ```
6 |
7 | everything related to the show content from the show content section is also valid here
8 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/Show/ShowContentVC.md:
--------------------------------------------------------------------------------
1 | Displaying content in DSKit is easy, all you have to do is just call one function with content you want to display or want to update.
2 |
3 | ```swift
4 | show(content: [YOUR_SECTION])
5 | ```
6 |
7 | Content is composed of two data structures **DSSection** and **DSViewModel**
8 |
9 | **DSSection** - is used to describe how content will be displayed on the screen, in one word: [Layout ](https://dskit.app/layout.html) **DSViewModel** - is used to describe your content on the screen, labels, texts, images, actions, and so on.
10 |
11 | You can display your view models in **Lists, Grids, and Galleries**.
12 |
13 | To easily transform an array of **DSViewModel's** in a section just call **.list() .grid() .gallery()** method on your view models array.
14 |
15 | Every time your need to update content on the screen, add, delete, change position, just change your content structure and `call show(content: [YOUR_SECTION])` DSKit will automatically update the changes, remove non-existent content, or switch position, and it will be animated.
16 |
17 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/Show/ShowContentVC.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ShowContentVC.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 05.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import DSKit
11 |
12 | class ShowContentVC: DSViewController {
13 |
14 | override func viewDidLoad() {
15 |
16 | super.viewDidLoad()
17 | title = documentTitle
18 | showDemo()
19 | showCode(code: documentCode)
20 | }
21 |
22 | func showDemo() {
23 |
24 | // Demo begin
25 |
26 | let texts = ["Petrichor","Sumptuous","Angst","Aesthete","Nadir"]
27 |
28 | let viewModels = texts.map { (text) -> DSViewModel in
29 | DSLabelVM(.body, text: text)
30 | }
31 |
32 | show(content: viewModels.list())
33 | // Demo end
34 | }
35 | }
36 |
37 | extension ShowContentVC: Documentable {
38 |
39 | var documentViewController: UIViewController? {
40 | return self.viewController
41 | }
42 |
43 | var documentTitle: String {
44 | "Content"
45 | }
46 |
47 | var documentSubtitle: String {
48 | "Show Content"
49 | }
50 |
51 | var documentCode: String {
52 | """
53 | let texts = ["Petrichor","Sumptuous","Angst","Aesthete","Nadir"]
54 |
55 | let viewModels = texts.map { (text) -> DSViewModel in
56 | DSTextVM(.body, text: text)
57 | }
58 |
59 | show(content: viewModels.list())
60 | """
61 | }
62 |
63 | var documentMarkdownFileName: String? {
64 | return nil
65 | }
66 | }
67 |
68 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/Show/ShowTopBottomContentVC.md:
--------------------------------------------------------------------------------
1 | Here is an example of how to show and update content in all positions of the screen
2 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/Show/ShowTopContentVC.md:
--------------------------------------------------------------------------------
1 | As for the center content of the screen you can easily show content on the top of the screen, all you have to do is just call
2 |
3 | ```swift
4 | showTop(content: [YOUR_SECTION])
5 | ```
6 |
7 | everything related to the show content from the show content section is also valid here
8 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/SourceCodeViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SourceCodeViewController.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | //
7 |
8 | import UIKit
9 | import DSKit
10 | import Splash
11 |
12 | class SourceCodeViewController: DSViewController {
13 |
14 | let code: String
15 |
16 | override func viewDidLoad() {
17 | super.viewDidLoad()
18 | title = "Source Code"
19 | show(content: DSActionVM.code(codeString: code, traitCollection.userInterfaceStyle))
20 | }
21 |
22 | override func viewDidAppear(_ animated: Bool) {
23 | super.viewDidAppear(animated)
24 | }
25 |
26 | init(code: String) {
27 | self.code = code
28 | super.init(nibName: nil, bundle: nil)
29 | }
30 |
31 | required init?(coder aDecoder: NSCoder) {
32 | fatalError("init(coder:) has not been implemented")
33 | // Demo end
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/Style/StyleVC.md:
--------------------------------------------------------------------------------
1 | Main DSKit idea is to configure the app appearance once and to not care anymore about spaces colors and typography, if you need just that please read the article about [appearance in DSKit](appearance.html)
2 |
3 | But DSKit offers more than that, you can add small adjustments to specific view models in your UI if you need that.
4 |
5 | Using **style** property on your view model you can adjust `borderStyle` , `colorStyle`, `cornerStyle`,`shadowStyle`
6 |
7 | Explore the example bellow:
8 |
9 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/Style/StyleViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StyleViewController.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 05.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import DSKit
11 |
12 | class StyleViewController: DSViewController {
13 |
14 | override func viewDidLoad() {
15 |
16 | super.viewDidLoad()
17 | title = "Content Style"
18 |
19 | var style = action(title: "Style", description: "View models style", icon: "rectangle.fill.on.rectangle.fill")
20 | style.didTap { [unowned self] (_ :DSActionVM) in
21 | self.push(StyleVC())
22 | }
23 |
24 | show(content: style)
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/Typography/TypographyHtmlVC.md:
--------------------------------------------------------------------------------
1 | # Welcome to DSAppKit
2 |
3 | In order to get started to display DSKit view models on the screen, you should
4 |
5 | ```
6 | import DSKit
7 | ```
8 |
9 | and subclass your view controller from **DSViewController**, and you are ready to show content.
10 |
11 | > In order to get started to display DSKit view models on the screen, you should import DSKit and subclass your view controller from **DSViewController**, and you are ready to show content.
12 |
13 | ## Welcome to DSAppKit
14 |
15 | ### Welcome to DSAppKit
16 |
17 | another example of our code here
18 |
19 | ```
20 | show(content: [viewModels3.gallery(), viewModels5.gallery()])
21 | ```
22 |
23 | DSKit and subclass your view controller from **DSViewController**
24 |
25 | ```swift
26 | let numbers = [1,2,3,4,5]
27 |
28 | let viewModels3 = numbers.map { (index) -> DSViewModel in
29 |
30 | var viewModel = DSBoxVM(text: index.string())
31 | viewModel.height = .absolute(150)
32 | viewModel.width = .fractional(0.7)
33 | return viewModel
34 | }
35 |
36 | let viewModels5 = numbers.map { (index) -> DSViewModel in
37 |
38 | var viewModel = DSBoxVM(text: index.string())
39 | viewModel.height = .absolute(50)
40 | viewModel.width = .fractional(0.5)
41 | return viewModel
42 | }
43 |
44 | show(content: [viewModels3.gallery(), viewModels5.gallery()])
45 |
46 | ```
47 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/Typography/TypographyTextTypesVC.md:
--------------------------------------------------------------------------------
1 | In essence, **typography** is the art of arranging letters and text in a way that makes the copy legible, clear, and visually appealing to the reader. **Typography** involves font style, appearance, and structure, which aims to elicit certain emotions and convey specific messages.
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/ViewModels/Buttons/ButtonViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ButtonViewController.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | //
7 |
8 | import UIKit
9 | import DSKit
10 |
11 | class ButtonViewController: DSViewController {
12 |
13 | override func viewDidLoad() {
14 |
15 | super.viewDidLoad()
16 | title = "Buttons"
17 |
18 | // Layout
19 | var list = action(title: "List", description: "Button", icon: "list.bullet")
20 | list.didTap { [unowned self] (_ :DSActionVM) in
21 | self.push(ButtonListVC())
22 | }
23 |
24 | var grid = action(title: "Grid", description: "Button", icon: "rectangle.grid.2x2.fill")
25 | grid.didTap { [unowned self] (_ :DSActionVM) in
26 | self.push(ButtonGridVC())
27 | }
28 |
29 | var gallery = action(title: "Gallery", description: "Button", icon: "square.lefthalf.fill")
30 | gallery.didTap { [unowned self] (_ :DSActionVM) in
31 | self.push(ButtonGalleryVC())
32 | }
33 |
34 | // Buttons
35 | var buttons = action(title: "Buttons", description: "Button", icon: "link.circle.fill")
36 | buttons.didTap { [unowned self] (_ :DSActionVM) in
37 | self.push(ButtonsVC())
38 | }
39 |
40 | let layoutSection = [list, grid, gallery].list().subheadlineHeader("Layout")
41 | let buttonsSection = [buttons].list().subheadlineHeader("Buttons")
42 |
43 | let sections: [DSSection] = [layoutSection,
44 | buttonsSection]
45 | show(content: sections)
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/ViewModels/Images/ImageViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ImageViewController.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | //
7 |
8 | import UIKit
9 | import DSKit
10 |
11 | class ImageViewController: DSViewController {
12 |
13 | override func viewDidLoad() {
14 | super.viewDidLoad()
15 | title = "Image"
16 |
17 | // Layout
18 | var list = action(title: "List", description: "Image", icon: "list.bullet")
19 | list.didTap { [unowned self] (_ :DSActionVM) in
20 | self.push(ImageListVC())
21 | }
22 |
23 | var grid = action(title: "Grid", description: "Image", icon: "rectangle.grid.2x2.fill")
24 | grid.didTap { [unowned self] (_ :DSActionVM) in
25 | self.push(ImageGridVC())
26 | }
27 |
28 | var gallery = action(title: "Gallery", description: "Image", icon: "square.lefthalf.fill")
29 | gallery.didTap { [unowned self] (_ :DSActionVM) in
30 | self.push(ImageGalleryVC())
31 | }
32 |
33 | // Images
34 | var Images = action(title: "Images", description: "Image", icon: "link.circle.fill")
35 | Images.didTap { [unowned self] (_ :DSActionVM) in
36 | self.push(ImagesVC())
37 | }
38 |
39 | let layoutSection = [list, grid, gallery].list().subheadlineHeader("Layout")
40 | let ImagesSection = [Images].list().subheadlineHeader("Images")
41 |
42 | let sections: [DSSection] = [layoutSection,
43 | ImagesSection]
44 | show(content: sections)
45 | // Demo end
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/ViewModels/Page/PageViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SegmentViewController.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | //
7 |
8 | import UIKit
9 | import DSKit
10 |
11 | class PageViewController: DSViewController {
12 |
13 | override func viewDidLoad() {
14 |
15 | super.viewDidLoad()
16 | title = "Pages"
17 |
18 | var simplePage = action(title: "Default page", description: "Example of default page", icon: "list.bullet")
19 | simplePage.didTap { [unowned self] (_ :DSActionVM) in
20 | self.push(PageSimplePageVC())
21 | }
22 |
23 | var insetsPage = action(title: "With insets", description: "Example with insets", icon: "list.bullet")
24 | insetsPage.didTap { [unowned self] (_ :DSActionVM) in
25 | self.push(PageSimplePageWithInsetsVC())
26 | }
27 |
28 | show(content: [simplePage, insetsPage].list())
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/ViewModels/QuantityPicker/QuantityPickerViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // QuantityPickerViewController.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | //
7 |
8 | import UIKit
9 | import DSKit
10 |
11 | class QuantityPickerViewController: DSViewController {
12 |
13 | override func viewDidLoad() {
14 |
15 | super.viewDidLoad()
16 | title = "Quantity Picker"
17 |
18 | var quantityPicker = action(title: "Quantity Picker", description: "Simple", icon: "list.bullet")
19 | quantityPicker.didTap { [unowned self] (_ :DSActionVM) in
20 | self.push(QuantityPickerVC())
21 | }
22 |
23 | show(content: [quantityPicker].list())
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/ViewModels/TextFields/TextFieldBuiltInValidationVC.md:
--------------------------------------------------------------------------------
1 | **DSKit** contains built-in validation, you can easily add any validation you need for your form using these three properties:
2 |
3 | 1. validateMinimumLength
4 | 2. validateMaximumLength
5 | 3. validationPattern
6 |
7 | Regular expressions snippet:
8 |
9 | ```swift
10 | let patternNumbers = "^[0-9]*$"
11 | let patternLetters = "^[a-zA-Z]*$"
12 | let patternNameUmlaute = "^[\\ü\\ö\\ä\\Ä\\Ü\\Ö\\ß\\u0600-\\u06FFa-zA-Z\\s\\'\\-]*$"
13 | let patternName = "^[\\u0600-\\u06FFa-zA-Z\\s\\'\\-]*$"
14 | let patternLettersAndSpaces = "^[\\u0600-\\u06FFa-zA-Z\\s]*$"
15 | let patternLettersAndNumbers = "^[a-zA-Z0-9]*$"
16 | let patternLettersNumbersAndSpaces = "^[\\u0600-\\u06FFa-zA-Z0-9\\s]*$"
17 | let patternAddressUmlaute = "^[\\ü\\ö\\ä\\Ä\\Ü\\Ö\\ß\\u0600-\\u06FFa-zA-Z0-9\\s\\'\\-]*$"
18 | let patternAddress = "^[\\u0600-\\u06FFa-zA-Z0-9\\s\\'\\-]*$"
19 | let patternEmail = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
20 | let patternPhoneNumber = "^\\s*(?:\\+?(\\d{1,3}))?([-. (]*(\\d{3})[-. )]*)?((\\d{3})[-. ]*(\\d{2,4})(?:[-.x ]*(\\d+))?)\\s*$"
21 | let patternPhoneNumber2 = "(\\+?( |-|\\.)?\\d{1,3}( |-|\\.)?)?(\\(?\\d{1,5}\\)?|\\d{1,5})( |-|\\.)?(\\d{1,4}( |-|\\.)?\\d{3,4})"
22 | let patternMin8Max20CharsAtLeastOneDigitAtLeastOneLetter = "^(?=.*\\d)((?=.*[a-z])|(?=.*[A-Z])).*$"
23 | let patternCityNameUmlaute = "^[\\ü\\ö\\ä\\Ä\\Ü\\Ö\\ß\\u0600-\\u06FFa-zA-Z\\s\\'\\-]*$"
24 | let patternCityName = "^[\\u0600-\\u06FFa-zA-Z\\s\\'\\-]*$"
25 | ```
26 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/ViewModels/TextFields/TextFieldCustomInvalidPlaceHolderMessageVC.md:
--------------------------------------------------------------------------------
1 | Customize your error message displayed directly in the text field if the user types an invalid value, you can add a message or an example of what kind of value he should type.
2 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/ViewModels/TextFields/TextFieldCustomValidationVC.md:
--------------------------------------------------------------------------------
1 | If built-in text field validation is not enough for your project requirements you can easily add custom validation to any text field in your form.
2 | Using **handleValidation** closure you are in control, if you implement **handleValidation** closure, all built-in validations will not affect the validation, you are in control for minimum or the maximum number of characters and other validation patterns.
3 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/ViewModels/TextFields/TextFieldIconsVC.md:
--------------------------------------------------------------------------------
1 | Customize your text fields with specific icons using apple SF Symbols library
2 | https://developer.apple.com/sf-symbols/
3 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/ViewModels/TextFields/TextFieldInvalidDataVC.md:
--------------------------------------------------------------------------------
1 | Display a list of text fields with initial invalid values
2 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/ViewModels/TextFields/TextFieldShortcutsVC.md:
--------------------------------------------------------------------------------
1 | **DSKit** contains built-in text field configurations, just pick the one you need and add it to your form, each configuration comes with a specific regular expression validation, icon, minimum and maximum number of required characters for validation.
2 |
3 | We can use a shortcut text field and add some custom elements after initialization, for example changing the minimum of characters for a text field to be valid.
4 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/ViewModels/TextFields/TextFieldValidDataVC.md:
--------------------------------------------------------------------------------
1 | Display a list of text fields with initial valid values
2 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/ViewModels/TextFields/TextFieldsGridVC.md:
--------------------------------------------------------------------------------
1 | Display a list of text fields in a grid layout
2 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/ViewModels/TextFields/TextFieldsGroupedGridVC.md:
--------------------------------------------------------------------------------
1 | Display a list of text fields in a grouped grid layout
2 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/ViewModels/TextFields/TextFieldsGroupedVC.md:
--------------------------------------------------------------------------------
1 | Display a list of text fields grouped in section
2 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/ViewModels/TextFields/TextFieldsVC.md:
--------------------------------------------------------------------------------
1 | Display a list of text fields
2 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/ViewModels/TextView/TextViewViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TextViewViewController.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | //
7 |
8 | import UIKit
9 | import DSKit
10 |
11 | class TextViewViewController: DSViewController {
12 |
13 | override func viewDidLoad() {
14 |
15 | super.viewDidLoad()
16 | title = "TextView"
17 |
18 | var textView = action(title: "TextView", description: "Example of default page", icon: "list.bullet")
19 | textView.didTap { [unowned self] (_ :DSActionVM) in
20 | self.push(TextViewSimpleVC())
21 | }
22 |
23 | show(content: [textView].list())
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/WebsiteGenerator/Documentable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Document.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 05.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | protocol Documentable {
13 |
14 | var documentTitle: String {get}
15 | var documentSubtitle: String {get}
16 | var documentCode: String {get}
17 | var documentMarkdownFileName: String? {get}
18 | var documentViewController: UIViewController? {get}
19 | }
20 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Documentation/WebsiteGenerator/DocumentsGroup.swift:
--------------------------------------------------------------------------------
1 | //
2 | // WebDocumentsGroup.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 06.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | struct DocumentsGroup {
12 | var title: String
13 | var documents: [Documentable]
14 | }
15 |
16 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Extensions/DSActionVM+SourceCode.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSActionVM+SourceCode.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | //
7 |
8 | import Foundation
9 | import DSKit
10 | import Splash
11 | import UIKit
12 |
13 | extension DSActionVM {
14 |
15 | static func code(codeString: String, _ style: UIUserInterfaceStyle) -> DSActionVM {
16 |
17 | let isLightColor = DSAppearance.shared.main.secondaryView.background.isLight()
18 |
19 | let theme: Theme = !(isLightColor ?? false) ? .sunset(withFont: Font(size: 12)) : .midnight(withFont: Font(size: 12))
20 | let output = AttributedStringOutputFormat(theme: theme)
21 | let highlighter = SyntaxHighlighter(format: output)
22 | let code = highlighter.highlight(codeString)
23 | let codeText = DSTextComposer()
24 | codeText.add(text: code)
25 |
26 | var action = DSActionVM(composer: codeText)
27 |
28 | action.rightButton(sfSymbolName: "doc.on.doc.fill", style: .small) {
29 | print("Copy Text")
30 | }
31 |
32 | return action
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Extensions/DSTextVM+Description.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSTextVM+Description.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | //
7 |
8 | import Foundation
9 | import DSKit
10 |
11 | extension DSLabelVM {
12 |
13 | static func description(text: String) -> DSLabelVM {
14 | return DSLabelVM(.subheadline, text: text)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Extensions/DSViewController+SourceCode.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSViewController+SourceCode.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | //
7 |
8 | import Foundation
9 | import DSKit
10 | import UIKit
11 |
12 | public extension DSViewController {
13 |
14 | func showSourceCodeButton(code: String) {
15 |
16 | var button = DSButtonVM(title: "Source Code")
17 | button.didTap { [unowned self] (_: DSButtonVM) in
18 | self.push(SourceCodeViewController(code: code))
19 | }
20 |
21 | showBottom(content: button)
22 | }
23 |
24 | func showCode(code: String) {
25 |
26 | if !ProcessInfo.processInfo.arguments.contains("UI_TEST_MODE") && (ProcessInfo.processInfo.environment["DOCUMENT"] == nil) {
27 |
28 | var codeViewModel = DSCodeVM(code: code)
29 |
30 | codeViewModel.didTap { (_: DSCodeVM) in
31 | let activityViewController = UIActivityViewController(activityItems: [code], applicationActivities: nil)
32 | UIApplication.shared.windows.first?.rootViewController?.present(activityViewController, animated: true, completion: nil)
33 | }
34 |
35 | let text = DSLabelVM(.caption2, text: "Tap on code to open share sheet, to send example code directly to your mac, or copy it.")
36 | showBottom(content: [text.list(), codeViewModel.gallery()])
37 |
38 | } else {
39 |
40 | showPoweredBy()
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UIApplicationSceneManifest
6 |
7 | UIApplicationSupportsMultipleScenes
8 |
9 | UISceneConfigurations
10 |
11 | UIWindowSceneSessionRoleApplication
12 |
13 |
14 | UISceneConfigurationName
15 | Default Configuration
16 | UISceneDelegateClassName
17 | $(PRODUCT_MODULE_NAME).SceneDelegate
18 | UISceneStoryboardFile
19 | Main
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/DSKitExplorer/DSKitExplorer/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // DSKitExplorer
4 | //
5 | // Created by Ivan Borinschi on 08.02.2022.
6 | //
7 |
8 | import UIKit
9 | import DSKit
10 |
11 | class ViewController: DSViewController {
12 |
13 | override func viewDidLoad() {
14 | super.viewDidLoad()
15 | title = "Components"
16 | let groups = DocumentsGroups()
17 | self.show(content: groups.sections(presenter: self))
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 DSKit
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "object": {
3 | "pins": [
4 | {
5 | "package": "ActiveLabel",
6 | "repositoryURL": "https://github.com/imodeveloperlab/ActiveLabel.swift",
7 | "state": {
8 | "branch": null,
9 | "revision": "ad145ba677be2f8e342033a1cadd8fee4059e017",
10 | "version": "1.1.7"
11 | }
12 | },
13 | {
14 | "package": "Cartography",
15 | "repositoryURL": "https://github.com/robb/Cartography",
16 | "state": {
17 | "branch": null,
18 | "revision": "b75197ea134f42b5feafb04b526b37eb1a41034b",
19 | "version": "4.0.0"
20 | }
21 | },
22 | {
23 | "package": "Fakery",
24 | "repositoryURL": "https://github.com/vadymmarkov/Fakery",
25 | "state": {
26 | "branch": null,
27 | "revision": "71cb3bf36a808534659d1248780c2bf3c4c4fc91",
28 | "version": "5.1.0"
29 | }
30 | },
31 | {
32 | "package": "HorizonCalendar",
33 | "repositoryURL": "https://github.com/airbnb/HorizonCalendar.git",
34 | "state": {
35 | "branch": null,
36 | "revision": "1e98736e42fe4e5bea39ce8b89838641f2261c32",
37 | "version": "1.13.3"
38 | }
39 | },
40 | {
41 | "package": "Kingfisher",
42 | "repositoryURL": "https://github.com/onevcat/Kingfisher",
43 | "state": {
44 | "branch": null,
45 | "revision": "5b92f029fab2cce44386d28588098b5be0824ef5",
46 | "version": "7.11.0"
47 | }
48 | }
49 | ]
50 | },
51 | "version": 1
52 | }
53 |
--------------------------------------------------------------------------------
/Sources/DSKit/Appearance/Colors/DSColor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DynamicColor.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 16.12.2020.
6 | //
7 |
8 | import UIKit
9 |
10 | public class DSColor {
11 |
12 | /// Generate light and dark color for dynamic interfaces
13 | /// - Parameters:
14 | /// - light: UIColor for light interface
15 | /// - dark: UIColor for dark interface
16 | /// - Returns: UIColor
17 | public static func color(light: UIColor, dark: UIColor) -> UIColor {
18 | return UIColor { (traitCollection: UITraitCollection) -> UIColor in
19 | if traitCollection.userInterfaceStyle == .dark {
20 | return dark
21 | } else {
22 | return light
23 | }
24 | }
25 | }
26 |
27 | /// Generate light and dark color for dynamic interfaces
28 | /// - Parameters:
29 | /// - light: UIColor fo light interface
30 | /// - dark: UIColor for dark interface
31 | /// - Returns: UIColor
32 | public static func color(light: Int, dark: Int) -> UIColor {
33 | return color(light: UIColor(light), dark: UIColor(dark))
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Sources/DSKit/Appearance/Designable/DSDesignableButtonColor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSDesignableButtonColor.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 01.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /// Button colors
12 | public struct DSDesignableButtonColor: Equatable, Hashable {
13 |
14 | /// Init designable button colors
15 | /// - Parameters:
16 | /// - background: UIColor
17 | /// - title: UIColor
18 | public init(background: UIColor, title: UIColor) {
19 | self.background = background
20 | self.title = title
21 | }
22 |
23 | /// Button background color
24 | public var background: UIColor
25 |
26 | /// Button title color
27 | public var title: UIColor
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/DSKit/Appearance/Designable/DSDesignableNavigationBarColor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSDesignableNavigationBarColor.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 01.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /// Navigation bar colors
12 | public struct DSDesignableNavigationBarColor {
13 |
14 | /// Init navigation bar colors
15 | /// - Parameters:
16 | /// - buttons: UIColor
17 | /// - text: UIColor
18 | /// - bar: UIColor
19 | /// - translucent: Bool
20 | public init(buttons: UIColor, text: UIColor, bar: UIColor, translucent: Bool = false) {
21 | self.buttons = buttons
22 | self.text = text
23 | self.bar = bar
24 | self.translucent = translucent
25 | }
26 |
27 | /// Buttons color
28 | public var buttons: UIColor
29 | /// Text color
30 | public var text: UIColor
31 | /// Bar color
32 | public var bar: UIColor
33 | /// Translucent
34 | public var translucent: Bool
35 | }
36 |
--------------------------------------------------------------------------------
/Sources/DSKit/Appearance/Designable/DSDesignablePriceColor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CurrencyColor.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 01.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /// Price colors
12 | public struct DSDesignablePriceColor: Equatable, Hashable {
13 |
14 | /// Init price colors
15 | /// - Parameters:
16 | /// - currency: UIColor
17 | /// - amount: UIColor
18 | public init(currency: UIColor, amount: UIColor, regularAmount: UIColor, badgeBackground: UIColor = .red, badgeText: UIColor = .white, badgeCornerRadius: CGFloat = 4.0) {
19 | self.currency = currency
20 | self.amount = amount
21 | self.badgeText = badgeText
22 | self.badgeBackground = badgeBackground
23 | self.badgeCornerRadius = badgeCornerRadius
24 | self.regularAmount = regularAmount
25 | }
26 |
27 | /// Currency color
28 | var currency: UIColor
29 |
30 | /// Amount color
31 | var amount: UIColor
32 |
33 | /// Regular amount color
34 | var regularAmount: UIColor
35 |
36 | /// Badge background color
37 | var badgeBackground: UIColor
38 |
39 | /// Badge text color
40 | var badgeText: UIColor
41 |
42 | /// Badge corner radius
43 | var badgeCornerRadius: CGFloat
44 | }
45 |
--------------------------------------------------------------------------------
/Sources/DSKit/Appearance/Designable/DSDesignableTabbarColor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSDesignableTabbarColor.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 01.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /// Tabbar colors
12 | public struct DSDesignableTabbarColor {
13 |
14 | /// Init tabbar colors
15 | /// - Parameters:
16 | /// - barTint: UIColor
17 | /// - itemTint: UIColor
18 | /// - unselectedItemTint: UIColor
19 | /// - badge: UIColor
20 | /// - translucent: Bool
21 | public init(barTint: UIColor,
22 | itemTint: UIColor,
23 | unselectedItemTint: UIColor,
24 | badge: UIColor,
25 | translucent: Bool = false) {
26 |
27 | self.barTint = barTint
28 | self.itemTint = itemTint
29 | self.unselectedItemTint = unselectedItemTint
30 | self.badge = badge
31 | self.translucent = translucent
32 | }
33 |
34 | /// Bar tint color
35 | public var barTint: UIColor
36 |
37 | /// Item tint color
38 | public var itemTint: UIColor
39 |
40 | /// Unselected item tint
41 | public var unselectedItemTint: UIColor
42 |
43 | /// Badge color
44 | public var badge: UIColor
45 |
46 | /// Translucent
47 | public var translucent: Bool
48 | }
49 |
--------------------------------------------------------------------------------
/Sources/DSKit/Appearance/Designable/DSDesignableTextFieldColor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TextFieldColor.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 01.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /// Text field colors
12 | public struct DSDesignableTextFieldColor: Equatable, Hashable {
13 |
14 | /// Init designable text field color
15 | /// - Parameters:
16 | /// - border: UIColor
17 | /// - background: UIColor
18 | /// - text: UIColor
19 | /// - placeHolder: UIColor
20 | public init(border: UIColor,
21 | background: UIColor,
22 | text: UIColor,
23 | placeHolder: UIColor) {
24 | self.border = border
25 | self.background = background
26 | self.text = text
27 | self.placeHolder = placeHolder
28 | }
29 |
30 | /// Border color
31 | public var border: UIColor
32 |
33 | /// Background color
34 | public var background: UIColor
35 |
36 | /// Text color
37 | public var text: UIColor
38 |
39 | /// Placeholder color
40 | public var placeHolder: UIColor
41 | }
42 |
--------------------------------------------------------------------------------
/Sources/DSKit/Appearance/Designable/DSDesignableViewColors.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BackgroundColors.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 01.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /// View colors
12 | public struct DSDesignableViewColors: Equatable, Hashable {
13 |
14 | /// Init designable view colors
15 | /// - Parameters:
16 | /// - button: DSDesignableButtonColor
17 | /// - text: DSDesignableTextColor
18 | /// - background: UIColor
19 | /// - separator: UIColor
20 | /// - cornerRadius: CGFloat
21 | public init(button: DSDesignableButtonColor,
22 | text: DSDesignableTextColor,
23 | textField: DSDesignableTextFieldColor,
24 | background: UIColor,
25 | separator: UIColor,
26 | cornerRadius: CGFloat) {
27 |
28 | self.button = button
29 | self.text = text
30 | self.background = background
31 | self.separator = separator
32 | self.cornerRadius = cornerRadius
33 | self.textField = textField
34 | }
35 |
36 | /// Any button on, view colors
37 | public var button: DSDesignableButtonColor
38 |
39 | /// Any text on, view colors
40 | public var text: DSDesignableTextColor
41 |
42 | /// Any textfield on, view colors
43 | public var textField: DSDesignableTextFieldColor
44 |
45 | /// View background colors
46 | public var background: UIColor
47 |
48 | /// View separator colors
49 | public var separator: UIColor
50 |
51 | /// View corner radius
52 | public var cornerRadius: CGFloat
53 | }
54 |
--------------------------------------------------------------------------------
/Sources/DSKit/Appearance/UIColor+String.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIColor+String.swift
3 | // DSKit+AppearanceMaker
4 | //
5 | // Created by Borinschi Ivan on 17.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIColor {
12 | var dsDescription: String {
13 | let light = self.resolvedColor(with: UITraitCollection.init(userInterfaceStyle: .light))
14 | let dark = self.resolvedColor(with: UITraitCollection.init(userInterfaceStyle: .dark))
15 | return "DSColor.color(light: 0x\(light.hexRGBColor), dark: 0x\(dark.hexRGBColor))"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/DSKit/CollectionView/DSCollectionViewPosition.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSCollectionViewPosition.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 23.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public enum DSCollectionViewPosition {
12 | case top
13 | case center
14 | case bottom
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/DSKit/CollectionView/Helpers/DSCollectionView+Config.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSCollectionView+Config.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 02.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension DSCollectionView {
12 |
13 | public var isPagingEnabled: Bool {
14 | get { view.isPagingEnabled }
15 | set { view.isPagingEnabled = newValue }
16 | }
17 |
18 | public var showsHorizontalScrollIndicator: Bool {
19 | get { view.showsHorizontalScrollIndicator }
20 | set { view.showsHorizontalScrollIndicator = newValue }
21 | }
22 |
23 | public var showsVerticalScrollIndicator: Bool {
24 | get { view.showsVerticalScrollIndicator }
25 | set { view.showsVerticalScrollIndicator = newValue }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/DSKit/CollectionView/Helpers/DSCollectionView+Forms.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSCollectionView+Forms.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 02.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension DSCollectionView {
12 |
13 | func isCurrentFormValid(_ validate: @escaping (Bool) -> Void) {
14 |
15 | guard !self.adaptedContent.isEmpty else {
16 | validate(true)
17 | return
18 | }
19 |
20 | var verifiedViewModels: Int = 0
21 |
22 | var isValid = true
23 |
24 | for section in adaptedContent {
25 |
26 | for model in section.viewModels {
27 |
28 | guard let model = model as? DSTextFieldVM else {
29 | continue
30 | }
31 |
32 | // Request view model to validate self
33 | model.validateTextField?()
34 |
35 | model.isValid(text: model.text, validateEmptyTextField: false, { isViewTextFieldValid in
36 |
37 | verifiedViewModels += 1
38 |
39 | if !isViewTextFieldValid {
40 | isValid = false
41 | }
42 |
43 | if verifiedViewModels == self.adaptedContent.totalTextFieldViewModelsCount {
44 | validate(isValid)
45 | }
46 | })
47 | }
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Sources/DSKit/CollectionView/Helpers/DSCollectionView+Identifiers.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSCollectionView+Sections.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 02.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension DSCollectionView {
12 |
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/Sources/DSKit/CollectionView/Helpers/DSCollectionView+Register.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSCollectionView+Register.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 02.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension DSCollectionView {
12 |
13 | public func registerCellClassIfNeed(for reusableIdentifier: String, cellClass: AnyClass) {
14 | if !registeredCells.contains(reusableIdentifier) {
15 | self.view.register(cellClass, forCellWithReuseIdentifier: reusableIdentifier)
16 | registeredCells.append(reusableIdentifier)
17 | }
18 | }
19 |
20 | public func registerClassForReusableViewIfNeed(kind: String, reuseIdentifier: String, viewClass: AnyClass) {
21 | if !registeredViews.contains(reuseIdentifier) {
22 | self.view.register(viewClass, forSupplementaryViewOfKind: kind, withReuseIdentifier: reuseIdentifier)
23 | registeredViews.append(reuseIdentifier)
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/DSKit/CollectionView/Helpers/DSCollectionView+Reload.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSCollectionView+Reload.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 02.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension DSCollectionView {
12 |
13 | /// Reload content
14 | /// - Parameters:
15 | /// - newContent: New content to show
16 | /// - scrollToBottom: Scroll to bottom after reload, default is `false`
17 | func reload(content newContent: [DSSection], animated: Bool = false, scrollToBottom: Bool = false) {
18 | show(content: newContent, animated: animated, scrollToBottom: scrollToBottom)
19 | }
20 |
21 | /// Reload current content
22 | /// - Parameter scrollToBottom: Scroll to bottom after reload, default is `false`
23 | func reload(scrollToBottom: Bool = false, animated: Bool = false) {
24 | self.reload(content: self.originalContent, animated: animated, scrollToBottom: scrollToBottom)
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/DSKit/ContentModels/Image/DSImage+DSViewable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSImage+DSViewAble.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 22.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension DSImage: DSViewable {
12 |
13 | public func view(_ designableViewColors: DSDesignableViewColors) -> UIView {
14 | let imageView = UIImageView()
15 | imageView.setImage(self, designableViewColors: designableViewColors)
16 | return imageView
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Sources/DSKit/ContentModels/Image/DSImage.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIButtonExtension.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 22.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public struct DSImage: Equatable, Hashable {
12 |
13 | public var size: DSImageSize
14 | public var displayStyle: DSImageDisplayStyle
15 | public var content: DSImageContent
16 | public var contentMode: DSImageContentMode
17 | public var tintColor: DSImageTintColor
18 |
19 | public init(content: DSImageContent,
20 | displayStyle: DSImageDisplayStyle = .default,
21 | size: DSImageSize = .size(CGSize(width: 25, height: 25)),
22 | tintColor: DSImageTintColor,
23 | contentMode: DSImageContentMode = .scaleAspectFit) {
24 |
25 | self.content = content
26 | self.displayStyle = displayStyle
27 | self.tintColor = tintColor
28 | self.size = size
29 | self.contentMode = contentMode
30 | }
31 | }
32 |
33 | extension UIImageView {
34 |
35 | func setImage(_ image: DSImage,
36 | designableViewColors: DSDesignableViewColors) {
37 |
38 | setImageContent(image.content)
39 | setImageTintColor(image.tintColor, designableViewColors: designableViewColors)
40 | setImageDisplayStyle(image.displayStyle, size: image.size, cornerRadius: designableViewColors.cornerRadius)
41 | setImageSize(image.size)
42 | setImageContentMode(image.contentMode)
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Sources/DSKit/ContentModels/Image/DSImageContentMode.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSImageTintColor.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 21.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public enum DSImageContentMode: Equatable, Hashable {
12 |
13 | case scaleAspectFit // contents scaled to fit with fixed aspect. remainder is transparent
14 | case scaleAspectFill // contents scaled to fill with fixed aspect. some portion of content may be clipped.
15 |
16 | public var rawValue: String {
17 | switch self {
18 | case .scaleAspectFit:
19 | return "ScaleAspectFit"
20 | case .scaleAspectFill:
21 | return "ScaleAspectFill"
22 | }
23 | }
24 | }
25 |
26 | extension UIImageView {
27 |
28 | /// Image Content mode
29 | /// - Parameters:
30 | /// - contentMode: DSImageContentMode
31 | func setImageContentMode(_ contentMode: DSImageContentMode) {
32 |
33 | switch contentMode {
34 | case .scaleAspectFill:
35 | self.contentMode = .scaleAspectFill
36 | case .scaleAspectFit:
37 | self.contentMode = .scaleAspectFit
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Sources/DSKit/ContentModels/Image/DSImageHeight.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSImageHeight.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 21.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public enum DSImageHeight: Equatable, Hashable {
12 |
13 | case equalTo(CGFloat)
14 | case zero
15 | case unknown
16 |
17 | var rawValue: String {
18 | switch self {
19 | case .equalTo(let height):
20 | return "ImageHeight\(height)"
21 | case .zero:
22 | return "ImageHeightZero"
23 | case .unknown:
24 | return "ImageHeightUnknown"
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/DSKit/ContentModels/Image/DSImageSize.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 21.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Cartography
11 |
12 | public enum DSImageSize: Equatable, Hashable {
13 |
14 | case size(CGSize)
15 | case unknown
16 |
17 | public var rawValue: String {
18 | switch self {
19 | case .size(let size):
20 | return "ImageSize_\(size.width)x\(size.height)"
21 | case .unknown:
22 | return "UnknownSize"
23 | }
24 | }
25 |
26 | var width: CGFloat? {
27 | switch self {
28 | case .size(let size):
29 | return size.width
30 | case .unknown:
31 | return nil
32 | }
33 | }
34 |
35 | var height: CGFloat? {
36 | switch self {
37 | case .size(let size):
38 | return size.height
39 | case .unknown:
40 | return nil
41 | }
42 | }
43 | }
44 |
45 | extension UIImageView {
46 |
47 | func setImageSize(_ size: DSImageSize) {
48 |
49 | switch size {
50 | case .size(let size):
51 |
52 | constrain(self) { (imageView) in
53 | imageView.width == size.width
54 | imageView.height == size.height
55 | }
56 |
57 | case .unknown:
58 |
59 | constrain(self) { (imageView) in
60 | imageView.width >= 0
61 | imageView.height >= 0
62 | }
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Sources/DSKit/ContentModels/Image/DSImageTintColor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSImageTintColor.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 21.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public enum DSImageTintColor: Equatable, Hashable {
12 |
13 | case `default`
14 | case text(DSTextColor)
15 | case custom(UIColor)
16 |
17 | public var rawValue: String {
18 | switch self {
19 | case .text(_):
20 | return "DSImageTintColorTextColor"
21 | case .custom(_):
22 | return "DSImageTintColorCustom"
23 | case .default:
24 | return "DSImageTintColorDefault"
25 | }
26 | }
27 | }
28 |
29 | extension UIImageView {
30 |
31 | func setImageTintColor(_ color: DSImageTintColor, designableViewColors: DSDesignableViewColors) {
32 |
33 | switch color {
34 | case .text(let textColor):
35 | tintColor = textColor.getColor(designableTextColor: designableViewColors.text)
36 | case .custom(let uiColor):
37 | tintColor = uiColor
38 | case .default:
39 | tintColor = designableViewColors.text.subheadline
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Sources/DSKit/ContentModels/Price/DSPrice+Viewable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSPrice+Viewable.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 22.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension DSPrice: DSViewable {
12 |
13 | func view(_ designableViewColors: DSDesignableViewColors) -> UIView {
14 |
15 | let label = UILabel()
16 | let composer = DSTextComposer()
17 | composer.add(price: self)
18 | label.set(text: composer, designableTextColor: designableViewColors.text)
19 | return label
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/DSKit/ContentModels/Text/DSTextComposer+DSViewable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSText.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 14.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension DSTextComposer: DSViewable {
12 |
13 | func view(_ designableViewColors: DSDesignableViewColors) -> UIView {
14 | let label = UILabel()
15 | label.set(text: self, designableTextColor: designableViewColors.text)
16 | return label
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Sources/DSKit/ContentModels/Text/DSTextComposer+ViewModels.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSTextComposer+ViewModels.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 05.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public extension DSTextComposer {
12 |
13 | /// Get text view model from composer
14 | /// - Returns: DSTextVM
15 | func textViewModel() -> DSLabelVM {
16 | return DSLabelVM(composer: self)
17 | }
18 |
19 | /// Get action view model from composer
20 | /// - Returns: DSTextVM
21 | func actionViewModel() -> DSActionVM {
22 | return DSActionVM(composer: self)
23 | }
24 |
25 | /// Checkbox Action ViewModel
26 | /// - Parameter selected: Bool
27 | /// - Returns: DSActionVM
28 | func checkboxActionViewModel(selected: Bool) -> DSActionVM {
29 |
30 | let appearance = DSAppearance.shared.main
31 | let icon = selected ? "checkmark.circle.fill" : "circle"
32 | let color = selected ? appearance.semanticGreenColor : appearance.secondaryView.text.subheadline.withAlphaComponent(0.5)
33 |
34 | var action = DSActionVM(composer: self)
35 | action.rightIcon(sfSymbolName: icon, style: selected ? .custom(size: 15, weight: .medium) : .custom(size: 12, weight: .light), tintColor: .custom(color))
36 | return action
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/DSKit/ContentModels/Text/DSTextParagraph.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSTextParagraph.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 21.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | struct DSTextParagraph: Equatable, Hashable {
12 |
13 | let type: DSTextParagraphType
14 | let newLine: Bool
15 | let spacing: CGFloat
16 | let lineSpacing: CGFloat
17 | let maximumLineHeight: CGFloat
18 |
19 | static func == (lhs: DSTextParagraph, rhs: DSTextParagraph) -> Bool {
20 | return
21 | lhs.newLine == rhs.newLine &&
22 | lhs.spacing == rhs.spacing &&
23 | lhs.type == rhs.type
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/DSKit/ContentModels/Text/DSTextParagraphType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSTextParagraphType.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 21.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | enum DSTextParagraphType: Equatable, Hashable {
12 | case attributed(text: NSAttributedString)
13 | case text(icon: UIImage?, text: String, font: UIFont, color: DSTextColor)
14 | case price(price: DSPrice, size: DSPrice.DisplaySize, color: DSPrice.DisplayColor)
15 | case symbol(sfSymbol: String, style: DSSFSymbolConfigStyle, tint: DSTextColor)
16 | case symbols(sfSymbols: [String], style: DSSFSymbolConfigStyle, tint: DSTextColor)
17 | case image(image: UIImage, size: CGSize)
18 | case badge(text: String, type: DSTextType, backgroundColor: UIColor, cornerRadius: CGFloat)
19 | }
20 |
--------------------------------------------------------------------------------
/Sources/DSKit/ContentModels/View/DSViewPosition.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSViewPosition.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 21.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public enum DSViewPosition {
12 | case top
13 | case center
14 | }
15 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/CGFloat+UIEdgeInsets.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CGFloat+UIEdgeInsets.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 30.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension CGFloat {
12 |
13 | /// Transform CGFloat to UIEdgeInsets with CGFloat
14 | public var edgeInsets: UIEdgeInsets {
15 | return UIEdgeInsets(top: self, left: self, bottom: self, right: self)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/Double+Rounded.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DoubleExtension.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 01.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension Double {
12 |
13 | /// Rounds the double to decimal places value
14 | /// - Parameter places: Place to round to, Example: Double(123.456789).rounded(toPlaces: 1) will equal to 123.5
15 | /// - Returns: Double
16 | func rounded(toPlaces places: Int) -> Double {
17 | let divisor = pow(10.0, Double(places))
18 | return (self * divisor).rounded() / divisor
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/Int+Cents.swift:
--------------------------------------------------------------------------------
1 | //
2 | // IntExtension.swift
3 | // MMModules
4 | //
5 | // Created by Borinschi Ivan on 5/23/17.
6 | // Copyright © 2017 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public extension Int {
12 |
13 | func toNSNumber() -> NSNumber {
14 | return NSNumber(value: self)
15 | }
16 |
17 | func stringAmount() -> String {
18 | return toNSNumber().fromCents().stringFormatted(withNumberOfDecimals: 2)
19 | }
20 |
21 | func toCents() -> Int {
22 | return self * 100
23 | }
24 |
25 | func string() -> String {
26 | return "\(self)"
27 | }
28 |
29 | func fromCents() -> Int {
30 | return self / 100
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/Int+Plural.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Int+Plural.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public extension Int {
12 |
13 | /// Return correct form of the string, singular or plural.
14 | ///
15 | /// - Parameters:
16 | /// - singular: Singular form of the string
17 | /// - plural: Plural form of the string
18 | /// - Returns: String with correct form.
19 | func getCorrectForm(singular: String, plural: String) -> String {
20 | if self == 1 {
21 | return singular
22 | } else if self > 1 {
23 | return plural
24 | } else {
25 | return plural
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/Int+TimeString.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Int+TimeString.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public extension Int {
12 |
13 | /// Convert int to time string, 120 seconds to 01:59
14 | ///
15 | /// - Returns: String
16 | func timeString() -> String {
17 |
18 | let minutes = (self % 3600) / 60
19 | let seconds = (self % 3600) % 60
20 |
21 | var minutesString = "\(minutes)"
22 | var secondsString = "\(seconds)"
23 |
24 | if minutesString.count == 1 {
25 | minutesString = "0\(minutesString)"
26 | }
27 |
28 | if secondsString.count == 1 {
29 | secondsString = "0\(secondsString)"
30 | }
31 |
32 | return "\(minutesString):\(secondsString)"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/NSNumber+Cents.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NSNumberExtension.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 5/23/20.
6 | // Copyright © 2020 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public extension NSNumber {
12 |
13 | func stringFormatted(withNumberOfDecimals numberOfDecimals: Int) -> String {
14 |
15 | let formatter = NumberFormatter()
16 | formatter.locale = Locale(identifier: "en_US")
17 | formatter.numberStyle = .decimal
18 | formatter.maximumFractionDigits = numberOfDecimals
19 | formatter.minimumFractionDigits = numberOfDecimals
20 |
21 | guard let finalValue = formatter.string(from: self) else {
22 | return "0.00"
23 | }
24 |
25 | return finalValue
26 | }
27 |
28 | func stringFormattedAmount() -> String {
29 | return stringFormatted(withNumberOfDecimals: 2)
30 | }
31 |
32 | func toCents() -> NSNumber {
33 | return NSNumber(value: lround(self.doubleValue * 100))
34 | }
35 |
36 | func fromCents() -> NSNumber {
37 | return NSNumber(value: self.doubleValue / 100)
38 | }
39 |
40 | class func divideFloat(first: Float, second: Float) -> Float {
41 |
42 | if first == 0 || second == 0 {
43 | return Float(0)
44 | }
45 |
46 | let result = first/second
47 |
48 | if result > 0 {
49 | return Float(result)
50 | } else {
51 | return Float(0)
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/Notification+FrameAndDuration.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotificationExtension.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 30.11.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public extension Notification {
12 |
13 | /// Get keyboard final frame and animation duration
14 | /// - Returns: frame: CGRect, duration: Double)
15 | func frameAndDuration() -> (frame: CGRect, duration: Double)? {
16 |
17 | guard let keyboardFrame = userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect,
18 | let duration = userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double else {
19 | return nil
20 | }
21 |
22 | return (frame: keyboardFrame, duration: duration)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/String+AppName.swift:
--------------------------------------------------------------------------------
1 | //
2 | // String+AppName.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public extension String {
12 |
13 | static func appName() -> String {
14 | return Bundle.main.infoDictionary!["CFBundleDisplayName"] as? String ?? "App"
15 | }
16 |
17 | func style(_ appearance: DSDesignable) -> String {
18 | return self
19 | }
20 |
21 | func toAccessibilityIdentifierStyle() -> String {
22 | return self.replace(target: " ", withString: "_").replace(target: "-", withString: "_").uppercased()
23 | }
24 |
25 | func replace(target: String, withString: String) -> String {
26 | return self.replacingOccurrences(of: target, with: withString, options: NSString.CompareOptions.literal, range: nil)
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/String+Currency.swift:
--------------------------------------------------------------------------------
1 | //
2 | // String+Currency.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension String {
12 | var currencySymbol: String {
13 | switch self {
14 | case "EUR": return "€"
15 | case "USD": return "$"
16 | case "GBP": return "£"
17 | default: return self
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/String+EstimatedHeight.swift:
--------------------------------------------------------------------------------
1 | //
2 | // String+EstimatedHeight.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 05.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension String {
12 |
13 | /// Get estimated height for text
14 | /// - Parameters:
15 | /// - textType: DSTextType
16 | /// - section: DSSection
17 | /// - layoutEnvironment: NSCollectionLayoutEnvironment
18 | /// - Returns: DSViewModelHeight
19 | func estimatedHeight(textType: DSTextType, section: DSSection, _ layoutEnvironment: NSCollectionLayoutEnvironment?) -> DSViewModelHeight {
20 |
21 | let width = section.sectionWidth(layoutEnvironment)
22 | let height = self.height(forFixedWidth: width, font: textType.style.font.getFont())
23 | return .estimated(height)
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/String+OpenURL.swift:
--------------------------------------------------------------------------------
1 | //
2 | // String+OpenURL.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public extension String {
12 |
13 | func open() {
14 |
15 | if let url = URL(string: self) {
16 |
17 | if self.isEmail() {
18 | self.openEmail()
19 | } else {
20 | URLOpener.open(url, options: [:], completion: nil)
21 | }
22 | }
23 | }
24 |
25 | @discardableResult
26 | func openEmail() -> URL? {
27 | let email = self
28 | if let url = URL(string: "mailto:\(email)") {
29 | URLOpener.open(url, options: [:], completion: nil)
30 | return url
31 | }
32 | return nil
33 | }
34 |
35 | @discardableResult
36 |
37 | func openPhone() -> URL? {
38 | var number = self.replacingOccurrences(of: "+", with: "00")
39 | number = number.replacingOccurrences(of: " ", with: "")
40 | guard let phoneNumber = URL(string: "tel://" + number) else {
41 | return nil
42 | }
43 |
44 | URLOpener.open(phoneNumber, options: [:], completion: nil)
45 | return phoneNumber
46 | }
47 |
48 | func isEmail() -> Bool {
49 | return self.contains("@")
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/String+Random.swift:
--------------------------------------------------------------------------------
1 | //
2 | // String+Random.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension String {
12 |
13 | public func randomString(length: Int) -> String {
14 |
15 | let letters: NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
16 | let len = UInt32(letters.length)
17 |
18 | var randomString = ""
19 |
20 | for _ in 0 ..< length {
21 | let rand = arc4random_uniform(len)
22 | var nextChar = letters.character(at: Int(rand))
23 | randomString += NSString(characters: &nextChar, length: 1) as String
24 | }
25 |
26 | return randomString
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/UIApplication+KeyWindow.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIApplication+KeyWindow.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 29.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public extension UIApplication {
12 |
13 | func getKeyWindow() -> UIWindow? {
14 |
15 | UIApplication.shared.connectedScenes
16 | .filter({$0.activationState == .foregroundActive})
17 | .map({$0 as? UIWindowScene})
18 | .compactMap({$0})
19 | .first?.windows
20 | .filter({$0.isKeyWindow}).first
21 | }
22 |
23 | var isRTL: Bool {
24 | UIApplication.shared.getKeyWindow()?.effectiveUserInterfaceLayoutDirection == .rightToLeft
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/UIApplication+TopViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIApplication+KeyWindow.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 29.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIViewController {
12 |
13 | /// Do not change this code !
14 | /// - Returns: UIViewController
15 | func topMostViewController() -> UIViewController? {
16 |
17 | if self.presentedViewController == nil {
18 |
19 | if let navigation = self as? UINavigationController {
20 | return navigation.visibleViewController?.topMostViewController() ?? nil
21 | }
22 |
23 | return self
24 | }
25 | if let navigation = self.presentedViewController as? UINavigationController {
26 | return navigation.visibleViewController?.topMostViewController() ?? nil
27 | }
28 |
29 | if let tab = self.presentedViewController as? UITabBarController {
30 | if let selectedTab = tab.selectedViewController {
31 | return selectedTab.topMostViewController()
32 | }
33 | return tab.topMostViewController()
34 | }
35 | return self.presentedViewController!.topMostViewController()
36 | }
37 | }
38 |
39 | extension UIApplication {
40 | func topMostViewController() -> UIViewController? {
41 |
42 | let controller = UIApplication.shared.getKeyWindow()?.rootViewController?.topMostViewController()
43 |
44 | return controller
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/UIButton+Colors.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIButton+Colors.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIButton {
12 |
13 | func setBackgroundColor(color: UIColor, forState: UIControl.State) {
14 |
15 | UIGraphicsBeginImageContext(CGSize(width: 1, height: 1))
16 | UIGraphicsGetCurrentContext()!.setFillColor(color.cgColor)
17 | UIGraphicsGetCurrentContext()!.fill(CGRect(x: 0, y: 0, width: 1, height: 1))
18 | let colorImage = UIGraphicsGetImageFromCurrentImageContext()
19 | UIGraphicsEndImageContext()
20 | self.setBackgroundImage(colorImage, for: forState)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/UIButton+EdgeInsets.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIButton+EdgeInsets.swift
3 | //
4 | //
5 | // Created by Zalan Mergl on 2022. 06. 10..
6 | //
7 |
8 | import UIKit
9 |
10 | public extension UIButton {
11 | func centerVertically(padding: CGFloat = 3.0) {
12 | if let imageViewSize = self.imageView?.frame.size,
13 | let titleLabelSize = self.titleLabel?.frame.size {
14 |
15 | let imageHeight: CGFloat = 30
16 | let totalHeight = imageHeight + titleLabelSize.height + padding
17 | let topMargin = (totalHeight) / 3
18 |
19 | self.imageEdgeInsets = UIEdgeInsets(
20 | top: -(totalHeight - imageHeight - topMargin),
21 | left: 0.0,
22 | bottom: 0.0,
23 | right: -titleLabelSize.width
24 | )
25 |
26 | self.titleEdgeInsets = UIEdgeInsets(
27 | top: 0.0,
28 | left: -imageViewSize.width,
29 | bottom: -(totalHeight - titleLabelSize.height + (topMargin / 2)),
30 | right: 0.0
31 | )
32 |
33 | self.contentEdgeInsets = UIEdgeInsets(
34 | top: 0.0,
35 | left: 0.0,
36 | bottom: titleLabelSize.height,
37 | right: 0.0
38 | )
39 | }
40 | }
41 |
42 | func moveImageEdgeInset(by delta: CGFloat) {
43 | imageEdgeInsets = UIEdgeInsets(top: 0, left: delta, bottom: 0, right: -delta)
44 | }
45 |
46 | func moveTitleEdgeInset(by delta: CGFloat) {
47 | titleEdgeInsets = UIEdgeInsets(top: 0, left: delta, bottom: 0, right: -delta)
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/UIColor+Equtable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIColor+Equatable.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIColor {
12 |
13 | static func == (l: UIColor, r: UIColor) -> Bool {
14 | var r1: CGFloat = 0
15 | var g1: CGFloat = 0
16 | var b1: CGFloat = 0
17 | var a1: CGFloat = 0
18 | l.getRed(&r1, green: &g1, blue: &b1, alpha: &a1)
19 | var r2: CGFloat = 0
20 | var g2: CGFloat = 0
21 | var b2: CGFloat = 0
22 | var a2: CGFloat = 0
23 | r.getRed(&r2, green: &g2, blue: &b2, alpha: &a2)
24 | return r1 == r2 && g1 == g2 && b1 == b2 && a1 == a2
25 | }
26 | }
27 |
28 | func == (l: UIColor?, r: UIColor?) -> Bool {
29 | let l = l ?? .clear
30 | let r = r ?? .clear
31 | return l == r
32 | }
33 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/UIColor+IsLight.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIColor+IsLight.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 26.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public extension UIColor {
12 |
13 | // Check if the color is light or dark, as defined by the injected lightness threshold.
14 | // Some people report that 0.7 is best. I suggest to find out for yourself.
15 | // A nil value is returned if the lightness couldn't be determined.
16 | func isLight(threshold: Float = 0.5) -> Bool? {
17 | let originalCGColor = self.cgColor
18 |
19 | // Now we need to convert it to the RGB colorspace. UIColor.white / UIColor.black are greyscale and not RGB.
20 | // If you don't do this then you will crash when accessing components index 2 below when evaluating greyscale colors.
21 | let RGBCGColor = originalCGColor.converted(to: CGColorSpaceCreateDeviceRGB(), intent: .defaultIntent, options: nil)
22 | guard let components = RGBCGColor?.components else {
23 | return nil
24 | }
25 | guard components.count >= 3 else {
26 | return nil
27 | }
28 |
29 | let brightness = Float(((components[0] * 299) + (components[1] * 587) + (components[2] * 114)) / 1000)
30 | return (brightness > threshold)
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/UIEdgeInsets+Add.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIEdgeInsets+Add.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 31.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIEdgeInsets {
12 |
13 | /// Add number to all edges and return new UIEdgeInsets
14 | /// - Parameter number: CGFloat
15 | /// - Returns: UIEdgeInsets
16 | func add(_ number: CGFloat) -> UIEdgeInsets {
17 | var insets = self
18 | insets.top += number
19 | insets.bottom += number
20 | insets.left += number
21 | insets.right += number
22 | return insets
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/UIEdgeInsets+NSDirectionalEdgeInsets.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIEdgeInsetsExtension.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 11.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIEdgeInsets {
12 |
13 | /// Transform UIEdgeInsets in to NSDirectionalEdgeInsets
14 | var directionalEdgeInsets: NSDirectionalEdgeInsets {
15 |
16 | return NSDirectionalEdgeInsets(top: top,
17 | leading: left,
18 | bottom: bottom,
19 | trailing: right)
20 | }
21 |
22 | var zeroLeftRightDirectionalEdgeInsets: NSDirectionalEdgeInsets {
23 |
24 | return NSDirectionalEdgeInsets(top: top,
25 | leading: 0,
26 | bottom: bottom,
27 | trailing: 0)
28 | }
29 |
30 | var groupedGridDirectionalEdgeInsets: NSDirectionalEdgeInsets {
31 |
32 | return NSDirectionalEdgeInsets(top: top,
33 | leading: left,
34 | bottom: bottom,
35 | trailing: right)
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/UIImage+SFSymbol.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | //
4 | //
5 | // Created by Zalan Mergl on 2022. 06. 01..
6 | //
7 |
8 | import UIKit
9 |
10 | public extension UIImage {
11 | static func symbolImage(with symbolName: String, configuration: UIImage.Configuration? = nil) -> UIImage? {
12 | if let symbolImage = UIImage(systemName: symbolName, withConfiguration: configuration) {
13 | return symbolImage
14 | } else if let customSymbolImage = UIImage(named: symbolName, in: nil, with: configuration) {
15 | return customSymbolImage
16 | }
17 |
18 | return nil
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/UILabelExtension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UILabelExtension.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 30.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public extension UILabel {
12 |
13 | func set(text: DSTextComposer, designableTextColor: DSDesignableTextColor) {
14 | numberOfLines = 0
15 | font = UIFont.systemFont(ofSize: 8)
16 | attributedText = text.attributedString(designableTextColor: designableTextColor)
17 | }
18 |
19 | func setStyle(type: DSTextType, designableTextColor: DSDesignableTextColor) {
20 | self.textColor = type.style.color.getColor(designableTextColor: designableTextColor)
21 | self.font = type.style.font.getFont()
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/UIPageControl+Appearance.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIPageControlExtension.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 09.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIPageControl {
12 |
13 | func updateAppearance() {
14 | let appearance = DSAppearance.shared.main
15 | backgroundColor = appearance.primaryView.background
16 | pageIndicatorTintColor = appearance.brandColor.lighten(.C500)
17 | currentPageIndicatorTintColor = appearance.brandColor
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/UIView+Border.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+Border.swift
3 | //
4 | //
5 | // Created by Zalan Mergl on 2022. 04. 14..
6 | //
7 |
8 | import UIKit
9 |
10 | public extension UIView {
11 | func configureBorder(_ borderStyle: DSViewModelBorderStyle, viewColors: DSDesignableViewColors? = nil) {
12 | switch borderStyle {
13 | case .none:
14 | layer.borderWidth = 0
15 | layer.borderColor = UIColor.clear.cgColor
16 | case .buttonColor:
17 | layer.borderWidth = 2.0
18 | layer.borderColor = viewColors?.button.background.cgColor ?? DSAppearance.shared.main.primaryView.button.background.cgColor
19 | case .brandColor:
20 | layer.borderWidth = 2.0
21 | layer.borderColor = DSAppearance.shared.main.brandColor.cgColor
22 | case .custom(width: let width, color: let color):
23 | layer.borderWidth = width
24 | layer.borderColor = color.cgColor
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/UIView+Constraints.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+Constraints.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 25.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | extension UIView {
13 |
14 | func clearConstraints() {
15 | for constraint in self.constraints {
16 | self.removeConstraint(constraint)
17 | }
18 | }
19 |
20 | func equalEdgesTo(view: UIView, insets: UIEdgeInsets = .zero) {
21 |
22 | self.clearConstraints()
23 |
24 | //print(self.constraints)
25 | //print(view.constraints)
26 |
27 | let leftConstraint = view.leftAnchor.constraint(equalTo: self.leftAnchor)
28 | let topConstraint = view.topAnchor.constraint(equalTo: self.topAnchor)
29 | let rightConstraint = view.rightAnchor.constraint(equalTo: self.rightAnchor)
30 | let bottomConstraint = view.bottomAnchor.constraint(equalTo: self.bottomAnchor)
31 |
32 | print(leftConstraint.isActive)
33 |
34 | leftConstraint.constant = insets.left
35 | topConstraint.constant = insets.top
36 | rightConstraint.constant = -insets.right
37 | bottomConstraint.constant = -insets.bottom
38 |
39 | bottomConstraint.priority = UILayoutPriority(rawValue: 999)
40 |
41 | leftConstraint.isActive = true
42 | topConstraint.isActive = true
43 | rightConstraint.isActive = true
44 | bottomConstraint.isActive = true
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Sources/DSKit/Extensions/UIView+EdgeInsets.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+Margins.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 04.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Cartography
11 |
12 | extension UIView {
13 |
14 | /// Place self in a subview and add insets from sides
15 | /// - Parameter insets: UIEdgeInsets
16 | /// - Returns: Subview with insets
17 | func subViewWith(insets: UIEdgeInsets) -> UIView {
18 |
19 | let holderView = UIView()
20 | holderView.addSubview(self)
21 |
22 | constrain(self, holderView) { view, holderView in
23 | view.left == holderView.left + insets.left
24 | view.top == holderView.top + insets.top
25 | view.bottom == holderView.bottom - insets.bottom
26 | view.right == holderView.right - insets.right
27 | }
28 |
29 | return holderView
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Sources/DSKit/Helpers/DispatchQueue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DispatchQueue.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 30.11.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public extension DispatchQueue {
12 |
13 | /// Execute closure after an random delay on main tread
14 | /// - Parameters:
15 | /// - min: Minim delay
16 | /// - max: Maxim delay
17 | /// - closure: Closure to execute
18 | func randomDelay(min: TimeInterval = 0.0, max: TimeInterval = 1.0, _ closure: @escaping () -> Void) {
19 | DispatchQueue.main.asyncAfter(deadline: .now() + Double.random(in: min...max)) {
20 | closure()
21 | }
22 | }
23 |
24 | /// Execute closure on main thread after delay
25 | /// - Parameters:
26 | /// - after: Delay
27 | /// - closure: Closure to execute
28 | func after(_ after: TimeInterval = 0.5, _ closure: @escaping () -> Void) {
29 | DispatchQueue.main.asyncAfter(deadline: .now() + after) {
30 | closure()
31 | }
32 | }
33 |
34 | /// Execute closure on main thread now, used to move executions from other threads to main
35 | /// - Parameter closure: Closure to execute
36 | func now(_ closure: @escaping () -> Void) {
37 | self.after(0.0, closure)
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Sources/DSKit/Helpers/IAKCacheManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSCacheManager.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 17.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | class DSImageCache: NSObject, NSDiscardableContent {
13 |
14 | public var image: UIImage?
15 |
16 | func beginContentAccess() -> Bool {
17 | return true
18 | }
19 |
20 | func endContentAccess() {
21 |
22 | }
23 |
24 | func discardContentIfPossible() {
25 |
26 | }
27 |
28 | func isContentDiscarded() -> Bool {
29 | return false
30 | }
31 | }
32 |
33 | public class DSCacheManager {
34 |
35 | let mapImageCache = NSCache()
36 |
37 | public static let shared = DSCacheManager()
38 |
39 | public init() {
40 | mapImageCache.countLimit = 200
41 | mapImageCache.totalCostLimit = 0
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Sources/DSKit/Helpers/NonEquatable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NonEquatable.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 14.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | @propertyWrapper
12 | public struct NonEquatable: Equatable, Hashable {
13 | public var wrappedValue: Value
14 |
15 | public init(wrappedValue: Value) {
16 | self.wrappedValue = wrappedValue
17 | }
18 |
19 | public static func == (lhs: NonEquatable, rhs: NonEquatable) -> Bool {
20 | true
21 | }
22 |
23 | public func hash(into hasher: inout Hasher) {
24 | hasher.combine("NonHashable")
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/DSKit/Helpers/PasswordValidator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PasswordValidator.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 9/21/20.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 | //
9 |
10 | import Foundation
11 | import UIKit
12 |
13 | public struct PasswordRule {
14 | let test: (String) -> Bool
15 | }
16 |
17 | public final class PasswordValidator {
18 |
19 | let rules: [PasswordRule] = [
20 |
21 | PasswordRule(test: { $0.count > 7 }),
22 | PasswordRule(test: { $0.satisfiesRegexp("[a-z]") }),
23 | PasswordRule(test: { $0.satisfiesRegexp("[0-9]") }),
24 | PasswordRule(test: { $0.satisfiesRegexp("[A-Z]") }),
25 | PasswordRule(test: { $0.satisfiesRegexp("[!@#$&()\\-`.+,/\"]*$]") })
26 | ]
27 |
28 | public func strengthForPassword(_ password: String) -> Double {
29 | return rules.reduce(0) { $0 + ($1.test(password) ? 1 : 0) }
30 | }
31 |
32 | public func colorForPassword(_ password: String) -> UIColor {
33 |
34 | return colorsForStrengths()[strengthForPassword(password)]!
35 | }
36 |
37 | public func colorsForStrengths() -> [Double: UIColor] {
38 | return [
39 | 0: UIColor(0xD73B00),
40 | 1: UIColor(0xC89100),
41 | 2: UIColor(0xAEAE00),
42 | 3: UIColor(0x97B73E),
43 | 4: UIColor(0x21AF46)
44 | ]
45 | }
46 | }
47 |
48 | internal extension String {
49 | func satisfiesRegexp(_ regexp: String) -> Bool {
50 | return range(of: regexp, options: .regularExpression) != nil
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Sources/DSKit/Helpers/PreviewContainer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PreviewContainer.swift
3 | // DSKit+FlowerStore
4 | //
5 | // Created by Borinschi Ivan on 23.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import SwiftUI
11 |
12 | public struct PreviewContainer: UIViewControllerRepresentable {
13 |
14 | let viewController: UIViewController
15 | let appearance: DSDesignable?
16 | let navigationController: Bool
17 |
18 | public init(VC: UIViewController, _ appearance: DSDesignable? = nil, _ navigationController: Bool = false) {
19 | self.viewController = VC
20 | self.appearance = appearance
21 | self.navigationController = navigationController
22 | }
23 |
24 | public func makeUIViewController(context: UIViewControllerRepresentableContext) -> UIViewController {
25 |
26 | if let appearance = self.appearance {
27 | DSAppearance.shared.main = appearance
28 | }
29 |
30 | if navigationController {
31 | return DSNavigationViewController(rootViewController: viewController)
32 | } else {
33 | return viewController
34 | }
35 | }
36 |
37 | public func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext) {
38 | }
39 |
40 | public typealias UIViewControllerType = UIViewController
41 | }
42 |
--------------------------------------------------------------------------------
/Sources/DSKit/Helpers/Rescale.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Rescale.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 01.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | struct Rescale {
12 |
13 | typealias RescaleDomain = (lowerBound: Type, upperBound: Type)
14 |
15 | var fromDomain: RescaleDomain
16 | var toDomain: RescaleDomain
17 |
18 | init(from: RescaleDomain, to: RescaleDomain) {
19 | self.fromDomain = from
20 | self.toDomain = to
21 | }
22 |
23 | func interpolate(_ x: Type ) -> Type {
24 | return self.toDomain.lowerBound * (1 - x) + self.toDomain.upperBound * x;
25 | }
26 |
27 | func uninterpolate(_ x: Type) -> Type {
28 | let b = (self.fromDomain.upperBound - self.fromDomain.lowerBound) != 0 ? self.fromDomain.upperBound - self.fromDomain.lowerBound : 1 / self.fromDomain.upperBound;
29 | return (x - self.fromDomain.lowerBound) / b
30 | }
31 |
32 | func rescale(_ x: Type ) -> Type {
33 | return interpolate( uninterpolate(x) )
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Sources/DSKit/Helpers/URLOpener.swift:
--------------------------------------------------------------------------------
1 | //
2 | // URLOpener.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 9/23/20.
6 | // Copyright © 2020 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | class URLOpener {
13 |
14 | typealias CompletionType = ((Bool) -> Swift.Void)
15 | typealias OptionsType = [UIApplication.OpenExternalURLOptionsKey: Any]
16 |
17 | static func open(_ url: URL, options: OptionsType, completion: CompletionType?) {
18 | if #available(iOS 10, *) {
19 | UIApplication.shared.open(url, options: options, completionHandler: completion)
20 | } else {
21 | UIApplication.shared.openURL(url)
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/DSKit/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Sources/DSKit/Images.xcassets/mapPlaceholder.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "mapPlaceholder.pdf",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "template"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/DSKit/Images.xcassets/mapPlaceholder.imageset/mapPlaceholder.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/Sources/DSKit/Images.xcassets/mapPlaceholder.imageset/mapPlaceholder.pdf
--------------------------------------------------------------------------------
/Sources/DSKit/Images.xcassets/placeholder.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "placeholder.pdf",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "template-rendering-intent" : "template"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/DSKit/Images.xcassets/placeholder.imageset/placeholder.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/Sources/DSKit/Images.xcassets/placeholder.imageset/placeholder.pdf
--------------------------------------------------------------------------------
/Sources/DSKit/Sections/DSDiffableSection.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSDiffableSection.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 02.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | enum DSDiffableSection: Hashable {
12 | case section(id: Int)
13 | }
14 |
--------------------------------------------------------------------------------
/Sources/DSKit/Sections/DSGallerySection.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSGallerySection.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 10.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /// Extension from DSSection
12 | public final class DSGallerySection: DSSection {
13 |
14 | /// Gallery type
15 | public var galleryType: DSSectionGalleryType
16 |
17 | /// Init Gallery section
18 | /// - Parameters:
19 | /// - viewModels: View models to display in section
20 | /// - type: DSSectionGalleryType
21 | public init(viewModels: [DSViewModel], type: DSSectionGalleryType = .default) {
22 |
23 | self.galleryType = type
24 | super.init()
25 | let appearance = DSAppearance.shared.main
26 | self.viewModels = viewModels
27 | self.type = .gallery(type: type)
28 |
29 | self.insets = UIEdgeInsets(top: appearance.margins,
30 | left: appearance.margins,
31 | bottom: 0,
32 | right: appearance.margins)
33 |
34 | self.interItemSpacing = appearance.interItemSpacing
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Sources/DSKit/Sections/DSGridSection.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSGridSection.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 10.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public final class DSGridSection: DSSection {
12 |
13 | /// Grid section
14 | /// - Parameters:
15 | /// - viewModels: View models to display
16 | /// - columns: Number of columns
17 | public init(viewModels: [DSViewModel], columns: Int = 2) {
18 |
19 | super.init()
20 | self.viewModels = viewModels
21 |
22 | let appearance = DSAppearance.shared.main
23 |
24 | insets = UIEdgeInsets(top: appearance.margins,
25 | left: appearance.margins,
26 | bottom: 0,
27 | right: appearance.margins)
28 |
29 | type = .grid(columns: columns)
30 | interItemSpacing = appearance.interItemSpacing
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Sources/DSKit/Sections/DSSection+Count.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSSection+Count.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 04.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public extension Array where Element == DSSection {
12 |
13 | var totalViewModelsCount: Int {
14 | return reduce(into: 0) { (count, section) in
15 | count += section.viewModels.count
16 | }
17 | }
18 |
19 | var totalTextFieldViewModelsCount: Int {
20 | return reduce(into: 0) { (count, section) in
21 | count += section.viewModels.reduce(into: 0, { (textFieldsCount, viewModel) in
22 | if viewModel is DSTextFieldVM {
23 | textFieldsCount += 1
24 | }
25 | })
26 | }
27 | }
28 | }
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Sources/DSKit/Sections/DSSection+Footer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSSection+Insets.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 03.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | public extension DSSection {
13 |
14 | /// Headline header with text
15 | /// - Parameter text: String
16 | /// - Returns: Self
17 | @discardableResult func headlineFooter(_ text: String) -> Self {
18 | self.footer = DSLabelVM(.headline, text: text)
19 | return self
20 | }
21 |
22 | /// Subheadline header with text
23 | /// - Parameter text: String
24 | /// - Returns: Self
25 | @discardableResult func subheadlineFooter(_ text: String) -> Self {
26 | self.footer = DSLabelVM(.subheadline, text: text)
27 | return self
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/DSKit/Sections/DSSection+Hash.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSSection+Count.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 04.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension DSSection {
12 |
13 | // Get diffable hash combined with
14 | // header and footer
15 | var diffableHash: Int {
16 |
17 | var hasher = Hasher()
18 |
19 | if let headerHash = self.headerModelHash {
20 | hasher.combine(headerHash)
21 | }
22 |
23 | if let footerHash = self.footerModelHash {
24 | hasher.combine(footerHash)
25 | }
26 |
27 | hasher.combine(self.type.hashValue)
28 |
29 | return hasher.finalize()
30 | }
31 |
32 | // Get footer hash if exists
33 | var footerModelHash: Int? {
34 |
35 | if let model = footer {
36 | var hasher = Hasher()
37 | hasher.combine(model.hash())
38 | return hasher.finalize()
39 | }
40 |
41 | return nil
42 | }
43 |
44 | /// Get header hash if exists
45 | var headerModelHash: Int? {
46 |
47 | if let model = header {
48 | var hasher = Hasher()
49 | hasher.combine(model.hash())
50 | return hasher.finalize()
51 | }
52 |
53 | return nil
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Sources/DSKit/Sections/DSSectionBackgroundColorPrimaryDecorationView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSSectionBackgroundColorPrimaryDecorationView.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 01.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Combine
11 |
12 | /// Section Background Decoration View
13 | class DSSectionBackgroundColorPrimaryDecorationView: UICollectionReusableView, Subscriber {
14 |
15 | typealias Input = DSDesignable
16 | typealias Failure = Never
17 |
18 | public func receive(subscription: Subscription) {
19 | subscription.request(.unlimited)
20 | }
21 |
22 | public func receive(_ input: Input) -> Subscribers.Demand {
23 | configure()
24 | return .none
25 | }
26 |
27 | public func receive(completion: Subscribers.Completion) {
28 | print("Received completion: \(completion)")
29 | }
30 |
31 | override init(frame: CGRect) {
32 | super.init(frame: frame)
33 | DSAppearance.shared.appearancePublisher.subscribe(self)
34 | configure()
35 | }
36 | required init?(coder: NSCoder) {
37 | fatalError("not implemented")
38 | }
39 | }
40 |
41 | extension DSSectionBackgroundColorPrimaryDecorationView {
42 |
43 | func configure() {
44 | let appearance = DSAppearance.shared.main
45 | backgroundColor = appearance.primaryView.background
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Sources/DSKit/Sections/DSSectionBackgroundColorSecondaryDecorationView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSSectionBackgroundColorSecondaryDecorationView.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 01.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Combine
11 |
12 | /// Section Background Decoration View
13 | class DSSectionBackgroundColorSecondaryDecorationView: UICollectionReusableView, Subscriber {
14 |
15 | typealias Input = DSDesignable
16 | typealias Failure = Never
17 |
18 | public func receive(subscription: Subscription) {
19 | subscription.request(.unlimited)
20 | }
21 |
22 | public func receive(_ input: Input) -> Subscribers.Demand {
23 | configure()
24 | return .none
25 | }
26 |
27 | public func receive(completion: Subscribers.Completion) {
28 | print("Received completion: \(completion)")
29 | }
30 |
31 | override init(frame: CGRect) {
32 | super.init(frame: frame)
33 | DSAppearance.shared.appearancePublisher.subscribe(self)
34 | configure()
35 | }
36 | required init?(coder: NSCoder) {
37 | fatalError("not implemented")
38 | }
39 | }
40 |
41 | extension DSSectionBackgroundColorSecondaryDecorationView {
42 |
43 | func configure() {
44 | let appearance = DSAppearance.shared.main
45 | backgroundColor = appearance.secondaryView.background
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Sources/DSKit/Sections/DSSectionBackgroundDecorationView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSSectionBackgroundDecorationView.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 01.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Combine
11 |
12 | /// Section Background Decoration View
13 | class DSSectionBackgroundDecorationView: UICollectionReusableView, Subscriber {
14 |
15 | typealias Input = DSDesignable
16 | typealias Failure = Never
17 |
18 | public func receive(subscription: Subscription) {
19 | subscription.request(.unlimited)
20 | }
21 |
22 | public func receive(_ input: Input) -> Subscribers.Demand {
23 | configure()
24 | return .none
25 | }
26 |
27 | public func receive(completion: Subscribers.Completion) {
28 | print("Received completion: \(completion)")
29 | }
30 |
31 | override init(frame: CGRect) {
32 | super.init(frame: frame)
33 | DSAppearance.shared.appearancePublisher.subscribe(self)
34 | configure()
35 | }
36 | required init?(coder: NSCoder) {
37 | fatalError("not implemented")
38 | }
39 | }
40 |
41 | extension DSSectionBackgroundDecorationView {
42 |
43 | func configure() {
44 | let appearance = DSAppearance.shared.main
45 | backgroundColor = appearance.secondaryView.background
46 | layer.cornerRadius = appearance.secondaryView.cornerRadius
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Sources/DSKit/Sections/DSSectionBackgroundType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSSectionBackgroundType.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 01.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /// Section background type
12 | public enum DSSectionBackgroundType {
13 | case `default`
14 | case grouped
15 | case primaryBackground
16 | case secondaryBackground
17 | }
18 |
19 | /// Is section background grouped
20 | extension DSSectionBackgroundType {
21 | var isGrouped: Bool {
22 | self == .grouped
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/DSKit/Sections/DSSectionGalleryType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSSectionGalleryType.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 30.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /// Gallery section type
12 | public enum DSSectionGalleryType: Equatable, Hashable {
13 | case `default`
14 | case fullWidth
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/DSKit/Sections/DSSectionType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSSectionType.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 30.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /// Section type
12 | public enum DSSectionType: Equatable, Hashable {
13 | case list
14 | case gallery(type: DSSectionGalleryType)
15 | case grid(columns: Int = 2)
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewControllers/DSViewController/DSViewController+Forms.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSViewController+Forms.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 02.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | public extension DSViewController {
10 | func isCurrentFormValid(_ validate: @escaping (Bool) -> Void) {
11 | collectionView.isCurrentFormValid(validate)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewControllers/DSViewController/DSViewController+Placeholder.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSViewController+Placeholder.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 02.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension DSViewController {
12 |
13 | /// Get placeholder section
14 | /// - Parameters:
15 | /// - image: UIImage
16 | /// - text: String
17 | /// - Returns: DSSection
18 | public func getPlaceholderSection(image: UIImage?, text: String) -> DSSection {
19 |
20 | var viewModels = [DSViewModel]()
21 |
22 | let space = DSSpaceVM(type: .custom(UIScreen.main.bounds.height / 7))
23 | viewModels.append(space)
24 |
25 | if let image = image {
26 | var imageView = DSImageVM(imageValue: .image(image: image), height: .absolute(70))
27 | imageView.contentMode = .scaleAspectFit
28 | imageView.imageDisplayStyle = .default
29 | viewModels.append(imageView)
30 | }
31 |
32 | let text = DSLabelVM(.subheadline, text: text, alignment: .center)
33 | viewModels.append(text)
34 |
35 | return viewModels.list()
36 | }
37 |
38 | /// Show placeholder
39 | /// - Parameters:
40 | /// - image: UIImage?
41 | /// - text: String
42 | public func showPlaceholder(image: UIImage? = nil, text: String) {
43 | self.show(content: getPlaceholderSection(image: image, text: text))
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModelProtocol/DSPageControlable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSPageControlable.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 21.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public protocol DSPageControlable {
12 | var updatePage: ((Int) -> Void)? {get set}
13 | }
14 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModelProtocol/DSReusableUIView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSReusableUIView.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 11.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | // Protocol that describes how `DSReusableUIView` should behave
12 | public protocol DSReusableUIView {
13 |
14 | /// This method is called each time a view model will display on screen
15 | /// - Parameter viewModel: DSViewModel
16 | func setUpWith(viewModel: DSViewModel)
17 |
18 | /// This view will be reused each time a view model will display on screen
19 | /// and will be updated with data using `setUpWith(viewModel: DSViewModel)` function
20 | var view: UIView {get}
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModelProtocol/DSSideView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSSupplementaryView.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 10.03.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | public struct DSSideView: Equatable, Hashable {
13 |
14 | var viewModel: DSViewModel
15 |
16 | public init(view: DSViewModel) {
17 | self.viewModel = view
18 | }
19 |
20 | public static func == (lhs: DSSideView, rhs: DSSideView) -> Bool {
21 | return lhs.viewModel.isEqual(to: rhs.viewModel)
22 | }
23 |
24 | public func hash(into hasher: inout Hasher) {
25 | hasher.combine(viewModel.hash())
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModelProtocol/DSViewModelBorderStyle.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSViewModelBorderStyle.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 21.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /// View model display style
12 | public enum DSViewModelBorderStyle: Equatable, Hashable {
13 |
14 | case none
15 | case buttonColor
16 | case brandColor
17 | case custom(width: CGFloat, color: UIColor)
18 |
19 | /// Raw value
20 | var rawValue: String {
21 |
22 | switch self {
23 | case .none:
24 | return "none"
25 | case .buttonColor:
26 | return "buttonColor"
27 | case .brandColor:
28 | return "brandColor"
29 | case .custom(let width, let color):
30 | return "\(width)\(color.dsDescription)"
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModelProtocol/DSViewModelColorStyle.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSViewModelColorStyle.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 21.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /// View model display style
12 | public enum DSViewModelColorStyle: Equatable, Hashable {
13 |
14 | case `default`
15 | case primary
16 | case secondary
17 | case custom(DSDesignableViewColors)
18 |
19 | /// Raw value
20 | var rawValue: String {
21 | switch self {
22 | case .primary:
23 | return "primary"
24 | case .secondary:
25 | return "secondary"
26 | case .custom(_):
27 | return "custom"
28 | case .default:
29 | return "default"
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModelProtocol/DSViewModelCornersStyle.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSViewModelCornersStyle.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 21.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /// View model corner style
12 | public enum DSViewModelCornersStyle: Equatable, Hashable {
13 |
14 | case `default`
15 | case zero
16 | case custom(CGFloat)
17 |
18 | /// Raw value
19 | var rawValue: String {
20 | switch self {
21 | case .zero:
22 | return "zero"
23 | case .default:
24 | return "default"
25 | case .custom(let cornerRadius):
26 | return "custom_\(cornerRadius)"
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModelProtocol/DSViewModelDataSource.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSViewModelDataSource.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 02.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /// Used to generate UICollectionViewDiffableDataSource
12 | struct DSViewModelDataSource: Hashable, Equatable {
13 |
14 | func hash(into hasher: inout Hasher) {
15 | hasher.combine(model.hash())
16 | }
17 |
18 | static func == (lhs: DSViewModelDataSource, rhs: DSViewModelDataSource) -> Bool {
19 | lhs.model.isEqual(to: rhs.model)
20 | }
21 |
22 | let model: DSViewModel
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModelProtocol/DSViewModelDisplayStyle.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSViewModelDisplayStyle.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 21.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /// View model display style
12 | public enum DSViewModelDisplayStyle: Equatable, Hashable {
13 |
14 | case `default` //Edge to edge with no margins
15 | case grouped(inSection: Bool) // DSDesignable groupMargins will be applied to each side in dependence in which context this view model is shown
16 |
17 | /// Raw value
18 | var rawValue: String {
19 | switch self {
20 | case .default:
21 | return "Default"
22 | case .grouped(inSection: let inSection):
23 | if inSection {
24 | return "SectionGrouped"
25 | } else {
26 | return "Grouped"
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModelProtocol/DSViewModelShadowStyle.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSViewModelShadowStyle.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 21.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /// View model display style
12 | public enum DSViewModelShadowStyle: Equatable, Hashable {
13 |
14 | case none
15 | case small
16 | case light
17 |
18 | /// Raw value
19 | var rawValue: String {
20 |
21 | switch self {
22 | case .none:
23 | return "none"
24 | case .small:
25 | return "small"
26 | case .light:
27 | return "light"
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModelProtocol/DSViewModelStyle.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSViewModelStyle.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 21.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /// View model display style
12 | public struct DSViewModelStyle: Equatable, Hashable {
13 |
14 | public var colorStyle: DSViewModelColorStyle = .default
15 | public var cornerStyle: DSViewModelCornersStyle = .default
16 | public var borderStyle: DSViewModelBorderStyle = .none
17 | public var shadowStyle: DSViewModelShadowStyle = .none
18 | public var displayStyle: DSViewModelDisplayStyle = .default
19 |
20 | public init(colorStyle: DSViewModelColorStyle = .default,
21 | cornerStyle: DSViewModelCornersStyle = .default,
22 | borderStyle: DSViewModelBorderStyle = .none,
23 | shadowStyle: DSViewModelShadowStyle = .none,
24 | displayStyle: DSViewModelDisplayStyle = .default) {
25 |
26 | self.colorStyle = colorStyle
27 | self.cornerStyle = cornerStyle
28 | self.borderStyle = borderStyle
29 | self.shadowStyle = shadowStyle
30 | self.displayStyle = displayStyle
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModelProtocol/DefaultReusableUIViewView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DefaultReusableUIViewView.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 02.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public class DefaultReusableUIViewView: UIView, DSReusableUIView {
12 |
13 | public var view: UIView {
14 | self
15 | }
16 |
17 | public func setUpWith(viewModel: DSViewModel) {
18 | print("Please implement getUIViewRepresentation() protocol method for \(viewModel)")
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModelProtocol/Extensions/DSViewModel+PrepareToDisplay.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSViewModel+SideViews.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 16.03.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension DSViewModel {
12 |
13 | mutating func prepareToDisplay() {
14 |
15 | if var vm = self.rightSideView?.viewModel {
16 | vm.style.displayStyle = self.style.displayStyle
17 | self.rightSideView = DSSideView(view: vm)
18 | }
19 |
20 | if var vm = self.leftSideView?.viewModel {
21 | vm.style.displayStyle = self.style.displayStyle
22 | self.leftSideView = DSSideView(view: vm)
23 | }
24 |
25 | if var vm = self.topSideView?.viewModel {
26 | vm.style.displayStyle = self.style.displayStyle
27 | self.topSideView = DSSideView(view: vm)
28 | }
29 |
30 | if var vm = self.bottomSideView?.viewModel {
31 | vm.style.displayStyle = self.style.displayStyle
32 | self.bottomSideView = DSSideView(view: vm)
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModelProtocol/Extensions/DSViewModel+isEqual.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSViewModel+isEqual.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 27.01.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public extension DSViewModel {
12 |
13 | /// Check if view model is equal to other view model
14 | /// - Parameter object: DSViewModel
15 | /// - Returns: Bool
16 | func isEqual(to object: DSViewModel) -> Bool {
17 | return false
18 | }
19 | }
20 |
21 | public extension Array where Element == DSViewModel {
22 |
23 | /// Check if array of view model are equal to other array of view models
24 | /// - Parameter array: [DSViewModel]
25 | /// - Returns: Bool
26 | func isEqual(to array: [DSViewModel]) -> Bool {
27 |
28 | if self.count != array.count {
29 | return false
30 | }
31 |
32 | for (index, element) in self.enumerated() {
33 | let compareTo = array[index]
34 | if !element.isEqual(to: compareTo) {
35 | return false
36 | }
37 | }
38 |
39 | return true
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModelProtocol/Extensions/DSViewModelDisplayStyle+UIEdgeInsets.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSViewModelDisplayStyle+UIEdgeInsets.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 02.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension DSViewModelDisplayStyle {
12 |
13 | /// Get view insets based on DSViewModelDisplayStyle
14 | /// - Returns: UIEdgeInsets
15 | func viewInsets() -> UIEdgeInsets {
16 |
17 | switch self {
18 | case .default:
19 | return .zero
20 | case .grouped(inSection: let inSection):
21 |
22 | if inSection {
23 | return .zero
24 | } else {
25 | return DSAppearance.shared.main.groupMargins.edgeInsets
26 | }
27 | }
28 | }
29 |
30 | /// Get view insets when this view model is displayed as supplementary view
31 | /// - Parameters:
32 | /// - section: DSSection
33 | /// - kind: String, supplementary view kind
34 | /// - Returns: UIEdgeInsets
35 | func supplementaryViewInsets(section: DSSection, kind: String) -> UIEdgeInsets {
36 |
37 | if kind == UICollectionView.elementKindSectionHeader {
38 | return UIEdgeInsets(top: DSAppearance.shared.main.margins, left: 0, bottom: -5, right: 0)
39 | } else if kind == UICollectionView.elementKindSectionFooter {
40 | return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
41 | }
42 |
43 | return .zero
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModels/Action/DSActionVM+TopContent.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSActionVM+LeftContent.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 03.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public extension DSActionVM {
12 |
13 | /// Set action top image with UIImage
14 | /// - Parameters:
15 | /// - image: UIImage
16 | /// - height: DSImageHeight
17 | /// - contentMode: DSImageContentMode
18 | mutating func topImage(image: UIImage?,
19 | height: DSImageHeight = .unknown,
20 | contentMode: DSImageContentMode = .scaleAspectFill) {
21 |
22 | self.topImage = DSImageContent.image(image: image)
23 | self.topImageContentMode = contentMode
24 | self.topImageHeight = height
25 | }
26 |
27 | /// Set action top image with URL?
28 | /// - Parameters:
29 | /// - url: URL?
30 | /// - height: DSImageHeight
31 | /// - contentMode: DSImageContentMode
32 | mutating func topImage(url: URL?,
33 | height: DSImageHeight = .unknown,
34 | contentMode: DSImageContentMode = .scaleAspectFill) {
35 |
36 | self.topImage = DSImageContent.imageURL(url: url)
37 | self.topImageContentMode = contentMode
38 | self.topImageHeight = height
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModels/ActiveText/DSActiveTextUIView.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModels/Button/DSButtonUIView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSButtonUIView.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 11.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | final class DSButtonUIView: UIView, DSReusableUIView {
12 |
13 | @IBOutlet weak var button: ImoUIButton!
14 |
15 | var viewModel: DSButtonVM?
16 |
17 | public var view: UIView { self }
18 |
19 | public func setUpWith(viewModel: DSViewModel) {
20 |
21 | guard let viewModel = viewModel as? DSButtonVM else {
22 | return
23 | }
24 |
25 | self.viewModel = viewModel
26 | update(viewModel: viewModel)
27 | }
28 |
29 | /// This method is called each time a copy of DSButtonUIView is prepared to be displayed on screen
30 | /// - Parameter viewModel: DSButtonVM
31 | func update(viewModel: DSButtonVM) {
32 |
33 | button.setUpWith(viewModel: viewModel)
34 |
35 | /// Handle did tap on button
36 | button.button.didTouchUpInside = { [weak self] _ in
37 |
38 | guard let _self = self else {
39 | return
40 | }
41 |
42 | _self.viewModel?.didTap?(viewModel)
43 | }
44 | }
45 |
46 | override func awakeFromNib() {
47 | super.awakeFromNib()
48 | backgroundColor = .clear
49 | button.backgroundColor = .clear
50 | }
51 |
52 | class func instanceFromNib() -> DSButtonUIView {
53 | let view: DSButtonUIView = initFromNib()
54 | return view
55 | }
56 | }
57 |
58 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModels/Color/DSColorUIView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSColorUIView.swift
3 | // DSKit Explorer
4 | //
5 | // Created by Borinschi Ivan on 18.03.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | final class DSColorUIView: UIView, DSReusableUIView {
12 |
13 | @IBOutlet weak var colorView: UIView!
14 |
15 | /// DSReusableUIView protocol
16 | public var view: UIView { self }
17 |
18 | /// Set up with view model is called each time when a copy of
19 | /// this uiview is prepared to be displayed on the screen
20 | /// - Parameter viewModel: DSViewModel
21 | public func setUpWith(viewModel: DSViewModel) {
22 |
23 | guard let viewModel = viewModel as? DSColorVM else { return }
24 | update(viewModel: viewModel)
25 | }
26 |
27 | /// Update view with view model
28 | /// - Parameter viewModel: DSColorVM
29 | func update(viewModel: DSColorVM) {
30 | colorView.backgroundColor = viewModel.color
31 | colorView.layer.cornerRadius = viewModel.viewColors().cornerRadius
32 | colorView.clipsToBounds = true
33 | colorView.layer.borderWidth = 1.5
34 | colorView.layer.borderColor = DSAppearance.shared.main.secondaryView.background.cgColor
35 | }
36 |
37 | override func awakeFromNib() {
38 | super.awakeFromNib()
39 | backgroundColor = .clear
40 | }
41 |
42 | class func instanceFromNib() -> DSColorUIView {
43 | let view: DSColorUIView = initFromNib()
44 | return view
45 | }
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModels/Label/DSLabelUIView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSLabelUIView.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 15.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | final class DSLabelUIView: UIView, DSReusableUIView {
12 |
13 | @IBOutlet weak var textLabel: UILabel!
14 | var appearance = DSAppearance.shared.main
15 | var fonts = DSAppearance.shared.main.fonts
16 |
17 | public var view: UIView { self }
18 |
19 | public func setUpWith(viewModel: DSViewModel) {
20 |
21 | guard let viewModel = viewModel as? DSLabelVM else {
22 | return
23 | }
24 |
25 | update(viewModel: viewModel)
26 | }
27 |
28 | func update(viewModel: DSLabelVM) {
29 | textLabel.set(text: viewModel.textComposer, designableTextColor: viewModel.viewColors().text)
30 | }
31 |
32 | override func awakeFromNib() {
33 | super.awakeFromNib()
34 | backgroundColor = .clear
35 | }
36 |
37 | class func instanceFromNib() -> DSLabelUIView {
38 | let view: DSLabelUIView = initFromNib()
39 | return view
40 | }
41 | }
42 |
43 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModels/Page/DSPageUIView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSWalkthroughPageUIView.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 27.01.2021.
6 | //
7 | //
8 |
9 | import UIKit
10 |
11 | final class DSPageUIView: UIView, DSReusableUIView {
12 |
13 | @IBOutlet weak var collectionView: DSCollectionView!
14 | var appearance = DSAppearance.shared.main
15 |
16 | public var view: UIView { self }
17 |
18 | public func setUpWith(viewModel: DSViewModel) {
19 |
20 | guard let viewModel = viewModel as? DSPageVM else { return }
21 | update(viewModel: viewModel)
22 | }
23 |
24 | func update(viewModel: DSPageVM) {
25 |
26 | let section = viewModel.viewModels.list()
27 | section.insets = viewModel.contentInsets
28 | collectionView.show(content: [section], animated: false)
29 | collectionView.backgroundColor = viewModel.viewColors().background
30 | collectionView.view.backgroundColor = viewModel.viewColors().background
31 | collectionView.view.backgroundColor = .clear
32 | collectionView.view.bounces = false
33 | }
34 |
35 | override func awakeFromNib() {
36 | super.awakeFromNib()
37 | backgroundColor = .clear
38 | }
39 |
40 | class func instanceFromNib() -> DSPageUIView {
41 | let view: DSPageUIView = initFromNib()
42 | return view
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModels/Separator/DSSeparatorUIView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSSeparatorUIView.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 18.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | final class DSSeparatorUIView: UIView, DSReusableUIView {
12 |
13 | @IBOutlet weak var separatorView: UIView!
14 | @IBOutlet weak var leftSpace: NSLayoutConstraint!
15 | @IBOutlet weak var rightSpace: NSLayoutConstraint!
16 | public var view: UIView { self }
17 |
18 | let appearance = DSAppearance.shared.main
19 |
20 | public func setUpWith(viewModel: DSViewModel) {
21 | guard let viewModel = viewModel as? DSSeparatorVM else { return }
22 | update(viewModel: viewModel)
23 | }
24 |
25 | func update(viewModel: DSSeparatorVM) {
26 |
27 | backgroundColor = .clear
28 | separatorView.backgroundColor = viewModel.viewColors().separator
29 | leftSpace.constant = 0
30 | rightSpace.constant = 0
31 | }
32 |
33 | class func instanceFromNib() -> DSSeparatorUIView {
34 | let view: DSSeparatorUIView = initFromNib()
35 | return view
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModels/Space/DSSpaceUIView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSSpaceUIView.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 18.12.2020.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | final class DSSpaceUIView: UIView, DSReusableUIView {
12 |
13 | public var view: UIView { self }
14 | @IBOutlet weak var spaceView: UIView!
15 |
16 | public func setUpWith(viewModel: DSViewModel) {
17 | guard let viewModel = viewModel as? DSSpaceVM else { return }
18 | update(viewModel: viewModel)
19 | }
20 |
21 | func update(viewModel: DSSpaceVM) {
22 | spaceView.backgroundColor = .clear
23 | }
24 |
25 | class func instanceFromNib() -> DSSpaceUIView {
26 | let view: DSSpaceUIView = initFromNib()
27 | return view
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModels/Switch/DSSwitchUIView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSSwitchUIView.swift
3 | // DSKit Explorer
4 | //
5 | // Created by Borinschi Ivan on 19.03.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | final class DSSwitchUIView: UIView, DSReusableUIView {
12 |
13 | @IBOutlet weak var switchView: UISwitch!
14 | /// DSReusableUIView protocol
15 | public var view: UIView { self }
16 |
17 | var viewModel: DSSwitchVM?
18 |
19 | /// Set up with view model is called each time when a copy of
20 | /// this uiview is prepared to be displayed on the screen
21 | /// - Parameter viewModel: DSViewModel
22 | public func setUpWith(viewModel: DSViewModel) {
23 |
24 | guard let viewModel = viewModel as? DSSwitchVM else { return }
25 | self.viewModel = viewModel
26 | update(viewModel: viewModel)
27 | }
28 |
29 | /// Update view with view model
30 | /// - Parameter viewModel: DSSwitchVM
31 | func update(viewModel: DSSwitchVM) {
32 | switchView.isOn = viewModel.isOn
33 | switchView.onTintColor = DSAppearance.shared.main.semanticGreenColor
34 | }
35 |
36 | override func awakeFromNib() {
37 | super.awakeFromNib()
38 | backgroundColor = .clear
39 | }
40 |
41 | @IBAction func didUpdate(_ sender: Any) {
42 |
43 | guard let viewModel = self.viewModel else {
44 | return
45 | }
46 |
47 | viewModel.didUpdate?(self.switchView.isOn)
48 | }
49 |
50 | class func instanceFromNib() -> DSSwitchUIView {
51 | let view: DSSwitchUIView = initFromNib()
52 | return view
53 | }
54 | }
55 |
56 |
--------------------------------------------------------------------------------
/Sources/DSKit/ViewModels/TextField/DSTextFieldVM+Validations.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DSTextFieldVM+Validations.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 04.02.2021.
6 | // Copyright © 2021 Borinschi Ivan. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public extension DSTextFieldVM {
12 |
13 | /// Is text valid
14 | /// - Parameters:
15 | /// - text: Text to validate
16 | /// - validateEmptyTextField: Should result be valid is textfield is empty
17 | /// - validate: validation result closure
18 | func isValid(text: String?, validateEmptyTextField: Bool,_ validate: @escaping (Bool) -> Void) {
19 |
20 | // We will use user defined validation
21 | if let userValidation = self.handleValidation {
22 |
23 | // Send current value to user validation
24 | validate(userValidation(text))
25 |
26 | } else {
27 |
28 | // If text is empty and validateEmptyTextField == true
29 | // then validate true
30 | if text == "" && validateEmptyTextField {
31 | validate(true)
32 |
33 | } else if validator.isValidMinimLength(validateMinimumLength, text) &&
34 | validator.isValidMaximLength(validateMaximumLength, text) &&
35 | validator.validate(string: text, pattern: validationPattern) &&
36 | validator.isValidWhiteSpaces(string: text) {
37 |
38 | validate(true)
39 |
40 | } else {
41 | validate(false)
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Sources/DSKitCalendar/DSDayLabel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HCDayLabel.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 23.12.2020.
6 | //
7 |
8 | import UIKit
9 | import HorizonCalendar
10 | import DSKit
11 |
12 | struct DSDayLabel: CalendarItemViewRepresentable {
13 |
14 | /// Properties that are set once when we initialize the view.
15 | struct InvariantViewProperties: Hashable {
16 | let font: UIFont
17 | var textColor: UIColor
18 | var backgroundColor: UIColor
19 | var alpha: CGFloat
20 | }
21 |
22 | /// Properties that will vary depending on the particular date being displayed.
23 | struct ViewModel: Equatable {
24 | let day: Day
25 | }
26 |
27 | static func makeView(withInvariantViewProperties invariantViewProperties: InvariantViewProperties) -> UILabel {
28 |
29 | let label = UILabel()
30 |
31 | label.backgroundColor = invariantViewProperties.backgroundColor
32 | label.font = invariantViewProperties.font
33 | label.textColor = invariantViewProperties.textColor
34 |
35 | label.textAlignment = .center
36 | label.clipsToBounds = true
37 | label.layer.cornerRadius = DSAppearance.shared.main.secondaryView.cornerRadius
38 | label.alpha = invariantViewProperties.alpha
39 |
40 | return label
41 | }
42 |
43 | static func setViewModel(_ viewModel: ViewModel, on view: UILabel) {
44 | view.text = "\(viewModel.day.day)"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Sources/DSKitCalendar/DSDayOfWeekLabel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HCDayLabel.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 23.12.2020.
6 | //
7 |
8 | import UIKit
9 | import HorizonCalendar
10 |
11 | struct DSDayOfWeekLabel: CalendarItemViewRepresentable {
12 |
13 | /// Properties that are set once when we initialize the view.
14 | struct InvariantViewProperties: Hashable {
15 | let font: UIFont
16 | var textColor: UIColor
17 | }
18 |
19 | /// Properties that will vary depending on the particular date being displayed.
20 | struct ViewModel: Equatable {
21 | let month: Month?
22 | let day: Int
23 | }
24 |
25 | static func makeView(withInvariantViewProperties invariantViewProperties: InvariantViewProperties) -> UILabel {
26 |
27 | let label = UILabel()
28 | label.font = invariantViewProperties.font
29 | label.textColor = invariantViewProperties.textColor
30 |
31 | label.textAlignment = .center
32 | label.clipsToBounds = true
33 |
34 | return label
35 | }
36 |
37 | static func setViewModel(_ viewModel: ViewModel, on view: UILabel) {
38 |
39 | guard var components = viewModel.month?.components else {
40 | return
41 | }
42 |
43 | components.day = viewModel.day
44 |
45 | let date = Calendar.current.date(from: components)
46 |
47 | guard let text = date?.stringFormattedWeekDay(dateStyle: .short) else {
48 | return
49 | }
50 |
51 | view.text = text
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Sources/DSKitCalendar/DSMonthLabel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HCDayLabel.swift
3 | // DSKit
4 | //
5 | // Created by Borinschi Ivan on 23.12.2020.
6 | //
7 |
8 | import HorizonCalendar
9 | import UIKit
10 |
11 | struct DSMonthLabel: CalendarItemViewRepresentable {
12 |
13 | /// Properties that are set once when we initialize the view.
14 | struct InvariantViewProperties: Hashable {
15 | let font: UIFont
16 | var textColor: UIColor
17 | }
18 |
19 | /// Properties that will vary depending on the particular date being displayed.
20 | struct ViewModel: Equatable {
21 | let month: Month
22 | }
23 |
24 | static func makeView(withInvariantViewProperties invariantViewProperties: InvariantViewProperties) -> UILabel {
25 |
26 | let label = UILabel()
27 | label.font = invariantViewProperties.font
28 | label.textColor = invariantViewProperties.textColor
29 |
30 | label.textAlignment = .left
31 | label.clipsToBounds = true
32 |
33 | return label
34 | }
35 |
36 | static func setViewModel(_ viewModel: ViewModel, on view: UILabel) {
37 |
38 | let date = Calendar.current.date(from: viewModel.month.components)
39 |
40 | guard let text = date?.stringFormattedMonth() else {
41 | return
42 | }
43 |
44 | view.text = text
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Sources/DSKitFakery/Models/DSAddress.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FakeAddress.swift
3 | // DSKit+Fakery
4 | //
5 | // Created by Borinschi Ivan on 27.01.2021.
6 | //
7 |
8 | import Foundation
9 | import MapKit
10 |
11 | public struct DSAddress {
12 |
13 | public let address: String
14 | public let coordinate: CLLocationCoordinate2D
15 | public var title: String {
16 | self.address.components(separatedBy: ",").first ?? address
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Sources/DSKitFakery/Models/DSPerson.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Person.swift
3 | // DSKit+Fakery
4 | //
5 | // Created by Borinschi Ivan on 27.01.2021.
6 | //
7 |
8 | import Foundation
9 |
10 | public struct DSPerson {
11 | public let name: String
12 | public let description: String
13 | public var image: URL?
14 | public var email: String
15 | public var phone: String
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/DSKitFakery/URL+AdditionalProducts.swift:
--------------------------------------------------------------------------------
1 | //
2 | // URL+Flowers.swift
3 | // DSKit+Fakery
4 | //
5 | // Created by Borinschi Ivan on 27.01.2021.
6 | //
7 |
8 | import Foundation
9 |
10 | public extension URL {
11 |
12 | static let balloons = URL(string: "https://images.unsplash.com/photo-1554719805-92eb757a4ca4?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=934&q=80")
13 |
14 | static let bunny = URL(string: "https://images.unsplash.com/photo-1562224780-ba39856ecadd?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1952&q=80")
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/DSKitFakery/URL+Cards.swift:
--------------------------------------------------------------------------------
1 | //
2 | // URL+Flowers.swift
3 | // DSKit+Fakery
4 | //
5 | // Created by Borinschi Ivan on 27.01.2021.
6 | //
7 |
8 | import Foundation
9 |
10 | public extension URL {
11 |
12 | static let standardCard = URL(string: "https://images.unsplash.com/photo-1566125882500-87e10f726cdc?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1867&q=80")
13 |
14 | static let cardLoveIt = URL(string: "https://images.unsplash.com/photo-1579532649051-ed5208863cd9?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=934&q=80")
15 |
16 | static let cardForYou = URL(string: "https://images.unsplash.com/photo-1535381273077-21e00c27b1b7?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=1867&q=80")
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/DSKitFakery/URL+Echeveria.swift:
--------------------------------------------------------------------------------
1 | //
2 | // URL+Echeveria.swift
3 | // DSKit+Fakery
4 | //
5 | // Created by Borinschi Ivan on 27.01.2021.
6 | //
7 |
8 | import Foundation
9 |
10 | public extension URL {
11 |
12 | static let echeveriaPink = URL(string: "https://images.unsplash.com/photo-1587788793142-fe98e1521131?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=975&q=80")
13 |
14 | static let echeveriaGreen = URL(string: "https://images.unsplash.com/photo-1562536404-7664b90d738e?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=1951&q=80")
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/DSKitFakery/URL+Flowers.swift:
--------------------------------------------------------------------------------
1 | //
2 | // URL+Flowers.swift
3 | // DSKit+Fakery
4 | //
5 | // Created by Borinschi Ivan on 27.01.2021.
6 | //
7 |
8 | import Foundation
9 |
10 | public extension URL {
11 |
12 | static let flowersBirthday = URL(string: "https://images.unsplash.com/photo-1607215121535-c52a7957bb18?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=934&q=80")
13 |
14 | static let flowersValentines = URL(string: "https://images.unsplash.com/photo-1557872048-d2c03143cabc?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=934&q=80")
15 |
16 | static let flowersJust = URL(string: "https://images.unsplash.com/photo-1559533914-a0849c51e503?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=934&q=80")
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/Sources/DSKitFakery/URL+Hydrangea.swift:
--------------------------------------------------------------------------------
1 | //
2 | // URL+Echeveria.swift
3 | // DSKit+Fakery
4 | //
5 | // Created by Borinschi Ivan on 27.01.2021.
6 | //
7 |
8 | import Foundation
9 |
10 | public extension URL {
11 |
12 | static let hydrangeaPink = URL(string: "https://images.unsplash.com/photo-1438268056692-f9603ecc1def?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80")
13 |
14 | static let hydrangeaGreen = URL(string: "https://images.unsplash.com/photo-1528750164675-112c3f715fd9?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1949&q=80")
15 |
16 | static let hydrangeaBlue = URL(string: "https://images.unsplash.com/photo-1536349528643-35e757a105d0?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80")
17 |
18 | static let hydrangeaRed = URL(string: "https://images.unsplash.com/photo-1475873326779-99eac8da25b0?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=933&q=80")
19 | }
20 |
--------------------------------------------------------------------------------
/Sources/DSKitFakery/URL+Jeans.swift:
--------------------------------------------------------------------------------
1 | //
2 | // URL+Sneakers.swift
3 | // DSKit+Fakery
4 | //
5 | // Created by Borinschi Ivan on 27.01.2021.
6 | //
7 |
8 | import Foundation
9 |
10 | public extension URL {
11 |
12 | static let jeansOnBlackBg = URL(string: "https://images.pexels.com/photos/1598507/pexels-photo-1598507.jpeg?cs=srgb&dl=pexels-mnz-1598507.jpg&fm=jpg")
13 |
14 | static let jeansPairs = URL(string: "https://images.pexels.com/photos/4210863/pexels-photo-4210863.jpeg?cs=srgb&dl=pexels-karolina-grabowska-4210863.jpg&fm=jpg")
15 |
16 | static let pantsTrack = URL(string: "https://images.pexels.com/photos/5067705/pexels-photo-5067705.jpeg?cs=srgb&dl=pexels-anna-shvets-5067705.jpg&fm=jpg")
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/Sources/DSKitFakery/URL+Roses.swift:
--------------------------------------------------------------------------------
1 | //
2 | // URL+Roses.swift
3 | // DSKit+Fakery
4 | //
5 | // Created by Borinschi Ivan on 27.01.2021.
6 | //
7 |
8 | import Foundation
9 |
10 | public extension URL {
11 |
12 | static let rosesYellow = URL(string: "https://images.pexels.com/photos/2342264/pexels-photo-2342264.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260")
13 |
14 | static let rosesPink = URL(string: "https://images.pexels.com/photos/2512281/pexels-photo-2512281.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500")
15 |
16 | static let rosesRed = URL(string: "https://images.unsplash.com/photo-1552174965-c6616f62fc4f?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80")
17 |
18 | static let rosesMulticolor = URL(string: "https://images.unsplash.com/photo-1584447310566-bb4d13797f36?ixid=MXwxMjA3fDB8MHxzZWFyY2h8Njh8fHJvc2VzJTIwYm91cXVldHxlbnwwfHwwfA%3D%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=900&q=60")
19 |
20 | static let rosesWhite = URL(string: "https://images.unsplash.com/photo-1571086803179-00ab0eaa6e02?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1951&q=80")
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/DSKitFakery/URL+Shirts.swift:
--------------------------------------------------------------------------------
1 | //
2 | // URL+Sneakers.swift
3 | // DSKit+Fakery
4 | //
5 | // Created by Borinschi Ivan on 27.01.2021.
6 | //
7 |
8 | import Foundation
9 |
10 | public extension URL {
11 |
12 | static let shirtsThreePairs = URL(string: "https://images.unsplash.com/photo-1602810318383-e386cc2a3ccf?ixid=MXwxMjA3fDB8MHxzZWFyY2h8MXx8c2hpcnRzfGVufDB8fDB8&ixlib=rb-1.2.1&auto=format&fit=crop&w=900&q=60")
13 | }
14 |
--------------------------------------------------------------------------------
/Sources/DSKitFakery/URL+Shoes.swift:
--------------------------------------------------------------------------------
1 | //
2 | // URL+Sneakers.swift
3 | // DSKit+Fakery
4 | //
5 | // Created by Borinschi Ivan on 27.01.2021.
6 | //
7 |
8 | import Foundation
9 |
10 | public extension URL {
11 |
12 | static let shoesThreePairs = URL(string: "https://images.pexels.com/photos/267301/pexels-photo-267301.jpeg?cs=srgb&dl=pexels-pixabay-267301.jpg&fm=jpg")
13 |
14 | static let purpleShoes = URL(string: "https://images.pexels.com/photos/2351858/pexels-photo-2351858.jpeg?cs=srgb&dl=pexels-lorena-mart%C3%ADnez-2351858.jpg&fm=jpg")
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/Sources/DSKitFakery/URL+Sneakers.swift:
--------------------------------------------------------------------------------
1 | //
2 | // URL+Sneakers.swift
3 | // DSKit+Fakery
4 | //
5 | // Created by Borinschi Ivan on 27.01.2021.
6 | //
7 |
8 | import Foundation
9 |
10 | public extension URL {
11 |
12 | static let sneakersWhiteOnYellowBg = URL(string: "https://images.pexels.com/photos/2421374/pexels-photo-2421374.jpeg?cs=srgb&dl=pexels-hoang-loc-2421374.jpg&fm=jpg")
13 |
14 | static let sneakersBlackOnBlueBg = URL(string: "https://images.pexels.com/photos/1478442/pexels-photo-1478442.jpeg?cs=srgb&dl=pexels-ray-piedra-1478442.jpg&fm=jpg")
15 |
16 | static let sneakersThreePairs = URL(string: "https://images.pexels.com/photos/2300334/pexels-photo-2300334.jpeg?cs=srgb&dl=pexels-adrian-dorobantu-2300334.jpg&fm=jpg")
17 |
18 | static let sneakersOnWhiteBg = URL(string: "https://images.pexels.com/photos/1858404/pexels-photo-1858404.jpeg?cs=srgb&dl=pexels-athena-1858404.jpg&fm=jpg")
19 |
20 | static let sneakersOnBlackBg = URL(string: "https://images.pexels.com/photos/582485/pexels-photo-582485.jpeg?cs=srgb&dl=pexels-karol-d-582485.jpg&fm=jpg")
21 |
22 | static let sneakersNeon = URL(string: "https://images.pexels.com/photos/6698232/pexels-photo-6698232.jpeg?cs=srgb&dl=pexels-smith-major-6698232.jpg&fm=jpg")
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/DSKitFakery/URL+TShirts.swift:
--------------------------------------------------------------------------------
1 | //
2 | // URL+Sneakers.swift
3 | // DSKit+Fakery
4 | //
5 | // Created by Borinschi Ivan on 27.01.2021.
6 | //
7 |
8 | import Foundation
9 |
10 | public extension URL {
11 | static let tShirtGirlOnYellowBg = URL(string: "https://images.pexels.com/photos/761963/pexels-photo-761963.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260")
12 | }
13 |
--------------------------------------------------------------------------------
/Sources/DSKitFakery/URL+TopFlowers.swift:
--------------------------------------------------------------------------------
1 | //
2 | // URL+Roses.swift
3 | // DSKit+Fakery
4 | //
5 | // Created by Borinschi Ivan on 27.01.2021.
6 | //
7 |
8 | import Foundation
9 |
10 | public extension URL {
11 |
12 | static let topFlowers1 = URL(string: "https://images.unsplash.com/photo-1510894399130-57dfa8dcc45d?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1875&q=80")
13 |
14 | static let topFlowers2 = URL(string: "https://images.unsplash.com/photo-1452827073306-6e6e661baf57?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1867&q=80")
15 |
16 | static let topFlowers3 = URL(string: "https://images.unsplash.com/photo-1508369311886-278fdb148796?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1973&q=80")
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/DSKitFakery/URL+Tulips.swift:
--------------------------------------------------------------------------------
1 | //
2 | // URL+Tulips.swift
3 | // DSKit+Fakery
4 | //
5 | // Created by Borinschi Ivan on 27.01.2021.
6 | //
7 |
8 | import Foundation
9 |
10 | public extension URL {
11 |
12 | static let tulipsMulticolor = URL(string: "https://images.pexels.com/photos/350349/pexels-photo-350349.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260")
13 |
14 | static let tulipsRed = URL(string: "https://images.pexels.com/photos/2058499/pexels-photo-2058499.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260")
15 |
16 | static let tulipsYellow = URL(string: "https://images.unsplash.com/photo-1587000202890-07c8338c6e34?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1300&q=80")
17 |
18 | static let tulipsWhite = URL(string: "https://images.unsplash.com/photo-1581490418272-51f08b7b7418?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=934&q=80")
19 |
20 | static let tulipsSpecial = URL(string: "https://images.unsplash.com/photo-1522585330351-9d852961c300?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1867&q=80")
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/DSKitFakery/URL+Watches.swift:
--------------------------------------------------------------------------------
1 | //
2 | // URL+Sneakers.swift
3 | // DSKit+Fakery
4 | //
5 | // Created by Borinschi Ivan on 27.01.2021.
6 | //
7 |
8 | import Foundation
9 |
10 | public extension URL {
11 |
12 | static let watchesFernandoAcros = URL(string: "https://images.pexels.com/photos/190819/pexels-photo-190819.jpeg?cs=srgb&dl=pexels-fernando-arcos-190819.jpg&fm=jpg")
13 |
14 | static let watchesOnYellowBg = URL(string: "https://images.pexels.com/photos/277390/pexels-photo-277390.jpeg?cs=srgb&dl=pexels-pixabay-277390.jpg&fm=jpg")
15 |
16 | static let blazers = URL(string: "https://images.pexels.com/photos/3555456/pexels-photo-3555456.jpeg?cs=srgb&dl=pexels-mikotoraw-3555456.jpg&fm=jpg")
17 |
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/Templates/ViewModelTemplates/ViewModel.xctemplate/DS___FILEBASENAME___UIView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // ___COPYRIGHT___
7 | //
8 |
9 | import UIKit
10 | import DSKit
11 |
12 | final class DS___VARIABLE_moduleName___UIView: UIView, DSReusableUIView {
13 |
14 | /// DSReusableUIView protocol
15 | public var view: UIView { self }
16 |
17 | /// Set up with view model is called each time when a copy of
18 | /// this UI View is prepared to be displayed on the screen
19 | /// - Parameter viewModel: DSViewModel
20 | public func setUpWith(viewModel: DSViewModel) {
21 |
22 | guard let viewModel = viewModel as? DS___VARIABLE_moduleName___VM else { return }
23 | update(viewModel: viewModel)
24 | }
25 |
26 | /// Update view with view model
27 | /// - Parameter viewModel: DS___VARIABLE_moduleName___VM
28 | func update(viewModel: DS___VARIABLE_moduleName___VM) {
29 |
30 | // DO YOUR WORK HERE
31 | // THIS IS A REUSABLE VIEW
32 | // THIS METHOD IS CALLED EVERY-TIME THIS VIEW IS DISPLAYED ON SCREEN
33 | }
34 |
35 | class func instanceFromNib() -> DS___VARIABLE_moduleName___UIView {
36 | let view: DS___VARIABLE_moduleName___UIView = initFromNib()
37 | return view
38 | }
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/Templates/ViewModelTemplates/ViewModel.xctemplate/DS___FILEBASENAME___UIView.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Templates/ViewModelTemplates/ViewModel.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/Templates/ViewModelTemplates/ViewModel.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Templates/ViewModelTemplates/ViewModel.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imodeveloperlab/dskit/c9810f80d2a1052aa3bd999e2d91eac1b0d5b1e9/Templates/ViewModelTemplates/ViewModel.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Templates/ViewModelTemplates/install.sh:
--------------------------------------------------------------------------------
1 |
2 | #!/bin/bash
3 | abort()
4 | {
5 | echo >&2 '
6 | ***************
7 | *** ABORTED ***
8 | ***************
9 | '
10 | echo "An error occurred. Exiting..." >&2
11 | exit 1
12 | }
13 |
14 | trap 'abort' 0
15 | set -e
16 |
17 | BASEDIR=$HOME
18 | TEMPLATESDIR1=~/Applications/Xcode.app/Contents/Developer/Library/Xcode/Templates/File\ Templates
19 | TEMPLATESDIR2=~/Downloads/Xcode.app/Contents/Developer/Library/Xcode/Templates/File\ Templates
20 | FULLTEMPLATESDIR1="$TEMPLATESDIR1/DSKit"
21 | FULLTEMPLATESDIR2="$TEMPLATESDIR2/DSKit"
22 |
23 | echo "Templates will be installed"
24 |
25 | if [ -d "${FULLTEMPLATESDIR1}" ]; then
26 | rm -r "${FULLTEMPLATESDIR1}"
27 | fi
28 |
29 | if [ -d "${FULLTEMPLATESDIR2}" ]; then
30 | rm -r "${FULLTEMPLATESDIR2}"
31 | fi
32 |
33 | mkdir -p "${FULLTEMPLATESDIR1}"
34 | cp -r *.xctemplate "${FULLTEMPLATESDIR1}"
35 |
36 | mkdir -p "${FULLTEMPLATESDIR2}"
37 | cp -r *.xctemplate "${FULLTEMPLATESDIR2}"
38 |
39 | trap : 0
40 |
41 | echo >&2 '
42 | ***********************************************
43 | *** DSKit templates, successfully installed ***
44 | ***********************************************
45 | '
46 |
--------------------------------------------------------------------------------
/Tests/DSKitTests/DSKitTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import DSKit
3 |
4 | final class DSKitTests: XCTestCase {
5 | func testExample() throws {
6 | // This is an example of a functional test case.
7 | // Use XCTAssert and related functions to verify your tests produce the correct
8 | // results.
9 | XCTAssertNotNil(nil, "Oh")
10 | }
11 | }
12 |
--------------------------------------------------------------------------------