@slango/reazione 1.0.7 → 1.0.8

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.
Files changed (43) hide show
  1. package/dist/hooks/useClickOutside.d.ts +3 -0
  2. package/dist/hooks/useClickOutside.d.ts.map +1 -0
  3. package/dist/hooks/useClickOutside.js +18 -0
  4. package/dist/hooks/useClickOutside.js.map +1 -0
  5. package/dist/hooks/useClientValue.d.ts +7 -0
  6. package/dist/hooks/useClientValue.d.ts.map +1 -0
  7. package/dist/hooks/useClientValue.js +11 -0
  8. package/dist/hooks/useClientValue.js.map +1 -0
  9. package/dist/hooks/useDebouncedCallback.d.ts +6 -0
  10. package/dist/hooks/useDebouncedCallback.d.ts.map +1 -0
  11. package/dist/hooks/useDebouncedCallback.js +15 -0
  12. package/dist/hooks/useDebouncedCallback.js.map +1 -0
  13. package/dist/hooks/useMounted.d.ts +2 -0
  14. package/dist/hooks/useMounted.d.ts.map +1 -0
  15. package/dist/hooks/useMounted.js +10 -0
  16. package/dist/hooks/useMounted.js.map +1 -0
  17. package/dist/hooks/usePreventScrolling.d.ts +3 -0
  18. package/dist/hooks/usePreventScrolling.d.ts.map +1 -0
  19. package/dist/hooks/usePreventScrolling.js +24 -0
  20. package/dist/hooks/usePreventScrolling.js.map +1 -0
  21. package/dist/hooks/useScrollEdge.d.ts +16 -0
  22. package/dist/hooks/useScrollEdge.d.ts.map +1 -0
  23. package/dist/hooks/useScrollEdge.js +34 -0
  24. package/dist/hooks/useScrollEdge.js.map +1 -0
  25. package/package.json +7 -4
  26. package/CHANGELOG.md +0 -49
  27. package/eslint.config.js +0 -1
  28. package/lint-staged.config.js +0 -1
  29. package/src/hooks/useClickOutside.spec.ts +0 -52
  30. package/src/hooks/useClickOutside.ts +0 -29
  31. package/src/hooks/useClientValue.spec.ts +0 -39
  32. package/src/hooks/useClientValue.ts +0 -28
  33. package/src/hooks/useDebouncedCallback.spec.ts +0 -65
  34. package/src/hooks/useDebouncedCallback.ts +0 -36
  35. package/src/hooks/useMounted.spec.ts +0 -20
  36. package/src/hooks/useMounted.ts +0 -17
  37. package/src/hooks/usePreventScrolling.spec.ts +0 -76
  38. package/src/hooks/usePreventScrolling.ts +0 -30
  39. package/src/hooks/useScrollEdge.spec.ts +0 -110
  40. package/src/hooks/useScrollEdge.ts +0 -61
  41. package/tsconfig.build.json +0 -10
  42. package/tsconfig.json +0 -11
  43. package/vitest.config.js +0 -1
