@jsenv/navi 0.29.421 → 0.29.423

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.
@@ -74248,10 +74248,22 @@ const useListScrollSync = ({
74248
74248
  visibleCount: position.visibleCount
74249
74249
  };
74250
74250
  };
74251
- const reportPosition = () => {
74251
+ // A position read at a scroll event is read before the window has drawn what
74252
+ // the scroll brought on screen: the items below the top one can still be
74253
+ // fillers then, and `visibleCount` counts the items drawn. So it is read
74254
+ // again once the screen is better known — a window change on screen, items
74255
+ // landing or resizing — and said again when it reads differently (`ifChanged`):
74256
+ // the same scroll, the screen said right.
74257
+ const announcedRef = useRef(null);
74258
+ const reportPosition = ({
74259
+ ifChanged
74260
+ } = {}) => {
74252
74261
  if (!ref.current) {
74253
74262
  return;
74254
74263
  }
74264
+ if (ifChanged && !announcedRef.current) {
74265
+ return;
74266
+ }
74255
74267
  const remember = rememberScrollRef.current;
74256
74268
  const onScrolledChange = onScrolledChangeRef.current;
74257
74269
  const position = captureListAnchor(remember || Boolean(onScrolledChange));
@@ -74263,6 +74275,10 @@ const useListScrollSync = ({
74263
74275
  return;
74264
74276
  }
74265
74277
  const scrolledNow = toScrolledPosition(position);
74278
+ if (ifChanged && isSamePosition(scrolledNow, announcedRef.current)) {
74279
+ return;
74280
+ }
74281
+ announcedRef.current = scrolledNow;
74266
74282
  if (remember) {
74267
74283
  rememberScrollerPosition(listId, scrolledNow);
74268
74284
  }
@@ -74274,8 +74290,15 @@ const useListScrollSync = ({
74274
74290
  // laid out, its items have arrived, one of them grew. A list read where it
74275
74291
  // opened would otherwise come back with nothing kept — opening again as a
74276
74292
  // fresh arrival does, all of its window drawn in the first commit instead of
74277
- // the items that were on screen. Kept, and told to nobody: nobody scrolled.
74293
+ // the items that were on screen. Kept, and told to nobody while nobody
74294
+ // scrolled; once a position was said, it is said again (see reportPosition).
74278
74295
  const rememberPosition = () => {
74296
+ if (announcedRef.current) {
74297
+ reportPosition({
74298
+ ifChanged: true
74299
+ });
74300
+ return;
74301
+ }
74279
74302
  if (!rememberScrollRef.current || !ref.current) {
74280
74303
  return;
74281
74304
  }
@@ -74768,6 +74791,15 @@ const useListScrollSync = ({
74768
74791
  };
74769
74792
  }, [scrollerElResolved]);
74770
74793
  holdWindow();
74794
+ const {
74795
+ start: windowStart,
74796
+ end: windowEnd
74797
+ } = renderWindowRef.current;
74798
+ useLayoutEffect(() => {
74799
+ reportPosition({
74800
+ ifChanged: true
74801
+ });
74802
+ }, [windowStart, windowEnd]);
74771
74803
  return {
74772
74804
  virtualItemSizeSignal,
74773
74805
  renderWindow: renderWindowRef.current,
@@ -75326,6 +75358,18 @@ const captureScrollAnchor = ({
75326
75358
  }
75327
75359
  return fallbackAnchor;
75328
75360
  };
75361
+ // Two positions handed out say the same thing (see reportPosition): the same
75362
+ // item, as far below the top within a pixel, as many items on screen.
75363
+ const isSamePosition = (a, b) => {
75364
+ if (a.id !== b.id || a.index !== b.index) {
75365
+ return false;
75366
+ }
75367
+ if (a.visibleCount !== b.visibleCount) {
75368
+ return false;
75369
+ }
75370
+ const offsetDelta = a.offset - b.offset;
75371
+ return offsetDelta > -0.5 && offsetDelta < 0.5;
75372
+ };
75329
75373
  // How many of the items from `fromIndex` on start before `to` along the scroll
75330
75374
  // axis — the ones on screen, when `to` is where the view ends.
75331
75375
  const countItemsStartingBefore = (itemEls, fromIndex, to, horizontal) => {
@@ -75596,9 +75640,12 @@ const readRoomAround = ({
75596
75640
  // too — and an item not drawn is taken to weigh what the drawn items at that
75597
75641
  // edge of the window weigh. Items of one kind come together (the one-line
75598
75642
  // items of the past, the cards ahead), and an item misjudged is weighed again
75599
- // once it is drawn (see "after slide"): weighing it at the average of all
75600
- // items would draw the cards next to one-line items at the one-line size, and
75601
- // a few dozen of them.
75643
+ // once it is drawn (see "after slide"): a window that came up short is
75644
+ // extended on the next frame, from what it measured. Weighing an item not drawn
75645
+ // at the average of all items, or at the smallest an item can be so that the
75646
+ // window never comes up short, walks into the cards at the one-line size,
75647
+ // several at a time — the latter measured in wematch: no blank spared, 50–65 ms
75648
+ // tasks while reading down through the cards.
75602
75649
  const EDGE_SAMPLE_ITEM_COUNT = 8;
75603
75650
  const createItemSizeReader = (items, start, end, itemSize) => {
75604
75651
  const sizeByIndex = new Map();
@@ -78047,9 +78094,12 @@ const ListResolved = /*#__PURE__*/createComponentResolver([ListFirstResolver, Li
78047
78094
  * @param {(scrolled: {id: string, index: number, offset: number, visibleCount: number}) => void} [props.onScrolledChange]
78048
78095
  * Where the list is, as the user scrolls: the item at the top of the view and
78049
78096
  * how far below the place an item lands on its own (see `defaultScrolled`) it
78050
- * starts, and how many items are on screen from that one on. Keep it whole to
78051
- * come back to it later through `scrolled`/`defaultScrolled` — an index alone
78052
- * would not do, since items get inserted while a list is being read.
78097
+ * starts, and how many items are on screen from that one on. Said again for
78098
+ * the same scroll when the screen reads differently once the items it
78099
+ * brought are drawn, or once items landing change what it shows: the last
78100
+ * one said is the one to keep. Keep it whole to come back to it later
78101
+ * through `scrolled`/`defaultScrolled` — an index alone would not do, since
78102
+ * items get inserted while a list is being read.
78053
78103
  * @param {number|string|{initial?: number|string, after?: number|string}} [props.renderBudget="100item"]
78054
78104
  * How much of a `<List.Items>` run is in the DOM at once: the render window,
78055
78105
  * which slides as the user scrolls while fillers hold the room of the items
@@ -78080,11 +78130,18 @@ const ListResolved = /*#__PURE__*/createComponentResolver([ListFirstResolver, Li
78080
78130
  * source for is a page (see `<List.Items pageSize>`), whatever either says,
78081
78131
  * so the first picture costs no second request.
78082
78132
  * @param {number} [props.virtualItemSize]
78083
- * The size of one item along the scroll axis, in px, when every item has the
78084
- * same: what the fillers are sized with and what a scroll position is
78085
- * estimated from. Left out, the list measures its items — once when it
78086
- * mounts, again when a popup around it opens, and after each commit while
78087
- * items are held off screen. Given, it never measures.
78133
+ * The room an item not drawn is held at, in px along the scroll axis: what
78134
+ * the fillers hold for each item outside the render window, what a scroll
78135
+ * position inside them is read with, and the least an item on its way takes
78136
+ * (see `renderSkeleton`). Left out, it is the average of the items measured
78137
+ * so far — once when the list mounts, again when a popup around it opens,
78138
+ * and after each commit while items are held off screen. Given, it is the
78139
+ * worst case: the size every item has, or, in a list whose items differ, the
78140
+ * smallest an item can be (a thread of one-line items and cards: the
78141
+ * one-line size) — an item guessed too small builds one more, an item
78142
+ * guessed too big leaves a blank (see docs/scroll.md, "What the list knows,
78143
+ * and what it guesses"). The items drawn are measured either way: the render
78144
+ * window is sized on them.
78088
78145
  * @param {"self"|"parent"|"document"|Element|{current: Element}} [props.scroller="self"]
78089
78146
  * Which box scrolls — and with it, which box the render window follows and
78090
78147
  * which box a scroll position is read from (`onScrolledChange`). `"self"`