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

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
@@ -369,8 +369,10 @@ Same-container sortable preview keeps its movement-responsive first-placement
369
369
  behavior: forward movement places after a newly active target, backward movement
370
370
  places before, and no sortable-axis movement uses the target midpoint. When a
371
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.
372
+ on the current sortable placement position against the target midpoint on the
373
+ sortable axis: above or left of midpoint places before, while below or right of
374
+ midpoint places after. Pointer-based targeting uses the pointer as that position;
375
+ rect-based targeting such as `centerToCenter` uses the overlay center.
374
376
 
375
377
  `placementBoundary` is used after a preview placement already exists to control
376
378
  same-target reversal and hysteresis thresholds. It does not decide the initial
@@ -12,6 +12,8 @@ export type SortablePreviewPlacementState = {
12
12
  activeDropTargetId: string | null;
13
13
  placement: SortablePlacementSide | null;
14
14
  movementDirection: SortableAxisMovementDirection;
15
+ containerElement: HTMLElement | null;
16
+ pendingMidpointInitialPlacement: boolean;
15
17
  };
16
18
  export type SortablePreviewPlacementDecision = {
17
19
  placement: SortablePlacementSide;
@@ -36,10 +38,6 @@ export declare function moveSortablePreview(input: {
36
38
  runtime: DomSortableRuntime;
37
39
  draggedDraggableId: string;
38
40
  activeDropTargetId: string | null;
39
- pointerPosition: {
40
- x: number;
41
- y: number;
42
- };
43
41
  placementPosition: {
44
42
  x: number;
45
43
  y: number;
@@ -76,10 +76,15 @@ export function moveSortablePreview(input) {
76
76
  addRegistrationContainerId(measurementIds, target);
77
77
  if (target.capabilities.container) {
78
78
  measurementIds.add(target.id);
79
+ const previousListElement = input.registry.activeDrag.previewPlacement?.containerElement ?? null;
80
+ const pendingMidpointInitialPlacement = draggedElement.parentElement !== target.element ||
81
+ (previousListElement !== null && previousListElement !== target.element);
79
82
  setSortablePreviewPlacementState({
80
83
  registry: input.registry,
81
84
  activeDropTargetId: target.id,
82
85
  placement: null,
86
+ containerElement: target.element,
87
+ pendingMidpointInitialPlacement,
83
88
  movementDirection: getCurrentAxisMovementDirection({
84
89
  placementPosition: input.placementPosition,
85
90
  movement: input.registry.activeDrag.pointerMovement,
@@ -106,7 +111,13 @@ export function moveSortablePreview(input) {
106
111
  if (!listElement) {
107
112
  return;
108
113
  }
109
- const useMidpointInitialPlacement = draggedElement.parentElement !== listElement;
114
+ const previousPlacement = input.registry.activeDrag.previewPlacement;
115
+ const previousListElement = previousPlacement?.containerElement ?? null;
116
+ const useMidpointInitialPlacement = draggedElement.parentElement !== listElement ||
117
+ (previousListElement !== null && previousListElement !== listElement) ||
118
+ (previousPlacement?.placement === null &&
119
+ previousPlacement.pendingMidpointInitialPlacement &&
120
+ previousListElement === listElement);
110
121
  if (!target.capabilities.sortable) {
111
122
  return;
112
123
  }
@@ -129,6 +140,8 @@ export function moveSortablePreview(input) {
129
140
  activeDropTargetId,
130
141
  placement,
131
142
  movementDirection: placementDecision.movementDirection,
143
+ containerElement: listElement,
144
+ pendingMidpointInitialPlacement: false,
132
145
  });
133
146
  if (isSortablePreviewAlreadyPlaced({
134
147
  draggedElement,
@@ -166,19 +179,24 @@ export function getSortablePreviewPlacement(input) {
166
179
  previousPlacement.activeDropTargetId !== input.activeDropTargetId ||
167
180
  previousPlacement.placement === null ||
168
181
  previousPlacement.movementDirection === "none") {
182
+ if (input.useMidpointInitialPlacement) {
183
+ const placement = getPlacementSideFromTargetMidpoint({
184
+ axis,
185
+ axisPosition,
186
+ targetRect,
187
+ });
188
+ return {
189
+ placement,
190
+ movementDirection: getMovementDirectionFromPlacementSide(placement),
191
+ };
192
+ }
169
193
  return {
170
- placement: input.useMidpointInitialPlacement
171
- ? getPlacementSideFromTargetMidpoint({
172
- axis,
173
- axisPosition,
174
- targetRect,
175
- })
176
- : getOptimisticPlacement({
177
- axis,
178
- axisPosition,
179
- currentDirection,
180
- targetRect,
181
- }),
194
+ placement: getOptimisticPlacement({
195
+ axis,
196
+ axisPosition,
197
+ currentDirection,
198
+ targetRect,
199
+ }),
182
200
  movementDirection: currentDirection,
183
201
  };
184
202
  }
@@ -213,6 +231,8 @@ function setSortablePreviewPlacementState(input) {
213
231
  activeDropTargetId: input.activeDropTargetId,
214
232
  placement: input.placement,
215
233
  movementDirection: input.movementDirection,
234
+ containerElement: input.containerElement,
235
+ pendingMidpointInitialPlacement: input.pendingMidpointInitialPlacement,
216
236
  };
217
237
  }
218
238
  function getOptimisticPlacement(input) {
@@ -236,6 +256,9 @@ function getPlacementSideFromTargetMidpoint(input) {
236
256
  const midpoint = targetStart + targetSize / 2;
237
257
  return input.axisPosition < midpoint ? "before" : "after";
238
258
  }
259
+ function getMovementDirectionFromPlacementSide(placement) {
260
+ return placement === "before" ? "backward" : "forward";
261
+ }
239
262
  function getCurrentAxisMovementDirection(input) {
240
263
  const axisPosition = getAxisPosition(input.placementPosition, input.axis);
241
264
  const previousAxisPosition = input.movement
@@ -34,7 +34,6 @@ export function getSortableRegistry(runtime) {
34
34
  runtime,
35
35
  draggedDraggableId: event.draggableId,
36
36
  activeDropTargetId: event.activeDropTargetId,
37
- pointerPosition: event.pointerPosition,
38
37
  placementPosition: event.placementPosition ?? event.pointerPosition,
39
38
  options: getSortableOptions(registry, event.draggableId),
40
39
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mk-drag-and-drop/dom",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
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",