import SwiftUI import AppKit // MARK: - AppKit NSTextField 桥接(支持 Cmd+A/C/V/X) struct AppKitTextField: NSViewRepresentable { @Binding var text: String var placeholder: String var isEditable: Bool var onSubmit: () -> Void func makeNSView(context: Context) -> KeyEquivalentTextField { let textField = KeyEquivalentTextField() textField.isBordered = false textField.isBezeled = false textField.drawsBackground = false textField.focusRingType = .none textField.font = .systemFont(ofSize: 12) textField.textColor = .white textField.placeholderString = placeholder textField.isEditable = isEditable textField.delegate = context.coordinator textField.cell?.wraps = false textField.cell?.isScrollable = true textField.lineBreakMode = .byClipping return textField } func updateNSView(_ nsView: KeyEquivalentTextField, context: Context) { if nsView.stringValue != text { nsView.stringValue = text } nsView.placeholderString = placeholder nsView.isEditable = isEditable } func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject, NSTextFieldDelegate { let parent: AppKitTextField init(_ parent: AppKitTextField) { self.parent = parent } func controlTextDidChange(_ obj: Notification) { guard let textField = obj.object as? NSTextField else { return } parent.text = textField.stringValue } func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool { if commandSelector == #selector(NSResponder.insertNewline(_:)) { parent.onSubmit() return true } return false } } } // MARK: - Cmd+A/C/V/X 支持 final class KeyEquivalentTextField: NSTextField { override func performKeyEquivalent(with event: NSEvent) -> Bool { guard event.modifierFlags.contains(.command), let chars = event.charactersIgnoringModifiers?.lowercased() else { return super.performKeyEquivalent(with: event) } switch chars { case "a": return NSApp.sendAction(#selector(NSText.selectAll(_:)), to: currentEditor() ?? self, from: self) case "c": return NSApp.sendAction(#selector(NSText.copy(_:)), to: currentEditor() ?? self, from: self) case "v": return NSApp.sendAction(#selector(NSText.paste(_:)), to: currentEditor() ?? self, from: self) case "x": return NSApp.sendAction(#selector(NSText.cut(_:)), to: currentEditor() ?? self, from: self) default: return super.performKeyEquivalent(with: event) } } }