Skip to content

Commit

Permalink
implement onChangeActiveId prop
Browse files Browse the repository at this point in the history
  • Loading branch information
toviszsolt committed May 23, 2024
1 parent 63b137b commit 56b7a34
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 13 deletions.
41 changes: 30 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,17 +128,18 @@ _Note: The much loved `Refs` used in the previous version and React were thrown

### Optional `ScrollSpy` props

| Prop | Type | Default | Description |
| ----------- | ------------------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| activeClass | string | '' | Class name(s) to be applied to the active link |
| activeAttr | boolean | false | If true, the active link will have an attribute `data-active` attached to it. |
| offsetTop | number | 0 | Offset the final scroll position from top in pixels. |
| offsetLeft | number | 0 | Offset the final scroll position from left in pixels. |
| behavior | 'smooth' \| 'instant' \| 'auto' | 'smooth' | Behavior of the scroll animation. See: [Element: scrollTo()](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTo#options) |
| root | HTMLElement \| null | null | Root element for the intersection observer. See: [IntersectionObserver: IntersectionObserver()](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/IntersectionObserver#options) |
| rootMargin | string | '0px' | Root margin for the intersection observer. See: [IntersectionObserver: IntersectionObserver()](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/IntersectionObserver#options) |
| threshold | number \| number[] | [0, 0.25, 0.5, 0.75, 1] | Thresholds for the intersection observer. See: [IntersectionObserver: IntersectionObserver()](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/IntersectionObserver#options) |
| onClickEach | function | undefined | Callback function for handle the click event |
| Prop | Type | Default | Description |
| ---------------- | ------------------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| activeClass | string | '' | Class name(s) to be applied to the active link |
| activeAttr | boolean | false | If true, the active link will have an attribute `data-active` attached to it. |
| offsetTop | number | 0 | Offset the final scroll position from top in pixels. |
| offsetLeft | number | 0 | Offset the final scroll position from left in pixels. |
| behavior | 'smooth' \| 'instant' \| 'auto' | 'smooth' | Behavior of the scroll animation. See: [Element: scrollTo()](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTo#options) |
| root | HTMLElement \| null | null | Root element for the intersection observer. See: [IntersectionObserver: IntersectionObserver()](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/IntersectionObserver#options) |
| rootMargin | string | '0px' | Root margin for the intersection observer. See: [IntersectionObserver: IntersectionObserver()](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/IntersectionObserver#options) |
| threshold | number \| number[] | [0, 0.25, 0.5, 0.75, 1] | Thresholds for the intersection observer. See: [IntersectionObserver: IntersectionObserver()](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/IntersectionObserver#options) |
| onClickEach | function | undefined | Callback function for handle the click event |
| onChangeActiveId | function | undefined | Callback function for handle the active element change event |

### `onClickEach(event, internalClickHandler, container)`

Expand All @@ -161,6 +162,24 @@ const Comp = () => {
};
```

## `onChangeActiveId(currentId, prevId)`

- `currentId`: The id of the active element
- `prevId`: The id of previous active element

Example:

```jsx
const Comp = () => {
const onChangeActiveId = (current, prev) => {
console.log('Active element changed');
console.log({ current, prev });
};

return <ScrollSpy onChangeActiveId={onClickEach}>...</ScrollSpy>;
};
```

## Compatibility

The component depends on the following functions or classes, which define its compatibility.
Expand Down
10 changes: 10 additions & 0 deletions lib/ScrollSpy.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,16 @@ declare function ScrollSpy(props: {
/** Container element that is being scrolled */
container: HTMLElement,
) => void;

/** Callback function for handle the active element change event */
onChangeActiveId?(
/** The id of the active element */
currentId: string | null,

/** The id of previous active element */
prevId: string | null,
): void;

children?: React.ReactNode;
}): JSX.Element;

Expand Down
3 changes: 2 additions & 1 deletion lib/ScrollSpy.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ const ScrollSpy = ({
rootMargin = '0px',
threshold = [0, 0.25, 0.5, 0.75, 1],
onClickEach = null,
onChangeActiveId = null,
children = null,
}) => {
const { idsRef, activeLink } = useScrollObserver({ root, rootMargin, threshold });
const { idsRef, activeLink } = useScrollObserver({ root, rootMargin, threshold, onChangeActiveId });

const modifiedChildren = (children) => {
return Children.map(children, (child) => {
Expand Down
6 changes: 5 additions & 1 deletion lib/useScrollObserver.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { useEffect, useRef, useState } from 'react';

const useScrollObserver = ({ root, rootMargin, threshold }) => {
const useScrollObserver = ({ root, rootMargin, threshold, onChangeActiveId }) => {
const [activeLink, setActiveLink] = useState(null);
const idsRef = useRef([]);

Expand All @@ -17,6 +17,10 @@ const useScrollObserver = ({ root, rootMargin, threshold }) => {
const entry = idsRef.current.find((el) => el.ratio === maxRatio);

setActiveLink(entry && entry.id);

if (entry && entry.id && activeLink !== entry.id && typeof onChangeActiveId === 'function') {
onChangeActiveId(entry.id, activeLink);
}
};

const optionsObserver = { root, rootMargin, threshold };
Expand Down

0 comments on commit 56b7a34

Please sign in to comment.