Pick the topmost id from a body-hit list, using whatever signal the
adapter exposes.
Why this exists: pickEvery returns every id whose body covers the pointer.
Naively taking ids[0] makes containers swallow clicks on their children
(the container's bounds also cover the hit point, and demo iteration
order tends to put parents before children). This helper resolves the
ambiguity in a way that's correct by default for the common parent/child
case, while remaining a no-op for the trivial single-hit case.
Resolution rules (in order):
Empty / single hit. Return null / the lone id.
Parent/child collapse. When adapter.getParent is present, drop
any id in the hit set that is an ancestor of another id in the hit
set. After the collapse, if exactly one id remains, return it.
Tiebreaker. Return the LAST id in the (collapsed) array. Demos
that walk their scene forward (Object.keys, for of items) return
bottom-first by convention; "last" gives the topmost. Demos that
already z-sort with topmost first should pass an array of length 1
(resolve before calling) — this helper doesn't try to detect that.
Pure sibling z-order without a parent/child relation is not resolved
here yet — see "Sibling z-order is unresolved in hit-picking" under
Tools & gestures in docs/TODO.md. The shape it wants is an optional
getZIndex / compareZ on the adapter below, composing with the
parent/child collapse rather than replacing it.
Pick the topmost id from a body-hit list, using whatever signal the adapter exposes.
Why this exists:
pickEveryreturns every id whose body covers the pointer. Naively takingids[0]makes containers swallow clicks on their children (the container's bounds also cover the hit point, and demo iteration order tends to put parents before children). This helper resolves the ambiguity in a way that's correct by default for the common parent/child case, while remaining a no-op for the trivial single-hit case.Resolution rules (in order):
null/ the lone id.adapter.getParentis present, drop any id in the hit set that is an ancestor of another id in the hit set. After the collapse, if exactly one id remains, return it.Object.keys,for of items) return bottom-first by convention; "last" gives the topmost. Demos that already z-sort with topmost first should pass an array of length 1 (resolve before calling) — this helper doesn't try to detect that.Pure sibling z-order without a parent/child relation is not resolved here yet — see "Sibling z-order is unresolved in hit-picking" under Tools & gestures in
docs/TODO.md. The shape it wants is an optionalgetZIndex/compareZon the adapter below, composing with the parent/child collapse rather than replacing it.