@jsenv/navi 0.29.67 → 0.29.68

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.
@@ -72,8 +72,11 @@ consistency across the app, not from any single call site.
72
72
  what updates from a response without any request, `rerunOn` and its defaults,
73
73
  and how a paginated `<List.Items>` re-reads its slices without disappearing,
74
74
  including on its way back from a screen that unmounted it.
75
- Read it before adding verbs to `rerunOn`, hiding a list on `loading`, or
76
- remounting a list with a `key` to refresh it.
75
+ It also says who decides a re-read on the way back the source the list
76
+ reads through, never the navigation and never a route transition.
77
+ Read it before adding verbs to `rerunOn`, hiding a list on `loading`,
78
+ remounting a list with a `key` to refresh it, or reporting that a page
79
+ stopped refreshing since a transition was defined on its pair.
77
80
  - `docs/error_handling.md` — the two kinds of error and how navi keeps them
78
81
  apart: where an error is shown depending on where it came from (a control's
79
82
  action shows it on what was clicked, a route action replaces the page, a
@@ -168,8 +171,9 @@ consistency across the app, not from any single call site.
168
171
  - `docs/navigation.md` — how to build navigation: declaring routes
169
172
  (`route()` / `setupRoutes()`), when a section is a route of its own rather
170
173
  than a param, search params bound to signals, rendering with `<Route>`,
171
- tab rows (`Nav` / `Link` / `RouteTravel`), and the few cases where tabs are
172
- legitimately not URLs. Read it before writing any routing code the
174
+ tab rows (`Nav` / `Link` / `RouteTravel`), where a navigation lands
175
+ (scroll: a push arrives at the top, a back or forward lands where the page
176
+ was left), and the few cases where tabs are legitimately not URLs. Read it before writing any routing code — the
173
177
  position of the user belongs in the URL by default, and that decision is
174
178
  not retrofittable.
175
179
  - Source code and demos on GitHub:
@@ -132,8 +132,9 @@ stale copy of anything.
132
132
  A run that finds a composition takes the `refreshing` line of the table above
133
133
  rather than the loading one: the rows are on screen while it asks again for the
134
134
  window it draws. So the two lists an app cannot tell apart from the outside —
135
- one reading `GET_MANY`, one reading `GET_RANGE` — behave the same on the way
136
- back.
135
+ one reading `GET_MANY`, one reading `GET_RANGE` — look the same on the way back:
136
+ neither blanks, neither shows a first load. What they do behind that is not the
137
+ same, and the next section is about exactly that.
137
138
 
138
139
  What a composition is about is the **values** its params hold, not the reader
139
140
  instance: `GET_RANGE.bindParams({ scope: "thread" })` called from two places
@@ -145,6 +146,36 @@ The rest follows the rules already stated: a verb in `rerunOn.GET_RANGE`, or
145
146
  gone — and `memoryBudget` (1000 ranks by default) trims the ranks far from any
146
147
  window, which are asked for again if the user goes back to them.
147
148
 
149
+ ### Who decides the re-read — and who does not
150
+
151
+ The navigation decides nothing. Neither the back button, nor the movement
152
+ playing between the two pages: the **source** the list reads through is what
153
+ answers, and it answers the same way whether the user arrived by a link, by
154
+ `history.back()`, or under a route transition.
155
+
156
+ | The list reads through | Coming back to it |
157
+ | ------------------------------- | ----------------------------------------------------------------------------------------------------- |
158
+ | `routeAction` over `GET_MANY` | **nothing goes out** — the action holds its response, and `.run()` on a `COMPLETED` action is a no-op |
159
+ | `<List.Items>` over `GET_RANGE` | **one ask goes out** — the reader kept ranks, not rows, and revalidates the window it draws |
160
+
161
+ Both are deliberate, and they are not in tension: an action that kept its answer
162
+ has the answer, while a composition is a claim about an order that any write
163
+ elsewhere may have made false. What a `GET_MANY` list wants on the way back it
164
+ has to say itself — `.rerun()` when the route becomes current again, or a verb
165
+ in `rerunOn` if a write is what makes it stale.
166
+
167
+ Nothing above changes when `defineRouteTransition` is written for the pair the
168
+ list is walked through. A transition states a relation between two pages (see
169
+ [route_transitions.md](./route_transitions.md)); it takes the document's
170
+ rendering hold for the one frame the browser needs to photograph it, and gives
171
+ it back. It never decides what the page arriving is allowed to ask for. Held by
172
+ `tests/route_transition_list_revisit/`, which mounts the same app twice — with
173
+ and without a relation on the pair — and compares both counts.
174
+
175
+ So a list that stopped refreshing after a transition was added has, in the
176
+ overwhelming majority of cases, never refreshed on its own: it was reading
177
+ through `GET_MANY`, and something else in the app was doing the re-read.
178
+
148
179
  ## `rerunOn`, verb by verb
149
180
 
150
181
  `rerunOn` says which verbs invalidate this resource's `GET` / `GET_MANY` /
@@ -294,6 +294,32 @@ settings page rising over whatever showed it — are animated with
294
294
  `defineRouteTransition` instead, and a given pair must be animated by one of
295
295
  the two, never both: see [route_transitions.md](./route_transitions.md).
296
296
 
297
+ ## Where a navigation lands: the scroll
298
+
299
+ Three cases, and they are not a policy to configure but three different facts:
300
+
301
+ - **Going somewhere new** (a `<Link>`, anything that pushes) lands at the top.
302
+ It is an arrival: the offset one had elsewhere means nothing here, and left
303
+ alone the new entry would be born holding the previous page's offset — which
304
+ the browser would then hand back as if it were this page's own.
305
+ - **Going back or forward** (the browser's buttons, `navBack()`,
306
+ `history.back()`) lands where that page was left. navi keeps the position and
307
+ puts it back once the page is really rendered, which is what the browser
308
+ cannot do: it restores at the instant the entry changes, when the document
309
+ still holds the page being left, so anything further down than that page is
310
+ tall is clamped away.
311
+ - **A reload** lands where one was, as it would have without navi.
312
+
313
+ The consequence worth knowing when building a screen: **a "back" written as a
314
+ `<Link>` is a push**, so it lands at the top like any arrival — no mechanism
315
+ can guess that a push was morally a return. A back arrow that should feel like
316
+ one is `navBack()`. Where there may be nothing to go back to (a shared link
317
+ opened cold), decide what the arrow does from the history, not from the link.
318
+
319
+ What is not covered: a page whose height depends on something still loading is
320
+ not tall enough at the moment its position is put back, so a deep position is
321
+ clamped as it was before. Only the page knows when it is whole.
322
+
297
323
  ## Creating something, then editing it
298
324
 
299
325
  The create screen, the page of what was created, the edit screen — three routes,
@@ -8,7 +8,7 @@ decides which movement (if any) a navigation deserves. The API grammar itself
8
8
 
9
9
  Demos: [the movements](../src/nav/demos/route_transition/route_transition.html),
10
10
  [a default transition](../src/nav/demos/route_transition/route_transition_default.html),
11
- [pages between fixed bars](../src/nav/demos/route_transition/route_transition_fixed_bars.html),
11
+ [pages between fixed bars](../src/nav/demos/route_transition_fixed_bars/route_transition_fixed_bars.html),
12
12
  [with a RouteTravel inside](../src/nav/demos/route_transition/route_transition_with_travel.html)
13
13
 
14
14
  ## What a transition is for
@@ -110,6 +110,12 @@ through, not the page's own size: a page is as tall as its content, and a
110
110
  vertical movement measured on the picture would send it several screens away —
111
111
  off screen for most of the transition, flying past at the end.
112
112
 
113
+ A page that was **scrolled** is photographed where the reader was, and travels
114
+ from there: the document is not put back to its top until the picture has been
115
+ taken. Without that wait the picture keeps only the band the browser had
116
+ already painted at the new offset, and the movement carries a fragment of the
117
+ page instead of the page.
118
+
113
119
  With an area marked, the page around it is left LIVE rather than photographed:
114
120
  the bars keep answering the pointer for the whole movement, which a captured
115
121
  element cannot do. The flip side is that anything around the area which must
@@ -176,6 +182,30 @@ animates. A `<RouteTravel>` rendered inside the `element` of each of the routes
176
182
  it travels between is destroyed mid-travel by the router. Give the row a single
177
183
  branch — its tabs as params of one route is the usual shape.
178
184
 
185
+ ## A transition says nothing about data
186
+
187
+ A relation is about the map of the app, and about nothing else. Defining one
188
+ does not change what the page arriving loads, reloads, or keeps:
189
+
190
+ - an action that `COMPLETED` still holds its response, on the way back as on the
191
+ way in — a page wanting fresh data says `.rerun()`, with or without a
192
+ movement;
193
+ - a `<List.Items>` reading through `GET_RANGE` still revalidates the window it
194
+ draws when it is mounted again.
195
+
196
+ What a transition takes is the document's **rendering** for the one frame the
197
+ browser needs to photograph the page being left (see `rendering_hold.js`), and
198
+ it gives it back in the same callback. The hold is about a picture, not about
199
+ data: nothing waits on it, nothing is skipped because of it.
200
+
201
+ So "this list stopped refreshing since we animated the pair" is a claim worth
202
+ checking twice before believing: it is held by
203
+ `tests/route_transition_list_revisit/`, which mounts one app twice — the two
204
+ mounts differing by a single `defineRouteTransition` line — and compares what
205
+ each one sends to the network on the way back. See
206
+ [list_refresh.md](./list_refresh.md#who-decides-the-re-read--and-who-does-not)
207
+ for which source refreshes on a revisit and which does not.
208
+
179
209
  ## The rest, briefly
180
210
 
181
211
  - Pace: `--navi-route-transition-duration` (CSS, default 300ms) for everyone;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/navi",
3
- "version": "0.29.67",
3
+ "version": "0.29.68",
4
4
  "type": "module",
5
5
  "description": "Library of components including navigation to create frontend applications",
6
6
  "repository": {