@@ -16,6 +16,7 @@ import {
16
16
} from 'vue'
17
17
18
18
import { ARIA as ARIAComponent } from '@/components/ARIA'
19
+ import { useDragging } from '@/composables'
19
20
import {
20
21
CarouselConfig ,
21
22
createSlideRegistry ,
@@ -330,11 +331,7 @@ export const Carousel = defineComponent({
330
331
/**
331
332
* Carousel Event listeners
332
333
*/
333
- let isTouch = false
334
- const startPosition = { x : 0 , y : 0 }
335
- const dragged = reactive ( { x : 0 , y : 0 } )
336
334
const isHover = ref ( false )
337
- const isDragging = ref ( false )
338
335
339
336
const handleMouseEnter = ( ) : void => {
340
337
isHover . value = true
@@ -375,92 +372,6 @@ export const Carousel = defineComponent({
375
372
document . removeEventListener ( 'keydown' , handleArrowKeys )
376
373
}
377
374
378
- function handleDragStart ( event : MouseEvent | TouchEvent ) : void {
379
- // Prevent drag initiation on input elements or if already sliding
380
- const targetTagName = ( event . target as HTMLElement ) . tagName
381
- if ( [ 'INPUT' , 'TEXTAREA' , 'SELECT' ] . includes ( targetTagName ) || isSliding . value ) {
382
- return
383
- }
384
-
385
- // Detect if the event is a touchstart or mousedown event
386
- isTouch = event . type === 'touchstart'
387
-
388
- // For mouse events, prevent default to avoid text selection
389
- if ( ! isTouch ) {
390
- event . preventDefault ( )
391
- if ( ( event as MouseEvent ) . button !== 0 ) {
392
- // Ignore non-left-click mouse events
393
- return
394
- }
395
- }
396
-
397
- // Initialize start positions for the drag
398
- startPosition . x = 'touches' in event ? event . touches [ 0 ] . clientX : event . clientX
399
- startPosition . y = 'touches' in event ? event . touches [ 0 ] . clientY : event . clientY
400
-
401
- // Attach event listeners for dragging and drag end
402
-
403
- const moveEvent = isTouch ? 'touchmove' : 'mousemove'
404
- const endEvent = isTouch ? 'touchend' : 'mouseup'
405
- document . addEventListener ( moveEvent , handleDragging , { passive : false } )
406
- document . addEventListener ( endEvent , handleDragEnd , { passive : true } )
407
- }
408
-
409
- const handleDragging = throttle ( ( event : TouchEvent | MouseEvent ) : void => {
410
- isDragging . value = true
411
-
412
- // Get the current position based on the interaction type (touch or mouse)
413
- const currentX = 'touches' in event ? event . touches [ 0 ] . clientX : event . clientX
414
- const currentY = 'touches' in event ? event . touches [ 0 ] . clientY : event . clientY
415
-
416
- // Calculate deltas for X and Y axes
417
- dragged . x = currentX - startPosition . x
418
- dragged . y = currentY - startPosition . y
419
-
420
- const draggedSlides = getDraggedSlidesCount ( {
421
- isVertical : isVertical . value ,
422
- isReversed : isReversed . value ,
423
- dragged,
424
- effectiveSlideSize : effectiveSlideSize . value ,
425
- } )
426
-
427
- activeSlideIndex . value = config . wrapAround
428
- ? currentSlideIndex . value + draggedSlides
429
- : getNumberInRange ( {
430
- val : currentSlideIndex . value + draggedSlides ,
431
- max : maxSlideIndex . value ,
432
- min : minSlideIndex . value ,
433
- } )
434
-
435
- // Emit a drag event for further customization if needed
436
- emit ( 'drag' , { deltaX : dragged . x , deltaY : dragged . y } )
437
- } )
438
-
439
- function handleDragEnd ( ) : void {
440
- handleDragging . cancel ( )
441
-
442
- // Prevent accidental clicks when there is a slide drag
443
- if ( activeSlideIndex . value !== currentSlideIndex . value && ! isTouch ) {
444
- const preventClick = ( e : MouseEvent ) => {
445
- e . preventDefault ( )
446
- window . removeEventListener ( 'click' , preventClick )
447
- }
448
- window . addEventListener ( 'click' , preventClick )
449
- }
450
-
451
- slideTo ( activeSlideIndex . value )
452
-
453
- // Reset drag state
454
- dragged . x = 0
455
- dragged . y = 0
456
- isDragging . value = false
457
-
458
- const moveEvent = isTouch ? 'touchmove' : 'mousemove'
459
- const endEvent = isTouch ? 'touchend' : 'mouseup'
460
- document . removeEventListener ( moveEvent , handleDragging )
461
- document . removeEventListener ( endEvent , handleDragEnd )
462
- }
463
-
464
375
/**
465
376
* Autoplay
466
377
*/
@@ -495,6 +406,33 @@ export const Carousel = defineComponent({
495
406
*/
496
407
const isSliding = ref ( false )
497
408
409
+ const onDrag = ( { deltaX, deltaY } : { deltaX : number ; deltaY : number } ) => {
410
+ const draggedSlides = getDraggedSlidesCount ( {
411
+ isVertical : isVertical . value ,
412
+ isReversed : isReversed . value ,
413
+ dragged : { x : deltaX , y : deltaY } ,
414
+ effectiveSlideSize : effectiveSlideSize . value ,
415
+ } )
416
+
417
+ activeSlideIndex . value = config . wrapAround
418
+ ? currentSlideIndex . value + draggedSlides
419
+ : getNumberInRange ( {
420
+ val : currentSlideIndex . value + draggedSlides ,
421
+ max : maxSlideIndex . value ,
422
+ min : minSlideIndex . value ,
423
+ } )
424
+
425
+ emit ( 'drag' , { deltaX, deltaY } )
426
+ }
427
+ const onDragEnd = ( ) => {
428
+ slideTo ( activeSlideIndex . value )
429
+ }
430
+ const { dragged, isDragging, handleDragStart } = useDragging ( {
431
+ isSliding : isSliding . value ,
432
+ onDrag,
433
+ onDragEnd,
434
+ } )
435
+
498
436
function slideTo ( slideIndex : number , skipTransition = false ) : void {
499
437
if ( ! skipTransition && isSliding . value ) {
500
438
return
0 commit comments