Merge branch 'main' of github.com:swiftwasm/Tokamak into dark-mode

# Conflicts:
#	Sources/TokamakCore/Modifiers/FlexFrameLayout.swift
#	Sources/TokamakCore/Modifiers/ModifiedContent.swift
#	Sources/TokamakCore/Tokens/Color.swift
#	Sources/TokamakCore/Views/Text/Text.swift
#	Sources/TokamakDemo/TokamakDemo.swift
#	Sources/TokamakStaticHTML/Views/Containers/List.swift
This commit is contained in:
Max Desiatov 2020-08-05 17:44:29 +01:00
commit 487543d692
No known key found for this signature in database
GPG Key ID: FE08EBF9CF58CBA2
57 changed files with 1284 additions and 768 deletions

View File

@ -1,9 +1,12 @@
--indent 2
--indentcase false
--trimwhitespace always
--empty tuple
--voidtype tuple
--nospaceoperators ..<,...
--ifdef noindent
--stripunusedargs closure-only
--maxwidth 100
--wraparguments before-first
--funcattributes prev-line
--disable andOperator
--swiftversion 5.2
--swiftversion 5.3

View File

@ -9,6 +9,7 @@ disabled_rules:
- type_name
- todo
- large_tuple
- opening_brace
line_length: 100

View File

@ -1,4 +1,7 @@
{
"editor.formatOnSave": true,
"licenser.author": "Tokamak contributors"
"licenser.author": "Tokamak contributors",
"cSpell.words": [
"Tokamak"
]
}

View File

