Add Primary/Secondary/Tertiary/QuaternaryContentStyle (#419)
This commit is contained in:
parent
4a7748ad6b
commit
2efa80a57d
|
@ -74,6 +74,9 @@ public extension View {
|
|||
}
|
||||
|
||||
public func modifyEnvironment(_ values: inout EnvironmentValues) {
|
||||
values._backgroundStyle = .init(styles: [style, style, style], environment: values)
|
||||
values._backgroundStyle = .init(
|
||||
styles: (primary: style, secondary: style, tertiary: style),
|
||||
environment: values
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
// Copyright 2020-2021 Tokamak contributors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Created by Carson Katri on 7/7/21.
|
||||
//
|
||||
|
||||
@frozen public struct PrimaryContentStyle {
|
||||
@inlinable
|
||||
public init() {}
|
||||
}
|
||||
|
||||
extension PrimaryContentStyle: ShapeStyle {
|
||||
public func _apply(to shape: inout _ShapeStyle_Shape) {
|
||||
if !shape.inRecursiveStyle,
|
||||
let foregroundStyle = shape.environment._foregroundStyle
|
||||
{
|
||||
if foregroundStyle.styles.primary is Self {
|
||||
shape.inRecursiveStyle = true
|
||||
}
|
||||
foregroundStyle.styles.primary._apply(to: &shape)
|
||||
} else {
|
||||
shape.result = .color(shape.environment.foregroundColor ?? .primary)
|
||||
}
|
||||
}
|
||||
|
||||
public static func _apply(to shape: inout _ShapeStyle_ShapeType) {}
|
||||
}
|
||||
|
||||
@frozen public struct SecondaryContentStyle {
|
||||
@inlinable
|
||||
public init() {}
|
||||
}
|
||||
|
||||
extension SecondaryContentStyle: ShapeStyle {
|
||||
public func _apply(to shape: inout _ShapeStyle_Shape) {
|
||||
if !shape.inRecursiveStyle,
|
||||
let foregroundStyle = shape.environment._foregroundStyle
|
||||
{
|
||||
if foregroundStyle.styles.secondary is Self {
|
||||
shape.inRecursiveStyle = true
|
||||
}
|
||||
foregroundStyle.styles.secondary._apply(to: &shape)
|
||||
} else {
|
||||
shape.result = .color((shape.environment.foregroundColor ?? .primary).opacity(0.5))
|
||||
}
|
||||
}
|
||||
|
||||
public static func _apply(to shape: inout _ShapeStyle_ShapeType) {}
|
||||
}
|
||||
|
||||
@frozen public struct TertiaryContentStyle {
|
||||
@inlinable
|
||||
public init() {}
|
||||
}
|
||||
|
||||
extension TertiaryContentStyle: ShapeStyle {
|
||||
public func _apply(to shape: inout _ShapeStyle_Shape) {
|
||||
if !shape.inRecursiveStyle,
|
||||
let foregroundStyle = shape.environment._foregroundStyle
|
||||
{
|
||||
if foregroundStyle.styles.tertiary is Self {
|
||||
shape.inRecursiveStyle = true
|
||||
}
|
||||
foregroundStyle.styles.tertiary._apply(to: &shape)
|
||||
} else {
|
||||
shape.result = .color((shape.environment.foregroundColor ?? .primary).opacity(0.3))
|
||||
}
|
||||
}
|
||||
|
||||
public static func _apply(to shape: inout _ShapeStyle_ShapeType) {}
|
||||
}
|
||||
|
||||
@frozen public struct QuaternaryContentStyle {
|
||||
@inlinable
|
||||
public init() {}
|
||||
}
|
||||
|
||||
extension QuaternaryContentStyle: ShapeStyle {
|
||||
public func _apply(to shape: inout _ShapeStyle_Shape) {
|
||||
if !shape.inRecursiveStyle,
|
||||
let foregroundStyle = shape.environment._foregroundStyle
|
||||
{
|
||||
if foregroundStyle.styles.tertiary is Self {
|
||||
shape.inRecursiveStyle = true
|
||||
}
|
||||
foregroundStyle.styles.tertiary._apply(to: &shape)
|
||||
} else {
|
||||
shape.result = .color((shape.environment.foregroundColor ?? .primary).opacity(0.2))
|
||||
}
|
||||
}
|
||||
|
||||
public static func _apply(to shape: inout _ShapeStyle_ShapeType) {}
|
||||
}
|
|
@ -60,24 +60,36 @@ public extension View {
|
|||
}
|
||||
|
||||
@inlinable
|
||||
func foregroundStyle<S1, S2, S3>(_ primary: S1, _ secondary: S2,
|
||||
_ tertiary: S3) -> some View
|
||||
func foregroundStyle<S1, S2, S3>(
|
||||
_ primary: S1,
|
||||
_ secondary: S2,
|
||||
_ tertiary: S3
|
||||
) -> some View
|
||||
where S1: ShapeStyle, S2: ShapeStyle, S3: ShapeStyle
|
||||
{
|
||||
modifier(_ForegroundStyleModifier(styles: [primary, secondary, tertiary]))
|
||||
modifier(_ForegroundStyleModifier(primary: primary, secondary: secondary, tertiary: tertiary))
|
||||
}
|
||||
}
|
||||
|
||||
@frozen public struct _ForegroundStyleModifier: ViewModifier, EnvironmentModifier {
|
||||
public var styles: [ShapeStyle]
|
||||
@frozen public struct _ForegroundStyleModifier<Primary, Secondary, Tertiary>: ViewModifier,
|
||||
EnvironmentModifier
|
||||
where Primary: ShapeStyle, Secondary: ShapeStyle, Tertiary: ShapeStyle
|
||||
{
|
||||
public var primary: Primary
|
||||
public var secondary: Secondary
|
||||
public var tertiary: Tertiary
|
||||
|
||||
@inlinable
|
||||
public init(styles: [ShapeStyle]) {
|
||||
self.styles = styles
|
||||
public init(
|
||||
primary: Primary,
|
||||
secondary: Secondary,
|
||||
tertiary: Tertiary
|
||||
) {
|
||||
(self.primary, self.secondary, self.tertiary) = (primary, secondary, tertiary)
|
||||
}
|
||||
|
||||
public typealias Body = Never
|
||||
public func modifyEnvironment(_ values: inout EnvironmentValues) {
|
||||
values._foregroundStyle = .init(styles: styles, environment: values)
|
||||
values._foregroundStyle = .init(styles: (primary, secondary, tertiary), environment: values)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,23 +23,23 @@ public protocol ShapeStyle {
|
|||
}
|
||||
|
||||
public struct AnyShapeStyle: ShapeStyle {
|
||||
let styles: [ShapeStyle]
|
||||
let styles: (primary: ShapeStyle, secondary: ShapeStyle, tertiary: ShapeStyle)
|
||||
var stylesArray: [ShapeStyle] {
|
||||
[styles.primary, styles.secondary, styles.tertiary]
|
||||
}
|
||||
|
||||
let environment: EnvironmentValues
|
||||
|
||||
public func _apply(to shape: inout _ShapeStyle_Shape) {
|
||||
shape.environment = environment
|
||||
if styles.count > 1 {
|
||||
let results = styles.map { style -> _ShapeStyle_Shape.Result in
|
||||
var copy = shape
|
||||
style._apply(to: ©)
|
||||
return copy.result
|
||||
}
|
||||
shape
|
||||
.result =
|
||||
.resolved(.array(results.compactMap { $0.resolvedStyle(on: shape, in: environment) }))
|
||||
} else if let first = styles.first {
|
||||
first._apply(to: &shape)
|
||||
let results = stylesArray.map { style -> _ShapeStyle_Shape.Result in
|
||||
var copy = shape
|
||||
style._apply(to: ©)
|
||||
return copy.result
|
||||
}
|
||||
shape
|
||||
.result =
|
||||
.resolved(.array(results.compactMap { $0.resolvedStyle(on: shape, in: environment) }))
|
||||
|
||||
switch shape.operation {
|
||||
case let .prepare(text, level):
|
||||
|
@ -50,7 +50,9 @@ public struct AnyShapeStyle: ShapeStyle {
|
|||
shape.result = .prepared(Text(storage: text.storage, modifiers: modifiers))
|
||||
case let .resolveStyle(levels):
|
||||
if case let .resolved(resolved) = shape.result {
|
||||
if case let .array(children) = resolved {
|
||||
if case let .array(children) = resolved,
|
||||
children.count >= levels.upperBound
|
||||
{
|
||||
shape.result = .resolved(.array(.init(children[levels])))
|
||||
}
|
||||
} else if let resolved = shape.result.resolvedStyle(on: shape, in: environment) {
|
||||
|
|
|
@ -83,7 +83,16 @@ public typealias Rectangle = TokamakCore.Rectangle
|
|||
public typealias RoundedRectangle = TokamakCore.RoundedRectangle
|
||||
public typealias ContainerRelativeShape = TokamakCore.ContainerRelativeShape
|
||||
|
||||
// MARK: Shape Styles
|
||||
|
||||
public typealias PrimaryContentStyle = TokamakCore.PrimaryContentStyle
|
||||
public typealias SecondaryContentStyle = TokamakCore.SecondaryContentStyle
|
||||
public typealias TertiaryContentStyle = TokamakCore.TertiaryContentStyle
|
||||
public typealias QuaternaryContentStyle = TokamakCore.QuaternaryContentStyle
|
||||
|
||||
public typealias ForegroundStyle = TokamakCore.ForegroundStyle
|
||||
public typealias BackgroundStyle = TokamakCore.BackgroundStyle
|
||||
|
||||
public typealias Material = TokamakCore.Material
|
||||
|
||||
// MARK: Primitive values
|
||||
|
|
|
@ -89,6 +89,18 @@ struct ShapeStyleDemo: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
HStack {
|
||||
VStack {
|
||||
Text("Primary")
|
||||
.foregroundStyle(PrimaryContentStyle())
|
||||
Text("Secondary")
|
||||
.foregroundStyle(SecondaryContentStyle())
|
||||
Text("Tertiary")
|
||||
.foregroundStyle(TertiaryContentStyle())
|
||||
Text("Quaternary")
|
||||
.foregroundStyle(QuaternaryContentStyle())
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,16 @@ public typealias Rectangle = TokamakCore.Rectangle
|
|||
public typealias RoundedRectangle = TokamakCore.RoundedRectangle
|
||||
public typealias ContainerRelativeShape = TokamakCore.ContainerRelativeShape
|
||||
|
||||
// MARK: Shape Styles
|
||||
|
||||
public typealias PrimaryContentStyle = TokamakCore.PrimaryContentStyle
|
||||
public typealias SecondaryContentStyle = TokamakCore.SecondaryContentStyle
|
||||
public typealias TertiaryContentStyle = TokamakCore.TertiaryContentStyle
|
||||
public typealias QuaternaryContentStyle = TokamakCore.QuaternaryContentStyle
|
||||
|
||||
public typealias ForegroundStyle = TokamakCore.ForegroundStyle
|
||||
public typealias BackgroundStyle = TokamakCore.BackgroundStyle
|
||||
|
||||
public typealias Material = TokamakCore.Material
|
||||
|
||||
// MARK: Primitive values
|
||||
|
|
|
@ -200,6 +200,28 @@ final class RenderingTests: XCTestCase {
|
|||
)
|
||||
}
|
||||
|
||||
func testContentStyles() {
|
||||
assertSnapshot(
|
||||
matching: HStack {
|
||||
Rectangle()
|
||||
.frame(width: 50, height: 50)
|
||||
.foregroundStyle(PrimaryContentStyle())
|
||||
Rectangle()
|
||||
.frame(width: 50, height: 50)
|
||||
.foregroundStyle(SecondaryContentStyle())
|
||||
Rectangle()
|
||||
.frame(width: 50, height: 50)
|
||||
.foregroundStyle(TertiaryContentStyle())
|
||||
Rectangle()
|
||||
.frame(width: 50, height: 50)
|
||||
.foregroundStyle(QuaternaryContentStyle())
|
||||
}
|
||||
.foregroundColor(.blue),
|
||||
as: .image(size: .init(width: 275, height: 100)),
|
||||
timeout: defaultSnapshotTimeout
|
||||
)
|
||||
}
|
||||
|
||||
func testMaterial() {
|
||||
assertSnapshot(
|
||||
matching: ZStack {
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
Loading…
Reference in New Issue