@lotics/ui 42.3.0 → 43.0.0

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.
@@ -252,6 +252,25 @@ export function useOptionList<T extends string, MULTI extends boolean = false, D
252
252
  if (index >= 0) scrollRef.current?.scrollTo({ y: index * OPTION_HEIGHT - 80, animated: false });
253
253
  }, []);
254
254
 
255
+ // Scroll the OPENING seat into view.
256
+ //
257
+ // `initialIndex` seats the highlight through `useState`, which fires no
258
+ // `onActiveChange` — so the row it lands on was highlighted and never scrolled
259
+ // to. On a list short enough to fit that is invisible; past a screenful the
260
+ // list opens at the top with the current value somewhere below the fold, which
261
+ // is the one row it was opened to show. A day of times at 15-minute steps is 96
262
+ // rows, so an afternoon value sat two thirds of the way down an unscrolled list.
263
+ //
264
+ // Gated on rows ARRIVING rather than on mount, so an async list (options still
265
+ // loading when the popover opens) seats on its real value instead of on the
266
+ // empty list's index 0. Once only: after that the member owns the scroll.
267
+ const scrollSeatedRef = useRef(false);
268
+ useEffect(() => {
269
+ if (scrollSeatedRef.current || rows.length === 0) return;
270
+ scrollSeatedRef.current = true;
271
+ scrollToIndex(initialActiveIndex);
272
+ }, [rows.length, initialActiveIndex, scrollToIndex]);
273
+
255
274
  const requestClose = useCallback(() => {
256
275
  onRequestClose?.();
257
276
  if (onClose) {