@jsenv/dom 0.17.72 → 0.17.73

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.
Files changed (2) hide show
  1. package/dist/jsenv_dom.js +200 -133
  2. package/package.json +1 -1
package/dist/jsenv_dom.js CHANGED
@@ -8891,6 +8891,7 @@ const captureHolderByPointerId = new Map();
8891
8891
  * `[data-droppable]` places) goes inert, a backdrop unifies the cursor and takes
8892
8892
  * the pointer events, the focus moves to what is held and comes back at the
8893
8893
  * release, and the selection is refused for the length of the gesture.
8894
+ * `documentInteractions` and `selection` each hand their part back to the caller.
8894
8895
  *
8895
8896
  * Whether the element may be grabbed AT ALL is decided before the finger lands
8896
8897
  * and elsewhere: see `markDragSource` in drag_after_intent.js for the
@@ -8914,6 +8915,13 @@ const captureHolderByPointerId = new Map();
8914
8915
  * @param {"auto"|"manual"} [options.documentInteractions="auto"]
8915
8916
  * `"manual"` leaves the document alone — no inertness, no backdrop, no focus taken. For a
8916
8917
  * gesture that only measures and hands over (see `dragAfterIntent`).
8918
+ * @param {"auto"|"manual"} [options.selection="auto"]
8919
+ * `"auto"` refuses the selection from the grab to the release, a press that may
8920
+ * become a drag not being a press that starts a selection. `"manual"` leaves it
8921
+ * alone — nothing refused, nothing collapsed, double and triple clicks the
8922
+ * browser's — for a gesture where a press on text is still a selection until it
8923
+ * has become something else, and says so itself once it has (a travel, see
8924
+ * drag_to_travel.js).
8917
8925
  * @param {boolean} [options.backdrop=true]
8918
8926
  * @param {number} [options.backdropZIndex=999999]
8919
8927
  * @returns {{grab: function, grabViaPointer: function}}
@@ -8937,6 +8945,7 @@ const createDragGestureController = (options = {}) => {
8937
8945
  threshold = 5,
8938
8946
  direction: defaultDirection = { x: true, y: true },
8939
8947
  documentInteractions = "auto",
8948
+ selection = "auto",
8940
8949
  backdrop = true,
8941
8950
  backdropZIndex = 999999,
8942
8951
  } = options;
@@ -9459,96 +9468,101 @@ const createDragGestureController = (options = {}) => {
9459
9468
  };
9460
9469
  dragGesture.dragViaPointer = dragViaPointer;
9461
9470
  dragGesture.releaseViaPointer = releaseViaPointer;
