@jsenv/dom 0.17.95 → 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 +165 -41
- package/package.json +1 -1
package/dist/jsenv_dom.js
CHANGED
|
@@ -14846,7 +14846,8 @@ const DRAG_IGNORED_SELECTOR =
|
|
|
14846
14846
|
* Creates a gesture controller that moves elements via drag.
|
|
14847
14847
|
*
|
|
14848
14848
|
* Wraps `createDragGestureController` and adds:
|
|
14849
|
-
* - Element translation
|
|
14849
|
+
* - Element translation, on the `translate` property (or inside `transform`,
|
|
14850
|
+
* see `positionProperty`), added to the translate the element already had
|
|
14850
14851
|
* - Auto-scroll while dragging near scroll-container edges
|
|
14851
14852
|
* - Constraints (area boundaries, obstacle elements)
|
|
14852
14853
|
*
|
|
@@ -14859,10 +14860,11 @@ const DRAG_IGNORED_SELECTOR =
|
|
|
14859
14860
|
* If omitted, `element` is translated. The translate is read from `dragStyleController`
|
|
14860
14861
|
* at grab time so any pre-existing translate is accumulated rather than reset.
|
|
14861
14862
|
*
|
|
14862
|
-
*
|
|
14863
|
-
*
|
|
14864
|
-
*
|
|
14865
|
-
*
|
|
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.
|
|
14866
14868
|
*
|
|
14867
14869
|
* @param {object} [options]
|
|
14868
14870
|
* @param {boolean} [options.stickyFrontiers=true]
|
|
@@ -14885,9 +14887,15 @@ const DRAG_IGNORED_SELECTOR =
|
|
|
14885
14887
|
* Renders a visual line when the pointer deviates from the element due to constraints.
|
|
14886
14888
|
* @param {boolean} [options.showDebugMarkers=false]
|
|
14887
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).
|
|
14888
14896
|
* @param {"translate"|"manual"} [options.dragPositionEffect="translate"]
|
|
14889
14897
|
* Who puts the element where the hand is, while the hand is moving.
|
|
14890
|
-
* - `"translate"`: this controller does
|
|
14898
|
+
* - `"translate"`: this controller does (default), on `positionProperty`.
|
|
14891
14899
|
* - `"manual"`: nobody — the element stays where it was drawn, and whoever is
|
|
14892
14900
|
* told the gesture draws it. For a thing whose position is state.
|
|
14893
14901
|
* @param {"commit"|"cancel"|"cancel-animated"|"manual"} [options.releasePositionEffect="commit"]
|
|
@@ -14917,6 +14925,7 @@ const createDragToMoveGestureController = ({
|
|
|
14917
14925
|
obstacleAttributeName = "data-drag-obstacle",
|
|
14918
14926
|
showConstraintFeedbackLine = false,
|
|
14919
14927
|
showDebugMarkers = false,
|
|
14928
|
+
positionProperty = "translate",
|
|
14920
14929
|
dragPositionEffect = "translate",
|
|
14921
14930
|
releasePositionEffect = "commit",
|
|
14922
14931
|
cancelAnimationDuration = 200,
|
|
@@ -14938,10 +14947,21 @@ const createDragToMoveGestureController = ({
|
|
|
14938
14947
|
// rather than resetting it to zero on the first drag event.
|
|
14939
14948
|
// Nothing is written on the element on "manual" (the caller draws it where
|
|
14940
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;
|
|
14941
14961
|
const transformAtGrabOrNull =
|
|
14942
|
-
|
|
14943
|
-
?
|
|
14944
|
-
:
|
|
14962
|
+
writesPosition && !carriesOnTranslate
|
|
14963
|
+
? dragStyleController.getUnderlyingValue(elementImpacted, "transform")
|
|
14964
|
+
: null;
|
|
14945
14965
|
// A transform that cannot be read as named parts (a complex 3D matrix)
|
|
14946
14966
|
// comes back undefined: the drag then starts from a zero baseline.
|
|
14947
14967
|
const transformAtGrab = transformAtGrabOrNull || {};
|
|
@@ -14951,24 +14971,28 @@ const createDragToMoveGestureController = ({
|
|
|
14951
14971
|
const cancelPosition = () => {
|
|
14952
14972
|
dragStyleController.clear(elementImpacted);
|
|
14953
14973
|
};
|
|
14954
|
-
// Reading the
|
|
14974
|
+
// Reading the property on either side of the clear is what lets this work
|
|
14955
14975
|
// without knowing anything about the element: how it looked while held and
|
|
14956
|
-
// how it looks once let go are both just computed
|
|
14976
|
+
// how it looks once let go are both just computed values, and the
|
|
14957
14977
|
// animation has only to bridge the two.
|
|
14958
14978
|
const cancelPositionAnimated = ({
|
|
14959
14979
|
duration = cancelAnimationDuration,
|
|
14960
14980
|
easing = cancelAnimationEasing,
|
|
14961
14981
|
} = {}) => {
|
|
14962
|
-
const
|
|
14982
|
+
const valueWhileHeld =
|
|
14983
|
+
getComputedStyle(elementImpacted)[positionProperty];
|
|
14963
14984
|
cancelPosition();
|
|
14964
|
-
const
|
|
14965
|
-
if (
|
|
14985
|
+
const valueAtRest = getComputedStyle(elementImpacted)[positionProperty];
|
|
14986
|
+
if (valueWhileHeld === valueAtRest) {
|
|
14966
14987
|
return null;
|
|
14967
14988
|
}
|
|
14968
|
-
// No fill: the element already sits at its resting
|
|
14989
|
+
// No fill: the element already sits at its resting position, the
|
|
14969
14990
|
// animation only replays the way back to it.
|
|
14970
14991
|
return elementImpacted.animate(
|
|
14971
|
-
[
|
|
14992
|
+
[
|
|
14993
|
+
{ [positionProperty]: valueWhileHeld },
|
|
14994
|
+
{ [positionProperty]: valueAtRest },
|
|
14995
|
+
],
|
|
14972
14996
|
{ duration, easing },
|
|
14973
14997
|
);
|
|
14974
14998
|
};
|
|
@@ -15178,6 +15202,19 @@ const createDragToMoveGestureController = ({
|
|
|
15178
15202
|
scrollableLeft,
|
|
15179
15203
|
scrollableTop,
|
|
15180
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
|
+
}
|
|
15181
15218
|
// Build the transform to apply, preserving any transforms that were
|
|
15182
15219
|
// already on the element before the grab (e.g. rotate from another
|
|
15183
15220
|
// controller), and accumulating from the pre-grab translate baseline.
|
|
@@ -15260,6 +15297,47 @@ const createDragToMoveGestureController = ({
|
|
|
15260
15297
|
return dragGestureController;
|
|
15261
15298
|
};
|
|
15262
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
|
+
|
|
15263
15341
|
/**
|
|
15264
15342
|
* Starts a drag, for one or more of the outcomes listed.
|
|
15265
15343
|
*
|
|
@@ -15298,6 +15376,13 @@ const createDragToMoveGestureController = ({
|
|
|
15298
15376
|
* reject. Beside a copy, the copy fades where it was let go of and comes back
|
|
15299
15377
|
* if the promise rejects. Picked up and put straight back down is a cancel:
|
|
15300
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.
|
|
15301
15386
|
* @param {(detail: {gestureInfo: object, x: number, y: number, outcome: "move"|"reorder"|"land"|"toss"|"leave"|null}) => void} [options.onRelease]
|
|
15302
15387
|
* The hand let go — the mirror of `onDragStart`, and the one thing that is told
|
|
15303
15388
|
* whatever the release meant, a cancelled gesture included. `outcome` is what
|
|
@@ -15547,6 +15632,7 @@ const startDragToMoveElement = (
|
|
|
15547
15632
|
onMove,
|
|
15548
15633
|
onLeave,
|
|
15549
15634
|
onRelease,
|
|
15635
|
+
onCarryEnd,
|
|
15550
15636
|
outsideOf,
|
|
15551
15637
|
// A thing that can be let go of outside has to be able to get there. Same
|
|
15552
15638
|
// reason and same shape as the default of the copy path below.
|
|
@@ -15607,7 +15693,8 @@ const startDragToMoveElement = (
|
|
|
15607
15693
|
if (dropMeans === "cancel") {
|
|
15608
15694
|
// Nothing answers it: whatever the gesture translated goes home — and
|
|
15609
15695
|
// there is nothing to take back when `onMoving` had the caller draw.
|
|
15610
|
-
gestureInfo.cancelPositionAnimated();
|
|
15696
|
+
await whenAnimationDone(gestureInfo.cancelPositionAnimated());
|
|
15697
|
+
onCarryEnd?.({ outcome: null, refused: false });
|
|
15611
15698
|
return;
|
|
15612
15699
|
}
|
|
15613
15700
|
if (dropMeans === "leave") {
|
|
@@ -15618,10 +15705,13 @@ const startDragToMoveElement = (
|
|
|
15618
15705
|
// it where it goes back to; travelled home on a reject.
|
|
15619
15706
|
try {
|
|
15620
15707
|
await onLeave?.({ gestureInfo, x: xDelta, y: yDelta });
|
|
15621
|
-
|
|
15622
|
-
|
|
15623
|
-
|
|
15708
|
+
} catch (error) {
|
|
15709
|
+
await whenAnimationDone(gestureInfo.cancelPositionAnimated());
|
|
15710
|
+
onCarryEnd?.({ outcome: dropMeans, refused: true, error });
|
|
15711
|
+
return;
|
|
15624
15712
|
}
|
|
15713
|
+
gestureInfo.cancelPosition();
|
|
15714
|
+
onCarryEnd?.({ outcome: dropMeans, refused: false });
|
|
15625
15715
|
return;
|
|
15626
15716
|
}
|
|
15627
15717
|
// Kept where the hand let go of it while the answer is asked — a thing
|
|
@@ -15630,17 +15720,18 @@ const startDragToMoveElement = (
|
|
|
15630
15720
|
const layoutBeforeAnswer = readOwnLayout(draggedElement);
|
|
15631
15721
|
try {
|
|
15632
15722
|
await onMove?.({ gestureInfo, x: xDelta, y: yDelta });
|
|
15633
|
-
} catch {
|
|
15634
|
-
gestureInfo.cancelPositionAnimated();
|
|
15723
|
+
} catch (error) {
|
|
15724
|
+
await whenAnimationDone(gestureInfo.cancelPositionAnimated());
|
|
15725
|
+
onCarryEnd?.({ outcome: dropMeans, refused: true, error });
|
|
15635
15726
|
return;
|
|
15636
15727
|
}
|
|
15637
|
-
|
|
15638
|
-
|
|
15639
|
-
|
|
15640
|
-
|
|
15641
|
-
|
|
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);
|
|
15642
15733
|
}
|
|
15643
|
-
|
|
15734
|
+
onCarryEnd?.({ outcome: dropMeans, refused: false });
|
|
15644
15735
|
});
|
|
15645
15736
|
return dragGesture;
|
|
15646
15737
|
},
|
|
@@ -15806,6 +15897,7 @@ const startDragToCarryCopy = (
|
|
|
15806
15897
|
onToss,
|
|
15807
15898
|
onLeave,
|
|
15808
15899
|
onRelease,
|
|
15900
|
+
onCarryEnd,
|
|
15809
15901
|
outsideOf,
|
|
15810
15902
|
tossDistance,
|
|
15811
15903
|
tossSpeed,
|
|
@@ -15884,6 +15976,10 @@ const startDragToCarryCopy = (
|
|
|
15884
15976
|
|
|
15885
15977
|
const gestureController = createDragToMoveGestureController({
|
|
15886
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",
|
|
15887
15983
|
releasePositionEffect: "manual",
|
|
15888
15984
|
areaConstraint,
|
|
15889
15985
|
...options,
|
|
@@ -16154,6 +16250,9 @@ const startDragToCarryCopy = (
|
|
|
16154
16250
|
}),
|
|
16155
16251
|
);
|
|
16156
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;
|
|
16157
16256
|
// The copy stops where the hand left it, and the answer is given a way to
|
|
16158
16257
|
// take it the rest of the way — synchronously, inside a view transition, so
|
|
16159
16258
|
// it is captured where it lands rather than where it was let go of.
|
|
@@ -16178,11 +16277,12 @@ const startDragToCarryCopy = (
|
|
|
16178
16277
|
};
|
|
16179
16278
|
try {
|
|
16180
16279
|
await answer(syncCloneWithDropTarget);
|
|
16181
|
-
} catch {
|
|
16280
|
+
} catch (error) {
|
|
16182
16281
|
// Coming down on a place can be a QUESTION, and the answer may be
|
|
16183
16282
|
// no. Refused, the thing is still where it was and the screen has
|
|
16184
16283
|
// to say so: the copy takes the same journey home a refused throw
|
|
16185
16284
|
// takes — from wherever it got to, which is where it visibly is.
|
|
16285
|
+
refusal = { error };
|
|
16186
16286
|
await settleCloneBack(cloneWrapper, draggedElement);
|
|
16187
16287
|
}
|
|
16188
16288
|
};
|
|
@@ -16192,18 +16292,24 @@ const startDragToCarryCopy = (
|
|
|
16192
16292
|
// there rather than from where the clone was declared.
|
|
16193
16293
|
setCloneViewportRect(cloneWrapper, cloneWrapper);
|
|
16194
16294
|
gestureInfo.cancelPosition();
|
|
16195
|
-
const
|
|
16196
|
-
|
|
16295
|
+
const tossed = await tossCloneAway(
|
|
16296
|
+
cloneWrapper,
|
|
16297
|
+
gestureInfo,
|
|
16298
|
+
onToss,
|
|
16299
|
+
);
|
|
16300
|
+
if (!tossed.gone) {
|
|
16197
16301
|
// It still exists, so the screen has to say so: the copy comes back
|
|
16198
16302
|
// over the original, and taking it away then reveals the row in
|
|
16199
16303
|
// place.
|
|
16304
|
+
refusal = { error: tossed.error };
|
|
16200
16305
|
await settleCloneBack(cloneWrapper, draggedElement);
|
|
16201
16306
|
}
|
|
16202
16307
|
} else if (dropMeans === "leave") {
|
|
16203
16308
|
setCloneViewportRect(cloneWrapper, cloneWrapper);
|
|
16204
16309
|
gestureInfo.cancelPosition();
|
|
16205
|
-
const
|
|
16206
|
-
if (!gone) {
|
|
16310
|
+
const left = await letCloneGo(cloneWrapper, gestureInfo, onLeave);
|
|
16311
|
+
if (!left.gone) {
|
|
16312
|
+
refusal = { error: left.error };
|
|
16207
16313
|
await settleCloneBack(cloneWrapper, draggedElement);
|
|
16208
16314
|
}
|
|
16209
16315
|
} else if (dropMeans === "land") {
|
|
@@ -16235,6 +16341,11 @@ const startDragToCarryCopy = (
|
|
|
16235
16341
|
}
|
|
16236
16342
|
draggedElement.removeAttribute("navi-drag-clone-source");
|
|
16237
16343
|
cloneWrapper.remove();
|
|
16344
|
+
onCarryEnd?.({
|
|
16345
|
+
outcome: dropMeans === "cancel" ? null : dropMeans,
|
|
16346
|
+
refused: Boolean(refusal),
|
|
16347
|
+
error: refusal?.error,
|
|
16348
|
+
});
|
|
16238
16349
|
});
|
|
16239
16350
|
|
|
16240
16351
|
return dragGesture;
|
|
@@ -16505,7 +16616,8 @@ const findPlaceOnNearestLine = (dragElementRect, items, flow) => {
|
|
|
16505
16616
|
|
|
16506
16617
|
/**
|
|
16507
16618
|
* The copy leaves the screen the way it was thrown, and the caller says what that
|
|
16508
|
-
* 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.
|
|
16509
16621
|
*
|
|
16510
16622
|
* The answer is asked for WHILE it flies rather than after: the thing is already
|
|
16511
16623
|
* far away by the time the request lands, which is the whole point of a gesture
|
|
@@ -16520,15 +16632,15 @@ const tossCloneAway = async (cloneWrapper, gestureInfo, onToss) => {
|
|
|
16520
16632
|
}px`;
|
|
16521
16633
|
try {
|
|
16522
16634
|
await onToss?.({ gestureInfo });
|
|
16523
|
-
return true;
|
|
16524
|
-
} catch {
|
|
16525
|
-
return false;
|
|
16635
|
+
return { gone: true };
|
|
16636
|
+
} catch (error) {
|
|
16637
|
+
return { gone: false, error };
|
|
16526
16638
|
}
|
|
16527
16639
|
};
|
|
16528
16640
|
|
|
16529
16641
|
/**
|
|
16530
16642
|
* The copy fades where the hand let go of it, and the caller says what being let
|
|
16531
|
-
* go of there meant. Resolves
|
|
16643
|
+
* go of there meant. Resolves like tossCloneAway.
|
|
16532
16644
|
*
|
|
16533
16645
|
* No flight, unlike a throw: nothing was thrown. The thing was put down over
|
|
16534
16646
|
* nothing, and it goes from there — the same attribute as a throw, so that a
|
|
@@ -16539,9 +16651,9 @@ const letCloneGo = async (cloneWrapper, gestureInfo, onLeave) => {
|
|
|
16539
16651
|
try {
|
|
16540
16652
|
const { xDelta, yDelta } = gestureInfo.layout;
|
|
16541
16653
|
await onLeave?.({ gestureInfo, x: xDelta, y: yDelta });
|
|
16542
|
-
return true;
|
|
16543
|
-
} catch {
|
|
16544
|
-
return false;
|
|
16654
|
+
return { gone: true };
|
|
16655
|
+
} catch (error) {
|
|
16656
|
+
return { gone: false, error };
|
|
16545
16657
|
}
|
|
16546
16658
|
};
|
|
16547
16659
|
|
|
@@ -16599,6 +16711,18 @@ const settleCloneBack = (cloneWrapper, sourceElement) => {
|
|
|
16599
16711
|
});
|
|
16600
16712
|
};
|
|
16601
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
|
+
|
|
16602
16726
|
/**
|
|
16603
16727
|
* The copy is let go of, and it is still there: flying home, coming down on a
|
|
16604
16728
|
* place, waiting on an answer. It is still the object for all that time — a hand
|