@jsenv/navi 0.29.442 → 0.29.443

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.
@@ -186,10 +186,11 @@ start when unsure which export solves a problem.
186
186
  `scroller`, where a list opens (a position handed back whole, `visibleCount`
187
187
  included), a list that comes back (its `id` names one list of the app), a
188
188
  popup that scrolls, many rows (`<List.Items>`, the render window and its first
189
- picture, `findText`), many sections (`<Box mount="after-paint">` and what it
190
- leaves out of reach), hover while scrolling. Before writing CSS to
191
- make something scroll, before rendering a collection as `<List.Item>`
192
- children, and before deferring part of a page.
189
+ picture, skeletons at the size of their item, `itemSize`, `findText`), many
190
+ sections (`<Box mount="after-paint">` and what it leaves out of reach), hover
191
+ while scrolling. Before writing CSS to make something scroll, before
192
+ rendering a collection as `<List.Item>` children, before writing a
193
+ `renderSkeleton`, and before deferring part of a page.
193
194
  - `z_index.md` — DOM order first; a `z-index` without `isolation: isolate`
194
195
  competes with the page; navi's bands. Before writing a `z-index`.
195
196
  - `typography.md` — text is a component; `maxLines` is the one truncation; one
@@ -207,8 +207,9 @@ below, though: the obvious ones hide the race.
207
207
  **Chrome**: drive DevTools' touch emulator, which goes through Chrome's
208
208
  gesture detector with the **mobile** configuration (8px slop):
209
209
 
210
- - a headed Chromium (`chromium.launch({ headless: false })`) — headless
211
- delivers nothing through this path;
210
+ - a full browser: Chrome (`chromium.launch({ channel: "chrome" })`), headless
211
+ or not, or a headed Chromium (`headless: false`) — Playwright's default
212
+ headless shell delivers nothing through this path;
212
213
  - on a CDP session, `Emulation.setEmitTouchEventsForMouse({ enabled: true,
213
214
  configuration: "mobile" })`, then `Input.dispatchMouseEvent` with
214
215
  `mousePressed` / `mouseMoved` / `mouseReleased` (`buttons: 1` while down). The
@@ -237,6 +238,18 @@ them exactly as on a phone:
237
238
  and a restarted `safaridriver`. The page's `localStorage` does not survive
238
239
  that, so whatever must be read is read before the swipe.
239
240
 
241
+ A fling — the momentum a lifted finger leaves — is out of `safaridriver`'s
242
+ reach for the same reason. The Simulator turns the Mac's mouse into a finger:
243
+ system mouse events (`CGEvent`, a press, moves a frame apart, a release while
244
+ still moving fast) on the Simulator window fling Safari exactly like a thumb,
245
+ its momentum included (over 3 s: flings closer than that add up). The window
246
+ has to be on screen in the current Space: when it is not, activating the
247
+ Simulator does not bring it, and the events land in whatever window is under
248
+ the pointer — check which window is topmost at the points of the drag before
249
+ sending any, and wait for the Space to switch after activating. What the page
250
+ records is read back through a request it sends itself (the page runs on a
251
+ local server), since nothing can query it.
252
+
240
253
  What to synthesize is the hand's imperfection — a gesture simulated as clean,
241
254
  evenly spaced points passes forever and proves nothing: a slow start landing a
242
255
  report between 6 and 9px, steep first pixels, a report that jumps. What to read:
@@ -244,10 +257,10 @@ the `touchmove`s with `cancelable` and `defaultPrevented`, the `pointercancel`,
244
257
  `scrollY`, and what the gesture itself says (for a travel,
245
258
  `data-drag-travel-walking` on `:root` and the slide that ends up current).
246
259
 
247
- What neither path shows: the lift of a real finger (the last reports before
248
- `pointerup`), a real device's event timing (the order in which the browser's
249
- cancel and the next report reach the page), a momentum tail killed by a landing
250
- finger. Those remain device questions.
260
+ What these paths do not show: the lift of a real finger (the last reports
261
+ before `pointerup`), a real device's event timing (the order in which the
262
+ browser's cancel and the next report reach the page), a momentum tail killed by
263
+ a landing finger. Those remain device questions.
251
264
 
252
265
  Reference: `src/layout/demos/lab/slide_container_touch_race.html` — a row of
253
266
  slides that do not scroll and a row that do, for the two cases above.
package/docs/scroll.md CHANGED
@@ -196,8 +196,10 @@ takes the list back to where it was, which may be nowhere near that row.
196
196
  `loading` (with `loadingFallback`, `loadingSkeletonCount`, `renderSkeleton`)
197
197
  says "I have nothing at all to show yet": placeholder rows stand in for the
198
198
  whole list. `<List.Items count>` says "I know how many rows are coming": the
