Skip to content

Commit 9f07a7b

Browse files
Merge pull request #88 from componentskit/no-focus-inits
Add inits without `focus` to `SUInputField` and `SUTextInput`
2 parents d159ace + ca0ee89 commit 9f07a7b

File tree

3 files changed

+79
-12
lines changed

3 files changed

+79
-12
lines changed

Sources/ComponentsKit/Components/InputField/SUInputField.swift

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public struct SUInputField<FocusValue: Hashable>: View {
1414
///
1515
/// When the `localFocus` value matches `globalFocus`, this input field becomes focused.
1616
/// This enables centralized focus management for multiple text inputs and input fields within a single view.
17-
@FocusState.Binding public var globalFocus: FocusValue
17+
public let globalFocus: FocusState<FocusValue>.Binding?
1818

1919
/// The unique value for this field to match against the global focus state to determine whether this input field is focused.
2020
///
@@ -24,7 +24,7 @@ public struct SUInputField<FocusValue: Hashable>: View {
2424
///
2525
/// - Warning: The `localFocus` value must be unique to each text input and input field, to ensure that different
2626
/// text inputs and input fields within the same view can be independently focused based on the shared `globalFocus`.
27-
public var localFocus: FocusValue
27+
public let localFocus: FocusValue
2828

2929
// MARK: Initialization
3030

@@ -41,7 +41,7 @@ public struct SUInputField<FocusValue: Hashable>: View {
4141
model: InputFieldVM = .init()
4242
) {
4343
self._text = text
44-
self._globalFocus = globalFocus
44+
self.globalFocus = globalFocus
4545
self.localFocus = localFocus
4646
self.model = model
4747
}
@@ -71,7 +71,7 @@ public struct SUInputField<FocusValue: Hashable>: View {
7171
.tint(self.model.tintColor.color)
7272
.font(self.model.preferredFont.font)
7373
.foregroundStyle(self.model.foregroundColor.color)
74-
.focused(self.$globalFocus, equals: self.localFocus)
74+
.applyFocus(globalFocus: self.globalFocus, localFocus: self.localFocus)
7575
.disabled(!self.model.isEnabled)
7676
.keyboardType(self.model.keyboardType)
7777
.submitLabel(self.model.submitType.submitLabel)
@@ -82,7 +82,7 @@ public struct SUInputField<FocusValue: Hashable>: View {
8282
.frame(height: self.model.height)
8383
.background(self.model.backgroundColor.color)
8484
.onTapGesture {
85-
self.globalFocus = self.localFocus
85+
self.globalFocus?.wrappedValue = self.localFocus
8686
}
8787
.clipShape(
8888
RoundedRectangle(
@@ -92,6 +92,22 @@ public struct SUInputField<FocusValue: Hashable>: View {
9292
}
9393
}
9494

95+
// MARK: Helpers
96+
97+
extension View {
98+
@ViewBuilder
99+
fileprivate func applyFocus<FocusValue: Hashable>(
100+
globalFocus: FocusState<FocusValue>.Binding?,
101+
localFocus: FocusValue,
102+
) -> some View {
103+
if let globalFocus {
104+
self.focused(globalFocus, equals: localFocus)
105+
} else {
106+
self
107+
}
108+
}
109+
}
110+
95111
// MARK: - Boolean Focus Value
96112

97113
extension SUInputField where FocusValue == Bool {
@@ -106,7 +122,25 @@ extension SUInputField where FocusValue == Bool {
106122
model: InputFieldVM = .init()
107123
) {
108124
self._text = text
109-
self._globalFocus = isFocused
125+
self.globalFocus = isFocused
126+
self.localFocus = true
127+
self.model = model
128+
}
129+
}
130+
131+
// MARK: - No Focus Value
132+
133+
extension SUInputField where FocusValue == Bool {
134+
/// Initializer.
135+
/// - Parameters:
136+
/// - text: A Binding value to control the inputted text.
137+
/// - model: A model that defines the appearance properties.
138+
public init(
139+
text: Binding<String>,
140+
model: InputFieldVM = .init()
141+
) {
142+
self._text = text
143+
self.globalFocus = nil
110144
self.localFocus = true
111145
self.model = model
112146
}

Sources/ComponentsKit/Components/TextInput/SUTextInput.swift

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public struct SUTextInput<FocusValue: Hashable>: View {
1414
///
1515
/// When the `localFocus` value matches `globalFocus`, this text input becomes focused.
1616
/// This enables centralized focus management for multiple text inputs and input fields within a single view.
17-
@FocusState.Binding public var globalFocus: FocusValue
17+
public let globalFocus: FocusState<FocusValue>.Binding?
1818

1919
/// The unique value for this field to match against the global focus state to determine whether this text input is focused.
2020
///
@@ -24,7 +24,7 @@ public struct SUTextInput<FocusValue: Hashable>: View {
2424
///
2525
/// - Warning: The `localFocus` value must be unique to each text input and input field, to ensure that different
2626
/// text inputs and input fields within the same view can be independently focused based on the shared `globalFocus`.
27-
public var localFocus: FocusValue
27+
public let localFocus: FocusValue
2828

2929
@State private var textEditorPreferredHeight: CGFloat = 0
3030

@@ -43,7 +43,7 @@ public struct SUTextInput<FocusValue: Hashable>: View {
4343
model: TextInputVM = .init()
4444
) {
4545
self._text = text
46-
self._globalFocus = globalFocus
46+
self.globalFocus = globalFocus
4747
self.localFocus = localFocus
4848
self.model = model
4949
}
@@ -67,7 +67,7 @@ public struct SUTextInput<FocusValue: Hashable>: View {
6767
.font(self.model.preferredFont.font)
6868
.foregroundStyle(self.model.foregroundColor.color)
6969
.tint(self.model.tintColor.color)
70-
.focused(self.$globalFocus, equals: self.localFocus)
70+
.applyFocus(globalFocus: self.globalFocus, localFocus: self.localFocus)
7171
.disabled(!self.model.isEnabled)
7272
.keyboardType(self.model.keyboardType)
7373
.submitLabel(self.model.submitType.submitLabel)
@@ -154,6 +154,18 @@ extension View {
154154
UITextView.appearance().textContainer.lineFragmentPadding = 0
155155
}
156156
}
157+
158+
@ViewBuilder
159+
fileprivate func applyFocus<FocusValue: Hashable>(
160+
globalFocus: FocusState<FocusValue>.Binding?,
161+
localFocus: FocusValue,
162+
) -> some View {
163+
if let globalFocus {
164+
self.focused(globalFocus, equals: localFocus)
165+
} else {
166+
self
167+
}
168+
}
157169
}
158170

159171
// MARK: - Boolean Focus Value
@@ -170,7 +182,25 @@ extension SUTextInput where FocusValue == Bool {
170182
model: TextInputVM = .init()
171183
) {
172184
self._text = text
173-
self._globalFocus = isFocused
185+
self.globalFocus = isFocused
186+
self.localFocus = true
187+
self.model = model
188+
}
189+
}
190+
191+
// MARK: - No Focus Value
192+
193+
extension SUTextInput where FocusValue == Bool {
194+
/// Initializer.
195+
/// - Parameters:
196+
/// - text: A Binding value to control the inputted text.
197+
/// - model: A model that defines the appearance properties.
198+
public init(
199+
text: Binding<String>,
200+
model: TextInputVM = .init()
201+
) {
202+
self._text = text
203+
self.globalFocus = nil
174204
self.localFocus = true
175205
self.model = model
176206
}

Sources/ComponentsKit/Components/TextInput/UKTextInput.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,11 @@ extension UKTextInput {
205205
}
206206

207207
static func textView(_ textView: UITextView, padding: CGFloat) {
208-
textView.textContainerInset = .init(inset: padding)
209208
textView.textContainer.lineFragmentPadding = 0
209+
textView.textContainerInset.top = padding
210+
textView.textContainerInset.left = padding
211+
textView.textContainerInset.right = padding
212+
textView.textContainerInset.bottom = padding
210213
}
211214

212215
static func placeholder(

0 commit comments

Comments
 (0)