Skip to content

Commit eceb3d6

Browse files
Fix tests + tint
1 parent dc155d1 commit eceb3d6

File tree

1 file changed

+185
-0
lines changed

1 file changed

+185
-0
lines changed
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
//
2+
// RichTextStyleToggle.swift
3+
// RichTextKit
4+
//
5+
// Created by Daniel Saidi on 2022-12-08.
6+
// Copyright © 2022-2023 Daniel Saidi. All rights reserved.
7+
//
8+
9+
import SwiftUI
10+
11+
/**
12+
This button can be used to toggle a ``RichTextStyle`` value.
13+
14+
This view renders a plain `Toggle` that uses a button style.
15+
This means that you can use and configure it as normal. The
16+
only exception is the tint, which is specified by the style
17+
that you can inject.
18+
19+
Note that the view will use a ``RichTextStyleButton`` if it
20+
is used on iOS 14, macOS 11, tvOS 14 and watchOS 8.
21+
*/
22+
public struct RichTextStyleToggle: View {
23+
24+
/**
25+
Create a rich text style toggle toggle.
26+
27+
- Parameters:
28+
- style: The style to toggle.
29+
- buttonStyle: The button style to use, by default ``RichTextStyleToggle/Style/standard``.
30+
- value: The value to bind to.
31+
- fillVertically: Whether or not fill up vertical space in a non-greedy way, by default `false`.
32+
*/
33+
public init(
34+
style: RichTextStyle,
35+
buttonStyle: Style = .standard,
36+
value: Binding<Bool>,
37+
fillVertically: Bool = false
38+
) {
39+
self.style = style
40+
self.buttonStyle = buttonStyle
41+
self.value = value
42+
self.fillVertically = fillVertically
43+
}
44+
45+
/**
46+
Create a rich text style toggle.
47+
48+
- Parameters:
49+
- style: The style to toggle.
50+
- buttonStyle: The button style to use, by default ``RichTextStyleToggle/Style/standard``.
51+
- context: The context to affect.
52+
- fillVertically: Whether or not fill up vertical space in a non-greedy way, by default `false`.
53+
*/
54+
public init(
55+
style: RichTextStyle,
56+
buttonStyle: Style = .standard,
57+
context: RichTextContext,
58+
fillVertically: Bool = false
59+
) {
60+
self.init(
61+
style: style,
62+
buttonStyle: buttonStyle,
63+
value: context.binding(for: style),
64+
fillVertically: fillVertically
65+
)
66+
}
67+
68+
private let style: RichTextStyle
69+
private let buttonStyle: Style
70+
private let value: Binding<Bool>
71+
private let fillVertically: Bool
72+
73+
public var body: some View {
74+
#if os(tvOS) || os(watchOS)
75+
toggle
76+
#else
77+
toggle.toggleStyle(.button)
78+
#endif
79+
}
80+
81+
private var toggle: some View {
82+
Toggle(isOn: value) {
83+
style.icon
84+
.frame(maxHeight: fillVertically ? .infinity : nil)
85+
.foregroundColor(tintColor)
86+
}
87+
.keyboardShortcut(for: style)
88+
.accessibilityLabel(style.title)
89+
}
90+
}
91+
92+
private extension RichTextStyleToggle {
93+
94+
var backgroundColor: Color {
95+
value.wrappedValue ? buttonStyle.activeColor.opacity(0.2) : .clear
96+
}
97+
}
98+
99+
public extension RichTextStyleToggle {
100+
101+
/**
102+
This style can be used to style a ``RichTextStyleToggle``.
103+
*/
104+
struct Style {
105+
106+
/**
107+
Create a rich text style button style.
108+
109+
- Parameters:
110+
- inactiveColor: The color to apply when the button is inactive, by default `nil`.
111+
- activeColor: The color to apply when the button is active, by default `.blue`.
112+
*/
113+
public init(
114+
inactiveColor: Color? = nil,
115+
activeColor: Color = .blue
116+
) {
117+
self.inactiveColor = inactiveColor
118+
self.activeColor = activeColor
119+
}
120+
121+
/// The color to apply when the button is inactive.
122+
public var inactiveColor: Color?
123+
124+
/// The color to apply when the button is active.
125+
public var activeColor: Color
126+
}
127+
}
128+
129+
public extension RichTextStyleToggle.Style {
130+
131+
/**
132+
The standard ``RichTextStyleToggle`` style.
133+
*/
134+
static var standard = RichTextStyleToggle.Style()
135+
}
136+
137+
private extension RichTextStyleToggle {
138+
139+
var isOn: Bool {
140+
value.wrappedValue
141+
}
142+
143+
var tintColor: Color? {
144+
isOn ? buttonStyle.activeColor : buttonStyle.inactiveColor
145+
}
146+
}
147+
148+
struct RichTextStyleToggle_Previews: PreviewProvider {
149+
150+
struct Preview: View {
151+
152+
@State
153+
private var isBoldOn = false
154+
155+
@State
156+
private var isItalicOn = true
157+
158+
@State
159+
private var isStrikethroughOn = true
160+
161+
@State
162+
private var isUnderlinedOn = true
163+
164+
var body: some View {
165+
HStack {
166+
RichTextStyleToggle(
167+
style: .bold,
168+
value: $isBoldOn)
169+
RichTextStyleToggle(
170+
style: .italic,
171+
value: $isItalicOn)
172+
RichTextStyleToggle(
173+
style: .strikethrough,
174+
value: $isStrikethroughOn)
175+
RichTextStyleToggle(
176+
style: .underlined,
177+
value: $isUnderlinedOn)
178+
}.padding()
179+
}
180+
}
181+
182+
static var previews: some View {
183+
Preview()
184+
}
185+
}

0 commit comments

Comments
 (0)