Skip to content

Commit 8411180

Browse files
committed
feat: integrate useWheel composable for mouse wheel navigation in Carousel
1 parent 207b804 commit 8411180

File tree

3 files changed

+87
-46
lines changed

3 files changed

+87
-46
lines changed

src/components/Carousel/Carousel.ts

Lines changed: 11 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
} from 'vue'
1818

1919
import { ARIA as ARIAComponent } from '@/components/ARIA'
20-
import { useDragging, useHover } from '@/composables'
20+
import { useDragging, useHover, useWheel } from '@/composables'
2121
import {
2222
CarouselConfig,
2323
createSlideRegistry,
@@ -366,50 +366,6 @@ export const Carousel = defineComponent({
366366
document.removeEventListener('keydown', handleArrowKeys)
367367
}
368368

369-
const handleScroll = throttle((event: Event): void => {
370-
if (!config.mouseScroll || isSliding.value) {
371-
return
372-
}
373-
374-
// Prevent default scrolling behavior when wheel navigation is enabled
375-
event.preventDefault()
376-
377-
const wheelEvent = event as WheelEvent
378-
379-
// Add sensitivity threshold to prevent small movements from triggering navigation
380-
const threshold = config.mouseScrollThreshold ?? 30 // Default to 30 if undefined
381-
382-
// Determine scroll direction
383-
const deltaY = Math.abs(wheelEvent.deltaY) > threshold ? wheelEvent.deltaY : 0
384-
const deltaX = Math.abs(wheelEvent.deltaX) > threshold ? wheelEvent.deltaX : 0
385-
386-
// If neither delta exceeds the threshold, don't navigate
387-
if (deltaY === 0 && deltaX === 0) {
388-
return
389-
}
390-
391-
const isScrollingDown = deltaY > 0
392-
const isScrollingRight = deltaX > 0
393-
394-
// Determine direction based on carousel orientation and scroll direction
395-
if (
396-
(isVertical.value && isScrollingDown) ||
397-
(!isVertical.value && isScrollingRight)
398-
) {
399-
if (isReversed.value) {
400-
prev()
401-
} else {
402-
next()
403-
}
404-
} else {
405-
if (isReversed.value) {
406-
next()
407-
} else {
408-
prev()
409-
}
410-
}
411-
}, 150)
412-
413369
/**
414370
* Autoplay
415371
*/
@@ -444,6 +400,15 @@ export const Carousel = defineComponent({
444400
*/
445401
const isSliding = ref(false)
446402

403+
const { handleScroll } = useWheel({
404+
isVertical: isVertical.value,
405+
isReversed: isReversed.value,
406+
isSliding: isSliding.value,
407+
config,
408+
next,
409+
prev,
410+
})
411+
447412
const onDrag = ({ deltaX, deltaY }: { deltaX: number; deltaY: number }) => {
448413
const draggedSlides = getDraggedSlidesCount({
449414
isVertical: isVertical.value,
@@ -882,7 +847,7 @@ export const Carousel = defineComponent({
882847
style: { transform: trackTransform.value },
883848
onMousedownCapture: config.mouseDrag ? handleDragStart : null,
884849
onTouchstartPassiveCapture: config.touchDrag ? handleDragStart : null,
885-
onWheelPassive: config.mouseScroll ? handleScroll : null,
850+
onWheel: config.mouseScroll ? handleScroll : null,
886851
},
887852
output
888853
)

src/composables/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export * from './useDragging'
22
export * from './useHover'
3+
export * from './useWheel'

src/composables/useWheel.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { ComputedRef, Ref, computed } from 'vue'
2+
3+
import { CarouselConfig } from '@/shared'
4+
import { throttle } from '@/utils'
5+
6+
interface UseWheelOptions {
7+
isVertical: boolean | ComputedRef<boolean>
8+
isReversed: boolean | ComputedRef<boolean>
9+
isSliding: boolean | Ref<boolean>
10+
config: CarouselConfig
11+
next: (skipTransition?: boolean) => void
12+
prev: (skipTransition?: boolean) => void
13+
}
14+
15+
export function useWheel(options: UseWheelOptions) {
16+
const { isVertical, isReversed, isSliding, config, next, prev } = options
17+
18+
// Create computed values to handle both reactive and non-reactive inputs
19+
const vertical = computed(() => {
20+
return typeof isVertical === 'boolean' ? isVertical : isVertical.value
21+
})
22+
23+
const reversed = computed(() => {
24+
return typeof isReversed === 'boolean' ? isReversed : isReversed.value
25+
})
26+
27+
const sliding = computed(() => {
28+
return typeof isSliding === 'boolean' ? isSliding : isSliding.value
29+
})
30+
31+
const handleScroll = throttle((event: Event): void => {
32+
if (!config.mouseScroll || sliding.value) {
33+
return
34+
}
35+
36+
// Prevent default scrolling behavior when wheel navigation is enabled
37+
event.preventDefault()
38+
39+
const wheelEvent = event as WheelEvent
40+
41+
// Add sensitivity threshold to prevent small movements from triggering navigation
42+
const threshold = config.mouseScrollThreshold as number // Default to 30 if undefined
43+
44+
// Determine scroll direction
45+
const deltaY = Math.abs(wheelEvent.deltaY) > threshold ? wheelEvent.deltaY : 0
46+
const deltaX = Math.abs(wheelEvent.deltaX) > threshold ? wheelEvent.deltaX : 0
47+
48+
// If neither delta exceeds the threshold, don't navigate
49+
if (deltaY === 0 && deltaX === 0) {
50+
return
51+
}
52+
53+
const isScrollingDown = deltaY > 0
54+
const isScrollingRight = deltaX > 0
55+
56+
// Determine direction based on carousel orientation and scroll direction
57+
if ((vertical.value && isScrollingDown) || (!vertical.value && isScrollingRight)) {
58+
if (reversed.value) {
59+
prev()
60+
} else {
61+
next()
62+
}
63+
} else {
64+
if (reversed.value) {
65+
next()
66+
} else {
67+
prev()
68+
}
69+
}
70+
}, 16)
71+
72+
return {
73+
handleScroll,
74+
}
75+
}

0 commit comments

Comments
 (0)