Skip to content

Commit

Permalink
fix(target): flaws on SSR and bottom, right position
Browse files Browse the repository at this point in the history
Also, extract types from `index.ts` to `types.ts`
  • Loading branch information
SMAKSS committed Jul 27, 2024
1 parent 2d044a0 commit a08c78e
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 129 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
"object-shorthand": "error",
"no-console": "warn"
"no-console": ["warn", { "allow": ["warn", "error", "info"] }]
}
}
15 changes: 8 additions & 7 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,14 @@ To use a custom scrollable element as a target rather than the default window:
```js
const customElementRef = useRef<HTMLDivElement>(null);
const [customElement, setCustomElement] = useState<HTMLDivElement>();
useEffect(() => {
if(customElementRef.current) {
setHomepageElement(customElementRef.current);
}
}, [customElementRef])
const scrollDir = useDetectScroll({target: customElement});
console.log(scrollDir);

const scrollDir = useDetectScroll({target: customElement});

useEffect(() => {
if(customElementRef.current) {
setHomepageElement(customElementRef.current);
}
}, [customElementRef])
```

## Contributing
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,5 +80,5 @@
},
"type": "module",
"types": "./dist/index.d.ts",
"version": "4.2.0"
"version": "4.2.0-beta.0"
}
166 changes: 46 additions & 120 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,99 +1,11 @@
import { useState, useEffect, useCallback, useRef } from 'react';

/** Enumeration for axis values */
export enum Axis {
/**
* The x-axis represents the horizontal direction.
*/
X = 'x',
/**
* The y-axis represents the vertical direction.
*/
Y = 'y'
}

/** Enumeration for direction values */
export enum Direction {
/**
* The up direction represents the scroll direction moving towards the top.
*/
Up = 'up',
/**
* The down direction represents the scroll direction moving towards the bottom.
*/
Down = 'down',
/**
* The left direction represents the scroll direction moving towards the left.
*/
Left = 'left',
/**
* The right direction represents the scroll direction moving towards the right.
*/
Right = 'right',
/**
* The still direction represents the scroll direction when the user is not scrolling.
*/
Still = 'still'
}

type ScrollPosition = {
/**
* The top position represents the distance from the top edge of the page.
*/
top: number;
/**
* The bottom position represents the distance from the bottom edge of the page.
*/
bottom: number;
/**
* The left position represents the distance from the left edge of the page.
*/
left: number;
/**
* The right position represents the distance from the right edge of the page.
*/
right: number;
};

/** Type declaration for the returned scroll information */
type ScrollInfo = {
/**
* The scrollDir represents the current scroll direction.
*/
scrollDir: Direction;
/**
* The scrollPosition represents the current scroll position.
*/
scrollPosition: ScrollPosition;
};

/** Type declaration for scroll properties */
type ScrollProps = {
/**
* The target represents the scrollable element to check for scroll detection.
*/
target?: HTMLDivElement | Window;
/**
* The thr represents the threshold value for scroll detection.
*/
thr?: number;
/**
* The axis represents the scroll axis (x or y).
*/
axis?: Axis;
/**
* The scrollUp represents the scroll direction when moving up.
*/
scrollUp?: Direction;
/**
* The scrollDown represents the scroll direction when moving down.
*/
scrollDown?: Direction;
/**
* The still represents the scroll direction when the user is not scrolling.
*/
still?: Direction;
};
import {
Axis,
Direction,
ScrollInfo,
ScrollPosition,
ScrollProps
} from './types';

