@mk-drag-and-drop/dom 0.4.2 → 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,10 +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 pointer position against the target midpoint on the sortable axis: above
373
- or left of midpoint places before, while below or right of midpoint places
374
- after. Rect-based targeting such as `centerToCenter` still selects the active
375
- target; cross-container initial preview side follows the pointer.
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.
376
376
 
377
377
  `placementBoundary` is used after a preview placement already exists to control
378
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;
@@ -53,10 +51,6 @@ export declare function getSortablePreviewPlacement(input: {
53
51
  x: number;
54
52
  y: number;
55
53
  };
56
- midpointPlacementPosition?: {
57
- x: number;
58
- y: number;
59
- };
60
54
  movement: SortablePointerMovementState | null;
61
55
  previewPlacement: SortablePreviewPlacementState | null;
62
56
  options: NormalizedSortableOptions;
@@ -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,9 +111,13 @@ export function moveSortablePreview(input) {
106
111
  if (!listElement) {
107
112
  return;
108
113
  }
109
- const sourceListElement = input.registry.activeDrag.snapshots.get(input.draggedDraggableId)?.parent ??
110
- draggedElement.parentElement;
111
- const useMidpointInitialPlacement = sourceListElement !== 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);
112
121
  if (!target.capabilities.sortable) {
113
122
  return;
114
123
  }
@@ -120,9 +129,6 @@ export function moveSortablePreview(input) {
120
129
  activeDropTargetId,
121
130
  targetElement,
122
131
  placementPosition: input.placementPosition,
123
- midpointPlacementPosition: useMidpointInitialPlacement
124
- ? input.pointerPosition
125
- : input.placementPosition,
126
132
  movement: input.registry.activeDrag.pointerMovement,
127
133
  previewPlacement: input.registry.activeDrag.previewPlacement,
128
134
  options: input.options,
@@ -134,6 +140,8 @@ export function moveSortablePreview(input) {
134
140
  activeDropTargetId,
135
141
  placement,
136
142
  movementDirection: placementDecision.movementDirection,
143
+ containerElement: listElement,
144
+ pendingMidpointInitialPlacement: false,
137
145
  });
138
146
  if (isSortablePreviewAlreadyPlaced({
139
147
  draggedElement,
@@ -160,7 +168,6 @@ export function moveSortablePreview(input) {
160
168
  export function getSortablePreviewPlacement(input) {
161
169
  const axis = input.options.axis;
162
170
  const axisPosition = getAxisPosition(input.placementPosition, axis);
163
- const midpointAxisPosition = getAxisPosition(input.midpointPlacementPosition ?? input.placementPosition, axis);
164
171
  const targetRect = input.targetElement.getBoundingClientRect();
165
172
  const currentDirection = getCurrentAxisMovementDirection({
166
173
  placementPosition: input.placementPosition,
@@ -172,19 +179,24 @@ export function getSortablePreviewPlacement(input) {
172
179
  previousPlacement.activeDropTargetId !== input.activeDropTargetId ||
173
180
  previousPlacement.placement === null ||
174
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
+ }
175
193
  return {
176
- placement: input.useMidpointInitialPlacement
177
- ? getPlacementSideFromTargetMidpoint({
178
- axis,
179
- axisPosition: midpointAxisPosition,
180
- targetRect,
181
- })
182
- : getOptimisticPlacement({
183
- axis,
184
- axisPosition,
185
- currentDirection,
186
- targetRect,
187
- }),
194
+ placement: getOptimisticPlacement({
195
+ axis,
196
+ axisPosition,
197
+ currentDirection,
198
+ targetRect,
199
+ }),
188
200
  movementDirection: currentDirection,
189
201
  };
190
202
  }
@@ -219,6 +231,8 @@ function setSortablePreviewPlacementState(input) {
219
231
  activeDropTargetId: input.activeDropTargetId,
220
232
  placement: input.placement,
221
233
  movementDirection: input.movementDirection,
234
+ containerElement: input.containerElement,
235
+ pendingMidpointInitialPlacement: input.pendingMidpointInitialPlacement,
222
236
  };
223
237
  }
224
238
  function getOptimisticPlacement(input) {
@@ -242,6 +256,9 @@ function getPlacementSideFromTargetMidpoint(input) {
242
256
  const midpoint = targetStart + targetSize / 2;
243
257
  return input.axisPosition < midpoint ? "before" : "after";
244
258
  }
259
+ function getMovementDirectionFromPlacementSide(placement) {
260
+ return placement === "before" ? "backward" : "forward";
261
+ }
245
262
  function getCurrentAxisMovementDirection(input) {
246
263
  const axisPosition = getAxisPosition(input.placementPosition, input.axis);
247
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.2",
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",