diff --git a/Sources/OpenSwiftUI/EventHandling/Focus/FocusStore.swift b/Sources/OpenSwiftUI/EventHandling/Focus/FocusStore.swift index b5769e4aa..2211a22d9 100644 --- a/Sources/OpenSwiftUI/EventHandling/Focus/FocusStore.swift +++ b/Sources/OpenSwiftUI/EventHandling/Focus/FocusStore.swift @@ -1,3 +1,6 @@ +@_spi(ForOpenSwiftUIOnly) +import OpenSwiftUICore + struct FocusStore { var seed: VersionSeed var focusedResponders: ContiguousArray diff --git a/Sources/OpenSwiftUICore/Event/Event_TODO.swift b/Sources/OpenSwiftUICore/Event/Event_TODO.swift index 41518eabb..19ec7c57e 100644 --- a/Sources/OpenSwiftUICore/Event/Event_TODO.swift +++ b/Sources/OpenSwiftUICore/Event/Event_TODO.swift @@ -1,7 +1,5 @@ // FIXME -package class ResponderNode {} - package struct ExclusiveGesture: PrimitiveGesture {} package struct _MapGesture: PrimitiveGesture where Content: Gesture { diff --git a/Sources/OpenSwiftUICore/Event/Responder/ResponderNode.swift b/Sources/OpenSwiftUICore/Event/Responder/ResponderNode.swift new file mode 100644 index 000000000..aa16566fd --- /dev/null +++ b/Sources/OpenSwiftUICore/Event/Responder/ResponderNode.swift @@ -0,0 +1,72 @@ +// +// ResponderNode.swift +// OpenSwiftUICore +// +// Status: Complete + +// MARK: - ResponderNode [6.5.4] + +@_spi(ForOpenSwiftUIOnly) +@available(OpenSwiftUI_v6_0, *) +open class ResponderNode { + public init() {} + + open var nextResponder: ResponderNode? { + preconditionFailure("") + } + + open func bindEvent(_ event: any EventType) -> ResponderNode? { + nil + } + + @discardableResult + open func visit(applying visitor: (ResponderNode) -> ResponderVisitorResult) -> ResponderVisitorResult { + visitor(self) + } + + open func makeGesture(inputs: _GestureInputs) -> _GestureOutputs { + _GestureOutputs(phase: inputs.intern(.failed, id: .failedValue)) + } + + open func resetGesture() {} + + final package var sequence: some Sequence { + Swift.sequence(first: self) { $0.nextResponder } + } + + final package func isDescendant(of responder: ResponderNode) -> Bool { + var current: ResponderNode? = self + while let currentResponder = current { + guard currentResponder !== responder else { + return true + } + current = currentResponder.nextResponder + } + return false + } + + final package func firstAncestor(ofType type: T.Type = T.self) -> T? { + Swift.sequence(first: self) { $0.nextResponder } + .first(ofType: type) + } +} + +@_spi(ForOpenSwiftUIOnly) +@available(*, unavailable) +extension ResponderNode: Sendable {} + +// MARK: - ResponderVisitorResult [6.5.4] [WIP] + +@_spi(ForOpenSwiftUIOnly) +@available(OpenSwiftUI_v6_0, *) +public enum ResponderVisitorResult: Equatable { + case next + + case skipToNextSibling + + case cancel +} + +@_spi(ForOpenSwiftUIOnly) +@available(*, unavailable) +extension ResponderVisitorResult: Sendable {}