@jsenv/navi 0.29.479 → 0.29.481

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.
@@ -59,7 +59,8 @@ start when unsure which export solves a problem.
59
59
  ### Routing and movement
60
60
 
61
61
  - `navigation.md` — the position of the user belongs in the URL by default:
62
- routes and which branch renders, search params, redirections, the back arrow
62
+ routes and which branch renders, a page (`/x`) or a frame (`/x/`), search
63
+ params, redirections, the back arrow
63
64
  (`navBack`), where a navigation lands (a `#id` for an element; a page not
64
65
  whole yet holds its position with `useHoldScrollRestoration`), a
65
66
  `SlideContainer` read from the URL, what a layer drawn over the screen may say
@@ -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`
@@ -129,17 +156,20 @@ The default section can also have an address of its own, when the bare address
129
156
  is another page:
130
157
 
131
158
  ```js
132
- export const PROFILE_ROUTE = route("/me");
159
+ export const PROFILE_ROUTE = route("/me"); // a page, not a frame
133
160
  export const ADDRESS_BOOK_ROUTE = route(`/me/:section=${bookSectionSignal}`); // default "players"
134
161
  export const PLAYERS_ROUTE = route("/me/players");
135
162
  export const GROUPS_ROUTE = route("/me/groups");
136
163
  ```
137
164
 
138
- Declaring both `/me` and a literal for the default is what says so: the param
139
- is then required, `/me` is the profile alone, and `ADDRESS_BOOK_ROUTE.buildUrl()`
140
- gives `/me/players` or `/me/groups`, never `/me`. A visit to the profile leaves
141
- the section where it was. Leave out the literal for the default and `/me` is the
142
- default section, as with `/games/me` above.
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).
143
173
 
144
174
  That the literals exist is what tells navi these values name pages. Where none is
145
175
  declared, the value stays a qualifier, carried by an ancestor url:
@@ -275,10 +305,13 @@ export const HOME_ROUTE = route("/", { searchParams: { vue: vueSignal } });
275
305
 
276
306
  The signal and the URL are the same state: never keep a `useState` beside a route
277
307
  param for the same fact. Declared on the **root route**, a search param holds
278
- wherever one is in the application; declared on one route, it exists only there.
279
- A route declared "this and below" (`/map/`) lends its params to every address
280
- below it; `/places` lends nothing, so a `?q=` of its own and the `?q=` of
281
- `/places/clubs` are two states, even with a `/places/:section` matching both.
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.
282
315
 
283
316
  Writing it AMENDS the history entry one is on rather than stacking a new one: a
284
317
  param that qualifies a screen is not a place, and one entry per write turns a
@@ -321,7 +354,8 @@ the branch taken when no sibling matches.
321
354
  A route matches its own address and nothing below it — `/games/:gameId` does not
322
355
  match `/games/2/edit` — except `/` and a pattern ending in `/`, which match
323
356
  everything below them too (`route("/games/")` matches `/games/2/edit`): that is
324
- what keeps a section's container on screen while one is inside it. Two patterns
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
325
359
  can still match one url — `/games/my_games` is also a `/games/:gameId` — and a
326
360
  container renders the **first** branch that matches, in the order written, not
327
361
  the most specific. So the branches go from the most precise to the widest, and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/navi",
3
- "version": "0.29.479",
3
+ "version": "0.29.481",
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.94",
37
+ "@jsenv/dom": "0.17.95",
38
38
  "@jsenv/humanize": "1.8.8",
39
39
  "@jsenv/validity": "0.4.6"
40
40
  },