@ -200,18 +200,18 @@ appreciated and helps in maintaining the project.
### Coding Style
This project uses [SwiftFormat](https://github.com/nicklockwood/SwiftFormat)
and [SwiftLint](https://github.com/realm/SwiftLint) to
enforce formatting and coding style. We encourage you to run SwiftFormat within
a local clone of the repository in whatever way works best for you either
manually or automatically via an [Xcode
extension](https://github.com/nicklockwood/SwiftFormat#xcode-source-editor-extension),
[build phase](https://github.com/nicklockwood/SwiftFormat#xcode-build-phase) or
[git pre-commit
hook](https://github.com/nicklockwood/SwiftFormat#git-pre-commit-hook) etc.
This project uses [SwiftFormat](https://github.com/nicklockwood/SwiftFormat) and
[SwiftLint](https://github.com/realm/SwiftLint) to enforce formatting and coding style. SwiftFormat
0.45.3 and SwiftLint 0.39.2 or later versions are recommended. We encourage you to run SwiftFormat
and SwiftLint within a local clone of the repository in whatever way works best for you. You can do
that either manually, or automatically with VSCode extensions for
[SwiftFormat](https://github.com/vknabel/vscode-swiftformat) and
[SwiftLint](https://github.com/vknabel/vscode-swiftlint) respectively, or with the [Xcode
extension](https://github.com/nicklockwood/SwiftFormat#xcode-source-editor-extension), or [build
phase](https://github.com/nicklockwood/SwiftFormat#xcode-build-phase).
To guarantee that these tools run before you commit your changes on macOS, you're encouraged
to run this once to set up the [pre-commit](https://pre-commit.com/) hook:
To guarantee that these tools run before you commit your changes on macOS, you're encouraged to run
this once to set up the [pre-commit](https://pre-commit.com/) hook:
```
brew bundle # installs SwiftLint, SwiftFormat and pre-commit

View File

@ -54,9 +54,9 @@ import CombineShim
extension AppStorage: ObservedProperty {}
extension AppStorage {
public init(wrappedValue: Value,
_ key: String,
store: _StorageProvider? = nil) where Value == Bool {
public init(wrappedValue: Value, _ key: String, store: _StorageProvider? = nil)
where Value == Bool
{
defaultValue = wrappedValue
self.key = key
provider = store
@ -64,9 +64,9 @@ extension AppStorage {
read = { $0.read(key: $1) }
}
public init(wrappedValue: Value,
_ key: String,
store: _StorageProvider? = nil) where Value == Int {
public init(wrappedValue: Value, _ key: String, store: _StorageProvider? = nil)
where Value == Int
{
defaultValue = wrappedValue
self.key = key
provider = store
@ -74,9 +74,9 @@ extension AppStorage {
read = { $0.read(key: $1) }
}
public init(wrappedValue: Value,
_ key: String,
store: _StorageProvider? = nil) where Value == Double {
public init(wrappedValue: Value, _ key: String, store: _StorageProvider? = nil)
where Value == Double
{
defaultValue = wrappedValue
self.key = key
provider = store
@ -84,9 +84,9 @@ extension AppStorage {
read = { $0.read(key: $1) }
}
public init(wrappedValue: Value,
_ key: String,
store: _StorageProvider? = nil) where Value == String {
public init(wrappedValue: Value, _ key: String, store: _StorageProvider? = nil)
where Value == String
{
defaultValue = wrappedValue
self.key = key
provider = store
@ -94,10 +94,9 @@ extension AppStorage {
read = { $0.read(key: $1) }
}
public init(wrappedValue: Value,
_ key: String,
store: _StorageProvider? = nil)
where Value: RawRepresentable, Value.RawValue == Int {
public init(wrappedValue: Value, _ key: String, store: _StorageProvider? = nil)
where Value: RawRepresentable, Value.RawValue == Int
{
defaultValue = wrappedValue
self.key = key
provider = store
@ -110,10 +109,9 @@ extension AppStorage {
}
}
public init(wrappedValue: Value,
_ key: String,
store: _StorageProvider? = nil)
where Value: RawRepresentable, Value.RawValue == String {
public init(wrappedValue: Value, _ key: String, store: _StorageProvider? = nil)
where Value: RawRepresentable, Value.RawValue == String
{
defaultValue = wrappedValue
self.key = key
provider = store
@ -128,9 +126,9 @@ extension AppStorage {
}
extension AppStorage where Value: ExpressibleByNilLiteral {
public init(wrappedValue: Value,
_ key: String,
store: _StorageProvider? = nil) where Value == Bool? {
public init(wrappedValue: Value, _ key: String, store: _StorageProvider? = nil)
where Value == Bool?
{
defaultValue = wrappedValue
self.key = key
provider = store
@ -138,9 +136,9 @@ extension AppStorage where Value: ExpressibleByNilLiteral {
read = { $0.read(key: $1) }
}
public init(wrappedValue: Value,
_ key: String,
store: _StorageProvider? = nil) where Value == Int? {
public init(wrappedValue: Value, _ key: String, store: _StorageProvider? = nil)
where Value == Int?
{
defaultValue = wrappedValue
self.key = key
provider = store
@ -148,9 +146,9 @@ extension AppStorage where Value: ExpressibleByNilLiteral {
read = { $0.read(key: $1) }
}
public init(wrappedValue: Value,
_ key: String,
store: _StorageProvider? = nil) where Value == Double? {
public init(wrappedValue: Value, _ key: String, store: _StorageProvider? = nil)
where Value == Double?
{
defaultValue = wrappedValue
self.key = key
provider = store
@ -158,9 +156,9 @@ extension AppStorage where Value: ExpressibleByNilLiteral {
read = { $0.read(key: $1) }
}
public init(wrappedValue: Value,
_ key: String,
store: _StorageProvider? = nil) where Value == String? {
public init(wrappedValue: Value, _ key: String, store: _StorageProvider? = nil)
where Value == String?
{
defaultValue = wrappedValue
self.key = key
provider = store

View File

@ -22,60 +22,195 @@ public struct SceneBuilder {
}
}
// swiftlint:disable line_length
// swiftlint:disable large_tuple
// swiftlint:disable function_parameter_count
extension SceneBuilder {
public static func buildBlock<C0, C1>(_ c0: C0, _ c1: C1) -> some Scene where C0: Scene, C1: Scene {
public static func buildBlock<C0, C1>(_ c0: C0, _ c1: C1) -> some Scene where C0: Scene,
C1: Scene
{
_TupleScene((c0, c1), children: [_AnyScene(c0), _AnyScene(c1)])
}
}
extension SceneBuilder {
public static func buildBlock<C0, C1, C2>(_ c0: C0, _ c1: C1, _ c2: C2) -> some Scene where C0: Scene, C1: Scene, C2: Scene {
public static func buildBlock<C0, C1, C2>(_ c0: C0, _ c1: C1, _ c2: C2) -> some Scene
where C0: Scene, C1: Scene, C2: Scene
{
_TupleScene((c0, c1, c2), children: [_AnyScene(c0), _AnyScene(c1), _AnyScene(c2)])
}
}
extension SceneBuilder {
public static func buildBlock<C0, C1, C2, C3>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3) -> some Scene where C0: Scene, C1: Scene, C2: Scene, C3: Scene {
_TupleScene((c0, c1, c2, c3), children: [_AnyScene(c0), _AnyScene(c1), _AnyScene(c2), _AnyScene(c3)])
public static func buildBlock<C0, C1, C2, C3>(
_ c0: C0,
_ c1: C1,
_ c2: C2,
_ c3: C3
) -> some Scene where C0: Scene, C1: Scene, C2: Scene, C3: Scene {
_TupleScene(
(c0, c1, c2, c3),
children: [_AnyScene(c0), _AnyScene(c1), _AnyScene(c2), _AnyScene(c3)]
)
}
}
extension SceneBuilder {
public static func buildBlock<C0, C1, C2, C3, C4>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4) -> some Scene where C0: Scene, C1: Scene, C2: Scene, C3: Scene, C4: Scene {
_TupleScene((c0, c1, c2, c3, c4), children: [_AnyScene(c0), _AnyScene(c1), _AnyScene(c2), _AnyScene(c3), _AnyScene(c4)])
public static func buildBlock<C0, C1, C2, C3, C4>(
_ c0: C0,
_ c1: C1,
_ c2: C2,
_ c3: C3,
_ c4: C4
) -> some Scene where C0: Scene, C1: Scene, C2: Scene, C3: Scene, C4: Scene {
_TupleScene(
(c0, c1, c2, c3, c4),
children: [_AnyScene(c0), _AnyScene(c1), _AnyScene(c2), _AnyScene(c3), _AnyScene(c4)]
)
}
}
extension SceneBuilder {
public static func buildBlock<C0, C1, C2, C3, C4, C5>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4, _ c5: C5) -> some Scene where C0: Scene, C1: Scene, C2: Scene, C3: Scene, C4: Scene, C5: Scene {
_TupleScene((c0, c1, c2, c3, c4, c5), children: [_AnyScene(c0), _AnyScene(c1), _AnyScene(c2), _AnyScene(c3), _AnyScene(c4), _AnyScene(c5)])
public static func buildBlock<C0, C1, C2, C3, C4, C5>(
_ c0: C0,
_ c1: C1,
_ c2: C2,
_ c3: C3,
_ c4: C4,
_ c5: C5
) -> some Scene where C0: Scene, C1: Scene, C2: Scene, C3: Scene, C4: Scene,
C5: Scene
{
_TupleScene(
(c0, c1, c2, c3, c4, c5),
children: [
_AnyScene(c0),
_AnyScene(c1),
_AnyScene(c2),
_AnyScene(c3),
_AnyScene(c4),
_AnyScene(c5),
]
)
}
}
extension SceneBuilder {
public static func buildBlock<C0, C1, C2, C3, C4, C5, C6>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4, _ c5: C5, _ c6: C6) -> some Scene where C0: Scene, C1: Scene, C2: Scene, C3: Scene, C4: Scene, C5: Scene, C6: Scene {
_TupleScene((c0, c1, c2, c3, c4, c5, c6), children: [_AnyScene(c0), _AnyScene(c1), _AnyScene(c2), _AnyScene(c3), _AnyScene(c4), _AnyScene(c5), _AnyScene(c6)])
public static func buildBlock<C0, C1, C2, C3, C4, C5, C6>(
_ c0: C0,
_ c1: C1,
_ c2: C2,
_ c3: C3,
_ c4: C4,
_ c5: C5,
_ c6: C6
) -> some Scene where C0: Scene, C1: Scene, C2: Scene, C3: Scene,
C4: Scene, C5: Scene, C6: Scene
{
_TupleScene(
(c0, c1, c2, c3, c4, c5, c6),
children: [
_AnyScene(c0),
_AnyScene(c1),
_AnyScene(c2),
_AnyScene(c3),
_AnyScene(c4),
_AnyScene(c5),
_AnyScene(c6),
]
)
}
}
extension SceneBuilder {
public static func buildBlock<C0, C1, C2, C3, C4, C5, C6, C7>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4, _ c5: C5, _ c6: C6, _ c7: C7) -> some Scene where C0: Scene, C1: Scene, C2: Scene, C3: Scene, C4: Scene, C5: Scene, C6: Scene, C7: Scene {
_TupleScene((c0, c1, c2, c3, c4, c5, c6, c7), children: [_AnyScene(c0), _AnyScene(c1), _AnyScene(c2), _AnyScene(c3), _AnyScene(c4), _AnyScene(c5), _AnyScene(c6), _AnyScene(c7)])
public static func buildBlock<C0, C1, C2, C3, C4, C5, C6, C7>(
_ c0: C0,
_ c1: C1,
_ c2: C2,
_ c3: C3,
_ c4: C4,
_ c5: C5,
_ c6: C6,
_ c7: C7
) -> some Scene where C0: Scene, C1: Scene, C2: Scene, C3: Scene, C4: Scene, C5: Scene, C6: Scene,
C7: Scene
{
_TupleScene(
(c0, c1, c2, c3, c4, c5, c6, c7),
children: [
_AnyScene(c0),
_AnyScene(c1),
_AnyScene(c2),
_AnyScene(c3),
_AnyScene(c4),
_AnyScene(c5),
_AnyScene(c6),
_AnyScene(c7),
]
)
}
}
extension SceneBuilder {
public static func buildBlock<C0, C1, C2, C3, C4, C5, C6, C7, C8>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4, _ c5: C5, _ c6: C6, _ c7: C7, _ c8: C8) -> some Scene where C0: Scene, C1: Scene, C2: Scene, C3: Scene, C4: Scene, C5: Scene, C6: Scene, C7: Scene, C8: Scene {
_TupleScene((c0, c1, c2, c3, c4, c5, c6, c7, c8), children: [_AnyScene(c0), _AnyScene(c1), _AnyScene(c2), _AnyScene(c3), _AnyScene(c4), _AnyScene(c5), _AnyScene(c6), _AnyScene(c7), _AnyScene(c8)])
public static func buildBlock<C0, C1, C2, C3, C4, C5, C6, C7, C8>(
_ c0: C0,
_ c1: C1,
_ c2: C2,
_ c3: C3,
_ c4: C4,
_ c5: C5,
_ c6: C6,
_ c7: C7,
_ c8: C8
) -> some Scene where C0: Scene, C1: Scene, C2: Scene, C3: Scene, C4: Scene, C5: Scene, C6: Scene,
C7: Scene, C8: Scene
{
_TupleScene(
(c0, c1, c2, c3, c4, c5, c6, c7, c8),
children: [
_AnyScene(c0),
_AnyScene(c1),
_AnyScene(c2),
_AnyScene(c3),
_AnyScene(c4),
_AnyScene(c5),
_AnyScene(c6),
_AnyScene(c7),
_AnyScene(c8),
]
)
}
}
extension SceneBuilder {
public static func buildBlock<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4, _ c5: C5, _ c6: C6, _ c7: C7, _ c8: C8, _ c9: C9) -> some Scene where C0: Scene, C1: Scene, C2: Scene, C3: Scene, C4: Scene, C5: Scene, C6: Scene, C7: Scene, C8: Scene, C9: Scene {
_TupleScene((c0, c1, c2, c3, c4, c5, c6, c7, c8, c9), children: [_AnyScene(c0), _AnyScene(c1), _AnyScene(c2), _AnyScene(c3), _AnyScene(c4), _AnyScene(c5), _AnyScene(c6), _AnyScene(c7), _AnyScene(c8), _AnyScene(c9)])
public static func buildBlock<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>(
_ c0: C0,
_ c1: C1,
_ c2: C2,
_ c3: C3,
_ c4: C4,
_ c5: C5,
_ c6: C6,
_ c7: C7,
_ c8: C8,
_ c9: C9
) -> some Scene where C0: Scene, C1: Scene, C2: Scene, C3: Scene, C4: Scene, C5: Scene, C6: Scene,
C7: Scene, C8: Scene, C9: Scene
{
_TupleScene(
(c0, c1, c2, c3, c4, c5, c6, c7, c8, c9),
children: [
_AnyScene(c0),
_AnyScene(c1),
_AnyScene(c2),
_AnyScene(c3),
_AnyScene(c4),
_AnyScene(c5),
_AnyScene(c6),
_AnyScene(c7),
_AnyScene(c8),
_AnyScene(c9),
]
)
}
}

View File

@ -54,41 +54,37 @@ public enum _DefaultSceneStorageProvider {
extension SceneStorage: ObservedProperty {}
extension SceneStorage {
public init(wrappedValue: Value,
_ key: String) where Value == Bool {
public init(wrappedValue: Value, _ key: String) where Value == Bool {
defaultValue = wrappedValue
self.key = key
store = { $0.store(key: $1, value: $2) }
read = { $0.read(key: $1) }
}
public init(wrappedValue: Value,
_ key: String) where Value == Int {
public init(wrappedValue: Value, _ key: String) where Value == Int {
defaultValue = wrappedValue
self.key = key
store = { $0.store(key: $1, value: $2) }
read = { $0.read(key: $1) }
}
public init(wrappedValue: Value,
_ key: String) where Value == Double {
public init(wrappedValue: Value, _ key: String) where Value == Double {
defaultValue = wrappedValue
self.key = key
store = { $0.store(key: $1, value: $2) }
read = { $0.read(key: $1) }
}
public init(wrappedValue: Value,
_ key: String) where Value == String {
public init(wrappedValue: Value, _ key: String) where Value == String {
defaultValue = wrappedValue
self.key = key
store = { $0.store(key: $1, value: $2) }
read = { $0.read(key: $1) }
}
public init(wrappedValue: Value,
_ key: String)
where Value: RawRepresentable, Value.RawValue == Int {
public init(wrappedValue: Value, _ key: String) where Value: RawRepresentable,
Value.RawValue == Int
{
defaultValue = wrappedValue
self.key = key
store = { $0.store(key: $1, value: $2.rawValue) }
@ -100,9 +96,9 @@ extension SceneStorage {
}
}
public init(wrappedValue: Value,
_ key: String)
where Value: RawRepresentable, Value.RawValue == String {
public init(wrappedValue: Value, _ key: String)
where Value: RawRepresentable, Value.RawValue == String
{
defaultValue = wrappedValue
self.key = key
store = { $0.store(key: $1, value: $2.rawValue) }

View File

@ -27,18 +27,17 @@ public struct WindowGroup<Content>: Scene, TitledScene where Content: View {
self.content = content()
}
@_disfavoredOverload public init(_ title: Text,
id: String,
@ViewBuilder content: () -> Content) {
@_disfavoredOverload
public init(_ title: Text, id: String, @ViewBuilder content: () -> Content) {
self.id = id
self.title = title
self.content = content()
}
@_disfavoredOverload public init<S>(_ title: S,
id: String,
@ViewBuilder content: () -> Content)
where S: StringProtocol {
@_disfavoredOverload
public init<S>(_ title: S, id: String, @ViewBuilder content: () -> Content)
where S: StringProtocol
{
self.id = id
self.title = Text(title)
self.content = content()
@ -50,16 +49,15 @@ public struct WindowGroup<Content>: Scene, TitledScene where Content: View {
self.content = content()
}
@_disfavoredOverload public init(_ title: Text,
@ViewBuilder content: () -> Content) {
@_disfavoredOverload
public init(_ title: Text, @ViewBuilder content: () -> Content) {
id = ""
self.title = title
self.content = content()
}
@_disfavoredOverload public init<S>(_ title: S,
@ViewBuilder content: () -> Content)
where S: StringProtocol {
@_disfavoredOverload
public init<S>(_ title: S, @ViewBuilder content: () -> Content) where S: StringProtocol {
id = ""
self.title = Text(title)
self.content = content()

View File

@ -39,8 +39,7 @@ public struct _AnyApp: App {
fatalError("`_AnyApp` cannot be initialized without an underlying `App` type.")
}
public static func _launch(_ app: Self,
_ rootEnvironment: EnvironmentValues) {
public static func _launch(_ app: Self, _ rootEnvironment: EnvironmentValues) {
fatalError("`_AnyApp` cannot be launched. Access underlying `app` value.")
}

View File

@ -18,7 +18,8 @@
import CombineShim
@propertyWrapper public struct EnvironmentObject<ObjectType>: DynamicProperty
where ObjectType: ObservableObject {
where ObjectType: ObservableObject
{
@dynamicMemberLookup public struct Wrapper {
internal let root: ObjectType
public subscript<Subject>(

View File

@ -30,7 +30,8 @@ struct _AppearanceActionModifier: ViewModifier {
}
extension ModifiedContent: AppearanceActionType
where Content: View, Modifier == _AppearanceActionModifier {
where Content: View, Modifier == _AppearanceActionModifier
{
var appear: (() -> ())? { modifier.appear }
var disappear: (() -> ())? { modifier.disappear }
}

View File

@ -35,12 +35,16 @@ extension View {
}
public func clipped(antialiased: Bool = false) -> some View {
clipShape(Rectangle(),
style: FillStyle(antialiased: antialiased))
clipShape(
Rectangle(),
style: FillStyle(antialiased: antialiased)
)
}
public func cornerRadius(_ radius: CGFloat, antialiased: Bool = true) -> some View {
clipShape(RoundedRectangle(cornerRadius: radius),
style: FillStyle(antialiased: antialiased))
clipShape(
RoundedRectangle(cornerRadius: radius),
style: FillStyle(antialiased: antialiased)
)
}
}

View File

@ -31,13 +31,15 @@ public struct _FlexFrameLayout: ViewModifier {
minHeight == 0 && maxHeight == .infinity
}
init(minWidth: CGFloat? = nil,
idealWidth: CGFloat? = nil,
maxWidth: CGFloat? = nil,
minHeight: CGFloat? = nil,
idealHeight: CGFloat? = nil,
maxHeight: CGFloat? = nil,
alignment: Alignment) {
init(
minWidth: CGFloat? = nil,
idealWidth: CGFloat? = nil,
maxWidth: CGFloat? = nil,
minHeight: CGFloat? = nil,
idealHeight: CGFloat? = nil,
maxHeight: CGFloat? = nil,
alignment: Alignment
) {
self.minWidth = minWidth
self.idealWidth = idealWidth
self.maxWidth = maxWidth
@ -53,13 +55,15 @@ public struct _FlexFrameLayout: ViewModifier {
}
extension View {
public func frame(minWidth: CGFloat? = nil,
idealWidth: CGFloat? = nil,
maxWidth: CGFloat? = nil,
minHeight: CGFloat? = nil,
idealHeight: CGFloat? = nil,
maxHeight: CGFloat? = nil,
alignment: Alignment = .center) -> some View {
public func frame(
minWidth: CGFloat? = nil,
idealWidth: CGFloat? = nil,
maxWidth: CGFloat? = nil,
minHeight: CGFloat? = nil,
idealHeight: CGFloat? = nil,
maxHeight: CGFloat? = nil,
alignment: Alignment = .center
) -> some View {
func areInNondecreasingOrder(
_ min: CGFloat?, _ ideal: CGFloat?, _ max: CGFloat?
) -> Bool {
@ -69,8 +73,9 @@ extension View {
return min <= ideal && ideal <= max
}
if !areInNondecreasingOrder(minWidth, idealWidth, maxWidth)
|| !areInNondecreasingOrder(minHeight, idealHeight, maxHeight) {
if !areInNondecreasingOrder(minWidth, idealWidth, maxWidth) ||
!areInNondecreasingOrder(minHeight, idealHeight, maxHeight)
{
fatalError("Contradictory frame constraints specified.")
}
@ -81,6 +86,7 @@ extension View {
minHeight: minHeight,
idealHeight: idealHeight, maxHeight: maxHeight,
alignment: alignment
))
)
)
}
}

View File

@ -17,9 +17,7 @@ public struct _FrameLayout: ViewModifier {
public let height: CGFloat?
public let alignment: Alignment
init(width: CGFloat?,
height: CGFloat?,
alignment: Alignment) {
init(width: CGFloat?, height: CGFloat?, alignment: Alignment) {
self.width = width
self.height = height
self.alignment = alignment
@ -31,9 +29,11 @@ public struct _FrameLayout: ViewModifier {
}
extension View {
public func frame(width: CGFloat? = nil,
height: CGFloat? = nil,
alignment: Alignment = .center) -> some View {
public func frame(
width: CGFloat? = nil,
height: CGFloat? = nil,
alignment: Alignment = .center
) -> some View {
modifier(_FrameLayout(width: width, height: height, alignment: alignment))
}
}

View File

@ -16,7 +16,8 @@
//
public struct _BackgroundModifier<Background>: ViewModifier, EnvironmentReader
where Background: View {
where Background: View
{
public var environment: EnvironmentValues!
public var background: Background
public var alignment: Alignment
@ -36,8 +37,10 @@ public struct _BackgroundModifier<Background>: ViewModifier, EnvironmentReader
}
extension _BackgroundModifier: Equatable where Background: Equatable {
public static func == (lhs: _BackgroundModifier<Background>,
rhs: _BackgroundModifier<Background>) -> Bool {
public static func == (
lhs: _BackgroundModifier<Background>,
rhs: _BackgroundModifier<Background>
) -> Bool {
lhs.background == rhs.background
}
}
@ -52,7 +55,8 @@ extension View {
}
public struct _OverlayModifier<Overlay>: ViewModifier, EnvironmentReader
where Overlay: View {
where Overlay: View
{
public var environment: EnvironmentValues!
public var overlay: Overlay
public var alignment: Alignment
@ -75,15 +79,15 @@ public struct _OverlayModifier<Overlay>: ViewModifier, EnvironmentReader
}
extension _OverlayModifier: Equatable where Overlay: Equatable {
public static func == (lhs: _OverlayModifier<Overlay>,
rhs: _OverlayModifier<Overlay>) -> Bool {
public static func == (lhs: _OverlayModifier<Overlay>, rhs: _OverlayModifier<Overlay>) -> Bool {
lhs.overlay == rhs.overlay
}
}
extension View {
public func overlay<Overlay>(_ overlay: Overlay,
alignment: Alignment = .center) -> some View where Overlay: View {
public func overlay<Overlay>(_ overlay: Overlay, alignment: Alignment = .center) -> some View
where Overlay: View
{
modifier(_OverlayModifier(overlay: overlay, alignment: alignment))
}

View File

@ -40,8 +40,7 @@ class MountedCompositeElement<R: Renderer>: MountedElement<R> {
}
extension MountedCompositeElement: Hashable {
static func == (lhs: MountedCompositeElement<R>,
rhs: MountedCompositeElement<R>) -> Bool {
static func == (lhs: MountedCompositeElement<R>, rhs: MountedCompositeElement<R>) -> Bool {
lhs === rhs
}

View File

@ -106,7 +106,8 @@ public class MountedElement<R: Renderer> {
updateEnvironment()
}
@discardableResult func updateEnvironment() -> TypeInfo {
@discardableResult
func updateEnvironment() -> TypeInfo {
// swiftlint:disable:next force_try
let info = try! typeInfo(of: element.type)
switch element {
@ -143,7 +144,8 @@ extension TypeInfo {
// swiftlint:disable force_try
// Extract the view from the AnyView for modification, apply Environment changes:
if genericTypes.contains(where: { $0 is EnvironmentModifier.Type }),
let modifier = try! property(named: "modifier").get(from: element) as? EnvironmentModifier {
let modifier = try! property(named: "modifier").get(from: element) as? EnvironmentModifier
{
modifier.modifyEnvironment(&modifiedEnv)
}
@ -175,8 +177,7 @@ extension TypeInfo {
/// Extract all `DynamicProperty` from a type, recursively.
/// This is necessary as a `DynamicProperty` can be nested.
/// `EnvironmentValues` can also be injected at this point.
func dynamicProperties(_ environment: EnvironmentValues,
source: inout Any) -> [PropertyInfo] {
func dynamicProperties(_ environment: EnvironmentValues, source: inout Any) -> [PropertyInfo] {
var dynamicProps = [PropertyInfo]()
for prop in properties where prop.type is DynamicProperty.Type {
dynamicProps.append(prop)
@ -185,8 +186,10 @@ extension TypeInfo {
_ = propInfo.injectEnvironment(from: environment, into: &source)
var extracted = try! prop.get(from: source)
dynamicProps.append(
contentsOf: propInfo.dynamicProperties(environment,
source: &extracted)
contentsOf: propInfo.dynamicProperties(
environment,
source: &extracted
)
)
// swiftlint:disable:next force_cast
var extractedDynamicProp = extracted as! DynamicProperty

View File

@ -91,7 +91,8 @@ extension _AnyScene {
) -> MountedScene<R> {
var title: String?
if let titledSelf = scene as? TitledScene,
let text = titledSelf.title {
let text = titledSelf.title
{
title = _TextProxy(text).rawText
}
let children: [MountedElement<R>]

View File

@ -86,24 +86,21 @@ public struct Path: Equatable, LosslessStringConvertible {
self.init(storage: .rect(rect))
}
public init(roundedRect rect: CGRect,
cornerSize: CGSize,
style: RoundedCornerStyle = .circular) {
self.init(storage: .roundedRect(FixedRoundedRect(
rect: rect,
cornerSize: cornerSize,
style: style
)))
public init(roundedRect rect: CGRect, cornerSize: CGSize, style: RoundedCornerStyle = .circular) {
self.init(
storage: .roundedRect(FixedRoundedRect(rect: rect, cornerSize: cornerSize, style: style))
)
}
public init(roundedRect rect: CGRect,
cornerRadius: CGFloat,
style: RoundedCornerStyle = .circular) {
public init(
roundedRect rect: CGRect,
cornerRadius: CGFloat,
style: RoundedCornerStyle = .circular
) {
self.init(
storage: .roundedRect(FixedRoundedRect(
rect: rect,
cornerSize: CGSize(width: cornerRadius,
height: cornerRadius),
cornerSize: CGSize(width: cornerRadius, height: cornerRadius),
style: style
))
)
@ -192,55 +189,61 @@ extension Path {
public mutating func addRect(_ rect: CGRect, transform: CGAffineTransform = .identity) {
move(to: rect.origin)
addLine(to: CGPoint(x: rect.size.width, y: 0)
.offset(by: rect.origin))
addLine(to: CGPoint(x: rect.size.width, y: rect.size.height)
.offset(by: rect.origin))
addLine(to: CGPoint(x: 0, y: rect.size.height)
.offset(by: rect.origin))
addLine(to: CGPoint(x: rect.size.width, y: 0).offset(by: rect.origin))
addLine(to: CGPoint(x: rect.size.width, y: rect.size.height).offset(by: rect.origin))
addLine(to: CGPoint(x: 0, y: rect.size.height).offset(by: rect.origin))
closeSubpath()
}
public mutating func addRoundedRect(in rect: CGRect,
cornerSize: CGSize,
style: RoundedCornerStyle = .circular,
transform: CGAffineTransform = .identity) {
move(to: CGPoint(x: rect.size.width, y: rect.size.height / 2)
.offset(by: rect.origin))
addLine(to: CGPoint(x: rect.size.width, y: rect.size.height - cornerSize.height)
.offset(by: rect.origin))
addQuadCurve(to: CGPoint(x: rect.size.width - cornerSize.width, y: rect.size.height)
.offset(by: rect.origin),
control: CGPoint(x: rect.size.width, y: rect.size.height)
.offset(by: rect.origin))
addLine(to: CGPoint(x: cornerSize.width, y: rect.size.height)
.offset(by: rect.origin))
addQuadCurve(to: CGPoint(x: 0, y: rect.size.height - cornerSize.height)
.offset(by: rect.origin),
control: CGPoint(x: 0, y: rect.size.height)
.offset(by: rect.origin))
addLine(to: CGPoint(x: 0, y: cornerSize.height)
.offset(by: rect.origin))
addQuadCurve(to: CGPoint(x: cornerSize.width, y: 0)
.offset(by: rect.origin),
control: CGPoint.zero
.offset(by: rect.origin))
addLine(to: CGPoint(x: rect.size.width - cornerSize.width, y: 0)
.offset(by: rect.origin))
addQuadCurve(to: CGPoint(x: rect.size.width, y: cornerSize.height)
.offset(by: rect.origin),
control: CGPoint(x: rect.size.width, y: 0)
.offset(by: rect.origin))
public mutating func addRoundedRect(
in rect: CGRect,
cornerSize: CGSize,
style: RoundedCornerStyle = .circular,
transform: CGAffineTransform = .identity
) {
move(to: CGPoint(x: rect.size.width, y: rect.size.height / 2).offset(by: rect.origin))
addLine(
to: CGPoint(x: rect.size.width, y: rect.size.height - cornerSize.height)
.offset(by: rect.origin)
)
addQuadCurve(
to: CGPoint(x: rect.size.width - cornerSize.width, y: rect.size.height)
.offset(by: rect.origin),
control: CGPoint(x: rect.size.width, y: rect.size.height)
.offset(by: rect.origin)
)
addLine(to: CGPoint(x: cornerSize.width, y: rect.size.height).offset(by: rect.origin))
addQuadCurve(
to: CGPoint(x: 0, y: rect.size.height - cornerSize.height)
.offset(by: rect.origin),
control: CGPoint(x: 0, y: rect.size.height)
.offset(by: rect.origin)
)
addLine(to: CGPoint(x: 0, y: cornerSize.height).offset(by: rect.origin))
addQuadCurve(
to: CGPoint(x: cornerSize.width, y: 0)
.offset(by: rect.origin),
control: CGPoint.zero
.offset(by: rect.origin)
)
addLine(to: CGPoint(x: rect.size.width - cornerSize.width, y: 0).offset(by: rect.origin))
addQuadCurve(
to: CGPoint(x: rect.size.width, y: cornerSize.height)
.offset(by: rect.origin),
control: CGPoint(x: rect.size.width, y: 0)
.offset(by: rect.origin)
)
closeSubpath()
}
public mutating func addEllipse(in rect: CGRect, transform: CGAffineTransform = .identity) {
subpaths.append(.init(path: .init(ellipseIn: .init(origin: rect.origin
.offset(by: .init(x: rect.size.width / 2,
y: rect.size.height / 2)),
size: .init(width: rect.size.width / 2,
height: rect.size.height / 2))),
transform: transform))
subpaths.append(.init(
path: .init(ellipseIn: .init(
origin: rect.origin.offset(by: .init(x: rect.size.width / 2, y: rect.size.height / 2)),
size: .init(width: rect.size.width / 2, height: rect.size.height / 2)
)),
transform: transform
))
}
public mutating func addRects(_ rects: [CGRect], transform: CGAffineTransform = .identity) {
@ -251,71 +254,93 @@ extension Path {
lines.forEach { addLine(to: $0) }
}
public mutating func addRelativeArc(center: CGPoint,
radius: CGFloat,
startAngle: Angle,
delta: Angle,
transform: CGAffineTransform = .identity) {
addArc(center: center,
radius: radius,
startAngle: startAngle,
endAngle: startAngle + delta,
clockwise: false)
public mutating func addRelativeArc(
center: CGPoint,
radius: CGFloat,
startAngle: Angle,
delta: Angle,
transform: CGAffineTransform = .identity
) {
addArc(
center: center,
radius: radius,
startAngle: startAngle,
endAngle: startAngle + delta,
clockwise: false
)
}
// There's a great article on bezier curves here:
// https://pomax.github.io/bezierinfo
// FIXME: Handle negative delta
public mutating func addArc(center: CGPoint,
radius: CGFloat,
startAngle: Angle,
endAngle: Angle,
clockwise: Bool,
transform: CGAffineTransform = .identity) {
public mutating func addArc(
center: CGPoint,
radius: CGFloat,
startAngle: Angle,
endAngle: Angle,
clockwise: Bool,
transform: CGAffineTransform = .identity
) {
if clockwise {
addArc(center: center,
radius: radius,
startAngle: endAngle,
endAngle: endAngle + (.radians(.pi * 2) - endAngle) + startAngle,
clockwise: false)
addArc(
center: center,
radius: radius,
startAngle: endAngle,
endAngle: endAngle + (.radians(.pi * 2) - endAngle) + startAngle,
clockwise: false
)
} else {
let angle = abs(startAngle.radians - endAngle.radians)
if angle > .pi / 2 {
// Split the angle into 90º chunks
let chunk1 = Angle.radians(startAngle.radians + (.pi / 2))
addArc(center: center,
radius: radius,
startAngle: startAngle,
endAngle: chunk1,
clockwise: clockwise)
addArc(center: center,
radius: radius,
startAngle: chunk1,
endAngle: endAngle,
clockwise: clockwise)
addArc(
center: center,
radius: radius,
startAngle: startAngle,
endAngle: chunk1,
clockwise: clockwise
)
addArc(
center: center,
radius: radius,
startAngle: chunk1,
endAngle: endAngle,
clockwise: clockwise
)
} else {
let startPoint = CGPoint(x: radius + center.x,
y: center.y)
let endPoint = CGPoint(x: (radius * cos(angle)) + center.x,
y: (radius * sin(angle)) + center.y)
let startPoint = CGPoint(
x: radius + center.x,
y: center.y
)
let endPoint = CGPoint(
x: (radius * cos(angle)) + center.x,
y: (radius * sin(angle)) + center.y
)
let l = (4 / 3) * tan(angle / 4)
let c1 = CGPoint(x: radius + center.x, y: (l * radius) + center.y)
let c2 = CGPoint(x: ((cos(angle) + l * sin(angle)) * radius) + center.x,
y: ((sin(angle) - l * cos(angle)) * radius) + center.y)
let c2 = CGPoint(
x: ((cos(angle) + l * sin(angle)) * radius) + center.x,
y: ((sin(angle) - l * cos(angle)) * radius) + center.y
)
move(to: startPoint.rotate(startAngle, around: center))
addCurve(to: endPoint.rotate(startAngle, around: center),
control1: c1.rotate(startAngle, around: center),
control2: c2.rotate(startAngle, around: center))
addCurve(
to: endPoint.rotate(startAngle, around: center),
control1: c1.rotate(startAngle, around: center),
control2: c2.rotate(startAngle, around: center)
)
}
}
}
// FIXME: How does this arc method work?
public mutating func addArc(tangent1End p1: CGPoint,
tangent2End p2: CGPoint,
radius: CGFloat,
transform: CGAffineTransform = .identity) {}
public mutating func addArc(
tangent1End p1: CGPoint,
tangent2End p2: CGPoint,
radius: CGFloat,
transform: CGAffineTransform = .identity
) {}
public mutating func addPath(_ path: Path, transform: CGAffineTransform = .identity) {
subpaths.append(.init(path: path, transform: transform))

View File

@ -59,10 +59,16 @@ extension Rectangle: InsettableShape {
}
public func path(in rect: CGRect) -> Path {
.init(storage: .rect(CGRect(origin: rect.origin,
size: CGSize(width: rect.size.width - (amount / 2),
height: rect.size.height - (amount / 2)))),
sizing: .flexible)
.init(
storage: .rect(CGRect(
origin: rect.origin,
size: CGSize(
width: rect.size.width - (amount / 2),
height: rect.size.height - (amount / 2)
)
)),
sizing: .flexible
)
}
public func inset(by amount: CGFloat) -> Rectangle._Inset {

View File

@ -88,8 +88,11 @@ extension Shape {
y: CGFloat = 1,
anchor: UnitPoint = .center
) -> ScaledShape<Self> {
ScaledShape(shape: self,
scale: CGSize(width: x, height: y), anchor: anchor)
ScaledShape(
shape: self,
scale: CGSize(width: x, height: y),
anchor: anchor
)
}
public func scale(_ scale: CGFloat, anchor: UnitPoint = .center) -> ScaledShape<Self> {

View File

@ -39,13 +39,18 @@ extension InsettableShape {
lineWidth: CGFloat = 1,
antialiased: Bool = true
) -> some View where S: ShapeStyle {
strokeBorder(content, style: StrokeStyle(lineWidth: lineWidth),
antialiased: antialiased)
strokeBorder(
content,
style: StrokeStyle(lineWidth: lineWidth),
antialiased: antialiased
)
}
@inlinable
public func strokeBorder(lineWidth: CGFloat = 1, antialiased: Bool = true) -> some View {
strokeBorder(style: StrokeStyle(lineWidth: lineWidth),
antialiased: antialiased)
strokeBorder(
style: StrokeStyle(lineWidth: lineWidth),
antialiased: antialiased
)
}
}

View File

@ -23,12 +23,14 @@ public struct StrokeStyle: Equatable {
public var dash: [CGFloat]
public var dashPhase: CGFloat
public init(lineWidth: CGFloat = 1,
lineCap: CGLineCap = .butt,
lineJoin: CGLineJoin = .miter,
miterLimit: CGFloat = 10,
dash: [CGFloat] = [CGFloat](),
dashPhase: CGFloat = 0) {
public init(
lineWidth: CGFloat = 1,
lineCap: CGLineCap = .butt,
lineJoin: CGLineJoin = .miter,
miterLimit: CGFloat = 10,
dash: [CGFloat] = [CGFloat](),
dashPhase: CGFloat = 0
) {
self.lineWidth = lineWidth
self.lineCap = lineCap
self.lineJoin = lineJoin

View File

@ -186,9 +186,11 @@ public final class StackReconciler<R: Renderer> {
}.store(in: &mountedApp.subscriptions)
}
func render<T>(compositeElement: MountedCompositeElement<R>,
body bodyKeypath: ReferenceWritableKeyPath<MountedCompositeElement<R>, Any>,
result: KeyPath<MountedCompositeElement<R>, (Any) -> T>) -> T {
func render<T>(
compositeElement: MountedCompositeElement<R>,
body bodyKeypath: ReferenceWritableKeyPath<MountedCompositeElement<R>, Any>,
result: KeyPath<MountedCompositeElement<R>, (Any) -> T>
) -> T {
let info = compositeElement.updateEnvironment()
var stateIdx = 0

View File

@ -49,5 +49,6 @@ protocol ValueStorage {
extension State: ValueStorage {}
extension State where Value: ExpressibleByNilLiteral {
@inlinable public init() { self.init(wrappedValue: nil) }
@inlinable
public init() { self.init(wrappedValue: nil) }
}

View File

@ -38,13 +38,17 @@ public struct CGPoint: Equatable {
func rotate(_ angle: Angle, around origin: Self) -> Self {
let cosAngle = cos(angle.radians)
let sinAngle = sin(angle.radians)
return .init(x: cosAngle * (x - origin.x) - sinAngle * (y - origin.y) + origin.x,
y: sinAngle * (x - origin.x) + cosAngle * (y - origin.y) + origin.y)
return .init(
x: cosAngle * (x - origin.x) - sinAngle * (y - origin.y) + origin.x,
y: sinAngle * (x - origin.x) + cosAngle * (y - origin.y) + origin.y
)
}
func offset(by offset: Self) -> Self {
.init(x: x + offset.x,
y: y + offset.y)
.init(
x: x + offset.x,
y: y + offset.y
)
}
}
@ -107,13 +111,20 @@ public struct CGAffineTransform: Equatable {
public var ty: CGFloat
/// The identity matrix
public static let identity: Self = .init(a: 1, b: 0, // 0
c: 0, d: 1, // 0
tx: 0, ty: 0) // 1
public static let identity: Self = .init(
a: 1,
b: 0, // 0
c: 0,
d: 1, // 0
tx: 0,
ty: 0
) // 1
public init(a: CGFloat, b: CGFloat,
c: CGFloat, d: CGFloat,
tx: CGFloat, ty: CGFloat) {
public init(
a: CGFloat, b: CGFloat,
c: CGFloat, d: CGFloat,
tx: CGFloat, ty: CGFloat
) {
self.a = a
self.b = b
self.c = c
@ -135,28 +146,38 @@ public struct CGAffineTransform: Equatable {
/// - Parameters:
/// - sx: The factor by which to scale the x-axis of the coordinate system.
/// - sy: The factor by which to scale the y-axis of the coordinate system.
public init(scaleX sx: CGFloat,
y sy: CGFloat) {
self.init(a: sx, b: 0,
c: 0, d: sy,
tx: 0, ty: 0)
public init(scaleX sx: CGFloat, y sy: CGFloat) {
self.init(
a: sx,
b: 0,
c: 0,
d: sy,
tx: 0,
ty: 0
)
}
/// Returns an affine transformation matrix constructed from translation values you provide.
/// - Parameters:
/// - tx: The value by which to move the x-axis of the coordinate system.
/// - ty: The value by which to move the y-axis of the coordinate system.
public init(translationX tx: CGFloat,
y ty: CGFloat) {
self.init(a: 1, b: 0,
c: 0, d: 1,
tx: tx, ty: ty)
public init(translationX tx: CGFloat, y ty: CGFloat) {
self.init(
a: 1,
b: 0,
c: 0,
d: 1,
tx: tx,
ty: ty
)
}
/// Transform the point into the transform's coordinate system.
public func transform(point: CGPoint) -> CGPoint {
CGPoint(x: (a * point.x) + (c * point.y) + tx,
y: (b * point.x) + (d * point.y) + ty)
CGPoint(
x: (a * point.x) + (c * point.y) + tx,
y: (b * point.x) + (d * point.y) + ty
)
}
/// Returns an affine transformation matrix constructed by combining two existing affine
@ -180,9 +201,14 @@ public struct CGAffineTransform: Equatable {
}
}
}
return .init(a: res[0][0], b: res[0][1],
c: res[1][0], d: res[1][1],
tx: res[2][0], ty: res[2][1])
return .init(
a: res[0][0],
b: res[0][1],
c: res[1][0],
d: res[1][1],
tx: res[2][0],
ty: res[2][1]
)
}
/// Returns an affine transformation matrix constructed by inverting an existing affine transform.
@ -205,10 +231,9 @@ public struct CGAffineTransform: Equatable {
/// - tx: The value by which to move x values with the affine transform.
/// - ty: The value by which to move y values with the affine transform.
public func translatedBy(x tx: CGFloat,
y ty: CGFloat) -> Self {
.init(a: a, b: b,
c: c, d: d,
tx: self.tx + tx, ty: self.ty + ty)
y ty: CGFloat) -> Self
{
.init(a: a, b: b, c: c, d: d, tx: self.tx + tx, ty: self.ty + ty)
}
/// Returns an affine transformation matrix constructed by scaling an existing affine transform.
@ -216,10 +241,9 @@ public struct CGAffineTransform: Equatable {
/// - sx: The value by which to scale x values of the affine transform.
/// - sy: The value by which to scale y values of the affine transform.
public func scaledBy(x sx: CGFloat,
y sy: CGFloat) -> Self {
.init(a: a + sx, b: b,
c: c, d: d + sy,
tx: tx, ty: ty)
y sy: CGFloat) -> Self
{
.init(a: a + sx, b: b, c: c, d: d + sy, tx: tx, ty: ty)
}
public var isIdentity: Bool {

View File

@ -34,8 +34,7 @@ public extension ListStyleDeferredToRenderer {
}
func listRow<Row>(_ row: Row) -> AnyView where Row: View {
AnyView(row
.padding([.trailing, .top, .bottom]))
AnyView(row.padding([.trailing, .top, .bottom]))
}
func sectionHeader<Header>(_ header: Header) -> AnyView where Header: View {

View File

@ -49,46 +49,31 @@ public struct Color: Hashable, Equatable {
self.evaluator = evaluator
}
public init(_ colorSpace: RGBColorSpace = .sRGB,
red: Double,
green: Double,
blue: Double,
opacity: Double = 1) {
public init(
_ colorSpace: RGBColorSpace = .sRGB,
red: Double,
green: Double,
blue: Double,
opacity: Double = 1
) {
self.init { _ in
_RGBA(red: red,
green: green,
blue: blue,
opacity: opacity,
space: colorSpace)
_RGBA(red: red, green: green, blue: blue, opacity: opacity, space: colorSpace)
}
}
public init(_ colorSpace: RGBColorSpace = .sRGB,
white: Double,
opacity: Double = 1) {
self.init(colorSpace,
red: white,
green: white,
blue: white,
opacity: opacity)
public init(_ colorSpace: RGBColorSpace = .sRGB, white: Double, opacity: Double = 1) {
self.init(colorSpace, red: white, green: white, blue: white, opacity: opacity)
}
// Source for the formula:
// https://en.wikipedia.org/wiki/HSL_and_HSV#HSL_to_RGB_alternative
public init(hue: Double,
saturation: Double,
brightness: Double,
opacity: Double = 1) {
public init(hue: Double, saturation: Double, brightness: Double, opacity: Double = 1) {
let a = saturation * min(brightness / 2, 1 - (brightness / 2))
let f = { (n: Int) -> Double in
let k = Double((n + Int(hue * 12)) % 12)
return brightness - (a * max(-1, min(k - 3, 9 - k, 1)))
}
self.init(.sRGB,
red: f(0),
green: f(8),
blue: f(4),
opacity: opacity)
self.init(.sRGB, red: f(0), green: f(8), blue: f(4), opacity: opacity)
}
/// Create a `Color` dependent on the current `ColorScheme`.
@ -118,17 +103,9 @@ extension Color {
public static let primary: Self = .init {
switch $0.colorScheme {
case .light:
return .init(red: 0,
green: 0,
blue: 0,
opacity: 1,
space: .sRGB)
return .init(red: 0, green: 0, blue: 0, opacity: 1, space: .sRGB)
case .dark:
return .init(red: 1,
green: 1,
blue: 1,
opacity: 1,
space: .sRGB)
return .init(red: 1, green: 1, blue: 1, opacity: 1, space: .sRGB)
}
}
@ -145,11 +122,13 @@ extension Color {
extension Color: ExpressibleByIntegerLiteral {
/// Allows initializing value of `Color` type from hex values
public init(integerLiteral bitMask: UInt32) {
self.init(.sRGB,
red: Double((bitMask & 0xFF0000) >> 16) / 255,
green: Double((bitMask & 0x00FF00) >> 8) / 255,
blue: Double(bitMask & 0x0000FF) / 255,
opacity: 1)
self.init(
.sRGB,
red: Double((bitMask & 0xFF0000) >> 16) / 255,
green: Double((bitMask & 0x00FF00) >> 8) / 255,
blue: Double(bitMask & 0x0000FF) / 255,
opacity: 1
)
}
}
@ -166,11 +145,13 @@ extension Color {
else {
return nil
}
self.init(.sRGB,
red: Double(red) / 255,
green: Double(green) / 255,
blue: Double(blue) / 255,
opacity: 1)
self.init(
.sRGB,
red: Double(red) / 255,
green: Double(green) / 255,
blue: Double(blue) / 255,
opacity: 1
)
}
}

View File

@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// swiftlint:disable line_length
public struct Font: Hashable {
public let _name: String
public let _size: CGFloat
@ -25,11 +24,31 @@ public struct Font: Hashable {
public let _leading: Leading
public func italic() -> Self {
.init(_name: _name, _size: _size, _design: _design, _weight: _weight, _smallCaps: _smallCaps, _italic: true, _bold: _bold, _monospaceDigit: _monospaceDigit, _leading: _leading)
.init(
_name: _name,
_size: _size,
_design: _design,
_weight: _weight,
_smallCaps: _smallCaps,
_italic: true,
_bold: _bold,
_monospaceDigit: _monospaceDigit,
_leading: _leading
)
}
public func smallCaps() -> Self {
.init(_name: _name, _size: _size, _design: _design, _weight: _weight, _smallCaps: true, _italic: _italic, _bold: _bold, _monospaceDigit: _monospaceDigit, _leading: _leading)
.init(
_name: _name,
_size: _size,
_design: _design,
_weight: _weight,
_smallCaps: true,
_italic: _italic,
_bold: _bold,
_monospaceDigit: _monospaceDigit,
_leading: _leading
)
}
public func lowercaseSmallCaps() -> Self {
@ -41,19 +60,59 @@ public struct Font: Hashable {
}
public func monospacedDigit() -> Self {
.init(_name: _name, _size: _size, _design: _design, _weight: _weight, _smallCaps: _smallCaps, _italic: _italic, _bold: _bold, _monospaceDigit: true, _leading: _leading)
.init(
_name: _name,
_size: _size,
_design: _design,
_weight: _weight,
_smallCaps: _smallCaps,
_italic: _italic,
_bold: _bold,
_monospaceDigit: true,
_leading: _leading
)
}
public func weight(_ weight: Weight) -> Self {
.init(_name: _name, _size: _size, _design: _design, _weight: weight, _smallCaps: _smallCaps, _italic: _italic, _bold: _bold, _monospaceDigit: _monospaceDigit, _leading: _leading)
.init(
_name: _name,
_size: _size,
_design: _design,
_weight: weight,
_smallCaps: _smallCaps,
_italic: _italic,
_bold: _bold,
_monospaceDigit: _monospaceDigit,
_leading: _leading
)
}
public func bold() -> Self {
.init(_name: _name, _size: _size, _design: _design, _weight: _weight, _smallCaps: _smallCaps, _italic: _italic, _bold: true, _monospaceDigit: _monospaceDigit, _leading: _leading)
.init(
_name: _name,
_size: _size,
_design: _design,
_weight: _weight,
_smallCaps: _smallCaps,
_italic: _italic,
_bold: true,
_monospaceDigit: _monospaceDigit,
_leading: _leading
)
}
public func leading(_ leading: Leading) -> Self {
.init(_name: _name, _size: _size, _design: _design, _weight: _weight, _smallCaps: _smallCaps, _italic: _italic, _bold: true, _monospaceDigit: _monospaceDigit, _leading: leading)
.init(
_name: _name,
_size: _size,
_design: _design,
_weight: _weight,
_smallCaps: _smallCaps,
_italic: _italic,
_bold: true,
_monospaceDigit: _monospaceDigit,
_leading: leading
)
}
}
@ -86,8 +145,20 @@ public enum _FontNames: String, CaseIterable {
}
extension Font {
public static func system(size: CGFloat, weight: Weight = .regular, design: Design = .default) -> Self {
.init(_name: _FontNames.system.rawValue, _size: size, _design: design, _weight: weight, _smallCaps: false, _italic: false, _bold: false, _monospaceDigit: false, _leading: .standard)
public static func system(size: CGFloat, weight: Weight = .regular,
design: Design = .default) -> Self
{
.init(
_name: _FontNames.system.rawValue,
_size: size,
_design: design,
_weight: weight,
_smallCaps: false,
_italic: false,
_bold: false,
_monospaceDigit: false,
_leading: .standard
)
}
public enum Design: Hashable {

View File

@ -26,9 +26,11 @@ public struct GridItem {
public var spacing: CGFloat
public var alignment: Alignment
public init(_ size: GridItem.Size = .flexible(),
spacing: CGFloat? = nil,
alignment: Alignment? = nil) {
public init(
_ size: GridItem.Size = .flexible(),
spacing: CGFloat? = nil,
alignment: Alignment? = nil
) {
self.size = size
self.spacing = spacing ?? 4
self.alignment = alignment ?? .center

View File

@ -15,8 +15,7 @@
// Created by Carson Katri on 7/3/20.
//
public struct DisclosureGroup<Label, Content>: View
where Label: View, Content: View {
public struct DisclosureGroup<Label, Content>: View where Label: View, Content: View {
@State var isExpanded: Bool = false
let isExpandedBinding: Binding<Bool>?
@ -25,16 +24,17 @@ public struct DisclosureGroup<Label, Content>: View
let label: Label
let content: () -> Content
public init(@ViewBuilder content: @escaping () -> Content,
@ViewBuilder label: () -> Label) {
public init(@ViewBuilder content: @escaping () -> Content, @ViewBuilder label: () -> Label) {
isExpandedBinding = nil
self.label = label()
self.content = content
}
public init(isExpanded: Binding<Bool>,
@ViewBuilder content: @escaping () -> Content,
@ViewBuilder label: () -> Label) {
public init(
isExpanded: Binding<Bool>,
@ViewBuilder content: @escaping () -> Content,
@ViewBuilder label: () -> Label
) {
isExpandedBinding = isExpanded
self.label = label()
self.content = content
@ -53,22 +53,26 @@ extension DisclosureGroup where Label == Text {
// isExpanded: SwiftUI.Binding<Swift.Bool>,
// @SwiftUI.ViewBuilder content: @escaping () -> Content)
@_disfavoredOverload public init<S>(_ label: S,
@ViewBuilder content: @escaping () -> Content)
where S: StringProtocol {
@_disfavoredOverload
public init<S>(_ label: S, @ViewBuilder content: @escaping () -> Content)
where S: StringProtocol
{
self.init(content: content, label: { Text(label) })
}
@_disfavoredOverload public init<S>(_ label: S,
isExpanded: Binding<Bool>,
@ViewBuilder content: @escaping () -> Content)
where S: StringProtocol {
@_disfavoredOverload
public init<S>(
_ label: S,
isExpanded: Binding<Bool>,
@ViewBuilder content: @escaping () -> Content
) where S: StringProtocol {
self.init(isExpanded: isExpanded, content: content, label: { Text(label) })
}
}
public struct _DisclosureGroupProxy<Label, Content>
where Label: View, Content: View {
where Label: View, Content: View
{
public var subject: DisclosureGroup<Label, Content>
public init(_ subject: DisclosureGroup<Label, Content>) { self.subject = subject }

View File

@ -31,8 +31,9 @@ protocol ForEachProtocol: GroupView {
/// Text("\($0)")
/// }
/// }
public struct ForEach<Data, ID, Content>: View
where Data: RandomAccessCollection, ID: Hashable, Content: View {
public struct ForEach<Data, ID, Content>: View where Data: RandomAccessCollection, ID: Hashable,
Content: View
{
let data: Data
let id: KeyPath<Data.Element, ID>
public let content: (Data.Element) -> Content

View File

@ -16,7 +16,8 @@
//
public struct List<SelectionValue, Content>: View
where SelectionValue: Hashable, Content: View {
where SelectionValue: Hashable, Content: View
{
public enum _Selection {
case one(Binding<SelectionValue?>?)
case many(Binding<Set<SelectionValue>>?)
@ -46,9 +47,7 @@ public struct List<SelectionValue, Content>: View
if child.view is SectionView {
if currentSection.count > 0 {
sections.append(AnyView(Section {
ForEach(Array(currentSection.enumerated()), id: \.offset) { _, view in
view
}
ForEach(Array(currentSection.enumerated()), id: \.offset) { _, view in view }
}))
currentSection = []
}
@ -63,9 +62,7 @@ public struct List<SelectionValue, Content>: View
}
if currentSection.count > 0 {
sections.append(AnyView(Section {
ForEach(Array(currentSection.enumerated()), id: \.offset) { _, view in
view
}
ForEach(Array(currentSection.enumerated()), id: \.offset) { _, view in view }
}))
}
return AnyView(_ListRow.buildItems(sections) { view, isLast in
@ -84,18 +81,14 @@ public struct List<SelectionValue, Content>: View
public var body: some View {
if let style = style as? ListStyleDeferredToRenderer {
style.listBody(ScrollView {
HStack {
Spacer()
}
HStack { Spacer() }
listStack
.environment(\._outlineGroupStyle, _ListOutlineGroupStyle())
})
.frame(minHeight: 0, maxHeight: .infinity)
} else {
ScrollView {
HStack {
Spacer()
}
HStack { Spacer() }
listStack
.environment(\._outlineGroupStyle, _ListOutlineGroupStyle())
}
@ -104,14 +97,13 @@ public struct List<SelectionValue, Content>: View
}
public struct _ListRow {
static func buildItems<RowView>(_ children: [AnyView],
@ViewBuilder rowView: @escaping (AnyView, Bool) -> RowView)
-> some View where RowView: View {
static func buildItems<RowView>(
_ children: [AnyView],
@ViewBuilder rowView: @escaping (AnyView, Bool) -> RowView
) -> some View where RowView: View {
ForEach(Array(children.enumerated()), id: \.offset) { offset, view in
VStack(alignment: .leading) {
HStack {
Spacer()
}
HStack { Spacer() }
rowView(view, offset == children.count - 1)
}
}
@ -129,7 +121,8 @@ public struct _ListRow {
/// This is a helper class that works around absence of "package private" access control in Swift
public struct _ListProxy<SelectionValue, Content>
where SelectionValue: Hashable, Content: View {
where SelectionValue: Hashable, Content: View
{
public let subject: List<SelectionValue, Content>
public init(_ subject: List<SelectionValue, Content>) {
@ -142,48 +135,42 @@ public struct _ListProxy<SelectionValue, Content>
extension List {
// - MARK: Collection initializers
public init<Data, RowContent>(_ data: Data,
selection: Binding<Set<SelectionValue>>?,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent)
public init<Data, RowContent>(
_ data: Data,
selection: Binding<Set<SelectionValue>>?,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent
)
where Content == ForEach<Data, Data.Element.ID, HStack<RowContent>>,
Data: RandomAccessCollection, RowContent: View,
Data.Element: Identifiable {
self.init(selection: selection) {
ForEach(data) { row in
HStack {
rowContent(row)
}
}
}
Data.Element: Identifiable
{
self.init(selection: selection) { ForEach(data) { row in HStack { rowContent(row) } } }
}
public init<Data, ID, RowContent>(_ data: Data,
id: KeyPath<Data.Element, ID>,
selection: Binding<Set<SelectionValue>>?,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent)
where Content == ForEach<Data, ID, HStack<RowContent>>,
Data: RandomAccessCollection,
ID: Hashable, RowContent: View {
self.init(selection: selection) {
ForEach(data, id: id) { row in
HStack {
rowContent(row)
}
}
}
ID: Hashable, RowContent: View
{
self.init(selection: selection) { ForEach(data, id: id) { row in HStack { rowContent(row) } } }
}
public init<Data, ID, RowContent>(_ data: Data,
id: KeyPath<Data.Element, ID>,
selection: Binding<SelectionValue?>?,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent)
public init<Data, ID, RowContent>(
_ data: Data,
id: KeyPath<Data.Element, ID>,
selection: Binding<SelectionValue?>?,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent
)
where Content == ForEach<Data, ID, HStack<RowContent>>,
Data: RandomAccessCollection, ID: Hashable, RowContent: View {
Data: RandomAccessCollection, ID: Hashable, RowContent: View
{
self.init(selection: selection) {
ForEach(data, id: id) { row in
HStack {
rowContent(row)
}
HStack { rowContent(row) }
}
}
}
@ -192,7 +179,8 @@ extension List {
selection: Binding<SelectionValue?>?,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent)
where Content == ForEach<Data, Data.Element.ID, HStack<RowContent>>,
Data: RandomAccessCollection, RowContent: View, Data.Element: Identifiable {
Data: RandomAccessCollection, RowContent: View, Data.Element: Identifiable
{
self.init(selection: selection) {
ForEach(data) { row in
HStack {
@ -203,112 +191,118 @@ extension List {
}
// - MARK: Range initializers
public init<RowContent>(_ data: Range<Int>,
selection: Binding<Set<SelectionValue>>?,
@ViewBuilder rowContent: @escaping (Int) -> RowContent)
where Content == ForEach<Range<Int>, Int, HStack<RowContent>>, RowContent: View {
public init<RowContent>(
_ data: Range<Int>,
selection: Binding<Set<SelectionValue>>?,
@ViewBuilder rowContent: @escaping (Int) -> RowContent
)
where Content == ForEach<Range<Int>, Int, HStack<RowContent>>, RowContent: View
{
self.init(selection: selection) {
ForEach(data) { row in
HStack {
rowContent(row)
}
HStack { rowContent(row) }
}
}
}
public init<RowContent>(_ data: Range<Int>,
selection: Binding<SelectionValue?>?,
@ViewBuilder rowContent: @escaping (Int) -> RowContent)
where Content == ForEach<Range<Int>, Int, HStack<RowContent>>, RowContent: View {
public init<RowContent>(
_ data: Range<Int>,
selection: Binding<SelectionValue?>?,
@ViewBuilder rowContent: @escaping (Int) -> RowContent
)
where Content == ForEach<Range<Int>, Int, HStack<RowContent>>, RowContent: View
{
self.init(selection: selection) {
ForEach(data) { row in
HStack {
rowContent(row)
}
HStack { rowContent(row) }
}
}
}
// - MARK: OutlineGroup initializers
public init<Data, RowContent>(_ data: Data,
children: KeyPath<Data.Element, Data?>,
selection: Binding<Set<SelectionValue>>?,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent)
where Content == OutlineGroup<Data,
Data.Element.ID,
HStack<RowContent>,
HStack<RowContent>,
DisclosureGroup<HStack<RowContent>, OutlineSubgroupChildren>>,
Data: RandomAccessCollection,
RowContent: View,
Data.Element: Identifiable {
public init<Data, RowContent>(
_ data: Data,
children: KeyPath<Data.Element, Data?>,
selection: Binding<Set<SelectionValue>>?,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent
)
where Content == OutlineGroup<
Data,
Data.Element.ID,
HStack<RowContent>,
HStack<RowContent>,
DisclosureGroup<HStack<RowContent>, OutlineSubgroupChildren>
>, Data: RandomAccessCollection, RowContent: View, Data.Element: Identifiable
{
self.init(selection: selection) {
OutlineGroup(data, children: children) { row in
HStack {
rowContent(row)
}
HStack { rowContent(row) }
}
}
}
public init<Data, ID, RowContent>(_ data: Data,
id: KeyPath<Data.Element, ID>,
children: KeyPath<Data.Element, Data?>,
selection: Binding<Set<SelectionValue>>?,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent)
where Content == OutlineGroup<Data,
ID,
HStack<RowContent>,
HStack<RowContent>,
DisclosureGroup<HStack<RowContent>, OutlineSubgroupChildren>>,
Data: RandomAccessCollection,
ID: Hashable,
RowContent: View {
public init<Data, ID, RowContent>(
_ data: Data,
id: KeyPath<Data.Element, ID>,
children: KeyPath<Data.Element, Data?>,
selection: Binding<Set<SelectionValue>>?,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent
)
where Content == OutlineGroup<
Data,
ID,
HStack<RowContent>,
HStack<RowContent>,
DisclosureGroup<HStack<RowContent>, OutlineSubgroupChildren>
>, Data: RandomAccessCollection, ID: Hashable, RowContent: View
{
self.init(selection: selection) {
OutlineGroup(data, id: id, children: children) { row in
HStack {
rowContent(row)
}
HStack { rowContent(row) }
}
}
}
public init<Data, RowContent>(_ data: Data,
children: KeyPath<Data.Element, Data?>,
selection: Binding<SelectionValue?>?,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent)
where Content == OutlineGroup<Data,
Data.Element.ID,
HStack<RowContent>,
HStack<RowContent>,
DisclosureGroup<HStack<RowContent>, OutlineSubgroupChildren>>,
Data: RandomAccessCollection, RowContent: View, Data.Element: Identifiable {
public init<Data, RowContent>(
_ data: Data,
children: KeyPath<Data.Element, Data?>,
selection: Binding<SelectionValue?>?,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent
)
where Content == OutlineGroup<
Data,
Data.Element.ID,
HStack<RowContent>,
HStack<RowContent>,
DisclosureGroup<HStack<RowContent>, OutlineSubgroupChildren>
>, Data: RandomAccessCollection, RowContent: View, Data.Element: Identifiable
{
self.init(selection: selection) {
OutlineGroup(data, children: children) { row in
HStack {
rowContent(row)
}
HStack { rowContent(row) }
}
}
}
public init<Data, ID, RowContent>(_ data: Data,
id: KeyPath<Data.Element, ID>,
children: KeyPath<Data.Element, Data?>,
selection: Binding<SelectionValue?>?,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent)
where Content == OutlineGroup<Data,
ID,
HStack<RowContent>,
HStack<RowContent>,
DisclosureGroup<HStack<RowContent>, OutlineSubgroupChildren>>,
Data: RandomAccessCollection, ID: Hashable, RowContent: View {
public init<Data, ID, RowContent>(
_ data: Data,
id: KeyPath<Data.Element, ID>,
children: KeyPath<Data.Element, Data?>,
selection: Binding<SelectionValue?>?,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent
)
where Content == OutlineGroup<
Data,
ID,
HStack<RowContent>,
HStack<RowContent>,
DisclosureGroup<HStack<RowContent>, OutlineSubgroupChildren>
>, Data: RandomAccessCollection, ID: Hashable, RowContent: View
{
self.init(selection: selection) {
OutlineGroup(data, id: id, children: children) { row in
HStack {
rowContent(row)
}
HStack { rowContent(row) }
}
}
}
@ -320,76 +314,83 @@ extension List where SelectionValue == Never {
self.content = content()
}
public init<Data, RowContent>(_ data: Data,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent)
public init<Data, RowContent>(
_ data: Data,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent
)
where Content == ForEach<Data, Data.Element.ID, HStack<RowContent>>,
Data: RandomAccessCollection, RowContent: View, Data.Element: Identifiable {
Data: RandomAccessCollection, RowContent: View, Data.Element: Identifiable
{
selection = .one(nil)
content = ForEach(data) { row in
HStack {
rowContent(row)
}
HStack { rowContent(row) }
}
}
public init<Data, RowContent>(_ data: Data,
children: KeyPath<Data.Element, Data?>,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent)
where Content == OutlineGroup<Data,
Data.Element.ID,
HStack<RowContent>,
HStack<RowContent>,
DisclosureGroup<HStack<RowContent>, OutlineSubgroupChildren>>,
Data: RandomAccessCollection, RowContent: View, Data.Element: Identifiable {
public init<Data, RowContent>(
_ data: Data,
children: KeyPath<Data.Element, Data?>,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent
)
where Content == OutlineGroup<
Data,
Data.Element.ID,
HStack<RowContent>,
HStack<RowContent>,
DisclosureGroup<HStack<RowContent>, OutlineSubgroupChildren>
>, Data: RandomAccessCollection, RowContent: View, Data.Element: Identifiable
{
self.init {
OutlineGroup(data, children: children) { row in
HStack {
rowContent(row)
}
HStack { rowContent(row) }
}
}
}
public init<Data, ID, RowContent>(_ data: Data,
id: KeyPath<Data.Element, ID>,
children: KeyPath<Data.Element, Data?>,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent)
where Content == OutlineGroup<Data,
ID,
HStack<RowContent>,
HStack<RowContent>,
DisclosureGroup<HStack<RowContent>, OutlineSubgroupChildren>>,
Data: RandomAccessCollection, ID: Hashable, RowContent: View {
public init<Data, ID, RowContent>(
_ data: Data,
id: KeyPath<Data.Element, ID>,
children: KeyPath<Data.Element, Data?>,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent
)
where Content == OutlineGroup<
Data,
ID,
HStack<RowContent>,
HStack<RowContent>,
DisclosureGroup<HStack<RowContent>, OutlineSubgroupChildren>
>, Data: RandomAccessCollection, ID: Hashable, RowContent: View
{
self.init {
OutlineGroup(data, id: id, children: children) { row in
HStack {
rowContent(row)
}
HStack { rowContent(row) }
}
}
}
public init<Data, ID, RowContent>(_ data: Data,
id: KeyPath<Data.Element, ID>,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent)
public init<Data, ID, RowContent>(
_ data: Data,
id: KeyPath<Data.Element, ID>,
@ViewBuilder rowContent: @escaping (Data.Element) -> RowContent
)
where Content == ForEach<Data, ID, HStack<RowContent>>,
Data: RandomAccessCollection, ID: Hashable, RowContent: View {
Data: RandomAccessCollection, ID: Hashable, RowContent: View
{
selection = .one(nil)
content = ForEach(data, id: id) { row in
HStack {
rowContent(row)
}
HStack { rowContent(row) }
}
}
public init<RowContent>(_ data: Range<Int>,
@ViewBuilder rowContent: @escaping (Int) -> RowContent)
where Content == ForEach<Range<Int>, Int, HStack<RowContent>>, RowContent: View {
public init<RowContent>(
_ data: Range<Int>,
@ViewBuilder rowContent: @escaping (Int) -> RowContent
)
where Content == ForEach<Range<Int>, Int, HStack<RowContent>>, RowContent: View
{
selection = .one(nil)
content = ForEach(data) { row in
HStack {
rowContent(row)
}
HStack { rowContent(row) }
}
}
}

View File

@ -16,7 +16,8 @@
//
public struct OutlineGroup<Data, ID, Parent, Leaf, Subgroup>
where Data: RandomAccessCollection, ID: Hashable {
where Data: RandomAccessCollection, ID: Hashable
{
enum Root {
case collection(Data)
case single(Data.Element)
@ -32,49 +33,51 @@ extension OutlineGroup where ID == Data.Element.ID,
Parent: View,
Parent == Leaf,
Subgroup == DisclosureGroup<Parent, OutlineSubgroupChildren>,
Data.Element: Identifiable {
public init<DataElement>(_ root: DataElement,
children: KeyPath<DataElement, Data?>,
@ViewBuilder content: @escaping (DataElement) -> Leaf)
where ID == DataElement.ID, DataElement: Identifiable, DataElement == Data.Element {
self.init(root,
id: \.id,
children: children,
content: content)
Data.Element: Identifiable
{
public init<DataElement>(
_ root: DataElement,
children: KeyPath<DataElement, Data?>,
@ViewBuilder content: @escaping (DataElement) -> Leaf
) where ID == DataElement.ID, DataElement: Identifiable, DataElement == Data.Element {
self.init(root, id: \.id, children: children, content: content)
}
public init<DataElement>(_ data: Data,
children: KeyPath<DataElement, Data?>,
@ViewBuilder content: @escaping (DataElement) -> Leaf)
where ID == DataElement.ID,
DataElement: Identifiable,
DataElement == Data.Element {
self.init(data,
id: \.id,
children: children,
content: content)
public init<DataElement>(
_ data: Data,
children: KeyPath<DataElement, Data?>,
@ViewBuilder content: @escaping (DataElement) -> Leaf
) where ID == DataElement.ID, DataElement: Identifiable, DataElement == Data.Element {
self.init(data, id: \.id, children: children, content: content)
}
}
extension OutlineGroup where Parent: View,
Parent == Leaf,
Subgroup == DisclosureGroup<Parent, OutlineSubgroupChildren> {
public init<DataElement>(_ root: DataElement,
id: KeyPath<DataElement, ID>,
children: KeyPath<DataElement, Data?>,
@ViewBuilder content: @escaping (DataElement) -> Leaf)
where DataElement == Data.Element {
Subgroup == DisclosureGroup<Parent, OutlineSubgroupChildren>
{
public init<DataElement>(
_ root: DataElement,
id: KeyPath<DataElement, ID>,
children: KeyPath<DataElement, Data?>,
@ViewBuilder content: @escaping (DataElement) -> Leaf
)
where DataElement == Data.Element
{
self.root = .single(root)
self.children = children
self.id = id
self.content = content
}
public init<DataElement>(_ data: Data,
id: KeyPath<DataElement, ID>,
children: KeyPath<DataElement, Data?>,
@ViewBuilder content: @escaping (DataElement) -> Leaf)
where DataElement == Data.Element {
public init<DataElement>(
_ data: Data,
id: KeyPath<DataElement, ID>,
children: KeyPath<DataElement, Data?>,
@ViewBuilder content: @escaping (DataElement) -> Leaf
)
where DataElement == Data.Element
{
root = .collection(data)
self.id = id
self.children = children
@ -90,10 +93,12 @@ extension OutlineGroup: View where Parent: View, Leaf: View, Subgroup: View {
OutlineSubgroupChildren { () -> AnyView in
if let subgroup = elem[keyPath: children] {
return AnyView(DisclosureGroup(content: {
OutlineGroup(root: .collection(subgroup),
children: children,
id: id,
content: content)
OutlineGroup(
root: .collection(subgroup),
children: children,
id: id,
content: content
)
}) {
content(elem)
})

View File

@ -77,12 +77,14 @@ extension Section: View, SectionView where Parent: View, Content: View, Footer:
}
func listRow(_ style: ListStyle) -> AnyView {
AnyView(VStack(alignment: .leading) {
headerView(style)
sectionContent(style)
footerView(style)
}
.frame(minWidth: 0, maxWidth: .infinity))
AnyView(
VStack(alignment: .leading) {
headerView(style)
sectionContent(style)
footerView(style)
}
.frame(minWidth: 0, maxWidth: .infinity)
)
}
}

View File

@ -48,40 +48,141 @@ public struct TupleView<T>: View {
_children = [AnyView(v1), AnyView(v2), AnyView(v3)]
}
// swiftlint:disable line_length
init<T1: View, T2: View, T3: View, T4: View>(_ v1: T1, _ v2: T2, _ v3: T3, _ v4: T4) where T == (T1, T2, T3, T4) {
init<T1: View, T2: View, T3: View, T4: View>(_ v1: T1, _ v2: T2, _ v3: T3, _ v4: T4)
where T == (T1, T2, T3, T4)
{
value = (v1, v2, v3, v4)
_children = [AnyView(v1), AnyView(v2), AnyView(v3), AnyView(v4)]
}
init<T1: View, T2: View, T3: View, T4: View, T5: View>(_ v1: T1, _ v2: T2, _ v3: T3, _ v4: T4, _ v5: T5) where T == (T1, T2, T3, T4, T5) {
init<T1: View, T2: View, T3: View, T4: View, T5: View>(
_ v1: T1,
_ v2: T2,
_ v3: T3,
_ v4: T4,
_ v5: T5
) where T == (T1, T2, T3, T4, T5) {
value = (v1, v2, v3, v4, v5)
_children = [AnyView(v1), AnyView(v2), AnyView(v3), AnyView(v4), AnyView(v5)]
}
init<T1: View, T2: View, T3: View, T4: View, T5: View, T6: View>(_ v1: T1, _ v2: T2, _ v3: T3, _ v4: T4, _ v5: T5, _ v6: T6) where T == (T1, T2, T3, T4, T5, T6) {
init<T1: View, T2: View, T3: View, T4: View, T5: View, T6: View>(
_ v1: T1,
_ v2: T2,
_ v3: T3,
_ v4: T4,
_ v5: T5,
_ v6: T6
) where T == (T1, T2, T3, T4, T5, T6) {
value = (v1, v2, v3, v4, v5, v6)
_children = [AnyView(v1), AnyView(v2), AnyView(v3), AnyView(v4), AnyView(v5), AnyView(v6)]
}
init<T1: View, T2: View, T3: View, T4: View, T5: View, T6: View, T7: View>(_ v1: T1, _ v2: T2, _ v3: T3, _ v4: T4, _ v5: T5, _ v6: T6, _ v7: T7) where T == (T1, T2, T3, T4, T5, T6, T7) {
init<T1: View, T2: View, T3: View, T4: View, T5: View, T6: View, T7: View>(
_ v1: T1,
_ v2: T2,
_ v3: T3,
_ v4: T4,
_ v5: T5,
_ v6: T6,
_ v7: T7
) where T == (T1, T2, T3, T4, T5, T6, T7) {
value = (v1, v2, v3, v4, v5, v6, v7)
_children = [AnyView(v1), AnyView(v2), AnyView(v3), AnyView(v4), AnyView(v5), AnyView(v6), AnyView(v7)]
_children = [
AnyView(v1),
AnyView(v2),
AnyView(v3),
AnyView(v4),
AnyView(v5),
AnyView(v6),
AnyView(v7),
]
}
init<T1: View, T2: View, T3: View, T4: View, T5: View, T6: View, T7: View, T8: View>(_ v1: T1, _ v2: T2, _ v3: T3, _ v4: T4, _ v5: T5, _ v6: T6, _ v7: T7, _ v8: T8) where T == (T1, T2, T3, T4, T5, T6, T7, T8) {
init<T1: View, T2: View, T3: View, T4: View, T5: View, T6: View, T7: View, T8: View>(
_ v1: T1,
_ v2: T2,
_ v3: T3,
_ v4: T4,
_ v5: T5,
_ v6: T6,
_ v7: T7,
_ v8: T8
) where T == (T1, T2, T3, T4, T5, T6, T7, T8) {
value = (v1, v2, v3, v4, v5, v6, v7, v8)
_children = [AnyView(v1), AnyView(v2), AnyView(v3), AnyView(v4), AnyView(v5), AnyView(v6), AnyView(v7), AnyView(v8)]
_children = [
AnyView(v1),
AnyView(v2),
AnyView(v3),
AnyView(v4),
AnyView(v5),
AnyView(v6),
AnyView(v7),
AnyView(v8),
]
}
init<T1: View, T2: View, T3: View, T4: View, T5: View, T6: View, T7: View, T8: View, T9: View>(_ v1: T1, _ v2: T2, _ v3: T3, _ v4: T4, _ v5: T5, _ v6: T6, _ v7: T7, _ v8: T8, _ v9: T9) where T == (T1, T2, T3, T4, T5, T6, T7, T8, T9) {
init<T1: View, T2: View, T3: View, T4: View, T5: View, T6: View, T7: View, T8: View, T9: View>(
_ v1: T1,
_ v2: T2,
_ v3: T3,
_ v4: T4,
_ v5: T5,
_ v6: T6,
_ v7: T7,
_ v8: T8,
_ v9: T9
) where T == (T1, T2, T3, T4, T5, T6, T7, T8, T9) {
value = (v1, v2, v3, v4, v5, v6, v7, v8, v9)
_children = [AnyView(v1), AnyView(v2), AnyView(v3), AnyView(v4), AnyView(v5), AnyView(v6), AnyView(v7), AnyView(v8), AnyView(v9)]
_children = [
AnyView(v1),
AnyView(v2),
AnyView(v3),
AnyView(v4),
AnyView(v5),
AnyView(v6),
AnyView(v7),
AnyView(v8),
AnyView(v9),
]
}
init<T1: View, T2: View, T3: View, T4: View, T5: View, T6: View, T7: View, T8: View, T9: View, T10: View>(_ v1: T1, _ v2: T2, _ v3: T3, _ v4: T4, _ v5: T5, _ v6: T6, _ v7: T7, _ v8: T8, _ v9: T9, _ v10: T10) where T == (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) {
init<
T1: View,
T2: View,
T3: View,
T4: View,
T5: View,
T6: View,
T7: View,
T8: View,
T9: View,
T10: View
>(
_ v1: T1,
_ v2: T2,
_ v3: T3,
_ v4: T4,
_ v5: T5,
_ v6: T6,
_ v7: T7,
_ v8: T8,
_ v9: T9,
_ v10: T10
) where T == (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) {
value = (v1, v2, v3, v4, v5, v6, v7, v8, v9, v10)
_children = [AnyView(v1), AnyView(v2), AnyView(v3), AnyView(v4), AnyView(v5), AnyView(v6), AnyView(v7), AnyView(v8), AnyView(v9), AnyView(v10)]
_children = [
AnyView(v1),
AnyView(v2),
AnyView(v3),
AnyView(v4),
AnyView(v5),
AnyView(v6),
AnyView(v7),
AnyView(v8),
AnyView(v9),
AnyView(v10),
]
}
}

View File

@ -22,11 +22,13 @@ public struct LazyHGrid<Content>: View where Content: View {
let pinnedViews: PinnedScrollableViews
let content: Content
public init(rows: [GridItem],
alignment: VerticalAlignment = .center,
spacing: CGFloat? = nil,
pinnedViews: PinnedScrollableViews = .init(),
@ViewBuilder content: () -> Content) {
public init(
rows: [GridItem],
alignment: VerticalAlignment = .center,
spacing: CGFloat? = nil,
pinnedViews: PinnedScrollableViews = .init(),
@ViewBuilder content: () -> Content
) {
self.rows = rows
self.alignment = alignment
self.spacing = spacing ?? 8

View File

@ -22,11 +22,13 @@ public struct LazyVGrid<Content>: View where Content: View {
let pinnedViews: PinnedScrollableViews
let content: Content
public init(columns: [GridItem],
alignment: HorizontalAlignment = .center,
spacing: CGFloat? = nil,
pinnedViews: PinnedScrollableViews = .init(),
@ViewBuilder content: () -> Content) {
public init(
columns: [GridItem],
alignment: HorizontalAlignment = .center,
spacing: CGFloat? = nil,
pinnedViews: PinnedScrollableViews = .init(),
@ViewBuilder content: () -> Content
) {
self.columns = columns
self.alignment = alignment
self.spacing = spacing ?? 8

View File

@ -40,9 +40,11 @@ public struct ScrollView<Content>: View where Content: View {
public let axes: Axis.Set
public let showsIndicators: Bool
public init(_ axes: Axis.Set = .vertical,
showsIndicators: Bool = true,
@ViewBuilder content: () -> Content) {
public init(
_ axes: Axis.Set = .vertical,
showsIndicators: Bool = true,
@ViewBuilder content: () -> Content
) {
self.axes = axes
self.showsIndicators = showsIndicators
self.content = content()

View File

@ -81,8 +81,10 @@ public struct _NavigationLinkProxy<Label, Destination> where Label: View, Destin
}
public var label: AnyView {
subject.style.makeBody(configuration: .init(body: AnyView(subject.label),
isSelected: isSelected))
subject.style.makeBody(configuration: .init(
body: AnyView(subject.label),
isSelected: isSelected
))
}
public var style: _AnyNavigationLinkStyle { subject.style }

View File

@ -67,7 +67,8 @@ public struct Picker<Label: View, SelectionValue: Hashable, Content: View>: View
// update the binding.
ForEach(0..<children.count) { index in
if let forEach = mapAnyView(children[index], transform: { (v: ForEachProtocol) in v }),
forEach.elementType == SelectionValue.self {
forEach.elementType == SelectionValue.self
{
let nestedChildren = forEach.children
ForEach(0..<nestedChildren.count) { nestedIndex in
@ -82,7 +83,8 @@ public struct Picker<Label: View, SelectionValue: Hashable, Content: View>: View
}
extension Picker where Label == Text {
@_disfavoredOverload public init<S: StringProtocol>(
@_disfavoredOverload
public init<S: StringProtocol>(
_ title: S,
selection: Binding<SelectionValue>,
@ViewBuilder content: () -> Content

View File

@ -82,7 +82,7 @@ extension Text._Storage {
switch self {
case let .segmentedText(segments):
return segments
.map { $0.0.rawText }
.map(\.0.rawText)
.reduce("", +)
case let .verbatim(text):
return text

View File

@ -17,7 +17,8 @@
/// A `View` with no effect on rendering.
public struct EmptyView: View {
@inlinable public init() {}
@inlinable
public init() {}
public var body: Never {
neverBody("EmptyView")
@ -26,7 +27,8 @@ public struct EmptyView: View {
// swiftlint:disable:next type_name
public struct _ConditionalContent<TrueContent, FalseContent>: View
where TrueContent: View, FalseContent: View {
where TrueContent: View, FalseContent: View
{
enum Storage {
case trueContent(TrueContent)
case falseContent(FalseContent)
@ -86,60 +88,132 @@ extension Optional: View where Wrapped: View {
}
}
// swiftlint:disable line_length
// swiftlint:disable large_tuple
// swiftlint:disable function_parameter_count
extension ViewBuilder {
public static func buildBlock<C0, C1>(_ c0: C0, _ c1: C1) -> TupleView<(C0, C1)> where C0: View, C1: View {
public static func buildBlock<C0, C1>(_ c0: C0, _ c1: C1) -> TupleView<(C0, C1)>
where C0: View, C1: View
{
TupleView(c0, c1)
}
}
extension ViewBuilder {
public static func buildBlock<C0, C1, C2>(_ c0: C0, _ c1: C1, _ c2: C2) -> TupleView<(C0, C1, C2)> where C0: View, C1: View, C2: View {
public static func buildBlock<C0, C1, C2>(
_ c0: C0,
_ c1: C1,
_ c2: C2
) -> TupleView<(C0, C1, C2)> where C0: View, C1: View, C2: View {
TupleView(c0, c1, c2)
}
}
extension ViewBuilder {
public static func buildBlock<C0, C1, C2, C3>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3) -> TupleView<(C0, C1, C2, C3)> where C0: View, C1: View, C2: View, C3: View {
public static func buildBlock<C0, C1, C2, C3>(
_ c0: C0,
_ c1: C1,
_ c2: C2,
_ c3: C3
) -> TupleView<(C0, C1, C2, C3)> where C0: View, C1: View, C2: View, C3: View {
TupleView(c0, c1, c2, c3)
}
}
extension ViewBuilder {
public static func buildBlock<C0, C1, C2, C3, C4>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4) -> TupleView<(C0, C1, C2, C3, C4)> where C0: View, C1: View, C2: View, C3: View, C4: View {
public static func buildBlock<C0, C1, C2, C3, C4>(
_ c0: C0,
_ c1: C1,
_ c2: C2,
_ c3: C3,
_ c4: C4
) -> TupleView<(C0, C1, C2, C3, C4)> where C0: View, C1: View, C2: View, C3: View, C4: View {
TupleView(c0, c1, c2, c3, c4)
}
}
extension ViewBuilder {
public static func buildBlock<C0, C1, C2, C3, C4, C5>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4, _ c5: C5) -> TupleView<(C0, C1, C2, C3, C4, C5)> where C0: View, C1: View, C2: View, C3: View, C4: View, C5: View {
public static func buildBlock<C0, C1, C2, C3, C4, C5>(
_ c0: C0,
_ c1: C1,
_ c2: C2,
_ c3: C3,
_ c4: C4,
_ c5: C5
) -> TupleView<(C0, C1, C2, C3, C4, C5)>
where C0: View, C1: View, C2: View, C3: View, C4: View, C5: View
{
TupleView(c0, c1, c2, c3, c4, c5)
}
}
extension ViewBuilder {
public static func buildBlock<C0, C1, C2, C3, C4, C5, C6>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4, _ c5: C5, _ c6: C6) -> TupleView<(C0, C1, C2, C3, C4, C5, C6)> where C0: View, C1: View, C2: View, C3: View, C4: View, C5: View, C6: View {
public static func buildBlock<C0, C1, C2, C3, C4, C5, C6>(
_ c0: C0,
_ c1: C1,
_ c2: C2,
_ c3: C3,
_ c4: C4,
_ c5: C5,
_ c6: C6
) -> TupleView<(C0, C1, C2, C3, C4, C5, C6)>
where C0: View, C1: View, C2: View, C3: View, C4: View, C5: View, C6: View
{
TupleView(c0, c1, c2, c3, c4, c5, c6)
}
}
extension ViewBuilder {
public static func buildBlock<C0, C1, C2, C3, C4, C5, C6, C7>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4, _ c5: C5, _ c6: C6, _ c7: C7) -> TupleView<(C0, C1, C2, C3, C4, C5, C6, C7)> where C0: View, C1: View, C2: View, C3: View, C4: View, C5: View, C6: View, C7: View {
public static func buildBlock<C0, C1, C2, C3, C4, C5, C6, C7>(
_ c0: C0,
_ c1: C1,
_ c2: C2,
_ c3: C3,
_ c4: C4,
_ c5: C5,
_ c6: C6,
_ c7: C7
) -> TupleView<(C0, C1, C2, C3, C4, C5, C6, C7)>
where C0: View, C1: View, C2: View, C3: View, C4: View, C5: View, C6: View, C7: View
{
TupleView(c0, c1, c2, c3, c4, c5, c6, c7)
}
}
extension ViewBuilder {
public static func buildBlock<C0, C1, C2, C3, C4, C5, C6, C7, C8>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4, _ c5: C5, _ c6: C6, _ c7: C7, _ c8: C8) -> TupleView<(C0, C1, C2, C3, C4, C5, C6, C7, C8)> where C0: View, C1: View, C2: View, C3: View, C4: View, C5: View, C6: View, C7: View, C8: View {
public static func buildBlock<C0, C1, C2, C3, C4, C5, C6, C7, C8>(
_ c0: C0,
_ c1: C1,
_ c2: C2,
_ c3: C3,
_ c4: C4,
_ c5: C5,
_ c6: C6,
_ c7: C7,
_ c8: C8
) -> TupleView<(C0, C1, C2, C3, C4, C5, C6, C7, C8)>
where C0: View, C1: View, C2: View, C3: View, C4: View, C5: View, C6: View, C7: View, C8: View
{
TupleView(c0, c1, c2, c3, c4, c5, c6, c7, c8)
}
}
extension ViewBuilder {
public static func buildBlock<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4, _ c5: C5, _ c6: C6, _ c7: C7, _ c8: C8, _ c9: C9) -> TupleView<(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where C0: View, C1: View, C2: View, C3: View, C4: View, C5: View, C6: View, C7: View, C8: View, C9: View {
public static func buildBlock<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>(
_ c0: C0,
_ c1: C1,
_ c2: C2,
_ c3: C3,
_ c4: C4,
_ c5: C5,
_ c6: C6,
_ c7: C7,
_ c8: C8,
_ c9: C9
) -> TupleView<(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)>
where C0: View, C1: View, C2: View, C3: View, C4: View, C5: View, C6: View, C7: View, C8: View,
C9: View
{
TupleView(c0, c1, c2, c3, c4, c5, c6, c7, c8, c9)
}
}

View File

@ -28,7 +28,7 @@ enum ColorSchemeObserver {
publisher.value = .init(matchMediaDarkScheme: $0[0].object!)
return .undefined
}
_ = matchMediaDarkScheme.addEventListener!("change", closure)
_ = matchMediaDarkScheme.addListener!(closure)
Self.closure = closure
Self.cancellable = Self.publisher.sink { colorScheme in
let systemBackground: String

View File

@ -30,9 +30,11 @@ extension DisclosureGroup: ViewDeferredToRenderer {
]
) {
HTML("div", ["class": "_tokamak-disclosuregroup-chevron"])
.rotationEffect(_DisclosureGroupProxy(self).isExpanded ?
.degrees(90) :
.degrees(0))
.rotationEffect(
_DisclosureGroupProxy(self).isExpanded ?
.degrees(90) :
.degrees(0)
)
}
}

View File

@ -21,7 +21,8 @@ public struct ColorDemo: View {
var color: Color {
guard let v0d = Double(v0),
let v1d = Double(v1),
let v2d = Double(v2) else {
let v2d = Double(v2)
else {
return .white
}
switch colorForm {

View File

@ -34,16 +34,21 @@ struct PathDemo: View {
.fill(Color(red: 1, green: 0.75, blue: 0.1, opacity: 1))
Path { path in
path.addRect(.init(origin: .zero, size: .init(width: 20, height: 20)))
path.addEllipse(in: .init(origin: .init(x: 25, y: 0),
size: .init(width: 20, height: 20)))
path.addRoundedRect(in: .init(origin: .init(x: 50, y: 0),
size: .init(width: 20, height: 20)),
cornerSize: .init(width: 4, height: 4))
path.addArc(center: .init(x: 85, y: 10),
radius: 10,
startAngle: .degrees(90),
endAngle: .degrees(180),
clockwise: true)
path.addEllipse(in: .init(
origin: .init(x: 25, y: 0),
size: .init(width: 20, height: 20)
))
path.addRoundedRect(
in: .init(origin: .init(x: 50, y: 0), size: .init(width: 20, height: 20)),
cornerSize: .init(width: 4, height: 4)
)
path.addArc(
center: .init(x: 85, y: 10),
radius: 10,
startAngle: .degrees(90),
endAngle: .degrees(180),
clockwise: true
)
}
.stroke(Color(red: 1, green: 0.75, blue: 0.1, opacity: 1), lineWidth: 4)
.padding(.vertical)

View File

@ -20,8 +20,11 @@ struct PickerDemo: View {
@State private var selection = 0
var body: some View {
Picker(selection: $selection, label: Text("Text style")
.font(.system(textStyles[selection]))) {
Picker(
selection: $selection,
label: Text("Text style")
.font(.system(textStyles[selection]))
) {
Text("Pick a text style...")
ForEach(0..<textStyles.count) {
Text(String(describing: textStyles[$0]))

View File

@ -69,12 +69,15 @@ struct TokamakDemoView: View {
let list = title(
List {
Section(header: Text("Buttons")) {
NavItem("Counter", destination:
NavItem(
"Counter",
destination:
Counter(count: Count(value: 5), limit: 15)
.padding()
.background(Color(red: 0.9, green: 0.9, blue: 0.9, opacity: 1.0))
.border(Color.red, width: 3)
.foregroundColor(.black))
.foregroundColor(.black)
)
NavItem("ButtonStyle", destination: ButtonStyleDemo())
}
Section(header: Text("Containers")) {

View File

@ -15,9 +15,11 @@
import TokamakCore
private extension DOMViewModifier {
func unwrapToStyle<T>(_ key: KeyPath<Self, T?>,
property: String? = nil,
defaultValue: String = "") -> String {
func unwrapToStyle<T>(
_ key: KeyPath<Self, T?>,
property: String? = nil,
defaultValue: String = ""
) -> String {
if let val = self[keyPath: key] {
if let property = property {
return "\(property): \(val)px;"

View File

@ -34,7 +34,8 @@ extension ModifiedContent: ViewDeferredToRenderer where Content: View {
public var deferredBody: AnyView {
if let domModifier = modifier as? DOMViewModifier {
if let adjacentModifier = content as? AnyModifiedContent,
!(adjacentModifier.anyModifier.isOrderDependent || domModifier.isOrderDependent) {
!(adjacentModifier.anyModifier.isOrderDependent || domModifier.isOrderDependent)
{
// Flatten non-order-dependent modifiers
var attr = domModifier.attributes
for (key, val) in adjacentModifier.anyModifier.attributes {

View File

@ -25,7 +25,8 @@ extension DOMViewModifier {
}
extension ModifiedContent: DOMViewModifier
where Content: DOMViewModifier, Modifier: DOMViewModifier {
where Content: DOMViewModifier, Modifier: DOMViewModifier
{
// Merge attributes
public var attributes: [String: String] {
var attr = content.attributes

View File

@ -16,15 +16,18 @@
//
import TokamakCore
extension StrokeStyle {
static var zero: Self {
.init(lineWidth: 0, lineCap: .butt, lineJoin: .miter, miterLimit: 0, dash: [], dashPhase: 0)
}
}
extension Path: ViewDeferredToRenderer {
// TODO: Support transformations
func svgFrom(storage: Storage,
strokeStyle: StrokeStyle = .init(lineWidth: 0,
lineCap: .butt,
lineJoin: .miter,
miterLimit: 0,
dash: [],
dashPhase: 0)) -> AnyView {
func svgFrom(
storage: Storage,
strokeStyle: StrokeStyle = .zero
) -> AnyView {
let stroke = [
"stroke-width": "\(strokeStyle.lineWidth)",
]
@ -44,11 +47,14 @@ extension Path: ViewDeferredToRenderer {
"y": "\(rect.origin.y - (rect.size.height / 2))",
].merging(stroke, uniquingKeysWith: uniqueKeys))))
case let .ellipse(rect):
return AnyView(HTML("ellipse", ["cx": flexibleCenterX ?? "\(rect.origin.x)",
"cy": flexibleCenterY ?? "\(rect.origin.y)",
"rx": flexibleCenterX ?? "\(rect.size.width)",
"ry": flexibleCenterY ?? "\(rect.size.height)"]
.merging(stroke, uniquingKeysWith: uniqueKeys)))
return AnyView(HTML(
"ellipse",
["cx": flexibleCenterX ?? "\(rect.origin.x)",
"cy": flexibleCenterY ?? "\(rect.origin.y)",
"rx": flexibleCenterX ?? "\(rect.size.width)",
"ry": flexibleCenterY ?? "\(rect.size.height)"]
.merging(stroke, uniquingKeysWith: uniqueKeys)
))
case let .roundedRect(roundedRect):
// When cornerRadius is nil we use 50% rx.
let size = roundedRect.rect.size
@ -56,11 +62,7 @@ extension Path: ViewDeferredToRenderer {
if let cornerSize = roundedRect.cornerSize {
return [
"rx": "\(cornerSize.width)",
"ry": """
\(roundedRect.style == .continuous ?
cornerSize.width :
cornerSize.height)
""",
"ry": " \(roundedRect.style == .continuous ? cornerSize.width : cornerSize.height)",
]
} else {
// For this to support vertical capsules, we need
@ -68,29 +70,31 @@ extension Path: ViewDeferredToRenderer {
return ["ry": "50%"]
}
}()
return AnyView(HTML("rect", [
"width": flexibleWidth ?? "\(size.width)",
"height": flexibleHeight ?? "\(size.height)",
"x": "\(roundedRect.rect.origin.x)",
"y": "\(roundedRect.rect.origin.y)",
]
.merging(cornerRadius, uniquingKeysWith: uniqueKeys)
.merging(stroke, uniquingKeysWith: uniqueKeys)))
return AnyView(HTML(
"rect",
[
"width": flexibleWidth ?? "\(size.width)",
"height": flexibleHeight ?? "\(size.height)",
"x": "\(roundedRect.rect.origin.x)",
"y": "\(roundedRect.rect.origin.y)",
]
.merging(cornerRadius, uniquingKeysWith: uniqueKeys)
.merging(stroke, uniquingKeysWith: uniqueKeys)
))
case let .stroked(stroked):
return AnyView(stroked.path.svgBody(strokeStyle: stroked.style))
case let .trimmed(trimmed):
return trimmed.path.svgFrom(storage: trimmed.path.storage,
strokeStyle: strokeStyle) // TODO: Trim the path
return trimmed.path.svgFrom(
storage: trimmed.path.storage,
strokeStyle: strokeStyle
) // TODO: Trim the path
}
}
func svgFrom(elements: [Element],
strokeStyle: StrokeStyle = .init(lineWidth: 0,
lineCap: .butt,
lineJoin: .miter,
miterLimit: 0,
dash: [],
dashPhase: 0)) -> AnyView {
func svgFrom(
elements: [Element],
strokeStyle: StrokeStyle = .zero
) -> AnyView {
var d = [String]()
for element in elements {
switch element {
@ -112,13 +116,10 @@ extension Path: ViewDeferredToRenderer {
]))
}
func svgFrom(subpaths: [_SubPath],
strokeStyle: StrokeStyle = .init(lineWidth: 0,
lineCap: .butt,
lineJoin: .miter,
miterLimit: 0,
dash: [],
dashPhase: 0)) -> AnyView {
func svgFrom(
subpaths: [_SubPath],
strokeStyle: StrokeStyle = .zero
) -> AnyView {
AnyView(ForEach(Array(subpaths.enumerated()), id: \.offset) { _, path in
path.path.svgBody(strokeStyle: strokeStyle)
})
@ -161,17 +162,16 @@ extension Path: ViewDeferredToRenderer {
}
var size: CGSize {
.init(width: max(storageSize.width, elementsSize.width),
height: max(storageSize.height, elementsSize.height))
.init(
width: max(storageSize.width, elementsSize.width),
height: max(storageSize.height, elementsSize.height)
)
}
@ViewBuilder
func svgBody(strokeStyle: StrokeStyle = .init(lineWidth: 0,
lineCap: .butt,
lineJoin: .miter,
miterLimit: 0,
dash: [],
dashPhase: 0)) -> some View {
func svgBody(
strokeStyle: StrokeStyle = .zero
) -> some View {
svgFrom(storage: storage, strokeStyle: strokeStyle)
svgFrom(elements: elements, strokeStyle: strokeStyle)
svgFrom(subpaths: subpaths, strokeStyle: strokeStyle)

View File

@ -19,7 +19,8 @@ import TokamakCore
// Border modifier
extension _OverlayModifier: DOMViewModifier
where Overlay == _ShapeView<_StrokedShape<TokamakCore.Rectangle._Inset>, Color> {
where Overlay == _ShapeView<_StrokedShape<TokamakCore.Rectangle._Inset>, Color>
{
public var attributes: [String: String] {
let style = overlay.shape.style.dashPhase == 0 ? "solid" : "dashed"
return ["style": """

View File

@ -16,22 +16,25 @@ import TokamakCore
extension PlainListStyle: ListStyleDeferredToRenderer {
public func sectionHeader<Header>(_ header: Header) -> AnyView where Header: View {
AnyView(header
.font(.system(size: 17, weight: .medium))
.padding(.vertical, 4)
.padding(.leading)
.background(Color.listSectionHeader)
.frame(minWidth: 0, maxWidth: .infinity)
AnyView(
header
.font(.system(size: 17, weight: .medium))
.padding(.vertical, 4)
.padding(.leading)
.background(Color.listSectionHeader)
.frame(minWidth: 0, maxWidth: .infinity)
)
}
public func sectionFooter<Footer>(_ footer: Footer) -> AnyView where Footer: View {
AnyView(VStack(alignment: .leading) {
Divider()
_ListRow.listRow(footer, self, isLast: true)
}
.padding(.leading)
.frame(minWidth: 0, maxWidth: .infinity))
AnyView(
VStack(alignment: .leading) {
Divider()
_ListRow.listRow(footer, self, isLast: true)
}
.padding(.leading)
.frame(minWidth: 0, maxWidth: .infinity)
)
}
public func sectionBody<SectionBody>(_ section: SectionBody) -> AnyView where SectionBody: View {
@ -45,28 +48,32 @@ extension PlainListStyle: ListStyleDeferredToRenderer {
extension InsetListStyle: ListStyleDeferredToRenderer {
public func sectionHeader<Header>(_ header: Header) -> AnyView where Header: View {
AnyView(header
.font(.system(size: 17, weight: .medium))
.padding(.vertical, 4)
.padding(.leading, 24)
.background(Color.listSectionHeader)
.frame(minWidth: 0, maxWidth: .infinity)
AnyView(
header
.font(.system(size: 17, weight: .medium))
.padding(.vertical, 4)
.padding(.leading, 24)
.background(Color.listSectionHeader)
.frame(minWidth: 0, maxWidth: .infinity)
)
}
public func sectionFooter<Footer>(_ footer: Footer) -> AnyView where Footer: View {
AnyView(VStack(alignment: .leading) {
Divider()
_ListRow.listRow(footer, self, isLast: true)
}
.padding(.leading, 24)
.frame(minWidth: 0, maxWidth: .infinity))
AnyView(
VStack(alignment: .leading) {
Divider()
_ListRow.listRow(footer, self, isLast: true)
}
.padding(.leading, 24)
.frame(minWidth: 0, maxWidth: .infinity)
)
}
public func sectionBody<SectionBody>(_ section: SectionBody) -> AnyView where SectionBody: View {
AnyView(section
.padding(.leading, 24)
.frame(minWidth: 0, maxWidth: .infinity)
AnyView(
section
.padding(.leading, 24)
.frame(minWidth: 0, maxWidth: .infinity)
)
}
@ -77,31 +84,36 @@ extension InsetListStyle: ListStyleDeferredToRenderer {
extension GroupedListStyle: ListStyleDeferredToRenderer {
public func listBody<ListBody>(_ content: ListBody) -> AnyView where ListBody: View {
AnyView(content
.background(Color.groupedListBackground)
AnyView(
content
.background(Color.groupedListBackground)
)
}
public func sectionHeader<Header>(_ header: Header) -> AnyView where Header: View {
AnyView(header
.font(.caption)
.padding([.top, .leading])
.frame(minWidth: 0, maxWidth: .infinity)
AnyView(
header
.font(.caption)
.padding([.top, .leading])
.frame(minWidth: 0, maxWidth: .infinity)
)
}
public func sectionBody<SectionBody>(_ section: SectionBody) -> AnyView where SectionBody: View {
AnyView(section
.padding(.leading)
.background(Color.listGroupBackground)
.padding(.top)
.frame(minWidth: 0, maxWidth: .infinity))
AnyView(
section
.padding(.leading)
.background(Color.listGroupBackground)
.padding(.top)
.frame(minWidth: 0, maxWidth: .infinity)
)
}
public func sectionFooter<Footer>(_ footer: Footer) -> AnyView where Footer: View {
AnyView(footer
.font(.caption)
.padding([.top, .leading])
AnyView(
footer
.font(.caption)
.padding([.top, .leading])
)
}
@ -116,28 +128,32 @@ extension InsetGroupedListStyle: ListStyleDeferredToRenderer {
}
public func sectionHeader<Header>(_ header: Header) -> AnyView where Header: View {
AnyView(header
.font(.caption)
.padding([.top, .leading])
.padding(.leading)
.frame(minWidth: 0, maxWidth: .infinity)
AnyView(
header
.font(.caption)
.padding([.top, .leading])
.padding(.leading)
.frame(minWidth: 0, maxWidth: .infinity)
)
}
public func sectionBody<SectionBody>(_ section: SectionBody) -> AnyView where SectionBody: View {
AnyView(section
.padding(.leading)
.background(Color.listGroupBackground)
.cornerRadius(10)
.padding([.horizontal, .top])
.frame(minWidth: 0, maxWidth: .infinity))
AnyView(
section
.padding(.leading)
.background(Color.listGroupBackground)
.cornerRadius(10)
.padding([.horizontal, .top])
.frame(minWidth: 0, maxWidth: .infinity)
)
}
public func sectionFooter<Footer>(_ footer: Footer) -> AnyView where Footer: View {
AnyView(footer
.font(.caption)
.padding([.top, .leading])
.padding(.leading)
AnyView(
footer
.font(.caption)
.padding([.top, .leading])
.padding(.leading)
)
}
@ -149,16 +165,18 @@ extension InsetGroupedListStyle: ListStyleDeferredToRenderer {
// TODO: Make sections collabsible (see Section.swift for more impl. details)
extension SidebarListStyle: ListStyleDeferredToRenderer {
public func sectionHeader<Header>(_ header: Header) -> AnyView where Header: View {
AnyView(header
.font(.system(size: 11, weight: .medium))
.foregroundColor(Color._withScheme {
switch $0 {
case .light: return Color(.sRGB, white: 0, opacity: 0.4)
case .dark: return Color(.sRGB, white: 1, opacity: 0.4)
}
})
.padding(.vertical, 2)
.padding(.leading, 4))
AnyView(
header
.font(.system(size: 11, weight: .medium))
.foregroundColor(Color._withScheme {
switch $0 {
case .light: return Color(.sRGB, white: 0, opacity: 0.4)
case .dark: return Color(.sRGB, white: 1, opacity: 0.4)
}
})
.padding(.vertical, 2)
.padding(.leading, 4)
)
}
public func listRow<Row>(_ row: Row) -> AnyView where Row: View {
@ -166,10 +184,11 @@ extension SidebarListStyle: ListStyleDeferredToRenderer {
}
public func listBody<ListBody>(_ content: ListBody) -> AnyView where ListBody: View {
AnyView(content
._navigationLinkStyle(_SidebarNavigationLinkStyle())
.padding([.horizontal, .top], 6)
.background(Color.sidebarBackground)
AnyView(
content
._navigationLinkStyle(_SidebarNavigationLinkStyle())
.padding([.horizontal, .top], 6)
.background(Color.sidebarBackground)
)
}
}

View File

@ -106,10 +106,14 @@ extension Text: AnyHTML {
case let .segmentedText(segments):
return segments
.map {
TextSpan(content: $0.0.rawText,
attributes: Self.attributes(from: $0.1,
environment: proxy.environment))
.outerHTML
TextSpan(
content: $0.0.rawText,
attributes: Self.attributes(
from: $0.1,
environment: proxy.environment
)
)
.outerHTML
}
.reduce("", +)
}
@ -118,14 +122,18 @@ extension Text: AnyHTML {
public var tag: String { "span" }
public var attributes: [String: String] {
let proxy = _TextProxy(self)
return Self.attributes(from: proxy.modifiers,
environment: proxy.environment)
return Self.attributes(
from: proxy.modifiers,
environment: proxy.environment
)
}
}
extension Text {
static func attributes(from modifiers: [_Modifier],
environment: EnvironmentValues) -> [String: String] {
static func attributes(
from modifiers: [_Modifier],
environment: EnvironmentValues
) -> [String: String] {
let isRedacted = environment.redactionReasons.contains(.placeholder)
var font: Font?

View File

@ -30,8 +30,7 @@ public final class TestView: Target {
public var view: AnyView
/** Initialize a new test view. */
init<V: View>(_ view: V,
_ subviews: [TestView] = []) {
init<V: View>(_ view: V, _ subviews: [TestView] = []) {
self.subviews = subviews
self.view = AnyView(view)
}