fix(hierarchy): rank spatial-fallback matches by specificity

The bounds-containment fallback returned the first pre-order match, so
a screen-sized container could win over the intended small element.
Matches are now ordered smallest-area first; equal-area matches keep
pre-order, preserving the iOS-flat equal-bounds sibling pattern.
This commit is contained in:
pj committed 2026-06-06 00:36:32 +05:30
1 parent 29ec13adcd
commit c356340563
2 files changed
+82

No files matched your search

+14
View File
@@ -28,6 +28,7 @@ import (
"fmt"
"maps"
"regexp"
"sort"
"strconv"
"strings"
)
@@ -426,9 +427,22 @@ func (n *Node) scopedNodes(accept func(*Element) bool) []*Node {
result = append(result, candidate)
}
}
// Spatial containment alone lets a large container outrank the intended
// small element; the most specific (smallest) match wins instead.
sortBySpecificity(result)
return result
}
// sortBySpecificity orders nodes ascending by bounds area, so the smallest
// (most specific) containing match comes first. Equal-area nodes keep their
// pre-order position.
func sortBySpecificity(nodes []*Node) {
sort.SliceStable(nodes, func(i, j int) bool {
return nodes[i].Bounds.Width()*nodes[i].Bounds.Height() <
nodes[j].Bounds.Width()*nodes[j].Bounds.Height()
})
}
func collectMatches(node *Node, accept func(*Element) bool, result *[]*Node) {
if accept(&node.Element) {
*result = append(*result, node)