@jsenv/dom 0.17.82 → 0.17.84

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 +81 -35
  2. package/package.json +1 -1
package/dist/jsenv_dom.js CHANGED
@@ -4611,19 +4611,20 @@ const waitForPressHeld = (
4611
4611
  ) => {
4612
4612
  const { pointerId, clientX, clientY } = pressEvent;
4613
4613
 
4614
- /* The one capture that says nothing about the press. A pointer that cannot
4615
- hover is given a capture the moment it lands, by the browser and to the
4616
- element it landed on, without anybody asking — and it is announced like any
4617
- other, just before the first pointer event that follows. EVERY touch press
4618
- has it, so it cannot be read as this one having been settled: read that way,
4619
- the wait dies at the first pixel of a finger that was only resting on the
4620
- glass, which is what a finger does. That is the hold that fails one time in
4621
- two, on the pointer this whole module exists for.
4622
- Asked rather than assumed, and asked HERE: the press is the one moment where
4623
- a capture can only be the browser's, since nothing has taken one yet. */
4624
- const implicitCaptureHolder = pressEvent.target.hasPointerCapture?.(pointerId)
4625
- ? pressEvent.target
4626
- : null;
4614
+ /* The one capture that says nothing about the press. A finger is given a
4615
+ capture the moment it lands, by the browser and to the element it landed
4616
+ on, without anybody asking — and it is announced like any other, just
4617
+ before the first pointer event that follows. EVERY touch press has it, so it
4618
+ cannot be read as this one having been settled: read that way, the wait
4619
+ dies at the first pixel of a finger that was only resting on the glass,
4620
+ which is what a finger does. A mouse or a pen is given none.
4621
+ Known from the press, never asked with hasPointerCapture: the capture goes
4622
+ to the deepest element under the finger, and inside a shadow tree (the
4623
+ inner editor of every <input> and <textarea>, any web component) the
4624
+ element the page sees answers false, while the announcement reaches the
4625
+ page retargeted to it. */
4626
+ const implicitCaptureHolder =
4627
+ pressEvent.pointerType === "touch" ? pressEvent.target : null;
4627
4628
 
4628
4629
  const pressCleanupCallbacks = [];
4629
4630
  // Who is still holding the refusal. The finger holds it because the finger is
@@ -4750,8 +4751,8 @@ const waitForPressHeld = (
4750
4751
  }
4751
4752
  holdGiveUps.add(cancelPress);
4752
4753
  // A gesture that captures the pointer without takePress: heard only when the
4753
- // capture moves, the one it takes on the implicit holder being announced to
4754
- // nobody (see takePress).
4754
+ // capture moves, the one it takes on the implicit holder being
4755
+ // indistinguishable from the browser's (see takePress).
4755
4756
  const onGotPointerCapture = (captureEvent) => {
4756
4757
  if (captureEvent.pointerId !== pointerId) {
4757
4758
  return;
@@ -10147,6 +10148,11 @@ const dragSourceThatStoodDown = (pressEvent) => {
10147
10148
  return pressEvent[STOOD_DOWN] || null;
10148
10149
  };
10149
10150
 
10151
+ // How far (px) a press travels before it means drag. Also how far a carry that
10152
+ // was handed over must go before it has gone anywhere (see handedOver in
10153
+ // drag_to.js): that is the same question, asked of the hand holding it.
10154
+ const DRAG_INTENT_THRESHOLD = 5;
10155
+
10150
10156
  /**
10151
10157
  * Waits for the user to mean it, then starts a drag gesture.
10152
10158
  *
@@ -10192,7 +10198,7 @@ const dragAfterIntent = (
10192
10198
  grabEvent,
10193
10199
  dragGestureInitializer,
10194
10200
  {
10195
- threshold = 5,
10201
+ threshold = DRAG_INTENT_THRESHOLD,
10196
10202
  longPress = "if-touch",
10197
10203
  longPressDelay = 400,
10198
10204
  longPressSlop = 8,
@@ -14960,8 +14966,12 @@ const createDragToMoveGestureController = ({
14960
14966
  * hold that handed it over, so the carry starts at once. And where the hand is
14961
14967
  * has nothing to do with where the element stands, so the copy is brought to
14962
14968
  * the hand — centred on the finger, flying there from the element's box —
14963
- * rather than following it from a distance. The pointer is taken on the
14964
- * element, away from what the finger first touched. Only a copy can be brought
14969
+ * rather than following it from a distance. Where it was brought then stands
14970
+ * for the element's own place: over whatever the finger happened to be on, so
14971
+ * nothing counts as under it until the hand has taken it further than
14972
+ * `threshold`, and a release before that is a hand that changed its mind. The
14973
+ * pointer is taken on the element, away from what the finger first touched.
14974
+ * Only a copy can be brought
14965
14975
  * like that: `move` carries the element itself, which would leave its place
14966
14976
  * just by being handed a press, and is not started.
14967
14977
  *
@@ -15316,6 +15326,10 @@ const resolveDropMeaning = ({
15316
15326
  canLeave,
15317
15327
  tossDistance = TOSS_DISTANCE_TO_COMMIT,
15318
15328
  tossSpeed = TOSS_SPEED_TO_COMMIT,
15329
+ // How far it may have been taken and still have been taken nowhere: not at
15330
+ // all for a carry that starts over its own place, the drag threshold for one
15331
+ // brought to a hand (see handedOver).
15332
+ stillWithin = 0,
15319
15333
  }) => {
15320
15334
  if (gestureInfo.cancelled) {
15321
15335
  // Nobody let go of anything: the gesture was taken away mid-air (the
@@ -15341,7 +15355,7 @@ const resolveDropMeaning = ({
15341
15355
  // It has to have gone somewhere to be put anywhere, or away from anything:
15342
15356
  // picked up and put straight back down is a hand that changed its mind.
15343
15357
  const { xDelta, yDelta } = gestureInfo.layout;
15344
- if (!xDelta && !yDelta) {
15358
+ if (Math.hypot(xDelta, yDelta) <= stillWithin) {
15345
15359
  return "cancel";
15346
15360
  }
15347
15361
  if (canLeave && releasedOutside) {
@@ -15399,7 +15413,9 @@ const startDragToCarryCopy = (
15399
15413
  direction = canLand || canLeave
15400
15414
  ? { x: true, y: true }
15401
15415
  : { x: false, y: true },
15402
- threshold,
15416
+ // Defaulted here rather than left to dragAfterIntent: a carry handed over
15417
+ // reads it too (see stillWithin).
15418
+ threshold = DRAG_INTENT_THRESHOLD,
15403
15419
  longPress,
15404
15420
  longPressDelay,
15405
15421
  longPressSlop,
@@ -15448,6 +15464,13 @@ const startDragToCarryCopy = (
15448
15464
  const reach = handedTo
15449
15465
  ? measureReach(draggedElement, handedTo)
15450
15466
  : undefined;
15467
+ // …and has been taken nowhere until it is further from there than a
15468
+ // press travels to mean drag.
15469
+ const stillWithin = handedTo ? threshold : 0;
15470
+ const hasNotLeftHand = (gestureInfo) =>
15471
+ Boolean(handedTo) &&
15472
+ Math.hypot(gestureInfo.layout.xDelta, gestureInfo.layout.yDelta) <=
15473
+ stillWithin;
15451
15474
  const cloneWrapper =
15452
15475
  cloneWrapperCaught ||
15453
15476
  createDragClone(draggedElement, handedTo || pointerEvent, reach);
@@ -15540,6 +15563,16 @@ const startDragToCarryCopy = (
15540
15563
  if (!dropHintEl) {
15541
15564
  return;
15542
15565
  }
15566
+ // Brought to the hand, the copy starts over whatever the finger is on,
15567
+ // and a place found there is one it was never taken to — the release
15568
+ // frame included, which is how a hold let go of without moving would
15569
+ // land. Around where it was brought is its own place, as the element's
15570
+ // box is for a carry that starts there: nothing is under it yet.
15571
+ if (hasNotLeftHand(gestureInfo)) {
15572
+ clearDropHint();
15573
+ gestureInfo.dropTargetInfo = null;
15574
+ return;
15575
+ }
15543
15576
  const allItems = [];
15544
15577
  const items = [];
15545
15578
  for (const el of containerElement.querySelectorAll(itemSelector)) {
@@ -15686,6 +15719,7 @@ const startDragToCarryCopy = (
15686
15719
  canLeave,
15687
15720
  tossDistance,
15688
15721
  tossSpeed,
15722
+ stillWithin,
15689
15723
  });
15690
15724
  // The hand has let go, and what that means is already known — the
15691
15725
  // answer to it has not run yet. Told, not asked: nothing here waits on
@@ -22186,33 +22220,45 @@ const measureWidestChildRow = (el) => {
22186
22220
  const borderLeft = parseFloat(containerStyle.borderLeftWidth);
22187
22221
  const borderRight = parseFloat(containerStyle.borderRightWidth);
22188
22222
 
22189
- // Group children by row using their top position
22190
- const rowsByTop = new Map();
22223
+ // Rows are found by vertical overlap, not by top: in an "align-items: center"
22224
+ // row, a child taller than its neighbours (a 1px border is enough) starts
22225
+ // higher than them and would open a row of its own.
22226
+ const rows = [];
22191
22227
  for (const child of children) {
22192
22228
  const rect = child.getBoundingClientRect();
22193
22229
  if (rect.width === 0 && rect.height === 0) {
22194
22230
  continue;
22195
22231
  }
22196
- const top = Math.round(rect.top);
22197
- const existing = rowsByTop.get(top);
22198
- if (existing === undefined) {
22199
- rowsByTop.set(top, { left: rect.left, right: rect.right });
22200
- } else {
22201
- if (rect.left < existing.left) {
22202
- existing.left = rect.left;
22203
- }
22204
- if (rect.right > existing.right) {
22205
- existing.right = rect.right;
22206
- }
22232
+ const row = rows.find((candidate) => sharesLine(candidate, rect));
22233
+ if (row === undefined) {
22234
+ rows.push({
22235
+ top: rect.top,
22236
+ bottom: rect.bottom,
22237
+ left: rect.left,
22238
+ right: rect.right,
22239
+ });
22240
+ continue;
22241
+ }
22242
+ if (rect.top < row.top) {
22243
+ row.top = rect.top;
22244
+ }
22245
+ if (rect.bottom > row.bottom) {
22246
+ row.bottom = rect.bottom;
22247
+ }
22248
+ if (rect.left < row.left) {
22249
+ row.left = rect.left;
22250
+ }
22251
+ if (rect.right > row.right) {
22252
+ row.right = rect.right;
22207
22253
  }
22208
22254
  }
22209
22255
 
22210
- if (rowsByTop.size <= 1) {
22256
+ if (rows.length <= 1) {
22211
22257
  return null;
22212
22258
  }
22213
22259
 
22214
22260
  let widestRowWidth = 0;
22215
- for (const { left, right } of rowsByTop.values()) {
22261
+ for (const { left, right } of rows) {
22216
22262
  const rowWidth = right - left;
22217
22263
  if (rowWidth > widestRowWidth) {
22218
22264
  widestRowWidth = rowWidth;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/dom",
3
- "version": "0.17.82",
3
+ "version": "0.17.84",
4
4
  "type": "module",
5
5
  "description": "DOM utilities for writing frontend code",
6
6
  "repository": {