@alessiofrittoli/react-hooks 3.1.0 → 3.2.0-alpha.2

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/index.d.mts CHANGED
@@ -766,6 +766,140 @@ declare const useIsFirstRender: () => boolean;
766
766
  */
767
767
  declare const useUpdateEffect: (effect: React.EffectCallback, deps?: React.DependencyList) => void;
768
768
 
769
+ type InputType = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | null;
770
+ interface InputState<I = unknown, O = I> {
771
+ /**
772
+ * The input value.
773
+ *
774
+ */
775
+ value?: O;
776
+ /**
777
+ * Indicates whether the input has been focused and valued.
778
+ *
779
+ */
780
+ isTouched: boolean;
781
+ /**
782
+ * Indicates whether the Input is valid or not based on the given validation callback. Default `true` if no callback is given.
783
+ *
784
+ */
785
+ isValid: boolean;
786
+ }
787
+ /**
788
+ * Input change handler.
789
+ *
790
+ * @param value The new value.
791
+ */
792
+ type ChangeHandler<O = unknown> = (value?: O) => void;
793
+ /**
794
+ * Validate value.
795
+ *
796
+ * @param value The value to validate. If `parse` callback is given, the `value` will be parsed before validation.
797
+ * @returns `true` if the `value` has a valid state, `false` otherwise.
798
+ */
799
+ type ValidateValueHandler<O = unknown> = (value?: O) => boolean;
800
+ /**
801
+ * Parse value.
802
+ *
803
+ * @param value The value to parse.
804
+ * @returns The parsed `value`.
805
+ */
806
+ type ParseValueHandler<I = unknown, O = I> = (value: I) => O | undefined;
807
+
808
+ /**
809
+ * useInput options.
810
+ *
811
+ * @template I The input value type.
812
+ * @template O The output parsed value type.
813
+ */
814
+ interface UseInputOptions<I = unknown, O = I> {
815
+ /**
816
+ * The React HTML input element ref.
817
+ *
818
+ * This is required to properly execute the {@link UseInputOutput.focus}.
819
+ */
820
+ inputRef?: React.RefObject<InputType>;
821
+ /**
822
+ * The input initial value.
823
+ *
824
+ */
825
+ initialValue?: O | null;
826
+ /**
827
+ * A timeout in milliseconds which will be used to define the input as "touched" thus validations are triggered and errors can be displayed.
828
+ *
829
+ * @default 600
830
+ */
831
+ touchTimeout?: number;
832
+ /**
833
+ * Validate value.
834
+ *
835
+ * @param value The value to validate. If `parse` callback is given, the `value` will be parsed before validation.
836
+ * @returns `true` if the `value` has a valid state, `false` otherwise.
837
+ */
838
+ validate?: ValidateValueHandler<O>;
839
+ /**
840
+ * Parse value.
841
+ *
842
+ * @param value The value to parse.
843
+ * @returns The parsed `value`.
844
+ */
845
+ parse?: ParseValueHandler<I, O>;
846
+ /**
847
+ * A callable function executed when the `ChangeEvent` is dispatched on the HTML input element.
848
+ * @param value The input value.
849
+ */
850
+ onChange?: ChangeHandler<O>;
851
+ }
852
+ interface UseInputOutput<I = unknown, O = I> extends InputState<I, O> {
853
+ /**
854
+ * Indicates whether the Input is empty or not.
855
+ *
856
+ */
857
+ isEmpty: boolean;
858
+ /**
859
+ * Indicates whether the input has error or not.
860
+ * It will return true if the Input does not pass the validation checks and it has been touched.
861
+ * Please refer to the `isValid` property to check the Input validity regardless of whether it has been touched or not.
862
+ */
863
+ hasError: boolean;
864
+ /**
865
+ * Change handler callback used to handle Input change events.
866
+ *
867
+ */
868
+ changeHandler: React.ChangeEventHandler<InputType>;
869
+ /**
870
+ * Blur handler callback used to handle Input blur events.
871
+ *
872
+ */
873
+ blurHandler: () => void;
874
+ /**
875
+ * Call `setValue` method to update input value.
876
+ *
877
+ */
878
+ setValue: (value: O) => void;
879
+ /**
880
+ * Call `submit` method to re-run validations and ensure error state is updated successfully.
881
+ *
882
+ */
883
+ submit: () => void;
884
+ /**
885
+ * Call `reset` method to reset the Input state.
886
+ *
887
+ */
888
+ reset: () => void;
889
+ /**
890
+ * Call `focus` method to focus the Input Element. A ref object must be provided.
891
+ *
892
+ */
893
+ focus: () => void;
894
+ }
895
+ /**
896
+ * Handle input states with ease.
897
+ *
898
+ * @param options An object defining custom options. See {@link UseInputOptions} for more info.
899
+ * @returns An object containing Input state and utility functions. See {@link UseInputOutput} for more info.
900
+ */
901
+ declare const useInput: <I = unknown, O = I>(options?: UseInputOptions<I, O>) => UseInputOutput<I, O>;
902
+
769
903
  /**
770
904
  * The function called when the timer elapses.
771
905
  *
@@ -1054,4 +1188,4 @@ declare function useTimeout<T extends readonly unknown[]>(callback: TimerHandler
1054
1188
  */