@@ -0,0 +1,3 @@
1
+ import type { RefObject } from 'react';
2
+ export declare const useClickOutside: (ref: RefObject<HTMLElement | null>, onOutside: () => void, active?: boolean) => void;
3
+ //# sourceMappingURL=useClickOutside.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useClickOutside.d.ts","sourceRoot":"","sources":["../../src/hooks/useClickOutside.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAQvC,eAAO,MAAM,eAAe,GAC1B,KAAK,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EAClC,WAAW,MAAM,IAAI,EACrB,gBAAa,KACZ,IAcF,CAAC"}
@@ -0,0 +1,18 @@
1
+ 'use client';
2
+ import { useEffect, useRef } from 'react';
3
+ export const useClickOutside = (ref, onOutside, active = true) => {
4
+ const onOutsideRef = useRef(onOutside);
5
+ onOutsideRef.current = onOutside;
6
+ useEffect(() => {
7
+ if (!active)
8
+ return;
9
+ const handleClick = (event) => {
10
+ if (ref.current && !ref.current.contains(event.target)) {
11
+ onOutsideRef.current();
12
+ }
13
+ };
14
+ document.addEventListener('mousedown', handleClick);
15
+ return () => document.removeEventListener('mousedown', handleClick);
16
+ }, [ref, active]);
17
+ };
18
+ //# sourceMappingURL=useClickOutside.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useClickOutside.js","sourceRoot":"","sources":["../../src/hooks/useClickOutside.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAIb,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAM1C,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,GAAkC,EAClC,SAAqB,EACrB,MAAM,GAAG,IAAI,EACP,EAAE;IACR,MAAM,YAAY,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;IACvC,YAAY,CAAC,OAAO,GAAG,SAAS,CAAC;IAEjC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,MAAM,WAAW,GAAG,CAAC,KAAiB,EAAE,EAAE;YACxC,IAAI,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAc,CAAC,EAAE,CAAC;gBAC/D,YAAY,CAAC,OAAO,EAAE,CAAC;YACzB,CAAC;QACH,CAAC,CAAC;QACF,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QACpD,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACtE,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;AACpB,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ type Options<T> = {
2
+ deps?: unknown[];
3
+ initialValue: T;
4
+ };
5
+ export declare function useClientValue<T>(initializer: () => T, { deps, initialValue }: Options<T>): T;
6
+ export {};
7
+ //# sourceMappingURL=useClientValue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useClientValue.d.ts","sourceRoot":"","sources":["../../src/hooks/useClientValue.ts"],"names":[],"mappings":"AAIA,KAAK,OAAO,CAAC,CAAC,IAAI;IAChB,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;IACjB,YAAY,EAAE,CAAC,CAAC;CACjB,CAAC;AAOF,wBAAgB,cAAc,CAAC,CAAC,EAC9B,WAAW,EAAE,MAAM,CAAC,EACpB,EAAE,IAAS,EAAE,YAAY,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,GACtC,CAAC,CAUH"}
@@ -0,0 +1,11 @@
1
+ 'use client';
2
+ import { useEffect, useMemo, useState } from 'react';
3
+ export function useClientValue(initializer, { deps = [], initialValue }) {
4
+ const [value, setValue] = useState(initialValue);
5
+ const memoizedInitializer = useMemo(() => initializer, deps);
6
+ useEffect(() => {
7
+ setValue(memoizedInitializer());
8
+ }, [memoizedInitializer]);
9
+ return value;
10
+ }
11
+ //# sourceMappingURL=useClientValue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useClientValue.js","sourceRoot":"","sources":["../../src/hooks/useClientValue.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAYrD,MAAM,UAAU,cAAc,CAC5B,WAAoB,EACpB,EAAE,IAAI,GAAG,EAAE,EAAE,YAAY,EAAc;IAEvC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAI,YAAY,CAAC,CAAC;IAEpD,MAAM,mBAAmB,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAE7D,SAAS,CAAC,GAAG,EAAE;QACb,QAAQ,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAClC,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAE1B,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,6 @@
1
+ export type DebouncedCallback<Args extends unknown[]> = {
2
+ run: (...args: Args) => void;
3
+ cancel: () => void;
4
+ };
5
+ export declare const useDebouncedCallback: <Args extends unknown[]>(callback: (...args: Args) => void, delayMs: number) => DebouncedCallback<Args>;
6
+ //# sourceMappingURL=useDebouncedCallback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDebouncedCallback.d.ts","sourceRoot":"","sources":["../../src/hooks/useDebouncedCallback.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,iBAAiB,CAAC,IAAI,SAAS,OAAO,EAAE,IAAI;IACtD,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB,CAAC;AAOF,eAAO,MAAM,oBAAoB,GAAI,IAAI,SAAS,OAAO,EAAE,EACzD,UAAU,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,IAAI,EACjC,SAAS,MAAM,KACd,iBAAiB,CAAC,IAAI,CAkBxB,CAAC"}
@@ -0,0 +1,15 @@
1
+ 'use client';
2
+ import { useCallback, useEffect, useRef } from 'react';
3
+ export const useDebouncedCallback = (callback, delayMs) => {
4
+ const timeoutRef = useRef(undefined);
5
+ const callbackRef = useRef(callback);
6
+ callbackRef.current = callback;
7
+ useEffect(() => () => clearTimeout(timeoutRef.current), []);
8
+ const cancel = useCallback(() => clearTimeout(timeoutRef.current), []);
9
+ const run = useCallback((...args) => {
10
+ clearTimeout(timeoutRef.current);
11
+ timeoutRef.current = setTimeout(() => callbackRef.current(...args), delayMs);
12
+ }, [delayMs]);
13
+ return { run, cancel };
14
+ };
15
+ //# sourceMappingURL=useDebouncedCallback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDebouncedCallback.js","sourceRoot":"","sources":["../../src/hooks/useDebouncedCallback.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAYvD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,QAAiC,EACjC,OAAe,EACU,EAAE;IAC3B,MAAM,UAAU,GAAG,MAAM,CAA4C,SAAS,CAAC,CAAC;IAChF,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IACrC,WAAW,CAAC,OAAO,GAAG,QAAQ,CAAC;IAE/B,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAE5D,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAEvE,MAAM,GAAG,GAAG,WAAW,CACrB,CAAC,GAAG,IAAU,EAAE,EAAE;QAChB,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACjC,UAAU,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;IAC/E,CAAC,EACD,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AACzB,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const useMounted: () => boolean;
2
+ //# sourceMappingURL=useMounted.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMounted.d.ts","sourceRoot":"","sources":["../../src/hooks/useMounted.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,UAAU,QAAO,OAQ7B,CAAC"}
@@ -0,0 +1,10 @@
1
+ 'use client';
2
+ import { useEffect, useState } from 'react';
3
+ export const useMounted = () => {
4
+ const [isMounted, setIsMounted] = useState(false);
5
+ useEffect(() => {
6
+ setIsMounted(true);
7
+ }, []);
8
+ return isMounted;
9
+ };
10
+ //# sourceMappingURL=useMounted.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMounted.js","sourceRoot":"","sources":["../../src/hooks/useMounted.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAM5C,MAAM,CAAC,MAAM,UAAU,GAAG,GAAY,EAAE;IACtC,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAElD,SAAS,CAAC,GAAG,EAAE;QACb,YAAY,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare const SCROLLBAR_WIDTH_VAR = "--scrollbar-width";
2
+ export declare const usePreventScrolling: (active?: boolean) => void;
3
+ //# sourceMappingURL=usePreventScrolling.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePreventScrolling.d.ts","sourceRoot":"","sources":["../../src/hooks/usePreventScrolling.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AAOvD,eAAO,MAAM,mBAAmB,GAAI,gBAAa,KAAG,IAkBnD,CAAC"}
@@ -0,0 +1,24 @@
1
+ 'use client';
2
+ import { useEffect } from 'react';
3
+ export const SCROLLBAR_WIDTH_VAR = '--scrollbar-width';
4
+ export const usePreventScrolling = (active = true) => {
5
+ useEffect(() => {
6
+ if (!active)
7
+ return;
8
+ const html = document.documentElement;
9
+ const scrollbarWidth = window.innerWidth - html.clientWidth;
10
+ const previousOverflow = html.style.overflow;
11
+ const previousPaddingRight = html.style.paddingRight;
12
+ html.style.overflow = 'hidden';
13
+ if (scrollbarWidth > 0) {
14
+ html.style.paddingRight = `${scrollbarWidth}px`;
15
+ html.style.setProperty(SCROLLBAR_WIDTH_VAR, `${scrollbarWidth}px`);
16
+ }
17
+ return () => {
18
+ html.style.overflow = previousOverflow;
19
+ html.style.paddingRight = previousPaddingRight;
20
+ html.style.removeProperty(SCROLLBAR_WIDTH_VAR);
21
+ };
22
+ }, [active]);
23
+ };
24
+ //# sourceMappingURL=usePreventScrolling.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePreventScrolling.js","sourceRoot":"","sources":["../../src/hooks/usePreventScrolling.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,MAAM,CAAC,MAAM,mBAAmB,GAAG,mBAAmB,CAAC;AAOvD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,MAAM,GAAG,IAAI,EAAQ,EAAE;IACzD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,MAAM,IAAI,GAAG,QAAQ,CAAC,eAAe,CAAC;QACtC,MAAM,cAAc,GAAG,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC;QAC5D,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;QAC7C,MAAM,oBAAoB,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC;QACrD,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAC/B,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;YACvB,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,GAAG,cAAc,IAAI,CAAC;YAChD,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,mBAAmB,EAAE,GAAG,cAAc,IAAI,CAAC,CAAC;QACrE,CAAC;QACD,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,gBAAgB,CAAC;YACvC,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,oBAAoB,CAAC;YAC/C,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC;QACjD,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;AACf,CAAC,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { RefObject } from 'react';
2
+ export declare enum Edge {
3
+ BOTTOM = "bottom",
4
+ LEFT = "left",
5
+ RIGHT = "right",
6
+ TOP = "top"
7
+ }
8
+ export type UseScrollEdgeOptions = {
9
+ debounceDelay?: number;
10
+ edge?: Edge;
11
+ offset?: number;
12
+ onEdgeReached: () => Promise<void> | void;
13
+ scrollElement?: RefObject<HTMLElement | null>;
14
+ };
15
+ export declare const useScrollEdge: ({ debounceDelay, edge, offset, onEdgeReached, scrollElement, }: UseScrollEdgeOptions) => void;
16
+ //# sourceMappingURL=useScrollEdge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useScrollEdge.d.ts","sourceRoot":"","sources":["../../src/hooks/useScrollEdge.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,oBAAY,IAAI;IACd,MAAM,WAAW;IACjB,IAAI,SAAS;IACb,KAAK,UAAU;IACf,GAAG,QAAQ;CACZ;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1C,aAAa,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;CAC/C,CAAC;AAMF,eAAO,MAAM,aAAa,GAAI,gEAM3B,oBAAoB,KAAG,IA2BzB,CAAC"}
@@ -0,0 +1,34 @@
1
+ 'use client';
2
+ import { useEffect } from 'react';
3
+ import { useDebouncedCallback } from './useDebouncedCallback.js';
4
+ export var Edge;
5
+ (function (Edge) {
6
+ Edge["BOTTOM"] = "bottom";
7
+ Edge["LEFT"] = "left";
8
+ Edge["RIGHT"] = "right";
9
+ Edge["TOP"] = "top";
10
+ })(Edge || (Edge = {}));
11
+ export const useScrollEdge = ({ debounceDelay = 200, edge = Edge.BOTTOM, offset = 100, onEdgeReached, scrollElement, }) => {
12
+ const { run: handleScroll, cancel } = useDebouncedCallback(() => {
13
+ const container = scrollElement?.current || document.documentElement;
14
+ const { clientHeight, clientWidth, scrollHeight, scrollLeft, scrollTop, scrollWidth } = container;
15
+ const edgeConditions = {
16
+ [Edge.BOTTOM]: () => scrollHeight - scrollTop - clientHeight <= offset,
17
+ [Edge.LEFT]: () => scrollLeft <= offset,
18
+ [Edge.RIGHT]: () => scrollWidth - scrollLeft - clientWidth <= offset,
19
+ [Edge.TOP]: () => scrollTop <= offset,
20
+ };
21
+ if (edgeConditions[edge]()) {
22
+ void onEdgeReached();
23
+ }
24
+ }, debounceDelay);
25
+ useEffect(() => {
26
+ const container = scrollElement?.current || window;
27
+ container.addEventListener('scroll', handleScroll);
28
+ return () => {
29
+ container.removeEventListener('scroll', handleScroll);
30
+ cancel();
31
+ };
32
+ }, [handleScroll, cancel, scrollElement]);
33
+ };
34
+ //# sourceMappingURL=useScrollEdge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useScrollEdge.js","sourceRoot":"","sources":["../../src/hooks/useScrollEdge.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAIb,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,MAAM,CAAN,IAAY,IAKX;AALD,WAAY,IAAI;IACd,yBAAiB,CAAA;IACjB,qBAAa,CAAA;IACb,uBAAe,CAAA;IACf,mBAAW,CAAA;AACb,CAAC,EALW,IAAI,KAAJ,IAAI,QAKf;AAcD,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAC5B,aAAa,GAAG,GAAG,EACnB,IAAI,GAAG,IAAI,CAAC,MAAM,EAClB,MAAM,GAAG,GAAG,EACZ,aAAa,EACb,aAAa,GACQ,EAAQ,EAAE;IAC/B,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,oBAAoB,CAAC,GAAG,EAAE;QAC9D,MAAM,SAAS,GAAG,aAAa,EAAE,OAAO,IAAI,QAAQ,CAAC,eAAe,CAAC;QACrE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,GACnF,SAAS,CAAC;QAEZ,MAAM,cAAc,GAAgC;YAClD,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,YAAY,GAAG,SAAS,GAAG,YAAY,IAAI,MAAM;YACtE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,UAAU,IAAI,MAAM;YACvC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,WAAW,GAAG,UAAU,GAAG,WAAW,IAAI,MAAM;YACpE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,SAAS,IAAI,MAAM;SACtC,CAAC;QAEF,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YAC3B,KAAK,aAAa,EAAE,CAAC;QACvB,CAAC;IACH,CAAC,EAAE,aAAa,CAAC,CAAC;IAElB,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,SAAS,GAAG,aAAa,EAAE,OAAO,IAAI,MAAM,CAAC;QACnD,SAAS,CAAC,gBAAgB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;QAEnD,OAAO,GAAG,EAAE;YACV,SAAS,CAAC,mBAAmB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;YACtD,MAAM,EAAE,CAAC;QACX,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;AAC5C,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slango/reazione",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "private": false,
5
5
  "description": "Collection of generic react utilities",
