@jsenv/navi 0.29.521 → 0.29.523

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.
@@ -83,12 +83,14 @@ start when unsure which export solves a problem.
83
83
 
84
84
  ### Data
85
85
 
86
- - `actions.md` — calling versus binding, a failing run rejects, reading is not
87
- running (`{ run: true }` is the fallback), `action` versus `uiAction`, an
88
- action and a command on one press. Before running an action from a component.
86
+ - `actions.md` — calling versus binding, what a binding holds while its params
87
+ move (`inheritData`), a failing run rejects, reading is not running
88
+ (`{ run: true }` is the fallback), `action` versus `uiAction`, an action and a
89
+ command on one press. Before running an action from a component.
89
90
  - `resource.md` — `resource()` and its relations (never an `op` discriminator),
90
- `GET_RANGE` (its inclusive `end`, the count for the screen around the list, a
91
- question following a search field), a search as the same `GET_MANY`, `withParams()` scopes and
91
+ what each read shows while its params move, `GET_RANGE` (its inclusive `end`,
92
+ the count for the screen around the list, a question following a search
93
+ field), a search as the same `GET_MANY`, `withParams()` scopes and
92
94
  `dependencies`, `persist` (and `keepPageOnScreen` for the page on screen), a
93
95
  function versus the verb's instance. Before writing a resource, and before
94
96
  caching a response yourself.
package/docs/actions.md CHANGED
@@ -22,6 +22,7 @@ them by hand — see [resource.md](./resource.md).
22
22
 
