@mk-drag-and-drop/dom 0.4.0 → 0.4.1

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/README.md CHANGED
@@ -365,6 +365,17 @@ registry may narrow measured candidates to relevant sortable item, neighbor, or
365
365
  container entries before the targeting algorithm runs; the algorithm still makes
366
366
  the active-target decision from that narrowed measured list.
367
367
 
368
+ Same-container sortable preview keeps its movement-responsive first-placement
369
+ behavior: forward movement places after a newly active target, backward movement
370
+ places before, and no sortable-axis movement uses the target midpoint. When a
371
+ sortable item first enters a different DOM container, the initial side is based
372
+ on the target midpoint on the sortable axis: above or left of midpoint places
373
+ before, while below or right of midpoint places after.
374
+
375
+ `placementBoundary` is used after a preview placement already exists to control
376
+ same-target reversal and hysteresis thresholds. It does not decide the initial
377
+ side for cross-container sortable entry.
378
+
368
379
  ## Modifiers
369
380
 
370
381
  Modifiers transform pointer movement before drag state updates. Built-ins:
@@ -56,6 +56,7 @@ export declare function getSortablePreviewPlacement(input: {
56
56
  movement: SortablePointerMovementState | null;
57
57
  previewPlacement: SortablePreviewPlacementState | null;
58
58
  options: NormalizedSortableOptions;
59
+ useMidpointInitialPlacement?: boolean;
59
60
  }): SortablePreviewPlacementDecision;
60
61
  export declare function isSortablePreviewAlreadyPlaced(input: {
61
62
  draggedElement: HTMLElement;
@@ -106,6 +106,7 @@ export function moveSortablePreview(input) {
106
106
  if (!listElement) {
107
107
  return;
108
108
  }
109
+ const useMidpointInitialPlacement = draggedElement.parentElement !== listElement;
109
110
  if (!target.capabilities.sortable) {
110
111
  return;
111
112
  }
@@ -120,6 +121,7 @@ export function moveSortablePreview(input) {
120
121
  movement: input.registry.activeDrag.pointerMovement,
121
122
  previewPlacement: input.registry.activeDrag.previewPlacement,
122
123
  options: input.options,
124
+ useMidpointInitialPlacement,
123
125
  });
124
126
  const placement = placementDecision.placement;
125
127
  setSortablePreviewPlacementState({
@@ -165,12 +167,18 @@ export function getSortablePreviewPlacement(input) {
165
167
  previousPlacement.placement === null ||
166
168
  previousPlacement.movementDirection === "none") {
167
169
  return {
168
- placement: getOptimisticPlacement({
169
- axis,
170
- axisPosition,
171
- currentDirection,
172
- targetRect,
173
- }),
170
+ placement: input.useMidpointInitialPlacement
171
+ ? getPlacementSideFromTargetMidpoint({
172
+ axis,
173
+ axisPosition,
174
+ targetRect,
175
+ })
176
+ : getOptimisticPlacement({
177
+ axis,
178
+ axisPosition,
179
+ currentDirection,
180
+ targetRect,
181
+ }),
174
182
  movementDirection: currentDirection,
175
183
  };
176
184
  }
@@ -222,6 +230,12 @@ function getOptimisticPlacement(input) {
222
230
  endRatio: neutralPlacementBoundaryRatio,
223
231
  }));
224
232
  }
233
+ function getPlacementSideFromTargetMidpoint(input) {
234
+ const targetStart = input.axis === "horizontal" ? input.targetRect.left : input.targetRect.top;
235
+ const targetSize = input.axis === "horizontal" ? input.targetRect.width : input.targetRect.height;
236
+ const midpoint = targetStart + targetSize / 2;
237
+ return input.axisPosition < midpoint ? "before" : "after";
238
+ }
225
239
  function getCurrentAxisMovementDirection(input) {
226
240
  const axisPosition = getAxisPosition(input.placementPosition, input.axis);
227
241
  const previousAxisPosition = input.movement
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mk-drag-and-drop/dom",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Headless DOM drag-and-drop primitives for draggable, droppable, sortable, and grouped interactions.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://mkramer.dev",
@@ -47,8 +47,8 @@
47
47
  "jsdom": "^24.1.3",
48
48
  "typescript": "5.5.4",
49
49
  "vitest": "^2.1.9",
50
- "@repo/typescript-config": "0.0.0",
51
- "@repo/eslint-config": "0.0.0"
50
+ "@repo/eslint-config": "0.0.0",
51
+ "@repo/typescript-config": "0.0.0"
52
52
  },
53
53
  "scripts": {
54
54
  "clean": "node -e \"require('fs').rmSync('dist', { recursive: true, force: true })\"",