@jsenv/navi 0.29.460 → 0.29.462

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.
@@ -58,7 +58,8 @@ start when unsure which export solves a problem.
58
58
 
59
59
  - `navigation.md` — the position of the user belongs in the URL by default:
60
60
  routes and which branch renders, search params, redirections, the back arrow
61
- (`navBack`), where a navigation lands (a `#id` for an element), a
61
+ (`navBack`), where a navigation lands (a `#id` for an element; a page not
62
+ whole yet holds its position with `useHoldScrollRestoration`), a
62
63
  `SlideContainer` read from the URL, what a layer drawn over the screen may say
63
64
  in its address. Before any routing code.
64
65
  - `route_transitions.md` — a transition states a relation between two pages;
package/docs/actions.md CHANGED
@@ -202,8 +202,9 @@ this one cannot start before the component that draws it exists — a render lat
202
202
  at best, a gesture late in a popup. It is for a parameter chosen inside the
203
203
  component and dying with it. Outside a component,
204
204
  `actionRunEffect(action, () => …)` is that same run declared once — it runs on
205
- the first truthy params, reruns when they change, aborts when they go false —
206
- and the machinery `routeAction` is built on.
205
+ the first truthy params, reruns when they change (unless the action declared
206
+ `keep` and still holds the answer for the new ones), aborts when they go
207
+ false — and the machinery `routeAction` is built on.
207
208
 
208
209
  **Which of the two it is, is decided by the parameter, not by what draws it.**
209
210
  If the parameter is in the address — a path param, a search param bound to a
@@ -68,6 +68,10 @@ Everything the data layer decides then holds for the code:
68
68
  `activeRouteReadsSignal`, which leaves the code out: rerun, it would take a
69
69
  page reading it delegated off the screen for a frame.
