Files
Carson Sievert e07298a728 Replace jQuery event-driven output info with per-output ResizeObserver/IntersectionObserver (#3682)
* Use ResizeObserver/IntersectionObserver for per-output resize handling

Replace the old window-resize + Bootstrap event listener approach with
per-output ResizeObserver, IntersectionObserver, and MutationObserver.
Each bound output now gets its own observers that handle resize,
visibility, and theme changes independently, rather than relying on
global window resize events and jQuery Bootstrap hooks.

Also renames sendImageSize -> sendOutputInfo, simplifies bind.ts by
removing sendOutputHiddenState/maybeAddThemeObserver from BindInputsCtx,
and makes ImageOutputBinding.resize() actually set width/height on the
img element.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix observer cleanup, zoom-aware sizing, and edge cases in resize handling

- Disconnect ResizeObserver/IntersectionObserver/MutationObserver on unbind
  to prevent callbacks firing on stale elements
- Restore getBoundingClientSizeBeforeZoom for size reporting to fix CSS zoom
  regression (see #4135)
- Guard doTriggerResize against missing binding during teardown races
- Fix visibleOutputs set to properly remove hidden outputs
- Hoist observer setup out of doSendOutputInfo loop to avoid re-allocating
  closures on every call

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix pending output observer callbacks after unbind

* Flush pending output info before input send

* test and restore theme refresh for output observers

* fix: avoid theme mutation observers for non-theme outputs

* Replace custom isHidden() with native el.checkVisibility()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Simplify observer setup: inline outputInfoObserver, consolidate cleanup, guard null IDs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Revert image resize width/height attr setting

The resize() method only needs to trigger the jQuery resize event for
brush re-projection. Setting width/height attrs on the <img> just
briefly stretched the stale plot before the server re-render replaced
it, with no meaningful effect on behavior.

* Restore image resize() to match main exactly

The previous commit over-scoped the revert by changing the method
signature. This restores the original signature from main.

* Remove review doc

* Skip doTriggerResize() during initial output info send

* Add isVisible() fallback for browsers without checkVisibility()

* `npm run build` (GitHub Actions)

* Update NEWS.md

* Remove unnecessary type cast in debounce cancel test

The debounce() function already returns DebouncedFunction with a
required `cancel` property. The cast to an optional `cancel` weakened
type checking.

* Defer sendOutputInfoFns.regular lookup to execution time

Wrap setTimeout callbacks with arrow functions so regular is resolved
at call time rather than captured when it may still be undefined.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: cpsievert <cpsievert@users.noreply.github.com>
2026-04-28 09:41:16 -05:00
..