@jsenv/navi 0.29.119 → 0.29.121

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.
@@ -418,8 +418,8 @@ cache, is what makes a screen already visited open instantly — and what a
418
418
  ## Movement between them
419
419
 
420
420
  The screens are places, so the movement between them is `RouteTravel` — not
421
- `SlideContainer`, which is for positions with no url (see
422
- [navigation.md](./navigation.md#tabs-with-no-url)).
421
+ `SlideContainer`, which is for positions that are not routes (see
422
+ [navigation.md](./navigation.md#tabs-that-are-not-routes)).
423
423
 
424
424
  A row says two things at once, and they are said apart. Its `<Route>` children
425
425
  are ordered by matching precision (above); `routes` is the order of the
@@ -33,6 +33,19 @@ and are referenced from here rather than restated.
33
33
  the distance decides, as usual.
34
34
  - Pulling towards nothing follows the finger at a fraction of its distance and
35
35
  comes back: a wall one can lean on, never walk through.
36
+ - **A direction that will be refused is one of those walls, and it must be a
37
+ wall from the first pixel.** Whatever holds the user where they are — a slide
38
+ waiting for its answer, a step reachable only by finishing the one before —
39
+ the gesture has to read it where it is ARMED, not only when it is let go of.
40
+ Read at the release alone, the hold does half its job: it forbids the arrival
41
+ and allows the whole journey, so the screen one may not reach is walked to,
42
+ read on the way, and then taken back. A wall that shows what is behind it and
43
+ pushes you back reads as a bug even when it is a rule. What the consumer owes
44
+ the gesture is therefore not "is there a screen that way" but "may I go
45
+ there" — the same question its release gate asks, asked earlier. Said `false`
46
+ there, the direction is simply a dead end like any other, and everything else
47
+ follows for free: the rubber band, the screen kept off stage, and a release
48
+ with nothing left to refuse.
36
49
  - A hand can go further than one box, and those extra pixels are not owed back:
37
50
  once the end is reached the gesture is measured from where the finger IS, so
38
51
  turning around moves the picture at once. Measured from the origin instead, a
@@ -20,7 +20,9 @@ retrofitted later:
20
20
 
21
21
  So the default shape of a tab row is routes: `<Nav>` + `<Link route>` +
22
22
  `<RouteTravel>`. `SlideContainer` is the exception, not the starting point — see
23
- [Tabs with no URL](#tabs-with-no-url) for the cases that genuinely are one.
23
+ [Tabs that are not routes](#tabs-that-are-not-routes) for the cases that
24
+ genuinely are one, and for the middle answer: a position READ from the URL and
25
+ restored on reload, without a route and without a history entry per step.
24
26
 
25
27
  ## Declaring routes
26
28
 
@@ -531,11 +533,12 @@ one form, and a movement between them. It is assembled in
531
533
  rules that decide the shape of the `<Route>` tree are spelled out (several routes
532
534
  match at once; the first matching branch wins).
533
535
 
534
- ## Tabs with no URL
536
+ ## Tabs that are not routes
535
537
 
536
538
  `SlideContainer` holds slides that replace one another in one box, with the same
537
- gestures and the same travelling bar, and nothing written to the URL. Use it when
538
- the position genuinely is not a place one should be able to link to:
539
+ gestures and the same travelling bar, and unless it is given a `urlParam`, see
540
+ below nothing written to the URL. Use it when the position genuinely is not a
541
+ place one should be able to link to:
539
542
 
540
543
  - the steps of a wizard, or the screens of a picker, inside a dialog or a popover
541
544
  — a popup is promoted to the browser's top layer, so no container can hold two
@@ -562,4 +565,59 @@ page. It reads which slide is on screen from the container itself, and its bar
562
565
  follows the slides, a finger dragging them included. `<Link slide>` has no href
563
566
  and behaves like a button: this is not a link to anywhere.
564
567
 
568
+ ### The middle answer: a position in the URL that is not a place one came from
569
+
570
+ "Should a link be able to open the app on this?" has a third answer, and a wizard
571
+ is exactly it: **yes for reading and for reloading, no for history.** The step one
572
+ is on should be legible in the address bar and should survive a reload —
573
+ `/alerts/W-123/edit` reopening on "Lieu" because that is where the reader was —
574
+ and it should NOT stack an entry per step, because the back arrow of a form means
575
+ "leave this form", not "one question back". Four steps that each push turn one
576
+ back-press into four, and walk the reader backwards through a form they thought
577
+ they had left.
578
+
579
+ Neither pure answer fits: routes would want one route per step, a real navigation
580
+ per move (so a push per move), and the walk's own rules — a step held until it is
581
+ answered, a confirmation reachable only by publishing — re-expressed as route
582
+ guards. A plain `SlideContainer` writes nothing at all.
583
+
584
+ `urlParam` is that middle answer: the container owns one search param, writes
585
+ where it stands into it **by replacement**, and opens on what it names.
586
+
587
+ ```jsx
588
+ <SlideContainer id="alert_editor" signal={stepSignal} urlParam="step">
589
+ ```
590
+
591
+ Two things it does that a `useEffect` calling `history.replaceState` beside the
592
+ container cannot, and they are the reason it lives inside:
593
+
594
+ - it writes the travels that HAPPENED. A travel a lock refused, or one the caller
595
+ refused late, never reaches the address — or is written back when it does;
596
+ - it READS the param through the walk rather than jumping to it. The address
597
+ comes from outside the box (typed, shared, kept from a session that has moved
598
+ on), so every slide between here and there is asked to let go the way a key
599
+ going that way would ask it, and the first one that holds is where one stops.
600
+ `?step=done` cannot open a confirmation screen for something nobody sent — and
601
+ the address is then rewritten with the area actually shown, so it never says
602
+ one is somewhere one is not.
603
+
604
+ A container remembers nothing across a reload, so a step whose `required` the app
605
+ knows is already satisfied says so itself (`required={!alreadyFilled}`); the same
606
+ holds for a hold that a finished job lifts (`preventNavNext={!published}`).
607
+
608
+ `history: "push"` is the other half, for slides that ARE places one came from — a
609
+ gallery one browses:
610
+
611
+ ```jsx
612
+ <SlideContainer urlParam={{ name: "photo", history: "push" }}>
613
+ ```
614
+
615
+ Even there, a slide reached by DRAGGING replaces rather than pushes: swiping back
616
+ and forth with a thumb is browsing, not a trail one wants to walk home along.
617
+
618
+ What `urlParam` is not: a route. Nothing is declared, nothing matches, no page
619
+ transition plays — what travels is the box, and the address is a label on where
620
+ the box stands. A position several parts of the app must react to is still a
621
+ route.
622
+
565
623
  Demo: [../src/layout/demos/8_slide_container_demo.html](../src/layout/demos/8_slide_container_demo.html).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/navi",
3
- "version": "0.29.119",
3
+ "version": "0.29.121",
4
4
  "type": "module",
5
5
  "description": "Library of components including navigation to create frontend applications",
6
6
  "repository": {