@threadlabs/looma 0.23.23 → 0.23.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -205,6 +205,8 @@ export function createAnchoredSurface(surface, options = {}) {
205
205
  let point = null;
206
206
  let open = false;
207
207
  let frame = null;
208
+ let anchorFrame = null;
209
+ let lastAnchorRect = null;
208
210
  let abort = null;
209
211
  let sizeObserver = null;
210
212
  surface.setAttribute("popover", "manual");
@@ -218,12 +220,31 @@ export function createAnchoredSurface(surface, options = {}) {
218
220
  return;
219
221
  }
220
222
  if (!anchor) return;
221
- fallbackPosition(surface, anchor.getBoundingClientRect(), placement, gap(), viewportGap);
223
+ lastAnchorRect = anchor.getBoundingClientRect();
224
+ fallbackPosition(surface, lastAnchorRect, placement, gap(), viewportGap);
222
225
  };
223
226
  const schedule = () => {
224
227
  if (open && frame === null) frame = owner.requestAnimationFrame(position);
225
228
  };
229
+ // Resize and scroll events do not report an ancestor's transition or layout shift.
230
+ // While visible, sample the anchor and only re-position when its bounds change.
231
+ const trackAnchor = () => {
232
+ anchorFrame = null;
233
+ if (!open || !anchor || point) return;
234
+ const rect = anchor.getBoundingClientRect();
235
+ if (!lastAnchorRect || rect.left !== lastAnchorRect.left || rect.top !== lastAnchorRect.top
236
+ || rect.width !== lastAnchorRect.width || rect.height !== lastAnchorRect.height) schedule();
237
+ anchorFrame = owner.requestAnimationFrame(trackAnchor);
238
+ };
239
+ const stopTracking = () => {
240
+ if (anchorFrame !== null) owner.cancelAnimationFrame(anchorFrame);
241
+ anchorFrame = null;
242
+ lastAnchorRect = null;
243
+ };
226
244
  const syncListeners = () => {
245
+ if (open && anchor && !point) {
246
+ if (anchorFrame === null) anchorFrame = owner.requestAnimationFrame(trackAnchor);
247
+ } else stopTracking();
227
248
  const needed = open && (point || anchor);
228
249
  if (!needed) {
229
250
  abort?.abort();
@@ -251,7 +272,7 @@ export function createAnchoredSurface(surface, options = {}) {
251
272
  showAtPoint(next) { point = next; open = true; syncListeners(); show(surface); position(); schedule(); observeSize(); },
252
273
  hide() { open = false; point = null; syncListeners(); stopSize(); if (frame !== null) owner.cancelAnimationFrame(frame); frame = null; hide(surface); },
253
274
  refresh: schedule,
254
- destroy() { open = false; abort?.abort(); abort = null; stopSize(); if (frame !== null) owner.cancelAnimationFrame(frame); frame = null; hide(surface); anchor = null; },
275
+ destroy() { open = false; stopTracking(); abort?.abort(); abort = null; stopSize(); if (frame !== null) owner.cancelAnimationFrame(frame); frame = null; hide(surface); anchor = null; },
255
276
  };
256
277
  }
257
278
 
@@ -268,6 +268,7 @@
268
268
  :host-state([variant="card"]) {
269
269
  display: grid;
270
270
  grid-template-columns: auto minmax(0, 1fr) auto;
271
+ align-content: center;
271
272
  align-items: start;
272
273
  gap: var(--ui-space-3);
273
274
  inline-size: 100%;