@snap-carousel/core
Advanced tools
Comparing version 0.0.19-next.1 to 0.0.19-next.2
@@ -1,4 +0,3 @@ | ||
export declare const getActiveSnap: ({ root, onChange, snapAlign }: { | ||
export declare const getActiveSnap: ({ root, onChange, }: { | ||
root: HTMLDivElement; | ||
snapAlign?: "start" | "center" | "end" | undefined; | ||
onChange?: ((snapIndex: number) => void) | undefined; | ||
@@ -5,0 +4,0 @@ }) => { |
const mergeStyles = (...classnames) => classnames.filter(Boolean).join(' '); | ||
const extractStyleProperty = (property, styles) => styles[property] || ''; | ||
const getStyles = ($item, props) => { | ||
const styles = window.getComputedStyle($item); | ||
return props.reduce((acc, curr) => { | ||
acc[curr] = parseInt(extractStyleProperty(curr, styles)); | ||
return acc; | ||
}, {}); | ||
}; | ||
const mapStyles = ($item) => { | ||
@@ -18,3 +25,3 @@ const styles = window.getComputedStyle($item); | ||
const mapItem = ({ element, viewport, }) => { | ||
const { paddingLeft, paddingRight, paddingTop, paddingBottom, snapAlign, } = mapStyles(element); | ||
const { paddingLeft, paddingRight, paddingTop, paddingBottom, snapAlign } = mapStyles(element); | ||
const left = element.offsetLeft - viewport.offsetLeft + paddingLeft; | ||
@@ -62,2 +69,3 @@ const width = element.offsetWidth - paddingLeft - paddingRight; | ||
mergeStyles: mergeStyles, | ||
getStyles: getStyles, | ||
mapStyles: mapStyles, | ||
@@ -69,7 +77,6 @@ mapItem: mapItem, | ||
const getActiveSnap = ({ root, onChange, snapAlign = 'start' }) => { | ||
const getActiveSnap = ({ root, onChange, }) => { | ||
let activeSnapObserver; | ||
let activeSnapIndex; | ||
let timeout = null; | ||
let isScrolling = false; | ||
const children = root.children; | ||
@@ -96,93 +103,102 @@ const triggerChange = (snapIndex) => { | ||
const handleScrolling = () => { | ||
isScrolling = true; | ||
if (timeout) | ||
clearTimeout(timeout); | ||
timeout = setTimeout(() => { | ||
// if (root.scrollLeft === 0) { | ||
// setSnapIndex(0); | ||
// } else if (root.scrollLeft === root.scrollWidth - root.offsetWidth) { | ||
// setSnapIndex(children.length - 1); | ||
// } | ||
isScrolling = false; | ||
if (root.scrollLeft === 0) { | ||
setSnapIndex(0); | ||
} | ||
}, 50); | ||
}; | ||
const init = () => { | ||
const rootWidth = root.offsetWidth; | ||
const $viewport = root; | ||
const viewportWidth = $viewport.offsetWidth; | ||
activeSnapIndex = 0; | ||
switch (snapAlign) { | ||
case 'start': | ||
activeSnapObserver = new IntersectionObserver((entries) => { | ||
entries.forEach((entry) => { | ||
// console.log('active snap: ', entry); | ||
if (activeSnapIndex === null) | ||
return; | ||
const entryIndex = Array.prototype.indexOf.call(children, entry.target); | ||
if (entry.isIntersecting && entry.boundingClientRect.right > 0) { | ||
setSnapIndex(entryIndex + 1); | ||
return; | ||
} | ||
if (!entry.isIntersecting && | ||
entry.intersectionRatio > 0 && | ||
entry.boundingClientRect.right > 0) { | ||
setSnapIndex(entryIndex); | ||
return; | ||
} | ||
activeSnapObserver = new IntersectionObserver((entries) => { | ||
entries.forEach((entry) => { | ||
if (entry.isIntersecting) { | ||
const styles = window.getComputedStyle(entry.target); | ||
const observer = getObserver(styles.scrollSnapAlign); | ||
observer.observe(entry.target); | ||
} | ||
}); | ||
}, { | ||
root, | ||
rootMargin: `0px 0px`, | ||
threshold: [0.5], | ||
}); | ||
const getObserver = (snapAlign) => { | ||
switch (snapAlign) { | ||
case 'start': | ||
return new IntersectionObserver((entries) => { | ||
entries.forEach((entry) => { | ||
console.log('active snap: ', entry); | ||
if (activeSnapIndex === null || !entry.rootBounds) | ||
return; | ||
const entryIndex = Array.prototype.indexOf.call(children, entry.target); | ||
if (entry.isIntersecting && | ||
entry.boundingClientRect.right > 0) { | ||
setSnapIndex(entryIndex + 1); | ||
return; | ||
} | ||
if (!entry.isIntersecting && | ||
entry.intersectionRatio > 0 && | ||
entry.boundingClientRect.right - entry.rootBounds.right > 0) { | ||
setSnapIndex(entryIndex); | ||
return; | ||
} | ||
}); | ||
}, { | ||
root, | ||
rootMargin: `0px -100% 0px 50%`, | ||
threshold: [0.5], | ||
}); | ||
}, { | ||
root, | ||
rootMargin: `0px -100% 0px 50%`, | ||
threshold: [0.5], | ||
}); | ||
break; | ||
case 'end': | ||
activeSnapObserver = new IntersectionObserver((entries) => { | ||
entries.forEach((entry) => { | ||
// console.log('active snap: ', entry); | ||
if (activeSnapIndex === null || !isScrolling) | ||
return; | ||
const entryIndex = Array.prototype.indexOf.call(children, entry.target); | ||
if (entry.isIntersecting && | ||
entry.boundingClientRect.left < rootWidth) { | ||
setSnapIndex(entryIndex - 1); | ||
return; | ||
} | ||
if (!entry.isIntersecting && | ||
entry.intersectionRatio > 0 && | ||
entry.boundingClientRect.left < rootWidth) { | ||
setSnapIndex(entryIndex); | ||
return; | ||
} | ||
case 'end': | ||
return new IntersectionObserver((entries) => { | ||
entries.forEach((entry) => { | ||
// console.log('active snap: ', entry); | ||
if (activeSnapIndex === null) | ||
return; | ||
const entryIndex = Array.prototype.indexOf.call(children, entry.target); | ||
if (entry.isIntersecting && | ||
entry.boundingClientRect.left < viewportWidth) { | ||
setSnapIndex(entryIndex - 1); | ||
return; | ||
} | ||
if (!entry.isIntersecting && | ||
entry.intersectionRatio > 0 && | ||
entry.boundingClientRect.left < viewportWidth) { | ||
setSnapIndex(entryIndex); | ||
return; | ||
} | ||
}); | ||
}, { | ||
root, | ||
rootMargin: `0px 50% 0px -100%`, | ||
threshold: [0.5], | ||
}); | ||
}, { | ||
root, | ||
rootMargin: `0px 50% 0px -100%`, | ||
threshold: [0.5], | ||
}); | ||
break; | ||
case 'center': | ||
default: | ||
activeSnapObserver = new IntersectionObserver((entries) => { | ||
entries.forEach((entry) => { | ||
// console.log('active snap: ', entry); | ||
if (activeSnapIndex === null || !isScrolling || !entry.rootBounds) | ||
return; | ||
if (entry.intersectionRatio >= 0.49 && | ||
entry.intersectionRatio <= 0.51 && | ||
entry.boundingClientRect.left <= | ||
case 'center': | ||
default: | ||
return new IntersectionObserver((entries) => { | ||
entries.forEach((entry) => { | ||
// console.log('active snap: ', entry); | ||
if (activeSnapIndex === null || !entry.rootBounds) | ||
return; | ||
if (entry.boundingClientRect.left <= | ||
entry.rootBounds.left + | ||
entry.boundingClientRect.width * 0.01 && | ||
entry.boundingClientRect.right >= | ||
entry.rootBounds.left + entry.boundingClientRect.width * 0.01) { | ||
const entryIndex = Array.prototype.indexOf.call(children, entry.target); | ||
setSnapIndex(entryIndex); | ||
return; | ||
} | ||
entry.boundingClientRect.right >= | ||
entry.rootBounds.left + | ||
entry.boundingClientRect.width * 0.01) { | ||
const entryIndex = Array.prototype.indexOf.call(children, entry.target); | ||
setSnapIndex(entryIndex); | ||
return; | ||
} | ||
}); | ||
}, { | ||
root, | ||
rootMargin: `0px 0px 0px -50%`, | ||
threshold: [0.49, 0.51], | ||
}); | ||
}, { | ||
root, | ||
rootMargin: `0px 0px 0px -50%`, | ||
threshold: [0.49, 0.51], | ||
}); | ||
break; | ||
} | ||
} | ||
}; | ||
root.addEventListener('scroll', handleScrolling); | ||
@@ -251,2 +267,3 @@ Array.from(root.children).forEach((child) => { | ||
return; | ||
// Can't use scrollIntoView() yet since Safari support is still weak: https://caniuse.com/scrollintoview | ||
return smoothScrollPolyfill({ node, scrollTarget, duration }); | ||
@@ -291,6 +308,3 @@ }; | ||
target = { | ||
left: item.left - | ||
// item.paddingLeft - | ||
viewport.paddingLeft - | ||
viewport.scrollPaddingLeft, | ||
left: item.left - viewport.paddingLeft - viewport.scrollPaddingLeft, | ||
top: item.top - | ||
@@ -326,4 +340,4 @@ item.paddingTop - | ||
return { | ||
left: target.left, | ||
top: target.top, | ||
left: Math.min(Math.max(0, target.left), viewport.scrollWidth - viewport.width), | ||
top: Math.min(Math.max(0, target.top), viewport.scrollHeight - viewport.height), | ||
}; | ||
@@ -348,3 +362,3 @@ }; | ||
case 'start': | ||
return item.left; | ||
return Math.max(0, item.left); | ||
case 'end': | ||
@@ -376,2 +390,7 @@ return item.left - (viewport.offsetWidth / 2 - item.width / 2); | ||
let originalScrollSnapType = undefined; | ||
const $viewport = root; | ||
const viewportStyles = getStyles($viewport, [ | ||
'paddingLeft', | ||
'scrollPaddingLeft', | ||
]); | ||
// used to determine whether slider is scrolling. After scrolling ends, reset css classes | ||
@@ -448,3 +467,7 @@ const handleScrolling = () => { | ||
return; | ||
const dragEndPositionX = root.scrollLeft; | ||
const dragEndPositionX = root.scrollLeft + | ||
(root.scrollLeft > 0 | ||
? viewportStyles.scrollPaddingLeft || 0 | ||
: viewportStyles.paddingLeft || 0); | ||
console.log(viewportStyles.scrollPaddingLeft); | ||
const dragEndPositionY = root.scrollTop; | ||
@@ -451,0 +474,0 @@ const isDraggedAllTheWay = root.scrollWidth - root.offsetWidth === root.scrollLeft; |
@@ -7,2 +7,9 @@ 'use strict'; | ||
const extractStyleProperty = (property, styles) => styles[property] || ''; | ||
const getStyles = ($item, props) => { | ||
const styles = window.getComputedStyle($item); | ||
return props.reduce((acc, curr) => { | ||
acc[curr] = parseInt(extractStyleProperty(curr, styles)); | ||
return acc; | ||
}, {}); | ||
}; | ||
const mapStyles = ($item) => { | ||
@@ -23,3 +30,3 @@ const styles = window.getComputedStyle($item); | ||
const mapItem = ({ element, viewport, }) => { | ||
const { paddingLeft, paddingRight, paddingTop, paddingBottom, snapAlign, } = mapStyles(element); | ||
const { paddingLeft, paddingRight, paddingTop, paddingBottom, snapAlign } = mapStyles(element); | ||
const left = element.offsetLeft - viewport.offsetLeft + paddingLeft; | ||
@@ -67,2 +74,3 @@ const width = element.offsetWidth - paddingLeft - paddingRight; | ||
mergeStyles: mergeStyles, | ||
getStyles: getStyles, | ||
mapStyles: mapStyles, | ||
@@ -74,7 +82,6 @@ mapItem: mapItem, | ||
const getActiveSnap = ({ root, onChange, snapAlign = 'start' }) => { | ||
const getActiveSnap = ({ root, onChange, }) => { | ||
let activeSnapObserver; | ||
let activeSnapIndex; | ||
let timeout = null; | ||
let isScrolling = false; | ||
const children = root.children; | ||
@@ -101,93 +108,102 @@ const triggerChange = (snapIndex) => { | ||
const handleScrolling = () => { | ||
isScrolling = true; | ||
if (timeout) | ||
clearTimeout(timeout); | ||
timeout = setTimeout(() => { | ||
// if (root.scrollLeft === 0) { | ||
// setSnapIndex(0); | ||
// } else if (root.scrollLeft === root.scrollWidth - root.offsetWidth) { | ||
// setSnapIndex(children.length - 1); | ||
// } | ||
isScrolling = false; | ||
if (root.scrollLeft === 0) { | ||
setSnapIndex(0); | ||
} | ||
}, 50); | ||
}; | ||
const init = () => { | ||
const rootWidth = root.offsetWidth; | ||
const $viewport = root; | ||
const viewportWidth = $viewport.offsetWidth; | ||
activeSnapIndex = 0; | ||
switch (snapAlign) { | ||
case 'start': | ||
activeSnapObserver = new IntersectionObserver((entries) => { | ||
entries.forEach((entry) => { | ||
// console.log('active snap: ', entry); | ||
if (activeSnapIndex === null) | ||
return; | ||
const entryIndex = Array.prototype.indexOf.call(children, entry.target); | ||
if (entry.isIntersecting && entry.boundingClientRect.right > 0) { | ||
setSnapIndex(entryIndex + 1); | ||
return; | ||
} | ||
if (!entry.isIntersecting && | ||
entry.intersectionRatio > 0 && | ||
entry.boundingClientRect.right > 0) { | ||
setSnapIndex(entryIndex); | ||
return; | ||
} | ||
activeSnapObserver = new IntersectionObserver((entries) => { | ||
entries.forEach((entry) => { | ||
if (entry.isIntersecting) { | ||
const styles = window.getComputedStyle(entry.target); | ||
const observer = getObserver(styles.scrollSnapAlign); | ||
observer.observe(entry.target); | ||
} | ||
}); | ||
}, { | ||
root, | ||
rootMargin: `0px 0px`, | ||
threshold: [0.5], | ||
}); | ||
const getObserver = (snapAlign) => { | ||
switch (snapAlign) { | ||
case 'start': | ||
return new IntersectionObserver((entries) => { | ||
entries.forEach((entry) => { | ||
console.log('active snap: ', entry); | ||
if (activeSnapIndex === null || !entry.rootBounds) | ||
return; | ||
const entryIndex = Array.prototype.indexOf.call(children, entry.target); | ||
if (entry.isIntersecting && | ||
entry.boundingClientRect.right > 0) { | ||
setSnapIndex(entryIndex + 1); | ||
return; | ||
} | ||
if (!entry.isIntersecting && | ||
entry.intersectionRatio > 0 && | ||
entry.boundingClientRect.right - entry.rootBounds.right > 0) { | ||
setSnapIndex(entryIndex); | ||
return; | ||
} | ||
}); | ||
}, { | ||
root, | ||
rootMargin: `0px -100% 0px 50%`, | ||
threshold: [0.5], | ||
}); | ||
}, { | ||
root, | ||
rootMargin: `0px -100% 0px 50%`, | ||
threshold: [0.5], | ||
}); | ||
break; | ||
case 'end': | ||
activeSnapObserver = new IntersectionObserver((entries) => { | ||
entries.forEach((entry) => { | ||
// console.log('active snap: ', entry); | ||
if (activeSnapIndex === null || !isScrolling) | ||
return; | ||
const entryIndex = Array.prototype.indexOf.call(children, entry.target); | ||
if (entry.isIntersecting && | ||
entry.boundingClientRect.left < rootWidth) { | ||
setSnapIndex(entryIndex - 1); | ||
return; | ||
} | ||
if (!entry.isIntersecting && | ||
entry.intersectionRatio > 0 && | ||
entry.boundingClientRect.left < rootWidth) { | ||
setSnapIndex(entryIndex); | ||
return; | ||
} | ||
case 'end': | ||
return new IntersectionObserver((entries) => { | ||
entries.forEach((entry) => { | ||
// console.log('active snap: ', entry); | ||
if (activeSnapIndex === null) | ||
return; | ||
const entryIndex = Array.prototype.indexOf.call(children, entry.target); | ||
if (entry.isIntersecting && | ||
entry.boundingClientRect.left < viewportWidth) { | ||
setSnapIndex(entryIndex - 1); | ||
return; | ||
} | ||
if (!entry.isIntersecting && | ||
entry.intersectionRatio > 0 && | ||
entry.boundingClientRect.left < viewportWidth) { | ||
setSnapIndex(entryIndex); | ||
return; | ||
} | ||
}); | ||
}, { | ||
root, | ||
rootMargin: `0px 50% 0px -100%`, | ||
threshold: [0.5], | ||
}); | ||
}, { | ||
root, | ||
rootMargin: `0px 50% 0px -100%`, | ||
threshold: [0.5], | ||
}); | ||
break; | ||
case 'center': | ||
default: | ||
activeSnapObserver = new IntersectionObserver((entries) => { | ||
entries.forEach((entry) => { | ||
// console.log('active snap: ', entry); | ||
if (activeSnapIndex === null || !isScrolling || !entry.rootBounds) | ||
return; | ||
if (entry.intersectionRatio >= 0.49 && | ||
entry.intersectionRatio <= 0.51 && | ||
entry.boundingClientRect.left <= | ||
case 'center': | ||
default: | ||
return new IntersectionObserver((entries) => { | ||
entries.forEach((entry) => { | ||
// console.log('active snap: ', entry); | ||
if (activeSnapIndex === null || !entry.rootBounds) | ||
return; | ||
if (entry.boundingClientRect.left <= | ||
entry.rootBounds.left + | ||
entry.boundingClientRect.width * 0.01 && | ||
entry.boundingClientRect.right >= | ||
entry.rootBounds.left + entry.boundingClientRect.width * 0.01) { | ||
const entryIndex = Array.prototype.indexOf.call(children, entry.target); | ||
setSnapIndex(entryIndex); | ||
return; | ||
} | ||
entry.boundingClientRect.right >= | ||
entry.rootBounds.left + | ||
entry.boundingClientRect.width * 0.01) { | ||
const entryIndex = Array.prototype.indexOf.call(children, entry.target); | ||
setSnapIndex(entryIndex); | ||
return; | ||
} | ||
}); | ||
}, { | ||
root, | ||
rootMargin: `0px 0px 0px -50%`, | ||
threshold: [0.49, 0.51], | ||
}); | ||
}, { | ||
root, | ||
rootMargin: `0px 0px 0px -50%`, | ||
threshold: [0.49, 0.51], | ||
}); | ||
break; | ||
} | ||
} | ||
}; | ||
root.addEventListener('scroll', handleScrolling); | ||
@@ -256,2 +272,3 @@ Array.from(root.children).forEach((child) => { | ||
return; | ||
// Can't use scrollIntoView() yet since Safari support is still weak: https://caniuse.com/scrollintoview | ||
return smoothScrollPolyfill({ node, scrollTarget, duration }); | ||
@@ -296,6 +313,3 @@ }; | ||
target = { | ||
left: item.left - | ||
// item.paddingLeft - | ||
viewport.paddingLeft - | ||
viewport.scrollPaddingLeft, | ||
left: item.left - viewport.paddingLeft - viewport.scrollPaddingLeft, | ||
top: item.top - | ||
@@ -331,4 +345,4 @@ item.paddingTop - | ||
return { | ||
left: target.left, | ||
top: target.top, | ||
left: Math.min(Math.max(0, target.left), viewport.scrollWidth - viewport.width), | ||
top: Math.min(Math.max(0, target.top), viewport.scrollHeight - viewport.height), | ||
}; | ||
@@ -353,3 +367,3 @@ }; | ||
case 'start': | ||
return item.left; | ||
return Math.max(0, item.left); | ||
case 'end': | ||
@@ -381,2 +395,7 @@ return item.left - (viewport.offsetWidth / 2 - item.width / 2); | ||
let originalScrollSnapType = undefined; | ||
const $viewport = root; | ||
const viewportStyles = getStyles($viewport, [ | ||
'paddingLeft', | ||
'scrollPaddingLeft', | ||
]); | ||
// used to determine whether slider is scrolling. After scrolling ends, reset css classes | ||
@@ -453,3 +472,7 @@ const handleScrolling = () => { | ||
return; | ||
const dragEndPositionX = root.scrollLeft; | ||
const dragEndPositionX = root.scrollLeft + | ||
(root.scrollLeft > 0 | ||
? viewportStyles.scrollPaddingLeft || 0 | ||
: viewportStyles.paddingLeft || 0); | ||
console.log(viewportStyles.scrollPaddingLeft); | ||
const dragEndPositionY = root.scrollTop; | ||
@@ -456,0 +479,0 @@ const isDraggedAllTheWay = root.scrollWidth - root.offsetWidth === root.scrollLeft; |
export declare const mergeStyles: (...classnames: (string | null | undefined)[]) => string; | ||
export declare const getStyles: ($item: HTMLElement | Element, props: Array<keyof CSSStyleDeclaration>) => { | ||
[key: string]: string | number; | ||
}; | ||
export declare const mapStyles: ($item: HTMLElement | Element) => { | ||
@@ -3,0 +6,0 @@ paddingLeft: number; |
{ | ||
"name": "@snap-carousel/core", | ||
"version": "0.0.19-next.1", | ||
"version": "0.0.19-next.2", | ||
"main": "dist/index.js", | ||
@@ -26,3 +26,3 @@ "module": "dist/index.es.js", | ||
}, | ||
"gitHead": "41cab1bc8a6d15d5d7d3cccdc2fe5a8e1890cbea" | ||
"gitHead": "abc79363e32b599cae386d24c200009286d347b5" | ||
} |
@@ -1,2 +0,2 @@ | ||
import { isTouchDevice, mapItem } from './utils'; | ||
import { getStyles, isTouchDevice, mapItem } from './utils'; | ||
import { scrollTo } from './scrollTo'; | ||
@@ -16,3 +16,3 @@ | ||
case 'start': | ||
return item.left; | ||
return Math.max(0, item.left); | ||
case 'end': | ||
@@ -63,2 +63,8 @@ return item.left - (viewport.offsetWidth / 2 - item.width / 2); | ||
const $viewport: HTMLElement = root; | ||
const viewportStyles = getStyles($viewport, [ | ||
'paddingLeft', | ||
'scrollPaddingLeft', | ||
]); | ||
// used to determine whether slider is scrolling. After scrolling ends, reset css classes | ||
@@ -146,3 +152,8 @@ const handleScrolling = () => { | ||
const dragEndPositionX = root.scrollLeft; | ||
const dragEndPositionX = | ||
root.scrollLeft + | ||
((root.scrollLeft > 0 | ||
? viewportStyles.scrollPaddingLeft || 0 | ||
: viewportStyles.paddingLeft || 0) as number); | ||
console.log(viewportStyles.scrollPaddingLeft); | ||
const dragEndPositionY = root.scrollTop; | ||
@@ -149,0 +160,0 @@ const isDraggedAllTheWay = |
@@ -6,6 +6,4 @@ import { debounceHOF } from './utils'; | ||
onChange, | ||
snapAlign = 'start' | ||
}: { | ||
root: HTMLDivElement; | ||
snapAlign?: 'start' | 'center' | 'end'; | ||
onChange?: (snapIndex: number) => void; | ||
@@ -52,8 +50,6 @@ }) => { | ||
timeout = setTimeout(() => { | ||
// if (root.scrollLeft === 0) { | ||
// setSnapIndex(0); | ||
// } else if (root.scrollLeft === root.scrollWidth - root.offsetWidth) { | ||
// setSnapIndex(children.length - 1); | ||
// } | ||
isScrolling = false; | ||
if (root.scrollLeft === 0) { | ||
setSnapIndex(0); | ||
} | ||
}, 50) as any; | ||
@@ -63,99 +59,77 @@ }; | ||
const init = () => { | ||
const rootWidth = root.offsetWidth; | ||
const $viewport: HTMLElement = root; | ||
const viewportWidth = $viewport.offsetWidth; | ||
activeSnapIndex = 0; | ||
switch (snapAlign) { | ||
case 'start': | ||
activeSnapObserver = new IntersectionObserver( | ||
(entries) => { | ||
entries.forEach((entry) => { | ||
// console.log('active snap: ', entry); | ||
activeSnapObserver = new IntersectionObserver( | ||
(entries) => { | ||
entries.forEach((entry) => { | ||
let observer: IntersectionObserver | undefined; | ||
if (activeSnapIndex === null) return; | ||
if (entry.isIntersecting) { | ||
const styles = window.getComputedStyle( | ||
entry.target | ||
) as CSSStyleDeclaration; | ||
const observer = getObserver(styles.scrollSnapAlign); | ||
observer.observe(entry.target); | ||
} else { | ||
if (observer) observer.disconnect(); | ||
} | ||
}); | ||
}, | ||
{ | ||
root, | ||
rootMargin: `0px 0px`, | ||
threshold: [0.5], | ||
} | ||
); | ||
const entryIndex = Array.prototype.indexOf.call( | ||
children, | ||
entry.target | ||
); | ||
const getObserver = (snapAlign: string) => { | ||
switch (snapAlign) { | ||
case 'start': | ||
return new IntersectionObserver( | ||
(entries) => { | ||
entries.forEach((entry) => { | ||
console.log('active snap: ', entry); | ||
if (entry.isIntersecting && entry.boundingClientRect.right > 0) { | ||
setSnapIndex(entryIndex + 1); | ||
return; | ||
} | ||
if (activeSnapIndex === null || !entry.rootBounds) return; | ||
if ( | ||
!entry.isIntersecting && | ||
entry.intersectionRatio > 0 && | ||
entry.boundingClientRect.right > 0 | ||
) { | ||
setSnapIndex(entryIndex); | ||
return; | ||
} | ||
}); | ||
}, | ||
{ | ||
root, | ||
rootMargin: `0px -100% 0px 50%`, | ||
threshold: [0.5], | ||
} | ||
); | ||
break; | ||
case 'end': | ||
activeSnapObserver = new IntersectionObserver( | ||
(entries) => { | ||
entries.forEach((entry) => { | ||
// console.log('active snap: ', entry); | ||
const entryIndex = Array.prototype.indexOf.call( | ||
children, | ||
entry.target | ||
); | ||
if (activeSnapIndex === null || !isScrolling) return; | ||
if ( | ||
entry.isIntersecting && | ||
entry.boundingClientRect.right > 0 | ||
) { | ||
setSnapIndex(entryIndex + 1); | ||
return; | ||
} | ||
const entryIndex = Array.prototype.indexOf.call( | ||
children, | ||
entry.target | ||
); | ||
if ( | ||
!entry.isIntersecting && | ||
entry.intersectionRatio > 0 && | ||
entry.boundingClientRect.right - entry.rootBounds.right > 0 | ||
) { | ||
setSnapIndex(entryIndex); | ||
return; | ||
} | ||
}); | ||
}, | ||
{ | ||
root, | ||
rootMargin: `0px -100% 0px 50%`, | ||
threshold: [0.5], | ||
} | ||
); | ||
case 'end': | ||
return new IntersectionObserver( | ||
(entries) => { | ||
entries.forEach((entry) => { | ||
// console.log('active snap: ', entry); | ||
if ( | ||
entry.isIntersecting && | ||
entry.boundingClientRect.left < rootWidth | ||
) { | ||
setSnapIndex(entryIndex - 1); | ||
return; | ||
} | ||
if (activeSnapIndex === null) return; | ||
if ( | ||
!entry.isIntersecting && | ||
entry.intersectionRatio > 0 && | ||
entry.boundingClientRect.left < rootWidth | ||
) { | ||
setSnapIndex(entryIndex); | ||
return; | ||
} | ||
}); | ||
}, | ||
{ | ||
root, | ||
rootMargin: `0px 50% 0px -100%`, | ||
threshold: [0.5], | ||
} | ||
); | ||
break; | ||
case 'center': | ||
default: | ||
activeSnapObserver = new IntersectionObserver( | ||
(entries) => { | ||
entries.forEach((entry) => { | ||
// console.log('active snap: ', entry); | ||
if (activeSnapIndex === null || !isScrolling || !entry.rootBounds) | ||
return; | ||
if ( | ||
entry.intersectionRatio >= 0.49 && | ||
entry.intersectionRatio <= 0.51 && | ||
entry.boundingClientRect.left <= | ||
entry.rootBounds.left + | ||
entry.boundingClientRect.width * 0.01 && | ||
entry.boundingClientRect.right >= | ||
entry.rootBounds.left + entry.boundingClientRect.width * 0.01 | ||
) { | ||
const entryIndex = Array.prototype.indexOf.call( | ||
@@ -166,16 +140,62 @@ children, | ||
setSnapIndex(entryIndex); | ||
return; | ||
} | ||
}); | ||
}, | ||
{ | ||
root, | ||
rootMargin: `0px 0px 0px -50%`, | ||
threshold: [0.49, 0.51], | ||
} | ||
); | ||
break; | ||
} | ||
if ( | ||
entry.isIntersecting && | ||
entry.boundingClientRect.left < viewportWidth | ||
) { | ||
setSnapIndex(entryIndex - 1); | ||
return; | ||
} | ||
if ( | ||
!entry.isIntersecting && | ||
entry.intersectionRatio > 0 && | ||
entry.boundingClientRect.left < viewportWidth | ||
) { | ||
setSnapIndex(entryIndex); | ||
return; | ||
} | ||
}); | ||
}, | ||
{ | ||
root, | ||
rootMargin: `0px 50% 0px -100%`, | ||
threshold: [0.5], | ||
} | ||
); | ||
case 'center': | ||
default: | ||
return new IntersectionObserver( | ||
(entries) => { | ||
entries.forEach((entry) => { | ||
// console.log('active snap: ', entry); | ||
if (activeSnapIndex === null || !entry.rootBounds) return; | ||
if ( | ||
entry.boundingClientRect.left <= | ||
entry.rootBounds.left + | ||
entry.boundingClientRect.width * 0.01 && | ||
entry.boundingClientRect.right >= | ||
entry.rootBounds.left + | ||
entry.boundingClientRect.width * 0.01 | ||
) { | ||
const entryIndex = Array.prototype.indexOf.call( | ||
children, | ||
entry.target | ||
); | ||
setSnapIndex(entryIndex); | ||
return; | ||
} | ||
}); | ||
}, | ||
{ | ||
root, | ||
rootMargin: `0px 0px 0px -50%`, | ||
threshold: [0.49, 0.51], | ||
} | ||
); | ||
} | ||
}; | ||
root.addEventListener('scroll', handleScrolling); | ||
@@ -182,0 +202,0 @@ |
@@ -98,4 +98,10 @@ import { mapItem, mapStyles } from './utils'; | ||
return { | ||
left: target.left, | ||
top: target.top, | ||
left: Math.min( | ||
Math.max(0, target.left), | ||
viewport.scrollWidth - viewport.width | ||
), | ||
top: Math.min( | ||
Math.max(0, target.top), | ||
viewport.scrollHeight - viewport.height | ||
), | ||
}; | ||
@@ -102,0 +108,0 @@ }; |
@@ -85,3 +85,4 @@ const easingOutQuint = (t: number, b: number, c: number, d: number) => | ||
if (!node) return; | ||
// Can't use scrollIntoView() yet since Safari support is still weak: https://caniuse.com/scrollintoview | ||
return smoothScrollPolyfill({ node, scrollTarget, duration }); | ||
}; |
@@ -9,2 +9,13 @@ export const mergeStyles = (...classnames: (string | null | undefined)[]) => | ||
export const getStyles = ( | ||
$item: HTMLElement | Element, | ||
props: Array<keyof CSSStyleDeclaration> | ||
) => { | ||
const styles = window.getComputedStyle($item) as CSSStyleDeclaration; | ||
return props.reduce((acc: { [key: string]: string | number }, curr) => { | ||
(acc[curr] as any) = parseInt(extractStyleProperty(curr, styles)); | ||
return acc; | ||
}, {}); | ||
}; | ||
export const mapStyles = ($item: HTMLElement | Element) => { | ||
@@ -41,9 +52,4 @@ const styles = window.getComputedStyle($item) as CSSStyleDeclaration; | ||
}) => { | ||
const { | ||
paddingLeft, | ||
paddingRight, | ||
paddingTop, | ||
paddingBottom, | ||
snapAlign, | ||
} = mapStyles(element); | ||
const { paddingLeft, paddingRight, paddingTop, paddingBottom, snapAlign } = | ||
mapStyles(element); | ||
const left = element.offsetLeft - viewport.offsetLeft + paddingLeft; | ||
@@ -50,0 +56,0 @@ const width = element.offsetWidth - paddingLeft - paddingRight; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
149522
1851