@jsenv/dom 0.17.10 → 0.17.12
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 +335 -149
- package/package.json +1 -1
package/dist/jsenv_dom.js
CHANGED
|
@@ -8623,6 +8623,72 @@ const createDragGestureController = (options = {}) => {
|
|
|
8623
8623
|
};
|
|
8624
8624
|
dragGesture.dragViaPointer = dragViaPointer;
|
|
8625
8625
|
dragGesture.releaseViaPointer = releaseViaPointer;
|
|
8626
|
+
/*
|
|
8627
|
+
* A press that starts a drag is not a press that starts a selection: the
|
|
8628
|
+
* browser sees a pointer going down on text and moving, and that is its
|
|
8629
|
+
* own gesture — the words under the finger turn blue while the element
|
|
8630
|
+
* travels, and the selection outlives the release.
|
|
8631
|
+
*
|
|
8632
|
+
* Refused from the grab, before any threshold: whether the press becomes a
|
|
8633
|
+
* drag is decided a few pixels later, but the selection is decided at the
|
|
8634
|
+
* FIRST move, and by then it is too late to say no.
|
|
8635
|
+
*
|
|
8636
|
+
* `user-select: none` would say it in CSS, but it would say it to
|
|
8637
|
+
* everybody: the element would stop being selectable even when nobody is
|
|
8638
|
+
* dragging it. Here it is refused for the length of one gesture.
|
|
8639
|
+
*/
|
|
8640
|
+
const preventSelectStart = selectStartEvent => {
|
|
8641
|
+
selectStartEvent.preventDefault();
|
|
8642
|
+
};
|
|
8643
|
+
document.addEventListener("selectstart", preventSelectStart);
|
|
8644
|
+
// A press also puts an end to the selection the page was already holding,
|
|
8645
|
+
// the way the browser's own press does: refusing selectstart keeps a new
|
|
8646
|
+
// selection from being made, it says nothing about the one painted before
|
|
8647
|
+
// — which would otherwise sit there through a gesture that has nothing to
|
|
8648
|
+
// do with it.
|
|
8649
|
+
collapseSelection();
|
|
8650
|
+
dragGesture.addReleaseCallback(() => {
|
|
8651
|
+
document.removeEventListener("selectstart", preventSelectStart);
|
|
8652
|
+
});
|
|
8653
|
+
/*
|
|
8654
|
+
* Refusing every selection also refuses the one a press is entitled to
|
|
8655
|
+
* make: a double click selects the word under it, and that selection is
|
|
8656
|
+
* over before the pointer has gone anywhere. It is made here instead,
|
|
8657
|
+
* spelled out (see selectWordAtPoint) rather than left to a browser
|
|
8658
|
+
* heuristic that cannot tell a drag from a click.
|
|
8659
|
+
*
|
|
8660
|
+
* On the document and outliving the gesture, because the gesture is
|
|
8661
|
+
* already over when the second click completes: dblclick comes after
|
|
8662
|
+
* mouseup, the gesture ends at pointerup. It is dropped when it fires, and
|
|
8663
|
+
* otherwise when the next press installs its own — a listener waiting for
|
|
8664
|
+
* a double click that never comes costs nothing until then.
|
|
8665
|
+
*/
|
|
8666
|
+
removePendingDoubleClickListener();
|
|
8667
|
+
const onDoubleClick = dblclickEvent => {
|
|
8668
|
+
removePendingDoubleClickListener = NOOP;
|
|
8669
|
+
// A drag that happened is a gesture, not a click: the second press of a
|
|
8670
|
+
// double click can be the one that drags, and what it drags must not end
|
|
8671
|
+
// up selected too.
|
|
8672
|
+
if (dragGesture.gestureInfo.started) {
|
|
8673
|
+
return;
|
|
8674
|
+
}
|
|
8675
|
+
// Text the page says is not selectable stays not selectable: a
|
|
8676
|
+
// programmatic selection goes through `user-select: none` in every
|
|
8677
|
+
// engine — it is a rule about what the USER may start, and the browser
|
|
8678
|
+
// does not read it back when asked directly. Read here so that doing the
|
|
8679
|
+
// browser's work does not also undo what the page asked of it.
|
|
8680
|
+
if (!isSelectable(dblclickEvent.target)) {
|
|
8681
|
+
return;
|
|
8682
|
+
}
|
|
8683
|
+
selectWordAtPoint(dblclickEvent.clientX, dblclickEvent.clientY);
|
|
8684
|
+
};
|
|
8685
|
+
document.addEventListener("dblclick", onDoubleClick, {
|
|
8686
|
+
once: true
|
|
8687
|
+
});
|
|
8688
|
+
removePendingDoubleClickListener = () => {
|
|
8689
|
+
removePendingDoubleClickListener = NOOP;
|
|
8690
|
+
document.removeEventListener("dblclick", onDoubleClick);
|
|
8691
|
+
};
|
|
8626
8692
|
const cleanup = initializer({
|
|
8627
8693
|
onMove: dragViaPointer,
|
|
8628
8694
|
onRelease: releaseViaPointer,
|
|
@@ -8815,6 +8881,57 @@ const definePropertyAsReadOnly = (object, propertyName) => {
|
|
|
8815
8881
|
value: object[propertyName]
|
|
8816
8882
|
});
|
|
8817
8883
|
};
|
|
8884
|
+
const NOOP = () => {};
|
|
8885
|
+
let removePendingDoubleClickListener = NOOP;
|
|
8886
|
+
|
|
8887
|
+
// What a double click selects when the browser is allowed to do it itself: the
|
|
8888
|
+
// word around the caret the click lands on.
|
|
8889
|
+
const selectWordAtPoint = (x, y) => {
|
|
8890
|
+
const caretRange = createCaretRange(x, y);
|
|
8891
|
+
if (!caretRange) {
|
|
8892
|
+
return;
|
|
8893
|
+
}
|
|
8894
|
+
const selection = window.getSelection();
|
|
8895
|
+
selection.removeAllRanges();
|
|
8896
|
+
selection.addRange(caretRange);
|
|
8897
|
+
// "word" is not a position a Range can be built from — it is a movement the
|
|
8898
|
+
// selection knows how to make, and the caret walking to both of its edges is
|
|
8899
|
+
// what draws the word.
|
|
8900
|
+
if (selection.modify) {
|
|
8901
|
+
selection.modify("move", "backward", "word");
|
|
8902
|
+
selection.modify("extend", "forward", "word");
|
|
8903
|
+
}
|
|
8904
|
+
};
|
|
8905
|
+
const createCaretRange = (x, y) => {
|
|
8906
|
+
if (document.caretPositionFromPoint) {
|
|
8907
|
+
const caretPosition = document.caretPositionFromPoint(x, y);
|
|
8908
|
+
if (!caretPosition) {
|
|
8909
|
+
return null;
|
|
8910
|
+
}
|
|
8911
|
+
const range = document.createRange();
|
|
8912
|
+
range.setStart(caretPosition.offsetNode, caretPosition.offset);
|
|
8913
|
+
range.collapse(true);
|
|
8914
|
+
return range;
|
|
8915
|
+
}
|
|
8916
|
+
if (document.caretRangeFromPoint) {
|
|
8917
|
+
return document.caretRangeFromPoint(x, y);
|
|
8918
|
+
}
|
|
8919
|
+
return null;
|
|
8920
|
+
};
|
|
8921
|
+
const isSelectable = element => {
|
|
8922
|
+
if (!element || element.nodeType !== 1) {
|
|
8923
|
+
return true;
|
|
8924
|
+
}
|
|
8925
|
+
const computedStyle = window.getComputedStyle(element);
|
|
8926
|
+
const userSelect = computedStyle.userSelect || computedStyle.webkitUserSelect;
|
|
8927
|
+
return userSelect !== "none";
|
|
8928
|
+
};
|
|
8929
|
+
const collapseSelection = () => {
|
|
8930
|
+
const selection = window.getSelection();
|
|
8931
|
+
if (selection && !selection.isCollapsed) {
|
|
8932
|
+
selection.removeAllRanges();
|
|
8933
|
+
}
|
|
8934
|
+
};
|
|
8818
8935
|
|
|
8819
8936
|
installImportMetaCssBuild(import.meta);/**
|
|
8820
8937
|
* When a press becomes a drag.
|
|
@@ -8976,11 +9093,47 @@ const dragAfterLongPress = (grabEvent, dragGestureInitializer, {
|
|
|
8976
9093
|
onPressCancel,
|
|
8977
9094
|
onPress
|
|
8978
9095
|
}) => {
|
|
9096
|
+
/*
|
|
9097
|
+
* WHETHER a touchmove can be refused at all is decided when the touch BEGINS,
|
|
9098
|
+
* from the non-passive listeners present at that moment — and on this path the
|
|
9099
|
+
* gesture, which is what refuses it (see preventTouchScroll in
|
|
9100
|
+
* drag_gesture.js), is only born once the wait is over. By then the browser has
|
|
9101
|
+
* long made up its mind: every touchmove it hands over is already
|
|
9102
|
+
* `cancelable: false`, the refusal does nothing, and the page scrolls away with
|
|
9103
|
+
* the object still under the finger — until the touch is taken for a scroll and
|
|
9104
|
+
* the pointer stream is cancelled, which is the drag dying mid-gesture.
|
|
9105
|
+
*
|
|
9106
|
+
* So the listener the decision looks for is put down with the FINGER, before
|
|
9107
|
+
* anyone knows whether this press is a drag. It refuses nothing — a press that
|
|
9108
|
+
* is still only a press must leave the scroll alone, which is exactly what the
|
|
9109
|
+
* wait is there to tell apart. Its only job is to be there, so that the
|
|
9110
|
+
* refusal made later is one the browser still listens to.
|
|
9111
|
+
*/
|
|
9112
|
+
const keepTouchRefusable = () => {
|
|
9113
|
+
// Being registered IS the whole of it — see above.
|
|
9114
|
+
};
|
|
9115
|
+
const grabTarget = grabEvent.target;
|
|
9116
|
+
window.addEventListener("touchmove", keepTouchRefusable, {
|
|
9117
|
+
passive: false,
|
|
9118
|
+
capture: true
|
|
9119
|
+
});
|
|
9120
|
+
grabTarget.addEventListener("touchmove", keepTouchRefusable, {
|
|
9121
|
+
passive: false
|
|
9122
|
+
});
|
|
9123
|
+
const stopKeepingTouchRefusable = () => {
|
|
9124
|
+
window.removeEventListener("touchmove", keepTouchRefusable, {
|
|
9125
|
+
capture: true
|
|
9126
|
+
});
|
|
9127
|
+
grabTarget.removeEventListener("touchmove", keepTouchRefusable);
|
|
9128
|
+
};
|
|
8979
9129
|
waitForPressHeld(grabEvent, {
|
|
8980
9130
|
delay: longPressDelay,
|
|
8981
9131
|
slop: longPressSlop,
|
|
8982
9132
|
onPressStart,
|
|
8983
|
-
onPressCancel
|
|
9133
|
+
onPressCancel: pointerEvent => {
|
|
9134
|
+
stopKeepingTouchRefusable();
|
|
9135
|
+
onPressCancel?.(pointerEvent);
|
|
9136
|
+
},
|
|
8984
9137
|
onPressHeld: (pressEvent, {
|
|
8985
9138
|
endPress
|
|
8986
9139
|
}) => {
|
|
@@ -8990,10 +9143,14 @@ const dragAfterLongPress = (grabEvent, dragGestureInitializer, {
|
|
|
8990
9143
|
// for every way a drag can begin.
|
|
8991
9144
|
const dragGesture = startDragGesture(dragGestureInitializer);
|
|
8992
9145
|
if (!dragGesture) {
|
|
9146
|
+
stopKeepingTouchRefusable();
|
|
8993
9147
|
endPress();
|
|
8994
9148
|
return;
|
|
8995
9149
|
}
|
|
8996
|
-
dragGesture.addReleaseCallback(
|
|
9150
|
+
dragGesture.addReleaseCallback(() => {
|
|
9151
|
+
stopKeepingTouchRefusable();
|
|
9152
|
+
endPress();
|
|
9153
|
+
});
|
|
8997
9154
|
}
|
|
8998
9155
|
});
|
|
8999
9156
|
};
|
|
@@ -10921,33 +11078,6 @@ const findTableCellCol = (cellElement) => {
|
|
|
10921
11078
|
return correspondingCol;
|
|
10922
11079
|
};
|
|
10923
11080
|
|
|
10924
|
-
// Temporarily attach to the element so inherited CSS vars resolve correctly,
|
|
10925
|
-
// then snapshot all drop-hint custom properties onto the scroll container
|
|
10926
|
-
// so they survive once the element moves to the scroll container.
|
|
10927
|
-
const moveCSSVars = (vars, fromEl, toEl) => {
|
|
10928
|
-
const fromComputedStyle = getComputedStyle(fromEl);
|
|
10929
|
-
const savedVars = {};
|
|
10930
|
-
for (const varName of vars) {
|
|
10931
|
-
const value = fromComputedStyle.getPropertyValue(varName).trim();
|
|
10932
|
-
if (value) {
|
|
10933
|
-
savedVars[varName] = toEl.style.getPropertyValue(varName);
|
|
10934
|
-
toEl.style.setProperty(varName, value);
|
|
10935
|
-
}
|
|
10936
|
-
}
|
|
10937
|
-
|
|
10938
|
-
return () => {
|
|
10939
|
-
for (const varName of vars) {
|
|
10940
|
-
if (varName in savedVars) {
|
|
10941
|
-
if (savedVars[varName]) {
|
|
10942
|
-
toEl.style.setProperty(varName, savedVars[varName]);
|
|
10943
|
-
} else {
|
|
10944
|
-
toEl.style.removeProperty(varName);
|
|
10945
|
-
}
|
|
10946
|
-
}
|
|
10947
|
-
}
|
|
10948
|
-
};
|
|
10949
|
-
};
|
|
10950
|
-
|
|
10951
11081
|
const applyStickyFrontiersToAutoScrollArea = (
|
|
10952
11082
|
autoScrollArea,
|
|
10953
11083
|
{ direction, scrollContainer, dragName },
|
|
@@ -11081,6 +11211,12 @@ installImportMetaCssBuild(import.meta);/**
|
|
|
11081
11211
|
* stable row of items to look between.
|
|
11082
11212
|
* - **toss**: it is gotten rid of. The same copy, for the opposite reason: the
|
|
11083
11213
|
* original stays until the answer says it is really gone.
|
|
11214
|
+
* - **land**: it comes down ON something. Also a copy, and the closest to
|
|
11215
|
+
* `reorder` — the difference is what a target IS: a row of a list is a place
|
|
11216
|
+
* BETWEEN two others, whereas a square of a board is a place of its own, which
|
|
11217
|
+
* may already be taken. So nothing is inserted and nothing is a no-op: the
|
|
11218
|
+
* answer is "this one came down on that one", and what that means (take the
|
|
11219
|
+
* place, swap the two, refuse) is the caller's.
|
|
11084
11220
|
*
|
|
11085
11221
|
* The caller lists which outcomes ITS element can answer, and only the machinery
|
|
11086
11222
|
* those need runs: no copy for a move, no drop hint for something that can only be
|
|
@@ -11102,13 +11238,14 @@ const TOSS_DURATION_MS = 320;
|
|
|
11102
11238
|
// Far enough to be off any screen, in the direction the hand was going.
|
|
11103
11239
|
const TOSS_DISTANCE = 900;
|
|
11104
11240
|
const css$1 = /* css */`
|
|
11105
|
-
/*
|
|
11106
|
-
|
|
11107
|
-
|
|
11241
|
+
/* IT COSTS THE LIST NOTHING: the hint lands on the edge of a row, which for
|
|
11242
|
+
the last one is the very bottom of the scroll area — a line taking up room
|
|
11243
|
+
there would push the scrollable area a few pixels further and make a
|
|
11108
11244
|
scrollbar appear (or hide the hint under it) exactly when one is trying to
|
|
11109
|
-
drop at the end.
|
|
11110
|
-
|
|
11111
|
-
the
|
|
11245
|
+
drop at the end. Being fixed is what avoids it: a fixed box has the
|
|
11246
|
+
viewport as containing block, so it is left out of the scrollable overflow
|
|
11247
|
+
of every ancestor and can overhang the list freely. Same for the clone it
|
|
11248
|
+
accompanies. */
|
|
11112
11249
|
.navi_drop_hint {
|
|
11113
11250
|
/* A popover, so it lands in the top layer: no z-index to bid against the
|
|
11114
11251
|
page, and nothing it can be hidden behind. Shown BEFORE the clone, which
|
|
@@ -11150,8 +11287,8 @@ const css$1 = /* css */`
|
|
|
11150
11287
|
/* A chevron at each end, pointing in: the line alone is easy to lose against
|
|
11151
11288
|
a list of borders and separators, two arrows read as "here" at a glance
|
|
11152
11289
|
(same idea as the table's column drop preview). They overhang the line,
|
|
11153
|
-
which costs nothing
|
|
11154
|
-
|
|
11290
|
+
which costs nothing to a box left out of the scrollable area — and the more
|
|
11291
|
+
they stick out, the easier they are to spot. */
|
|
11155
11292
|
.navi_drop_hint_cap {
|
|
11156
11293
|
position: absolute;
|
|
11157
11294
|
top: 50%;
|
|
@@ -11172,14 +11309,45 @@ const css$1 = /* css */`
|
|
|
11172
11309
|
rotate: 90deg;
|
|
11173
11310
|
}
|
|
11174
11311
|
|
|
11312
|
+
/* WHERE IT LANDS, when landing is ON a thing rather than between two: the
|
|
11313
|
+
place itself is lit up, because there is no gap to draw a line in. Fixed
|
|
11314
|
+
and in the top layer for the same reasons as the line above. */
|
|
11315
|
+
.navi_drop_surface {
|
|
11316
|
+
position: fixed;
|
|
11317
|
+
inset: auto;
|
|
11318
|
+
top: var(--drop-target-top);
|
|
11319
|
+
left: var(--drop-target-left);
|
|
11320
|
+
display: none;
|
|
11321
|
+
box-sizing: border-box;
|
|
11322
|
+
width: var(--drop-target-width);
|
|
11323
|
+
height: var(--drop-target-height);
|
|
11324
|
+
margin: 0;
|
|
11325
|
+
padding: 0;
|
|
11326
|
+
color: inherit;
|
|
11327
|
+
background: var(--drop-surface-background-color, rgba(68, 118, 255, 0.16));
|
|
11328
|
+
border: var(--drop-surface-border-width, 2px) solid
|
|
11329
|
+
var(--drop-surface-border-color, #4476ff);
|
|
11330
|
+
border-radius: var(--drop-surface-border-radius, 6px);
|
|
11331
|
+
pointer-events: none;
|
|
11332
|
+
overflow: visible;
|
|
11333
|
+
}
|
|
11334
|
+
.navi_drop_surface[data-drop-over]:popover-open {
|
|
11335
|
+
display: block;
|
|
11336
|
+
}
|
|
11337
|
+
|
|
11175
11338
|
/* WHO CAN START A DRAG, said in the cursor.
|
|
11176
|
-
A handle
|
|
11177
|
-
the
|
|
11178
|
-
|
|
11179
|
-
|
|
11180
|
-
|
|
11181
|
-
|
|
11182
|
-
|
|
11339
|
+
A handle exists only to drag, so it shows the hand. A source does not, and
|
|
11340
|
+
the gesture must not claim its cursor: it drags only once the intent shows
|
|
11341
|
+
(a few pixels of travel, or a long press), a plain click on it stays a
|
|
11342
|
+
click, and it is usually something else FIRST — a link, a card one opens.
|
|
11343
|
+
The cursor says what the element is, and a hand insisting on the one thing
|
|
11344
|
+
it can also be would talk over that. So it is left alone — default, and not
|
|
11345
|
+
an I-beam, because dragging across the text does not select it (the gesture
|
|
11346
|
+
takes the pointer; see the selectstart refused in drag_gesture.js) — and
|
|
11347
|
+
whoever puts the drag there asks for the hand when a grab really is the
|
|
11348
|
+
first thing the element offers.
|
|
11349
|
+
An opted-out area keeps both its cursor and its selection, and never starts
|
|
11350
|
+
a drag (see the check in startDragTo).
|
|
11183
11351
|
Controls inside a source keep their own cursor: cursor is inherited, and
|
|
11184
11352
|
anything setting its own (a button's pointer) wins on itself.
|
|
11185
11353
|
Only the resting cursor is set here: what it becomes once a drag is under
|
|
@@ -11190,11 +11358,9 @@ const css$1 = /* css */`
|
|
|
11190
11358
|
}
|
|
11191
11359
|
[data-drag-source] {
|
|
11192
11360
|
cursor: default;
|
|
11193
|
-
user-select: none;
|
|
11194
11361
|
}
|
|
11195
11362
|
[data-drag-ignore] {
|
|
11196
11363
|
cursor: auto;
|
|
11197
|
-
user-select: auto;
|
|
11198
11364
|
}
|
|
11199
11365
|
|
|
11200
11366
|
[navi-drag-clone-source] {
|
|
@@ -11218,13 +11384,10 @@ const css$1 = /* css */`
|
|
|
11218
11384
|
color: inherit;
|
|
11219
11385
|
background: transparent;
|
|
11220
11386
|
border: none;
|
|
11221
|
-
/*
|
|
11222
|
-
|
|
11223
|
-
|
|
11224
|
-
shade is a theme's business either way. */
|
|
11225
|
-
box-shadow: var(--drag-clone-shadow, 0 12px 28px rgba(0, 0, 0, 0.22));
|
|
11387
|
+
/* Carries the chain down to the copy, for an item whose own radius is an
|
|
11388
|
+
"inherit" from the list around it. */
|
|
11389
|
+
border-radius: inherit;
|
|
11226
11390
|
opacity: 0.95;
|
|
11227
|
-
transition: box-shadow 0.15s ease;
|
|
11228
11391
|
pointer-events: none;
|
|
11229
11392
|
/* Nothing in a copy being carried by a pointer is text to select: the
|
|
11230
11393
|
selection belongs to the original, which is still in the page. This is the
|
|
@@ -11247,17 +11410,23 @@ const css$1 = /* css */`
|
|
|
11247
11410
|
}
|
|
11248
11411
|
|
|
11249
11412
|
[navi-drag-clone] {
|
|
11413
|
+
/* Cast by the copy itself rather than by the box around it, so it takes the
|
|
11414
|
+
shape of the thing — a rounded row throws a rounded shadow. Its value is a
|
|
11415
|
+
var read on the copy, which IS the dragged element: what being carried
|
|
11416
|
+
looks like belongs to whoever owns the thing — a row lifted off a list
|
|
11417
|
+
wants this shadow, a sheet of paper leaving a board wants none, and its
|
|
11418
|
+
shade is a theme's business either way. */
|
|
11419
|
+
box-shadow: var(--drag-clone-shadow, 0 12px 28px rgba(0, 0, 0, 0.22));
|
|
11250
11420
|
transform: scale(var(--drag-clone-scale, 1.03));
|
|
11251
11421
|
transform-origin: var(--drag-origin);
|
|
11252
|
-
transition:
|
|
11422
|
+
transition:
|
|
11423
|
+
transform 0.15s cubic-bezier(0.34, 1.56, 0.64, 1),
|
|
11424
|
+
box-shadow 0.15s ease;
|
|
11253
11425
|
}
|
|
11254
11426
|
|
|
11255
11427
|
@starting-style {
|
|
11256
|
-
[navi-drag-clone-wrapper] {
|
|
11257
|
-
box-shadow: none;
|
|
11258
|
-
}
|
|
11259
|
-
|
|
11260
11428
|
[navi-drag-clone] {
|
|
11429
|
+
box-shadow: none;
|
|
11261
11430
|
transform: scale(1);
|
|
11262
11431
|
}
|
|
11263
11432
|
}
|
|
@@ -11265,7 +11434,6 @@ const css$1 = /* css */`
|
|
|
11265
11434
|
// At module scope, not inside startDragTo: the cursor rules above say who
|
|
11266
11435
|
// can start a drag, and they have to be true BEFORE anyone drags anything.
|
|
11267
11436
|
import.meta.css = [css$1, "@jsenv/dom/src/interaction/drag/drag_to.js"];
|
|
11268
|
-
const dragCSSVars = ["--drop-hint-size", "--drop-hint-background-color", "--drop-hint-border-radius", "--drop-hint-margin-x", "--drop-hint-margin-y", "--drop-hint-arrow-size", "--drag-clone-scale", "--drag-clone-shadow"];
|
|
11269
11437
|
|
|
11270
11438
|
/**
|
|
11271
11439
|
* Starts a drag-to-reorder interaction on a list item.
|
|
@@ -11276,9 +11444,9 @@ const dragCSSVars = ["--drop-hint-size", "--drop-hint-background-color", "--drop
|
|
|
11276
11444
|
* reorders anything by accident.
|
|
11277
11445
|
* - Clones the grabbed element and moves the clone while the original stays hidden in place
|
|
11278
11446
|
* (keeps the layout intact so other items don't shift during the drag).
|
|
11279
|
-
* -
|
|
11280
|
-
*
|
|
11281
|
-
*
|
|
11447
|
+
* - The clone and the drop-hint live in the dragged element's own parent, so the CSS vars
|
|
11448
|
+
* that dress them (`--drag-clone-shadow`, `--drop-hint-size`, …) reach them by plain
|
|
11449
|
+
* inheritance, and so do the rules the list writes for its items.
|
|
11282
11450
|
* - Shows a drop-hint line indicating where the item will land.
|
|
11283
11451
|
* - Drop-target detection is intersection-based: the clone's bounding rect is compared
|
|
11284
11452
|
* against every item that matches `itemSelector` in the scroll container.
|
|
@@ -11715,10 +11883,11 @@ const createDragToMoveGestureController = ({
|
|
|
11715
11883
|
* Starts a drag, for one or more of the outcomes listed.
|
|
11716
11884
|
*
|
|
11717
11885
|
* @param {PointerEvent} event The `pointerdown` that may become a drag.
|
|
11718
|
-
* @param {("move"|"reorder"|"toss")[]} effects
|
|
11719
|
-
* What letting go of this element can mean. `reorder` and `
|
|
11720
|
-
* `move` carries the element itself. Asking for `move` and `reorder`
|
|
11721
|
-
* asking one release to mean two things
|
|
11886
|
+
* @param {("move"|"reorder"|"toss"|"land")[]} effects
|
|
11887
|
+
* What letting go of this element can mean. `reorder`, `toss` and `land` carry a
|
|
11888
|
+
* copy; `move` carries the element itself. Asking for `move` and `reorder`
|
|
11889
|
+
* together is asking one release to mean two things, and so is asking for
|
|
11890
|
+
* `reorder` and `land`.
|
|
11722
11891
|
* @param {object} [options]
|
|
11723
11892
|
* @param {Element} [options.draggedElement=event.currentTarget]
|
|
11724
11893
|
* @param {(detail: {gestureInfo: object, x: number, y: number}) => Promise|void} [options.onMove]
|
|
@@ -11734,6 +11903,12 @@ const createDragToMoveGestureController = ({
|
|
|
11734
11903
|
* It was thrown away. The copy leaves the screen while this runs and comes back
|
|
11735
11904
|
* if the promise rejects, because the thing still exists and the screen has to
|
|
11736
11905
|
* say so.
|
|
11906
|
+
* @param {function} [options.onLand]
|
|
11907
|
+
* `onLand(fromId, toId, syncCloneWithDropTarget)` — it came down on `toId`, which
|
|
11908
|
+
* is an element and never null: nothing under the copy is a cancelled release.
|
|
11909
|
+
* The copy is held until what comes back settles, exactly like `onReorder`.
|
|
11910
|
+
* `syncCloneWithDropTarget` takes an element when the place is not the shape of
|
|
11911
|
+
* what stands on it: the copy then takes THAT box instead of the target's.
|
|
11737
11912
|
* @param {number} [options.tossDistance=110] How far a throw goes, in px.
|
|
11738
11913
|
* @param {number} [options.tossSpeed=0.45] And how fast, in px/ms. BOTH are asked
|
|
11739
11914
|
* for: one without the other is moving the thing while hesitating, and nothing is
|
|
@@ -11768,11 +11943,13 @@ const startDragTo = (event, effects, {
|
|
|
11768
11943
|
}
|
|
11769
11944
|
const canReorder = effects.includes("reorder");
|
|
11770
11945
|
const canToss = effects.includes("toss");
|
|
11771
|
-
|
|
11946
|
+
const canLand = effects.includes("land");
|
|
11947
|
+
if (canReorder || canToss || canLand) {
|
|
11772
11948
|
return startDragToCarryCopy(event, {
|
|
11773
11949
|
draggedElement,
|
|
11774
11950
|
canReorder,
|
|
11775
11951
|
canToss,
|
|
11952
|
+
canLand,
|
|
11776
11953
|
...options
|
|
11777
11954
|
});
|
|
11778
11955
|
}
|
|
@@ -11857,6 +12034,7 @@ const resolveDropMeaning = ({
|
|
|
11857
12034
|
hasDropTarget,
|
|
11858
12035
|
canReorder,
|
|
11859
12036
|
canToss,
|
|
12037
|
+
canLand,
|
|
11860
12038
|
tossDistance = TOSS_DISTANCE_TO_COMMIT,
|
|
11861
12039
|
tossSpeed = TOSS_SPEED_TO_COMMIT
|
|
11862
12040
|
}) => {
|
|
@@ -11870,8 +12048,13 @@ const resolveDropMeaning = ({
|
|
|
11870
12048
|
return "toss";
|
|
11871
12049
|
}
|
|
11872
12050
|
}
|
|
11873
|
-
if (
|
|
11874
|
-
|
|
12051
|
+
if (hasDropTarget) {
|
|
12052
|
+
if (canLand) {
|
|
12053
|
+
return "land";
|
|
12054
|
+
}
|
|
12055
|
+
if (canReorder) {
|
|
12056
|
+
return "reorder";
|
|
12057
|
+
}
|
|
11875
12058
|
}
|
|
11876
12059
|
return "cancel";
|
|
11877
12060
|
};
|
|
@@ -11880,13 +12063,15 @@ const resolveDropMeaning = ({
|
|
|
11880
12063
|
* A COPY of the element is carried, and the original keeps its place in the
|
|
11881
12064
|
* layout — which is what makes a reorder possible at all: nothing else moves
|
|
11882
12065
|
* while the hand looks for a place, so there is a stable row of items to look
|
|
11883
|
-
* between. A
|
|
11884
|
-
* until the answer says it is really
|
|
12066
|
+
* between. A landing on a place of a board is the same, and a throw uses that copy
|
|
12067
|
+
* for the opposite reason: the original stays until the answer says it is really
|
|
12068
|
+
* gone.
|
|
11885
12069
|
*/
|
|
11886
12070
|
const startDragToCarryCopy = (event, {
|
|
11887
12071
|
draggedElement,
|
|
11888
12072
|
canReorder,
|
|
11889
12073
|
canToss,
|
|
12074
|
+
canLand,
|
|
11890
12075
|
// Something that can be thrown away has to be able to LEAVE. The default of
|
|
11891
12076
|
// the layer below keeps what is dragged inside its scroll area, which is right
|
|
11892
12077
|
// for a reorder (a row belongs to its list) and makes a throw impossible — the
|
|
@@ -11901,10 +12086,16 @@ const startDragToCarryCopy = (event, {
|
|
|
11901
12086
|
itemSelector,
|
|
11902
12087
|
getItemId,
|
|
11903
12088
|
onReorder,
|
|
12089
|
+
onLand,
|
|
11904
12090
|
onToss,
|
|
11905
12091
|
tossDistance,
|
|
11906
12092
|
tossSpeed,
|
|
11907
|
-
|
|
12093
|
+
// A list runs one way and reordering walks it; a board has places all around,
|
|
12094
|
+
// so something landing on one of them goes wherever the hand takes it.
|
|
12095
|
+
direction = canLand ? {
|
|
12096
|
+
x: true,
|
|
12097
|
+
y: true
|
|
12098
|
+
} : {
|
|
11908
12099
|
x: false,
|
|
11909
12100
|
y: true
|
|
11910
12101
|
},
|
|
@@ -11930,9 +12121,6 @@ const startDragToCarryCopy = (event, {
|
|
|
11930
12121
|
return dragAfterIntent(event, () => {
|
|
11931
12122
|
const cloneWrapper = createDragClone(draggedElement, event);
|
|
11932
12123
|
draggedElement.setAttribute("navi-drag-clone-source", "");
|
|
11933
|
-
// Move drag related CSS vars from the element to the document
|
|
11934
|
-
// so they're accessible to .navi_drop_hint and the clone (which are both in document.body)
|
|
11935
|
-
const restoreCSSVars = moveCSSVars(dragCSSVars, draggedElement, document.documentElement);
|
|
11936
12124
|
const gestureController = createDragToMoveGestureController({
|
|
11937
12125
|
direction,
|
|
11938
12126
|
releasePositionEffect: "manual",
|
|
@@ -11948,10 +12136,14 @@ const startDragToCarryCopy = (event, {
|
|
|
11948
12136
|
dragGesture.gestureInfo.elementImpacted = cloneWrapper;
|
|
11949
12137
|
|
|
11950
12138
|
// No place to land, no hint: an element that can only be thrown away has
|
|
11951
|
-
// nowhere to be put.
|
|
11952
|
-
|
|
12139
|
+
// nowhere to be put. What the hint LOOKS like follows what a place is here —
|
|
12140
|
+
// a line in the gap between two items, or the place itself lit up.
|
|
12141
|
+
const dropHintEl = canLand ? createDropSurface() : canReorder ? createDropHint() : null;
|
|
11953
12142
|
if (dropHintEl) {
|
|
11954
|
-
|
|
12143
|
+
// In the container it draws into, which is where its own vars are set: the
|
|
12144
|
+
// shape of a drop hint is a property of the list or board it belongs to,
|
|
12145
|
+
// and reading it from there is inheritance rather than a hand-off.
|
|
12146
|
+
draggedElement.parentElement.appendChild(dropHintEl);
|
|
11955
12147
|
}
|
|
11956
12148
|
// The hint first, the clone second: that order is what stacks them in the
|
|
11957
12149
|
// top layer.
|
|
@@ -11967,10 +12159,12 @@ const startDragToCarryCopy = (event, {
|
|
|
11967
12159
|
return;
|
|
11968
12160
|
}
|
|
11969
12161
|
dropHintEl.removeAttribute("data-drop-edge");
|
|
12162
|
+
dropHintEl.removeAttribute("data-drop-over");
|
|
11970
12163
|
dropHintEl.style.removeProperty("--drop-target-top");
|
|
11971
12164
|
dropHintEl.style.removeProperty("--drop-target-bottom");
|
|
11972
12165
|
dropHintEl.style.removeProperty("--drop-target-left");
|
|
11973
12166
|
dropHintEl.style.removeProperty("--drop-target-width");
|
|
12167
|
+
dropHintEl.style.removeProperty("--drop-target-height");
|
|
11974
12168
|
};
|
|
11975
12169
|
const clearDropHint = () => {
|
|
11976
12170
|
currentBeforeElement = undefined;
|
|
@@ -11990,13 +12184,32 @@ const startDragToCarryCopy = (event, {
|
|
|
11990
12184
|
}
|
|
11991
12185
|
}
|
|
11992
12186
|
const dropTargetInfo = getDropTargetInfo(gestureInfo, items, {
|
|
11993
|
-
|
|
12187
|
+
// The edges of a LIST: above the first row means the top of it, below
|
|
12188
|
+
// the last one means the end of it. A board has no such reading — away
|
|
12189
|
+
// from every place is away from every place.
|
|
12190
|
+
fallbackToEdge: !canLand
|
|
11994
12191
|
});
|
|
11995
12192
|
gestureInfo.dropTargetInfo = dropTargetInfo || null;
|
|
11996
12193
|
if (!dropTargetInfo) {
|
|
11997
12194
|
clearDropHint();
|
|
11998
12195
|
return;
|
|
11999
12196
|
}
|
|
12197
|
+
if (canLand) {
|
|
12198
|
+
// The whole element is the target, so which of its edges the copy came
|
|
12199
|
+
// in by says nothing: there is no gap to be on one side of.
|
|
12200
|
+
const dropElement = dropTargetInfo.element;
|
|
12201
|
+
if (dropElement === currentReleaseElement) {
|
|
12202
|
+
return;
|
|
12203
|
+
}
|
|
12204
|
+
currentReleaseElement = dropElement;
|
|
12205
|
+
const dropRect = dropElement.getBoundingClientRect();
|
|
12206
|
+
dropHintEl.setAttribute("data-drop-over", "");
|
|
12207
|
+
dropHintEl.style.setProperty("--drop-target-top", `${dropRect.top}px`);
|
|
12208
|
+
dropHintEl.style.setProperty("--drop-target-left", `${dropRect.left}px`);
|
|
12209
|
+
dropHintEl.style.setProperty("--drop-target-width", `${dropRect.width}px`);
|
|
12210
|
+
dropHintEl.style.setProperty("--drop-target-height", `${dropRect.height}px`);
|
|
12211
|
+
return;
|
|
12212
|
+
}
|
|
12000
12213
|
// Convert {element, edge} to a beforeElement using the items array
|
|
12001
12214
|
// (not nextElementSibling, which breaks if non-item elements exist between items).
|
|
12002
12215
|
// edge "start" → insert before the hovered element
|
|
@@ -12037,21 +12250,44 @@ const startDragToCarryCopy = (event, {
|
|
|
12037
12250
|
dragGesture.addReleaseCallback(async gestureInfo => {
|
|
12038
12251
|
clearDropHintDOM();
|
|
12039
12252
|
dropHintEl?.remove();
|
|
12040
|
-
restoreCSSVars();
|
|
12041
12253
|
|
|
12042
12254
|
// What THIS release means, from what the element said it can answer. A
|
|
12043
12255
|
// throw is asked about first: it is the more insistent of the two, and a
|
|
12044
12256
|
// hand that sent the thing across the screen has not asked for it to swap
|
|
12045
12257
|
// places with whatever it happened to fly over.
|
|
12046
|
-
const hasDropTarget = currentBeforeElement !== undefined;
|
|
12258
|
+
const hasDropTarget = canLand ? currentReleaseElement !== undefined : currentBeforeElement !== undefined;
|
|
12047
12259
|
const dropMeans = resolveDropMeaning({
|
|
12048
12260
|
gestureInfo,
|
|
12049
12261
|
hasDropTarget,
|
|
12050
12262
|
canReorder,
|
|
12051
12263
|
canToss,
|
|
12264
|
+
canLand,
|
|
12052
12265
|
tossDistance,
|
|
12053
12266
|
tossSpeed
|
|
12054
12267
|
});
|
|
12268
|
+
|
|
12269
|
+
// The copy stops where the hand left it, and the answer is given a way to
|
|
12270
|
+
// take it the rest of the way — synchronously, inside a view transition, so
|
|
12271
|
+
// it is captured where it lands rather than where it was let go of.
|
|
12272
|
+
const landCopyOn = async (targetElement, answer) => {
|
|
12273
|
+
const clone = cloneWrapper.firstElementChild;
|
|
12274
|
+
// Bake the current visual position (transform included) into the CSS vars
|
|
12275
|
+
// so the copy stays where the user released it when the transform goes.
|
|
12276
|
+
setCloneViewportRect(cloneWrapper, cloneWrapper);
|
|
12277
|
+
gestureInfo.cancelPosition();
|
|
12278
|
+
// Where the copy comes down is not always the thing it came down ON: a
|
|
12279
|
+
// place of a board can be larger than what stands on it, and the copy
|
|
12280
|
+
// has to keep its own size and land where the item will be. Said with
|
|
12281
|
+
// an element, because the caller has one — the piece already standing
|
|
12282
|
+
// there, the empty slot waiting.
|
|
12283
|
+
const syncCloneWithDropTarget = (landingElement = targetElement) => {
|
|
12284
|
+
setCloneViewportRect(cloneWrapper, landingElement);
|
|
12285
|
+
// Removing this attr drops the CSS scale, so the browser captures the
|
|
12286
|
+
// copy at scale 1 as the "new" state.
|
|
12287
|
+
clone.removeAttribute("navi-drag-clone");
|
|
12288
|
+
};
|
|
12289
|
+
await answer(syncCloneWithDropTarget);
|
|
12290
|
+
};
|
|
12055
12291
|
if (dropMeans === "toss") {
|
|
12056
12292
|
// Bake the position the hand left it at, so the flight starts from
|
|
12057
12293
|
// there rather than from where the clone was declared.
|
|
@@ -12064,25 +12300,10 @@ const startDragToCarryCopy = (event, {
|
|
|
12064
12300
|
// place.
|
|
12065
12301
|
await settleCloneBack(cloneWrapper, draggedElement);
|
|
12066
12302
|
}
|
|
12067
|
-
} else if (dropMeans === "
|
|
12068
|
-
|
|
12069
|
-
|
|
12070
|
-
|
|
12071
|
-
setCloneViewportRect(cloneWrapper, cloneWrapper);
|
|
12072
|
-
gestureInfo.cancelPosition();
|
|
12073
|
-
const fromId = getItemId(draggedElement);
|
|
12074
|
-
const toId = currentBeforeElement ? getItemId(currentBeforeElement) : null;
|
|
12075
|
-
// provide onReorder a way to synchronously move the clone to the drop target
|
|
12076
|
-
// (meant to be used inside a startViewTransition callback)
|
|
12077
|
-
const syncCloneWithDropTarget = () => {
|
|
12078
|
-
// Snap the CSS-var position to the drop target rect so the browser
|
|
12079
|
-
// captures the "new" state at the landing position.
|
|
12080
|
-
setCloneViewportRect(cloneWrapper, currentReleaseElement);
|
|
12081
|
-
// Removing this attr drops the CSS scale(1.15), so the browser
|
|
12082
|
-
// captures the clone at scale 1 as the "new" state.
|
|
12083
|
-
clone.removeAttribute("navi-drag-clone");
|
|
12084
|
-
};
|
|
12085
|
-
await onReorder(fromId, toId, syncCloneWithDropTarget);
|
|
12303
|
+
} else if (dropMeans === "land") {
|
|
12304
|
+
await landCopyOn(currentReleaseElement, syncCloneWithDropTarget => onLand(getItemId(draggedElement), getItemId(currentReleaseElement), syncCloneWithDropTarget));
|
|
12305
|
+
} else if (dropMeans === "reorder") {
|
|
12306
|
+
await landCopyOn(currentReleaseElement, syncCloneWithDropTarget => onReorder(getItemId(draggedElement), currentBeforeElement ? getItemId(currentBeforeElement) : null, syncCloneWithDropTarget));
|
|
12086
12307
|
}
|
|
12087
12308
|
draggedElement.removeAttribute("navi-drag-clone-source");
|
|
12088
12309
|
cloneWrapper.remove();
|
|
@@ -12153,6 +12374,14 @@ const createDropHint = () => {
|
|
|
12153
12374
|
div.innerHTML = dropHintTemplate.trim();
|
|
12154
12375
|
return div.firstElementChild;
|
|
12155
12376
|
};
|
|
12377
|
+
const createDropSurface = () => {
|
|
12378
|
+
const div = document.createElement("div");
|
|
12379
|
+
div.className = "navi_drop_surface";
|
|
12380
|
+
// Manual, like the copy it accompanies: it is opened and closed with the drag
|
|
12381
|
+
// and must survive an Escape or a click elsewhere.
|
|
12382
|
+
div.setAttribute("popover", "manual");
|
|
12383
|
+
return div;
|
|
12384
|
+
};
|
|
12156
12385
|
|
|
12157
12386
|
/**
|
|
12158
12387
|
* The copy leaves the screen the way it was thrown, and the caller says what that
|
|
@@ -12211,13 +12440,6 @@ const createDragClone = (element, pointerEvent) => {
|
|
|
12211
12440
|
// scale(1.15) expands from where the user clicked, not the element center.
|
|
12212
12441
|
// These offsets are element-relative so viewport coords are correct here.
|
|
12213
12442
|
wrapper.style.setProperty("--drag-origin", `${pointerEvent.clientX - rect.left}px ${pointerEvent.clientY - rect.top}px`);
|
|
12214
|
-
// The clone is appended to document.body, so it loses inherited styles
|
|
12215
|
-
// from the original parent. Copy the computed inherited properties that
|
|
12216
|
-
// are most likely to affect visual appearance.
|
|
12217
|
-
const computedStyle = getComputedStyle(element.parentElement);
|
|
12218
|
-
for (const property of INHERITED_PROPERTIES_TO_COPY_SET) {
|
|
12219
|
-
wrapper.style.setProperty(property, computedStyle.getPropertyValue(property));
|
|
12220
|
-
}
|
|
12221
12443
|
const elementClone = element.cloneNode(true);
|
|
12222
12444
|
// A deep copy copies the ids too, and two elements answering to one id is a
|
|
12223
12445
|
// document that lies: getElementById picks whichever comes first, an anchor
|
|
@@ -12235,12 +12457,15 @@ const createDragClone = (element, pointerEvent) => {
|
|
|
12235
12457
|
elementClone.setAttribute("data-grabbed", "");
|
|
12236
12458
|
elementClone.style.viewTransitionName = "navi-drag-clone";
|
|
12237
12459
|
wrapper.appendChild(elementClone);
|
|
12238
|
-
|
|
12460
|
+
// Beside the thing it copies, so it stands where that thing stands: every
|
|
12461
|
+
// inherited value and every custom property the original reads, the copy reads
|
|
12462
|
+
// too, and a rule written for an item in this list finds the copy as well. The
|
|
12463
|
+
// top layer is what lets it stay there — a popover is painted above the page
|
|
12464
|
+
// whatever its depth in the tree, and being fixed keeps it out of the
|
|
12465
|
+
// scrollable overflow of the list it sits in.
|
|
12466
|
+
element.parentElement.appendChild(wrapper);
|
|
12239
12467
|
return wrapper;
|
|
12240
12468
|
};
|
|
12241
|
-
const INHERITED_PROPERTIES_TO_COPY_SET = new Set(["color", "font-family", "font-size", "font-weight", "font-style", "line-height", "letter-spacing",
|
|
12242
|
-
// in case the item has border-radius: inherit. The clone can inherit too
|
|
12243
|
-
"border-radius"]);
|
|
12244
12469
|
|
|
12245
12470
|
const startDragToResizeGesture = (
|
|
12246
12471
|
pointerdownEvent,
|
|
@@ -12392,15 +12617,6 @@ import.meta.css = [/* css */`
|
|
|
12392
12617
|
[data-drag-travel*="y"] * {
|
|
12393
12618
|
overscroll-behavior-y: contain !important;
|
|
12394
12619
|
}
|
|
12395
|
-
:root[${WALKING_ATTRIBUTE}] {
|
|
12396
|
-
/* A drag over text selects it on the way, and the blue trail says the
|
|
12397
|
-
gesture was understood as something else. Not from the press: a press on
|
|
12398
|
-
text IS how one selects it, and only a press that has become a travel has
|
|
12399
|
-
said it was about something else — which is also why this cannot be the
|
|
12400
|
-
whole answer, and why the selection made meanwhile is dropped by hand
|
|
12401
|
-
(see dropSelection). */
|
|
12402
|
-
user-select: none;
|
|
12403
|
-
}
|
|
12404
12620
|
`, "@jsenv/dom/src/interaction/drag/drag_to_travel.js"];
|
|
12405
12621
|
|
|
12406
12622
|
// How far a pointer goes before it is a travel rather than a click: below this
|
|
@@ -12476,29 +12692,6 @@ const axesLeftBy = (axes, fromElement, stopElement, attribute) => {
|
|
|
12476
12692
|
return left;
|
|
12477
12693
|
};
|
|
12478
12694
|
|
|
12479
|
-
/**
|
|
12480
|
-
* What the browser painted blue while it was still allowed to think this press
|
|
12481
|
-
* was about text.
|
|
12482
|
-
*
|
|
12483
|
-
* A mouse dragged across a page selects what it crosses, and it starts doing so
|
|
12484
|
-
* from the first pixel — while this is still spending ten of them deciding
|
|
12485
|
-
* whether the press is a travel at all. By the time it is one, a trail is
|
|
12486
|
-
* already there. `user-select: none` (see the CSS) stops it GROWING, it does not
|
|
12487
|
-
* take back what was made, and a selection already under way goes on being
|
|
12488
|
-
* extended by some browsers whatever the property says.
|
|
12489
|
-
*
|
|
12490
|
-
* So it is dropped, and dropped again as it comes back. The cause is outside —
|
|
12491
|
-
* one gesture, two things answering it, and the browser answers first — and
|
|
12492
|
-
* cannot be removed from here; what can be removed is its trace, on every frame
|
|
12493
|
-
* of a travel that is walking.
|
|
12494
|
-
*/
|
|
12495
|
-
const dropSelection = () => {
|
|
12496
|
-
const selection = window.getSelection();
|
|
12497
|
-
if (selection && !selection.isCollapsed) {
|
|
12498
|
-
selection.removeAllRanges();
|
|
12499
|
-
}
|
|
12500
|
-
};
|
|
12501
|
-
|
|
12502
12695
|
/**
|
|
12503
12696
|
* A scroller between the pointer and the box it is in, with room left the way
|
|
12504
12697
|
* the gesture goes: it gets the gesture, and nothing travels — dragging a row
|
|
@@ -12817,9 +13010,6 @@ const startDragToTravel = (pointerDownEvent, {
|
|
|
12817
13010
|
};
|
|
12818
13011
|
document.documentElement.setAttribute(WALKING_ATTRIBUTE, axis);
|
|
12819
13012
|
}
|
|
12820
|
-
// Whatever the press was taken for until now, it was taken for something
|
|
12821
|
-
// else (see dropSelection).
|
|
12822
|
-
dropSelection();
|
|
12823
13013
|
const {
|
|
12824
13014
|
axis
|
|
12825
13015
|
} = travel;
|
|
@@ -12881,10 +13071,6 @@ const startDragToTravel = (pointerDownEvent, {
|
|
|
12881
13071
|
return;
|
|
12882
13072
|
}
|
|
12883
13073
|
finish();
|
|
12884
|
-
// Last chance: the pointer moves once more as it goes up, and by then the
|
|
12885
|
-
// attribute above is off — so a trail made on that last move would be the
|
|
12886
|
-
// one that stays (see dropSelection).
|
|
12887
|
-
dropSelection();
|
|
12888
13074
|
const {
|
|
12889
13075
|
axis,
|
|
12890
13076
|
size,
|