@jsenv/dom 0.17.93 → 0.17.94

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 +70 -38
  2. package/package.json +1 -1
package/dist/jsenv_dom.js CHANGED
@@ -16384,62 +16384,94 @@ const areLevel = (a, b) => {
16384
16384
 
16385
16385
  /**
16386
16386
  * The item the copy is at, and its `side` in the order of the list: "start" for
16387
- * before it, "end" for after it. Down a list, read by the copy's leading edge
16388
- * (see getDropTargetInfo); along a row, by its middle against the item's — how
16389
- * high the copy is says nothing there, and the leading edge assumes a copy as
16390
- * large as what it passes over: items of a row are as wide as their content,
16391
- * and one wider than its neighbour could never be put after it.
16392
- *
16393
- * Beyond an end of the list, over no item, is a place too: above the first line
16394
- * or below the last, and along a row beside the first item or past the last.
16387
+ * before it, "end" for after it.
16388
+ *
16389
+ * Down a list, the item under the copy, read by the copy's leading edge (see
16390
+ * getDropTargetInfo); over no item, above the first one is the start of the
16391
+ * list and below the last one its end.
16392
+ *
16393
+ * Along a row, the copy's middle decides, the way a click puts the caret in a
16394
+ * text: on the nearest line, before the first item whose middle it has not
16395
+ * reached. How high the copy is says which line and nothing more, its size
16396
+ * nothing at all — the leading edge assumes a copy as large as what it passes
16397
+ * over, and items of a row are as wide as their content: read by its edge, one
16398
+ * wider than its neighbour could never be put after it.
16395
16399
  */
16396
16400
  const findPlaceInList = (gestureInfo, items, flow) => {
16397
16401
  const dragElementRect = gestureInfo.elementImpacted.getBoundingClientRect();
16402
+ if (flow !== "down") {
16403
+ return findPlaceOnNearestLine(dragElementRect, items, flow);
16404
+ }
16398
16405
  const dropTargetInfo = getDropTargetInfo(gestureInfo, items);
16399
16406
  if (dropTargetInfo) {
16400
- const { element } = dropTargetInfo;
16401
- if (flow === "down") {
16402
- return { element, side: dropTargetInfo.elementSide.y };
16403
- }
16404
- const elementRect = element.getBoundingClientRect();
16405
- const dragMiddle = dragElementRect.left + dragElementRect.width / 2;
16406
- const elementMiddle = elementRect.left + elementRect.width / 2;
16407
- const beforeItsMiddle =
16408
- flow === "right"
16409
- ? dragMiddle < elementMiddle
16410
- : dragMiddle > elementMiddle;
16411
- return { element, side: beforeItsMiddle ? "start" : "end" };
16407
+ return {
16408
+ element: dropTargetInfo.element,
16409
+ side: dropTargetInfo.elementSide.y,
16410
+ };
16412
16411
  }
16413
16412
  const firstItem = items[0];
16414
16413
  if (!firstItem) {
16415
16414
  return null;
16416
16415
  }
16417
16416
  const lastItem = items[items.length - 1];
16418
- const firstRect = firstItem.getBoundingClientRect();
16419
- const lastRect = lastItem.getBoundingClientRect();
16420
- if (
16421
- dragElementRect.bottom < firstRect.top ||
16422
- (flow !== "down" &&
16423
- areLevel(dragElementRect, firstRect) &&
16424
- isBeyond(dragElementRect, firstRect, flow === "right" ? "left" : "right"))
16425
- ) {
16417
+ if (dragElementRect.bottom < firstItem.getBoundingClientRect().top) {
16426
16418
  return { element: firstItem, side: "start" };
16427
16419
  }
16428
- if (
16429
- dragElementRect.top > lastRect.bottom ||
16430
- (flow !== "down" &&
16431
- areLevel(dragElementRect, lastRect) &&
16432
- isBeyond(dragElementRect, lastRect, flow))
16433
- ) {
16420
+ if (dragElementRect.top > lastItem.getBoundingClientRect().bottom) {
16434
16421
  return { element: lastItem, side: "end" };
16435
16422
  }
16436
16423
  return null;
16437
16424
  };
16438
16425
 
16439
- const isBeyond = (dragElementRect, itemRect, towards) => {
16440
- return towards === "left"
16441
- ? dragElementRect.right < itemRect.left
16442
- : dragElementRect.left > itemRect.right;
16426
+ const findPlaceOnNearestLine = (dragElementRect, items, flow) => {
16427
+ const lines = [];
16428
+ let previousRect;
16429
+ for (const item of items) {
16430
+ const rect = item.getBoundingClientRect();
16431
+ // A box that takes no room stands on no line (see readItemFlow).
16432
+ if (rect.width === 0 && rect.height === 0) {
16433
+ continue;
16434
+ }
16435
+ if (!previousRect || !areLevel(previousRect, rect)) {
16436
+ lines.push({ top: rect.top, bottom: rect.bottom, entries: [] });
16437
+ }
16438
+ const line = lines[lines.length - 1];
16439
+ if (rect.top < line.top) {
16440
+ line.top = rect.top;
16441
+ }
16442
+ if (rect.bottom > line.bottom) {
16443
+ line.bottom = rect.bottom;
16444
+ }
16445
+ line.entries.push({ item, middle: rect.left + rect.width / 2 });
16446
+ previousRect = rect;
16447
+ }
16448
+ const dragMiddleY = dragElementRect.top + dragElementRect.height / 2;
16449
+ let nearestLine;
16450
+ let nearestDistance;
16451
+ for (const line of lines) {
16452
+ const distance =
16453
+ dragMiddleY < line.top
16454
+ ? line.top - dragMiddleY
16455
+ : dragMiddleY > line.bottom
16456
+ ? dragMiddleY - line.bottom
16457
+ : 0;
16458
+ if (nearestLine === undefined || distance < nearestDistance) {
16459
+ nearestLine = line;
16460
+ nearestDistance = distance;
16461
+ }
16462
+ }
16463
+ if (!nearestLine) {
16464
+ return null;
16465
+ }
16466
+ const dragMiddleX = dragElementRect.left + dragElementRect.width / 2;
16467
+ for (const { item, middle } of nearestLine.entries) {
16468
+ const notReached =
16469
+ flow === "right" ? middle > dragMiddleX : middle < dragMiddleX;
16470
+ if (notReached) {
16471
+ return { element: item, side: "start" };
16472
+ }
16473
+ }
16474
+ return { element: nearestLine.entries.at(-1).item, side: "end" };
16443
16475
  };
16444
16476
 
16445
16477
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/dom",
3
- "version": "0.17.93",
3
+ "version": "0.17.94",
4
4
  "type": "module",
5
5
  "description": "DOM utilities for writing frontend code",
6
6
  "repository": {