import Foundation import Combine import AppKit /// Type of panel content public enum PanelType: String, Codable, Sendable { case terminal case browser case markdown } public enum TerminalPanelFocusIntent: Equatable { case surface case findField } public enum BrowserPanelFocusIntent: Equatable { case webView case addressBar case findField } public enum PanelFocusIntent: Equatable { case panel case terminal(TerminalPanelFocusIntent) case browser(BrowserPanelFocusIntent) } enum FocusFlashCurve: Equatable { case easeIn case easeOut } struct FocusFlashSegment: Equatable { let delay: TimeInterval let duration: TimeInterval let targetOpacity: Double let curve: FocusFlashCurve } enum FocusFlashPattern { static let values: [Double] = [0, 1, 0, 1, 0] static let keyTimes: [Double] = [0, 0.25, 0.5, 0.75, 1] static let duration: TimeInterval = 0.9 static let curves: [FocusFlashCurve] = [.easeOut, .easeIn, .easeOut, .easeIn] static let ringInset: Double = 6 static let ringCornerRadius: Double = 10 static var segments: [FocusFlashSegment] { let stepCount = min(curves.count, values.count - 1, keyTimes.count - 1) return (0.. PanelFocusIntent /// Return the best focus target to restore when this panel becomes active again. func preferredFocusIntentForActivation() -> PanelFocusIntent /// Prime panel-local focus state before activation side effects run. func prepareFocusIntentForActivation(_ intent: PanelFocusIntent) /// Restore a previously captured focus target. @discardableResult func restoreFocusIntent(_ intent: PanelFocusIntent) -> Bool /// Return the semantic focus target currently owned by this panel, if any. func ownedFocusIntent(for responder: NSResponder, in window: NSWindow) -> PanelFocusIntent? /// Explicitly yield a previously owned focus target before another panel restores focus. @discardableResult func yieldFocusIntent(_ intent: PanelFocusIntent, in window: NSWindow) -> Bool } /// Extension providing default implementations extension Panel { public var displayIcon: String? { nil } public var isDirty: Bool { false } func captureFocusIntent(in window: NSWindow?) -> PanelFocusIntent { _ = window return preferredFocusIntentForActivation() } func preferredFocusIntentForActivation() -> PanelFocusIntent { .panel } func prepareFocusIntentForActivation(_ intent: PanelFocusIntent) { _ = intent } @discardableResult func restoreFocusIntent(_ intent: PanelFocusIntent) -> Bool { guard intent == .panel else { return false } focus() return true } func ownedFocusIntent(for responder: NSResponder, in window: NSWindow) -> PanelFocusIntent? { _ = responder _ = window return nil } @discardableResult func yieldFocusIntent(_ intent: PanelFocusIntent, in window: NSWindow) -> Bool { _ = intent _ = window return false } }