diff --git a/.gitignore b/.gitignore index 28dec87f7..b6db53bac 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,15 @@ xcuserdata/ *.dSYM.zip *.dSYM +## SwiftPM +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/config/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc + # fastlane # # It is recommended to not store the screenshots in the git repo. @@ -26,4 +35,4 @@ Tools/Scripts/element-android ## macOS Files .DS_Store -._* \ No newline at end of file +._* diff --git a/DesignKit/Sources/Buttons/PrimaryActionButtonStyle.swift b/DesignKit/Sources/Buttons/PrimaryActionButtonStyle.swift new file mode 100644 index 000000000..46bef181e --- /dev/null +++ b/DesignKit/Sources/Buttons/PrimaryActionButtonStyle.swift @@ -0,0 +1,83 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import SwiftUI +import DesignTokens + +public struct PrimaryActionButtonStyle: ButtonStyle { + @Environment(\.isEnabled) private var isEnabled + @Environment(\.colorScheme) private var colorScheme + + public var customColor: Color? + + private var fontColor: Color { + // Always white unless disabled with a dark theme. + .white.opacity(colorScheme == .dark && !isEnabled ? 0.3 : 1.0) + } + + private var backgroundColor: Color { + customColor ?? .element.accent + } + + public init(customColor: Color? = nil) { + self.customColor = customColor + } + + public func makeBody(configuration: Self.Configuration) -> some View { + configuration.label + .padding(12.0) + .frame(maxWidth: .infinity) + .foregroundColor(fontColor) + .font(.element.body) + .background(backgroundColor.opacity(backgroundOpacity(when: configuration.isPressed))) + .cornerRadius(8.0) + } + + private func backgroundOpacity(when isPressed: Bool) -> CGFloat { + guard isEnabled else { return 0.3 } + return isPressed ? 0.6 : 1.0 + } +} + +public struct PrimaryActionButtonStyle_Previews: PreviewProvider { + public static var states: some View { + VStack { + Button("Enabled") { /* preview */ } + .buttonStyle(PrimaryActionButtonStyle()) + + Button("Disabled") { /* preview */ } + .buttonStyle(PrimaryActionButtonStyle()) + .disabled(true) + + Button { /* preview */ } label: { + Text("Clear BG") + .foregroundColor(.element.alert) + } + .buttonStyle(PrimaryActionButtonStyle(customColor: .clear)) + + Button("Red BG") { /* preview */ } + .buttonStyle(PrimaryActionButtonStyle(customColor: .element.alert)) + } + .padding() + } + + public static var previews: some View { + states + .preferredColorScheme(.light) + states + .preferredColorScheme(.dark) + } +} diff --git a/DesignKit/Sources/Buttons/SecondaryActionButtonStyle.swift b/DesignKit/Sources/Buttons/SecondaryActionButtonStyle.swift new file mode 100644 index 000000000..1329e8985 --- /dev/null +++ b/DesignKit/Sources/Buttons/SecondaryActionButtonStyle.swift @@ -0,0 +1,82 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import SwiftUI +import DesignTokens + +public struct SecondaryActionButtonStyle: ButtonStyle { + @Environment(\.isEnabled) private var isEnabled + + public var customColor: Color? + + public init(customColor: Color? = nil) { + self.customColor = customColor + } + + public func makeBody(configuration: Self.Configuration) -> some View { + configuration.label + .padding(12.0) + .frame(maxWidth: .infinity) + .foregroundColor(strokeColor(configuration.isPressed)) + .font(.element.body) + .background(RoundedRectangle(cornerRadius: 8) + .strokeBorder() + .foregroundColor(strokeColor(configuration.isPressed))) + .opacity(isEnabled ? 1.0 : 0.6) + } + + private func strokeColor(_ isPressed: Bool) -> Color { + if let customColor = customColor { + return customColor + } + + return isPressed ? .element.accent.opacity(0.6) : .element.accent + } +} + +public struct SecondaryActionButtonStyle_Previews: PreviewProvider { + public static var previews: some View { + Group { + states + } + .preferredColorScheme(.light) + Group { + states + } + .preferredColorScheme(.dark) + } + + public static var states: some View { + VStack { + Button("Enabled") { /* preview */ } + .buttonStyle(SecondaryActionButtonStyle()) + + Button("Disabled") { /* preview */ } + .buttonStyle(SecondaryActionButtonStyle()) + .disabled(true) + + Button { /* preview */ } label: { + Text("Clear BG") + .foregroundColor(.element.alert) + } + .buttonStyle(SecondaryActionButtonStyle(customColor: .clear)) + + Button("Red BG") { /* preview */ } + .buttonStyle(SecondaryActionButtonStyle(customColor: .element.alert)) + } + .padding() + } +} diff --git a/DesignKit/Sources/Fonts/ElementFonts.swift b/DesignKit/Sources/Fonts/ElementFonts.swift new file mode 100644 index 000000000..bdddbf88b --- /dev/null +++ b/DesignKit/Sources/Fonts/ElementFonts.swift @@ -0,0 +1,69 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import SwiftUI + +public extension Font { + /// The fonts used by Element as defined in https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=1362%3A0 + static let element = ElementFonts(values: ElementSharedFonts()) +} + +/// Struct for holding fonts for use in SwiftUI. +public struct ElementFonts: Fonts { + public let largeTitle: Font + public let largeTitleB: Font + public let title1: Font + public let title1B: Font + public let title2: Font + public let title2B: Font + public let title3: Font + public let title3SB: Font + public let headline: Font + public let subheadline: Font + public let body: Font + public let bodySB: Font + public let callout: Font + public let calloutSB: Font + public let footnote: Font + public let footnoteSB: Font + public let caption1: Font + public let caption1SB: Font + public let caption2: Font + public let caption2SB: Font + + public init(values: ElementSharedFonts) { + largeTitle = values.largeTitle.font + largeTitleB = values.largeTitleB.font + title1 = values.title1.font + title1B = values.title1B.font + title2 = values.title2.font + title2B = values.title2B.font + title3 = values.title3.font + title3SB = values.title3SB.font + headline = values.headline.font + subheadline = values.subheadline.font + body = values.body.font + bodySB = values.bodySB.font + callout = values.callout.font + calloutSB = values.calloutSB.font + footnote = values.footnote.font + footnoteSB = values.footnoteSB.font + caption1 = values.caption1.font + caption1SB = values.caption1SB.font + caption2 = values.caption2.font + caption2SB = values.caption2SB.font + } +} diff --git a/DesignKit/Sources/Fonts/ElementSharedFonts.swift b/DesignKit/Sources/Fonts/ElementSharedFonts.swift new file mode 100644 index 000000000..2fb05db2f --- /dev/null +++ b/DesignKit/Sources/Fonts/ElementSharedFonts.swift @@ -0,0 +1,145 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import SwiftUI + +/// Fonts at https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=1362%3A0 +@objcMembers +public class ElementSharedFonts { + + // MARK: - Types + + /// A wrapper to provide both a `UIFont` and a SwiftUI `Font` in the same type. + /// The need for this comes from `Font` not adapting for dynamic type until the app + /// is restarted (or working at all in Xcode Previews) when initialised from a `UIFont` + /// (even if that font was created with the appropriate metrics). + public struct SharedFont { + public let uiFont: UIFont + public let font: Font + } + + // MARK: - Private + + /// Returns an instance of the font associated with the text style and scaled appropriately for the content size category defined in the trait collection. + /// Keep this method private method at the moment and create a DesignKit.Fonts.TextStyle if needed. + fileprivate func font(forTextStyle textStyle: UIFont.TextStyle, compatibleWith traitCollection: UITraitCollection? = nil) -> UIFont { + return UIFont.preferredFont(forTextStyle: textStyle, compatibleWith: traitCollection) + } +} + +// MARK: - Fonts protocol +extension ElementSharedFonts { + + public var largeTitle: SharedFont { + let uiFont = font(forTextStyle: .largeTitle) + return SharedFont(uiFont: uiFont, font: .largeTitle) + } + + public var largeTitleB: SharedFont { + let uiFont = largeTitle.uiFont.bold + return SharedFont(uiFont: uiFont, font: .largeTitle.bold()) + } + + public var title1: SharedFont { + let uiFont = font(forTextStyle: .title1) + return SharedFont(uiFont: uiFont, font: .title) + } + + public var title1B: SharedFont { + let uiFont = title1.uiFont.bold + return SharedFont(uiFont: uiFont, font: .title.bold()) + } + + public var title2: SharedFont { + let uiFont = font(forTextStyle: .title2) + return SharedFont(uiFont: uiFont, font: .title2) + } + + public var title2B: SharedFont { + let uiFont = title2.uiFont.bold + return SharedFont(uiFont: uiFont, font: .title2.bold()) + } + + public var title3: SharedFont { + let uiFont = font(forTextStyle: .title3) + return SharedFont(uiFont: uiFont, font: .title3) + } + + public var title3SB: SharedFont { + let uiFont = title3.uiFont.semiBold + return SharedFont(uiFont: uiFont, font: .title3.weight(.semibold)) + } + + public var headline: SharedFont { + let uiFont = font(forTextStyle: .headline) + return SharedFont(uiFont: uiFont, font: .headline) + } + + public var subheadline: SharedFont { + let uiFont = font(forTextStyle: .subheadline) + return SharedFont(uiFont: uiFont, font: .subheadline) + } + + public var body: SharedFont { + let uiFont = font(forTextStyle: .body) + return SharedFont(uiFont: uiFont, font: .body) + } + + public var bodySB: SharedFont { + let uiFont = body.uiFont.semiBold + return SharedFont(uiFont: uiFont, font: .body.weight(.semibold)) + } + + public var callout: SharedFont { + let uiFont = font(forTextStyle: .callout) + return SharedFont(uiFont: uiFont, font: .callout) + } + + public var calloutSB: SharedFont { + let uiFont = callout.uiFont.semiBold + return SharedFont(uiFont: uiFont, font: .callout.weight(.semibold)) + } + + public var footnote: SharedFont { + let uiFont = font(forTextStyle: .footnote) + return SharedFont(uiFont: uiFont, font: .footnote) + } + + public var footnoteSB: SharedFont { + let uiFont = footnote.uiFont.semiBold + return SharedFont(uiFont: uiFont, font: .footnote.weight(.semibold)) + } + + public var caption1: SharedFont { + let uiFont = font(forTextStyle: .caption1) + return SharedFont(uiFont: uiFont, font: .caption) + } + + public var caption1SB: SharedFont { + let uiFont = caption1.uiFont.semiBold + return SharedFont(uiFont: uiFont, font: .caption.weight(.semibold)) + } + + public var caption2: SharedFont { + let uiFont = font(forTextStyle: .caption2) + return SharedFont(uiFont: uiFont, font: .caption2) + } + + public var caption2SB: SharedFont { + let uiFont = caption2.uiFont.semiBold + return SharedFont(uiFont: uiFont, font: .caption2.weight(.semibold)) + } +} diff --git a/DesignKit/Sources/Fonts/ElementUIFonts.swift b/DesignKit/Sources/Fonts/ElementUIFonts.swift new file mode 100644 index 000000000..fb181f50e --- /dev/null +++ b/DesignKit/Sources/Fonts/ElementUIFonts.swift @@ -0,0 +1,69 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import UIKit + +public extension UIFont { + /// The fonts used by Element as defined in https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=1362%3A0 + @objc static let element = ElementUIFonts(values: ElementSharedFonts()) +} + +/// ObjC class for holding fonts for use in UIKit. +@objcMembers public class ElementUIFonts: NSObject, Fonts { + public let largeTitle: UIFont + public let largeTitleB: UIFont + public let title1: UIFont + public let title1B: UIFont + public let title2: UIFont + public let title2B: UIFont + public let title3: UIFont + public let title3SB: UIFont + public let headline: UIFont + public let subheadline: UIFont + public let body: UIFont + public let bodySB: UIFont + public let callout: UIFont + public let calloutSB: UIFont + public let footnote: UIFont + public let footnoteSB: UIFont + public let caption1: UIFont + public let caption1SB: UIFont + public let caption2: UIFont + public let caption2SB: UIFont + + public init(values: ElementSharedFonts) { + largeTitle = values.largeTitle.uiFont + largeTitleB = values.largeTitleB.uiFont + title1 = values.title1.uiFont + title1B = values.title1B.uiFont + title2 = values.title2.uiFont + title2B = values.title2B.uiFont + title3 = values.title3.uiFont + title3SB = values.title3SB.uiFont + headline = values.headline.uiFont + subheadline = values.subheadline.uiFont + body = values.body.uiFont + bodySB = values.bodySB.uiFont + callout = values.callout.uiFont + calloutSB = values.calloutSB.uiFont + footnote = values.footnote.uiFont + footnoteSB = values.footnoteSB.uiFont + caption1 = values.caption1.uiFont + caption1SB = values.caption1SB.uiFont + caption2 = values.caption2.uiFont + caption2SB = values.caption2SB.uiFont + } +} diff --git a/DesignKit/Sources/Fonts/Fonts.swift b/DesignKit/Sources/Fonts/Fonts.swift new file mode 100644 index 000000000..faa2b3132 --- /dev/null +++ b/DesignKit/Sources/Fonts/Fonts.swift @@ -0,0 +1,85 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +/// Describe fonts used in the application. +/// Font names are based on Element typography https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=1362%3A0 which is based on Apple font text styles (UIFont.TextStyle): https://developer.apple.com/documentation/uikit/uifonttextstyle +/// Create a custom TextStyle enum (like DesignKit.Fonts.TextStyle) is also a possibility +public protocol Fonts { + + associatedtype FontType + + /// The font for large titles. + var largeTitle: FontType { get } + + /// `largeTitle` with a Bold weight. + var largeTitleB: FontType { get } + + /// The font for first-level hierarchical headings. + var title1: FontType { get } + + /// `title1` with a Bold weight. + var title1B: FontType { get } + + /// The font for second-level hierarchical headings. + var title2: FontType { get } + + /// `title2` with a Bold weight. + var title2B: FontType { get } + + /// The font for third-level hierarchical headings. + var title3: FontType { get } + + /// `title3` with a Semi Bold weight. + var title3SB: FontType { get } + + /// The font for headings. + var headline: FontType { get } + + /// The font for subheadings. + var subheadline: FontType { get } + + /// The font for body text. + var body: FontType { get } + + /// `body` with a Semi Bold weight. + var bodySB: FontType { get } + + /// The font for callouts. + var callout: FontType { get } + + /// `callout` with a Semi Bold weight. + var calloutSB: FontType { get } + + /// The font for footnotes. + var footnote: FontType { get } + + /// `footnote` with a Semi Bold weight. + var footnoteSB: FontType { get } + + /// The font for standard captions. + var caption1: FontType { get } + + /// `caption1` with a Semi Bold weight. + var caption1SB: FontType { get } + + /// The font for alternate captions. + var caption2: FontType { get } + + /// `caption2` with a Semi Bold weight. + var caption2SB: FontType { get } +} diff --git a/DesignKit/Sources/Fonts/UIFont.swift b/DesignKit/Sources/Fonts/UIFont.swift new file mode 100644 index 000000000..7d8ad6d77 --- /dev/null +++ b/DesignKit/Sources/Fonts/UIFont.swift @@ -0,0 +1,57 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import UIKit + +public extension UIFont { + + // MARK: - Convenient methods + + /// Update current font with a SymbolicTraits + func withTraits(_ traits: UIFontDescriptor.SymbolicTraits) -> UIFont { + guard let descriptor = fontDescriptor.withSymbolicTraits(traits) else { + return self + } + + // Size 0 means keep the size as it is + return UIFont(descriptor: descriptor, size: 0) + } + + /// Update current font with a given Weight + func withWeight(weight: Weight) -> UIFont { + // Add the font weight to the descriptor + let weightedFontDescriptor = fontDescriptor.addingAttributes([ + UIFontDescriptor.AttributeName.traits: [ + UIFontDescriptor.TraitKey.weight: weight + ] + ]) + return UIFont(descriptor: weightedFontDescriptor, size: 0) + } + + // MARK: - Shortcuts + + var bold: UIFont { + return withTraits(.traitBold) + } + + var semiBold: UIFont { + return withWeight(weight: .semibold) + } + + var italic: UIFont { + return withTraits(.traitItalic) + } +} diff --git a/DesignKit/Sources/TextFields/BorderedInputFieldStyle.swift b/DesignKit/Sources/TextFields/BorderedInputFieldStyle.swift new file mode 100644 index 000000000..fc138802a --- /dev/null +++ b/DesignKit/Sources/TextFields/BorderedInputFieldStyle.swift @@ -0,0 +1,125 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import SwiftUI +import DesignTokens +import Introspect + +/// A bordered style of text input +/// +/// As defined in: +/// https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=2039%3A26415 +public struct BorderedInputFieldStyle: TextFieldStyle { + @Environment(\.isEnabled) var isEnabled + @Environment(\.colorScheme) var colorScheme + + public var isEditing: Bool + public var isError: Bool + + private var borderColor: Color { + if isError { + return .element.alert + } else if isEditing { + return .element.accent + } else { + return .element.quinaryContent + } + } + + private var accentColor: Color { + if isError { + return .element.alert + } + return .element.accent + } + + private var textColor: Color { + if colorScheme == .dark { + return isEnabled ? .element.primaryContent : .element.tertiaryContent + } else { + return isEnabled ? .element.primaryContent : .element.quaternaryContent + } + } + + private var backgroundColor: Color { + if !isEnabled && colorScheme == .dark { + return .element.quinaryContent + } + return .element.background + } + + private var placeholderColor: Color { + return .element.tertiaryContent + } + + private var borderWidth: CGFloat { + return isEditing || isError ? 2.0 : 1.5 + } + + public init(isEditing: Bool = false, isError: Bool = false) { + self.isEditing = isEditing + self.isError = isError + } + + public func _body(configuration: TextField<_Label>) -> some View { + let rect = RoundedRectangle(cornerRadius: 8.0) + return configuration + .font(.element.callout) + .foregroundColor(textColor) + .accentColor(accentColor) + .frame(height: 48.0) + .padding(.horizontal, 8.0) + .background(backgroundColor) + .clipShape(rect) + .overlay(rect.stroke(borderColor, lineWidth: borderWidth)) + .introspectTextField { textField in + textField.returnKeyType = .done + textField.clearButtonMode = .whileEditing + textField.attributedPlaceholder = NSAttributedString(string: textField.placeholder ?? "", + attributes: [NSAttributedString.Key.foregroundColor: UIColor(placeholderColor)]) + } + } +} + +public struct BorderedInputFieldStyle_Previews: PreviewProvider { + public static var states: some View { + VStack { + TextField("Placeholder", text: .constant("")) + .textFieldStyle(BorderedInputFieldStyle()) + TextField("Placeholder", text: .constant("")) + .textFieldStyle(BorderedInputFieldStyle(isEditing: true)) + TextField("Placeholder", text: .constant("Web")) + .textFieldStyle(BorderedInputFieldStyle()) + TextField("Placeholder", text: .constant("Web")) + .textFieldStyle(BorderedInputFieldStyle(isEditing: true)) + TextField("Placeholder", text: .constant("Web")) + .textFieldStyle(BorderedInputFieldStyle()) + .disabled(true) + TextField("Placeholder", text: .constant("Web")) + .textFieldStyle(BorderedInputFieldStyle(isEditing: true, isError: true)) + } + .padding() + } + + public static var previews: some View { + Group { + states + .preferredColorScheme(.light) + states + .preferredColorScheme(.dark) + } + } +} diff --git a/DesignKit/Sources/TextFields/RoundedCornerShape.swift b/DesignKit/Sources/TextFields/RoundedCornerShape.swift new file mode 100644 index 000000000..8b51cc9c5 --- /dev/null +++ b/DesignKit/Sources/TextFields/RoundedCornerShape.swift @@ -0,0 +1,28 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import SwiftUI + +struct RoundedCornerShape: Shape { + + let radius: CGFloat + let corners: UIRectCorner + + func path(in rect: CGRect) -> Path { + let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius)) + return Path(path.cgPath) + } +} diff --git a/DesignKitTests/DesignKitTests.swift b/DesignKitTests/DesignKitTests.swift new file mode 100644 index 000000000..a38bdac68 --- /dev/null +++ b/DesignKitTests/DesignKitTests.swift @@ -0,0 +1,8 @@ +import XCTest +@testable import DesignKit + +final class DesignKitTests: XCTestCase { + func testExample() throws { + XCTAssert(true) + } +} diff --git a/Package.resolved b/Package.resolved new file mode 100644 index 000000000..36260626b --- /dev/null +++ b/Package.resolved @@ -0,0 +1,23 @@ +{ + "pins" : [ + { + "identity" : "element-design-tokens", + "kind" : "remoteSourceControl", + "location" : "https://github.com/vector-im/element-design-tokens.git", + "state" : { + "branch" : "main", + "revision" : "ed45767113b703dad6e66d33ad7da388066504f8" + } + }, + { + "identity" : "swiftui-introspect", + "kind" : "remoteSourceControl", + "location" : "https://github.com/siteline/SwiftUI-Introspect.git", + "state" : { + "revision" : "f2616860a41f9d9932da412a8978fec79c06fe24", + "version" : "0.1.4" + } + } + ], + "version" : 2 +} diff --git a/Package.swift b/Package.swift new file mode 100644 index 000000000..2301e37bf --- /dev/null +++ b/Package.swift @@ -0,0 +1,27 @@ +// swift-tools-version: 5.6 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "DesignKit", + platforms: [.iOS(.v14)], + products: [ + .library(name: "DesignKit", targets: ["DesignKit"]) + ], + dependencies: [ + .package(url: "https://github.com/vector-im/element-design-tokens.git", branch: "main"), + .package(url: "https://github.com/siteline/SwiftUI-Introspect.git", .upToNextMajor(from: "0.1.4")) + ], + targets: [ + .target(name: "DesignKit", + dependencies: [ + .product(name: "DesignTokens", package: "element-design-tokens"), + .product(name: "Introspect", package: "SwiftUI-Introspect") + ], + path: "DesignKit"), + .testTarget(name: "DesignKitTests", + dependencies: ["DesignKit"], + path: "DesignKitTests") + ] +) diff --git a/changelog.d/43.feature b/changelog.d/43.feature new file mode 100644 index 000000000..4428e64ab --- /dev/null +++ b/changelog.d/43.feature @@ -0,0 +1 @@ +DesignKit: Add initial implementation of DesignKit to the repo as a Swift package.