Protected Readonly_classProtected_closeClose button (clicked → hide(), surfaces the pill).
Protected Readonly_containerProtected_destroyedProtected_headerDrag handle inside the panel — usually the title row.
Protected Readonly_minProtected Readonly_minProtected Readonly_modalProtected_panelRoot panel element. Populated by subclass in _buildDom().
Protected_pillFloating "reopen" pill shown while the panel is hidden.
Protected Readonly_resizableProtected Readonly_storageProtected Readonly_tierReadonlyonFires while the user drags the panel (one notification per
pointermove during a drag) and once when the drag ends.
Drag changes the panel's CSS left / top but never its
size, so a ResizeObserver on any descendant element never
sees it. Subclasses or hosts that need to track the panel's
viewport position — for example a View
embedded in the body whose shared WebGL canvas must follow
the panel — should subscribe to this and re-read the
panel's bounding rect.
ReadonlyonFires when show() / hide() toggles the panel's visibility.
The body's controls container. Use this when none of the builders fit — append arbitrary DOM and wire its events yourself. Widgets added via the builders are appended here too, so your raw nodes interleave naturally with them in insertion order.
true when the panel is mounted and visible (pill hidden).
Protected_bindWire the shared chrome behaviour onto the DOM the subclass built. Idempotent — calling twice is a no-op.
Protected_bindInject eight invisible drag handles (4 edges + 4 corners)
into _panel and wire pointer events. Each handle pins the
panel to absolute left / top on pointerdown (so subsequent
size + position writes take effect over any CSS that uses
right / bottom), then writes new width / height —
and, for north / west edges, new left / top — on
pointermove. onLayoutChanged fires per move and at drag-end;
the saved layout is updated on drag-end.
min-width / min-height enforced from _minWidth /
_minHeight; max-width / max-height are released by
setting them to "none" inline so user-driven size is not
clipped by CSS bounds like max-height: calc(100vh - 32px).
Protected_buildSubclass populates _panel, _pill, _header, _closeBtn
here, and appends _panel + _pill to _container. Called
exactly once, before _bindChrome.
Protected_clampProtected_restoreForce a fixed initial position instead of reading
a saved layout. Called by the base's _bindChrome.
Protected_saveNo-op. Drags, resizes, and minimize/restore all
call into this and would normally persist to
localStorage; for InfoPanel we want every session to
start at the same place regardless of what the user did
last time.
Engage the header drag from an external pointerdown / move
event so the panel begins following ev immediately. Used by
the drag-to-undock gesture on docked View cells — the cell's
own pointer listener detects motion-past-threshold, replaces
the cell with this freshly-created floating panel, and hands
the live pointer over via this method.
The panel is reflowed so the pointer sits inside its header at
(panelOffsetX, panelOffsetY) from the panel's top-left. Then
setPointerCapture routes all subsequent pointermove /
pointerup events for this pointerId to the panel's own
header, where _bindChrome's existing listeners drive
the drag — no parallel drag loop required.
OptionalpanelOffsetX: numberOptionalpanelOffsetY: numberTear down DOM + global listeners. Idempotent.
Hide the panel and surface the floating reopen pill.
Replace the description block with the given HTML. Pass an empty string to hide the description entirely.
Update the value text of a stat row added via addStat.
No-op if id was never registered.
Update the panel's header (and reopen-pill) title.
Re-surface the pill after super.show() hides it.
The InfoPanel pill is a permanent landmark, not just a
minimised-state affordance.
Toggle visibility.
Floating info card — see the module overview for usage. The caller owns the panel reference and uses the imperative
addToggle/addSlider/addStat/ etc. builders to grow the control list, andsetStat(id, value)to update read-only fields.bodyis the escape hatch for one-off DOM that doesn't fit the builders.