@jsenv/navi 0.29.364 → 0.29.366

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.
@@ -175,7 +175,9 @@ to start when unsure which export solves a problem.
175
175
  trigger's box is the card's box; `lift="box"` for a card, `"scene"` for a
176
176
  drawing framed the same way; one popup for a whole row, walked from the front
177
177
  through a `SlideContainer`, `liftAnchor` naming where the closing comes back
178
- to; what an opening costs and where the time goes;
178
+ to; `animation={{ open, close: "lifting" }}` for a popup that did not come out of what it
179
+ lands in, the landing rendered by `onClose`; what an opening costs and where
180
+ the time goes;
179
181
  the wall at half strength on the frame before the movement. Read before
180
182
  giving a `Dialog` or a `Picker` `animation="lifting"`, or before measuring
181
183
  why one opens slowly.
@@ -5,7 +5,9 @@ for one situation: the thing the user pressed is the thing the popup shows,
5
5
  brought to the front to be looked at or written in. A card in a feed becomes
6
6
  its edit sheet; a drawing in a corner becomes the drawing full width. The page
7
7
  recedes behind a wall, the box leaves its place, travels and grows, and comes
8
- back into its place on close.
8
+ back into its place on close — or, with `animation={{ open: "scaling", close: "lifting" }}`, only
9
+ lands somewhere on close (see [lifting on the way back
10
+ only](#lifting-on-the-way-back-only)).
9
11
 
10
12
  It is not a way to open a dialog with a nicer entrance. A dialog that shows
11
13
  something else than what was pressed — a menu, a confirmation, a form the
@@ -19,6 +21,7 @@ and everything below follows from that one fact.
19
21
  - [The lifted node paints itself](#the-lifted-node-paints-itself)
20
22
  - [Same width, or a wider box](#same-width-or-a-wider-box)
21
23
  - [A row of cards: one popup that walks](#a-row-of-cards-one-popup-that-walks)
24
+ - [Lifting on the way back only](#lifting-on-the-way-back-only)
22
25
  - [What it costs, and where the time goes](#what-it-costs-and-where-the-time-goes)
23
26
  - [The wall, and the frame before the movement](#the-wall-and-the-frame-before-the-movement)
24
27
  - [What the browser does around it](#what-the-browser-does-around-it)
@@ -242,12 +245,89 @@ bound to is the shortest way to say it, the row's tiles carrying the matching
242
245
  ids. Left out, the box comes back where it came from, which is right exactly
243
246
  as long as nothing walked.
244
247
 
248
+ When the walk signal is the address's — the popup's `signal`, so the sheet
249
+ comes back open on the same card after leaving the page (see
250
+ [popup_open.md](./popup_open.md#signal--the-app-holds-it-both-ways)) — a close
251
+ that comes through the address, the back button, empties it before the popup
252
+ knows it is closing, and a name built from it at that render says nothing:
253
+ the box flies home into the first tile. Name the tile from the last key the
254
+ walk held — a ref written while the signal holds one — not from the signal
255
+ itself.
256
+
245
257
  **A press on the surface that dismisses is `data-navi-popup-outside`.** Marking
246
258
  the see-through box as backdrop (see
247
259
  [popup_backdrop.md](./popup_backdrop.md)) is read on the press itself. A close
248
260
  written by hand on a click has to tell a click from the end of a swipe — and
249
261
  that guard is the sign the marker was missed.
250
262
 
263
+ ## Lifting on the way back only
264
+
265
+ Sometimes the opening is not a lift and the closing is. A banner says "your
266
+ level is computed"; pressing it opens a full-screen reveal, the crest big in a
267
+ halo; collecting it sends the crest down into its place on the rank plate,
268
+ which replaces the banner at that moment. The banner is not the reveal, so
269
+ nothing morphs on the way in. But on the way out one box does travel into
270
+ another, and that other box did not exist when the reveal opened.
271
+
272
+ ```jsx
273
+ <Dialog
274
+ animation={{ open: "scaling", close: "lifting" }}
275
+ liftAnchor="profile_level_crest"
276
+ onClose={(e) => {
277
+ if (e.detail.requester?.id === "level_collect") {
278
+ levelRevealedSignal.value = true; // renders the plate, and its crest
279
+ }
280
+ }}
281
+ >
282
+ <span data-lift>
283
+ <RankCrest size="220px" />
284
+ </span>
285
+ <Button id="level_collect" command="--navi-close" variant="bare">
286
+ Collect
287
+ </Button>
288
+ </Dialog>
289
+ ```
290
+
291
+ **The opening is whatever `open` says** (`"auto"` included). Only the close lifts, so none of
292
+ what a lifting opening brings is there: no wait for `data-lift`, no opaque
293
+ wall. `data-lift` is read at the close alone.
294
+
295
+ **The box it lands in can be rendered by the close.** `liftAnchor` is read
296
+ once the close has been made, `onClose` included, inside the transition. A
297
+ state written in `onClose` has rendered by the time the landing is looked up,
298
+ so the landing box can come from that state. This is also the one place where
299
+ that state can be written: before the close, the reveal would disappear from
300
+ the picture being left; after it, the picture of the arrival is already taken.
301
+ Do not write it by hand around the dialog either. Unmounting the dialog with
302
+ the component that holds it takes it off screen without a close, and the lift
303
+ never happens.
304
+
305
+ **It is waited for, briefly.** When `liftAnchor` names nothing yet, navi waits
306
+ for it to appear, up to 300 ms, before it takes the new picture. The screen is
307
+ frozen on the reveal meanwhile, so this covers a render and not a fetch: the
308
+ landing must be drawable from what the page already holds. Past the wait, the
309
+ dialog closes without landing (its picture fades out) and dev warns.
310
+
311
+ **Tell the collecting close from the others.** Escape, the back button and a
312
+ press on the wall also close the dialog, and they usually mean "not now" rather
313
+ than "collect". `onClose` receives who asked (`e.detail.requester`, the button
314
+ of a `--navi-close`). Only the close that collects writes the state, and the
315
+ others close the dialog without writing it, back into the element it opened from.
316
+
317
+ **The dialog may go away with the state.** A reveal shown in place of the
318
+ plate usually lives in the same branch as the banner and is unmounted by the
319
+ state it writes. That is fine: the picture of the reveal was taken before the
320
+ close.
321
+
322
+ **The landing box is the crest's box**, for the same reason the trigger's box
323
+ is the card's box (see [above](#the-triggers-box-is-the-cards-box)): the id
324
+ goes on the element that is exactly the small crest, not on the plate around
325
+ it.
326
+
327
+ **The opening's own exit does not play.** While a closing lift runs, the
328
+ dialog's transitions are off. `scaling`'s exit would keep the dialog painted
329
+ into the picture of the state it closes into.
330
+
251
331
  ## What it costs, and where the time goes
252
332
 
253
333
  Measured at CPU ×6 on the demo bench (`12_picker_card_demo.html#lift-bench`),
@@ -875,6 +875,14 @@ the id from the signal, a card's press writes it, and the popup never writes
875
875
  over it: opening writes `true` only into a signal that reads closed, closing
876
876
  writes `undefined` (or `false`, where the signal held `true`).
877
877
 
878
+ When the popup is opened ON a card (`<Button command="--navi-open" value={id}>`),
879
+ `onOpen` is where the id is written: it runs before the popup writes its own
880
+ open, and a signal that already reads open is left as it is — the address holds
881
+ the card, never `true`. With the route's search-param `stateSignal` as the walk
882
+ signal, that is how [a row of
883
+ cards](./popup_lift.md#a-row-of-cards-one-popup-that-walks) survives leaving
884
+ the page: the address names the card, and the sheet reopens on it.
885
+
878
886
  ```jsx
879
887
  <SidePanel signal={errorOpenSignal} side="right">
880
888
  <ErrorPanel /> {/* reads errorOpenSignal.value to know which card */}
@@ -892,8 +900,13 @@ finds the popup as it was, and so does a reload. `true` stores it under the
892
900
  popup's own `id`; a string names the key instead. `{ type: "push" }` makes the
893
901
  opening an entry of its own — the back button then closes the popup rather than
894
902
  leaving the screen, and the cancel takes back with it whatever was written to
895
- the url while it was open. A `Picker` needs none of this: its popup's open state
896
- is nav state by construction.
903
+ the url while it was open. A `Picker` given an `id` needs none of this: its
904
+ popup's open state is nav state by construction, under that id, and in dialog
905
+ mode the opening is an entry of its own. Without an `id` the key is a generated
906
+ one, which names one mount: the page left with the picker open and come back to
907
+ is a new mount with a new id, and the state stays in the entry with nothing to
908
+ read it — navi warns when a mount finds such a key. A picker whose popup leads
909
+ somewhere, a link inside it, has an `id`.
897
910
 
898
911
  The two meet when the signal IS a route's: a search-param `stateSignal` given to
899
912
  `signal` puts the open state in the address itself, where a link can point at
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/navi",
3
- "version": "0.29.364",
3
+ "version": "0.29.366",
4
4
  "type": "module",
5
5
  "description": "Library of components including navigation to create frontend applications",
6
6
  "repository": {