use-carousel-hook
Advanced tools
Comparing version 0.0.11 to 0.0.13
@@ -6,2 +6,3 @@ import React from 'react'; | ||
direction?: 'horizontal' | 'vertical'; | ||
initialRef?: React.RefObject<HTMLElement>; | ||
} | ||
@@ -13,6 +14,6 @@ interface CarouselPosition { | ||
interface CarouselHook { | ||
ref: React.MutableRefObject<HTMLElement>; | ||
previous: () => void; | ||
next: () => void; | ||
setCurrent: (current: number) => void; | ||
ref: React.RefObject<HTMLElement>; | ||
previous: (amount?: number, interaction?: Interaction) => void; | ||
next: (amount?: number, interaction?: Interaction) => void; | ||
setCurrent: (current: number, interaction?: Interaction) => void; | ||
reset: () => void; | ||
@@ -23,3 +24,3 @@ position: CarouselPosition; | ||
} | ||
declare const useCarousel: (options?: Options | undefined) => CarouselHook; | ||
declare const useCarousel: (options?: Options) => CarouselHook; | ||
export default useCarousel; |
@@ -9,4 +9,6 @@ "use strict"; | ||
const reducer_1 = __importDefault(require("./reducer")); | ||
const useCarousel = (options) => { | ||
const ref = react_1.useRef(); | ||
const useCarousel = (options = {}) => { | ||
const ref = options.initialRef | ||
? options.initialRef | ||
: react_1.useRef(); | ||
const [{ current, interaction }, dispatch] = react_1.useReducer(reducer_1.default, { | ||
@@ -17,8 +19,11 @@ current: 0, | ||
const [maxIndex, setMaxIndex] = react_1.useState(-1); | ||
const [isUserScroll, setIsUserScroll] = react_1.useState(null); | ||
const [position, setPosition] = react_1.useState({ isAtStart: true, isAtEnd: false }); | ||
const [inView, setInView] = react_1.useState([0]); | ||
const updateMaxIndex = react_1.useCallback(() => { | ||
if (!ref.current) | ||
return; | ||
const el = ref.current; | ||
const children = [...el.children]; | ||
const lastScrollableChild = children.findIndex(child => (options === null || options === void 0 ? void 0 : options.direction) === 'vertical' | ||
const lastScrollableChild = children.findIndex(child => options.direction === 'vertical' | ||
? child.offsetTop >= el.scrollHeight - el.offsetHeight | ||
@@ -29,2 +34,4 @@ : child.offsetLeft >= el.scrollWidth - el.offsetWidth); | ||
const updateInView = () => { | ||
if (!ref.current) | ||
return; | ||
const carouselEl = ref.current; | ||
@@ -38,3 +45,3 @@ const childEls = [...carouselEl.children]; | ||
for (let index = current + 1; index < childEls.length; index++) { | ||
if ((options === null || options === void 0 ? void 0 : options.direction) === 'vertical') { | ||
if (options.direction === 'vertical') { | ||
if (childEls[index].offsetTop + childEls[index].offsetHeight <= carouselBottom) { | ||
@@ -59,2 +66,4 @@ inView.push(index); | ||
const updateCurrentOnScroll = (current) => { | ||
if (!ref.current) | ||
return; | ||
const carouselEl = ref.current; | ||
@@ -71,3 +80,18 @@ for (let index = 0; index < carouselEl.children.length; index++) { | ||
}; | ||
// Add events to handle setting of isUserScroll | ||
react_1.useEffect(() => { | ||
if (!ref.current) | ||
return; | ||
const mouseDownHandler = () => setIsUserScroll(true); | ||
const mouseUpHandler = () => setIsUserScroll(false); | ||
ref.current.addEventListener('mousedown', mouseDownHandler); | ||
ref.current.addEventListener('mouseup', mouseUpHandler); | ||
return () => { | ||
if (!ref.current) | ||
return; | ||
ref.current.removeEventListener('mousedown', mouseDownHandler); | ||
ref.current.removeEventListener('mouseup', mouseUpHandler); | ||
}; | ||
}, []); | ||
react_1.useEffect(() => { | ||
window.addEventListener('resize', updateMaxIndex); | ||
@@ -81,8 +105,14 @@ window.addEventListener('resize', updateInView); | ||
react_1.useEffect(() => { | ||
if (!ref.current) | ||
return; | ||
// When current updates, attach a new event handler with the updated | ||
// current value to call updateCurrentOnScroll | ||
const scrollHandler = () => updateCurrentOnScroll(current); | ||
const scrollHandler = () => isUserScroll && updateCurrentOnScroll(current); | ||
ref.current.addEventListener('scroll', scrollHandler); | ||
return () => ref.current.removeEventListener('scroll', scrollHandler); | ||
}, [current]); | ||
return () => { | ||
if (!ref.current) | ||
return; | ||
ref.current.removeEventListener('scroll', scrollHandler); | ||
}; | ||
}, [current, isUserScroll]); | ||
react_1.useEffect(() => { | ||
@@ -93,2 +123,4 @@ updateMaxIndex(); | ||
did_update_1.default(() => { | ||
if (!ref.current) | ||
return; | ||
// If interaction is scroll, the carousel doesn't need to handle the scrolling | ||
@@ -99,3 +131,3 @@ if (interaction !== 'scroll') { | ||
// Scroll to the element | ||
if ((options === null || options === void 0 ? void 0 : options.direction) === 'vertical') { | ||
if (options.direction === 'vertical') { | ||
carouselEl.scrollTo({ | ||
@@ -109,7 +141,10 @@ top: currentChildEl.offsetTop, | ||
left: currentChildEl.offsetLeft, | ||
behavior: (options === null || options === void 0 ? void 0 : options.scrollBehavior) || 'smooth' | ||
behavior: options.scrollBehavior || 'smooth' | ||
}); | ||
} | ||
} | ||
// Update the inView items | ||
updateInView(); | ||
// Not a user scroll so set to false | ||
setIsUserScroll(false); | ||
// Update the carousel position | ||
@@ -116,0 +151,0 @@ setPosition({ |
@@ -6,2 +6,3 @@ import React from 'react'; | ||
direction?: 'horizontal' | 'vertical'; | ||
initialRef?: React.RefObject<HTMLElement>; | ||
} | ||
@@ -13,6 +14,6 @@ interface CarouselPosition { | ||
interface CarouselHook { | ||
ref: React.MutableRefObject<HTMLElement>; | ||
previous: () => void; | ||
next: () => void; | ||
setCurrent: (current: number) => void; | ||
ref: React.RefObject<HTMLElement>; | ||
previous: (amount?: number, interaction?: Interaction) => void; | ||
next: (amount?: number, interaction?: Interaction) => void; | ||
setCurrent: (current: number, interaction?: Interaction) => void; | ||
reset: () => void; | ||
@@ -23,3 +24,3 @@ position: CarouselPosition; | ||
} | ||
declare const useCarousel: (options?: Options | undefined) => CarouselHook; | ||
declare const useCarousel: (options?: Options) => CarouselHook; | ||
export default useCarousel; |
import { useState, useRef, useEffect, useReducer, useCallback } from 'react'; | ||
import useDidUpdateEffect from '@use-effect/did-update'; | ||
import reducer from './reducer'; | ||
const useCarousel = (options) => { | ||
const ref = useRef(); | ||
const useCarousel = (options = {}) => { | ||
const ref = options.initialRef | ||
? options.initialRef | ||
: useRef(); | ||
const [{ current, interaction }, dispatch] = useReducer(reducer, { | ||
@@ -11,8 +13,11 @@ current: 0, | ||
const [maxIndex, setMaxIndex] = useState(-1); | ||
const [isUserScroll, setIsUserScroll] = useState(null); | ||
const [position, setPosition] = useState({ isAtStart: true, isAtEnd: false }); | ||
const [inView, setInView] = useState([0]); | ||
const updateMaxIndex = useCallback(() => { | ||
if (!ref.current) | ||
return; | ||
const el = ref.current; | ||
const children = [...el.children]; | ||
const lastScrollableChild = children.findIndex(child => (options === null || options === void 0 ? void 0 : options.direction) === 'vertical' | ||
const lastScrollableChild = children.findIndex(child => options.direction === 'vertical' | ||
? child.offsetTop >= el.scrollHeight - el.offsetHeight | ||
@@ -23,2 +28,4 @@ : child.offsetLeft >= el.scrollWidth - el.offsetWidth); | ||
const updateInView = () => { | ||
if (!ref.current) | ||
return; | ||
const carouselEl = ref.current; | ||
@@ -32,3 +39,3 @@ const childEls = [...carouselEl.children]; | ||
for (let index = current + 1; index < childEls.length; index++) { | ||
if ((options === null || options === void 0 ? void 0 : options.direction) === 'vertical') { | ||
if (options.direction === 'vertical') { | ||
if (childEls[index].offsetTop + childEls[index].offsetHeight <= carouselBottom) { | ||
@@ -53,2 +60,4 @@ inView.push(index); | ||
const updateCurrentOnScroll = (current) => { | ||
if (!ref.current) | ||
return; | ||
const carouselEl = ref.current; | ||
@@ -65,3 +74,18 @@ for (let index = 0; index < carouselEl.children.length; index++) { | ||
}; | ||
// Add events to handle setting of isUserScroll | ||
useEffect(() => { | ||
if (!ref.current) | ||
return; | ||
const mouseDownHandler = () => setIsUserScroll(true); | ||
const mouseUpHandler = () => setIsUserScroll(false); | ||
ref.current.addEventListener('mousedown', mouseDownHandler); | ||
ref.current.addEventListener('mouseup', mouseUpHandler); | ||
return () => { | ||
if (!ref.current) | ||
return; | ||
ref.current.removeEventListener('mousedown', mouseDownHandler); | ||
ref.current.removeEventListener('mouseup', mouseUpHandler); | ||
}; | ||
}, []); | ||
useEffect(() => { | ||
window.addEventListener('resize', updateMaxIndex); | ||
@@ -75,8 +99,14 @@ window.addEventListener('resize', updateInView); | ||
useEffect(() => { | ||
if (!ref.current) | ||
return; | ||
// When current updates, attach a new event handler with the updated | ||
// current value to call updateCurrentOnScroll | ||
const scrollHandler = () => updateCurrentOnScroll(current); | ||
const scrollHandler = () => isUserScroll && updateCurrentOnScroll(current); | ||
ref.current.addEventListener('scroll', scrollHandler); | ||
return () => ref.current.removeEventListener('scroll', scrollHandler); | ||
}, [current]); | ||
return () => { | ||
if (!ref.current) | ||
return; | ||
ref.current.removeEventListener('scroll', scrollHandler); | ||
}; | ||
}, [current, isUserScroll]); | ||
useEffect(() => { | ||
@@ -87,2 +117,4 @@ updateMaxIndex(); | ||
useDidUpdateEffect(() => { | ||
if (!ref.current) | ||
return; | ||
// If interaction is scroll, the carousel doesn't need to handle the scrolling | ||
@@ -93,3 +125,3 @@ if (interaction !== 'scroll') { | ||
// Scroll to the element | ||
if ((options === null || options === void 0 ? void 0 : options.direction) === 'vertical') { | ||
if (options.direction === 'vertical') { | ||
carouselEl.scrollTo({ | ||
@@ -103,7 +135,10 @@ top: currentChildEl.offsetTop, | ||
left: currentChildEl.offsetLeft, | ||
behavior: (options === null || options === void 0 ? void 0 : options.scrollBehavior) || 'smooth' | ||
behavior: options.scrollBehavior || 'smooth' | ||
}); | ||
} | ||
} | ||
// Update the inView items | ||
updateInView(); | ||
// Not a user scroll so set to false | ||
setIsUserScroll(false); | ||
// Update the carousel position | ||
@@ -110,0 +145,0 @@ setPosition({ |
{ | ||
"name": "use-carousel-hook", | ||
"version": "0.0.11", | ||
"version": "0.0.13", | ||
"description": "Adds functionality for carousels using React hooks", | ||
@@ -9,3 +9,4 @@ "main": "dist/index.js", | ||
"build": "cross-env ./node_modules/typescript/bin/tsc", | ||
"build:cjs": "cross-env ./node_modules/typescript/bin/tsc --p tsconfig.cjs.json" | ||
"build:cjs": "cross-env ./node_modules/typescript/bin/tsc --p tsconfig.cjs.json", | ||
"test": "cross-env ./node_modules/jest/bin/jest.js" | ||
}, | ||
@@ -17,2 +18,4 @@ "peerDependencies": { | ||
"devDependencies": { | ||
"@testing-library/react-hooks": "^7.0.1", | ||
"@types/jest": "^26.0.24", | ||
"@types/node": "^16.3.1", | ||
@@ -28,5 +31,7 @@ "@types/react": "^17.0.14", | ||
"eslint-plugin-react": "^7.24.0", | ||
"jest": "^27.0.6", | ||
"prettier": "^2.3.2", | ||
"react": "^16.14.0", | ||
"react-dom": "^16.14.0", | ||
"react": "17", | ||
"react-dom": "^17.0.2", | ||
"ts-jest": "^27.0.4", | ||
"typescript": "^4.3.5" | ||
@@ -33,0 +38,0 @@ }, |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
28738
18
615
18