@mk-drag-and-drop/dom 0.4.0 → 0.4.2
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,19 @@ 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 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.
|
|
376
|
+
|
|
377
|
+
`placementBoundary` is used after a preview placement already exists to control
|
|
378
|
+
same-target reversal and hysteresis thresholds. It does not decide the initial
|
|
379
|
+
side for cross-container sortable entry.
|
|
380
|
+
|
|
368
381
|
## Modifiers
|
|
369
382
|
|
|
370
383
|
Modifiers transform pointer movement before drag state updates. Built-ins:
|
|
@@ -53,9 +53,14 @@ export declare function getSortablePreviewPlacement(input: {
|
|
|
53
53
|
x: number;
|
|
54
54
|
y: number;
|
|
55
55
|
};
|
|
56
|
+
midpointPlacementPosition?: {
|
|
57
|
+
x: number;
|
|
58
|
+
y: number;
|
|
59
|
+
};
|
|
56
60
|
movement: SortablePointerMovementState | null;
|
|
57
61
|
previewPlacement: SortablePreviewPlacementState | null;
|
|
58
62
|
options: NormalizedSortableOptions;
|
|
63
|
+
useMidpointInitialPlacement?: boolean;
|
|
59
64
|
}): SortablePreviewPlacementDecision;
|
|
60
65
|
export declare function isSortablePreviewAlreadyPlaced(input: {
|
|
61
66
|
draggedElement: HTMLElement;
|
|
@@ -106,6 +106,9 @@ export function moveSortablePreview(input) {
|
|
|
106
106
|
if (!listElement) {
|
|
107
107
|
return;
|
|
108
108
|
}
|
|
109
|
+
const sourceListElement = input.registry.activeDrag.snapshots.get(input.draggedDraggableId)?.parent ??
|
|
110
|
+
draggedElement.parentElement;
|
|
111
|
+
const useMidpointInitialPlacement = sourceListElement !== listElement;
|
|
109
112
|
if (!target.capabilities.sortable) {
|
|
110
113
|
return;
|
|
111
114
|
}
|
|
@@ -117,9 +120,13 @@ export function moveSortablePreview(input) {
|
|
|
117
120
|
activeDropTargetId,
|
|
118
121
|
targetElement,
|
|
119
122
|
placementPosition: input.placementPosition,
|
|
123
|
+
midpointPlacementPosition: useMidpointInitialPlacement
|
|
124
|
+
? input.pointerPosition
|
|
125
|
+
: input.placementPosition,
|
|
120
126
|
movement: input.registry.activeDrag.pointerMovement,
|
|
121
127
|
previewPlacement: input.registry.activeDrag.previewPlacement,
|
|
122
128
|
options: input.options,
|
|
129
|
+
useMidpointInitialPlacement,
|
|
123
130
|
});
|
|
124
131
|
const placement = placementDecision.placement;
|
|
125
132
|
setSortablePreviewPlacementState({
|
|
@@ -153,6 +160,7 @@ export function moveSortablePreview(input) {
|
|
|
153
160
|
export function getSortablePreviewPlacement(input) {
|
|
154
161
|
const axis = input.options.axis;
|
|
155
162
|
const axisPosition = getAxisPosition(input.placementPosition, axis);
|
|
163
|
+
const midpointAxisPosition = getAxisPosition(input.midpointPlacementPosition ?? input.placementPosition, axis);
|
|
156
164
|
const targetRect = input.targetElement.getBoundingClientRect();
|
|
157
165
|
const currentDirection = getCurrentAxisMovementDirection({
|
|
158
166
|
placementPosition: input.placementPosition,
|
|
@@ -165,12 +173,18 @@ export function getSortablePreviewPlacement(input) {
|
|
|
165
173
|
previousPlacement.placement === null ||
|
|
166
174
|
previousPlacement.movementDirection === "none") {
|
|
167
175
|
return {
|
|
168
|
-
placement:
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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
|
+
}),
|
|
174
188
|
movementDirection: currentDirection,
|
|
175
189
|
};
|
|
176
190
|
}
|
|
@@ -222,6 +236,12 @@ function getOptimisticPlacement(input) {
|
|
|
222
236
|
endRatio: neutralPlacementBoundaryRatio,
|
|
223
237
|
}));
|
|
224
238
|
}
|
|
239
|
+
function getPlacementSideFromTargetMidpoint(input) {
|
|
240
|
+
const targetStart = input.axis === "horizontal" ? input.targetRect.left : input.targetRect.top;
|
|
241
|
+
const targetSize = input.axis === "horizontal" ? input.targetRect.width : input.targetRect.height;
|
|
242
|
+
const midpoint = targetStart + targetSize / 2;
|
|
243
|
+
return input.axisPosition < midpoint ? "before" : "after";
|
|
244
|
+
}
|
|
225
245
|
function getCurrentAxisMovementDirection(input) {
|
|
226
246
|
const axisPosition = getAxisPosition(input.placementPosition, input.axis);
|
|
227
247
|
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.
|
|
3
|
+
"version": "0.4.2",
|
|
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/
|
|
51
|
-
"@repo/
|
|
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 })\"",
|