@jsenv/dom 0.17.73 → 0.17.74
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_dom.js +94 -35
- package/package.json +1 -1
package/dist/jsenv_dom.js
CHANGED
|
@@ -4549,6 +4549,39 @@ const clickIsSuppressed = (clickEvent) =>
|
|
|
4549
4549
|
it. */
|
|
4550
4550
|
const MENU_GRACE_AFTER_CANCEL = 300;
|
|
4551
4551
|
|
|
4552
|
+
/* The presses a gesture has taken, and the holds still counting on each. Keyed
|
|
4553
|
+
by the `pointerdown` itself: every listener of one press is handed that same
|
|
4554
|
+
object, so a hold asked for further along the dispatch that took the press is
|
|
4555
|
+
told as surely as one already counting. */
|
|
4556
|
+
const takenPressSet = new WeakSet();
|
|
4557
|
+
const holdGiveUpsByPress = new WeakMap();
|
|
4558
|
+
|
|
4559
|
+
/**
|
|
4560
|
+
* A gesture takes the press: the pointer is captured on `element`, and every
|
|
4561
|
+
* hold waiting on that press gives up — whatever the press turned out to be, it
|
|
4562
|
+
* is that gesture and not a hold.
|
|
4563
|
+
*
|
|
4564
|
+
* Said here rather than left to the capture, because the browser announces a
|
|
4565
|
+
* capture only when it MOVES. A finger lands already captured to what it touched
|
|
4566
|
+
* (see implicitCaptureHolder below): a gesture taking that same element changes
|
|
4567
|
+
* nothing the browser reports, and a hold listening for the capture alone
|
|
4568
|
+
* answers in the middle of the gesture that took its press.
|
|
4569
|
+
*
|
|
4570
|
+
* @param {PointerEvent} pressEvent The `pointerdown` of the press taken.
|
|
4571
|
+
* @param {Element} element What holds the pointer from here.
|
|
4572
|
+
*/
|
|
4573
|
+
const takePress = (pressEvent, element) => {
|
|
4574
|
+
element.setPointerCapture(pressEvent.pointerId);
|
|
4575
|
+
takenPressSet.add(pressEvent);
|
|
4576
|
+
const holdGiveUps = holdGiveUpsByPress.get(pressEvent);
|
|
4577
|
+
if (!holdGiveUps) {
|
|
4578
|
+
return;
|
|
4579
|
+
}
|
|
4580
|
+
for (const giveUp of [...holdGiveUps]) {
|
|
4581
|
+
giveUp();
|
|
4582
|
+
}
|
|
4583
|
+
};
|
|
4584
|
+
|
|
4552
4585
|
/**
|
|
4553
4586
|
* Waits for a press to be held still, then tells the caller.
|
|
4554
4587
|
*
|
|
@@ -4563,7 +4596,7 @@ const MENU_GRACE_AFTER_CANCEL = 300;
|
|
|
4563
4596
|
* @param {function} [options.onPressStart] The wait began (a cue that the press
|
|
4564
4597
|
* counts).
|
|
4565
4598
|
* @param {function} [options.onPressCancel] The pointer moved or lifted before
|
|
4566
|
-
* the wait was over.
|
|
4599
|
+
* the wait was over, or another gesture took the press (see takePress).
|
|
4567
4600
|
* @param {(pressEvent: PointerEvent, handle: {endPress: () => void}) => void} options.onPressHeld
|
|
4568
4601
|
* The wait completed. Whatever the press now means outlives this call — an
|
|
4569
4602
|
* object is being carried, a menu is open under the finger — so the caller
|
|
@@ -4703,22 +4736,28 @@ const waitForPressHeld = (
|
|
|
4703
4736
|
}
|
|
4704
4737
|
cancelPress(pointerEndEvent);
|
|
4705
4738
|
};
|
|
4706
|
-
// Somebody else settled what this press is
|
|
4707
|
-
//
|
|
4708
|
-
//
|
|
4709
|
-
//
|
|
4710
|
-
//
|
|
4711
|
-
//
|
|
4712
|
-
//
|
|
4713
|
-
|
|
4739
|
+
// Somebody else settled what this press is, and whatever it turned out to be,
|
|
4740
|
+
// it is not a hold. Two waits on one press is the ordinary case rather than an
|
|
4741
|
+
// odd one: an element that can be picked up AND held answers a finger with two
|
|
4742
|
+
// delays, the shorter one wins, and without this the longer one would answer a
|
|
4743
|
+
// hundred milliseconds into the carry. A gesture says it with takePress. Both
|
|
4744
|
+
// ways of hearing it go with the countdown, so the gesture THIS wait starts
|
|
4745
|
+
// (which takes the press from inside onPressHeld) never reaches them.
|
|
4746
|
+
let holdGiveUps = holdGiveUpsByPress.get(pressEvent);
|
|
4747
|
+
if (!holdGiveUps) {
|
|
4748
|
+
holdGiveUps = new Set();
|
|
4749
|
+
holdGiveUpsByPress.set(pressEvent, holdGiveUps);
|
|
4750
|
+
}
|
|
4751
|
+
holdGiveUps.add(cancelPress);
|
|
4752
|
+
// A gesture that captures the pointer without takePress: heard only when the
|
|
4753
|
+
// capture moves, the one it takes on the implicit holder being announced to
|
|
4754
|
+
// nobody (see takePress).
|
|
4714
4755
|
const onGotPointerCapture = (captureEvent) => {
|
|
4715
4756
|
if (captureEvent.pointerId !== pointerId) {
|
|
4716
4757
|
return;
|
|
4717
4758
|
}
|
|
4718
4759
|
if (captureEvent.target === implicitCaptureHolder) {
|
|
4719
4760
|
// The capture the press was born with, not one somebody took (see above).
|
|
4720
|
-
// A gesture taking that same element instead changes nothing for the
|
|
4721
|
-
// browser, so it announces nothing, and there is nothing to miss here.
|
|
4722
4761
|
return;
|
|
4723
4762
|
}
|
|
4724
4763
|
cancelPress(captureEvent);
|
|
@@ -4730,13 +4769,20 @@ const waitForPressHeld = (
|
|
|
4730
4769
|
window.addEventListener("pointercancel", onPointerEnd);
|
|
4731
4770
|
window.addEventListener("gotpointercapture", onGotPointerCapture, true);
|
|
4732
4771
|
countdownCleanupCallbacks.push(() => {
|
|
4772
|
+
holdGiveUps.delete(cancelPress);
|
|
4733
4773
|
window.removeEventListener("pointermove", onPointerMove);
|
|
4734
4774
|
window.removeEventListener("pointerup", onPointerEnd);
|
|
4735
4775
|
window.removeEventListener("pointercancel", onPointerEnd);
|
|
4736
4776
|
window.removeEventListener("gotpointercapture", onGotPointerCapture, true);
|
|
4737
4777
|
});
|
|
4738
4778
|
|
|
4739
|
-
|
|
4779
|
+
if (takenPressSet.has(pressEvent)) {
|
|
4780
|
+
// Taken before this wait was asked for, by a listener earlier in the same
|
|
4781
|
+
// dispatch: over before it began.
|
|
4782
|
+
cancelPress();
|
|
4783
|
+
} else {
|
|
4784
|
+
onPressStart?.(pressEvent);
|
|
4785
|
+
}
|
|
4740
4786
|
|
|
4741
4787
|
return {
|
|
4742
4788
|
cancel: () => {
|
|
@@ -9615,7 +9661,10 @@ const createDragGestureController = (options = {}) => {
|
|
|
9615
9661
|
// last — which is what tells a hand-over from a capture the browser
|
|
9616
9662
|
// dropped on its own (see onCaptureLost).
|
|
9617
9663
|
captureHolderByPointerId.set(grabEvent.pointerId, dragGesture);
|
|
9618
|
-
|
|
9664
|
+
// The capture is often where the finger landed, which the browser
|
|
9665
|
+
// does not announce again: takePress is what tells a hold waiting
|
|
9666
|
+
// on this press that it is a drag.
|
|
9667
|
+
takePress(grabEvent, target);
|
|
9619
9668
|
};
|
|
9620
9669
|
if (!options?.pointerCaptureDeferred) {
|
|
9621
9670
|
dragGesture.capturePointer();
|
|
@@ -13603,8 +13652,8 @@ const installPanZoom = (
|
|
|
13603
13652
|
// is the pan on contact, which a surface that does not pan has none of.
|
|
13604
13653
|
keepTheHand();
|
|
13605
13654
|
}
|
|
13606
|
-
for (const
|
|
13607
|
-
element
|
|
13655
|
+
for (const pointer of pointers.values()) {
|
|
13656
|
+
takePress(pointer.pressEvent, element);
|
|
13608
13657
|
}
|
|
13609
13658
|
anchor = readHand(anchorWhere);
|
|
13610
13659
|
// The click the release leaves behind is not for what is under the hand.
|
|
@@ -13675,6 +13724,7 @@ const installPanZoom = (
|
|
|
13675
13724
|
window.addEventListener("pointercancel", onPointerEnd, true);
|
|
13676
13725
|
}
|
|
13677
13726
|
const pointer = {
|
|
13727
|
+
pressEvent: event,
|
|
13678
13728
|
x: event.clientX,
|
|
13679
13729
|
y: event.clientY,
|
|
13680
13730
|
startX: event.clientX,
|
|
@@ -13686,7 +13736,7 @@ const installPanZoom = (
|
|
|
13686
13736
|
};
|
|
13687
13737
|
pointers.set(event.pointerId, pointer);
|
|
13688
13738
|
if (active) {
|
|
13689
|
-
|
|
13739
|
+
takePress(event, element);
|
|
13690
13740
|
anchor = readHand();
|
|
13691
13741
|
return;
|
|
13692
13742
|
}
|
|
@@ -13768,13 +13818,13 @@ const installPanZoom = (
|
|
|
13768
13818
|
}
|
|
13769
13819
|
};
|
|
13770
13820
|
|
|
13771
|
-
//
|
|
13772
|
-
//
|
|
13773
|
-
//
|
|
13774
|
-
//
|
|
13775
|
-
// the
|
|
13776
|
-
//
|
|
13777
|
-
//
|
|
13821
|
+
// A touch drag left unrefused makes Chrome Android drop the click of the NEXT
|
|
13822
|
+
// tap, whatever `touch-action` says (see navi's
|
|
13823
|
+
// docs/mobile_tap_suppression_after_drag.md), so the surface refuses every
|
|
13824
|
+
// touchmove while it moves. Whether one can be refused at all is settled when
|
|
13825
|
+
// the touch begins, before the surface moves: the listener goes down with the
|
|
13826
|
+
// surface and refuses nothing until then — a tap, a hold, or under
|
|
13827
|
+
// `afterHold` the page scrolling, which is the whole point of the wait.
|
|
13778
13828
|
const preventTouchScroll = (touchMoveEvent) => {
|
|
13779
13829
|
if (active && touchMoveEvent.cancelable) {
|
|
13780
13830
|
touchMoveEvent.preventDefault();
|
|
@@ -13847,11 +13897,9 @@ const installPanZoom = (
|
|
|
13847
13897
|
|
|
13848
13898
|
element.addEventListener("pointerdown", onPointerDown);
|
|
13849
13899
|
element.addEventListener("lostpointercapture", onLostPointerCapture);
|
|
13850
|
-
|
|
13851
|
-
|
|
13852
|
-
|
|
13853
|
-
});
|
|
13854
|
-
}
|
|
13900
|
+
element.addEventListener("touchmove", preventTouchScroll, {
|
|
13901
|
+
passive: false,
|
|
13902
|
+
});
|
|
13855
13903
|
if (onZoom) {
|
|
13856
13904
|
element.addEventListener("wheel", onWheel, { passive: false });
|
|
13857
13905
|
}
|
|
@@ -14783,12 +14831,13 @@ const refuseDragTo = (
|
|
|
14783
14831
|
onRefuse?.({ event });
|
|
14784
14832
|
return null;
|
|
14785
14833
|
}
|
|
14786
|
-
// Nothing is carried, and the
|
|
14834
|
+
// Nothing is carried, and the press is taken all the same: taking it is
|
|
14787
14835
|
// how a gesture says the press is settled, and another wait counting on the
|
|
14788
|
-
// same finger
|
|
14789
|
-
//
|
|
14836
|
+
// same finger gives up (see takePress in press_held.js), even when the
|
|
14837
|
+
// finger landed on this very element. A `longpress` declared beside the
|
|
14838
|
+
// drag is answered by the grab when there is one; there must be no
|
|
14790
14839
|
// difference when there is none.
|
|
14791
|
-
|
|
14840
|
+
takePress(event, draggedElement);
|
|
14792
14841
|
// And the click the browser fires afterwards belongs to what answered the
|
|
14793
14842
|
// press, a refusal included: something pulled and told to stay put must not
|
|
14794
14843
|
// also be clicked. Lifted at the release rather than with the click, which
|
|
@@ -15504,14 +15553,16 @@ const getRectInside = (element, containerElement) => {
|
|
|
15504
15553
|
//
|
|
15505
15554
|
// Layer 2 — inner clone (navi-drag-clone):
|
|
15506
15555
|
// A deep clone of the grabbed element, and what the eye follows — so it is
|
|
15507
|
-
// the one named
|
|
15556
|
+
// the one named: a view-transition-name of its own (navi-drag-clone-<n>),
|
|
15557
|
+
// and the view-transition-class navi-drag-clone that every copy shares.
|
|
15508
15558
|
// Casts the shadow and applies transform: scale(var(--drag-clone-scale, 1.03))
|
|
15509
15559
|
// via the CSS rule for [navi-drag-clone], giving the "lifted" feel. The
|
|
15510
15560
|
// transform-origin is set to the grab point so the element expands naturally
|
|
15511
15561
|
// from where the user clicked.
|
|
15512
15562
|
// On release, the `navi-drag-clone` attribute is removed inside
|
|
15513
15563
|
// startViewTransition to drop the scale back to 1 as the "new" state; the
|
|
15514
|
-
// name
|
|
15564
|
+
// name and the class stay, so the scale is morphed with the box rather than
|
|
15565
|
+
// cross-faded.
|
|
15515
15566
|
|
|
15516
15567
|
// The chevron is the one the table's column drop preview uses, rotated by the
|
|
15517
15568
|
// CSS above so each cap points into the line.
|
|
@@ -15756,6 +15807,7 @@ const liftDragClone = (cloneWrapper, pointerEvent) => {
|
|
|
15756
15807
|
cloneWrapper.firstElementChild.setAttribute("navi-drag-clone", "");
|
|
15757
15808
|
};
|
|
15758
15809
|
|
|
15810
|
+
let dragCloneCount = 0;
|
|
15759
15811
|
const createDragClone = (element, pointerEvent) => {
|
|
15760
15812
|
const rect = element.getBoundingClientRect();
|
|
15761
15813
|
|
|
@@ -15792,7 +15844,14 @@ const createDragClone = (element, pointerEvent) => {
|
|
|
15792
15844
|
// dresses `[data-grabbed]` on its own element once, and the copy is that element.
|
|
15793
15845
|
// (The original wears it too, but it is hidden — see navi-drag-clone-source.)
|
|
15794
15846
|
elementClone.setAttribute("data-grabbed", "");
|
|
15795
|
-
|
|
15847
|
+
// A name of its own: a copy outlives its gesture while its answer is asked,
|
|
15848
|
+
// so two can be on screen at once, and a name claimed twice aborts the
|
|
15849
|
+
// transition. The class is what every copy shares — inline like the name,
|
|
15850
|
+
// since a landing takes the [navi-drag-clone] attribute off before the
|
|
15851
|
+
// capture its group's class is read from.
|
|
15852
|
+
dragCloneCount++;
|
|
15853
|
+
elementClone.style.viewTransitionName = `navi-drag-clone-${dragCloneCount}`;
|
|
15854
|
+
elementClone.style.viewTransitionClass = "navi-drag-clone";
|
|
15796
15855
|
// The copy takes the wrapper's box, and nothing the page said about where the
|
|
15797
15856
|
// ORIGINAL stands may place it: a piece drawn at "left: 40px; top: 130px" on
|
|
15798
15857
|
// its board, a marker centred by a translate, a card pushed by a margin — the
|