@jsenv/navi 0.29.209 → 0.29.211
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/dev/jsenv_navi.js +137 -44
- package/dist/dev/jsenv_navi.js.map +8 -8
- package/dist/jsenv_navi.js +137 -44
- package/dist/jsenv_navi.js.map +8 -8
- package/docs/pan_zoom.md +19 -2
- package/package.json +2 -2
package/dist/jsenv_navi.js
CHANGED
|
@@ -10967,6 +10967,10 @@ const isMac = detectMac();
|
|
|
10967
10967
|
* it, which is the hand saying it has moved on. What answers "away" is the same
|
|
10968
10968
|
* thing that closes a popup, and the surface is the one that watches for it, so
|
|
10969
10969
|
* an application never keeps a `pointerdown` listener on the window to know.
|
|
10970
|
+
* `[data-hand-kept]` is on the element for as long as it holds the hand that
|
|
10971
|
+
* way, so the paid wait can be drawn — a page darkened around a plan that
|
|
10972
|
+
* answers on contact now. `[data-grabbed]` stays the narrower one: a hand on it
|
|
10973
|
+
* at this instant.
|
|
10970
10974
|
*
|
|
10971
10975
|
* The WHEEL is the same question asked of a mouse, and it is not asked of the
|
|
10972
10976
|
* caller at all: a wheel event is read rather than settled beforehand, so
|
|
@@ -27431,7 +27435,7 @@ installImportMetaCssBuild(import.meta);
|
|
|
27431
27435
|
|
|
27432
27436
|
/**
|
|
27433
27437
|
* The window two pages are seen through while one replaces the other, measured
|
|
27434
|
-
*
|
|
27438
|
+
* at the one moment both exist and published for the length of the movement.
|
|
27435
27439
|
*
|
|
27436
27440
|
* Both ways of moving from one route to another need the same numbers, so they
|
|
27437
27441
|
* are written under the same names and read by the same CSS formulas —
|
|
@@ -27456,6 +27460,18 @@ installImportMetaCssBuild(import.meta);
|
|
|
27456
27460
|
* in the window — one page is scrolled and the other is not, one has a top
|
|
27457
27461
|
* bar over it and the other has the screen. Each picture is placed at its
|
|
27458
27462
|
* own corner inside the window.
|
|
27463
|
+
* - **where the arriving state IS, frame after frame.** The browser places the
|
|
27464
|
+
* group from the live arriving element on every frame of the movement — that
|
|
27465
|
+
* is what makes a picture pair follow an element that moves — and the
|
|
27466
|
+
* formula that moves the group back to the window's corner cancels that
|
|
27467
|
+
* placement with this corner. Read once, the two stop cancelling the moment
|
|
27468
|
+
* anything scrolls the document under the movement (a slice landing and
|
|
27469
|
+
* putting a row back, a list placing its default row, a height growing under
|
|
27470
|
+
* a restored offset): the window drifts by as much, and both pictures with
|
|
27471
|
+
* it — the photograph of the page being left included. So this corner alone
|
|
27472
|
+
* is kept live, as often as the browser reads its side of it. It is also
|
|
27473
|
+
* the arriving picture's own corner, which then stays where the page really
|
|
27474
|
+
* is and lands with no jump when the pictures are dropped.
|
|
27459
27475
|
* - **the band the state being left kept free**, next to the one the arriving
|
|
27460
27476
|
* state keeps free. A band is furniture — a fixed bar, a sticky row — and
|
|
27461
27477
|
* the pictures are cut at it so they are not watched painting over it. Read
|
|
@@ -27465,8 +27481,11 @@ installImportMetaCssBuild(import.meta);
|
|
|
27465
27481
|
* at the one moment the state being left still exists, the cut can be taken
|
|
27466
27482
|
* at what is furniture on BOTH sides (see the clip formulas).
|
|
27467
27483
|
*
|
|
27468
|
-
* Only the measuring needs JS, and
|
|
27469
|
-
* the page arriving is in the DOM and the
|
|
27484
|
+
* Only the measuring needs JS, and apart from the arriving corner it happens
|
|
27485
|
+
* at the one moment both states exist: the page arriving is in the DOM and the
|
|
27486
|
+
* transition has not started playing. The window, the corner of the state
|
|
27487
|
+
* being left and its band describe a state that no longer exists, and reading
|
|
27488
|
+
* them again is what must never happen.
|
|
27470
27489
|
* Everything DERIVED from these numbers — the band a fixed bar covers, how far
|
|
27471
27490
|
* a page travels — is derived in CSS, so the application's own numbers (the
|
|
27472
27491
|
* room its bars give back, see layout/safe_area.js; what covers the box from
|
|
@@ -27567,6 +27586,8 @@ const WINDOW_PROPERTIES = [
|
|
|
27567
27586
|
// after another has replaced it must not wipe numbers the new one is standing
|
|
27568
27587
|
// on.
|
|
27569
27588
|
let windowOwner = null;
|
|
27589
|
+
// Stops re-reading the arriving state's corner, when a movement is on.
|
|
27590
|
+
let unfollowArrivingState = null;
|
|
27570
27591
|
|
|
27571
27592
|
/**
|
|
27572
27593
|
* The state being left, taken while rendering is held — the page arriving is
|
|
@@ -27612,6 +27633,7 @@ const holdTransitionWindow = (owner, element, stateBefore) => {
|
|
|
27612
27633
|
style.setProperty(OLD_BAND_RIGHT_PROPERTY, `${oldBand.right}px`);
|
|
27613
27634
|
style.setProperty(OLD_BAND_BOTTOM_PROPERTY, `${oldBand.bottom}px`);
|
|
27614
27635
|
style.setProperty(OLD_BAND_LEFT_PROPERTY, `${oldBand.left}px`);
|
|
27636
|
+
followArrivingState(element, rectAfter);
|
|
27615
27637
|
};
|
|
27616
27638
|
|
|
27617
27639
|
// The live layout takes the box back. A discontinuity by construction — the
|
|
@@ -27623,12 +27645,45 @@ const releaseTransitionWindow = (owner) => {
|
|
|
27623
27645
|
return;
|
|
27624
27646
|
}
|
|
27625
27647
|
windowOwner = null;
|
|
27648
|
+
if (unfollowArrivingState) {
|
|
27649
|
+
unfollowArrivingState();
|
|
27650
|
+
}
|
|
27626
27651
|
const { style } = document.documentElement;
|
|
27627
27652
|
for (const property of WINDOW_PROPERTIES) {
|
|
27628
27653
|
style.removeProperty(property);
|
|
27629
27654
|
}
|
|
27630
27655
|
};
|
|
27631
27656
|
|
|
27657
|
+
// The arriving state's corner, re-read every frame — as often as the browser
|
|
27658
|
+
// refreshes the group's placement from the same element (see the top of the
|
|
27659
|
+
// file). Requested, never awaited: the first call runs inside the update
|
|
27660
|
+
// callback, where a frame cannot come. Written only when it moved: a custom
|
|
27661
|
+
// property set on the root recomputes the style of the whole document.
|
|
27662
|
+
const followArrivingState = (element, rectAtHold) => {
|
|
27663
|
+
if (unfollowArrivingState) {
|
|
27664
|
+
unfollowArrivingState();
|
|
27665
|
+
}
|
|
27666
|
+
const { style } = document.documentElement;
|
|
27667
|
+
let top = rectAtHold.top;
|
|
27668
|
+
let left = rectAtHold.left;
|
|
27669
|
+
let frame = requestAnimationFrame(function read() {
|
|
27670
|
+
const rect = element.getBoundingClientRect();
|
|
27671
|
+
if (rect.top !== top) {
|
|
27672
|
+
top = rect.top;
|
|
27673
|
+
style.setProperty(WINDOW_NEW_TOP_PROPERTY, `${top}px`);
|
|
27674
|
+
}
|
|
27675
|
+
if (rect.left !== left) {
|
|
27676
|
+
left = rect.left;
|
|
27677
|
+
style.setProperty(WINDOW_NEW_LEFT_PROPERTY, `${left}px`);
|
|
27678
|
+
}
|
|
27679
|
+
frame = requestAnimationFrame(read);
|
|
27680
|
+
});
|
|
27681
|
+
unfollowArrivingState = () => {
|
|
27682
|
+
unfollowArrivingState = null;
|
|
27683
|
+
cancelAnimationFrame(frame);
|
|
27684
|
+
};
|
|
27685
|
+
};
|
|
27686
|
+
|
|
27632
27687
|
// A band nothing can be wider than, published for an edge nothing is known
|
|
27633
27688
|
// about: taken as the smaller of the two, it leaves the live band standing on
|
|
27634
27689
|
// its own, which is the movement navi played before it knew any of this.
|
|
@@ -56322,8 +56377,9 @@ const getAvailableWidth = (layer, element) => {
|
|
|
56322
56377
|
*
|
|
56323
56378
|
* `animation="slide-from-*"` (anchorReference/point mode only): a real
|
|
56324
56379
|
* translate-based entrance, 8 directions (cardinal + 4 diagonals), each
|
|
56325
|
-
* 100%-of-own-size, cut
|
|
56326
|
-
*
|
|
56380
|
+
* 100%-of-own-size, cut on the side it comes from — at the edge of the area it
|
|
56381
|
+
* was placed in, so the part of the travel that happens outside that area is
|
|
56382
|
+
* not watched crossing it. It travels through `transform`, not through the
|
|
56327
56383
|
* `translate` property, which belongs to the popup's own placement
|
|
56328
56384
|
* (applyNewPosition in visible_rect.js — see its doc for why the placement is
|
|
56329
56385
|
* a transform at all, and why it has to be the outermost one: the individual
|
|
@@ -56424,38 +56480,58 @@ const popupCss = /* css */ `
|
|
|
56424
56480
|
|
|
56425
56481
|
/* slide — anchorReference/point mode family: direction multipliers,
|
|
56426
56482
|
one per concrete navi-animation value, 100%-of-own-size distance
|
|
56427
|
-
(see this file's top comment).
|
|
56483
|
+
(see this file's top comment).
|
|
56484
|
+
Each also names the side(s) it comes from, as a cut placed on the edge
|
|
56485
|
+
of the area the popup was placed in — and ONLY those sides: a popup
|
|
56486
|
+
travelling down crosses the top edge of that area and no other, so
|
|
56487
|
+
cutting the three it never reaches would take away what it legitimately
|
|
56488
|
+
paints outside its own box (its shadow, a popup opened from inside it)
|
|
56489
|
+
for nothing. A drawer the width of the app is the case that shows it:
|
|
56490
|
+
its room to the left and right is zero, and cutting there would shave
|
|
56491
|
+
its sides flat. See the shared rule below for what the cut is. */
|
|
56428
56492
|
&[navi-animation="slide-from-top"] {
|
|
56429
56493
|
--x-popup-slide-x: 0;
|
|
56430
56494
|
--x-popup-slide-y: -1;
|
|
56495
|
+
--x-popup-cut-top: var(--x-popup-cut-top-at-area);
|
|
56431
56496
|
}
|
|
56432
56497
|
&[navi-animation="slide-from-bottom"] {
|
|
56433
56498
|
--x-popup-slide-x: 0;
|
|
56434
56499
|
--x-popup-slide-y: 1;
|
|
56500
|
+
--x-popup-cut-bottom: var(--x-popup-cut-bottom-at-area);
|
|
56435
56501
|
}
|
|
56436
56502
|
&[navi-animation="slide-from-left"] {
|
|
56437
56503
|
--x-popup-slide-x: -1;
|
|
56438
56504
|
--x-popup-slide-y: 0;
|
|
56505
|
+
--x-popup-cut-left: var(--x-popup-cut-left-at-area);
|
|
56439
56506
|
}
|
|
56440
56507
|
&[navi-animation="slide-from-right"] {
|
|
56441
56508
|
--x-popup-slide-x: 1;
|
|
56442
56509
|
--x-popup-slide-y: 0;
|
|
56510
|
+
--x-popup-cut-right: var(--x-popup-cut-right-at-area);
|
|
56443
56511
|
}
|
|
56444
56512
|
&[navi-animation="slide-from-top-left"] {
|
|
56445
56513
|
--x-popup-slide-x: -1;
|
|
56446
56514
|
--x-popup-slide-y: -1;
|
|
56515
|
+
--x-popup-cut-top: var(--x-popup-cut-top-at-area);
|
|
56516
|
+
--x-popup-cut-left: var(--x-popup-cut-left-at-area);
|
|
56447
56517
|
}
|
|
56448
56518
|
&[navi-animation="slide-from-top-right"] {
|
|
56449
56519
|
--x-popup-slide-x: 1;
|
|
56450
56520
|
--x-popup-slide-y: -1;
|
|
56521
|
+
--x-popup-cut-top: var(--x-popup-cut-top-at-area);
|
|
56522
|
+
--x-popup-cut-right: var(--x-popup-cut-right-at-area);
|
|
56451
56523
|
}
|
|
56452
56524
|
&[navi-animation="slide-from-bottom-left"] {
|
|
56453
56525
|
--x-popup-slide-x: -1;
|
|
56454
56526
|
--x-popup-slide-y: 1;
|
|
56527
|
+
--x-popup-cut-bottom: var(--x-popup-cut-bottom-at-area);
|
|
56528
|
+
--x-popup-cut-left: var(--x-popup-cut-left-at-area);
|
|
56455
56529
|
}
|
|
56456
56530
|
&[navi-animation="slide-from-bottom-right"] {
|
|
56457
56531
|
--x-popup-slide-x: 1;
|
|
56458
56532
|
--x-popup-slide-y: 1;
|
|
56533
|
+
--x-popup-cut-bottom: var(--x-popup-cut-bottom-at-area);
|
|
56534
|
+
--x-popup-cut-right: var(--x-popup-cut-right-at-area);
|
|
56459
56535
|
}
|
|
56460
56536
|
&[navi-animation="slide-from-top"],
|
|
56461
56537
|
&[navi-animation="slide-from-bottom"],
|
|
@@ -56466,32 +56542,35 @@ const popupCss = /* css */ `
|
|
|
56466
56542
|
&[navi-animation="slide-from-bottom-left"],
|
|
56467
56543
|
&[navi-animation="slide-from-bottom-right"] {
|
|
56468
56544
|
opacity: 1;
|
|
56469
|
-
/*
|
|
56470
|
-
|
|
56471
|
-
|
|
56472
|
-
(
|
|
56473
|
-
|
|
56474
|
-
|
|
56475
|
-
|
|
56476
|
-
|
|
56477
|
-
(
|
|
56478
|
-
|
|
56479
|
-
|
|
56480
|
-
|
|
56481
|
-
--x-popup-cut-
|
|
56545
|
+
/* Where the area the popup was placed in has its edges, in the popup's
|
|
56546
|
+
own coordinates: --container-position-room-* is how far past each of
|
|
56547
|
+
its own edges the popup may still paint before reaching that edge
|
|
56548
|
+
(applyNewPosition in @jsenv/dom), so the negated value puts a cut ON
|
|
56549
|
+
it. Only the side(s) the travel comes from take one (see the direction
|
|
56550
|
+
rules above); the rest stay far outside the box, uncut. A popup that
|
|
56551
|
+
was never placed reads 100vmax and is not cut at all.
|
|
56552
|
+
Outside that area is either the glass beside an app narrowed with
|
|
56553
|
+
--navi-app-max-width (layout/safe_area.js) or whatever surrounds a
|
|
56554
|
+
container — neither the popup's to paint, and a popup in the top layer
|
|
56555
|
+
answers to no overflow of the document. The popup itself is never cut
|
|
56556
|
+
either: the rooms floor at 0. */
|
|
56557
|
+
--x-popup-cut-top-at-area: calc(
|
|
56558
|
+
-1 * var(--container-position-room-top, 100vmax)
|
|
56559
|
+
);
|
|
56560
|
+
--x-popup-cut-right-at-area: calc(
|
|
56482
56561
|
-1 * var(--container-position-room-right, 100vmax)
|
|
56483
56562
|
);
|
|
56484
|
-
--x-popup-cut-bottom: calc(
|
|
56563
|
+
--x-popup-cut-bottom-at-area: calc(
|
|
56485
56564
|
-1 * var(--container-position-room-bottom, 100vmax)
|
|
56486
56565
|
);
|
|
56487
|
-
--x-popup-cut-left: calc(
|
|
56566
|
+
--x-popup-cut-left-at-area: calc(
|
|
56488
56567
|
-1 * var(--container-position-room-left, 100vmax)
|
|
56489
56568
|
);
|
|
56490
56569
|
--x-popup-travel-x: calc(var(--x-popup-slide-x, 0) * 100%);
|
|
56491
56570
|
--x-popup-travel-y: calc(var(--x-popup-slide-y, -1) * 100%);
|
|
56492
56571
|
clip-path: inset(
|
|
56493
|
-
var(--x-popup-cut-top) var(--x-popup-cut-right)
|
|
56494
|
-
var(--x-popup-cut-bottom) var(--x-popup-cut-left)
|
|
56572
|
+
var(--x-popup-cut-top, -100vmax) var(--x-popup-cut-right, -100vmax)
|
|
56573
|
+
var(--x-popup-cut-bottom, -100vmax) var(--x-popup-cut-left, -100vmax)
|
|
56495
56574
|
);
|
|
56496
56575
|
|
|
56497
56576
|
transform: translate(0px, 0px);
|
|
@@ -56505,10 +56584,10 @@ const popupCss = /* css */ `
|
|
|
56505
56584
|
ends of the transition — and so at every instant in between, the two
|
|
56506
56585
|
interpolating over one duration and one easing. */
|
|
56507
56586
|
clip-path: inset(
|
|
56508
|
-
calc(var(--x-popup-cut-top) - var(--x-popup-travel-y))
|
|
56509
|
-
calc(var(--x-popup-cut-right) + var(--x-popup-travel-x))
|
|
56510
|
-
calc(var(--x-popup-cut-bottom) + var(--x-popup-travel-y))
|
|
56511
|
-
calc(var(--x-popup-cut-left) - var(--x-popup-travel-x))
|
|
56587
|
+
calc(var(--x-popup-cut-top, -100vmax) - var(--x-popup-travel-y))
|
|
56588
|
+
calc(var(--x-popup-cut-right, -100vmax) + var(--x-popup-travel-x))
|
|
56589
|
+
calc(var(--x-popup-cut-bottom, -100vmax) + var(--x-popup-travel-y))
|
|
56590
|
+
calc(var(--x-popup-cut-left, -100vmax) - var(--x-popup-travel-x))
|
|
56512
56591
|
);
|
|
56513
56592
|
transform: translate(var(--x-popup-travel-x), var(--x-popup-travel-y));
|
|
56514
56593
|
}
|
|
@@ -56731,7 +56810,7 @@ const createSwipeToClose = (side, { grip } = {}) => {
|
|
|
56731
56810
|
// composes under the placement instead of replacing it.
|
|
56732
56811
|
const styleAt = (distance) => ({
|
|
56733
56812
|
transform: translateOf(axis, distance),
|
|
56734
|
-
clipPath: clipOf(
|
|
56813
|
+
clipPath: clipOf(side, distance),
|
|
56735
56814
|
});
|
|
56736
56815
|
const paint = (distance) => {
|
|
56737
56816
|
Object.assign(panelEl.style, styleAt(distance));
|
|
@@ -56819,21 +56898,27 @@ const translateOf = (axis, distance) =>
|
|
|
56819
56898
|
? `translate(${distance}px, 0px)`
|
|
56820
56899
|
: `translate(0px, ${distance}px)`;
|
|
56821
56900
|
// The same cut the entry/exit animation makes (popup_css.js), at a distance the
|
|
56822
|
-
// finger decides instead of a transition:
|
|
56823
|
-
// room ran out (--container-position-room-*, written
|
|
56824
|
-
//
|
|
56825
|
-
//
|
|
56826
|
-
//
|
|
56827
|
-
|
|
56828
|
-
|
|
56829
|
-
|
|
56830
|
-
|
|
56831
|
-
|
|
56832
|
-
|
|
56833
|
-
|
|
56834
|
-
|
|
56835
|
-
|
|
56836
|
-
)
|
|
56901
|
+
// finger decides instead of a transition: the edge the popup is pushed back
|
|
56902
|
+
// through sits where its own room ran out (--container-position-room-*, written
|
|
56903
|
+
// by applyNewPosition), plus what has been pulled, so the cut holds that line
|
|
56904
|
+
// while the box travels under it. The three other sides are left far outside
|
|
56905
|
+
// the box — the pull never takes the popup past them, and cutting there would
|
|
56906
|
+
// only shave what it legitimately paints outside its own box. An unset room —
|
|
56907
|
+
// a popup that was never placed — reads 100vmax and cuts nothing.
|
|
56908
|
+
const UNCUT = "-100vmax";
|
|
56909
|
+
const clipOf = (side, distance) => {
|
|
56910
|
+
const pulled = distance < 0 ? -distance : distance;
|
|
56911
|
+
const cut = `calc(-1 * var(--container-position-room-${side}, 100vmax) + ${pulled}px)`;
|
|
56912
|
+
if (side === "top") {
|
|
56913
|
+
return `inset(${cut} ${UNCUT} ${UNCUT} ${UNCUT})`;
|
|
56914
|
+
}
|
|
56915
|
+
if (side === "right") {
|
|
56916
|
+
return `inset(${UNCUT} ${cut} ${UNCUT} ${UNCUT})`;
|
|
56917
|
+
}
|
|
56918
|
+
if (side === "bottom") {
|
|
56919
|
+
return `inset(${UNCUT} ${UNCUT} ${cut} ${UNCUT})`;
|
|
56920
|
+
}
|
|
56921
|
+
return `inset(${UNCUT} ${UNCUT} ${UNCUT} ${cut})`;
|
|
56837
56922
|
};
|
|
56838
56923
|
|
|
56839
56924
|
/**
|
|
@@ -74846,6 +74931,14 @@ function WheelUI(props) {
|
|
|
74846
74931
|
if (trackedItemsRef.current.length === 0) {
|
|
74847
74932
|
return;
|
|
74848
74933
|
}
|
|
74934
|
+
// Without a box (display: none, rows not laid out yet) every position below
|
|
74935
|
+
// multiplies by an item size of 0: nothing can be placed. Leave
|
|
74936
|
+
// centeredIndexRef null rather than claim a row is centered, so the render
|
|
74937
|
+
// that brings the wheel back on screen doesn't read it as "already there".
|
|
74938
|
+
if (getItemSize(viewportEl) === 0) {
|
|
74939
|
+
centeredIndexRef.current = null;
|
|
74940
|
+
return;
|
|
74941
|
+
}
|
|
74849
74942
|
let selectedIndex = getIndexForValue(currentValueRef.current);
|
|
74850
74943
|
if (selectedIndex < 0) {
|
|
74851
74944
|
selectedIndex = 0;
|
|
@@ -74892,7 +74985,7 @@ function WheelUI(props) {
|
|
|
74892
74985
|
const requestedBehavior = pendingBehaviorRef.current;
|
|
74893
74986
|
pendingBehaviorRef.current = null;
|
|
74894
74987
|
const viewportEl = getViewport();
|
|
74895
|
-
if (!viewportEl
|
|
74988
|
+
if (!viewportEl) {
|
|
74896
74989
|
return;
|
|
74897
74990
|
}
|
|
74898
74991
|
let behavior = "auto";
|