1055
1189
  declare const useLightTimeout: <T extends readonly unknown[]>(callback: TimerHandler<T>, options?: BasicTimerOptions<T>) => void;
1056
1190
 
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 };
1191
+ export { type AddEventListenerOptions, type BasicTimerOptions, type ChangeHandler, type CommonListenerOptions, type CustomEventListenerOptions, type DocumentEventListener, type DocumentListenerOptions, type ElementEventListener, type ElementListenerOptions, type InputState, type InputType, type IntersectionState, type ListenerOptions, type MarginType, type MarginValue, type MediaQueryChangeListener, type MediaQueryEventListener, type MediaQueryListenerOptions, type OnChangeHandler, type OnIntersectHandler, type OnIntersectStateHandler, type ParseValueHandler, 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 UseInputOptions, type UseInputOutput, type UseIntervalWhenVisibleReturnType, type UseIntervalWhenVisibleStateReturnType, type UseMediaQueryOptions, type UseMediaQueryStateOptions, type ValidateValueHandler, type WindowEventListener, type WindowListenerOptions, useDarkMode, useDebounce, useEffectOnce, useEventListener, useFocusTrap, useInView, useInput, useInterval, useIntervalWhenVisible, useIsClient, useIsFirstRender, useIsPortrait, useLightInterval, useLightTimeout, useLocalStorage, useMediaQuery, useScrollBlock, useSessionStorage, useStorage, useTimeout, useUpdateEffect };
package/dist/index.d.ts CHANGED
@@ -766,6 +766,140 @@ declare const useIsFirstRender: () => boolean;
766
766
  */
767
767
  declare const useUpdateEffect: (effect: React.EffectCallback, deps?: React.DependencyList) => void;
768
768
 
769
+ type InputType = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | null;
770
+ interface InputState<I = unknown, O = I> {
771
+ /**
772
+ * The input value.
773
+ *
774
+ */
775
+ value?: O;
776
+ /**
777
+ * Indicates whether the input has been focused and valued.
778
+ *
779
+ */
780
+ isTouched: boolean;
781
+ /**
782
+ * Indicates whether the Input is valid or not based on the given validation callback. Default `true` if no callback is given.
783
+ *
784
+ */
785
+ isValid: boolean;
786
+ }
787
+ /**
788
+ * Input change handler.
789
+ *
790
+ * @param value The new value.
791
+ */
792
+ type ChangeHandler<O = unknown> = (value?: O) => void;
793
+ /**
794
+ * Validate value.
795
+ *
796
+ * @param value The value to validate. If `parse` callback is given, the `value` will be parsed before validation.
797
+ * @returns `true` if the `value` has a valid state, `false` otherwise.
798
+ */
799
+ type ValidateValueHandler<O = unknown> = (value?: O) => boolean;
800
+ /**
801
+ * Parse value.
802
+ *
803
+ * @param value The value to parse.
804
+ * @returns The parsed `value`.
805
+ */
806
+ type ParseValueHandler<I = unknown, O = I> = (value: I) => O | undefined;
807
+
808
+ /**
809
+ * useInput options.
810
+ *
811
+ * @template I The input value type.
812
+ * @template O The output parsed value type.
813
+ */
814
+ interface UseInputOptions<I = unknown, O = I> {
815
+ /**
816
+ * The React HTML input element ref.
817
+ *
818
+ * This is required to properly execute the {@link UseInputOutput.focus}.
819
+ */
820
+ inputRef?: React.RefObject<InputType>;
821
+ /**
822
+ * The input initial value.
823
+ *
824
+ */
825
+ initialValue?: O | null;
826
+ /**
827
+ * A timeout in milliseconds which will be used to define the input as "touched" thus validations are triggered and errors can be displayed.
828
+ *
829
+ * @default 600
830
+ */
831
+ touchTimeout?: number;
832
+ /**
833
+ * Validate value.
834
+ *
835
+ * @param value The value to validate. If `parse` callback is given, the `value` will be parsed before validation.
836
+ * @returns `true` if the `value` has a valid state, `false` otherwise.
837
+ */
838
+ validate?: ValidateValueHandler<O>;
839
+ /**
840
+ * Parse value.
841
+ *
842
+ * @param value The value to parse.
843
+ * @returns The parsed `value`.
844
+ */
845
+ parse?: ParseValueHandler<I, O>;
846
+ /**
847
+ * A callable function executed when the `ChangeEvent` is dispatched on the HTML input element.
848
+ * @param value The input value.
849
+ */
850
+ onChange?: ChangeHandler<O>;
851
+ }
852
+ interface UseInputOutput<I = unknown, O = I> extends InputState<I, O> {
853
+ /**
854
+ * Indicates whether the Input is empty or not.
855
+ *
856
+ */
857
+ isEmpty: boolean;
858
+ /**
859
+ * Indicates whether the input has error or not.
860
+ * It will return true if the Input does not pass the validation checks and it has been touched.
861
+ * Please refer to the `isValid` property to check the Input validity regardless of whether it has been touched or not.
862
+ */
863
+ hasError: boolean;
864
+ /**
865
+ * Change handler callback used to handle Input change events.
866
+ *
867
+ */
868
+ changeHandler: React.ChangeEventHandler<InputType>;
869
+ /**
870
+ * Blur handler callback used to handle Input blur events.
871
+ *
872
+ */
873
+ blurHandler: () => void;
874
+ /**
875
+ * Call `setValue` method to update input value.
876
+ *
877
+ */
878
+ setValue: (value: O) => void;
879
+ /**
880
+ * Call `submit` method to re-run validations and ensure error state is updated successfully.
881
+ *
882
+ */
883
+ submit: () => void;
884
+ /**
885
+ * Call `reset` method to reset the Input state.
886
+ *
887
+ */
888
+ reset: () => void;
889
+ /**
890
+ * Call `focus` method to focus the Input Element. A ref object must be provided.
891
+ *
892
+ */
893
+ focus: () => void;
894
+ }
895
+ /**
896
+ * Handle input states with ease.
897
+ *
898
+ * @param options An object defining custom options. See {@link UseInputOptions} for more info.
899
+ * @returns An object containing Input state and utility functions. See {@link UseInputOutput} for more info.
900
+ */
901
+ declare const useInput: <I = unknown, O = I>(options?: UseInputOptions<I, O>) => UseInputOutput<I, O>;
902
+
769
903
  /**
770
904
  * The function called when the timer elapses.
771
905
  *
@@ -1054,4 +1188,4 @@ declare function useTimeout<T extends readonly unknown[]>(callback: TimerHandler
1054
1188
  */
