@sohanemon/utils 5.1.2 → 5.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hooks/index.d.ts +28 -0
- package/dist/hooks/index.js +67 -13
- package/package.json +1 -1
package/dist/hooks/index.d.ts
CHANGED
|
@@ -160,3 +160,31 @@ export declare const useIsAtTop: ({ offset }?: {
|
|
|
160
160
|
scrollableContainerRef: React.RefObject<HTMLElement>;
|
|
161
161
|
isAtTop: boolean;
|
|
162
162
|
};
|
|
163
|
+
interface UseIntersectionOptions extends IntersectionObserverInit {
|
|
164
|
+
onInteractionStart?: () => void;
|
|
165
|
+
onInteractionEnd?: () => void;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* React hook that tracks when an element enters or leaves the viewport
|
|
169
|
+
* using the Intersection Observer API.
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```tsx
|
|
173
|
+
* const { ref, isIntersecting } = useIntersection({
|
|
174
|
+
* threshold: 0.1,
|
|
175
|
+
* onInteractionStart: () => console.log('👀 Element entered viewport'),
|
|
176
|
+
* onInteractionEnd: () => console.log('🙈 Element left viewport'),
|
|
177
|
+
* });
|
|
178
|
+
*
|
|
179
|
+
* return <div ref={ref}>Watch me</div>;
|
|
180
|
+
* ```
|
|
181
|
+
*
|
|
182
|
+
* @param options - Configuration for the intersection observer.
|
|
183
|
+
* @returns Object containing:
|
|
184
|
+
* - `ref`: React ref to attach to the observed element.
|
|
185
|
+
* - `isIntersecting`: Whether the element is currently visible.
|
|
186
|
+
*/
|
|
187
|
+
export declare const useIntersection: ({ threshold, root, rootMargin, onInteractionStart, onInteractionEnd, }?: UseIntersectionOptions) => {
|
|
188
|
+
ref: React.RefObject<any>;
|
|
189
|
+
isIntersecting: boolean;
|
|
190
|
+
};
|
package/dist/hooks/index.js
CHANGED
|
@@ -154,17 +154,15 @@ export const useSessionStorage = (key, defaultValue) => {
|
|
|
154
154
|
setStoredValue(JSON.parse(value));
|
|
155
155
|
}
|
|
156
156
|
}, [key]);
|
|
157
|
-
const updateStoredValue = (valueOrFn) => {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
newValue
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
setStoredValue(newValue);
|
|
167
|
-
};
|
|
157
|
+
const updateStoredValue = React.useCallback((valueOrFn) => {
|
|
158
|
+
setStoredValue((prev) => {
|
|
159
|
+
const newValue = typeof valueOrFn === 'function'
|
|
160
|
+
? valueOrFn(prev)
|
|
161
|
+
: valueOrFn;
|
|
162
|
+
sessionStorage.setItem(key, JSON.stringify(newValue));
|
|
163
|
+
return newValue;
|
|
164
|
+
});
|
|
165
|
+
}, [key]);
|
|
168
166
|
return [storedValue, updateStoredValue];
|
|
169
167
|
};
|
|
170
168
|
/**
|
|
@@ -181,7 +179,7 @@ export const useLocalStorage = (key, defaultValue) => {
|
|
|
181
179
|
setStoredValue(JSON.parse(value));
|
|
182
180
|
}
|
|
183
181
|
}, [key]);
|
|
184
|
-
const updateStoredValue = (valueOrFn) => {
|
|
182
|
+
const updateStoredValue = React.useCallback((valueOrFn) => {
|
|
185
183
|
let newValue;
|
|
186
184
|
if (typeof valueOrFn === 'function') {
|
|
187
185
|
newValue = valueOrFn(storedValue);
|
|
@@ -191,7 +189,7 @@ export const useLocalStorage = (key, defaultValue) => {
|
|
|
191
189
|
}
|
|
192
190
|
localStorage.setItem(key, JSON.stringify(newValue));
|
|
193
191
|
setStoredValue(newValue);
|
|
194
|
-
};
|
|
192
|
+
}, [key]);
|
|
195
193
|
return [storedValue, updateStoredValue];
|
|
196
194
|
};
|
|
197
195
|
/**
|
|
@@ -475,3 +473,59 @@ export const useIsAtTop = ({ offset } = {}) => {
|
|
|
475
473
|
});
|
|
476
474
|
return { scrollableContainerRef, isAtTop };
|
|
477
475
|
};
|
|
476
|
+
/**
|
|
477
|
+
* React hook that tracks when an element enters or leaves the viewport
|
|
478
|
+
* using the Intersection Observer API.
|
|
479
|
+
*
|
|
480
|
+
* @example
|
|
481
|
+
* ```tsx
|
|
482
|
+
* const { ref, isIntersecting } = useIntersection({
|
|
483
|
+
* threshold: 0.1,
|
|
484
|
+
* onInteractionStart: () => console.log('👀 Element entered viewport'),
|
|
485
|
+
* onInteractionEnd: () => console.log('🙈 Element left viewport'),
|
|
486
|
+
* });
|
|
487
|
+
*
|
|
488
|
+
* return <div ref={ref}>Watch me</div>;
|
|
489
|
+
* ```
|
|
490
|
+
*
|
|
491
|
+
* @param options - Configuration for the intersection observer.
|
|
492
|
+
* @returns Object containing:
|
|
493
|
+
* - `ref`: React ref to attach to the observed element.
|
|
494
|
+
* - `isIntersecting`: Whether the element is currently visible.
|
|
495
|
+
*/
|
|
496
|
+
export const useIntersection = ({ threshold = 0.1, root = null, rootMargin, onInteractionStart, onInteractionEnd, } = {}) => {
|
|
497
|
+
const [isIntersecting, setIsIntersecting] = React.useState(false);
|
|
498
|
+
const ref = React.useRef(null);
|
|
499
|
+
React.useEffect(() => {
|
|
500
|
+
if (!ref.current)
|
|
501
|
+
return;
|
|
502
|
+
const observer = new IntersectionObserver((entries) => {
|
|
503
|
+
for (const entry of entries) {
|
|
504
|
+
if (entry.isIntersecting) {
|
|
505
|
+
if (!isIntersecting) {
|
|
506
|
+
onInteractionStart?.();
|
|
507
|
+
setIsIntersecting(true);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
else {
|
|
511
|
+
if (isIntersecting) {
|
|
512
|
+
onInteractionEnd?.();
|
|
513
|
+
setIsIntersecting(false);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}, { threshold, root, rootMargin });
|
|
518
|
+
observer.observe(ref.current);
|
|
519
|
+
return () => {
|
|
520
|
+
observer.disconnect();
|
|
521
|
+
};
|
|
522
|
+
}, [
|
|
523
|
+
threshold,
|
|
524
|
+
root,
|
|
525
|
+
rootMargin,
|
|
526
|
+
onInteractionStart,
|
|
527
|
+
onInteractionEnd,
|
|
528
|
+
isIntersecting,
|
|
529
|
+
]);
|
|
530
|
+
return { ref, isIntersecting };
|
|
531
|
+
};
|