@jsenv/dom 0.17.94 → 0.17.96
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 +204 -51
- package/package.json +1 -1
package/dist/jsenv_dom.js
CHANGED
|
@@ -13253,6 +13253,14 @@ const startDragToTravel = (
|
|
|
13253
13253
|
if (movingAxis && !axesLeft.includes(movingAxis)) {
|
|
13254
13254
|
return null;
|
|
13255
13255
|
}
|
|
13256
|
+
// A link and an image are draggable without anyone asking, and the browser
|
|
13257
|
+
// starts that drag about 3px in, under the threshold below: it cancels the
|
|
13258
|
+
// pointer and keeps the rest of the press, so the travel never forms. Refused
|
|
13259
|
+
// for this press only — one excluded above, or left to a box inside, keeps it.
|
|
13260
|
+
const refuseNativeDrag = (dragStartEvent) => {
|
|
13261
|
+
dragStartEvent.preventDefault();
|
|
13262
|
+
};
|
|
13263
|
+
element.addEventListener("dragstart", refuseNativeDrag);
|
|
13256
13264
|
const startThreshold =
|
|
13257
13265
|
pointerDownEvent.pointerType === "mouse"
|
|
13258
13266
|
? DRAG_START_THRESHOLD
|
|
@@ -13278,6 +13286,7 @@ const startDragToTravel = (
|
|
|
13278
13286
|
clearTimeout(holdTimeout);
|
|
13279
13287
|
document.documentElement.removeAttribute(GESTURE_ATTRIBUTE);
|
|
13280
13288
|
document.documentElement.removeAttribute(WALKING_ATTRIBUTE);
|
|
13289
|
+
element.removeEventListener("dragstart", refuseNativeDrag);
|
|
13281
13290
|
window.removeEventListener("pointerup", onPressOver);
|
|
13282
13291
|
window.removeEventListener("pointercancel", onPressOver);
|
|
13283
13292
|
};
|
|
@@ -14091,10 +14100,11 @@ const findPanZoomSurface = (element) => {
|
|
|
14091
14100
|
* @param {boolean|"kept"} [options.afterHold=false] Whether a FINGER must be held
|
|
14092
14101
|
* still before it pans, the page keeping its scroll until then. For a surface
|
|
14093
14102
|
* standing in something that scrolls; a mouse pans by travelling either way.
|
|
14094
|
-
* `"kept"` asks for the wait once: from the moment
|
|
14095
|
-
* pans on contact, and it asks again only after a pointer
|
|
14096
|
-
* from it. `data-hand-kept` is on the element for as long
|
|
14097
|
-
* that way, a hand touching it or not
|
|
14103
|
+
* `"kept"` asks for the wait once: from the moment a finger has given the
|
|
14104
|
+
* surface the hand it pans on contact, and it asks again only after a pointer
|
|
14105
|
+
* has gone down away from it. `data-hand-kept` is on the element for as long
|
|
14106
|
+
* as it holds the hand that way, a hand touching it or not; a mouse pan never
|
|
14107
|
+
* sets it.
|
|
14098
14108
|
* @param {"auto"|"always"} [options.wheelZoom="auto"] Whether a BARE wheel zooms.
|
|
14099
14109
|
* `"auto"` gives it to whatever scrolls around the surface when there is one,
|
|
14100
14110
|
* and zooms when there is none; `"always"` takes it back, for a surface that
|
|
@@ -14115,8 +14125,8 @@ const installPanZoom = (
|
|
|
14115
14125
|
} = {},
|
|
14116
14126
|
) => {
|
|
14117
14127
|
// Whether a finger still owes the wait. Constant under a plain `afterHold`;
|
|
14118
|
-
// under `"kept"` it is spent the first time the surface
|
|
14119
|
-
// asked for again once the hand has gone elsewhere.
|
|
14128
|
+
// under `"kept"` it is spent the first time a finger gives the surface the hand
|
|
14129
|
+
// and asked for again once the hand has gone elsewhere.
|
|
14120
14130
|
let holdIsOwed = Boolean(afterHold);
|
|
14121
14131
|
const reflectHoldOwed = () => {
|
|
14122
14132
|
// What a touch may do is settled before it lands, so the mode is in the DOM
|
|
@@ -14195,10 +14205,14 @@ const installPanZoom = (
|
|
|
14195
14205
|
|
|
14196
14206
|
const activate = (anchorWhere, event) => {
|
|
14197
14207
|
active = true;
|
|
14198
|
-
if (
|
|
14199
|
-
|
|
14200
|
-
|
|
14201
|
-
|
|
14208
|
+
if (
|
|
14209
|
+
afterHold === "kept" &&
|
|
14210
|
+
[...pointers.values()].some((pointer) => pointer.waitsForHold)
|
|
14211
|
+
) {
|
|
14212
|
+
// Spent by the finger that owed it, whether the hold or a second finger
|
|
14213
|
+
// proved it: the surface is the hand's from here. A mouse never owed the
|
|
14214
|
+
// wait, so it neither spends it nor marks it — and a surface that does not
|
|
14215
|
+
// pan asks no finger to wait, having no pan on contact to keep.
|
|
14202
14216
|
keepTheHand();
|
|
14203
14217
|
}
|
|
14204
14218
|
for (const pointer of pointers.values()) {
|
|
@@ -14379,6 +14393,16 @@ const installPanZoom = (
|
|
|
14379
14393
|
}
|
|
14380
14394
|
};
|
|
14381
14395
|
|
|
14396
|
+
// A link and an image are draggable without anyone asking, and the browser
|
|
14397
|
+
// starts that drag about 3px in, under `threshold`: it cancels the pointer and
|
|
14398
|
+
// keeps the rest of the press, so the pan never forms. Refused only while the
|
|
14399
|
+
// surface reads a press — one yielded to something inside never got here.
|
|
14400
|
+
const refuseNativeDrag = (dragStartEvent) => {
|
|
14401
|
+
if (pointers.size > 0) {
|
|
14402
|
+
dragStartEvent.preventDefault();
|
|
14403
|
+
}
|
|
14404
|
+
};
|
|
14405
|
+
|
|
14382
14406
|
// What the first event of the burst going on settled: a key let go of (or
|
|
14383
14407
|
// pressed) halfway through must not hand a zoom to the page mid-gesture, and
|
|
14384
14408
|
// a burst has no end but a silence.
|
|
@@ -14448,6 +14472,10 @@ const installPanZoom = (
|
|
|
14448
14472
|
element.addEventListener("touchmove", preventTouchScroll, {
|
|
14449
14473
|
passive: false,
|
|
14450
14474
|
});
|
|
14475
|
+
// Without a pan, one pointer is whatever else reads it, its drag included.
|
|
14476
|
+
if (onPan) {
|
|
14477
|
+
element.addEventListener("dragstart", refuseNativeDrag);
|
|
14478
|
+
}
|
|
14451
14479
|
if (onZoom) {
|
|
14452
14480
|
element.addEventListener("wheel", onWheel, { passive: false });
|
|
14453
14481
|
}
|
|
@@ -14459,6 +14487,7 @@ const installPanZoom = (
|
|
|
14459
14487
|
element.removeEventListener("pointerdown", onPointerDown);
|
|
14460
14488
|
element.removeEventListener("lostpointercapture", onLostPointerCapture);
|
|
14461
14489
|
element.removeEventListener("touchmove", preventTouchScroll);
|
|
14490
|
+
element.removeEventListener("dragstart", refuseNativeDrag);
|
|
14462
14491
|
element.removeEventListener("wheel", onWheel);
|
|
14463
14492
|
window.removeEventListener("pointerdown", onPointerDownAway, true);
|
|
14464
14493
|
element.removeAttribute(SURFACE_ATTRIBUTE);
|
|
@@ -14817,7 +14846,8 @@ const DRAG_IGNORED_SELECTOR =
|
|
|
14817
14846
|
* Creates a gesture controller that moves elements via drag.
|
|
14818
14847
|
*
|
|
14819
14848
|
* Wraps `createDragGestureController` and adds:
|
|
14820
|
-
* - Element translation
|
|
14849
|
+
* - Element translation, on the `translate` property (or inside `transform`,
|
|
14850
|
+
* see `positionProperty`), added to the translate the element already had
|
|
14821
14851
|
* - Auto-scroll while dragging near scroll-container edges
|
|
14822
14852
|
* - Constraints (area boundaries, obstacle elements)
|
|
14823
14853
|
*
|
|
@@ -14830,10 +14860,11 @@ const DRAG_IGNORED_SELECTOR =
|
|
|
14830
14860
|
* If omitted, `element` is translated. The translate is read from `dragStyleController`
|
|
14831
14861
|
* at grab time so any pre-existing translate is accumulated rather than reset.
|
|
14832
14862
|
*
|
|
14833
|
-
*
|
|
14834
|
-
*
|
|
14835
|
-
*
|
|
14836
|
-
*
|
|
14863
|
+
* Carried on `translate`, the element keeps everything else it is drawn with:
|
|
14864
|
+
* the element's matrix is translate, then rotate, then scale, then `transform`,
|
|
14865
|
+
* so the hand's translate applies outside a rotation or a scale of its own,
|
|
14866
|
+
* whether written as properties or inside `transform`, and lands exactly where
|
|
14867
|
+
* the hand is.
|
|
14837
14868
|
*
|
|
14838
14869
|
* @param {object} [options]
|
|
14839
14870
|
* @param {boolean} [options.stickyFrontiers=true]
|
|
@@ -14856,9 +14887,15 @@ const DRAG_IGNORED_SELECTOR =
|
|
|
14856
14887
|
* Renders a visual line when the pointer deviates from the element due to constraints.
|
|
14857
14888
|
* @param {boolean} [options.showDebugMarkers=false]
|
|
14858
14889
|
* Renders debug markers for constraint regions.
|
|
14890
|
+
* @param {"translate"|"transform"} [options.positionProperty="translate"]
|
|
14891
|
+
* Where the hand's translate is written. `"transform"` puts it first in the
|
|
14892
|
+
* element's transform list, for a box whose `translate` property is already
|
|
14893
|
+
* spoken for — the copy `startDragTo` carries, which travels on it to the
|
|
14894
|
+
* hand and home. Inside `transform` it lands within a `rotate` or a `scale`
|
|
14895
|
+
* property and comes out rotated and scaled (a warning says so in dev).
|
|
14859
14896
|
* @param {"translate"|"manual"} [options.dragPositionEffect="translate"]
|
|
14860
14897
|
* Who puts the element where the hand is, while the hand is moving.
|
|
14861
|
-
* - `"translate"`: this controller does
|
|
14898
|
+
* - `"translate"`: this controller does (default), on `positionProperty`.
|
|
14862
14899
|
* - `"manual"`: nobody — the element stays where it was drawn, and whoever is
|
|
14863
14900
|
* told the gesture draws it. For a thing whose position is state.
|
|
14864
14901
|
* @param {"commit"|"cancel"|"cancel-animated"|"manual"} [options.releasePositionEffect="commit"]
|
|
@@ -14888,6 +14925,7 @@ const createDragToMoveGestureController = ({
|
|
|
14888
14925
|
obstacleAttributeName = "data-drag-obstacle",
|
|
14889
14926
|
showConstraintFeedbackLine = false,
|
|
14890
14927
|
showDebugMarkers = false,
|
|
14928
|
+
positionProperty = "translate",
|
|
14891
14929
|
dragPositionEffect = "translate",
|
|
14892
14930
|
releasePositionEffect = "commit",
|
|
14893
14931
|
cancelAnimationDuration = 200,
|
|
@@ -14909,10 +14947,21 @@ const createDragToMoveGestureController = ({
|
|
|
14909
14947
|
// rather than resetting it to zero on the first drag event.
|
|
14910
14948
|
// Nothing is written on the element on "manual" (the caller draws it where
|
|
14911
14949
|
// it goes), so there is nothing to accumulate on and nothing to read.
|
|
14950
|
+
const writesPosition = dragPositionEffect !== "manual";
|
|
14951
|
+
const carriesOnTranslate = positionProperty === "translate";
|
|
14952
|
+
const translateAtGrab =
|
|
14953
|
+
writesPosition && carriesOnTranslate
|
|
14954
|
+
? readTranslateParts(
|
|
14955
|
+
dragStyleController.getUnderlyingValue(
|
|
14956
|
+
elementImpacted,
|
|
14957
|
+
"translate",
|
|
14958
|
+
),
|
|
14959
|
+
)
|
|
14960
|
+
: null;
|
|
14912
14961
|
const transformAtGrabOrNull =
|
|
14913
|
-
|
|
14914
|
-
?
|
|
14915
|
-
:
|
|
14962
|
+
writesPosition && !carriesOnTranslate
|
|
14963
|
+
? dragStyleController.getUnderlyingValue(elementImpacted, "transform")
|
|
14964
|
+
: null;
|
|
14916
14965
|
// A transform that cannot be read as named parts (a complex 3D matrix)
|
|
14917
14966
|
// comes back undefined: the drag then starts from a zero baseline.
|
|
14918
14967
|
const transformAtGrab = transformAtGrabOrNull || {};
|
|
@@ -14922,24 +14971,28 @@ const createDragToMoveGestureController = ({
|
|
|
14922
14971
|
const cancelPosition = () => {
|
|
14923
14972
|
dragStyleController.clear(elementImpacted);
|
|
14924
14973
|
};
|
|
14925
|
-
// Reading the
|
|
14974
|
+
// Reading the property on either side of the clear is what lets this work
|
|
14926
14975
|
// without knowing anything about the element: how it looked while held and
|
|
14927
|
-
// how it looks once let go are both just computed
|
|
14976
|
+
// how it looks once let go are both just computed values, and the
|
|
14928
14977
|
// animation has only to bridge the two.
|
|
14929
14978
|
const cancelPositionAnimated = ({
|
|
14930
14979
|
duration = cancelAnimationDuration,
|
|
14931
14980
|
easing = cancelAnimationEasing,
|
|
14932
14981
|
} = {}) => {
|
|
14933
|
-
const
|
|
14982
|
+
const valueWhileHeld =
|
|
14983
|
+
getComputedStyle(elementImpacted)[positionProperty];
|
|
14934
14984
|
cancelPosition();
|
|
14935
|
-
const
|
|
14936
|
-
if (
|
|
14985
|
+
const valueAtRest = getComputedStyle(elementImpacted)[positionProperty];
|
|
14986
|
+
if (valueWhileHeld === valueAtRest) {
|
|
14937
14987
|
return null;
|
|
14938
14988
|
}
|
|
14939
|
-
// No fill: the element already sits at its resting
|
|
14989
|
+
// No fill: the element already sits at its resting position, the
|
|
14940
14990
|
// animation only replays the way back to it.
|
|
14941
14991
|
return elementImpacted.animate(
|
|
14942
|
-
[
|
|
14992
|
+
[
|
|
14993
|
+
{ [positionProperty]: valueWhileHeld },
|
|
14994
|
+
{ [positionProperty]: valueAtRest },
|
|
14995
|
+
],
|
|
14943
14996
|
{ duration, easing },
|
|
14944
14997
|
);
|
|
14945
14998
|
};
|
|
@@ -15149,6 +15202,19 @@ const createDragToMoveGestureController = ({
|
|
|
15149
15202
|
scrollableLeft,
|
|
15150
15203
|
scrollableTop,
|
|
15151
15204
|
);
|
|
15205
|
+
if (carriesOnTranslate) {
|
|
15206
|
+
const { x, y, z } = translateAtGrab;
|
|
15207
|
+
const xMoved = direction.x
|
|
15208
|
+
? addPixels(x, positionedLeft - dragGesture.gestureInfo.leftAtGrab)
|
|
15209
|
+
: x;
|
|
15210
|
+
const yMoved = direction.y
|
|
15211
|
+
? addPixels(y, positionedTop - dragGesture.gestureInfo.topAtGrab)
|
|
15212
|
+
: y;
|
|
15213
|
+
dragStyleController.set(elementImpacted, {
|
|
15214
|
+
translate: z ? `${xMoved} ${yMoved} ${z}` : `${xMoved} ${yMoved}`,
|
|
15215
|
+
});
|
|
15216
|
+
break move;
|
|
15217
|
+
}
|
|
15152
15218
|
// Build the transform to apply, preserving any transforms that were
|
|
15153
15219
|
// already on the element before the grab (e.g. rotate from another
|
|
15154
15220
|
// controller), and accumulating from the pre-grab translate baseline.
|
|
@@ -15231,6 +15297,47 @@ const createDragToMoveGestureController = ({
|
|
|
15231
15297
|
return dragGestureController;
|
|
15232
15298
|
};
|
|
15233
15299
|
|
|
15300
|
+
// The computed `translate` an element has of its own ("none", "10px",
|
|
15301
|
+
// "10px 20px", "50% 0px 4px"), as the three parts the hand's movement is added
|
|
15302
|
+
// to.
|
|
15303
|
+
const readTranslateParts = (translate) => {
|
|
15304
|
+
if (!translate || translate === "none") {
|
|
15305
|
+
return { x: "0px", y: "0px", z: "" };
|
|
15306
|
+
}
|
|
15307
|
+
// Split on the spaces between the parts, not on those inside a calc().
|
|
15308
|
+
const parts = [];
|
|
15309
|
+
let part = "";
|
|
15310
|
+
let depth = 0;
|
|
15311
|
+
for (const char of translate) {
|
|
15312
|
+
if (char === " " && depth === 0) {
|
|
15313
|
+
if (part) {
|
|
15314
|
+
parts.push(part);
|
|
15315
|
+
}
|
|
15316
|
+
part = "";
|
|
15317
|
+
continue;
|
|
15318
|
+
}
|
|
15319
|
+
if (char === "(") {
|
|
15320
|
+
depth++;
|
|
15321
|
+
} else if (char === ")") {
|
|
15322
|
+
depth--;
|
|
15323
|
+
}
|
|
15324
|
+
part += char;
|
|
15325
|
+
}
|
|
15326
|
+
if (part) {
|
|
15327
|
+
parts.push(part);
|
|
15328
|
+
}
|
|
15329
|
+
const [x = "0px", y = "0px", z = ""] = parts;
|
|
15330
|
+
return { x, y, z };
|
|
15331
|
+
};
|
|
15332
|
+
// A movement in pixels added to a length: a sum when it is in pixels too, a
|
|
15333
|
+
// calc() otherwise — a percentage is only resolved by the browser.
|
|
15334
|
+
const addPixels = (length, pixels) => {
|
|
15335
|
+
if (/^-?[\d.]+(?:e-?\d+)?px$/.test(length)) {
|
|
15336
|
+
return `${parseFloat(length) + pixels}px`;
|
|
15337
|
+
}
|
|
15338
|
+
return `calc(${length} + ${pixels}px)`;
|
|
15339
|
+
};
|
|
15340
|
+
|
|
15234
15341
|
/**
|
|
15235
15342
|
* Starts a drag, for one or more of the outcomes listed.
|
|
15236
15343
|
*
|
|
@@ -15269,6 +15376,13 @@ const createDragToMoveGestureController = ({
|
|
|
15269
15376
|
* reject. Beside a copy, the copy fades where it was let go of and comes back
|
|
15270
15377
|
* if the promise rejects. Picked up and put straight back down is a cancel:
|
|
15271
15378
|
* it has to have gone somewhere to be away from anything.
|
|
15379
|
+
* @param {(detail: {outcome: "move"|"reorder"|"land"|"toss"|"leave"|null, refused: boolean, error?: any}) => void} [options.onCarryEnd]
|
|
15380
|
+
* Whatever was carried is at rest: the copy gone and the original shown again,
|
|
15381
|
+
* or the element settled where it stays — after the answer and the journey
|
|
15382
|
+
* home a refusal takes. `refused` says the answer rejected, and `error` is what
|
|
15383
|
+
* it rejected with, so it can be said on the element now that it stands where
|
|
15384
|
+
* it was. Not told for a copy taken back in hand on its way home: that carry
|
|
15385
|
+
* goes on, and its own end is told. Told, not asked.
|
|
15272
15386
|
* @param {(detail: {gestureInfo: object, x: number, y: number, outcome: "move"|"reorder"|"land"|"toss"|"leave"|null}) => void} [options.onRelease]
|
|
15273
15387
|
* The hand let go — the mirror of `onDragStart`, and the one thing that is told
|
|
15274
15388
|
* whatever the release meant, a cancelled gesture included. `outcome` is what
|
|
@@ -15518,6 +15632,7 @@ const startDragToMoveElement = (
|
|
|
15518
15632
|
onMove,
|
|
15519
15633
|
onLeave,
|
|
15520
15634
|
onRelease,
|
|
15635
|
+
onCarryEnd,
|
|
15521
15636
|
outsideOf,
|
|
15522
15637
|
// A thing that can be let go of outside has to be able to get there. Same
|
|
15523
15638
|
// reason and same shape as the default of the copy path below.
|
|
@@ -15578,7 +15693,8 @@ const startDragToMoveElement = (
|
|
|
15578
15693
|
if (dropMeans === "cancel") {
|
|
15579
15694
|
// Nothing answers it: whatever the gesture translated goes home — and
|
|
15580
15695
|
// there is nothing to take back when `onMoving` had the caller draw.
|
|
15581
|
-
gestureInfo.cancelPositionAnimated();
|
|
15696
|
+
await whenAnimationDone(gestureInfo.cancelPositionAnimated());
|
|
15697
|
+
onCarryEnd?.({ outcome: null, refused: false });
|
|
15582
15698
|
return;
|
|
15583
15699
|
}
|
|
15584
15700
|
if (dropMeans === "leave") {
|
|
@@ -15589,10 +15705,13 @@ const startDragToMoveElement = (
|
|
|
15589
15705
|
// it where it goes back to; travelled home on a reject.
|
|
15590
15706
|
try {
|
|
15591
15707
|
await onLeave?.({ gestureInfo, x: xDelta, y: yDelta });
|
|
15592
|
-
|
|
15593
|
-
|
|
15594
|
-
|
|
15708
|
+
} catch (error) {
|
|
15709
|
+
await whenAnimationDone(gestureInfo.cancelPositionAnimated());
|
|
15710
|
+
onCarryEnd?.({ outcome: dropMeans, refused: true, error });
|
|
15711
|
+
return;
|
|
15595
15712
|
}
|
|
15713
|
+
gestureInfo.cancelPosition();
|
|
15714
|
+
onCarryEnd?.({ outcome: dropMeans, refused: false });
|
|
15596
15715
|
return;
|
|
15597
15716
|
}
|
|
15598
15717
|
// Kept where the hand let go of it while the answer is asked — a thing
|
|
@@ -15601,17 +15720,18 @@ const startDragToMoveElement = (
|
|
|
15601
15720
|
const layoutBeforeAnswer = readOwnLayout(draggedElement);
|
|
15602
15721
|
try {
|
|
15603
15722
|
await onMove?.({ gestureInfo, x: xDelta, y: yDelta });
|
|
15604
|
-
} catch {
|
|
15605
|
-
gestureInfo.cancelPositionAnimated();
|
|
15723
|
+
} catch (error) {
|
|
15724
|
+
await whenAnimationDone(gestureInfo.cancelPositionAnimated());
|
|
15725
|
+
onCarryEnd?.({ outcome: dropMeans, refused: true, error });
|
|
15606
15726
|
return;
|
|
15607
15727
|
}
|
|
15608
|
-
|
|
15609
|
-
|
|
15610
|
-
|
|
15611
|
-
|
|
15612
|
-
|
|
15728
|
+
// Nothing was translated under `onMoving`, so there is nothing to keep
|
|
15729
|
+
// or to take back: who owns the position was settled when the gesture
|
|
15730
|
+
// was declared, rather than read off the element afterwards.
|
|
15731
|
+
if (!onMoving) {
|
|
15732
|
+
settleMovedElement(draggedElement, gestureInfo, layoutBeforeAnswer);
|
|
15613
15733
|
}
|
|
15614
|
-
|
|
15734
|
+
onCarryEnd?.({ outcome: dropMeans, refused: false });
|
|
15615
15735
|
});
|
|
15616
15736
|
return dragGesture;
|
|
15617
15737
|
},
|
|
@@ -15777,6 +15897,7 @@ const startDragToCarryCopy = (
|
|
|
15777
15897
|
onToss,
|
|
15778
15898
|
onLeave,
|
|
15779
15899
|
onRelease,
|
|
15900
|
+
onCarryEnd,
|
|
15780
15901
|
outsideOf,
|
|
15781
15902
|
tossDistance,
|
|
15782
15903
|
tossSpeed,
|
|
@@ -15855,6 +15976,10 @@ const startDragToCarryCopy = (
|
|
|
15855
15976
|
|
|
15856
15977
|
const gestureController = createDragToMoveGestureController({
|
|
15857
15978
|
direction,
|
|
15979
|
+
// The wrapper's own `translate` carries its flights — to the hand
|
|
15980
|
+
// that pressed elsewhere, away when thrown, home when refused — and
|
|
15981
|
+
// nothing rotates or scales it: the hand goes in its transform.
|
|
15982
|
+
positionProperty: "transform",
|
|
15858
15983
|
releasePositionEffect: "manual",
|
|
15859
15984
|
areaConstraint,
|
|
15860
15985
|
...options,
|
|
@@ -16125,6 +16250,9 @@ const startDragToCarryCopy = (
|
|
|
16125
16250
|
}),
|
|
16126
16251
|
);
|
|
16127
16252
|
|
|
16253
|
+
// What the answer said no with, once the copy is home: told with the
|
|
16254
|
+
// end of the carry, where the original stands again.
|
|
16255
|
+
let refusal = null;
|
|
16128
16256
|
// The copy stops where the hand left it, and the answer is given a way to
|
|
16129
16257
|
// take it the rest of the way — synchronously, inside a view transition, so
|
|
16130
16258
|
// it is captured where it lands rather than where it was let go of.
|
|
@@ -16149,11 +16277,12 @@ const startDragToCarryCopy = (
|
|
|
16149
16277
|
};
|
|
16150
16278
|
try {
|
|
16151
16279
|
await answer(syncCloneWithDropTarget);
|
|
16152
|
-
} catch {
|
|
16280
|
+
} catch (error) {
|
|
16153
16281
|
// Coming down on a place can be a QUESTION, and the answer may be
|
|
16154
16282
|
// no. Refused, the thing is still where it was and the screen has
|
|
16155
16283
|
// to say so: the copy takes the same journey home a refused throw
|
|
16156
16284
|
// takes — from wherever it got to, which is where it visibly is.
|
|
16285
|
+
refusal = { error };
|
|
16157
16286
|
await settleCloneBack(cloneWrapper, draggedElement);
|
|
16158
16287
|
}
|
|
16159
16288
|
};
|
|
@@ -16163,18 +16292,24 @@ const startDragToCarryCopy = (
|
|
|
16163
16292
|
// there rather than from where the clone was declared.
|
|
16164
16293
|
setCloneViewportRect(cloneWrapper, cloneWrapper);
|
|
16165
16294
|
gestureInfo.cancelPosition();
|
|
16166
|
-
const
|
|
16167
|
-
|
|
16295
|
+
const tossed = await tossCloneAway(
|
|
16296
|
+
cloneWrapper,
|
|
16297
|
+
gestureInfo,
|
|
16298
|
+
onToss,
|
|
16299
|
+
);
|
|
16300
|
+
if (!tossed.gone) {
|
|
16168
16301
|
// It still exists, so the screen has to say so: the copy comes back
|
|
16169
16302
|
// over the original, and taking it away then reveals the row in
|
|
16170
16303
|
// place.
|
|
16304
|
+
refusal = { error: tossed.error };
|
|
16171
16305
|
await settleCloneBack(cloneWrapper, draggedElement);
|
|
16172
16306
|
}
|
|
16173
16307
|
} else if (dropMeans === "leave") {
|
|
16174
16308
|
setCloneViewportRect(cloneWrapper, cloneWrapper);
|
|
16175
16309
|
gestureInfo.cancelPosition();
|
|
16176
|
-
const
|
|
16177
|
-
if (!gone) {
|
|
16310
|
+
const left = await letCloneGo(cloneWrapper, gestureInfo, onLeave);
|
|
16311
|
+
if (!left.gone) {
|
|
16312
|
+
refusal = { error: left.error };
|
|
16178
16313
|
await settleCloneBack(cloneWrapper, draggedElement);
|
|
16179
16314
|
}
|
|
16180
16315
|
} else if (dropMeans === "land") {
|
|
@@ -16206,6 +16341,11 @@ const startDragToCarryCopy = (
|
|
|
16206
16341
|
}
|
|
16207
16342
|
draggedElement.removeAttribute("navi-drag-clone-source");
|
|
16208
16343
|
cloneWrapper.remove();
|
|
16344
|
+
onCarryEnd?.({
|
|
16345
|
+
outcome: dropMeans === "cancel" ? null : dropMeans,
|
|
16346
|
+
refused: Boolean(refusal),
|
|
16347
|
+
error: refusal?.error,
|
|
16348
|
+
});
|
|
16209
16349
|
});
|
|
16210
16350
|
|
|
16211
16351
|
return dragGesture;
|
|
@@ -16476,7 +16616,8 @@ const findPlaceOnNearestLine = (dragElementRect, items, flow) => {
|
|
|
16476
16616
|
|
|
16477
16617
|
/**
|
|
16478
16618
|
* The copy leaves the screen the way it was thrown, and the caller says what that
|
|
16479
|
-
* meant. Resolves true when it is really gone
|
|
16619
|
+
* meant. Resolves `{ gone: true }` when it is really gone, and with what the
|
|
16620
|
+
* answer refused with otherwise.
|
|
16480
16621
|
*
|
|
16481
16622
|
* The answer is asked for WHILE it flies rather than after: the thing is already
|
|
16482
16623
|
* far away by the time the request lands, which is the whole point of a gesture
|
|
@@ -16491,15 +16632,15 @@ const tossCloneAway = async (cloneWrapper, gestureInfo, onToss) => {
|
|
|
16491
16632
|
}px`;
|
|
16492
16633
|
try {
|
|
16493
16634
|
await onToss?.({ gestureInfo });
|
|
16494
|
-
return true;
|
|
16495
|
-
} catch {
|
|
16496
|
-
return false;
|
|
16635
|
+
return { gone: true };
|
|
16636
|
+
} catch (error) {
|
|
16637
|
+
return { gone: false, error };
|
|
16497
16638
|
}
|
|
16498
16639
|
};
|
|
16499
16640
|
|
|
16500
16641
|
/**
|
|
16501
16642
|
* The copy fades where the hand let go of it, and the caller says what being let
|
|
16502
|
-
* go of there meant. Resolves
|
|
16643
|
+
* go of there meant. Resolves like tossCloneAway.
|
|
16503
16644
|
*
|
|
16504
16645
|
* No flight, unlike a throw: nothing was thrown. The thing was put down over
|
|
16505
16646
|
* nothing, and it goes from there — the same attribute as a throw, so that a
|
|
@@ -16510,9 +16651,9 @@ const letCloneGo = async (cloneWrapper, gestureInfo, onLeave) => {
|
|
|
16510
16651
|
try {
|
|
16511
16652
|
const { xDelta, yDelta } = gestureInfo.layout;
|
|
16512
16653
|
await onLeave?.({ gestureInfo, x: xDelta, y: yDelta });
|
|
16513
|
-
return true;
|
|
16514
|
-
} catch {
|
|
16515
|
-
return false;
|
|
16654
|
+
return { gone: true };
|
|
16655
|
+
} catch (error) {
|
|
16656
|
+
return { gone: false, error };
|
|
16516
16657
|
}
|
|
16517
16658
|
};
|
|
16518
16659
|
|
|
@@ -16570,6 +16711,18 @@ const settleCloneBack = (cloneWrapper, sourceElement) => {
|
|
|
16570
16711
|
});
|
|
16571
16712
|
};
|
|
16572
16713
|
|
|
16714
|
+
// The way home an element travels on its own (cancelPositionAnimated), waited
|
|
16715
|
+
// out: what is said about it after is said where it stands again.
|
|
16716
|
+
const whenAnimationDone = (animation) => {
|
|
16717
|
+
if (!animation) {
|
|
16718
|
+
return Promise.resolve();
|
|
16719
|
+
}
|
|
16720
|
+
return animation.finished.then(
|
|
16721
|
+
() => {},
|
|
16722
|
+
() => {},
|
|
16723
|
+
);
|
|
16724
|
+
};
|
|
16725
|
+
|
|
16573
16726
|
/**
|
|
16574
16727
|
* The copy is let go of, and it is still there: flying home, coming down on a
|
|
16575
16728
|
* place, waiting on an answer. It is still the object for all that time — a hand
|