@jsenv/dom 0.17.18 → 0.17.20
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 +211 -44
- package/package.json +1 -1
package/dist/jsenv_dom.js
CHANGED
|
@@ -261,11 +261,22 @@ const chainEvent = (customEvent, parentEvent) => {
|
|
|
261
261
|
if (!parentEvent) {
|
|
262
262
|
return customEvent;
|
|
263
263
|
}
|
|
264
|
-
if (!customEvent.detail) {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
264
|
+
if (!customEvent.detail || typeof customEvent.detail !== "object") {
|
|
265
|
+
// A native event has nowhere to hang the chain: `Event` has no detail at
|
|
266
|
+
// all and `UIEvent` (so `InputEvent` too) exposes it as a readonly number.
|
|
267
|
+
// Give it an own detail object, shadowing the prototype getter, so a
|
|
268
|
+
// synthetic event dispatched on behalf of a gesture can still say what
|
|
269
|
+
// caused it.
|
|
270
|
+
if (nativeDetailHasMeaning(customEvent)) {
|
|
271
|
+
console.warn(
|
|
272
|
+
`Chaining "${customEvent.type}" to "${parentEvent.type}" replaces its native detail (${customEvent.detail}), which carries the click count on this event type. Chain a custom event instead, or read the click count before chaining.`,
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
Object.defineProperty(customEvent, "detail", {
|
|
276
|
+
value: {},
|
|
277
|
+
configurable: true,
|
|
278
|
+
enumerable: true,
|
|
279
|
+
});
|
|
269
280
|
}
|
|
270
281
|
// Always build eventChain from the first wrapping so callers can rely on it
|
|
271
282
|
// being present whenever `parentEvent` is set.
|
|
@@ -309,6 +320,24 @@ const findEvent = (event, predicate) => {
|
|
|
309
320
|
return undefined;
|
|
310
321
|
};
|
|
311
322
|
|
|
323
|
+
// `detail` is a click count on the pointer events that define one, and 0
|
|
324
|
+
// everywhere else (`input`, `focus`, `wheel`…). Overwriting it there loses the
|
|
325
|
+
// only way to tell a real click from a keyboard/programmatic one (detail === 0),
|
|
326
|
+
// so those events must not be chained.
|
|
327
|
+
const EVENT_TYPES_WITH_MEANINGFUL_DETAIL = new Set([
|
|
328
|
+
"click",
|
|
329
|
+
"auxclick",
|
|
330
|
+
"dblclick",
|
|
331
|
+
"mousedown",
|
|
332
|
+
"mouseup",
|
|
333
|
+
]);
|
|
334
|
+
const nativeDetailHasMeaning = (event) => {
|
|
335
|
+
if (EVENT_TYPES_WITH_MEANINGFUL_DETAIL.has(event.type)) {
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
return typeof event.detail === "number" && event.detail !== 0;
|
|
339
|
+
};
|
|
340
|
+
|
|
312
341
|
const resolveEventPredicate = (predicate) => {
|
|
313
342
|
if (typeof predicate === "string") {
|
|
314
343
|
return (e) => e.type === predicate;
|
|
@@ -8244,7 +8273,12 @@ const createDragGestureController = (options = {}) => {
|
|
|
8244
8273
|
// metadata about interaction sources
|
|
8245
8274
|
grabEvent: event,
|
|
8246
8275
|
dragEvent: null,
|
|
8247
|
-
releaseEvent: null
|
|
8276
|
+
releaseEvent: null,
|
|
8277
|
+
// The gesture ended without the hand ever letting go: the browser took
|
|
8278
|
+
// the touch to scroll with, another gesture took the pointer. Whoever
|
|
8279
|
+
// reads it must not commit anything — a release that was not asked for
|
|
8280
|
+
// says nothing about where things belong.
|
|
8281
|
+
cancelled: false
|
|
8248
8282
|
};
|
|
8249
8283
|
definePropertyAsReadOnly(gestureInfo, "name");
|
|
8250
8284
|
definePropertyAsReadOnly(gestureInfo, "direction");
|
|
@@ -8556,9 +8590,13 @@ const createDragGestureController = (options = {}) => {
|
|
|
8556
8590
|
};
|
|
8557
8591
|
const release = ({
|
|
8558
8592
|
event = new CustomEvent("programmatic"),
|
|
8593
|
+
cancelled = event.type === "pointercancel",
|
|
8559
8594
|
releaseX = gestureInfo.dragX,
|
|
8560
8595
|
releaseY = gestureInfo.dragY
|
|
8561
8596
|
} = {}) => {
|
|
8597
|
+
// Written before the last drag is reported, so the callbacks reading the
|
|
8598
|
+
// end of the gesture all see the same one.
|
|
8599
|
+
gestureInfo.cancelled = cancelled;
|
|
8562
8600
|
drag(releaseX, releaseY, {
|
|
8563
8601
|
event,
|
|
8564
8602
|
isRelease: true
|
|
@@ -8613,10 +8651,13 @@ const createDragGestureController = (options = {}) => {
|
|
|
8613
8651
|
event: dragEvent
|
|
8614
8652
|
});
|
|
8615
8653
|
};
|
|
8616
|
-
const releaseViaPointer =
|
|
8617
|
-
|
|
8654
|
+
const releaseViaPointer = (pointerEvent, {
|
|
8655
|
+
cancelled
|
|
8656
|
+
} = {}) => {
|
|
8657
|
+
const [mouseReleaseX, mouseReleaseY] = mouseEventCoords(pointerEvent);
|
|
8618
8658
|
dragGesture.release({
|
|
8619
|
-
event:
|
|
8659
|
+
event: pointerEvent,
|
|
8660
|
+
cancelled,
|
|
8620
8661
|
releaseX: mouseReleaseX,
|
|
8621
8662
|
releaseY: mouseReleaseY
|
|
8622
8663
|
});
|
|
@@ -8713,7 +8754,8 @@ const createDragGestureController = (options = {}) => {
|
|
|
8713
8754
|
const cleanup = initializer({
|
|
8714
8755
|
onMove: dragViaPointer,
|
|
8715
8756
|
onRelease: releaseViaPointer,
|
|
8716
|
-
gestureInfo: dragGesture.gestureInfo
|
|
8757
|
+
gestureInfo: dragGesture.gestureInfo,
|
|
8758
|
+
dragGesture
|
|
8717
8759
|
});
|
|
8718
8760
|
dragGesture.addReleaseCallback(() => {
|
|
8719
8761
|
cleanup();
|
|
@@ -8725,7 +8767,8 @@ const createDragGestureController = (options = {}) => {
|
|
|
8725
8767
|
return initDragByPointer(grabEvent, options, ({
|
|
8726
8768
|
onMove,
|
|
8727
8769
|
onRelease,
|
|
8728
|
-
gestureInfo
|
|
8770
|
+
gestureInfo,
|
|
8771
|
+
dragGesture
|
|
8729
8772
|
}) => {
|
|
8730
8773
|
// Captured on something that will still be there at the end of the
|
|
8731
8774
|
// gesture: the browser releases the capture when its element leaves the
|
|
@@ -8733,7 +8776,21 @@ const createDragGestureController = (options = {}) => {
|
|
|
8733
8776
|
// finger would lose the pointer at its first move. Callers whose target
|
|
8734
8777
|
// is stable have nothing to say and keep it.
|
|
8735
8778
|
const target = options?.pointerCaptureElement || grabEvent.target;
|
|
8736
|
-
|
|
8779
|
+
// The capture is ONE per pointer for the whole document: taking it is
|
|
8780
|
+
// taking it away from whoever had it, who is then told the exact same
|
|
8781
|
+
// thing it is told when its own gesture ends. So it is taken when this
|
|
8782
|
+
// gesture is established and not a moment earlier — for most callers
|
|
8783
|
+
// that is the grab itself (the intent was settled before, by a handle
|
|
8784
|
+
// or a long press), and for a caller that is still deciding what the
|
|
8785
|
+
// press means, it is whenever it says so (see capturePointer).
|
|
8786
|
+
let captured = false;
|
|
8787
|
+
dragGesture.capturePointer = () => {
|
|
8788
|
+
captured = true;
|
|
8789
|
+
target.setPointerCapture(grabEvent.pointerId);
|
|
8790
|
+
};
|
|
8791
|
+
if (!options?.pointerCaptureDeferred) {
|
|
8792
|
+
dragGesture.capturePointer();
|
|
8793
|
+
}
|
|
8737
8794
|
/*
|
|
8738
8795
|
* A touchmove left alone is the browser deciding the touch belongs to
|
|
8739
8796
|
* it: it takes it to scroll with, and a touch it has taken is a pointer
|
|
@@ -8767,7 +8824,7 @@ const createDragGestureController = (options = {}) => {
|
|
|
8767
8824
|
grabTarget.addEventListener("touchmove", preventTouchScroll, {
|
|
8768
8825
|
passive: false
|
|
8769
8826
|
});
|
|
8770
|
-
// Only OUR capture ending
|
|
8827
|
+
// Only OUR capture ending is this gesture's business:
|
|
8771
8828
|
// lostpointercapture bubbles, so a descendant giving up its own capture
|
|
8772
8829
|
// walks straight into this listener. That is not a rare shape — it is
|
|
8773
8830
|
// exactly what happens when a gesture hands over to another one (a
|
|
@@ -8775,16 +8832,37 @@ const createDragGestureController = (options = {}) => {
|
|
|
8775
8832
|
// the pressed element, while the real one is being held on a container
|
|
8776
8833
|
// above it), and taken as our own it kills the new gesture one
|
|
8777
8834
|
// millisecond after it started.
|
|
8835
|
+
//
|
|
8836
|
+
// And when it IS ours, it is a loss, never an end: the ends a gesture
|
|
8837
|
+
// has are the pointer going up and the pointer being cancelled, both
|
|
8838
|
+
// listened for below. A capture that goes while the pointer is still
|
|
8839
|
+
// down was taken — by another gesture, or by the element it was held
|
|
8840
|
+
// on leaving the document — and what was being carried must go back
|
|
8841
|
+
// rather than land wherever the hand happened to be.
|
|
8778
8842
|
const onCaptureLost = pointerEvent => {
|
|
8779
|
-
if (pointerEvent.target !== target) {
|
|
8843
|
+
if (!captured || pointerEvent.target !== target) {
|
|
8780
8844
|
return;
|
|
8781
8845
|
}
|
|
8782
|
-
onRelease(pointerEvent
|
|
8846
|
+
onRelease(pointerEvent, {
|
|
8847
|
+
cancelled: true
|
|
8848
|
+
});
|
|
8783
8849
|
};
|
|
8784
8850
|
target.addEventListener("lostpointercapture", onCaptureLost);
|
|
8785
8851
|
target.addEventListener("pointercancel", onRelease);
|
|
8786
|
-
target.addEventListener("pointermove", onMove);
|
|
8787
8852
|
target.addEventListener("pointerup", onRelease);
|
|
8853
|
+
// Read from the window rather than from the element while the pointer
|
|
8854
|
+
// is not this gesture's: without a capture a move is delivered to
|
|
8855
|
+
// whatever is under the pointer, and a hand that has left the element
|
|
8856
|
+
// is exactly the hand this gesture is trying to make sense of. The
|
|
8857
|
+
// capture phase reaches the window before anything else, captured or
|
|
8858
|
+
// not, so there is one place to read whichever way the gesture ends up.
|
|
8859
|
+
const onPointerMove = pointerEvent => {
|
|
8860
|
+
if (pointerEvent.pointerId !== grabEvent.pointerId) {
|
|
8861
|
+
return;
|
|
8862
|
+
}
|
|
8863
|
+
onMove(pointerEvent);
|
|
8864
|
+
};
|
|
8865
|
+
window.addEventListener("pointermove", onPointerMove, true);
|
|
8788
8866
|
// The end of the pointer is also listened for on the window, because
|
|
8789
8867
|
// the end is the one event a gesture cannot afford to miss and the
|
|
8790
8868
|
// element it is captured on is not always on its way: a pointer can
|
|
@@ -8814,15 +8892,17 @@ const createDragGestureController = (options = {}) => {
|
|
|
8814
8892
|
grabTarget.removeEventListener("touchmove", preventTouchScroll);
|
|
8815
8893
|
target.removeEventListener("lostpointercapture", onCaptureLost);
|
|
8816
8894
|
target.removeEventListener("pointercancel", onRelease);
|
|
8817
|
-
|
|
8895
|
+
window.removeEventListener("pointermove", onPointerMove, true);
|
|
8818
8896
|
target.removeEventListener("pointerup", onRelease);
|
|
8819
8897
|
window.removeEventListener("pointerup", onPointerEnd, true);
|
|
8820
8898
|
window.removeEventListener("pointercancel", onPointerEnd, true);
|
|
8821
|
-
//
|
|
8822
|
-
//
|
|
8899
|
+
// Only what this gesture took, and only while there is something to
|
|
8900
|
+
// give back: a capture on that element may be someone else's (two
|
|
8901
|
+
// gestures reading the same press hold the same node), and a pointer
|
|
8902
|
+
// that is up no longer exists — the browser has already dropped the
|
|
8823
8903
|
// capture with it, and asking again throws ("No active pointer with
|
|
8824
|
-
// the given id is found")
|
|
8825
|
-
if (target.hasPointerCapture(grabEvent.pointerId)) {
|
|
8904
|
+
// the given id is found") on the most ordinary release there is.
|
|
8905
|
+
if (captured && target.hasPointerCapture(grabEvent.pointerId)) {
|
|
8826
8906
|
target.releasePointerCapture(grabEvent.pointerId);
|
|
8827
8907
|
}
|
|
8828
8908
|
};
|
|
@@ -9066,12 +9146,16 @@ const css$4 = /* css */`
|
|
|
9066
9146
|
/* A source taken by long press must let the scroll through until the grab —
|
|
9067
9147
|
which is exactly what the long press is there to tell apart. Zoom has
|
|
9068
9148
|
nothing to do with the gesture and nobody should lose it by resting a
|
|
9069
|
-
finger on a word.
|
|
9149
|
+
finger on a word.
|
|
9150
|
+
|
|
9151
|
+
Vertical, because that is the way the page and the lists in it go: a
|
|
9152
|
+
source dragged along one axis is surrounded by something scrolling along
|
|
9153
|
+
that same axis (a row of a list runs the way the list scrolls), and a
|
|
9154
|
+
source dragged both ways sits on the usual vertical page. */
|
|
9070
9155
|
touch-action: pan-y pinch-zoom;
|
|
9071
9156
|
}
|
|
9072
9157
|
[data-drag-source="x"] {
|
|
9073
|
-
/*
|
|
9074
|
-
knows which way what surrounds the source scrolls. */
|
|
9158
|
+
/* …and the sideways one, for the same reason read the other way. */
|
|
9075
9159
|
touch-action: pan-x pinch-zoom;
|
|
9076
9160
|
}
|
|
9077
9161
|
[data-drag-on-contact] [data-drag-source],
|
|
@@ -9107,23 +9191,36 @@ import.meta.css = [css$4, "@jsenv/dom/src/interaction/drag/drag_after_intent.js"
|
|
|
9107
9191
|
*
|
|
9108
9192
|
* On the element and not on the window, so the rest of the page keeps its
|
|
9109
9193
|
* touches on the compositor's fast path.
|
|
9194
|
+
*
|
|
9195
|
+
* Exported because a drag does not always begin on a drag source: a copy caught
|
|
9196
|
+
* on its way home is pressed through the pictures of a view transition, and the
|
|
9197
|
+
* touch lands on the document root (see letCopyBeCaught in drag_to.js). Same
|
|
9198
|
+
* rule, other element — and it has to be the same function, or the listener put
|
|
9199
|
+
* down is not the one taken back off.
|
|
9110
9200
|
*/
|
|
9111
9201
|
const keepTouchRefusable = () => {
|
|
9112
9202
|
// Being registered IS the whole of it — see above.
|
|
9113
9203
|
};
|
|
9114
9204
|
|
|
9115
9205
|
/**
|
|
9116
|
-
* Says an element is something a drag can start from
|
|
9206
|
+
* Says an element is something a drag can start from, and which way that drag
|
|
9207
|
+
* goes.
|
|
9208
|
+
*
|
|
9209
|
+
* The axes are written in the DOM rather than kept here because they are what
|
|
9210
|
+
* someone ELSE reads: a box above this one that travels under the same finger
|
|
9211
|
+
* (a row of slides, a sheet pushed down to close it) has to know which axes are
|
|
9212
|
+
* already spoken for before it answers the press — the same thing a travel says
|
|
9213
|
+
* about itself with `data-travel-by-drag`. It is also what leaves the browser
|
|
9214
|
+
* the pan it may still do until the grab (see the stylesheet above).
|
|
9117
9215
|
*
|
|
9118
9216
|
* @param {Element} element
|
|
9119
|
-
* @param {
|
|
9120
|
-
* Which way the
|
|
9121
|
-
*
|
|
9122
|
-
* else for the usual vertical page.
|
|
9217
|
+
* @param {"x"|"y"|"xy"} [axes="xy"]
|
|
9218
|
+
* Which way the drag walks. A list reordered along its own line says `"y"`;
|
|
9219
|
+
* something carried across a board, or thrown, goes both ways.
|
|
9123
9220
|
* @returns {function} Takes the mark back off.
|
|
9124
9221
|
*/
|
|
9125
|
-
const markDragSource = (element, axes) => {
|
|
9126
|
-
element.setAttribute("data-drag-source", axes
|
|
9222
|
+
const markDragSource = (element, axes = "xy") => {
|
|
9223
|
+
element.setAttribute("data-drag-source", axes);
|
|
9127
9224
|
element.addEventListener("touchmove", keepTouchRefusable, {
|
|
9128
9225
|
passive: false
|
|
9129
9226
|
});
|
|
@@ -9223,7 +9320,13 @@ const dragAfterDistance = (grabEvent, dragGestureInitializer, threshold) => {
|
|
|
9223
9320
|
}
|
|
9224
9321
|
});
|
|
9225
9322
|
const significantDragGesture = significantDragGestureController.grabViaPointer(grabEvent, {
|
|
9226
|
-
element: grabEvent.target
|
|
9323
|
+
element: grabEvent.target,
|
|
9324
|
+
// This one owns nothing: it measures a distance to find out whether there
|
|
9325
|
+
// is a gesture at all, and it is over the moment there is. Taking the
|
|
9326
|
+
// pointer for that would take it from whoever is already holding this same
|
|
9327
|
+
// element for a gesture of their own — and giving it back at the threshold
|
|
9328
|
+
// would tell them theirs is over.
|
|
9329
|
+
pointerCaptureDeferred: true
|
|
9227
9330
|
});
|
|
9228
9331
|
};
|
|
9229
9332
|
const dragAfterLongPress = (grabEvent, dragGestureInitializer, {
|
|
@@ -11512,6 +11615,18 @@ const css$1 = /* css */`
|
|
|
11512
11615
|
pointer-events: auto;
|
|
11513
11616
|
}
|
|
11514
11617
|
|
|
11618
|
+
/* …and a FINGER reaching for it does not land on it: the pictures of the
|
|
11619
|
+
transition cover the page, so as far as the browser is concerned the touch
|
|
11620
|
+
began on the document root. What a touch may do is decided there and at that
|
|
11621
|
+
moment, so the root says it for as long as the copy can be caught — the pan
|
|
11622
|
+
is ours (nothing should scroll while something is landing), zoom stays the
|
|
11623
|
+
reader's. Half of a pair: without the non-passive listener put down at the
|
|
11624
|
+
same moment (see letCopyBeCaught) every touchmove arrives already
|
|
11625
|
+
non-cancelable and refusing it does nothing. */
|
|
11626
|
+
[data-drag-catchable] {
|
|
11627
|
+
touch-action: pinch-zoom;
|
|
11628
|
+
}
|
|
11629
|
+
|
|
11515
11630
|
/* Ce qui a été lancé: il continue dans la direction du geste jusqu'à sortir de
|
|
11516
11631
|
l'écran, et revient par le même chemin si la réponse refuse. */
|
|
11517
11632
|
[navi-drag-clone-wrapper][data-tossed] {
|
|
@@ -12152,6 +12267,12 @@ const resolveDropMeaning = ({
|
|
|
12152
12267
|
tossDistance = TOSS_DISTANCE_TO_COMMIT,
|
|
12153
12268
|
tossSpeed = TOSS_SPEED_TO_COMMIT
|
|
12154
12269
|
}) => {
|
|
12270
|
+
if (gestureInfo.cancelled) {
|
|
12271
|
+
// Nobody let go of anything: the gesture was taken away mid-air (the
|
|
12272
|
+
// pointer cancelled, another gesture taking it). Where the thing happened
|
|
12273
|
+
// to be at that moment is not a place it was put.
|
|
12274
|
+
return "cancel";
|
|
12275
|
+
}
|
|
12155
12276
|
if (canToss) {
|
|
12156
12277
|
const {
|
|
12157
12278
|
xDelta,
|
|
@@ -12451,7 +12572,15 @@ const startDragToCarryCopy = (event, {
|
|
|
12451
12572
|
return dragGesture;
|
|
12452
12573
|
}, {
|
|
12453
12574
|
threshold,
|
|
12454
|
-
|
|
12575
|
+
// A copy caught on its way home is not an ambiguous press: the hand
|
|
12576
|
+
// reached for something moving, and the press was already matched
|
|
12577
|
+
// against the copy's own box before it got here. The wait a finger is
|
|
12578
|
+
// asked for elsewhere tells a scroll from a drag, and there is no scroll
|
|
12579
|
+
// to tell it from — the copy covers that spot from the top layer. Asked
|
|
12580
|
+
// for anyway it cannot even be answered: the wait is about as long as the
|
|
12581
|
+
// journey, so the thing is home before the proof is done, while a mouse
|
|
12582
|
+
// takes it in five pixels.
|
|
12583
|
+
longPress: cloneWrapperCaught ? false : longPress,
|
|
12455
12584
|
longPressDelay,
|
|
12456
12585
|
longPressSlop,
|
|
12457
12586
|
onPressStart,
|
|
@@ -12641,6 +12770,17 @@ const letCopyBeCaught = (cloneWrapper, carryAgain) => {
|
|
|
12641
12770
|
// gesture holds what it grabbed rather than whatever was behind.
|
|
12642
12771
|
cloneWrapper.setAttribute("data-catchable", "");
|
|
12643
12772
|
document.addEventListener("pointerdown", onPointerDown, true);
|
|
12773
|
+
// The touch half of the same reach, said on the root because that is where a
|
|
12774
|
+
// finger pressing through the pictures lands (see the stylesheet). Both go
|
|
12775
|
+
// down before the copy sets off, since what a touch may do is settled when it
|
|
12776
|
+
// begins: put down later, the press is still read, the carry still starts, and
|
|
12777
|
+
// the browser cancels the pointer one move afterwards — a copy that cannot be
|
|
12778
|
+
// caught with a finger and can with a mouse.
|
|
12779
|
+
const root = document.documentElement;
|
|
12780
|
+
root.setAttribute("data-drag-catchable", "");
|
|
12781
|
+
root.addEventListener("touchmove", keepTouchRefusable, {
|
|
12782
|
+
passive: false
|
|
12783
|
+
});
|
|
12644
12784
|
return {
|
|
12645
12785
|
settled: async () => {
|
|
12646
12786
|
// A hand that lets go and presses again while the copy is still there is
|
|
@@ -12652,6 +12792,8 @@ const letCopyBeCaught = (cloneWrapper, carryAgain) => {
|
|
|
12652
12792
|
}
|
|
12653
12793
|
cloneWrapper.removeAttribute("data-catchable");
|
|
12654
12794
|
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
12795
|
+
root.removeAttribute("data-drag-catchable");
|
|
12796
|
+
root.removeEventListener("touchmove", keepTouchRefusable);
|
|
12655
12797
|
return caught;
|
|
12656
12798
|
}
|
|
12657
12799
|
};
|
|
@@ -12943,10 +13085,13 @@ const DRAG_FLICK_DISTANCE = 8;
|
|
|
12943
13085
|
// way. Let go and it comes back — a wall one can lean on, never walk through.
|
|
12944
13086
|
const DRAG_RESISTANCE = 0.3;
|
|
12945
13087
|
|
|
12946
|
-
// What a drag must not start on: something that reads the pointer itself
|
|
12947
|
-
// button or a link is not in the list — dragging
|
|
12948
|
-
// click it would have made is swallowed on the way
|
|
12949
|
-
|
|
13088
|
+
// What a drag must not start on: something that reads the pointer itself, whole,
|
|
13089
|
+
// with no axis left to share. A button or a link is not in the list — dragging
|
|
13090
|
+
// from one travels, and the click it would have made is swallowed on the way
|
|
13091
|
+
// out. A drag SOURCE is not either: it says which way it goes and only takes
|
|
13092
|
+
// that (see DRAG_SOURCE_AXES_ATTRIBUTE) — but a dedicated handle is, being a
|
|
13093
|
+
// place whose only purpose is to be taken hold of, from the first pixel.
|
|
13094
|
+
const DRAG_EXCLUDED_SELECTOR = ["input", "textarea", "select", '[contenteditable=""]', '[contenteditable="true"]', "[data-drag-handle]", "[data-no-drag-travel]"].join(",");
|
|
12950
13095
|
|
|
12951
13096
|
// Which axes a box travels on, one attribute per gesture, said in the DOM by
|
|
12952
13097
|
// whoever owns the box: it is what a box ABOVE another reads to know the
|
|
@@ -12954,6 +13099,12 @@ const DRAG_EXCLUDED_SELECTOR = ["input", "textarea", "select", '[contenteditable
|
|
|
12954
13099
|
// from the outside.
|
|
12955
13100
|
const DRAG_AXES_ATTRIBUTE = "data-travel-by-drag";
|
|
12956
13101
|
const WHEEL_AXES_ATTRIBUTE = "data-travel-by-wheel";
|
|
13102
|
+
// The same thing said by something that is PICKED UP rather than travelled: a
|
|
13103
|
+
// row taken out of a list, a card carried across a board (see markDragSource).
|
|
13104
|
+
// It holds the pointer from the press exactly as a nested travel does, so it is
|
|
13105
|
+
// read exactly as one — a list reordered along its own line takes the axis it
|
|
13106
|
+
// runs on and leaves the other to whoever is above.
|
|
13107
|
+
const DRAG_SOURCE_AXES_ATTRIBUTE = "data-drag-source";
|
|
12957
13108
|
|
|
12958
13109
|
// A surface the browser paints in the top layer: it is still a DOM descendant
|
|
12959
13110
|
// of whatever it was written in, and it is nowhere near it on screen — it
|
|
@@ -13169,10 +13320,12 @@ const startDragToTravel = (pointerDownEvent, {
|
|
|
13169
13320
|
if (!target.closest || target.closest(DRAG_EXCLUDED_SELECTOR)) {
|
|
13170
13321
|
return null;
|
|
13171
13322
|
}
|
|
13172
|
-
// A box between the finger and this one that travels the same way
|
|
13173
|
-
//
|
|
13174
|
-
//
|
|
13175
|
-
|
|
13323
|
+
// A box between the finger and this one that travels the same way, and then
|
|
13324
|
+
// anything between them that is picked up and carried the same way: the
|
|
13325
|
+
// gesture is theirs, and this one is left with the axes none of them walks —
|
|
13326
|
+
// none at all, most of the time, and then there is no gesture here to read.
|
|
13327
|
+
const axesLeftByTravels = axesLeftBy(axes, target, element, DRAG_AXES_ATTRIBUTE);
|
|
13328
|
+
const axesLeft = axesLeftByTravels && axesLeftBy(axesLeftByTravels, target, element, DRAG_SOURCE_AXES_ATTRIBUTE);
|
|
13176
13329
|
if (!axesLeft) {
|
|
13177
13330
|
return null;
|
|
13178
13331
|
}
|
|
@@ -13339,6 +13492,9 @@ const startDragToTravel = (pointerDownEvent, {
|
|
|
13339
13492
|
pulled: started.slack || 0
|
|
13340
13493
|
};
|
|
13341
13494
|
document.documentElement.setAttribute(WALKING_ATTRIBUTE, axis);
|
|
13495
|
+
// The travel exists: from here the pointer is this box's, and it is
|
|
13496
|
+
// followed wherever it goes.
|
|
13497
|
+
dragGesture.capturePointer();
|
|
13342
13498
|
}
|
|
13343
13499
|
const {
|
|
13344
13500
|
axis
|
|
@@ -13410,9 +13566,12 @@ const startDragToTravel = (pointerDownEvent, {
|
|
|
13410
13566
|
const towardsSomething = pulled > 0 ? travel.travelBack : travel.travelOn;
|
|
13411
13567
|
const velocity = axis === "x" ? gestureInfo.velocityX : gestureInfo.velocityY;
|
|
13412
13568
|
// A gesture taken away rather than let go of (the browser scrolling
|
|
13413
|
-
// something else, a call coming in
|
|
13569
|
+
// something else, a call coming in, another gesture taking the pointer)
|
|
13570
|
+
// said nothing: things go back.
|
|
13414
13571
|
const releaseEvent = gestureInfo.releaseEvent || gestureInfo.dragEvent;
|
|
13415
|
-
const
|
|
13572
|
+
const {
|
|
13573
|
+
cancelled
|
|
13574
|
+
} = gestureInfo;
|
|
13416
13575
|
onEnd({
|
|
13417
13576
|
axis,
|
|
13418
13577
|
pulled,
|
|
@@ -13443,7 +13602,15 @@ const startDragToTravel = (pointerDownEvent, {
|
|
|
13443
13602
|
// gesture may take that away (a page that travels navigates, and the
|
|
13444
13603
|
// router unmounts the page being left), and a capture whose element
|
|
13445
13604
|
// leaves the document is a capture the browser drops.
|
|
13446
|
-
pointerCaptureElement: element
|
|
13605
|
+
pointerCaptureElement: element,
|
|
13606
|
+
// A travel is established in two steps, and the pointer is only owned
|
|
13607
|
+
// after the second: the distance below says the press is not a click, and
|
|
13608
|
+
// the first move says which axis it leans on — which this box may not
|
|
13609
|
+
// walk, or the caller may refuse. Taken at the first step, the capture
|
|
13610
|
+
// would be taken away from whoever else is reading the same press for
|
|
13611
|
+
// gestures that give themselves up one event later. It is claimed once
|
|
13612
|
+
// the travel exists, in onDrag below.
|
|
13613
|
+
pointerCaptureDeferred: true
|
|
13447
13614
|
});
|
|
13448
13615
|
return dragGesture;
|
|
13449
13616
|
};
|