feat: Complete zCode CLI X with Telegram bot integration

- Add full Telegram bot functionality with Z.AI API integration
- Implement 4 tools: Bash, FileEdit, WebSearch, Git
- Add 3 agents: Code Reviewer, Architect, DevOps Engineer
- Add 6 skills for common coding tasks
- Add systemd service file for 24/7 operation
- Add nginx configuration for HTTPS webhook
- Add comprehensive documentation
- Implement WebSocket server for real-time updates
- Add logging system with Winston
- Add environment validation

🤖 zCode CLI X - Agentic coder with Z.AI + Telegram integration
This commit is contained in:
admin
2026-05-05 09:01:26 +00:00
Unverified
parent 4a7035dd92
commit 875c7f9b91
24688 changed files with 3224957 additions and 221 deletions

View File

@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2020 Julien CARON
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,473 @@
<img src="https://github.com/juliencrn/usehooks-ts/blob/master/.github/screenshot.png" alt="usehooks-ts banner" align="center" />
<br />
<div align="center">
<h1>usehooks-ts</h1>
<div>React hook library, ready to use, written in Typescript.</div>
<br />
<!-- Badges -->
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](code_of_conduct.md)
![NPM Downloads](https://img.shields.io/npm/dm/usehooks-ts)
![NPM Downloads](https://img.shields.io/npm/dt/usehooks-ts)
[![License](https://badgen.net/badge/License/MIT/blue)](https://github.com/juliencrn/usehooks-ts/blob/master/LICENSE)
![npm bundle size](https://img.shields.io/bundlephobia/minzip/usehooks-ts)
![npm](https://img.shields.io/npm/v/usehooks-ts)<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-253-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->
<br />
<pre>npm i <a href="https://www.npmjs.com/package/usehooks-ts">usehooks-ts</a></pre>
<br />
<div align="center">
<sub>Created by <a href="https://github.com/juliencrn">Julien Caron</a> and maintained with ❤️ by an amazing <a href="#contributors">team of developers</a>.</sub>
</div>
</div>
<br />
## 💫 Introduction
useHooks(🔥).ts is a React hooks library, written in Typescript and easy to use. It provides a set of hooks that enables you to build your React applications faster. The hooks are built upon the principles of DRY (Don't Repeat Yourself). There are hooks for most common use cases you might need.
The library is designed to be as minimal as possible. It is fully tree-shakable (using the ESM version), meaning that you only import the hooks you need, and the rest will be removed from your bundle making the cost of using this library negligible. Most hooks are extensively tested and are being used in production environments.
### Usage example
```tsx
import { useLocalStorage } from 'usehooks-ts'
function Component() {
const [value, setValue] = useLocalStorage('my-localStorage-key', 0)
// ...
}
```
## 🪝 Available Hooks
<!-- HOOKS:START -->
- [`useBoolean`](https://usehooks-ts.com/react-hook/use-boolean) — handles boolean state with useful utility functions.
- [`useClickAnyWhere`](https://usehooks-ts.com/react-hook/use-click-any-where) — handles click events anywhere on the document.
- [`useCopyToClipboard`](https://usehooks-ts.com/react-hook/use-copy-to-clipboard) — copies text to the clipboard using the [Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API).
- [`useCountdown`](https://usehooks-ts.com/react-hook/use-countdown) — manages countdown.
- [`useCounter`](https://usehooks-ts.com/react-hook/use-counter) — manages a counter with increment, decrement, reset, and setCount functionalities.
- [`useDarkMode`](https://usehooks-ts.com/react-hook/use-dark-mode) — returns the current state of the dark mode.
- [`useDebounceCallback`](https://usehooks-ts.com/react-hook/use-debounce-callback) — creates a debounced version of a callback function.
- [`useDebounceValue`](https://usehooks-ts.com/react-hook/use-debounce-value) — returns a debounced version of the provided value, along with a function to update it.
- [`useDocumentTitle`](https://usehooks-ts.com/react-hook/use-document-title) — sets the document title.
- [`useEventCallback`](https://usehooks-ts.com/react-hook/use-event-callback) — creates a memoized event callback.
- [`useEventListener`](https://usehooks-ts.com/react-hook/use-event-listener) — attaches event listeners to DOM elements, the window, or media query lists.
- [`useHover`](https://usehooks-ts.com/react-hook/use-hover) — tracks whether a DOM element is being hovered over.
- [`useIntersectionObserver`](https://usehooks-ts.com/react-hook/use-intersection-observer) — tracks the intersection of a DOM element with its containing element or the viewport using the [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API).
- [`useInterval`](https://usehooks-ts.com/react-hook/use-interval) — creates an interval that invokes a callback function at a specified delay using the [setInterval API](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval).
- [`useIsClient`](https://usehooks-ts.com/react-hook/use-is-client) — determines if the code is running on the client side (in the browser).
- [`useIsMounted`](https://usehooks-ts.com/react-hook/use-is-mounted) — determines if the component is currently mounted.
- [`useIsomorphicLayoutEffect`](https://usehooks-ts.com/react-hook/use-isomorphic-layout-effect) — uses either useLayoutEffect or useEffect based on the environment (client-side or server-side).
- [`useLocalStorage`](https://usehooks-ts.com/react-hook/use-local-storage) — uses the [localStorage API](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) to persist state across page reloads.
- [`useMap`](https://usehooks-ts.com/react-hook/use-map) — manages a key-value [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) state with setter actions.
- [`useMediaQuery`](https://usehooks-ts.com/react-hook/use-media-query) — tracks the state of a media query using the [Match Media API](https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia).
- [`useOnClickOutside`](https://usehooks-ts.com/react-hook/use-on-click-outside) — handles clicks outside a specified element.
- [`useReadLocalStorage`](https://usehooks-ts.com/react-hook/use-read-local-storage) — reads a value from [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage), closely related to [useLocalStorage()](https://usehooks-ts.com/react-hook/use-local-storage).
- [`useResizeObserver`](https://usehooks-ts.com/react-hook/use-resize-observer) — observes the size of an element using the [ResizeObserver API](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver).
- [`useScreen`](https://usehooks-ts.com/react-hook/use-screen) — tracks the [screen](https://developer.mozilla.org/en-US/docs/Web/API/Window/screen) dimensions and properties.
- [`useScript`](https://usehooks-ts.com/react-hook/use-script) — dynamically loads scripts and tracking their loading status.
- [`useScrollLock`](https://usehooks-ts.com/react-hook/use-scroll-lock) — A custom hook that locks and unlocks scroll.
- [`useSessionStorage`](https://usehooks-ts.com/react-hook/use-session-storage) — uses the [sessionStorage API](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage) to persist state across page reloads.
- [`useStep`](https://usehooks-ts.com/react-hook/use-step) — manages and navigates between steps in a multi-step process.
- [`useTernaryDarkMode`](https://usehooks-ts.com/react-hook/use-ternary-dark-mode) — manages ternary (system, dark, light) dark mode with local storage support.
- [`useTimeout`](https://usehooks-ts.com/react-hook/use-timeout) — handles timeouts in React components using the [setTimeout API](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout).
- [`useToggle`](https://usehooks-ts.com/react-hook/use-toggle) — manages a boolean toggle state in React components.
- [`useUnmount`](https://usehooks-ts.com/react-hook/use-unmount) — runs a cleanup function when the component is unmounted.
- [`useWindowSize`](https://usehooks-ts.com/react-hook/use-window-size) — tracks the size of the window.
<!-- HOOKS:END -->
## 💚 Backers
Big thanks go to all our backers! [[Become a backer](https://github.com/sponsors/juliencrn)]
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/getsentry"><img src="https://avatars.githubusercontent.com/u/1396951?v=4" width="100px;" alt="Sentry"/><br /><sub><b>Sentry</b></sub></a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/KATT"><img src="https://avatars.githubusercontent.com/u/459267?v=4" width="100px;" alt="KATT"/><br /><sub><b>KATT</b></sub></a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/adhiravishankar"><img src="https://avatars.githubusercontent.com/u/3884741?v=4" width="100px;" alt="Adhi Ravishankar"/><br /><sub><b>Adhi Ravishankar</b></sub></a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/great-work-told-is"><img src="https://avatars.githubusercontent.com/u/113922084?v=4" width="100px;" alt="great-work-told-is"/><br /><sub><b>great-work-told-is</b></sub></a></td>
</tr>
</tbody>
</table>
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
## ✨ Contributors
Big thanks go to all our contributors! [[Become a contributor](https://github.com/juliencrn/usehooks-ts/blob/master/.github/CONTRIBUTING.md)]
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/juliencrn"><img src="https://avatars.githubusercontent.com/u/14028029?v=4?s=64" width="64px;" alt="Julien"/><br /><sub><b>Julien</b></sub></a><br /><a href="#content-juliencrn" title="Content">🖋</a> <a href="https://github.com/juliencrn/usehooks-ts/commits?author=juliencrn" title="Code">💻</a> <a href="#design-juliencrn" title="Design">🎨</a> <a href="#ideas-juliencrn" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/a777med"><img src="https://avatars.githubusercontent.com/u/15968280?v=4?s=64" width="64px;" alt="a777med"/><br /><sub><b>a777med</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=a777med" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://datkira.com/"><img src="https://avatars.githubusercontent.com/u/53250212?v=4?s=64" width="64px;" alt="Nguyen Tien Dat"/><br /><sub><b>Nguyen Tien Dat</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=datkira" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/elifer5000"><img src="https://avatars.githubusercontent.com/u/4311278?v=4?s=64" width="64px;" alt="Elias Cohenca"/><br /><sub><b>Elias Cohenca</b></sub></a><br /><a href="#content-elifer5000" title="Content">🖋</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://joaov.com.br/"><img src="https://avatars.githubusercontent.com/u/17601527?v=4?s=64" width="64px;" alt="João Deroldo"/><br /><sub><b>João Deroldo</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Ajoaoderoldo" title="Bug reports">🐛</a> <a href="https://github.com/juliencrn/usehooks-ts/commits?author=joaoderoldo" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Nishit-Dua"><img src="https://avatars.githubusercontent.com/u/35453301?v=4?s=64" width="64px;" alt="Nishit"/><br /><sub><b>Nishit</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=Nishit-Dua" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jonkoops"><img src="https://avatars.githubusercontent.com/u/695720?v=4?s=64" width="64px;" alt="Jon Koops"/><br /><sub><b>Jon Koops</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=jonkoops" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/LoneRifle"><img src="https://avatars.githubusercontent.com/u/10572368?v=4?s=64" width="64px;" alt="LoneRifle"/><br /><sub><b>LoneRifle</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=LoneRifle" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/vfonic"><img src="https://avatars.githubusercontent.com/u/67437?v=4?s=64" width="64px;" alt="Viktor"/><br /><sub><b>Viktor</b></sub></a><br /><a href="#ideas-vfonic" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Avfonic" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bclermont"><img src="https://avatars.githubusercontent.com/u/474302?v=4?s=64" width="64px;" alt="Bruno Clermont"/><br /><sub><b>Bruno Clermont</b></sub></a><br /><a href="#question-bclermont" title="Answering Questions">💬</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yoannesbourg"><img src="https://avatars.githubusercontent.com/u/73404603?v=4?s=64" width="64px;" alt="yoannesbourg"/><br /><sub><b>yoannesbourg</b></sub></a><br /><a href="#ideas-yoannesbourg" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/strange2x"><img src="https://avatars.githubusercontent.com/u/10759731?v=4?s=64" width="64px;" alt="Strange2x"/><br /><sub><b>Strange2x</b></sub></a><br /><a href="#ideas-strange2x" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/steinybot"><img src="https://avatars.githubusercontent.com/u/4659562?v=4?s=64" width="64px;" alt="Jason Pickens"/><br /><sub><b>Jason Pickens</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Asteinybot" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://smackagency.com/"><img src="https://avatars.githubusercontent.com/u/3469560?v=4?s=64" width="64px;" alt="Sel-Vin Kuik"/><br /><sub><b>Sel-Vin Kuik</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aselvinkuik" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/isaacalves"><img src="https://avatars.githubusercontent.com/u/1765942?v=4?s=64" width="64px;" alt="isaac"/><br /><sub><b>isaac</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aisaacalves" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/brunorzn"><img src="https://avatars.githubusercontent.com/u/18266054?v=4?s=64" width="64px;" alt="Bruno RZN"/><br /><sub><b>Bruno RZN</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=brunorzn" title="Code">💻</a> <a href="https://github.com/juliencrn/usehooks-ts/pulls?q=is%3Apr+reviewed-by%3Abrunorzn" title="Reviewed Pull Requests">👀</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.cykeprojects.com/"><img src="https://avatars.githubusercontent.com/u/2979318?v=4?s=64" width="64px;" alt="Nathan Manceaux-Panot"/><br /><sub><b>Nathan Manceaux-Panot</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=Cykelero" title="Code">💻</a> <a href="https://github.com/juliencrn/usehooks-ts/pulls?q=is%3Apr+reviewed-by%3ACykelero" title="Reviewed Pull Requests">👀</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/meotimdihia"><img src="https://avatars.githubusercontent.com/u/300961?v=4?s=64" width="64px;" alt="Dien Vu"/><br /><sub><b>Dien Vu</b></sub></a><br /><a href="#ideas-meotimdihia" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/olegKusov"><img src="https://avatars.githubusercontent.com/u/28058268?v=4?s=64" width="64px;" alt="Oleg Kusov"/><br /><sub><b>Oleg Kusov</b></sub></a><br /><a href="#ideas-olegKusov" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://mattguy.me/"><img src="https://avatars.githubusercontent.com/u/6647355?v=4?s=64" width="64px;" alt="Matthew Guy"/><br /><sub><b>Matthew Guy</b></sub></a><br /><a href="#ideas-mankittens" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/andrewbihl"><img src="https://avatars.githubusercontent.com/u/16709744?v=4?s=64" width="64px;" alt="andrewbihl"/><br /><sub><b>andrewbihl</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aandrewbihl" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lancepollard"><img src="https://avatars.githubusercontent.com/u/86631222?v=4?s=64" width="64px;" alt="lancepollard"/><br /><sub><b>lancepollard</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Alancepollard" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gmukul01"><img src="https://avatars.githubusercontent.com/u/3636885?v=4?s=64" width="64px;" alt="Mukul Bansal"/><br /><sub><b>Mukul Bansal</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Agmukul01" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://127.0.0.1:8000/"><img src="https://avatars.githubusercontent.com/u/474302?v=4?s=64" width="64px;" alt="Jean-Luc Mongrain sur la Brosse"/><br /><sub><b>Jean-Luc Mongrain sur la Brosse</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=jeanlucmongrain" title="Code">💻</a> <a href="#ideas-jeanlucmongrain" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/n1c"><img src="https://avatars.githubusercontent.com/u/284075?v=4?s=64" width="64px;" alt="Nic"/><br /><sub><b>Nic</b></sub></a><br /><a href="#content-n1c" title="Content">🖋</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://valtism.com/"><img src="https://avatars.githubusercontent.com/u/1286001?v=4?s=64" width="64px;" alt="Dan Wood"/><br /><sub><b>Dan Wood</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=valtism" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.sixt.de/"><img src="https://avatars.githubusercontent.com/u/25299148?v=4?s=64" width="64px;" alt="jo wendenbuerger"/><br /><sub><b>jo wendenbuerger</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AWendenburg" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://nozillium.com/"><img src="https://avatars.githubusercontent.com/u/4774875?v=4?s=64" width="64px;" alt="Andrew Nosenko"/><br /><sub><b>Andrew Nosenko</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Anoseratio" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/CharlieJhonSmith"><img src="https://avatars.githubusercontent.com/u/90845154?v=4?s=64" width="64px;" alt="CharlieJhonSmith"/><br /><sub><b>CharlieJhonSmith</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=CharlieJhonSmith" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://keybase.io/soullivaneuh"><img src="https://avatars.githubusercontent.com/u/1698357?v=4?s=64" width="64px;" alt="Sullivan SENECHAL"/><br /><sub><b>Sullivan SENECHAL</b></sub></a><br /><a href="#ideas-soullivaneuh" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Asoullivaneuh" title="Bug reports">🐛</a> <a href="https://github.com/juliencrn/usehooks-ts/commits?author=soullivaneuh" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jaslong"><img src="https://avatars.githubusercontent.com/u/797348?v=4?s=64" width="64px;" alt="Jason Long"/><br /><sub><b>Jason Long</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Ajaslong" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/kxm766"><img src="https://avatars.githubusercontent.com/u/88443148?v=4?s=64" width="64px;" alt="kxm766"/><br /><sub><b>kxm766</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Akxm766" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://qlaffont.com/"><img src="https://avatars.githubusercontent.com/u/10044790?v=4?s=64" width="64px;" alt="Quentin"/><br /><sub><b>Quentin</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=qlaffont" title="Code">💻</a> <a href="#ideas-qlaffont" title="Ideas, Planning, & Feedback">🤔</a> <a href="#content-qlaffont" title="Content">🖋</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ducktordanny"><img src="https://avatars.githubusercontent.com/u/38068717?v=4?s=64" width="64px;" alt="Daniel Lazar"/><br /><sub><b>Daniel Lazar</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=ducktordanny" title="Code">💻</a> <a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aducktordanny" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mterrel"><img src="https://avatars.githubusercontent.com/u/17746857?v=4?s=64" width="64px;" alt="Mark Terrel"/><br /><sub><b>Mark Terrel</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Amterrel" title="Bug reports">🐛</a> <a href="https://github.com/juliencrn/usehooks-ts/commits?author=mterrel" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mendrik"><img src="https://avatars.githubusercontent.com/u/160805?v=4?s=64" width="64px;" alt="Andreas Herd"/><br /><sub><b>Andreas Herd</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Amendrik" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://sonjoydatta.me/"><img src="https://avatars.githubusercontent.com/u/49079726?v=4?s=64" width="64px;" alt="Sonjoy Datta"/><br /><sub><b>Sonjoy Datta</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=sonjoydatta" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/oluckyman"><img src="https://avatars.githubusercontent.com/u/642673?v=4?s=64" width="64px;" alt="Ilya Belsky"/><br /><sub><b>Ilya Belsky</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aoluckyman" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://jamesbarrett.io/"><img src="https://avatars.githubusercontent.com/u/42980207?v=4?s=64" width="64px;" alt="James Barrett"/><br /><sub><b>James Barrett</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=JamesBarrettDev" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/AbbalYouness"><img src="https://avatars.githubusercontent.com/u/15120524?v=4?s=64" width="64px;" alt="AbbalYouness"/><br /><sub><b>AbbalYouness</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=AbbalYouness" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DidrikLind"><img src="https://avatars.githubusercontent.com/u/14201715?v=4?s=64" width="64px;" alt="didriklind"/><br /><sub><b>didriklind</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=DidrikLind" title="Code">💻</a> <a href="https://github.com/juliencrn/usehooks-ts/commits?author=DidrikLind" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hexp1989"><img src="https://avatars.githubusercontent.com/u/2241985?v=4?s=64" width="64px;" alt="hexp1989"/><br /><sub><b>hexp1989</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=hexp1989" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/alvaro-serrano-rivas/"><img src="https://avatars.githubusercontent.com/u/43758471?v=4?s=64" width="64px;" alt="Alvaro Serrano"/><br /><sub><b>Alvaro Serrano</b></sub></a><br /><a href="#content-alvaroserrrano" title="Content">🖋</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/egehandulger"><img src="https://avatars.githubusercontent.com/u/14878259?v=4?s=64" width="64px;" alt="Egehan Dülger"/><br /><sub><b>Egehan Dülger</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=egehandulger" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/PabloLION"><img src="https://avatars.githubusercontent.com/u/36828324?v=4?s=64" width="64px;" alt="PabloLION"/><br /><sub><b>PabloLION</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3APabloLION" title="Bug reports">🐛</a> <a href="https://github.com/juliencrn/usehooks-ts/commits?author=PabloLION" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://davidsanchez.me/"><img src="https://avatars.githubusercontent.com/u/84061?v=4?s=64" width="64px;" alt="David Sanchez"/><br /><sub><b>David Sanchez</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aemulienfou" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/AjayTheWizard"><img src="https://avatars.githubusercontent.com/u/92772740?v=4?s=64" width="64px;" alt="Ajay Raja"/><br /><sub><b>Ajay Raja</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AAjayTheWizard" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://andymerskin.com/"><img src="https://avatars.githubusercontent.com/u/758090?v=4?s=64" width="64px;" alt="Andy Merskin"/><br /><sub><b>Andy Merskin</b></sub></a><br /><a href="#ideas-docmars" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/GrayGalaxy"><img src="https://avatars.githubusercontent.com/u/49820575?v=4?s=64" width="64px;" alt="Avirup Ghosh"/><br /><sub><b>Avirup Ghosh</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=GrayGalaxy" title="Code">💻</a> <a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AGrayGalaxy" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tilnea"><img src="https://avatars.githubusercontent.com/u/3692320?v=4?s=64" width="64px;" alt="Sanne Wintrén"/><br /><sub><b>Sanne Wintrén</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Atilnea" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://lacolonia.studio/"><img src="https://avatars.githubusercontent.com/u/1528468?v=4?s=64" width="64px;" alt="Alessandro"/><br /><sub><b>Alessandro</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aa-barbieri" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/atatarenko"><img src="https://avatars.githubusercontent.com/u/9846273?v=4?s=64" width="64px;" alt="Andrey Tatarenko"/><br /><sub><b>Andrey Tatarenko</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aatatarenko" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/arusak"><img src="https://avatars.githubusercontent.com/u/4231915?v=4?s=64" width="64px;" alt="Anton Rusak"/><br /><sub><b>Anton Rusak</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aarusak" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/createdbymahmood"><img src="https://avatars.githubusercontent.com/u/40164360?v=4?s=64" width="64px;" alt="Mahmood Bagheri"/><br /><sub><b>Mahmood Bagheri</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=createdbymahmood" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://wpowner.com/"><img src="https://avatars.githubusercontent.com/u/506491?v=4?s=64" width="64px;" alt="Anver Sadutt"/><br /><sub><b>Anver Sadutt</b></sub></a><br /><a href="#content-anver" title="Content">🖋</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bogdanailincaipnt"><img src="https://avatars.githubusercontent.com/u/93596663?v=4?s=64" width="64px;" alt="Bogdan Ailincai"/><br /><sub><b>Bogdan Ailincai</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=bogdanailincaipnt" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/SimeonGriggs"><img src="https://avatars.githubusercontent.com/u/9684022?v=4?s=64" width="64px;" alt="Simeon Griggs"/><br /><sub><b>Simeon Griggs</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3ASimeonGriggs" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Kepro"><img src="https://avatars.githubusercontent.com/u/1714370?v=4?s=64" width="64px;" alt="Kepro"/><br /><sub><b>Kepro</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AKepro" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Jake-Lippert"><img src="https://avatars.githubusercontent.com/u/17753127?v=4?s=64" width="64px;" alt="Jake Lippert"/><br /><sub><b>Jake Lippert</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AJake-Lippert" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TunA-Kai"><img src="https://avatars.githubusercontent.com/u/92641762?v=4?s=64" width="64px;" alt="Tu Nguyen Anh"/><br /><sub><b>Tu Nguyen Anh</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3ATunA-Kai" title="Bug reports">🐛</a> <a href="https://github.com/juliencrn/usehooks-ts/commits?author=TunA-Kai" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/skve"><img src="https://avatars.githubusercontent.com/u/47612057?v=4?s=64" width="64px;" alt="Luke Shiels"/><br /><sub><b>Luke Shiels</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Askve" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/SleLLl"><img src="https://avatars.githubusercontent.com/u/66108429?v=4?s=64" width="64px;" alt="Sergei Kolyago"/><br /><sub><b>Sergei Kolyago</b></sub></a><br /><a href="#ideas-SleLLl" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/adhamaa"><img src="https://avatars.githubusercontent.com/u/50027371?v=4?s=64" width="64px;" alt="Adham Akmal Azmi"/><br /><sub><b>Adham Akmal Azmi</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aadhamaa" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/alex-kowalczyk"><img src="https://avatars.githubusercontent.com/u/7422175?v=4?s=64" width="64px;" alt="Alek Kowalczyk"/><br /><sub><b>Alek Kowalczyk</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aalex-kowalczyk" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Scalahansolo"><img src="https://avatars.githubusercontent.com/u/4317253?v=4?s=64" width="64px;" alt="Sean Callahan"/><br /><sub><b>Sean Callahan</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AScalahansolo" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jbean96"><img src="https://avatars.githubusercontent.com/u/22803097?v=4?s=64" width="64px;" alt="Joshua Bean"/><br /><sub><b>Joshua Bean</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=jbean96" title="Code">💻</a> <a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Ajbean96" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ZhaoTim"><img src="https://avatars.githubusercontent.com/u/30540533?v=4?s=64" width="64px;" alt="Tim Zhao"/><br /><sub><b>Tim Zhao</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AZhaoTim" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/patryk-smc"><img src="https://avatars.githubusercontent.com/u/37963339?v=4?s=64" width="64px;" alt="Patrick"/><br /><sub><b>Patrick</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Apatryk-smc" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://bryce.io/"><img src="https://avatars.githubusercontent.com/u/3171252?v=4?s=64" width="64px;" alt="Bryce Dorn"/><br /><sub><b>Bryce Dorn</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=brycedorn" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/angusd3v"><img src="https://avatars.githubusercontent.com/u/52683145?v=4?s=64" width="64px;" alt="angusd3v"/><br /><sub><b>angusd3v</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=angusd3v" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ddisimone"><img src="https://avatars.githubusercontent.com/u/78792352?v=4?s=64" width="64px;" alt="Davide Di Simone"/><br /><sub><b>Davide Di Simone</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Addisimone" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jherr"><img src="https://avatars.githubusercontent.com/u/22392?v=4?s=64" width="64px;" alt="Jack Herrington"/><br /><sub><b>Jack Herrington</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Ajherr" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://sharvit.github.io/"><img src="https://avatars.githubusercontent.com/u/1262502?v=4?s=64" width="64px;" alt="Avi Sharvit"/><br /><sub><b>Avi Sharvit</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=sharvit" title="Code">💻</a> <a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Asharvit" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/nmaties"><img src="https://avatars.githubusercontent.com/u/16613184?v=4?s=64" width="64px;" alt="Nicolae Maties"/><br /><sub><b>Nicolae Maties</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Anmaties" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/secretshardul"><img src="https://avatars.githubusercontent.com/u/49580849?v=4?s=64" width="64px;" alt="Shardul Aeer"/><br /><sub><b>Shardul Aeer</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Asecretshardul" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/herlon214"><img src="https://avatars.githubusercontent.com/u/3419441?v=4?s=64" width="64px;" alt="Herlon Aguiar"/><br /><sub><b>Herlon Aguiar</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aherlon214" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/alexisoney"><img src="https://avatars.githubusercontent.com/u/28802989?v=4?s=64" width="64px;" alt="Alexis Oney"/><br /><sub><b>Alexis Oney</b></sub></a><br /><a href="#content-alexisoney" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://convictional.com/"><img src="https://avatars.githubusercontent.com/u/96080054?v=4?s=64" width="64px;" alt="curtvict"/><br /><sub><b>curtvict</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=curtvict" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/JoshuaCS94"><img src="https://avatars.githubusercontent.com/u/23385700?v=4?s=64" width="64px;" alt="Josué Cortina"/><br /><sub><b>Josué Cortina</b></sub></a><br /><a href="#content-JoshuaCS94" title="Content">🖋</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://katt.dev/"><img src="https://avatars.githubusercontent.com/u/459267?v=4?s=64" width="64px;" alt="Alex / KATT"/><br /><sub><b>Alex / KATT</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=KATT" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/modex98"><img src="https://avatars.githubusercontent.com/u/72814784?v=4?s=64" width="64px;" alt="Mourad EL CADI"/><br /><sub><b>Mourad EL CADI</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=modex98" title="Code">💻</a> <a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Amodex98" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Guesswhoitis"><img src="https://avatars.githubusercontent.com/u/63756285?v=4?s=64" width="64px;" alt="James Hulena"/><br /><sub><b>James Hulena</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AGuesswhoitis" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://hailwood.nz/"><img src="https://avatars.githubusercontent.com/u/709773?v=4?s=64" width="64px;" alt="Matthew Hailwood"/><br /><sub><b>Matthew Hailwood</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=hailwood" title="Code">💻</a> <a href="https://github.com/juliencrn/usehooks-ts/pulls?q=is%3Apr+reviewed-by%3Ahailwood" title="Reviewed Pull Requests">👀</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mike247"><img src="https://avatars.githubusercontent.com/u/676071?v=4?s=64" width="64px;" alt="Michael Norrie"/><br /><sub><b>Michael Norrie</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Amike247" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/valentinpolitov"><img src="https://avatars.githubusercontent.com/u/39585375?v=4?s=64" width="64px;" alt="Valentin Politov"/><br /><sub><b>Valentin Politov</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=valentinpolitov" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/marnusw"><img src="https://avatars.githubusercontent.com/u/971499?v=4?s=64" width="64px;" alt="Marnus Weststrate"/><br /><sub><b>Marnus Weststrate</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=marnusw" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mancuoj"><img src="https://avatars.githubusercontent.com/u/45707684?v=4?s=64" width="64px;" alt="mancuoj"/><br /><sub><b>mancuoj</b></sub></a><br /><a href="#content-mancuoj" title="Content">🖋</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.chatsumlin.com/"><img src="https://avatars.githubusercontent.com/u/3067479?v=4?s=64" width="64px;" alt="Chat Sumlin"/><br /><sub><b>Chat Sumlin</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=jcsumlin" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/owenshaupt"><img src="https://avatars.githubusercontent.com/u/52288188?v=4?s=64" width="64px;" alt="Owen Haupt"/><br /><sub><b>Owen Haupt</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aowenshaupt" title="Bug reports">🐛</a> <a href="#content-owenshaupt" title="Content">🖋</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ubarbaxor"><img src="https://avatars.githubusercontent.com/u/26365493?v=4?s=64" width="64px;" alt="ubarbaxor"/><br /><sub><b>ubarbaxor</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=ubarbaxor" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://michael.mior.ca/"><img src="https://avatars.githubusercontent.com/u/82501?v=4?s=64" width="64px;" alt="Michael Mior"/><br /><sub><b>Michael Mior</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Amichaelmior" title="Bug reports">🐛</a> <a href="#content-michaelmior" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pkhodaveissi"><img src="https://avatars.githubusercontent.com/u/4170795?v=4?s=64" width="64px;" alt="Pierre"/><br /><sub><b>Pierre</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=pkhodaveissi" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/harrywebdev"><img src="https://avatars.githubusercontent.com/u/3617415?v=4?s=64" width="64px;" alt="Harry B"/><br /><sub><b>Harry B</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aharrywebdev" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/valyrie97"><img src="https://avatars.githubusercontent.com/u/6365746?v=4?s=64" width="64px;" alt="Valerie"/><br /><sub><b>Valerie</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Avalyrie97" title="Bug reports">🐛</a> <a href="https://github.com/juliencrn/usehooks-ts/commits?author=valyrie97" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://svachon.com/"><img src="https://avatars.githubusercontent.com/u/170197?v=4?s=64" width="64px;" alt="Steven Vachon"/><br /><sub><b>Steven Vachon</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=stevenvachon" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sskirby"><img src="https://avatars.githubusercontent.com/u/25760?v=4?s=64" width="64px;" alt="Sean Kirby"/><br /><sub><b>Sean Kirby</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=sskirby" title="Tests">⚠️</a> <a href="https://github.com/juliencrn/usehooks-ts/commits?author=sskirby" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/AlecsFarias"><img src="https://avatars.githubusercontent.com/u/91743821?v=4?s=64" width="64px;" alt="Alecsander Farias"/><br /><sub><b>Alecsander Farias</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=AlecsFarias" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://blankparticle.in/"><img src="https://avatars.githubusercontent.com/u/130567419?v=4?s=64" width="64px;" alt="Rahul Mishra"/><br /><sub><b>Rahul Mishra</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=BlankParticle" title="Code">💻</a> <a href="https://github.com/juliencrn/usehooks-ts/pulls?q=is%3Apr+reviewed-by%3ABlankParticle" title="Reviewed Pull Requests">👀</a> <a href="#content-BlankParticle" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bryantcodesart"><img src="https://avatars.githubusercontent.com/u/14097078?v=4?s=64" width="64px;" alt="Bryant Smith"/><br /><sub><b>Bryant Smith</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=bryantcodesart" title="Code">💻</a> <a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Abryantcodesart" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/RobHannay"><img src="https://avatars.githubusercontent.com/u/609062?v=4?s=64" width="64px;" alt="Rob Hannay"/><br /><sub><b>Rob Hannay</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=RobHannay" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hooriza"><img src="https://avatars.githubusercontent.com/u/507927?v=4?s=64" width="64px;" alt="Hooriza"/><br /><sub><b>Hooriza</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=hooriza" title="Code">💻</a> <a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Ahooriza" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ShanSenanayake"><img src="https://avatars.githubusercontent.com/u/8779685?v=4?s=64" width="64px;" alt="ShanSenanayake"/><br /><sub><b>ShanSenanayake</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=ShanSenanayake" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/philipgher"><img src="https://avatars.githubusercontent.com/u/32325241?v=4?s=64" width="64px;" alt="Philip Ghering"/><br /><sub><b>Philip Ghering</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=philipgher" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ladislasdellinger"><img src="https://avatars.githubusercontent.com/u/111739019?v=4?s=64" width="64px;" alt="Ladislas Dellinger"/><br /><sub><b>Ladislas Dellinger</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=ladislasdellinger" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TheHaff"><img src="https://avatars.githubusercontent.com/u/2486653?v=4?s=64" width="64px;" alt="Haff"/><br /><sub><b>Haff</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=TheHaff" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lisandro52"><img src="https://avatars.githubusercontent.com/u/5612241?v=4?s=64" width="64px;" alt="Lisandro"/><br /><sub><b>Lisandro</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=lisandro52" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/amirking59"><img src="https://avatars.githubusercontent.com/u/58273240?v=4?s=64" width="64px;" alt="Amir hossein rezaei"/><br /><sub><b>Amir hossein rezaei</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=amirking59" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/nmacianx"><img src="https://avatars.githubusercontent.com/u/40004186?v=4?s=64" width="64px;" alt="Nicolas Macian"/><br /><sub><b>Nicolas Macian</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Anmacianx" title="Bug reports">🐛</a> <a href="https://github.com/juliencrn/usehooks-ts/commits?author=nmacianx" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://dreamsof.dev/"><img src="https://avatars.githubusercontent.com/u/13162026?v=4?s=64" width="64px;" alt="Nate Forsyth"/><br /><sub><b>Nate Forsyth</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=nateforsyth" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/satelllte"><img src="https://avatars.githubusercontent.com/u/20585619?v=4?s=64" width="64px;" alt="satelllte"/><br /><sub><b>satelllte</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=satelllte" title="Code">💻</a> <a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Asatelllte" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fedemp"><img src="https://avatars.githubusercontent.com/u/735314?v=4?s=64" width="64px;" alt="Federico Panico"/><br /><sub><b>Federico Panico</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=fedemp" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/iamwillnbcu"><img src="https://avatars.githubusercontent.com/u/137317773?v=4?s=64" width="64px;" alt="William Pei Yuan"/><br /><sub><b>William Pei Yuan</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=iamwillnbcu" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://www.gazeta-cu-anunturi.ro/"><img src="https://avatars.githubusercontent.com/u/757999?v=4?s=64" width="64px;" alt="Mihai"/><br /><sub><b>Mihai</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=DarkAng3L" title="Code">💻</a> <a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3ADarkAng3L" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://habib.ogunsola.me/"><img src="https://avatars.githubusercontent.com/u/39172573?v=4?s=64" width="64px;" alt="Habib Ogunsola"/><br /><sub><b>Habib Ogunsola</b></sub></a><br /><a href="#content-ogunsolahabib" title="Content">🖋</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://ashfurrow.com/"><img src="https://avatars.githubusercontent.com/u/498212?v=4?s=64" width="64px;" alt="Ash Furrow"/><br /><sub><b>Ash Furrow</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=ashfurrow" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://turus.ro/"><img src="https://avatars.githubusercontent.com/u/32390499?v=4?s=64" width="64px;" alt="Daniel Turuș"/><br /><sub><b>Daniel Turuș</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=danielturus" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/rahulchaudhary2244/"><img src="https://avatars.githubusercontent.com/u/54467972?v=4?s=64" width="64px;" alt="Rahul Chaudhary"/><br /><sub><b>Rahul Chaudhary</b></sub></a><br /><a href="#content-rahulchaudhary2244" title="Content">🖋</a> <a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Arahulchaudhary2244" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Joshyahweh"><img src="https://avatars.githubusercontent.com/u/61137067?v=4?s=64" width="64px;" alt="Joshua Ojoawo"/><br /><sub><b>Joshua Ojoawo</b></sub></a><br /><a href="#ideas-Joshyahweh" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AJoshyahweh" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://jackdh.com/"><img src="https://avatars.githubusercontent.com/u/1907451?v=4?s=64" width="64px;" alt="Jack"/><br /><sub><b>Jack</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=jackdh" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jonlinkens"><img src="https://avatars.githubusercontent.com/u/20417521?v=4?s=64" width="64px;" alt="Jon Linkens"/><br /><sub><b>Jon Linkens</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=jonlinkens" title="Code">💻</a> <a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Ajonlinkens" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://velog.io/@ojj1123"><img src="https://avatars.githubusercontent.com/u/33178048?v=4?s=64" width="64px;" alt="Jeongjin Oh"/><br /><sub><b>Jeongjin Oh</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aojj1123" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tli26"><img src="https://avatars.githubusercontent.com/u/114947190?v=4?s=64" width="64px;" alt="Tianning Li"/><br /><sub><b>Tianning Li</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=tli26" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://larsartmann.com/"><img src="https://avatars.githubusercontent.com/u/23587853?v=4?s=64" width="64px;" alt="Lars Artmann"/><br /><sub><b>Lars Artmann</b></sub></a><br /><a href="#content-LarsArtmann" title="Content">🖋</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/KBobovskiy"><img src="https://avatars.githubusercontent.com/u/35502578?v=4?s=64" width="64px;" alt="KBobovskiy"/><br /><sub><b>KBobovskiy</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=KBobovskiy" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ryngonzalez"><img src="https://avatars.githubusercontent.com/u/635300?v=4?s=64" width="64px;" alt="✨ Kathryn Gonzalez ✨"/><br /><sub><b>✨ Kathryn Gonzalez ✨</b></sub></a><br /><a href="#content-ryngonzalez" title="Content">🖋</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/slavik-chapelskyi"><img src="https://avatars.githubusercontent.com/u/33541009?v=4?s=64" width="64px;" alt="Yaroslav Chapelskyi"/><br /><sub><b>Yaroslav Chapelskyi</b></sub></a><br /><a href="#content-slavik-chapelskyi" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sverps"><img src="https://avatars.githubusercontent.com/u/15879327?v=4?s=64" width="64px;" alt="Samuel Van Erps"/><br /><sub><b>Samuel Van Erps</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/pulls?q=is%3Apr+reviewed-by%3Asverps" title="Reviewed Pull Requests">👀</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ojolowoblue"><img src="https://avatars.githubusercontent.com/u/104099474?v=4?s=64" width="64px;" alt="ojolowoblue"/><br /><sub><b>ojolowoblue</b></sub></a><br /><a href="#content-ojolowoblue" title="Content">🖋</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://short.io/"><img src="https://avatars.githubusercontent.com/u/75169?v=4?s=64" width="64px;" alt="Andrii Kostenko"/><br /><sub><b>Andrii Kostenko</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=gugu" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/AkeemAllen"><img src="https://avatars.githubusercontent.com/u/32404761?v=4?s=64" width="64px;" alt="Akeem Allen"/><br /><sub><b>Akeem Allen</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=AkeemAllen" title="Code">💻</a> <a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AAkeemAllen" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/trongbinh15"><img src="https://avatars.githubusercontent.com/u/43725147?v=4?s=64" width="64px;" alt="trongbinhnguyen"/><br /><sub><b>trongbinhnguyen</b></sub></a><br /><a href="#content-trongbinh15" title="Content">🖋</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://lawlesx.vercel.app/"><img src="https://avatars.githubusercontent.com/u/52166437?v=4?s=64" width="64px;" alt="Aniruddha Sil"/><br /><sub><b>Aniruddha Sil</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=lawlesx" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/okinawaa"><img src="https://avatars.githubusercontent.com/u/69495129?v=4?s=64" width="64px;" alt="박찬혁"/><br /><sub><b>박찬혁</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/pulls?q=is%3Apr+reviewed-by%3Aokinawaa" title="Reviewed Pull Requests">👀</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://anishchhetri.com.np/"><img src="https://avatars.githubusercontent.com/u/98446102?v=4?s=64" width="64px;" alt="Anish"/><br /><sub><b>Anish</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=novanish" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://hutri.fi/"><img src="https://avatars.githubusercontent.com/u/55588133?v=4?s=64" width="64px;" alt="Hugo Hutri"/><br /><sub><b>Hugo Hutri</b></sub></a><br /><a href="#content-hugohutri" title="Content">🖋</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://balzguenat.ch/"><img src="https://avatars.githubusercontent.com/u/6719014?v=4?s=64" width="64px;" alt="Balz Guenat"/><br /><sub><b>Balz Guenat</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=BalzGuenat" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ottergeorge"><img src="https://avatars.githubusercontent.com/u/108759685?v=4?s=64" width="64px;" alt="OtterGeorge"/><br /><sub><b>OtterGeorge</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=ottergeorge" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/samay-rgb"><img src="https://avatars.githubusercontent.com/u/73112080?v=4?s=64" width="64px;" alt="Samay Sagar"/><br /><sub><b>Samay Sagar</b></sub></a><br /><a href="#content-samay-rgb" title="Content">🖋</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pedrobslisboa"><img src="https://avatars.githubusercontent.com/u/35539594?v=4?s=64" width="64px;" alt="Pedro Lisboa"/><br /><sub><b>Pedro Lisboa</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Apedrobslisboa" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/henriqemalheiros"><img src="https://avatars.githubusercontent.com/u/23730762?v=4?s=64" width="64px;" alt="Henrique Malheiros"/><br /><sub><b>Henrique Malheiros</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Ahenriqemalheiros" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://www.unfocus.com/"><img src="https://avatars.githubusercontent.com/u/245825?v=4?s=64" width="64px;" alt="Kevin Newman"/><br /><sub><b>Kevin Newman</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=CaptainN" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/a503189"><img src="https://avatars.githubusercontent.com/u/28802989?v=4?s=64" width="64px;" alt="a503189"/><br /><sub><b>a503189</b></sub></a><br /><a href="#content-a503189" title="Content">🖋</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://t.me/mouradelcadi"><img src="https://avatars.githubusercontent.com/u/72814784?v=4?s=64" width="64px;" alt="Mourad EL CADI"/><br /><sub><b>Mourad EL CADI</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=mod7ex" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Lop3sPedro"><img src="https://avatars.githubusercontent.com/u/89090945?v=4?s=64" width="64px;" alt="Pedro Henrique Lopes"/><br /><sub><b>Pedro Henrique Lopes</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=Lop3sPedro" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/danbiilee"><img src="https://avatars.githubusercontent.com/u/53761241?v=4?s=64" width="64px;" alt="Danbi Lee"/><br /><sub><b>Danbi Lee</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=danbiilee" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cojennin"><img src="https://avatars.githubusercontent.com/u/1888152?v=4?s=64" width="64px;" alt="Connor Jennings"/><br /><sub><b>Connor Jennings</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=cojennin" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lgxm3z"><img src="https://avatars.githubusercontent.com/u/28831375?v=4?s=64" width="64px;" alt="Lucas Gomes"/><br /><sub><b>Lucas Gomes</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Algxm3z" title="Bug reports">🐛</a> <a href="https://github.com/juliencrn/usehooks-ts/commits?author=lgxm3z" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zaggino"><img src="https://avatars.githubusercontent.com/u/1067319?v=4?s=64" width="64px;" alt="Martin Zagora"/><br /><sub><b>Martin Zagora</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=zaggino" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/kvdo2"><img src="https://avatars.githubusercontent.com/u/78251524?v=4?s=64" width="64px;" alt="KvD"/><br /><sub><b>KvD</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=kvdo2" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/SupraSmooth"><img src="https://avatars.githubusercontent.com/u/18029247?v=4?s=64" width="64px;" alt="Alex"/><br /><sub><b>Alex</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=SupraSmooth" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/kaceycleveland"><img src="https://avatars.githubusercontent.com/u/88064187?v=4?s=64" width="64px;" alt="Kacey Cleveland"/><br /><sub><b>Kacey Cleveland</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/pulls?q=is%3Apr+reviewed-by%3Akaceycleveland" title="Reviewed Pull Requests">👀</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/oviirup"><img src="https://avatars.githubusercontent.com/u/49820575?v=4?s=64" width="64px;" alt="Avirup Ghosh"/><br /><sub><b>Avirup Ghosh</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aoviirup" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yabbal"><img src="https://avatars.githubusercontent.com/u/15120524?v=4?s=64" width="64px;" alt="yabbal"/><br /><sub><b>yabbal</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=yabbal" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://patik.com/"><img src="https://avatars.githubusercontent.com/u/262137?v=4?s=64" width="64px;" alt="Craig Patik"/><br /><sub><b>Craig Patik</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Apatik" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Silverium"><img src="https://avatars.githubusercontent.com/u/10578392?v=4?s=64" width="64px;" alt="Soldeplata Saketos Candela"/><br /><sub><b>Soldeplata Saketos Candela</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=Silverium" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TENDOUZHI"><img src="https://avatars.githubusercontent.com/u/82806526?v=4?s=64" width="64px;" alt="TENDOUZHI"/><br /><sub><b>TENDOUZHI</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3ATENDOUZHI" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wachulski"><img src="https://avatars.githubusercontent.com/u/1669844?v=4?s=64" width="64px;" alt="Marcin Wachulski"/><br /><sub><b>Marcin Wachulski</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Awachulski" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://salmans.work/"><img src="https://avatars.githubusercontent.com/u/15085416?v=4?s=64" width="64px;" alt="Salman Fazal"/><br /><sub><b>Salman Fazal</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Asalmanfazal01" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/shrugs"><img src="https://avatars.githubusercontent.com/u/1535001?v=4?s=64" width="64px;" alt="shrugs"/><br /><sub><b>shrugs</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Ashrugs" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Hyodori04"><img src="https://avatars.githubusercontent.com/u/57362573?v=4?s=64" width="64px;" alt="hyodori"/><br /><sub><b>hyodori</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AHyodori04" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/eleazareramos"><img src="https://avatars.githubusercontent.com/u/25910203?v=4?s=64" width="64px;" alt="Eleazar “E” Ramos"/><br /><sub><b>Eleazar “E” Ramos</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aeleazareramos" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/retnag"><img src="https://avatars.githubusercontent.com/u/18302198?v=4?s=64" width="64px;" alt="retnag"/><br /><sub><b>retnag</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aretnag" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://jaeyoung.dev/"><img src="https://avatars.githubusercontent.com/u/55247450?v=4?s=64" width="64px;" alt="J young Lee"/><br /><sub><b>J young Lee</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Abeefiker" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fiws"><img src="https://avatars.githubusercontent.com/u/3409958?v=4?s=64" width="64px;" alt="Filip Weiss"/><br /><sub><b>Filip Weiss</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Afiws" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://mariusgundersen.net/"><img src="https://avatars.githubusercontent.com/u/464152?v=4?s=64" width="64px;" alt="Marius Gundersen"/><br /><sub><b>Marius Gundersen</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AmariusGundersen" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/VenomFate-619"><img src="https://avatars.githubusercontent.com/u/67755128?v=4?s=64" width="64px;" alt="Syed Aman Ali"/><br /><sub><b>Syed Aman Ali</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AVenomFate-619" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://ingadi.work/"><img src="https://avatars.githubusercontent.com/u/6121225?v=4?s=64" width="64px;" alt="Axel Ingadi"/><br /><sub><b>Axel Ingadi</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aingadi" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/andyjphu"><img src="https://avatars.githubusercontent.com/u/51890861?v=4?s=64" width="64px;" alt="AndyP"/><br /><sub><b>AndyP</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aandyjphu" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ishanVaghasiya"><img src="https://avatars.githubusercontent.com/u/98661936?v=4?s=64" width="64px;" alt="ishanVaghasiya"/><br /><sub><b>ishanVaghasiya</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AishanVaghasiya" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/nico-martinucci"><img src="https://avatars.githubusercontent.com/u/80868741?v=4?s=64" width="64px;" alt="Nico Martinucci"/><br /><sub><b>Nico Martinucci</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Anico-martinucci" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/technophile-04"><img src="https://avatars.githubusercontent.com/u/80153681?v=4?s=64" width="64px;" alt="Shiv Bhonde &#124; shivbhonde.eth"/><br /><sub><b>Shiv Bhonde &#124; shivbhonde.eth</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Atechnophile-04" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fritzmonkey"><img src="https://avatars.githubusercontent.com/u/10103840?v=4?s=64" width="64px;" alt="fritzmonkey"/><br /><sub><b>fritzmonkey</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Afritzmonkey" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/rrmesquita"><img src="https://avatars.githubusercontent.com/u/30835404?v=4?s=64" width="64px;" alt="Rodrigo Mesquita"/><br /><sub><b>Rodrigo Mesquita</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Arrmesquita" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://moshe.io/"><img src="https://avatars.githubusercontent.com/u/534911?v=4?s=64" width="64px;" alt="Moshe Simantov"/><br /><sub><b>Moshe Simantov</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Amoshest" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/BekaArabidze98"><img src="https://avatars.githubusercontent.com/u/122085038?v=4?s=64" width="64px;" alt="Beka"/><br /><sub><b>Beka</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3ABekaArabidze98" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/abdofola"><img src="https://avatars.githubusercontent.com/u/30251052?v=4?s=64" width="64px;" alt="Abdallah Alkaser"/><br /><sub><b>Abdallah Alkaser</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aabdofola" title="Bug reports">🐛</a> <a href="https://github.com/juliencrn/usehooks-ts/commits?author=abdofola" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/CarlosNZ"><img src="https://avatars.githubusercontent.com/u/5456533?v=4?s=64" width="64px;" alt="Carl Smith"/><br /><sub><b>Carl Smith</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3ACarlosNZ" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ogroppo"><img src="https://avatars.githubusercontent.com/u/4820803?v=4?s=64" width="64px;" alt="Orlando Groppo"/><br /><sub><b>Orlando Groppo</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aogroppo" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/thany"><img src="https://avatars.githubusercontent.com/u/152227?v=4?s=64" width="64px;" alt="Martijn Saly"/><br /><sub><b>Martijn Saly</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Athany" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://quinn.io/"><img src="https://avatars.githubusercontent.com/u/3764?v=4?s=64" width="64px;" alt="Quinn Shanahan"/><br /><sub><b>Quinn Shanahan</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aquinn" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://antoinek.fr/"><img src="https://avatars.githubusercontent.com/u/54948363?v=4?s=64" width="64px;" alt="Antoine Kingue"/><br /><sub><b>Antoine Kingue</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AAntoineKM" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zanzlender"><img src="https://avatars.githubusercontent.com/u/44570474?v=4?s=64" width="64px;" alt="Žan Žlender"/><br /><sub><b>Žan Žlender</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Azanzlender" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sebadom"><img src="https://avatars.githubusercontent.com/u/3877952?v=4?s=64" width="64px;" alt="Sebastian Dominguez"/><br /><sub><b>Sebastian Dominguez</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Asebadom" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jmc420"><img src="https://avatars.githubusercontent.com/u/11723529?v=4?s=64" width="64px;" alt="James Cowan"/><br /><sub><b>James Cowan</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Ajmc420" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bayraak"><img src="https://avatars.githubusercontent.com/u/10470072?v=4?s=64" width="64px;" alt="Bayram Ali Basgul"/><br /><sub><b>Bayram Ali Basgul</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Abayraak" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://wyatt.castaneda.family/"><img src="https://avatars.githubusercontent.com/u/17957937?v=4?s=64" width="64px;" alt="Wyatt Castaneda"/><br /><sub><b>Wyatt Castaneda</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AWyattCast44" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tsnevillecom"><img src="https://avatars.githubusercontent.com/u/3151454?v=4?s=64" width="64px;" alt="Tim Neville"/><br /><sub><b>Tim Neville</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Atsnevillecom" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/shoooe"><img src="https://avatars.githubusercontent.com/u/733227?v=4?s=64" width="64px;" alt="Thomas Pigarelli"/><br /><sub><b>Thomas Pigarelli</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Ashoooe" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jherdman"><img src="https://avatars.githubusercontent.com/u/3300?v=4?s=64" width="64px;" alt="James Herdman"/><br /><sub><b>James Herdman</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Ajherdman" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pociej"><img src="https://avatars.githubusercontent.com/u/3854675?v=4?s=64" width="64px;" alt="Grzegorz Pociejewski"/><br /><sub><b>Grzegorz Pociejewski</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Apociej" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/flyon"><img src="https://avatars.githubusercontent.com/u/341567?v=4?s=64" width="64px;" alt="René Verheij"/><br /><sub><b>René Verheij</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aflyon" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/PatrykKuniczak"><img src="https://avatars.githubusercontent.com/u/64608510?v=4?s=64" width="64px;" alt="PatrykKuniczak"/><br /><sub><b>PatrykKuniczak</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3APatrykKuniczak" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://cromodder.github.io/"><img src="https://avatars.githubusercontent.com/u/7691110?v=4?s=64" width="64px;" alt="Paolo Božac"/><br /><sub><b>Paolo Božac</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3ACroModder" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/reinos"><img src="https://avatars.githubusercontent.com/u/633730?v=4?s=64" width="64px;" alt="Rein"/><br /><sub><b>Rein</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Areinos" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FloorianB"><img src="https://avatars.githubusercontent.com/u/110407858?v=4?s=64" width="64px;" alt="FloorianB"/><br /><sub><b>FloorianB</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AFloorianB" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xuanhung1509"><img src="https://avatars.githubusercontent.com/u/89293664?v=4?s=64" width="64px;" alt="Xuan Hung"/><br /><sub><b>Xuan Hung</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Axuanhung1509" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://monawwar.io/"><img src="https://avatars.githubusercontent.com/u/31907722?v=4?s=64" width="64px;" alt="Monawwar Abdullah"/><br /><sub><b>Monawwar Abdullah</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Amxvsh" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/haroldo-ok"><img src="https://avatars.githubusercontent.com/u/1457465?v=4?s=64" width="64px;" alt="Haroldo de Oliveira Pinheiro"/><br /><sub><b>Haroldo de Oliveira Pinheiro</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aharoldo-ok" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://portfoliobytamjid.vercel.app/"><img src="https://avatars.githubusercontent.com/u/57794102?v=4?s=64" width="64px;" alt="Tamjid Ahmed"/><br /><sub><b>Tamjid Ahmed</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3ATamjidAhmed10" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jv-lopez"><img src="https://avatars.githubusercontent.com/u/93750956?v=4?s=64" width="64px;" alt="jv-lopez"/><br /><sub><b>jv-lopez</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Ajv-lopez" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://macr.ae/"><img src="https://avatars.githubusercontent.com/u/472830?v=4?s=64" width="64px;" alt="Callum Macrae"/><br /><sub><b>Callum Macrae</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Acallumacrae" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/0529bill"><img src="https://avatars.githubusercontent.com/u/62455148?v=4?s=64" width="64px;" alt="bywater529"/><br /><sub><b>bywater529</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3A0529bill" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/kevinxh"><img src="https://avatars.githubusercontent.com/u/10948652?v=4?s=64" width="64px;" alt="Kevin He"/><br /><sub><b>Kevin He</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Akevinxh" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FredericoGauz"><img src="https://avatars.githubusercontent.com/u/18327882?v=4?s=64" width="64px;" alt="FredericoGauz"/><br /><sub><b>FredericoGauz</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AFredericoGauz" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.jonlemofficial.com/"><img src="https://avatars.githubusercontent.com/u/38771842?v=4?s=64" width="64px;" alt="Jonathan &quot;JonLem&quot; Lemos"/><br /><sub><b>Jonathan &quot;JonLem&quot; Lemos</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AJonLemOfficial" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xegulon"><img src="https://avatars.githubusercontent.com/u/74178038?v=4?s=64" width="64px;" alt="Xegulon"/><br /><sub><b>Xegulon</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Axegulon" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TomSmedley"><img src="https://avatars.githubusercontent.com/u/95056193?v=4?s=64" width="64px;" alt="Tom Smedley"/><br /><sub><b>Tom Smedley</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3ATomSmedley" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lightbluepoppy"><img src="https://avatars.githubusercontent.com/u/65863981?v=4?s=64" width="64px;" alt="lightbluepoppy"/><br /><sub><b>lightbluepoppy</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Alightbluepoppy" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Dchole"><img src="https://avatars.githubusercontent.com/u/47068381?v=4?s=64" width="64px;" alt="Derek Oware"/><br /><sub><b>Derek Oware</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3ADchole" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://fragmentedthought.com/"><img src="https://avatars.githubusercontent.com/u/12085479?v=4?s=64" width="64px;" alt="Lance Gliser"/><br /><sub><b>Lance Gliser</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Alancegliser" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lewxdev"><img src="https://avatars.githubusercontent.com/u/6710419?v=4?s=64" width="64px;" alt="J. Lewis"/><br /><sub><b>J. Lewis</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Alewxdev" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yairy"><img src="https://avatars.githubusercontent.com/u/3206243?v=4?s=64" width="64px;" alt="Yair"/><br /><sub><b>Yair</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Ayairy" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://firecamp.dev/"><img src="https://avatars.githubusercontent.com/u/5078921?v=4?s=64" width="64px;" alt="Nishchit"/><br /><sub><b>Nishchit</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3ANishchit14" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Nejjer"><img src="https://avatars.githubusercontent.com/u/80219537?v=4?s=64" width="64px;" alt="Devofy"/><br /><sub><b>Devofy</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3ANejjer" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://joshguyette.com/"><img src="https://avatars.githubusercontent.com/u/28668902?v=4?s=64" width="64px;" alt="Josh Guyette"/><br /><sub><b>Josh Guyette</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Anightness" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dora-ljh"><img src="https://avatars.githubusercontent.com/u/35205701?v=4?s=64" width="64px;" alt="Dora Li"/><br /><sub><b>Dora Li</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Adora-ljh" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/kg-currenxie"><img src="https://avatars.githubusercontent.com/u/48229166?v=4?s=64" width="64px;" alt="Kristian Gerardsson"/><br /><sub><b>Kristian Gerardsson</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Akg-currenxie" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jdpt0"><img src="https://avatars.githubusercontent.com/u/19761394?v=4?s=64" width="64px;" alt="James Powell"/><br /><sub><b>James Powell</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Ajdpt0" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/boaz-poolman-662162115/"><img src="https://avatars.githubusercontent.com/u/9551934?v=4?s=64" width="64px;" alt="Boaz Poolman"/><br /><sub><b>Boaz Poolman</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aboazpoolman" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/roker15"><img src="https://avatars.githubusercontent.com/u/59526869?v=4?s=64" width="64px;" alt="roker15"/><br /><sub><b>roker15</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aroker15" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fadhilx"><img src="https://avatars.githubusercontent.com/u/15516786?v=4?s=64" width="64px;" alt="Fadhil Ahmad"/><br /><sub><b>Fadhil Ahmad</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Afadhilx" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Chandler-Zhu"><img src="https://avatars.githubusercontent.com/u/61914365?v=4?s=64" width="64px;" alt="Chandler-Zhu"/><br /><sub><b>Chandler-Zhu</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AChandler-Zhu" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/nixjs"><img src="https://avatars.githubusercontent.com/u/23132483?v=4?s=64" width="64px;" alt="Nghi Nguyen"/><br /><sub><b>Nghi Nguyen</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Anixjs" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ShravanSunder"><img src="https://avatars.githubusercontent.com/u/5294949?v=4?s=64" width="64px;" alt="Shravan Sunder"/><br /><sub><b>Shravan Sunder</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AShravanSunder" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Johannes5"><img src="https://avatars.githubusercontent.com/u/14299835?v=4?s=64" width="64px;" alt="Johannes5"/><br /><sub><b>Johannes5</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AJohannes5" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sebahhpeya"><img src="https://avatars.githubusercontent.com/u/93996817?v=4?s=64" width="64px;" alt="sebahhpeya"/><br /><sub><b>sebahhpeya</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Asebahhpeya" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://onezero.co.il/"><img src="https://avatars.githubusercontent.com/u/45389557?v=4?s=64" width="64px;" alt="Or Nakash"/><br /><sub><b>Or Nakash</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aornakash" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hepiyellow"><img src="https://avatars.githubusercontent.com/u/6338722?v=4?s=64" width="64px;" alt="Erez Makavy"/><br /><sub><b>Erez Makavy</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Ahepiyellow" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://andymerskin.com/"><img src="https://avatars.githubusercontent.com/u/758090?v=4?s=64" width="64px;" alt="Andy Merskin"/><br /><sub><b>Andy Merskin</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aandymerskin" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/chainalert-bot"><img src="https://avatars.githubusercontent.com/u/95303823?v=4?s=64" width="64px;" alt="ChainAlert Bot"/><br /><sub><b>ChainAlert Bot</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Achainalert-bot" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tmdesigned"><img src="https://avatars.githubusercontent.com/u/3608018?v=4?s=64" width="64px;" alt="Taylor Morgan"/><br /><sub><b>Taylor Morgan</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Atmdesigned" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://abkabioye.me/"><img src="https://avatars.githubusercontent.com/u/18709032?v=4?s=64" width="64px;" alt="wisdomabioye"/><br /><sub><b>wisdomabioye</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Awisdomabioye" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://www.samtheq.com"><img src="https://avatars.githubusercontent.com/u/51345689?v=4?s=64" width="64px;" alt="Samuel Quiñones"/><br /><sub><b>Samuel Quiñones</b></sub></a><br /><a href="#ideas-SamuelQuinones" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ymc-maha"><img src="https://avatars.githubusercontent.com/u/697307?v=4?s=64" width="64px;" alt="Manuel"/><br /><sub><b>Manuel</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=ymc-maha" title="Code">💻</a> <a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aymc-maha" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Yurchishin"><img src="https://avatars.githubusercontent.com/u/36650915?v=4?s=64" width="64px;" alt="Yurii Rybak"/><br /><sub><b>Yurii Rybak</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3AYurchishin" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/iuriiiurevich"><img src="https://avatars.githubusercontent.com/u/15759600?v=4?s=64" width="64px;" alt="Yury Demin"/><br /><sub><b>Yury Demin</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aiuriiiurevich" title="Bug reports">🐛</a> <a href="https://github.com/juliencrn/usehooks-ts/commits?author=iuriiiurevich" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://tewks.io/"><img src="https://avatars.githubusercontent.com/u/3970573?v=4?s=64" width="64px;" alt="Jon Tewksbury"/><br /><sub><b>Jon Tewksbury</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=jontewks" title="Code">💻</a> <a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Ajontewks" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/novacdenis"><img src="https://avatars.githubusercontent.com/u/45555668?v=4?s=64" width="64px;" alt="Novac Denis"/><br /><sub><b>Novac Denis</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=novacdenis" title="Code">💻</a> <a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Anovacdenis" title="Bug reports">🐛</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/kyrylo-soulandwolf"><img src="https://avatars.githubusercontent.com/u/54762253?v=4?s=64" width="64px;" alt="kyrylo-soulandwolf"/><br /><sub><b>kyrylo-soulandwolf</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=kyrylo-soulandwolf" title="Code">💻</a> <a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Akyrylo-soulandwolf" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/misidoro"><img src="https://avatars.githubusercontent.com/u/3635023?v=4?s=64" width="64px;" alt="Miguel Isidoro"/><br /><sub><b>Miguel Isidoro</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=misidoro" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://crowds.space/"><img src="https://avatars.githubusercontent.com/u/828918?v=4?s=64" width="64px;" alt="Yuriy Gromchenko"/><br /><sub><b>Yuriy Gromchenko</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=gromchen" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="http://jcbhmr.me"><img src="https://avatars.githubusercontent.com/u/61068799?v=4?s=64" width="64px;" alt="Jacob Hummer"/><br /><sub><b>Jacob Hummer</b></sub></a><br /><a href="#ideas-jcbhmr" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/k-melnychuk"><img src="https://avatars.githubusercontent.com/u/22131019?v=4?s=64" width="64px;" alt="Kyrylo Melnychuk"/><br /><sub><b>Kyrylo Melnychuk</b></sub></a><br /><a href="#content-k-melnychuk" title="Content">🖋</a> <a href="https://github.com/juliencrn/usehooks-ts/commits?author=k-melnychuk" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/LumaKernel"><img src="https://avatars.githubusercontent.com/u/29811106?v=4?s=64" width="64px;" alt="Luma"/><br /><sub><b>Luma</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=LumaKernel" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Newbie012"><img src="https://avatars.githubusercontent.com/u/10504365?v=4?s=64" width="64px;" alt="Eliya Cohen"/><br /><sub><b>Eliya Cohen</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=Newbie012" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/isumix"><img src="https://avatars.githubusercontent.com/u/16747416?v=4?s=64" width="64px;" alt="Igor Sukharev"/><br /><sub><b>Igor Sukharev</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Aisumix" title="Bug reports">🐛</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pookmish"><img src="https://avatars.githubusercontent.com/u/7185045?v=4?s=64" width="64px;" alt="pookmish"/><br /><sub><b>pookmish</b></sub></a><br /><a href="#ideas-pookmish" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/metav-drimz"><img src="https://avatars.githubusercontent.com/u/113976282?v=4?s=64" width="64px;" alt="metav-drimz"/><br /><sub><b>metav-drimz</b></sub></a><br /><a href="#ideas-metav-drimz" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://luckrnx09.com/"><img src="https://avatars.githubusercontent.com/u/113882203?v=4?s=64" width="64px;" alt="luckrnx09"/><br /><sub><b>luckrnx09</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=luckrnx09" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/RubyHuntsman"><img src="https://avatars.githubusercontent.com/u/24682602?v=4?s=64" width="64px;" alt="Hubert Kuczmierczyk"/><br /><sub><b>Hubert Kuczmierczyk</b></sub></a><br /><a href="#ideas-RubyHuntsman" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/juliencrn/usehooks-ts/pulls?q=is%3Apr+reviewed-by%3ARubyHuntsman" title="Reviewed Pull Requests">👀</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dandubya"><img src="https://avatars.githubusercontent.com/u/67660308?v=4?s=64" width="64px;" alt="dandubya"/><br /><sub><b>dandubya</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=dandubya" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/LonelyFellas"><img src="https://avatars.githubusercontent.com/u/38754760?v=4?s=64" width="64px;" alt="Darwish"/><br /><sub><b>Darwish</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/commits?author=LonelyFellas" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://www.jesuisjo.com/"><img src="https://avatars.githubusercontent.com/u/2046871?v=4?s=64" width="64px;" alt="Jonathan Raoult"/><br /><sub><b>Jonathan Raoult</b></sub></a><br /><a href="https://github.com/juliencrn/usehooks-ts/issues?q=author%3Ajraoult" title="Bug reports">🐛</a> <a href="https://github.com/juliencrn/usehooks-ts/pulls?q=is%3Apr+reviewed-by%3Ajraoult" title="Reviewed Pull Requests">👀</a></td>
</tr>
</tbody>
</table>
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification ([emoji key](https://allcontributors.org/docs/en/emoji-key)). Contributions of any kind welcome!
## 💞 Donate
If you find this piece of software helpful, please consider a donation. Any amount is greatly appreciated.
[![GitHub Sponsors](https://badgen.net/badge/GitHub%20Sponsors/Donate/blue)](https://github.com/sponsors/juliencrn)
[![Paypal](https://badgen.net/badge/Paypal/Donate/blue)](https://www.paypal.com/paypalme/juliencrn)
[![Stripe](https://badgen.net/badge/Stripe/Donate/blue)](https://buy.stripe.com/fZefZY8Bv32cg9O3cc)
[![Buy me a coffee](https://badgen.net/badge/Buy%20me%20a%20coffee/Donate/blue)](https://www.buymeacoffee.com/juliencrn)
BTC: `bc1qwys40tnd0lxf9lr9l0t6xc63dpxyucj4x4nay0`
ETH: `0x36a85155a8300754C56395D5af24553FB18915D6`
## 📝 License
This project is [MIT](https://github.com/juliencrn/usehooks-ts/blob/master/LICENSE) licensed.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,953 @@
import { Dispatch, SetStateAction, RefObject, useLayoutEffect } from 'react';
/** The useBoolean return type. */
type UseBooleanReturn = {
/** The current boolean state value. */
value: boolean;
/** Function to set the boolean state directly. */
setValue: Dispatch<SetStateAction<boolean>>;
/** Function to set the boolean state to `true`. */
setTrue: () => void;
/** Function to set the boolean state to `false`. */
setFalse: () => void;
/** Function to toggle the boolean state. */
toggle: () => void;
};
/**
* Custom hook that handles boolean state with useful utility functions.
* @param {boolean} [defaultValue] - The initial value for the boolean state (default is `false`).
* @returns {UseBooleanReturn} An object containing the boolean state value and utility functions to manipulate the state.
* @throws Will throw an error if `defaultValue` is an invalid boolean value.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-boolean)
* @example
* ```tsx
* const { value, setTrue, setFalse, toggle } = useBoolean(true);
* ```
*/
declare function useBoolean(defaultValue?: boolean): UseBooleanReturn;
/**
* Custom hook that handles click events anywhere on the document.
* @param {Function} handler - The function to be called when a click event is detected anywhere on the document.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-click-any-where)
* @example
* ```tsx
* const handleClick = (event) => {
* console.log('Document clicked!', event);
* };
*
* // Attach click event handler to document
* useClickAnywhere(handleClick);
* ```
*/
declare function useClickAnyWhere(handler: (event: MouseEvent) => void): void;
/**
* The copied text as `string` or `null` if nothing has been copied yet.
*/
type CopiedValue = string | null;
/**
* Function to copy text to the clipboard.
* @param text - The text to copy to the clipboard.
* @returns {Promise<boolean>} A promise that resolves to `true` if the text was copied successfully, or `false` otherwise.
*/
type CopyFn = (text: string) => Promise<boolean>;
/**
* Custom hook that copies text to the clipboard using the [`Clipboard API`](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API).
* @returns {[CopiedValue, CopyFn]} An tuple containing the copied text and a function to copy text to the clipboard.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-copy-to-clipboard)
* @example
* ```tsx
* const [copiedText, copyToClipboard] = useCopyToClipboard();
* const textToCopy = 'Hello, world!';
*
* // Attempt to copy text to the clipboard
* copyToClipboard(textToCopy)
* .then(success => {
* if (success) {
* console.log(`Text "${textToCopy}" copied to clipboard successfully.`);
* } else {
* console.error('Failed to copy text to clipboard.');
* }
* });
* ```
*/
declare function useCopyToClipboard(): [CopiedValue, CopyFn];
/** The countdown's options. */
type CountdownOptions = {
/** The countdown's starting number, initial value of the returned number. */
countStart: number;
/**
* The countdown's interval, in milliseconds.
* @default 1000
*/
intervalMs?: number;
/**
* True if the countdown is increment.
* @default false
*/
isIncrement?: boolean;
/**
* The countdown's stopping number. Pass `-Infinity` to decrease forever.
* @default 0
*/
countStop?: number;
};
/** The countdown's controllers. */
type CountdownControllers = {
/** Start the countdown. */
startCountdown: () => void;
/** Stop the countdown. */
stopCountdown: () => void;
/** Reset the countdown. */
resetCountdown: () => void;
};
/**
* Custom hook that manages countdown.
* @param {CountdownOptions} countdownOptions - The countdown's options.
* @returns {[number, CountdownControllers]} An array containing the countdown's count and its controllers.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-countdown)
* @example
* ```tsx
* const [counter, { start, stop, reset }] = useCountdown({
* countStart: 10,
* intervalMs: 1000,
* isIncrement: false,
* });
* ```
*/
declare function useCountdown({ countStart, countStop, intervalMs, isIncrement, }: CountdownOptions): [number, CountdownControllers];
/** The hook return type. */
type UseCounterReturn = {
/** The current count value. */
count: number;
/** Function to increment the counter by 1. */
increment: () => void;
/** Function to decrement the counter by 1. */
decrement: () => void;
/** Function to reset the counter to its initial value. */
reset: () => void;
/** Function to set a specific value to the counter. */
setCount: Dispatch<SetStateAction<number>>;
};
/**
* Custom hook that manages a counter with increment, decrement, reset, and setCount functionalities.
* @param {number} [initialValue] - The initial value for the counter.
* @returns {UseCounterReturn} An object containing the current count and functions to interact with the counter.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-counter)
* @example
* ```tsx
* const { count, increment, decrement, reset, setCount } = useCounter(5);
* ```
*/
declare function useCounter(initialValue?: number): UseCounterReturn;
/** The hook options. */
type DarkModeOptions = {
/**
* The initial value of the dark mode.
* @default false
*/
defaultValue?: boolean;
/**
* The key to use in the local storage.
* @default 'usehooks-ts-dark-mode'
*/
localStorageKey?: string;
/**
* If `true` (default), the hook will initialize reading `localStorage`.
* In SSR, you should set it to `false`, returning the `defaultValue` or `false` initially.
* @default true
*/
initializeWithValue?: boolean;
};
/** The hook return type. */
type DarkModeReturn = {
/** The current state of the dark mode. */
isDarkMode: boolean;
/** Function to toggle the dark mode. */
toggle: () => void;
/** Function to enable the dark mode. */
enable: () => void;
/** Function to disable the dark mode. */
disable: () => void;
/** Function to set a specific value to the dark mode. */
set: (value: boolean) => void;
};
/**
* Custom hook that returns the current state of the dark mode.
* @param {?DarkModeOptions} [options] - The initial value of the dark mode, default `false`.
* @returns {DarkModeReturn} An object containing the dark mode's state and its controllers.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-dark-mode)
* @example
* ```tsx
* const { isDarkMode, toggle, enable, disable, set } = useDarkMode({ defaultValue: true });
* ```
*/
declare function useDarkMode(options?: DarkModeOptions): DarkModeReturn;
/** Configuration options for controlling the behavior of the debounced function. */
type DebounceOptions = {
/**
* Determines whether the function should be invoked on the leading edge of the timeout.
* @default false
*/
leading?: boolean;
/**
* Determines whether the function should be invoked on the trailing edge of the timeout.
* @default false
*/
trailing?: boolean;
/**
* The maximum time the specified function is allowed to be delayed before it is invoked.
*/
maxWait?: number;
};
/** Functions to manage a debounced callback. */
type ControlFunctions = {
/** Cancels pending function invocations. */
cancel: () => void;
/** Immediately invokes pending function invocations. */
flush: () => void;
/**
* Checks if there are any pending function invocations.
* @returns `true` if there are pending invocations, otherwise `false`.
*/
isPending: () => boolean;
};
/**
* Represents the state and control functions of a debounced callback.
* Subsequent calls to the debounced function return the result of the last invocation.
* Note: If there are no previous invocations, the result will be undefined.
* Ensure proper handling in your code.
*/
type DebouncedState<T extends (...args: any) => ReturnType<T>> = ((...args: Parameters<T>) => ReturnType<T> | undefined) & ControlFunctions;
/**
* Custom hook that creates a debounced version of a callback function.
* @template T - Type of the original callback function.
* @param {T} func - The callback function to be debounced.
* @param {number} delay - The delay in milliseconds before the callback is invoked (default is `500` milliseconds).
* @param {DebounceOptions} [options] - Options to control the behavior of the debounced function.
* @returns {DebouncedState<T>} A debounced version of the original callback along with control functions.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-debounce-callback)
* @example
* ```tsx
* const debouncedCallback = useDebounceCallback(
* (searchTerm) => {
* // Perform search after user stops typing for 500 milliseconds
* searchApi(searchTerm);
* },
* 500
* );
*
* // Later in the component
* debouncedCallback('react hooks'); // Will invoke the callback after 500 milliseconds of inactivity.
* ```
*/
declare function useDebounceCallback<T extends (...args: any) => ReturnType<T>>(func: T, delay?: number, options?: DebounceOptions): DebouncedState<T>;
/**
* Hook options.
* @template T - The type of the value.
*/
type UseDebounceValueOptions<T> = {
/**
* Determines whether the function should be invoked on the leading edge of the timeout.
* @default false
*/
leading?: boolean;
/**
* Determines whether the function should be invoked on the trailing edge of the timeout.
* @default false
*/
trailing?: boolean;
/**
* The maximum time the specified function is allowed to be delayed before it is invoked.
*/
maxWait?: number;
/** A function to determine if the value has changed. Defaults to a function that checks if the value is strictly equal to the previous value. */
equalityFn?: (left: T, right: T) => boolean;
};
/**
* Custom hook that returns a debounced version of the provided value, along with a function to update it.
* @template T - The type of the value.
* @param {T | (() => T)} initialValue - The value to be debounced.
* @param {number} delay - The delay in milliseconds before the value is updated (default is 500ms).
* @param {object} [options] - Optional configurations for the debouncing behavior.
* @returns {[T, DebouncedState<(value: T) => void>]} An array containing the debounced value and the function to update it.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-debounce-value)
* @example
* ```tsx
* const [debouncedValue, updateDebouncedValue] = useDebounceValue(inputValue, 500, { leading: true });
* ```
*/
declare function useDebounceValue<T>(initialValue: T | (() => T), delay: number, options?: UseDebounceValueOptions<T>): [T, DebouncedState<(value: T) => void>];
/** Hook options. */
type UseDocumentTitleOptions = {
/** Whether to keep the title after unmounting the component (default is `true`). */
preserveTitleOnUnmount?: boolean;
};
/**
* Custom hook that sets the document title.
* @param {string} title - The title to set.
* @param {?UseDocumentTitleOptions} [options] - The options.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-document-title)
* @example
* ```tsx
* useDocumentTitle('My new title');
* ```
*/
declare function useDocumentTitle(title: string, options?: UseDocumentTitleOptions): void;
/**
* Custom hook that creates a memoized event callback.
* @template Args - An array of argument types for the event callback.
* @template R - The return type of the event callback.
* @param {(...args: Args) => R} fn - The callback function.
* @returns {(...args: Args) => R} A memoized event callback function.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-event-callback)
* @example
* ```tsx
* const handleClick = useEventCallback((event) => {
* // Handle the event here
* });
* ```
*/
declare function useEventCallback<Args extends unknown[], R>(fn: (...args: Args) => R): (...args: Args) => R;
declare function useEventCallback<Args extends unknown[], R>(fn: ((...args: Args) => R) | undefined): ((...args: Args) => R) | undefined;
declare function useEventListener<K extends keyof MediaQueryListEventMap>(eventName: K, handler: (event: MediaQueryListEventMap[K]) => void, element: RefObject<MediaQueryList>, options?: boolean | AddEventListenerOptions): void;
declare function useEventListener<K extends keyof WindowEventMap>(eventName: K, handler: (event: WindowEventMap[K]) => void, element?: undefined, options?: boolean | AddEventListenerOptions): void;
declare function useEventListener<K extends keyof HTMLElementEventMap & keyof SVGElementEventMap, T extends Element = K extends keyof HTMLElementEventMap ? HTMLDivElement : SVGElement>(eventName: K, handler: ((event: HTMLElementEventMap[K]) => void) | ((event: SVGElementEventMap[K]) => void), element: RefObject<T>, options?: boolean | AddEventListenerOptions): void;
declare function useEventListener<K extends keyof DocumentEventMap>(eventName: K, handler: (event: DocumentEventMap[K]) => void, element: RefObject<Document>, options?: boolean | AddEventListenerOptions): void;
/**
* Custom hook that tracks whether a DOM element is being hovered over.
* @template T - The type of the DOM element. Defaults to `HTMLElement`.
* @param {RefObject<T>} elementRef - The ref object for the DOM element to track.
* @returns {boolean} A boolean value indicating whether the element is being hovered over.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-hover)
* @example
* ```tsx
* const buttonRef = useRef<HTMLButtonElement>(null);
* const isHovered = useHover(buttonRef);
* // Access the isHovered variable to determine if the button is being hovered over.
* ```
*/
declare function useHover<T extends HTMLElement = HTMLElement>(elementRef: RefObject<T>): boolean;
/** Represents the options for configuring the Intersection Observer. */
type UseIntersectionObserverOptions = {
/**
* The element that is used as the viewport for checking visibility of the target.
* @default null
*/
root?: Element | Document | null;
/**
* A margin around the root.
* @default '0%'
*/
rootMargin?: string;
/**
* A threshold indicating the percentage of the target's visibility needed to trigger the callback.
* @default 0
*/
threshold?: number | number[];
/**
* If true, freezes the intersection state once the element becomes visible.
* @default false
*/
freezeOnceVisible?: boolean;
/**
* A callback function to be invoked when the intersection state changes.
* @param {boolean} isIntersecting - A boolean indicating if the element is intersecting.
* @param {IntersectionObserverEntry} entry - The intersection observer Entry.
* @default undefined
*/
onChange?: (isIntersecting: boolean, entry: IntersectionObserverEntry) => void;
/**
* The initial state of the intersection.
* @default false
*/
initialIsIntersecting?: boolean;
};
/**
* The return type of the useIntersectionObserver hook.
*
* Supports both tuple and object destructing.
* @param {(node: Element | null) => void} ref - The ref callback function.
* @param {boolean} isIntersecting - A boolean indicating if the element is intersecting.
* @param {IntersectionObserverEntry | undefined} entry - The intersection observer Entry.
*/
type IntersectionReturn = [
(node?: Element | null) => void,
boolean,
IntersectionObserverEntry | undefined
] & {
ref: (node?: Element | null) => void;
isIntersecting: boolean;
entry?: IntersectionObserverEntry;
};
/**
* Custom hook that tracks the intersection of a DOM element with its containing element or the viewport using the [`Intersection Observer API`](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API).
* @param {UseIntersectionObserverOptions} options - The options for the Intersection Observer.
* @returns {IntersectionReturn} The ref callback, a boolean indicating if the element is intersecting, and the intersection observer entry.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-intersection-observer)
* @example
* ```tsx
* // Example 1
* const [ref, isIntersecting, entry] = useIntersectionObserver({ threshold: 0.5 });
* ```
*
* ```tsx
* // Example 2
* const { ref, isIntersecting, entry } = useIntersectionObserver({ threshold: 0.5 });
* ```
*/
declare function useIntersectionObserver({ threshold, root, rootMargin, freezeOnceVisible, initialIsIntersecting, onChange, }?: UseIntersectionObserverOptions): IntersectionReturn;
/**
* Custom hook that creates an interval that invokes a callback function at a specified delay using the [`setInterval API`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval).
* @param {() => void} callback - The function to be invoked at each interval.
* @param {number | null} delay - The time, in milliseconds, between each invocation of the callback. Use `null` to clear the interval.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-interval)
* @example
* ```tsx
* const handleInterval = () => {
* // Code to be executed at each interval
* };
* useInterval(handleInterval, 1000);
* ```
*/
declare function useInterval(callback: () => void, delay: number | null): void;
/**
* Custom hook that determines if the code is running on the client side (in the browser).
* @returns {boolean} A boolean value indicating whether the code is running on the client side.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-is-client)
* @example
* ```tsx
* const isClient = useIsClient();
* // Use isClient to conditionally render or execute code specific to the client side.
* ```
*/
declare function useIsClient(): boolean;
/**
* Custom hook that determines if the component is currently mounted.
* @returns {() => boolean} A function that returns a boolean value indicating whether the component is mounted.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-is-mounted)
* @example
* ```tsx
* const isComponentMounted = useIsMounted();
* // Use isComponentMounted() to check if the component is currently mounted before performing certain actions.
* ```
*/
declare function useIsMounted(): () => boolean;
/**
* Custom hook that uses either `useLayoutEffect` or `useEffect` based on the environment (client-side or server-side).
* @param {Function} effect - The effect function to be executed.
* @param {Array<any>} [dependencies] - An array of dependencies for the effect (optional).
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-isomorphic-layout-effect)
* @example
* ```tsx
* useIsomorphicLayoutEffect(() => {
* // Code to be executed during the layout phase on the client side
* }, [dependency1, dependency2]);
* ```
*/
declare const useIsomorphicLayoutEffect: typeof useLayoutEffect;
declare global {
interface WindowEventMap {
'local-storage': CustomEvent;
}
}
/**
* Options for customizing the behavior of serialization and deserialization.
* @template T - The type of the state to be stored in local storage.
*/
type UseLocalStorageOptions<T> = {
/** A function to serialize the value before storing it. */
serializer?: (value: T) => string;
/** A function to deserialize the stored value. */
deserializer?: (value: string) => T;
/**
* If `true` (default), the hook will initialize reading the local storage. In SSR, you should set it to `false`, returning the initial value initially.
* @default true
*/
initializeWithValue?: boolean;
};
/**
* Custom hook that uses the [`localStorage API`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) to persist state across page reloads.
* @template T - The type of the state to be stored in local storage.
* @param {string} key - The key under which the value will be stored in local storage.
* @param {T | (() => T)} initialValue - The initial value of the state or a function that returns the initial value.
* @param {UseLocalStorageOptions<T>} [options] - Options for customizing the behavior of serialization and deserialization (optional).
* @returns {[T, Dispatch<SetStateAction<T>>, () => void]} A tuple containing the stored value, a function to set the value and a function to remove the key from storage.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-local-storage)
* @example
* ```tsx
* const [count, setCount, removeCount] = useLocalStorage('count', 0);
* // Access the `count` value, the `setCount` function to update it and `removeCount` function to remove the key from storage.
* ```
*/
declare function useLocalStorage<T>(key: string, initialValue: T | (() => T), options?: UseLocalStorageOptions<T>): [T, Dispatch<SetStateAction<T>>, () => void];
/**
* Represents the type for either a Map or an array of key-value pairs.
* @template K - The type of keys in the map.
* @template V - The type of values in the map.
*/
type MapOrEntries<K, V> = Map<K, V> | [K, V][];
/**
* Represents the actions available to interact with the map state.
* @template K - The type of keys in the map.
* @template V - The type of values in the map.
*/
type UseMapActions<K, V> = {
/** Set a key-value pair in the map. */
set: (key: K, value: V) => void;
/** Set all key-value pairs in the map. */
setAll: (entries: MapOrEntries<K, V>) => void;
/** Remove a key-value pair from the map. */
remove: (key: K) => void;
/** Reset the map to an empty state. */
reset: Map<K, V>['clear'];
};
/**
* Represents the return type of the `useMap` hook.
* We hide some setters from the returned map to disable autocompletion.
* @template K - The type of keys in the map.
* @template V - The type of values in the map.
*/
type UseMapReturn<K, V> = [
Omit<Map<K, V>, 'set' | 'clear' | 'delete'>,
UseMapActions<K, V>
];
/**
* Custom hook that manages a key-value [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) state with setter actions.
* @template K - The type of keys in the map.
* @template V - The type of values in the map.
* @param {MapOrEntries<K, V>} [initialState] - The initial state of the map as a Map or an array of key-value pairs (optional).
* @returns {UseMapReturn<K, V>} A tuple containing the map state and actions to interact with the map.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-map)
* @example
* ```tsx
* const [map, mapActions] = useMap();
* // Access the `map` state and use `mapActions` to set, remove, or reset entries.
* ```
*/
declare function useMap<K, V>(initialState?: MapOrEntries<K, V>): UseMapReturn<K, V>;
/** Hook options. */
type UseMediaQueryOptions = {
/**
* The default value to return if the hook is being run on the server.
* @default false
*/
defaultValue?: boolean;
/**
* If `true` (default), the hook will initialize reading the media query. In SSR, you should set it to `false`, returning `options.defaultValue` or `false` initially.
* @default true
*/
initializeWithValue?: boolean;
};
/**
* Custom hook that tracks the state of a media query using the [`Match Media API`](https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia).
* @param {string} query - The media query to track.
* @param {?UseMediaQueryOptions} [options] - The options for customizing the behavior of the hook (optional).
* @returns {boolean} The current state of the media query (true if the query matches, false otherwise).
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-media-query)
* @example
* ```tsx
* const isSmallScreen = useMediaQuery('(max-width: 600px)');
* // Use `isSmallScreen` to conditionally apply styles or logic based on the screen size.
* ```
*/
declare function useMediaQuery(query: string, { defaultValue, initializeWithValue, }?: UseMediaQueryOptions): boolean;
/** Supported event types. */
type EventType = 'mousedown' | 'mouseup' | 'touchstart' | 'touchend' | 'focusin' | 'focusout';
/**
* Custom hook that handles clicks outside a specified element.
* @template T - The type of the element's reference.
* @param {RefObject<T> | RefObject<T>[]} ref - The React ref object(s) representing the element(s) to watch for outside clicks.
* @param {(event: MouseEvent | TouchEvent | FocusEvent) => void} handler - The callback function to be executed when a click outside the element occurs.
* @param {EventType} [eventType] - The mouse event type to listen for (optional, default is 'mousedown').
* @param {?AddEventListenerOptions} [eventListenerOptions] - The options object to be passed to the `addEventListener` method (optional).
* @returns {void}
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-on-click-outside)
* @example
* ```tsx
* const containerRef = useRef(null);
* useOnClickOutside([containerRef], () => {
* // Handle clicks outside the container.
* });
* ```
*/
declare function useOnClickOutside<T extends HTMLElement = HTMLElement>(ref: RefObject<T> | RefObject<T>[], handler: (event: MouseEvent | TouchEvent | FocusEvent) => void, eventType?: EventType, eventListenerOptions?: AddEventListenerOptions): void;
/**
* Represents the type for the options available when reading from local storage.
* @template T - The type of the stored value.
*/
type Options<T, InitializeWithValue extends boolean | undefined> = {
/** Custom deserializer function to convert the stored string value to the desired type (optional). */
deserializer?: (value: string) => T;
/** If `true` (default), the hook will initialize reading the local storage. In SSR, you should set it to `false`, returning `undefined` initially. */
initializeWithValue: InitializeWithValue;
};
declare function useReadLocalStorage<T>(key: string, options: Options<T, false>): T | null | undefined;
declare function useReadLocalStorage<T>(key: string, options?: Partial<Options<T, true>>): T | null;
/** The size of the observed element. */
type Size = {
/** The width of the observed element. */
width: number | undefined;
/** The height of the observed element. */
height: number | undefined;
};
/** The options for the ResizeObserver. */
type UseResizeObserverOptions<T extends HTMLElement = HTMLElement> = {
/** The ref of the element to observe. */
ref: RefObject<T>;
/**
* When using `onResize`, the hook doesn't re-render on element size changes; it delegates handling to the provided callback.
* @default undefined
*/
onResize?: (size: Size) => void;
/**
* The box model to use for the ResizeObserver.
* @default 'content-box'
*/
box?: 'border-box' | 'content-box' | 'device-pixel-content-box';
};
/**
* Custom hook that observes the size of an element using the [`ResizeObserver API`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver).
* @template T - The type of the element to observe.
* @param {UseResizeObserverOptions<T>} options - The options for the ResizeObserver.
* @returns {Size} - The size of the observed element.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-resize-observer)
* @example
* ```tsx
* const myRef = useRef(null);
* const { width = 0, height = 0 } = useResizeObserver({
* ref: myRef,
* box: 'content-box',
* });
*
* <div ref={myRef}>Hello, world!</div>
* ```
*/
declare function useResizeObserver<T extends HTMLElement = HTMLElement>(options: UseResizeObserverOptions<T>): Size;
/**
* The hooks options.
* @template InitializeWithValue - If `true` (default), the hook will initialize reading the screen dimensions. In SSR, you should set it to `false`, returning `undefined` initially.
*/
type UseScreenOptions<InitializeWithValue extends boolean | undefined> = {
/**
* If `true` (default), the hook will initialize reading the screen dimensions. In SSR, you should set it to `false`, returning `undefined` initially.
* @default true
*/
initializeWithValue: InitializeWithValue;
/**
* The delay in milliseconds before the state is updated (disabled by default for retro-compatibility).
* @default undefined
*/
debounceDelay?: number;
};
declare function useScreen(options: UseScreenOptions<false>): Screen | undefined;
declare function useScreen(options?: Partial<UseScreenOptions<true>>): Screen;
/** Script loading status. */
type UseScriptStatus = 'idle' | 'loading' | 'ready' | 'error';
/** Hook options. */
type UseScriptOptions = {
/** If `true`, prevents the script from being loaded (optional). */
shouldPreventLoad?: boolean;
/** If `true`, removes the script from the DOM when the component unmounts (optional). */
removeOnUnmount?: boolean;
/** Script's `id` (optional). */
id?: string;
};
/**
* Custom hook that dynamically loads scripts and tracking their loading status.
* @param {string | null} src - The source URL of the script to load. Set to `null` or omit to prevent loading (optional).
* @param {UseScriptOptions} [options] - Additional options for controlling script loading (optional).
* @returns {UseScriptStatus} The status of the script loading, which can be one of 'idle', 'loading', 'ready', or 'error'.
* @see [Documentation](https://usehooks-ts.com/react-hook/use-script)
* @example
* const scriptStatus = useScript('https://example.com/script.js', { removeOnUnmount: true });
* // Access the status of the script loading (e.g., 'loading', 'ready', 'error').
*/
declare function useScript(src: string | null, options?: UseScriptOptions): UseScriptStatus;
/** Hook options. */
type UseScrollLockOptions = {
/**
* Whether to lock the scroll initially.
* @default true
*/
autoLock?: boolean;
/**
* The target element to lock the scroll (default is the body element).
* @default document.body
*/
lockTarget?: HTMLElement | string;
/**
* Whether to prevent width reflow when locking the scroll.
* @default true
*/
widthReflow?: boolean;
};
/** Hook return type. */
type UseScrollLockReturn = {
/** Whether the scroll is locked. */
isLocked: boolean;
/** Lock the scroll. */
lock: () => void;
/** Unlock the scroll. */
unlock: () => void;
};
/**
* A custom hook that locks and unlocks scroll.
* @param {UseScrollLockOptions} [options] - Options to configure the hook, by default it will lock the scroll automatically.
* @returns {UseScrollLockReturn} - An object containing the lock and unlock functions.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-scroll-lock)
* @example
* ```tsx
* // Lock the scroll when the modal is mounted, and unlock it when it's unmounted
* useScrollLock()
* ```
* @example
* ```tsx
* // Manually lock and unlock the scroll
* const { lock, unlock } = useScrollLock({ autoLock: false })
*
* return (
* <div>
* <button onClick={lock}>Lock</button>
* <button onClick={unlock}>Unlock</button>
* </div>
* )
* ```
*/
declare function useScrollLock(options?: UseScrollLockOptions): UseScrollLockReturn;
declare global {
interface WindowEventMap {
'session-storage': CustomEvent;
}
}
/**
* Represents the options for customizing the behavior of serialization and deserialization.
* @template T - The type of the state to be stored in session storage.
*/
type UseSessionStorageOptions<T> = {
/** A function to serialize the value before storing it. */
serializer?: (value: T) => string;
/** A function to deserialize the stored value. */
deserializer?: (value: string) => T;
/**
* If `true` (default), the hook will initialize reading the session storage. In SSR, you should set it to `false`, returning the initial value initially.
* @default true
*/
initializeWithValue?: boolean;
};
/**
* Custom hook that uses the [`sessionStorage API`](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage) to persist state across page reloads.
* @template T - The type of the state to be stored in session storage.
* @param {string} key - The key under which the value will be stored in session storage.
* @param {T | (() => T)} initialValue - The initial value of the state or a function that returns the initial value.
* @param {?UseSessionStorageOptions<T>} [options] - Options for customizing the behavior of serialization and deserialization (optional).
* @returns {[T, Dispatch<SetStateAction<T>>, () => void]} A tuple containing the stored value, a function to set the value and a function to remove the key from storage.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-session-storage)
* @example
* ```tsx
* const [count, setCount, removeCount] = useSessionStorage('count', 0);
* // Access the `count` value, the `setCount` function to update it and `removeCount` function to remove the key from storage.
* ```
*/
declare function useSessionStorage<T>(key: string, initialValue: T | (() => T), options?: UseSessionStorageOptions<T>): [T, Dispatch<SetStateAction<T>>, () => void];
/** Represents the second element of the output of the `useStep` hook. */
type UseStepActions = {
/** Go to the next step in the process. */
goToNextStep: () => void;
/** Go to the previous step in the process. */
goToPrevStep: () => void;
/** Reset the step to the initial step. */
reset: () => void;
/** Check if the next step is available. */
canGoToNextStep: boolean;
/** Check if the previous step is available. */
canGoToPrevStep: boolean;
/** Set the current step to a specific value. */
setStep: Dispatch<SetStateAction<number>>;
};
/**
* Custom hook that manages and navigates between steps in a multi-step process.
* @param {number} maxStep - The maximum step in the process.
* @returns {[number, UseStepActions]} An tuple containing the current step and helper functions for navigating steps.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-step)
* @example
* ```tsx
* const [currentStep, { goToNextStep, goToPrevStep, reset, canGoToNextStep, canGoToPrevStep, setStep }] = useStep(3);
* // Access and use the current step and provided helper functions.
* ```
*/
declare function useStep(maxStep: number): [number, UseStepActions];
/** Ternary dark mode options. */
type TernaryDarkMode = 'system' | 'dark' | 'light';
/** Options for the `useTernaryDarkMode` hook. */
type TernaryDarkModeOptions = {
/**
* The default value for the dark mode.
* @default 'system'
*/
defaultValue?: TernaryDarkMode;
/**
* The key for storing dark mode preference in local storage.
* @default 'usehooks-ts-ternary-dark-mode'
*/
localStorageKey?: string;
/**
* If `true` (default), the hook will initialize reading `localStorage`. In SSR, you should set it to `false`, returning default values initially.
* @default true
*/
initializeWithValue?: boolean;
};
/** Represents the return type of the `useTernaryDarkMode` hook. */
type TernaryDarkModeReturn = {
/** The current state of the dark mode. */
isDarkMode: boolean;
/** The current state of the dark mode. */
ternaryDarkMode: TernaryDarkMode;
/** A function to set the dark mode state. */
setTernaryDarkMode: Dispatch<SetStateAction<TernaryDarkMode>>;
/** A function to toggle the dark mode state. */
toggleTernaryDarkMode: () => void;
};
/**
* Custom hook that manages ternary (system, dark, light) dark mode with local storage support.
* @param {?TernaryDarkModeOptions | string} [options] - Options or the local storage key for the hook.
* @returns {TernaryDarkModeReturn} An object containing the dark mode state and helper functions.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-ternary-dark-mode)
* @example
* ```tsx
* const { isDarkMode, ternaryDarkMode, setTernaryDarkMode, toggleTernaryDarkMode } = useTernaryDarkMode({ defaultValue: 'dark' });
* // Access and use the dark mode state and provided helper functions.
* ```
*/
declare function useTernaryDarkMode({ defaultValue, localStorageKey, initializeWithValue, }?: TernaryDarkModeOptions): TernaryDarkModeReturn;
/**
* Custom hook that handles timeouts in React components using the [`setTimeout API`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout).
* @param {() => void} callback - The function to be executed when the timeout elapses.
* @param {number | null} delay - The duration (in milliseconds) for the timeout. Set to `null` to clear the timeout.
* @returns {void} This hook does not return anything.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-timeout)
* @example
* ```tsx
* // Usage of useTimeout hook
* useTimeout(() => {
* // Code to be executed after the specified delay
* }, 1000); // Set a timeout of 1000 milliseconds (1 second)
* ```
*/
declare function useTimeout(callback: () => void, delay: number | null): void;
/**
* Custom hook that manages a boolean toggle state in React components.
* @param {boolean} [defaultValue] - The initial value for the toggle state.
* @returns {[boolean, () => void, Dispatch<SetStateAction<boolean>>]} A tuple containing the current state,
* a function to toggle the state, and a function to set the state explicitly.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-toggle)
* @example
* ```tsx
* const [isToggled, toggle, setToggle] = useToggle(); // Initial value is false
* // OR
* const [isToggled, toggle, setToggle] = useToggle(true); // Initial value is true
* // Use isToggled in your component, toggle to switch the state, setToggle to set the state explicitly.
* ```
*/
declare function useToggle(defaultValue?: boolean): [boolean, () => void, Dispatch<SetStateAction<boolean>>];
/**
* Custom hook that runs a cleanup function when the component is unmounted.
* @param {() => void} func - The cleanup function to be executed on unmount.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-unmount)
* @example
* ```tsx
* useUnmount(() => {
* // Cleanup logic here
* });
* ```
*/
declare function useUnmount(func: () => void): void;
/**
* Represent the dimension of the window.
* @template T - The type of the dimension (number or undefined).
*/
type WindowSize<T extends number | undefined = number | undefined> = {
/** The width of the window. */
width: T;
/** The height of the window. */
height: T;
};
/**
* Hook options.
* @template InitializeWithValue - If `true` (default), the hook will initialize reading the window size. In SSR, you should set it to `false`, returning `undefined` initially.
*/
type UseWindowSizeOptions<InitializeWithValue extends boolean | undefined> = {
/**
* If `true` (default), the hook will initialize reading the window size. In SSR, you should set it to `false`, returning `undefined` initially.
* @default true
*/
initializeWithValue: InitializeWithValue;
/**
* The delay in milliseconds before the state is updated (disabled by default for retro-compatibility).
* @default undefined
*/
debounceDelay?: number;
};
declare function useWindowSize(options: UseWindowSizeOptions<false>): WindowSize;
declare function useWindowSize(options?: Partial<UseWindowSizeOptions<true>>): WindowSize<number>;
export { type DebouncedState, type TernaryDarkMode, type TernaryDarkModeOptions, type TernaryDarkModeReturn, useBoolean, useClickAnyWhere, useCopyToClipboard, useCountdown, useCounter, useDarkMode, useDebounceCallback, useDebounceValue, useDocumentTitle, useEventCallback, useEventListener, useHover, useIntersectionObserver, useInterval, useIsClient, useIsMounted, useIsomorphicLayoutEffect, useLocalStorage, useMap, useMediaQuery, useOnClickOutside, useReadLocalStorage, useResizeObserver, useScreen, useScript, useScrollLock, useSessionStorage, useStep, useTernaryDarkMode, useTimeout, useToggle, useUnmount, useWindowSize };

View File

@@ -0,0 +1,953 @@
import { Dispatch, SetStateAction, RefObject, useLayoutEffect } from 'react';
/** The useBoolean return type. */
type UseBooleanReturn = {
/** The current boolean state value. */
value: boolean;
/** Function to set the boolean state directly. */
setValue: Dispatch<SetStateAction<boolean>>;
/** Function to set the boolean state to `true`. */
setTrue: () => void;
/** Function to set the boolean state to `false`. */
setFalse: () => void;
/** Function to toggle the boolean state. */
toggle: () => void;
};
/**
* Custom hook that handles boolean state with useful utility functions.
* @param {boolean} [defaultValue] - The initial value for the boolean state (default is `false`).
* @returns {UseBooleanReturn} An object containing the boolean state value and utility functions to manipulate the state.
* @throws Will throw an error if `defaultValue` is an invalid boolean value.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-boolean)
* @example
* ```tsx
* const { value, setTrue, setFalse, toggle } = useBoolean(true);
* ```
*/
declare function useBoolean(defaultValue?: boolean): UseBooleanReturn;
/**
* Custom hook that handles click events anywhere on the document.
* @param {Function} handler - The function to be called when a click event is detected anywhere on the document.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-click-any-where)
* @example
* ```tsx
* const handleClick = (event) => {
* console.log('Document clicked!', event);
* };
*
* // Attach click event handler to document
* useClickAnywhere(handleClick);
* ```
*/
declare function useClickAnyWhere(handler: (event: MouseEvent) => void): void;
/**
* The copied text as `string` or `null` if nothing has been copied yet.
*/
type CopiedValue = string | null;
/**
* Function to copy text to the clipboard.
* @param text - The text to copy to the clipboard.
* @returns {Promise<boolean>} A promise that resolves to `true` if the text was copied successfully, or `false` otherwise.
*/
type CopyFn = (text: string) => Promise<boolean>;
/**
* Custom hook that copies text to the clipboard using the [`Clipboard API`](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API).
* @returns {[CopiedValue, CopyFn]} An tuple containing the copied text and a function to copy text to the clipboard.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-copy-to-clipboard)
* @example
* ```tsx
* const [copiedText, copyToClipboard] = useCopyToClipboard();
* const textToCopy = 'Hello, world!';
*
* // Attempt to copy text to the clipboard
* copyToClipboard(textToCopy)
* .then(success => {
* if (success) {
* console.log(`Text "${textToCopy}" copied to clipboard successfully.`);
* } else {
* console.error('Failed to copy text to clipboard.');
* }
* });
* ```
*/
declare function useCopyToClipboard(): [CopiedValue, CopyFn];
/** The countdown's options. */
type CountdownOptions = {
/** The countdown's starting number, initial value of the returned number. */
countStart: number;
/**
* The countdown's interval, in milliseconds.
* @default 1000
*/
intervalMs?: number;
/**
* True if the countdown is increment.
* @default false
*/
isIncrement?: boolean;
/**
* The countdown's stopping number. Pass `-Infinity` to decrease forever.
* @default 0
*/
countStop?: number;
};
/** The countdown's controllers. */
type CountdownControllers = {
/** Start the countdown. */
startCountdown: () => void;
/** Stop the countdown. */
stopCountdown: () => void;
/** Reset the countdown. */
resetCountdown: () => void;
};
/**
* Custom hook that manages countdown.
* @param {CountdownOptions} countdownOptions - The countdown's options.
* @returns {[number, CountdownControllers]} An array containing the countdown's count and its controllers.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-countdown)
* @example
* ```tsx
* const [counter, { start, stop, reset }] = useCountdown({
* countStart: 10,
* intervalMs: 1000,
* isIncrement: false,
* });
* ```
*/
declare function useCountdown({ countStart, countStop, intervalMs, isIncrement, }: CountdownOptions): [number, CountdownControllers];
/** The hook return type. */
type UseCounterReturn = {
/** The current count value. */
count: number;
/** Function to increment the counter by 1. */
increment: () => void;
/** Function to decrement the counter by 1. */
decrement: () => void;
/** Function to reset the counter to its initial value. */
reset: () => void;
/** Function to set a specific value to the counter. */
setCount: Dispatch<SetStateAction<number>>;
};
/**
* Custom hook that manages a counter with increment, decrement, reset, and setCount functionalities.
* @param {number} [initialValue] - The initial value for the counter.
* @returns {UseCounterReturn} An object containing the current count and functions to interact with the counter.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-counter)
* @example
* ```tsx
* const { count, increment, decrement, reset, setCount } = useCounter(5);
* ```
*/
declare function useCounter(initialValue?: number): UseCounterReturn;
/** The hook options. */
type DarkModeOptions = {
/**
* The initial value of the dark mode.
* @default false
*/
defaultValue?: boolean;
/**
* The key to use in the local storage.
* @default 'usehooks-ts-dark-mode'
*/
localStorageKey?: string;
/**
* If `true` (default), the hook will initialize reading `localStorage`.
* In SSR, you should set it to `false`, returning the `defaultValue` or `false` initially.
* @default true
*/
initializeWithValue?: boolean;
};
/** The hook return type. */
type DarkModeReturn = {
/** The current state of the dark mode. */
isDarkMode: boolean;
/** Function to toggle the dark mode. */
toggle: () => void;
/** Function to enable the dark mode. */
enable: () => void;
/** Function to disable the dark mode. */
disable: () => void;
/** Function to set a specific value to the dark mode. */
set: (value: boolean) => void;
};
/**
* Custom hook that returns the current state of the dark mode.
* @param {?DarkModeOptions} [options] - The initial value of the dark mode, default `false`.
* @returns {DarkModeReturn} An object containing the dark mode's state and its controllers.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-dark-mode)
* @example
* ```tsx
* const { isDarkMode, toggle, enable, disable, set } = useDarkMode({ defaultValue: true });
* ```
*/
declare function useDarkMode(options?: DarkModeOptions): DarkModeReturn;
/** Configuration options for controlling the behavior of the debounced function. */
type DebounceOptions = {
/**
* Determines whether the function should be invoked on the leading edge of the timeout.
* @default false
*/
leading?: boolean;
/**
* Determines whether the function should be invoked on the trailing edge of the timeout.
* @default false
*/
trailing?: boolean;
/**
* The maximum time the specified function is allowed to be delayed before it is invoked.
*/
maxWait?: number;
};
/** Functions to manage a debounced callback. */
type ControlFunctions = {
/** Cancels pending function invocations. */
cancel: () => void;
/** Immediately invokes pending function invocations. */
flush: () => void;
/**
* Checks if there are any pending function invocations.
* @returns `true` if there are pending invocations, otherwise `false`.
*/
isPending: () => boolean;
};
/**
* Represents the state and control functions of a debounced callback.
* Subsequent calls to the debounced function return the result of the last invocation.
* Note: If there are no previous invocations, the result will be undefined.
* Ensure proper handling in your code.
*/
type DebouncedState<T extends (...args: any) => ReturnType<T>> = ((...args: Parameters<T>) => ReturnType<T> | undefined) & ControlFunctions;
/**
* Custom hook that creates a debounced version of a callback function.
* @template T - Type of the original callback function.
* @param {T} func - The callback function to be debounced.
* @param {number} delay - The delay in milliseconds before the callback is invoked (default is `500` milliseconds).
* @param {DebounceOptions} [options] - Options to control the behavior of the debounced function.
* @returns {DebouncedState<T>} A debounced version of the original callback along with control functions.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-debounce-callback)
* @example
* ```tsx
* const debouncedCallback = useDebounceCallback(
* (searchTerm) => {
* // Perform search after user stops typing for 500 milliseconds
* searchApi(searchTerm);
* },
* 500
* );
*
* // Later in the component
* debouncedCallback('react hooks'); // Will invoke the callback after 500 milliseconds of inactivity.
* ```
*/
declare function useDebounceCallback<T extends (...args: any) => ReturnType<T>>(func: T, delay?: number, options?: DebounceOptions): DebouncedState<T>;
/**
* Hook options.
* @template T - The type of the value.
*/
type UseDebounceValueOptions<T> = {
/**
* Determines whether the function should be invoked on the leading edge of the timeout.
* @default false
*/
leading?: boolean;
/**
* Determines whether the function should be invoked on the trailing edge of the timeout.
* @default false
*/
trailing?: boolean;
/**
* The maximum time the specified function is allowed to be delayed before it is invoked.
*/
maxWait?: number;
/** A function to determine if the value has changed. Defaults to a function that checks if the value is strictly equal to the previous value. */
equalityFn?: (left: T, right: T) => boolean;
};
/**
* Custom hook that returns a debounced version of the provided value, along with a function to update it.
* @template T - The type of the value.
* @param {T | (() => T)} initialValue - The value to be debounced.
* @param {number} delay - The delay in milliseconds before the value is updated (default is 500ms).
* @param {object} [options] - Optional configurations for the debouncing behavior.
* @returns {[T, DebouncedState<(value: T) => void>]} An array containing the debounced value and the function to update it.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-debounce-value)
* @example
* ```tsx
* const [debouncedValue, updateDebouncedValue] = useDebounceValue(inputValue, 500, { leading: true });
* ```
*/
declare function useDebounceValue<T>(initialValue: T | (() => T), delay: number, options?: UseDebounceValueOptions<T>): [T, DebouncedState<(value: T) => void>];
/** Hook options. */
type UseDocumentTitleOptions = {
/** Whether to keep the title after unmounting the component (default is `true`). */
preserveTitleOnUnmount?: boolean;
};
/**
* Custom hook that sets the document title.
* @param {string} title - The title to set.
* @param {?UseDocumentTitleOptions} [options] - The options.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-document-title)
* @example
* ```tsx
* useDocumentTitle('My new title');
* ```
*/
declare function useDocumentTitle(title: string, options?: UseDocumentTitleOptions): void;
/**
* Custom hook that creates a memoized event callback.
* @template Args - An array of argument types for the event callback.
* @template R - The return type of the event callback.
* @param {(...args: Args) => R} fn - The callback function.
* @returns {(...args: Args) => R} A memoized event callback function.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-event-callback)
* @example
* ```tsx
* const handleClick = useEventCallback((event) => {
* // Handle the event here
* });
* ```
*/
declare function useEventCallback<Args extends unknown[], R>(fn: (...args: Args) => R): (...args: Args) => R;
declare function useEventCallback<Args extends unknown[], R>(fn: ((...args: Args) => R) | undefined): ((...args: Args) => R) | undefined;
declare function useEventListener<K extends keyof MediaQueryListEventMap>(eventName: K, handler: (event: MediaQueryListEventMap[K]) => void, element: RefObject<MediaQueryList>, options?: boolean | AddEventListenerOptions): void;
declare function useEventListener<K extends keyof WindowEventMap>(eventName: K, handler: (event: WindowEventMap[K]) => void, element?: undefined, options?: boolean | AddEventListenerOptions): void;
declare function useEventListener<K extends keyof HTMLElementEventMap & keyof SVGElementEventMap, T extends Element = K extends keyof HTMLElementEventMap ? HTMLDivElement : SVGElement>(eventName: K, handler: ((event: HTMLElementEventMap[K]) => void) | ((event: SVGElementEventMap[K]) => void), element: RefObject<T>, options?: boolean | AddEventListenerOptions): void;
declare function useEventListener<K extends keyof DocumentEventMap>(eventName: K, handler: (event: DocumentEventMap[K]) => void, element: RefObject<Document>, options?: boolean | AddEventListenerOptions): void;
/**
* Custom hook that tracks whether a DOM element is being hovered over.
* @template T - The type of the DOM element. Defaults to `HTMLElement`.
* @param {RefObject<T>} elementRef - The ref object for the DOM element to track.
* @returns {boolean} A boolean value indicating whether the element is being hovered over.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-hover)
* @example
* ```tsx
* const buttonRef = useRef<HTMLButtonElement>(null);
* const isHovered = useHover(buttonRef);
* // Access the isHovered variable to determine if the button is being hovered over.
* ```
*/
declare function useHover<T extends HTMLElement = HTMLElement>(elementRef: RefObject<T>): boolean;
/** Represents the options for configuring the Intersection Observer. */
type UseIntersectionObserverOptions = {
/**
* The element that is used as the viewport for checking visibility of the target.
* @default null
*/
root?: Element | Document | null;
/**
* A margin around the root.
* @default '0%'
*/
rootMargin?: string;
/**
* A threshold indicating the percentage of the target's visibility needed to trigger the callback.
* @default 0
*/
threshold?: number | number[];
/**
* If true, freezes the intersection state once the element becomes visible.
* @default false
*/
freezeOnceVisible?: boolean;
/**
* A callback function to be invoked when the intersection state changes.
* @param {boolean} isIntersecting - A boolean indicating if the element is intersecting.
* @param {IntersectionObserverEntry} entry - The intersection observer Entry.
* @default undefined
*/
onChange?: (isIntersecting: boolean, entry: IntersectionObserverEntry) => void;
/**
* The initial state of the intersection.
* @default false
*/
initialIsIntersecting?: boolean;
};
/**
* The return type of the useIntersectionObserver hook.
*
* Supports both tuple and object destructing.
* @param {(node: Element | null) => void} ref - The ref callback function.
* @param {boolean} isIntersecting - A boolean indicating if the element is intersecting.
* @param {IntersectionObserverEntry | undefined} entry - The intersection observer Entry.
*/
type IntersectionReturn = [
(node?: Element | null) => void,
boolean,
IntersectionObserverEntry | undefined
] & {
ref: (node?: Element | null) => void;
isIntersecting: boolean;
entry?: IntersectionObserverEntry;
};
/**
* Custom hook that tracks the intersection of a DOM element with its containing element or the viewport using the [`Intersection Observer API`](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API).
* @param {UseIntersectionObserverOptions} options - The options for the Intersection Observer.
* @returns {IntersectionReturn} The ref callback, a boolean indicating if the element is intersecting, and the intersection observer entry.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-intersection-observer)
* @example
* ```tsx
* // Example 1
* const [ref, isIntersecting, entry] = useIntersectionObserver({ threshold: 0.5 });
* ```
*
* ```tsx
* // Example 2
* const { ref, isIntersecting, entry } = useIntersectionObserver({ threshold: 0.5 });
* ```
*/
declare function useIntersectionObserver({ threshold, root, rootMargin, freezeOnceVisible, initialIsIntersecting, onChange, }?: UseIntersectionObserverOptions): IntersectionReturn;
/**
* Custom hook that creates an interval that invokes a callback function at a specified delay using the [`setInterval API`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval).
* @param {() => void} callback - The function to be invoked at each interval.
* @param {number | null} delay - The time, in milliseconds, between each invocation of the callback. Use `null` to clear the interval.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-interval)
* @example
* ```tsx
* const handleInterval = () => {
* // Code to be executed at each interval
* };
* useInterval(handleInterval, 1000);
* ```
*/
declare function useInterval(callback: () => void, delay: number | null): void;
/**
* Custom hook that determines if the code is running on the client side (in the browser).
* @returns {boolean} A boolean value indicating whether the code is running on the client side.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-is-client)
* @example
* ```tsx
* const isClient = useIsClient();
* // Use isClient to conditionally render or execute code specific to the client side.
* ```
*/
declare function useIsClient(): boolean;
/**
* Custom hook that determines if the component is currently mounted.
* @returns {() => boolean} A function that returns a boolean value indicating whether the component is mounted.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-is-mounted)
* @example
* ```tsx
* const isComponentMounted = useIsMounted();
* // Use isComponentMounted() to check if the component is currently mounted before performing certain actions.
* ```
*/
declare function useIsMounted(): () => boolean;
/**
* Custom hook that uses either `useLayoutEffect` or `useEffect` based on the environment (client-side or server-side).
* @param {Function} effect - The effect function to be executed.
* @param {Array<any>} [dependencies] - An array of dependencies for the effect (optional).
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-isomorphic-layout-effect)
* @example
* ```tsx
* useIsomorphicLayoutEffect(() => {
* // Code to be executed during the layout phase on the client side
* }, [dependency1, dependency2]);
* ```
*/
declare const useIsomorphicLayoutEffect: typeof useLayoutEffect;
declare global {
interface WindowEventMap {
'local-storage': CustomEvent;
}
}
/**
* Options for customizing the behavior of serialization and deserialization.
* @template T - The type of the state to be stored in local storage.
*/
type UseLocalStorageOptions<T> = {
/** A function to serialize the value before storing it. */
serializer?: (value: T) => string;
/** A function to deserialize the stored value. */
deserializer?: (value: string) => T;
/**
* If `true` (default), the hook will initialize reading the local storage. In SSR, you should set it to `false`, returning the initial value initially.
* @default true
*/
initializeWithValue?: boolean;
};
/**
* Custom hook that uses the [`localStorage API`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) to persist state across page reloads.
* @template T - The type of the state to be stored in local storage.
* @param {string} key - The key under which the value will be stored in local storage.
* @param {T | (() => T)} initialValue - The initial value of the state or a function that returns the initial value.
* @param {UseLocalStorageOptions<T>} [options] - Options for customizing the behavior of serialization and deserialization (optional).
* @returns {[T, Dispatch<SetStateAction<T>>, () => void]} A tuple containing the stored value, a function to set the value and a function to remove the key from storage.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-local-storage)
* @example
* ```tsx
* const [count, setCount, removeCount] = useLocalStorage('count', 0);
* // Access the `count` value, the `setCount` function to update it and `removeCount` function to remove the key from storage.
* ```
*/
declare function useLocalStorage<T>(key: string, initialValue: T | (() => T), options?: UseLocalStorageOptions<T>): [T, Dispatch<SetStateAction<T>>, () => void];
/**
* Represents the type for either a Map or an array of key-value pairs.
* @template K - The type of keys in the map.
* @template V - The type of values in the map.
*/
type MapOrEntries<K, V> = Map<K, V> | [K, V][];
/**
* Represents the actions available to interact with the map state.
* @template K - The type of keys in the map.
* @template V - The type of values in the map.
*/
type UseMapActions<K, V> = {
/** Set a key-value pair in the map. */
set: (key: K, value: V) => void;
/** Set all key-value pairs in the map. */
setAll: (entries: MapOrEntries<K, V>) => void;
/** Remove a key-value pair from the map. */
remove: (key: K) => void;
/** Reset the map to an empty state. */
reset: Map<K, V>['clear'];
};
/**
* Represents the return type of the `useMap` hook.
* We hide some setters from the returned map to disable autocompletion.
* @template K - The type of keys in the map.
* @template V - The type of values in the map.
*/
type UseMapReturn<K, V> = [
Omit<Map<K, V>, 'set' | 'clear' | 'delete'>,
UseMapActions<K, V>
];
/**
* Custom hook that manages a key-value [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) state with setter actions.
* @template K - The type of keys in the map.
* @template V - The type of values in the map.
* @param {MapOrEntries<K, V>} [initialState] - The initial state of the map as a Map or an array of key-value pairs (optional).
* @returns {UseMapReturn<K, V>} A tuple containing the map state and actions to interact with the map.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-map)
* @example
* ```tsx
* const [map, mapActions] = useMap();
* // Access the `map` state and use `mapActions` to set, remove, or reset entries.
* ```
*/
declare function useMap<K, V>(initialState?: MapOrEntries<K, V>): UseMapReturn<K, V>;
/** Hook options. */
type UseMediaQueryOptions = {
/**
* The default value to return if the hook is being run on the server.
* @default false
*/
defaultValue?: boolean;
/**
* If `true` (default), the hook will initialize reading the media query. In SSR, you should set it to `false`, returning `options.defaultValue` or `false` initially.
* @default true
*/
initializeWithValue?: boolean;
};
/**
* Custom hook that tracks the state of a media query using the [`Match Media API`](https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia).
* @param {string} query - The media query to track.
* @param {?UseMediaQueryOptions} [options] - The options for customizing the behavior of the hook (optional).
* @returns {boolean} The current state of the media query (true if the query matches, false otherwise).
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-media-query)
* @example
* ```tsx
* const isSmallScreen = useMediaQuery('(max-width: 600px)');
* // Use `isSmallScreen` to conditionally apply styles or logic based on the screen size.
* ```
*/
declare function useMediaQuery(query: string, { defaultValue, initializeWithValue, }?: UseMediaQueryOptions): boolean;
/** Supported event types. */
type EventType = 'mousedown' | 'mouseup' | 'touchstart' | 'touchend' | 'focusin' | 'focusout';
/**
* Custom hook that handles clicks outside a specified element.
* @template T - The type of the element's reference.
* @param {RefObject<T> | RefObject<T>[]} ref - The React ref object(s) representing the element(s) to watch for outside clicks.
* @param {(event: MouseEvent | TouchEvent | FocusEvent) => void} handler - The callback function to be executed when a click outside the element occurs.
* @param {EventType} [eventType] - The mouse event type to listen for (optional, default is 'mousedown').
* @param {?AddEventListenerOptions} [eventListenerOptions] - The options object to be passed to the `addEventListener` method (optional).
* @returns {void}
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-on-click-outside)
* @example
* ```tsx
* const containerRef = useRef(null);
* useOnClickOutside([containerRef], () => {
* // Handle clicks outside the container.
* });
* ```
*/
declare function useOnClickOutside<T extends HTMLElement = HTMLElement>(ref: RefObject<T> | RefObject<T>[], handler: (event: MouseEvent | TouchEvent | FocusEvent) => void, eventType?: EventType, eventListenerOptions?: AddEventListenerOptions): void;
/**
* Represents the type for the options available when reading from local storage.
* @template T - The type of the stored value.
*/
type Options<T, InitializeWithValue extends boolean | undefined> = {
/** Custom deserializer function to convert the stored string value to the desired type (optional). */
deserializer?: (value: string) => T;
/** If `true` (default), the hook will initialize reading the local storage. In SSR, you should set it to `false`, returning `undefined` initially. */
initializeWithValue: InitializeWithValue;
};
declare function useReadLocalStorage<T>(key: string, options: Options<T, false>): T | null | undefined;
declare function useReadLocalStorage<T>(key: string, options?: Partial<Options<T, true>>): T | null;
/** The size of the observed element. */
type Size = {
/** The width of the observed element. */
width: number | undefined;
/** The height of the observed element. */
height: number | undefined;
};
/** The options for the ResizeObserver. */
type UseResizeObserverOptions<T extends HTMLElement = HTMLElement> = {
/** The ref of the element to observe. */
ref: RefObject<T>;
/**
* When using `onResize`, the hook doesn't re-render on element size changes; it delegates handling to the provided callback.
* @default undefined
*/
onResize?: (size: Size) => void;
/**
* The box model to use for the ResizeObserver.
* @default 'content-box'
*/
box?: 'border-box' | 'content-box' | 'device-pixel-content-box';
};
/**
* Custom hook that observes the size of an element using the [`ResizeObserver API`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver).
* @template T - The type of the element to observe.
* @param {UseResizeObserverOptions<T>} options - The options for the ResizeObserver.
* @returns {Size} - The size of the observed element.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-resize-observer)
* @example
* ```tsx
* const myRef = useRef(null);
* const { width = 0, height = 0 } = useResizeObserver({
* ref: myRef,
* box: 'content-box',
* });
*
* <div ref={myRef}>Hello, world!</div>
* ```
*/
declare function useResizeObserver<T extends HTMLElement = HTMLElement>(options: UseResizeObserverOptions<T>): Size;
/**
* The hooks options.
* @template InitializeWithValue - If `true` (default), the hook will initialize reading the screen dimensions. In SSR, you should set it to `false`, returning `undefined` initially.
*/
type UseScreenOptions<InitializeWithValue extends boolean | undefined> = {
/**
* If `true` (default), the hook will initialize reading the screen dimensions. In SSR, you should set it to `false`, returning `undefined` initially.
* @default true
*/
initializeWithValue: InitializeWithValue;
/**
* The delay in milliseconds before the state is updated (disabled by default for retro-compatibility).
* @default undefined
*/
debounceDelay?: number;
};
declare function useScreen(options: UseScreenOptions<false>): Screen | undefined;
declare function useScreen(options?: Partial<UseScreenOptions<true>>): Screen;
/** Script loading status. */
type UseScriptStatus = 'idle' | 'loading' | 'ready' | 'error';
/** Hook options. */
type UseScriptOptions = {
/** If `true`, prevents the script from being loaded (optional). */
shouldPreventLoad?: boolean;
/** If `true`, removes the script from the DOM when the component unmounts (optional). */
removeOnUnmount?: boolean;
/** Script's `id` (optional). */
id?: string;
};
/**
* Custom hook that dynamically loads scripts and tracking their loading status.
* @param {string | null} src - The source URL of the script to load. Set to `null` or omit to prevent loading (optional).
* @param {UseScriptOptions} [options] - Additional options for controlling script loading (optional).
* @returns {UseScriptStatus} The status of the script loading, which can be one of 'idle', 'loading', 'ready', or 'error'.
* @see [Documentation](https://usehooks-ts.com/react-hook/use-script)
* @example
* const scriptStatus = useScript('https://example.com/script.js', { removeOnUnmount: true });
* // Access the status of the script loading (e.g., 'loading', 'ready', 'error').
*/
declare function useScript(src: string | null, options?: UseScriptOptions): UseScriptStatus;
/** Hook options. */
type UseScrollLockOptions = {
/**
* Whether to lock the scroll initially.
* @default true
*/
autoLock?: boolean;
/**
* The target element to lock the scroll (default is the body element).
* @default document.body
*/
lockTarget?: HTMLElement | string;
/**
* Whether to prevent width reflow when locking the scroll.
* @default true
*/
widthReflow?: boolean;
};
/** Hook return type. */
type UseScrollLockReturn = {
/** Whether the scroll is locked. */
isLocked: boolean;
/** Lock the scroll. */
lock: () => void;
/** Unlock the scroll. */
unlock: () => void;
};
/**
* A custom hook that locks and unlocks scroll.
* @param {UseScrollLockOptions} [options] - Options to configure the hook, by default it will lock the scroll automatically.
* @returns {UseScrollLockReturn} - An object containing the lock and unlock functions.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-scroll-lock)
* @example
* ```tsx
* // Lock the scroll when the modal is mounted, and unlock it when it's unmounted
* useScrollLock()
* ```
* @example
* ```tsx
* // Manually lock and unlock the scroll
* const { lock, unlock } = useScrollLock({ autoLock: false })
*
* return (
* <div>
* <button onClick={lock}>Lock</button>
* <button onClick={unlock}>Unlock</button>
* </div>
* )
* ```
*/
declare function useScrollLock(options?: UseScrollLockOptions): UseScrollLockReturn;
declare global {
interface WindowEventMap {
'session-storage': CustomEvent;
}
}
/**
* Represents the options for customizing the behavior of serialization and deserialization.
* @template T - The type of the state to be stored in session storage.
*/
type UseSessionStorageOptions<T> = {
/** A function to serialize the value before storing it. */
serializer?: (value: T) => string;
/** A function to deserialize the stored value. */
deserializer?: (value: string) => T;
/**
* If `true` (default), the hook will initialize reading the session storage. In SSR, you should set it to `false`, returning the initial value initially.
* @default true
*/
initializeWithValue?: boolean;
};
/**
* Custom hook that uses the [`sessionStorage API`](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage) to persist state across page reloads.
* @template T - The type of the state to be stored in session storage.
* @param {string} key - The key under which the value will be stored in session storage.
* @param {T | (() => T)} initialValue - The initial value of the state or a function that returns the initial value.
* @param {?UseSessionStorageOptions<T>} [options] - Options for customizing the behavior of serialization and deserialization (optional).
* @returns {[T, Dispatch<SetStateAction<T>>, () => void]} A tuple containing the stored value, a function to set the value and a function to remove the key from storage.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-session-storage)
* @example
* ```tsx
* const [count, setCount, removeCount] = useSessionStorage('count', 0);
* // Access the `count` value, the `setCount` function to update it and `removeCount` function to remove the key from storage.
* ```
*/
declare function useSessionStorage<T>(key: string, initialValue: T | (() => T), options?: UseSessionStorageOptions<T>): [T, Dispatch<SetStateAction<T>>, () => void];
/** Represents the second element of the output of the `useStep` hook. */
type UseStepActions = {
/** Go to the next step in the process. */
goToNextStep: () => void;
/** Go to the previous step in the process. */
goToPrevStep: () => void;
/** Reset the step to the initial step. */
reset: () => void;
/** Check if the next step is available. */
canGoToNextStep: boolean;
/** Check if the previous step is available. */
canGoToPrevStep: boolean;
/** Set the current step to a specific value. */
setStep: Dispatch<SetStateAction<number>>;
};
/**
* Custom hook that manages and navigates between steps in a multi-step process.
* @param {number} maxStep - The maximum step in the process.
* @returns {[number, UseStepActions]} An tuple containing the current step and helper functions for navigating steps.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-step)
* @example
* ```tsx
* const [currentStep, { goToNextStep, goToPrevStep, reset, canGoToNextStep, canGoToPrevStep, setStep }] = useStep(3);
* // Access and use the current step and provided helper functions.
* ```
*/
declare function useStep(maxStep: number): [number, UseStepActions];
/** Ternary dark mode options. */
type TernaryDarkMode = 'system' | 'dark' | 'light';
/** Options for the `useTernaryDarkMode` hook. */
type TernaryDarkModeOptions = {
/**
* The default value for the dark mode.
* @default 'system'
*/
defaultValue?: TernaryDarkMode;
/**
* The key for storing dark mode preference in local storage.
* @default 'usehooks-ts-ternary-dark-mode'
*/
localStorageKey?: string;
/**
* If `true` (default), the hook will initialize reading `localStorage`. In SSR, you should set it to `false`, returning default values initially.
* @default true
*/
initializeWithValue?: boolean;
};
/** Represents the return type of the `useTernaryDarkMode` hook. */
type TernaryDarkModeReturn = {
/** The current state of the dark mode. */
isDarkMode: boolean;
/** The current state of the dark mode. */
ternaryDarkMode: TernaryDarkMode;
/** A function to set the dark mode state. */
setTernaryDarkMode: Dispatch<SetStateAction<TernaryDarkMode>>;
/** A function to toggle the dark mode state. */
toggleTernaryDarkMode: () => void;
};
/**
* Custom hook that manages ternary (system, dark, light) dark mode with local storage support.
* @param {?TernaryDarkModeOptions | string} [options] - Options or the local storage key for the hook.
* @returns {TernaryDarkModeReturn} An object containing the dark mode state and helper functions.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-ternary-dark-mode)
* @example
* ```tsx
* const { isDarkMode, ternaryDarkMode, setTernaryDarkMode, toggleTernaryDarkMode } = useTernaryDarkMode({ defaultValue: 'dark' });
* // Access and use the dark mode state and provided helper functions.
* ```
*/
declare function useTernaryDarkMode({ defaultValue, localStorageKey, initializeWithValue, }?: TernaryDarkModeOptions): TernaryDarkModeReturn;
/**
* Custom hook that handles timeouts in React components using the [`setTimeout API`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout).
* @param {() => void} callback - The function to be executed when the timeout elapses.
* @param {number | null} delay - The duration (in milliseconds) for the timeout. Set to `null` to clear the timeout.
* @returns {void} This hook does not return anything.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-timeout)
* @example
* ```tsx
* // Usage of useTimeout hook
* useTimeout(() => {
* // Code to be executed after the specified delay
* }, 1000); // Set a timeout of 1000 milliseconds (1 second)
* ```
*/
declare function useTimeout(callback: () => void, delay: number | null): void;
/**
* Custom hook that manages a boolean toggle state in React components.
* @param {boolean} [defaultValue] - The initial value for the toggle state.
* @returns {[boolean, () => void, Dispatch<SetStateAction<boolean>>]} A tuple containing the current state,
* a function to toggle the state, and a function to set the state explicitly.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-toggle)
* @example
* ```tsx
* const [isToggled, toggle, setToggle] = useToggle(); // Initial value is false
* // OR
* const [isToggled, toggle, setToggle] = useToggle(true); // Initial value is true
* // Use isToggled in your component, toggle to switch the state, setToggle to set the state explicitly.
* ```
*/
declare function useToggle(defaultValue?: boolean): [boolean, () => void, Dispatch<SetStateAction<boolean>>];
/**
* Custom hook that runs a cleanup function when the component is unmounted.
* @param {() => void} func - The cleanup function to be executed on unmount.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-unmount)
* @example
* ```tsx
* useUnmount(() => {
* // Cleanup logic here
* });
* ```
*/
declare function useUnmount(func: () => void): void;
/**
* Represent the dimension of the window.
* @template T - The type of the dimension (number or undefined).
*/
type WindowSize<T extends number | undefined = number | undefined> = {
/** The width of the window. */
width: T;
/** The height of the window. */
height: T;
};
/**
* Hook options.
* @template InitializeWithValue - If `true` (default), the hook will initialize reading the window size. In SSR, you should set it to `false`, returning `undefined` initially.
*/
type UseWindowSizeOptions<InitializeWithValue extends boolean | undefined> = {
/**
* If `true` (default), the hook will initialize reading the window size. In SSR, you should set it to `false`, returning `undefined` initially.
* @default true
*/
initializeWithValue: InitializeWithValue;
/**
* The delay in milliseconds before the state is updated (disabled by default for retro-compatibility).
* @default undefined
*/
debounceDelay?: number;
};
declare function useWindowSize(options: UseWindowSizeOptions<false>): WindowSize;
declare function useWindowSize(options?: Partial<UseWindowSizeOptions<true>>): WindowSize<number>;
export { type DebouncedState, type TernaryDarkMode, type TernaryDarkModeOptions, type TernaryDarkModeReturn, useBoolean, useClickAnyWhere, useCopyToClipboard, useCountdown, useCounter, useDarkMode, useDebounceCallback, useDebounceValue, useDocumentTitle, useEventCallback, useEventListener, useHover, useIntersectionObserver, useInterval, useIsClient, useIsMounted, useIsomorphicLayoutEffect, useLocalStorage, useMap, useMediaQuery, useOnClickOutside, useReadLocalStorage, useResizeObserver, useScreen, useScript, useScrollLock, useSessionStorage, useStep, useTernaryDarkMode, useTimeout, useToggle, useUnmount, useWindowSize };

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,74 @@
{
"name": "usehooks-ts",
"private": false,
"version": "3.1.1",
"description": "React hook library, ready to use, written in Typescript.",
"author": "Julien CARON <juliencaron@protonmail.com>",
"homepage": "https://usehooks-ts.com",
"keywords": [
"typescript",
"react",
"hooks"
],
"license": "MIT",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
"./package.json": "./package.json",
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
}
},
"sideEffects": false,
"devDependencies": {
"@juggle/resize-observer": "^3.4.0",
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^14.2.1",
"@types/lodash.debounce": "^4.0.9",
"@types/node": "^20.11.19",
"@types/react": "18.2.73",
"eslint-plugin-jsdoc": "^48.1.0",
"eslint-plugin-tree-shaking": "^1.12.1",
"jsdom": "^24.0.0",
"react": "18.2.0",
"tsup": "^8.0.2",
"typescript": "^5.3.3",
"vitest": "^1.3.1",
"eslint-config-custom": "2.0.0"
},
"dependencies": {
"lodash.debounce": "^4.0.8"
},
"peerDependencies": {
"react": "^16.8.0 || ^17 || ^18 || ^19 || ^19.0.0-rc"
},
"engines": {
"node": ">=16.15.0"
},
"files": [
"dist"
],
"repository": {
"type": "git",
"url": "https://github.com/juliencrn/usehooks-ts"
},
"bugs": {
"url": "https://github.com/juliencrn/usehooks-ts/issues"
},
"scripts": {
"build": "tsup",
"dev": "tsup --watch",
"test": "vitest run",
"test:watch": "vitest",
"clean": "rimraf dist .turbo *.tsbuildinfo",
"lint": "eslint './src/**/*.{ts,tsx}' && tsc --noEmit"
}
}