@alessiofrittoli/react-hooks 3.4.0 → 3.6.0

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 CHANGED
@@ -13,7 +13,6 @@
13
13
  [downloads-badge]: https://img.shields.io/npm/dm/%40alessiofrittoli%2Freact-hooks.svg
14
14
  [deps-badge]: https://img.shields.io/librariesio/release/npm/%40alessiofrittoli%2Freact-hooks
15
15
  [deps-url]: https://libraries.io/npm/%40alessiofrittoli%2Freact-hooks
16
-
17
16
  [sponsor-badge]: https://img.shields.io/static/v1?label=Fund%20this%20package&message=%E2%9D%A4&logo=GitHub&color=%23DB61A2
18
17
  [sponsor-url]: https://github.com/sponsors/alessiofrittoli
19
18
 
@@ -33,7 +32,10 @@
33
32
  - [`useDarkMode`](#usedarkmode)
34
33
  - [`useEventListener`](#useeventlistener)
35
34
  - [`useIsPortrait`](#useisportrait)
35
+ - [`useIsTouchDevice`](#useistouchdevice)
36
36
  - [`useMediaQuery`](#usemediaquery)
37
+ - [`useDocumentVisibility`](#usedocumentvisibility)
38
+ - [`useWakeLock`](#usewakelock)
37
39
  - [DOM API](#dom-api)
38
40
  - [`useFocusTrap`](#usefocustrap)
39
41
  - [`useInView`](#useinview)
@@ -88,16 +90,15 @@ This library may define and exports hooks that requires additional ESLint config
88
90
  Simply imports recommended configuration from `@alessiofrittoli/react-hooks/eslint` and add them to your ESLint configuration like so:
89
91
 
90
92
  ```mjs
91
- import { config as AFReactHooksEslint } from '@alessiofrittoli/react-hooks/eslint'
93
+ import { config as AFReactHooksEslint } from "@alessiofrittoli/react-hooks/eslint";
92
94
 
93
95
  /** @type {import('eslint').Linter.Config[]} */
94
96
  const config = [
95
97
  ...AFReactHooksEslint.recommended,
96
98
  // ... other configurations
97
- ]
98
-
99
+ ];
99
100
 
100
- export default config
101
+ export default config;
101
102
  ```
102
103
 
103
104
  ---
@@ -106,8 +107,9 @@ export default config
106
107
 
107
108
  #### Updates in the latest release 🎉
108
109
 
109
- - Add `useDeferCallback`. See [API Reference](#usedefercallback) for more info.
110
- - Add missing API Referefence sections.
110
+ - Added `useDocumentVisibility`. See [API Reference](#usedocumentvisibility) for more info.
111
+ - Added `useWakeLock`. See [API Reference](#usewakelock) for more info.
112
+ - Added `useDeferCallback`. See [API Reference](#usedefercallback) for more info.
111
113
 
112
114
  ---
113
115
 
@@ -127,8 +129,8 @@ Easly handle Local or Session Storage State.
127
129
 
128
130
  <summary style="cursor:pointer">Type parameters</summary>
129
131
 
130
- | Parameter | Type | Default | Description |
131
- |-----------|------|---------|-------------|
132
+ | Parameter | Type | Default | Description |
133
+ | --------- | ----- | -------- | ----------------------------------------- |
132
134
  | `T` | `any` | `string` | A custom type applied to the stored item. |
133
135
 
134
136
  </details>
@@ -139,11 +141,11 @@ Easly handle Local or Session Storage State.
139
141
 
140
142
  <summary style="cursor:pointer">Parameters</summary>
141
143
 
142
- | Parameter | Type | Default | Description |
143
- |-----------|------|---------|-------------|
144
- | `key` | `string` | - | The storage item key. |
145
- | `initial` | `T` | - | The storage item initial value. |
146
- | `type` | `local\|session` | local | (Optional) The storage API to use. |
144
+ | Parameter | Type | Default | Description |
145
+ | --------- | ---------------- | ------- | ---------------------------------- |
146
+ | `key` | `string` | - | The storage item key. |
147
+ | `initial` | `T` | - | The storage item initial value. |
148
+ | `type` | `local\|session` | local | (Optional) The storage API to use. |
147
149
 
148
150
  </details>
149
151
 
@@ -169,8 +171,10 @@ A tuple with the stored item value or initial value and the setter function.
169
171
 
170
172
  ```tsx
171
173
  import {
172
- useStorage, useLocalStorage, useSessionStorage
173
- } from '@alessiofrittoli/react-hooks'
174
+ useStorage,
175
+ useLocalStorage,
176
+ useSessionStorage,
177
+ } from "@alessiofrittoli/react-hooks";
174
178
  ```
175
179
 
176
180
  ---
@@ -302,7 +306,6 @@ An object with the following properties:
302
306
 
303
307
  ---
304
308
 
305
-
306
309
  ##### `useDarkMode`
307
310
 
308
311
  Easily manage dark mode with full respect for user device preferences.
@@ -317,11 +320,11 @@ This hook is user-oriented and built to honor system-level color scheme settings
317
320
 
318
321
  <summary style="cursor:pointer">Parameters</summary>
319
322
 
320
- | Parameter | Type | Description |
321
- |-----------|------|-------------|
322
- | `options` | `UseDarkModeOptions` | (Optional) Configuration object for the hook. |
323
- | `options.initial` | `boolean` | (Optional) The fallback value to use if no preference is saved in `localStorage`. Defaults to `true` if the device prefers dark mode. |
324
- | `options.docClassNames` | `[dark: string, light: string]` | (Optional) Array of class names to toggle on the `<html>` element, e.g. `['dark', 'light']`. |
323
+ | Parameter | Type | Description |
324
+ | ----------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
325
+ | `options` | `UseDarkModeOptions` | (Optional) Configuration object for the hook. |
326
+ | `options.initial` | `boolean` | (Optional) The fallback value to use if no preference is saved in `localStorage`. Defaults to `true` if the device prefers dark mode. |
327
+ | `options.docClassNames` | `[dark: string, light: string]` | (Optional) Array of class names to toggle on the `<html>` element, e.g. `['dark', 'light']`. |
325
328
 
326
329
  </details>
327
330
 
@@ -352,17 +355,15 @@ An object containing utilities for managing dark mode:
352
355
  ###### Basic usage
353
356
 
354
357
  ```tsx
355
- 'use client'
358
+ "use client";
356
359
 
357
- import { useDarkMode } from '@alessiofrittoli/react-hooks'
360
+ import { useDarkMode } from "@alessiofrittoli/react-hooks";
358
361
 
359
362
  export const Component: React.FC = () => {
360
- const { isDarkMode } = useDarkMode()
363
+ const { isDarkMode } = useDarkMode();
361
364
 
362
- return (
363
- <div>{ isDarkMode ? 'Dark mode enabled' : 'Dark mode disabled' }</div>
364
- )
365
- }
365
+ return <div>{isDarkMode ? "Dark mode enabled" : "Dark mode disabled"}</div>;
366
+ };
366
367
  ```
367
368
 
368
369
  ---
@@ -371,19 +372,17 @@ export const Component: React.FC = () => {
371
372
 
372
373
  ```tsx
373
374
  // Component.tsx
374
- 'use client'
375
+ "use client";
375
376
 
376
- import { useDarkMode } from '@alessiofrittoli/react-hooks'
377
+ import { useDarkMode } from "@alessiofrittoli/react-hooks";
377
378
 
378
379
  export const Component: React.FC = () => {
379
- const { isDarkMode } = useDarkMode( {
380
- docClassNames: [ 'dark', 'light' ],
381
- } )
380
+ const { isDarkMode } = useDarkMode({
381
+ docClassNames: ["dark", "light"],
382
+ });
382
383
 
383
- return (
384
- <div>{ isDarkMode ? 'Dark mode enabled' : 'Dark mode disabled' }</div>
385
- )
386
- }
384
+ return <div>{isDarkMode ? "Dark mode enabled" : "Dark mode disabled"}</div>;
385
+ };
387
386
  ```
388
387
 
389
388
  ```css
@@ -396,15 +395,13 @@ export const Component: React.FC = () => {
396
395
  color-scheme: dark;
397
396
  }
398
397
 
399
- .light body
400
- {
401
- color : black;
398
+ .light body {
399
+ color: black;
402
400
  background: white;
403
401
  }
404
402
 
405
- .dark body
406
- {
407
- color : white;
403
+ .dark body {
404
+ color: white;
408
405
  background: black;
409
406
  }
410
407
  ```
@@ -414,19 +411,15 @@ export const Component: React.FC = () => {
414
411
  ###### Custom theme switcher
415
412
 
416
413
  ```tsx
417
- 'use client'
414
+ "use client";
418
415
 
419
- import { useDarkMode } from '@alessiofrittoli/react-hooks'
416
+ import { useDarkMode } from "@alessiofrittoli/react-hooks";
420
417
 
421
418
  export const ThemeSwitcher: React.FC = () => {
422
- const { isDarkMode, toggleDarkMode } = useDarkMode()
419
+ const { isDarkMode, toggleDarkMode } = useDarkMode();
423
420
 
424
- return (
425
- <button onClick={ toggleDarkMode }>
426
- { isDarkMode ? '🌙' : '☀️' }
427
- </button>
428
- )
429
- }
421
+ return <button onClick={toggleDarkMode}>{isDarkMode ? "🌙" : "☀️"}</button>;
422
+ };
430
423
  ```
431
424
 
432
425
  ---
@@ -436,10 +429,10 @@ export const ThemeSwitcher: React.FC = () => {
436
429
  Browsers automatically apply colorization using:
437
430
 
438
431
  ```html
439
- <meta name='theme-color' media='(prefers-color-scheme: dark)' />
432
+ <meta name="theme-color" media="(prefers-color-scheme: dark)" />
440
433
  ```
441
434
 
442
- This works based on the OS preference — *not your site theme*. That can cause mismatches if, for example, the system is in dark mode but the user disabled dark mode via a web toggle.
435
+ This works based on the OS preference — _not your site theme_. That can cause mismatches if, for example, the system is in dark mode but the user disabled dark mode via a web toggle.
443
436
 
444
437
  To ensure consistency, `useDarkMode` updates these meta tags dynamically based on the actual mode.
445
438
 
@@ -447,8 +440,16 @@ Just make sure to define both `light` and `dark` theme-color tags in your docume
447
440
 
448
441
  ```html
449
442
  <head>
450
- <meta name='theme-color' media='(prefers-color-scheme: light)' content='lime'>
451
- <meta name='theme-color' media='(prefers-color-scheme: dark)' content='aqua'>
443
+ <meta
444
+ name="theme-color"
445
+ media="(prefers-color-scheme: light)"
446
+ content="lime"
447
+ />
448
+ <meta
449
+ name="theme-color"
450
+ media="(prefers-color-scheme: dark)"
451
+ content="aqua"
452
+ />
452
453
  </head>
453
454
  ```
454
455
 
@@ -468,14 +469,14 @@ Attach a new Event listener to the `Window`, `Document`, `MediaQueryList` or an
468
469
 
469
470
  <summary style="cursor:pointer">Window events</summary>
470
471
 
471
- | Parameter | Type | Description |
472
- |-----------|----------|-------------|
473
- | `type` | `K\|K[]` | The `Window` event name or an array of event names. |
474
- | `options` | `WindowListenerOptions<K>` | An object defining init options. |
475
- | `options.listener` | `WindowEventListener<K>` | The Window Event listener. |
476
- | `options.onLoad` | `() => void` | A custom callback executed before event listener get attached. |
477
- | `options.onCleanUp` | `() => void` | A custom callback executed after event listener get removed. |
478
- | `options.options` | `ListenerOptions` | Specifies characteristics about the event listener. See [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options). |
472
+ | Parameter | Type | Description |
473
+ | ------------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
474
+ | `type` | `K\|K[]` | The `Window` event name or an array of event names. |
475
+ | `options` | `WindowListenerOptions<K>` | An object defining init options. |
476
+ | `options.listener` | `WindowEventListener<K>` | The Window Event listener. |
477
+ | `options.onLoad` | `() => void` | A custom callback executed before event listener get attached. |
478
+ | `options.onCleanUp` | `() => void` | A custom callback executed after event listener get removed. |
479
+ | `options.options` | `ListenerOptions` | Specifies characteristics about the event listener. See [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options). |
479
480
 
480
481
  </details>
481
482
 
@@ -485,15 +486,15 @@ Attach a new Event listener to the `Window`, `Document`, `MediaQueryList` or an
485
486
 
486
487
  <summary style="cursor:pointer">Document events</summary>
487
488
 
488
- | Parameter | Type | Description |
489
- |-----------|----------|-------------|
490
- | `type` | `K\|K[]` | The `Document` event name or an array of event names. |
491
- | `options` | `DocumentListenerOptions<K>` | An object defining init options. |
492
- | `options.target` | `Document\|null\|React.RefObject<Document\|null>` | The `Document` reference or a React RefObject of the `Document`. |
493
- | `options.listener` | `DocumentEventListener<K>` | The Document Event listener. |
494
- | `options.onLoad` | `() => void` | A custom callback executed before event listener get attached. |
495
- | `options.onCleanUp` | `() => void` | A custom callback executed after event listener get removed. |
496
- | `options.options` | `ListenerOptions` | Specifies characteristics about the event listener. See [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options). |
489
+ | Parameter | Type | Description |
490
+ | ------------------- | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
491
+ | `type` | `K\|K[]` | The `Document` event name or an array of event names. |
492
+ | `options` | `DocumentListenerOptions<K>` | An object defining init options. |
493
+ | `options.target` | `Document\|null\|React.RefObject<Document\|null>` | The `Document` reference or a React RefObject of the `Document`. |
494
+ | `options.listener` | `DocumentEventListener<K>` | The Document Event listener. |
495
+ | `options.onLoad` | `() => void` | A custom callback executed before event listener get attached. |
496
+ | `options.onCleanUp` | `() => void` | A custom callback executed after event listener get removed. |
497
+ | `options.options` | `ListenerOptions` | Specifies characteristics about the event listener. See [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options). |
497
498
 
498
499
  </details>
499
500
 
@@ -503,15 +504,15 @@ Attach a new Event listener to the `Window`, `Document`, `MediaQueryList` or an
503
504
 
504
505
  <summary style="cursor:pointer">HTMLElement events</summary>
505
506
 
506
- | Parameter | Type | Description |
507
- |-----------|----------|-------------|
508
- | `type` | `K\|K[]` | The `HTMLElement` event name or an array of event names. |
509
- | `options` | `ElementListenerOptions<K>` | An object defining init options. |
510
- | `options.target` | `T\|React.RefObject<T\| null>` | The React RefObject of the target where the listener get attached to. |
511
- | `options.listener` | `ElementEventListener<K>` | The HTMLElement Event listener. |
512
- | `options.onLoad` | `() => void` | A custom callback executed before event listener get attached. |
513
- | `options.onCleanUp` | `() => void` | A custom callback executed after event listener get removed. |
514
- | `options.options` | `ListenerOptions` | Specifies characteristics about the event listener. See [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options). |
507
+ | Parameter | Type | Description |
508
+ | ------------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
509
+ | `type` | `K\|K[]` | The `HTMLElement` event name or an array of event names. |
510
+ | `options` | `ElementListenerOptions<K>` | An object defining init options. |
511
+ | `options.target` | `T\|React.RefObject<T\| null>` | The React RefObject of the target where the listener get attached to. |
512
+ | `options.listener` | `ElementEventListener<K>` | The HTMLElement Event listener. |
513
+ | `options.onLoad` | `() => void` | A custom callback executed before event listener get attached. |
514
+ | `options.onCleanUp` | `() => void` | A custom callback executed after event listener get removed. |
515
+ | `options.options` | `ListenerOptions` | Specifies characteristics about the event listener. See [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options). |
515
516
 
516
517
  </details>
517
518
 
@@ -521,15 +522,15 @@ Attach a new Event listener to the `Window`, `Document`, `MediaQueryList` or an
521
522
 
522
523
  <summary style="cursor:pointer">MediaQuery events</summary>
523
524
 
524
- | Parameter | Type | Description |
525
- |-----------|----------|-------------|
526
- | `type` | `change` | The `MediaQueryList` event name. |
527
- | `options` | `MediaQueryListenerOptions` | An object defining init options. |
528
- | `options.query` | `string` | The Media Query string to check. |
529
- | `options.listener` | `MediaQueryChangeListener` | The MediaQueryList Event listener. |
530
- | `options.onLoad` | `() => void` | A custom callback executed before event listener get attached. |
531
- | `options.onCleanUp` | `() => void` | A custom callback executed after event listener get removed. |
532
- | `options.options` | `ListenerOptions` | Specifies characteristics about the event listener. See [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options). |
525
+ | Parameter | Type | Description |
526
+ | ------------------- | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
527
+ | `type` | `change` | The `MediaQueryList` event name. |
528
+ | `options` | `MediaQueryListenerOptions` | An object defining init options. |
529
+ | `options.query` | `string` | The Media Query string to check. |
530
+ | `options.listener` | `MediaQueryChangeListener` | The MediaQueryList Event listener. |
531
+ | `options.onLoad` | `() => void` | A custom callback executed before event listener get attached. |
532
+ | `options.onCleanUp` | `() => void` | A custom callback executed after event listener get removed. |
533
+ | `options.options` | `ListenerOptions` | Specifies characteristics about the event listener. See [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options). |
533
534
 
534
535
  </details>
535
536
 
@@ -539,15 +540,15 @@ Attach a new Event listener to the `Window`, `Document`, `MediaQueryList` or an
539
540
 
540
541
  <summary style="cursor:pointer">Custom events</summary>
541
542
 
542
- | Parameter | Type | Description |
543
- |-----------|----------|-------------|
544
- | `type` | `K\|K[]` | The custom event name or an array of event names. |
545
- | `options` | `CustomEventListenerOptions<T, K>` | An object defining init options. |
546
- | `options.target` | `Document\|HTMLElement\|null\|React.RefObject<Document\|HTMLElement\|null>` | (Optional) The target where the listener get attached to. If not set, the listener will get attached to the `Window` object. |
547
- | `options.listener` | `( event: T[ K ] ) => void` | The Event listener. |
548
- | `options.onLoad` | `() => void` | A custom callback executed before event listener get attached. |
549
- | `options.onCleanUp` | `() => void` | A custom callback executed after event listener get removed. |
550
- | `options.options` | `ListenerOptions` | Specifies characteristics about the event listener. See [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options). |
543
+ | Parameter | Type | Description |
544
+ | ------------------- | --------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
545
+ | `type` | `K\|K[]` | The custom event name or an array of event names. |
546
+ | `options` | `CustomEventListenerOptions<T, K>` | An object defining init options. |
547
+ | `options.target` | `Document\|HTMLElement\|null\|React.RefObject<Document\|HTMLElement\|null>` | (Optional) The target where the listener get attached to. If not set, the listener will get attached to the `Window` object. |
548
+ | `options.listener` | `( event: T[ K ] ) => void` | The Event listener. |
549
+ | `options.onLoad` | `() => void` | A custom callback executed before event listener get attached. |
550
+ | `options.onCleanUp` | `() => void` | A custom callback executed after event listener get removed. |
551
+ | `options.options` | `ListenerOptions` | Specifies characteristics about the event listener. See [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options). |
551
552
 
552
553
  </details>
553
554
 
@@ -730,9 +731,40 @@ Type: `boolean`
730
731
  ###### Check if user device is in landscape
731
732
 
732
733
  ```tsx
733
- import { useIsPortrait } from '@alessiofrittoli/react-hooks'
734
+ import { useIsPortrait } from "@alessiofrittoli/react-hooks";
735
+
736
+ const isLandscape = !useIsPortrait();
737
+ ```
738
+
739
+ </details>
740
+
741
+ ---
742
+
743
+ ##### `useIsTouchDevice`
744
+
745
+ Detects if the current device supports touch events.
746
+
747
+ <details>
748
+
749
+ <summary style="cursor:pointer">Returns</summary>
750
+
751
+ Type: `boolean`
752
+
753
+ - `true` if the device is touch device.
754
+ - `false` otherwise.
755
+
756
+ </details>
757
+
758
+ ---
759
+
760
+ <details>
761
+
762
+ <summary style="cursor:pointer">Usage</summary>
763
+
764
+ ```tsx
765
+ import { useIsTouchDevice } from "@alessiofrittoli/react-hooks";
734
766
 
735
- const isLandscape = ! useIsPortrait()
767
+ const isTouchDevice = useIsTouchDevice();
736
768
  ```
737
769
 
738
770
  </details>
@@ -747,13 +779,13 @@ Get Document Media matches and listen for changes.
747
779
 
748
780
  <summary style="cursor:pointer">Parameters</summary>
749
781
 
750
- | Parameter | Type | Default | Description |
751
- |-----------|----------|---------|-------------|
752
- | `query` | `string` | - | A string specifying the media query to parse into a `MediaQueryList`. |
753
- | `options` | `UseMediaQueryOptions\|UseMediaQueryStateOptions` | - | An object defining custom options. |
754
- | `options.updateState` | `boolean` | `true` | Indicates whether the hook will dispatch a React state update when the given `query` change event get dispatched. |
755
- | `options.onChange` | `OnChangeHandler` | - | A custom callback that will be invoked on initial page load and when the given `query` change event get dispatched. |
756
- | | | | This callback is required if `updateState` is set to `false`. |
782
+ | Parameter | Type | Default | Description |
783
+ | --------------------- | ------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------- |
784
+ | `query` | `string` | - | A string specifying the media query to parse into a `MediaQueryList`. |
785
+ | `options` | `UseMediaQueryOptions\|UseMediaQueryStateOptions` | - | An object defining custom options. |
786
+ | `options.updateState` | `boolean` | `true` | Indicates whether the hook will dispatch a React state update when the given `query` change event get dispatched. |
787
+ | `options.onChange` | `OnChangeHandler` | - | A custom callback that will be invoked on initial page load and when the given `query` change event get dispatched. |
788
+ | | | | This callback is required if `updateState` is set to `false`. |
757
789
 
758
790
  </details>
759
791
 
@@ -779,9 +811,9 @@ Type: `boolean|void`
779
811
  ###### Check if user device prefers dark color scheme
780
812
 
781
813
  ```tsx
782
- import { useMediaQuery } from '@alessiofrittoli/react-hooks'
814
+ import { useMediaQuery } from "@alessiofrittoli/react-hooks";
783
815
 
784
- const isDarkOS = useMediaQuery( '(prefers-color-scheme: dark)' )
816
+ const isDarkOS = useMediaQuery("(prefers-color-scheme: dark)");
785
817
  ```
786
818
 
787
819
  ---
@@ -789,14 +821,174 @@ const isDarkOS = useMediaQuery( '(prefers-color-scheme: dark)' )
789
821
  ###### Listen changes with no state updates
790
822
 
791
823
  ```tsx
792
- import { useMediaQuery } from '@alessiofrittoli/react-hooks'
824
+ import { useMediaQuery } from "@alessiofrittoli/react-hooks";
793
825
 
794
- useMediaQuery( '(prefers-color-scheme: dark)', {
826
+ useMediaQuery("(prefers-color-scheme: dark)", {
795
827
  updateState: false,
796
- onChange( matches ) {
797
- console.log( 'is dark OS?', matches )
798
- }
799
- } )
828
+ onChange(matches) {
829
+ console.log("is dark OS?", matches);
830
+ },
831
+ });
832
+ ```
833
+
834
+ </details>
835
+
836
+ ---
837
+
838
+ ##### `useDocumentVisibility`
839
+
840
+ Track the visibility state of the document (i.e., whether the page is visible or hidden).
841
+
842
+ <details>
843
+
844
+ <summary style="cursor:pointer">Parameters</summary>
845
+
846
+ | Parameter | Type | Default | Description |
847
+ | ---------------------------- | ------------------------------------------------------------------------- | ------- | --------------------------------------------------------------------- |
848
+ | `options` | `UseDocumentVisibilityOptions\|StateDisabledUseDocumentVisibilityOptions` | - | Configuration options for the hook. |
849
+ | `options.updateState` | `boolean` | `true` | Whether to update React state about Document visibility state or not. |
850
+ | `options.onVisibilityChange` | `VisibilityChangeHandler` | - | A custom callback executed when Document visiblity sate changes. |
851
+
852
+ </details>
853
+
854
+ ---
855
+
856
+ <details>
857
+
858
+ <summary style="cursor:pointer">Returns</summary>
859
+
860
+ Type: `boolean | void`
861
+
862
+ Returns `true` if the document is visible, `false` if hidden, or `void` if `updateState` is set to `false`.
863
+
864
+ </details>
865
+
866
+ ---
867
+
868
+ <details>
869
+
870
+ <summary style="cursor:pointer">Usage</summary>
871
+
872
+ ###### Simple usage
873
+
874
+ ```tsx
875
+ import { useDocumentVisibility } from "@alessiofrittoli/react-hooks";
876
+
877
+ const isDocumentVisible = useDocumentVisibility();
878
+ ```
879
+
880
+ ---
881
+
882
+ ###### Disable state updates and listen visibility changes
883
+
884
+ ```tsx
885
+ import {
886
+ useDocumentVisibility,
887
+ type VisibilityChangeHandler,
888
+ } from "@alessiofrittoli/react-hooks";
889
+
890
+ const onVisibilityChange = useCallback<VisibilityChangeHandler>((isVisible) => {
891
+ // ... do something
892
+ }, []);
893
+ useDocumentVisibility({ updateState: false, onVisibilityChange });
894
+ ```
895
+
896
+ </details>
897
+
898
+ ---
899
+
900
+ ##### `useWakeLock`
901
+
902
+ Easily manage the [Screen Wake Lock API](https://developer.mozilla.org/en-US/docs/Web/API/Screen_Wake_Lock_API) to prevent the device screen from dimming or locking while your app is in use.
903
+
904
+ <details>
905
+
906
+ <summary style="cursor:pointer">Parameters</summary>
907
+
908
+ | Parameter | Type | Default | Description |
909
+ | ----------------- | ------------------------ | ------- | ---------------------------------------------------------------- |
910
+ | `options` | `UseWakeLockOptions` | - | (Optional) An object defining hook options. |
911
+ | `options.onMount` | `boolean` | `true` | Indicates whether to request the screen WakeLock on mount. |
912
+ | `options.onError` | `OnWakeLockRequestError` | - | A custom callback executed when a screen WakeLock request fails. |
913
+
914
+ </details>
915
+
916
+ ---
917
+
918
+ <details>
919
+
920
+ <summary style="cursor:pointer">Returns</summary>
921
+
922
+ Type: `UseWakeLock`
923
+
924
+ An object returning The current `WakeLockSentinel` instance or `null` if not enabled and utility functions.
925
+
926
+ - `wakeLock`: `WakeLockSentinel | null` — The current Wake Lock instance, or null if not enabled.
927
+ - `enabled`: `boolean` — Whether the Wake Lock is currently active.
928
+ - `requestWakeLock`: `() => Promise<void>` — Manually request the Wake Lock.
929
+ - `releaseWakeLock`: `() => Promise<void>` — Manually release the Wake Lock.
930
+
931
+ </details>
932
+
933
+ ---
934
+
935
+ <details>
936
+
937
+ <summary style="cursor:pointer">Usage</summary>
938
+
939
+ ###### Enable Wake Lock on mount
940
+
941
+ ```tsx
942
+ import { useWakeLock } from "@alessiofrittoli/react-hooks";
943
+
944
+ useWakeLock();
945
+ ```
946
+
947
+ ---
948
+
949
+ ###### Manually enable and disable Wake Lock
950
+
951
+ ```tsx
952
+ import { useWakeLock } from "@alessiofrittoli/react-hooks";
953
+
954
+ export const WakeLockButton: React.FC = () => {
955
+ const { enabled, requestWakeLock, releaseWakeLock } = useWakeLock({
956
+ enableOnLoad: false,
957
+ });
958
+
959
+ return (
960
+ <>
961
+ <h1>Wakelock enabled: {enabled.toString()}</h1>
962
+ <button onClick={requestWakeLock}>Enable wakelock</button>
963
+ <button onClick={releaseWakeLock}>Disable wakelock</button>
964
+ </>
965
+ );
966
+ };
967
+ ```
968
+
969
+ ---
970
+
971
+ ###### Handling Wake Lock errors
972
+
973
+ ```tsx
974
+ import {
975
+ useWakeLock,
976
+ type OnWakeLockRequestError,
977
+ } from "@alessiofrittoli/react-hooks";
978
+
979
+ const onError: OnWakeLockRequestError = (error) => {
980
+ alert("Could not enable Wake Lock: " + error.message);
981
+ };
982
+
983
+ export const WakeLockWithError: React.FC = () => {
984
+ const { enabled, requestWakeLock } = useWakeLock({ onError });
985
+
986
+ return (
987
+ <button onClick={requestWakeLock}>
988
+ {enabled ? "Wake Lock enabled" : "Enable Wake Lock"}
989
+ </button>
990
+ );
991
+ };
800
992
  ```
801
993
 
802
994
  </details>
@@ -815,10 +1007,10 @@ This comes pretty handy when rendering a modal that shouldn't be closed without
815
1007
 
816
1008
  <summary style="cursor:pointer">Parameters</summary>
817
1009
 
818
- | Parameter | Type | Description |
819
- |-----------|------|-------------|
820
- | `target` | `React.RefObject<HTMLElement\|null>` | The target HTMLElement React RefObject to trap focus within. |
821
- | | | If no target is given, you must provide the target HTMLElement when calling `setFocusTrap`. |
1010
+ | Parameter | Type | Description |
1011
+ | --------- | ------------------------------------ | ------------------------------------------------------------------------------------------- |
1012
+ | `target` | `React.RefObject<HTMLElement\|null>` | The target HTMLElement React RefObject to trap focus within. |
1013
+ | | | If no target is given, you must provide the target HTMLElement when calling `setFocusTrap`. |
822
1014
 
823
1015
  </details>
824
1016
 
@@ -846,22 +1038,22 @@ A tuple containing:
846
1038
  ###### Defining the target on hook initialization
847
1039
 
848
1040
  ```tsx
849
- import { useFocusTrap } from '@alessiofrittoli/react-hooks'
1041
+ import { useFocusTrap } from "@alessiofrittoli/react-hooks";
850
1042
 
851
- const modalRef = useRef<HTMLDivElement>( null )
852
- const [ setFocusTrap, restoreFocusTrap ] = useFocusTrap( modalRef )
1043
+ const modalRef = useRef<HTMLDivElement>(null);
1044
+ const [setFocusTrap, restoreFocusTrap] = useFocusTrap(modalRef);
853
1045
 
854
- const modalOpenHandler = useCallback( () => {
855
- if ( ! modalRef.current ) return
1046
+ const modalOpenHandler = useCallback(() => {
1047
+ if (!modalRef.current) return;
856
1048
  // ... open modal
857
- setFocusTrap()
858
- modalRef.current.focus() // focus the dialog so next tab will focus the next element inside the modal
859
- }, [ setFocusTrap ] )
1049
+ setFocusTrap();
1050
+ modalRef.current.focus(); // focus the dialog so next tab will focus the next element inside the modal
1051
+ }, [setFocusTrap]);
860
1052
 
861
- const modalCloseHandler = useCallback( () => {
1053
+ const modalCloseHandler = useCallback(() => {
862
1054
  // ... close modal
863
- restoreFocusTrap() // cancel focus trap and restore focus to the last active element before enablig the focus trap
864
- }, [ restoreFocusTrap ] )
1055
+ restoreFocusTrap(); // cancel focus trap and restore focus to the last active element before enablig the focus trap
1056
+ }, [restoreFocusTrap]);
865
1057
  ```
866
1058
 
867
1059
  ---
@@ -869,25 +1061,25 @@ const modalCloseHandler = useCallback( () => {
869
1061
  ###### Defining the target ondemand
870
1062
 
871
1063
  ```tsx
872
- import { useFocusTrap } from '@alessiofrittoli/react-hooks'
1064
+ import { useFocusTrap } from "@alessiofrittoli/react-hooks";
873
1065
 
874
- const modalRef = useRef<HTMLDivElement>( null )
875
- const modal2Ref = useRef<HTMLDivElement>( null )
876
- const [ setFocusTrap, restoreFocusTrap ] = useFocusTrap()
1066
+ const modalRef = useRef<HTMLDivElement>(null);
1067
+ const modal2Ref = useRef<HTMLDivElement>(null);
1068
+ const [setFocusTrap, restoreFocusTrap] = useFocusTrap();
877
1069
 
878
- const modalOpenHandler = useCallback( () => {
879
- if ( ! modalRef.current ) return
1070
+ const modalOpenHandler = useCallback(() => {
1071
+ if (!modalRef.current) return;
880
1072
  // ... open modal
881
- setFocusTrap( modalRef.current )
882
- modalRef.current.focus()
883
- }, [ setFocusTrap ] )
1073
+ setFocusTrap(modalRef.current);
1074
+ modalRef.current.focus();
1075
+ }, [setFocusTrap]);
884
1076
 
885
- const modal2OpenHandler = useCallback( () => {
886
- if ( ! modal2Ref.current ) return
1077
+ const modal2OpenHandler = useCallback(() => {
1078
+ if (!modal2Ref.current) return;
887
1079
  // ... open modal
888
- setFocusTrap( modal2Ref.current )
889
- modal2Ref.current.focus()
890
- }, [ setFocusTrap ] )
1080
+ setFocusTrap(modal2Ref.current);
1081
+ modal2Ref.current.focus();
1082
+ }, [setFocusTrap]);
891
1083
  ```
892
1084
 
893
1085
  </details>
@@ -902,33 +1094,33 @@ Check if the given target Element is intersecting with an ancestor Element or wi
902
1094
 
903
1095
  <summary style="cursor:pointer">Parameters</summary>
904
1096
 
905
- | Parameter | Type | Description |
906
- |-----------|------|-------------|
907
- | `target` | `React.RefObject<Element\|null>` | The React.RefObject of the target Element to observe. |
908
- | `options` | `UseInViewOptions` | (Optional) An object defining custom `IntersectionObserver` options. |
909
- | `options.root` | `Element\|Document\|false\|null` | (Optional) Identifies the `Element` or `Document` whose bounds are treated as the bounding box of the viewport for the Element which is the observer's target. |
910
- | `options.margin` | `MarginType` | (Optional) A string, formatted similarly to the CSS margin property's value, which contains offsets for one or more sides of the root's bounding box. |
911
- | `options.amount` | `'all'\|'some'\|number\|number[]` | (Optional) The intersecting target thresholds. |
912
- | | | Threshold can be set to: |
913
- | | | - `all` - `1` will be used. |
914
- | | | - `some` - `0.5` will be used. |
915
- | | | - `number` |
916
- | | | - `number[]` |
917
- | `options.once` | `boolean` | (Optional) By setting this to `true` the observer will be disconnected after the target Element enters the viewport. |
918
- | `options.initial` | `boolean` | (Optional) Initial value. This value is used while server rendering then will be updated in the client based on target visibility. Default: `false`. |
919
- | `options.enable` | `boolean` | (Optional) Defines the initial observation activity. Use the returned `setEnabled` to update this state. Default: `true`. |
920
- | `options.onIntersect` | `OnIntersectStateHandler` | (Optional) A custom callback executed when target element's visibility has crossed one or more thresholds. |
921
- | | | This callback is awaited before any state update. |
922
- | | | If an error is thrown the React State update won't be fired. |
923
- | | | ⚠️ Wrap your callback with `useCallback` to avoid unnecessary `IntersectionObserver` recreation. |
924
- | `options.onEnter` | `OnIntersectHandler` | (Optional) A custom callback executed when target element's visibility has crossed one or more thresholds. |
925
- | | | This callback is awaited before any state update. |
926
- | | | If an error is thrown the React State update won't be fired. |
927
- | | | ⚠️ Wrap your callback with `useCallback` to avoid unnecessary `IntersectionObserver` recreation. |
928
- | `options.onExit` | `OnIntersectHandler` | (Optional) A custom callback executed when target element's visibility has crossed one or more thresholds. |
929
- | | | This callback is awaited before any state update. |
930
- | | | If an error is thrown the React State update won't be fired. |
931
- | | | ⚠️ Wrap your callback with `useCallback` to avoid unnecessary `IntersectionObserver` recreation. |
1097
+ | Parameter | Type | Description |
1098
+ | --------------------- | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1099
+ | `target` | `React.RefObject<Element\|null>` | The React.RefObject of the target Element to observe. |
1100
+ | `options` | `UseInViewOptions` | (Optional) An object defining custom `IntersectionObserver` options. |
1101
+ | `options.root` | `Element\|Document\|false\|null` | (Optional) Identifies the `Element` or `Document` whose bounds are treated as the bounding box of the viewport for the Element which is the observer's target. |
1102
+ | `options.margin` | `MarginType` | (Optional) A string, formatted similarly to the CSS margin property's value, which contains offsets for one or more sides of the root's bounding box. |
1103
+ | `options.amount` | `'all'\|'some'\|number\|number[]` | (Optional) The intersecting target thresholds. |
1104
+ | | | Threshold can be set to: |
1105
+ | | | - `all` - `1` will be used. |
1106
+ | | | - `some` - `0.5` will be used. |
1107
+ | | | - `number` |
1108
+ | | | - `number[]` |
1109
+ | `options.once` | `boolean` | (Optional) By setting this to `true` the observer will be disconnected after the target Element enters the viewport. |
1110
+ | `options.initial` | `boolean` | (Optional) Initial value. This value is used while server rendering then will be updated in the client based on target visibility. Default: `false`. |
1111
+ | `options.enable` | `boolean` | (Optional) Defines the initial observation activity. Use the returned `setEnabled` to update this state. Default: `true`. |
1112
+ | `options.onIntersect` | `OnIntersectStateHandler` | (Optional) A custom callback executed when target element's visibility has crossed one or more thresholds. |
1113
+ | | | This callback is awaited before any state update. |
1114
+ | | | If an error is thrown the React State update won't be fired. |
1115
+ | | | ⚠️ Wrap your callback with `useCallback` to avoid unnecessary `IntersectionObserver` recreation. |
1116
+ | `options.onEnter` | `OnIntersectHandler` | (Optional) A custom callback executed when target element's visibility has crossed one or more thresholds. |
1117
+ | | | This callback is awaited before any state update. |
1118
+ | | | If an error is thrown the React State update won't be fired. |
1119
+ | | | ⚠️ Wrap your callback with `useCallback` to avoid unnecessary `IntersectionObserver` recreation. |
1120
+ | `options.onExit` | `OnIntersectHandler` | (Optional) A custom callback executed when target element's visibility has crossed one or more thresholds. |
1121
+ | | | This callback is awaited before any state update. |
1122
+ | | | If an error is thrown the React State update won't be fired. |
1123
+ | | | ⚠️ Wrap your callback with `useCallback` to avoid unnecessary `IntersectionObserver` recreation. |
932
1124
 
933
1125
  </details>
934
1126
 
@@ -959,46 +1151,44 @@ An object containing:
959
1151
  ###### Basic usage
960
1152
 
961
1153
  ```tsx
962
- 'use client'
1154
+ "use client";
963
1155
 
964
- import { useRef } from 'react'
965
- import { useInView } from '@alessiofrittoli/react-hooks'
1156
+ import { useRef } from "react";
1157
+ import { useInView } from "@alessiofrittoli/react-hooks";
966
1158
 
967
1159
  const UseInViewExample: React.FC = () => {
1160
+ const targetRef = useRef<HTMLDivElement>(null);
1161
+ const { inView } = useInView(ref);
968
1162
 
969
- const targetRef = useRef<HTMLDivElement>( null )
970
- const { inView } = useInView( ref )
971
-
972
- return (
973
- Array.from( Array( 6 ) ).map( ( value, index ) => (
1163
+ return Array.from(Array(6)).map((value, index) => (
1164
+ <div
1165
+ key={index}
1166
+ style={{
1167
+ height: "50vh",
1168
+ border: "1px solid red",
1169
+ display: "flex",
1170
+ alignItems: "center",
1171
+ justifyContent: "center",
1172
+ }}
1173
+ >
974
1174
  <div
975
- key={ index }
976
- style={ {
977
- height : '50vh',
978
- border : '1px solid red',
979
- display : 'flex',
980
- alignItems : 'center',
981
- justifyContent : 'center',
982
- } }
1175
+ ref={index === 2 ? targetRef : undefined}
1176
+ style={{
1177
+ width: 150,
1178
+ height: 150,
1179
+ borderRadius: 12,
1180
+ display: "flex",
1181
+ alignItems: "center",
1182
+ justifyContent: "center",
1183
+ background: inView ? "#51AF83" : "#201A1B",
1184
+ color: inView ? "#201A1B" : "#FFFFFF",
1185
+ }}
983
1186
  >
984
- <div
985
- ref={ index === 2 ? targetRef : undefined }
986
- style={ {
987
- width : 150,
988
- height : 150,
989
- borderRadius : 12,
990
- display : 'flex',
991
- alignItems : 'center',
992
- justifyContent : 'center',
993
- background : inView ? '#51AF83' : '#201A1B',
994
- color : inView ? '#201A1B' : '#FFFFFF',
995
- } }
996
- >{ index + 1 }</div>
1187
+ {index + 1}
997
1188
  </div>
998
- ) )
999
- )
1000
-
1001
- }
1189
+ </div>
1190
+ ));
1191
+ };
1002
1192
  ```
1003
1193
 
1004
1194
  ---
@@ -1006,34 +1196,30 @@ const UseInViewExample: React.FC = () => {
1006
1196
  ###### Disconnect observer after target enters the viewport
1007
1197
 
1008
1198
  ```tsx
1009
- 'use client'
1199
+ "use client";
1010
1200
 
1011
- import { useRef } from 'react'
1012
- import { useInView } from '@alessiofrittoli/react-hooks'
1201
+ import { useRef } from "react";
1202
+ import { useInView } from "@alessiofrittoli/react-hooks";
1013
1203
 
1014
1204
  const OnceExample: React.FC = () => {
1205
+ const targetRef = useRef<HTMLDivElement>(null);
1206
+ const { inView } = useInView(targetRef, { once: true });
1015
1207
 
1016
- const targetRef = useRef<HTMLDivElement>( null )
1017
- const { inView } = useInView( targetRef, { once: true } )
1018
-
1019
- useEffect( () => {
1020
-
1021
- if ( ! inView ) return
1022
- console.count( 'Fired only once: element entered viewport.' )
1023
-
1024
- }, [ inView ] )
1208
+ useEffect(() => {
1209
+ if (!inView) return;
1210
+ console.count("Fired only once: element entered viewport.");
1211
+ }, [inView]);
1025
1212
 
1026
1213
  return (
1027
1214
  <div
1028
- ref={ targetRef }
1029
- style={ {
1030
- height : 200,
1031
- background : inView ? 'lime' : 'gray',
1032
- } }
1215
+ ref={targetRef}
1216
+ style={{
1217
+ height: 200,
1218
+ background: inView ? "lime" : "gray",
1219
+ }}
1033
1220
  />
1034
- )
1035
-
1036
- }
1221
+ );
1222
+ };
1037
1223
  ```
1038
1224
 
1039
1225
  ---
@@ -1041,35 +1227,33 @@ const OnceExample: React.FC = () => {
1041
1227
  ###### Observe target only when needed
1042
1228
 
1043
1229
  ```tsx
1044
- 'use client'
1230
+ "use client";
1045
1231
 
1046
- import { useRef } from 'react'
1047
- import { useInView } from '@alessiofrittoli/react-hooks'
1232
+ import { useRef } from "react";
1233
+ import { useInView } from "@alessiofrittoli/react-hooks";
1048
1234
 
1049
1235
  const OnDemandObservation: React.FC = () => {
1050
-
1051
- const targetRef = useRef<HTMLDivElement>( null )
1052
- const {
1053
- inView, enabled, setEnabled
1054
- } = useInView( targetRef, { enable: false } )
1236
+ const targetRef = useRef<HTMLDivElement>(null);
1237
+ const { inView, enabled, setEnabled } = useInView(targetRef, {
1238
+ enable: false,
1239
+ });
1055
1240
 
1056
1241
  return (
1057
1242
  <div>
1058
- <button onClick={ () => setEnabled( prev => ! prev ) }>
1059
- { enabled ? 'Disconnect observer' : 'Observe' }
1243
+ <button onClick={() => setEnabled((prev) => !prev)}>
1244
+ {enabled ? "Disconnect observer" : "Observe"}
1060
1245
  </button>
1061
1246
  <div
1062
- ref={ targetRef }
1063
- style={ {
1064
- height : 200,
1065
- marginTop : 50,
1066
- background : inView ? 'lime' : 'gray',
1067
- } }
1247
+ ref={targetRef}
1248
+ style={{
1249
+ height: 200,
1250
+ marginTop: 50,
1251
+ background: inView ? "lime" : "gray",
1252
+ }}
1068
1253
  />
1069
1254
  </div>
1070
- )
1071
-
1072
- }
1255
+ );
1256
+ };
1073
1257
  ```
1074
1258
 
1075
1259
  ---
@@ -1077,42 +1261,44 @@ const OnDemandObservation: React.FC = () => {
1077
1261
  ###### Execute custom callback when intersection occurs
1078
1262
 
1079
1263
  ```tsx
1080
- 'use client'
1081
-
1082
- import { useRef } from 'react'
1083
- import { useInView, type OnIntersectStateHandler } from '@alessiofrittoli/react-hooks'
1264
+ "use client";
1084
1265
 
1266
+ import { useRef } from "react";
1267
+ import {
1268
+ useInView,
1269
+ type OnIntersectStateHandler,
1270
+ } from "@alessiofrittoli/react-hooks";
1085
1271
 
1086
1272
  const AsyncStartExample: React.FC = () => {
1273
+ const targetRef = useRef<HTMLDivElement>(null);
1274
+ const onIntersect = useCallback<OnIntersectStateHandler>(
1275
+ async ({ entry, isEntering }) => {
1276
+ if (isEntering) {
1277
+ console.log("Delaying state update...");
1278
+ await new Promise((resolve) => setTimeout(resolve, 1000)); // Simulate delay
1279
+ console.log("Async task completed. `inView` will now be updated.");
1280
+ return;
1281
+ }
1087
1282
 
1088
- const targetRef = useRef<HTMLDivElement>( null )
1089
- const onIntersect = useCallback<OnIntersectStateHandler>( async ( { entry, isEntering } ) => {
1283
+ console.log("Delaying state update...");
1284
+ await new Promise((resolve) => setTimeout(resolve, 1000)); // Simulate delay
1285
+ console.log("Async task completed. `inView` will now be updated.");
1286
+ },
1287
+ []
1288
+ );
1090
1289
 
1091
- if ( isEntering ) {
1092
- console.log( 'Delaying state update...' )
1093
- await new Promise( resolve => setTimeout( resolve, 1000 ) ) // Simulate delay
1094
- console.log( 'Async task completed. `inView` will now be updated.' )
1095
- return
1096
- }
1097
-
1098
- console.log( 'Delaying state update...' )
1099
- await new Promise( resolve => setTimeout( resolve, 1000 ) ) // Simulate delay
1100
- console.log( 'Async task completed. `inView` will now be updated.' )
1101
-
1102
- }, [] )
1103
-
1104
- const { inView } = useInView( targetRef, { onIntersect } )
1290
+ const { inView } = useInView(targetRef, { onIntersect });
1105
1291
 
1106
1292
  return (
1107
1293
  <div
1108
- ref={ targetRef }
1109
- style={ {
1110
- height : 200,
1111
- background : inView ? 'lime' : 'gray',
1112
- } }
1294
+ ref={targetRef}
1295
+ style={{
1296
+ height: 200,
1297
+ background: inView ? "lime" : "gray",
1298
+ }}
1113
1299
  />
1114
- )
1115
- }
1300
+ );
1301
+ };
1116
1302
  ```
1117
1303
 
1118
1304
  ---
@@ -1120,34 +1306,35 @@ const AsyncStartExample: React.FC = () => {
1120
1306
  ###### Execute custom callback when `onEnter` and `onExit`
1121
1307
 
1122
1308
  ```tsx
1123
- 'use client'
1124
-
1125
- import { useRef } from 'react'
1126
- import { useInView, type OnIntersectHandler } from '@alessiofrittoli/react-hooks'
1309
+ "use client";
1127
1310
 
1311
+ import { useRef } from "react";
1312
+ import {
1313
+ useInView,
1314
+ type OnIntersectHandler,
1315
+ } from "@alessiofrittoli/react-hooks";
1128
1316
 
1129
1317
  const AsyncStartExample: React.FC = () => {
1318
+ const targetRef = useRef<HTMLDivElement>(null);
1319
+ const onEnter = useCallback<OnIntersectHandler>(async ({ entry }) => {
1320
+ console.log("In viewport - ", entry);
1321
+ }, []);
1322
+ const onExit = useCallback<OnIntersectHandler>(async ({ entry }) => {
1323
+ console.log("Exited viewport - ", entry);
1324
+ }, []);
1130
1325
 
1131
- const targetRef = useRef<HTMLDivElement>( null )
1132
- const onEnter = useCallback<OnIntersectHandler>( async ( { entry } ) => {
1133
- console.log( 'In viewport - ', entry )
1134
- }, [] )
1135
- const onExit = useCallback<OnIntersectHandler>( async ( { entry } ) => {
1136
- console.log( 'Exited viewport - ', entry )
1137
- }, [] )
1138
-
1139
- const { inView } = useInView( targetRef, { onEnter, onExit } )
1326
+ const { inView } = useInView(targetRef, { onEnter, onExit });
1140
1327
 
1141
1328
  return (
1142
1329
  <div
1143
- ref={ targetRef }
1144
- style={ {
1145
- height : 200,
1146
- background : inView ? 'lime' : 'gray',
1147
- } }
1330
+ ref={targetRef}
1331
+ style={{
1332
+ height: 200,
1333
+ background: inView ? "lime" : "gray",
1334
+ }}
1148
1335
  />
1149
- )
1150
- }
1336
+ );
1337
+ };
1151
1338
  ```
1152
1339
 
1153
1340
  </details>
@@ -1162,8 +1349,8 @@ Prevent Element overflow.
1162
1349
 
1163
1350
  <summary style="cursor:pointer">Parameters</summary>
1164
1351
 
1165
- | Parameter | Type | Default | Description |
1166
- |-----------|------|---------|-------------|
1352
+ | Parameter | Type | Default | Description |
1353
+ | --------- | ------------------------------------ | -------------------------- | -------------------------------------------------- |
1167
1354
  | `target` | `React.RefObject<HTMLElement\|null>` | `Document.documentElement` | (Optional) The React RefObject target HTMLElement. |
1168
1355
 
1169
1356
  </details>
@@ -1243,7 +1430,7 @@ Handle input states with ease.
1243
1430
  <summary style="cursor:pointer">Type Parameters</summary>
1244
1431
 
1245
1432
  | Parameter | Description |
1246
- |-----------|------------------------|
1433
+ | --------- | ---------------------- |
1247
1434
  | `I` | The input value type. |
1248
1435
  | `O` | The output value type. |
1249
1436
 
@@ -1255,15 +1442,15 @@ Handle input states with ease.
1255
1442
 
1256
1443
  <summary style="cursor:pointer">Parameters</summary>
1257
1444
 
1258
- | Parameter | Type | Default | Description |
1259
- |-----------|----------|---------|-----------------------------|
1260
- | `options` | `UseInputOptions<I, O>` | `{}` | An object defining custom options. |
1261
- | `options.inputRef` | `React.RefObject<InputType>` | - | (Optional) The React HTML input element ref. |
1262
- | `options.initialValue` | `O\|null` | - | (Optional) The input initial value. |
1263
- | `options.touchTimeout` | `number` | 600 | (Optional) A timeout in milliseconds which will be used to define the input as "touched" thus validations are triggered and errors can be displayed. |
1264
- | `options.validate` | `ValidateValueHandler<O>` | - | (Optional) Value validation handler. If `parse` callback is given, the `value` will be parsed before validation. |
1265
- | `options.parse` | `ParseValueHandler<I, O>` | - | (Optional) Parse value. |
1266
- | `options.onChange` | `ChangeHandler<O>` | - | (Optional) A callable function executed when the `ChangeEvent` is dispatched on the HTML input element. |
1445
+ | Parameter | Type | Default | Description |
1446
+ | ---------------------- | ---------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
1447
+ | `options` | `UseInputOptions<I, O>` | `{}` | An object defining custom options. |
1448
+ | `options.inputRef` | `React.RefObject<InputType>` | - | (Optional) The React HTML input element ref. |
1449
+ | `options.initialValue` | `O\|null` | - | (Optional) The input initial value. |
1450
+ | `options.touchTimeout` | `number` | 600 | (Optional) A timeout in milliseconds which will be used to define the input as "touched" thus validations are triggered and errors can be displayed. |
1451
+ | `options.validate` | `ValidateValueHandler<O>` | - | (Optional) Value validation handler. If `parse` callback is given, the `value` will be parsed before validation. |
1452
+ | `options.parse` | `ParseValueHandler<I, O>` | - | (Optional) Parse value. |
1453
+ | `options.onChange` | `ChangeHandler<O>` | - | (Optional) A callable function executed when the `ChangeEvent` is dispatched on the HTML input element. |
1267
1454
 
1268
1455
  </details>
1269
1456
 
@@ -1277,18 +1464,18 @@ Type: `UseInputOutput<I, O>`
1277
1464
 
1278
1465
  An object containing the following properties:
1279
1466
 
1280
- | Property | Type | Description |
1281
- |-----------------|------|-------------|
1282
- | `isEmpty` | `boolean` | Indicates whether the Input is empty or not. |
1283
- | `hasError` | `boolean` | Indicates whether the input has error or not. |
1284
- | | | It will return true if the Input does not pass the validation checks and it has been touched. |
1285
- | | | Please refer to the `isValid` property to check the Input validity regardless of whether it has been touched or not. |
1286
- | `changeHandler` | `React.ChangeEventHandler<InputType>` | Change handler callback used to handle Input change events. |
1287
- | `blurHandler` | `() => void` | Blur handler callback used to handle Input blur events. |
1288
- | `setValue` | `( value: O ) => void` | Call `setValue` method to update input value. |
1289
- | `submit` | `() => void` | Call `submit` method to re-run validations and ensure error state is updated successfully. |
1290
- | `reset` | `() => void` | Call `reset` method to reset the Input state. |
1291
- | `focus` | `() => void` | Call `focus` method to focus the Input Element. `inputRef` must be provided in the input options. |
1467
+ | Property | Type | Description |
1468
+ | --------------- | ------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
1469
+ | `isEmpty` | `boolean` | Indicates whether the Input is empty or not. |
1470
+ | `hasError` | `boolean` | Indicates whether the input has error or not. |
1471
+ | | | It will return true if the Input does not pass the validation checks and it has been touched. |
1472
+ | | | Please refer to the `isValid` property to check the Input validity regardless of whether it has been touched or not. |
1473
+ | `changeHandler` | `React.ChangeEventHandler<InputType>` | Change handler callback used to handle Input change events. |
1474
+ | `blurHandler` | `() => void` | Blur handler callback used to handle Input blur events. |
1475
+ | `setValue` | `( value: O ) => void` | Call `setValue` method to update input value. |
1476
+ | `submit` | `() => void` | Call `submit` method to re-run validations and ensure error state is updated successfully. |
1477
+ | `reset` | `() => void` | Call `reset` method to reset the Input state. |
1478
+ | `focus` | `() => void` | Call `focus` method to focus the Input Element. `inputRef` must be provided in the input options. |
1292
1479
 
1293
1480
  </details>
1294
1481
 
@@ -1302,19 +1489,17 @@ An object containing the following properties:
1302
1489
 
1303
1490
  ```tsx
1304
1491
  const MyComponent: React.FC = () => {
1305
-
1306
- const input = useInput<string>()
1492
+ const input = useInput<string>();
1307
1493
 
1308
1494
  return (
1309
1495
  <input
1310
- type='text'
1311
- value={ input.value || '' }
1312
- onChange={ input.changeHandler }
1313
- onBlur={ input.blurHandler }
1496
+ type="text"
1497
+ value={input.value || ""}
1498
+ onChange={input.changeHandler}
1499
+ onBlur={input.blurHandler}
1314
1500
  />
1315
- )
1316
-
1317
- }
1501
+ );
1502
+ };
1318
1503
  ```
1319
1504
 
1320
1505
  ---
@@ -1322,32 +1507,30 @@ const MyComponent: React.FC = () => {
1322
1507
  ###### Displaying custom error messages
1323
1508
 
1324
1509
  ```tsx
1325
- import { useInput, type ValidateValueHandler } from '@alessiofrittoli/react-hooks'
1510
+ import {
1511
+ useInput,
1512
+ type ValidateValueHandler,
1513
+ } from "@alessiofrittoli/react-hooks";
1326
1514
 
1327
- const isNotEmpty: ValidateValueHandler<string> = value => (
1328
- ! value ? false : value.trim().length > 0
1329
- )
1515
+ const isNotEmpty: ValidateValueHandler<string> = (value) =>
1516
+ !value ? false : value.trim().length > 0;
1330
1517
 
1331
1518
  const MyComponent: React.FC = () => {
1332
-
1333
- const input = useInput<string>( {
1519
+ const input = useInput<string>({
1334
1520
  validate: isNotEmpty,
1335
- } )
1521
+ });
1336
1522
 
1337
1523
  return (
1338
1524
  <>
1339
1525
  <input
1340
- value={ input.value || '' }
1341
- onChange={ input.changeHandler }
1342
- onBlur={ input.blurHandler }
1526
+ value={input.value || ""}
1527
+ onChange={input.changeHandler}
1528
+ onBlur={input.blurHandler}
1343
1529
  />
1344
- { input.hasError && (
1345
- <span>The input cannot be empty.</span>
1346
- ) }
1530
+ {input.hasError && <span>The input cannot be empty.</span>}
1347
1531
  </>
1348
- )
1349
-
1350
- }
1532
+ );
1533
+ };
1351
1534
  ```
1352
1535
 
1353
1536
  ---
@@ -1355,42 +1538,39 @@ const MyComponent: React.FC = () => {
1355
1538
  ###### Parsing and validating parsed value
1356
1539
 
1357
1540
  ```tsx
1358
- import { formatDate, isValidDate } from '@alessiofrittoli/date-utils'
1359
- import { useInput, type ValidateValueHandler, type ParseValueHandler } from '@alessiofrittoli/react-hooks'
1360
-
1361
- const parseStringToDate: ParseValueHandler<string, Date> = value => (
1362
- value ? new Date( value ) : undefined
1363
- )
1364
-
1541
+ import { formatDate, isValidDate } from "@alessiofrittoli/date-utils";
1542
+ import {
1543
+ useInput,
1544
+ type ValidateValueHandler,
1545
+ type ParseValueHandler,
1546
+ } from "@alessiofrittoli/react-hooks";
1365
1547
 
1366
- const validateInputDate: ValidateValueHandler<Date> = value => (
1367
- isValidDate( value ) && value.getTime() > Date.now()
1368
- )
1548
+ const parseStringToDate: ParseValueHandler<string, Date> = (value) =>
1549
+ value ? new Date(value) : undefined;
1369
1550
 
1551
+ const validateInputDate: ValidateValueHandler<Date> = (value) =>
1552
+ isValidDate(value) && value.getTime() > Date.now();
1370
1553
 
1371
1554
  const MyComponent: React.FC = () => {
1372
-
1373
- const input = useInput<string, Date>( {
1374
- parse : parseStringToDate,
1375
- validate : validateInputDate,
1376
- } )
1377
-
1555
+ const input = useInput<string, Date>({
1556
+ parse: parseStringToDate,
1557
+ validate: validateInputDate,
1558
+ });
1378
1559
 
1379
1560
  return (
1380
1561
  <>
1381
1562
  <input
1382
- type='datetime-local'
1383
- value={ input.value ? formatDate( input.value, 'Y-m-dTH:i' ) : '' }
1384
- onChange={ input.changeHandler }
1385
- onBlur={ input.blurHandler }
1563
+ type="datetime-local"
1564
+ value={input.value ? formatDate(input.value, "Y-m-dTH:i") : ""}
1565
+ onChange={input.changeHandler}
1566
+ onBlur={input.blurHandler}
1386
1567
  />
1387
- { input.hasError && (
1568
+ {input.hasError && (
1388
1569
  <span>Please choose a date no earlier than today</span>
1389
- ) }
1570
+ )}
1390
1571
  </>
1391
- )
1392
-
1393
- }
1572
+ );
1573
+ };
1394
1574
  ```
1395
1575
 
1396
1576
  </details>
@@ -1410,10 +1590,10 @@ Take a look at [`deferTask`](https://npmjs.com/package/@alessiofrittoli/web-util
1410
1590
 
1411
1591
  <summary style="cursor:pointer">Type Parameters</summary>
1412
1592
 
1413
- | Parameter | Description |
1414
- |-----------|------------------------------|
1593
+ | Parameter | Description |
1594
+ | --------- | ------------------------------------------------------------------------------------------------- |
1415
1595
  | `T` | The task function definition. `unknown` types will be inherited by your function type definition. |
1416
- | `U` | The task function arguments. `unknown` types will be inherited by your function type. |
1596
+ | `U` | The task function arguments. `unknown` types will be inherited by your function type. |
1417
1597
 
1418
1598
  </details>
1419
1599
 
@@ -1423,9 +1603,9 @@ Take a look at [`deferTask`](https://npmjs.com/package/@alessiofrittoli/web-util
1423
1603
 
1424
1604
  <summary style="cursor:pointer">Parameters</summary>
1425
1605
 
1426
- | Parameter | Type | Description |
1427
- |-----------|----------|-----------------------------|
1428
- | `task` | `T` | The task callable function. |
1606
+ | Parameter | Type | Description |
1607
+ | --------- | ---- | --------------------------- |
1608
+ | `task` | `T` | The task callable function. |
1429
1609
 
1430
1610
  </details>
1431
1611
 
@@ -1473,8 +1653,8 @@ Modified version of `useEffect` that only run once on intial load.
1473
1653
 
1474
1654
  <summary style="cursor:pointer">Parameters</summary>
1475
1655
 
1476
- | Parameter | Type | Description |
1477
- |-----------|------------------------|-------------|
1656
+ | Parameter | Type | Description |
1657
+ | --------- | ---------------------- | ------------------------------------------------------- |
1478
1658
  | `effect` | `React.EffectCallback` | Imperative function that can return a cleanup function. |
1479
1659
 
1480
1660
  </details>
@@ -1486,34 +1666,30 @@ Modified version of `useEffect` that only run once on intial load.
1486
1666
  <summary style="cursor:pointer">Usage</summary>
1487
1667
 
1488
1668
  ```tsx
1489
- 'use client'
1669
+ "use client";
1490
1670
 
1491
- import { useEffect, useState } from 'react'
1492
- import { useEffectOnce } from '@alessiofrittoli/react-hooks'
1671
+ import { useEffect, useState } from "react";
1672
+ import { useEffectOnce } from "@alessiofrittoli/react-hooks";
1493
1673
 
1494
1674
  export const ClientComponent: React.FC = () => {
1675
+ const [count, setCount] = useState(0);
1495
1676
 
1496
- const [ count, setCount ] = useState( 0 )
1497
-
1498
- useEffect( () => {
1499
- const intv = setInterval( () => {
1500
- setCount( prev => prev + 1 ) // update state each 1s
1501
- }, 1000 )
1502
- return () => clearInterval( intv )
1503
- }, [] )
1677
+ useEffect(() => {
1678
+ const intv = setInterval(() => {
1679
+ setCount((prev) => prev + 1); // update state each 1s
1680
+ }, 1000);
1681
+ return () => clearInterval(intv);
1682
+ }, []);
1504
1683
 
1505
- useEffectOnce( () => {
1506
- console.log( 'Component did mount' )
1684
+ useEffectOnce(() => {
1685
+ console.log("Component did mount");
1507
1686
  return () => {
1508
- console.log( 'Component did unmount' )
1509
- }
1510
- } )
1511
-
1512
- return (
1513
- <div>{ count }</div>
1514
- )
1687
+ console.log("Component did unmount");
1688
+ };
1689
+ });
1515
1690
 
1516
- }
1691
+ return <div>{count}</div>;
1692
+ };
1517
1693
  ```
1518
1694
 
1519
1695
  </details>
@@ -1528,9 +1704,9 @@ Modified version of `useEffect` that skips the first render.
1528
1704
 
1529
1705
  <summary style="cursor:pointer">Parameters</summary>
1530
1706
 
1531
- | Parameter | Type | Description |
1532
- |-----------|------------------------|-------------|
1533
- | `effect` | `React.EffectCallback` | Imperative function that can return a cleanup function. |
1707
+ | Parameter | Type | Description |
1708
+ | --------- | ---------------------- | ----------------------------------------------------------------------- |
1709
+ | `effect` | `React.EffectCallback` | Imperative function that can return a cleanup function. |
1534
1710
  | `deps` | `React.DependencyList` | If present, effect will only activate if the values in the list change. |
1535
1711
 
1536
1712
  </details>
@@ -1542,41 +1718,37 @@ Modified version of `useEffect` that skips the first render.
1542
1718
  <summary style="cursor:pointer">Usage</summary>
1543
1719
 
1544
1720
  ```tsx
1545
- 'use client'
1721
+ "use client";
1546
1722
 
1547
- import { useEffect, useState } from 'react'
1548
- import { useUpdateEffect } from '@alessiofrittoli/react-hooks'
1723
+ import { useEffect, useState } from "react";
1724
+ import { useUpdateEffect } from "@alessiofrittoli/react-hooks";
1549
1725
 
1550
1726
  export const ClientComponent: React.FC = () => {
1727
+ const [count, setCount] = useState(0);
1551
1728
 
1552
- const [ count, setCount ] = useState( 0 )
1553
-
1554
- useEffect( () => {
1555
- const intv = setInterval( () => {
1556
- setCount( prev => prev + 1 )
1557
- }, 1000 )
1558
- return () => clearInterval( intv )
1559
- }, [] )
1729
+ useEffect(() => {
1730
+ const intv = setInterval(() => {
1731
+ setCount((prev) => prev + 1);
1732
+ }, 1000);
1733
+ return () => clearInterval(intv);
1734
+ }, []);
1560
1735
 
1561
- useEffect( () => {
1562
- console.log( 'useEffect', count ) // starts from 0
1736
+ useEffect(() => {
1737
+ console.log("useEffect", count); // starts from 0
1563
1738
  return () => {
1564
- console.log( 'useEffect - clean up', count ) // starts from 0
1565
- }
1566
- }, [ count ] )
1739
+ console.log("useEffect - clean up", count); // starts from 0
1740
+ };
1741
+ }, [count]);
1567
1742
 
1568
- useUpdateEffect( () => {
1569
- console.log( 'useUpdateEffect', count ) // starts from 1
1743
+ useUpdateEffect(() => {
1744
+ console.log("useUpdateEffect", count); // starts from 1
1570
1745
  return () => {
1571
- console.log( 'useUpdateEffect - clean up', count ) // starts from 1
1572
- }
1573
- }, [ count ] )
1746
+ console.log("useUpdateEffect - clean up", count); // starts from 1
1747
+ };
1748
+ }, [count]);
1574
1749
 
1575
- return (
1576
- <div>{ count }</div>
1577
- )
1578
-
1579
- }
1750
+ return <div>{count}</div>;
1751
+ };
1580
1752
  ```
1581
1753
 
1582
1754
  </details>
@@ -1607,19 +1779,15 @@ Type: `boolean`
1607
1779
  <summary style="cursor:pointer">Usage</summary>
1608
1780
 
1609
1781
  ```tsx
1610
- 'use client'
1782
+ "use client";
1611
1783
 
1612
- import { useIsClient } from '@alessiofrittoli/react-hooks'
1784
+ import { useIsClient } from "@alessiofrittoli/react-hooks";
1613
1785
 
1614
1786
  export const ClientComponent: React.FC = () => {
1787
+ const isClient = useIsClient();
1615
1788
 
1616
- const isClient = useIsClient()
1617
-
1618
- return (
1619
- <div>Running { ! isClient ? 'server' : 'client' }-side</div>
1620
- )
1621
-
1622
- }
1789
+ return <div>Running {!isClient ? "server" : "client"}-side</div>;
1790
+ };
1623
1791
  ```
1624
1792
 
1625
1793
  </details>
@@ -1650,31 +1818,29 @@ Note that if the React Hook/Component has no state updates, `useIsFirstRender` w
1650
1818
  <summary style="cursor:pointer">Usage</summary>
1651
1819
 
1652
1820
  ```tsx
1653
- 'use client'
1821
+ "use client";
1654
1822
 
1655
- import { useIsFirstRender } from '@alessiofrittoli/react-hooks'
1823
+ import { useIsFirstRender } from "@alessiofrittoli/react-hooks";
1656
1824
 
1657
1825
  export const ClientComponent: React.FC = () => {
1826
+ const isFirstRender = useIsFirstRender();
1827
+ const [counter, setCounter] = useState(0);
1658
1828
 
1659
- const isFirstRender = useIsFirstRender()
1660
- const [ counter, setCounter ] = useState( 0 )
1661
-
1662
- useEffect( () => {
1663
- const intv = setInterval( () => {
1664
- setCounter( prev => prev + 1 )
1665
- }, 1000 )
1666
- return () => clearInterval( intv )
1667
- }, [] )
1829
+ useEffect(() => {
1830
+ const intv = setInterval(() => {
1831
+ setCounter((prev) => prev + 1);
1832
+ }, 1000);
1833
+ return () => clearInterval(intv);
1834
+ }, []);
1668
1835
 
1669
1836
  return (
1670
1837
  <div>
1671
- { isFirstRender ? 'First render' : 'Subsequent render' }
1838
+ {isFirstRender ? "First render" : "Subsequent render"}
1672
1839
  <hr />
1673
- { counter }
1840
+ {counter}
1674
1841
  </div>
1675
- )
1676
-
1677
- }
1842
+ );
1843
+ };
1678
1844
  ```
1679
1845
 
1680
1846
  </details>
@@ -1701,8 +1867,8 @@ Provides functionality for single and group selection, as well as resetting the
1701
1867
 
1702
1868
  <summary style="cursor:pointer">Type Parameters</summary>
1703
1869
 
1704
- | Parameter | Description |
1705
- |-----------|------------------------------|
1870
+ | Parameter | Description |
1871
+ | --------- | -------------------------------------- |
1706
1872
  | `V` | The type of the values in the `array`. |
1707
1873
 
1708
1874
  </details>
@@ -1713,10 +1879,10 @@ Provides functionality for single and group selection, as well as resetting the
1713
1879
 
1714
1880
  <summary style="cursor:pointer">Parameters</summary>
1715
1881
 
1716
- | Parameter | Type | Default | Description |
1717
- |-----------|-------|---------|-----------------------------|
1718
- | `array` | `V[]` | - | The array of items to manage selection for. |
1719
- | `initial` | `V[]` | [] | The initial selection state. |
1882
+ | Parameter | Type | Default | Description |
1883
+ | --------- | ----- | ------- | ------------------------------------------- |
1884
+ | `array` | `V[]` | - | The array of items to manage selection for. |
1885
+ | `initial` | `V[]` | [] | The initial selection state. |
1720
1886
 
1721
1887
  </details>
1722
1888
 
@@ -1746,77 +1912,78 @@ An object containing the selection state and handlers.
1746
1912
  <summary style="cursor:pointer">Usage</summary>
1747
1913
 
1748
1914
  ```tsx
1749
- 'use client'
1915
+ "use client";
1750
1916
 
1751
- import { useCallback, useMemo } from 'react'
1752
- import { useSelection } from '@alessiofrittoli/react-hooks'
1917
+ import { useCallback, useMemo } from "react";
1918
+ import { useSelection } from "@alessiofrittoli/react-hooks";
1753
1919
 
1754
- interface Item
1755
- {
1756
- id : number
1757
- name : string
1920
+ interface Item {
1921
+ id: number;
1922
+ name: string;
1758
1923
  }
1759
1924
 
1760
1925
  const items: Item[] = [
1761
1926
  {
1762
- id : 1,
1763
- name : 'item-1',
1927
+ id: 1,
1928
+ name: "item-1",
1764
1929
  },
1765
1930
  {
1766
- id : 2,
1767
- name : 'item-2',
1931
+ id: 2,
1932
+ name: "item-2",
1768
1933
  },
1769
1934
  {
1770
- id : 3,
1771
- name : 'item-3',
1935
+ id: 3,
1936
+ name: "item-3",
1772
1937
  },
1773
1938
  {
1774
- id : 4,
1775
- name : 'item-4',
1939
+ id: 4,
1940
+ name: "item-4",
1776
1941
  },
1777
1942
  {
1778
- id : 5,
1779
- name : 'item-5',
1943
+ id: 5,
1944
+ name: "item-5",
1780
1945
  },
1781
- ]
1782
-
1946
+ ];
1783
1947
 
1784
1948
  const MyComponent: React.FC = () => {
1785
-
1786
- const {
1787
- setSelection, select, groupSelect, isSelected
1788
- } = useSelection( useMemo( () => items.map( item => item.id ), [] ) )
1789
-
1790
- const clickHandler = useCallback( ( id: Item[ 'id' ] ) => (
1791
- ( event: React.MouseEvent<HTMLButtonElement> ) => {
1792
- if ( event.shiftKey ) {
1793
- return groupSelect( id ) // group select
1949
+ const { setSelection, select, groupSelect, isSelected } = useSelection(
1950
+ useMemo(() => items.map((item) => item.id), [])
1951
+ );
1952
+
1953
+ const clickHandler = useCallback(
1954
+ (id: Item["id"]) => (event: React.MouseEvent<HTMLButtonElement>) => {
1955
+ if (event.shiftKey) {
1956
+ return groupSelect(id); // group select
1794
1957
  }
1795
- if ( event.metaKey || event.ctrlKey ) {
1796
- return select( id ) // toggle single item in selection
1958
+ if (event.metaKey || event.ctrlKey) {
1959
+ return select(id); // toggle single item in selection
1797
1960
  }
1798
- setSelection( prev => (
1799
- prev.includes( id ) ? [] : [ id ] // toggle single item selection
1800
- ) )
1801
- }
1802
- ), [ select, groupSelect, setSelection ] )
1961
+ setSelection(
1962
+ (prev) => (prev.includes(id) ? [] : [id]) // toggle single item selection
1963
+ );
1964
+ },
1965
+ [select, groupSelect, setSelection]
1966
+ );
1803
1967
 
1804
1968
  return (
1805
1969
  <ul>
1806
- { items.map( item => (
1807
- <li key={ item.id }>
1970
+ {items.map((item) => (
1971
+ <li key={item.id}>
1808
1972
  <button
1809
- onClick={ clickHandler( item.id ) }
1810
- style={ {
1811
- border: isSelected( item.id ) ? '1px solid red' : ' 1px solid black'
1812
- } }
1813
- >{ item.name }</button>
1973
+ onClick={clickHandler(item.id)}
1974
+ style={{
1975
+ border: isSelected(item.id)
1976
+ ? "1px solid red"
1977
+ : " 1px solid black",
1978
+ }}
1979
+ >
1980
+ {item.name}
1981
+ </button>
1814
1982
  </li>
1815
- ) ) }
1983
+ ))}
1816
1984
  </ul>
1817
- )
1818
-
1819
- }
1985
+ );
1986
+ };
1820
1987
  ```
1821
1988
 
1822
1989
  </details>
@@ -1842,7 +2009,7 @@ The `Timeout` automatically restarts when the given `value` changes.
1842
2009
  <summary style="cursor:pointer">Type Parameters</summary>
1843
2010
 
1844
2011
  | Parameter | Description |
1845
- |-----------|--------------------------|
2012
+ | --------- | ------------------------ |
1846
2013
  | `T` | The type of the `value`. |
1847
2014
 
1848
2015
  </details>
@@ -1853,10 +2020,10 @@ The `Timeout` automatically restarts when the given `value` changes.
1853
2020
 
1854
2021
  <summary style="cursor:pointer">Parameters</summary>
1855
2022
 
1856
- | Parameter | Type | Default | Description |
1857
- |-----------|----------|---------|-----------------------------|
2023
+ | Parameter | Type | Default | Description |
2024
+ | --------- | -------- | ------- | ----------------------------------------------- |
1858
2025
  | `value` | `T` | - | The value to debounce. This can be of any type. |
1859
- | `delay` | `number` | 500 | The debounce delay in milliseconds. |
2026
+ | `delay` | `number` | 500 | The debounce delay in milliseconds. |
1860
2027
 
1861
2028
  </details>
1862
2029
 
@@ -1879,33 +2046,26 @@ The debounced value, which updates only after the delay has passed.
1879
2046
  <summary style="cursor:pointer">Usage</summary>
1880
2047
 
1881
2048
  ```tsx
1882
- 'use client'
2049
+ "use client";
1883
2050
 
1884
- import { useEffect, useState } from 'react'
1885
- import { useDebounce } from '@alessiofrittoli/react-hooks'
2051
+ import { useEffect, useState } from "react";
2052
+ import { useDebounce } from "@alessiofrittoli/react-hooks";
1886
2053
 
1887
2054
  const MyComponent: React.FC = () => {
2055
+ const [query, setQuery] = useState("");
2056
+ const debouncedQuery = useDebounce(query);
1888
2057
 
1889
- const [ query, setQuery ] = useState( '' )
1890
- const debouncedQuery = useDebounce( query )
1891
-
1892
- useEffect( () => {
1893
- if ( ! debouncedQuery ) return
2058
+ useEffect(() => {
2059
+ if (!debouncedQuery) return;
1894
2060
 
1895
- fetch( '...', {
2061
+ fetch("...", {
1896
2062
  // ...
1897
- body: JSON.stringify( { query: debouncedQuery } )
1898
- } )
1899
-
1900
- }, [ debouncedQuery ] )
2063
+ body: JSON.stringify({ query: debouncedQuery }),
2064
+ });
2065
+ }, [debouncedQuery]);
1901
2066
 
1902
- return (
1903
- <input
1904
- onChange={ event => setQuery( event.target.value ) }
1905
- />
1906
- )
1907
-
1908
- }
2067
+ return <input onChange={(event) => setQuery(event.target.value)} />;
2068
+ };
1909
2069
  ```
1910
2070
 
1911
2071
  </details>
@@ -1925,8 +2085,8 @@ The `Timeout` is automatically cancelled on unmount.
1925
2085
 
1926
2086
  <summary style="cursor:pointer">Type Parameters</summary>
1927
2087
 
1928
- | Parameter | Description |
1929
- |-----------|--------------------------|
2088
+ | Parameter | Description |
2089
+ | --------- | -------------------------------------------------------------- |
1930
2090
  | `T` | An Array defining optional arguments passed to the `callback`. |
1931
2091
 
1932
2092
  </details>
@@ -1937,15 +2097,15 @@ The `Timeout` is automatically cancelled on unmount.
1937
2097
 
1938
2098
  <summary style="cursor:pointer">Parameters</summary>
1939
2099
 
1940
- | Parameter | Type | Default | Description |
1941
- |-----------|----------|---------|-----------------------------|
1942
- | `callback`| `TimerHandler<T>` | - | The function to call when the timer elapses. |
1943
- | `options` | `TimerOptions<T>` | - | (Optional) An object defining custom timer options. |
1944
- | `options.delay` | `number` | `1` | The number of milliseconds to wait before calling the `callback`. |
1945
- | `options.args` | `T` | - | Optional arguments to pass when the `callback` is called. |
1946
- | `options.autoplay` | `boolean` | `true` | Indicates whether auto start the timer. |
1947
- | `options.updateState` | `boolean` | `false` | Whether to update React state about Timer running status. |
1948
- | `options.runOnStart` | `boolean` | `false` | Indicates whether to execute the callback when timer starts. |
2100
+ | Parameter | Type | Default | Description |
2101
+ | --------------------- | ----------------- | ------- | ----------------------------------------------------------------- |
2102
+ | `callback` | `TimerHandler<T>` | - | The function to call when the timer elapses. |
2103
+ | `options` | `TimerOptions<T>` | - | (Optional) An object defining custom timer options. |
2104
+ | `options.delay` | `number` | `1` | The number of milliseconds to wait before calling the `callback`. |
2105
+ | `options.args` | `T` | - | Optional arguments to pass when the `callback` is called. |
2106
+ | `options.autoplay` | `boolean` | `true` | Indicates whether auto start the timer. |
2107
+ | `options.updateState` | `boolean` | `false` | Whether to update React state about Timer running status. |
2108
+ | `options.runOnStart` | `boolean` | `false` | Indicates whether to execute the callback when timer starts. |
1949
2109
 
1950
2110
  </details>
1951
2111
 
@@ -1977,22 +2137,21 @@ If `updateState` is set to `true` then the following property is added in the re
1977
2137
  ##### Basic usage
1978
2138
 
1979
2139
  ```tsx
1980
- 'use client'
2140
+ "use client";
1981
2141
 
1982
- import { useCallback } from 'react'
1983
- import { useInterval } from '@alessiofrittoli/react-hooks'
2142
+ import { useCallback } from "react";
2143
+ import { useInterval } from "@alessiofrittoli/react-hooks";
1984
2144
 
1985
2145
  const MyComponent: React.FC = () => {
1986
-
1987
- const { stop } = useInterval( useCallback( () => {
1988
- console.log( 'tick timer' )
1989
- }, [] ), { delay: 1000 } )
1990
-
1991
- return (
1992
- <button onClick={ stop }>Stop timer</button>
1993
- )
1994
-
1995
- }
2146
+ const { stop } = useInterval(
2147
+ useCallback(() => {
2148
+ console.log("tick timer");
2149
+ }, []),
2150
+ { delay: 1000 }
2151
+ );
2152
+
2153
+ return <button onClick={stop}>Stop timer</button>;
2154
+ };
1996
2155
  ```
1997
2156
 
1998
2157
  ---
@@ -2000,34 +2159,31 @@ const MyComponent: React.FC = () => {
2000
2159
  ##### Rely on state updates
2001
2160
 
2002
2161
  ```tsx
2003
- 'use client'
2162
+ "use client";
2004
2163
 
2005
- import { useCallback } from 'react'
2006
- import { useInterval } from '@alessiofrittoli/react-hooks'
2164
+ import { useCallback } from "react";
2165
+ import { useInterval } from "@alessiofrittoli/react-hooks";
2007
2166
 
2008
2167
  const MyComponent: React.FC = () => {
2009
-
2010
- const { isActive, start, stop } = useInterval( useCallback( () => {
2011
- console.log( 'tick timer' )
2012
- }, [] ), {
2013
- delay : 1000,
2014
- autoplay : false,
2015
- runOnStart : true,
2016
- updateState : true,
2017
- } )
2168
+ const { isActive, start, stop } = useInterval(
2169
+ useCallback(() => {
2170
+ console.log("tick timer");
2171
+ }, []),
2172
+ {
2173
+ delay: 1000,
2174
+ autoplay: false,
2175
+ runOnStart: true,
2176
+ updateState: true,
2177
+ }
2178
+ );
2018
2179
 
2019
2180
  return (
2020
2181
  <>
2021
- { ! isActive && (
2022
- <button onClick={ start }>Start timer</button>
2023
- ) }
2024
- { isActive && (
2025
- <button onClick={ stop }>Stop timer</button>
2026
- ) }
2182
+ {!isActive && <button onClick={start}>Start timer</button>}
2183
+ {isActive && <button onClick={stop}>Stop timer</button>}
2027
2184
  </>
2028
- )
2029
-
2030
- }
2185
+ );
2186
+ };
2031
2187
  ```
2032
2188
 
2033
2189
  </details>
@@ -2055,8 +2211,8 @@ This is a lighter version of [`useInterval`](#useinterval) and is suggested to u
2055
2211
 
2056
2212
  <summary style="cursor:pointer">Type Parameters</summary>
2057
2213
 
2058
- | Parameter | Description |
2059
- |-----------|--------------------------|
2214
+ | Parameter | Description |
2215
+ | --------- | -------------------------------------------------------------- |
2060
2216
  | `T` | An Array defining optional arguments passed to the `callback`. |
2061
2217
 
2062
2218
  </details>
@@ -2067,12 +2223,12 @@ This is a lighter version of [`useInterval`](#useinterval) and is suggested to u
2067
2223
 
2068
2224
  <summary style="cursor:pointer">Parameters</summary>
2069
2225
 
2070
- | Parameter | Type | Default | Description |
2071
- |-----------|----------|---------|-----------------------------|
2072
- | `callback`| `TimerHandler<T>` | - | The function to call when the timer elapses. |
2073
- | `options` | `BasicTimerOptions<T>` | - | (Optional) An object defining custom timer options. |
2074
- | `options.delay` | `number` | `1` | The number of milliseconds to wait before calling the `callback`. |
2075
- | `options.args` | `T` | - | Optional arguments to pass when the `callback` is called. |
2226
+ | Parameter | Type | Default | Description |
2227
+ | --------------- | ---------------------- | ------- | ----------------------------------------------------------------- |
2228
+ | `callback` | `TimerHandler<T>` | - | The function to call when the timer elapses. |
2229
+ | `options` | `BasicTimerOptions<T>` | - | (Optional) An object defining custom timer options. |
2230
+ | `options.delay` | `number` | `1` | The number of milliseconds to wait before calling the `callback`. |
2231
+ | `options.args` | `T` | - | Optional arguments to pass when the `callback` is called. |
2076
2232
 
2077
2233
  </details>
2078
2234
 
@@ -2083,18 +2239,19 @@ This is a lighter version of [`useInterval`](#useinterval) and is suggested to u
2083
2239
  <summary style="cursor:pointer">Usage</summary>
2084
2240
 
2085
2241
  ```tsx
2086
- 'use client'
2242
+ "use client";
2087
2243
 
2088
- import { useCallback } from 'react'
2089
- import { useLightInterval } from '@alessiofrittoli/react-hooks'
2244
+ import { useCallback } from "react";
2245
+ import { useLightInterval } from "@alessiofrittoli/react-hooks";
2090
2246
 
2091
2247
  const MyComponent: React.FC = () => {
2092
-
2093
- useLightInterval( useCallback( () => {
2094
- console.log( 'tick timer' )
2095
- }, [] ), { delay: 1000 } )
2096
-
2097
- }
2248
+ useLightInterval(
2249
+ useCallback(() => {
2250
+ console.log("tick timer");
2251
+ }, []),
2252
+ { delay: 1000 }
2253
+ );
2254
+ };
2098
2255
  ```
2099
2256
 
2100
2257
  </details>
@@ -2122,8 +2279,8 @@ The `Timeout` is automatically cancelled on unmount.
2122
2279
 
2123
2280
  <summary style="cursor:pointer">Type Parameters</summary>
2124
2281
 
2125
- | Parameter | Description |
2126
- |-----------|--------------------------|
2282
+ | Parameter | Description |
2283
+ | --------- | -------------------------------------------------------------- |
2127
2284
  | `T` | An Array defining optional arguments passed to the `callback`. |
2128
2285
 
2129
2286
  </details>
@@ -2134,15 +2291,15 @@ The `Timeout` is automatically cancelled on unmount.
2134
2291
 
2135
2292
  <summary style="cursor:pointer">Parameters</summary>
2136
2293
 
2137
- | Parameter | Type | Default | Description |
2138
- |-----------|----------|---------|-----------------------------|
2139
- | `callback`| `TimerHandler<T>` | - | The function to call when the timer elapses. |
2140
- | `options` | `TimerOptions<T>` | - | (Optional) An object defining custom timer options. |
2141
- | `options.delay` | `number` | `1` | The number of milliseconds to wait before calling the `callback`. |
2142
- | `options.args` | `T` | - | Optional arguments to pass when the `callback` is called. |
2143
- | `options.autoplay` | `boolean` | `true` | Indicates whether auto start the timer. |
2144
- | `options.updateState` | `boolean` | `false` | Whether to update React state about Timer running status. |
2145
- | `options.runOnStart` | `boolean` | `false` | Indicates whether to execute the callback when timer starts. |
2294
+ | Parameter | Type | Default | Description |
2295
+ | --------------------- | ----------------- | ------- | ----------------------------------------------------------------- |
2296
+ | `callback` | `TimerHandler<T>` | - | The function to call when the timer elapses. |
2297
+ | `options` | `TimerOptions<T>` | - | (Optional) An object defining custom timer options. |
2298
+ | `options.delay` | `number` | `1` | The number of milliseconds to wait before calling the `callback`. |
2299
+ | `options.args` | `T` | - | Optional arguments to pass when the `callback` is called. |
2300
+ | `options.autoplay` | `boolean` | `true` | Indicates whether auto start the timer. |
2301
+ | `options.updateState` | `boolean` | `false` | Whether to update React state about Timer running status. |
2302
+ | `options.runOnStart` | `boolean` | `false` | Indicates whether to execute the callback when timer starts. |
2146
2303
 
2147
2304
  </details>
2148
2305
 
@@ -2174,22 +2331,21 @@ If `updateState` is set to `true` then the following property is added in the re
2174
2331
  ##### Basic usage
2175
2332
 
2176
2333
  ```tsx
2177
- 'use client'
2334
+ "use client";
2178
2335
 
2179
- import { useCallback } from 'react'
2180
- import { useTimeout } from '@alessiofrittoli/react-hooks'
2336
+ import { useCallback } from "react";
2337
+ import { useTimeout } from "@alessiofrittoli/react-hooks";
2181
2338
 
2182
2339
  const MyComponent: React.FC = () => {
2183
-
2184
- const { stop } = useTimeout( useCallback( () => {
2185
- console.log( 'tick timer' )
2186
- }, [] ), { delay: 1000 } )
2187
-
2188
- return (
2189
- <button onClick={ stop }>Stop timer</button>
2190
- )
2191
-
2192
- }
2340
+ const { stop } = useTimeout(
2341
+ useCallback(() => {
2342
+ console.log("tick timer");
2343
+ }, []),
2344
+ { delay: 1000 }
2345
+ );
2346
+
2347
+ return <button onClick={stop}>Stop timer</button>;
2348
+ };
2193
2349
  ```
2194
2350
 
2195
2351
  ---
@@ -2197,34 +2353,31 @@ const MyComponent: React.FC = () => {
2197
2353
  ##### Rely on state updates
2198
2354
 
2199
2355
  ```tsx
2200
- 'use client'
2356
+ "use client";
2201
2357
 
2202
- import { useCallback } from 'react'
2203
- import { useTimeout } from '@alessiofrittoli/react-hooks'
2358
+ import { useCallback } from "react";
2359
+ import { useTimeout } from "@alessiofrittoli/react-hooks";
2204
2360
 
2205
2361
  const MyComponent: React.FC = () => {
2206
-
2207
- const { isActive, start, stop } = useTimeout( useCallback( () => {
2208
- console.log( 'tick timer' )
2209
- }, [] ), {
2210
- delay : 1000,
2211
- autoplay : false,
2212
- runOnStart : true,
2213
- updateState : true,
2214
- } )
2362
+ const { isActive, start, stop } = useTimeout(
2363
+ useCallback(() => {
2364
+ console.log("tick timer");
2365
+ }, []),
2366
+ {
2367
+ delay: 1000,
2368
+ autoplay: false,
2369
+ runOnStart: true,
2370
+ updateState: true,
2371
+ }
2372
+ );
2215
2373
 
2216
2374
  return (
2217
2375
  <>
2218
- { ! isActive && (
2219
- <button onClick={ start }>Start timer</button>
2220
- ) }
2221
- { isActive && (
2222
- <button onClick={ stop }>Stop timer</button>
2223
- ) }
2376
+ {!isActive && <button onClick={start}>Start timer</button>}
2377
+ {isActive && <button onClick={stop}>Stop timer</button>}
2224
2378
  </>
2225
- )
2226
-
2227
- }
2379
+ );
2380
+ };
2228
2381
  ```
2229
2382
 
2230
2383
  </details>
@@ -2241,8 +2394,8 @@ This is a lighter version of [`useTimeout`](#usetimeout) and is suggested to use
2241
2394
 
2242
2395
  <summary style="cursor:pointer">Type Parameters</summary>
2243
2396
 
2244
- | Parameter | Description |
2245
- |-----------|--------------------------|
2397
+ | Parameter | Description |
2398
+ | --------- | -------------------------------------------------------------- |
2246
2399
  | `T` | An Array defining optional arguments passed to the `callback`. |
2247
2400
 
2248
2401
  </details>
@@ -2253,12 +2406,12 @@ This is a lighter version of [`useTimeout`](#usetimeout) and is suggested to use
2253
2406
 
2254
2407
  <summary style="cursor:pointer">Parameters</summary>
2255
2408
 
2256
- | Parameter | Type | Default | Description |
2257
- |-----------|----------|---------|-----------------------------|
2258
- | `callback`| `TimerHandler<T>` | - | The function to call when the timer elapses. |
2259
- | `options` | `BasicTimerOptions<T>` | - | (Optional) An object defining custom timer options. |
2260
- | `options.delay` | `number` | `1` | The number of milliseconds to wait before calling the `callback`. |
2261
- | `options.args` | `T` | - | Optional arguments to pass when the `callback` is called. |
2409
+ | Parameter | Type | Default | Description |
2410
+ | --------------- | ---------------------- | ------- | ----------------------------------------------------------------- |
2411
+ | `callback` | `TimerHandler<T>` | - | The function to call when the timer elapses. |
2412
+ | `options` | `BasicTimerOptions<T>` | - | (Optional) An object defining custom timer options. |
2413
+ | `options.delay` | `number` | `1` | The number of milliseconds to wait before calling the `callback`. |
2414
+ | `options.args` | `T` | - | Optional arguments to pass when the `callback` is called. |
2262
2415
 
2263
2416
  </details>
2264
2417
 
@@ -2269,18 +2422,19 @@ This is a lighter version of [`useTimeout`](#usetimeout) and is suggested to use
2269
2422
  <summary style="cursor:pointer">Usage</summary>
2270
2423
 
2271
2424
  ```tsx
2272
- 'use client'
2425
+ "use client";
2273
2426
 
2274
- import { useCallback } from 'react'
2275
- import { useLightTimeout } from '@alessiofrittoli/react-hooks'
2427
+ import { useCallback } from "react";
2428
+ import { useLightTimeout } from "@alessiofrittoli/react-hooks";
2276
2429
 
2277
2430
  const MyComponent: React.FC = () => {
2278
-
2279
- useLightTimeout( useCallback( () => {
2280
- console.log( 'tick timer' )
2281
- }, [] ), { delay: 1000 } )
2282
-
2283
- }
2431
+ useLightTimeout(
2432
+ useCallback(() => {
2433
+ console.log("tick timer");
2434
+ }, []),
2435
+ { delay: 1000 }
2436
+ );
2437
+ };
2284
2438
  ```
2285
2439
 
2286
2440
  </details>