6
6
  "repository": {
@@ -9,6 +9,9 @@
9
9
  "directory": "packages/reazione"
10
10
  },
11
11
  "type": "module",
12
+ "files": [
13
+ "dist"
14
+ ],
12
15
  "exports": {
13
16
  "./*": {
14
17
  "import": "./dist/*.js",
@@ -29,9 +32,9 @@
29
32
  "react-dom": "19.2.7",
30
33
  "typescript": "6.0.3",
31
34
  "vitest": "4.1.10",
32
- "@slango.configs/eslint": "1.2.32",
33
- "@slango.configs/vitest": "2.0.41",
34
- "@slango.configs/typescript": "2.0.9"
35
+ "@slango.configs/vitest": "2.0.42",
36
+ "@slango.configs/eslint": "1.2.33",
37
+ "@slango.configs/typescript": "2.0.10"
35
38
  },
36
39
  "scripts": {
37
40
  "build": "tsc -p tsconfig.build.json",
package/CHANGELOG.md DELETED
@@ -1,49 +0,0 @@
1
- # @slango/reazione
2
-
3
- ## 1.0.7
4
-
5
- ### Patch Changes
6
-
7
- - 7d321c6: Dependencies bump
8
-
9
- ## 1.0.6
10
-
11
- ### Patch Changes
12
-
13
- - 463d9ce: Dependencies bump
14
-
15
- ## 1.0.5
16
-
17
- ### Patch Changes
18
-
19
- - 02b8cd1: Dependencies bump
20
-
21
- ## 1.0.4
22
-
23
- ### Patch Changes
24
-
25
- - 75b71f7: Dependencies bump
26
-
27
- ## 1.0.3
28
-
29
- ### Patch Changes
30
-
31
- - 7b9def8: Dependencies bump
32
-
33
- ## 1.0.2
34
-
35
- ### Patch Changes
36
-
37
- - 1052e1d: Dependencies bump
38
-
39
- ## 1.0.1
40
-
41
- ### Patch Changes
42
-
43
- - 52a706b: Dependencies bump
44
-
45
- ## 1.0.0
46
-
47
- ### Major Changes
48
-
49
- - a0c8af4: First version. Generic react hooks: useDebouncedCallback, useMounted, useClickOutside, useClientValue, usePreventScrolling and useScrollEdge.
package/eslint.config.js DELETED
@@ -1 +0,0 @@
1
- export { default } from '@slango.configs/eslint/typescript-react.js';
@@ -1 +0,0 @@
1
- export { default } from '@slango.configs/lint-staged/typescript.js';
@@ -1,52 +0,0 @@
1
- import { renderHook } from '@testing-library/react';
2
- import { describe, expect, it, vi } from 'vitest';
3
-
4
- import { useClickOutside } from './useClickOutside.js';
5
-
6
- const mouseDown = (target: Node) => {
7
- const event = new MouseEvent('mousedown', { bubbles: true });
8
- target.dispatchEvent(event);
9
- };
10
-
11
- describe('useClickOutside', () => {
12
- it('fires when clicking outside the element', () => {
13
- const element = document.createElement('div');
14
- document.body.appendChild(element);
15
- const onOutside = vi.fn();
16
-
17
- renderHook(() => useClickOutside({ current: element }, onOutside));
18
- mouseDown(document.body);
19
-
20
- expect(onOutside).toHaveBeenCalledTimes(1);
21
- element.remove();
22
- });
23
-
24
- it('does not fire when clicking inside the element', () => {
25
- const element = document.createElement('div');
26
- const child = document.createElement('span');
27
- element.appendChild(child);
28
- document.body.appendChild(element);
29
- const onOutside = vi.fn();
30
-
31
- renderHook(() => useClickOutside({ current: element }, onOutside));
32
- mouseDown(child);
33
-
34
- expect(onOutside).not.toHaveBeenCalled();
35
- element.remove();
36
- });
37
-
38
- it('does nothing while inactive and unsubscribes on unmount', () => {
39
- const element = document.createElement('div');
40
- document.body.appendChild(element);
41
- const onOutside = vi.fn();
42
-
43
- const { unmount } = renderHook(() => useClickOutside({ current: element }, onOutside, false));
44
- mouseDown(document.body);
45
- expect(onOutside).not.toHaveBeenCalled();
46
-
47
- unmount();
48
- mouseDown(document.body);
49
- expect(onOutside).not.toHaveBeenCalled();
50
- element.remove();
51
- });
52
- });
@@ -1,29 +0,0 @@
1
- 'use client';
2
-
3
- import type { RefObject } from 'react';
4
-
5
- import { useEffect, useRef } from 'react';
6
-
7
- /**
8
- * Invokes `onOutside` when a mousedown lands outside the referenced element.
9
- * The handler is kept fresh without re-subscribing the document listener.
10
- */
11
- export const useClickOutside = (
12
- ref: RefObject<HTMLElement | null>,
13
- onOutside: () => void,
14
- active = true,
15
- ): void => {
16
- const onOutsideRef = useRef(onOutside);
17
- onOutsideRef.current = onOutside;
18
-
19
- useEffect(() => {
20
- if (!active) return;
21
- const handleClick = (event: MouseEvent) => {
22
- if (ref.current && !ref.current.contains(event.target as Node)) {
23
- onOutsideRef.current();
24
- }
25
- };
26
- document.addEventListener('mousedown', handleClick);
27
- return () => document.removeEventListener('mousedown', handleClick);
28
- }, [ref, active]);
29
- };
@@ -1,39 +0,0 @@
1
- import { renderHook } from '@testing-library/react';
2
- import { describe, expect, it, vi } from 'vitest';
3
-
4
- import { useClientValue } from './useClientValue.js';
5
-
6
- describe('useClientValue', () => {
7
- it('resolves the initializer value after mount', () => {
8
- const { result } = renderHook(() => useClientValue(() => 'client', { initialValue: 'server' }));
9
-
10
- expect(result.current).toBe('client');
11
- });
12
-
13
- it('re-runs the initializer when deps change', () => {
14
- const initializer = vi.fn((suffix: string) => `value-${suffix}`);
15
- const { result, rerender } = renderHook(
16
- ({ suffix }) =>
17
- useClientValue(() => initializer(suffix), { deps: [suffix], initialValue: '' }),
18
- { initialProps: { suffix: 'a' } },
19
- );
20
-
21
- expect(result.current).toBe('value-a');
22
-
23
- rerender({ suffix: 'b' });
24
-
25
- expect(result.current).toBe('value-b');
26
- });
27
-
28
- it('does not re-run the initializer when deps are stable', () => {
29
- const initializer = vi.fn(() => 42);
30
- const { rerender } = renderHook(() =>
31
- useClientValue(initializer, { deps: ['fixed'], initialValue: 0 }),
32
- );
33
-
34
- rerender();
35
- rerender();
36
-
37
- expect(initializer).toHaveBeenCalledTimes(1);
38
- });
39
- });
@@ -1,28 +0,0 @@
1
- 'use client';
2
-
3
- import { useEffect, useMemo, useState } from 'react';
4
-
5
- type Options<T> = {
6
- deps?: unknown[];
7
- initialValue: T;
8
- };
9
-
10
- /**
11
- * Renders `initialValue` on the server/hydration pass, then resolves the
12
- * value with `initializer` on the client (re-running when `deps` change).
13
- * Avoids hydration mismatches for values that only exist client-side.
14
- */
15
- export function useClientValue<T>(
16
- initializer: () => T,
17
- { deps = [], initialValue }: Options<T>,
18
- ): T {
19
- const [value, setValue] = useState<T>(initialValue);
20
-
21
- const memoizedInitializer = useMemo(() => initializer, deps);
22
-
23
- useEffect(() => {
24
- setValue(memoizedInitializer());
25
- }, [memoizedInitializer]);
26
-
27
- return value;
28
- }
@@ -1,65 +0,0 @@
1
- import { renderHook } from '@testing-library/react';
2
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
3
-
4
- import { useDebouncedCallback } from './useDebouncedCallback.js';
5
-
6
- describe('useDebouncedCallback', () => {
7
- beforeEach(() => {
8
- vi.useFakeTimers();
9
- });
10
-
11
- afterEach(() => {
12
- vi.useRealTimers();
13
- });
14
-
15
- it('invokes the callback once after the delay with the last arguments', () => {
16
- const callback = vi.fn();
17
- const { result } = renderHook(() => useDebouncedCallback(callback, 100));
18
-
19
- result.current.run('a');
20
- result.current.run('b');
21
- vi.advanceTimersByTime(99);
22
- expect(callback).not.toHaveBeenCalled();
23
-
24
- vi.advanceTimersByTime(1);
25
- expect(callback).toHaveBeenCalledTimes(1);
26
- expect(callback).toHaveBeenCalledWith('b');
27
- });
28
-
29
- it('always invokes the latest callback', () => {
30
- const first = vi.fn();
31
- const second = vi.fn();
32
- const { result, rerender } = renderHook(({ cb }) => useDebouncedCallback(cb, 100), {
33
- initialProps: { cb: first },
34
- });
35
-
36
- result.current.run('a');
37
- rerender({ cb: second });
38
- vi.advanceTimersByTime(100);
39
-
40
- expect(first).not.toHaveBeenCalled();
41
- expect(second).toHaveBeenCalledWith('a');
42
- });
43
-
44
- it('cancel prevents a pending invocation', () => {
45
- const callback = vi.fn();
46
- const { result } = renderHook(() => useDebouncedCallback(callback, 100));
47
-
48
- result.current.run('a');
49
- result.current.cancel();
50
- vi.advanceTimersByTime(200);
51
-
52
- expect(callback).not.toHaveBeenCalled();
53
- });
54
-
55
- it('cleans up the timer on unmount', () => {
56
- const callback = vi.fn();
57
- const { result, unmount } = renderHook(() => useDebouncedCallback(callback, 100));
58
-
59
- result.current.run('a');
60
- unmount();
61
- vi.advanceTimersByTime(200);
62
-
63
- expect(callback).not.toHaveBeenCalled();
64
- });
65
- });
@@ -1,36 +0,0 @@
1
- 'use client';
2
-
3
- import { useCallback, useEffect, useRef } from 'react';
4
-
5
- export type DebouncedCallback<Args extends unknown[]> = {
6
- run: (...args: Args) => void;
7
- cancel: () => void;
8
- };
9
-
10
- /**
11
- * Returns a debounced wrapper around the latest `callback` plus a `cancel`
12
- * for flushing pending invocations (e.g. when clearing an input). The timer
13
- * is cleaned up on unmount and `run`/`cancel` have stable identities.
14
- */
15
- export const useDebouncedCallback = <Args extends unknown[]>(
16
- callback: (...args: Args) => void,
17
- delayMs: number,
18
- ): DebouncedCallback<Args> => {
19
- const timeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
20
- const callbackRef = useRef(callback);
21
- callbackRef.current = callback;
22
-
23
- useEffect(() => () => clearTimeout(timeoutRef.current), []);
24
-
25
- const cancel = useCallback(() => clearTimeout(timeoutRef.current), []);
26
-
27
- const run = useCallback(
28
- (...args: Args) => {
29
- clearTimeout(timeoutRef.current);
30
- timeoutRef.current = setTimeout(() => callbackRef.current(...args), delayMs);
31
- },
32
- [delayMs],
33
- );
34
-
35
- return { run, cancel };
36
- };
@@ -1,20 +0,0 @@
1
- import { renderHook } from '@testing-library/react';
2
- import { describe, expect, it } from 'vitest';
3
-
4
- import { useMounted } from './useMounted.js';
5
-
6
- describe('useMounted', () => {
7
- it('returns true once mounted', () => {
8
- const { result } = renderHook(() => useMounted());
9
-
10
- expect(result.current).toBe(true);
11
- });
12
-
13
- it('stays true across rerenders', () => {
14
- const { result, rerender } = renderHook(() => useMounted());
15
-
16
- rerender();
17
-
18
- expect(result.current).toBe(true);
19
- });
20
- });
@@ -1,17 +0,0 @@
1
- 'use client';
2
-
3
- import { useEffect, useState } from 'react';
4
-
5
- /**
6
- * Returns false during SSR/hydration and true after the component mounts.
7
- * Useful for gating client-only rendering.
8
- */
9
- export const useMounted = (): boolean => {
10
- const [isMounted, setIsMounted] = useState(false);
11
-
12
- useEffect(() => {
13
- setIsMounted(true);
14
- }, []);
15
-
16
- return isMounted;
17
- };
@@ -1,76 +0,0 @@
1
- import { renderHook } from '@testing-library/react';
2
- import { beforeEach, describe, expect, it, vi } from 'vitest';
3
-
4
- import { SCROLLBAR_WIDTH_VAR, usePreventScrolling } from './usePreventScrolling.js';
5
-
6
- describe('usePreventScrolling', () => {
7
- const html = document.documentElement;
8
-
9
- beforeEach(() => {
10
- html.style.overflow = '';
11
- html.style.paddingRight = '';
12
- html.style.removeProperty(SCROLLBAR_WIDTH_VAR);
13
- vi.restoreAllMocks();
14
- });
15
-
16
- it('sets html overflow to hidden when active', () => {
17
- renderHook(() => usePreventScrolling());
18
-
19
- expect(html.style.overflow).toBe('hidden');
20
- });
21
-
22
- it('restores previous overflow on unmount', () => {
23
- html.style.overflow = 'auto';
24
-
25
- const { unmount } = renderHook(() => usePreventScrolling());
26
-
27
- expect(html.style.overflow).toBe('hidden');
28
-
29
- unmount();
30
-
31
- expect(html.style.overflow).toBe('auto');
32
- });
33
-
34
- it('does not modify overflow when active is false', () => {
35
- html.style.overflow = 'scroll';
36
-
37
- renderHook(() => usePreventScrolling(false));
38
-
39
- expect(html.style.overflow).toBe('scroll');
40
- });
41
-
42
- it('compensates for scrollbar width with paddingRight', () => {
43
- vi.spyOn(html, 'clientWidth', 'get').mockReturnValue(984);
44
- vi.spyOn(window, 'innerWidth', 'get').mockReturnValue(1000);
45
-
46
- renderHook(() => usePreventScrolling());
47
-
48
- expect(html.style.paddingRight).toBe('16px');
49
- expect(html.style.getPropertyValue(SCROLLBAR_WIDTH_VAR)).toBe('16px');
50
- });
51
-
52
- it('restores previous paddingRight and removes the CSS variable on unmount', () => {
53
- vi.spyOn(html, 'clientWidth', 'get').mockReturnValue(984);
54
- vi.spyOn(window, 'innerWidth', 'get').mockReturnValue(1000);
55
- html.style.paddingRight = '8px';
56
-
57
- const { unmount } = renderHook(() => usePreventScrolling());
58
-
59
- expect(html.style.paddingRight).toBe('16px');
60
-
61
- unmount();
62
-
63
- expect(html.style.paddingRight).toBe('8px');
64
- expect(html.style.getPropertyValue(SCROLLBAR_WIDTH_VAR)).toBe('');
65
- });
66
-
67
- it('does not set paddingRight or the CSS variable when there is no scrollbar', () => {
68
- vi.spyOn(html, 'clientWidth', 'get').mockReturnValue(1000);
69
- vi.spyOn(window, 'innerWidth', 'get').mockReturnValue(1000);
70
-
71
- renderHook(() => usePreventScrolling());
72
-
73
- expect(html.style.paddingRight).toBe('');
74
- expect(html.style.getPropertyValue(SCROLLBAR_WIDTH_VAR)).toBe('');
75
- });
76
- });
@@ -1,30 +0,0 @@
1
- 'use client';
2
-
3
- import { useEffect } from 'react';
4
-
5
- export const SCROLLBAR_WIDTH_VAR = '--scrollbar-width';
6
-
7
- /**
8
- * Locks background scroll, padding the document to compensate for the removed
9
- * scrollbar so the layout doesn't shift. The scrollbar width is also exposed
10
- * as a CSS variable for fixed-position elements that need the same offset.
11
- */
12
- export const usePreventScrolling = (active = true): void => {
13
- useEffect(() => {
14
- if (!active) return;
15
- const html = document.documentElement;
16
- const scrollbarWidth = window.innerWidth - html.clientWidth;
17
- const previousOverflow = html.style.overflow;
18
- const previousPaddingRight = html.style.paddingRight;
19
- html.style.overflow = 'hidden';
20
- if (scrollbarWidth > 0) {
21
- html.style.paddingRight = `${scrollbarWidth}px`;
22
- html.style.setProperty(SCROLLBAR_WIDTH_VAR, `${scrollbarWidth}px`);
23
- }
24
- return () => {
25
- html.style.overflow = previousOverflow;
26
- html.style.paddingRight = previousPaddingRight;
27
- html.style.removeProperty(SCROLLBAR_WIDTH_VAR);
28
- };
29
- }, [active]);
30
- };
@@ -1,110 +0,0 @@
1
- import { renderHook } from '@testing-library/react';
2
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
3
-
4
- import { Edge, useScrollEdge } from './useScrollEdge.js';
5
-
6
- const makeScrollable = ({
7
- scrollTop = 0,
8
- scrollHeight = 1000,
9
- clientHeight = 500,
10
- }: Partial<Pick<HTMLElement, 'scrollTop' | 'scrollHeight' | 'clientHeight'>> = {}) => {
11
- const element = document.createElement('div');
12
- Object.defineProperties(element, {
13
- scrollTop: { value: scrollTop, configurable: true },
14
- scrollHeight: { value: scrollHeight, configurable: true },
15
- clientHeight: { value: clientHeight, configurable: true },
16
- scrollLeft: { value: 0, configurable: true },
17
- scrollWidth: { value: 0, configurable: true },
18
- clientWidth: { value: 0, configurable: true },
19
- });
20
- return element;
21
- };
22
-
23
- describe('useScrollEdge', () => {
24
- beforeEach(() => {
25
- vi.useFakeTimers();
26
- });
27
-
28
- afterEach(() => {
29
- vi.useRealTimers();
30
- });
31
-
32
- it('fires onEdgeReached when scrolled within the offset of the bottom', () => {
33
- const element = makeScrollable({ scrollTop: 450 });
34
- const onEdgeReached = vi.fn();
35
-
36
- renderHook(() =>
37
- useScrollEdge({ onEdgeReached, scrollElement: { current: element }, debounceDelay: 50 }),
38
- );
39
-
40
- element.dispatchEvent(new Event('scroll'));
41
- vi.advanceTimersByTime(50);
42
-
43
- expect(onEdgeReached).toHaveBeenCalledTimes(1);
44
- });
45
-
46
- it('does not fire when far from the edge', () => {
47
- const element = makeScrollable({ scrollTop: 0 });
48
- const onEdgeReached = vi.fn();
49
-
50
- renderHook(() =>
51
- useScrollEdge({ onEdgeReached, scrollElement: { current: element }, debounceDelay: 50 }),
52
- );
53
-
54
- element.dispatchEvent(new Event('scroll'));
55
- vi.advanceTimersByTime(50);
56
-
57
- expect(onEdgeReached).not.toHaveBeenCalled();
58
- });
59
-
60
- it('supports the top edge', () => {
61
- const element = makeScrollable({ scrollTop: 10 });
62
- const onEdgeReached = vi.fn();
63
-
64
- renderHook(() =>
65
- useScrollEdge({
66
- edge: Edge.TOP,
67
- onEdgeReached,
68
- scrollElement: { current: element },
69
- debounceDelay: 50,
70
- }),
71
- );
72
-
73
- element.dispatchEvent(new Event('scroll'));
74
- vi.advanceTimersByTime(50);
75
-
76
- expect(onEdgeReached).toHaveBeenCalledTimes(1);
77
- });
78
-
79
- it('debounces bursts of scroll events into one invocation', () => {
80
- const element = makeScrollable({ scrollTop: 450 });
81
- const onEdgeReached = vi.fn();
82
-
83
- renderHook(() =>
84
- useScrollEdge({ onEdgeReached, scrollElement: { current: element }, debounceDelay: 50 }),
85
- );
86
-
87
- for (let i = 0; i < 5; i++) {
88
- element.dispatchEvent(new Event('scroll'));
89
- vi.advanceTimersByTime(10);
90
- }
91
- vi.advanceTimersByTime(50);
92
-
93
- expect(onEdgeReached).toHaveBeenCalledTimes(1);
94
- });
95
-
96
- it('stops listening after unmount', () => {
97
- const element = makeScrollable({ scrollTop: 450 });
98
- const onEdgeReached = vi.fn();
99
-
100
- const { unmount } = renderHook(() =>
101
- useScrollEdge({ onEdgeReached, scrollElement: { current: element }, debounceDelay: 50 }),
102
- );
103
-
104
- unmount();
105
- element.dispatchEvent(new Event('scroll'));
106
- vi.advanceTimersByTime(100);
107
-
108
- expect(onEdgeReached).not.toHaveBeenCalled();
109
- });
110
- });
@@ -1,61 +0,0 @@
1
- 'use client';
2
-
3
- import type { RefObject } from 'react';
4
-
5
- import { useEffect } from 'react';
6
-
7
- import { useDebouncedCallback } from './useDebouncedCallback.js';
8
-
9
- export enum Edge {
10
- BOTTOM = 'bottom',
11
- LEFT = 'left',
12
- RIGHT = 'right',
13
- TOP = 'top',
14
- }
15
-
16
- export type UseScrollEdgeOptions = {
17
- debounceDelay?: number;
18
- edge?: Edge;
19
- offset?: number;
20
- onEdgeReached: () => Promise<void> | void;
21
- scrollElement?: RefObject<HTMLElement | null>;
22
- };
23
-
24
- /**
25
- * Invokes `onEdgeReached` (debounced) whenever scrolling comes within
26
- * `offset` pixels of the given edge of `scrollElement` (or the document).
27
- */
28
- export const useScrollEdge = ({
29
- debounceDelay = 200,
30
- edge = Edge.BOTTOM,
31
- offset = 100,
32
- onEdgeReached,
33
- scrollElement,
34
- }: UseScrollEdgeOptions): void => {
35
- const { run: handleScroll, cancel } = useDebouncedCallback(() => {
36
- const container = scrollElement?.current || document.documentElement;
37
- const { clientHeight, clientWidth, scrollHeight, scrollLeft, scrollTop, scrollWidth } =
38
- container;
39
-
40
- const edgeConditions: Record<Edge, () => boolean> = {
41
- [Edge.BOTTOM]: () => scrollHeight - scrollTop - clientHeight <= offset,
42
- [Edge.LEFT]: () => scrollLeft <= offset,
43
- [Edge.RIGHT]: () => scrollWidth - scrollLeft - clientWidth <= offset,
44
- [Edge.TOP]: () => scrollTop <= offset,
45
- };
46
-
47
- if (edgeConditions[edge]()) {
48
- void onEdgeReached();
49
- }
50
- }, debounceDelay);
51
-
52
- useEffect(() => {
53
- const container = scrollElement?.current || window;
54
- container.addEventListener('scroll', handleScroll);
55
-
56
- return () => {
57
- container.removeEventListener('scroll', handleScroll);
58
- cancel();
59
- };
60
- }, [handleScroll, cancel, scrollElement]);
61
- };
@@ -1,10 +0,0 @@
1
- {
2
- "$schema": "https://json.schemastore.org/tsconfig",
3
- "extends": "./tsconfig.json",
4
- "compilerOptions": {
5
- "noEmit": false,
6
- "outDir": "./dist",
7
- "rootDir": "./src"
8
- },
9
- "exclude": ["node_modules", "dist", "src/**/*.spec.ts"]
10
- }
package/tsconfig.json DELETED
@@ -1,11 +0,0 @@
1
- {
2
- "$schema": "https://json.schemastore.org/tsconfig",
3
- "extends": "@slango.configs/typescript/default.json",
4
- "compilerOptions": {
5
- "noEmit": true,
6
- "lib": ["dom", "dom.iterable", "esnext"],
7
- "types": []
8
- },
9
- "include": ["**/*.ts"],
10
- "exclude": ["node_modules", "dist"]
11
- }
package/vitest.config.js DELETED
@@ -1 +0,0 @@
1
- export { default } from '@slango.configs/vitest/react';