@jsenv/navi 0.29.66 → 0.29.67
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 +442 -153
- package/dist/jsenv_navi.js.map +85 -50
- package/docs/route_transitions.md +71 -13
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -38399,6 +38399,93 @@ const takeoverRoutingRenderingHold = () => {
|
|
|
38399
38399
|
return release;
|
|
38400
38400
|
};
|
|
38401
38401
|
|
|
38402
|
+
/**
|
|
38403
|
+
* The window two pages are seen through while one replaces the other, measured
|
|
38404
|
+
* once and published for the length of the movement.
|
|
38405
|
+
*
|
|
38406
|
+
* Both ways of moving from one route to another need the same six numbers, so
|
|
38407
|
+
* they are written under the same names and read by the same CSS formulas —
|
|
38408
|
+
* `route_travel.jsx` for a row a finger pushes, `route_transition.jsx` for a
|
|
38409
|
+
* relation between two pages. Only one of them ever plays at a time (there is
|
|
38410
|
+
* one view transition per document), which is what lets them share the names.
|
|
38411
|
+
*
|
|
38412
|
+
* What the numbers are for:
|
|
38413
|
+
*
|
|
38414
|
+
* - **the box the movement happens in**, in the WINDOW's coordinates. The
|
|
38415
|
+
* pictures of a transition are drawn in the top layer, above everything, so
|
|
38416
|
+
* no overflow of the document reaches them: where to cut them can only be
|
|
38417
|
+
* said from outside the document, and this is where that outside is known.
|
|
38418
|
+
* - **the height it is held at**, the taller of the two states. Left to the
|
|
38419
|
+
* browser the window's height animates from one to the other, and a window
|
|
38420
|
+
* that changes size under the pictures cuts the page being left from the
|
|
38421
|
+
* bottom, progressively. It does end up at the arriving height, and that is
|
|
38422
|
+
* right; what must not happen is the user watching it get there.
|
|
38423
|
+
* - **where the page being left WAS**, which is not where the window stands:
|
|
38424
|
+
* the two states are at the same place in the layout without being at the
|
|
38425
|
+
* same place in the window — one page is scrolled and the other is not.
|
|
38426
|
+
* Drawn at the window's own corner, the page being left would be seen
|
|
38427
|
+
* jumping to its top before it begins to leave.
|
|
38428
|
+
*
|
|
38429
|
+
* Only the measuring needs JS, and only for the one moment both states exist:
|
|
38430
|
+
* the page arriving is in the DOM and the transition has not started playing.
|
|
38431
|
+
* Everything DERIVED from these numbers — the band a fixed bar covers, how far
|
|
38432
|
+
* a page travels — is derived in CSS, so the application's own numbers (the
|
|
38433
|
+
* room its bars give back, see layout/safe_area.js) take part in it.
|
|
38434
|
+
*/
|
|
38435
|
+
|
|
38436
|
+
const WINDOW_TOP_PROPERTY = "--navi-transition-window-top";
|
|
38437
|
+
const WINDOW_LEFT_PROPERTY = "--navi-transition-window-left";
|
|
38438
|
+
const WINDOW_WIDTH_PROPERTY = "--navi-transition-window-width";
|
|
38439
|
+
const WINDOW_HEIGHT_PROPERTY = "--navi-transition-window-height";
|
|
38440
|
+
const WINDOW_OLD_TOP_PROPERTY = "--navi-transition-window-old-top";
|
|
38441
|
+
const WINDOW_OLD_LEFT_PROPERTY = "--navi-transition-window-old-left";
|
|
38442
|
+
const WINDOW_PROPERTIES = [
|
|
38443
|
+
WINDOW_TOP_PROPERTY,
|
|
38444
|
+
WINDOW_LEFT_PROPERTY,
|
|
38445
|
+
WINDOW_WIDTH_PROPERTY,
|
|
38446
|
+
WINDOW_HEIGHT_PROPERTY,
|
|
38447
|
+
WINDOW_OLD_TOP_PROPERTY,
|
|
38448
|
+
WINDOW_OLD_LEFT_PROPERTY,
|
|
38449
|
+
];
|
|
38450
|
+
|
|
38451
|
+
// Whose numbers are currently published. The window belongs to the movement
|
|
38452
|
+
// that measured it, and only that one may take it down: a movement ending
|
|
38453
|
+
// after another has replaced it must not wipe numbers the new one is standing
|
|
38454
|
+
// on.
|
|
38455
|
+
let windowOwner = null;
|
|
38456
|
+
|
|
38457
|
+
const holdTransitionWindow = (owner, element, rectBefore) => {
|
|
38458
|
+
const rectAfter = element.getBoundingClientRect();
|
|
38459
|
+
// It cannot be measured from one side alone: a page arriving shorter than
|
|
38460
|
+
// the one it replaces would cut the one leaving, a page arriving taller
|
|
38461
|
+
// would be cut itself.
|
|
38462
|
+
const height =
|
|
38463
|
+
rectBefore.height > rectAfter.height ? rectBefore.height : rectAfter.height;
|
|
38464
|
+
windowOwner = owner;
|
|
38465
|
+
const { style } = document.documentElement;
|
|
38466
|
+
style.setProperty(WINDOW_TOP_PROPERTY, `${rectAfter.top}px`);
|
|
38467
|
+
style.setProperty(WINDOW_LEFT_PROPERTY, `${rectAfter.left}px`);
|
|
38468
|
+
style.setProperty(WINDOW_WIDTH_PROPERTY, `${rectAfter.width}px`);
|
|
38469
|
+
style.setProperty(WINDOW_HEIGHT_PROPERTY, `${height}px`);
|
|
38470
|
+
style.setProperty(WINDOW_OLD_TOP_PROPERTY, `${rectBefore.top}px`);
|
|
38471
|
+
style.setProperty(WINDOW_OLD_LEFT_PROPERTY, `${rectBefore.left}px`);
|
|
38472
|
+
};
|
|
38473
|
+
|
|
38474
|
+
// The live layout takes the box back. A discontinuity by construction — the
|
|
38475
|
+
// window stands at the held height, the box is at its own — and an invisible
|
|
38476
|
+
// one: the page arriving is fully in place, and the strip below it that the
|
|
38477
|
+
// window still covers shows the page leaving only while it is still on screen.
|
|
38478
|
+
const releaseTransitionWindow = (owner) => {
|
|
38479
|
+
if (owner !== windowOwner) {
|
|
38480
|
+
return;
|
|
38481
|
+
}
|
|
38482
|
+
windowOwner = null;
|
|
38483
|
+
const { style } = document.documentElement;
|
|
38484
|
+
for (const property of WINDOW_PROPERTIES) {
|
|
38485
|
+
style.removeProperty(property);
|
|
38486
|
+
}
|
|
38487
|
+
};
|
|
38488
|
+
|
|
38402
38489
|
installImportMetaCssBuild(import.meta);/**
|
|
38403
38490
|
* How two routes move against each other, said one relation at a time —
|
|
38404
38491
|
* without putting them in a row, and without a box in the tree.
|
|
@@ -38473,14 +38560,158 @@ const ROUTE_TRAVEL_ATTRIBUTE = "data-navi-route-travel";
|
|
|
38473
38560
|
// or the marked area. The guard keeps the two exclusive — with an area marked,
|
|
38474
38561
|
// the root pictures must NOT move (they carry the whole viewport, blank bands
|
|
38475
38562
|
// included).
|
|
38476
|
-
|
|
38477
|
-
|
|
38478
|
-
|
|
38479
|
-
|
|
38480
|
-
|
|
38481
|
-
|
|
38482
|
-
|
|
38483
|
-
|
|
38563
|
+
|
|
38564
|
+
const css$T = /* css */`
|
|
38565
|
+
/* The marked region is a picture of its own during every view transition of
|
|
38566
|
+
the document — which is what keeps it out of the root snapshot, where its
|
|
38567
|
+
place would otherwise be blank. */
|
|
38568
|
+
[data-navi-route-transition-area] {
|
|
38569
|
+
view-transition-name: navi-route-transition;
|
|
38570
|
+
}
|
|
38571
|
+
|
|
38572
|
+
/* Only while a transition of OURS is playing: everything below changes how
|
|
38573
|
+
the document animates, and the document belongs to the application the
|
|
38574
|
+
rest of the time. */
|
|
38575
|
+
:root[data-navi-route-transition] {
|
|
38576
|
+
/* With an area marked, the page AROUND it is not taken as a picture — so
|
|
38577
|
+
exactly one of the two names below exists at a time, and the movements
|
|
38578
|
+
can be written once for both. It is also what a fixed bar wants: a
|
|
38579
|
+
captured element is not painted where it stands and cannot be pointed
|
|
38580
|
+
at either, so a bar photographed with the document is dead for the
|
|
38581
|
+
length of every transition. Left live, it answers as it always did, and
|
|
38582
|
+
nothing shows through where the pages are — the two pictures cover the
|
|
38583
|
+
area's rectangle between them at every moment. Anything around that must
|
|
38584
|
+
ANIMATE rather than stand still gets a view-transition-name of its own,
|
|
38585
|
+
and the browser moves it on the same clock. */
|
|
38586
|
+
&[data-navi-route-transition-target="area"] {
|
|
38587
|
+
view-transition-name: none;
|
|
38588
|
+
}
|
|
38589
|
+
|
|
38590
|
+
&::view-transition-old(root),
|
|
38591
|
+
&::view-transition-new(root),
|
|
38592
|
+
&::view-transition-old(navi-route-transition),
|
|
38593
|
+
&::view-transition-new(navi-route-transition) {
|
|
38594
|
+
/* Written on the direction alone, so a relation with no type — the
|
|
38595
|
+
browser's cross-fade — answers to it like every other. */
|
|
38596
|
+
animation-duration: var(--navi-route-transition-duration, 300ms);
|
|
38597
|
+
}
|
|
38598
|
+
|
|
38599
|
+
/* The window the pages are seen through, when it is an area. Nothing here
|
|
38600
|
+
names \`root\`: the root picture IS the window when the whole document
|
|
38601
|
+
travels, already the size of the screen and already cut by it. */
|
|
38602
|
+
&::view-transition-group(navi-route-transition),
|
|
38603
|
+
&::view-transition-image-pair(navi-route-transition) {
|
|
38604
|
+
/* The pages are cut at the edge of the area they move in. Said HERE and
|
|
38605
|
+
nowhere else: these pictures are drawn in the top layer, so no
|
|
38606
|
+
overflow on any element of the document can reach them. */
|
|
38607
|
+
overflow: clip;
|
|
38608
|
+
}
|
|
38609
|
+
&::view-transition-group(navi-route-transition) {
|
|
38610
|
+
/* Held still for the whole transition, at the taller of the two states,
|
|
38611
|
+
and standing where the area stands (see transition_window.js). Held by
|
|
38612
|
+
dropping the group's animation rather than by winning against it with
|
|
38613
|
+
!important — which also drops its position animation, fine for an area
|
|
38614
|
+
that stays in the same place from one page to the next. */
|
|
38615
|
+
height: var(--navi-transition-window-height);
|
|
38616
|
+
animation-name: none;
|
|
38617
|
+
|
|
38618
|
+
/* Cut at the safe area, on top of being cut at the area's own box. The
|
|
38619
|
+
pictures are drawn in the top layer, so they cover a fixed bar as
|
|
38620
|
+
easily as anything else — and the area runs UNDER the bars by design:
|
|
38621
|
+
that is what a fixed bar is for, and what the room it gives back is
|
|
38622
|
+
for. An area taller than the screen therefore ends below the bottom
|
|
38623
|
+
bar, and a scrolled one starts above the top bar, so the movement
|
|
38624
|
+
would be watched painting over them for its whole length.
|
|
38625
|
+
|
|
38626
|
+
The band left free is the app's own safe area (see
|
|
38627
|
+
layout/safe_area.js) — every kind of furniture at once, not the bars
|
|
38628
|
+
alone, and read rather than asked for, so one that grows, shrinks or
|
|
38629
|
+
unmounts mid-transition is followed without anything being told. What
|
|
38630
|
+
the window cannot know is only where it itself stands, and that is the
|
|
38631
|
+
measured half. */
|
|
38632
|
+
--navi-route-transition-clip-top: max(
|
|
38633
|
+
0px,
|
|
38634
|
+
var(--navi-safe-area-inset-top) - var(--navi-transition-window-top)
|
|
38635
|
+
);
|
|
38636
|
+
--navi-route-transition-clip-left: max(
|
|
38637
|
+
0px,
|
|
38638
|
+
var(--navi-safe-area-inset-left) - var(--navi-transition-window-left)
|
|
38639
|
+
);
|
|
38640
|
+
--navi-route-transition-clip-bottom: max(
|
|
38641
|
+
0px,
|
|
38642
|
+
var(--navi-transition-window-top) +
|
|
38643
|
+
var(--navi-transition-window-height) +
|
|
38644
|
+
var(--navi-safe-area-inset-bottom) - 100dvh
|
|
38645
|
+
);
|
|
38646
|
+
--navi-route-transition-clip-right: max(
|
|
38647
|
+
0px,
|
|
38648
|
+
var(--navi-transition-window-left) +
|
|
38649
|
+
var(--navi-transition-window-width) +
|
|
38650
|
+
var(--navi-safe-area-inset-right) - 100dvw
|
|
38651
|
+
);
|
|
38652
|
+
clip-path: inset(
|
|
38653
|
+
var(--navi-route-transition-clip-top)
|
|
38654
|
+
var(--navi-route-transition-clip-right)
|
|
38655
|
+
var(--navi-route-transition-clip-bottom)
|
|
38656
|
+
var(--navi-route-transition-clip-left)
|
|
38657
|
+
);
|
|
38658
|
+
|
|
38659
|
+
/* How far a page travels: the WINDOW it is seen through, not its own
|
|
38660
|
+
size. A page is as tall as its content — several screens of it — and a
|
|
38661
|
+
movement measured on the picture would send it thousands of pixels
|
|
38662
|
+
away, off screen for most of the transition and flying past at the
|
|
38663
|
+
end. What one page crossing another means is one window's worth of
|
|
38664
|
+
movement, whatever the pages are made of. Inherited by the pictures,
|
|
38665
|
+
which is where it is used (see the keyframes). */
|
|
38666
|
+
--navi-route-transition-travel-x: calc(
|
|
38667
|
+
var(--navi-transition-window-width) - var(
|
|
38668
|
+
--navi-route-transition-clip-left
|
|
38669
|
+
) - var(--navi-route-transition-clip-right)
|
|
38670
|
+
);
|
|
38671
|
+
--navi-route-transition-travel-y: calc(
|
|
38672
|
+
var(--navi-transition-window-height) - var(
|
|
38673
|
+
--navi-route-transition-clip-top
|
|
38674
|
+
) - var(--navi-route-transition-clip-bottom)
|
|
38675
|
+
);
|
|
38676
|
+
}
|
|
38677
|
+
&::view-transition-old(navi-route-transition) {
|
|
38678
|
+
/* Where the area WAS on screen, which is not where the window stands
|
|
38679
|
+
(see transition_window.js). Offset here rather than by \`translate\`,
|
|
38680
|
+
which the movement itself uses. */
|
|
38681
|
+
top: calc(
|
|
38682
|
+
var(--navi-transition-window-old-top) - var(
|
|
38683
|
+
--navi-transition-window-top
|
|
38684
|
+
)
|
|
38685
|
+
);
|
|
38686
|
+
left: calc(
|
|
38687
|
+
var(--navi-transition-window-old-left) - var(
|
|
38688
|
+
--navi-transition-window-left
|
|
38689
|
+
)
|
|
38690
|
+
);
|
|
38691
|
+
}
|
|
38692
|
+
|
|
38693
|
+
/* ------------------------------------------------------------------
|
|
38694
|
+
The movements. One of \`root\` and \`navi-route-transition\` exists at a
|
|
38695
|
+
time (see the opt-out above), so each is written for both.
|
|
38696
|
+
------------------------------------------------------------------ */
|
|
38697
|
+
&[data-navi-route-transition-type="slide-x"],
|
|
38698
|
+
&[data-navi-route-transition-type="slide-y"],
|
|
38699
|
+
&[data-navi-route-transition-type="cover-x"],
|
|
38700
|
+
&[data-navi-route-transition-type="cover-y"] {
|
|
38701
|
+
&::view-transition-old(root),
|
|
38702
|
+
&::view-transition-new(root),
|
|
38703
|
+
&::view-transition-old(navi-route-transition),
|
|
38704
|
+
&::view-transition-new(navi-route-transition) {
|
|
38705
|
+
width: auto;
|
|
38706
|
+
/* Each picture at the size it was taken at: a page is not resized by
|
|
38707
|
+
the page it crosses. The picture is as wide as the box the browser
|
|
38708
|
+
gives it — the arriving one's — so a page leaving a narrower box (a
|
|
38709
|
+
scrollbar appeared, a side panel closed) would be seen zooming over
|
|
38710
|
+
the length of the movement. Left to the untyped cross-fade, where
|
|
38711
|
+
scaling one picture into the other is the whole idea. */
|
|
38712
|
+
height: auto;
|
|
38713
|
+
object-fit: none;
|
|
38714
|
+
object-position: top left;
|
|
38484
38715
|
/* The default cross-fade, dropped: two pages sliding past each other
|
|
38485
38716
|
are two solid things, and seeing through one to the other says they
|
|
38486
38717
|
are the same page changing its mind. */
|
|
@@ -38489,183 +38720,177 @@ const movementsCSS = (name, guard) => /* css */`
|
|
|
38489
38720
|
animation-fill-mode: both;
|
|
38490
38721
|
}
|
|
38491
38722
|
}
|
|
38492
|
-
|
|
38493
|
-
|
|
38494
|
-
|
|
38723
|
+
|
|
38724
|
+
&[data-navi-route-transition-type="slide-x"] {
|
|
38725
|
+
&[data-navi-route-transition="forward"] {
|
|
38726
|
+
&::view-transition-old(root),
|
|
38727
|
+
&::view-transition-old(navi-route-transition) {
|
|
38495
38728
|
animation-name: navi-route-transition-leave-towards-start;
|
|
38496
38729
|
}
|
|
38497
|
-
&::view-transition-new(
|
|
38730
|
+
&::view-transition-new(root),
|
|
38731
|
+
&::view-transition-new(navi-route-transition) {
|
|
38498
38732
|
animation-name: navi-route-transition-enter-from-end;
|
|
38499
38733
|
}
|
|
38500
38734
|
}
|
|
38501
|
-
&[
|
|
38502
|
-
&::view-transition-old(
|
|
38735
|
+
&[data-navi-route-transition="back"] {
|
|
38736
|
+
&::view-transition-old(root),
|
|
38737
|
+
&::view-transition-old(navi-route-transition) {
|
|
38503
38738
|
animation-name: navi-route-transition-leave-towards-end;
|
|
38504
38739
|
}
|
|
38505
|
-
&::view-transition-new(
|
|
38740
|
+
&::view-transition-new(root),
|
|
38741
|
+
&::view-transition-new(navi-route-transition) {
|
|
38506
38742
|
animation-name: navi-route-transition-enter-from-start;
|
|
38507
38743
|
}
|
|
38508
38744
|
}
|
|
38509
38745
|
}
|
|
38746
|
+
|
|
38510
38747
|
/* The same four movements, along the other axis: the start of a column is
|
|
38511
38748
|
its top, so going forward there is the page rising and the next one
|
|
38512
38749
|
coming up from below. */
|
|
38513
|
-
&[
|
|
38514
|
-
&[
|
|
38515
|
-
&::view-transition-old(
|
|
38750
|
+
&[data-navi-route-transition-type="slide-y"] {
|
|
38751
|
+
&[data-navi-route-transition="forward"] {
|
|
38752
|
+
&::view-transition-old(root),
|
|
38753
|
+
&::view-transition-old(navi-route-transition) {
|
|
38516
38754
|
animation-name: navi-route-transition-leave-towards-top;
|
|
38517
38755
|
}
|
|
38518
|
-
&::view-transition-new(
|
|
38756
|
+
&::view-transition-new(root),
|
|
38757
|
+
&::view-transition-new(navi-route-transition) {
|
|
38519
38758
|
animation-name: navi-route-transition-enter-from-bottom;
|
|
38520
38759
|
}
|
|
38521
38760
|
}
|
|
38522
|
-
&[
|
|
38523
|
-
&::view-transition-old(
|
|
38761
|
+
&[data-navi-route-transition="back"] {
|
|
38762
|
+
&::view-transition-old(root),
|
|
38763
|
+
&::view-transition-old(navi-route-transition) {
|
|
38524
38764
|
animation-name: navi-route-transition-leave-towards-bottom;
|
|
38525
38765
|
}
|
|
38526
|
-
&::view-transition-new(
|
|
38766
|
+
&::view-transition-new(root),
|
|
38767
|
+
&::view-transition-new(navi-route-transition) {
|
|
38527
38768
|
animation-name: navi-route-transition-enter-from-top;
|
|
38528
38769
|
}
|
|
38529
38770
|
}
|
|
38530
38771
|
}
|
|
38772
|
+
|
|
38531
38773
|
/* One page over the other, the way a sheet covers a desk: the page
|
|
38532
38774
|
arriving slides in ON TOP of one that does not move, and going back it
|
|
38533
38775
|
slides off, uncovering it. The still page is animated all the same — to
|
|
38534
38776
|
a keyframe that goes nowhere — because left to the browser it would
|
|
38535
38777
|
fade. */
|
|
38536
|
-
&[
|
|
38537
|
-
&[
|
|
38538
|
-
&::view-transition-old(
|
|
38778
|
+
&[data-navi-route-transition-type="cover-x"] {
|
|
38779
|
+
&[data-navi-route-transition="forward"] {
|
|
38780
|
+
&::view-transition-old(root),
|
|
38781
|
+
&::view-transition-old(navi-route-transition) {
|
|
38539
38782
|
animation-name: navi-route-transition-still;
|
|
38540
38783
|
}
|
|
38541
|
-
&::view-transition-new(
|
|
38784
|
+
&::view-transition-new(root),
|
|
38785
|
+
&::view-transition-new(navi-route-transition) {
|
|
38542
38786
|
animation-name: navi-route-transition-enter-from-end;
|
|
38543
38787
|
}
|
|
38544
38788
|
}
|
|
38545
|
-
&[
|
|
38546
|
-
&::view-transition-old(
|
|
38789
|
+
&[data-navi-route-transition="back"] {
|
|
38790
|
+
&::view-transition-old(root),
|
|
38791
|
+
&::view-transition-old(navi-route-transition) {
|
|
38547
38792
|
/* The page leaving is the cover: it must slide off ABOVE the one it
|
|
38548
|
-
uncovers, against the browser's default of drawing the new page
|
|
38549
|
-
|
|
38793
|
+
uncovers, against the browser's default of drawing the new page on
|
|
38794
|
+
top. */
|
|
38550
38795
|
z-index: 1;
|
|
38551
38796
|
animation-name: navi-route-transition-leave-towards-end;
|
|
38552
38797
|
}
|
|
38553
|
-
&::view-transition-new(
|
|
38798
|
+
&::view-transition-new(root),
|
|
38799
|
+
&::view-transition-new(navi-route-transition) {
|
|
38554
38800
|
animation-name: navi-route-transition-still;
|
|
38555
38801
|
}
|
|
38556
38802
|
}
|
|
38557
38803
|
}
|
|
38558
|
-
&[
|
|
38559
|
-
&[
|
|
38560
|
-
&::view-transition-old(
|
|
38804
|
+
&[data-navi-route-transition-type="cover-y"] {
|
|
38805
|
+
&[data-navi-route-transition="forward"] {
|
|
38806
|
+
&::view-transition-old(root),
|
|
38807
|
+
&::view-transition-old(navi-route-transition) {
|
|
38561
38808
|
animation-name: navi-route-transition-still;
|
|
38562
38809
|
}
|
|
38563
|
-
&::view-transition-new(
|
|
38810
|
+
&::view-transition-new(root),
|
|
38811
|
+
&::view-transition-new(navi-route-transition) {
|
|
38564
38812
|
animation-name: navi-route-transition-enter-from-bottom;
|
|
38565
38813
|
}
|
|
38566
38814
|
}
|
|
38567
|
-
&[
|
|
38568
|
-
&::view-transition-old(
|
|
38815
|
+
&[data-navi-route-transition="back"] {
|
|
38816
|
+
&::view-transition-old(root),
|
|
38817
|
+
&::view-transition-old(navi-route-transition) {
|
|
38569
38818
|
z-index: 1;
|
|
38570
38819
|
animation-name: navi-route-transition-leave-towards-bottom;
|
|
38571
38820
|
}
|
|
38572
|
-
&::view-transition-new(
|
|
38821
|
+
&::view-transition-new(root),
|
|
38822
|
+
&::view-transition-new(navi-route-transition) {
|
|
38573
38823
|
animation-name: navi-route-transition-still;
|
|
38574
38824
|
}
|
|
38575
38825
|
}
|
|
38576
38826
|
}
|
|
38827
|
+
|
|
38577
38828
|
/* Going deeper is coming closer: the page arriving lands from slightly too
|
|
38578
38829
|
big, and going back it is the page leaving that grows away. The other
|
|
38579
38830
|
side keeps the browser's own fade under it. */
|
|
38580
|
-
&[
|
|
38581
|
-
&::view-transition-old(
|
|
38582
|
-
&::view-transition-new(
|
|
38831
|
+
&[data-navi-route-transition-type="zoom"] {
|
|
38832
|
+
&::view-transition-old(root),
|
|
38833
|
+
&::view-transition-new(root),
|
|
38834
|
+
&::view-transition-old(navi-route-transition),
|
|
38835
|
+
&::view-transition-new(navi-route-transition) {
|
|
38583
38836
|
animation-fill-mode: both;
|
|
38584
38837
|
}
|
|
38585
|
-
&[
|
|
38586
|
-
&::view-transition-new(
|
|
38838
|
+
&[data-navi-route-transition="forward"] {
|
|
38839
|
+
&::view-transition-new(root),
|
|
38840
|
+
&::view-transition-new(navi-route-transition) {
|
|
38587
38841
|
animation-name: navi-route-transition-zoom-in;
|
|
38588
38842
|
}
|
|
38589
38843
|
}
|
|
38590
|
-
&[
|
|
38591
|
-
&::view-transition-old(
|
|
38844
|
+
&[data-navi-route-transition="back"] {
|
|
38845
|
+
&::view-transition-old(root),
|
|
38846
|
+
&::view-transition-old(navi-route-transition) {
|
|
38592
38847
|
animation-name: navi-route-transition-zoom-out;
|
|
38593
38848
|
}
|
|
38594
38849
|
}
|
|
38595
38850
|
}
|
|
38596
38851
|
}
|
|
38597
|
-
`;
|
|
38598
|
-
const css$T = /* css */`
|
|
38599
|
-
/* The marked region is a picture of its own during every view transition of
|
|
38600
|
-
the document — which is what keeps it out of the root snapshot, where its
|
|
38601
|
-
place would be blank. */
|
|
38602
|
-
[${TRANSITION_AREA_ATTRIBUTE}] {
|
|
38603
|
-
view-transition-name: ${AREA_NAME};
|
|
38604
|
-
}
|
|
38605
|
-
|
|
38606
|
-
/* Only while a transition of OURS is playing: everything below changes how
|
|
38607
|
-
the document animates, and the document belongs to the application the
|
|
38608
|
-
rest of the time. The duration is written here, on the direction alone, so
|
|
38609
|
-
a relation with no type — the browser's cross-fade — answers to
|
|
38610
|
-
--navi-route-transition-duration like every other. */
|
|
38611
|
-
:root[${TRANSITION_ATTRIBUTE}] {
|
|
38612
|
-
&::view-transition-old(root),
|
|
38613
|
-
&::view-transition-new(root),
|
|
38614
|
-
&::view-transition-old(${AREA_NAME}),
|
|
38615
|
-
&::view-transition-new(${AREA_NAME}) {
|
|
38616
|
-
animation-duration: var(${TRANSITION_DURATION_PROPERTY}, 300ms);
|
|
38617
|
-
}
|
|
38618
|
-
|
|
38619
|
-
/* The pages are cut at the edge of the area they move in: its pictures are
|
|
38620
|
-
drawn in the top layer, above the bars, and a page sliding in would
|
|
38621
|
-
otherwise be seen crossing them. */
|
|
38622
|
-
&::view-transition-group(${AREA_NAME}),
|
|
38623
|
-
&::view-transition-image-pair(${AREA_NAME}) {
|
|
38624
|
-
overflow: clip;
|
|
38625
|
-
}
|
|
38626
|
-
}
|
|
38627
|
-
|
|
38628
|
-
${movementsCSS("root", `:not([${TRANSITION_TARGET_ATTRIBUTE}])`)}
|
|
38629
|
-
${movementsCSS(AREA_NAME, `[${TRANSITION_TARGET_ATTRIBUTE}="area"]`)}
|
|
38630
38852
|
|
|
38853
|
+
/* One window's worth of movement. The fallback is the picture's own size,
|
|
38854
|
+
which is what the window is when the whole document travels: the root
|
|
38855
|
+
picture IS the viewport. */
|
|
38631
38856
|
@keyframes navi-route-transition-leave-towards-start {
|
|
38632
38857
|
to {
|
|
38633
|
-
translate: -100% 0;
|
|
38858
|
+
translate: calc(-1 * var(--navi-route-transition-travel-x, 100%)) 0;
|
|
38634
38859
|
}
|
|
38635
38860
|
}
|
|
38636
38861
|
@keyframes navi-route-transition-enter-from-end {
|
|
38637
38862
|
from {
|
|
38638
|
-
translate: 100% 0;
|
|
38863
|
+
translate: var(--navi-route-transition-travel-x, 100%) 0;
|
|
38639
38864
|
}
|
|
38640
38865
|
}
|
|
38641
38866
|
@keyframes navi-route-transition-leave-towards-end {
|
|
38642
38867
|
to {
|
|
38643
|
-
translate: 100% 0;
|
|
38868
|
+
translate: var(--navi-route-transition-travel-x, 100%) 0;
|
|
38644
38869
|
}
|
|
38645
38870
|
}
|
|
38646
38871
|
@keyframes navi-route-transition-enter-from-start {
|
|
38647
38872
|
from {
|
|
38648
|
-
translate: -100% 0;
|
|
38873
|
+
translate: calc(-1 * var(--navi-route-transition-travel-x, 100%)) 0;
|
|
38649
38874
|
}
|
|
38650
38875
|
}
|
|
38651
38876
|
@keyframes navi-route-transition-leave-towards-top {
|
|
38652
38877
|
to {
|
|
38653
|
-
translate: 0 -100
|
|
38878
|
+
translate: 0 calc(-1 * var(--navi-route-transition-travel-y, 100%));
|
|
38654
38879
|
}
|
|
38655
38880
|
}
|
|
38656
38881
|
@keyframes navi-route-transition-enter-from-bottom {
|
|
38657
38882
|
from {
|
|
38658
|
-
translate: 0 100
|
|
38883
|
+
translate: 0 var(--navi-route-transition-travel-y, 100%);
|
|
38659
38884
|
}
|
|
38660
38885
|
}
|
|
38661
38886
|
@keyframes navi-route-transition-leave-towards-bottom {
|
|
38662
38887
|
to {
|
|
38663
|
-
translate: 0 100
|
|
38888
|
+
translate: 0 var(--navi-route-transition-travel-y, 100%);
|
|
38664
38889
|
}
|
|
38665
38890
|
}
|
|
38666
38891
|
@keyframes navi-route-transition-enter-from-top {
|
|
38667
38892
|
from {
|
|
38668
|
-
translate: 0 -100
|
|
38893
|
+
translate: 0 calc(-1 * var(--navi-route-transition-travel-y, 100%));
|
|
38669
38894
|
}
|
|
38670
38895
|
}
|
|
38671
38896
|
@keyframes navi-route-transition-zoom-in {
|
|
@@ -38689,6 +38914,41 @@ const css$T = /* css */`
|
|
|
38689
38914
|
}
|
|
38690
38915
|
`;
|
|
38691
38916
|
|
|
38917
|
+
/**
|
|
38918
|
+
* The region the pages live in — where the movements play.
|
|
38919
|
+
*
|
|
38920
|
+
* Wrap the `<Route>` tree with it in an application that has fixed furniture
|
|
38921
|
+
* (a top bar, a tab bar): the movements then play on THIS element's pictures,
|
|
38922
|
+
* clipped at its bounds, and the bars never move. Without it the document
|
|
38923
|
+
* itself travels, which is right only when the pages are the whole viewport —
|
|
38924
|
+
* with bars around, the moving root picture drags a blank band across the
|
|
38925
|
+
* screen where they stand.
|
|
38926
|
+
*
|
|
38927
|
+
* It is a real box, and it must be: what is photographed and clipped IS its
|
|
38928
|
+
* rectangle. So `display: contents` cannot be used on it — an element with no
|
|
38929
|
+
* box is never captured, the movement plays on nothing and the browser aborts
|
|
38930
|
+
* the transition. Give it the layout the pages need instead — it is a `Box`,
|
|
38931
|
+
* so `flex`, `className`, `style` and the rest are there for that. An
|
|
38932
|
+
* application that already has an element holding its pages can mark that one
|
|
38933
|
+
* with `data-navi-route-transition-area` rather than nesting another.
|
|
38934
|
+
*
|
|
38935
|
+
* @type {import("ignore:preact").FunctionComponent<{ children?: any, [key: string]: any }>}
|
|
38936
|
+
*/
|
|
38937
|
+
const RouteTransitionArea = ({
|
|
38938
|
+
children,
|
|
38939
|
+
...rest
|
|
38940
|
+
}) => {
|
|
38941
|
+
import.meta.css = [css$T, "@jsenv/navi/src/nav/route_transition.jsx"];
|
|
38942
|
+
const props = {
|
|
38943
|
+
...rest,
|
|
38944
|
+
[TRANSITION_AREA_ATTRIBUTE]: ""
|
|
38945
|
+
};
|
|
38946
|
+
return jsx(Box, {
|
|
38947
|
+
...props,
|
|
38948
|
+
children: children
|
|
38949
|
+
});
|
|
38950
|
+
};
|
|
38951
|
+
|
|
38692
38952
|
/**
|
|
38693
38953
|
* Declare how a pair of routes moves against each other.
|
|
38694
38954
|
*
|
|
@@ -38729,7 +38989,7 @@ const css$T = /* css */`
|
|
|
38729
38989
|
* @returns {() => void} remove this relation.
|
|
38730
38990
|
*/
|
|
38731
38991
|
const defineRouteTransition = (from, to, transition) => {
|
|
38732
|
-
import.meta.css = [css$T, "@jsenv/navi/src/nav/route_transition.
|
|
38992
|
+
import.meta.css = [css$T, "@jsenv/navi/src/nav/route_transition.jsx"];
|
|
38733
38993
|
const {
|
|
38734
38994
|
type,
|
|
38735
38995
|
duration
|
|
@@ -38767,7 +39027,7 @@ const defineRouteTransition = (from, to, transition) => {
|
|
|
38767
39027
|
* @returns {() => void} remove this default.
|
|
38768
39028
|
*/
|
|
38769
39029
|
const defineRouteDefaultTransition = transition => {
|
|
38770
|
-
import.meta.css = [css$T, "@jsenv/navi/src/nav/route_transition.
|
|
39030
|
+
import.meta.css = [css$T, "@jsenv/navi/src/nav/route_transition.jsx"];
|
|
38771
39031
|
const value = normalizeTransition(transition);
|
|
38772
39032
|
defaultTransition = value;
|
|
38773
39033
|
updateRoutingObservers();
|
|
@@ -38971,8 +39231,17 @@ const beginTransition = ({
|
|
|
38971
39231
|
// Looked up per transition, not once: the area is the application's own
|
|
38972
39232
|
// element and follows its lifecycle — a page layout without bars has none,
|
|
38973
39233
|
// and the movement then plays on the document itself.
|
|
38974
|
-
|
|
39234
|
+
const areaElements = document.querySelectorAll(`[${TRANSITION_AREA_ATTRIBUTE}]`);
|
|
39235
|
+
if (areaElements.length > 1) {
|
|
39236
|
+
warnOnce("several-areas", `${areaElements.length} elements carry ${TRANSITION_AREA_ATTRIBUTE}. They all take the same view-transition-name, and a name belongs to one element at a time: the browser refuses EVERY view transition of the document while this holds. Mark the one element the pages live in.`);
|
|
39237
|
+
}
|
|
39238
|
+
const areaElement = areaElements.length > 0 ? areaElements[0] : null;
|
|
39239
|
+
// The area as it stands before anything moves: rendering is held, so this is
|
|
39240
|
+
// still the page being left (see holdAreaGeometry).
|
|
39241
|
+
let areaRectBefore = null;
|
|
39242
|
+
if (areaElement) {
|
|
38975
39243
|
documentElement.setAttribute(TRANSITION_TARGET_ATTRIBUTE, "area");
|
|
39244
|
+
areaRectBefore = areaElement.getBoundingClientRect();
|
|
38976
39245
|
}
|
|
38977
39246
|
// A duration of this relation's own, worn for the length of the transition —
|
|
38978
39247
|
// and whatever the application had written inline put back afterwards, not
|
|
@@ -38995,6 +39264,28 @@ const beginTransition = ({
|
|
|
38995
39264
|
// been decided renders its page in between — a wait armed then waits for
|
|
38996
39265
|
// something that has already happened.
|
|
38997
39266
|
const renderWait = armRouteRenderWait$1();
|
|
39267
|
+
// What the browser ACTUALLY captured, read once the pictures exist: it is
|
|
39268
|
+
// the only place the two silent misconfigurations show. Both are about the
|
|
39269
|
+
// same thing — a movement playing on pictures that are not the pages.
|
|
39270
|
+
const viewTransitionReady = () => {
|
|
39271
|
+
const capturedNames = capturedViewTransitionNames();
|
|
39272
|
+
if (areaElements.length > 0) {
|
|
39273
|
+
if (!capturedNames.has(AREA_NAME)) {
|
|
39274
|
+
warnOnce("area-not-captured", `The element marked ${TRANSITION_AREA_ATTRIBUTE} was not captured, so the movement plays on nothing. An element is captured only if it generates a box: \`display: contents\` (or an element not rendered) cannot be the area — its rectangle is what gets photographed and clipped.`);
|
|
39275
|
+
}
|
|
39276
|
+
return;
|
|
39277
|
+
}
|
|
39278
|
+
for (const name of capturedNames) {
|
|
39279
|
+
if (name === "root") {
|
|
39280
|
+
continue;
|
|
39281
|
+
}
|
|
39282
|
+
// Something stands still while the whole document travels under it. The
|
|
39283
|
+
// root picture spans the viewport and has a HOLE where that thing was
|
|
39284
|
+
// captured, so what crosses the screen is a blank band.
|
|
39285
|
+
warnOnce("pages-travel-under-named-elements", `The movement plays on the whole document while "${name}" is captured on its own, so a blank band travels where it stands. Wrap the pages in <RouteTransitionArea> (or mark their element with ${TRANSITION_AREA_ATTRIBUTE}) so the movement plays on them rather than on the document.`);
|
|
39286
|
+
break;
|
|
39287
|
+
}
|
|
39288
|
+
};
|
|
38998
39289
|
const viewTransition = startViewTransition$1(async () => {
|
|
38999
39290
|
// The picture the browser is about to take must be of the page that was
|
|
39000
39291
|
// asked for, and a route matching is not yet a page rendered. Whatever
|
|
@@ -39016,6 +39307,11 @@ const beginTransition = ({
|
|
|
39016
39307
|
} finally {
|
|
39017
39308
|
renderWait.stop();
|
|
39018
39309
|
}
|
|
39310
|
+
// The page arriving is in the DOM and the transition has not started
|
|
39311
|
+
// playing: the one moment both states of the area can be known.
|
|
39312
|
+
if (areaElement) {
|
|
39313
|
+
holdTransitionWindow(transition, areaElement, areaRectBefore);
|
|
39314
|
+
}
|
|
39019
39315
|
});
|
|
39020
39316
|
const end = () => {
|
|
39021
39317
|
// Whatever ends it — played out, skipped by another transition starting,
|
|
@@ -39030,14 +39326,50 @@ const beginTransition = ({
|
|
|
39030
39326
|
documentElement.removeAttribute(TRANSITION_ATTRIBUTE);
|
|
39031
39327
|
documentElement.removeAttribute(TRANSITION_TYPE_ATTRIBUTE);
|
|
39032
39328
|
documentElement.removeAttribute(TRANSITION_TARGET_ATTRIBUTE);
|
|
39329
|
+
releaseTransitionWindow(transition);
|
|
39033
39330
|
if (restoreDuration) {
|
|
39034
39331
|
restoreDuration();
|
|
39035
39332
|
}
|
|
39036
39333
|
}
|
|
39037
39334
|
};
|
|
39335
|
+
viewTransition.ready.then(viewTransitionReady, ignoreSkipped$1);
|
|
39038
39336
|
viewTransition.finished.then(end, end);
|
|
39039
39337
|
};
|
|
39040
39338
|
|
|
39339
|
+
// A transition skipped by another one starting is an outcome, not a failure.
|
|
39340
|
+
const ignoreSkipped$1 = () => {};
|
|
39341
|
+
|
|
39342
|
+
// The names the browser captured, read off the pictures themselves: what was
|
|
39343
|
+
// asked for in CSS and what was taken are not the same question (see
|
|
39344
|
+
// viewTransitionReady).
|
|
39345
|
+
const capturedViewTransitionNames = () => {
|
|
39346
|
+
const names = new Set();
|
|
39347
|
+
for (const animation of document.getAnimations()) {
|
|
39348
|
+
const pseudoElement = animation.effect?.pseudoElement;
|
|
39349
|
+
if (!pseudoElement || !pseudoElement.startsWith("::view-transition")) {
|
|
39350
|
+
continue;
|
|
39351
|
+
}
|
|
39352
|
+
const nameStart = pseudoElement.indexOf("(");
|
|
39353
|
+
if (nameStart === -1) {
|
|
39354
|
+
continue;
|
|
39355
|
+
}
|
|
39356
|
+
names.add(pseudoElement.slice(nameStart + 1, -1));
|
|
39357
|
+
}
|
|
39358
|
+
return names;
|
|
39359
|
+
};
|
|
39360
|
+
|
|
39361
|
+
// Said once per kind, whatever the number of navigations: a misconfiguration
|
|
39362
|
+
// is one fact about the application, and repeating it every time the user
|
|
39363
|
+
// moves would bury it.
|
|
39364
|
+
const warningsSaid = new Set();
|
|
39365
|
+
const warnOnce = (id, message) => {
|
|
39366
|
+
if (warningsSaid.has(id)) {
|
|
39367
|
+
return;
|
|
39368
|
+
}
|
|
39369
|
+
warningsSaid.add(id);
|
|
39370
|
+
console.warn(message);
|
|
39371
|
+
};
|
|
39372
|
+
|
|
39041
39373
|
// A route matching is a signal changing; how many passes Preact takes to
|
|
39042
39374
|
// answer it is its own business, and the render is the moment the picture can
|
|
39043
39375
|
// be taken. Listening starts before the change, or a render landing while the
|
|
@@ -39159,19 +39491,6 @@ const DRAGGED_ATTRIBUTE = "data-navi-route-travel-dragged";
|
|
|
39159
39491
|
const TURNED_ATTRIBUTE = "data-navi-route-travel-turned";
|
|
39160
39492
|
// The name the box wears while it travels, and only then (see nameForTravel).
|
|
39161
39493
|
const TRAVEL_NAME = "navi-route-travel";
|
|
39162
|
-
// Where the two boxes of a travel stand in the window, published for the
|
|
39163
|
-
// length of it. Measurements only: what is DERIVED from them — where a picture
|
|
39164
|
-
// goes, what a bar covers — is derived in the CSS below, so the app's own
|
|
39165
|
-
// numbers (the room its fixed bars take) can take part in it. Only the
|
|
39166
|
-
// measuring needs JS, and only for the one moment both boxes exist (see
|
|
39167
|
-
// holdTravelGeometry).
|
|
39168
|
-
const TRAVEL_TOP_PROPERTY = "--navi-route-travel-top";
|
|
39169
|
-
const TRAVEL_LEFT_PROPERTY = "--navi-route-travel-left";
|
|
39170
|
-
const TRAVEL_WIDTH_PROPERTY = "--navi-route-travel-width";
|
|
39171
|
-
const TRAVEL_HEIGHT_PROPERTY = "--navi-route-travel-height";
|
|
39172
|
-
const TRAVEL_OLD_TOP_PROPERTY = "--navi-route-travel-old-top";
|
|
39173
|
-
const TRAVEL_OLD_LEFT_PROPERTY = "--navi-route-travel-old-left";
|
|
39174
|
-
const TRAVEL_GEOMETRY_PROPERTIES = [TRAVEL_TOP_PROPERTY, TRAVEL_LEFT_PROPERTY, TRAVEL_WIDTH_PROPERTY, TRAVEL_HEIGHT_PROPERTY, TRAVEL_OLD_TOP_PROPERTY, TRAVEL_OLD_LEFT_PROPERTY];
|
|
39175
39494
|
const css$S = /* css */`
|
|
39176
39495
|
/* The name that makes the page inside this box a picture of its own during a
|
|
39177
39496
|
transition — rather than part of the one big picture the document takes, so
|
|
@@ -39254,10 +39573,16 @@ const css$S = /* css */`
|
|
|
39254
39573
|
would be seen jumping back to its top before it even begins to leave.
|
|
39255
39574
|
Offset here rather than by \`translate\`, which the movement itself uses,
|
|
39256
39575
|
and at its own size rather than the group's so that nothing is cut off
|
|
39257
|
-
the far side of the shift (see
|
|
39258
|
-
top: calc(
|
|
39576
|
+
the far side of the shift (see transition_window.js). */
|
|
39577
|
+
top: calc(
|
|
39578
|
+
var(--navi-transition-window-old-top) - var(
|
|
39579
|
+
--navi-transition-window-top
|
|
39580
|
+
)
|
|
39581
|
+
);
|
|
39259
39582
|
left: calc(
|
|
39260
|
-
var(
|
|
39583
|
+
var(--navi-transition-window-old-left) - var(
|
|
39584
|
+
--navi-transition-window-left
|
|
39585
|
+
)
|
|
39261
39586
|
);
|
|
39262
39587
|
width: auto;
|
|
39263
39588
|
}
|
|
@@ -39272,7 +39597,7 @@ const css$S = /* css */`
|
|
|
39272
39597
|
}
|
|
39273
39598
|
&::view-transition-group(navi-route-travel) {
|
|
39274
39599
|
/* The window the two pictures are seen through, held still for the whole
|
|
39275
|
-
travel at the taller of the two boxes (see
|
|
39600
|
+
travel at the taller of the two boxes (see transition_window.js): the group
|
|
39276
39601
|
is what CLIPS, and the browser animates its height from the box being
|
|
39277
39602
|
left to the box arriving — so the window shrinks under the pictures and
|
|
39278
39603
|
cuts the page leaving from the bottom, progressively. The box does end
|
|
@@ -39283,7 +39608,7 @@ const css$S = /* css */`
|
|
|
39283
39608
|
winning against it with !important — which also drops its position
|
|
39284
39609
|
animation, fine while a travel box stands in the same place from one
|
|
39285
39610
|
route to the next. */
|
|
39286
|
-
height: var(
|
|
39611
|
+
height: var(--navi-transition-window-height);
|
|
39287
39612
|
|
|
39288
39613
|
/* Cut at the safe area, on top of being cut at the box. The pictures are
|
|
39289
39614
|
drawn in the top layer, so they cover a fixed bar as easily as anything
|
|
@@ -39300,20 +39625,22 @@ const css$S = /* css */`
|
|
|
39300
39625
|
only where it itself stands, and that is the measured half. */
|
|
39301
39626
|
--navi-route-travel-clip-top: max(
|
|
39302
39627
|
0px,
|
|
39303
|
-
var(--navi-safe-area-inset-top) - var(
|
|
39628
|
+
var(--navi-safe-area-inset-top) - var(--navi-transition-window-top)
|
|
39304
39629
|
);
|
|
39305
39630
|
--navi-route-travel-clip-left: max(
|
|
39306
39631
|
0px,
|
|
39307
|
-
var(--navi-safe-area-inset-left) - var(
|
|
39632
|
+
var(--navi-safe-area-inset-left) - var(--navi-transition-window-left)
|
|
39308
39633
|
);
|
|
39309
39634
|
--navi-route-travel-clip-bottom: max(
|
|
39310
39635
|
0px,
|
|
39311
|
-
var(
|
|
39636
|
+
var(--navi-transition-window-top) +
|
|
39637
|
+
var(--navi-transition-window-height) +
|
|
39312
39638
|
var(--navi-safe-area-inset-bottom) - 100dvh
|
|
39313
39639
|
);
|
|
39314
39640
|
--navi-route-travel-clip-right: max(
|
|
39315
39641
|
0px,
|
|
39316
|
-
var(
|
|
39642
|
+
var(--navi-transition-window-left) +
|
|
39643
|
+
var(--navi-transition-window-width) +
|
|
39317
39644
|
var(--navi-safe-area-inset-right) - 100dvw
|
|
39318
39645
|
);
|
|
39319
39646
|
clip-path: inset(
|
|
@@ -39635,7 +39962,7 @@ const RouteTravel = ({
|
|
|
39635
39962
|
}
|
|
39636
39963
|
pageAskedForRef.current = page;
|
|
39637
39964
|
// The box as it stands before anything moves: rendering is held, so this is
|
|
39638
|
-
// still the page being left (see
|
|
39965
|
+
// still the page being left (see transition_window.js).
|
|
39639
39966
|
const rectBefore = elementRef.current.getBoundingClientRect();
|
|
39640
39967
|
// The hold a navigation already took, if this travel is the answer to one:
|
|
39641
39968
|
// taking another would be taking a hold on a page that is holding still.
|
|
@@ -39663,7 +39990,7 @@ const RouteTravel = ({
|
|
|
39663
39990
|
}, renderWait);
|
|
39664
39991
|
// The page arriving is in the DOM and the transition has not started
|
|
39665
39992
|
// playing: the one moment both boxes can be known.
|
|
39666
|
-
|
|
39993
|
+
holdTransitionWindow(travel, elementRef.current, rectBefore);
|
|
39667
39994
|
});
|
|
39668
39995
|
travel.viewTransition = viewTransition;
|
|
39669
39996
|
if (scrub) {
|
|
@@ -39981,7 +40308,7 @@ const RouteTravel = ({
|
|
|
39981
40308
|
document.documentElement.removeAttribute(TRAVEL_AXIS_ATTRIBUTE);
|
|
39982
40309
|
document.documentElement.removeAttribute(DRAGGED_ATTRIBUTE);
|
|
39983
40310
|
document.documentElement.removeAttribute(TURNED_ATTRIBUTE);
|
|
39984
|
-
|
|
40311
|
+
releaseTransitionWindow(travel);
|
|
39985
40312
|
}
|
|
39986
40313
|
};
|
|
39987
40314
|
|
|
@@ -40364,44 +40691,6 @@ const releaseHold = travel => {
|
|
|
40364
40691
|
document.documentElement.removeAttribute(HOLD_ATTRIBUTE);
|
|
40365
40692
|
};
|
|
40366
40693
|
|
|
40367
|
-
// The two boxes of a travel, measured at the one moment both exist: the
|
|
40368
|
-
// arriving page is in the DOM and the transition has not started playing.
|
|
40369
|
-
//
|
|
40370
|
-
// The group stands at the ARRIVING box — its own animation is dropped, so it
|
|
40371
|
-
// takes the geometry the browser declared for it and holds it for the whole
|
|
40372
|
-
// travel. That is why both rectangles have to be published: a group that does
|
|
40373
|
-
// not move says nothing about where the page being left was, and its rectangle
|
|
40374
|
-
// in the window is the only thing CSS cannot work out on its own.
|
|
40375
|
-
const holdTravelGeometry = (element, rectBefore) => {
|
|
40376
|
-
const rectAfter = element.getBoundingClientRect();
|
|
40377
|
-
// The height it is held at is the taller of the two boxes, so neither picture
|
|
40378
|
-
// is ever cut. It cannot be measured from one side alone: a page arriving
|
|
40379
|
-
// shorter than the one it replaces would cut the one leaving, a page arriving
|
|
40380
|
-
// taller would be cut itself.
|
|
40381
|
-
const height = rectBefore.height > rectAfter.height ? rectBefore.height : rectAfter.height;
|
|
40382
|
-
const {
|
|
40383
|
-
style
|
|
40384
|
-
} = document.documentElement;
|
|
40385
|
-
style.setProperty(TRAVEL_TOP_PROPERTY, `${rectAfter.top}px`);
|
|
40386
|
-
style.setProperty(TRAVEL_LEFT_PROPERTY, `${rectAfter.left}px`);
|
|
40387
|
-
style.setProperty(TRAVEL_WIDTH_PROPERTY, `${rectAfter.width}px`);
|
|
40388
|
-
style.setProperty(TRAVEL_HEIGHT_PROPERTY, `${height}px`);
|
|
40389
|
-
style.setProperty(TRAVEL_OLD_TOP_PROPERTY, `${rectBefore.top}px`);
|
|
40390
|
-
style.setProperty(TRAVEL_OLD_LEFT_PROPERTY, `${rectBefore.left}px`);
|
|
40391
|
-
};
|
|
40392
|
-
// The live layout takes the box back. A discontinuity by construction — the
|
|
40393
|
-
// group stands at the held height, the box is at the new one — and an invisible
|
|
40394
|
-
// one: the page arriving is fully in place, and the strip below it that the
|
|
40395
|
-
// group still covers shows the page leaving only while it is still on screen.
|
|
40396
|
-
const releaseTravelGeometry = () => {
|
|
40397
|
-
const {
|
|
40398
|
-
style
|
|
40399
|
-
} = document.documentElement;
|
|
40400
|
-
for (const property of TRAVEL_GEOMETRY_PROPERTIES) {
|
|
40401
|
-
style.removeProperty(property);
|
|
40402
|
-
}
|
|
40403
|
-
};
|
|
40404
|
-
|
|
40405
40694
|
// The animations of the pictures, asked for again until there are some: they
|
|
40406
40695
|
// come into existence with the transition, several frames after it was asked
|
|
40407
40696
|
// for, and the gesture has already begun by then. Kept once found — the set
|
|
@@ -73738,5 +74027,5 @@ const UserSvg = () => jsx("svg", {
|
|
|
73738
74027
|
})
|
|
73739
74028
|
});
|
|
73740
74029
|
|
|
73741
|
-
export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, BadgeList, Binder, Box, Button, ButtonCopyToClipboard, Caption, CardLayout, CheckSvg, CheckboxGroup, CloseSvg, Code, Col, Colgroup, Color, ConstructionSvg, ControlGroup, DaySpin, Details, Dialog, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, EyeClosedSvg, EyeSvg, Field, FixedBar, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, Input, InputDuration, Interpolate, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, LinkCurrentSvg, List, ListItem, ListItemGroup, ListItems, Loading, LoadingDotsSvg, LoadingIndicator, LoadingIndicatorFluid, LoadingOutline, MessageBox, Meter, Nav, NaviDebug, NumberSpin, Paragraph, Picker, Popover, Popup, Quantity, RadioGroup, Route, RouteTravel, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, Select, SelectableInput, SelectionContext, Separator, SettingsSvg, SidePanel, Slide, SlideContainer, Spin, SpinGroup, SplitButton, StarSvg, SummaryMarker, Svg, Table, TableCell, Tbody, Text, TextBox, Textarea, TextareaCharCount, Thead, Time, TimeRangeSpin, TimeSpin, Title, Tr, UITransition, Unit, UserSvg, ViewportLayout, Wheel, WheelGroup, WheelItem, actionRunEffect, anyMatchingRouteSignal, applySearch, arraySignalMembership, compareTwoJsValues, createAction, createAvailableConstraint, createI18n, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, createSlot, defineInteractionDetector, defineNaviConfirmPopupOptions, defineRouteDefaultTransition, defineRouteTransition, detectHorizontalOverflow, enableDebugActions, enableDebugOnDocumentLoading, ensureDocumentStartViewTransition, errorIsDisplayed, filterTableSelection, formatDatetime, formatDay, formatDayRelative, formatMonth, formatNumber, formatTime, formatTimeRelative, getNowHours, getNowHoursRoundedToStep, interpolateText, isCellSelected, isColumnSelected, isRowSelected, isScrolling, isToday, languagesSignal, localStorageSignal, markErrorAsDisplayedBy, moveArrayItemByIndex, navBack, navForward, navIntegratedVia, navTo, naviI18n, openCallout, rawUrlPart, registerGlobalConstraint, reload, rerunActions, resource, route, routeAction, scrollActivitySignal, setBaseUrl, setPreferredLanguage, setSupportedLanguages, setUrlTargetOptions, setupRoutes, smallTouchScreenSignal, stateSignal, stopLoad, stringifyTableSelectionValue, swapArrayItemByIndex, syncOwnedResourceToSignals, syncResourceToSignals, triggerNaviCommand, updateActions, useActionStatus, useArraySignalMembership, useAsyncData, useCalloutRequestClose, useCancelPrevious, useCellGridFromRows, useConstraintValidityState, useDependenciesDiff, useDisplayedLayoutEffect, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useInputGroup, useKeyboardShortcuts, useNavState, useOrderedColumns, usePopupMode, useRouteStatus, useRunOnMount, useSearchText, useSelectableElement, useSelectionController, useSignalSync, useSlideValue, useStateArray, useTitleLevel, useUrlSearchParam, useUrlTargetId, valueInLocalStorage, windowWidthSignal };
|
|
74030
|
+
export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, BadgeList, Binder, Box, Button, ButtonCopyToClipboard, Caption, CardLayout, CheckSvg, CheckboxGroup, CloseSvg, Code, Col, Colgroup, Color, ConstructionSvg, ControlGroup, DaySpin, Details, Dialog, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, EyeClosedSvg, EyeSvg, Field, FixedBar, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, Input, InputDuration, Interpolate, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, LinkCurrentSvg, List, ListItem, ListItemGroup, ListItems, Loading, LoadingDotsSvg, LoadingIndicator, LoadingIndicatorFluid, LoadingOutline, MessageBox, Meter, Nav, NaviDebug, NumberSpin, Paragraph, Picker, Popover, Popup, Quantity, RadioGroup, Route, RouteTransitionArea, RouteTravel, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, Select, SelectableInput, SelectionContext, Separator, SettingsSvg, SidePanel, Slide, SlideContainer, Spin, SpinGroup, SplitButton, StarSvg, SummaryMarker, Svg, Table, TableCell, Tbody, Text, TextBox, Textarea, TextareaCharCount, Thead, Time, TimeRangeSpin, TimeSpin, Title, Tr, UITransition, Unit, UserSvg, ViewportLayout, Wheel, WheelGroup, WheelItem, actionRunEffect, anyMatchingRouteSignal, applySearch, arraySignalMembership, compareTwoJsValues, createAction, createAvailableConstraint, createI18n, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, createSlot, defineInteractionDetector, defineNaviConfirmPopupOptions, defineRouteDefaultTransition, defineRouteTransition, detectHorizontalOverflow, enableDebugActions, enableDebugOnDocumentLoading, ensureDocumentStartViewTransition, errorIsDisplayed, filterTableSelection, formatDatetime, formatDay, formatDayRelative, formatMonth, formatNumber, formatTime, formatTimeRelative, getNowHours, getNowHoursRoundedToStep, interpolateText, isCellSelected, isColumnSelected, isRowSelected, isScrolling, isToday, languagesSignal, localStorageSignal, markErrorAsDisplayedBy, moveArrayItemByIndex, navBack, navForward, navIntegratedVia, navTo, naviI18n, openCallout, rawUrlPart, registerGlobalConstraint, reload, rerunActions, resource, route, routeAction, scrollActivitySignal, setBaseUrl, setPreferredLanguage, setSupportedLanguages, setUrlTargetOptions, setupRoutes, smallTouchScreenSignal, stateSignal, stopLoad, stringifyTableSelectionValue, swapArrayItemByIndex, syncOwnedResourceToSignals, syncResourceToSignals, triggerNaviCommand, updateActions, useActionStatus, useArraySignalMembership, useAsyncData, useCalloutRequestClose, useCancelPrevious, useCellGridFromRows, useConstraintValidityState, useDependenciesDiff, useDisplayedLayoutEffect, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useInputGroup, useKeyboardShortcuts, useNavState, useOrderedColumns, usePopupMode, useRouteStatus, useRunOnMount, useSearchText, useSelectableElement, useSelectionController, useSignalSync, useSlideValue, useStateArray, useTitleLevel, useUrlSearchParam, useUrlTargetId, valueInLocalStorage, windowWidthSignal };
|
|
73742
74031
|
//# sourceMappingURL=jsenv_navi.js.map
|