From 998f8fe33046d8397bfcb850ef970f73cd50daac Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Thu, 12 Feb 2026 01:51:06 +0100 Subject: [PATCH] Implemented the OnEmptyNewlineResignFocus view modifier in the app target. --- .../OnEmptyNewlineResignFocusModifier.swift | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 App/Sources/View Modifiers/OnEmptyNewlineResignFocusModifier.swift diff --git a/App/Sources/View Modifiers/OnEmptyNewlineResignFocusModifier.swift b/App/Sources/View Modifiers/OnEmptyNewlineResignFocusModifier.swift new file mode 100644 index 0000000..c909894 --- /dev/null +++ b/App/Sources/View Modifiers/OnEmptyNewlineResignFocusModifier.swift @@ -0,0 +1,81 @@ +import SwiftUI + +/// A view modifier that clears text and removes focus when return is pressed on empty content. +/// +/// This modifier monitors text changes and provides smart handling of newlines: +/// - Empty text is allowed normally +/// - Newlines at the end of whitespace-only text clear the field and remove focus +/// - Multi-line content with actual text is preserved normally +struct OnEmptyNewlineResignFocusModifier: ViewModifier { + + // MARK: Properties + + /// Binding to the text being edited. + @Binding + private var text: String + + /// Binding to the focus state. + private let focusState: FocusState.Binding + + // MARK: Initializers + + /// Creates a modifier that clears text on empty newline. + /// + /// - Parameters: + /// - text: A binding to the text being edited. + /// - focusState: A binding to the focus state. + init( + text: Binding, + focusState: FocusState.Binding + ) { + self._text = text + self.focusState = focusState + } + + // 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.isEmpty == false else { + return + } + + if newValue.last == .newline { + if newValue.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { + text = "" + focusState.wrappedValue = nil + } + } + } + } + +} + +// MARK: - View Extension + +extension View { + + /// Clears the text and removes focus when return is pressed on empty content. + /// + /// This modifier allows users to dismiss an optional text field by pressing return + /// when the field is empty or contains only whitespace. Multi-line content is preserved normally. + /// + /// - Parameters: + /// - focusState: A binding to the focus state. + /// - text: A binding to the text being edited. + /// - Returns: A modified view with clear-on-empty behavior. + func onEmptyNewlineResignFocus( + text: Binding, + from focusState: FocusState.Binding + ) -> some View { + modifier( + OnEmptyNewlineResignFocusModifier( + text: text, + focusState: focusState + ) + ) + } + +}