1055
1189
  declare const useLightTimeout: <T extends readonly unknown[]>(callback: TimerHandler<T>, options?: BasicTimerOptions<T>) => void;
1056
1190
 
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 };
1191
+ export { type AddEventListenerOptions, type BasicTimerOptions, type ChangeHandler, type CommonListenerOptions, type CustomEventListenerOptions, type DocumentEventListener, type DocumentListenerOptions, type ElementEventListener, type ElementListenerOptions, type InputState, type InputType, type IntersectionState, type ListenerOptions, type MarginType, type MarginValue, type MediaQueryChangeListener, type MediaQueryEventListener, type MediaQueryListenerOptions, type OnChangeHandler, type OnIntersectHandler, type OnIntersectStateHandler, type ParseValueHandler, 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 UseInputOptions, type UseInputOutput, type UseIntervalWhenVisibleReturnType, type UseIntervalWhenVisibleStateReturnType, type UseMediaQueryOptions, type UseMediaQueryStateOptions, type ValidateValueHandler, type WindowEventListener, type WindowListenerOptions, useDarkMode, useDebounce, useEffectOnce, useEventListener, useFocusTrap, useInView, useInput, 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,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;
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 I=(e,r,t="local")=>{let s=_react.useCallback.call(void 0, ()=>_nullishCoalesce((t==="local"?_LocalStorage.LocalStorage:_SessionStorage.SessionStorage).get(e), () => (r)),[t,e,r]),[i,a]=_react.useState.call(void 0, r),o=_react.useCallback.call(void 0, n=>{a(u=>{let c=n instanceof Function?n(u):n;return(typeof window<"u"&&t==="local"?_LocalStorage.LocalStorage:_SessionStorage.SessionStorage).set(e,c),c})},[t,e]);return _react.useEffect.call(void 0, ()=>{a(s())},[s]),[i,o]};var F=(e,r)=>I(e,r,"local");var Qe=(e,r)=>I(e,r,"session");var h=()=>{let e=_react.useRef.call(void 0, !0);return e.current?(e.current=!1,!0):e.current};var Ge=e=>{let r=h();_react.useEffect.call(void 0, ()=>{if(r)return e()},[])};var $=()=>{let[e,r]=_react.useState.call(void 0, !1);return _react.useEffect.call(void 0, ()=>r(!0),[]),e};var b=(e,r)=>{let t=h();_react.useEffect.call(void 0, ()=>{if(!t)return e()},r)};var _webutils = require('@alessiofrittoli/web-utils');var L=e=>typeof e=="string"?_webutils.isEmpty.call(void 0, e):!e,C={value:"",isTouched:!1,isValid:!0},j=(e,r)=>{switch(r.type){case"TOUCHED":return{...e,isTouched:!0};case"CHANGE":return{...e,value:r.value};case"BLUR":return{...e,value:e.value,isTouched:!L(_nullishCoalesce(e.value, () => ("")))};case"RESET":return C}};var ct=(e={})=>{let{inputRef:r}=e,{initialValue:t}=e,{touchTimeout:s=600}=e,{validate:i,parse:a}=e,{onChange:o}=e,[n,u]=_react.useReducer.call(void 0, j,{...C,value:t}),c=a?a(n.value):n.value,{isTouched:l}=n,p=L(c),m=typeof i=="function"?i(c):!0,f=!m&&l||!!t&&!m;b(()=>{let T=setTimeout(()=>{L(c)||u({type:"TOUCHED"})},s);return()=>clearTimeout(T)},[c,s]);let v=_react.useCallback.call(void 0, T=>{let{target:E}=T,{type:y}=E,O=y==="checkbox"?E.checked:E.value;u({type:"CHANGE",value:O}),_optionalChain([o, 'optionalCall', _2 => _2(a?a(O):O)])},[o,a]),k=_react.useCallback.call(void 0, ()=>{u({type:"BLUR"})},[]),S=_react.useCallback.call(void 0, ()=>{u({type:"TOUCHED"})},[]),M=_react.useCallback.call(void 0, T=>{u({type:"CHANGE",value:T})},[]),x=_react.useCallback.call(void 0, ()=>{_optionalChain([r, 'optionalAccess', _3 => _3.current, 'optionalAccess', _4 => _4.focus, 'call', _5 => _5()])},[r]),H=_react.useCallback.call(void 0, ()=>{u({type:"RESET"})},[]);return{value:c,isTouched:l,isValid:m,isEmpty:p,hasError:f,changeHandler:v,blurHandler:k,setValue:M,submit:S,focus:x,reset:H}};var _browserapi = require('@alessiofrittoli/web-utils/browser-api');function R(e,r={}){let{updateState:t=!0,onChange:s}=r,[i,a]=_react.useState.call(void 0, _browserapi.getMediaMatches.call(void 0, e)),o=_react.useCallback.call(void 0, ()=>{let n=_browserapi.getMediaMatches.call(void 0, e);t&&a(n),_optionalChain([s, 'optionalCall', _6 => _6(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', _7 => _7(u)]),n.addEventListener("change",o),()=>{n.removeEventListener("change",o)}},[e,t,s,o]),!!t)return i}var Ot=(e={})=>{let r=$(),t=R("(prefers-color-scheme: dark)"),{initial:s=t,docClassNames:i=[]}=e,[a,o]=F("dark-mode",s),n=_nullishCoalesce(a, () => (t)),[u,c]=i,l=_react.useRef.call(void 0, {light:"",dark:""});return b(()=>{o(t)},[t,o]),_react.useEffect.call(void 0, ()=>{u&&document.documentElement.classList.toggle(u,n),c&&document.documentElement.classList.toggle(c,!n)},[n,u,c]),_react.useEffect.call(void 0, ()=>{document.head.querySelectorAll('meta[name="theme-color"]').forEach(p=>{let m=p.getAttribute("media"),f=p.getAttribute("content");if(f){if(!m||m==="(prefers-color-scheme: light)"){l.current.light=f;return}l.current.dark=f}})},[]),b(()=>{let p=l.current.dark,m=l.current.light;a&&!p||!a&&!m||document.head.querySelectorAll('meta[name="theme-color"]').forEach(f=>{f.setAttribute("content",a?p:m)})},[a]),{isDarkMode:r?n:!1,isDarkOS:r?t:!1,toggleDarkMode:_react.useCallback.call(void 0, ()=>o(p=>!p),[o]),enableDarkMode:_react.useCallback.call(void 0, ()=>o(!0),[o]),disableDarkMode:_react.useCallback.call(void 0, ()=>o(!1),[o])}};function bt(e,r){let{target:t,query:s,options:i,listener:a,onLoad:o,onCleanUp:n}=r;_react.useEffect.call(void 0, ()=>{let u=Array.isArray(e)?e:[e],c=_nullishCoalesce((s?window.matchMedia(s):t&&"current"in t?t.current:t), () => (window));if(c.addEventListener)return _optionalChain([o, 'optionalCall', _8 => _8()]),u.map(l=>{c.addEventListener(l,a,i)}),()=>{u.map(l=>{c.removeEventListener(l,a,i)}),_optionalChain([n, 'optionalCall', _9 => _9()])}},[e,t,s,i,a,o,n])}var _device = require('@alessiofrittoli/web-utils/device');var kt=()=>R(_device.portraitMediaQuery);var fe=["input","select","textarea","button","[href]",'[tabindex]:not([tabindex="-1"])'].join(", "),wt= exports.useFocusTrap =e=>{let[r,t]=_react.useState.call(void 0, !1),s=_react.useRef.call(void 0, null),i=_react.useCallback.call(void 0, o=>{s.current=document.activeElement;let n=o||_optionalChain([e, 'optionalAccess', _10 => _10.current])||!1;if(n)return t(n)},[e]),a=_react.useCallback.call(void 0, ()=>{_optionalChain([s, 'access', _11 => _11.current, 'optionalAccess', _12 => _12.focus, 'call', _13 => _13()]),t(!1)},[]);return _react.useEffect.call(void 0, ()=>{if(!r)return;let o=n=>{if(n.key!=="Tab")return;let u=Array.from(r.querySelectorAll(fe)),c=u.at(0),l=u.at(-1);if(!n.shiftKey){document.activeElement===l&&(n.preventDefault(),_optionalChain([c, 'optionalAccess', _14 => _14.focus, 'call', _15 => _15()]));return}document.activeElement===c&&(n.preventDefault(),_optionalChain([l, 'optionalAccess', _16 => _16.focus, 'call', _17 => _17()]))};return document.addEventListener("keydown",o),()=>{document.removeEventListener("keydown",o)}},[r]),[i,a]};var At=(e,r={})=>{let{initial:t=!1,once:s,amount:i,margin:a,root:o,enable:n=!0}=r,{onEnter:u,onExit:c,onIntersect:l}=r,p=_react.useRef.call(void 0, !0),[m,f]=_react.useState.call(void 0, t),[v,k]=_react.useState.call(void 0, n),S=_react.useRef.call(void 0, null),M=_react.useRef.call(void 0, !1),x=_react.useMemo.call(void 0, ()=>{if(!v||typeof IntersectionObserver>"u")return;let H=i==="all"?1:i==="some"?.5:i;try{return new IntersectionObserver(async([T],E)=>{if(!T)return;let y=T.isIntersecting;try{if(M.current=!y&&!!S.current,y&&u&&await u({entry:T,observer:E}),M.current&&c&&await c({entry:T,observer:E}),l&&(y||!y&&S.current!=null)){let O={isEntering:y,isExiting:M.current};await l({entry:T,observer:E,...O})}if(S.current=y,!p.current)return;f(y)}catch(O){console.error(O)}y&&s&&E.disconnect()},{root:o||void 0,rootMargin:a,threshold:H})}catch(T){console.error(T)}},[o,a,i,s,v,u,c,l]);return _react.useEffect.call(void 0, ()=>{if(p.current=!0,!(!v||!e.current||!x))return x.observe(e.current),()=>{p.current=!1,x.disconnect()}},[e,x,v]),{inView:m,enabled:v,observer:x,isExiting:M.current,setInView:f,setEnabled:k}};var _dom = require('@alessiofrittoli/web-utils/dom');var jt=e=>{let r=_react.useCallback.call(void 0, ()=>_dom.blockScroll.call(void 0, _optionalChain([e, 'optionalAccess', _18 => _18.current])||void 0),[e]),t=_react.useCallback.call(void 0, ()=>_dom.restoreScroll.call(void 0, _optionalChain([e, 'optionalAccess', _19 => _19.current])||void 0),[e]);return[r,t]};var z=(e,r={})=>{let{delay:t=1,args:s}=r;_react.useEffect.call(void 0, ()=>{let i=setTimeout(e,t,...s||[]);return()=>clearTimeout(i)},[t,s,e])};var Xt=(e,r=500)=>{let[t,s]=_react.useState.call(void 0, e),i=_react.useMemo.call(void 0, ()=>[e],[e]);return z(s,{delay:r,args:i}),t};function J(e,r={}){let{delay:t=1,args:s,autoplay:i=!0,runOnStart:a=!1,updateState:o=!1}=r,n=_react.useRef.call(void 0, void 0),[u,c]=_react.useState.call(void 0, i),l=_react.useCallback.call(void 0, ()=>n.current?(clearInterval(n.current),n.current=void 0,!0):!1,[]),p=_react.useCallback.call(void 0, ()=>{let f=l();return a&&(s?e(...s):e()),n.current=setInterval(e,t,...s||[]),!f&&o&&c(!0),n.current},[t,s,o,a,e,l]),m=_react.useCallback.call(void 0, ()=>{l()&&o&&c(!1)},[o,l]);return _react.useEffect.call(void 0, ()=>{if(i)return p(),m},[i,p,m]),o?{isActive:u,start:p,stop:m}:{start:p,stop:m}}var rn=(e,r={})=>{let{delay:t=1,args:s}=r;_react.useEffect.call(void 0, ()=>{let i=setInterval(e,t,...s||[]);return()=>clearInterval(i)},[t,s,e])};function cn(e,r={}){let{autoplay:t=!0}=r,s=J(e,{autoplay:!1,...r}),{start:i,stop:a}=s,o=_react.useCallback.call(void 0, ()=>document.hidden?a():i(),[i,a]),n=_react.useCallback.call(void 0, ()=>{if(document.addEventListener("visibilitychange",o),!document.hidden)return i()},[i,o]),u=_react.useCallback.call(void 0, ()=>{a(),document.removeEventListener("visibilitychange",o)},[a,o]);return _react.useEffect.call(void 0, ()=>{if(t)return n(),u},[t,n,u]),{...s,start:n,stop:u}}function mn(e,r={}){let{delay:t=1,args:s,autoplay:i=!0,runOnStart:a=!1,updateState:o=!1}=r,n=_react.useRef.call(void 0, void 0),[u,c]=_react.useState.call(void 0, i),l=_react.useCallback.call(void 0, ()=>n.current?(clearTimeout(n.current),n.current=void 0,!0):!1,[]),p=_react.useCallback.call(void 0, ()=>{let f=l();return a&&(s?e(...s):e()),n.current=setTimeout(()=>{if(n.current=void 0,o&&c(!1),s)return e(...s);e()},t),!f&&o&&c(!0),n.current},[t,s,o,a,e,l]),m=_react.useCallback.call(void 0, ()=>{l()&&o&&c(!1)},[o,l]);return _react.useEffect.call(void 0, ()=>{if(i)return p(),m},[i,p,m]),o?{isActive:u,start:p,stop:m}:{start:p,stop:m}}exports.useDarkMode = Ot; exports.useDebounce = Xt; exports.useEffectOnce = Ge; exports.useEventListener = bt; exports.useFocusTrap = wt; exports.useInView = At; exports.useInput = ct; exports.useInterval = J; exports.useIntervalWhenVisible = cn; exports.useIsClient = $; exports.useIsFirstRender = h; exports.useIsPortrait = kt; exports.useLightInterval = rn; exports.useLightTimeout = z; exports.useLocalStorage = F; exports.useMediaQuery = R; exports.useScrollBlock = jt; exports.useSessionStorage = Qe; exports.useStorage = I; exports.useTimeout = mn; exports.useUpdateEffect = b;
package/dist/index.mjs CHANGED
@@ -1 +1 @@
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};
1
+ import{useCallback as W,useEffect as Y,useState as Z}from"react";import{LocalStorage as Q}from"@alessiofrittoli/web-utils/storage/LocalStorage";import{SessionStorage as F}from"@alessiofrittoli/web-utils/storage/SessionStorage";var h=(e,r,t="local")=>{let s=W(()=>(t==="local"?Q:F).get(e)??r,[t,e,r]),[i,a]=Z(r),o=W(n=>{a(u=>{let c=n instanceof Function?n(u):n;return(typeof window<"u"&&t==="local"?Q:F).set(e,c),c})},[t,e]);return Y(()=>{a(s())},[s]),[i,o]};var $=(e,r)=>h(e,r,"local");var Fe=(e,r)=>h(e,r,"session");import{useCallback as w,useEffect as P,useRef as ce}from"react";import{useEffect as ee}from"react";import{useRef as _}from"react";var L=()=>{let e=_(!0);return e.current?(e.current=!1,!0):e.current};var ze=e=>{let r=L();ee(()=>{if(r)return e()},[])};import{useEffect as te,useState as ne}from"react";var j=()=>{let[e,r]=ne(!1);return te(()=>r(!0),[]),e};import{useEffect as re}from"react";var I=(e,r)=>{let t=L();re(()=>{if(!t)return e()},r)};import{useCallback as S,useReducer as se}from"react";import{isEmpty as oe}from"@alessiofrittoli/web-utils";var R=e=>typeof e=="string"?oe(e):!e,V={value:"",isTouched:!1,isValid:!0},B=(e,r)=>{switch(r.type){case"TOUCHED":return{...e,isTouched:!0};case"CHANGE":return{...e,value:r.value};case"BLUR":return{...e,value:e.value,isTouched:!R(e.value??"")};case"RESET":return V}};var lt=(e={})=>{let{inputRef:r}=e,{initialValue:t}=e,{touchTimeout:s=600}=e,{validate:i,parse:a}=e,{onChange:o}=e,[n,u]=se(B,{...V,value:t}),c=a?a(n.value):n.value,{isTouched:l}=n,p=R(c),f=typeof i=="function"?i(c):!0,T=!f&&l||!!t&&!f;I(()=>{let y=setTimeout(()=>{R(c)||u({type:"TOUCHED"})},s);return()=>clearTimeout(y)},[c,s]);let x=S(y=>{let{target:v}=y,{type:E}=v,M=E==="checkbox"?v.checked:v.value;u({type:"CHANGE",value:M}),o?.(a?a(M):M)},[o,a]),H=S(()=>{u({type:"BLUR"})},[]),b=S(()=>{u({type:"TOUCHED"})},[]),g=S(y=>{u({type:"CHANGE",value:y})},[]),O=S(()=>{r?.current?.focus()},[r]),C=S(()=>{u({type:"RESET"})},[]);return{value:c,isTouched:l,isValid:f,isEmpty:p,hasError:T,changeHandler:x,blurHandler:H,setValue:g,submit:b,focus:O,reset:C}};import{useCallback as ie,useEffect as ae,useState as ue}from"react";import{getMediaMatches as N}from"@alessiofrittoli/web-utils/browser-api";function k(e,r={}){let{updateState:t=!0,onChange:s}=r,[i,a]=ue(N(e)),o=ie(()=>{let n=N(e);t&&a(n),s?.(n)},[e,t,s]);if(ae(()=>{let n=window.matchMedia(e),{matches:u}=n;return t&&a(u),s?.(u),n.addEventListener("change",o),()=>{n.removeEventListener("change",o)}},[e,t,s,o]),!!t)return i}var Mt=(e={})=>{let r=j(),t=k("(prefers-color-scheme: dark)"),{initial:s=t,docClassNames:i=[]}=e,[a,o]=$("dark-mode",s),n=a??t,[u,c]=i,l=ce({light:"",dark:""});return I(()=>{o(t)},[t,o]),P(()=>{u&&document.documentElement.classList.toggle(u,n),c&&document.documentElement.classList.toggle(c,!n)},[n,u,c]),P(()=>{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)"){l.current.light=T;return}l.current.dark=T}})},[]),I(()=>{let p=l.current.dark,f=l.current.light;a&&!p||!a&&!f||document.head.querySelectorAll('meta[name="theme-color"]').forEach(T=>{T.setAttribute("content",a?p:f)})},[a]),{isDarkMode:r?n:!1,isDarkOS:r?t:!1,toggleDarkMode:w(()=>o(p=>!p),[o]),enableDarkMode:w(()=>o(!0),[o]),disableDarkMode:w(()=>o(!1),[o])}};import{useEffect as le}from"react";function It(e,r){let{target:t,query:s,options:i,listener:a,onLoad:o,onCleanUp:n}=r;le(()=>{let u=Array.isArray(e)?e:[e],c=(s?window.matchMedia(s):t&&"current"in t?t.current:t)??window;if(c.addEventListener)return o?.(),u.map(l=>{c.addEventListener(l,a,i)}),()=>{u.map(l=>{c.removeEventListener(l,a,i)}),n?.()}},[e,t,s,i,a,o,n])}import{portraitMediaQuery as pe}from"@alessiofrittoli/web-utils/device";var Ht=()=>k(pe);import{useCallback as q,useEffect as de,useRef as me,useState as fe}from"react";var Te=["input","select","textarea","button","[href]",'[tabindex]:not([tabindex="-1"])'].join(", "),Dt=e=>{let[r,t]=fe(!1),s=me(null),i=q(o=>{s.current=document.activeElement;let n=o||e?.current||!1;if(n)return t(n)},[e]),a=q(()=>{s.current?.focus(),t(!1)},[]);return de(()=>{if(!r)return;let o=n=>{if(n.key!=="Tab")return;let u=Array.from(r.querySelectorAll(Te)),c=u.at(0),l=u.at(-1);if(!n.shiftKey){document.activeElement===l&&(n.preventDefault(),c?.focus());return}document.activeElement===c&&(n.preventDefault(),l?.focus())};return document.addEventListener("keydown",o),()=>{document.removeEventListener("keydown",o)}},[r]),[i,a]};import{useEffect as ye,useMemo as Ee,useRef as D,useState as G}from"react";var Wt=(e,r={})=>{let{initial:t=!1,once:s,amount:i,margin:a,root:o,enable:n=!0}=r,{onEnter:u,onExit:c,onIntersect:l}=r,p=D(!0),[f,T]=G(t),[x,H]=G(n),b=D(null),g=D(!1),O=Ee(()=>{if(!x||typeof IntersectionObserver>"u")return;let C=i==="all"?1:i==="some"?.5:i;try{return new IntersectionObserver(async([y],v)=>{if(!y)return;let E=y.isIntersecting;try{if(g.current=!E&&!!b.current,E&&u&&await u({entry:y,observer:v}),g.current&&c&&await c({entry:y,observer:v}),l&&(E||!E&&b.current!=null)){let M={isEntering:E,isExiting:g.current};await l({entry:y,observer:v,...M})}if(b.current=E,!p.current)return;T(E)}catch(M){console.error(M)}E&&s&&v.disconnect()},{root:o||void 0,rootMargin:a,threshold:C})}catch(y){console.error(y)}},[o,a,i,s,x,u,c,l]);return ye(()=>{if(p.current=!0,!(!x||!e.current||!O))return O.observe(e.current),()=>{p.current=!1,O.disconnect()}},[e,O,x]),{inView:f,enabled:x,observer:O,isExiting:g.current,setInView:T,setEnabled:H}};import{useCallback as z}from"react";import{blockScroll as ve,restoreScroll as xe}from"@alessiofrittoli/web-utils/dom";var Bt=e=>{let r=z(()=>ve(e?.current||void 0),[e]),t=z(()=>xe(e?.current||void 0),[e]);return[r,t]};import{useMemo as Me,useState as ge}from"react";import{useEffect as Oe}from"react";var J=(e,r={})=>{let{delay:t=1,args:s}=r;Oe(()=>{let i=setTimeout(e,t,...s||[]);return()=>clearTimeout(i)},[t,s,e])};var Yt=(e,r=500)=>{let[t,s]=ge(e),i=Me(()=>[e],[e]);return J(s,{delay:r,args:i}),t};import{useCallback as K,useEffect as Se,useRef as be,useState as Ie}from"react";function X(e,r={}){let{delay:t=1,args:s,autoplay:i=!0,runOnStart:a=!1,updateState:o=!1}=r,n=be(void 0),[u,c]=Ie(i),l=K(()=>n.current?(clearInterval(n.current),n.current=void 0,!0):!1,[]),p=K(()=>{let T=l();return a&&(s?e(...s):e()),n.current=setInterval(e,t,...s||[]),!T&&o&&c(!0),n.current},[t,s,o,a,e,l]),f=K(()=>{l()&&o&&c(!1)},[o,l]);return Se(()=>{if(i)return p(),f},[i,p,f]),o?{isActive:u,start:p,stop:f}:{start:p,stop:f}}import{useEffect as he}from"react";var on=(e,r={})=>{let{delay:t=1,args:s}=r;he(()=>{let i=setInterval(e,t,...s||[]);return()=>clearInterval(i)},[t,s,e])};import{useCallback as U,useEffect as Le}from"react";function ln(e,r={}){let{autoplay:t=!0}=r,s=X(e,{autoplay:!1,...r}),{start:i,stop:a}=s,o=U(()=>document.hidden?a():i(),[i,a]),n=U(()=>{if(document.addEventListener("visibilitychange",o),!document.hidden)return i()},[i,o]),u=U(()=>{a(),document.removeEventListener("visibilitychange",o)},[a,o]);return Le(()=>{if(t)return n(),u},[t,n,u]),{...s,start:n,stop:u}}import{useCallback as A,useEffect as Re,useRef as ke,useState as He}from"react";function fn(e,r={}){let{delay:t=1,args:s,autoplay:i=!0,runOnStart:a=!1,updateState:o=!1}=r,n=ke(void 0),[u,c]=He(i),l=A(()=>n.current?(clearTimeout(n.current),n.current=void 0,!0):!1,[]),p=A(()=>{let T=l();return a&&(s?e(...s):e()),n.current=setTimeout(()=>{if(n.current=void 0,o&&c(!1),s)return e(...s);e()},t),!T&&o&&c(!0),n.current},[t,s,o,a,e,l]),f=A(()=>{l()&&o&&c(!1)},[o,l]);return Re(()=>{if(i)return p(),f},[i,p,f]),o?{isActive:u,start:p,stop:f}:{start:p,stop:f}}export{Mt as useDarkMode,Yt as useDebounce,ze as useEffectOnce,It as useEventListener,Dt as useFocusTrap,Wt as useInView,lt as useInput,X as useInterval,ln as useIntervalWhenVisible,j as useIsClient,L as useIsFirstRender,Ht as useIsPortrait,on as useLightInterval,J as useLightTimeout,$ as useLocalStorage,k as useMediaQuery,Bt as useScrollBlock,Fe as useSessionStorage,h as useStorage,fn as useTimeout,I as useUpdateEffect};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alessiofrittoli/react-hooks",
3
- "version": "3.1.0",
3
+ "version": "3.2.0-alpha.2",
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.4.0",
98
- "@alessiofrittoli/node-scripts": "^2.5.0",
99
- "@eslint/compat": "^1.2.9",
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.26.0",
102
- "@jest/globals": "^29.7.0",
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": "^29.5.14",
108
- "@types/node": "^22.15.18",
109
- "@types/react": "^19.1.4",
110
- "@types/react-dom": "^19.1.5",
111
- "concurrently": "^9.1.2",
112
- "dotenv": "^16.5.0",
113
- "eslint": "^9.26.0",
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.1.0",
110
+ "globals": "^16.3.0",
117
111
  "http-server": "^14.1.1",
118
- "jest": "^29.7.0",
119
- "jest-environment-jsdom": "^29.7.0",
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.3.3",
116
+ "ts-jest": "^29.4.0",
123
117
  "ts-node": "^10.9.2",
124
- "tsup": "^8.4.0",
118
+ "tsup": "^8.5.0",
125
119
  "typescript": "^5.8.3",
126
- "typescript-eslint": "^8.32.1"
120
+ "typescript-eslint": "^8.36.0"
127
121
  },
128
122
  "dependencies": {
129
- "@alessiofrittoli/math-utils": "^1.13.0",
123
+ "@alessiofrittoli/math-utils": "^1.14.0",
130
124
  "@alessiofrittoli/type-utils": "^1.8.0",
131
- "@alessiofrittoli/web-utils": "^1.10.0"
125
+ "@alessiofrittoli/web-utils": "^1.12.0"
132
126
  },
133
127
  "peerDependencies": {
134
128
  "@types/react": "^19",