Skip to content

Commit

Permalink
feat: Add fixed increment scroll behavior to useOverflowScroll
Browse files Browse the repository at this point in the history
  • Loading branch information
UvgenGen committed Mar 21, 2023
1 parent 3955a3e commit ed8f782
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 5 deletions.
4 changes: 4 additions & 0 deletions src/OverflowScroll/OverflowScroll.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ function OverflowScroll({
disableOpacityMasks,
onScrollPrevious,
onScrollNext,
offset,
}) {
const [overflowRef, setOverflowRef] = useState();

Expand All @@ -29,6 +30,7 @@ function OverflowScroll({
onScrollPrevious,
onScrollNext,
overflowRef,
offset,
});

const contextValue = useMemo(() => ({
Expand Down Expand Up @@ -71,6 +73,7 @@ OverflowScroll.propTypes = {
disableOpacityMasks: PropTypes.bool,
onScrollPrevious: PropTypes.func,
onScrollNext: PropTypes.func,
offset: PropTypes.string,
};

OverflowScroll.defaultProps = {
Expand All @@ -80,6 +83,7 @@ OverflowScroll.defaultProps = {
disableOpacityMasks: false,
onScrollPrevious: undefined,
onScrollNext: undefined,
offset: undefined,
};

export default OverflowScroll;
6 changes: 6 additions & 0 deletions src/OverflowScroll/data/useOverflowScroll.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import getOverflowElementScrollLeft from './getOverflowElementScrollLeft';
* @param {boolean} args.disableOpacityMasks Whether the start/end opacity masks should be shown, when applicable.
* @param {string} args.scrollAnimationBehavior Optional override for the scroll behavior. See https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTo for
* more details.
* @param {string} args.offset Fixed increment in pixels or percentage for scroll.
*
* @returns {object} An object with the following properties:
* - overflowRef
Expand All @@ -45,7 +46,9 @@ const useOverflowScroll = ({
disableScroll = false,
disableOpacityMasks = false,
scrollAnimationBehavior = 'smooth',
offset,
}) => {
const [currentOffset, setCurrentOffset] = useState(0);
const [isScrolledToStart, setIsScrolledToStart] = useState(true);
const [isScrolledToEnd, setIsScrolledToEnd] = useState(true);

Expand Down Expand Up @@ -153,6 +156,9 @@ const useOverflowScroll = ({
scrollAnimationBehavior,
onScrollPrevious: handleScrollPrevious,
onScrollNext: handleScrollNext,
onChangeOffset: setCurrentOffset,
currentOffset,
offset,
});

return {
Expand Down
50 changes: 45 additions & 5 deletions src/OverflowScroll/data/useOverflowScrollActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,24 @@ const useOverflowScrollActions = ({
scrollAnimationBehavior = 'smooth',
onScrollPrevious,
onScrollNext,
onChangeOffset,
currentOffset,
offset,
}) => {

const getOffset = (offsetString, maxOffset) => {
let offset = 0;

if (offsetString.endsWith("px")) {
offset = parseInt(offsetString);
} else if (offsetString.endsWith("%")) {
const percent = parseInt(offsetString) / 100;
offset = Math.round(maxOffset * percent);
}

return offset;
}

/**
* A helper function to scroll to the previous element in the overflow container.
*/
Expand All @@ -31,10 +48,21 @@ const useOverflowScrollActions = ({
// otherwise return the previous element
return childrenElements[previousChildElementIndex];
};

const previousChildElementIndex = activeChildElementIndex - 1;
const previousChildElement = getPreviousChildElement(previousChildElementIndex);
const calculatedOffsetLeft = calculateOffsetLeft(previousChildElement);
let calculatedOffsetLeft = calculateOffsetLeft(previousChildElement);

if (offset) {
const maxOffset = overflowRef.scrollWidth - overflowRef.clientWidth;
const offsetValue = getOffset(offset, maxOffset);
calculatedOffsetLeft = currentOffset - offsetValue;
if (calculatedOffsetLeft < 0) {
onChangeOffset(0);
} else {
onChangeOffset(calculatedOffsetLeft);
}
}

overflowRef.scrollTo({
left: calculatedOffsetLeft,
behavior: scrollAnimationBehavior,
Expand Down Expand Up @@ -65,15 +93,27 @@ const useOverflowScrollActions = ({

const getNextChildElement = () => {
// return the last element if the overflow container reached the end
if (isNextChildIndexAtEnd) {
if (isNextChildIndexAtEnd) { // useless ????
return childrenElements[lastChildElementIndex];
}
// otherwise return the next element
return childrenElements[nextChildElementIndex];
};

const nextChildElement = getNextChildElement();
const calculatedOffsetLeft = calculateOffsetLeft(nextChildElement);
let nextChildElement = getNextChildElement();
let calculatedOffsetLeft = calculateOffsetLeft(nextChildElement);

if (offset) {
const maxOffset = overflowRef.scrollWidth - overflowRef.clientWidth;
const offsetValue = getOffset(offset, maxOffset);
calculatedOffsetLeft = currentOffset + offsetValue;
if (calculatedOffsetLeft > maxOffset) {
onChangeOffset(maxOffset);
} else {
onChangeOffset(calculatedOffsetLeft);
}
}

overflowRef.scrollTo({
left: calculatedOffsetLeft,
behavior: scrollAnimationBehavior,
Expand Down

0 comments on commit ed8f782

Please sign in to comment.