@jsenv/navi 0.29.35 → 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.
- package/dist/jsenv_navi.js +459 -60
- package/dist/jsenv_navi.js.map +27 -16
- package/docs/interactions.md +77 -0
- package/package.json +2 -2
package/docs/interactions.md
CHANGED
|
@@ -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.
|
|
3
|
+
"version": "0.29.37",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Library of components including navigation to create frontend applications",
|
|
6
6
|
"repository": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"prepublishOnly": "npm run build"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@jsenv/dom": "0.17.
|
|
32
|
+
"@jsenv/dom": "0.17.12",
|
|
33
33
|
"@jsenv/humanize": "1.7.8",
|
|
34
34
|
"@jsenv/validity": "0.4.2"
|
|
35
35
|
},
|