From b5ccb1cdac8763bdde8a373cb59eb1ddd7999dc9 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Thu, 12 Feb 2026 01:39:55 +0100 Subject: [PATCH] Implemented the OnNewlineFocusModifier view modifier in the app target. --- .../OnNewlineFocusModifier.swift | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 App/Sources/View Modifiers/OnNewlineFocusModifier.swift diff --git a/App/Sources/View Modifiers/OnNewlineFocusModifier.swift b/App/Sources/View Modifiers/OnNewlineFocusModifier.swift new file mode 100644 index 0000000..d9efb52 --- /dev/null +++ b/App/Sources/View Modifiers/OnNewlineFocusModifier.swift @@ -0,0 +1,86 @@ +import SwiftUI + +/// A view modifier that intercepts newlines in a text field and transfers focus to another field. +/// +/// This modifier monitors text changes in a `TextField` component and prevents newlines +/// from being added. Instead, when a newline is detected, it updates the focus state to move to +/// a specified field. +struct OnNewlineFocusModifier: ViewModifier { + + // MARK: Properties + + /// Binding to the text being edited. + @Binding + private var text: String + + /// Binding to the focus state. + private let focusState: FocusState.Binding + + /// The field to focus when a newline is detected. + private let targetField: Field + + // MARK: Initializers + + /// Creates a modifier that transfers focus on newline. + /// + /// - Parameters: + /// - text: A binding to the text being edited. + /// - focusState: A binding to the focus state. + /// - targetField: The field to focus when a newline is detected. + init( + text: Binding, + focusState: FocusState.Binding, + targetField: Field + ) { + self._text = text + + self.focusState = focusState + self.targetField = targetField + } + + // MARK: Body + + /// The content and behavior of the view modifier. + func body(content: Content) -> some View { + content + .onChange(of: text) { oldValue, newValue in + guard newValue.contains(.newline) else { + return + } + + text = oldValue + focusState.wrappedValue = targetField + } + } + +} + +// MARK: - View Extension + +extension View { + + /// Transfers focus to another field when the user presses return in a text field. + /// + /// This modifier prevents newlines from being added and instead moves keyboard focus + /// to the specified field. Useful for creating a form-like flow between text fields. + /// + /// - Parameters: + /// - text: A binding to the text being edited. + /// - field: The field to focus when return is pressed. + /// - focusState: A binding to the focus state. + /// - Returns: A modified view with focus transfer behavior. + func onNewlineFocus( + _ text: Binding, + to field: Field, + on focusState: FocusState.Binding + ) -> some View { + modifier( + OnNewlineFocusModifier( + text: text, + focusState: focusState, + targetField: field + ) + ) + } + +}