@jsenv/navi 0.29.478 → 0.29.480
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.
- package/dist/dev/jsenv_navi.js +1732 -681
- package/dist/dev/jsenv_navi.js.map +38 -36
- package/dist/jsenv_navi.js +2161 -551
- package/dist/jsenv_navi.js.map +38 -36
- package/docs/AI_INSTRUCTIONS.md +5 -2
- package/docs/actions.md +23 -0
- package/docs/drag_to_travel.md +9 -3
- package/docs/form_changed.md +4 -3
- package/docs/interactions.md +8 -4
- package/docs/navigation.md +67 -4
- package/docs/pan_zoom.md +6 -4
- package/docs/popup_backdrop.md +5 -0
- package/docs/popup_lift.md +4 -3
- package/docs/route_transitions.md +7 -3
- package/docs/scroll.md +5 -5
- package/docs/testid.md +8 -5
- package/docs/view_transitions.md +3 -2
- package/package.json +3 -3
package/docs/AI_INSTRUCTIONS.md
CHANGED
|
@@ -26,7 +26,9 @@ source of knowledge has one job:
|
|
|
26
26
|
- **The built code, `dist/jsenv_navi.js`** — the exhaustive truth about the API,
|
|
27
27
|
JSDoc included, always under `node_modules/@jsenv/navi/`. When a signature, a
|
|
28
28
|
default or an accepted value is what you need, read it there rather than
|
|
29
|
-
guessing.
|
|
29
|
+
guessing. The formatters navi re-exports from `@jsenv/humanize` (`format*`,
|
|
30
|
+
`createI18n`, `interpolateText`) are a re-export there: their JSDoc is in
|
|
31
|
+
`node_modules/@jsenv/humanize/dist/browser/jsenv_humanize_browser.js`.
|
|
30
32
|
- **Sources, demos and tests** — how an export is really used:
|
|
31
33
|
`src/**/demos/*_demo.html` exercise one component per page, prop by prop. They
|
|
32
34
|
are not published to npm, so they live only in the repo
|
|
@@ -57,7 +59,8 @@ start when unsure which export solves a problem.
|
|
|
57
59
|
### Routing and movement
|
|
58
60
|
|
|
59
61
|
- `navigation.md` — the position of the user belongs in the URL by default:
|
|
60
|
-
routes and which branch renders,
|
|
62
|
+
routes and which branch renders, a page (`/x`) or a frame (`/x/`), search
|
|
63
|
+
params, redirections, the back arrow
|
|
61
64
|
(`navBack`), where a navigation lands (a `#id` for an element; a page not
|
|
62
65
|
whole yet holds its position with `useHoldScrollRestoration`), a
|
|
63
66
|
`SlideContainer` read from the URL, what a layer drawn over the screen may say
|
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
|
+
- [Nothing to ask, and coming back](#nothing-to-ask-and-coming-back)
|
|
25
26
|
- [The in-between states of a gesture are real params](#the-in-between-states-of-a-gesture-are-real-params)
|
|
26
27
|
- [Running: `run`, `rerun`, `prerun`, `reset`](#running-run-rerun-prerun-reset)
|
|
27
28
|
- [Aborting saves resources, it does not undo](#aborting-saves-resources-it-does-not-undo)
|
|
@@ -124,6 +125,28 @@ verb — `computed(() => ME.GET.dataSignal.value)` — only works for a verb
|
|
|
124
125
|
something runs **directly**, with no params; anything else derives from the
|
|
125
126
|
instance: `computed(() => COUNTS.dataSignal.value)`.
|
|
126
127
|
|
|
128
|
+
### Nothing to ask, and coming back
|
|
129
|
+
|
|
130
|
+
A binding has nothing to ask while its params as a whole are `undefined` or
|
|
131
|
+
`null` — a question computed from a form still missing a field.
|
|
132
|
+
`{ id: undefined }` is not that: it is a question, and it is asked. With nothing
|
|
133
|
+
to ask, the binding reads an instance holding nothing, idle: no data, no wait.
|
|
134
|
+
The previous answer stands in only while a newer one is coming, and none is.
|
|
135
|
+
|
|
136
|
+
What the previous params got stays on the instance that ran. A run still out
|
|
137
|
+
for them is called off by `actionRunEffect` (so by a route action) and carries
|
|
138
|
+
on under a plain binding; either way nothing is reset — an action does not
|
|
139
|
+
start over because its params went away.
|
|
140
|
+
|
|
141
|
+
Whether coming back to those params finds that answer depends on the instance
|
|
142
|
+
still being there. Without `keep` it lives as long as something references it,
|
|
143
|
+
and once nothing does it goes at a moment nothing in the code decides: coming
|
|
144
|
+
back may find it or ask again, and neither is something to build on.
|
|
145
|
+
`createAction(callback, { keep: { ms } })` is what decides. The answer stays
|
|
146
|
+
good for `ms` from the moment it landed, and the first screen asking for those
|
|
147
|
+
params after that asks again: a read worth asking at each visit — a
|
|
148
|
+
measurement, a quota — declares a short one.
|
|
149
|
+
|
|
127
150
|
### The in-between states of a gesture are real params
|
|
128
151
|
|
|
129
152
|
The delay decides _when_ a question goes out, never _which_ one is coherent: it
|
package/docs/drag_to_travel.md
CHANGED
|
@@ -79,9 +79,15 @@ are read at the press, before the box moves:
|
|
|
79
79
|
[interactions.md](./interactions.md#an-affordance-inside-somebody-elses-box-selfinteractions));
|
|
80
80
|
and a popover or a `<dialog>` inside the box, which is a layer over it. A
|
|
81
81
|
button, a link or a checkbox is not among them on purpose: a drag from one
|
|
82
|
-
travels, and the click it would have made is swallowed
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
travels, and the click it would have made is swallowed before any listener
|
|
83
|
+
hears it, the ancestors' included: an `onClick` on something that travels
|
|
84
|
+
needs no distance check of its own. For the same reason
|
|
85
|
+
navi refuses the browser's own drag of a link or an image for that press: it
|
|
86
|
+
starts a few pixels in and would take the pointer before the travel forms.
|
|
87
|
+
An app that wants an image dragged out of the page marks it
|
|
88
|
+
`data-no-drag-travel`. A field that only reads the press — a picker's façade
|
|
89
|
+
is an `<input>` that opens a popup — says so with `data-press-only`, and a
|
|
90
|
+
travel starts there like anywhere else.
|
|
85
91
|
2. **A scroller in between with room left that way.** It keeps the gesture until
|
|
86
92
|
it has no room left, and only then hands the travel over — so a row that
|
|
87
93
|
scrolls sideways inside a page still scrolls sideways. A row swiped with
|
package/docs/form_changed.md
CHANGED
|
@@ -53,9 +53,10 @@ for.
|
|
|
53
53
|
|
|
54
54
|
### A popup that stays open
|
|
55
55
|
|
|
56
|
-
A popup closes once a form inside it is sent
|
|
57
|
-
|
|
58
|
-
linked
|
|
56
|
+
A popup closes once a form inside it is sent, even when the send took the form
|
|
57
|
+
out of the page. When it is a place one keeps working in — a panel where a push
|
|
58
|
+
is sent, two fields are fixed, an account is linked, an answer drawn where the
|
|
59
|
+
form was ("link sent, check your inbox") — the form says it stays:
|
|
59
60
|
|
|
60
61
|
```jsx
|
|
61
62
|
<SidePanel signal={openUserSignal} value={user.id}>
|
package/docs/interactions.md
CHANGED
|
@@ -478,10 +478,14 @@ teardown, so a travelling container above it does not take the gesture (see
|
|
|
478
478
|
selection refused only for the length of its gesture — in time for a mouse,
|
|
479
479
|
too late for a finger held still — so it says `user-select: none` itself (see
|
|
480
480
|
[drag_interactions.md](./drag_interactions.md#the-text-inside-user-select-none)).
|
|
481
|
-
- **
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
481
|
+
- **What a press moves cannot also be dragged out of the page.** A swipe, a
|
|
482
|
+
travel (a `SlideContainer`, a `RouteTravel`, a sheet pushed back) and a `pan`
|
|
483
|
+
surface refuse the browser's own drag of the link or image a press lands on —
|
|
484
|
+
a native drag _is_ press-and-move, a link or an image is draggable without
|
|
485
|
+
anyone asking, and the browser starts it a few pixels in, before any of them
|
|
486
|
+
has decided. One gesture cannot mean both. What they leave alone keeps its
|
|
487
|
+
drag: an element inside marked `data-no-drag-travel` reads the pointer itself.
|
|
488
|
+
An element declaring a swipe also gets `draggable={false}`.
|
|
485
489
|
- **A popup can open while the finger is still down** — a menu under a waiting
|
|
486
490
|
finger is the native gesture (see
|
|
487
491
|
[popup_open.md](./popup_open.md#opening-while-the-finger-is-still-down), and
|
package/docs/navigation.md
CHANGED
|
@@ -5,6 +5,7 @@ linking to them, and turning them into tabs.
|
|
|
5
5
|
|
|
6
6
|
- [The rule that decides everything else: the position belongs in the URL](#the-rule-that-decides-everything-else-the-position-belongs-in-the-url)
|
|
7
7
|
- [Declaring routes](#declaring-routes)
|
|
8
|
+
- [A page or a frame: the trailing slash](#a-page-or-a-frame-the-trailing-slash)
|
|
8
9
|
- [A document that is not at the root: `setBaseUrl`](#a-document-that-is-not-at-the-root-setbaseurl)
|
|
9
10
|
- [A section is allowed to be a route of its own](#a-section-is-allowed-to-be-a-route-of-its-own)
|
|
10
11
|
- [Which values a param accepts](#which-values-a-param-accepts)
|
|
@@ -68,6 +69,32 @@ application, and an import line says which places a component deals with. Routes
|
|
|
68
69
|
are plain objects usable outside any component (`buildUrl()`, `navTo()`,
|
|
69
70
|
`redirectTo()`, `matching`), which is why they are declared apart from the JSX.
|
|
70
71
|
|
|
72
|
+
### A page or a frame: the trailing slash
|
|
73
|
+
|
|
74
|
+
The last character of a pattern is part of what the route stands for:
|
|
75
|
+
|
|
76
|
+
- `route("/map")` is a **page**: it matches `/map` and nothing below it.
|
|
77
|
+
- `route("/map/")` is a **frame**: it matches `/map` and every address below it,
|
|
78
|
+
`/map/flow` and `/map/isochrone/compare` included. The root `/` is always one.
|
|
79
|
+
|
|
80
|
+
A frame is what stays on screen while one moves below it: the map under its
|
|
81
|
+
panels, an admin shell around its sections. A page is one screen among others,
|
|
82
|
+
even when its address starts theirs: the profile at `/me`, beside the address
|
|
83
|
+
book at `/me/players`. To choose, ask whether the route is still on screen at
|
|
84
|
+
the addresses below it. The answer decides more than what renders:
|
|
85
|
+
|
|
86
|
+
| | page `route("/map")` | frame `route("/map/")` |
|
|
87
|
+
| ------------------------------------------------------------------ | -------------------------------------------------------------- | ------------------------------------------------------------------- |
|
|
88
|
+
| matches `/map/flow` | no | yes |
|
|
89
|
+
| its search params, on `/map/flow` | absent: they belong to `/map` alone | held: the url keeps them, the signal follows them |
|
|
90
|
+
| `/map/:panel` defaulting to `"isochrone"`, beside `/map/isochrone` | `/map` is this page alone, the panel lives at `/map/isochrone` | `/map` opens on the isochrone panel, and a link to it builds `/map` |
|
|
91
|
+
|
|
92
|
+
So a frame written without its slash shows itself in two ways: its search params
|
|
93
|
+
are left out of the addresses below it (not written there, not read from there),
|
|
94
|
+
and its address does not open on the default section. Details in
|
|
95
|
+
[Search params](#search-params) and in
|
|
96
|
+
[Declaring the sections](#declaring-the-sections-is-what-makes-them-places).
|
|
97
|
+
|
|
71
98
|
### A document that is not at the root: `setBaseUrl`
|
|
72
99
|
|
|
73
100
|
A second document in the same site — an admin panel at `/admin/admin.html`
|
|
@@ -125,6 +152,25 @@ already open — a tab pointing at the current page cannot be clicked. The defau
|
|
|
125
152
|
section has no segment, so its literal route is the **parent** of the
|
|
126
153
|
parameterized one, and still does not inherit the param.
|
|
127
154
|
|
|
155
|
+
The default section can also have an address of its own, when the bare address
|
|
156
|
+
is another page:
|
|
157
|
+
|
|
158
|
+
```js
|
|
159
|
+
export const PROFILE_ROUTE = route("/me"); // a page, not a frame
|
|
160
|
+
export const ADDRESS_BOOK_ROUTE = route(`/me/:section=${bookSectionSignal}`); // default "players"
|
|
161
|
+
export const PLAYERS_ROUTE = route("/me/players");
|
|
162
|
+
export const GROUPS_ROUTE = route("/me/groups");
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
A page at the bare address (see
|
|
166
|
+
[A page or a frame](#a-page-or-a-frame-the-trailing-slash)) and a literal for the
|
|
167
|
+
default are what say so: the param is then required, `/me` is the profile alone,
|
|
168
|
+
and `ADDRESS_BOOK_ROUTE.buildUrl()` gives `/me/players` or `/me/groups`, never
|
|
169
|
+
`/me`. A visit to the profile leaves the section where it was. The bare address
|
|
170
|
+
is the default section in the two other cases: when nothing is declared there
|
|
171
|
+
but a frame (`/map/` around its panels opens on the default one), and when no
|
|
172
|
+
literal is declared for the default (`/games/me` above).
|
|
173
|
+
|
|
128
174
|
That the literals exist is what tells navi these values name pages. Where none is
|
|
129
175
|
declared, the value stays a qualifier, carried by an ancestor url:
|
|
130
176
|
|
|
@@ -157,8 +203,10 @@ export const GAME_ROUTE = route(`/:gameId=${gameIdSignal}`, {
|
|
|
157
203
|
This is what lets a param sit at the root without swallowing every single-segment
|
|
158
204
|
address: `/cgu` stays another route's url, `<Route fallback>` is reachable, and
|
|
159
205
|
no signal is written for a url this route has nothing to do with. A constrained
|
|
160
|
-
param is also **required**: `/:gameId` does not match
|
|
161
|
-
|
|
206
|
+
param is also **required**: `/:gameId` does not match `/` — unless its default
|
|
207
|
+
stands for the bare address, as `/games/me` does for `/games/me/:section` (see
|
|
208
|
+
[Declaring the sections](#declaring-the-sections-is-what-makes-them-places)).
|
|
209
|
+
The accepted forms are in `route()`'s JSDoc.
|
|
162
210
|
|
|
163
211
|
#### Constrain the shape, never the existence
|
|
164
212
|
|
|
@@ -257,7 +305,13 @@ export const HOME_ROUTE = route("/", { searchParams: { vue: vueSignal } });
|
|
|
257
305
|
|
|
258
306
|
The signal and the URL are the same state: never keep a `useState` beside a route
|
|
259
307
|
param for the same fact. Declared on the **root route**, a search param holds
|
|
260
|
-
wherever one is in the application; declared on one route, it exists only there
|
|
308
|
+
wherever one is in the application; declared on one route, it exists only there:
|
|
309
|
+
on its own address for a page, on its own address and every address below it for
|
|
310
|
+
a frame (see [A page or a frame](#a-page-or-a-frame-the-trailing-slash)). Two
|
|
311
|
+
pages may each have a `?q=` of their own: the list at `/places` and the clubs at
|
|
312
|
+
`/places/clubs` keep two searches, even with a `/places/:section` matching both.
|
|
313
|
+
A param several pages need, and no frame holds, is declared on each of them,
|
|
314
|
+
with the same signal.
|
|
261
315
|
|
|
262
316
|
Writing it AMENDS the history entry one is on rather than stacking a new one: a
|
|
263
317
|
param that qualifies a screen is not a place, and one entry per write turns a
|
|
@@ -300,7 +354,8 @@ the branch taken when no sibling matches.
|
|
|
300
354
|
A route matches its own address and nothing below it — `/games/:gameId` does not
|
|
301
355
|
match `/games/2/edit` — except `/` and a pattern ending in `/`, which match
|
|
302
356
|
everything below them too (`route("/games/")` matches `/games/2/edit`): that is
|
|
303
|
-
what keeps a section's container on screen while one is inside it
|
|
357
|
+
what keeps a section's container on screen while one is inside it (see
|
|
358
|
+
[A page or a frame](#a-page-or-a-frame-the-trailing-slash)). Two patterns
|
|
304
359
|
can still match one url — `/games/my_games` is also a `/games/:gameId` — and a
|
|
305
360
|
container renders the **first** branch that matches, in the order written, not
|
|
306
361
|
the most specific. So the branches go from the most precise to the widest, and
|
|
@@ -398,6 +453,14 @@ section it does NOT stand for. Both amend what a link claims about itself and
|
|
|
398
453
|
nothing else — neither is an answer to a route that lies about where the reader
|
|
399
454
|
is (see [what its address may say](#a-layer-over-the-screen-what-its-address-may-say)).
|
|
400
455
|
|
|
456
|
+
The routing takes a plain click that moves this tab, and nothing else. A link
|
|
457
|
+
with `target="_blank"` (or any `target` other than `_self`) opens the app in that
|
|
458
|
+
tab or window, which loads it and routes there; a link with `download` saves its
|
|
459
|
+
address; a click with a modifier key (a new tab, a new window, a download) is the
|
|
460
|
+
browser's. None of them costs the page the reader is on — a half-filled form
|
|
461
|
+
beside a link to the terms stays filled. Nothing is fetched ahead for such a
|
|
462
|
+
link either: the other tab loads its own code.
|
|
463
|
+
|
|
401
464
|
## The back arrow: `navBack`
|
|
402
465
|
|
|
403
466
|
An arrow drawn inside the app promises the screen the reader came from — never
|
package/docs/pan_zoom.md
CHANGED
|
@@ -91,10 +91,12 @@ is not, and asking again is asking three times for one sentence:
|
|
|
91
91
|
<Box data-pan-after-hold="kept" interactions={{ pan, zoom }} />
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
-
From the moment the surface
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
94
|
+
From the moment a finger gives the surface the hand — the hold, or a pinch — it
|
|
95
|
+
pans on contact, the way the same plan does opened full screen, until a press
|
|
96
|
+
lands away from it; navi watches for that press itself, so nothing on your side
|
|
97
|
+
listens to the window. A mouse never owed the wait, so it neither spends it nor
|
|
98
|
+
marks it: after a mouse pan the next finger still waits, and the attribute is
|
|
99
|
+
safe to write for every device. The paid wait is a state to draw, and only a
|
|
98
100
|
`"kept"` surface carries it: `[data-hand-kept]`, for as long as it holds the
|
|
99
101
|
hand, a finger on it or not.
|
|
100
102
|
|
package/docs/popup_backdrop.md
CHANGED
|
@@ -138,6 +138,11 @@ wheel above is painted, so a press on it is a press on the popup — which is wh
|
|
|
138
138
|
lets one marker cover a whole row without swallowing the controls it holds. A
|
|
139
139
|
nested box that is see-through too needs its own marker.
|
|
140
140
|
|
|
141
|
+
**Inside a box that travels by drag, the marker answers the click.** A press on
|
|
142
|
+
a row of slides, or on a sheet that swipes closed, may be the start of that
|
|
143
|
+
travel; the popup closes on the click that ends the press, which a travel
|
|
144
|
+
swallows, rather than at the press itself.
|
|
145
|
+
|
|
141
146
|
**Space beside something, not space between two things.** What the wheel does
|
|
142
147
|
not cover is plainly nothing, and a press there reads as a press on the page.
|
|
143
148
|
The gap between two rows of a column does not read that way — it is a seam of
|
package/docs/popup_lift.md
CHANGED
|
@@ -218,9 +218,10 @@ closing, and a name built from it at that render names no tile: build it from
|
|
|
218
218
|
the last key the walk held — a ref written while the signal holds one.
|
|
219
219
|
|
|
220
220
|
**A press on the surface that dismisses is `data-navi-popup-outside`** (see
|
|
221
|
-
[popup_backdrop.md](./popup_backdrop.md#where-the-outside-begins))
|
|
222
|
-
|
|
223
|
-
|
|
221
|
+
[popup_backdrop.md](./popup_backdrop.md#where-the-outside-begins)). The row
|
|
222
|
+
travels, so the marker answers the press's click rather than its mousedown: a
|
|
223
|
+
swipe that starts on the free space walks, and only a press that stayed one
|
|
224
|
+
closes.
|
|
224
225
|
|
|
225
226
|
## Lifting on the way back only
|
|
226
227
|
|
|
@@ -287,9 +287,10 @@ Four misconfigurations are silent enough to be worth a console warning, each sai
|
|
|
287
287
|
once: an area that was not captured (the case above); several elements marked at
|
|
288
288
|
once — they share one `view-transition-name`, and the browser refuses every route
|
|
289
289
|
transition while they do; pages travelling on the document while something else
|
|
290
|
-
is captured on its own — the blank band; and
|
|
291
|
-
|
|
292
|
-
|
|
290
|
+
is captured on its own — the blank band; and a `view-transition-name` written
|
|
291
|
+
inside the area that only one of the two pages has: with nothing to morph into,
|
|
292
|
+
its element stands still and fades while the pages move, in every browser, and
|
|
293
|
+
without nested groups it is not even clipped (see
|
|
293
294
|
[view_transitions.md](./view_transitions.md#a-name-is-unique-per-document)). A
|
|
294
295
|
warning here is a bug to fix, not a mechanism to lean on.
|
|
295
296
|
|
|
@@ -474,6 +475,9 @@ What that means for a page and for the application around it:
|
|
|
474
475
|
it was (`<List id>`) under the same `id` as a list of the page arriving is the
|
|
475
476
|
same list to navi, and the two overwrite each other's position (see
|
|
476
477
|
[scroll.md](./scroll.md#a-list-that-comes-back-one-id-one-list)).
|
|
478
|
+
They let go of the document once hidden: a list scrolling the page stops
|
|
479
|
+
placing it on the item it opened on, and stops answering its scrolls and
|
|
480
|
+
resizes, so the page arriving lands where it was left, or at its top.
|
|
477
481
|
- **Never while a modal dialog is open.** An open modal keeps everything but
|
|
478
482
|
itself out of reach — the page arriving could not even take the focus — and one
|
|
479
483
|
in a page kept while leaving would stay open for the whole movement. The page is
|
package/docs/scroll.md
CHANGED
|
@@ -117,8 +117,8 @@ say so with `"document"` or the element itself.
|
|
|
117
117
|
### Where the list opens, and where it is
|
|
118
118
|
|
|
119
119
|
`defaultScrolled` (or `scrolled`, held) takes `{id, offset}` — what
|
|
120
|
-
`onScrolledChange` hands out — and asks for the
|
|
121
|
-
by MEASURING it: it lands where it was even if
|
|
120
|
+
`onScrolledChange` hands out — and asks for the item BY NAME, then puts it back
|
|
121
|
+
by MEASURING it: it lands where it was even if items were inserted before it,
|
|
122
122
|
whatever the screen it was saved on. "Reopen a thread where I left it" is
|
|
123
123
|
already provided; keep the position whole, its `visibleCount` sizes the first
|
|
124
124
|
paint. A `defaultScrolled` that changes before anyone has moved the list is
|
|
@@ -129,9 +129,9 @@ must name one list of the app, see [below](#a-list-that-comes-back-one-id-one-li
|
|
|
129
129
|
**`scrollResetOnNavigation`** opts out. What it draws there before its source
|
|
130
130
|
answers is another matter
|
|
131
131
|
([What a run knows when it opens](#what-a-run-knows-when-it-opens)). A list scrolling the document that
|
|
132
|
-
opens on
|
|
133
|
-
is not put back over it — the
|
|
134
|
-
height, and the same pixels now fall on other
|
|
132
|
+
opens on an item places the document itself: the offset the page kept for its url
|
|
133
|
+
is not put back over it — the items held off screen are fillers of an estimated
|
|
134
|
+
height, and the same pixels now fall on other items.
|
|
135
135
|
|
|
136
136
|
### A list that comes back: one `id`, one list
|
|
137
137
|
|
package/docs/testid.md
CHANGED
|
@@ -76,11 +76,14 @@ Navi hands the host the props it knows belong there (`id`, `name`, `type`,
|
|
|
76
76
|
root box instead — so a `data-test-id` or a `data-qa` of your own would name
|
|
77
77
|
the wrapper, which is the second reason to keep the standard spelling.
|
|
78
78
|
|
|
79
|
-
`aria-label` and `aria-labelledby`
|
|
80
|
-
|
|
81
|
-
role — it is a wrapper — so a name left on it would be
|
|
82
|
-
found by nothing, while the host is what the user
|
|
83
|
-
`getByRole(role, { name })` and `getByLabel()` read.
|
|
79
|
+
`aria-label` and `aria-labelledby` follow the role, for the reason the section
|
|
80
|
+
above gives: the name has to be where the role is. For most controls that is the
|
|
81
|
+
host. The root box has no role — it is a wrapper — so a name left on it would be
|
|
82
|
+
announced by nothing and found by nothing, while the host is what the user
|
|
83
|
+
focuses and what `getByRole(role, { name })` and `getByLabel()` read. A `Wheel`
|
|
84
|
+
is the other way round: its root is the `spinbutton` the user focuses, and its
|
|
85
|
+
host is an `aria-hidden` input carrying the value, so the name lands on the
|
|
86
|
+
root.
|
|
84
87
|
|
|
85
88
|
```jsx
|
|
86
89
|
<Picker variant="icon" aria-label="Aide" ui={<Icon>…</Icon>}>
|
package/docs/view_transitions.md
CHANGED
|
@@ -33,8 +33,9 @@ and `List` unnames its rows for the length of any route transition or travel. A
|
|
|
33
33
|
name the app puts inside the pages is given only for the gesture it serves, or
|
|
34
34
|
dropped while they move: `view-transition-name: none` under
|
|
35
35
|
`:root:is([data-navi-route-transition], [data-navi-route-travel])`. Without nested
|
|
36
|
-
groups it also escapes the pages' clip
|
|
37
|
-
transition area
|
|
36
|
+
groups it also escapes the pages' clip. navi warns about a name inside a
|
|
37
|
+
transition area that only one of the two pages has: with nothing to morph into,
|
|
38
|
+
it can only be this trap.
|
|
38
39
|
|
|
39
40
|
## Nested groups, and the fallback fade
|
|
40
41
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/navi",
|
|
3
|
-
"version": "0.29.
|
|
3
|
+
"version": "0.29.480",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Library of components including navigation to create frontend applications",
|
|
6
6
|
"repository": {
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@jsenv/dom": "0.17.94",
|
|
38
|
-
"@jsenv/humanize": "1.8.
|
|
39
|
-
"@jsenv/validity": "0.4.
|
|
38
|
+
"@jsenv/humanize": "1.8.8",
|
|
39
|
+
"@jsenv/validity": "0.4.6"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@jsenv/assert": "4.5.7",
|