@alessiofrittoli/react-hooks 3.0.0 → 3.2.0-alpha.1
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/README.md +25 -6
- package/dist/index.d.mts +46 -4
- package/dist/index.d.ts +46 -4
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +21 -27
package/README.md
CHANGED
|
@@ -267,9 +267,13 @@ Get Document Media matches and listen for changes.
|
|
|
267
267
|
|
|
268
268
|
<summary style="cursor:pointer">Parameters</summary>
|
|
269
269
|
|
|
270
|
-
| Parameter | Type | Description |
|
|
271
|
-
|
|
272
|
-
| `query` | `string` | A string specifying the media query to parse into a `MediaQueryList`. |
|
|
270
|
+
| Parameter | Type | Default | Description |
|
|
271
|
+
|-----------|----------|---------|-------------|
|
|
272
|
+
| `query` | `string` | - | A string specifying the media query to parse into a `MediaQueryList`. |
|
|
273
|
+
| `options` | `UseMediaQueryOptions\|UseMediaQueryStateOptions` | - | An object defining custom options. |
|
|
274
|
+
| `options.updateState` | `boolean` | `true` | Indicates whether the hook will dispatch a React state update when the given `query` change event get dispatched. |
|
|
275
|
+
| `options.onChange` | `OnChangeHandler` | - | A custom callback that will be invoked on initial page load and when the given `query` change event get dispatched. |
|
|
276
|
+
| | | | This callback is required if `updateState` is set to `false`. |
|
|
273
277
|
|
|
274
278
|
</details>
|
|
275
279
|
|
|
@@ -279,10 +283,10 @@ Get Document Media matches and listen for changes.
|
|
|
279
283
|
|
|
280
284
|
<summary style="cursor:pointer">Returns</summary>
|
|
281
285
|
|
|
282
|
-
Type: `boolean`
|
|
286
|
+
Type: `boolean|void`
|
|
283
287
|
|
|
284
|
-
- `true` if the document currently matches the media query list.
|
|
285
|
-
- `
|
|
288
|
+
- `true` or `false` if the document currently matches the media query list or not.
|
|
289
|
+
- `void` if `updateState` is set to `false`.
|
|
286
290
|
|
|
287
291
|
</details>
|
|
288
292
|
|
|
@@ -300,6 +304,21 @@ import { useMediaQuery } from '@alessiofrittoli/react-hooks'
|
|
|
300
304
|
const isDarkOS = useMediaQuery( '(prefers-color-scheme: dark)' )
|
|
301
305
|
```
|
|
302
306
|
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
###### Listen changes with no state updates
|
|
310
|
+
|
|
311
|
+
```tsx
|
|
312
|
+
import { useMediaQuery } from '@alessiofrittoli/react-hooks'
|
|
313
|
+
|
|
314
|
+
useMediaQuery( '(prefers-color-scheme: dark)', {
|
|
315
|
+
updateState: false,
|
|
316
|
+
onChange( matches ) {
|
|
317
|
+
console.log( 'is dark OS?', matches )
|
|
318
|
+
}
|
|
319
|
+
} )
|
|
320
|
+
```
|
|
321
|
+
|
|
303
322
|
</details>
|
|
304
323
|
|
|
305
324
|
---
|
package/dist/index.d.mts
CHANGED
|
@@ -481,15 +481,50 @@ declare function useEventListener<T extends Record<string, Event>, K extends key
|
|
|
481
481
|
*/
|
|
482
482
|
declare const useIsPortrait: () => boolean;
|
|
483
483
|
|
|
484
|
+
type OnChangeHandler = (matches: boolean) => void;
|
|
485
|
+
interface CommonOptions {
|
|
486
|
+
/**
|
|
487
|
+
* A custom callback that will be invoked on initial page load and when the given `query` change event get dispatched.
|
|
488
|
+
*
|
|
489
|
+
* @param matches Whether the document currently matches the media query list.
|
|
490
|
+
*/
|
|
491
|
+
onChange?: OnChangeHandler;
|
|
492
|
+
}
|
|
493
|
+
interface UseMediaQueryOptions extends CommonOptions {
|
|
494
|
+
/**
|
|
495
|
+
* Indicates whether the hook will dispatch a React state update when the given `query` change event get dispatched.
|
|
496
|
+
*
|
|
497
|
+
*/
|
|
498
|
+
updateState: false;
|
|
499
|
+
onChange: OnChangeHandler;
|
|
500
|
+
}
|
|
501
|
+
interface UseMediaQueryStateOptions extends CommonOptions {
|
|
502
|
+
/**
|
|
503
|
+
* Indicates whether the hook will dispatch a React state update when the given `query` change event get dispatched.
|
|
504
|
+
*
|
|
505
|
+
*/
|
|
506
|
+
updateState?: true;
|
|
507
|
+
}
|
|
484
508
|
/**
|
|
485
|
-
* Get Document Media matches and
|
|
509
|
+
* Get Document Media matches and dispatch a React state update on MediaQuery changes.
|
|
486
510
|
*
|
|
487
511
|
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia)
|
|
488
512
|
*
|
|
489
|
-
* @param query
|
|
513
|
+
* @param query A string specifying the media query to parse into a `MediaQueryList`.
|
|
514
|
+
* @param options An object defining custom options. See {@linkcode UseMediaQueryStateOptions} for more info.
|
|
515
|
+
*
|
|
490
516
|
* @returns A boolean value that returns `true` if the document currently matches the media query list, or `false` if not.
|
|
491
517
|
*/
|
|
492
|
-
declare
|
|
518
|
+
declare function useMediaQuery(query: string, options?: UseMediaQueryStateOptions): boolean;
|
|
519
|
+
/**
|
|
520
|
+
* Get Document Media matches and listen for changes.
|
|
521
|
+
*
|
|
522
|
+
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia)
|
|
523
|
+
*
|
|
524
|
+
* @param query A string specifying the media query to parse into a `MediaQueryList`.
|
|
525
|
+
* @param options An object defining custom options. See {@linkcode UseMediaQueryOptions} for more info.
|
|
526
|
+
*/
|
|
527
|
+
declare function useMediaQuery(query: string, options?: UseMediaQueryOptions): void;
|
|
493
528
|
|
|
494
529
|
type SetFocusTrap = (target?: HTMLElement) => void;
|
|
495
530
|
type RestoreFocusTrap = () => void;
|
|
@@ -701,6 +736,13 @@ declare const useInView: (target: React.RefObject<Element | null>, options?: Use
|
|
|
701
736
|
*/
|
|
702
737
|
declare const useScrollBlock: (target?: React.RefObject<HTMLElement | null>) => readonly [() => void, () => void];
|
|
703
738
|
|
|
739
|
+
/**
|
|
740
|
+
* Modified version of `useEffect` that only run once on intial load.
|
|
741
|
+
*
|
|
742
|
+
* @param effect Imperative function that can return a cleanup function.
|
|
743
|
+
*/
|
|
744
|
+
declare const useEffectOnce: (effect: React.EffectCallback) => void;
|
|
745
|
+
|
|
704
746
|
/**
|
|
705
747
|
* Check if the React Hook or Component where this hook is executed is running in a browser environment.
|
|
706
748
|
*
|
|
@@ -1012,4 +1054,4 @@ declare function useTimeout<T extends readonly unknown[]>(callback: TimerHandler
|
|
|
1012
1054
|
*/
|
|
1013
1055
|
declare const useLightTimeout: <T extends readonly unknown[]>(callback: TimerHandler<T>, options?: BasicTimerOptions<T>) => void;
|
|
1014
1056
|
|
|
1015
|
-
export { type AddEventListenerOptions, type BasicTimerOptions, type CommonListenerOptions, type CustomEventListenerOptions, type DocumentEventListener, type DocumentListenerOptions, type ElementEventListener, type ElementListenerOptions, type IntersectionState, type ListenerOptions, type MarginType, type MarginValue, type MediaQueryChangeListener, type MediaQueryEventListener, type MediaQueryListenerOptions, type OnIntersectHandler, type OnIntersectStateHandler, type StartTimer, type StateTimerOptions, type StateTimerReturnType, type StopTimer, type TimerHandler, type TimerId, type TimerOptions, type TimerReturnType, type UseDarkModeOptions, type UseDarkModeOutput, type UseInViewOptions, type UseInViewReturnType, type UseIntervalWhenVisibleReturnType, type UseIntervalWhenVisibleStateReturnType, type WindowEventListener, type WindowListenerOptions, useDarkMode, useDebounce, useEventListener, useFocusTrap, useInView, useInterval, useIntervalWhenVisible, useIsClient, useIsFirstRender, useIsPortrait, useLightInterval, useLightTimeout, useLocalStorage, useMediaQuery, useScrollBlock, useSessionStorage, useStorage, useTimeout, useUpdateEffect };
|
|
1057
|
+
export { type AddEventListenerOptions, type BasicTimerOptions, type CommonListenerOptions, type CustomEventListenerOptions, type DocumentEventListener, type DocumentListenerOptions, type ElementEventListener, type ElementListenerOptions, type IntersectionState, type ListenerOptions, type MarginType, type MarginValue, type MediaQueryChangeListener, type MediaQueryEventListener, type MediaQueryListenerOptions, type OnChangeHandler, type OnIntersectHandler, type OnIntersectStateHandler, type StartTimer, type StateTimerOptions, type StateTimerReturnType, type StopTimer, type TimerHandler, type TimerId, type TimerOptions, type TimerReturnType, type UseDarkModeOptions, type UseDarkModeOutput, type UseInViewOptions, type UseInViewReturnType, type UseIntervalWhenVisibleReturnType, type UseIntervalWhenVisibleStateReturnType, type UseMediaQueryOptions, type UseMediaQueryStateOptions, type WindowEventListener, type WindowListenerOptions, useDarkMode, useDebounce, useEffectOnce, useEventListener, useFocusTrap, useInView, useInterval, useIntervalWhenVisible, useIsClient, useIsFirstRender, useIsPortrait, useLightInterval, useLightTimeout, useLocalStorage, useMediaQuery, useScrollBlock, useSessionStorage, useStorage, useTimeout, useUpdateEffect };
|
package/dist/index.d.ts
CHANGED
|
@@ -481,15 +481,50 @@ declare function useEventListener<T extends Record<string, Event>, K extends key
|
|
|
481
481
|
*/
|
|
482
482
|
declare const useIsPortrait: () => boolean;
|
|
483
483
|
|
|
484
|
+
type OnChangeHandler = (matches: boolean) => void;
|
|
485
|
+
interface CommonOptions {
|
|
486
|
+
/**
|
|
487
|
+
* A custom callback that will be invoked on initial page load and when the given `query` change event get dispatched.
|
|
488
|
+
*
|
|
489
|
+
* @param matches Whether the document currently matches the media query list.
|
|
490
|
+
*/
|
|
491
|
+
onChange?: OnChangeHandler;
|
|
492
|
+
}
|
|
493
|
+
interface UseMediaQueryOptions extends CommonOptions {
|
|
494
|
+
/**
|
|
495
|
+
* Indicates whether the hook will dispatch a React state update when the given `query` change event get dispatched.
|
|
496
|
+
*
|
|
497
|
+
*/
|
|
498
|
+
updateState: false;
|
|
499
|
+
onChange: OnChangeHandler;
|
|
500
|
+
}
|
|
501
|
+
interface UseMediaQueryStateOptions extends CommonOptions {
|
|
502
|
+
/**
|
|
503
|
+
* Indicates whether the hook will dispatch a React state update when the given `query` change event get dispatched.
|
|
504
|
+
*
|
|
505
|
+
*/
|
|
506
|
+
updateState?: true;
|
|
507
|
+
}
|
|
484
508
|
/**
|
|
485
|
-
* Get Document Media matches and
|
|
509
|
+
* Get Document Media matches and dispatch a React state update on MediaQuery changes.
|
|
486
510
|
*
|
|
487
511
|
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia)
|
|
488
512
|
*
|
|
489
|
-
* @param query
|
|
513
|
+
* @param query A string specifying the media query to parse into a `MediaQueryList`.
|
|
514
|
+
* @param options An object defining custom options. See {@linkcode UseMediaQueryStateOptions} for more info.
|
|
515
|
+
*
|
|
490
516
|
* @returns A boolean value that returns `true` if the document currently matches the media query list, or `false` if not.
|
|
491
517
|
*/
|
|
492
|
-
declare
|
|
518
|
+
declare function useMediaQuery(query: string, options?: UseMediaQueryStateOptions): boolean;
|
|
519
|
+
/**
|
|
520
|
+
* Get Document Media matches and listen for changes.
|
|
521
|
+
*
|
|
522
|
+
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia)
|
|
523
|
+
*
|
|
524
|
+
* @param query A string specifying the media query to parse into a `MediaQueryList`.
|
|
525
|
+
* @param options An object defining custom options. See {@linkcode UseMediaQueryOptions} for more info.
|
|
526
|
+
*/
|
|
527
|
+
declare function useMediaQuery(query: string, options?: UseMediaQueryOptions): void;
|
|
493
528
|
|
|
494
529
|
type SetFocusTrap = (target?: HTMLElement) => void;
|
|
495
530
|
type RestoreFocusTrap = () => void;
|
|
@@ -701,6 +736,13 @@ declare const useInView: (target: React.RefObject<Element | null>, options?: Use
|
|
|
701
736
|
*/
|
|
702
737
|
declare const useScrollBlock: (target?: React.RefObject<HTMLElement | null>) => readonly [() => void, () => void];
|
|
703
738
|
|
|
739
|
+
/**
|
|
740
|
+
* Modified version of `useEffect` that only run once on intial load.
|
|
741
|
+
*
|
|
742
|
+
* @param effect Imperative function that can return a cleanup function.
|
|
743
|
+
*/
|
|
744
|
+
declare const useEffectOnce: (effect: React.EffectCallback) => void;
|
|
745
|
+
|
|
704
746
|
/**
|
|
705
747
|
* Check if the React Hook or Component where this hook is executed is running in a browser environment.
|
|
706
748
|
*
|
|
@@ -1012,4 +1054,4 @@ declare function useTimeout<T extends readonly unknown[]>(callback: TimerHandler
|
|
|
1012
1054
|
*/
|
|
1013
1055
|
declare const useLightTimeout: <T extends readonly unknown[]>(callback: TimerHandler<T>, options?: BasicTimerOptions<T>) => void;
|
|
1014
1056
|
|
|
1015
|
-
export { type AddEventListenerOptions, type BasicTimerOptions, type CommonListenerOptions, type CustomEventListenerOptions, type DocumentEventListener, type DocumentListenerOptions, type ElementEventListener, type ElementListenerOptions, type IntersectionState, type ListenerOptions, type MarginType, type MarginValue, type MediaQueryChangeListener, type MediaQueryEventListener, type MediaQueryListenerOptions, type OnIntersectHandler, type OnIntersectStateHandler, type StartTimer, type StateTimerOptions, type StateTimerReturnType, type StopTimer, type TimerHandler, type TimerId, type TimerOptions, type TimerReturnType, type UseDarkModeOptions, type UseDarkModeOutput, type UseInViewOptions, type UseInViewReturnType, type UseIntervalWhenVisibleReturnType, type UseIntervalWhenVisibleStateReturnType, type WindowEventListener, type WindowListenerOptions, useDarkMode, useDebounce, useEventListener, useFocusTrap, useInView, useInterval, useIntervalWhenVisible, useIsClient, useIsFirstRender, useIsPortrait, useLightInterval, useLightTimeout, useLocalStorage, useMediaQuery, useScrollBlock, useSessionStorage, useStorage, useTimeout, useUpdateEffect };
|
|
1057
|
+
export { type AddEventListenerOptions, type BasicTimerOptions, type CommonListenerOptions, type CustomEventListenerOptions, type DocumentEventListener, type DocumentListenerOptions, type ElementEventListener, type ElementListenerOptions, type IntersectionState, type ListenerOptions, type MarginType, type MarginValue, type MediaQueryChangeListener, type MediaQueryEventListener, type MediaQueryListenerOptions, type OnChangeHandler, type OnIntersectHandler, type OnIntersectStateHandler, type StartTimer, type StateTimerOptions, type StateTimerReturnType, type StopTimer, type TimerHandler, type TimerId, type TimerOptions, type TimerReturnType, type UseDarkModeOptions, type UseDarkModeOutput, type UseInViewOptions, type UseInViewReturnType, type UseIntervalWhenVisibleReturnType, type UseIntervalWhenVisibleStateReturnType, type UseMediaQueryOptions, type UseMediaQueryStateOptions, type WindowEventListener, type WindowListenerOptions, useDarkMode, useDebounce, useEffectOnce, useEventListener, useFocusTrap, useInView, useInterval, useIntervalWhenVisible, useIsClient, useIsFirstRender, useIsPortrait, useLightInterval, useLightTimeout, useLocalStorage, useMediaQuery, useScrollBlock, useSessionStorage, useStorage, useTimeout, useUpdateEffect };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _react = require('react');var _LocalStorage = require('@alessiofrittoli/web-utils/storage/LocalStorage');var _SessionStorage = require('@alessiofrittoli/web-utils/storage/SessionStorage');var g=(e,
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _react = require('react');var _LocalStorage = require('@alessiofrittoli/web-utils/storage/LocalStorage');var _SessionStorage = require('@alessiofrittoli/web-utils/storage/SessionStorage');var g=(e,o,t="local")=>{let s=_react.useCallback.call(void 0, ()=>_nullishCoalesce((t==="local"?_LocalStorage.LocalStorage:_SessionStorage.SessionStorage).get(e), () => (o)),[t,e,o]),[i,a]=_react.useState.call(void 0, o),r=_react.useCallback.call(void 0, n=>{a(u=>{let l=n instanceof Function?n(u):n;return(typeof window<"u"&&t==="local"?_LocalStorage.LocalStorage:_SessionStorage.SessionStorage).set(e,l),l})},[t,e]);return _react.useEffect.call(void 0, ()=>{a(s())},[s]),[i,r]};var K=(e,o)=>g(e,o,"local");var we=(e,o)=>g(e,o,"session");var O=()=>{let e=_react.useRef.call(void 0, !0);return e.current?(e.current=!1,!0):e.current};var $e=e=>{let o=O();_react.useEffect.call(void 0, ()=>{if(o)return e()},[])};var W=()=>{let[e,o]=_react.useState.call(void 0, !1);return _react.useEffect.call(void 0, ()=>o(!0),[]),e};var k=(e,o)=>{let t=O();_react.useEffect.call(void 0, ()=>{if(!t)return e()},o)};var _browserapi = require('@alessiofrittoli/web-utils/browser-api');function S(e,o={}){let{updateState:t=!0,onChange:s}=o,[i,a]=_react.useState.call(void 0, _browserapi.getMediaMatches.call(void 0, e)),r=_react.useCallback.call(void 0, ()=>{let n=_browserapi.getMediaMatches.call(void 0, e);t&&a(n),_optionalChain([s, 'optionalCall', _2 => _2(n)])},[e,t,s]);if(_react.useEffect.call(void 0, ()=>{let n=window.matchMedia(e),{matches:u}=n;return t&&a(u),_optionalChain([s, 'optionalCall', _3 => _3(u)]),n.addEventListener("change",r),()=>{n.removeEventListener("change",r)}},[e,t,s,r]),!!t)return i}var st=(e={})=>{let o=W(),t=S("(prefers-color-scheme: dark)"),{initial:s=t,docClassNames:i=[]}=e,[a,r]=K("dark-mode",s),n=_nullishCoalesce(a, () => (t)),[u,l]=i,c=_react.useRef.call(void 0, {light:"",dark:""});return k(()=>{r(t)},[t,r]),_react.useEffect.call(void 0, ()=>{u&&document.documentElement.classList.toggle(u,n),l&&document.documentElement.classList.toggle(l,!n)},[n,u,l]),_react.useEffect.call(void 0, ()=>{document.head.querySelectorAll('meta[name="theme-color"]').forEach(p=>{let d=p.getAttribute("media"),f=p.getAttribute("content");if(f){if(!d||d==="(prefers-color-scheme: light)"){c.current.light=f;return}c.current.dark=f}})},[]),k(()=>{let p=c.current.dark,d=c.current.light;a&&!p||!a&&!d||document.head.querySelectorAll('meta[name="theme-color"]').forEach(f=>{f.setAttribute("content",a?p:d)})},[a]),{isDarkMode:o?n:!1,isDarkOS:o?t:!1,toggleDarkMode:_react.useCallback.call(void 0, ()=>r(p=>!p),[r]),enableDarkMode:_react.useCallback.call(void 0, ()=>r(!0),[r]),disableDarkMode:_react.useCallback.call(void 0, ()=>r(!1),[r])}};function ct(e,o){let{target:t,query:s,options:i,listener:a,onLoad:r,onCleanUp:n}=o;_react.useEffect.call(void 0, ()=>{let u=Array.isArray(e)?e:[e],l=_nullishCoalesce((s?window.matchMedia(s):t&&"current"in t?t.current:t), () => (window));if(l.addEventListener)return _optionalChain([r, 'optionalCall', _4 => _4()]),u.map(c=>{l.addEventListener(c,a,i)}),()=>{u.map(c=>{l.removeEventListener(c,a,i)}),_optionalChain([n, 'optionalCall', _5 => _5()])}},[e,t,s,i,a,r,n])}var _device = require('@alessiofrittoli/web-utils/device');var ft=()=>S(_device.portraitMediaQuery);var ue=["input","select","textarea","button","[href]",'[tabindex]:not([tabindex="-1"])'].join(", "),vt= exports.useFocusTrap =e=>{let[o,t]=_react.useState.call(void 0, !1),s=_react.useRef.call(void 0, null),i=_react.useCallback.call(void 0, r=>{s.current=document.activeElement;let n=r||_optionalChain([e, 'optionalAccess', _6 => _6.current])||!1;if(n)return t(n)},[e]),a=_react.useCallback.call(void 0, ()=>{_optionalChain([s, 'access', _7 => _7.current, 'optionalAccess', _8 => _8.focus, 'call', _9 => _9()]),t(!1)},[]);return _react.useEffect.call(void 0, ()=>{if(!o)return;let r=n=>{if(n.key!=="Tab")return;let u=Array.from(o.querySelectorAll(ue)),l=u.at(0),c=u.at(-1);if(!n.shiftKey){document.activeElement===c&&(n.preventDefault(),_optionalChain([l, 'optionalAccess', _10 => _10.focus, 'call', _11 => _11()]));return}document.activeElement===l&&(n.preventDefault(),_optionalChain([c, 'optionalAccess', _12 => _12.focus, 'call', _13 => _13()]))};return document.addEventListener("keydown",r),()=>{document.removeEventListener("keydown",r)}},[o]),[i,a]};var Ot=(e,o={})=>{let{initial:t=!1,once:s,amount:i,margin:a,root:r,enable:n=!0}=o,{onEnter:u,onExit:l,onIntersect:c}=o,p=_react.useRef.call(void 0, !0),[d,f]=_react.useState.call(void 0, t),[E,q]=_react.useState.call(void 0, n),b=_react.useRef.call(void 0, null),x=_react.useRef.call(void 0, !1),v=_react.useMemo.call(void 0, ()=>{if(!E||typeof IntersectionObserver>"u")return;let N=i==="all"?1:i==="some"?.5:i;try{return new IntersectionObserver(async([y],M)=>{if(!y)return;let T=y.isIntersecting;try{if(x.current=!T&&!!b.current,T&&u&&await u({entry:y,observer:M}),x.current&&l&&await l({entry:y,observer:M}),c&&(T||!T&&b.current!=null)){let L={isEntering:T,isExiting:x.current};await c({entry:y,observer:M,...L})}if(b.current=T,!p.current)return;f(T)}catch(L){console.error(L)}T&&s&&M.disconnect()},{root:r||void 0,rootMargin:a,threshold:N})}catch(y){console.error(y)}},[r,a,i,s,E,u,l,c]);return _react.useEffect.call(void 0, ()=>{if(p.current=!0,!(!E||!e.current||!v))return v.observe(e.current),()=>{p.current=!1,v.disconnect()}},[e,v,E]),{inView:d,enabled:E,observer:v,isExiting:x.current,setInView:f,setEnabled:q}};var _dom = require('@alessiofrittoli/web-utils/dom');var ht=e=>{let o=_react.useCallback.call(void 0, ()=>_dom.blockScroll.call(void 0, _optionalChain([e, 'optionalAccess', _14 => _14.current])||void 0),[e]),t=_react.useCallback.call(void 0, ()=>_dom.restoreScroll.call(void 0, _optionalChain([e, 'optionalAccess', _15 => _15.current])||void 0),[e]);return[o,t]};var j=(e,o={})=>{let{delay:t=1,args:s}=o;_react.useEffect.call(void 0, ()=>{let i=setTimeout(e,t,...s||[]);return()=>clearTimeout(i)},[t,s,e])};var Kt=(e,o=500)=>{let[t,s]=_react.useState.call(void 0, e),i=_react.useMemo.call(void 0, ()=>[e],[e]);return j(s,{delay:o,args:i}),t};function B(e,o={}){let{delay:t=1,args:s,autoplay:i=!0,runOnStart:a=!1,updateState:r=!1}=o,n=_react.useRef.call(void 0, void 0),[u,l]=_react.useState.call(void 0, i),c=_react.useCallback.call(void 0, ()=>n.current?(clearInterval(n.current),n.current=void 0,!0):!1,[]),p=_react.useCallback.call(void 0, ()=>{let f=c();return a&&(s?e(...s):e()),n.current=setInterval(e,t,...s||[]),!f&&r&&l(!0),n.current},[t,s,r,a,e,c]),d=_react.useCallback.call(void 0, ()=>{c()&&r&&l(!1)},[r,c]);return _react.useEffect.call(void 0, ()=>{if(i)return p(),d},[i,p,d]),r?{isActive:u,start:p,stop:d}:{start:p,stop:d}}var jt=(e,o={})=>{let{delay:t=1,args:s}=o;_react.useEffect.call(void 0, ()=>{let i=setInterval(e,t,...s||[]);return()=>clearInterval(i)},[t,s,e])};function zt(e,o={}){let{autoplay:t=!0}=o,s=B(e,{autoplay:!1,...o}),{start:i,stop:a}=s,r=_react.useCallback.call(void 0, ()=>document.hidden?a():i(),[i,a]),n=_react.useCallback.call(void 0, ()=>{if(document.addEventListener("visibilitychange",r),!document.hidden)return i()},[i,r]),u=_react.useCallback.call(void 0, ()=>{a(),document.removeEventListener("visibilitychange",r)},[a,r]);return _react.useEffect.call(void 0, ()=>{if(t)return n(),u},[t,n,u]),{...s,start:n,stop:u}}function Yt(e,o={}){let{delay:t=1,args:s,autoplay:i=!0,runOnStart:a=!1,updateState:r=!1}=o,n=_react.useRef.call(void 0, void 0),[u,l]=_react.useState.call(void 0, i),c=_react.useCallback.call(void 0, ()=>n.current?(clearTimeout(n.current),n.current=void 0,!0):!1,[]),p=_react.useCallback.call(void 0, ()=>{let f=c();return a&&(s?e(...s):e()),n.current=setTimeout(()=>{if(n.current=void 0,r&&l(!1),s)return e(...s);e()},t),!f&&r&&l(!0),n.current},[t,s,r,a,e,c]),d=_react.useCallback.call(void 0, ()=>{c()&&r&&l(!1)},[r,c]);return _react.useEffect.call(void 0, ()=>{if(i)return p(),d},[i,p,d]),r?{isActive:u,start:p,stop:d}:{start:p,stop:d}}exports.useDarkMode = st; exports.useDebounce = Kt; exports.useEffectOnce = $e; exports.useEventListener = ct; exports.useFocusTrap = vt; exports.useInView = Ot; exports.useInterval = B; exports.useIntervalWhenVisible = zt; exports.useIsClient = W; exports.useIsFirstRender = O; exports.useIsPortrait = ft; exports.useLightInterval = jt; exports.useLightTimeout = j; exports.useLocalStorage = K; exports.useMediaQuery = S; exports.useScrollBlock = ht; exports.useSessionStorage = we; exports.useStorage = g; exports.useTimeout = Yt; exports.useUpdateEffect = k;
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useCallback as w,useEffect as z,useState as G}from"react";import{LocalStorage as
|
|
1
|
+
import{useCallback as w,useEffect as z,useState as G}from"react";import{LocalStorage as V}from"@alessiofrittoli/web-utils/storage/LocalStorage";import{SessionStorage as K}from"@alessiofrittoli/web-utils/storage/SessionStorage";var O=(e,o,t="local")=>{let s=w(()=>(t==="local"?V:K).get(e)??o,[t,e,o]),[i,a]=G(o),r=w(n=>{a(u=>{let l=n instanceof Function?n(u):n;return(typeof window<"u"&&t==="local"?V:K).set(e,l),l})},[t,e]);return z(()=>{a(s())},[s]),[i,r]};var W=(e,o)=>O(e,o,"local");var Ve=(e,o)=>O(e,o,"session");import{useCallback as R,useEffect as Q,useRef as re}from"react";import{useEffect as X}from"react";import{useRef as J}from"react";var S=()=>{let e=J(!0);return e.current?(e.current=!1,!0):e.current};var je=e=>{let o=S();X(()=>{if(o)return e()},[])};import{useEffect as Y,useState as Z}from"react";var U=()=>{let[e,o]=Z(!1);return Y(()=>o(!0),[]),e};import{useEffect as _}from"react";var h=(e,o)=>{let t=S();_(()=>{if(!t)return e()},o)};import{useCallback as ee,useEffect as te,useState as ne}from"react";import{getMediaMatches as A}from"@alessiofrittoli/web-utils/browser-api";function b(e,o={}){let{updateState:t=!0,onChange:s}=o,[i,a]=ne(A(e)),r=ee(()=>{let n=A(e);t&&a(n),s?.(n)},[e,t,s]);if(te(()=>{let n=window.matchMedia(e),{matches:u}=n;return t&&a(u),s?.(u),n.addEventListener("change",r),()=>{n.removeEventListener("change",r)}},[e,t,s,r]),!!t)return i}var it=(e={})=>{let o=U(),t=b("(prefers-color-scheme: dark)"),{initial:s=t,docClassNames:i=[]}=e,[a,r]=W("dark-mode",s),n=a??t,[u,l]=i,c=re({light:"",dark:""});return h(()=>{r(t)},[t,r]),Q(()=>{u&&document.documentElement.classList.toggle(u,n),l&&document.documentElement.classList.toggle(l,!n)},[n,u,l]),Q(()=>{document.head.querySelectorAll('meta[name="theme-color"]').forEach(p=>{let f=p.getAttribute("media"),T=p.getAttribute("content");if(T){if(!f||f==="(prefers-color-scheme: light)"){c.current.light=T;return}c.current.dark=T}})},[]),h(()=>{let p=c.current.dark,f=c.current.light;a&&!p||!a&&!f||document.head.querySelectorAll('meta[name="theme-color"]').forEach(T=>{T.setAttribute("content",a?p:f)})},[a]),{isDarkMode:o?n:!1,isDarkOS:o?t:!1,toggleDarkMode:R(()=>r(p=>!p),[r]),enableDarkMode:R(()=>r(!0),[r]),disableDarkMode:R(()=>r(!1),[r])}};import{useEffect as oe}from"react";function lt(e,o){let{target:t,query:s,options:i,listener:a,onLoad:r,onCleanUp:n}=o;oe(()=>{let u=Array.isArray(e)?e:[e],l=(s?window.matchMedia(s):t&&"current"in t?t.current:t)??window;if(l.addEventListener)return r?.(),u.map(c=>{l.addEventListener(c,a,i)}),()=>{u.map(c=>{l.removeEventListener(c,a,i)}),n?.()}},[e,t,s,i,a,r,n])}import{portraitMediaQuery as se}from"@alessiofrittoli/web-utils/device";var Tt=()=>b(se);import{useCallback as F,useEffect as ie,useRef as ae,useState as ue}from"react";var ce=["input","select","textarea","button","[href]",'[tabindex]:not([tabindex="-1"])'].join(", "),xt=e=>{let[o,t]=ue(!1),s=ae(null),i=F(r=>{s.current=document.activeElement;let n=r||e?.current||!1;if(n)return t(n)},[e]),a=F(()=>{s.current?.focus(),t(!1)},[]);return ie(()=>{if(!o)return;let r=n=>{if(n.key!=="Tab")return;let u=Array.from(o.querySelectorAll(ce)),l=u.at(0),c=u.at(-1);if(!n.shiftKey){document.activeElement===c&&(n.preventDefault(),l?.focus());return}document.activeElement===l&&(n.preventDefault(),c?.focus())};return document.addEventListener("keydown",r),()=>{document.removeEventListener("keydown",r)}},[o]),[i,a]};import{useEffect as le,useMemo as pe,useRef as I,useState as $}from"react";var St=(e,o={})=>{let{initial:t=!1,once:s,amount:i,margin:a,root:r,enable:n=!0}=o,{onEnter:u,onExit:l,onIntersect:c}=o,p=I(!0),[f,T]=$(t),[v,N]=$(n),L=I(null),M=I(!1),x=pe(()=>{if(!v||typeof IntersectionObserver>"u")return;let P=i==="all"?1:i==="some"?.5:i;try{return new IntersectionObserver(async([E],g)=>{if(!E)return;let y=E.isIntersecting;try{if(M.current=!y&&!!L.current,y&&u&&await u({entry:E,observer:g}),M.current&&l&&await l({entry:E,observer:g}),c&&(y||!y&&L.current!=null)){let k={isEntering:y,isExiting:M.current};await c({entry:E,observer:g,...k})}if(L.current=y,!p.current)return;T(y)}catch(k){console.error(k)}y&&s&&g.disconnect()},{root:r||void 0,rootMargin:a,threshold:P})}catch(E){console.error(E)}},[r,a,i,s,v,u,l,c]);return le(()=>{if(p.current=!0,!(!v||!e.current||!x))return x.observe(e.current),()=>{p.current=!1,x.disconnect()}},[e,x,v]),{inView:f,enabled:v,observer:x,isExiting:M.current,setInView:T,setEnabled:N}};import{useCallback as j}from"react";import{blockScroll as me,restoreScroll as de}from"@alessiofrittoli/web-utils/dom";var Rt=e=>{let o=j(()=>me(e?.current||void 0),[e]),t=j(()=>de(e?.current||void 0),[e]);return[o,t]};import{useMemo as Te,useState as ye}from"react";import{useEffect as fe}from"react";var B=(e,o={})=>{let{delay:t=1,args:s}=o;fe(()=>{let i=setTimeout(e,t,...s||[]);return()=>clearTimeout(i)},[t,s,e])};var Wt=(e,o=500)=>{let[t,s]=ye(e),i=Te(()=>[e],[e]);return B(s,{delay:o,args:i}),t};import{useCallback as H,useEffect as Ee,useRef as ve,useState as xe}from"react";function q(e,o={}){let{delay:t=1,args:s,autoplay:i=!0,runOnStart:a=!1,updateState:r=!1}=o,n=ve(void 0),[u,l]=xe(i),c=H(()=>n.current?(clearInterval(n.current),n.current=void 0,!0):!1,[]),p=H(()=>{let T=c();return a&&(s?e(...s):e()),n.current=setInterval(e,t,...s||[]),!T&&r&&l(!0),n.current},[t,s,r,a,e,c]),f=H(()=>{c()&&r&&l(!1)},[r,c]);return Ee(()=>{if(i)return p(),f},[i,p,f]),r?{isActive:u,start:p,stop:f}:{start:p,stop:f}}import{useEffect as Me}from"react";var Bt=(e,o={})=>{let{delay:t=1,args:s}=o;Me(()=>{let i=setInterval(e,t,...s||[]);return()=>clearInterval(i)},[t,s,e])};import{useCallback as C,useEffect as ge}from"react";function Gt(e,o={}){let{autoplay:t=!0}=o,s=q(e,{autoplay:!1,...o}),{start:i,stop:a}=s,r=C(()=>document.hidden?a():i(),[i,a]),n=C(()=>{if(document.addEventListener("visibilitychange",r),!document.hidden)return i()},[i,r]),u=C(()=>{a(),document.removeEventListener("visibilitychange",r)},[a,r]);return ge(()=>{if(t)return n(),u},[t,n,u]),{...s,start:n,stop:u}}import{useCallback as D,useEffect as Oe,useRef as Se,useState as be}from"react";function Zt(e,o={}){let{delay:t=1,args:s,autoplay:i=!0,runOnStart:a=!1,updateState:r=!1}=o,n=Se(void 0),[u,l]=be(i),c=D(()=>n.current?(clearTimeout(n.current),n.current=void 0,!0):!1,[]),p=D(()=>{let T=c();return a&&(s?e(...s):e()),n.current=setTimeout(()=>{if(n.current=void 0,r&&l(!1),s)return e(...s);e()},t),!T&&r&&l(!0),n.current},[t,s,r,a,e,c]),f=D(()=>{c()&&r&&l(!1)},[r,c]);return Oe(()=>{if(i)return p(),f},[i,p,f]),r?{isActive:u,start:p,stop:f}:{start:p,stop:f}}export{it as useDarkMode,Wt as useDebounce,je as useEffectOnce,lt as useEventListener,xt as useFocusTrap,St as useInView,q as useInterval,Gt as useIntervalWhenVisible,U as useIsClient,S as useIsFirstRender,Tt as useIsPortrait,Bt as useLightInterval,B as useLightTimeout,W as useLocalStorage,b as useMediaQuery,Rt as useScrollBlock,Ve as useSessionStorage,O as useStorage,Zt as useTimeout,h as useUpdateEffect};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alessiofrittoli/react-hooks",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.2.0-alpha.1",
|
|
4
4
|
"description": "TypeScript React utility Hooks",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Alessio Frittoli",
|
|
@@ -87,48 +87,42 @@
|
|
|
87
87
|
"test:misc": "pnpm test:watch misc/*",
|
|
88
88
|
"test:timers": "pnpm test:watch timers/*"
|
|
89
89
|
},
|
|
90
|
-
"pnpm": {
|
|
91
|
-
"onlyBuiltDependencies": [
|
|
92
|
-
"@alessiofrittoli/type-utils",
|
|
93
|
-
"esbuild"
|
|
94
|
-
]
|
|
95
|
-
},
|
|
96
90
|
"devDependencies": {
|
|
97
|
-
"@alessiofrittoli/event-emitter": "^1.
|
|
98
|
-
"@alessiofrittoli/node-scripts": "^2.
|
|
99
|
-
"@eslint/compat": "^1.
|
|
91
|
+
"@alessiofrittoli/event-emitter": "^1.5.0",
|
|
92
|
+
"@alessiofrittoli/node-scripts": "^2.6.0",
|
|
93
|
+
"@eslint/compat": "^1.3.1",
|
|
100
94
|
"@eslint/eslintrc": "^3.3.1",
|
|
101
|
-
"@eslint/js": "^9.
|
|
102
|
-
"@jest/globals": "^
|
|
95
|
+
"@eslint/js": "^9.30.1",
|
|
96
|
+
"@jest/globals": "^30.0.4",
|
|
103
97
|
"@testing-library/dom": "^10.4.0",
|
|
104
98
|
"@testing-library/jest-dom": "^6.6.3",
|
|
105
99
|
"@testing-library/react": "^16.3.0",
|
|
106
100
|
"@testing-library/user-event": "^14.6.1",
|
|
107
|
-
"@types/jest": "^
|
|
108
|
-
"@types/node": "^
|
|
109
|
-
"@types/react": "^19.1.
|
|
110
|
-
"@types/react-dom": "^19.1.
|
|
111
|
-
"concurrently": "^9.
|
|
112
|
-
"dotenv": "^
|
|
113
|
-
"eslint": "^9.
|
|
101
|
+
"@types/jest": "^30.0.0",
|
|
102
|
+
"@types/node": "^24.0.10",
|
|
103
|
+
"@types/react": "^19.1.8",
|
|
104
|
+
"@types/react-dom": "^19.1.6",
|
|
105
|
+
"concurrently": "^9.2.0",
|
|
106
|
+
"dotenv": "^17.1.0",
|
|
107
|
+
"eslint": "^9.30.1",
|
|
114
108
|
"eslint-plugin-react": "^7.37.5",
|
|
115
109
|
"eslint-plugin-react-hooks": "^5.2.0",
|
|
116
|
-
"globals": "^16.
|
|
110
|
+
"globals": "^16.3.0",
|
|
117
111
|
"http-server": "^14.1.1",
|
|
118
|
-
"jest": "^
|
|
119
|
-
"jest-environment-jsdom": "^
|
|
112
|
+
"jest": "^30.0.4",
|
|
113
|
+
"jest-environment-jsdom": "^30.0.4",
|
|
120
114
|
"react": "^19.1.0",
|
|
121
115
|
"react-dom": "^19.1.0",
|
|
122
|
-
"ts-jest": "^29.
|
|
116
|
+
"ts-jest": "^29.4.0",
|
|
123
117
|
"ts-node": "^10.9.2",
|
|
124
|
-
"tsup": "^8.
|
|
118
|
+
"tsup": "^8.5.0",
|
|
125
119
|
"typescript": "^5.8.3",
|
|
126
|
-
"typescript-eslint": "^8.
|
|
120
|
+
"typescript-eslint": "^8.36.0"
|
|
127
121
|
},
|
|
128
122
|
"dependencies": {
|
|
129
|
-
"@alessiofrittoli/math-utils": "^1.
|
|
123
|
+
"@alessiofrittoli/math-utils": "^1.14.0",
|
|
130
124
|
"@alessiofrittoli/type-utils": "^1.8.0",
|
|
131
|
-
"@alessiofrittoli/web-utils": "^1.
|
|
125
|
+
"@alessiofrittoli/web-utils": "^1.12.0"
|
|
132
126
|
},
|
|
133
127
|
"peerDependencies": {
|
|
134
128
|
"@types/react": "^19",
|