@@ -49,18 +49,20 @@ onMounted(() => {
4949const emit = defineEmits ([" update:list" , " start" , " end" , " update" ]);
5050
5151const hasHandleAtPosition = (event : MouseEvent | DragEvent ) => {
52- const { x, y } = event ;
52+ let { clientX : x, clientY : y } = event ;
5353 const elementsAtPosition = document .elementsFromPoint (x , y );
5454 return elementsAtPosition .reduce <boolean | null >(
5555 (clickedHandle , elementAtPosition ) => {
5656 // If we already have a boolean result, return that
57- if (typeof clickedHandle === " boolean" ) return clickedHandle ;
57+ if (typeof clickedHandle === " boolean" )
58+ return clickedHandle ;
5859 // If the clicked element (or one of its parents) has the handle class, we clicked the handle
5960 if (elementAtPosition .classList .contains (props .handleClass ! ))
6061 return true ;
6162 // If we've reached the draggable element itself, we found no handle, so return false to avoid
6263 // accidentally using handles with the same class outside the draggable element
63- if (elementAtPosition === event .target ) return false ;
64+ if (elementAtPosition .classList .contains (" draggable-item" ))
65+ return false ;
6466 return null ;
6567 },
6668 null
@@ -106,7 +108,8 @@ const onDragStart = (itemIndex: number, event: DragEvent) => {
106108 // If we only want to start dragging if the user clicked on a handle element
107109 if (props .handleClass ) {
108110 // If no handle was clicked, we don't want to start dragging the element
109- if (! hasHandleAtPosition (event )) return ;
111+ if (! hasHandleAtPosition (event ))
112+ return ;
110113 }
111114
112115 // Set the effect of moving an element, which by default is clone. Not being used right now
@@ -248,10 +251,25 @@ const hasSlotContent = (slot: SlotType | undefined, slotProps = {}) => {
248251 });
249252};
250253
251- const onTouchStart = () => {
254+ const onTouchStart = (event : TouchEvent ) => {
252255 touching .value = true ;
253256 touchDragging .value = false ;
254257
258+ // When we use handles, we need to find the element that is the handle, up until the draggable-item element itself
259+ if (props .handleClass ) {
260+ let handleElement = event .target as HTMLElement | null ;
261+ while (handleElement && ! handleElement .classList .contains (props .handleClass )) {
262+ if (handleElement .classList .contains (" draggable-item" )) {
263+ handleElement = null ;
264+ break ;
265+ }
266+ handleElement = handleElement .parentElement ;
267+ }
268+ // If the user is touching the handle, set isDraggable to true so dragging is allowed to start in onDragStart
269+ if (handleElement )
270+ isDraggable .value = true ;
271+ }
272+
255273 if (touchingTimeout .value ) clearTimeout (touchingTimeout .value );
256274
257275 touchingTimeout .value = setTimeout (() => {
@@ -262,8 +280,12 @@ const onTouchStart = () => {
262280const onTouchEnd = () => {
263281 touching .value = false ;
264282 touchDragging .value = false ;
283+ // When we use handles, isDragging should default to false, so the user has to start dragging the handle for isDragging to be changed to true
284+ if (props .handleClass )
285+ isDraggable .value = false ;
265286
266- if (touchingTimeout .value ) clearTimeout (touchingTimeout .value );
287+ if (touchingTimeout .value )
288+ clearTimeout (touchingTimeout .value );
267289 touchingTimeout .value = null ;
268290};
269291 </script >
@@ -304,7 +326,7 @@ window.addEventListener("touchmove", () => {});
304326 "
305327 @mousedown =" onMouseDown(itemIndex, $event)"
306328 @mouseup =" onMouseUp(itemIndex, $event)"
307- @touchstart.passive =" onTouchStart()"
329+ @touchstart.passive =" onTouchStart($event )"
308330 @touchend =" onTouchEnd()"
309331 @dragstart =" onDragStart(itemIndex, $event)"
310332 @dragenter.prevent
@@ -338,6 +360,7 @@ window.addEventListener("touchmove", () => {});
338360}
339361.draggable-item .draggable-handle {
340362 cursor : move ;
363+ user-select : none ;
341364}
342365.empty-list-placeholder {
343366 flex : 1 ;
0 commit comments