@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/dev/jsenv_navi.js
CHANGED
|
@@ -11232,6 +11232,10 @@ const isMac = detectMac();
|
|
|
11232
11232
|
* it, which is the hand saying it has moved on. What answers "away" is the same
|
|
11233
11233
|
* thing that closes a popup, and the surface is the one that watches for it, so
|
|
11234
11234
|
* an application never keeps a `pointerdown` listener on the window to know.
|
|
11235
|
+
* `[data-hand-kept]` is on the element for as long as it holds the hand that
|
|
11236
|
+
* way, so the paid wait can be drawn — a page darkened around a plan that
|
|
11237
|
+
* answers on contact now. `[data-grabbed]` stays the narrower one: a hand on it
|
|
11238
|
+
* at this instant.
|
|
11235
11239
|
*
|
|
11236
11240
|
* The WHEEL is the same question asked of a mouse, and it is not asked of the
|
|
11237
11241
|
* caller at all: a wheel event is read rather than settled beforehand, so
|
|
@@ -27867,7 +27871,7 @@ installImportMetaCssBuild(import.meta);
|
|
|
27867
27871
|
|
|
27868
27872
|
/**
|
|
27869
27873
|
* The window two pages are seen through while one replaces the other, measured
|
|
27870
|
-
*
|
|
27874
|
+
* at the one moment both exist and published for the length of the movement.
|
|
27871
27875
|
*
|
|
27872
27876
|
* Both ways of moving from one route to another need the same numbers, so they
|
|
27873
27877
|
* are written under the same names and read by the same CSS formulas —
|
|
@@ -27892,6 +27896,18 @@ installImportMetaCssBuild(import.meta);
|
|
|
27892
27896
|
* in the window — one page is scrolled and the other is not, one has a top
|
|
27893
27897
|
* bar over it and the other has the screen. Each picture is placed at its
|
|
27894
27898
|
* own corner inside the window.
|
|
27899
|
+
* - **where the arriving state IS, frame after frame.** The browser places the
|
|
27900
|
+
* group from the live arriving element on every frame of the movement — that
|
|
27901
|
+
* is what makes a picture pair follow an element that moves — and the
|
|
27902
|
+
* formula that moves the group back to the window's corner cancels that
|
|
27903
|
+
* placement with this corner. Read once, the two stop cancelling the moment
|
|
27904
|
+
* anything scrolls the document under the movement (a slice landing and
|
|
27905
|
+
* putting a row back, a list placing its default row, a height growing under
|
|
27906
|
+
* a restored offset): the window drifts by as much, and both pictures with
|
|
27907
|
+
* it — the photograph of the page being left included. So this corner alone
|
|
27908
|
+
* is kept live, as often as the browser reads its side of it. It is also
|
|
27909
|
+
* the arriving picture's own corner, which then stays where the page really
|
|
27910
|
+
* is and lands with no jump when the pictures are dropped.
|
|
27895
27911
|
* - **the band the state being left kept free**, next to the one the arriving
|
|
27896
27912
|
* state keeps free. A band is furniture — a fixed bar, a sticky row — and
|
|
27897
27913
|
* the pictures are cut at it so they are not watched painting over it. Read
|
|
@@ -27901,8 +27917,11 @@ installImportMetaCssBuild(import.meta);
|
|
|
27901
27917
|
* at the one moment the state being left still exists, the cut can be taken
|
|
27902
27918
|
* at what is furniture on BOTH sides (see the clip formulas).
|
|
27903
27919
|
*
|
|
27904
|
-
* Only the measuring needs JS, and
|
|
27905
|
-
* the page arriving is in the DOM and the
|
|
27920
|
+
* Only the measuring needs JS, and apart from the arriving corner it happens
|
|
27921
|
+
* at the one moment both states exist: the page arriving is in the DOM and the
|
|
27922
|
+
* transition has not started playing. The window, the corner of the state
|
|
27923
|
+
* being left and its band describe a state that no longer exists, and reading
|
|
27924
|
+
* them again is what must never happen.
|
|
27906
27925
|
* Everything DERIVED from these numbers — the band a fixed bar covers, how far
|
|
27907
27926
|
* a page travels — is derived in CSS, so the application's own numbers (the
|
|
27908
27927
|
* room its bars give back, see layout/safe_area.js; what covers the box from
|
|
@@ -28003,6 +28022,8 @@ const WINDOW_PROPERTIES = [
|
|
|
28003
28022
|
// after another has replaced it must not wipe numbers the new one is standing
|
|
28004
28023
|
// on.
|
|
28005
28024
|
let windowOwner = null;
|
|
28025
|
+
// Stops re-reading the arriving state's corner, when a movement is on.
|
|
28026
|
+
let unfollowArrivingState = null;
|
|
28006
28027
|
|
|
28007
28028
|
/**
|
|
28008
28029
|
* The state being left, taken while rendering is held — the page arriving is
|
|
@@ -28048,6 +28069,7 @@ const holdTransitionWindow = (owner, element, stateBefore) => {
|
|
|
28048
28069
|
style.setProperty(OLD_BAND_RIGHT_PROPERTY, `${oldBand.right}px`);
|
|
28049
28070
|
style.setProperty(OLD_BAND_BOTTOM_PROPERTY, `${oldBand.bottom}px`);
|
|
28050
28071
|
style.setProperty(OLD_BAND_LEFT_PROPERTY, `${oldBand.left}px`);
|
|
28072
|
+
followArrivingState(element, rectAfter);
|
|
28051
28073
|
};
|
|
28052
28074
|
|
|
28053
28075
|
// The live layout takes the box back. A discontinuity by construction — the
|
|
@@ -28059,12 +28081,45 @@ const releaseTransitionWindow = (owner) => {
|
|
|
28059
28081
|
return;
|
|
28060
28082
|
}
|
|
28061
28083
|
windowOwner = null;
|
|
28084
|
+
if (unfollowArrivingState) {
|
|
28085
|
+
unfollowArrivingState();
|
|
28086
|
+
}
|
|
28062
28087
|
const { style } = document.documentElement;
|
|
28063
28088
|
for (const property of WINDOW_PROPERTIES) {
|
|
28064
28089
|
style.removeProperty(property);
|
|
28065
28090
|
}
|
|
28066
28091
|
};
|
|
28067
28092
|
|
|
28093
|
+
// The arriving state's corner, re-read every frame — as often as the browser
|
|
28094
|
+
// refreshes the group's placement from the same element (see the top of the
|
|
28095
|
+
// file). Requested, never awaited: the first call runs inside the update
|
|
28096
|
+
// callback, where a frame cannot come. Written only when it moved: a custom
|
|
28097
|
+
// property set on the root recomputes the style of the whole document.
|
|
28098
|
+
const followArrivingState = (element, rectAtHold) => {
|
|
28099
|
+
if (unfollowArrivingState) {
|
|
28100
|
+
unfollowArrivingState();
|
|
28101
|
+
}
|
|
28102
|
+
const { style } = document.documentElement;
|
|
28103
|
+
let top = rectAtHold.top;
|
|
28104
|
+
let left = rectAtHold.left;
|
|
28105
|
+
let frame = requestAnimationFrame(function read() {
|
|
28106
|
+
const rect = element.getBoundingClientRect();
|
|
28107
|
+
if (rect.top !== top) {
|
|
28108
|
+
top = rect.top;
|
|
28109
|
+
style.setProperty(WINDOW_NEW_TOP_PROPERTY, `${top}px`);
|
|
28110
|
+
}
|
|
28111
|
+
if (rect.left !== left) {
|
|
28112
|
+
left = rect.left;
|
|
28113
|
+
style.setProperty(WINDOW_NEW_LEFT_PROPERTY, `${left}px`);
|
|
28114
|
+
}
|
|
28115
|
+
frame = requestAnimationFrame(read);
|
|
28116
|
+
});
|
|
28117
|
+
unfollowArrivingState = () => {
|
|
28118
|
+
unfollowArrivingState = null;
|
|
28119
|
+
cancelAnimationFrame(frame);
|
|
28120
|
+
};
|
|
28121
|
+
};
|
|
28122
|
+
|
|
28068
28123
|
// A band nothing can be wider than, published for an edge nothing is known
|
|
28069
28124
|
// about: taken as the smaller of the two, it leaves the live band standing on
|
|
28070
28125
|
// its own, which is the movement navi played before it knew any of this.
|
|
@@ -57000,8 +57055,9 @@ const getAvailableWidth = (layer, element) => {
|
|
|
57000
57055
|
*
|
|
57001
57056
|
* `animation="slide-from-*"` (anchorReference/point mode only): a real
|
|
57002
57057
|
* translate-based entrance, 8 directions (cardinal + 4 diagonals), each
|
|
57003
|
-
* 100%-of-own-size, cut
|
|
57004
|
-
*
|
|
57058
|
+
* 100%-of-own-size, cut on the side it comes from — at the edge of the area it
|
|
57059
|
+
* was placed in, so the part of the travel that happens outside that area is
|
|
57060
|
+
* not watched crossing it. It travels through `transform`, not through the
|
|
57005
57061
|
* `translate` property, which belongs to the popup's own placement
|
|
57006
57062
|
* (applyNewPosition in visible_rect.js — see its doc for why the placement is
|
|
57007
57063
|
* a transform at all, and why it has to be the outermost one: the individual
|
|
@@ -57102,38 +57158,58 @@ const popupCss = /* css */ `
|
|
|
57102
57158
|
|
|
57103
57159
|
/* slide — anchorReference/point mode family: direction multipliers,
|
|
57104
57160
|
one per concrete navi-animation value, 100%-of-own-size distance
|
|
57105
|
-
(see this file's top comment).
|
|
57161
|
+
(see this file's top comment).
|
|
57162
|
+
Each also names the side(s) it comes from, as a cut placed on the edge
|
|
57163
|
+
of the area the popup was placed in — and ONLY those sides: a popup
|
|
57164
|
+
travelling down crosses the top edge of that area and no other, so
|
|
57165
|
+
cutting the three it never reaches would take away what it legitimately
|
|
57166
|
+
paints outside its own box (its shadow, a popup opened from inside it)
|
|
57167
|
+
for nothing. A drawer the width of the app is the case that shows it:
|
|
57168
|
+
its room to the left and right is zero, and cutting there would shave
|
|
57169
|
+
its sides flat. See the shared rule below for what the cut is. */
|
|
57106
57170
|
&[navi-animation="slide-from-top"] {
|
|
57107
57171
|
--x-popup-slide-x: 0;
|
|
57108
57172
|
--x-popup-slide-y: -1;
|
|
57173
|
+
--x-popup-cut-top: var(--x-popup-cut-top-at-area);
|
|
57109
57174
|
}
|
|
57110
57175
|
&[navi-animation="slide-from-bottom"] {
|
|
57111
57176
|
--x-popup-slide-x: 0;
|
|
57112
57177
|
--x-popup-slide-y: 1;
|
|
57178
|
+
--x-popup-cut-bottom: var(--x-popup-cut-bottom-at-area);
|
|
57113
57179
|
}
|
|
57114
57180
|
&[navi-animation="slide-from-left"] {
|
|
57115
57181
|
--x-popup-slide-x: -1;
|
|
57116
57182
|
--x-popup-slide-y: 0;
|
|
57183
|
+
--x-popup-cut-left: var(--x-popup-cut-left-at-area);
|
|
57117
57184
|
}
|
|
57118
57185
|
&[navi-animation="slide-from-right"] {
|
|
57119
57186
|
--x-popup-slide-x: 1;
|
|
57120
57187
|
--x-popup-slide-y: 0;
|
|
57188
|
+
--x-popup-cut-right: var(--x-popup-cut-right-at-area);
|
|
57121
57189
|
}
|
|
57122
57190
|
&[navi-animation="slide-from-top-left"] {
|
|
57123
57191
|
--x-popup-slide-x: -1;
|
|
57124
57192
|
--x-popup-slide-y: -1;
|
|
57193
|
+
--x-popup-cut-top: var(--x-popup-cut-top-at-area);
|
|
57194
|
+
--x-popup-cut-left: var(--x-popup-cut-left-at-area);
|
|
57125
57195
|
}
|
|
57126
57196
|
&[navi-animation="slide-from-top-right"] {
|
|
57127
57197
|
--x-popup-slide-x: 1;
|
|
57128
57198
|
--x-popup-slide-y: -1;
|
|
57199
|
+
--x-popup-cut-top: var(--x-popup-cut-top-at-area);
|
|
57200
|
+
--x-popup-cut-right: var(--x-popup-cut-right-at-area);
|
|
57129
57201
|
}
|
|
57130
57202
|
&[navi-animation="slide-from-bottom-left"] {
|
|
57131
57203
|
--x-popup-slide-x: -1;
|
|
57132
57204
|
--x-popup-slide-y: 1;
|
|
57205
|
+
--x-popup-cut-bottom: var(--x-popup-cut-bottom-at-area);
|
|
57206
|
+
--x-popup-cut-left: var(--x-popup-cut-left-at-area);
|
|
57133
57207
|
}
|
|
57134
57208
|
&[navi-animation="slide-from-bottom-right"] {
|
|
57135
57209
|
--x-popup-slide-x: 1;
|
|
57136
57210
|
--x-popup-slide-y: 1;
|
|
57211
|
+
--x-popup-cut-bottom: var(--x-popup-cut-bottom-at-area);
|
|
57212
|
+
--x-popup-cut-right: var(--x-popup-cut-right-at-area);
|
|
57137
57213
|
}
|
|
57138
57214
|
&[navi-animation="slide-from-top"],
|
|
57139
57215
|
&[navi-animation="slide-from-bottom"],
|
|
@@ -57144,32 +57220,35 @@ const popupCss = /* css */ `
|
|
|
57144
57220
|
&[navi-animation="slide-from-bottom-left"],
|
|
57145
57221
|
&[navi-animation="slide-from-bottom-right"] {
|
|
57146
57222
|
opacity: 1;
|
|
57147
|
-
/*
|
|
57148
|
-
|
|
57149
|
-
|
|
57150
|
-
(
|
|
57151
|
-
|
|
57152
|
-
|
|
57153
|
-
|
|
57154
|
-
|
|
57155
|
-
(
|
|
57156
|
-
|
|
57157
|
-
|
|
57158
|
-
|
|
57159
|
-
--x-popup-cut-
|
|
57223
|
+
/* Where the area the popup was placed in has its edges, in the popup's
|
|
57224
|
+
own coordinates: --container-position-room-* is how far past each of
|
|
57225
|
+
its own edges the popup may still paint before reaching that edge
|
|
57226
|
+
(applyNewPosition in @jsenv/dom), so the negated value puts a cut ON
|
|
57227
|
+
it. Only the side(s) the travel comes from take one (see the direction
|
|
57228
|
+
rules above); the rest stay far outside the box, uncut. A popup that
|
|
57229
|
+
was never placed reads 100vmax and is not cut at all.
|
|
57230
|
+
Outside that area is either the glass beside an app narrowed with
|
|
57231
|
+
--navi-app-max-width (layout/safe_area.js) or whatever surrounds a
|
|
57232
|
+
container — neither the popup's to paint, and a popup in the top layer
|
|
57233
|
+
answers to no overflow of the document. The popup itself is never cut
|
|
57234
|
+
either: the rooms floor at 0. */
|
|
57235
|
+
--x-popup-cut-top-at-area: calc(
|
|
57236
|
+
-1 * var(--container-position-room-top, 100vmax)
|
|
57237
|
+
);
|
|
57238
|
+
--x-popup-cut-right-at-area: calc(
|
|
57160
57239
|
-1 * var(--container-position-room-right, 100vmax)
|
|
57161
57240
|
);
|
|
57162
|
-
--x-popup-cut-bottom: calc(
|
|
57241
|
+
--x-popup-cut-bottom-at-area: calc(
|
|
57163
57242
|
-1 * var(--container-position-room-bottom, 100vmax)
|
|
57164
57243
|
);
|
|
57165
|
-
--x-popup-cut-left: calc(
|
|
57244
|
+
--x-popup-cut-left-at-area: calc(
|
|
57166
57245
|
-1 * var(--container-position-room-left, 100vmax)
|
|
57167
57246
|
);
|
|
57168
57247
|
--x-popup-travel-x: calc(var(--x-popup-slide-x, 0) * 100%);
|
|
57169
57248
|
--x-popup-travel-y: calc(var(--x-popup-slide-y, -1) * 100%);
|
|
57170
57249
|
clip-path: inset(
|
|
57171
|
-
var(--x-popup-cut-top) var(--x-popup-cut-right)
|
|
57172
|
-
var(--x-popup-cut-bottom) var(--x-popup-cut-left)
|
|
57250
|
+
var(--x-popup-cut-top, -100vmax) var(--x-popup-cut-right, -100vmax)
|
|
57251
|
+
var(--x-popup-cut-bottom, -100vmax) var(--x-popup-cut-left, -100vmax)
|
|
57173
57252
|
);
|
|
57174
57253
|
|
|
57175
57254
|
transform: translate(0px, 0px);
|
|
@@ -57183,10 +57262,10 @@ const popupCss = /* css */ `
|
|
|
57183
57262
|
ends of the transition — and so at every instant in between, the two
|
|
57184
57263
|
interpolating over one duration and one easing. */
|
|
57185
57264
|
clip-path: inset(
|
|
57186
|
-
calc(var(--x-popup-cut-top) - var(--x-popup-travel-y))
|
|
57187
|
-
calc(var(--x-popup-cut-right) + var(--x-popup-travel-x))
|
|
57188
|
-
calc(var(--x-popup-cut-bottom) + var(--x-popup-travel-y))
|
|
57189
|
-
calc(var(--x-popup-cut-left) - var(--x-popup-travel-x))
|
|
57265
|
+
calc(var(--x-popup-cut-top, -100vmax) - var(--x-popup-travel-y))
|
|
57266
|
+
calc(var(--x-popup-cut-right, -100vmax) + var(--x-popup-travel-x))
|
|
57267
|
+
calc(var(--x-popup-cut-bottom, -100vmax) + var(--x-popup-travel-y))
|
|
57268
|
+
calc(var(--x-popup-cut-left, -100vmax) - var(--x-popup-travel-x))
|
|
57190
57269
|
);
|
|
57191
57270
|
transform: translate(var(--x-popup-travel-x), var(--x-popup-travel-y));
|
|
57192
57271
|
}
|
|
@@ -57409,7 +57488,7 @@ const createSwipeToClose = (side, { grip } = {}) => {
|
|
|
57409
57488
|
// composes under the placement instead of replacing it.
|
|
57410
57489
|
const styleAt = (distance) => ({
|
|
57411
57490
|
transform: translateOf(axis, distance),
|
|
57412
|
-
clipPath: clipOf(
|
|
57491
|
+
clipPath: clipOf(side, distance),
|
|
57413
57492
|
});
|
|
57414
57493
|
const paint = (distance) => {
|
|
57415
57494
|
Object.assign(panelEl.style, styleAt(distance));
|
|
@@ -57497,21 +57576,27 @@ const translateOf = (axis, distance) =>
|
|
|
57497
57576
|
? `translate(${distance}px, 0px)`
|
|
57498
57577
|
: `translate(0px, ${distance}px)`;
|
|
57499
57578
|
// The same cut the entry/exit animation makes (popup_css.js), at a distance the
|
|
57500
|
-
// finger decides instead of a transition:
|
|
57501
|
-
// room ran out (--container-position-room-*, written
|
|
57502
|
-
//
|
|
57503
|
-
//
|
|
57504
|
-
//
|
|
57505
|
-
|
|
57506
|
-
|
|
57507
|
-
|
|
57508
|
-
|
|
57509
|
-
|
|
57510
|
-
|
|
57511
|
-
|
|
57512
|
-
|
|
57513
|
-
|
|
57514
|
-
)
|
|
57579
|
+
// finger decides instead of a transition: the edge the popup is pushed back
|
|
57580
|
+
// through sits where its own room ran out (--container-position-room-*, written
|
|
57581
|
+
// by applyNewPosition), plus what has been pulled, so the cut holds that line
|
|
57582
|
+
// while the box travels under it. The three other sides are left far outside
|
|
57583
|
+
// the box — the pull never takes the popup past them, and cutting there would
|
|
57584
|
+
// only shave what it legitimately paints outside its own box. An unset room —
|
|
57585
|
+
// a popup that was never placed — reads 100vmax and cuts nothing.
|
|
57586
|
+
const UNCUT = "-100vmax";
|
|
57587
|
+
const clipOf = (side, distance) => {
|
|
57588
|
+
const pulled = distance < 0 ? -distance : distance;
|
|
57589
|
+
const cut = `calc(-1 * var(--container-position-room-${side}, 100vmax) + ${pulled}px)`;
|
|
57590
|
+
if (side === "top") {
|
|
57591
|
+
return `inset(${cut} ${UNCUT} ${UNCUT} ${UNCUT})`;
|
|
57592
|
+
}
|
|
57593
|
+
if (side === "right") {
|
|
57594
|
+
return `inset(${UNCUT} ${cut} ${UNCUT} ${UNCUT})`;
|
|
57595
|
+
}
|
|
57596
|
+
if (side === "bottom") {
|
|
57597
|
+
return `inset(${UNCUT} ${UNCUT} ${cut} ${UNCUT})`;
|
|
57598
|
+
}
|
|
57599
|
+
return `inset(${UNCUT} ${UNCUT} ${UNCUT} ${cut})`;
|
|
57515
57600
|
};
|
|
57516
57601
|
|
|
57517
57602
|
/**
|
|
@@ -76064,6 +76149,14 @@ function WheelUI(props) {
|
|
|
76064
76149
|
if (trackedItemsRef.current.length === 0) {
|
|
76065
76150
|
return;
|
|
76066
76151
|
}
|
|
76152
|
+
// Without a box (display: none, rows not laid out yet) every position below
|
|
76153
|
+
// multiplies by an item size of 0: nothing can be placed. Leave
|
|
76154
|
+
// centeredIndexRef null rather than claim a row is centered, so the render
|
|
76155
|
+
// that brings the wheel back on screen doesn't read it as "already there".
|
|
76156
|
+
if (getItemSize(viewportEl) === 0) {
|
|
76157
|
+
centeredIndexRef.current = null;
|
|
76158
|
+
return;
|
|
76159
|
+
}
|
|
76067
76160
|
let selectedIndex = getIndexForValue(currentValueRef.current);
|
|
76068
76161
|
if (selectedIndex < 0) {
|
|
76069
76162
|
selectedIndex = 0;
|
|
@@ -76110,7 +76203,7 @@ function WheelUI(props) {
|
|
|
76110
76203
|
const requestedBehavior = pendingBehaviorRef.current;
|
|
76111
76204
|
pendingBehaviorRef.current = null;
|
|
76112
76205
|
const viewportEl = getViewport();
|
|
76113
|
-
if (!viewportEl
|
|
76206
|
+
if (!viewportEl) {
|
|
76114
76207
|
return;
|
|
76115
76208
|
}
|
|
76116
76209
|
let behavior = "auto";
|