Keyboard ←/→ keep their place — a sticky ordinal that outlives the clamp
Lateral card navigation was pure geometry: the nearest drawn frame in the direction. That loses the walk in the card's own title — stepping from a 10-card lane's 8th card into a 3-card lane clamps to its 3rd, and coming back out, "the nearest frame at that height" is the 3rd card's height. The information the user was walking at stopped being on screen, so no rule over rectangles could have recovered it. So it is remembered instead. `TransientBoardState.lateralOrdinal` holds the 1-based position a run of ←/→ started from, counted over the cards the board is showing, and `NavigationMath.lateralHop` lands each hop on `min(ordinal, target lane's count)` of the next lane that is showing cards — collapsed and query-emptied lanes hopped over on `firstCard`'s rule rather than by the accident of registering no frames. 8th → 3rd → 8th. Every reset comes from one funnel and needs no enumeration anywhere: the ordinal is a defaulted `nil` parameter on `select`, so a click, a marquee, a ↑/↓ step, an ⌥-jump, a ⌫ successor, a lane-domain arrow and the reload's focus recovery all end the run by saying nothing. `resolve` adds the one rule a value referencing no item can need — the ordinal never outlives the head it was counted from — while a reload that leaves the cursor standing leaves the run standing too. A wide lane's interior masonry columns keep their spatial step and carry the ordinal through untouched: a column hop is not a lane hop, and stickiness is lane-granular over the logical order. With no lane in the direction the geometry has the last word, which is how → still reaches the shown trash. Claude-Session: https://claude.ai/code/session_014PtZdPwqZuqEDLc6wZMtEy
This commit is contained in:
@@ -4799,15 +4799,23 @@ public final class BoardStore: HealHost {
|
||||
///
|
||||
/// - Parameter defaultsSoleMember: forwarded verbatim — see `TransientBoardState.select`, whose
|
||||
/// sole-member default the rubber band opts out of.
|
||||
/// - Parameter lateralOrdinal: forwarded verbatim — see `TransientBoardState.lateralOrdinal`,
|
||||
/// whose `nil` default is what makes every caller here a reset of the ←/→ run.
|
||||
public func select(
|
||||
_ ids: Set<ItemID>,
|
||||
in container: ItemContainer,
|
||||
anchor: ItemID? = nil,
|
||||
head: ItemID? = nil,
|
||||
defaultsSoleMember: Bool = true
|
||||
defaultsSoleMember: Bool = true,
|
||||
lateralOrdinal: Int? = nil
|
||||
) {
|
||||
transient.select(
|
||||
ids, in: container, anchor: anchor, head: head, defaultsSoleMember: defaultsSoleMember
|
||||
ids,
|
||||
in: container,
|
||||
anchor: anchor,
|
||||
head: head,
|
||||
defaultsSoleMember: defaultsSoleMember,
|
||||
lateralOrdinal: lateralOrdinal
|
||||
)
|
||||
transient.noteActiveLane(Self.lane(holding: ids, in: snapshot))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user