@@ -1856,76 +1856,84 @@ export function handlePointercancel<T>(
18561856export function handleEnd < T > ( state : DragState < T > | SynthDragState < T > ) {
18571857 if ( state . draggedNode ) state . draggedNode . el . draggable = true ;
18581858
1859- if ( isSynthDragState ( state ) ) {
1860- state . clonedDraggedNode . remove ( ) ;
1859+ // --- Capture necessary data BEFORE resetState might affect it ---
1860+ const nodesToClean = state . draggedNodes . map ( ( x ) => x . el ) ;
1861+ const initialParentData = state . initialParent . data ;
1862+ const isSynth = isSynthDragState ( state ) ;
1863+ const config = parents . get ( state . initialParent . el ) ?. config ;
1864+ const dropZoneClass = isSynth
1865+ ? config ?. synthDropZoneClass
1866+ : config ?. dropZoneClass ;
1867+ const longPressClass = initialParentData ?. config ?. longPressClass ;
1868+ const placeholderClass = isSynth
1869+ ? initialParentData ?. config ?. synthDragPlaceholderClass // Corrected potential typo: used initialParentData
1870+ : initialParentData ?. config ?. dragPlaceholderClass ;
1871+ const originalZIndex = state . originalZIndex ;
1872+ // --- End data capture ---
18611873
1862- clearTimeout ( state . longPressTimeout ) ;
1874+ if ( isSynthDragState ( state ) ) {
1875+ // Ensure cloned node removal happens reasonably quickly
1876+ if ( state . clonedDraggedNode ) {
1877+ // Check if it exists
1878+ state . clonedDraggedNode . remove ( ) ;
1879+ }
1880+ if ( state . longPressTimeout ) {
1881+ // Check if timeout exists
1882+ clearTimeout ( state . longPressTimeout ) ;
1883+ }
18631884 }
18641885
1865- // Ensure scrolling is properly cancelled
1886+ // Ensure scrolling is properly cancelled (needs state, do before reset)
18661887 cancelSynthScroll ( state ) ;
18671888
1868- // Clear any lingering scroll directions and timeouts
1889+ // Clear any lingering scroll directions and timeouts (needs state, do before reset)
18691890 state . lastScrollDirectionX = undefined ;
18701891 state . lastScrollDirectionY = undefined ;
18711892 state . preventEnter = false ;
1872-
1873- // CRITICAL: Clear the scroll debounce timeout
18741893 if ( state . scrollDebounceTimeout ) {
18751894 clearTimeout ( state . scrollDebounceTimeout ) ;
1876- state . scrollDebounceTimeout = undefined ;
1895+ state . scrollDebounceTimeout = undefined ; // Ensure it's marked as cleared
18771896 }
18781897
1879- const config = parents . get ( state . initialParent . el ) ?. config ;
1880-
1881- const isSynth = isSynthDragState ( state ) ;
1882-
1883- const dropZoneClass = isSynth
1884- ? config ?. synthDropZoneClass
1885- : config ?. dropZoneClass ;
1886-
1887- if ( state . originalZIndex !== undefined ) {
1888- state . draggedNode . el . style . zIndex = state . originalZIndex ;
1898+ // Apply z-index change synchronously if needed
1899+ if ( originalZIndex !== undefined && state . draggedNode ) {
1900+ state . draggedNode . el . style . zIndex = originalZIndex ;
18891901 }
18901902
1903+ // Use single rAF with captured data for class removal
18911904 requestAnimationFrame ( ( ) => {
1892- requestAnimationFrame ( ( ) => {
1893- removeClass (
1894- state . draggedNodes . map ( ( x ) => x . el ) ,
1895- dropZoneClass
1896- ) ;
1897-
1898- removeClass (
1899- state . draggedNodes . map ( ( x ) => x . el ) ,
1900- state . initialParent . data ?. config ?. longPressClass
1901- ) ;
1902-
1903- removeClass (
1904- state . draggedNodes . map ( ( x ) => x . el ) ,
1905- isSynth
1906- ? state . initialParent . data . config . synthDragPlaceholderClass
1907- : state . initialParent . data ?. config ?. dragPlaceholderClass
1908- ) ;
1909- } ) ;
1905+ // Use the captured data, not the potentially reset global state
1906+ removeClass ( nodesToClean , dropZoneClass ) ;
1907+ removeClass ( nodesToClean , longPressClass ) ;
1908+ removeClass ( nodesToClean , placeholderClass ) ;
19101909 } ) ;
19111910
1911+ // Deselect and reset active state (needs state, do before reset)
19121912 deselect ( state . draggedNodes , state . currentParent , state ) ;
1913-
19141913 setActive ( state . currentParent , undefined , state ) ;
19151914
1916- resetState ( ) ;
1917-
1918- state . selectedState = undefined ;
1915+ // Prepare data for callback/event *before* resetState
1916+ const finalStateForCallback = { ...state } ; // Shallow copy for safety
19191917
1918+ // Call onDragend callback *before* resetState
19201919 config ?. onDragend ?.( {
1921- parent : state . currentParent ,
1922- values : parentValues ( state . currentParent . el , state . currentParent . data ) ,
1923- draggedNode : state . draggedNode ,
1924- draggedNodes : state . draggedNodes ,
1925- state,
1920+ parent : finalStateForCallback . currentParent ,
1921+ values : parentValues (
1922+ finalStateForCallback . currentParent . el ,
1923+ finalStateForCallback . currentParent . data
1924+ ) ,
1925+ draggedNode : finalStateForCallback . draggedNode ,
1926+ draggedNodes : finalStateForCallback . draggedNodes ,
1927+ state : finalStateForCallback ,
19261928 } ) ;
19271929
1928- state . emit ( "dragEnded" , state ) ;
1930+ // Emit event *before* resetState
1931+ state . emit ( "dragEnded" , finalStateForCallback ) ; // Emit with the final state representation
1932+
1933+ // Reset global state LAST
1934+ resetState ( ) ;
1935+
1936+ // No need to set state.selectedState = undefined; resetState handles it.
19291937}
19301938
19311939/**
0 commit comments