9462
- /*
9463
- * A press that starts a drag is not a press that starts a selection: the
9464
- * browser sees a pointer going down on text and moving, and that is its
9465
- * own gesture — the words under the finger turn blue while the element
9466
- * travels, and the selection outlives the release.
9467
- *
9468
- * Refused from the grab, before any threshold: whether the press becomes a
9469
- * drag is decided a few pixels later, but the selection is decided at the
9470
- * FIRST move, and by then it is too late to say no.
9471
- *
9472
- * `user-select: none` would say it in CSS, but it would say it to
9473
- * everybody: the element would stop being selectable even when nobody is
9474
- * dragging it. Here it is refused for the length of one gesture.
9475
- */
9476
- const preventSelectStart = (selectStartEvent) => {
9477
- selectStartEvent.preventDefault();
9478
- };
9479
- document.addEventListener("selectstart", preventSelectStart);
9480
- // A press also puts an end to the selection the page was already holding,
9481
- // the way the browser's own press does: refusing selectstart keeps a new
9482
- // selection from being made, it says nothing about the one painted before
9483
- // — which would otherwise sit there through a gesture that has nothing to
9484
- // do with it.
9485
- collapseSelection();
9486
- dragGesture.addReleaseCallback(() => {
9487
- document.removeEventListener("selectstart", preventSelectStart);
9488
- });
9489
- /*
9490
- * Refusing every selection also refuses the ones a press is entitled to
9491
- * make: a double click selects the word under it, a triple click the
9492
- * paragraph around it, and both are over before the pointer has gone
9493
- * anywhere. They are made here instead, spelled out (see
9494
- * selectWordAtPoint, selectParagraphAtPoint) rather than left to a browser
9495
- * heuristic that cannot tell a drag from a click.
9496
- *
9497
- * Read from `click` rather than `dblclick`, because a triple click has no
9498
- * event of its own: what tells the clicks apart is `detail`, the count the
9499
- * browser keeps of how many presses landed in the same place in a row — 2
9500
- * for a word, 3 and beyond for a paragraph (a fourth click keeps the
9501
- * paragraph, the way the browser does).
9502
- *
9503
- * On the document and outliving the gesture, because the gesture is
9504
- * already over when the second click completes: click comes after mouseup,
9505
- * the gesture ends at pointerup. Kept installed after it fires, since the
9506
- * click that selects a word is also the one the next click turns into a
9507
- * paragraph; it goes when the next press installs its own — a listener
9508
- * waiting for a click that never comes costs nothing until then.
9509
- */
9510
- removePendingMultiClickListener();
9511
- const onClick = (clickEvent) => {
9512
- const clickCount = clickEvent.detail;
9513
- if (clickCount < 2) {
9514
- return;
9515
- }
9516
- // A drag that happened is a gesture, not a click: the second press of a
9517
- // double click can be the one that drags, and what it drags must not end
9518
- // up selected too.
9519
- if (dragGesture.gestureInfo.started) {
9520
- return;
9521
- }
9522
- // Only the clicks that continue THIS press: the listener outlives the
9523
- // gesture and the page keeps being clicked elsewhere, where the browser
9524
- // is doing its own selecting — a second opinion there would only fight
9525
- // it.
9526
- const clickTarget = clickEvent.target;
9527
- if (
9528
- clickTarget !== grabEvent.target &&
9529
- !clickTarget.contains(grabEvent.target)
9530
- ) {
9531
- return;
9471
+ refuse_selection: {
9472
+ if (selection === "manual") {
9473
+ break refuse_selection;
9532
9474
  }
9533
- // Text the page says is not selectable stays not selectable: a
9534
- // programmatic selection goes through `user-select: none` in every
9535
- // engine — it is a rule about what the USER may start, and the browser
9536
- // does not read it back when asked directly. Read here so that doing the
9537
- // browser's work does not also undo what the page asked of it.
9538
- if (!isSelectable(clickEvent.target)) {
9539
- return;
9540
- }
9541
- if (clickCount === 2) {
9542
- selectWordAtPoint(clickEvent.clientX, clickEvent.clientY);
9543
- return;
9544
- }
9545
- selectParagraphAtPoint(clickEvent.clientX, clickEvent.clientY);
9546
- };
9547
- document.addEventListener("click", onClick);
9548
- removePendingMultiClickListener = () => {
9549
- removePendingMultiClickListener = NOOP;
9550
- document.removeEventListener("click", onClick);
9551
- };
9475
+ /*
9476
+ * A press that starts a drag is not a press that starts a selection: the
9477
+ * browser sees a pointer going down on text and moving, and that is its
9478
+ * own gesture — the words under the finger turn blue while the element
9479
+ * travels, and the selection outlives the release.
9480
+ *
9481
+ * Refused from the grab, before any threshold: whether the press becomes a
9482
+ * drag is decided a few pixels later, but the selection is decided at the
9483
+ * FIRST move, and by then it is too late to say no.
9484
+ *
9485
+ * `user-select: none` would say it in CSS, but it would say it to
9486
+ * everybody: the element would stop being selectable even when nobody is
9487
+ * dragging it. Here it is refused for the length of one gesture.
9488
+ */
9489
+ const preventSelectStart = (selectStartEvent) => {
9490
+ selectStartEvent.preventDefault();
9491
+ };
9492
+ document.addEventListener("selectstart", preventSelectStart);
9493
+ // A press also puts an end to the selection the page was already holding,
9494
+ // the way the browser's own press does: refusing selectstart keeps a new
9495
+ // selection from being made, it says nothing about the one painted before
9496
+ // — which would otherwise sit there through a gesture that has nothing to
9497
+ // do with it.
9498
+ collapseSelection();
9499
+ dragGesture.addReleaseCallback(() => {
9500
+ document.removeEventListener("selectstart", preventSelectStart);
9501
+ });
9502
+ /*
9503
+ * Refusing every selection also refuses the ones a press is entitled to
9504
+ * make: a double click selects the word under it, a triple click the
9505
+ * paragraph around it, and both are over before the pointer has gone
9506
+ * anywhere. They are made here instead, spelled out (see
9507
+ * selectWordAtPoint, selectParagraphAtPoint) rather than left to a browser
9508
+ * heuristic that cannot tell a drag from a click.
9509
+ *
9510
+ * Read from `click` rather than `dblclick`, because a triple click has no
9511
+ * event of its own: what tells the clicks apart is `detail`, the count the
9512
+ * browser keeps of how many presses landed in the same place in a row — 2
9513
+ * for a word, 3 and beyond for a paragraph (a fourth click keeps the
9514
+ * paragraph, the way the browser does).
9515
+ *
9516
+ * On the document and outliving the gesture, because the gesture is
9517
+ * already over when the second click completes: click comes after mouseup,
9518
+ * the gesture ends at pointerup. Kept installed after it fires, since the
9519
+ * click that selects a word is also the one the next click turns into a
9520
+ * paragraph; it goes when the next press installs its own — a listener
9521
+ * waiting for a click that never comes costs nothing until then.
9522
+ */
9523
+ removePendingMultiClickListener();
9524
+ const onClick = (clickEvent) => {
9525
+ const clickCount = clickEvent.detail;
9526
+ if (clickCount < 2) {
9527
+ return;
9528
+ }
9529
+ // A drag that happened is a gesture, not a click: the second press of a
9530
+ // double click can be the one that drags, and what it drags must not end
9531
+ // up selected too.
9532
+ if (dragGesture.gestureInfo.started) {
9533
+ return;
9534
+ }
9535
+ // Only the clicks that continue THIS press: the listener outlives the
9536
+ // gesture and the page keeps being clicked elsewhere, where the browser
9537
+ // is doing its own selecting — a second opinion there would only fight
9538
+ // it.
9539
+ const clickTarget = clickEvent.target;
9540
+ if (
9541
+ clickTarget !== grabEvent.target &&
9542
+ !clickTarget.contains(grabEvent.target)
9543
+ ) {
9544
+ return;
9545
+ }
9546
+ // Text the page says is not selectable stays not selectable: a
9547
+ // programmatic selection goes through `user-select: none` in every
9548
+ // engine — it is a rule about what the USER may start, and the browser
9549
+ // does not read it back when asked directly. Read here so that doing the
9550
+ // browser's work does not also undo what the page asked of it.
9551
+ if (!isSelectable(clickEvent.target)) {
9552
+ return;
9553
+ }
9554
+ if (clickCount === 2) {
9555
+ selectWordAtPoint(clickEvent.clientX, clickEvent.clientY);
9556
+ return;
9557
+ }
9558
+ selectParagraphAtPoint(clickEvent.clientX, clickEvent.clientY);
9559
+ };
9560
+ document.addEventListener("click", onClick);
9561
+ removePendingMultiClickListener = () => {
9562
+ removePendingMultiClickListener = NOOP;
9563
+ document.removeEventListener("click", onClick);
9564
+ };
9565
+ }
9552
9566
  const cleanup = initializer({
9553
9567
  onMove: dragViaPointer,
9554
9568
  onRelease: releaseViaPointer,
@@ -10110,6 +10124,13 @@ const dragSourceThatStoodDown = (pressEvent) => {
10110
10124
  * The pointer moved or lifted before the wait was over.
10111
10125
  * @param {function} [options.onPress]
10112
10126
  * The wait completed and the object is now held (haptics, scale…).
10127
+ * @param {"auto"|"manual"} [options.selection="auto"]
10128
+ * Whether the selection is refused while the press travels towards the
10129
+ * distance: a press on a source belongs to the drag, so what its first pixels
10130
+ * would select is refused before the drag is sure (see `selection` in
10131
+ * drag_gesture.js). `"manual"` leaves the press to the browser until the
10132
+ * caller's own gesture says otherwise. A long press waits without refusing
10133
+ * anything either way (see the stylesheet above).
10113
10134
  */
10114
10135
  const dragAfterIntent = (
10115
10136
  grabEvent,
@@ -10122,6 +10143,7 @@ const dragAfterIntent = (
10122
10143
  onPressStart,
10123
10144
  onPressCancel,
10124
10145
  onPress,
10146
+ selection = "auto",
10125
10147
  } = {},
10126
10148
  ) => {
10127
10149
  if (!isPrimaryButtonEvent(grabEvent)) {
@@ -10151,7 +10173,7 @@ const dragAfterIntent = (
10151
10173
  });
10152
10174
  return;
10153
10175
  }
10154
- dragAfterDistance(grabEvent, dragGestureInitializer, threshold);
10176
+ dragAfterDistance(grabEvent, dragGestureInitializer, threshold, selection);
10155
10177
  };
10156
10178
 
10157
10179
  const startDragGesture = (dragGestureInitializer, catchUpEvent) => {
@@ -10168,13 +10190,19 @@ const startDragGesture = (dragGestureInitializer, catchUpEvent) => {
10168
10190
  return dragGesture;
10169
10191
  };
10170
10192
 
10171
- const dragAfterDistance = (grabEvent, dragGestureInitializer, threshold) => {
10193
+ const dragAfterDistance = (
10194
+ grabEvent,
10195
+ dragGestureInitializer,
10196
+ threshold,
10197
+ selection,
10198
+ ) => {
10172
10199
  const significantDragGestureController = createDragGestureController({
10173
10200
  threshold,
10174
10201
  // allow interaction for this intermediate gesture:
10175
10202
  // user should still be able to scroll or interact with the document
10176
10203
  // only once the gesture is significant we take control
10177
10204
  documentInteractions: "manual",
10205
+ selection,
10178
10206
  onDragStart: (gestureInfo) => {
10179
10207
  significantDragGesture.release(); // kill that gesture
10180
10208
  startDragGesture(dragGestureInitializer, gestureInfo.dragEvent);
@@ -12249,6 +12277,10 @@ import.meta.css = /* css */ [`:root[data-drag-travel-gesture] {
12249
12277
  overscroll-behavior: none;
12250
12278
  }
12251
12279
 
12280
+ :root[data-drag-travel-walking] {
12281
+ user-select: none;
12282
+ }
12283
+
12252
12284
  [data-drag-travel*="x"] {
12253
12285
  overscroll-behavior-x: contain !important;
12254
12286
  }
@@ -12783,8 +12815,11 @@ const startDragToTravel = (
12783
12815
  // never come.
12784
12816
  // Nothing is being carried: the page keeps its focus, its scrolling and its
12785
12817
  // cursor while a screen slides under the finger. That is the whole
12786
- // difference with a drag that moves an object, and it is one option.
12818
+ // difference with a drag that moves an object.
12787
12819
  documentInteractions: "manual",
12820
+ // And a press on text is a selection until it has become a travel, which
12821
+ // is where the selection is refused (see where WALKING_ATTRIBUTE is set).
12822
+ selection: "manual",
12788
12823
  onDragStart: () => {
12789
12824
  document.documentElement.setAttribute(GESTURE_ATTRIBUTE, "");
12790
12825
  },
@@ -12885,6 +12920,9 @@ const startDragToTravel = (
12885
12920
  pulled: started.slack || 0,
12886
12921
  };
12887
12922
  document.documentElement.setAttribute(WALKING_ATTRIBUTE, axis);
12923
+ // What the first pixels may have started selecting is not a selection:
12924
+ // it is the beginning of this travel.
12925
+ collapseSelection();
12888
12926
  // The travel exists: from here the pointer is this box's, and it is
12889
12927
  // followed wherever it goes.
12890
12928
  dragGesture.capturePointer();
@@ -13008,6 +13046,7 @@ const startDragToTravel = (
13008
13046
  dragAfterIntent(pointerDownEvent, grab, {
13009
13047
  longPress: false,
13010
13048
  threshold: DRAG_START_THRESHOLD,
13049
+ selection: "manual",
13011
13050
  });
13012
13051
  }
13013
13052
  window.addEventListener("pointerup", onPressOver);
@@ -13431,7 +13470,11 @@ const findPanZoomSurface = (element) => {
13431
13470
  * @param {Element} element
13432
13471
  * @param {object} options
13433
13472
  * @param {(detail: {event: PointerEvent, x: number, y: number}) => void} [options.onPan]
13434
- * The hand moved: `x`/`y` are how far since the last report, in px.
13473
+ * The hand moved: `x`/`y` are how far since the last report, in px. Left out,
13474
+ * one pointer is not the surface's: it is heard only for the pinch a second
13475
+ * one would make with it, and otherwise left to whatever else reads it — no
13476
+ * capture, no hold waited for, no click swallowed, no grab. `afterHold` then
13477
+ * leaves its scroll to the page, and `"kept"` has no pan to keep.
13435
13478
  * @param {(detail: {event: PointerEvent|WheelEvent, factor: number, x: number, y: number}) => void} [options.onZoom]
13436
13479
  * The zoom changed by `factor` (above 1 is in) around the point `x`/`y` of the
13437
13480
  * surface, measured inside its border. Left out, a wheel over the surface is
@@ -13554,9 +13597,10 @@ const installPanZoom = (
13554
13597
 
13555
13598
  const activate = (anchorWhere, event) => {
13556
13599
  active = true;
13557
- if (afterHold === "kept" && holdIsOwed) {
13600
+ if (afterHold === "kept" && holdIsOwed && onPan) {
13558
13601
  // Asked for and given: whatever proved it — the hold, a second finger, a
13559
- // mouse travelling — the surface is the hand's from here.
13602
+ // mouse travelling — the surface is the hand's from here. What it keeps
13603
+ // is the pan on contact, which a surface that does not pan has none of.
13560
13604
  keepTheHand();
13561
13605
  }
13562
13606
  for (const pointerId of pointers.keys()) {
@@ -13650,6 +13694,12 @@ const installPanZoom = (
13650
13694
  activate("now", event);
13651
13695
  return;
13652
13696
  }
13697
+ if (!onPan) {
13698
+ // One pointer is the pan's to read. Without one it is only heard for the
13699
+ // pinch a second pointer would make with it: a tap, a hold or a double
13700
+ // click on it belongs to whatever else reads it.
13701
+ return;
13702
+ }
13653
13703
  if (holdIsOwed && event.pointerType === "touch") {
13654
13704
  pointer.waitsForHold = true;
13655
13705
  pointer.holdWait = waitForPressHeld(event, {
@@ -13670,7 +13720,9 @@ const installPanZoom = (
13670
13720
  pointer.x = event.clientX;
13671
13721
  pointer.y = event.clientY;
13672
13722
  if (!active) {
13673
- if (pointer.waitsForHold) {
13723
+ // No pan for the travel to start (see onPointerDown), or a finger whose
13724
+ // travel is the page scrolling.
13725
+ if (!onPan || pointer.waitsForHold) {
13674
13726
  return;
13675
13727
  }
13676
13728
  const travelled = Math.hypot(
@@ -14530,10 +14582,12 @@ const createDragToMoveGestureController = ({
14530
14582
  *
14531
14583
  * @param {PointerEvent} event The `pointerdown` that may become a drag.
14532
14584
  * @param {("move"|"reorder"|"toss"|"land"|"leave")[]} effects
14533
- * What letting go of this element can mean. `reorder`, `toss` and `land` carry a
14534
- * copy; `move` carries the element itself, and `leave` goes with either. Asking
14535
- * for `move` beside any of the three that carry a copy is asking one release to
14536
- * mean two things, and so is asking for `reorder` and `land`.
14585
+ * What letting go of this element can mean, and only what is listed is ever
14586
+ * answered. `reorder`, `toss` and `land` carry a copy; `move` carries the
14587
+ * element itself, and `leave` goes with either. Asking for `move` beside any of
14588
+ * the three that carry a copy is asking one release to mean two things, and so
14589
+ * is asking for `reorder` and `land`. A gesture taken away mid-air
14590
+ * (`gestureInfo.cancelled`) means none of them, and what it carried goes back.
14537
14591
  * @param {object} [options]
14538
14592
  * @param {Element} [options.draggedElement=event.currentTarget]
14539
14593
  * @param {(detail: {gestureInfo: object, x: number, y: number}) => void} [options.onMoving]
@@ -14652,6 +14706,7 @@ const startDragTo = (
14652
14706
  }
14653
14707
  return startDragToMoveElement(event, {
14654
14708
  draggedElement,
14709
+ canMove,
14655
14710
  canLeave,
14656
14711
  ...options,
14657
14712
  });
@@ -14763,12 +14818,14 @@ const refuseDragTo = (
14763
14818
  * go of away from it, when it can `leave`.
14764
14819
  *
14765
14820
  * No copy, unlike the others: what is being moved is the thing and not a
14766
- * stand-in for it, so there is nothing to put back and nothing to reveal.
14821
+ * stand-in for it, so there is nothing to put back and nothing to reveal. What a
14822
+ * release means is read by resolveDropMeaning, as it is for a copy.
14767
14823
  */
14768
14824
  const startDragToMoveElement = (
14769
14825
  event,
14770
14826
  {
14771
14827
  draggedElement,
14828
+ canMove,
14772
14829
  canLeave,
14773
14830
  onMoving,
14774
14831
  onMove,
@@ -14818,26 +14875,26 @@ const startDragToMoveElement = (
14818
14875
  });
14819
14876
  }
14820
14877
  dragGesture.addReleaseCallback(async (gestureInfo) => {
14878
+ const dropMeans = resolveDropMeaning({
14879
+ gestureInfo,
14880
+ releasedOutside: canLeave && isOutsideOf(gestureInfo, outsideOf),
14881
+ canMove,
14882
+ canLeave,
14883
+ });
14821
14884
  const { xDelta, yDelta } = gestureInfo.layout;
14822
- if (!xDelta && !yDelta) {
14823
- // Picked up and put back down: nothing moved, so no outcome is told.
14824
- onRelease?.({ gestureInfo, x: xDelta, y: yDelta, outcome: null });
14825
- gestureInfo.cancelPosition();
14826
- return;
14827
- }
14828
- const leaving =
14829
- canLeave &&
14830
- !gestureInfo.cancelled &&
14831
- isOutsideOf(gestureInfo, outsideOf);
14832
14885
  onRelease?.({
14833
14886
  gestureInfo,
14834
14887
  x: xDelta,
14835
14888
  y: yDelta,
14836
- // Nothing answers a release that only ever said where the hand was
14837
- // going: `onMoving` alone has already told all of it.
14838
- outcome: leaving ? "leave" : onMove ? "move" : null,
14889
+ outcome: dropMeans === "cancel" ? null : dropMeans,
14839
14890
  });
14840
- if (leaving) {
14891
+ if (dropMeans === "cancel") {
14892
+ // Nothing answers it: whatever the gesture translated goes home — and
14893
+ // there is nothing to take back when `onMoving` had the caller draw.
14894
+ gestureInfo.cancelPositionAnimated();
14895
+ return;
14896
+ }
14897
+ if (dropMeans === "leave") {
14841
14898
  // Left where the hand let go of it while the answer is asked — a thing
14842
14899
  // that snaps home with the request in flight says the gesture was not
14843
14900
  // understood. The answer then says what becomes of that position: let
@@ -14931,10 +14988,14 @@ const readOwnLayout = (element) => ({
14931
14988
  const TOSS_DISTANCE_TO_COMMIT = 110;
14932
14989
  const TOSS_SPEED_TO_COMMIT = 0.45;
14933
14990
 
14991
+ // What a release means, whether it carried the element itself or a copy: one
14992
+ // reading, so a gesture taken away mid-air is nothing on both paths, and an
14993
+ // outcome is answered only when the caller listed it.
14934
14994
  const resolveDropMeaning = ({
14935
14995
  gestureInfo,
14936
14996
  hasDropTarget,
14937
14997
  releasedOutside,
14998
+ canMove,
14938
14999
  canReorder,
14939
15000
  canToss,
14940
15001
  canLand,
@@ -14963,15 +15024,19 @@ const resolveDropMeaning = ({
14963
15024
  return "reorder";
14964
15025
  }
14965
15026
  }
15027
+ // It has to have gone somewhere to be put anywhere, or away from anything:
15028
+ // picked up and put straight back down is a hand that changed its mind.
15029
+ const { xDelta, yDelta } = gestureInfo.layout;
15030
+ if (!xDelta && !yDelta) {
15031
+ return "cancel";
15032
+ }
14966
15033
  if (canLeave && releasedOutside) {
14967
15034
  // Let go of away from every place — off the plan and down, deliberate and
14968
- // never a flick. It has to have gone somewhere to be away from anything:
14969
- // picked up and put straight back down is a hand that changed its mind, not
14970
- // a thing dropped over nothing.
14971
- const { xDelta, yDelta } = gestureInfo.layout;
14972
- if (xDelta || yDelta) {
14973
- return "leave";
14974
- }
15035
+ // never a flick.
15036
+ return "leave";
15037
+ }
15038
+ if (canMove) {
15039
+ return "move";
14975
15040
  }
14976
15041
  return "cancel";
14977
15042
  };
@@ -15429,21 +15494,24 @@ const getRectInside = (element, containerElement) => {
15429
15494
  };
15430
15495
  };
15431
15496
 
15432
- // Creates the two-layer clone structure used for drag-to-reorder.
15497
+ // Creates the two-layer clone structure carried by reorder, land, toss and leave.
15433
15498
  //
15434
15499
  // Layer 1 — wrapper (navi-drag-clone-wrapper):
15435
- // Positioned fixed via --clone-top/--clone-left CSS vars.
15436
- // Carries the box-shadow and size. Moved every drag frame via dragStyleController.
15437
- // Has a view-transition-name so the View Transitions API can animate it on release.
15500
+ // Positioned fixed via the --clone-* CSS vars, which also give it its size.
15501
+ // Moved every drag frame via dragStyleController.
15502
+ // It paints nothing, so it takes no view-transition-name: a name on it would
15503
+ // be a group with an empty image, and one more name to keep unique.
15438
15504
  //
15439
15505
  // Layer 2 — inner clone (navi-drag-clone):
15440
- // A deep clone of the grabbed element.
15441
- // Applies transform: scale(var(--drag-clone-scale, 1.03)) via the CSS rule
15442
- // for [navi-drag-clone],
15443
- // giving the "lifted" feel. The transform-origin is set to the grab point
15444
- // so the element expands naturally from where the user clicked.
15506
+ // A deep clone of the grabbed element, and what the eye follows — so it is
15507
+ // the one named (view-transition-name: navi-drag-clone).
15508
+ // Casts the shadow and applies transform: scale(var(--drag-clone-scale, 1.03))
15509
+ // via the CSS rule for [navi-drag-clone], giving the "lifted" feel. The
15510
+ // transform-origin is set to the grab point so the element expands naturally
15511
+ // from where the user clicked.
15445
15512
  // On release, the `navi-drag-clone` attribute is removed inside
15446
- // startViewTransition to drop the scale back to 1 as the "new" state.
15513
+ // startViewTransition to drop the scale back to 1 as the "new" state; the
15514
+ // name stays, so the scale is morphed with the box rather than cross-faded.
15447
15515
 
15448
15516
  // The chevron is the one the table's column drop preview uses, rotated by the
15449
15517
  // CSS above so each cap points into the line.
@@ -15701,7 +15769,6 @@ const createDragClone = (element, pointerEvent) => {
15701
15769
  // Manual: it is opened and closed with the drag, and must survive an Escape
15702
15770
  // or a click elsewhere (light dismiss would take it away mid-gesture).
15703
15771
  wrapper.setAttribute("popover", "manual");
15704
- wrapper.viewTransitionName = "navi-drag-clone-wrapper";
15705
15772
  setCloneViewportRect(wrapper, element);
15706
15773
  // Grab point within the element — used as transform-origin so the
15707
15774
  // scale expands from where the user clicked, not the element center.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/dom",
3
- "version": "0.17.72",
3
+ "version": "0.17.73",
4
4
  "type": "module",
5
5
  "description": "DOM utilities for writing frontend code",
6
6
  "repository": {