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)
+ }
+}