199
- rows not held yet are skeletons in their own place, asked for as they enter the
200
- render window — a list that knows its count has no use for the first one.
199
+ rows not held yet are skeletons in their own place, at their own size (see
200
+ [What the list knows, and what it guesses](#what-the-list-knows-and-what-it-guesses)),
201
+ asked for as they enter the render window — a list that knows its count has no
202
+ use for the first one.
201
203
 
202
204
  Reference: `src/control/list/list.jsx` (JSDoc on `List` and `List.Items`).
203
205
 
@@ -362,9 +364,9 @@ room it took — the window sliding changes nothing above the screen. What was
362
364
  never drawn it cannot measure, so it guesses:
363
365
 
364
366
  - the fillers hold every item never drawn at one size — `virtualItemSize` when
365
- given, the average of the items measured so far otherwise. A scroll position
366
- inside a filler is read with it too, and an item on its way takes at least
367
- that room;
367
+ given, the average of the items measured so far otherwise — unless its run
368
+ says the room it takes (see below). A scroll position inside a filler is
369
+ read with it too, and an item on its way takes at least that room;
368
370
  - when the window reaches past what it has drawn, it weighs the next items like
369
371
  the drawn ones next to them, and measures them once they are drawn.
370
372
 
@@ -375,10 +377,35 @@ item guessed **bigger** makes it count too few, and a blank shows until they
375
377
  are measured. So a size you give is the **worst case**: in a list whose items
376
378
  differ in height, `virtualItemSize` is the smallest an item can be — the
377
379
  one-line item, in a thread of one-line items and cards. The scrollbar then
378
- under-states a list made mostly of big items; the screen stays covered. One
379
- number for the whole list is the point: a size per kind of item, or per state
380
- of one, is a model to keep in step with the markup, for a scrollbar a little
381
- more exact.
380
+ under-states a list made mostly of big items; the screen stays covered.
381
+
382
+ A guess costs something else when its item is drawn above the screen: the item
383
+ takes its real room, and what is on screen moves by the difference. The list
384
+ puts the screen back by writing the scroll, except where a write would cost the
385
+ user the scroll in progress — and on iOS a fling stops at any write, so during
386
+ a fling every card drawn above the screen pushes it down. A list that knows
387
+ the room of each item before the item arrives says it with `<List.Items
388
+ itemSize>`, and guesses nothing: the fillers hold every item at its own room.
389
+ That is a model to keep in step with the markup (in development, a drawn item
390
+ whose room differs from it is reported), worth it where the items above the
391
+ screen come in a few sizes the data tells apart before it arrives — the
392
+ one-line games and the compact cards of a thread, when the server says which
393
+ past games have a score.
394
+
395
+ The items on their way are held the same way: a skeleton stands where its item
396
+ will be, at the room it is drawn at, and when the page lands each item takes
397
+ its own room — what is below a skeleton of the wrong size moves by the
398
+ difference. The list puts the screen back while a real item is on it, but a
399
+ fling into a part of the collection not loaded yet leaves a screen of skeletons
400
+ alone, with no item to hold: the screen moves with every skeleton that was
401
+ wrong (hundreds of pixels, in a thread drawing one-line skeletons where compact
402
+ cards land). So `renderSkeleton` draws each index at the room its item will
403
+ take, from what is known before the data — the same knowledge `itemSize` gives
404
+ the fillers. Items that cannot be told apart before they arrive are better
405
+ drawn at one height than announced by skeletons that guess. And anything drawn
406
+ above the screen that changes size afterwards — an image without its
407
+ dimensions, a block that expands — moves the screen the same way, which nothing
408
+ puts back during a fling on iOS: reserve its room.
382
409
 
383
410
  The window's own guess past what it has drawn is the one that is not the worst
384
411
  case, on purpose. Guessing the smallest there walks into cards at the one-line
@@ -457,6 +484,9 @@ Reference: `src/control/demos/19_list_find_in_page_demo.html`.
457
484
 
458
485
  ### Doing it well
459
486
 
487
+ - **Skeletons at the size of their item**, and `itemSize` when the items above
488
+ the screen come in sizes the data tells apart before it arrives (see
489
+ [What the list knows, and what it guesses](#what-the-list-knows-and-what-it-guesses)).
460
490
  - **A stable `id` on every item.** The run keys its rows on `item.id` — it is
461
491
  what addresses a row from outside (`--navi-select`, `scrolled={{ id }}`), and
462
492
  what tells a row that moved from a row that changed.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/navi",
3
- "version": "0.29.442",
3
+ "version": "0.29.443",
4
4
  "type": "module",
5
5
  "description": "Library of components including navigation to create frontend applications",
6
6
  "repository": {