@jsenv/navi 0.30.6 → 0.30.7
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 +147 -45
- package/dist/dev/jsenv_navi.js.map +4 -4
- package/dist/jsenv_navi.js +143 -44
- package/dist/jsenv_navi.js.map +4 -4
- package/docs/drag_to_travel.md +5 -4
- package/package.json +1 -1
package/dist/dev/jsenv_navi.js
CHANGED
|
@@ -41679,17 +41679,19 @@ const STOPPED_SILENCE = 150;
|
|
|
41679
41679
|
const isOnRow = (page) =>
|
|
41680
41680
|
page.offsetWidth > 0 && !page.hasAttribute("data-off-row");
|
|
41681
41681
|
|
|
41682
|
-
|
|
41682
|
+
// `sideways`: see readRowStretch.
|
|
41683
|
+
const restsOn = (scroller, page, { sideways } = {}) =>
|
|
41683
41684
|
Math.abs(page.offsetLeft - scroller.scrollLeft) <= AT_REST_DISTANCE &&
|
|
41684
|
-
|
|
41685
|
+
(sideways ||
|
|
41686
|
+
Math.abs(page.offsetTop - scroller.scrollTop) <= AT_REST_DISTANCE);
|
|
41685
41687
|
|
|
41686
41688
|
/**
|
|
41687
41689
|
* @returns {Element|undefined} the page the row rests on, nothing while it stands
|
|
41688
41690
|
* between two: a hand can pause midway, and an engine may call that the end of
|
|
41689
41691
|
* a scroll.
|
|
41690
41692
|
*/
|
|
41691
|
-
const pageAtRest = (scroller, pages) =>
|
|
41692
|
-
pages.find((page) => isOnRow(page) && restsOn(scroller, page));
|
|
41693
|
+
const pageAtRest = (scroller, pages, options) =>
|
|
41694
|
+
pages.find((page) => isOnRow(page) && restsOn(scroller, page, options));
|
|
41693
41695
|
|
|
41694
41696
|
/**
|
|
41695
41697
|
* Where the row stands between two neighbouring pages, on the side it has moved
|
|
@@ -41697,14 +41699,18 @@ const pageAtRest = (scroller, pages) =>
|
|
|
41697
41699
|
* since is walked over. A map moves along one axis at a time, the one it has
|
|
41698
41700
|
* moved furthest on.
|
|
41699
41701
|
*
|
|
41702
|
+
* @param {object} [options]
|
|
41703
|
+
* @param {boolean} [options.sideways] - a row with one line, whatever `offsetTop` its
|
|
41704
|
+
* pages read: a page pinned with `top` is still on it.
|
|
41700
41705
|
* @returns {{base: Element, toward: Element|undefined, fraction: number, forward: boolean}}
|
|
41701
41706
|
* the last page the row has passed (`page` itself until then), the one after,
|
|
41702
41707
|
* and how far between the two from 0 to 1. Nothing `toward` past the last.
|
|
41703
41708
|
*/
|
|
41704
|
-
const readRowStretch = (scroller, pages, page) => {
|
|
41709
|
+
const readRowStretch = (scroller, pages, page, { sideways } = {}) => {
|
|
41705
41710
|
const alongX =
|
|
41711
|
+
sideways ||
|
|
41706
41712
|
Math.abs(scroller.scrollLeft - page.offsetLeft) >=
|
|
41707
|
-
|
|
41713
|
+
Math.abs(scroller.scrollTop - page.offsetTop);
|
|
41708
41714
|
const position = alongX ? "offsetLeft" : "offsetTop";
|
|
41709
41715
|
const cross = alongX ? "offsetTop" : "offsetLeft";
|
|
41710
41716
|
const scrolled = alongX ? scroller.scrollLeft : scroller.scrollTop;
|
|
@@ -41712,7 +41718,8 @@ const readRowStretch = (scroller, pages, page) => {
|
|
|
41712
41718
|
const step = forward ? 1 : -1;
|
|
41713
41719
|
const line = pages
|
|
41714
41720
|
.filter(
|
|
41715
|
-
(candidate) =>
|
|
41721
|
+
(candidate) =>
|
|
41722
|
+
isOnRow(candidate) && (sideways || candidate[cross] === page[cross]),
|
|
41716
41723
|
)
|
|
41717
41724
|
.sort((pageA, pageB) => pageA[position] - pageB[position]);
|
|
41718
41725
|
let index = line.indexOf(page);
|
|
@@ -41919,6 +41926,11 @@ const css$16 = /* css */`.navi_route_travel {
|
|
|
41919
41926
|
// there yet: past what a hand that only shook covers, so that a shake costs
|
|
41920
41927
|
// neither a navigation nor the requests of a page.
|
|
41921
41928
|
const SET_OFF_PULL = 16;
|
|
41929
|
+
// A row of routes is one line, whatever `offsetTop` its pinned panes read (see the pin
|
|
41930
|
+
// above): they are on it all the same.
|
|
41931
|
+
const ROW_READING = {
|
|
41932
|
+
sideways: true
|
|
41933
|
+
};
|
|
41922
41934
|
|
|
41923
41935
|
/**
|
|
41924
41936
|
* @type {import("preact").FunctionComponent<{
|
|
@@ -42092,10 +42104,7 @@ const RouteTravel = ({
|
|
|
42092
42104
|
const paneCurrent = panesOf(row)[currentIndex];
|
|
42093
42105
|
if (paneCurrent) {
|
|
42094
42106
|
movement.travelling = true;
|
|
42095
|
-
|
|
42096
|
-
left: paneCurrent.offsetLeft,
|
|
42097
|
-
behavior: "smooth"
|
|
42098
|
-
});
|
|
42107
|
+
travelRowTo(currentIndex, movement);
|
|
42099
42108
|
}
|
|
42100
42109
|
});
|
|
42101
42110
|
};
|
|
@@ -42112,7 +42121,7 @@ const RouteTravel = ({
|
|
|
42112
42121
|
base,
|
|
42113
42122
|
toward,
|
|
42114
42123
|
fraction
|
|
42115
|
-
} =
|
|
42124
|
+
} = readRowFrame(row, panes);
|
|
42116
42125
|
publishRouteRowMove({
|
|
42117
42126
|
basePath: pathOf(pages[panes.indexOf(base)]),
|
|
42118
42127
|
towardPath: toward ? pathOf(pages[panes.indexOf(toward)]) : null,
|
|
@@ -42120,6 +42129,81 @@ const RouteTravel = ({
|
|
|
42120
42129
|
});
|
|
42121
42130
|
};
|
|
42122
42131
|
|
|
42132
|
+
// A travel no hand set off is one box long however far the page is, as in a
|
|
42133
|
+
// SlideContainer: the browser's smooth scroll would fly past every page in between.
|
|
42134
|
+
// So the page asked for takes the column next to what is in the frame, on the side
|
|
42135
|
+
// it already stands, which moves nothing on screen, and endMovement puts the columns
|
|
42136
|
+
// back. Columns rather than offsets: every page stays a place to snap to, and none
|
|
42137
|
+
// has to be hidden.
|
|
42138
|
+
const travelRowTo = (index, movement) => {
|
|
42139
|
+
const row = rowRef.current;
|
|
42140
|
+
const panes = panesOf(row);
|
|
42141
|
+
const pane = panes[index];
|
|
42142
|
+
if (!pane) {
|
|
42143
|
+
return;
|
|
42144
|
+
}
|
|
42145
|
+
const {
|
|
42146
|
+
base,
|
|
42147
|
+
toward,
|
|
42148
|
+
fraction
|
|
42149
|
+
} = readRowFrame(row, panes);
|
|
42150
|
+
const inFrame = toward && fraction > 0 ? [base, toward] : [base];
|
|
42151
|
+
if (!inFrame.includes(pane)) {
|
|
42152
|
+
// In a window, what the window put in a column moves with its pane.
|
|
42153
|
+
const standingIn = paneIndex => {
|
|
42154
|
+
const standing = [panes[paneIndex]];
|
|
42155
|
+
if (windowed) {
|
|
42156
|
+
const picture = movement.pictures.get(paneIndex);
|
|
42157
|
+
if (picture) {
|
|
42158
|
+
standing.push(picture);
|
|
42159
|
+
}
|
|
42160
|
+
if (paneIndex === latestRef.current.liveIndex) {
|
|
42161
|
+
standing.push(liveRef.current);
|
|
42162
|
+
}
|
|
42163
|
+
}
|
|
42164
|
+
return standing;
|
|
42165
|
+
};
|
|
42166
|
+
const columns = [...panes].sort((a, b) => a.offsetLeft - b.offsetLeft);
|
|
42167
|
+
const first = columns.indexOf(inFrame[0]);
|
|
42168
|
+
const last = columns.indexOf(inFrame[inFrame.length - 1]);
|
|
42169
|
+
const from = columns.indexOf(pane);
|
|
42170
|
+
columns.splice(from, 1);
|
|
42171
|
+
columns.splice(from < first ? first - 1 : last + 1, 0, pane);
|
|
42172
|
+
movement.placed ||= new Map();
|
|
42173
|
+
columns.forEach((eachPane, column) => {
|
|
42174
|
+
for (const element of standingIn(panes.indexOf(eachPane))) {
|
|
42175
|
+
if (!movement.placed.has(element)) {
|
|
42176
|
+
movement.placed.set(element, element.style.gridColumn);
|
|
42177
|
+
}
|
|
42178
|
+
element.style.gridColumn = String(column + 1);
|
|
42179
|
+
}
|
|
42180
|
+
});
|
|
42181
|
+
}
|
|
42182
|
+
row.scrollTo({
|
|
42183
|
+
left: pane.offsetLeft,
|
|
42184
|
+
behavior: "smooth"
|
|
42185
|
+
});
|
|
42186
|
+
};
|
|
42187
|
+
|
|
42188
|
+
// Every column back where the map says, and the row on the page of the address, in
|
|
42189
|
+
// one go: that page stands at the same place on screen either way.
|
|
42190
|
+
const putRowBack = movement => {
|
|
42191
|
+
const row = rowRef.current;
|
|
42192
|
+
if (movement.placed) {
|
|
42193
|
+
for (const [element, column] of movement.placed) {
|
|
42194
|
+
element.style.gridColumn = column;
|
|
42195
|
+
}
|
|
42196
|
+
movement.placed = null;
|
|
42197
|
+
}
|
|
42198
|
+
const pane = panesOf(row)[latestRef.current.currentIndex];
|
|
42199
|
+
if (pane && !restsOn(row, pane, ROW_READING)) {
|
|
42200
|
+
row.scrollTo({
|
|
42201
|
+
left: pane.offsetLeft,
|
|
42202
|
+
behavior: "instant"
|
|
42203
|
+
});
|
|
42204
|
+
}
|
|
42205
|
+
};
|
|
42206
|
+
|
|
42123
42207
|
// A tab pressed over a row a hand has left moving, which the browser plays on and
|
|
42124
42208
|
// overwrites a travel with once that travel is over: the snap is ended first. Given
|
|
42125
42209
|
// back, the row stands where it stood. A frame later, because until then WebKit still
|
|
@@ -42140,12 +42224,8 @@ const RouteTravel = ({
|
|
|
42140
42224
|
row.setAttribute("data-route-row-taken", "");
|
|
42141
42225
|
row.style.removeProperty("--navi-route-row-stand");
|
|
42142
42226
|
afterFrames(1, () => {
|
|
42143
|
-
|
|
42144
|
-
|
|
42145
|
-
row.scrollTo({
|
|
42146
|
-
left: pane.offsetLeft,
|
|
42147
|
-
behavior: "smooth"
|
|
42148
|
-
});
|
|
42227
|
+
if (movementRef.current === movement) {
|
|
42228
|
+
travelRowTo(latestRef.current.currentIndex, movement);
|
|
42149
42229
|
}
|
|
42150
42230
|
});
|
|
42151
42231
|
});
|
|
@@ -42160,6 +42240,7 @@ const RouteTravel = ({
|
|
|
42160
42240
|
return;
|
|
42161
42241
|
}
|
|
42162
42242
|
movementRef.current = null;
|
|
42243
|
+
putRowBack(movement);
|
|
42163
42244
|
row.removeAttribute("data-moving");
|
|
42164
42245
|
row.removeAttribute("data-route-row-taken");
|
|
42165
42246
|
publishRouteRowMove(null);
|
|
@@ -42199,7 +42280,7 @@ const RouteTravel = ({
|
|
|
42199
42280
|
const pane = panesOf(row)[currentIndex];
|
|
42200
42281
|
const answered = answeredPageRef.current;
|
|
42201
42282
|
if (samePage(answered, page)) {
|
|
42202
|
-
if (pane && !movementRef.current && !restsOn(row, pane)) {
|
|
42283
|
+
if (pane && !movementRef.current && !restsOn(row, pane, ROW_READING)) {
|
|
42203
42284
|
row.scrollTo({
|
|
42204
42285
|
left: pane.offsetLeft,
|
|
42205
42286
|
behavior: "instant"
|
|
@@ -42215,13 +42296,13 @@ const RouteTravel = ({
|
|
|
42215
42296
|
if (asked && samePage(asked, page)) {
|
|
42216
42297
|
askedPageRef.current = null;
|
|
42217
42298
|
// The hand landed before the address did.
|
|
42218
|
-
if (movementRef.current?.landed && restsOn(row, pane)) {
|
|
42299
|
+
if (movementRef.current?.landed && restsOn(row, pane, ROW_READING)) {
|
|
42219
42300
|
Promise.resolve().then(endMovement);
|
|
42220
42301
|
}
|
|
42221
42302
|
return;
|
|
42222
42303
|
}
|
|
42223
|
-
if (!answered || restsOn(row, pane)) {
|
|
42224
|
-
if (!restsOn(row, pane)) {
|
|
42304
|
+
if (!answered || restsOn(row, pane, ROW_READING)) {
|
|
42305
|
+
if (!restsOn(row, pane, ROW_READING)) {
|
|
42225
42306
|
row.scrollTo({
|
|
42226
42307
|
left: pane.offsetLeft,
|
|
42227
42308
|
behavior: "instant"
|
|
@@ -42233,19 +42314,17 @@ const RouteTravel = ({
|
|
|
42233
42314
|
const movement = beginMovement({
|
|
42234
42315
|
travelling: true
|
|
42235
42316
|
});
|
|
42236
|
-
// In this very commit: the tab pressed already wears its bar, and the first
|
|
42237
|
-
// scroll event is a frame away.
|
|
42238
|
-
sayRowMoves();
|
|
42239
42317
|
if (movementBefore?.byHand && !movementBefore.rowTaken) {
|
|
42318
|
+
sayRowMoves();
|
|
42240
42319
|
takeRowFromHand(movement);
|
|
42241
42320
|
return;
|
|
42242
42321
|
}
|
|
42243
42322
|
if (row.getAttribute("data-route-row-taken") !== "clip") {
|
|
42244
|
-
|
|
42245
|
-
left: pane.offsetLeft,
|
|
42246
|
-
behavior: "smooth"
|
|
42247
|
-
});
|
|
42323
|
+
travelRowTo(currentIndex, movement);
|
|
42248
42324
|
}
|
|
42325
|
+
// In this very commit: the tab pressed already wears its bar, and the first
|
|
42326
|
+
// scroll event is a frame away.
|
|
42327
|
+
sayRowMoves();
|
|
42249
42328
|
});
|
|
42250
42329
|
|
|
42251
42330
|
// Somebody else is about to move the address to another page of a window: its
|
|
@@ -42292,7 +42371,7 @@ const RouteTravel = ({
|
|
|
42292
42371
|
}
|
|
42293
42372
|
const moving = movementRef.current;
|
|
42294
42373
|
const pane = panes[currentIndex];
|
|
42295
|
-
if (!moving && pane && restsOn(row, pane)) {
|
|
42374
|
+
if (!moving && pane && restsOn(row, pane, ROW_READING)) {
|
|
42296
42375
|
// Written by this box, at rest: nobody is moving anything.
|
|
42297
42376
|
return;
|
|
42298
42377
|
}
|
|
@@ -42311,7 +42390,7 @@ const RouteTravel = ({
|
|
|
42311
42390
|
base,
|
|
42312
42391
|
toward,
|
|
42313
42392
|
fraction
|
|
42314
|
-
} =
|
|
42393
|
+
} = readRowFrame(row, panes);
|
|
42315
42394
|
followPageOnScreen(pages[panes.indexOf(fraction >= 0.5 && toward ? toward : base)], askedPageRef.current || pages[currentIndex]);
|
|
42316
42395
|
}
|
|
42317
42396
|
const pulled = row.scrollLeft - pane.offsetLeft;
|
|
@@ -42351,7 +42430,7 @@ const RouteTravel = ({
|
|
|
42351
42430
|
const {
|
|
42352
42431
|
base,
|
|
42353
42432
|
toward
|
|
42354
|
-
} =
|
|
42433
|
+
} = readRowFrame(row, panes);
|
|
42355
42434
|
const index = panes.indexOf(forward && toward ? toward : base);
|
|
42356
42435
|
const page = pages[index];
|
|
42357
42436
|
if (!page) {
|
|
@@ -42370,8 +42449,18 @@ const RouteTravel = ({
|
|
|
42370
42449
|
return;
|
|
42371
42450
|
}
|
|
42372
42451
|
const panes = panesOf(row);
|
|
42373
|
-
const pane = pageAtRest(row, panes);
|
|
42452
|
+
const pane = pageAtRest(row, panes, ROW_READING);
|
|
42374
42453
|
if (!pane) {
|
|
42454
|
+
// A travel stopped short of its page: the layout moved under it (a scrollbar
|
|
42455
|
+
// coming in narrows the row), and where it was sent is not where the page
|
|
42456
|
+
// stands. Sent again: the row then rests, or does not move and is not heard.
|
|
42457
|
+
const target = panes[latestRef.current.currentIndex];
|
|
42458
|
+
if (movement.travelling && !isClipped() && target) {
|
|
42459
|
+
row.scrollTo({
|
|
42460
|
+
left: target.offsetLeft,
|
|
42461
|
+
behavior: "smooth"
|
|
42462
|
+
});
|
|
42463
|
+
}
|
|
42375
42464
|
return;
|
|
42376
42465
|
}
|
|
42377
42466
|
movement.landed = true;
|
|
@@ -42395,8 +42484,15 @@ const RouteTravel = ({
|
|
|
42395
42484
|
onLand,
|
|
42396
42485
|
onLeftToSnap
|
|
42397
42486
|
});
|
|
42398
|
-
// A
|
|
42399
|
-
|
|
42487
|
+
// A finger on a travel still playing: the row is the finger's from here, and it
|
|
42488
|
+
// stands where the travel was going, as in a SlideContainer. A wheel only gives the
|
|
42489
|
+
// row its snapping back: a page scrolled vertically over it is no hand on it.
|
|
42490
|
+
const onTouchOnTravel = () => {
|
|
42491
|
+
if (movementRef.current?.travelling && !isClipped()) {
|
|
42492
|
+
endMovement();
|
|
42493
|
+
}
|
|
42494
|
+
};
|
|
42495
|
+
const onWheelOnTravel = () => {
|
|
42400
42496
|
if (row.getAttribute("data-route-row-taken") === "") {
|
|
42401
42497
|
row.removeAttribute("data-route-row-taken");
|
|
42402
42498
|
}
|
|
@@ -42421,10 +42517,10 @@ const RouteTravel = ({
|
|
|
42421
42517
|
movement.travelling = true;
|
|
42422
42518
|
takeRowFromHand(movement);
|
|
42423
42519
|
};
|
|
42424
|
-
row.addEventListener("touchstart",
|
|
42520
|
+
row.addEventListener("touchstart", onTouchOnTravel, {
|
|
42425
42521
|
passive: true
|
|
42426
42522
|
});
|
|
42427
|
-
row.addEventListener("wheel",
|
|
42523
|
+
row.addEventListener("wheel", onWheelOnTravel, {
|
|
42428
42524
|
passive: true
|
|
42429
42525
|
});
|
|
42430
42526
|
document.addEventListener("click", onPress, {
|
|
@@ -42432,8 +42528,8 @@ const RouteTravel = ({
|
|
|
42432
42528
|
});
|
|
42433
42529
|
return () => {
|
|
42434
42530
|
stopWatching();
|
|
42435
|
-
row.removeEventListener("touchstart",
|
|
42436
|
-
row.removeEventListener("wheel",
|
|
42531
|
+
row.removeEventListener("touchstart", onTouchOnTravel);
|
|
42532
|
+
row.removeEventListener("wheel", onWheelOnTravel);
|
|
42437
42533
|
document.removeEventListener("click", onPress, {
|
|
42438
42534
|
capture: true
|
|
42439
42535
|
});
|
|
@@ -42452,7 +42548,7 @@ const RouteTravel = ({
|
|
|
42452
42548
|
return;
|
|
42453
42549
|
}
|
|
42454
42550
|
const pane = panesOf(rowRef.current)[currentIndex];
|
|
42455
|
-
if (pane && restsOn(rowRef.current, pane)) {
|
|
42551
|
+
if (pane && restsOn(rowRef.current, pane, ROW_READING)) {
|
|
42456
42552
|
Promise.resolve().then(endMovement);
|
|
42457
42553
|
}
|
|
42458
42554
|
}, [currentIndex]);
|
|
@@ -42560,10 +42656,6 @@ const copyScrollPositions = (from, to) => {
|
|
|
42560
42656
|
}
|
|
42561
42657
|
}
|
|
42562
42658
|
};
|
|
42563
|
-
|
|
42564
|
-
// A page of the row: a route, and the params that say which of its tabs when
|
|
42565
|
-
// several of them share it. Written as a bare route by a caller whose tabs are
|
|
42566
|
-
// routes of their own — which is the same page with nothing to tell apart.
|
|
42567
42659
|
const afterFrames = (count, callback) => {
|
|
42568
42660
|
if (count === 0) {
|
|
42569
42661
|
callback();
|
|
@@ -42573,6 +42665,13 @@ const afterFrames = (count, callback) => {
|
|
|
42573
42665
|
afterFrames(count - 1, callback);
|
|
42574
42666
|
});
|
|
42575
42667
|
};
|
|
42668
|
+
|
|
42669
|
+
// The two pages the row stands between.
|
|
42670
|
+
const readRowFrame = (row, panes) => readRowStretch(row, panes, panes[0], ROW_READING);
|
|
42671
|
+
|
|
42672
|
+
// A page of the row: a route, and the params that say which of its tabs when
|
|
42673
|
+
// several of them share it. Written as a bare route by a caller whose tabs are
|
|
42674
|
+
// routes of their own — which is the same page with nothing to tell apart.
|
|
42576
42675
|
const normalizePage = page => page.isRoute ? {
|
|
42577
42676
|
route: page,
|
|
42578
42677
|
params: undefined
|
|
@@ -78781,7 +78880,10 @@ const KEYBOARD_RAISING_CONTROL_SELECTOR = `
|
|
|
78781
78880
|
[contenteditable]:not([contenteditable="false"])
|
|
78782
78881
|
`;
|
|
78783
78882
|
const warnBottomSheetHoldingKeyboardControl = dialogEl => {
|
|
78784
|
-
|
|
78883
|
+
// A popup opens inside its opener's subtree, so the sheet's subtree also
|
|
78884
|
+
// holds the fields of popups opened from it. Those are typed into in that
|
|
78885
|
+
// popup, and a nested Dialog docked to the bottom runs this check itself.
|
|
78886
|
+
const controlEl = Array.from(dialogEl.querySelectorAll(KEYBOARD_RAISING_CONTROL_SELECTOR)).find(el => el.closest(`[navi-control="dialog"], [navi-control="popover"]`) === dialogEl);
|
|
78785
78887
|
if (!controlEl) {
|
|
78786
78888
|
return;
|
|
78787
78889
|
}
|