/**
* useDetectScroll hook.
Expand All @@ -107,14 +19,24 @@ type ScrollProps = {
* import useDetectScroll, { Axis, Direction } from '@smakss/react-scroll-direction';
*
* function App() {
* const customElementRef = useRef<HTMLDivElement>(null);
* const [customElement, setCustomElement] = useState<HTMLDivElement>();
*
* const { scrollDir, scrollPosition } = useDetectScroll({
* target: customElement,
* thr: 100,
* axis: Axis.Y,
* scrollUp: Direction.Up,
* scrollDown: Direction.Down,
* still: Direction.Still
* });
*
* useEffect(() => {
* if (customElementRef.current) {
* setCustomElement(customElementRef.current);
* }
* }, [customElementRef]);
*
* return (
* <div>
* <p>Current scroll direction: {scrollDir}</p>
Expand All @@ -129,7 +51,7 @@ type ScrollProps = {
*/
function useDetectScroll(props: ScrollProps = {}): ScrollInfo {
const {
target = window,
target = typeof window !== 'undefined' ? window : undefined,
thr = 0,
axis = Axis.Y,
scrollUp = axis === Axis.Y ? Direction.Up : Direction.Left,
Expand All @@ -151,14 +73,13 @@ function useDetectScroll(props: ScrollProps = {}): ScrollInfo {

/** Function to update scroll direction */
const updateScrollDir = useCallback(() => {
if (!target) return;

let scroll: number;
if (target instanceof Window) {
scroll = axis === Axis.Y ? target.scrollY : target.scrollX;
} else {
scroll =
axis === Axis.Y
? (target as HTMLDivElement).scrollTop
: (target as HTMLDivElement).scrollLeft;
scroll = axis === Axis.Y ? target.scrollTop : target.scrollLeft;
}

if (Math.abs(scroll - lastScroll.current) >= threshold) {
Expand All @@ -169,33 +90,33 @@ function useDetectScroll(props: ScrollProps = {}): ScrollInfo {
}, [target, axis, threshold, scrollDown, scrollUp]);

useEffect(() => {
if (!target) {
console.warn(
'useDetectScroll: target is not set. Falling back to window.'
);
return;
}

/** Function to update scroll position */
const updateScrollPosition = () => {
const top =
target instanceof Window
? target.scrollY
: (target as HTMLDivElement).scrollTop;
if (!target) return;

const top = target instanceof Window ? target.scrollY : target.scrollTop;
const left =
target instanceof Window
? target.scrollX
: (target as HTMLDivElement).scrollLeft;
target instanceof Window ? target.scrollX : target.scrollLeft;

const bottom =
document.documentElement.scrollHeight -
(target instanceof Window
? target.innerHeight
: (target as HTMLDivElement).scrollHeight) -
top;
? document.documentElement.scrollHeight - target.innerHeight
: target.scrollHeight - target.clientHeight) - top;
const right =
document.documentElement.scrollWidth -
(target instanceof Window
? target.innerWidth
: (target as HTMLDivElement).scrollWidth) -
left;
? document.documentElement.scrollWidth - target.innerWidth
: target.scrollWidth - target.clientWidth) - left;

setScrollPosition({ top, bottom, left, right });
};

/** Call the update function when the component mounts */
updateScrollPosition();

const targetElement = target as EventTarget;
Expand All @@ -207,16 +128,20 @@ function useDetectScroll(props: ScrollProps = {}): ScrollInfo {
}, [target]);

useEffect(() => {
if (!target) {
console.warn(
'useDetectScroll: target is not set. Falling back to window.'
);
return;
}

if (target instanceof Window) {
lastScroll.current = axis === Axis.Y ? target.scrollY : target.scrollX;
} else {
lastScroll.current =
axis === Axis.Y
? (target as HTMLDivElement).scrollTop
: (target as HTMLDivElement).scrollLeft;
axis === Axis.Y ? target.scrollTop : target.scrollLeft;
}

/** Function to handle onScroll event */
const onScroll = () => {
if (!ticking.current) {
window.requestAnimationFrame(updateScrollDir);
Expand All @@ -233,4 +158,5 @@ function useDetectScroll(props: ScrollProps = {}): ScrollInfo {
return { scrollDir, scrollPosition };
}

export { Axis, Direction };
export default useDetectScroll;
94 changes: 94 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/** Enumeration for axis values */
export enum Axis {
/**
* The x-axis represents the horizontal direction.
*/
X = 'x',
/**
* The y-axis represents the vertical direction.
*/
Y = 'y'
}

/** Enumeration for direction values */
export enum Direction {
/**
* The up direction represents the scroll direction moving towards the top.
*/
Up = 'up',
/**
* The down direction represents the scroll direction moving towards the bottom.
*/
Down = 'down',
/**
* The left direction represents the scroll direction moving towards the left.
*/
Left = 'left',
/**
* The right direction represents the scroll direction moving towards the right.
*/
Right = 'right',
/**
* The still direction represents the scroll direction when the user is not scrolling.
*/
Still = 'still'
}

export type ScrollPosition = {
/**
* The top position represents the distance from the top edge of the page.
*/
top: number;
/**
* The bottom position represents the distance from the bottom edge of the page.
*/
bottom: number;
/**
* The left position represents the distance from the left edge of the page.
*/
left: number;
/**
* The right position represents the distance from the right edge of the page.
*/
right: number;
};

/** Type declaration for the returned scroll information */
export type ScrollInfo = {
/**
* The scrollDir represents the current scroll direction.
*/
scrollDir: Direction;
/**
* The scrollPosition represents the current scroll position.
*/
scrollPosition: ScrollPosition;
};

/** Type declaration for scroll properties */
export type ScrollProps = {
/**
* The target represents the scrollable element to check for scroll detection.
*/
target?: HTMLDivElement | Window;
/**
* The thr represents the threshold value for scroll detection.
*/
thr?: number;
/**
* The axis represents the scroll axis (x or y).
*/
axis?: Axis;
/**
* The scrollUp represents the scroll direction when moving up.
*/
scrollUp?: Direction;
/**
* The scrollDown represents the scroll direction when moving down.
*/
scrollDown?: Direction;
/**
* The still represents the scroll direction when the user is not scrolling.
*/
still?: Direction;
};

0 comments on commit a08c78e

Please sign in to comment.