70
70
  - **Fetched ahead**, on intent ([below](#ahead-of-the-render-intent)).
71
+ - **A reload lands where the reader was.** The scroll position waits for the
72
+ code and the render that draws the page, rather than being written into the
73
+ pending screen and clamped to its height
74
+ ([navigation.md](./navigation.md#a-page-that-is-not-whole-yet)).
71
75
 
72
76
  ## A component inside a page that stays: who asks for its code
73
77
 
@@ -16,6 +16,7 @@ linking to them, and turning them into tabs.
16
16
  - [The back arrow: `navBack`](#the-back-arrow-navback)
17
17
  - [Tabs that travel: `RouteTravel`](#tabs-that-travel-routetravel)
18
18
  - [Where a navigation lands: the scroll](#where-a-navigation-lands-the-scroll)
19
+ - [A page that is not whole yet](#a-page-that-is-not-whole-yet)
19
20
  - [Landing on an element: the fragment](#landing-on-an-element-the-fragment)
20
21
  - [Creating something, then editing it](#creating-something-then-editing-it)
21
22
  - [Tabs that are not routes](#tabs-that-are-not-routes)
@@ -481,7 +482,8 @@ Five cases, and they are not a policy to configure but five different facts:
481
482
  - **Replacing the entry** (`<Link replace>`, `route.redirectTo()`, a param
482
483
  settling) moves nothing: the same place said differently — except in a row of
483
484
  tabs, below.
484
- - **A reload** lands where one was, as it would have without navi.
485
+ - **A reload** lands where one was, as it would have without navi, once the
486
+ page is there ([below](#a-page-that-is-not-whole-yet)).
485
487
 
486
488
  Where the browser exposes its stack (the Navigation API), **a `<Link>` whose
487
489
  destination is the entry right next to the current one becomes a real
@@ -490,6 +492,56 @@ A, B, A, B… growth, and the scroll comes back — and one step forward too. On
490
492
  towards entries of this document, and never when the push carries explicit
491
493
  state. An arrow that must ALWAYS behave as a back is `navBack()`.
492
494
 
495
+ ### A page that is not whole yet
496
+
497
+ A position is put back into whatever the page shows at that moment. When that is
498
+ a stand-in — a pending screen, a `<Loading>` fallback, a list of three skeletons
499
+ — the document is shorter than the page the position was taken on, the offset is
500
+ clamped to it, and the reader lands at the top of a page that arrives a moment
501
+ later.
502
+
503
+ **After a reload, navi waits for the route actions** that the first render had
504
+ nothing to draw for: the page's code arriving on its own
505
+ ([dynamic_import.md](./dynamic_import.md)), a read the previous document did not
506
+ keep ([`keepPageOnScreen`](./resource.md#keeppageonscreen-the-page-on-screen-drawn-again-by-the-next-document) draws a kept one at once, and that one
507
+ is not waited for). The position is put back once they have answered and the
508
+ page has rendered. When one of them fails, nothing is written: the screen saying
509
+ so is not the page the position was taken on, and the position stays for the
510
+ reload that brings it back. What it costs: a slow read that every page asks for
511
+ delays the position of every page, since nothing tells navi which reads set the
512
+ height.
513
+
514
+ A route action that starts asking only after that render is waited for too: one
515
+ gated on app state the first render did not have yet (`when`, or params that
516
+ read an app-wide read such as the signed-in user), or one whose params are
517
+ another's answer. Before it asks, nothing tells "not yet" from "never", so the
518
+ position is written into what the page shows. When the document is too short to
519
+ hold it, the position is not spent: the next route action that starts without an
520
+ answer is waited for the same way, and the position is put back again once it
521
+ is drawn.
522
+
523
+ **What navi cannot see, the page says**: a read it starts itself
524
+ (`useAsyncData(…, { run: true })`), content whose height arrives late. While
525
+ `useHoldScrollRestoration(held)` is given `true`, the position of a reload or of
526
+ a back/forward waits; it is put back after the render that turns it `false`:
527
+
528
+ ```jsx
529
+ const [games] = useAsyncData(GAMES, { loading: true, run: true });
530
+ useHoldScrollRestoration(games === undefined);
531
+ ```
532
+
533
+ A read that fails leaves it `true`, and nothing is written, for the same reason
534
+ as above. A row of tabs is not held: it gives a tab its position as it travels,
535
+ and measures right after (see [below](#a-row-of-tabs-where-a-replace-is-an-arrival)).
536
+
537
+ **The reader taking over cancels it.** A finger, a click, a wheel or a key
538
+ before the position is written, and it is not written: moved afterwards, they
539
+ would lose whatever they had started on. Going elsewhere cancels it too.
540
+
541
+ A `<List>` that opens on an item is the opposite case, and needs nothing: it
542
+ places the document itself, by measuring the item, and the url's offset is not
543
+ put back over it ([scroll.md](./scroll.md#where-the-list-opens-and-where-it-is)).
544
+
493
545
  ### Landing on an element: the fragment
494
546
 
495
547
  A link meant to bring one element under the reader's eyes — a notification
@@ -564,9 +616,10 @@ the viewport may scroll, and a row inside a scroller of its own leaves that
564
616
  offset alone. An `overflow: hidden` on any ancestor is enough to take the row out
565
617
  of the document's scrollport — it holds an offset even without a scrollbar, where
566
618
  `overflow: clip` holds none — so it is the first thing to look for when a row
567
- does not give positions back. And a page whose height depends on something still
568
- loading is not tall enough when its position is put back: only the page knows
569
- when it is whole. What navi itself builds after the first frame
619
+ does not give positions back. And a tab whose height depends on something still
620
+ loading is not tall enough when its position is put back: the row does not wait
621
+ for it ([A page that is not whole yet](#a-page-that-is-not-whole-yet) is for a
622
+ reload and a back). What navi itself builds after the first frame
570
623
  (`<Box mount="after-paint">`, see
571
624
  [scroll.md](./scroll.md#many-sections-box-mountafter-paint)) is not such a
572
625
  page: the part the position shows is built before it is written.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/navi",
3
- "version": "0.29.460",
3
+ "version": "0.29.462",
4
4
  "type": "module",
5
5
  "description": "Library of components including navigation to create frontend applications",
6
6
  "repository": {