@jsenv/navi 0.29.36 → 0.29.37

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.
@@ -288,6 +288,83 @@ land: (event) => {
288
288
  };
289
289
  ```
290
290
 
291
+ #### Naming what travels
292
+
293
+ **The copy is already named, and it is the copy that does the visible travel.**
294
+ The wrapper carrying it answers to `navi-drag-clone-wrapper`, the copy inside it
295
+ to `navi-drag-clone`, and `syncCloneWithDropTarget` moves that box onto the
296
+ destination inside the callback — so the piece the hand let go of slides to its
297
+ place whether the application names anything or not. What is left to name is the
298
+ OTHER one: the piece that was standing there and has to go the other way.
299
+
300
+ **And the original is hidden for the whole landing**, not only for the drag: it
301
+ wears `navi-drag-clone-source` (`visibility: hidden`) until the promise returned
302
+ by `land` settles, because the copy stands for it until then. An element that
303
+ paints nothing is still captured — the group gets an empty image — so a name put
304
+ on the source is a group fading in from nothing, or out into nothing, over the
305
+ copy that is doing the real travel. That is what a swap looks like when it fades
306
+ instead of sliding.
307
+
308
+ Both follow from one rule: **a name rides the element that MOVES, and that
309
+ element has to be visible at both ends of the transition.** Where the places are
310
+ fixed and the pieces are drawn into them, nothing moves — two boxes change
311
+ content, and hand-writing a name on each so that it "follows the player" names a
312
+ journey whose start or end is the hidden source. Key the piece by WHO it is and
313
+ let it be re-parented:
314
+
315
+ ```jsx
316
+ {places.map((place) => {
317
+ const playerId = lineupAt(place.id);
318
+ // Keyed by the player: the same DOM node walks from one place to the other,
319
+ // so the browser has something to morph — and the displaced one was visible
320
+ // before and is visible after.
321
+ return <Piece key={playerId} id={playerId} style={boxOf(place)} … />;
322
+ })}
323
+ ```
324
+
325
+ **The name is written twice, and neither write is redundant.** The old state is
326
+ captured the moment `startViewTransition` is called, before any render, so the
327
+ name must be on the DOM by then — written by hand, on the element. The render
328
+ happening inside the callback would then put the plain name straight back, so
329
+ the same name must also come from state. Clear that state when `finished`
330
+ resolves: a name left behind is claimed twice by the next transition, and that
331
+ one is dropped for it.
332
+
333
+ ```jsx
334
+ land: (event) => {
335
+ const { fromId, toId, syncCloneWithDropTarget } = event.detail;
336
+ const displacedId = playerAt(toId);
337
+ const roles = { [fromId]: OVER, [displacedId]: UNDER };
338
+ for (const id of Object.keys(roles)) {
339
+ document.getElementById(id).style.viewTransitionName = roles[id];
340
+ }
341
+ const transition = document.startViewTransition(() => {
342
+ syncCloneWithDropTarget(document.getElementById(displacedId));
343
+ setSwapRoles(roles); // the render inside the callback keeps the names
344
+ setLineup((previous) => swapPlaces(previous, fromId, toId));
345
+ });
346
+ transition.finished.then(() => setSwapRoles(null));
347
+ return transition.finished;
348
+ };
349
+ ```
350
+
351
+ The roles are names because a `::view-transition` pseudo can be selected by name
352
+ and by nothing else — which is also how one of the two is told to pass over the
353
+ other, and how the travel is given a length worth a card crossing a board rather
354
+ than a menu opening. Both the group and the image pair are addressed: the morph
355
+ lives in one, anything a style adds rides in the other.
356
+
357
+ ```css
358
+ ::view-transition-group(swap_over) {
359
+ z-index: 20;
360
+ }
361
+ ::view-transition-group(swap_over),
362
+ ::view-transition-image-pair(swap_over) {
363
+ animation-duration: 420ms;
364
+ animation-timing-function: ease-in-out;
365
+ }
366
+ ```
367
+
291
368
  The hint follows what a place is: a line drawn in the gap for `reorder`, the
292
369
  place itself lit up for `land`. Both are drawn inside the carried element's
293
370
  parent, so the variables dressing them are read from the list or the board and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/navi",
3
- "version": "0.29.36",
3
+ "version": "0.29.37",
4
4
  "type": "module",
5
5
  "description": "Library of components including navigation to create frontend applications",
6
6
  "repository": {