Make the open-panel mark find and fit its module

A center-anchored module is mounted twice: the copy that is drawn, and a
zero-size placeholder holding its place in the flow beside the anchor.
findPanelWidget returned whichever registered first, and that order is
not stable across a live bar reconfiguration, so a panel could open
anchored to the invisible copy -- mispositioned, with the drawn slot
never lighting up and switchPanelFrom unable to find it again.

The mark was also always 55% of the slot, which fits an icon but
underlines only a fraction of a text label, and runs the full height of a
multi-line module on a vertical bar. Modules can now say how long the
mark should be along the bar; anything that does not answer keeps the old
proportion.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
David Heinemeier Hansson
2026-07-26 19:10:06 -07:00
co-authored by Claude Opus 5
parent d4c835afb5
commit 6d4fa7acaf
4 changed files with 89 additions and 4 deletions
+24
View File
@@ -96,8 +96,32 @@ function customModulePath(entry, home, configDir) {
return source
}
// A center module is mounted twice once an anchor is set: the copy that is
// actually drawn, and a zero-size placeholder holding its place in the flow
// beside the anchor. Panel routing has to pick the drawn one — it is the only
// one that can anchor a popup, carry the open-panel mark, or be found again
// by switchPanelFrom — and fall back to the placeholder only when nothing is
// on screen. The order the two are registered in is not stable across a live
// bar reconfiguration, so picking the first match is not good enough.
function isDrawnSlot(slot) {
return !!slot && slot.visible === true && slot.width > 0 && slot.height > 0
}
function pickDrawnSlot(slots) {
var placeholder = null
var list = slots || []
for (var i = 0; i < list.length; i++) {
if (!list[i]) continue
if (isDrawnSlot(list[i])) return list[i]
if (!placeholder) placeholder = list[i]
}
return placeholder
}
if (typeof module !== "undefined") {
module.exports = {
isDrawnSlot: isDrawnSlot,
pickDrawnSlot: pickDrawnSlot,
normalizePosition: normalizePosition,
entrySettings: entrySettings,
entryId: entryId,