@jsenv/navi 0.30.38 → 0.30.40

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.
@@ -42637,6 +42637,11 @@ const css$16 = /* css */`@property --navi-route-row-pin {
42637
42637
  inherits: false
42638
42638
  }
42639
42639
 
42640
+ @property --navi-route-row-stand {
42641
+ syntax: "*";
42642
+ inherits: false
42643
+ }
42644
+
42640
42645
  .navi_route_travel {
42641
42646
  flex-direction: column;
42642
42647
  display: flex;
@@ -43178,16 +43183,14 @@ const RouteTravel = ({
43178
43183
  movement.rowTaken = true;
43179
43184
  // A travel no hand set off holds nothing: it goes where it goes.
43180
43185
  releaseHeldPage();
43181
- row.style.setProperty("--navi-route-row-stand", `${-position}px`);
43182
- row.setAttribute("data-route-row-taken", "");
43186
+ holdRowAt(row, position);
43183
43187
  afterFrames(2, () => {
43184
43188
  if (movementRef.current !== movement) {
43185
43189
  return;
43186
43190
  }
43187
43191
  // A scroller again, standing where no page does: not snapped meanwhile.
43188
43192
  row.setAttribute("data-route-row-travelling", "");
43189
- row.removeAttribute("data-route-row-taken");
43190
- row.style.removeProperty("--navi-route-row-stand");
43193
+ releaseTakenRow(row);
43191
43194
  afterFrames(1, () => {
43192
43195
  if (movementRef.current === movement) {
43193
43196
  travelRowTo(latestRef.current.currentIndex, movement);
@@ -43207,7 +43210,7 @@ const RouteTravel = ({
43207
43210
  movementRef.current = null;
43208
43211
  letRowGo(movement);
43209
43212
  putRowBack(movement);
43210
- row.removeAttribute("data-route-row-taken");
43213
+ releaseTakenRow(row);
43211
43214
  publishRouteRowMove(null);
43212
43215
  releaseHeldPage();
43213
43216
  releasePaneAtRest(row);
@@ -43685,6 +43688,22 @@ const copyScrollPositions = (from, to) => {
43685
43688
  // A tab pressed over a row a hand has left moving holds it still (takeRowFromHand):
43686
43689
  // what the row says meanwhile is not a hand moving it.
43687
43690
  const isRowTaken = row => row.hasAttribute("data-route-row-taken");
43691
+
43692
+ // What the CSS offsets while the row is taken. A picture left meanwhile is a clone
43693
+ // of the live page, and takes its offset along.
43694
+ const STANDING_IN_ROW = ":scope > [data-route-row-pane], :scope > [data-route-row-live], :scope > [data-route-row-pictures] > *";
43695
+ const holdRowAt = (row, position) => {
43696
+ for (const element of row.querySelectorAll(STANDING_IN_ROW)) {
43697
+ element.style.setProperty("--navi-route-row-stand", `${-position}px`);
43698
+ }
43699
+ row.setAttribute("data-route-row-taken", "");
43700
+ };
43701
+ const releaseTakenRow = row => {
43702
+ row.removeAttribute("data-route-row-taken");
43703
+ for (const element of row.querySelectorAll(STANDING_IN_ROW)) {
43704
+ element.style.removeProperty("--navi-route-row-stand");
43705
+ }
43706
+ };
43688
43707
  const afterFrames = (count, callback) => {
43689
43708
  if (count === 0) {
43690
43709
  callback();
@@ -85474,6 +85493,17 @@ const createListItems = () => {
85474
85493
  }
85475
85494
  return null;
85476
85495
  },
85496
+ // Whether a run stands for the item at that index without holding it: the
85497
+ // page it belongs to has not answered yet. An id missing from what the runs
85498
+ // hold says the item is gone only once the page where it stood is in.
85499
+ itemOnItsWayAt: (index) => {
85500
+ for (const locator of locatorByOwner.values()) {
85501
+ if (locator.awaits(index)) {
85502
+ return true;
85503
+ }
85504
+ }
85505
+ return false;
85506
+ },
85477
85507
  // The room the item at that index takes: the room it took when it was
85478
85508
  // last drawn, else the room its run is given for it (see List.Items'
85479
85509
  // itemSize), else undefined.
@@ -88500,10 +88530,14 @@ const useListScrollSync = ({
88500
88530
  // Not there yet, but where it stood is drawn already: the item
88501
88531
  // standing in for it at that index (see holdWindow). The list is placed
88502
88532
  // on that one, measured like any other, and the named item takes over
88503
- // where it lands.
88504
- if (listItems.pagesSignal.peek() === 0) {
88505
- if (typeof scrolledWanted.index === "number") {
88506
- placeItem(findItemElementAt(getListEl(), scrolledWanted.index), scrolledWanted.offset || 0);
88533
+ // where it lands. Held for as long as the page at that index has not
88534
+ // answered — the first one, or the one a press sends the list to: only
88535
+ // an answer without the item says it is gone.
88536
+ const standInIndex = scrolledWanted.index;
88537
+ const hasStandIn = typeof standInIndex === "number";
88538
+ if (listItems.pagesSignal.peek() === 0 || hasStandIn && listItems.itemOnItsWayAt(standInIndex)) {
88539
+ if (hasStandIn) {
88540
+ placeItem(findItemElementAt(getListEl(), standInIndex), scrolledWanted.offset || 0, scrolledWanted.align);
88507
88541
  }
88508
88542
  return;
88509
88543
  }
@@ -88567,11 +88601,13 @@ const useListScrollSync = ({
88567
88601
  const itemRect = itemEl.getBoundingClientRect();
88568
88602
  const viewportSize = (horizontal ? viewportRect.width : viewportRect.height) / scale;
88569
88603
  const itemSize = (horizontal ? itemRect.width : itemRect.height) / scale;
88570
- const scrollInset = getItemScrollInset(scrollerEl, itemEl, horizontal);
88571
- // Centred in what the room at the start leaves of the view (a fixed bar,
88572
- // a sticky header), not in the whole of it.
88573
- const alignedOffset = align === "center" ? scrollInset + (viewportSize - scrollInset - itemSize) / 2 : align === "end" ? viewportSize - itemSize : scrollInset;
88574
- const offsetWanted = resolveOpenOffset(alignedOffset + offset, viewportSize, itemSize);
88604
+ const offsetWanted = resolveHeldOffset({
88605
+ align,
88606
+ offset,
88607
+ scrollInset: getItemScrollInset(scrollerEl, itemEl, horizontal),
88608
+ viewportSize,
88609
+ itemSize
88610
+ });
88575
88611
  const offsetNow = (horizontal ? itemRect.left - viewportRect.left : itemRect.top - viewportRect.top) / scale;
88576
88612
  const scrollNow = horizontal ? scrollerEl.scrollLeft : scrollerEl.scrollTop;
88577
88613
  const delta = offsetNow - offsetWanted;
@@ -89310,6 +89346,7 @@ const useListScrollSync = ({
89310
89346
  }
89311
89347
  let index = null;
89312
89348
  let offset = 0;
89349
+ let align;
89313
89350
  if (typeof wanted === "number") {
89314
89351
  index = wanted;
89315
89352
  } else if (wanted && wanted.id !== undefined) {
@@ -89318,6 +89355,7 @@ const useListScrollSync = ({
89318
89355
  index = wanted.index;
89319
89356
  }
89320
89357
  offset = wanted.offset || 0;
89358
+ align = wanted.align;
89321
89359
  }
89322
89360
  if (index === null || index < 0 || index >= total) {
89323
89361
  return null;
@@ -89328,7 +89366,15 @@ const useListScrollSync = ({
89328
89366
  const rect = itemEl.getBoundingClientRect();
89329
89367
  itemSize = horizontal ? rect.width : rect.height;
89330
89368
  }
89331
- const above = resolveOpenOffset(getItemScrollInset(scrollerEl, itemEl, horizontal) + offset, screenSize, itemSize);
89369
+ // Not drawn yet, the item weighs nothing and has no inset: centred, it
89370
+ // stands half the screen down, which is where it will be put.
89371
+ const above = resolveHeldOffset({
89372
+ align,
89373
+ offset,
89374
+ scrollInset: getItemScrollInset(scrollerEl, itemEl, horizontal),
89375
+ viewportSize: screenSize,
89376
+ itemSize
89377
+ });
89332
89378
  return {
89333
89379
  index,
89334
89380
  above
@@ -90000,6 +90046,21 @@ const resolveOpenOffset = (offset, viewportSize, itemSize) => {
90000
90046
  }
90001
90047
  return offset;
90002
90048
  };
90049
+ // How far from the start of the view an item held at `{ offset, align }`
90050
+ // stands: read the same way where the list is placed (placeItem) and where the
90051
+ // window is sized around it (readHold), or the window frames a screen the
90052
+ // item is not on. Centred in what the room at the start leaves of the view (a
90053
+ // fixed bar, a sticky header), not in the whole of it.
90054
+ const resolveHeldOffset = ({
90055
+ align,
90056
+ offset,
90057
+ scrollInset,
90058
+ viewportSize,
90059
+ itemSize
90060
+ }) => {
90061
+ const alignedOffset = align === "center" ? scrollInset + (viewportSize - scrollInset - itemSize) / 2 : align === "end" ? viewportSize - itemSize : scrollInset;
90062
+ return resolveOpenOffset(alignedOffset + offset, viewportSize, itemSize);
90063
+ };
90003
90064
 
90004
90065
  // The room an item must be given at the top (or left) of the view: the
90005
90066
  // scroller's own scroll-padding — where a fixed bar publishes the space it
@@ -92171,6 +92232,7 @@ const useRunItems = (store, {
92171
92232
  });
92172
92233
  return found;
92173
92234
  },
92235
+ awaits: itemIndex => itemIndex >= runStart && itemIndex < runEnd && getItemAt(itemIndex) === undefined,
92174
92236
  roomAt: roomOf,
92175
92237
  givenRoomAt: givenRoomOf
92176
92238
  });