@jsenv/navi 0.29.407 → 0.29.409

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.
@@ -238,8 +238,9 @@ to start when unsure which export solves a problem.
238
238
  `scroller`, where a list opens and what a search does to where it is, a popup
239
239
  that scrolls, hover while scrolling; many rows: `<List.Items>` and the render
240
240
  window (`renderBudget`, its `{ initial, after }` form for a list opening in
241
- a click, `virtualItemSize`). Read before writing CSS to make something
242
- scroll, and before rendering a collection as `<List.Item>` children.
241
+ a click, `virtualItemSize`, `findText` for Cmd/Ctrl + F beyond the window).
242
+ Read before writing CSS to make something scroll, and before rendering a
243
+ collection as `<List.Item>` children.
243
244
  - `mobile_layout_pitfalls.md` — a horizontal overflow inflates the layout
244
245
  viewport on Chrome Android and miscenters every dialog; `overflow-x: clip`.
245
246
  - `z_index.md` — DOM order first; a `z-index` without `isolation: isolate`
package/docs/scroll.md CHANGED
@@ -400,6 +400,57 @@ this by hand with a `useEffect` that widens a slice: that effect is one preact
400
400
  runs early, and it fails for that reason. The runs ask their source for `after`
401
401
  rows from the start, so the smaller first window costs no second request.
402
402
 
403
+ ### Cmd/Ctrl + F: `findText`
404
+
405
+ The browser's find in page searches the DOM, and a row outside the render
406
+ window is not in it: Cmd/Ctrl + F finds the rows on screen and a few around
407
+ them, nothing else.
408
+
409
+ ```jsx
410
+ <List.Items
411
+ items={users}
412
+ renderItem={renderUser}
413
+ findText={(user) => user.name}
414
+ />
415
+ ```
416
+
417
+ With `findText`, the fillers carry the text of the rows they hold the room of,
418
+ one line per row at the row size, inside `hidden="until-found"` elements:
419
+ nothing of it is laid out or painted, and find still reaches it. On a match the
420
+ browser reveals the element and scrolls to the line — which is where the row
421
+ stands — and the render window, following that scroll like any other, draws
422
+ the row. A row inside the window has no hidden copy, so every row is found
423
+ exactly once and the count in the find bar is right.
424
+
425
+ What it costs, and where it stops:
426
+
427
+ - **A cost that follows the collection again.** The text of every row outside
428
+ the window is rebuilt when the window slides (one `findText` call per row)
429
+ and sits in the DOM as text, one element per 64 rows. Give it to a list a
430
+ user would search with the browser, not to every run.
431
+ - **One line per row**, and only that line is found while the row is not
432
+ drawn: return what a user would type, not everything the row shows.
433
+ - **What the client holds, no more.** A row a paginated run has not loaded has
434
+ no text to be found by.
435
+ - **Chrome 102, Firefox 148, Safari 26.2.** Elsewhere the attribute reads as a
436
+ plain `hidden`: find stops at the window, as without `findText`.
437
+
438
+ Two things not to write beside it:
439
+
440
+ - **A transparent copy of the list's text laid over it** (a `<textarea>` or a
441
+ `<div>` in `color: transparent`). Every row in the window is then found
442
+ twice, drawn and copied, and the copy only lines up with rows of one fixed
443
+ height. It is the first idea everyone has; the demo keeps it for comparison.
444
+ - **A `beforematch` listener moving the window.** The list re-renders in the
445
+ microtask after the event, which removes the element before the browser has
446
+ scrolled to it. The browser's own scroll is what moves the window.
447
+
448
+ And one trap outside the list: a CSS reset forcing `[hidden] { display: none }`
449
+ must leave `[hidden="until-found"]` out — an element hidden with `display: none`
450
+ is never revealed. navi's own does (`src/box/box.jsx`).
451
+
452
+ Reference: `src/control/demos/19_list_find_in_page_demo.html`.
453
+
403
454
  ### Doing it well
404
455
 
405
456
  - **A stable `id` on every item.** The run keys its rows on `item.id` — it is
@@ -434,7 +485,7 @@ row is ever a skeleton with `items`, and it costs what the same rows would as
434
485
  children. There is no reason to hold back from it for a list that might grow.
435
486
 
436
487
  Reference: `src/control/list/list.jsx` (JSDoc on `List` — `renderBudget`,
437
- `virtualItemSize` — and on `List.Items`),
488
+ `virtualItemSize` — and on `List.Items` — `findText`),
438
489
  `src/control/demos/17_virtual_scroll_and_filter_demo.html` (a run in memory,
439
490
  searched), `src/control/demos/integration/1_list_loaded_by_scroll_demo.html`
440
491
  (a run reading a slice at a time). What a run reads back after a write is in
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/navi",
3
- "version": "0.29.407",
3
+ "version": "0.29.409",
4
4
  "type": "module",
5
5
  "description": "Library of components including navigation to create frontend applications",
6
6
  "repository": {
@@ -34,7 +34,7 @@
34
34
  "preact": "^11.0.0-rc.2"
35
35
  },
36
36
  "dependencies": {
37
- "@jsenv/dom": "0.17.79",
37
+ "@jsenv/dom": "0.17.80",
38
38
  "@jsenv/humanize": "1.8.6",
39
39
  "@jsenv/validity": "0.4.5"
40
40
  },