Realign search, clipboard, and lane-hover code with the second batch

Creation now clears the search by mechanism, not gesture: one seam
(noteUserCreation) states 04's rule once, called from the placeholder
funnel, paste — cards and lanes, after the staleness guard so a stale
paste clears nothing — and Finder file-drop creation; the attach path
deliberately doesn't clear, and cross-board arrivals and New Lane stay
outside the seam (a transfer isn't creation; a lane can't be born
invisible). An open inline rename now survives the filter hiding its
card: the model already kept the editor, but the field renders in the
card's slot, so renderedCards keeps the renaming card's slot exactly as
long as the editor is open — the query stands throughout, and commit or
Escape lets the predicate apply in the same pass. Verified conformant
and newly pinned: query-emptied lanes keep their slot with a 0 badge,
pasteboard staleness (takeover before paste and mid-staging both no-op),
out-transition reachability and the strip pre-divide hold by
construction with comments citing their rulings.

Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
2026-07-28 08:45:12 -04:00
parent 524488122f
commit 5c0c0e5619
9 changed files with 423 additions and 21 deletions
+10 -7
View File
@@ -97,13 +97,16 @@ extension View {
/// it registers nothing, and the two surfaces that navigate by drawn frames narrow with the
/// masonry rather than re-running the predicate.
///
/// One bounded honesty about that: a card leaving under the filter's transition stays registered
/// until the transition ends (`onDisappear` fires when the view really goes, not when the query
/// changed), so for the length of one content-reflow spring a fading card is still sweepable and
/// still an arrow's neighbour. It is on screen for exactly that span, and it has already left the
/// selection (`TransientBoardState.constrainToSearch(in:)` runs at the keystroke), so the window
/// is visible rather than phantom accepted rather than closed by teaching three input sites a
/// predicate the layout already applied.
/// **A leaving card stays input-reachable for its out-transition** (04-interactions.md § Search,
/// settled): "marquee and arrow targets deregister when the ~0.28 s animate-out ends, so a card
/// mid-departure is briefly reachable while already out of the selection accepted: it is
/// literally on screen for that span, and closing the window would teach three input sites a
/// predicate the layout already applied". That is this modifier's construction rather than a rule
/// it implements: `onDisappear` fires when SwiftUI really removes the view at the end of the
/// card transition `Motion.contentReflow` is timing not when the query changed, so the
/// registration outlives the filter by exactly the length of the animation and not a frame more.
/// The card has already left the selection by then (`TransientBoardState.constrainToSearch(in:)`
/// runs at the keystroke), which is what makes the window visible rather than phantom.
@MainActor
func marqueeTarget(
_ id: ItemID,