23
23
  - [Params: `bindParams`, and calling the action](#params-bindparams-and-calling-the-action)
24
24
  - [The answer is kept on the instance that ran](#the-answer-is-kept-on-the-instance-that-ran)
25
+ - [While the next answer comes](#while-the-next-answer-comes)
25
26
  - [Nothing to ask, and coming back](#nothing-to-ask-and-coming-back)
26
27
  - [The in-between states of a gesture are real params](#the-in-between-states-of-a-gesture-are-real-params)
27
28
  - [Running: `run`, `rerun`, `prerun`, `reset`](#running-run-rerun-prerun-reset)
@@ -112,9 +113,11 @@ A request that follows typing — the suggestions under an address field — is
112
113
  this binding, never the field's `action`: a field whose action runs is busy,
113
114
  and a busy field is read-only, so the person could not go on typing.
114
115
  `actionDebounce` delays an action that saves what was typed. Such a request,
115
- written with a plain `createAction`, has no verb for the network policy to see
116
- ([network_policy.md](./network_policy.md)): offline, its params say there is
117
- nothing to ask (`undefined`, [below](#nothing-to-ask-and-coming-back)).
116
+ written with a plain `createAction`, declares that its previous suggestions
117
+ stand in ([below](#while-the-next-answer-comes)), and has no verb for the
118
+ network policy to see ([network_policy.md](./network_policy.md)): offline, its
119
+ params say there is nothing to ask (`undefined`,
120
+ [below](#nothing-to-ask-and-coming-back)).
118
121
  `src/control/demos/integration/0_address_autocomplete_demo.html` is this shape.
119
122
 
120
123
  ### The answer is kept on the instance that ran
@@ -138,13 +141,48 @@ verb — `computed(() => ME.GET.dataSignal.value)` — only works for a verb
138
141
  something runs **directly**, with no params; anything else derives from the
139
142
  instance: `computed(() => COUNTS.dataSignal.value)`.
140
143
 
144
+ ### While the next answer comes
145
+
146
+ A binding moving to new params lands on an instance with no answer yet: `data`
147
+ is `undefined` until its own arrives, and the screen draws its wait. The previous
148
+ answer would be about something else — a club's podium under the name of the
149
+ department just pressed, one person's partners on another's profile — and nothing
150
+ would give it away: it reads as data, it only shows on a slow network, and it
151
+ fixes itself when the answer lands.
152
+
153
+ Another answer to **the same question** is different: results refined by a
154
+ keystroke, a window recentred along a list, a thread read again because it grew.
155
+ A blank between two of those is the only thing wrong on the screen, and the
156
+ action says so:
157
+
158
+ ```js
159
+ const searchAddresses = createAction(search, { inheritData: true });
160
+ ```
161
+
162
+ The new instance then starts on what the previous one held, its failure included,
163
+ and `loading` says a newer answer is coming. A resource declares this for each of
164
+ its reads: one item starts on nothing, a list hands over
165
+ ([resource.md](./resource.md#what-a-read-shows-while-its-params-move)). When one
166
+ action serves both kinds of screen, a binding says it for itself, in either
167
+ direction:
168
+
169
+ ```js
170
+ routeAction(AUTHOR_PAGE, VIDEOS, () => ({ author: authorSignal.value }), {
171
+ inheritData: false,
172
+ });
173
+ ```
174
+
175
+ Only a binding following a signal moves. Plain params make an instance that stays
176
+ what it is, and hand nothing over.
177
+
141
178
  ### Nothing to ask, and coming back
142
179
 
143
180
  A binding has nothing to ask while its params as a whole are `undefined` or
144
181
  `null` — a question computed from a form still missing a field.
145
182
  `{ id: undefined }` is not that: it is a question, and it is asked. With nothing
146
183
  to ask, the binding reads an instance holding nothing, idle: no data, no wait.
147
- The previous answer stands in only while a newer one is coming, and none is.
184
+ An answer declared to stand in does so only while a newer one is coming, and none
185
+ is.
148
186
 
149
187
  What the previous params got stays on the instance that ran. A run still out
150
188
  for them is called off by `actionRunEffect` (so by a route action) and carries
@@ -90,6 +90,14 @@ puts a reload on the second line as well, and so does
90
90
  [`keepPageOnScreen`](./resource.md#keeppageonscreen-the-page-on-screen-drawn-again-by-the-next-document) for
91
91
  what the page on screen reads — a `GET_MANY` and a `GET_RANGE` included.
92
92
 
93
+ **Params moving ask another question, and its first answer is a first load.** A
94
+ binding following a signal lands on an instance with no answer, on the first
95
+ line: an action made with `createAction`, or the `GET` of a relation, which does
96
+ not look in the store. What declares that the previous answer stands in starts on
97
+ the second line: a `GET_MANY`, or `createAction(callback, { inheritData: true })`
98
+ ([actions.md](./actions.md#while-the-next-answer-comes),
99
+ [resource.md](./resource.md#what-a-read-shows-while-its-params-move)).
100
+
93
101
  **The emptiness test is `data === undefined`, never `loading`.** Reading
94
102
  `loading` as "there is nothing to display" blanks the screen on every refresh —
95
103
  for a checkbox ticked on one row of a list, the whole list goes. A list is no
@@ -38,12 +38,21 @@ the pointer inside a box that travels.
38
38
  pointer it has already cancelled (see
39
39
  [mobile_touch.md](./mobile_touch.md#the-browser-decides-about-8px-in-and-does-not-wait)).
40
40
  Its price is the click of a tap that shook more than 6px.
41
- - **A hand still moving when it lets go says where this goes, and it says it
42
- both ways.** Towards what it was bringing in, the travel carries on, however
43
- slowly, once it has pulled a few pixels. Away from it, fast, everything goes
44
- back whatever the distance already covered — otherwise a screen caught in
45
- flight and thrown back still arrives. Only a release at rest is judged by the
46
- picture: about a third of the box.
41
+ - **A page change is asked for a little later than the press is taken.** A
42
+ `RouteTravel` holds the press at the same 6px, but nothing is asked of the
43
+ router until the hand has pulled 10px further, 16px in all with a finger: a
44
+ navigation, a render and the requests of the page arriving are not worth a
45
+ hand that only shook. Turned around before that, it simply picks the other
46
+ neighbour. The picture sets off from where it stands rather than jumping those
47
+ pixels, and let go of before that, nothing has moved.
48
+ - **Letting go asks where the hand is about to put things.** Where the picture
49
+ stands, plus half a second at the speed the fingertip has as it lifts, against
50
+ half the box. A flick lands far and goes. A hand thrown back lands short and
51
+ everything goes back, otherwise a screen caught in flight and thrown back
52
+ still arrives. A hand that slowed to a stop has no speed left, and the picture
53
+ answers alone. Speed counts from 25px of finger, a tap that slipped not being
54
+ a flick, and past 0.4 px/ms it answers on its own, or half a wide box would be
55
+ out of reach of any flick.
47
56
  - Pulling towards nothing follows the finger at a fraction of its distance and
48
57
  comes back: a wall one can lean on, never walk through.
49
58
  - **A direction that will be refused is one of those walls, and it must be a
@@ -210,6 +219,7 @@ carry screens.
210
219
  | what the screens are | `<Slide>`s in one box, all mounted | routes — one mounted, ever |
211
220
  | what says which is here | a `signal`, `current` / a command | the URL |
212
221
  | what the finger moves | a translated track | the pictures of a view transition |
222
+ | when the picture moves | from the press becoming a gesture | from 10px after that |
213
223
  | letting go too early | the track comes back | the transition is played backwards |
214
224
  | what says the order | the layout map | the `<Route>` children, in order |
215
225
  | what one wheel push is | `move(±1)`, as an arrow key | one travel, as a tab pressed |
@@ -554,6 +554,23 @@ replace moves the scroll
554
554
  ([below](#a-row-of-tabs-where-a-replace-is-an-arrival)). Several `RouteTravel`
555
555
  boxes may live on one page, and only the one travelling is captured.
556
556
 
557
+ **The URL says where the hand is heading, not where the reader is.** It changes
558
+ once the hand has really pulled, and comes back if the page is let go of. So a
559
+ counter, a title or a breadcrumb around the box reads
560
+ `routeTravelSettledPageSignal` first, or it moves for a pull that goes nowhere:
561
+
562
+ ```jsx
563
+ const settledPage = routeTravelSettledPageSignal.value;
564
+ const shownId = settledPage ? settledPage.params.gameId : currentId;
565
+ ```
566
+
567
+ It holds the `{ route, params }` the travel set off from for as long as the
568
+ pictures move, and is `null` when they stop, the URL being the truth again. A
569
+ page walked whole under the hand has arrived. A tab pressed or a wheel pushed
570
+ holds nothing, and `null` is all they ever read. One signal for the document, as
571
+ there is one transition at a time: on a page with several boxes, `route` says
572
+ which row is travelling.
573
+
557
574
  `RouteTravel` is for pages that form a ROW the finger can push; pages related
558
575
  pair by pair are animated with `defineRouteTransition`, and a given pair by one
559
576
  of the two, never both (see
package/docs/resource.md CHANGED
@@ -42,6 +42,7 @@ Actions are read in components through the action system (`useAsyncData`,
42
42
  - [Callback return contracts](#callback-return-contracts)
43
43
  - [When the backend answers a sub-route with the whole parent](#when-the-backend-answers-a-sub-route-with-the-whole-parent)
44
44
  - [Relations and autorerun](#relations-and-autorerun)
45
+ - [What a read shows while its params move](#what-a-read-shows-while-its-params-move)
45
46
  - [`withParams()`: a scope with reruns of its own](#withparams-a-scope-with-reruns-of-its-own)
46
47
  - [`dependencies`: rerun after another resource writes](#dependencies-rerun-after-another-resource-writes)
47
48
  - [A function calling the verb, or the instance](#a-function-calling-the-verb-or-the-instance)
@@ -666,6 +667,43 @@ is a resource of its own, refreshed only by these rules. When a parent field
666
667
  depends on a child mutation, say so with `dependencies` rather than relying on a
667
668
  rerun that will not happen.
668
669
 
670
+ ## What a read shows while its params move
671
+
672
+ A binding following a signal — a route action, `bindParams(signal)` — moves to
673
+ another instance when its params change, and that instance has no answer yet.
674
+ What it holds until its answer lands depends on the action
675
+ ([actions.md](./actions.md#while-the-next-answer-comes)):
676
+
677
+ | Action | Until its answer lands |
678
+ | -------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
679
+ | `GET` | the row the store holds for these params, or nothing |
680
+ | the `GET` of a relation (`.one()`, `.scopedOne()`, one item of `.many()` or `.scopedMany()`) | nothing, whatever the store holds |
681
+ | `GET_MANY`, and the `GET_MANY` of `.many()` or `.scopedMany()` | the previous list |
682
+ | a write (`POST`, `PUT`, `PATCH`, `DELETE`, plural or not) | what the previous instance held |
683
+
684
+ A read of one item never starts on the previous answer: it would be another row,
685
+ or another owner's, drawn under the new params, and nothing would give it away.
686
+
687
+ A list hands over because one standing in for the next beats a skeleton. That is
688
+ right for a search, the same collection asked again, and for a list nobody reads
689
+ as a claim about its owner: a sheet of courts that catches up with the club a
690
+ round trip later. It is false where the list says something about who it belongs
691
+ to: one person's partners, on another's profile. The read cannot tell the two
692
+ apart and the screen can, so the screen says it on its binding:
693
+
694
+ ```js
695
+ const PARTNERS_ACTION = routeAction(
696
+ PROFILE_ROUTE,
697
+ USER_PARTNERS.GET_MANY,
698
+ () => ({ id: profileIdSignal.value }),
699
+ { inheritData: false },
700
+ );
701
+ ```
702
+
703
+ A `GET_RANGE` reader has no such choice to make: bound to other params it is
704
+ another collection, drawn from its first item
705
+ ([above](#a-question-that-follows-a-search-field)).
706
+
669
707
  ## `withParams()`: a scope with reruns of its own
670
708
 
671
709
  A resource reruns its own reads after its own writes (`rerunOn`, see
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/navi",
3
- "version": "0.29.521",
3
+ "version": "0.29.523",
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.101",
37
+ "@jsenv/dom": "0.17.102",
38
38
  "@jsenv/humanize": "1.8.11",
39
39
  "@jsenv/validity": "0.4.7"
40
40
  },