diff --git a/.gitignore b/.gitignore index 1238364fd..a64a77b22 100644 --- a/.gitignore +++ b/.gitignore @@ -103,3 +103,6 @@ out #snapshots spark-ios-snapshots + +#plists +*.plist diff --git a/Spark.yml b/Spark.yml index 3ff6211ad..a325198a5 100644 --- a/Spark.yml +++ b/Spark.yml @@ -16,6 +16,10 @@ targetTemplates: PRODUCT_NAME: Spark info: path: spark/Sources/Info.plist + properties: + UIAppFonts: + - "NunitoSans-Bold.ttf" + - "NunitoSans-Regular.ttf" sources: - path: spark/Sources excludes: @@ -24,6 +28,8 @@ targetTemplates: testTargets: - name: SparkTests gatherCoverageData: true + dependencies: + - target: SparkCore SparkTestsTemplate: type: bundle.unit-test @@ -57,6 +63,8 @@ targetTemplates: info: path: spark/Demo/Info.plist properties: + UILaunchScreen: [] + UIApplicationSceneManifest: UIApplicationSupportsMultipleScenes: false UISceneConfigurations: {} diff --git a/core/Demo/Info.plist b/core/Demo/Info.plist deleted file mode 100644 index 2f2f77534..000000000 --- a/core/Demo/Info.plist +++ /dev/null @@ -1,29 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - UIApplicationSceneManifest - - UIApplicationSupportsMultipleScenes - - UISceneConfigurations - - - - diff --git a/core/Info.plist b/core/Info.plist deleted file mode 100644 index 323e5ecfc..000000000 --- a/core/Info.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - - diff --git a/core/Sources/Extension/Bundle+Extension.swift b/core/Sources/Extension/Bundle+Extension.swift new file mode 100644 index 000000000..8cbc30429 --- /dev/null +++ b/core/Sources/Extension/Bundle+Extension.swift @@ -0,0 +1,44 @@ +// +// Bundle+Extension.swift +// Spark +// +// Created by robin.lemaire on 02/03/2023. +// + +import Foundation +import UIKit + +public extension Bundle { + + // MARK: - Constants + + private enum Constants { + static let fontExtensions = ["ttf", "otf"] + } + + // MARK: - Fonts + + func registerAllFonts() { + // Get all custom fonts on bundle + let fontURLs = Constants.fontExtensions.compactMap { fontExtension in + self.urls(forResourcesWithExtension: fontExtension, subdirectory: nil) + } + .flatMap { + $0 + } + .map { + $0 as CFURL + } + + // Try to register all customs fonts + fontURLs.forEach { + guard let fontDataProvider = CGDataProvider(url: $0), + let font = CGFont(fontDataProvider) else { + return + } + + var error: Unmanaged? + CTFontManagerRegisterGraphicsFont(font, &error) + } + } +} diff --git a/core/Sources/Info.plist b/core/Sources/Info.plist deleted file mode 100644 index 323e5ecfc..000000000 --- a/core/Sources/Info.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - - diff --git a/core/Sources/Theming/Configuration.swift b/core/Sources/Theming/Configuration.swift new file mode 100644 index 000000000..98ce95406 --- /dev/null +++ b/core/Sources/Theming/Configuration.swift @@ -0,0 +1,11 @@ +// +// Configuration.swift +// Spark +// +// Created by robin.lemaire on 02/03/2023. +// + +public protocol Configuration { + + static func load() +} diff --git a/core/Sources/Theming/Content/Border/Border.swift b/core/Sources/Theming/Content/Border/Border.swift new file mode 100644 index 000000000..48903ad93 --- /dev/null +++ b/core/Sources/Theming/Content/Border/Border.swift @@ -0,0 +1,39 @@ +// +// Border.swift +// SparkCore +// +// Created by robin.lemaire on 28/02/2023. +// + +import Foundation + +public protocol Border { + var width: BorderWidth { get } + var radius: BorderRadius { get } +} + +// MARK: - Width + +public protocol BorderWidth { + var none: CGFloat { get } + var small: CGFloat { get } + var medium: CGFloat { get } +} + +public extension BorderWidth { + var none: CGFloat { 0 } +} + +// MARK: - Radius + +public protocol BorderRadius { + var none: CGFloat { get } + var small: CGFloat { get } + var medium: CGFloat { get } + var large: CGFloat { get } + var xLarge: CGFloat { get } +} + +public extension BorderRadius { + var none: CGFloat { 0 } +} diff --git a/core/Sources/Theming/Content/Border/BorderDefault.swift b/core/Sources/Theming/Content/Border/BorderDefault.swift new file mode 100644 index 000000000..f303f434b --- /dev/null +++ b/core/Sources/Theming/Content/Border/BorderDefault.swift @@ -0,0 +1,65 @@ +// +// BorderDefault.swift +// SparkCore +// +// Created by robin.lemaire on 28/02/2023. +// + +import Foundation + +public struct BorderDefault: Border { + + // MARK: - Properties + + public let width: BorderWidth + public let radius: BorderRadius + + // MARK: - Initialization + + public init(width: BorderWidth, radius: BorderRadius) { + self.width = width + self.radius = radius + } +} + +// MARK: - Width + +public struct BorderWidthDefault: BorderWidth { + + // MARK: - Properties + + public let small: CGFloat + public let medium: CGFloat + + // MARK: - Initialization + + public init(small: CGFloat, + medium: CGFloat) { + self.small = small + self.medium = medium + } +} + +// MARK: - Radius + +public struct BorderRadiusDefault: BorderRadius { + + // MARK: - Properties + + public let small: CGFloat + public let medium: CGFloat + public let large: CGFloat + public let xLarge: CGFloat + + // MARK: - Initialization + + public init(small: CGFloat, + medium: CGFloat, + large: CGFloat, + xLarge: CGFloat) { + self.small = small + self.medium = medium + self.large = large + self.xLarge = xLarge + } +} diff --git a/core/Sources/Theming/Content/Colors/Colors.swift b/core/Sources/Theming/Content/Colors/Colors.swift new file mode 100644 index 000000000..660baf1d4 --- /dev/null +++ b/core/Sources/Theming/Content/Colors/Colors.swift @@ -0,0 +1,52 @@ +// +// Colors.swift +// SparkCore +// +// Created by louis.borlee on 23/02/2023. +// + +import UIKit +import SwiftUI + +public protocol Colors { + var primary: ColorToken { get } + var primaryVariant: ColorToken { get } + + var secondary: ColorToken { get } + var secondaryVariant: ColorToken { get } + + var background: ColorToken { get } + + var surface: ColorToken { get } + var surfaceInverse: ColorToken { get } + + var success: ColorToken { get } + var alert: ColorToken { get } + var error: ColorToken { get } + var info: ColorToken { get } + var neutral: ColorToken { get } + + var primaryContainer: ColorToken { get } + var secondaryContainer: ColorToken { get } + var successContainer: ColorToken { get } + var alertContainer: ColorToken { get } + var errorContainer: ColorToken { get } + var infoContainer: ColorToken { get } + var neutralContainer: ColorToken { get } +} + +// MARK: - Token + +public protocol ColorToken { + var enabled: ColorTokenValue { get } + var pressed: ColorTokenValue { get } + var disabled: ColorTokenValue { get } + var on: ColorTokenValue { get } +} + +// MARK: - Value + +public protocol ColorTokenValue { + var uiColor: UIColor { get } + var swiftUIcolor: Color { get } +} diff --git a/core/Sources/Theming/Content/Colors/ColorsDefault.swift b/core/Sources/Theming/Content/Colors/ColorsDefault.swift new file mode 100644 index 000000000..a72a344c9 --- /dev/null +++ b/core/Sources/Theming/Content/Colors/ColorsDefault.swift @@ -0,0 +1,123 @@ +// +// ColorsDefault.swift +// SparkCore +// +// Created by louis.borlee on 23/02/2023. +// + +import SwiftUI +import UIKit + +public struct ColorsDefault: Colors { + + // MARK: - Properties + + public let primary: ColorToken + public let primaryVariant: ColorToken + + public let secondary: ColorToken + public let secondaryVariant: ColorToken + + public let background: ColorToken + + public let surface: ColorToken + public let surfaceInverse: ColorToken + + public let success: ColorToken + public let alert: ColorToken + public let error: ColorToken + public let info: ColorToken + public let neutral: ColorToken + + public let primaryContainer: ColorToken + public let secondaryContainer: ColorToken + public let successContainer: ColorToken + public let alertContainer: ColorToken + public let errorContainer: ColorToken + public let infoContainer: ColorToken + public let neutralContainer: ColorToken + + // MARK: - Initialization + + public init(primary: ColorToken, + primaryVariant: ColorToken, + secondary: ColorToken, + secondaryVariant: ColorToken, + background: ColorToken, + surface: ColorToken, + surfaceInverse: ColorToken, + success: ColorToken, + alert: ColorToken, + error: ColorToken, + info: ColorToken, + neutral: ColorToken, + primaryContainer: ColorToken, + secondaryContainer: ColorToken, + successContainer: ColorToken, + alertContainer: ColorToken, + errorContainer: ColorToken, + infoContainer: ColorToken, + neutralContainer: ColorToken) { + self.primary = primary + self.primaryVariant = primaryVariant + self.secondary = secondary + self.secondaryVariant = secondaryVariant + self.background = background + self.surface = surface + self.surfaceInverse = surfaceInverse + self.success = success + self.alert = alert + self.error = error + self.info = info + self.neutral = neutral + self.primaryContainer = primaryContainer + self.secondaryContainer = secondaryContainer + self.successContainer = successContainer + self.alertContainer = alertContainer + self.errorContainer = errorContainer + self.infoContainer = infoContainer + self.neutralContainer = neutralContainer + } +} + +// MARK: - Token + +public struct ColorTokenDefault: ColorToken { + + // MARK: - Properties + + public let enabled: ColorTokenValue + public let pressed: ColorTokenValue + public let disabled: ColorTokenValue + public let on: ColorTokenValue + + // MARK: - Initialization + + public init(enabled: ColorTokenValue, + pressed: ColorTokenValue, + disabled: ColorTokenValue, + on: ColorTokenValue) { + self.enabled = enabled + self.pressed = pressed + self.disabled = disabled + self.on = on + } +} + +// MARK: - Value + +public struct ColorTokenValueDefault: ColorTokenValue { + + // MARK: - Properties + + public let uiColor: UIColor + public let swiftUIcolor: Color + + // MARK: - Initialization + + public init(uiColor: UIColor, + swiftUIcolor: Color) { + self.uiColor = uiColor + self.swiftUIcolor = swiftUIcolor + } +} diff --git a/core/Sources/Theming/Content/Iconography/Iconography.swift b/core/Sources/Theming/Content/Iconography/Iconography.swift new file mode 100644 index 000000000..bd3864706 --- /dev/null +++ b/core/Sources/Theming/Content/Iconography/Iconography.swift @@ -0,0 +1,10 @@ +// +// Iconography.swift +// SparkCore +// +// Created by louis.borlee on 23/02/2023. +// + +import Foundation + +public protocol Iconography {} diff --git a/core/Sources/Theming/Content/Iconography/IconographyDefault.swift b/core/Sources/Theming/Content/Iconography/IconographyDefault.swift new file mode 100644 index 000000000..e7effa72d --- /dev/null +++ b/core/Sources/Theming/Content/Iconography/IconographyDefault.swift @@ -0,0 +1,8 @@ +// +// IconographyDefault.swift +// SparkCore +// +// Created by louis.borlee on 23/02/2023. +// + +public struct IconographyDefault: Iconography {} diff --git a/core/Sources/Theming/Content/Layout/Layout.swift b/core/Sources/Theming/Content/Layout/Layout.swift new file mode 100644 index 000000000..afc70c219 --- /dev/null +++ b/core/Sources/Theming/Content/Layout/Layout.swift @@ -0,0 +1,28 @@ +// +// Layout.swift +// SparkCore +// +// Created by louis.borlee on 23/02/2023. +// + +import Foundation + +public protocol Layout { + var spacing: LayoutSpacing { get } +} + +// MARK: - Spacing + +public protocol LayoutSpacing { + var none: CGFloat { get } + var small: CGFloat { get } + var medium: CGFloat { get } + var large: CGFloat { get } + var xLarge: CGFloat { get } + var xxLarge: CGFloat { get } + var xxxLarge: CGFloat { get } +} + +public extension LayoutSpacing { + var none: CGFloat { 0 } +} diff --git a/core/Sources/Theming/Content/Layout/LayoutDefault.swift b/core/Sources/Theming/Content/Layout/LayoutDefault.swift new file mode 100644 index 000000000..420ce3395 --- /dev/null +++ b/core/Sources/Theming/Content/Layout/LayoutDefault.swift @@ -0,0 +1,51 @@ +// +// LayoutDefault.swift +// SparkCore +// +// Created by louis.borlee on 23/02/2023. +// + +import Foundation + +public struct LayoutDefault: Layout { + + // MARK: - Properties + + public let spacing: LayoutSpacing + + // MARK: - Initialization + + public init(spacing: LayoutSpacing) { + self.spacing = spacing + } +} + +// MARK: - Spacing + +public struct LayoutSpacingDefault: LayoutSpacing { + + // MARK: - Properties + + public let small: CGFloat + public let medium: CGFloat + public let large: CGFloat + public let xLarge: CGFloat + public let xxLarge: CGFloat + public let xxxLarge: CGFloat + + // MARK: - Initialization + + public init(small: CGFloat, + medium: CGFloat, + large: CGFloat, + xLarge: CGFloat, + xxLarge: CGFloat, + xxxLarge: CGFloat) { + self.small = small + self.medium = medium + self.large = large + self.xLarge = xLarge + self.xxLarge = xxLarge + self.xxxLarge = xxxLarge + } +} diff --git a/core/Sources/Theming/Content/Typography/Typography.swift b/core/Sources/Theming/Content/Typography/Typography.swift new file mode 100644 index 000000000..aed5babc7 --- /dev/null +++ b/core/Sources/Theming/Content/Typography/Typography.swift @@ -0,0 +1,41 @@ +// +// Typography.swift +// SparkCore +// +// Created by louis.borlee on 23/02/2023. +// + +import UIKit +import SwiftUI + +public protocol Typography { + var display1: TypographyFont { get } + var display2: TypographyFont { get } + var display3: TypographyFont { get } + + var headline1: TypographyFont { get } + var headline2: TypographyFont { get } + + var subhead: TypographyFont { get } + + var body1: TypographyFont { get } + var body1Highlight: TypographyFont { get } + + var body2: TypographyFont { get } + var body2Highlight: TypographyFont { get } + + var caption: TypographyFont { get } + var captionHighlight: TypographyFont { get } + + var small: TypographyFont { get } + var smallHighlight: TypographyFont { get } + + var callout: TypographyFont { get } +} + +// MARK: - Font + +public protocol TypographyFont { + var font: UIFont { get } + var swiftUIFont: Font { get } +} diff --git a/core/Sources/Theming/Content/Typography/TypographyDefault.swift b/core/Sources/Theming/Content/Typography/TypographyDefault.swift new file mode 100644 index 000000000..cd85c3c18 --- /dev/null +++ b/core/Sources/Theming/Content/Typography/TypographyDefault.swift @@ -0,0 +1,89 @@ +// +// TypographyDefault.swift +// SparkCore +// +// Created by louis.borlee on 23/02/2023. +// + +import SwiftUI +import UIKit + +public struct TypographyDefault: Typography { + + // MARK: - Properties + + public let display1: TypographyFont + public let display2: TypographyFont + public let display3: TypographyFont + + public let headline1: TypographyFont + public let headline2: TypographyFont + + public let subhead: TypographyFont + + public let body1: TypographyFont + public let body1Highlight: TypographyFont + + public let body2: TypographyFont + public let body2Highlight: TypographyFont + + public let caption: TypographyFont + public let captionHighlight: TypographyFont + + public let small: TypographyFont + public let smallHighlight: TypographyFont + + public let callout: TypographyFont + + // MARK: - Initialization + + public init(display1: TypographyFont, + display2: TypographyFont, + display3: TypographyFont, + headline1: TypographyFont, + headline2: TypographyFont, + subhead: TypographyFont, + body1: TypographyFont, + body1Highlight: TypographyFont, + body2: TypographyFont, + body2Highlight: TypographyFont, + caption: TypographyFont, + captionHighlight: TypographyFont, + small: TypographyFont, + smallHighlight: TypographyFont, + callout: TypographyFont) { + self.display1 = display1 + self.display2 = display2 + self.display3 = display3 + self.headline1 = headline1 + self.headline2 = headline2 + self.subhead = subhead + self.body1 = body1 + self.body1Highlight = body1Highlight + self.body2 = body2 + self.body2Highlight = body2Highlight + self.caption = caption + self.captionHighlight = captionHighlight + self.small = small + self.smallHighlight = smallHighlight + self.callout = callout + } +} + +// MARK: - Font + +public struct TypographyFontDefault: TypographyFont { + + // MARK: - Properties + + public let font: UIFont + public let swiftUIFont: Font + + // MARK: - Initialization + + public init(font: UIFont, + swiftUIFont: Font) { + self.font = font + self.swiftUIFont = swiftUIFont + } +} diff --git a/core/Sources/Theming/CurrentTheme.swift b/core/Sources/Theming/CurrentTheme.swift new file mode 100644 index 000000000..0601f50e8 --- /dev/null +++ b/core/Sources/Theming/CurrentTheme.swift @@ -0,0 +1,15 @@ +// +// CurrentTheme.swift +// SparkCore +// +// Created by robin.lemaire on 02/03/2023. +// + +public struct CurrentTheme { + + // MARK: - Properties + + // TODO: remove forcecast + public static var part: Theme! + public static var pro: Theme! +} diff --git a/core/Sources/Theming/Theme/Theme.swift b/core/Sources/Theming/Theme/Theme.swift new file mode 100644 index 000000000..c8636dc5c --- /dev/null +++ b/core/Sources/Theming/Theme/Theme.swift @@ -0,0 +1,16 @@ +// +// Theme.swift +// Spark +// +// Created by louis.borlee on 23/02/2023. +// + +import Foundation + +public protocol Theme { + var border: Border { get } + var colors: Colors { get } + var iconography: Iconography { get } + var layout: Layout { get } + var typography: Typography { get } +} diff --git a/core/Sources/Theming/Theme/ThemeDefault.swift b/core/Sources/Theming/Theme/ThemeDefault.swift new file mode 100644 index 000000000..5e570f760 --- /dev/null +++ b/core/Sources/Theming/Theme/ThemeDefault.swift @@ -0,0 +1,31 @@ +// +// ThemeDefault.swift +// SparkCore +// +// Created by robin.lemaire on 06/03/2023. +// + +public struct ThemeDefault: Theme { + + // MARK: - Properties + + public let border: Border + public let colors: Colors + public let iconography: Iconography + public let layout: Layout + public let typography: Typography + + // MARK: - Initialization + + public init(border: Border, + colors: Colors, + iconography: Iconography, + layout: Layout, + typography: Typography) { + self.border = border + self.colors = colors + self.iconography = iconography + self.layout = layout + self.typography = typography + } +} diff --git a/core/Unit-tests/Info.plist b/core/Unit-tests/Info.plist deleted file mode 100644 index 6c40a6cd0..000000000 --- a/core/Unit-tests/Info.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - - diff --git a/core/Unit-tests/SparkTests.swift b/core/Unit-tests/SparkCoreTests.swift similarity index 78% rename from core/Unit-tests/SparkTests.swift rename to core/Unit-tests/SparkCoreTests.swift index 1fb3de2d1..6e8d7b989 100644 --- a/core/Unit-tests/SparkTests.swift +++ b/core/Unit-tests/SparkCoreTests.swift @@ -1,6 +1,6 @@ // -// SparkTests.swift -// SparkTests +// SparkCoreTests.swift +// SparkCoreTests // // Created by luis.figueiredo-ext on 08/02/2023. // @@ -8,7 +8,7 @@ import XCTest import SnapshotTesting -final class SparkTests: XCTestCase { +final class SparkCoreTests: XCTestCase { func testExample() throws { let view = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 300)) diff --git a/core/Unit-tests/SparkTestsUtils.swift b/core/Unit-tests/SparkCoreTestsUtils.swift similarity index 94% rename from core/Unit-tests/SparkTestsUtils.swift rename to core/Unit-tests/SparkCoreTestsUtils.swift index d859e6c20..4642535d4 100644 --- a/core/Unit-tests/SparkTestsUtils.swift +++ b/core/Unit-tests/SparkCoreTestsUtils.swift @@ -1,6 +1,6 @@ // -// SparkTestsUtils.swift -// SparkTests +// SparkCoreTestsUtils.swift +// SparkCoreTests // // Created by luis.figueiredo-ext on 08/02/2023. // diff --git a/spark/Demo/Classes/ContentView.swift b/spark/Demo/Classes/ContentView.swift deleted file mode 100644 index a497f2875..000000000 --- a/spark/Demo/Classes/ContentView.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// ContentView.swift -// SparkDemo -// -// Created by luis.figueiredo-ext on 08/02/2023. -// - -import SwiftUI - -struct ContentView: View { - var body: some View { - VStack { - Image(systemName: "globe") - .imageScale(.large) - .foregroundColor(.accentColor) - Text("Hello, Spark Demo!") - } - .padding() - } -} - -struct ContentView_Previews: PreviewProvider { - static var previews: some View { - ContentView() - } -} diff --git a/spark/Demo/Classes/SparkDemoApp.swift b/spark/Demo/Classes/SparkDemoApp.swift index 707dab5d3..b0855199f 100644 --- a/spark/Demo/Classes/SparkDemoApp.swift +++ b/spark/Demo/Classes/SparkDemoApp.swift @@ -6,12 +6,28 @@ // import SwiftUI +import SparkCore +import Spark @main struct SparkDemoApp: App { + + // MARK: - Initialization + + init() { + // Configuration + SparkConfiguration.load() + + // Set themes + CurrentTheme.part = SparkCurrentTheme.theme + CurrentTheme.pro = SparkCurrentTheme.theme + } + + // MARK: - Scene + var body: some Scene { WindowGroup { - ContentView() + MainView() } } } diff --git a/spark/Demo/Classes/View/Border/BorderItemView.swift b/spark/Demo/Classes/View/Border/BorderItemView.swift new file mode 100644 index 000000000..c937ea83a --- /dev/null +++ b/spark/Demo/Classes/View/Border/BorderItemView.swift @@ -0,0 +1,41 @@ +// +// BorderItemView.swift +// SparkDemo +// +// Created by robin.lemaire on 01/03/2023. +// + +import SwiftUI + +struct BorderItemView: View { + + // MARK: - Properties + + let viewModel: BorderItemViewModel + + // MARK: - View + + var body: some View { + VStack(alignment: .leading) { + Text(self.viewModel.name) + Text(self.viewModel.description) + .font(Font.caption2) + .italic() + .foregroundColor(.gray) + + Color.gray + .cornerRadius(self.viewModel.radius) + .frame(width: 200, height: 50) + .overlay( + RoundedRectangle(cornerRadius: self.viewModel.radius) + .stroke(Color.black, lineWidth: self.viewModel.width) + ) + } + } +} + +struct BorderItemView_Previews: PreviewProvider { + static var previews: some View { + BorderItemView(viewModel: .init(name: "Title", width: 10, radius: 4)) + } +} diff --git a/spark/Demo/Classes/View/Border/BorderItemViewModel.swift b/spark/Demo/Classes/View/Border/BorderItemViewModel.swift new file mode 100644 index 000000000..329706270 --- /dev/null +++ b/spark/Demo/Classes/View/Border/BorderItemViewModel.swift @@ -0,0 +1,29 @@ +// +// BorderItemViewModel.swift +// SparkDemo +// +// Created by robin.lemaire on 01/03/2023. +// + +import SwiftUI + +struct BorderItemViewModel: Hashable { + + // MARK: - Properties + + let name: String + let description: String + let width: CGFloat + let radius: CGFloat + + // MARK: - Initialization + + init(name: String, + width: CGFloat, + radius: CGFloat) { + self.name = name + " radius" + self.description = "width: \(Int(width))px - radius: \(Int(radius))px" + self.width = width + self.radius = radius + } +} diff --git a/spark/Demo/Classes/View/Border/BorderSectionViewModel.swift b/spark/Demo/Classes/View/Border/BorderSectionViewModel.swift new file mode 100644 index 000000000..870512ade --- /dev/null +++ b/spark/Demo/Classes/View/Border/BorderSectionViewModel.swift @@ -0,0 +1,14 @@ +// +// BorderSectionViewModel.swift +// SparkDemo +// +// Created by robin.lemaire on 02/03/2023. +// + +struct BorderSectionViewModel: Hashable { + + // MARK: - Properties + + let name: String + let itemViewModels: [BorderItemViewModel] +} diff --git a/spark/Demo/Classes/View/Border/BorderView.swift b/spark/Demo/Classes/View/Border/BorderView.swift new file mode 100644 index 000000000..1eaa4ab21 --- /dev/null +++ b/spark/Demo/Classes/View/Border/BorderView.swift @@ -0,0 +1,34 @@ +// +// BorderView.swift +// SparkDemo +// +// Created by luis.figueiredo-ext on 08/02/2023. +// + +import SwiftUI + +struct BorderView: View { + + // MARK: - Properties + + private let viewModel = BorderViewModel() + + // MARK: - View + + var body: some View { + List(self.viewModel.sectionViewModels, id: \.self) { sectionViewModel in + Section(header: Text(sectionViewModel.name)) { + ForEach(sectionViewModel.itemViewModels, id: \.self) { itemViewModel in + BorderItemView(viewModel: itemViewModel) + } + } + } + .navigationBarTitle(Text("Border")) + } +} + +struct BorderView_Previews: PreviewProvider { + static var previews: some View { + BorderView() + } +} diff --git a/spark/Demo/Classes/View/Border/BorderViewModel.swift b/spark/Demo/Classes/View/Border/BorderViewModel.swift new file mode 100644 index 000000000..6846dbb87 --- /dev/null +++ b/spark/Demo/Classes/View/Border/BorderViewModel.swift @@ -0,0 +1,49 @@ +// +// BorderViewModel.swift +// SparkDemo +// +// Created by robin.lemaire on 01/03/2023. +// + +import SparkCore + +struct BorderViewModel { + + // MARK: - Properties + + let sectionViewModels: [BorderSectionViewModel] + + // MARK: - Initialization + + init() { + let border = CurrentTheme.part.border + self.sectionViewModels = [ + .init(name: "none width", + itemViewModels: [ + .init(name: "none", width: border.width.none, radius: border.radius.none), + .init(name: "small", width: border.width.none, radius: border.radius.small), + .init(name: "medium", width: border.width.none, radius: border.radius.medium), + .init(name: "large", width: border.width.none, radius: border.radius.large), + .init(name: "xLarge", width: border.width.none, radius: border.radius.xLarge) + ]), + + .init(name: "small width", + itemViewModels: [ + .init(name: "none", width: border.width.small, radius: border.radius.none), + .init(name: "small", width: border.width.small, radius: border.radius.small), + .init(name: "medium", width: border.width.small, radius: border.radius.medium), + .init(name: "large", width: border.width.small, radius: border.radius.large), + .init(name: "xLarge", width: border.width.small, radius: border.radius.xLarge) + ]), + + .init(name: "medium width", + itemViewModels: [ + .init(name: "none", width: border.width.medium, radius: border.radius.none), + .init(name: "small", width: border.width.medium, radius: border.radius.small), + .init(name: "medium", width: border.width.medium, radius: border.radius.medium), + .init(name: "large", width: border.width.medium, radius: border.radius.large), + .init(name: "xLarge", width: border.width.medium, radius: border.radius.xLarge) + ]) + ] + } +} diff --git a/spark/Demo/Classes/View/Color/ColorItemView.swift b/spark/Demo/Classes/View/Color/ColorItemView.swift new file mode 100644 index 000000000..8bc634111 --- /dev/null +++ b/spark/Demo/Classes/View/Color/ColorItemView.swift @@ -0,0 +1,46 @@ +// +// ColorItemView.swift +// SparkDemo +// +// Created by robin.lemaire on 01/03/2023. +// + +import SwiftUI +import SparkCore + +struct ColorItemView: View { + + // MARK: - Properties + + let viewModel: ColorItemViewModel + + // MARK: - View + + var body: some View { + VStack(alignment: .leading, spacing: 16) { + Text(self.viewModel.name) + VStack(alignment: .leading, spacing: 8) { + ForEach(self.viewModel.states, id: \.self) { stateViewModel in + Text(stateViewModel.name) + .font(Font.caption2) + .foregroundColor(.gray).contrast(-5) + .padding(16) + .frame(maxWidth: .infinity, alignment: .leading) + .background(stateViewModel.color) + .cornerRadius(8) + } + } + + } + } +} + +struct ColorItemView_Previews: PreviewProvider { + static var previews: some View { + ColorItemView(viewModel: .init(name: "Name", + colorToken: ColorTokenDefault(enabled: ColorTokenValueDefault(uiColor: .blue, swiftUIcolor: .orange), + pressed: ColorTokenValueDefault(uiColor: .green, swiftUIcolor: .blue), + disabled: ColorTokenValueDefault(uiColor: .yellow, swiftUIcolor: .green), + on: ColorTokenValueDefault(uiColor: .purple, swiftUIcolor: .yellow)))) + } +} diff --git a/spark/Demo/Classes/View/Color/ColorItemViewModel.swift b/spark/Demo/Classes/View/Color/ColorItemViewModel.swift new file mode 100644 index 000000000..61df858f3 --- /dev/null +++ b/spark/Demo/Classes/View/Color/ColorItemViewModel.swift @@ -0,0 +1,45 @@ +// +// ColorItemViewModel.swift +// SparkDemo +// +// Created by robin.lemaire on 01/03/2023. +// + +import SparkCore +import SwiftUI + +struct ColorItemViewModel: Hashable { + + // MARK: - Properties + + let name: String + let states: [ColorItemStateViewModel] + + // MARK: - Initialization + + init(name: String, + colorToken: ColorToken) { + self.name = name + self.states = [ + .init(name: "enabled", colorValue: colorToken.enabled), + .init(name: "pressed", colorValue: colorToken.pressed), + .init(name: "disabled", colorValue: colorToken.disabled), + .init(name: "on", colorValue: colorToken.on) + ] + } +} + +struct ColorItemStateViewModel: Hashable { + + // MARK: - Properties + + let name: String + let color: Color + + // MARK: - Initialization + + init(name: String, colorValue: ColorTokenValue) { + self.name = name + self.color = colorValue.swiftUIcolor + } +} diff --git a/spark/Demo/Classes/View/Color/ColorView.swift b/spark/Demo/Classes/View/Color/ColorView.swift new file mode 100644 index 000000000..48230ac64 --- /dev/null +++ b/spark/Demo/Classes/View/Color/ColorView.swift @@ -0,0 +1,34 @@ +// +// ColorView.swift +// SparkDemo +// +// Created by luis.figueiredo-ext on 08/02/2023. +// + +import SwiftUI + +struct ColorView: View { + + // MARK: - Properties + + private let viewModel = ColorViewModel() + + // MARK: - View + + var body: some View { + List(self.viewModel.itemViewModels, id: \.self) { itemViewModels in + Section { + ForEach(itemViewModels, id: \.self) { itemViewModel in + ColorItemView(viewModel: itemViewModel) + } + } + } + .navigationBarTitle(Text("Color")) + } +} + +struct ColorView_Previews: PreviewProvider { + static var previews: some View { + ColorView() + } +} diff --git a/spark/Demo/Classes/View/Color/ColorViewModel.swift b/spark/Demo/Classes/View/Color/ColorViewModel.swift new file mode 100644 index 000000000..8123bb391 --- /dev/null +++ b/spark/Demo/Classes/View/Color/ColorViewModel.swift @@ -0,0 +1,59 @@ +// +// ColorViewModel.swift +// SparkDemo +// +// Created by robin.lemaire on 01/03/2023. +// + +import SparkCore + +struct ColorViewModel { + + // MARK: - Properties + + let itemViewModels: [[ColorItemViewModel]] + + // MARK: - Initialization + + init() { + let colors = CurrentTheme.part.colors + self.itemViewModels = [ + [ + .init(name: "primary", colorToken: colors.primary), + .init(name: "primaryVariant", colorToken: colors.primaryVariant) + ], + + [ + .init(name: "secondary", colorToken: colors.secondary), + .init(name: "secondaryVariant", colorToken: colors.secondaryVariant) + ], + + [ + .init(name: "background", colorToken: colors.background) + ], + + [ + .init(name: "surface", colorToken: colors.surface), + .init(name: "surfaceInverse", colorToken: colors.surfaceInverse) + ], + + [ + .init(name: "success", colorToken: colors.success), + .init(name: "alert", colorToken: colors.alert), + .init(name: "error", colorToken: colors.error), + .init(name: "info", colorToken: colors.info), + .init(name: "neutral", colorToken: colors.neutral) + ], + + [ + .init(name: "primaryContainer", colorToken: colors.primaryContainer), + .init(name: "secondaryContainer", colorToken: colors.secondaryContainer), + .init(name: "successContainer", colorToken: colors.successContainer), + .init(name: "alertContainer", colorToken: colors.alertContainer), + .init(name: "errorContainer", colorToken: colors.errorContainer), + .init(name: "infoContainer", colorToken: colors.infoContainer), + .init(name: "neutralContainer", colorToken: colors.neutralContainer) + ] + ] + } +} diff --git a/spark/Demo/Classes/View/Layout/LayoutSpacingItemView.swift b/spark/Demo/Classes/View/Layout/LayoutSpacingItemView.swift new file mode 100644 index 000000000..5422e877e --- /dev/null +++ b/spark/Demo/Classes/View/Layout/LayoutSpacingItemView.swift @@ -0,0 +1,40 @@ +// +// LayoutSpacingItemView.swift +// SparkDemo +// +// Created by robin.lemaire on 01/03/2023. +// + +import SwiftUI + +struct LayoutSpacingItemView: View { + + // MARK: - Properties + + let viewModel: LayoutSpacingItemViewModel + + // MARK: - View + + var body: some View { + VStack(alignment: .leading) { + Text(self.viewModel.name) + Text(self.viewModel.description) + .font(Font.caption2) + .italic() + .foregroundColor(.gray) + + if self.viewModel.value > 0 { + Rectangle() + .fill(.gray) + .frame(width: self.viewModel.value, + height: 20) + } + } + } +} + +struct LayoutSpacingItemView_Previews: PreviewProvider { + static var previews: some View { + LayoutSpacingItemView(viewModel: .init(name: "Small", value: 10)) + } +} diff --git a/spark/Demo/Classes/View/Layout/LayoutSpacingItemViewModel.swift b/spark/Demo/Classes/View/Layout/LayoutSpacingItemViewModel.swift new file mode 100644 index 000000000..5cdb38e9f --- /dev/null +++ b/spark/Demo/Classes/View/Layout/LayoutSpacingItemViewModel.swift @@ -0,0 +1,26 @@ +// +// LayoutSpacingItemViewModel.swift +// SparkDemo +// +// Created by robin.lemaire on 01/03/2023. +// + +import SwiftUI + +struct LayoutSpacingItemViewModel: Hashable { + + // MARK: - Properties + + let name: String + let description: String + let value: CGFloat + + // MARK: - Initialization + + init(name: String, + value: CGFloat) { + self.name = name + self.description = "\(Int(value))px" + self.value = value + } +} diff --git a/spark/Demo/Classes/View/Layout/LayoutView.swift b/spark/Demo/Classes/View/Layout/LayoutView.swift new file mode 100644 index 000000000..0541cb875 --- /dev/null +++ b/spark/Demo/Classes/View/Layout/LayoutView.swift @@ -0,0 +1,30 @@ +// +// LayoutView.swift +// SparkDemo +// +// Created by luis.figueiredo-ext on 08/02/2023. +// + +import SwiftUI + +struct LayoutView: View { + + // MARK: - Properties + + private let viewModel = LayoutViewModel() + + // MARK: - View + + var body: some View { + List(self.viewModel.spacingItemViewModels, id: \.self) { + LayoutSpacingItemView(viewModel: $0) + } + .navigationBarTitle(Text("Layout")) + } +} + +struct LayoutView_Previews: PreviewProvider { + static var previews: some View { + LayoutView() + } +} diff --git a/spark/Demo/Classes/View/Layout/LayoutViewModel.swift b/spark/Demo/Classes/View/Layout/LayoutViewModel.swift new file mode 100644 index 000000000..d04a5b0f4 --- /dev/null +++ b/spark/Demo/Classes/View/Layout/LayoutViewModel.swift @@ -0,0 +1,30 @@ +// +// LayoutViewModel.swift +// SparkDemo +// +// Created by robin.lemaire on 01/03/2023. +// + +import SparkCore + +struct LayoutViewModel { + + // MARK: - Properties + + let spacingItemViewModels: [LayoutSpacingItemViewModel] + + // MARK: - Initialization + + init() { + let layout = CurrentTheme.part.layout + + self.spacingItemViewModels = [ + .init(name: "none", value: layout.spacing.none), + .init(name: "small", value: layout.spacing.small), + .init(name: "medium", value: layout.spacing.medium), + .init(name: "large", value: layout.spacing.large), + .init(name: "xLarge", value: layout.spacing.xLarge), + .init(name: "xxLarge", value: layout.spacing.xxLarge) + ] + } +} diff --git a/spark/Demo/Classes/View/Main/MainView.swift b/spark/Demo/Classes/View/Main/MainView.swift new file mode 100644 index 000000000..327612137 --- /dev/null +++ b/spark/Demo/Classes/View/Main/MainView.swift @@ -0,0 +1,39 @@ +// +// MainView.swift +// SparkDemo +// +// Created by robin.lemaire on 02/03/2023. +// + +import SwiftUI + +struct MainView: View { + var body: some View { + NavigationView { + List { + NavigationLink("Border") { + BorderView() + } + + NavigationLink("Color") { + ColorView() + } + + NavigationLink("Layout") { + LayoutView() + } + + NavigationLink("Typography") { + TypographyView() + } + } + .navigationBarTitle(Text("Spark")) + } + } +} + +struct MainView_Previews: PreviewProvider { + static var previews: some View { + MainView() + } +} diff --git a/spark/Demo/Classes/View/Typography/TypographyItemView.swift b/spark/Demo/Classes/View/Typography/TypographyItemView.swift new file mode 100644 index 000000000..b86b6cc3c --- /dev/null +++ b/spark/Demo/Classes/View/Typography/TypographyItemView.swift @@ -0,0 +1,37 @@ +// +// TypographyItemView.swift +// SparkDemo +// +// Created by robin.lemaire on 01/03/2023. +// + +import SwiftUI +import SparkCore + +struct TypographyItemView: View { + + // MARK: - Properties + + let viewModel: TypographyItemViewModel + + // MARK: - View + + var body: some View { + VStack(alignment: .leading) { + Text(self.viewModel.name) + .font(self.viewModel.font) + Text(self.viewModel.description) + .font(Font.caption2) + .italic() + .foregroundColor(.gray) + } + } +} + +struct TypographyItemView_Previews: PreviewProvider { + static var previews: some View { + TypographyItemView(viewModel: .init(name: "Title", + typographyFont: TypographyFontDefault(font: .systemFont(ofSize: 12), + swiftUIFont: .body))) + } +} diff --git a/spark/Demo/Classes/View/Typography/TypographyItemViewModel.swift b/spark/Demo/Classes/View/Typography/TypographyItemViewModel.swift new file mode 100644 index 000000000..066ce2cc3 --- /dev/null +++ b/spark/Demo/Classes/View/Typography/TypographyItemViewModel.swift @@ -0,0 +1,27 @@ +// +// TypographyItemViewModel.swift +// SparkDemo +// +// Created by robin.lemaire on 01/03/2023. +// + +import SparkCore +import SwiftUI + +struct TypographyItemViewModel: Hashable { + + // MARK: - Properties + + let name: String + let description: String + let font: Font + + // MARK: - Initialization + + init(name: String, + typographyFont: TypographyFont) { + self.name = name + self.description = typographyFont.font.fontName + "\(Int(typographyFont.font.pointSize))" + self.font = typographyFont.swiftUIFont + } +} diff --git a/spark/Demo/Classes/View/Typography/TypographyView.swift b/spark/Demo/Classes/View/Typography/TypographyView.swift new file mode 100644 index 000000000..fe13548fd --- /dev/null +++ b/spark/Demo/Classes/View/Typography/TypographyView.swift @@ -0,0 +1,34 @@ +// +// TypographyView.swift +// SparkDemo +// +// Created by luis.figueiredo-ext on 08/02/2023. +// + +import SwiftUI + +struct TypographyView: View { + + // MARK: - Properties + + private let viewModel = TypographyViewModel() + + // MARK: - View + + var body: some View { + List(self.viewModel.itemViewModels, id: \.self) { itemViewModels in + Section { + ForEach(itemViewModels, id: \.self) { itemViewModel in + TypographyItemView(viewModel: itemViewModel) + } + } + } + .navigationBarTitle(Text("Typography")) + } +} + +struct TypographyView_Previews: PreviewProvider { + static var previews: some View { + TypographyView() + } +} diff --git a/spark/Demo/Classes/View/Typography/TypographyViewModel.swift b/spark/Demo/Classes/View/Typography/TypographyViewModel.swift new file mode 100644 index 000000000..70d179b0e --- /dev/null +++ b/spark/Demo/Classes/View/Typography/TypographyViewModel.swift @@ -0,0 +1,52 @@ +// +// TypographyViewModel.swift +// SparkDemo +// +// Created by robin.lemaire on 01/03/2023. +// + +import SparkCore + +struct TypographyViewModel { + + // MARK: - Properties + + let itemViewModels: [[TypographyItemViewModel]] + + // MARK: - Initialization + + init() { + let typographies = CurrentTheme.part.typography + self.itemViewModels = [ + [ + .init(name: "display1", typographyFont: typographies.display1), + .init(name: "display2", typographyFont: typographies.display2), + .init(name: "display3", typographyFont: typographies.display3) + ], + [ + .init(name: "headline1", typographyFont: typographies.headline1), + .init(name: "headline2", typographyFont: typographies.headline2) + ], + [ + .init(name: "subhead", typographyFont: typographies.subhead) + ], + [ + .init(name: "body1", typographyFont: typographies.body1), + .init(name: "body1Highlight", typographyFont: typographies.body1Highlight), + .init(name: "body2", typographyFont: typographies.body2), + .init(name: "body2Highlight", typographyFont: typographies.body2Highlight) + ], + [ + .init(name: "caption", typographyFont: typographies.caption), + .init(name: "captionHighlight", typographyFont: typographies.captionHighlight) + ], + [ + .init(name: "small", typographyFont: typographies.small), + .init(name: "smallHighlight", typographyFont: typographies.smallHighlight) + ], + [ + .init(name: "callout", typographyFont: typographies.callout) + ] + ] + } +} diff --git a/spark/Demo/Info.plist b/spark/Demo/Info.plist deleted file mode 100644 index 2f2f77534..000000000 --- a/spark/Demo/Info.plist +++ /dev/null @@ -1,29 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - UIApplicationSceneManifest - - UIApplicationSupportsMultipleScenes - - UISceneConfigurations - - - - diff --git a/spark/Sources/Info.plist b/spark/Sources/Info.plist deleted file mode 100644 index 323e5ecfc..000000000 --- a/spark/Sources/Info.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - - diff --git a/spark/Sources/Resources/Colors.xcassets/Primary.colorset/Contents.json b/spark/Sources/Resources/Colors.xcassets/Primary.colorset/Contents.json new file mode 100644 index 000000000..277532cbf --- /dev/null +++ b/spark/Sources/Resources/Colors.xcassets/Primary.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x2B", + "green" : "0x6C", + "red" : "0x99" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x50", + "green" : "0xB6", + "red" : "0xA1" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/spark/Sources/Resources/Colors.xcassets/Secondary.colorset/Contents.json b/spark/Sources/Resources/Colors.xcassets/Secondary.colorset/Contents.json new file mode 100644 index 000000000..572d3f50b --- /dev/null +++ b/spark/Sources/Resources/Colors.xcassets/Secondary.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x4F", + "green" : "0x34", + "red" : "0x86" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xCC", + "green" : "0xAB", + "red" : "0x66" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/spark/Sources/Resources/Font/NunitoSans-Bold.ttf b/spark/Sources/Resources/Font/NunitoSans-Bold.ttf new file mode 100644 index 000000000..fb01ae356 Binary files /dev/null and b/spark/Sources/Resources/Font/NunitoSans-Bold.ttf differ diff --git a/spark/Sources/Resources/Font/NunitoSans-Regular.ttf b/spark/Sources/Resources/Font/NunitoSans-Regular.ttf new file mode 100644 index 000000000..ac7162d83 Binary files /dev/null and b/spark/Sources/Resources/Font/NunitoSans-Regular.ttf differ diff --git a/spark/Sources/Resources/Generated/Colors+Generated.swift b/spark/Sources/Resources/Generated/Colors+Generated.swift index 0eb48373f..82768dbf8 100644 --- a/spark/Sources/Resources/Generated/Colors+Generated.swift +++ b/spark/Sources/Resources/Generated/Colors+Generated.swift @@ -13,6 +13,8 @@ #endif // Deprecated typealiases +@available(*, deprecated, renamed: "ColorAsset.Color", message: "This typealias will be removed in SwiftGen 7.0") +public typealias AssetColorTypeAlias = ColorAsset.Color // swiftlint:disable superfluous_disable_command file_length implicit_return @@ -20,11 +22,77 @@ // swiftlint:disable identifier_name line_length nesting type_body_length type_name public enum SparkColorAsset { + public static let primary = ColorAsset(name: "Primary") + public static let secondary = ColorAsset(name: "Secondary") } // swiftlint:enable identifier_name line_length nesting type_body_length type_name // MARK: - Implementation Details +public final class ColorAsset { + public fileprivate(set) var name: String + + #if os(macOS) + public typealias Color = NSColor + #elseif os(iOS) || os(tvOS) || os(watchOS) + public typealias Color = UIColor + #endif + + @available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, *) + public private(set) lazy var color: Color = { + guard let color = Color(asset: self) else { + fatalError("Unable to load color asset named \(name).") + } + return color + }() + + #if os(iOS) || os(tvOS) + @available(iOS 11.0, tvOS 11.0, *) + public func color(compatibleWith traitCollection: UITraitCollection) -> Color { + let bundle = BundleToken.bundle + guard let color = Color(named: name, in: bundle, compatibleWith: traitCollection) else { + fatalError("Unable to load color asset named \(name).") + } + return color + } + #endif + + #if canImport(SwiftUI) + @available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *) + public private(set) lazy var swiftUIColor: SwiftUI.Color = { + SwiftUI.Color(asset: self) + }() + #endif + + fileprivate init(name: String) { + self.name = name + } +} + +public extension ColorAsset.Color { + @available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, *) + convenience init?(asset: ColorAsset) { + let bundle = BundleToken.bundle + #if os(iOS) || os(tvOS) + self.init(named: asset.name, in: bundle, compatibleWith: nil) + #elseif os(macOS) + self.init(named: NSColor.Name(asset.name), bundle: bundle) + #elseif os(watchOS) + self.init(named: asset.name) + #endif + } +} + +#if canImport(SwiftUI) +@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *) +public extension SwiftUI.Color { + init(asset: ColorAsset) { + let bundle = BundleToken.bundle + self.init(asset.name, bundle: bundle) + } +} +#endif + // swiftlint:disable convenience_type private final class BundleToken { static let bundle: Bundle = { diff --git a/spark/Sources/Theming/Content/SparkBorder.swift b/spark/Sources/Theming/Content/SparkBorder.swift new file mode 100644 index 000000000..85adacd82 --- /dev/null +++ b/spark/Sources/Theming/Content/SparkBorder.swift @@ -0,0 +1,20 @@ +// +// SparkTheme.swift +// Spark +// +// Created by robin.lemaire on 28/02/2023. +// + +import SparkCore + +struct SparkBorder: Border { + + // MARK: - Properties + + let width: BorderWidth = BorderWidthDefault(small: 1, + medium: 2) + let radius: BorderRadius = BorderRadiusDefault(small: 4, + medium: 8, + large: 16, + xLarge: 24) +} diff --git a/spark/Sources/Theming/Content/SparkColors.swift b/spark/Sources/Theming/Content/SparkColors.swift new file mode 100644 index 000000000..b976bfd7e --- /dev/null +++ b/spark/Sources/Theming/Content/SparkColors.swift @@ -0,0 +1,173 @@ +// +// SparkColors.swift +// Spark +// +// Created by robin.lemaire on 28/02/2023. +// + +import SparkCore + +// TODO: + +struct SparkColors: Colors { + + // MARK: - Properties + + let primary: ColorToken = ColorTokenDefault(enabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + pressed: ColorTokenValueDefault(uiColor: .blue, + swiftUIcolor: .blue), + disabled: ColorTokenValueDefault(uiColor: .green, + swiftUIcolor: .green), + on: ColorTokenValueDefault(uiColor: .yellow, + swiftUIcolor: .yellow)) + let primaryVariant: ColorToken = ColorTokenDefault(enabled: ColorTokenValueDefault(uiColor: .yellow, + swiftUIcolor: .yellow), + pressed: ColorTokenValueDefault(uiColor: .red, + swiftUIcolor: .red), + disabled: ColorTokenValueDefault(uiColor: .purple, + swiftUIcolor: .purple), + on: ColorTokenValueDefault(uiColor: .gray, + swiftUIcolor: .gray)) + + let secondary: ColorToken = ColorTokenDefault(enabled: ColorTokenValueDefault(uiColor: .black, + swiftUIcolor: .black), + pressed: ColorTokenValueDefault(uiColor: .white, + swiftUIcolor: .white), + disabled: ColorTokenValueDefault(uiColor: .red, + swiftUIcolor: .red), + on: ColorTokenValueDefault(uiColor: .yellow, + swiftUIcolor: .yellow)) + let secondaryVariant: ColorToken = ColorTokenDefault(enabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + pressed: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + disabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + on: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange)) + + let background: ColorToken = ColorTokenDefault(enabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + pressed: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + disabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + on: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange)) + + let surface: ColorToken = ColorTokenDefault(enabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + pressed: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + disabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + on: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange)) + let surfaceInverse: ColorToken = ColorTokenDefault(enabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + pressed: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + disabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + on: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange)) + + let success: ColorToken = ColorTokenDefault(enabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + pressed: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + disabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + on: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange)) + let alert: ColorToken = ColorTokenDefault(enabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + pressed: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + disabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + on: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange)) + let error: ColorToken = ColorTokenDefault(enabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + pressed: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + disabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + on: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange)) + let info: ColorToken = ColorTokenDefault(enabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + pressed: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + disabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + on: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange)) + let neutral: ColorToken = ColorTokenDefault(enabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + pressed: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + disabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + on: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange)) + + let primaryContainer: ColorToken = ColorTokenDefault(enabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + pressed: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + disabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + on: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange)) + let secondaryContainer: ColorToken = ColorTokenDefault(enabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + pressed: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + disabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + on: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange)) + let successContainer: ColorToken = ColorTokenDefault(enabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + pressed: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + disabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + on: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange)) + let alertContainer: ColorToken = ColorTokenDefault(enabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + pressed: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + disabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + on: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange)) + let errorContainer: ColorToken = ColorTokenDefault(enabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + pressed: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + disabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + on: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange)) + let infoContainer: ColorToken = ColorTokenDefault(enabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + pressed: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + disabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + on: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange)) + let neutralContainer: ColorToken = ColorTokenDefault(enabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + pressed: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + disabled: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange), + on: ColorTokenValueDefault(uiColor: .orange, + swiftUIcolor: .orange)) +} diff --git a/spark/Sources/Theming/Content/SparkIconography.swift b/spark/Sources/Theming/Content/SparkIconography.swift new file mode 100644 index 000000000..ade66b5c0 --- /dev/null +++ b/spark/Sources/Theming/Content/SparkIconography.swift @@ -0,0 +1,14 @@ +// +// SparkIconography.swift +// Spark +// +// Created by robin.lemaire on 28/02/2023. +// + +import SparkCore + +struct SparkIconography: Iconography { + + // MARK: - Properties + +} diff --git a/spark/Sources/Theming/Content/SparkLayout.swift b/spark/Sources/Theming/Content/SparkLayout.swift new file mode 100644 index 000000000..9de3cedc2 --- /dev/null +++ b/spark/Sources/Theming/Content/SparkLayout.swift @@ -0,0 +1,20 @@ +// +// SparkLayout.swift +// Spark +// +// Created by robin.lemaire on 28/02/2023. +// + +import SparkCore + +struct SparkLayout: Layout { + + // MARK: - Properties + + let spacing: LayoutSpacing = LayoutSpacingDefault(small: 4, + medium: 8, + large: 16, + xLarge: 24, + xxLarge: 32, + xxxLarge: 40) +} diff --git a/spark/Sources/Theming/Content/SparkTypography.swift b/spark/Sources/Theming/Content/SparkTypography.swift new file mode 100644 index 000000000..2cee5e1c9 --- /dev/null +++ b/spark/Sources/Theming/Content/SparkTypography.swift @@ -0,0 +1,98 @@ +// +// SparkTypography.swift +// Spark +// +// Created by robin.lemaire on 28/02/2023. +// + +import Foundation +import SparkCore +import SwiftUI +import UIKit + +struct SparkTypography: Typography { + + // MARK: - Properties + + let display1: TypographyFont = TypographyFontDefault(size: 40, + isHighlight: true, + textStyle: .largeTitle) + let display2: TypographyFont = TypographyFontDefault(size: 32, + isHighlight: true, + textStyle: .largeTitle) + let display3: TypographyFont = TypographyFontDefault(size: 24, + isHighlight: true, + textStyle: .largeTitle) + + let headline1: TypographyFont = TypographyFontDefault(size: 20, + isHighlight: true, + textStyle: .headline) + let headline2: TypographyFont = TypographyFontDefault(size: 18, + isHighlight: true, + textStyle: .headline) + + let subhead: TypographyFont = TypographyFontDefault(size: 16, + isHighlight: true, + textStyle: .subheadline) + + let body1: TypographyFont = TypographyFontDefault(size: 16, + isHighlight: false, + textStyle: .body) + let body1Highlight: TypographyFont = TypographyFontDefault(size: 16, + isHighlight: true, + textStyle: .body) + + let body2: TypographyFont = TypographyFontDefault(size: 14, + isHighlight: false, + textStyle: .body) + let body2Highlight: TypographyFont = TypographyFontDefault(size: 14, + isHighlight: true, + textStyle: .body) + + let caption: TypographyFont = TypographyFontDefault(size: 12, + isHighlight: false, + textStyle: .caption) + let captionHighlight: TypographyFont = TypographyFontDefault(size: 12, + isHighlight: true, + textStyle: .caption) + + let small: TypographyFont = TypographyFontDefault(size: 10, + isHighlight: false, + textStyle: .footnote) + let smallHighlight: TypographyFont = TypographyFontDefault(size: 10, + isHighlight: true, + textStyle: .footnote) + + let callout: TypographyFont = TypographyFontDefault(size: 16, + isHighlight: true, + textStyle: .callout) +} + +// MARK: - TypographyFont Extension + +private extension TypographyFontDefault { + + // MARK: - Constants + + private enum Constants { + static let boldFontName = "NunitoSans-Bold" + static let regularFontName = "NunitoSans-Regular" + } + + // MARK: - Initialization + + init(size: CGFloat, + isHighlight: Bool, + textStyle: Font.TextStyle) { + // Properties + let fontName = isHighlight ? Constants.boldFontName : Constants.regularFontName + let fontWeight: UIFont.Weight = isHighlight ? .bold : .regular + + // Fonts + let font = UIFont(name: fontName, size: size) ?? .systemFont(ofSize: size, weight: fontWeight) + let swiftUIFont = Font.custom(fontName, size: size, relativeTo: textStyle) + + self.init(font: font, + swiftUIFont: swiftUIFont) + } +} diff --git a/spark/Sources/Theming/SparkConfiguration.swift b/spark/Sources/Theming/SparkConfiguration.swift new file mode 100644 index 000000000..49932f3a7 --- /dev/null +++ b/spark/Sources/Theming/SparkConfiguration.swift @@ -0,0 +1,23 @@ +// +// SparkConfiguration.swift +// Spark +// +// Created by robin.lemaire on 02/03/2023. +// + +import SparkCore +import Foundation +import UIKit + +public struct SparkConfiguration: Configuration { + + // MARK: - Subclass + + private class Class {} + + // MARK: - static func + + public static func load() { + Bundle(for: Class.self).registerAllFonts() + } +} diff --git a/spark/Sources/Theming/SparkCurrentTheme.swift b/spark/Sources/Theming/SparkCurrentTheme.swift new file mode 100644 index 000000000..922957be5 --- /dev/null +++ b/spark/Sources/Theming/SparkCurrentTheme.swift @@ -0,0 +1,15 @@ +// +// SparkCurrentTheme.swift +// Spark +// +// Created by robin.lemaire on 02/03/2023. +// + +import SparkCore + +public struct SparkCurrentTheme { + + // MARK: - Properties + + public static var theme: Theme = SparkTheme() +} diff --git a/spark/Sources/Theming/SparkTheme.swift b/spark/Sources/Theming/SparkTheme.swift new file mode 100644 index 000000000..4534f67f8 --- /dev/null +++ b/spark/Sources/Theming/SparkTheme.swift @@ -0,0 +1,20 @@ +// +// SparkTheme.swift +// Spark +// +// Created by robin.lemaire on 28/02/2023. +// + +import SparkCore +import Foundation + +struct SparkTheme: Theme { + + // MARK: - Properties + + let border: Border = SparkBorder() + let colors: Colors = SparkColors() + let iconography: Iconography = SparkIconography() + let layout: Layout = SparkLayout() + let typography: Typography = SparkTypography() +} diff --git a/spark/Unit-tests/Info.plist b/spark/Unit-tests/Info.plist deleted file mode 100644 index 6c40a6cd0..000000000 --- a/spark/Unit-tests/Info.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - - diff --git a/spark/Unit-tests/SparkTests.swift b/spark/Unit-tests/SparkTests.swift new file mode 100644 index 000000000..945eafcbb --- /dev/null +++ b/spark/Unit-tests/SparkTests.swift @@ -0,0 +1,15 @@ +// +// SparkTests.swift +// SparkCoreTests +// +// Created by louis.borlee on 08/03/2023. +// + +import XCTest + +final class SparkTests: XCTestCase { + + func test() { + XCTAssertTrue(true) + } +}