diff --git a/.changeset/brown-bears-cheat.md b/.changeset/brown-bears-cheat.md
new file mode 100644
index 0000000..70be95e
--- /dev/null
+++ b/.changeset/brown-bears-cheat.md
@@ -0,0 +1,5 @@
+---
+'classic-react-hooks': patch
+---
+
+build: upgrade from tsup to tsdown bundler
diff --git a/.changeset/brown-wolves-play.md b/.changeset/brown-wolves-play.md
new file mode 100644
index 0000000..26b3930
--- /dev/null
+++ b/.changeset/brown-wolves-play.md
@@ -0,0 +1,21 @@
+---
+'classic-react-hooks': minor
+---
+
+## Major Rewrite for the Documentation
+- home page and overview
+- use-can-reach-to-internet
+- use-copy-to-clipboard
+- use-counter
+- use-debounced-fn
+- use-event-listener
+- use-intersection-observer
+- use-multi-intersection-observer
+- use-interval-effect
+- use-on-mount-effect
+- use-outside-effect
+- use-synced-effect
+- use-synced-ref
+- use-throttled-fn
+- use-timeout-effect
+- use-window-resize
diff --git a/.changeset/clean-coats-occur.md b/.changeset/clean-coats-occur.md
new file mode 100644
index 0000000..321d05b
--- /dev/null
+++ b/.changeset/clean-coats-occur.md
@@ -0,0 +1,5 @@
+---
+'classic-react-hooks': minor
+---
+
+Doc update
diff --git a/.changeset/cool-emus-lie.md b/.changeset/cool-emus-lie.md
new file mode 100644
index 0000000..21fb956
--- /dev/null
+++ b/.changeset/cool-emus-lie.md
@@ -0,0 +1,5 @@
+---
+'classic-react-hooks': patch
+---
+
+Docs: Update features and overview section
diff --git a/.changeset/cool-spoons-fold.md b/.changeset/cool-spoons-fold.md
new file mode 100644
index 0000000..818efa7
--- /dev/null
+++ b/.changeset/cool-spoons-fold.md
@@ -0,0 +1,6 @@
+---
+'classic-react-hooks': minor
+---
+
+Feature:
+- Add cross-tab sync and ssr support and function based initial value support for `useLocalStorage` hook.
diff --git a/.changeset/cuddly-melons-turn.md b/.changeset/cuddly-melons-turn.md
new file mode 100644
index 0000000..fbb3420
--- /dev/null
+++ b/.changeset/cuddly-melons-turn.md
@@ -0,0 +1,10 @@
+---
+'classic-react-hooks': minor
+---
+
+
+- Doc: Add `what problem it solves` doc for useCanReachToInternet
+- Doc: Refactor the docs for hooks
+
+
+
diff --git a/.changeset/early-apes-march.md b/.changeset/early-apes-march.md
new file mode 100644
index 0000000..bcc640e
--- /dev/null
+++ b/.changeset/early-apes-march.md
@@ -0,0 +1,5 @@
+---
+'classic-react-hooks': patch
+---
+
+- Update dependencies, pnpm and node version for better security and performance
diff --git a/.changeset/fresh-hounds-move.md b/.changeset/fresh-hounds-move.md
new file mode 100644
index 0000000..385ac7b
--- /dev/null
+++ b/.changeset/fresh-hounds-move.md
@@ -0,0 +1,5 @@
+---
+'classic-react-hooks': patch
+---
+
+Include src folder in npm publish
diff --git a/.changeset/good-vans-impress.md b/.changeset/good-vans-impress.md
new file mode 100644
index 0000000..f77dbf2
--- /dev/null
+++ b/.changeset/good-vans-impress.md
@@ -0,0 +1,5 @@
+---
+'classic-react-hooks': minor
+---
+
+Add CanReachToInterernetCtxProvder and useCanReachToInternetCtx component's documentation
diff --git a/.changeset/hungry-moons-serve.md b/.changeset/hungry-moons-serve.md
new file mode 100644
index 0000000..50d848a
--- /dev/null
+++ b/.changeset/hungry-moons-serve.md
@@ -0,0 +1,5 @@
+---
+'classic-react-hooks': minor
+---
+Feat: Introduce `layoutEffect` boolean prop in use-event-listener hook to pickup `useEffect` between `useLayoutEffect`. By default `useEffect` hook will be used.
+Feat: Using layoutEffect for use-window-resize hook.
diff --git a/.changeset/icy-boats-make.md b/.changeset/icy-boats-make.md
new file mode 100644
index 0000000..283b98e
--- /dev/null
+++ b/.changeset/icy-boats-make.md
@@ -0,0 +1,7 @@
+---
+'classic-react-hooks': major
+---
+
+Breaking
+- v2 release prepare
+- Rewrite all of the hooks and their documenation
diff --git a/.changeset/mighty-donkeys-roll.md b/.changeset/mighty-donkeys-roll.md
new file mode 100644
index 0000000..d2065d6
--- /dev/null
+++ b/.changeset/mighty-donkeys-roll.md
@@ -0,0 +1,5 @@
+---
+'classic-react-hooks': minor
+---
+
+ref: Initialize context lazily within ContextProvider component for can-reach-to-internet-context
diff --git a/.changeset/modern-ants-add.md b/.changeset/modern-ants-add.md
new file mode 100644
index 0000000..0ae5fd6
--- /dev/null
+++ b/.changeset/modern-ants-add.md
@@ -0,0 +1,7 @@
+---
+'classic-react-hooks': minor
+---
+
+
+- breaking: use the implementation and working for `useIntersection` observer hook.
+- feat: introduce new hook `useMultiIntersectionObserver` hook.
\ No newline at end of file
diff --git a/.changeset/moody-pens-poke.md b/.changeset/moody-pens-poke.md
new file mode 100644
index 0000000..662995a
--- /dev/null
+++ b/.changeset/moody-pens-poke.md
@@ -0,0 +1,12 @@
+---
+'classic-react-hooks': minor
+---
+
+
+## Fixes following issues
+- Fix: use-can-reach-to-internet `subscribe` handler for `useSyncExternalStore`. It was adding events instead of removing.
+- Fix: Prevent from re-triggering the call of `checkIfCanReachToInternet` function in useEffect when `isNetworkPollingEnabled` is disabled.
+
+## Test cases
+- Wrote test cases for use-can-reach-to-internet and use-copy-to-clipboard hook. Previously not written.
+
diff --git a/.changeset/pink-pugs-eat.md b/.changeset/pink-pugs-eat.md
new file mode 100644
index 0000000..1f06d8e
--- /dev/null
+++ b/.changeset/pink-pugs-eat.md
@@ -0,0 +1,7 @@
+---
+'classic-react-hooks': minor
+---
+
+- breaking: remove useIsOnline hook
+- Feat: add useCanReachToInternet for getting network connection
+- Feat: add useCanReachToInternetCtx and CanReachToInternetCtxProvider for subscribing the application to get network reachability with context
\ No newline at end of file
diff --git a/.changeset/popular-students-happen.md b/.changeset/popular-students-happen.md
new file mode 100644
index 0000000..d63ba9f
--- /dev/null
+++ b/.changeset/popular-students-happen.md
@@ -0,0 +1,5 @@
+---
+'classic-react-hooks': patch
+---
+
+Add canary branch in CI release
diff --git a/.changeset/pre.json b/.changeset/pre.json
new file mode 100644
index 0000000..c3207a7
--- /dev/null
+++ b/.changeset/pre.json
@@ -0,0 +1,34 @@
+{
+ "mode": "pre",
+ "tag": "canary",
+ "initialVersions": {
+ "classic-react-hooks": "1.4.0"
+ },
+ "changesets": [
+ "brown-bears-cheat",
+ "brown-wolves-play",
+ "clean-coats-occur",
+ "cool-emus-lie",
+ "cool-spoons-fold",
+ "cuddly-melons-turn",
+ "early-apes-march",
+ "fresh-hounds-move",
+ "good-vans-impress",
+ "hungry-moons-serve",
+ "icy-boats-make",
+ "mighty-donkeys-roll",
+ "modern-ants-add",
+ "moody-pens-poke",
+ "pink-pugs-eat",
+ "popular-students-happen",
+ "silver-radios-tickle",
+ "slick-carrots-stick",
+ "spotty-jeans-carry",
+ "stale-radios-rule",
+ "tender-sites-occur",
+ "thirty-foxes-wink",
+ "twenty-pans-search",
+ "violet-cherries-applaud",
+ "warm-olives-punch"
+ ]
+}
diff --git a/.changeset/silver-radios-tickle.md b/.changeset/silver-radios-tickle.md
new file mode 100644
index 0000000..a9ac39e
--- /dev/null
+++ b/.changeset/silver-radios-tickle.md
@@ -0,0 +1,5 @@
+---
+'classic-react-hooks': minor
+---
+
+- Fix timeout and interval effect cleanup when interval changes
diff --git a/.changeset/slick-carrots-stick.md b/.changeset/slick-carrots-stick.md
new file mode 100644
index 0000000..506615f
--- /dev/null
+++ b/.changeset/slick-carrots-stick.md
@@ -0,0 +1,5 @@
+---
+'classic-react-hooks': minor
+---
+
+Update target build to esnext in builder
diff --git a/.changeset/spotty-jeans-carry.md b/.changeset/spotty-jeans-carry.md
new file mode 100644
index 0000000..7ed304b
--- /dev/null
+++ b/.changeset/spotty-jeans-carry.md
@@ -0,0 +1,5 @@
+---
+'classic-react-hooks': minor
+---
+
+- Fix missing export for `useMultipleIntersectionObserver` hook
diff --git a/.changeset/stale-radios-rule.md b/.changeset/stale-radios-rule.md
new file mode 100644
index 0000000..a34b42d
--- /dev/null
+++ b/.changeset/stale-radios-rule.md
@@ -0,0 +1,6 @@
+---
+'classic-react-hooks': patch
+---
+
+Docs: Start overhauling to new documentation
+- Create new docs for `use-event-listener` and `use-intersection-observer` hooks
diff --git a/.changeset/tender-sites-occur.md b/.changeset/tender-sites-occur.md
new file mode 100644
index 0000000..b42eec7
--- /dev/null
+++ b/.changeset/tender-sites-occur.md
@@ -0,0 +1,5 @@
+---
+'classic-react-hooks': minor
+---
+
+Docs - add usage example in js-doc for all of the hooks
diff --git a/.changeset/thirty-foxes-wink.md b/.changeset/thirty-foxes-wink.md
new file mode 100644
index 0000000..7fef3ed
--- /dev/null
+++ b/.changeset/thirty-foxes-wink.md
@@ -0,0 +1,5 @@
+---
+'classic-react-hooks': minor
+---
+
+- Introduce second method `setElementRef` function for observing target with `ref` attribute (i.e. ref={setElementRef})
diff --git a/.changeset/twenty-pans-search.md b/.changeset/twenty-pans-search.md
new file mode 100644
index 0000000..e6cde0f
--- /dev/null
+++ b/.changeset/twenty-pans-search.md
@@ -0,0 +1,17 @@
+---
+'classic-react-hooks': minor
+---
+
+## Doc Fixes
+- docs: fix imports in js-doc examples
+- types: Update type definitions to common types folder
+- docs: update docs for hooks
+
+## Test Updates
+- test: refactor and add new the test cases
+
+## Bug Fixes
+- fix: network state update on online/offline event when polling is off(7c765e984556b8496667dd057ca20bc6586e82b6)
+- fix: create seperate setElementRef for target setting in use-outside-click(ff812ca88e527c12b3604fb559c1b3d6b87ca7d9)
+- fix: making capture flag to false for use-outside-click(fd31ba46b569ed298de6c7a445204beea2c57284)
+- fix: lazily set target for outside and use-event-listener(1a387a1fe05dc8a736a629d8a66d067a3162340e)
diff --git a/.changeset/violet-cherries-applaud.md b/.changeset/violet-cherries-applaud.md
new file mode 100644
index 0000000..4dc67d5
--- /dev/null
+++ b/.changeset/violet-cherries-applaud.md
@@ -0,0 +1,5 @@
+---
+'classic-react-hooks': patch
+---
+
+Update docs for copy-to-clipboard and deboucned-fn hook
diff --git a/.changeset/warm-olives-punch.md b/.changeset/warm-olives-punch.md
new file mode 100644
index 0000000..4cd50cb
--- /dev/null
+++ b/.changeset/warm-olives-punch.md
@@ -0,0 +1,5 @@
+---
+'classic-react-hooks': minor
+---
+
+docs: revamp to new doc version for `use-multi-intersection-observer`
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..4ad820f
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,11 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_style = space
+indent_size = 3
+tab_width = 3
+max_line_length = 120
+trim_trailing_whitespace = true
+insert_final_newline = true
\ No newline at end of file
diff --git a/.github/workflows/canary-publish.yml b/.github/workflows/canary-publish.yml
new file mode 100644
index 0000000..232da07
--- /dev/null
+++ b/.github/workflows/canary-publish.yml
@@ -0,0 +1,32 @@
+name: Publish
+on:
+ push:
+ branches:
+ - canary
+
+concurrency: ${{ github.workflow }}-${{ github.ref }}
+
+jobs:
+ canary:
+ runs-on: 'ubuntu-latest'
+ permissions: write-all
+ steps:
+ - uses: actions/checkout@v3
+ - uses: pnpm/action-setup@v4
+ # with:
+ # version: 8
+ - uses: actions/setup-node@v4
+ with:
+ node-version: ${{ matrix.node }}
+ cache: 'pnpm'
+
+ - run: pnpm install --no-frozen-lockfile
+
+ - name: Create Canary Release Pull Request or Canary Publish
+ id: changesets
+ uses: changesets/action@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
+ with:
+ publish: pnpm release
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 5730f80..81a61de 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -3,6 +3,7 @@ on:
pull_request:
branches:
- 'main'
+ - 'canary'
jobs:
build:
diff --git a/.gitignore b/.gitignore
index f8c4d87..0d893a7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,4 +12,8 @@ apps/*
apps/doc/.vitepress/cache
-src/**/*.dev.tsx
\ No newline at end of file
+/**/*.dev.tsx
+/**/*.dev.ts
+/**/*.dev.jsx
+/**/*.dev.js
+/**/*.dev.md
diff --git a/.nvmrc b/.nvmrc
index e06fc80..fc37597 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-18.14.2
\ No newline at end of file
+22.17.0
diff --git a/.prettierignore b/.prettierignore
index 71c4766..306851e 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -4,4 +4,6 @@ node_modules
public
apps/doc/.vitepress/cache
apps/example
-.changeset
\ No newline at end of file
+.changeset
+
+pnpm-lock.yaml
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9d89d03..c3dce8b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,203 @@
# classic-react-hooks
+## 2.0.0-canary.24
+
+### Patch Changes
+
+- ab12cc5: build: upgrade from tsup to tsdown bundler
+
+## 2.0.0-canary.23
+
+### Minor Changes
+
+- a0c4e96: ref: Initialize context lazily within ContextProvider component for can-reach-to-internet-context
+
+## 2.0.0-canary.22
+
+### Minor Changes
+
+- 5e43e42: Update target build to esnext in builder
+
+## 2.0.0-canary.21
+
+### Minor Changes
+
+- f5197b4: ## Doc Fixes
+
+ - docs: fix imports in js-doc examples
+ - types: Update type definitions to common types folder
+ - docs: update docs for hooks
+
+ ## Test Updates
+
+ - test: refactor and add new the test cases
+
+ ## Bug Fixes
+
+ - fix: network state update on online/offline event when polling is off(7c765e984556b8496667dd057ca20bc6586e82b6)
+ - fix: create seperate setElementRef for target setting in use-outside-click(ff812ca88e527c12b3604fb559c1b3d6b87ca7d9)
+ - fix: making capture flag to false for use-outside-click(fd31ba46b569ed298de6c7a445204beea2c57284)
+ - fix: lazily set target for outside and use-event-listener(1a387a1fe05dc8a736a629d8a66d067a3162340e)
+
+## 2.0.0-canary.20
+
+### Patch Changes
+
+- f8af3e3: - Update dependencies, pnpm and node version for better security and performance
+
+## 2.0.0-canary.19
+
+### Minor Changes
+
+- c534ff5: - Introduce second method `setElementRef` function for observing target with `ref` attribute (i.e. ref={setElementRef})
+
+## 2.0.0-canary.18
+
+### Minor Changes
+
+- 8305b6d: - Fix missing export for `useMultipleIntersectionObserver` hook
+
+## 2.0.0-canary.17
+
+### Minor Changes
+
+- 0d1ac96: - Fix timeout and interval effect cleanup when interval changes
+
+## 2.0.0-canary.16
+
+### Minor Changes
+
+- 87b8bbb: Feature:
+ - Add cross-tab sync and ssr support and function based initial value support for `useLocalStorage` hook.
+
+## 2.0.0-canary.15
+
+### Minor Changes
+
+- fb26e91: ## Fixes following issues
+
+ - Fix: use-can-reach-to-internet `subscribe` handler for `useSyncExternalStore`. It was adding events instead of removing.
+ - Fix: Prevent from re-triggering the call of `checkIfCanReachToInternet` function in useEffect when `isNetworkPollingEnabled` is disabled.
+
+ ## Test cases
+
+ - Wrote test cases for use-can-reach-to-internet and use-copy-to-clipboard hook. Previously not written.
+
+## 2.0.0-canary.14
+
+### Minor Changes
+
+- a2f9744: ## Major Rewrite for the Documentation
+ - home page and overview
+ - use-can-reach-to-internet
+ - use-copy-to-clipboard
+ - use-counter
+ - use-debounced-fn
+ - use-event-listener
+ - use-intersection-observer
+ - use-multi-intersection-observer
+ - use-interval-effect
+ - use-on-mount-effect
+ - use-outside-effect
+ - use-synced-effect
+ - use-synced-ref
+ - use-throttled-fn
+ - use-timeout-effect
+ - use-window-resize
+
+## 2.0.0-canary.13
+
+### Minor Changes
+
+- ff4615c: docs: revamp to new doc version for `use-multi-intersection-observer`
+
+## 2.0.0-canary.12
+
+### Patch Changes
+
+- 5877980: Docs: Start overhauling to new documentation
+ - Create new docs for `use-event-listener` and `use-intersection-observer` hooks
+
+## 2.0.0-canary.11
+
+### Minor Changes
+
+- 4f5bb6c: - breaking: use the implementation and working for `useIntersection` observer hook.
+ - feat: introduce new hook `useMultiIntersectionObserver` hook.
+
+## 2.0.0-canary.10
+
+### Patch Changes
+
+- 5807a38: Add canary branch in CI release
+
+## 2.0.0-canary.9
+
+### Minor Changes
+
+- e73af53: Feat: Introduce `layoutEffect` boolean prop in use-event-listener hook to pickup `useEffect` between `useLayoutEffect`. By default `useEffect` hook will be used.
+ Feat: Using layoutEffect for use-window-resize hook.
+
+## 2.0.0-canary.8
+
+### Patch Changes
+
+- 56478c2: Docs: Update features and overview section
+
+## 2.0.0-canary.7
+
+### Patch Changes
+
+- cc71e9c: Update docs for copy-to-clipboard and deboucned-fn hook
+
+## 2.0.0-canary.6
+
+### Patch Changes
+
+- c20ae22: Include src folder in npm publish
+
+## 2.0.0-canary.5
+
+### Minor Changes
+
+- 51e96f8: Doc update
+
+## 2.0.0-canary.4
+
+### Minor Changes
+
+- c52bb9f: Add CanReachToInterernetCtxProvder and useCanReachToInternetCtx component's documentation
+
+## 2.0.0-canary.3
+
+### Minor Changes
+
+- 3e110b2: - Doc: Add `what problem it solves` doc for useCanReachToInternet
+ - Doc: Refactor the docs for hooks
+
+## 2.0.0-canary.2
+
+### Minor Changes
+
+- 703c876: - breaking: remove useIsOnline hook
+ - Feat: add useCanReachToInternet for getting network connection
+ - Feat: add useCanReachToInternetCtx and CanReachToInternetCtxProvider for subscribing the application to get network reachability with context
+
+## 2.0.0-canary.1
+
+### Minor Changes
+
+- 44ce4b9: Docs - add usage example in js-doc for all of the hooks
+
+## 2.0.0-canary.0
+
+### Major Changes
+
+Breaking
+
+- v2 release prepare
+- Rewrite all of the hooks and their documenation
+
## 1.4.0
### Minor Changes
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 7580c6e..689aa42 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -2,28 +2,52 @@
Hi! We are really excited that you are interested in contributing to classic-react-hooks. Before submitting your contribution, please make sure to take a moment and read through the following guide:
-## Repo Setup
-The package manager used to install and link dependencies should be [pnpm](https://pnpm.io/) v8.12.0 or higher. NodeJS version should be v18.14.2 or higher
+## 🔧 System Requirements
+- [Node.js](https://nodejs.org/en) v16 or higher
+- [Pnpm](https://pnpm.io/) v8 or higher
-1. Run `pnpm install` in root folder
-2. Run `pnpm run build` to build the package
+----
+## 🏗️ Repo Setup
-3. Run `pnpm run test` to run the test cases
+```bash
+git clone https://github.com/Ashish-simpleCoder/classic-react-hooks.git
-4. Run `pnpm run format` to format all of the coding with prettier
+cd classic-react-hooks
+```
-## Pull Request Guidelines
+
+### Install dependencies
+```sh
+pnpm install
+```
+
+### Build project
+```sh
+pnpm build
+```
+### Run tests
+```sh
+pnpm test
+```
+### Format code
+```sh
+pnpm format
+```
+
+
+----
+## 🔃 Pull Request Guidelines
- Checkout a topic branch from a base branch, e.g. `main`, and merge back against that branch.
- If adding a new feature:
- - Add accompanying test case.
- Provide a convincing reason to add this feature. Ideally, you should open a suggestion issue first and have it approved before working on it.
+ - Add accompanying test case.
-- If fixing bug:
+- If fixing a bug:
- If you are resolving a special issue, add `(fix #xxxx[,#xxxx])` (#xxxx is the issue id) in your PR title for a better release log, e.g. `fix: update fetch logic (fix #3899)`.
- Provide a detailed description of the bug in the PR. Live demo preferred.
@@ -35,9 +59,13 @@ The package manager used to install and link dependencies should be [pnpm](https
- Use `pnpm format` to format files according to the project guidelines.
-## Documenation Guidelines
-- To contribute in the documentation, go to apps/doc directory
+---
+## 📄 Documenation Guidelines
+
+To contribute in the documentation, go to `apps/doc` directory
+
+### Steps to contribute
1. Run `pnpm install` to install all of the dependencies
diff --git a/README.md b/README.md
index 537715b..443ed9d 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,9 @@
# 🚀 classic-react-hooks
-#### An awesome collection of `feature packed custom hooks`.
+Essential Custom Hooks for React Developers
-
@@ -18,18 +17,28 @@
+
+
## Read the Documentation
https://classic-react-hooks.vercel.app/
-## Features
+## ✨ Features
- Comes with treeshaking
- Typescript support
- Small bundle size
- Minimal and Easy to use
-## Installation
+## 🛠️ Tech Stack
+- React 18 with TypeScript
+- Vitepress for documentation
+- Changeset for sementic version releases
+- Vitest for testing the components
+- tsup for build tooling
+
+
+## 🚀 Install in your project
For npm users
@@ -55,22 +64,13 @@ For bun users
$ bun add classic-react-hooks
```
-## Hooks
-- use-event-listener
-- use-copy-to-clipboard
-- use-local-storage
-- use-outside-click
-- use-debounced-fn
-- use-throttled-hook
-- use-is-online
-- use-timeout-effect
-- use-interval-effect
-- use-synced-ref
-- use-synced-effect
-- use-on-mount-effect
-- use-counter
-
-## Contribution
+## 📝 Contribution
See [Contributing Guide](https://github.com/Ashish-simpleCoder/classic-react-hooks/blob/main/CONTRIBUTING.md).
+
+
+## 📄 License
+- This project is licensed under the MIT License - see the LICENSE file for details. Say builds on top of earlier demos of how to use Whisper with Transformers.js.
+
+
diff --git a/apps/doc/.vitepress/config.mts b/apps/doc/.vitepress/config.mts
index ae0a2f4..53c085b 100644
--- a/apps/doc/.vitepress/config.mts
+++ b/apps/doc/.vitepress/config.mts
@@ -1,5 +1,6 @@
import { defineConfig, type DefaultTheme } from 'vitepress'
import { version } from '../../../package.json'
+import { groupIconMdPlugin, groupIconVitePlugin } from 'vitepress-plugin-group-icons'
// https://vitepress.dev/reference/site-config
export default defineConfig({
@@ -10,6 +11,17 @@ export default defineConfig({
lastUpdated: true,
cleanUrls: false,
+ markdown: {
+ lineNumbers: true,
+ config(md) {
+ md.use(groupIconMdPlugin)
+ },
+ },
+
+ vite: {
+ plugins: [groupIconVitePlugin()],
+ },
+
sitemap: {
hostname: 'https://classic-react-hooks.vercel.app',
transformItems(items) {
@@ -32,7 +44,28 @@ export default defineConfig({
},
{
text: `v${version}`,
- link: `https://github.com/Ashish-simpleCoder/classic-react-hooks/releases/tag/v${version}`,
+ items: [
+ {
+ items: [
+ {
+ text: `v${version}`,
+ link: `https://github.com/Ashish-simpleCoder/classic-react-hooks/releases/tag/v${version}`,
+ },
+ ],
+ },
+ {
+ items: [
+ {
+ text: 'Unreleased',
+ link: `https://canary-classic-react-hooks.vercel.app/`,
+ },
+ {
+ text: 'v1.x',
+ link: `https://v1-classic-react-hooks.vercel.app`,
+ },
+ ],
+ },
+ ],
},
],
@@ -52,9 +85,10 @@ export default defineConfig({
icon: 'github',
link: 'https://github.com/Ashish-simpleCoder/classic-react-hooks',
},
- { icon: 'x', link: 'https://twitter.com/ashish_devloper' },
{ icon: 'linkedin', link: 'https://linkedin.com/in/ashish-prajapati-002154193' },
+ { icon: 'bluesky', link: 'https://bsky.app/profile/ashish-simplecoder.bsky.social' },
{ icon: 'npm', link: 'https://www.npmjs.com/package/classic-react-hooks' },
+ { icon: 'x', link: 'https://twitter.com/ashish_devloper' },
],
editLink: {
pattern: 'https://github.com/Ashish-simpleCoder/classic-react-hooks/edit/main/apps/doc/:path',
@@ -86,13 +120,14 @@ function sidebarGuide(): DefaultTheme.SidebarItem[] {
items: [
{ text: 'use-event-listener', link: 'use-event-listener' },
{ text: 'use-intersection-observer', link: 'use-intersection-observer' },
+ { text: 'use-multi-intersection-observer', link: 'use-multi-intersection-observer' },
{ text: 'use-window-resize', link: 'use-window-resize' },
{ text: 'use-copy-to-clipboard', link: 'use-copy-to-clipboard' },
{ text: 'use-local-storage', link: 'use-local-storage' },
{ text: 'use-outside-click', link: 'use-outside-click' },
{ text: 'use-debounced-fn', link: 'use-debounced-fn' },
{ text: 'use-throttled-fn', link: 'use-throttled-fn' },
- { text: 'use-is-online', link: 'use-is-online' },
+ { text: 'use-can-reach-to-internet', link: 'use-can-reach-to-internet' ,collapsed: true},
{ text: 'use-timeout-effect', link: 'use-timeout-effect' },
{ text: 'use-interval-effect', link: 'use-interval-effect' },
{ text: 'use-synced-ref', link: 'use-synced-ref' },
@@ -101,5 +136,13 @@ function sidebarGuide(): DefaultTheme.SidebarItem[] {
{ text: 'use-counter', link: 'use-counter' },
]
},
+ {
+ text: 'Components',
+ collapsed: false,
+ base: "/components/",
+ items: [
+ { text: 'Internet Connectivity Context', link: 'CanReachToInternetCtxProvider' },
+ ]
+ },
]
}
diff --git a/apps/doc/.vitepress/theme/index.ts b/apps/doc/.vitepress/theme/index.ts
index 2323d71..cac02b2 100644
--- a/apps/doc/.vitepress/theme/index.ts
+++ b/apps/doc/.vitepress/theme/index.ts
@@ -2,6 +2,8 @@
import { h } from 'vue'
import type { Theme } from 'vitepress'
import DefaultTheme from 'vitepress/theme'
+
+import 'virtual:group-icons.css'
import './style.css'
export default {
diff --git a/apps/doc/components/CanReachToInternetCtxProvider.md b/apps/doc/components/CanReachToInternetCtxProvider.md
new file mode 100644
index 0000000..3eade04
--- /dev/null
+++ b/apps/doc/components/CanReachToInternetCtxProvider.md
@@ -0,0 +1,90 @@
+---
+outline: deep
+---
+
+# Internet Connectivity Context
+
+A React Context provider and hook for sharing internet connectivity status across your component tree without prop drilling.
+
+Built on top of the [useCanReachToInternet](/hooks/use-can-reach-to-internet.html) hook to provide centralized connectivity monitoring.
+
+## Features
+
+- **Centralized connectivity state:** Share connectivity status across your entire app
+- **No prop drilling:** Access connectivity data from any component in the tree
+- **Same configuration options:** All `useCanReachToInternet` options available at provider level
+
+## Components & Hooks
+
+### CanReachToInternetCtxProvider
+
+A context provider component that wraps your application to provide connectivity status to all child components.
+
+It takes following props
+
+| Parameter | Type | Required | Default Value | Description |
+| ---------------------- | :-------: | :------: | :----------------: | --------------------------------------------------------------------------- |
+| children | ReactNode | ✅ | - | React children components that will have access to the connectivity context |
+| enableNetworkPolling | boolean | ❌ | true | Enable automatic network polling to continuously check connectivity |
+| networkPollingInterval | number | ❌ | 3000 | Interval in milliseconds between network polls |
+| testUrl | string | ❌ | https://dns.google | URL to test internet connectivity against |
+
+### useCanReachToInternetCtx
+
+A custom hook to consume the internet connectivity context values.
+
+Return value(s):
+
+| Property | Type | Description |
+| --------------------------- | ------------- | -------------------------------------------------------------------------------- |
+| isOnline | boolean | Browser's native online/offline status from `navigator.onLine` |
+| canReachToInternet | boolean | Whether the device can actually reach the internet (verified via HTTP request) |
+| isFullyConnected | boolean | Combined status: `true` when both `isOnline` and `canReachToInternet` are `true` |
+| isNetworkPollingEnabled | boolean | Current state of automatic network polling |
+| isCheckingConnection | boolean | Whether a connectivity check is currently in progress |
+| startNetworkPolling | () => void | Function to start automatic network polling |
+| stopNetworkPolling | () => void | Function to stop automatic network polling |
+| forceCheckNetwork | () => void | Function to manually trigger a connectivity check |
+| getCanReachToInternetStatus | () => boolean | Function to get current internet reachability status |
+
+## Usage Examples
+
+### Basic App Setup
+
+```tsx
+import { CanReachToInternetCtxProvider } from 'classic-react-hooks'
+
+function App() {
+ return (
+
+
+
+
+
+ )
+}
+```
+
+### Custom Configuration
+
+::: details Example
+
+```tsx
+import { CanReachToInternetCtxProvider } from 'classic-react-hooks'
+
+function App() {
+ return (
+
+
+
+
+
+ )
+}
+```
+
+:::
diff --git a/apps/doc/getting-started/overview.md b/apps/doc/getting-started/overview.md
index 7904c90..186642b 100644
--- a/apps/doc/getting-started/overview.md
+++ b/apps/doc/getting-started/overview.md
@@ -1,35 +1,27 @@
# Overview
-## What is **classic-react-hooks**?
+**_`classic-react-hooks`_** is a lightweight yet powerful library of custom _react-hooks_ and _components_ that streamline everyday development.
-- **`classic-react-hooks`** is collection of feature packed custom react hooks
-- It helps you to write day-to-day code in a manner which is easy to write, declarative and maintainable.
+It encourages you write _`clean`_, _`declarative`_, and _`modular`_ code that remains easy to maintain and scale as your project grows.
## Installation
::: code-group
-```bash [npm]
-npm install classic-react-hooks
+```sh [npm]
+$ npm install classic-react-hooks
```
-```bash [yarn]
-yarn add classic-react-hooks
+```sh [yarn]
+$ yarn add classic-react-hooks
```
-```bash [pnpm]
-pnpm add classic-react-hooks
+```sh [pnpm]
+$ pnpm add classic-react-hooks
```
-```bash [bun]
-bun add classic-react-hooks
+```sh [bun]
+$ bun add classic-react-hooks
```
:::
-
-## Features
-
-- Comprehensive hooks collection
-- Typesafe (Built in Typescript)
-- Comes with treeshaking
-- Small, Minimal and Easy to use
diff --git a/apps/doc/hooks/use-can-reach-to-internet.md b/apps/doc/hooks/use-can-reach-to-internet.md
new file mode 100644
index 0000000..6ca444e
--- /dev/null
+++ b/apps/doc/hooks/use-can-reach-to-internet.md
@@ -0,0 +1,154 @@
+---
+outline: deep
+---
+
+# use-can-reach-to-internet
+
+A comprehensive React hook for monitoring internet connectivity status that goes beyond basic online/offline detection by actually testing network reachability.
+
+## Features
+
+- **Real connectivity testing:** Performs actual HTTP requests to verify internet access
+- **Dual-layer detection:** Combines browser's `navigator.onLine` with network reachability tests
+- **Automatic monitoring:** Configurable polling intervals for continuous connectivity monitoring
+- **Manual control:** Start/stop polling and force connectivity checks on demand
+- **Cleanup handling:** Proper cleanup of network requests and timers to prevent memory leaks
+
+## Problem It Solves
+
+::: details The Problem with `navigator.onLine`
+
+---
+
+**Problem:-** `navigator.onLine` only tells you if the browser thinks it's connected to a network, not if it can actually reach the internet.
+
+Common Scenarios Where `navigator.onLine` Fails
+
+- **Limited Connectivity:** Your device is connected to a router, but the router has no internet connection. The browser sees the local network connection and reports online status as true.
+- **Network Issues:** DNS problems or ISP outages where you have network connection but can't reach to external servers.
+- **Captive Portals:** You're connected to WiFi at a hotel, airport but haven't authenticated yet. `navigator.onLine` returns true, but you can't access any websites.
+
+---
+
+**Solution:-** How `useCanReachToInternet` solve these problems
+
+It provides two layers of connectivity detection
+
+- **`isOnline`:** Browser's basic network status (via `navigator.onLine`)
+- **`canReachToInternet`:** Actual internet reachability (via real HTTP requests to a test server)
+- **`isFullyConnected`:** Both conditions must be true for genuine internet access
+ :::
+
+## Important Notes
+
+::: danger Important
+
+- Performance Considerations:
+ - Network polling makes regular HTTP requests - use appropriate intervals
+ - Consider battery usage on mobile devices with frequent polling
+ - The hook automatically cleans up requests to prevent memory leaks
+- CORS Limitations:
+ - Uses `mode: 'no-cors'` for broader compatibility
+ - Default test URL `(https://dns.google)` is chosen for reliability
+
+:::
+
+## Parameters
+
+| Parameter | Type | Required | Default Value | Description |
+| --------- | :--------------------------------------------: | :------: | :-----------: | -------------------------------------------------- |
+| options | [CanReachToInternetOptions](#type-definitions) | ❌ | {} | Configuration object for customizing hook behavior |
+
+### Options Parameter
+
+| Property | Type | Default | Description |
+| ---------------------- | ------- | ------------------- | ----------------------------------------------------------------------------------------------------------------- |
+| enableNetworkPolling | boolean | true | Controls whether the hook should automatically and continuously check internet connectivity at regular intervals. |
+| networkPollingInterval | number | 3000 | Specifies the interval in milliseconds for polling. |
+| testUrl | string | https://dns.google' | The URL endpoint used to test actual internet connectivity with HEAD method. |
+
+### Type Definitions
+
+```ts
+type CanReachToInternetOptions = {
+ /** Enable automatic network polling to continuously check connectivity */
+ enableNetworkPolling?: boolean
+ /** Interval in milliseconds between network polls */
+ networkPollingInterval?: number
+ /** URL to test internet connectivity against */
+ testUrl?: string
+}
+
+type CanReachToInternetBoolean = boolean
+```
+
+## Return value(s)
+
+This hook provides full list of status flags and callbacks for internet reachability tracking
+
+| Property | Type | Description |
+| --------------------------- | ------------- | -------------------------------------------------------------------------------- |
+| isOnline | boolean | Browser's native online/offline status from `navigator.onLine` |
+| canReachToInternet | boolean | Whether the device can actually reach the internet (verified via HTTP request) |
+| isFullyConnected | boolean | Combined status: `true` when both `isOnline` and `canReachToInternet` are `true` |
+| isNetworkPollingEnabled | boolean | Current state of automatic network polling |
+| isCheckingConnection | boolean | Whether a connectivity check is currently in progress |
+| startNetworkPolling | () => void | Function to start automatic network polling |
+| stopNetworkPolling | () => void | Function to stop automatic network polling |
+| forceCheckNetwork | () => void | Function to manually trigger a connectivity check |
+| getCanReachToInternetStatus | () => boolean | Function to get current internet reachability status |
+
+## Common Use Cases
+
+- **Real Internet stats:** Show connection status, disable features when offline
+- **Error handling:** Distinguish between network errors and server errors
+- **Auto-retry logic:** Retry failed requests when connectivity is restored
+
+## Usage Examples
+
+### Basic Network query
+
+```ts
+import { useCanReachToInternet } from 'classic-react-hooks'
+
+function NetworkStatus() {
+ const { isOnline, canReachToInternet, isFullyConnected } = useCanReachToInternet()
+
+ return (
+
+
Browser Online: {isOnline ? '✅' : '❌'}
+
Internet Reachable: {canReachToInternet ? '✅' : '❌'}
+
Fully Connected: {isFullyConnected ? '🟢 Connected' : '🔴 Disconnected'}
+
+ )
+}
+```
+
+### Conditional Rendering Based on Connectivity
+
+::: details Example
+
+```ts
+import { useCanReachToInternet } from 'classic-react-hooks'
+
+function DataFetchingComponent() {
+ const { isFullyConnected, isCheckingConnection } = useCanReachToInternet()
+
+ if (isCheckingConnection) {
+ return Checking connection...
+ }
+
+ if (!isFullyConnected) {
+ return (
+
+
No Internet Connection
+
Please check your connection and try again.
+
+ )
+ }
+
+ return
+}
+```
+
+:::
diff --git a/apps/doc/hooks/use-copy-to-clipboard.md b/apps/doc/hooks/use-copy-to-clipboard.md
index 1945c40..be622dc 100644
--- a/apps/doc/hooks/use-copy-to-clipboard.md
+++ b/apps/doc/hooks/use-copy-to-clipboard.md
@@ -4,65 +4,95 @@ outline: deep
# use-copy-to-clipboard
-- A hook for copying the data in the clipboard with success and error callbacks.
+A React hook that provides simple and reliable way to copy text to the clipboard with success and error handling callbacks.
-### Parameters
+## Features
-| Parameter | Type | Required | Default Value | Description |
-| --------- | :---------------------: | :------: | :-----------: | ----------- |
-| Object | [Props](#parametertype) | ❌ | - | Object |
+- **Clipboard API Support:** Uses the modern [navigator.clipboard](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API) API for secure clipboard access
+- **Fallback Handling:** Gracefully handles cases where clipboard API is not available
+- **Success/Error Callbacks:** Built-in success and error handling with customizable callbacks
+- **Flexible Configuration:** Configure global callbacks via props or override per-call
+- **Performance Optimized:** Zero re-renders - purely ref-based
-### Returns
+## Parameters
-[`CopyToClipboardFn`](#returntype) : A function for copying the data into clipboard
+| Parameter | Type | Required | Default Value | Description |
+| --------- | :----------------------------: | :------: | :-----------: | --------------------------------- |
+| onSuccess | [OnSuccess](#type-definitions) | ❌ | - | Default success callback function |
+| onError | [OnError](#type-definitions) | ❌ | - | Default error callback function |
-### Types
+::: warning
+Any occured errors during operation are passed to the `onError` callback with descriptive error messages.
+:::
----
-
-#### ParameterType
+### Type Definitions
```ts
-type Props = {
- onSuccess?: OnSuccess
- onError?: onError
-}
-
type OnSuccess = () => void
type OnError = (err: Error) => void
```
-#### ReturnType
+## Return Value(s)
+
+The hook returns a function which will copy the provided data into the clipboard
+
+| Return Value | Type | Description |
+| -------------------------- | ------------------- | ---------------------------------- |
+| `copyToClipboard` function | `CopyToClipboardFn` | Handler function to copy text data |
+
+### Type Definitions
```ts
type CopyToClipboardFn = (data: string, onSuccess?: OnSuccess, onError?: OnError) => Promise
```
-### Usage
+## Common Use Cases
-```ts
+- Copy text data programatically
+
+## Usage Examples
+
+### Basic usage
+
+```ts {7-15}
import { useState } from 'react'
import { useCopyToClipboard } from 'classic-react-hooks'
-export default function YourComponent() {
- const [data, setData] = useState('')
- const copyToClipboard = useCopyToClipboard()
-
- return (
-
- setData(e.target.value)} />
-
- copyToClipboard(
- data,
- () => console.log('success'),
- (err) => console.log(err)
- )
- }
- >
- copy
-
-
- )
+export default function CopyButton() {
+ const [copied, setCopied] = useState(false)
+
+ const copyToClipboard = useCopyToClipboard({
+ onSuccess: () => {
+ setCopied(true)
+ setTimeout(() => setCopied(false), 2000)
+ },
+ onError: (error) => {
+ console.error('Failed to copy:', error)
+ },
+ })
+
+ const handleCopy = () => {
+ copyToClipboard('Hello, World!')
+ }
+
+ return {copied ? 'Copied!' : 'Copy Text'}
}
```
+
+## Alternative: Non-React Usage
+
+For use outside of React components, use the standalone function:
+
+```ts
+import { copyToClipboardFn } from 'classic-react-hooks'
+
+// Simple copy
+copyToClipboardFn('Text to copy')
+
+// With callbacks
+copyToClipboardFn(
+ 'Text to copy',
+ () => console.log('Copied successfully!'),
+ (error) => console.error('Copy failed:', error)
+)
+```
diff --git a/apps/doc/hooks/use-counter.md b/apps/doc/hooks/use-counter.md
index 409d779..9538581 100644
--- a/apps/doc/hooks/use-counter.md
+++ b/apps/doc/hooks/use-counter.md
@@ -4,23 +4,42 @@ outline: deep
# use-counter
-- A simple hook for managing counter.
+A Hook for Fun
-### Parameters
+A type-safe React hook for managing counter state with customizable step values and dynamic property naming.
-| Parameter | Type | Required | Default Value | Description |
-| ------------ | :----: | :------: | :-----------: | --------------------------------------------------------------------------- |
-| key | string | ❌ | "" | Based on the key, it generates `type-safe` object with `prefixed` proprety. |
-| initialValue | number | ❌ | 0 | Initial value of the counter. |
+## Features
-### Returns
+- Find out yourself buddy
-- It returns an object.
-- `counter` : number
-- `incrementCounter` : () => void
-- `decrementCounter` : () => void
+## Parameters
-### Usage
+| Parameter | Type | Required | Default Value | Description |
+| ------------ | ------ | :------: | :-----------: | ------------------------------------------------------------------------- |
+| key | string | ❌ | "" | Prefix for generated property names. Creates type-safe object properties. |
+| props | object | ❌ | undefined | Configuration object containing `initialValue` and `stepper`. |
+| initialValue | number | ❌ | 0 | Initial value for the counter. |
+| stepper | number | ❌ | 1 | Amount to increment/decrement by on each operation. |
+
+## Return value(s)
+
+Returns a type-safe object with dynamically named properties:
+
+### Without key (default):
+
+- `counter:` number - Current counter value
+- `incrementCounter:` () => void - Function to increment counter
+- `decrementCounter:` () => void - Function to decrement counter
+
+### With key (e.g., "user"):
+
+- `userCounter:` number - Current counter value
+- `incrementUserCounter:` () => void - Function to increment counter
+- `decrementUserCounter:` () => void - Function to decrement counter
+
+## Usage Examples
+
+### Basic Counter
```ts
import { useCounter } from 'classic-react-hooks'
@@ -42,3 +61,24 @@ export default function YourComponent() {
)
}
```
+
+### Named Counter with Custom Step
+
+```ts
+import { useCounter } from 'classic-react-hooks'
+
+export default function UserScoreCounter() {
+ const { userCounter, incrementUserCounter, decrementUserCounter } = useCounter('user', {
+ initialValue: 10,
+ stepper: 5,
+ })
+
+ return (
+
+
User Score: {userCounter}
+ -5
+ +5
+
+ )
+}
+```
diff --git a/apps/doc/hooks/use-debounced-fn.md b/apps/doc/hooks/use-debounced-fn.md
index d225959..0c4a926 100644
--- a/apps/doc/hooks/use-debounced-fn.md
+++ b/apps/doc/hooks/use-debounced-fn.md
@@ -2,39 +2,188 @@
outline: deep
---
-# use-debouced-fn
+# use-debounced-fn
-- A hook which returns a debounced function.
+A React hook that returns a debounced version of any function, delaying its execution until after a specified delay has passed since the last time it was invoked.
-### Parameters
+## Features
-| Parameter | Type | Required | Default Value | Description |
-| --------- | :------: | :------: | :-----------: | ----------------------------------------------------------- |
-| cb | Function | ✅ | - | A callback which is to be debounced. |
-| delay | number | ❌ | 300 | A delay in milliseconds after that the callback gets fired. |
+- **Auto cleanup:** Timeouts are automatically cleared on unmount or dependency changes
+- **Flexible delay:** Configurable delay with sensible defaults
+- **Performance Optimized:** Prevents excessive function calls during rapid user interactions
+- **Error handling:** Preserves original function's error behavior
-### Returns
+::: tip
+The `debounced function` is purely ref based and does not change across re-renders.
+:::
-- It returns a function which is debouced version of passed callback.
+## Problem It Solves
-### Usage
+::: details **Boilerplate Reduction**
+
+---
+
+**Problem:-** Manually implementing debouncing in React components leads to lengthy, error-prone code with potential memory leaks and stale closures.
+
+```tsx
+// ❌ Problematic approach which is redundant and lengthy
+function SearchInput() {
+ const [query, setQuery] = useState('')
+ const [results, setResults] = useState([])
+ const timeoutRef = useRef()
+
+ const handleSearch = useCallback(async (searchTerm: string) => {
+ if (timeoutRef.current) {
+ clearTimeout(timeoutRef.current)
+ }
+
+ timeoutRef.current = setTimeout(async () => {
+ try {
+ if (searchTerm.trim()) {
+ const response = await fetch(`/api/search?q=${searchTerm}`)
+ const data = await response.json()
+ setResults(data.results)
+ }
+ } catch (error) {
+ console.error('Search failed:', error)
+ }
+ }, 500)
+ }, [])
+
+ useEffect(() => {
+ return () => {
+ if (timeoutRef.current) {
+ clearTimeout(timeoutRef.current) // Manual cleanup on unmount
+ }
+ }
+ }, [])
+
+ const handleInputChange = (e: React.ChangeEvent) => {
+ const value = e.target.value
+ setQuery(value)
+ handleSearch(value)
+ }
+
+ return
+}
+```
+
+---
+
+**Solution:-**
+
+- Eliminates repetitive debounce timing logic
+- Automatic cleanup ensures timeouts are cleared when:
+ - Component unmounts
+ - Delay value changes
+ - Function reference changes
+
+```tsx
+// ✅ Clean, declarative approach
+function SearchInput() {
+ const [query, setQuery] = useState('')
+ const [results, setResults] = useState([])
+
+ const debouncedSearch = useDebouncedFn({
+ callbackToBounce: async (searchTerm: string) => {
+ if (searchTerm.trim()) {
+ const response = await fetch(`/api/search?q=${searchTerm}`)
+ const data = await response.json()
+ setResults(data.results)
+ }
+ },
+ delay: 500,
+ })
+
+ const handleInputChange = (e: React.ChangeEvent) => {
+ const value = e.target.value
+ setQuery(value)
+ debouncedSearch(value)
+ }
+
+ return
+}
+```
+
+:::
+
+::: details **Performance Benefits**
+
+- **Reduces execution frequency:** Limits function calls during rapid user input
+- **Memory efficient:** Proper cleanup prevents memory leaks from pending timeouts
+- **Stable references:** Function reference remains stable across re-renders
+
+:::
+
+## Parameters
+
+| Parameter | Type | Required | Default Value | Description |
+| ---------------- | :------------------------------: | :------: | :-----------: | ----------------------------------------------- |
+| callbackToBounce | [DebouncedFn](#type-definitions) | ✅ | - | The function to debounce |
+| delay | number | ❌ | 300ms | Delay in milliseconds before function execution |
+
+### Type Definitions
+
+::: details
```ts
+export type DebouncedFn any> = (...args: Parameters) => void
+```
+
+:::
+
+## Return Value(s)
+
+The hook returns a debounced version of the provided callback.
+
+| Return Value | Type | Description |
+| ------------- | ---------------------------------- | --------------------------------------------------------------------------------------- |
+| `debouncedFn` | `(...args: Parameters) => void` | Debounced version of the original function that delays execution by the specified delay |
+
+## Common Use Cases
+
+- **Search functionality:** Debouncing search queries to reduce API calls
+- **API rate limiting:** Preventing excessive API requests
+
+## Usage Examples
+
+### Basic Search Debouncing
+
+```tsx {8-19}
import { useState } from 'react'
import { useDebouncedFn } from 'classic-react-hooks'
-export default function YourComponent() {
- const [debouncedInput, setDebouncedInput] = useState('')
- const updateInput = useDebouncedFn((e) => {
- setDebouncedInput(e.target.value)
- }, 300)
+export default function SearchExample() {
+ const [query, setQuery] = useState('')
+ const [results, setResults] = useState([])
+
+ const debouncedSearch = useDebouncedFn({
+ callbackToBounce: async (searchTerm: string) => {
+ if (searchTerm.trim()) {
+ const response = await fetch(`https://api.example.com/search?q=${searchTerm}`)
+ const data = await response.json()
+ setResults(data.results)
+ } else {
+ setResults([])
+ }
+ },
+ delay: 500,
+ })
+
+ const handleInputChange = (e: React.ChangeEvent) => {
+ const value = e.target.value
+ setQuery(value)
+ debouncedSearch(value)
+ }
return (
-
-
- value - {debouncedInput}
-
+
+
+ {results.map((result) => (
+
{result.name}
+ ))}
+
)
}
diff --git a/apps/doc/hooks/use-event-listener.md b/apps/doc/hooks/use-event-listener.md
index d52c965..643e6f0 100644
--- a/apps/doc/hooks/use-event-listener.md
+++ b/apps/doc/hooks/use-event-listener.md
@@ -4,45 +4,262 @@ outline: deep
# use-event-listener
-- A hook which handles dom events in efficient and declarative manner.
+A React hook that makes it easy to attach DOM event listeners declaratively with automatic cleanup.
-### Parameters
+## Features
-| Parameter | Type | Required | Default Value | Description |
-| --------- | :-----------------------: | :------: | :-----------: | ------------------------------ |
-| target | [Target](#parametertype) | ✅ | - | Reference of the html element |
-| event | string | ✅ | - | Event name |
-| handler | [Handler](#parametertype) | ❌ | undefined | Callback for the event |
-| options | [Options](#parametertype) | ❌ | undefined | For managing Event Propagation |
+- **Flexible Targeting:** Observe elements via the _`target`_ prop or _`setElementRef`_ function.
+- **Auto Cleanup:** Listeners are automatically managed on unmount or dependency changes.
+- **Reactive:** Listeners intelligently reattach when _`target`_, _`event`_, or _`options`_ change.
+- **Conditional Binding:** Attach listeners only when _`target`_, a _`handler`_, and _`shouldInjectEvent`_ are valid.
+- **Full options support:** Fully compatible with all _`AddEventListenerOptions`_ including _capture_, _once_, _passive_, and _signal_.
-### Types
+::: warning Usage Note
+
+- Do not pass _`target`_ prop if using _`setElementRef`_ and vise-versa.
+
+:::
+
+## Problem It Solves
+
+::: details **Boilerplate Reduction**
+
+Manually managing event listeners in React components leads to verbose, repetitive and error-prone code with potential memory leaks.
+See the below implementation:
+
+```tsx
+// ❌ Problematic approach which is redundant and verbose
+function Component() {
+ const [scrollY, setScrollY] = useState(0)
+
+ useEffect(() => {
+ const handleScroll = () => {
+ setScrollY(window.scrollY)
+ }
+
+ window.addEventListener('scroll', handleScroll)
+ return () => window.removeEventListener('scroll', handleScroll) // Doing proper cleanup on unmount
+ }, [])
+
+ return Current: {scrollY}
+}
+```
---
-#### ParameterType
+How _`use-event-listener`_ solves it:
+
+- Eliminates repetitive `addEventListener/removeEventListener` code
+- Reduces component complexity by abstracting event handling logic
+- Automatic cleanup ensures listeners are removed when:-
+ - Component unmounts
+ - `target` element changes
+ - `event` type changes
+ - Any of `options` params:- (_shouldInjectEvent_, _capture_, _once_, _passive_, _signal_) gets changed
+
+```tsx
+// ✅ Clean, declarative approach
+function Component() {
+ const [scrollY, setScrollY] = useState(0)
+ const breakpoint = useEventListener({
+ target: () => window,
+ event: 'scroll',
+ handler: () => {
+ setScrollY(window.scrollY)
+ },
+ })
+
+ return Current: {scrollY}
+}
+```
+
+:::
+
+::: details **Performance Benefits**
+
+- Stable references accross re-renders which prevents listeners from being repeatedly added/removed
+
+- Efficient dependency tracking
+
+:::
+
+## Parameters
+
+| Parameter | Type | Required | Default Value | Description |
+| --------- | :----------------------------: | :------: | :-----------: | ------------------------------------------------- |
+| target | [EvTarget](#type-definitions) | ✅ | - | Target element on which the event is listened to. |
+| event | string | ✅ | - | Event name (e.g. 'click', 'keydown') |
+| handler | [EvHandler](#type-definitions) | ❌ | undefined | Event listener callback function |
+| options | [EvOptions](#type-definitions) | ❌ | undefined | Standard Options and Feature flags |
+| |
+
+### Options Parameter
+
+The _`options`_ parameter supports all standard _`AddEventListenerOptions`_ and introduces extra custom properties to control conditional event binding.
+
+#### Standard _`AddEventListenerOptions`_
+
+| Property | Type | Default | Description |
+| -------- | ----------- | --------- | -------------------------------------------------------------------------------- |
+| capture | boolean | false | If `true`, the listener will be triggered during the capture phase |
+| once | boolean | false | If `true`, the listener will be automatically removed after being triggered once |
+| passive | boolean | false | If `true`, indicates that the function will never call `preventDefault()` |
+| signal | AbortSignal | undefined | An AbortSignal that can be used to remove the event listener |
+
+#### Custom _`Options`_
+
+| Property | Type | Default | Description |
+| ----------------- | -------------- | ------- | --------------------------------------------------------------------------------------------------- |
+| shouldInjectEvent | boolean \| any | true | Controls whether the event listener should be attached. When false, the event listener is not added |
+
+### Type Definitions
+
+::: details
```ts
-type Target = null | EventTarget | (() => EventTarget | null)
-type Options = boolean | (AddEventListenerOptions & { shouldInjectEvent?: boolean | any })
-type Handler = (event: Event) => void
+export type EvTarget = () => EventTarget | null
+export type EvHandler = (event: Event) => void
+
+export interface EvOptions extends AddEventListenerOptions {
+ // Standard AddEventListenerOptions:
+ capture?: boolean
+ once?: boolean
+ passive?: boolean
+ signal?: AbortSignal
+
+ // Custom option:
+ shouldInjectEvent?: boolean | any // Controls whether the event should be attached
+}
```
-### Usage
+:::
+
+## Return Value(s)
+
+This hook returns an object that includes a setter function, allowing you to observe and manage the target element through its ref attribute.
+
+| Property | Type | Description |
+| ------------- | ------------------------- | ------------------------------------------------------------------- |
+| setElementRef | [Function](#return-types) | A ref callback that observes the target element for event listening |
+
+### Return Types
+
+::: details
```ts
+export type UseEventListenerReturnValues = {
+ setElementRef: (elementNode: HTMLElement | null) => void
+}
+```
+
+:::
+
+## Common Use Cases
+
+- Adding dom events (e.g 'click', 'keydown', 'resize', 'scroll')
+
+## Usage Examples
+
+### Basic Click Handler
+
+```ts {7-13}
import { useRef } from 'react'
import { useEventListener } from 'classic-react-hooks'
-export default function YourComponent() {
- const ref = useRef()
- useEventListener(ref, 'click', (e) => {
- console.log(e)
+export default function ClickExample() {
+ const buttonRef = useRef(null)
+
+ useEventListener({
+ target: () => buttonRef.current,
+ event: 'click',
+ handler: (e) => {
+ console.log('Button clicked!', e)
+ },
+ })
+
+ return Click me
+}
+```
+
+### Listening Window Event
+
+::: details Example
+
+```ts {6-9}
+import { useEventListener } from 'classic-react-hooks'
+
+export default function WindowExample() {
+ useEventListener({
+ target: () => window,
+ event: 'resize',
+ handler: (e) => {
+ console.log('Window resized:', window.innerWidth, window.innerHeight)
+ },
+ })
+
+ return Resize the window and check console
+}
+```
+
+:::
+
+### Conditional Event Listening
+
+::: details Example
+
+```ts
+import { useState } from 'react'
+import { useEventListener } from 'classic-react-hooks'
+
+export default function ConditionalExample() {
+ const [isListening, setIsListening] = useState(true) // [!code ++]
+
+ useEventListener({
+ target: () => document,
+ event: 'keydown',
+ handler: (e) => {
+ console.log('Key pressed:', e.key)
+ },
+ options: {
+ shouldInjectEvent: isListening, // Only listen when enabled // [!code ++]
+ },
})
return (
-
button
+
setIsListening(!isListening)}>{isListening ? 'Stop' : 'Start'} Listening
+
Press any key (when listening is enabled)
)
}
```
+
+:::
+
+### Usage with `setElementRef`
+
+::: details Example
+
+```ts {6,16}
+import { useState } from 'react'
+import { useEventListener } from 'classic-react-hooks'
+
+export default function ConditionalExample() {
+ const [counter, setCounter] = useState(0)
+ const { setElementRef } = useEventListener({
+ event: 'click',
+ handler: () => {
+ console.log(counter)
+ },
+ })
+
+ return (
+
+
setCounter((c) => c + 1)}>update counter {counter}
+
log value
+
+ )
+}
+```
+
+:::
diff --git a/apps/doc/hooks/use-intersection-observer.md b/apps/doc/hooks/use-intersection-observer.md
index 5636ece..ec2aa24 100644
--- a/apps/doc/hooks/use-intersection-observer.md
+++ b/apps/doc/hooks/use-intersection-observer.md
@@ -4,77 +4,249 @@ outline: deep
# use-intersection-observer
-- A hook which provides a way for listening to the Intersection Observer event for given target.
-- It returns an array of boolean values which represents whether the targets are intersecting the screen or not.
+A React hook that provides a declarative way to observe element visibility using the [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) API.
-### Parameters
+::: danger Important
-| Parameter | Type | Required | Default Value | Description |
-| --------- | :------------------------: | :------: | :-----------: | ------------------------------------------------------------- |
-| targets | [Target[]](#parametertype) | ✅ | - | Array of targets which contains reference of the html element |
-| options | [Options](#parametertype) | ❌ | {} | Options to pass as feature flag |
+This hook automatically checks for `IntersectionObserver` support and logs a warning in development if it's not available. The hook will gracefully handle unsupported browsers by not creating observers.
+:::
-### Types
+## Features
----
+- **Auto cleanup:** Automatic cleanup of observers on unmount and dependency change
+- **Reactive:** Listeners intelligently reattach when _`element`_ or _`onlyTriggerOnce`_ changes
+- **Flexible keys:** Support for custom property naming through the `key` parameter with full-type safety
+- **One-time Observation:** Built-in support for observing elements only once
+- **Full options support:** Full support for all `IntersectionObserverInit` options ([root](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/root), [rootMargin](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/rootMargin), [threshold](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/thresholds))
-#### ParameterType
+::: tip
+This hook internally uses [useSyncedRef](/hooks/use-synced-ref) to avoid unnecessary re-renders when callback functions change
+:::
-```ts
-type Target = HTMLElement | RefObject | (() => HTMLElement | null) | null
-type Options = {
- mode?: 'lazy' | 'virtualized'
-} & IntersectionObserverInit
-```
+## Problem It Solves
+
+::: details Type-Safe Instance Management
+
+- **Dynamic & Type-Safe Properties:** Generates uniquely named properties for each observer with full TypeScript and IntelliSense support.
+- **Scalable:** Efficiently observe any number of elements without property naming conflicts.
+
+````tsx
+// Example: Dynamically named properties based on the 'key'
+const { element, setElementRef, isElementIntersecting } = useIntersectionObserver() // Without key
+const { sidebarElement, setSidebarElementRef, isSidebarElementIntersecting } = useIntersectionObserver({
+ key: 'sidebar', // With key 'sidebar'
+})
+
+
+:::
+
+::: details One-Time Observation Complexity
+
+- _`onlyTriggerOnce`_ option for automatically cleaning up observer after first intersection
+ :::
+
+## Parameters
+
+| Parameter | Type | Required | Default Value | Description |
+| --------- | :----------------------------------------------: | :------: | :-----------: | -------------------------------------------------- |
+| options | [IntersectionObserverOptions](#type-definitions) | ❌ | undefined | Configuration object for the intersection observer |
+
+### Options Parameter
+
+The `options` parameter accepts an object that extends the standard `IntersectionObserverInit` with an additional custom property for conditional event handling and post callback.
+
+#### Standard _`IntersectionObserverInit`_ Options
+
+| Property | Type | Default | Description |
+| ---------- | :-------------------------: | :-----: | ------------------------------- |
+| key | string | '' | Custom key for property naming |
+| root | Element \| Document \| null | null | Root element for intersection |
+| rootMargin | string | 0px | Margin around root element |
+| threshold | number \| number[] | 0 | Intersection ratio threshold(s) |
+
+#### Custom _`Options`_
+
+| Property | Type | Default | Description |
+| --------------- | :----------------------------------------: | :-------: | --------------------------------------------------------- |
+| onlyTriggerOnce | boolean | false | Controls whether to observe only the initial intersection |
+| onIntersection | (entry: IntersectionObserverEntry) => void | undefined | Callback fired on every intersection of the element |
+
+### Type Definitions
-### Usage
+::: details
```ts
-import { ElementRef, useRef } from 'react'
-import { useInterSectionObserver } from 'classic-react-hooks'
-
-export default function Intersection() {
- const purpleBoxRef = useRef>(null)
- const greenBoxRef = useRef>(null)
- const [isPurpleVisible, isGreenVisible] = useInterSectionObserver([purpleBoxRef, greenBoxRef], {
- threshold: 0,
- root: null,
- rootMargin: '-150px',
- mode: 'virtualized',
+export interface BaseIntersectionObserverOptions {
+ onIntersection?: (entry: IntersectionObserverEntry) => void
+ onlyTriggerOnce?: boolean
+}
+
+export interface IntersectionObserverOptions
+ extends IntersectionObserverInit,
+ BaseIntersectionObserverOptions {
+ key?: Key
+}
+
+export type IntersectionObserverResult = {
+ // Dynamic property names based on key
+ [K in Key as Key extends '' ? 'element' : `${Key}Element`]: HTMLElement | null
+} & {
+ [K in Key as Key extends '' ? 'setElementRef' : `set${Capitalize}ElementRef`]: (
+ elementNode: HTMLElement | null
+ ) => void
+} & {
+ [K in Key as Key extends '' ? 'isElementIntersecting' : `is${Capitalize}ElementIntersecting`]: boolean
+}
+````
+
+:::
+
+## Return Value(s)
+
+The hook returns an object with dynamically named properties based on the `key` parameter:
+
+- **Without key:** `element`, `setElementRef`, `isElementIntersecting`
+- **With key:** `{key}Element`, `set{Key}ElementRef`, `is{Key}ElementIntersecting`
+
+::: info
+**`element`:** Holds the reference of element which is being observed, initial value is undefined.
+
+**`setElementRef`:** A Setter function to store the element reference within `element`, which will be observed.
+
+**`isElementIntersecting`:** Holds the boolean intersection status of the `element` weather it is intersecting the screen or not.
+:::
+
+## Common Use Cases
+
+- **Lazy loading:** Load images or content when they come into view
+- **Infinite scrolling:** Load more content when reaching the end
+- **Performance optimization:** Pause expensive operations when elements are not visible
+
+## Usage Examples
+
+### Basic Intersection Observer
+
+```tsx {4-9,14}
+import { useIntersectionObserver } from 'classic-react-hooks'
+
+export default function BasicExample() {
+ const { element, setElementRef, isElementIntersecting } = useIntersectionObserver({
+ threshold: 0.5,
+ onIntersection: (entry) => {
+ console.log('Intersection changed:', entry.isIntersecting)
+ },
})
return (
- <>
-
- Scroll to the very bottom of the page
-
-
-
- Lorem ipsum dolor sit amet consectetur adipisicing elit. Modi quae illum rem quod recusandae a tempora
- officia natus quos dignissimos, eum beatae ea! Consectetur nemo assumenda eligendi optio voluptatum fuga.
-
-
- Lorem ipsum dolor sit amet consectetur adipisicing elit. Modi quae illum rem quod recusandae a tempora
- officia natus quos dignissimos, eum beatae ea! Consectetur nemo assumenda eligendi optio voluptatum fuga.
-
+
+
+
+ {isElementIntersecting ? 'Visible!' : 'Not visible'}
+
+
+
+ )
+}
+```
-
+
- purple
+ Hero Section {isHeroElementIntersecting ? '(Visible)' : '(Hidden)'}
+
+
+
Scroll to see the hero section intersection status change
+
+
+ )
+}
+```
+
+:::
+
+### One-Time Trigger
+
+::: details Example
+
+```tsx {7-16}
+import { useState } from 'react'
+import { useIntersectionObserver } from 'classic-react-hooks'
+
+export default function OneTimeExample() {
+ const [hasBeenSeen, setHasBeenSeen] = useState(false)
+
+ const { setElementRef, isElementIntersecting } = useIntersectionObserver({
+ onlyTriggerOnce: true, // [!code ++]
+ threshold: 0.8,
+ onIntersection: (entry) => {
+ if (entry.isIntersecting) {
+ setHasBeenSeen(true)
+ console.log('Element seen for the first time!')
+ }
+ },
+ })
+
+ return (
+
+
+
+ {hasBeenSeen ? 'I was seen!' : 'Scroll down to see me'}
+
+
+ )
+}
+```
+
+:::
+
+### Multiple Thresholds
+
+::: details Example
+
+```tsx {4-10}
+import { useIntersectionObserver } from 'classic-react-hooks'
+
+export default function MultipleThresholdsExample() {
+ const { setElementRef, isElementIntersecting } = useIntersectionObserver({
+ threshold: [0, 0.25, 0.5, 0.75, 1.0], // [!code ++]
+ onIntersection: (entry) => {
+ const percentage = Math.round(entry.intersectionRatio * 100)
+ console.log(`Element is ${percentage}% visible`)
+ },
+ })
+
+ return (
+
+
- green
+
Check console for intersection percentage
- >
+
)
}
```
+
+:::
diff --git a/apps/doc/hooks/use-interval-effect.md b/apps/doc/hooks/use-interval-effect.md
index d572d7a..20a0ce2 100644
--- a/apps/doc/hooks/use-interval-effect.md
+++ b/apps/doc/hooks/use-interval-effect.md
@@ -4,38 +4,53 @@ outline: deep
# use-interval-effect
-- A hooks which fires the provided callback every time when the given delay is passed, just like the `setInterval`.
+A React hook that executes a callback function at regular intervals, similar to `setInterval` but with additional control methods for clearing and restarting the timer.
-### Parameters
+## Features
-| Parameter | Type | Required | Default Value | Description |
-| --------- | :------: | :------: | :-----------: | -------------------------------------------------------------------- |
-| cb | Function | ✅ | - | Callback gets fired after every given amount of interval is passed . |
-| interval | number | ❌ | 100 | Interval value after which the callback is fired. |
+- **Recurring execution:** Executes a callback at regular intervals
+- **Flexible control:** Provides methods to clear or restart the timer with different intervals
+- **Auto cleanup:** Automatically clears up interval on component unmount
-### Returns
+## Parameters
-- It returns an object.
-- `clearTimer` : () => void
-- `restartTimer` : () => void
+| Parameter | Type | Required | Default Value | Description |
+| --------- | :------: | :------: | :-----------: | --------------------------------------------------------------- |
+| handler | Function | ✅ | - | The callback function to execute at each interval |
+| interval | number | ❌ | 100 | The delay in milliseconds between each execution of the handler |
-### Usage
+## Return value(s)
+
+This hooks returns an object having several utility functions for controlling the interval-effect:
+
+| Property | Type | Description |
+| ------------ | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| clearTimer | () => void | Clears the current interval timer, stopping the recurring execution of the handler. Similar to calling `clearInterval()` on a standard interval. |
+| restartTimer | (new_interval?: number) => void | Clears the current timer and starts a new one. Optionally accepts a `new_interval` parameter to use a different interval duration. If no interval is provided, uses the original interval value. |
+
+## Usage Examples
+
+### Basic example
```ts
import { useState } from 'react'
import { useIntervalEffect } from 'classic-react-hooks'
-export default function YourComponent() {
- const [counter, setCounter] = useState(0)
- const { clearTimer, restartTimer } = useIntervalEffect(() => {
- setCounter((c) => c + 1)
- }, 1000)
+export default function Counter() {
+ const [count, setCount] = useState(0)
+
+ const { clearTimer, restartTimer } = useIntervalEffect({
+ handler: () => setCount((prev) => prev + 1),
+ interval: 1000, // 1 second
+ })
return (
-
{counter}
-
Pause timer
-
Restart timer
+
Count: {count}
+
Pause
+
restartTimer()}>Resume
+
restartTimer(500)}>Speed Up (500ms)
+
restartTimer(2000)}>Slow Down (2s)
)
}
diff --git a/apps/doc/hooks/use-is-online.md b/apps/doc/hooks/use-is-online.md
deleted file mode 100644
index b42297c..0000000
--- a/apps/doc/hooks/use-is-online.md
+++ /dev/null
@@ -1,23 +0,0 @@
----
-outline: deep
----
-
-# use-is-online
-
-- A simple hook for getting the network connection state.
-
-### Returns
-
-- `connectionState` : boolean
-
-### Usage
-
-```ts
-import { useIsOnline } from 'classic-react-hooks'
-
-export default function YourComponent() {
- const isOnline = useIsOnline()
-
- return {isOnline ? 'online' : 'offline'}
-}
-```
diff --git a/apps/doc/hooks/use-local-storage.md b/apps/doc/hooks/use-local-storage.md
index 4af8e56..979fb83 100644
--- a/apps/doc/hooks/use-local-storage.md
+++ b/apps/doc/hooks/use-local-storage.md
@@ -4,49 +4,326 @@ outline: deep
# use-local-storage
-- A hook for managing the states with `local-storage`
-- It automatically updates the state in `local-storage`
-- It is `useState` with local storage power.
+A React hook that provides a seamless way to persist and synchronize state with `localStorage`, offering a `useState`-like API with cross-tab synchronization.
-### Parameters
+## Features
-| Parameter | Type | Required | Default Value | Description |
-| ------------ | :----: | :------: | :-----------: | ---------------------------------------------------- |
-| key | string | ✅ | - | key for getting an item from local-storage |
-| defaultValue | any | ❌ | - | A initial value when item is not found local-storage |
+- **`useState` Compatible API:** Drop-in replacement with identical API including functional updates
+- **SSR Compatible:** Default values prevent hydration mismatches
+- **Auto Synchronization:** Seamless bidirectional sync between React state, `localStorage` and across different browser tabs
+- **Error handling:** Graceful fallbacks when localStorage operations fail
-### Returns
+::: danger Important Notes
-- It returns an array of `state` and setter function `setState`.
-- `state` : It's type get inferred by `defaultValue` parameter.
-- `setState` : A function just like the setter function from `useState`.
+- **Automatic Serialization:** Data is automatically serialized to JSON when storing.
+- **Synchronous Updates:** State updates are synchronous and immediately persisted.
+- **Fallback value:** Always provide default values for SSR fallback.
+ :::
-### Usage
+## Problem It Solves
-```ts
-import { useLocalStorage } from 'classic-react-hooks'
+::: details Manual LocalStorage Synchronization
+
+---
+
+**Problem:-** Manually keeping React state synchronized with `localStorage` requires complex boilerplate code and is prone to sync issues.
+
+```tsx
+// ❌ Manual synchronization nightmare
+function UserSettings() {
+ const [theme, setTheme] = useState('light')
+
+ // Load from localStorage on mount
+ useEffect(() => {
+ const saved = localStorage.getItem('theme')
+ if (saved) {
+ try {
+ setTheme(JSON.parse(saved))
+ } catch (error) {
+ console.error('Failed to parse theme from localStorage')
+ }
+ }
+ }, [])
+
+ // Save to localStorage on every change
+ useEffect(() => {
+ localStorage.setItem('theme', JSON.stringify(theme))
+ }, [theme])
+
+ return (
+ {
+ setTheme(e.target.value)
+
+ // Or do this manually to sync with localStorage
+ // localStorage.setItem('theme', JSON.stringify(theme))
+ }}
+ >
+ Light
+ Dark
+
+ )
+}
+```
+
+---
+
+**Solution:-** This hook provides automatic bidirectional synchronization between React state and localStorage with a single line of code.
+
+It's designed to be a drop-in replacement for `useState`, maintaining the familiar API.
+
+```tsx
+// ✅ Automatic synchronization
+function UserSettings() {
+ const [theme, setTheme] = useLocalStorage({ key: 'theme', defaultValue: 'light' })
+
+ return (
+ setTheme(e.target.value)}>
+ Light
+ Dark
+
+ )
+}
+```
+
+:::
+::: details Inconsistent useState API Compatibility
+
+---
+
+**Problem:-** Custom localStorage solutions often don't maintain the familiar `useState` API, breaking developer expectations and existing code patterns.
+
+```tsx
+// ❌ Non-standard API breaks familiar patterns
+function BrokenComponent() {
+ const [count, updateCount] = someLocalStorageHook('count', 0)
+
+ // This doesn't work because updateCount doesn't support function updates
+ updateCount((prev) => prev + 1) // ❌ TypeError
+
+ // Forced to use unfamiliar patterns
+ updateCount(count + 1) // ❌ Race condition risk
+}
+```
+
+---
+
+**Solution:-** This hook maintains 100% API compatibility with useState, including support for functional updates and previous value callbacks.
+
+```tsx
+// ✅ Perfect useState compatibility
+function Component() {
+ const [count, setCount] = useLocalStorage({ key: 'count', defaultValue: 0 })
+
+ // All familiar useState patterns work perfectly
+ setCount(5) // Direct value
+ setCount((prev) => prev + 1) // Functional update
+ setCount((c) => c * 2) // Previous value callback
+}
+```
+
+:::
+
+::: details Server-Side Rendering Compatibility Issues
+
+---
+
+**Problem:-** Direct localStorage access during SSR causes `hydration mismatches` and crashes because localStorage isn't available on the server.
+
+```tsx
+// ❌ SSR/hydration nightmare
+function ProblematicComponent() {
+ const [theme, setTheme] = useState(() => {
+ return localStorage.getItem('theme') || 'light' // ❌ Crashes during SSR
+ })
+
+ // Hydration mismatch: server renders 'light', client might render 'dark'
+}
+```
+
+---
+
+**Solution:-** The hook's `defaultValue` prop ensures consistent initial renders and smooth hydration by providing predictable fallback values.
+
+```tsx
+// ✅ SSR-compatible with smooth hydration
+function SSRFriendlyComponent() {
+ const [theme, setTheme] = useLocalStorage({
+ key: 'theme',
+ defaultValue: 'light', // Used during SSR and as fallback
+ })
-export default function YourComponent() {
- const [user_details, setUserDetails] = useLocalStorage('user_details', {
- name: '',
+ // Server and client both start with 'light'
+ // Client hydrates smoothly, then updates from localStorage
+}
+```
+
+:::
+
+::: details Lack of Type Safety
+
+---
+
+**Problem:-** localStorage operations are inherently `untyped`, leading to runtime errors and `unpredictable` behavior when data types don't match expectations.
+
+```tsx
+// ❌ No type safety leads to runtime errors
+function UnsafeComponent() {
+ const [settings, setSettings] = useState()
+
+ useEffect(() => {
+ const saved = localStorage.getItem('settings')
+ setSettings(JSON.parse(saved)) // Could be anything!
+ }, [])
+
+ // Runtime error if settings isn't the expected shape
+ return {settings.theme.mode}
// ❌ Potential crash
+}
+```
+
+---
+
+**Solution:-** The hook provides full TypeScript support with generic type parameters that ensure type safety throughout the application.
+
+```tsx
+// ✅ Full type safety with TypeScript generics
+interface UserSettings {
+ theme: 'light' | 'dark'
+ language: 'en' | 'es' | 'fr'
+ notifications: boolean
+}
+
+function SafeComponent() {
+ const [settings, setSettings] = useLocalStorage({
+ key: 'user-settings',
+ defaultValue: { theme: 'light', language: 'en', notifications: true },
})
+ // TypeScript ensures settings has the correct shape
+ return {settings.theme}
// ✅ Type-safe access
+
+ // TypeScript prevents invalid updates
+ setSettings({ theme: 'blue' }) // ❌ TypeScript error: 'blue' not assignable
+}
+```
+
+:::
+
+## Parameters
+
+| Parameter | Type | Required | Default Value | Description |
+| ------------ | :----: | :------: | :-----------: | ----------------------------------------- |
+| key | string | ✅ | - | Unique key for localStorage item |
+| defaultValue | any | ❌ | undefined | Initial value when no stored value exists |
+
+## Return Value(s)
+
+Returns a tuple `[state, setState]` similar to `useState`:
+
+| Index | Type | Description |
+| ----- | ----------------------------------- | ---------------------------------------------------------------------------- |
+| 0 | State | Current state value from localStorage |
+| 1 | Dispatch\\> | Function to update state (supports both direct values and updater functions) |
+
+## Common Use Cases
+
+- Theme preferences (dark/light mode)
+- Form draft saving (auto-save functionality)
+- Shopping cart persistence
+- User settings and preferences
+- Feature flags for application
+
+## Usage Examples
+
+### Basic User Preferences
+
+```ts {4,5,9,14}
+import { useLocalStorage } from 'classic-react-hooks'
+
+function UserPreferences() {
+ const [theme, setTheme] = useLocalStorage({ key: 'theme', defaultValue: 'light' })
+ const [language, setLanguage] = useLocalStorage({ key: 'language', defaultValue: 'en' })
+
return (
+ setTheme(e.target.value)}>
+ Light
+ Dark
+
+
+ setLanguage(e.target.value)}>
+ English
+ Spanish
+ French
+
+
+ )
+}
+```
+
+### Complex Object State
+
+::: details
+
+```ts
+interface UserProfile {
+ name: string
+ email: string
+ preferences: {
+ notifications: boolean
+ newsletter: boolean
+ }
+}
+
+function ProfileForm() {
+ const [profile, setProfile] = useLocalStorage({
+ key: 'user-profile',
+ defaultValue: {
+ name: '',
+ email: '',
+ preferences: {
+ notifications: true,
+ newsletter: false,
+ },
+ },
+ })
+
+ const updateName = (name: string) => {
+ setProfile((prev) => ({
+ ...prev,
+ name,
+ }))
+ }
+
+ const toggleNotifications = () => {
+ setProfile((prev) => ({
+ ...prev,
+ preferences: {
+ ...prev.preferences,
+ notifications: !prev.preferences.notifications,
+ },
+ }))
+ }
+
+ return (
+
)
}
```
+
+:::
diff --git a/apps/doc/hooks/use-multi-intersection-observer.md b/apps/doc/hooks/use-multi-intersection-observer.md
new file mode 100644
index 0000000..570d64d
--- /dev/null
+++ b/apps/doc/hooks/use-multi-intersection-observer.md
@@ -0,0 +1,209 @@
+---
+outline: deep
+---
+
+# use-multi-intersection-observer
+
+A React hook that provides a convenient way to observe multiple elements simultaneously using the [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) API.
+
+::: info
+Built on top of [useIntersectionObserver](use-intersection-observer.html) hook for type-safety and consistent behaviors.
+:::
+
+## Features
+
+- **Multiple Observers:** Create multiple intersection observers with a single hook call
+- **Unified API:** Each observer follows the same pattern as `useIntersectionObserver`
+- **Shared configuration:** Apply same options to all of the observers while maintaining individual keys
+
+## Problem It Solves
+
+::: details Multiple Hook Instance Boilerplate
+**Problem:** Managing many intersection observers requires repetitive hook calls
+
+```ts
+// ❌ Without multi-observer hook - repetitive
+const hero = useIntersectionObserver({ key: 'hero', threshold: 0.5 })
+const about = useIntersectionObserver({ key: 'about', threshold: 0.5 })
+const services = useIntersectionObserver({ key: 'services', threshold: 0.5 })
+const contact = useIntersectionObserver({ key: 'contact', threshold: 0.5 })
+```
+
+**Solution:** Single hook call for multiple observers
+
+```ts
+// ✅ With multi-observer hook
+const sections = useMultiIntersectionObserver(['hero', 'about', 'services', 'contact'], { threshold: 0.5 })
+```
+
+:::
+
+::: details Type Safety at Scale
+**Problem:** Maintaining type safety with multiple dynamically named properties
+
+- Loses type inference while managing multiple observers manually
+- No IntelliSense for dynamically generated property names
+- Runtime errors due to typos in property access
+
+**Solution:** This hook provides full type safety and comprehensive IntelliSense for all generated observer properties
+
+```ts
+// ✅ Full type safety and IntelliSense
+const observers = useMultiIntersectionObserver(['hero', 'footer'] as const)
+// TypeScript knows: observers.hero.setHeroElementRef, observers.hero.isHeroElementIntersecting
+// TypeScript knows: observers.footer.setFooterElementRef, observers.footer.isFooterElementIntersecting
+```
+
+:::
+
+## Parameters
+
+| Parameter | Type | Required | Default Value | Description |
+| --------- | :------------------------------------------: | :------: | :-----------: | ------------------------------------------------- |
+| keys | readonly Key[] | ✅ | - | Array of unique keys for creating named observers |
+| options | [MultipleObserverOptions](#type-definitions) | ❌ | undefined | Shared configuration for all observers |
+
+### Options Parameter
+
+All options from [useIntersectionObserver](use-intersection-observer.html) except `key` (which is provided via the `keys` array):
+
+### Type Definitions
+
+::: details
+
+```ts
+export type MultipleObserverOptions = Omit
+
+// Return type is a record where each key maps to its observer result
+type MultipleIntersectionObserverResult = Record<
+ Key,
+ ReturnType>
+>
+```
+
+:::
+
+## Return Value(s)
+
+The hook returns a record object where each key from the input array maps to its corresponding intersection observer result:
+
+- **Without key:** `element`, `setElementRef`, `isElementIntersecting`
+- **With key:** `{key}Element`, `set{Key}ElementRef`, `is{Key}ElementIntersecting`
+
+```ts
+// Object contains all of the obervers
+{ // [!code ++]
+ [key]: {
+ [`${key}Element`]: HTMLElement | null,
+ [`set${Capitalize}ElementRef`]: (element: HTMLElement | null) => void,
+ [`is${Capitalize}ElementIntersecting`]: boolean
+ }
+} // [!code ++]
+```
+
+::: info
+**`{key}Element`:** Holds the element reference which is being observed, it's initially undefined.
+
+**`set{Capitalize}ElementRef`:** Setter function to store the element reference within `element`, which is going tobe observed.
+
+**`is{Capitalize}ElementIntersecting`:** Holds the boolean intersection status of the `element` weather it is intersecting the screen or not.
+:::
+
+## Common Use Cases
+
+- **Multi-section navigation:** Track visibility of multiple page sections for active navigation states
+- **Lazy loading galleries:** Load multiple images or content blocks as they come into view
+
+## Usage Examples
+
+### Basic Multiple Observers
+
+```tsx {4-9}
+import { useMultiIntersectionObserver } from 'classic-react-hooks'
+
+export default function MultipleObserversExample() {
+ const observers = useMultiIntersectionObserver(['header', 'main', 'footer'] as const, {
+ threshold: 0.3,
+ onIntersection: (entry) => {
+ console.log('Element intersection changed:', entry.target.id)
+ },
+ })
+
+ return (
+
+
+
+ Header {observers.header.isHeaderElementIntersecting ? '(Visible)' : '(Hidden)'}
+
+
+
+
+
+ Main Content {observers.main.isMainElementIntersecting ? '(Visible)' : '(Hidden)'}
+
+
+
+
+
+ Footer {observers.footer.isFooterElementIntersecting ? '(Visible)' : '(Hidden)'}
+
+
+
+ )
+}
+```
+
+::: danger Important
+Each key in the array creates a separate `useIntersectionObserver` instance. While this provides maximum flexibility, consider the performance impact when observing many elements simultaneously.
+:::
+
+### One-Time Trigger
+
+::: details Example
+
+```tsx {7-16}
+import { useState } from 'react'
+import { useMultiIntersectionObserver } from 'classic-react-hooks'
+
+export default function OneTimeExample() {
+ const [hasBeenSeen, setHasBeenSeen] = useState(false)
+
+ const { setElementRef, isElementIntersecting } = useMultiIntersectionObserver({
+ onlyTriggerOnce: true, // [!code ++]
+ threshold: 0.8,
+ onIntersection: (entry) => {
+ if (entry.isIntersecting) {
+ setHasBeenSeen(true)
+ console.log('Element seen for the first time!')
+ }
+ },
+ })
+
+ return (
+
+
+
+ {hasBeenSeen ? 'I was seen!' : 'Scroll down to see me'}
+
+
+
+ )
+}
+```
+
+:::
diff --git a/apps/doc/hooks/use-on-mount-effect.md b/apps/doc/hooks/use-on-mount-effect.md
index c96d4ea..924d3c5 100644
--- a/apps/doc/hooks/use-on-mount-effect.md
+++ b/apps/doc/hooks/use-on-mount-effect.md
@@ -4,16 +4,32 @@ outline: deep
# use-on-mount-effect
-- A hooks that fires the given callback only once after the mount.
-- It doesn't take any dependencies.
+A React hook that executes a callback function only once after the component mounts. This is a simplified wrapper around useEffect with an empty dependency array.
-### Parameters
+::: tip
+This hook is perfect for initialization logic that should run exactly once when a component first renders.
+:::
-| Parameter | Type | Required | Default Value | Description |
-| --------- | :------: | :------: | :-----------: | ------------------------------------- |
-| cb | Function | ✅ | - | Callback to fire after initial mount. |
+## Features
-### Usage
+- **One-time execution:** Runs callback only once after component mounts
+- **Mount-only focus:** Explicitly designed for mount-time operations
+- **Compatible API:** Wrapper around `useEffect` hook
+
+## Parameters
+
+| Parameter | Type | Required | Default Value | Description |
+| --------- | :------------------: | :------: | :-----------: | ------------------------------------------------------------------------------------------------------- |
+| cb | React.EffectCallback | ✅ | - | The callback function to execute once after component mounts. Can optionally return a cleanup function. |
+
+## Common Use Cases
+
+- **Setup Initialization:** Running one-time setup code
+- **Third-party libraries:** Initializing external libraries or plugins
+
+## Usage Examples
+
+### Basic Usage - Initialization Logic
```ts
import { useOnMountEffect } from 'classic-react-hooks'
@@ -26,3 +42,13 @@ export default function YourComponent() {
return
}
```
+
+## Comparison with useEffect
+
+| Scenario | useEffect(cb, []) | useOnMountEffect(cb) |
+| ------------------- | -------------------- | ------------------------- |
+| Intent clarity | ❌ Less obvious | ✅ Crystal clear |
+| Code brevity | ❌ More verbose | ✅ Cleaner |
+| Dependency mistakes | ⚠️ Easy to forget [] | ✅ No dependencies needed |
+| TypeScript support | ✅ Yes | ✅ Yes |
+| Cleanup support | ✅ Yes | ✅ Yes |
diff --git a/apps/doc/hooks/use-outside-click.md b/apps/doc/hooks/use-outside-click.md
index 919e75c..d848dc6 100644
--- a/apps/doc/hooks/use-outside-click.md
+++ b/apps/doc/hooks/use-outside-click.md
@@ -4,54 +4,106 @@ outline: deep
# use-outside-click
-- A hook that fires the given callback when clicked outside anywhere of the given html element.
+A React hook that detects outside click for specified element and triggers the given callback.
-### Parameters
+::: tip
+Perfect for implementing modals, dropdowns and other UI components that need to be closed when users click outside of them.
+:::
-| Parameter | Type | Required | Default Value | Description |
-| --------- | :-----------------------: | :------: | :-----------: | ----------------------------- |
-| target | [Target](#parametertype) | ✅ | - | Reference of the html element |
-| handler | [Handler](#parametertype) | ❌ | undefined | Callback for the event |
-| options | [Options](#parametertype) | ❌ | undefined | Extra params |
+## Features
-### Types
+- **Precise trigger:** Precise outside click detection
+- **Performance:** Optimized with capture phase events
+- **Underlying hook:** At its core, it uses [useEventListener](use-event-listener.html) hook
----
+## Parameters
-#### ParameterType
+| Parameter | Type | Required | Default Value | Description |
+| --------- | :----------------------------: | :------: | :-----------: | ------------------------------------------------ |
+| target | [EvTarget](#type-definitions) | ✅ | - | Function that returns the target element or null |
+| handler | [EvHandler](#type-definitions) | ❌ | undefined | Callback executed on outside click |
+| options | [EvOptions](#type-definitions) | ❌ | undefined | Event listener options and feature flags |
-```ts
-type Target = null | EventTarget | (() => EventTarget | null)
-type Options = { shouldInjectEvent?: boolean | any }
-type Handler = (event: Event) => void
+#### Standard AddEventListenerOptions
+
+| Property | Type | Default | Description |
+| -------- | ----------- | --------- | -------------------------------------------------------------------------------- |
+| capture | boolean | false | If `true`, the listener will be triggered during the capture phase |
+| once | boolean | false | If `true`, the listener will be automatically removed after being triggered once |
+| passive | boolean | false | If `true`, indicates that the function will never call `preventDefault()` |
+| signal | AbortSignal | undefined | An AbortSignal that can be used to remove the event listener |
+
+#### Custom Options
+
+| Property | Type | Default | Description |
+| ----------------- | -------------- | ------- | --------------------------------------------------------------------------------------------------- |
+| shouldInjectEvent | boolean \| any | true | Controls whether the event listener should be attached. When false, the event listener is not added |
+
+### Type Definitions
+
+::: details
+
+```tsx
+type EvTarget = () => EventTarget | null
+type EvHandler = (event: DocumentEventMap['click']) => void
+
+interface EvOptions extends AddEventListenerOptions {
+ // Standard AddEventListenerOptions:
+ capture?: boolean
+ once?: boolean
+ passive?: boolean
+ signal?: AbortSignal
+
+ // Custom option:
+ shouldInjectEvent?: boolean | any // Controls whether the event should be attached
+}
```
-### Usage
+:::
+
+## Return Value(s)
+
+This hook returns an object that includes a setter function, allowing you to observe and manage the target element through its ref attribute.
+
+| Property | Type | Description |
+| ------------- | ------------------------- | ------------------------------------------------------------------- |
+| setElementRef | [Function](#return-types) | A ref callback that observes the target element for event listening |
+
+## Common Use Cases
+
+- Modal dialogs - Close when clicking backdrop
+- Dropdown menus - Hide when clicking elsewhere
+- Context menus - Dismiss on outside click
+
+## Usage Examples
+
+::: info Note
+Refer to [use-event-listener](/hooks/use-event-listener.html#basic-click-handler) hook for more examples.
+:::
+
+### Modal Component
```ts
-import { useRef } from 'react'
+import { useState } from 'react'
import { useOutsideClick } from 'classic-react-hooks'
-export default function YourComponent() {
- const modalRef = useRef(null)
- useOutsideClick(
- modalRef,
- (e) => {
- console.log('clicked outside on modal. Target = ', e.target)
- },
- { shouldInjectEvent: true }
- )
+function Modal() {
+ const [isOpen, setIsOpen] = useState(false)
+
+ const { setElementRef } = useOutsideClick({
+ handler: () => setIsOpen(false),
+ })
+
+ if (!isOpen) {
+ return setIsOpen(true)}>Open Modal
+ }
return (
-
-
- This is modal
+
+
+
Modal Title
+
Click outside this modal to close it.
+
setIsOpen(false)}>Close
)
diff --git a/apps/doc/hooks/use-synced-effect.md b/apps/doc/hooks/use-synced-effect.md
index 9d2402c..80ef2a0 100644
--- a/apps/doc/hooks/use-synced-effect.md
+++ b/apps/doc/hooks/use-synced-effect.md
@@ -4,17 +4,33 @@ outline: deep
# use-synced-effect
-- A hooks that fires the given callback for given dependencies when they get change.
-- It works exacatly like `useEffect`. But callback doesn't get fired on initial mount.
+A React hook that executes a callback when dependencies change, similar to `useEffect`, but skips execution on the initial mount.
-### Parameters
+::: tip
+This is particularly useful when you want to respond to state changes without triggering side effects during the component's first render.
+:::
-| Parameter | Type | Required | Default Value | Description |
-| --------- | :------: | :------: | :-----------: | ----------------------------------------------- |
-| cb | Function | ✅ | - | Callback to fire when dependencies get changed. |
-| deps | Array | ❌ | [] | Dependencies. |
+## Features
-### Usage
+- **Skip initial mount:** Skipping the callback on initial mount
+- **Reactive:** Running the callback only when dependencies actually change
+- **React StrictMode:** Handling React StrictMode double execution correctly
+- **Flexible control:** Supporting cleanup functions just like useEffect
+
+## Parameters
+
+| Parameter | Type | Required | Default Value | Description |
+| --------- | :------------------: | :------: | :-----------: | --------------------------------------------------------------------------------------------------- |
+| cb | React.EffectCallback | ✅ | - | The callback function to execute when dependencies change. Can optionally return a cleanup function |
+| deps | React.DependencyList | ❌ | [] | An array of dependencies that the effect depends on. |
+
+## Common Use Cases
+
+- Use everywhere just like `useEffect`
+
+## Usage Examples
+
+### Basic Usage - Responding to State Changes
```ts
import { useState } from 'react'
@@ -34,3 +50,49 @@ export default function YourComponent() {
)
}
```
+
+### Same cleanup behaviour just like `useEffect`
+
+::: details Example
+
+```ts {21-23}
+import { useState } from 'react'
+import { useSyncedEffect } from 'classic-react-hooks'
+
+function SearchComponent() {
+ const [query, setQuery] = useState('')
+
+ useSyncedEffect(() => {
+ // Only search when query actually changes, not on initial empty string
+ if (query) {
+ const controller = new AbortController()
+
+ fetch(`/api/search?q=${query}`, {
+ signal: controller.signal,
+ })
+ .then((response) => response.json())
+ .then((data) => {
+ // Handle search results
+ })
+
+ // Cleanup function to cancel the request
+ return () => {
+ controller.abort()
+ }
+ }
+ }, [query])
+
+ return
setQuery(e.target.value)} placeholder='Search...' />
+}
+```
+
+:::
+
+## Comparison with useEffect
+
+| Scenario | useEffect | useSyncedEffect |
+| ------------------- | ---------------- | -------------------- |
+| Initial mount | ✅ Runs | ❌ Skips |
+| Dependency changes | ✅ Runs | ✅ Runs |
+| Cleanup support | ✅ Yes | ✅ Yes |
+| StrictMode handling | ⚠️ May run twice | ✅ Handles correctly |
diff --git a/apps/doc/hooks/use-synced-ref.md b/apps/doc/hooks/use-synced-ref.md
index 6dd2059..ef60a00 100644
--- a/apps/doc/hooks/use-synced-ref.md
+++ b/apps/doc/hooks/use-synced-ref.md
@@ -4,34 +4,175 @@ outline: deep
# use-synced-ref
-- A replacement for `useRef` hook, which automatically syncs-up with the given state.
-- No need to manually update the ref.
+A React hook that creates a ref that automatically stays in sync with the provided value, ensuring you always have access to the latest state in asynchronous operations.
-### Parameters
+## Features
-| Parameter | Type | Required | Default Value | Description |
-| --------- | :--: | :------: | :-----------: | --------------------------- |
-| value | any | ✅ | - | Value to be tracked in ref. |
+- **Always current:** Ref automatically updates to reflect the latest value
+- **Stale closure prevention:** Prevents accessing stale values in async operations
+- **Simple API:** Minimal interface with automatic synchronization
+- **Type safe:** Full TypeScript support with generic typing
-### Returns
+## Problem It Solves
-- It returns the ref of given state.
+::: details **Stale Closure Problem**
-### Usage
+---
+
+**Problem:-** In React, when you capture state values in closures (like in `setTimeout`, event handlers, or async operations), you might get stale values due to how JavaScript closures work.
+
+```tsx
+// ❌ Problematic approach - stale closure issue
+function Component() {
+ const [count, setCount] = useState(0)
+
+ const handleAsyncOperation = () => {
+ setTimeout(() => {
+ // This will always log the value of count when handleAsyncOperation was called
+ // Not the current value after 2 seconds
+ console.log('Stale count:', count) // Might be outdated!
+ }, 2000)
+ }
+
+ return (
+
+
Count: {count}
+
setCount((c) => c + 1)}>Increment
+
Log count after 2s
+
+ )
+}
+```
+
+---
+
+**Solution:-**
+
+- Provides a ref that always contains the current value
+- Eliminates stale closure issues in async operations
+- Ensures you can access the latest state regardless of when the closure was created
+
+```tsx
+// ✅ Clean approach with useSyncedRef
+function Component() {
+ const [count, setCount] = useState(0)
+ const countRef = useSyncedRef(count)
+
+ const handleAsyncOperation = () => {
+ setTimeout(() => {
+ // countRef.current always has the latest value
+ console.log('Current count:', countRef.current) // Always up-to-date!
+ }, 2000)
+ }
+
+ return (
+
+
Count: {count}
+
setCount((c) => c + 1)}>Increment
+
Log count after 2s
+
+ )
+}
+```
+
+:::
+
+::: details **Performance Benefits**
+
+- Lightweight solution with minimal overhead
+- No unnecessary re-renders or effect dependencies
+- Simple ref assignment on every render ensures synchronization
+
+:::
+
+## Parameters
+
+| Parameter | Type | Required | Default Value | Description |
+| --------- | :--: | :------: | :-----------: | ------------------------------------------- |
+| state | T | ✅ | - | The value to keep synchronized with the ref |
+
+## Return Value(s)
+
+This hook returns the ref version of the provided state, which auto syncs up
+
+| Return Value | Type | Description |
+| ------------ | ------------- | ------------------------------------------------------------------------------------- |
+| syncedRef | RefObject
| A mutable ref object whose `.current` property always contains the latest state value |
+
+## Common Use Cases
+
+- **Async operations:** Accessing latest state in `setTimeout`, `setInterval`, or API calls
+- **Event handlers:** Ensuring event callbacks have access to current state without stale closures
+- **WebSocket handlers:** Accessing current state in WebSocket message handlers
+
+## Usage Examples
+
+### Basic State Synchronization
```ts
import { useState } from 'react'
import { useSyncedRef } from 'classic-react-hooks'
-export default function YourComponent() {
- const [counter, setCounter] = useState(0)
+export default function Counter() {
+ const [count, setCount] = useState(0)
+ const countRef = useSyncedRef(count)
+
+ const handleAsyncOperation = () => {
+ setTimeout(() => {
+ // countRef.current always has the latest value
+ console.log('Current count:', countRef.current)
+ alert(`Count is now: ${countRef.current}`)
+ }, 2000)
+ }
+
+ return (
+
+
Count: {count}
+
setCount((c) => c + 1)}>Increment
+
Show count after 2 seconds
+
+ )
+}
+```
+
+### Event Handlers with Latest State
+
+::: details Example
+
+```ts {6,11}
+import { useState, useCallback } from 'react'
+import { useSyncedRef } from 'classic-react-hooks'
+
+export default function EventExample() {
+ const [messages, setMessages] = useState([])
+ const messagesRef = useSyncedRef(messages)
- const counterRef = useSyncedRef(counter)
+ const handleKeyPress = useCallback((event: KeyboardEvent) => {
+ if (event.key === 'Enter') {
+ // Always access the latest messages array
+ const currentMessages = messagesRef.current
+ console.log('Current messages count:', currentMessages.length)
+
+ setMessages((prev) => [...prev, `Message ${prev.length + 1}`])
+ }
+ }, []) // No need to include messages in dependencies
+
+ useEffect(() => {
+ document.addEventListener('keydown', handleKeyPress)
+ return () => document.removeEventListener('keydown', handleKeyPress)
+ }, [handleKeyPress])
return (
-
setCounter((c) => c + 1)}>increment
+
Press Enter to add messages
+
+ {messages.map((msg, index) => (
+ {msg}
+ ))}
+
)
}
```
+
+:::
diff --git a/apps/doc/hooks/use-throttled-fn.md b/apps/doc/hooks/use-throttled-fn.md
index acca427..8a01c26 100644
--- a/apps/doc/hooks/use-throttled-fn.md
+++ b/apps/doc/hooks/use-throttled-fn.md
@@ -4,38 +4,245 @@ outline: deep
# use-throttled-fn
-- A hook which returns a throttled function.
+A React hook that returns a throttled version of provided function, ensuring it executes at most once per specified time interval, regardless of how frequently it's called.
-### Parameters
+## Features
-| Parameter | Type | Required | Default Value | Description |
-| --------- | :------: | :------: | :-----------: | ----------------------------------------------------------- |
-| cb | Function | ✅ | - | A callback which is to be throttled. |
-| delay | number | ❌ | 300 | A delay in milliseconds after that the callback gets fired. |
+- **Rate limiting:** Ensures function executes at most once per specified interval
+- **Immediate Execution:** First call executes immediately, subsequent calls are throttled
+- **Performance Optimized:** Prevents excessive function calls during rapid user interactions
+- **Context preservation:** Maintains original function's `this` context and error behavior
+- **Error handling:** Preserves original function's error behavior
-### Returns
+::: tip
+The `throttled function` is purely ref based and does not change across re-renders.
+:::
-- It returns a function which is throttled version of passed callback.
+## Problem It Solves
-### Usage
+::: details **Boilerplate Reduction**
+
+---
+
+**Problem:-** Manually implementing throttling in React components becomes lengthy, little bit complex code with potential performance issues and inconsistent behavior.
+
+```tsx
+// ❌ Problematic approach which is redundant and verbose
+function ScrollTracker() {
+ const [scrollPosition, setScrollPosition] = useState(0)
+ const lastExecutionTimeRef = useRef(0)
+ const THROTTLE_DELAY = 100
+
+ const handleScroll = useCallback(() => {
+ const currentTime = Date.now()
+
+ if (currentTime - lastExecutionTimeRef.current >= THROTTLE_DELAY) {
+ setScrollPosition(window.scrollY)
+ lastExecutionTimeRef.current = currentTime
+
+ // Additional complex logic for tracking scroll performance
+ console.log('Scroll position updated:', window.scrollY)
+ }
+ }, [])
+
+ useEffect(() => {
+ const throttledScrollHandler = (event: Event) => {
+ handleScroll()
+ }
+
+ window.addEventListener('scroll', throttledScrollHandler, { passive: true })
+
+ return () => {
+ window.removeEventListener('scroll', throttledScrollHandler)
+ }
+ }, [handleScroll])
+
+ return Current scroll: {scrollPosition}px
+}
+```
+
+---
+
+**Solution:-**
+
+- Eliminates repetitive throttling logic
+- Automatic handling of:
+ - First call immediate execution
+ - Context preservation
+ - Error handling
+
+```tsx
+// ✅ Clean, declarative approach
+function ScrollTracker() {
+ const [scrollPosition, setScrollPosition] = useState(0)
+
+ const throttledScrollHandler = useThrottledFn({
+ callbackToThrottle: () => {
+ setScrollPosition(window.scrollY)
+ console.log('Scroll position updated:', window.scrollY)
+ },
+ delay: 100,
+ })
+
+ useEffect(() => {
+ window.addEventListener('scroll', throttledScrollHandler, { passive: true })
+ return () => window.removeEventListener('scroll', throttledScrollHandler)
+ }, [throttledScrollHandler])
+
+ return Current scroll: {scrollPosition}px
+}
+```
+
+:::
+
+::: details **Performance Benefits**
+
+- **Reduces execution frequency:** Limits function calls to specified intervals, preventing performance bottlenecks
+- **Memory efficient:** Minimal overhead with simple timestamp tracking
+
+:::
+
+## Throttling vs Debouncing
+
+| Aspect | Throttling | Debouncing |
+| -------------------- | ---------------------------------- | ------------------------------------------ |
+| **Execution timing** | Executes at regular intervals | Executes after inactivity period |
+| **First call** | Executes immediately | May delay first execution |
+| **Use case** | Continuous events (scroll, resize) | User input completion (search, validation) |
+| **Frequency** | Limited to X times per interval | Executes only after pause |
+
+## Parameters
+
+| Parameter | Type | Required | Default Value | Description |
+| ------------------ | :------------------------------: | :------: | :-----------: | ----------------------------------------------------------------- |
+| callbackToThrottle | [ThrottledFn](#type-definitions) | ✅ | - | The function to throttle |
+| delay | number | ❌ | 300ms | Minimum time interval between function executions in milliseconds |
+
+### Type Definitions
+
+::: details
```ts
+export type ThrottledFn any> = (...args: Parameters) => void
+```
+
+:::
+
+## Return Value(s)
+
+This hook returns the throttled version of provided callback.
+
+| Return Value | Type | Description |
+| ------------- | ---------------------------------- | ------------------------------------------------------------------------------------------ |
+| `throttledFn` | `(...args: Parameters) => void` | Throttled version of the original function that limits execution to the specified interval |
+
+## Common Use Cases
+
+- **API Rate Limiting:** Limiting search API calls while typing
+- **Mouse Movement Tracking:** Tracking mouse coordinate and update on screen
+- **Real-time data updates:** Managing WebSocket or polling frequency
+
+## Usage Examples
+
+### API Rate Limiting
+
+```tsx {9-25}
import { useState } from 'react'
import { useThrottledFn } from 'classic-react-hooks'
-export default function YourComponent() {
- const [throttledInput, setThrottledInput] = useState('')
- const updateInput = useThrottledFn((e) => {
- setThrottledInput(e.target.value)
- }, 300)
+export default function ApiExample() {
+ const [data, setData] = useState([])
+ const [requestCount, setRequestCount] = useState(0)
+ const [isLoading, setIsLoading] = useState(false)
+
+ const throttledFetch = useThrottledFn({
+ callbackToThrottle: async () => {
+ setIsLoading(true)
+ setRequestCount((prev) => prev + 1)
+
+ try {
+ const response = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=5')
+ const result = await response.json()
+ setData(result)
+ } catch (error) {
+ console.error('Fetch failed:', error)
+ } finally {
+ setIsLoading(false)
+ }
+ },
+ delay: 2000, // Max 1 request per 2 seconds
+ })
return (
-
-
+
+
+ {isLoading ? 'Loading...' : 'Fetch Data (max 1/2sec)'}
+
+
API calls made: {requestCount}
+
+ {data.map((item) => (
+
+ {item.title}
+
+ ))}
+
+
+ Click rapidly - API calls are throttled to 1 per 2 seconds
+
+
+ )
+}
+```
+
+### Mouse Movement Tracking
+
+::: details Example
+
+```tsx {8-17}
+import { useState, useEffect } from 'react'
+import { useThrottledFn } from 'classic-react-hooks'
+
+export default function MouseTracker() {
+ const [mousePos, setMousePos] = useState({ x: 0, y: 0 })
+ const [updateCount, setUpdateCount] = useState(0)
+
+ const throttledMouseMove = useThrottledFn({
+ callbackToThrottle: (event: MouseEvent) => {
+ setMousePos({
+ x: event.clientX,
+ y: event.clientY,
+ })
+ setUpdateCount((prev) => prev + 1)
+ },
+ delay: 50, // 20 updates per second max
+ })
+
+ useEffect(() => {
+ const handleMouseMove = (event: MouseEvent) => {
+ throttledMouseMove(event)
+ }
+
+ document.addEventListener('mousemove', handleMouseMove)
+ return () => document.removeEventListener('mousemove', handleMouseMove)
+ }, [throttledMouseMove])
+
+ return (
+
+
Mouse Position Tracker
+
+ Position: ({mousePos.x}, {mousePos.y})
+
+
Updates: {updateCount}
- value - {throttledInput}
+ Move your mouse around this area
)
}
```
+
+:::
diff --git a/apps/doc/hooks/use-timeout-effect.md b/apps/doc/hooks/use-timeout-effect.md
index 2e19336..df1902b 100644
--- a/apps/doc/hooks/use-timeout-effect.md
+++ b/apps/doc/hooks/use-timeout-effect.md
@@ -4,35 +4,48 @@ outline: deep
# use-timeout-effect
-- A hooks which fires the provided callback only once when the given delay is passed, just like the `setTimeout`.
+A React hook that fires a provided callback after a specified timeout, similar to `setTimeout`, but with additional control methods for clearing and restarting the timer.
-### Parameters
+## Features
-| Parameter | Type | Required | Default Value | Description |
-| --------- | :------: | :------: | :-----------: | --------------------------------------------------------- |
-| cb | Function | ✅ | - | Callback to fire after given amount of timeout is passed. |
-| timeout | number | ❌ | 100 | Timeout value after which the callback is fired. |
+- **Scheduled execution:** Executes a callback after a specified delay
+- **Flexible control:** Provides methods to clear or restart the timer
+- **Auto cleanup:** Automatically clears up timer on component unmount
-### Returns
+## Parameters
-- It returns an object.
-- `clearTimer` : () => void
-- `restartTimer` : () => void
+| Parameter | Type | Required | Default Value | Description |
+| --------- | :------: | :------: | :-----------: | ------------------------------------------------------ |
+| handler | Function | ✅ | - | The callback function to execute after the timeout |
+| timeout | number | ❌ | 100 | The delay in milliseconds before executing the handler |
-### Usage
+## Return value(s)
+
+This hooks returns an object having several utility functions for controlling the timeout-effect:
+
+| Property | Type | Description |
+| ------------ | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| clearTimer | () => void | Clears the current timeout timer, preventing the handler from executing if it hasn't already run. Similar to calling `clearTimeout()` on a standard timeout. |
+| restartTimer | (new_interval?: number) => void | Clears the current timer and starts a new one. Optionally accepts a `new_interval` parameter to use a different timeout duration. If no interval is provided, uses the original timeout value. |
+
+## Usage Examples
+
+### Basic use
```ts
import { useState } from 'react'
-import { useTimeoutEffect } from 'classic-react-hooks'
+import useTimeoutEffect from './useTimeoutEffect'
-export default function YourComponent() {
- const [show, setShow] = useState(false)
+export default function BasicExample() {
+ const [message, setMessage] = useState('')
- useTimeoutEffect(() => {
- console.log('use-timeout-callback')
- setShow(true)
- }, 2000)
+ useTimeoutEffect({
+ handler: () => {
+ setMessage('Timer executed!')
+ },
+ timeout: 2000,
+ })
- return
+ return
{message}
}
```
diff --git a/apps/doc/hooks/use-window-resize.md b/apps/doc/hooks/use-window-resize.md
index 522c6cd..bef1f1c 100644
--- a/apps/doc/hooks/use-window-resize.md
+++ b/apps/doc/hooks/use-window-resize.md
@@ -4,48 +4,129 @@ outline: deep
# use-window-resize
-- A hook which evaluates the passed callback on window resize event and returns the result of that callback.
+A React hook that evaluates provided callback function on window resize event and returns the result of it.
-### Parameters
+::: info
+At it's core, [useEventListener](use-event-listener.html) hook is used internally for listening to resize event.
+:::
-| Parameter | Type | Required | Default Value | Description |
-| --------- | :------------------------: | :------: | :-----------: | ------------------------------------------------------------------- |
-| cb | [Callback](#parametertype) | ✅ | - | A callback which gets fired whenever the window resize event occurs |
-| options | [Options](#parametertype) | ❌ | undefined | Options to pass as feature flag |
+## Features
-#### ParameterType
+- **Custom handler:** Execute custom logic on window resize
+- **Reactive:** Automatic re-evaluation and state updates
+- **Configurable:** Configurable default values and event injection
+- **Performance:** It uses [useLayoutEffect](https://react.dev/reference/react/useLayoutEffect) hook for resize event listening
+
+## Parameters
+
+| Parameter | Type | Required | Default Value | Description |
+| --------- | :--------------------------: | :------: | :-----------: | ------------------------------------------- |
+| handler | [Handler](#type-definitions) | ✅ | - | Callback function executed on window resize |
+| options | [Options](#type-definitions) | ❌ | undefined | Configuration options |
+| |
+
+### Options Parameter
+
+| Property | Type | Default | Description |
+| ----------------- | ----------- | --------- | ----------------------------------------------------------------------------------------------------------------------- |
+| defaultValue | Generic `T` | undefined | The initial value returned before the first resize event. If not provided, the `handler` is called immediately on mount |
+| shouldInjectEvent | boolean | true | Controls whether the resize event listener should be attached. When `false`, the listener is not added |
+
+### Type Definitions
+
+::: details
```ts
-type Callback = () => T
-type Options = { shouldInjectEvent?: boolean; defaultValue?: T }
+type Handler
= () => T
+type Options = { shouldInjectEvent?: boolean; defaultValue?: T }
```
-### Returns
+:::
-- It returns the value, which is the result of the passed callback.
+## Return value(s)
-### Usage
+Returns the evaluated result of the `handler` function call on resize event.
-```ts
+| Return Value | Type | Description |
+| --------------------------------- | ----------- | -------------------------- |
+| Result of `handler` function call | Generic `T` | Result to use in component |
+
+## Common Use Cases
+
+- Creating dynamic layouts
+- Toggling element visibility based on window dimension
+- Dynamically lazy loading components for mobile and desktop screens
+
+## Usage Examples
+
+### Basic Responsive Breakpoints
+
+```ts {4-10,15-17}
import { useWindowResize } from 'classic-react-hooks'
-export default function YourComponent() {
- const result = useWindowResize(() => {
- if (window.innerWidth < 500) {
- return 'md'
- }
- if (window.innerWidth > 500 && window.innerWidth < 800) {
- return 'lg'
- }
+function ResponsiveComponent() {
+ const breakpoint = useWindowResize(() => {
+ const width = window.innerWidth
+ if (width < 640) return 'sm'
+ if (width < 768) return 'md'
+ if (width < 1024) return 'lg'
return 'xl'
})
return (
- <>
- {result == 'md' && md }
- {result == 'lg' && lg }
- {result == 'xl' && xl }
- >
+
+
Current breakpoint: {breakpoint}
+ {breakpoint === 'sm' &&
}
+ {breakpoint === 'md' &&
}
+ {['lg', 'xl'].includes(breakpoint) &&
}
+
+ )
+}
+```
+
+### With Default Value
+
+:::details Example
+
+```ts
+import { useWindowResize } from 'classic-react-hooks'
+
+function ComponentWithDefault() {
+ const isMobile = useWindowResize(() => window.innerWidth < 768, {
+ defaultValue: false, // Assume desktop by default // [!code ++]
+ shouldInjectEvent: false,
+ })
+
+ return {/* Navigation content */}
+}
+```
+
+:::
+
+## Advanced Usage
+
+### Debounced Resize Handler
+
+::: details Example
+
+```ts {7-10}
+import { useMemo } from 'react'
+import { useWindowResize, useDebouncedFn } from 'classic-react-hooks'
+
+function ExpensiveCalculation() {
+ const expensiveHandler = useDebouncedFn(
+ () =>
+ debounce(() => {
+ // Expensive calculation here
+ return performComplexCalculation()
+ }),
+ 250
)
+
+ const result = useWindowResize(expensiveHandler)
+
+ return {result}
}
```
+
+:::
diff --git a/apps/doc/index.md b/apps/doc/index.md
index c10b436..b1189d9 100644
--- a/apps/doc/index.md
+++ b/apps/doc/index.md
@@ -3,11 +3,11 @@
layout: home
name: 'classic-react-hooks'
-tagline: An awesome collection of feature packed custom hooks
+tagline: Essential Custom Hooks for React Developers
hero:
name: 'classic-react-hooks'
- tagline: Collection of feature packed custom hooks
+ tagline: Lightweight · Minimal · Fast
actions:
- theme: brand
text: Get Started
@@ -15,14 +15,18 @@ hero:
features:
- icon: 🚀
- title: Awesome Collection of Hooks
- details: Feature packed custom hooks to make your feature building easy.
+ title: Essential React Hooks
+ details: Comprehensive collection of custom hooks
+
+ - icon: 🌲
+ title: Lightweight
+ details: Zero deps and tiny bundle
- icon:
- title: Type safe
- details: Built in Typescript.
+ title: Type-safe
+ details: Built with TypeScript
- icon: 🌏
title: Open-Source
- details: 100% open-source & Happy to recieve contributions.
+ details: 100% open-source
---
diff --git a/apps/doc/package.json b/apps/doc/package.json
index 1db545c..8e1d1f4 100644
--- a/apps/doc/package.json
+++ b/apps/doc/package.json
@@ -1,6 +1,6 @@
{
"name": "docs",
- "version": "0.0.0",
+ "version": "2.0.0",
"description": "Documentation for classic-react-hooks package",
"main": "index.js",
"scripts": {
@@ -10,13 +10,16 @@
},
"keywords": [
"classic-react-hooks",
- "hooks",
- "react hooks"
+ "React hooks",
+ "Custom react hooks",
+ "Essential react hooks",
+ "Functional hook",
+ "hooks"
],
"author": "Ashish-simpleCoder",
"license": "MIT",
- "dependencies": {},
"devDependencies": {
- "vitepress": "^1.0.1"
+ "vitepress": "^1.0.1",
+ "vitepress-plugin-group-icons": "^1.6.5"
}
}
diff --git a/apps/doc/pnpm-lock.yaml b/apps/doc/pnpm-lock.yaml
index db7504e..7c4257a 100644
--- a/apps/doc/pnpm-lock.yaml
+++ b/apps/doc/pnpm-lock.yaml
@@ -1,1205 +1,1729 @@
-lockfileVersion: '6.0'
+lockfileVersion: '9.0'
settings:
- autoInstallPeers: true
- excludeLinksFromLockfile: false
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
-devDependencies:
- vitepress:
- specifier: ^1.0.1
- version: 1.0.1(@algolia/client-search@4.23.2)(search-insights@2.13.0)
+importers:
+
+ .:
+ devDependencies:
+ vitepress:
+ specifier: ^1.0.1
+ version: 1.6.3(@algolia/client-search@5.25.0)(postcss@8.5.3)(search-insights@2.17.3)
+ vitepress-plugin-group-icons:
+ specifier: ^1.6.5
+ version: 1.6.5(vite@5.4.19)
packages:
- /@algolia/autocomplete-core@1.9.3(@algolia/client-search@4.23.2)(algoliasearch@4.23.2)(search-insights@2.13.0):
- resolution:
- { integrity: sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw== }
- dependencies:
- '@algolia/autocomplete-plugin-algolia-insights': 1.9.3(@algolia/client-search@4.23.2)(algoliasearch@4.23.2)(search-insights@2.13.0)
- '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.23.2)(algoliasearch@4.23.2)
- transitivePeerDependencies:
- - '@algolia/client-search'
- - algoliasearch
- - search-insights
- dev: true
-
- /@algolia/autocomplete-plugin-algolia-insights@1.9.3(@algolia/client-search@4.23.2)(algoliasearch@4.23.2)(search-insights@2.13.0):
- resolution:
- { integrity: sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg== }
- peerDependencies:
- search-insights: '>= 1 < 3'
- dependencies:
- '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.23.2)(algoliasearch@4.23.2)
- search-insights: 2.13.0
- transitivePeerDependencies:
- - '@algolia/client-search'
- - algoliasearch
- dev: true
-
- /@algolia/autocomplete-preset-algolia@1.9.3(@algolia/client-search@4.23.2)(algoliasearch@4.23.2):
- resolution:
- { integrity: sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA== }
- peerDependencies:
- '@algolia/client-search': '>= 4.9.1 < 6'
- algoliasearch: '>= 4.9.1 < 6'
- dependencies:
- '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.23.2)(algoliasearch@4.23.2)
- '@algolia/client-search': 4.23.2
- algoliasearch: 4.23.2
- dev: true
-
- /@algolia/autocomplete-shared@1.9.3(@algolia/client-search@4.23.2)(algoliasearch@4.23.2):
- resolution:
- { integrity: sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ== }
- peerDependencies:
- '@algolia/client-search': '>= 4.9.1 < 6'
- algoliasearch: '>= 4.9.1 < 6'
- dependencies:
- '@algolia/client-search': 4.23.2
- algoliasearch: 4.23.2
- dev: true
-
- /@algolia/cache-browser-local-storage@4.23.2:
- resolution:
- { integrity: sha512-PvRQdCmtiU22dw9ZcTJkrVKgNBVAxKgD0/cfiqyxhA5+PHzA2WDt6jOmZ9QASkeM2BpyzClJb/Wr1yt2/t78Kw== }
- dependencies:
- '@algolia/cache-common': 4.23.2
- dev: true
-
- /@algolia/cache-common@4.23.2:
- resolution:
- { integrity: sha512-OUK/6mqr6CQWxzl/QY0/mwhlGvS6fMtvEPyn/7AHUx96NjqDA4X4+Ju7aXFQKh+m3jW9VPB0B9xvEQgyAnRPNw== }
- dev: true
-
- /@algolia/cache-in-memory@4.23.2:
- resolution:
- { integrity: sha512-rfbi/SnhEa3MmlqQvgYz/9NNJ156NkU6xFxjbxBtLWnHbpj+qnlMoKd+amoiacHRITpajg6zYbLM9dnaD3Bczw== }
- dependencies:
- '@algolia/cache-common': 4.23.2
- dev: true
-
- /@algolia/client-account@4.23.2:
- resolution:
- { integrity: sha512-VbrOCLIN/5I7iIdskSoSw3uOUPF516k4SjDD4Qz3BFwa3of7D9A0lzBMAvQEJJEPHWdVraBJlGgdJq/ttmquJQ== }
- dependencies:
- '@algolia/client-common': 4.23.2
- '@algolia/client-search': 4.23.2
- '@algolia/transporter': 4.23.2
- dev: true
-
- /@algolia/client-analytics@4.23.2:
- resolution:
- { integrity: sha512-lLj7irsAztGhMoEx/SwKd1cwLY6Daf1Q5f2AOsZacpppSvuFvuBrmkzT7pap1OD/OePjLKxicJS8wNA0+zKtuw== }
- dependencies:
- '@algolia/client-common': 4.23.2
- '@algolia/client-search': 4.23.2
- '@algolia/requester-common': 4.23.2
- '@algolia/transporter': 4.23.2
- dev: true
-
- /@algolia/client-common@4.23.2:
- resolution:
- { integrity: sha512-Q2K1FRJBern8kIfZ0EqPvUr3V29ICxCm/q42zInV+VJRjldAD9oTsMGwqUQ26GFMdFYmqkEfCbY4VGAiQhh22g== }
- dependencies:
- '@algolia/requester-common': 4.23.2
- '@algolia/transporter': 4.23.2
- dev: true
-
- /@algolia/client-personalization@4.23.2:
- resolution:
- { integrity: sha512-vwPsgnCGhUcHhhQG5IM27z8q7dWrN9itjdvgA6uKf2e9r7vB+WXt4OocK0CeoYQt3OGEAExryzsB8DWqdMK5wg== }
- dependencies:
- '@algolia/client-common': 4.23.2
- '@algolia/requester-common': 4.23.2
- '@algolia/transporter': 4.23.2
- dev: true
-
- /@algolia/client-search@4.23.2:
- resolution:
- { integrity: sha512-CxSB29OVGSE7l/iyoHvamMonzq7Ev8lnk/OkzleODZ1iBcCs3JC/XgTIKzN/4RSTrJ9QybsnlrN/bYCGufo7qw== }
- dependencies:
- '@algolia/client-common': 4.23.2
- '@algolia/requester-common': 4.23.2
- '@algolia/transporter': 4.23.2
- dev: true
-
- /@algolia/logger-common@4.23.2:
- resolution:
- { integrity: sha512-jGM49Q7626cXZ7qRAWXn0jDlzvoA1FvN4rKTi1g0hxKsTTSReyYk0i1ADWjChDPl3Q+nSDhJuosM2bBUAay7xw== }
- dev: true
-
- /@algolia/logger-console@4.23.2:
- resolution:
- { integrity: sha512-oo+lnxxEmlhTBTFZ3fGz1O8PJ+G+8FiAoMY2Qo3Q4w23xocQev6KqDTA1JQAGPDxAewNA2VBwWOsVXeXFjrI/Q== }
- dependencies:
- '@algolia/logger-common': 4.23.2
- dev: true
-
- /@algolia/recommend@4.23.2:
- resolution:
- { integrity: sha512-Q75CjnzRCDzgIlgWfPnkLtrfF4t82JCirhalXkSSwe/c1GH5pWh4xUyDOR3KTMo+YxxX3zTlrL/FjHmUJEWEcg== }
- dependencies:
- '@algolia/cache-browser-local-storage': 4.23.2
- '@algolia/cache-common': 4.23.2
- '@algolia/cache-in-memory': 4.23.2
- '@algolia/client-common': 4.23.2
- '@algolia/client-search': 4.23.2
- '@algolia/logger-common': 4.23.2
- '@algolia/logger-console': 4.23.2
- '@algolia/requester-browser-xhr': 4.23.2
- '@algolia/requester-common': 4.23.2
- '@algolia/requester-node-http': 4.23.2
- '@algolia/transporter': 4.23.2
- dev: true
-
- /@algolia/requester-browser-xhr@4.23.2:
- resolution:
- { integrity: sha512-TO9wLlp8+rvW9LnIfyHsu8mNAMYrqNdQ0oLF6eTWFxXfxG3k8F/Bh7nFYGk2rFAYty4Fw4XUtrv/YjeNDtM5og== }
- dependencies:
- '@algolia/requester-common': 4.23.2
- dev: true
-
- /@algolia/requester-common@4.23.2:
- resolution:
- { integrity: sha512-3EfpBS0Hri0lGDB5H/BocLt7Vkop0bTTLVUBB844HH6tVycwShmsV6bDR7yXbQvFP1uNpgePRD3cdBCjeHmk6Q== }
- dev: true
-
- /@algolia/requester-node-http@4.23.2:
- resolution:
- { integrity: sha512-SVzgkZM/malo+2SB0NWDXpnT7nO5IZwuDTaaH6SjLeOHcya1o56LSWXk+3F3rNLz2GVH+I/rpYKiqmHhSOjerw== }
- dependencies:
- '@algolia/requester-common': 4.23.2
- dev: true
-
- /@algolia/transporter@4.23.2:
- resolution:
- { integrity: sha512-GY3aGKBy+8AK4vZh8sfkatDciDVKad5rTY2S10Aefyjh7e7UGBP4zigf42qVXwU8VOPwi7l/L7OACGMOFcjB0Q== }
- dependencies:
- '@algolia/cache-common': 4.23.2
- '@algolia/logger-common': 4.23.2
- '@algolia/requester-common': 4.23.2
- dev: true
-
- /@babel/helper-string-parser@7.24.1:
- resolution:
- { integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ== }
- engines: { node: '>=6.9.0' }
- dev: true
-
- /@babel/helper-validator-identifier@7.22.20:
- resolution:
- { integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== }
- engines: { node: '>=6.9.0' }
- dev: true
-
- /@babel/parser@7.24.1:
- resolution:
- { integrity: sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg== }
- engines: { node: '>=6.0.0' }
- hasBin: true
- dependencies:
- '@babel/types': 7.24.0
- dev: true
-
- /@babel/types@7.24.0:
- resolution:
- { integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w== }
- engines: { node: '>=6.9.0' }
- dependencies:
- '@babel/helper-string-parser': 7.24.1
- '@babel/helper-validator-identifier': 7.22.20
- to-fast-properties: 2.0.0
- dev: true
-
- /@docsearch/css@3.6.0:
- resolution:
- { integrity: sha512-+sbxb71sWre+PwDK7X2T8+bhS6clcVMLwBPznX45Qu6opJcgRjAp7gYSDzVFp187J+feSj5dNBN1mJoi6ckkUQ== }
- dev: true
-
- /@docsearch/js@3.6.0(@algolia/client-search@4.23.2)(search-insights@2.13.0):
- resolution:
- { integrity: sha512-QujhqINEElrkIfKwyyyTfbsfMAYCkylInLYMRqHy7PHc8xTBQCow73tlo/Kc7oIwBrCLf0P3YhjlOeV4v8hevQ== }
- dependencies:
- '@docsearch/react': 3.6.0(@algolia/client-search@4.23.2)(search-insights@2.13.0)
- preact: 10.20.1
- transitivePeerDependencies:
- - '@algolia/client-search'
- - '@types/react'
- - react
- - react-dom
- - search-insights
- dev: true
-
- /@docsearch/react@3.6.0(@algolia/client-search@4.23.2)(search-insights@2.13.0):
- resolution:
- { integrity: sha512-HUFut4ztcVNmqy9gp/wxNbC7pTOHhgVVkHVGCACTuLhUKUhKAF9KYHJtMiLUJxEqiFLQiuri1fWF8zqwM/cu1w== }
- peerDependencies:
- '@types/react': '>= 16.8.0 < 19.0.0'
- react: '>= 16.8.0 < 19.0.0'
- react-dom: '>= 16.8.0 < 19.0.0'
- search-insights: '>= 1 < 3'
- peerDependenciesMeta:
- '@types/react':
- optional: true
- react:
- optional: true
- react-dom:
- optional: true
- search-insights:
- optional: true
- dependencies:
- '@algolia/autocomplete-core': 1.9.3(@algolia/client-search@4.23.2)(algoliasearch@4.23.2)(search-insights@2.13.0)
- '@algolia/autocomplete-preset-algolia': 1.9.3(@algolia/client-search@4.23.2)(algoliasearch@4.23.2)
- '@docsearch/css': 3.6.0
- algoliasearch: 4.23.2
- search-insights: 2.13.0
- transitivePeerDependencies:
- - '@algolia/client-search'
- dev: true
-
- /@esbuild/aix-ppc64@0.20.2:
- resolution:
- { integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g== }
- engines: { node: '>=12' }
- cpu: [ppc64]
- os: [aix]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/android-arm64@0.20.2:
- resolution:
- { integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg== }
- engines: { node: '>=12' }
- cpu: [arm64]
- os: [android]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/android-arm@0.20.2:
- resolution:
- { integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w== }
- engines: { node: '>=12' }
- cpu: [arm]
- os: [android]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/android-x64@0.20.2:
- resolution:
- { integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg== }
- engines: { node: '>=12' }
- cpu: [x64]
- os: [android]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/darwin-arm64@0.20.2:
- resolution:
- { integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA== }
- engines: { node: '>=12' }
- cpu: [arm64]
- os: [darwin]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/darwin-x64@0.20.2:
- resolution:
- { integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA== }
- engines: { node: '>=12' }
- cpu: [x64]
- os: [darwin]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/freebsd-arm64@0.20.2:
- resolution:
- { integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw== }
- engines: { node: '>=12' }
- cpu: [arm64]
- os: [freebsd]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/freebsd-x64@0.20.2:
- resolution:
- { integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw== }
- engines: { node: '>=12' }
- cpu: [x64]
- os: [freebsd]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/linux-arm64@0.20.2:
- resolution:
- { integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A== }
- engines: { node: '>=12' }
- cpu: [arm64]
- os: [linux]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/linux-arm@0.20.2:
- resolution:
- { integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg== }
- engines: { node: '>=12' }
- cpu: [arm]
- os: [linux]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/linux-ia32@0.20.2:
- resolution:
- { integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig== }
- engines: { node: '>=12' }
- cpu: [ia32]
- os: [linux]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/linux-loong64@0.20.2:
- resolution:
- { integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ== }
- engines: { node: '>=12' }
- cpu: [loong64]
- os: [linux]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/linux-mips64el@0.20.2:
- resolution:
- { integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA== }
- engines: { node: '>=12' }
- cpu: [mips64el]
- os: [linux]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/linux-ppc64@0.20.2:
- resolution:
- { integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg== }
- engines: { node: '>=12' }
- cpu: [ppc64]
- os: [linux]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/linux-riscv64@0.20.2:
- resolution:
- { integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg== }
- engines: { node: '>=12' }
- cpu: [riscv64]
- os: [linux]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/linux-s390x@0.20.2:
- resolution:
- { integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ== }
- engines: { node: '>=12' }
- cpu: [s390x]
- os: [linux]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/linux-x64@0.20.2:
- resolution:
- { integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw== }
- engines: { node: '>=12' }
- cpu: [x64]
- os: [linux]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/netbsd-x64@0.20.2:
- resolution:
- { integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ== }
- engines: { node: '>=12' }
- cpu: [x64]
- os: [netbsd]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/openbsd-x64@0.20.2:
- resolution:
- { integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ== }
- engines: { node: '>=12' }
- cpu: [x64]
- os: [openbsd]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/sunos-x64@0.20.2:
- resolution:
- { integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w== }
- engines: { node: '>=12' }
- cpu: [x64]
- os: [sunos]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/win32-arm64@0.20.2:
- resolution:
- { integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ== }
- engines: { node: '>=12' }
- cpu: [arm64]
- os: [win32]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/win32-ia32@0.20.2:
- resolution:
- { integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ== }
- engines: { node: '>=12' }
- cpu: [ia32]
- os: [win32]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/win32-x64@0.20.2:
- resolution:
- { integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ== }
- engines: { node: '>=12' }
- cpu: [x64]
- os: [win32]
- requiresBuild: true
- dev: true
- optional: true
-
- /@jridgewell/sourcemap-codec@1.4.15:
- resolution:
- { integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== }
- dev: true
-
- /@rollup/rollup-android-arm-eabi@4.13.2:
- resolution:
- { integrity: sha512-3XFIDKWMFZrMnao1mJhnOT1h2g0169Os848NhhmGweEcfJ4rCi+3yMCOLG4zA61rbJdkcrM/DjVZm9Hg5p5w7g== }
- cpu: [arm]
- os: [android]
- requiresBuild: true
- dev: true
- optional: true
-
- /@rollup/rollup-android-arm64@4.13.2:
- resolution:
- { integrity: sha512-GdxxXbAuM7Y/YQM9/TwwP+L0omeE/lJAR1J+olu36c3LqqZEBdsIWeQ91KBe6nxwOnb06Xh7JS2U5ooWU5/LgQ== }
- cpu: [arm64]
- os: [android]
- requiresBuild: true
- dev: true
- optional: true
-
- /@rollup/rollup-darwin-arm64@4.13.2:
- resolution:
- { integrity: sha512-mCMlpzlBgOTdaFs83I4XRr8wNPveJiJX1RLfv4hggyIVhfB5mJfN4P8Z6yKh+oE4Luz+qq1P3kVdWrCKcMYrrA== }
- cpu: [arm64]
- os: [darwin]
- requiresBuild: true
- dev: true
- optional: true
-
- /@rollup/rollup-darwin-x64@4.13.2:
- resolution:
- { integrity: sha512-yUoEvnH0FBef/NbB1u6d3HNGyruAKnN74LrPAfDQL3O32e3k3OSfLrPgSJmgb3PJrBZWfPyt6m4ZhAFa2nZp2A== }
- cpu: [x64]
- os: [darwin]
- requiresBuild: true
- dev: true
- optional: true
-
- /@rollup/rollup-linux-arm-gnueabihf@4.13.2:
- resolution:
- { integrity: sha512-GYbLs5ErswU/Xs7aGXqzc3RrdEjKdmoCrgzhJWyFL0r5fL3qd1NPcDKDowDnmcoSiGJeU68/Vy+OMUluRxPiLQ== }
- cpu: [arm]
- os: [linux]
- requiresBuild: true
- dev: true
- optional: true
-
- /@rollup/rollup-linux-arm64-gnu@4.13.2:
- resolution:
- { integrity: sha512-L1+D8/wqGnKQIlh4Zre9i4R4b4noxzH5DDciyahX4oOz62CphY7WDWqJoQ66zNR4oScLNOqQJfNSIAe/6TPUmQ== }
- cpu: [arm64]
- os: [linux]
- requiresBuild: true
- dev: true
- optional: true
-
- /@rollup/rollup-linux-arm64-musl@4.13.2:
- resolution:
- { integrity: sha512-tK5eoKFkXdz6vjfkSTCupUzCo40xueTOiOO6PeEIadlNBkadH1wNOH8ILCPIl8by/Gmb5AGAeQOFeLev7iZDOA== }
- cpu: [arm64]
- os: [linux]
- requiresBuild: true
- dev: true
- optional: true
-
- /@rollup/rollup-linux-powerpc64le-gnu@4.13.2:
- resolution:
- { integrity: sha512-zvXvAUGGEYi6tYhcDmb9wlOckVbuD+7z3mzInCSTACJ4DQrdSLPNUeDIcAQW39M3q6PDquqLWu7pnO39uSMRzQ== }
- cpu: [ppc64le]
- os: [linux]
- requiresBuild: true
- dev: true
- optional: true
-
- /@rollup/rollup-linux-riscv64-gnu@4.13.2:
- resolution:
- { integrity: sha512-C3GSKvMtdudHCN5HdmAMSRYR2kkhgdOfye4w0xzyii7lebVr4riCgmM6lRiSCnJn2w1Xz7ZZzHKuLrjx5620kw== }
- cpu: [riscv64]
- os: [linux]
- requiresBuild: true
- dev: true
- optional: true
-
- /@rollup/rollup-linux-s390x-gnu@4.13.2:
- resolution:
- { integrity: sha512-l4U0KDFwzD36j7HdfJ5/TveEQ1fUTjFFQP5qIt9gBqBgu1G8/kCaq5Ok05kd5TG9F8Lltf3MoYsUMw3rNlJ0Yg== }
- cpu: [s390x]
- os: [linux]
- requiresBuild: true
- dev: true
- optional: true
-
- /@rollup/rollup-linux-x64-gnu@4.13.2:
- resolution:
- { integrity: sha512-xXMLUAMzrtsvh3cZ448vbXqlUa7ZL8z0MwHp63K2IIID2+DeP5iWIT6g1SN7hg1VxPzqx0xZdiDM9l4n9LRU1A== }
- cpu: [x64]
- os: [linux]
- requiresBuild: true
- dev: true
- optional: true
-
- /@rollup/rollup-linux-x64-musl@4.13.2:
- resolution:
- { integrity: sha512-M/JYAWickafUijWPai4ehrjzVPKRCyDb1SLuO+ZyPfoXgeCEAlgPkNXewFZx0zcnoIe3ay4UjXIMdXQXOZXWqA== }
- cpu: [x64]
- os: [linux]
- requiresBuild: true
- dev: true
- optional: true
-
- /@rollup/rollup-win32-arm64-msvc@4.13.2:
- resolution:
- { integrity: sha512-2YWwoVg9KRkIKaXSh0mz3NmfurpmYoBBTAXA9qt7VXk0Xy12PoOP40EFuau+ajgALbbhi4uTj3tSG3tVseCjuA== }
- cpu: [arm64]
- os: [win32]
- requiresBuild: true
- dev: true
- optional: true
-
- /@rollup/rollup-win32-ia32-msvc@4.13.2:
- resolution:
- { integrity: sha512-2FSsE9aQ6OWD20E498NYKEQLneShWes0NGMPQwxWOdws35qQXH+FplabOSP5zEe1pVjurSDOGEVCE2agFwSEsw== }
- cpu: [ia32]
- os: [win32]
- requiresBuild: true
- dev: true
- optional: true
-
- /@rollup/rollup-win32-x64-msvc@4.13.2:
- resolution:
- { integrity: sha512-7h7J2nokcdPePdKykd8wtc8QqqkqxIrUz7MHj6aNr8waBRU//NLDVnNjQnqQO6fqtjrtCdftpbTuOKAyrAQETQ== }
- cpu: [x64]
- os: [win32]
- requiresBuild: true
- dev: true
- optional: true
-
- /@shikijs/core@1.2.1:
- resolution:
- { integrity: sha512-KaIS0H4EQ3KI2d++TjYqRNgwp8E3M/68e9veR4QtInzA7kKFgcjeiJqb80fuXW+blDy5fmd11PN9g9soz/3ANQ== }
- dev: true
-
- /@shikijs/transformers@1.2.1:
- resolution:
- { integrity: sha512-H7cVtrdv6BW2kx83t2IQgP5ri1IA50mE3QnzgJ0AvOKCGtCEieXu0JIP3245cgjNLrL+LBwb8DtTXdky1iQL9Q== }
- dependencies:
- shiki: 1.2.1
- dev: true
-
- /@types/estree@1.0.5:
- resolution:
- { integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== }
- dev: true
-
- /@types/linkify-it@3.0.5:
- resolution:
- { integrity: sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw== }
- dev: true
-
- /@types/markdown-it@13.0.7:
- resolution:
- { integrity: sha512-U/CBi2YUUcTHBt5tjO2r5QV/x0Po6nsYwQU4Y04fBS6vfoImaiZ6f8bi3CjTCxBPQSO1LMyUqkByzi8AidyxfA== }
- dependencies:
- '@types/linkify-it': 3.0.5
- '@types/mdurl': 1.0.5
- dev: true
-
- /@types/mdurl@1.0.5:
- resolution:
- { integrity: sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA== }
- dev: true
-
- /@types/web-bluetooth@0.0.20:
- resolution:
- { integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow== }
- dev: true
-
- /@vitejs/plugin-vue@5.0.4(vite@5.2.7)(vue@3.4.21):
- resolution:
- { integrity: sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ== }
- engines: { node: ^18.0.0 || >=20.0.0 }
- peerDependencies:
- vite: ^5.0.0
- vue: ^3.2.25
- dependencies:
- vite: 5.2.7
- vue: 3.4.21
- dev: true
-
- /@vue/compiler-core@3.4.21:
- resolution:
- { integrity: sha512-MjXawxZf2SbZszLPYxaFCjxfibYrzr3eYbKxwpLR9EQN+oaziSu3qKVbwBERj1IFIB8OLUewxB5m/BFzi613og== }
- dependencies:
- '@babel/parser': 7.24.1
- '@vue/shared': 3.4.21
- entities: 4.5.0
- estree-walker: 2.0.2
- source-map-js: 1.2.0
- dev: true
-
- /@vue/compiler-dom@3.4.21:
- resolution:
- { integrity: sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA== }
- dependencies:
- '@vue/compiler-core': 3.4.21
- '@vue/shared': 3.4.21
- dev: true
-
- /@vue/compiler-sfc@3.4.21:
- resolution:
- { integrity: sha512-me7epoTxYlY+2CUM7hy9PCDdpMPfIwrOvAXud2Upk10g4YLv9UBW7kL798TvMeDhPthkZ0CONNrK2GoeI1ODiQ== }
- dependencies:
- '@babel/parser': 7.24.1
- '@vue/compiler-core': 3.4.21
- '@vue/compiler-dom': 3.4.21
- '@vue/compiler-ssr': 3.4.21
- '@vue/shared': 3.4.21
- estree-walker: 2.0.2
- magic-string: 0.30.8
- postcss: 8.4.38
- source-map-js: 1.2.0
- dev: true
-
- /@vue/compiler-ssr@3.4.21:
- resolution:
- { integrity: sha512-M5+9nI2lPpAsgXOGQobnIueVqc9sisBFexh5yMIMRAPYLa7+5wEJs8iqOZc1WAa9WQbx9GR2twgznU8LTIiZ4Q== }
- dependencies:
- '@vue/compiler-dom': 3.4.21
- '@vue/shared': 3.4.21
- dev: true
-
- /@vue/devtools-api@7.0.25(vue@3.4.21):
- resolution:
- { integrity: sha512-fL6DlRp4MSXCLYcqYvKU7QhQZWE3Hfu7X8pC25BS74coJi7uJeSWs4tmrITcwFihNmC9S5GPiffkMdckkeWjzg== }
- dependencies:
- '@vue/devtools-kit': 7.0.25(vue@3.4.21)
- transitivePeerDependencies:
- - vue
- dev: true
-
- /@vue/devtools-kit@7.0.25(vue@3.4.21):
- resolution:
- { integrity: sha512-wbLkSnOTsKHPb1mB9koFHUoSAF8Dp6Ii/ocR2+DeXFY4oKqIjCeJb/4Lihk4rgqEhCy1WwxLfTgNDo83VvDYkQ== }
- peerDependencies:
- vue: ^3.0.0
- dependencies:
- '@vue/devtools-shared': 7.0.25
- hookable: 5.5.3
- mitt: 3.0.1
- perfect-debounce: 1.0.0
- speakingurl: 14.0.1
- vue: 3.4.21
- dev: true
-
- /@vue/devtools-shared@7.0.25:
- resolution:
- { integrity: sha512-5+XYhcHSXuJSguYnNwL6/e6VTmXwCfryWQOkffh9ZU2zMByybqqqBrMWqvBkqTmMFCjPdzulo66xXbVbwLaElQ== }
- dependencies:
- rfdc: 1.3.1
- dev: true
-
- /@vue/reactivity@3.4.21:
- resolution:
- { integrity: sha512-UhenImdc0L0/4ahGCyEzc/pZNwVgcglGy9HVzJ1Bq2Mm9qXOpP8RyNTjookw/gOCUlXSEtuZ2fUg5nrHcoqJcw== }
- dependencies:
- '@vue/shared': 3.4.21
- dev: true
-
- /@vue/runtime-core@3.4.21:
- resolution:
- { integrity: sha512-pQthsuYzE1XcGZznTKn73G0s14eCJcjaLvp3/DKeYWoFacD9glJoqlNBxt3W2c5S40t6CCcpPf+jG01N3ULyrA== }
- dependencies:
- '@vue/reactivity': 3.4.21
- '@vue/shared': 3.4.21
- dev: true
-
- /@vue/runtime-dom@3.4.21:
- resolution:
- { integrity: sha512-gvf+C9cFpevsQxbkRBS1NpU8CqxKw0ebqMvLwcGQrNpx6gqRDodqKqA+A2VZZpQ9RpK2f9yfg8VbW/EpdFUOJw== }
- dependencies:
- '@vue/runtime-core': 3.4.21
- '@vue/shared': 3.4.21
- csstype: 3.1.3
- dev: true
-
- /@vue/server-renderer@3.4.21(vue@3.4.21):
- resolution:
- { integrity: sha512-aV1gXyKSN6Rz+6kZ6kr5+Ll14YzmIbeuWe7ryJl5muJ4uwSwY/aStXTixx76TwkZFJLm1aAlA/HSWEJ4EyiMkg== }
- peerDependencies:
- vue: 3.4.21
- dependencies:
- '@vue/compiler-ssr': 3.4.21
- '@vue/shared': 3.4.21
- vue: 3.4.21
- dev: true
-
- /@vue/shared@3.4.21:
- resolution:
- { integrity: sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g== }
- dev: true
-
- /@vueuse/core@10.9.0(vue@3.4.21):
- resolution:
- { integrity: sha512-/1vjTol8SXnx6xewDEKfS0Ra//ncg4Hb0DaZiwKf7drgfMsKFExQ+FnnENcN6efPen+1kIzhLQoGSy0eDUVOMg== }
- dependencies:
- '@types/web-bluetooth': 0.0.20
- '@vueuse/metadata': 10.9.0
- '@vueuse/shared': 10.9.0(vue@3.4.21)
- vue-demi: 0.14.7(vue@3.4.21)
- transitivePeerDependencies:
- - '@vue/composition-api'
- - vue
- dev: true
-
- /@vueuse/integrations@10.9.0(focus-trap@7.5.4)(vue@3.4.21):
- resolution:
- { integrity: sha512-acK+A01AYdWSvL4BZmCoJAcyHJ6EqhmkQEXbQLwev1MY7NBnS+hcEMx/BzVoR9zKI+UqEPMD9u6PsyAuiTRT4Q== }
- peerDependencies:
- async-validator: '*'
- axios: '*'
- change-case: '*'
- drauu: '*'
- focus-trap: '*'
- fuse.js: '*'
- idb-keyval: '*'
- jwt-decode: '*'
- nprogress: '*'
- qrcode: '*'
- sortablejs: '*'
- universal-cookie: '*'
- peerDependenciesMeta:
- async-validator:
- optional: true
- axios:
- optional: true
- change-case:
- optional: true
- drauu:
- optional: true
- focus-trap:
- optional: true
- fuse.js:
- optional: true
- idb-keyval:
- optional: true
- jwt-decode:
- optional: true
- nprogress:
- optional: true
- qrcode:
- optional: true
- sortablejs:
- optional: true
- universal-cookie:
- optional: true
- dependencies:
- '@vueuse/core': 10.9.0(vue@3.4.21)
- '@vueuse/shared': 10.9.0(vue@3.4.21)
- focus-trap: 7.5.4
- vue-demi: 0.14.7(vue@3.4.21)
- transitivePeerDependencies:
- - '@vue/composition-api'
- - vue
- dev: true
-
- /@vueuse/metadata@10.9.0:
- resolution:
- { integrity: sha512-iddNbg3yZM0X7qFY2sAotomgdHK7YJ6sKUvQqbvwnf7TmaVPxS4EJydcNsVejNdS8iWCtDk+fYXr7E32nyTnGA== }
- dev: true
-
- /@vueuse/shared@10.9.0(vue@3.4.21):
- resolution:
- { integrity: sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw== }
- dependencies:
- vue-demi: 0.14.7(vue@3.4.21)
- transitivePeerDependencies:
- - '@vue/composition-api'
- - vue
- dev: true
-
- /algoliasearch@4.23.2:
- resolution:
- { integrity: sha512-8aCl055IsokLuPU8BzLjwzXjb7ty9TPcUFFOk0pYOwsE5DMVhE3kwCMFtsCFKcnoPZK7oObm+H5mbnSO/9ioxQ== }
- dependencies:
- '@algolia/cache-browser-local-storage': 4.23.2
- '@algolia/cache-common': 4.23.2
- '@algolia/cache-in-memory': 4.23.2
- '@algolia/client-account': 4.23.2
- '@algolia/client-analytics': 4.23.2
- '@algolia/client-common': 4.23.2
- '@algolia/client-personalization': 4.23.2
- '@algolia/client-search': 4.23.2
- '@algolia/logger-common': 4.23.2
- '@algolia/logger-console': 4.23.2
- '@algolia/recommend': 4.23.2
- '@algolia/requester-browser-xhr': 4.23.2
- '@algolia/requester-common': 4.23.2
- '@algolia/requester-node-http': 4.23.2
- '@algolia/transporter': 4.23.2
- dev: true
-
- /csstype@3.1.3:
- resolution:
- { integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== }
- dev: true
-
- /entities@4.5.0:
- resolution:
- { integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== }
- engines: { node: '>=0.12' }
- dev: true
-
- /esbuild@0.20.2:
- resolution:
- { integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g== }
- engines: { node: '>=12' }
- hasBin: true
- requiresBuild: true
- optionalDependencies:
- '@esbuild/aix-ppc64': 0.20.2
- '@esbuild/android-arm': 0.20.2
- '@esbuild/android-arm64': 0.20.2
- '@esbuild/android-x64': 0.20.2
- '@esbuild/darwin-arm64': 0.20.2
- '@esbuild/darwin-x64': 0.20.2
- '@esbuild/freebsd-arm64': 0.20.2
- '@esbuild/freebsd-x64': 0.20.2
- '@esbuild/linux-arm': 0.20.2
- '@esbuild/linux-arm64': 0.20.2
- '@esbuild/linux-ia32': 0.20.2
- '@esbuild/linux-loong64': 0.20.2
- '@esbuild/linux-mips64el': 0.20.2
- '@esbuild/linux-ppc64': 0.20.2
- '@esbuild/linux-riscv64': 0.20.2
- '@esbuild/linux-s390x': 0.20.2
- '@esbuild/linux-x64': 0.20.2
- '@esbuild/netbsd-x64': 0.20.2
- '@esbuild/openbsd-x64': 0.20.2
- '@esbuild/sunos-x64': 0.20.2
- '@esbuild/win32-arm64': 0.20.2
- '@esbuild/win32-ia32': 0.20.2
- '@esbuild/win32-x64': 0.20.2
- dev: true
-
- /estree-walker@2.0.2:
- resolution:
- { integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== }
- dev: true
-
- /focus-trap@7.5.4:
- resolution:
- { integrity: sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w== }
- dependencies:
- tabbable: 6.2.0
- dev: true
-
- /fsevents@2.3.3:
- resolution:
- { integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== }
- engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 }
- os: [darwin]
- requiresBuild: true
- dev: true
- optional: true
-
- /hookable@5.5.3:
- resolution:
- { integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ== }
- dev: true
-
- /magic-string@0.30.8:
- resolution:
- { integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ== }
- engines: { node: '>=12' }
- dependencies:
- '@jridgewell/sourcemap-codec': 1.4.15
- dev: true
-
- /mark.js@8.11.1:
- resolution:
- { integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ== }
- dev: true
-
- /minisearch@6.3.0:
- resolution:
- { integrity: sha512-ihFnidEeU8iXzcVHy74dhkxh/dn8Dc08ERl0xwoMMGqp4+LvRSCgicb+zGqWthVokQKvCSxITlh3P08OzdTYCQ== }
- dev: true
-
- /mitt@3.0.1:
- resolution:
- { integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw== }
- dev: true
-
- /nanoid@3.3.7:
- resolution:
- { integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== }
- engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 }
- hasBin: true
- dev: true
-
- /perfect-debounce@1.0.0:
- resolution:
- { integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA== }
- dev: true
-
- /picocolors@1.0.0:
- resolution:
- { integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== }
- dev: true
-
- /postcss@8.4.38:
- resolution:
- { integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== }
- engines: { node: ^10 || ^12 || >=14 }
- dependencies:
- nanoid: 3.3.7
- picocolors: 1.0.0
- source-map-js: 1.2.0
- dev: true
-
- /preact@10.20.1:
- resolution:
- { integrity: sha512-JIFjgFg9B2qnOoGiYMVBtrcFxHqn+dNXbq76bVmcaHYJFYR4lW67AOcXgAYQQTDYXDOg/kTZrKPNCdRgJ2UJmw== }
- dev: true
-
- /rfdc@1.3.1:
- resolution:
- { integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg== }
- dev: true
-
- /rollup@4.13.2:
- resolution:
- { integrity: sha512-MIlLgsdMprDBXC+4hsPgzWUasLO9CE4zOkj/u6j+Z6j5A4zRY+CtiXAdJyPtgCsc42g658Aeh1DlrdVEJhsL2g== }
- engines: { node: '>=18.0.0', npm: '>=8.0.0' }
- hasBin: true
- dependencies:
- '@types/estree': 1.0.5
- optionalDependencies:
- '@rollup/rollup-android-arm-eabi': 4.13.2
- '@rollup/rollup-android-arm64': 4.13.2
- '@rollup/rollup-darwin-arm64': 4.13.2
- '@rollup/rollup-darwin-x64': 4.13.2
- '@rollup/rollup-linux-arm-gnueabihf': 4.13.2
- '@rollup/rollup-linux-arm64-gnu': 4.13.2
- '@rollup/rollup-linux-arm64-musl': 4.13.2
- '@rollup/rollup-linux-powerpc64le-gnu': 4.13.2
- '@rollup/rollup-linux-riscv64-gnu': 4.13.2
- '@rollup/rollup-linux-s390x-gnu': 4.13.2
- '@rollup/rollup-linux-x64-gnu': 4.13.2
- '@rollup/rollup-linux-x64-musl': 4.13.2
- '@rollup/rollup-win32-arm64-msvc': 4.13.2
- '@rollup/rollup-win32-ia32-msvc': 4.13.2
- '@rollup/rollup-win32-x64-msvc': 4.13.2
- fsevents: 2.3.3
- dev: true
-
- /search-insights@2.13.0:
- resolution:
- { integrity: sha512-Orrsjf9trHHxFRuo9/rzm0KIWmgzE8RMlZMzuhZOJ01Rnz3D0YBAe+V6473t6/H6c7irs6Lt48brULAiRWb3Vw== }
- dev: true
-
- /shiki@1.2.1:
- resolution:
- { integrity: sha512-u+XW6o0vCkUNlneZb914dLO+AayEIwK5tI62WeS//R5HIXBFiYaj/Hc5xcq27Yh83Grr4JbNtUBV8W6zyK4hWg== }
- dependencies:
- '@shikijs/core': 1.2.1
- dev: true
-
- /source-map-js@1.2.0:
- resolution:
- { integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== }
- engines: { node: '>=0.10.0' }
- dev: true
-
- /speakingurl@14.0.1:
- resolution:
- { integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ== }
- engines: { node: '>=0.10.0' }
- dev: true
-
- /tabbable@6.2.0:
- resolution:
- { integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew== }
- dev: true
-
- /to-fast-properties@2.0.0:
- resolution:
- { integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== }
- engines: { node: '>=4' }
- dev: true
-
- /vite@5.2.7:
- resolution:
- { integrity: sha512-k14PWOKLI6pMaSzAuGtT+Cf0YmIx12z9YGon39onaJNy8DLBfBJrzg9FQEmkAM5lpHBZs9wksWAsyF/HkpEwJA== }
- engines: { node: ^18.0.0 || >=20.0.0 }
- hasBin: true
- peerDependencies:
- '@types/node': ^18.0.0 || >=20.0.0
- less: '*'
- lightningcss: ^1.21.0
- sass: '*'
- stylus: '*'
- sugarss: '*'
- terser: ^5.4.0
- peerDependenciesMeta:
- '@types/node':
- optional: true
- less:
- optional: true
- lightningcss:
- optional: true
- sass:
- optional: true
- stylus:
- optional: true
- sugarss:
- optional: true
- terser:
- optional: true
- dependencies:
- esbuild: 0.20.2
- postcss: 8.4.38
- rollup: 4.13.2
- optionalDependencies:
- fsevents: 2.3.3
- dev: true
-
- /vitepress@1.0.1(@algolia/client-search@4.23.2)(search-insights@2.13.0):
- resolution:
- { integrity: sha512-eNr5pOBppYUUjEhv8S0S2t9Tv95LQ6mMeHj6ivaGwfHxpov70Vduuwl/QQMDRznKDSaP0WKV7a82Pb4JVOaqEw== }
- hasBin: true
- peerDependencies:
- markdown-it-mathjax3: ^4
- postcss: ^8
- peerDependenciesMeta:
- markdown-it-mathjax3:
- optional: true
- postcss:
- optional: true
- dependencies:
- '@docsearch/css': 3.6.0
- '@docsearch/js': 3.6.0(@algolia/client-search@4.23.2)(search-insights@2.13.0)
- '@shikijs/core': 1.2.1
- '@shikijs/transformers': 1.2.1
- '@types/markdown-it': 13.0.7
- '@vitejs/plugin-vue': 5.0.4(vite@5.2.7)(vue@3.4.21)
- '@vue/devtools-api': 7.0.25(vue@3.4.21)
- '@vueuse/core': 10.9.0(vue@3.4.21)
- '@vueuse/integrations': 10.9.0(focus-trap@7.5.4)(vue@3.4.21)
- focus-trap: 7.5.4
- mark.js: 8.11.1
- minisearch: 6.3.0
- shiki: 1.2.1
- vite: 5.2.7
- vue: 3.4.21
- transitivePeerDependencies:
- - '@algolia/client-search'
- - '@types/node'
- - '@types/react'
- - '@vue/composition-api'
- - async-validator
- - axios
- - change-case
- - drauu
- - fuse.js
- - idb-keyval
- - jwt-decode
- - less
- - lightningcss
- - nprogress
- - qrcode
- - react
- - react-dom
- - sass
- - search-insights
- - sortablejs
- - stylus
- - sugarss
- - terser
- - typescript
- - universal-cookie
- dev: true
-
- /vue-demi@0.14.7(vue@3.4.21):
- resolution:
- { integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA== }
- engines: { node: '>=12' }
- hasBin: true
- requiresBuild: true
- peerDependencies:
- '@vue/composition-api': ^1.0.0-rc.1
- vue: ^3.0.0-0 || ^2.6.0
- peerDependenciesMeta:
- '@vue/composition-api':
- optional: true
- dependencies:
- vue: 3.4.21
- dev: true
-
- /vue@3.4.21:
- resolution:
- { integrity: sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA== }
- peerDependencies:
- typescript: '*'
- peerDependenciesMeta:
- typescript:
- optional: true
- dependencies:
- '@vue/compiler-dom': 3.4.21
- '@vue/compiler-sfc': 3.4.21
- '@vue/runtime-dom': 3.4.21
- '@vue/server-renderer': 3.4.21(vue@3.4.21)
- '@vue/shared': 3.4.21
- dev: true
+
+ '@algolia/autocomplete-core@1.17.7':
+ resolution: {integrity: sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==}
+
+ '@algolia/autocomplete-plugin-algolia-insights@1.17.7':
+ resolution: {integrity: sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==}
+ peerDependencies:
+ search-insights: '>= 1 < 3'
+
+ '@algolia/autocomplete-preset-algolia@1.17.7':
+ resolution: {integrity: sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==}
+ peerDependencies:
+ '@algolia/client-search': '>= 4.9.1 < 6'
+ algoliasearch: '>= 4.9.1 < 6'
+
+ '@algolia/autocomplete-shared@1.17.7':
+ resolution: {integrity: sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==}
+ peerDependencies:
+ '@algolia/client-search': '>= 4.9.1 < 6'
+ algoliasearch: '>= 4.9.1 < 6'
+
+ '@algolia/client-abtesting@5.25.0':
+ resolution: {integrity: sha512-1pfQulNUYNf1Tk/svbfjfkLBS36zsuph6m+B6gDkPEivFmso/XnRgwDvjAx80WNtiHnmeNjIXdF7Gos8+OLHqQ==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/client-analytics@5.25.0':
+ resolution: {integrity: sha512-AFbG6VDJX/o2vDd9hqncj1B6B4Tulk61mY0pzTtzKClyTDlNP0xaUiEKhl6E7KO9I/x0FJF5tDCm0Hn6v5x18A==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/client-common@5.25.0':
+ resolution: {integrity: sha512-il1zS/+Rc6la6RaCdSZ2YbJnkQC6W1wiBO8+SH+DE6CPMWBU6iDVzH0sCKSAtMWl9WBxoN6MhNjGBnCv9Yy2bA==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/client-insights@5.25.0':
+ resolution: {integrity: sha512-blbjrUH1siZNfyCGeq0iLQu00w3a4fBXm0WRIM0V8alcAPo7rWjLbMJMrfBtzL9X5ic6wgxVpDADXduGtdrnkw==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/client-personalization@5.25.0':
+ resolution: {integrity: sha512-aywoEuu1NxChBcHZ1pWaat0Plw7A8jDMwjgRJ00Mcl7wGlwuPt5dJ/LTNcg3McsEUbs2MBNmw0ignXBw9Tbgow==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/client-query-suggestions@5.25.0':
+ resolution: {integrity: sha512-a/W2z6XWKjKjIW1QQQV8PTTj1TXtaKx79uR3NGBdBdGvVdt24KzGAaN7sCr5oP8DW4D3cJt44wp2OY/fZcPAVA==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/client-search@5.25.0':
+ resolution: {integrity: sha512-9rUYcMIBOrCtYiLX49djyzxqdK9Dya/6Z/8sebPn94BekT+KLOpaZCuc6s0Fpfq7nx5J6YY5LIVFQrtioK9u0g==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/ingestion@1.25.0':
+ resolution: {integrity: sha512-jJeH/Hk+k17Vkokf02lkfYE4A+EJX+UgnMhTLR/Mb+d1ya5WhE+po8p5a/Nxb6lo9OLCRl6w3Hmk1TX1e9gVbQ==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/monitoring@1.25.0':
+ resolution: {integrity: sha512-Ls3i1AehJ0C6xaHe7kK9vPmzImOn5zBg7Kzj8tRYIcmCWVyuuFwCIsbuIIz/qzUf1FPSWmw0TZrGeTumk2fqXg==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/recommend@5.25.0':
+ resolution: {integrity: sha512-79sMdHpiRLXVxSjgw7Pt4R1aNUHxFLHiaTDnN2MQjHwJ1+o3wSseb55T9VXU4kqy3m7TUme3pyRhLk5ip/S4Mw==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/requester-browser-xhr@5.25.0':
+ resolution: {integrity: sha512-JLaF23p1SOPBmfEqozUAgKHQrGl3z/Z5RHbggBu6s07QqXXcazEsub5VLonCxGVqTv6a61AAPr8J1G5HgGGjEw==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/requester-fetch@5.25.0':
+ resolution: {integrity: sha512-rtzXwqzFi1edkOF6sXxq+HhmRKDy7tz84u0o5t1fXwz0cwx+cjpmxu/6OQKTdOJFS92JUYHsG51Iunie7xbqfQ==}
+ engines: {node: '>= 14.0.0'}
+
+ '@algolia/requester-node-http@5.25.0':
+ resolution: {integrity: sha512-ZO0UKvDyEFvyeJQX0gmZDQEvhLZ2X10K+ps6hViMo1HgE2V8em00SwNsQ+7E/52a+YiBkVWX61pJJJE44juDMQ==}
+ engines: {node: '>= 14.0.0'}
+
+ '@antfu/install-pkg@1.1.0':
+ resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==}
+
+ '@antfu/utils@9.3.0':
+ resolution: {integrity: sha512-9hFT4RauhcUzqOE4f1+frMKLZrgNog5b06I7VmZQV1BkvwvqrbC8EBZf3L1eEL2AKb6rNKjER0sEvJiSP1FXEA==}
+
+ '@babel/helper-string-parser@7.27.1':
+ resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-identifier@7.27.1':
+ resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/parser@7.27.2':
+ resolution: {integrity: sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
+ '@babel/types@7.27.1':
+ resolution: {integrity: sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==}
+ engines: {node: '>=6.9.0'}
+
+ '@docsearch/css@3.8.2':
+ resolution: {integrity: sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ==}
+
+ '@docsearch/js@3.8.2':
+ resolution: {integrity: sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ==}
+
+ '@docsearch/react@3.8.2':
+ resolution: {integrity: sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg==}
+ peerDependencies:
+ '@types/react': '>= 16.8.0 < 19.0.0'
+ react: '>= 16.8.0 < 19.0.0'
+ react-dom: '>= 16.8.0 < 19.0.0'
+ search-insights: '>= 1 < 3'
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ react:
+ optional: true
+ react-dom:
+ optional: true
+ search-insights:
+ optional: true
+
+ '@esbuild/aix-ppc64@0.21.5':
+ resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@esbuild/android-arm64@0.21.5':
+ resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm@0.21.5':
+ resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-x64@0.21.5':
+ resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/darwin-arm64@0.21.5':
+ resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.21.5':
+ resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/freebsd-arm64@0.21.5':
+ resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.21.5':
+ resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/linux-arm64@0.21.5':
+ resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.21.5':
+ resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.21.5':
+ resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.21.5':
+ resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.21.5':
+ resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.21.5':
+ resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.21.5':
+ resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.21.5':
+ resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.21.5':
+ resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/netbsd-x64@0.21.5':
+ resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/openbsd-x64@0.21.5':
+ resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/sunos-x64@0.21.5':
+ resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/win32-arm64@0.21.5':
+ resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.21.5':
+ resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.21.5':
+ resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+
+ '@iconify-json/logos@1.2.10':
+ resolution: {integrity: sha512-qxaXKJ6fu8jzTMPQdHtNxlfx6tBQ0jXRbHZIYy5Ilh8Lx9US9FsAdzZWUR8MXV8PnWTKGDFO4ZZee9VwerCyMA==}
+
+ '@iconify-json/simple-icons@1.2.34':
+ resolution: {integrity: sha512-1FRWEA94hSl5zmBogRh6lQL36l7bVTfrl0n5+QJ+WmXmw70RccPT5phqeiSynwo3IhUWKoW2LiajyUMeweXW8g==}
+
+ '@iconify-json/vscode-icons@1.2.33':
+ resolution: {integrity: sha512-2lKDybGxXXeLeeqeNT2YVDYXs5va0YMHf06w3GemS22j/0CCTpKwKDK7REaibsCq3bRV8qX0RJDM4AbREE7L+w==}
+
+ '@iconify/types@2.0.0':
+ resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
+
+ '@iconify/utils@3.0.2':
+ resolution: {integrity: sha512-EfJS0rLfVuRuJRn4psJHtK2A9TqVnkxPpHY6lYHiB9+8eSuudsxbwMiavocG45ujOo6FJ+CIRlRnlOGinzkaGQ==}
+
+ '@jridgewell/sourcemap-codec@1.5.0':
+ resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
+
+ '@rollup/rollup-android-arm-eabi@4.40.2':
+ resolution: {integrity: sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg==}
+ cpu: [arm]
+ os: [android]
+
+ '@rollup/rollup-android-arm64@4.40.2':
+ resolution: {integrity: sha512-13unNoZ8NzUmnndhPTkWPWbX3vtHodYmy+I9kuLxN+F+l+x3LdVF7UCu8TWVMt1POHLh6oDHhnOA04n8oJZhBw==}
+ cpu: [arm64]
+ os: [android]
+
+ '@rollup/rollup-darwin-arm64@4.40.2':
+ resolution: {integrity: sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rollup/rollup-darwin-x64@4.40.2':
+ resolution: {integrity: sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rollup/rollup-freebsd-arm64@4.40.2':
+ resolution: {integrity: sha512-8t6aL4MD+rXSHHZUR1z19+9OFJ2rl1wGKvckN47XFRVO+QL/dUSpKA2SLRo4vMg7ELA8pzGpC+W9OEd1Z/ZqoQ==}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@rollup/rollup-freebsd-x64@4.40.2':
+ resolution: {integrity: sha512-C+AyHBzfpsOEYRFjztcYUFsH4S7UsE9cDtHCtma5BK8+ydOZYgMmWg1d/4KBytQspJCld8ZIujFMAdKG1xyr4Q==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.40.2':
+ resolution: {integrity: sha512-de6TFZYIvJwRNjmW3+gaXiZ2DaWL5D5yGmSYzkdzjBDS3W+B9JQ48oZEsmMvemqjtAFzE16DIBLqd6IQQRuG9Q==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm-musleabihf@4.40.2':
+ resolution: {integrity: sha512-urjaEZubdIkacKc930hUDOfQPysezKla/O9qV+O89enqsqUmQm8Xj8O/vh0gHg4LYfv7Y7UsE3QjzLQzDYN1qg==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-gnu@4.40.2':
+ resolution: {integrity: sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-musl@4.40.2':
+ resolution: {integrity: sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-loongarch64-gnu@4.40.2':
+ resolution: {integrity: sha512-Ybc/1qUampKuRF4tQXc7G7QY9YRyeVSykfK36Y5Qc5dmrIxwFhrOzqaVTNoZygqZ1ZieSWTibfFhQ5qK8jpWxw==}
+ cpu: [loong64]
+ os: [linux]
+
+ '@rollup/rollup-linux-powerpc64le-gnu@4.40.2':
+ resolution: {integrity: sha512-3FCIrnrt03CCsZqSYAOW/k9n625pjpuMzVfeI+ZBUSDT3MVIFDSPfSUgIl9FqUftxcUXInvFah79hE1c9abD+Q==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-gnu@4.40.2':
+ resolution: {integrity: sha512-QNU7BFHEvHMp2ESSY3SozIkBPaPBDTsfVNGx3Xhv+TdvWXFGOSH2NJvhD1zKAT6AyuuErJgbdvaJhYVhVqrWTg==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-musl@4.40.2':
+ resolution: {integrity: sha512-5W6vNYkhgfh7URiXTO1E9a0cy4fSgfE4+Hl5agb/U1sa0kjOLMLC1wObxwKxecE17j0URxuTrYZZME4/VH57Hg==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-s390x-gnu@4.40.2':
+ resolution: {integrity: sha512-B7LKIz+0+p348JoAL4X/YxGx9zOx3sR+o6Hj15Y3aaApNfAshK8+mWZEf759DXfRLeL2vg5LYJBB7DdcleYCoQ==}
+ cpu: [s390x]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-gnu@4.40.2':
+ resolution: {integrity: sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-musl@4.40.2':
+ resolution: {integrity: sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-win32-arm64-msvc@4.40.2':
+ resolution: {integrity: sha512-Bjv/HG8RRWLNkXwQQemdsWw4Mg+IJ29LK+bJPW2SCzPKOUaMmPEppQlu/Fqk1d7+DX3V7JbFdbkh/NMmurT6Pg==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rollup/rollup-win32-ia32-msvc@4.40.2':
+ resolution: {integrity: sha512-dt1llVSGEsGKvzeIO76HToiYPNPYPkmjhMHhP00T9S4rDern8P2ZWvWAQUEJ+R1UdMWJ/42i/QqJ2WV765GZcA==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-msvc@4.40.2':
+ resolution: {integrity: sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA==}
+ cpu: [x64]
+ os: [win32]
+
+ '@shikijs/core@2.5.0':
+ resolution: {integrity: sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg==}
+
+ '@shikijs/engine-javascript@2.5.0':
+ resolution: {integrity: sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w==}
+
+ '@shikijs/engine-oniguruma@2.5.0':
+ resolution: {integrity: sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw==}
+
+ '@shikijs/langs@2.5.0':
+ resolution: {integrity: sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w==}
+
+ '@shikijs/themes@2.5.0':
+ resolution: {integrity: sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw==}
+
+ '@shikijs/transformers@2.5.0':
+ resolution: {integrity: sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg==}
+
+ '@shikijs/types@2.5.0':
+ resolution: {integrity: sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw==}
+
+ '@shikijs/vscode-textmate@10.0.2':
+ resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}
+
+ '@types/estree@1.0.7':
+ resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==}
+
+ '@types/hast@3.0.4':
+ resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
+
+ '@types/linkify-it@5.0.0':
+ resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==}
+
+ '@types/markdown-it@14.1.2':
+ resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==}
+
+ '@types/mdast@4.0.4':
+ resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
+
+ '@types/mdurl@2.0.0':
+ resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==}
+
+ '@types/unist@3.0.3':
+ resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
+
+ '@types/web-bluetooth@0.0.21':
+ resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==}
+
+ '@ungap/structured-clone@1.3.0':
+ resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
+
+ '@vitejs/plugin-vue@5.2.4':
+ resolution: {integrity: sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ peerDependencies:
+ vite: ^5.0.0 || ^6.0.0
+ vue: ^3.2.25
+
+ '@vue/compiler-core@3.5.14':
+ resolution: {integrity: sha512-k7qMHMbKvoCXIxPhquKQVw3Twid3Kg4s7+oYURxLGRd56LiuHJVrvFKI4fm2AM3c8apqODPfVJGoh8nePbXMRA==}
+
+ '@vue/compiler-dom@3.5.14':
+ resolution: {integrity: sha512-1aOCSqxGOea5I80U2hQJvXYpPm/aXo95xL/m/mMhgyPUsKe9jhjwWpziNAw7tYRnbz1I61rd9Mld4W9KmmRoug==}
+
+ '@vue/compiler-sfc@3.5.14':
+ resolution: {integrity: sha512-9T6m/9mMr81Lj58JpzsiSIjBgv2LiVoWjIVa7kuXHICUi8LiDSIotMpPRXYJsXKqyARrzjT24NAwttrMnMaCXA==}
+
+ '@vue/compiler-ssr@3.5.14':
+ resolution: {integrity: sha512-Y0G7PcBxr1yllnHuS/NxNCSPWnRGH4Ogrp0tsLA5QemDZuJLs99YjAKQ7KqkHE0vCg4QTKlQzXLKCMF7WPSl7Q==}
+
+ '@vue/devtools-api@7.7.6':
+ resolution: {integrity: sha512-b2Xx0KvXZObePpXPYHvBRRJLDQn5nhKjXh7vUhMEtWxz1AYNFOVIsh5+HLP8xDGL7sy+Q7hXeUxPHB/KgbtsPw==}
+
+ '@vue/devtools-kit@7.7.6':
+ resolution: {integrity: sha512-geu7ds7tem2Y7Wz+WgbnbZ6T5eadOvozHZ23Atk/8tksHMFOFylKi1xgGlQlVn0wlkEf4hu+vd5ctj1G4kFtwA==}
+
+ '@vue/devtools-shared@7.7.6':
+ resolution: {integrity: sha512-yFEgJZ/WblEsojQQceuyK6FzpFDx4kqrz2ohInxNj5/DnhoX023upTv4OD6lNPLAA5LLkbwPVb10o/7b+Y4FVA==}
+
+ '@vue/reactivity@3.5.14':
+ resolution: {integrity: sha512-7cK1Hp343Fu/SUCCO52vCabjvsYu7ZkOqyYu7bXV9P2yyfjUMUXHZafEbq244sP7gf+EZEz+77QixBTuEqkQQw==}
+
+ '@vue/runtime-core@3.5.14':
+ resolution: {integrity: sha512-w9JWEANwHXNgieAhxPpEpJa+0V5G0hz3NmjAZwlOebtfKyp2hKxKF0+qSh0Xs6/PhfGihuSdqMprMVcQU/E6ag==}
+
+ '@vue/runtime-dom@3.5.14':
+ resolution: {integrity: sha512-lCfR++IakeI35TVR80QgOelsUIdcKjd65rWAMfdSlCYnaEY5t3hYwru7vvcWaqmrK+LpI7ZDDYiGU5V3xjMacw==}
+
+ '@vue/server-renderer@3.5.14':
+ resolution: {integrity: sha512-Rf/ISLqokIvcySIYnv3tNWq40PLpNLDLSJwwVWzG6MNtyIhfbcrAxo5ZL9nARJhqjZyWWa40oRb2IDuejeuv6w==}
+ peerDependencies:
+ vue: 3.5.14
+
+ '@vue/shared@3.5.14':
+ resolution: {integrity: sha512-oXTwNxVfc9EtP1zzXAlSlgARLXNC84frFYkS0HHz0h3E4WZSP9sywqjqzGCP9Y34M8ipNmd380pVgmMuwELDyQ==}
+
+ '@vueuse/core@12.8.2':
+ resolution: {integrity: sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==}
+
+ '@vueuse/integrations@12.8.2':
+ resolution: {integrity: sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g==}
+ peerDependencies:
+ async-validator: ^4
+ axios: ^1
+ change-case: ^5
+ drauu: ^0.4
+ focus-trap: ^7
+ fuse.js: ^7
+ idb-keyval: ^6
+ jwt-decode: ^4
+ nprogress: ^0.2
+ qrcode: ^1.5
+ sortablejs: ^1
+ universal-cookie: ^7
+ peerDependenciesMeta:
+ async-validator:
+ optional: true
+ axios:
+ optional: true
+ change-case:
+ optional: true
+ drauu:
+ optional: true
+ focus-trap:
+ optional: true
+ fuse.js:
+ optional: true
+ idb-keyval:
+ optional: true
+ jwt-decode:
+ optional: true
+ nprogress:
+ optional: true
+ qrcode:
+ optional: true
+ sortablejs:
+ optional: true
+ universal-cookie:
+ optional: true
+
+ '@vueuse/metadata@12.8.2':
+ resolution: {integrity: sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==}
+
+ '@vueuse/shared@12.8.2':
+ resolution: {integrity: sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==}
+
+ acorn@8.15.0:
+ resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+
+ algoliasearch@5.25.0:
+ resolution: {integrity: sha512-n73BVorL4HIwKlfJKb4SEzAYkR3Buwfwbh+MYxg2mloFph2fFGV58E90QTzdbfzWrLn4HE5Czx/WTjI8fcHaMg==}
+ engines: {node: '>= 14.0.0'}
+
+ birpc@2.3.0:
+ resolution: {integrity: sha512-ijbtkn/F3Pvzb6jHypHRyve2QApOCZDR25D/VnkY2G/lBNcXCTsnsCxgY4k4PkVB7zfwzYbY3O9Lcqe3xufS5g==}
+
+ ccount@2.0.1:
+ resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
+
+ character-entities-html4@2.1.0:
+ resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
+
+ character-entities-legacy@3.0.0:
+ resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}
+
+ comma-separated-tokens@2.0.3:
+ resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
+
+ confbox@0.1.8:
+ resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==}
+
+ confbox@0.2.2:
+ resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==}
+
+ copy-anything@3.0.5:
+ resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==}
+ engines: {node: '>=12.13'}
+
+ csstype@3.1.3:
+ resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
+
+ debug@4.4.3:
+ resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ dequal@2.0.3:
+ resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
+ engines: {node: '>=6'}
+
+ devlop@1.1.0:
+ resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
+
+ emoji-regex-xs@1.0.0:
+ resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==}
+
+ entities@4.5.0:
+ resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
+ engines: {node: '>=0.12'}
+
+ esbuild@0.21.5:
+ resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
+ engines: {node: '>=12'}
+ hasBin: true
+
+ estree-walker@2.0.2:
+ resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
+
+ exsolve@1.0.7:
+ resolution: {integrity: sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==}
+
+ focus-trap@7.6.4:
+ resolution: {integrity: sha512-xx560wGBk7seZ6y933idtjJQc1l+ck+pI3sKvhKozdBV1dRZoKhkW5xoCaFv9tQiX5RH1xfSxjuNu6g+lmN/gw==}
+
+ fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+
+ globals@15.15.0:
+ resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==}
+ engines: {node: '>=18'}
+
+ hast-util-to-html@9.0.5:
+ resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==}
+
+ hast-util-whitespace@3.0.0:
+ resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
+
+ hookable@5.5.3:
+ resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
+
+ html-void-elements@3.0.0:
+ resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
+
+ is-what@4.1.16:
+ resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==}
+ engines: {node: '>=12.13'}
+
+ kolorist@1.8.0:
+ resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==}
+
+ local-pkg@1.1.2:
+ resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==}
+ engines: {node: '>=14'}
+
+ magic-string@0.30.17:
+ resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
+
+ mark.js@8.11.1:
+ resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==}
+
+ mdast-util-to-hast@13.2.0:
+ resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==}
+
+ micromark-util-character@2.1.1:
+ resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==}
+
+ micromark-util-encode@2.0.1:
+ resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==}
+
+ micromark-util-sanitize-uri@2.0.1:
+ resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==}
+
+ micromark-util-symbol@2.0.1:
+ resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==}
+
+ micromark-util-types@2.0.2:
+ resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==}
+
+ minisearch@7.1.2:
+ resolution: {integrity: sha512-R1Pd9eF+MD5JYDDSPAp/q1ougKglm14uEkPMvQ/05RGmx6G9wvmLTrTI/Q5iPNJLYqNdsDQ7qTGIcNWR+FrHmA==}
+
+ mitt@3.0.1:
+ resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
+
+ mlly@1.8.0:
+ resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==}
+
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+ nanoid@3.3.11:
+ resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ oniguruma-to-es@3.1.1:
+ resolution: {integrity: sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ==}
+
+ package-manager-detector@1.5.0:
+ resolution: {integrity: sha512-uBj69dVlYe/+wxj8JOpr97XfsxH/eumMt6HqjNTmJDf/6NO9s+0uxeOneIz3AsPt2m6y9PqzDzd3ATcU17MNfw==}
+
+ pathe@2.0.3:
+ resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
+
+ perfect-debounce@1.0.0:
+ resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==}
+
+ picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+ pkg-types@1.3.1:
+ resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==}
+
+ pkg-types@2.3.0:
+ resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==}
+
+ postcss@8.5.3:
+ resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==}
+ engines: {node: ^10 || ^12 || >=14}
+
+ preact@10.26.6:
+ resolution: {integrity: sha512-5SRRBinwpwkaD+OqlBDeITlRgvd8I8QlxHJw9AxSdMNV6O+LodN9nUyYGpSF7sadHjs6RzeFShMexC6DbtWr9g==}
+
+ property-information@7.1.0:
+ resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==}
+
+ quansync@0.2.11:
+ resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==}
+
+ regex-recursion@6.0.2:
+ resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==}
+
+ regex-utilities@2.3.0:
+ resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==}
+
+ regex@6.0.1:
+ resolution: {integrity: sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==}
+
+ rfdc@1.4.1:
+ resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
+
+ rollup@4.40.2:
+ resolution: {integrity: sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+
+ search-insights@2.17.3:
+ resolution: {integrity: sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==}
+
+ shiki@2.5.0:
+ resolution: {integrity: sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ==}
+
+ source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+
+ space-separated-tokens@2.0.2:
+ resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
+
+ speakingurl@14.0.1:
+ resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==}
+ engines: {node: '>=0.10.0'}
+
+ stringify-entities@4.0.4:
+ resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
+
+ superjson@2.2.2:
+ resolution: {integrity: sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==}
+ engines: {node: '>=16'}
+
+ tabbable@6.2.0:
+ resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==}
+
+ tinyexec@1.0.2:
+ resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==}
+ engines: {node: '>=18'}
+
+ trim-lines@3.0.1:
+ resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
+
+ ufo@1.6.1:
+ resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==}
+
+ unist-util-is@6.0.0:
+ resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==}
+
+ unist-util-position@5.0.0:
+ resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
+
+ unist-util-stringify-position@4.0.0:
+ resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
+
+ unist-util-visit-parents@6.0.1:
+ resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==}
+
+ unist-util-visit@5.0.0:
+ resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
+
+ vfile-message@4.0.2:
+ resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==}
+
+ vfile@6.0.3:
+ resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
+
+ vite@5.4.19:
+ resolution: {integrity: sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || >=20.0.0
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ sass-embedded: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.4.0
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+
+ vitepress-plugin-group-icons@1.6.5:
+ resolution: {integrity: sha512-+pg4+GKDq2fLqKb1Sat5p1p4SuIZ5tEPxu8HjpwoeecZ/VaXKy6Bdf0wyjedjaTAyZQzXbvyavJegqAcQ+B0VA==}
+ peerDependencies:
+ vite: '>=3'
+ peerDependenciesMeta:
+ vite:
+ optional: true
+
+ vitepress@1.6.3:
+ resolution: {integrity: sha512-fCkfdOk8yRZT8GD9BFqusW3+GggWYZ/rYncOfmgcDtP3ualNHCAg+Robxp2/6xfH1WwPHtGpPwv7mbA3qomtBw==}
+ hasBin: true
+ peerDependencies:
+ markdown-it-mathjax3: ^4
+ postcss: ^8
+ peerDependenciesMeta:
+ markdown-it-mathjax3:
+ optional: true
+ postcss:
+ optional: true
+
+ vue@3.5.14:
+ resolution: {integrity: sha512-LbOm50/vZFG6Mhy6KscQYXZMQ0LMCC/y40HDJPPvGFQ+i/lUH+PJHR6C3assgOQiXdl6tAfsXHbXYVBZZu65ew==}
+ peerDependencies:
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ zwitch@2.0.4:
+ resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
+
+snapshots:
+
+ '@algolia/autocomplete-core@1.17.7(@algolia/client-search@5.25.0)(algoliasearch@5.25.0)(search-insights@2.17.3)':
+ dependencies:
+ '@algolia/autocomplete-plugin-algolia-insights': 1.17.7(@algolia/client-search@5.25.0)(algoliasearch@5.25.0)(search-insights@2.17.3)
+ '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.25.0)(algoliasearch@5.25.0)
+ transitivePeerDependencies:
+ - '@algolia/client-search'
+ - algoliasearch
+ - search-insights
+
+ '@algolia/autocomplete-plugin-algolia-insights@1.17.7(@algolia/client-search@5.25.0)(algoliasearch@5.25.0)(search-insights@2.17.3)':
+ dependencies:
+ '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.25.0)(algoliasearch@5.25.0)
+ search-insights: 2.17.3
+ transitivePeerDependencies:
+ - '@algolia/client-search'
+ - algoliasearch
+
+ '@algolia/autocomplete-preset-algolia@1.17.7(@algolia/client-search@5.25.0)(algoliasearch@5.25.0)':
+ dependencies:
+ '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.25.0)(algoliasearch@5.25.0)
+ '@algolia/client-search': 5.25.0
+ algoliasearch: 5.25.0
+
+ '@algolia/autocomplete-shared@1.17.7(@algolia/client-search@5.25.0)(algoliasearch@5.25.0)':
+ dependencies:
+ '@algolia/client-search': 5.25.0
+ algoliasearch: 5.25.0
+
+ '@algolia/client-abtesting@5.25.0':
+ dependencies:
+ '@algolia/client-common': 5.25.0
+ '@algolia/requester-browser-xhr': 5.25.0
+ '@algolia/requester-fetch': 5.25.0
+ '@algolia/requester-node-http': 5.25.0
+
+ '@algolia/client-analytics@5.25.0':
+ dependencies:
+ '@algolia/client-common': 5.25.0
+ '@algolia/requester-browser-xhr': 5.25.0
+ '@algolia/requester-fetch': 5.25.0
+ '@algolia/requester-node-http': 5.25.0
+
+ '@algolia/client-common@5.25.0': {}
+
+ '@algolia/client-insights@5.25.0':
+ dependencies:
+ '@algolia/client-common': 5.25.0
+ '@algolia/requester-browser-xhr': 5.25.0
+ '@algolia/requester-fetch': 5.25.0
+ '@algolia/requester-node-http': 5.25.0
+
+ '@algolia/client-personalization@5.25.0':
+ dependencies:
+ '@algolia/client-common': 5.25.0
+ '@algolia/requester-browser-xhr': 5.25.0
+ '@algolia/requester-fetch': 5.25.0
+ '@algolia/requester-node-http': 5.25.0
+
+ '@algolia/client-query-suggestions@5.25.0':
+ dependencies:
+ '@algolia/client-common': 5.25.0
+ '@algolia/requester-browser-xhr': 5.25.0
+ '@algolia/requester-fetch': 5.25.0
+ '@algolia/requester-node-http': 5.25.0
+
+ '@algolia/client-search@5.25.0':
+ dependencies:
+ '@algolia/client-common': 5.25.0
+ '@algolia/requester-browser-xhr': 5.25.0
+ '@algolia/requester-fetch': 5.25.0
+ '@algolia/requester-node-http': 5.25.0
+
+ '@algolia/ingestion@1.25.0':
+ dependencies:
+ '@algolia/client-common': 5.25.0
+ '@algolia/requester-browser-xhr': 5.25.0
+ '@algolia/requester-fetch': 5.25.0
+ '@algolia/requester-node-http': 5.25.0
+
+ '@algolia/monitoring@1.25.0':
+ dependencies:
+ '@algolia/client-common': 5.25.0
+ '@algolia/requester-browser-xhr': 5.25.0
+ '@algolia/requester-fetch': 5.25.0
+ '@algolia/requester-node-http': 5.25.0
+
+ '@algolia/recommend@5.25.0':
+ dependencies:
+ '@algolia/client-common': 5.25.0
+ '@algolia/requester-browser-xhr': 5.25.0
+ '@algolia/requester-fetch': 5.25.0
+ '@algolia/requester-node-http': 5.25.0
+
+ '@algolia/requester-browser-xhr@5.25.0':
+ dependencies:
+ '@algolia/client-common': 5.25.0
+
+ '@algolia/requester-fetch@5.25.0':
+ dependencies:
+ '@algolia/client-common': 5.25.0
+
+ '@algolia/requester-node-http@5.25.0':
+ dependencies:
+ '@algolia/client-common': 5.25.0
+
+ '@antfu/install-pkg@1.1.0':
+ dependencies:
+ package-manager-detector: 1.5.0
+ tinyexec: 1.0.2
+
+ '@antfu/utils@9.3.0': {}
+
+ '@babel/helper-string-parser@7.27.1': {}
+
+ '@babel/helper-validator-identifier@7.27.1': {}
+
+ '@babel/parser@7.27.2':
+ dependencies:
+ '@babel/types': 7.27.1
+
+ '@babel/types@7.27.1':
+ dependencies:
+ '@babel/helper-string-parser': 7.27.1
+ '@babel/helper-validator-identifier': 7.27.1
+
+ '@docsearch/css@3.8.2': {}
+
+ '@docsearch/js@3.8.2(@algolia/client-search@5.25.0)(search-insights@2.17.3)':
+ dependencies:
+ '@docsearch/react': 3.8.2(@algolia/client-search@5.25.0)(search-insights@2.17.3)
+ preact: 10.26.6
+ transitivePeerDependencies:
+ - '@algolia/client-search'
+ - '@types/react'
+ - react
+ - react-dom
+ - search-insights
+
+ '@docsearch/react@3.8.2(@algolia/client-search@5.25.0)(search-insights@2.17.3)':
+ dependencies:
+ '@algolia/autocomplete-core': 1.17.7(@algolia/client-search@5.25.0)(algoliasearch@5.25.0)(search-insights@2.17.3)
+ '@algolia/autocomplete-preset-algolia': 1.17.7(@algolia/client-search@5.25.0)(algoliasearch@5.25.0)
+ '@docsearch/css': 3.8.2
+ algoliasearch: 5.25.0
+ optionalDependencies:
+ search-insights: 2.17.3
+ transitivePeerDependencies:
+ - '@algolia/client-search'
+
+ '@esbuild/aix-ppc64@0.21.5':
+ optional: true
+
+ '@esbuild/android-arm64@0.21.5':
+ optional: true
+
+ '@esbuild/android-arm@0.21.5':
+ optional: true
+
+ '@esbuild/android-x64@0.21.5':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.21.5':
+ optional: true
+
+ '@esbuild/darwin-x64@0.21.5':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.21.5':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.21.5':
+ optional: true
+
+ '@esbuild/linux-arm64@0.21.5':
+ optional: true
+
+ '@esbuild/linux-arm@0.21.5':
+ optional: true
+
+ '@esbuild/linux-ia32@0.21.5':
+ optional: true
+
+ '@esbuild/linux-loong64@0.21.5':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.21.5':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.21.5':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.21.5':
+ optional: true
+
+ '@esbuild/linux-s390x@0.21.5':
+ optional: true
+
+ '@esbuild/linux-x64@0.21.5':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.21.5':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.21.5':
+ optional: true
+
+ '@esbuild/sunos-x64@0.21.5':
+ optional: true
+
+ '@esbuild/win32-arm64@0.21.5':
+ optional: true
+
+ '@esbuild/win32-ia32@0.21.5':
+ optional: true
+
+ '@esbuild/win32-x64@0.21.5':
+ optional: true
+
+ '@iconify-json/logos@1.2.10':
+ dependencies:
+ '@iconify/types': 2.0.0
+
+ '@iconify-json/simple-icons@1.2.34':
+ dependencies:
+ '@iconify/types': 2.0.0
+
+ '@iconify-json/vscode-icons@1.2.33':
+ dependencies:
+ '@iconify/types': 2.0.0
+
+ '@iconify/types@2.0.0': {}
+
+ '@iconify/utils@3.0.2':
+ dependencies:
+ '@antfu/install-pkg': 1.1.0
+ '@antfu/utils': 9.3.0
+ '@iconify/types': 2.0.0
+ debug: 4.4.3
+ globals: 15.15.0
+ kolorist: 1.8.0
+ local-pkg: 1.1.2
+ mlly: 1.8.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@jridgewell/sourcemap-codec@1.5.0': {}
+
+ '@rollup/rollup-android-arm-eabi@4.40.2':
+ optional: true
+
+ '@rollup/rollup-android-arm64@4.40.2':
+ optional: true
+
+ '@rollup/rollup-darwin-arm64@4.40.2':
+ optional: true
+
+ '@rollup/rollup-darwin-x64@4.40.2':
+ optional: true
+
+ '@rollup/rollup-freebsd-arm64@4.40.2':
+ optional: true
+
+ '@rollup/rollup-freebsd-x64@4.40.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.40.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm-musleabihf@4.40.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-gnu@4.40.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-musl@4.40.2':
+ optional: true
+
+ '@rollup/rollup-linux-loongarch64-gnu@4.40.2':
+ optional: true
+
+ '@rollup/rollup-linux-powerpc64le-gnu@4.40.2':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-gnu@4.40.2':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-musl@4.40.2':
+ optional: true
+
+ '@rollup/rollup-linux-s390x-gnu@4.40.2':
+ optional: true
+
+ '@rollup/rollup-linux-x64-gnu@4.40.2':
+ optional: true
+
+ '@rollup/rollup-linux-x64-musl@4.40.2':
+ optional: true
+
+ '@rollup/rollup-win32-arm64-msvc@4.40.2':
+ optional: true
+
+ '@rollup/rollup-win32-ia32-msvc@4.40.2':
+ optional: true
+
+ '@rollup/rollup-win32-x64-msvc@4.40.2':
+ optional: true
+
+ '@shikijs/core@2.5.0':
+ dependencies:
+ '@shikijs/engine-javascript': 2.5.0
+ '@shikijs/engine-oniguruma': 2.5.0
+ '@shikijs/types': 2.5.0
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.4
+ hast-util-to-html: 9.0.5
+
+ '@shikijs/engine-javascript@2.5.0':
+ dependencies:
+ '@shikijs/types': 2.5.0
+ '@shikijs/vscode-textmate': 10.0.2
+ oniguruma-to-es: 3.1.1
+
+ '@shikijs/engine-oniguruma@2.5.0':
+ dependencies:
+ '@shikijs/types': 2.5.0
+ '@shikijs/vscode-textmate': 10.0.2
+
+ '@shikijs/langs@2.5.0':
+ dependencies:
+ '@shikijs/types': 2.5.0
+
+ '@shikijs/themes@2.5.0':
+ dependencies:
+ '@shikijs/types': 2.5.0
+
+ '@shikijs/transformers@2.5.0':
+ dependencies:
+ '@shikijs/core': 2.5.0
+ '@shikijs/types': 2.5.0
+
+ '@shikijs/types@2.5.0':
+ dependencies:
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.4
+
+ '@shikijs/vscode-textmate@10.0.2': {}
+
+ '@types/estree@1.0.7': {}
+
+ '@types/hast@3.0.4':
+ dependencies:
+ '@types/unist': 3.0.3
+
+ '@types/linkify-it@5.0.0': {}
+
+ '@types/markdown-it@14.1.2':
+ dependencies:
+ '@types/linkify-it': 5.0.0
+ '@types/mdurl': 2.0.0
+
+ '@types/mdast@4.0.4':
+ dependencies:
+ '@types/unist': 3.0.3
+
+ '@types/mdurl@2.0.0': {}
+
+ '@types/unist@3.0.3': {}
+
+ '@types/web-bluetooth@0.0.21': {}
+
+ '@ungap/structured-clone@1.3.0': {}
+
+ '@vitejs/plugin-vue@5.2.4(vite@5.4.19)(vue@3.5.14)':
+ dependencies:
+ vite: 5.4.19
+ vue: 3.5.14
+
+ '@vue/compiler-core@3.5.14':
+ dependencies:
+ '@babel/parser': 7.27.2
+ '@vue/shared': 3.5.14
+ entities: 4.5.0
+ estree-walker: 2.0.2
+ source-map-js: 1.2.1
+
+ '@vue/compiler-dom@3.5.14':
+ dependencies:
+ '@vue/compiler-core': 3.5.14
+ '@vue/shared': 3.5.14
+
+ '@vue/compiler-sfc@3.5.14':
+ dependencies:
+ '@babel/parser': 7.27.2
+ '@vue/compiler-core': 3.5.14
+ '@vue/compiler-dom': 3.5.14
+ '@vue/compiler-ssr': 3.5.14
+ '@vue/shared': 3.5.14
+ estree-walker: 2.0.2
+ magic-string: 0.30.17
+ postcss: 8.5.3
+ source-map-js: 1.2.1
+
+ '@vue/compiler-ssr@3.5.14':
+ dependencies:
+ '@vue/compiler-dom': 3.5.14
+ '@vue/shared': 3.5.14
+
+ '@vue/devtools-api@7.7.6':
+ dependencies:
+ '@vue/devtools-kit': 7.7.6
+
+ '@vue/devtools-kit@7.7.6':
+ dependencies:
+ '@vue/devtools-shared': 7.7.6
+ birpc: 2.3.0
+ hookable: 5.5.3
+ mitt: 3.0.1
+ perfect-debounce: 1.0.0
+ speakingurl: 14.0.1
+ superjson: 2.2.2
+
+ '@vue/devtools-shared@7.7.6':
+ dependencies:
+ rfdc: 1.4.1
+
+ '@vue/reactivity@3.5.14':
+ dependencies:
+ '@vue/shared': 3.5.14
+
+ '@vue/runtime-core@3.5.14':
+ dependencies:
+ '@vue/reactivity': 3.5.14
+ '@vue/shared': 3.5.14
+
+ '@vue/runtime-dom@3.5.14':
+ dependencies:
+ '@vue/reactivity': 3.5.14
+ '@vue/runtime-core': 3.5.14
+ '@vue/shared': 3.5.14
+ csstype: 3.1.3
+
+ '@vue/server-renderer@3.5.14(vue@3.5.14)':
+ dependencies:
+ '@vue/compiler-ssr': 3.5.14
+ '@vue/shared': 3.5.14
+ vue: 3.5.14
+
+ '@vue/shared@3.5.14': {}
+
+ '@vueuse/core@12.8.2':
+ dependencies:
+ '@types/web-bluetooth': 0.0.21
+ '@vueuse/metadata': 12.8.2
+ '@vueuse/shared': 12.8.2
+ vue: 3.5.14
+ transitivePeerDependencies:
+ - typescript
+
+ '@vueuse/integrations@12.8.2(focus-trap@7.6.4)':
+ dependencies:
+ '@vueuse/core': 12.8.2
+ '@vueuse/shared': 12.8.2
+ vue: 3.5.14
+ optionalDependencies:
+ focus-trap: 7.6.4
+ transitivePeerDependencies:
+ - typescript
+
+ '@vueuse/metadata@12.8.2': {}
+
+ '@vueuse/shared@12.8.2':
+ dependencies:
+ vue: 3.5.14
+ transitivePeerDependencies:
+ - typescript
+
+ acorn@8.15.0: {}
+
+ algoliasearch@5.25.0:
+ dependencies:
+ '@algolia/client-abtesting': 5.25.0
+ '@algolia/client-analytics': 5.25.0
+ '@algolia/client-common': 5.25.0
+ '@algolia/client-insights': 5.25.0
+ '@algolia/client-personalization': 5.25.0
+ '@algolia/client-query-suggestions': 5.25.0
+ '@algolia/client-search': 5.25.0
+ '@algolia/ingestion': 1.25.0
+ '@algolia/monitoring': 1.25.0
+ '@algolia/recommend': 5.25.0
+ '@algolia/requester-browser-xhr': 5.25.0
+ '@algolia/requester-fetch': 5.25.0
+ '@algolia/requester-node-http': 5.25.0
+
+ birpc@2.3.0: {}
+
+ ccount@2.0.1: {}
+
+ character-entities-html4@2.1.0: {}
+
+ character-entities-legacy@3.0.0: {}
+
+ comma-separated-tokens@2.0.3: {}
+
+ confbox@0.1.8: {}
+
+ confbox@0.2.2: {}
+
+ copy-anything@3.0.5:
+ dependencies:
+ is-what: 4.1.16
+
+ csstype@3.1.3: {}
+
+ debug@4.4.3:
+ dependencies:
+ ms: 2.1.3
+
+ dequal@2.0.3: {}
+
+ devlop@1.1.0:
+ dependencies:
+ dequal: 2.0.3
+
+ emoji-regex-xs@1.0.0: {}
+
+ entities@4.5.0: {}
+
+ esbuild@0.21.5:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.21.5
+ '@esbuild/android-arm': 0.21.5
+ '@esbuild/android-arm64': 0.21.5
+ '@esbuild/android-x64': 0.21.5
+ '@esbuild/darwin-arm64': 0.21.5
+ '@esbuild/darwin-x64': 0.21.5
+ '@esbuild/freebsd-arm64': 0.21.5
+ '@esbuild/freebsd-x64': 0.21.5
+ '@esbuild/linux-arm': 0.21.5
+ '@esbuild/linux-arm64': 0.21.5
+ '@esbuild/linux-ia32': 0.21.5
+ '@esbuild/linux-loong64': 0.21.5
+ '@esbuild/linux-mips64el': 0.21.5
+ '@esbuild/linux-ppc64': 0.21.5
+ '@esbuild/linux-riscv64': 0.21.5
+ '@esbuild/linux-s390x': 0.21.5
+ '@esbuild/linux-x64': 0.21.5
+ '@esbuild/netbsd-x64': 0.21.5
+ '@esbuild/openbsd-x64': 0.21.5
+ '@esbuild/sunos-x64': 0.21.5
+ '@esbuild/win32-arm64': 0.21.5
+ '@esbuild/win32-ia32': 0.21.5
+ '@esbuild/win32-x64': 0.21.5
+
+ estree-walker@2.0.2: {}
+
+ exsolve@1.0.7: {}
+
+ focus-trap@7.6.4:
+ dependencies:
+ tabbable: 6.2.0
+
+ fsevents@2.3.3:
+ optional: true
+
+ globals@15.15.0: {}
+
+ hast-util-to-html@9.0.5:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/unist': 3.0.3
+ ccount: 2.0.1
+ comma-separated-tokens: 2.0.3
+ hast-util-whitespace: 3.0.0
+ html-void-elements: 3.0.0
+ mdast-util-to-hast: 13.2.0
+ property-information: 7.1.0
+ space-separated-tokens: 2.0.2
+ stringify-entities: 4.0.4
+ zwitch: 2.0.4
+
+ hast-util-whitespace@3.0.0:
+ dependencies:
+ '@types/hast': 3.0.4
+
+ hookable@5.5.3: {}
+
+ html-void-elements@3.0.0: {}
+
+ is-what@4.1.16: {}
+
+ kolorist@1.8.0: {}
+
+ local-pkg@1.1.2:
+ dependencies:
+ mlly: 1.8.0
+ pkg-types: 2.3.0
+ quansync: 0.2.11
+
+ magic-string@0.30.17:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.0
+
+ mark.js@8.11.1: {}
+
+ mdast-util-to-hast@13.2.0:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ '@ungap/structured-clone': 1.3.0
+ devlop: 1.1.0
+ micromark-util-sanitize-uri: 2.0.1
+ trim-lines: 3.0.1
+ unist-util-position: 5.0.0
+ unist-util-visit: 5.0.0
+ vfile: 6.0.3
+
+ micromark-util-character@2.1.1:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-encode@2.0.1: {}
+
+ micromark-util-sanitize-uri@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-encode: 2.0.1
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-symbol@2.0.1: {}
+
+ micromark-util-types@2.0.2: {}
+
+ minisearch@7.1.2: {}
+
+ mitt@3.0.1: {}
+
+ mlly@1.8.0:
+ dependencies:
+ acorn: 8.15.0
+ pathe: 2.0.3
+ pkg-types: 1.3.1
+ ufo: 1.6.1
+
+ ms@2.1.3: {}
+
+ nanoid@3.3.11: {}
+
+ oniguruma-to-es@3.1.1:
+ dependencies:
+ emoji-regex-xs: 1.0.0
+ regex: 6.0.1
+ regex-recursion: 6.0.2
+
+ package-manager-detector@1.5.0: {}
+
+ pathe@2.0.3: {}
+
+ perfect-debounce@1.0.0: {}
+
+ picocolors@1.1.1: {}
+
+ pkg-types@1.3.1:
+ dependencies:
+ confbox: 0.1.8
+ mlly: 1.8.0
+ pathe: 2.0.3
+
+ pkg-types@2.3.0:
+ dependencies:
+ confbox: 0.2.2
+ exsolve: 1.0.7
+ pathe: 2.0.3
+
+ postcss@8.5.3:
+ dependencies:
+ nanoid: 3.3.11
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
+ preact@10.26.6: {}
+
+ property-information@7.1.0: {}
+
+ quansync@0.2.11: {}
+
+ regex-recursion@6.0.2:
+ dependencies:
+ regex-utilities: 2.3.0
+
+ regex-utilities@2.3.0: {}
+
+ regex@6.0.1:
+ dependencies:
+ regex-utilities: 2.3.0
+
+ rfdc@1.4.1: {}
+
+ rollup@4.40.2:
+ dependencies:
+ '@types/estree': 1.0.7
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.40.2
+ '@rollup/rollup-android-arm64': 4.40.2
+ '@rollup/rollup-darwin-arm64': 4.40.2
+ '@rollup/rollup-darwin-x64': 4.40.2
+ '@rollup/rollup-freebsd-arm64': 4.40.2
+ '@rollup/rollup-freebsd-x64': 4.40.2
+ '@rollup/rollup-linux-arm-gnueabihf': 4.40.2
+ '@rollup/rollup-linux-arm-musleabihf': 4.40.2
+ '@rollup/rollup-linux-arm64-gnu': 4.40.2
+ '@rollup/rollup-linux-arm64-musl': 4.40.2
+ '@rollup/rollup-linux-loongarch64-gnu': 4.40.2
+ '@rollup/rollup-linux-powerpc64le-gnu': 4.40.2
+ '@rollup/rollup-linux-riscv64-gnu': 4.40.2
+ '@rollup/rollup-linux-riscv64-musl': 4.40.2
+ '@rollup/rollup-linux-s390x-gnu': 4.40.2
+ '@rollup/rollup-linux-x64-gnu': 4.40.2
+ '@rollup/rollup-linux-x64-musl': 4.40.2
+ '@rollup/rollup-win32-arm64-msvc': 4.40.2
+ '@rollup/rollup-win32-ia32-msvc': 4.40.2
+ '@rollup/rollup-win32-x64-msvc': 4.40.2
+ fsevents: 2.3.3
+
+ search-insights@2.17.3: {}
+
+ shiki@2.5.0:
+ dependencies:
+ '@shikijs/core': 2.5.0
+ '@shikijs/engine-javascript': 2.5.0
+ '@shikijs/engine-oniguruma': 2.5.0
+ '@shikijs/langs': 2.5.0
+ '@shikijs/themes': 2.5.0
+ '@shikijs/types': 2.5.0
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.4
+
+ source-map-js@1.2.1: {}
+
+ space-separated-tokens@2.0.2: {}
+
+ speakingurl@14.0.1: {}
+
+ stringify-entities@4.0.4:
+ dependencies:
+ character-entities-html4: 2.1.0
+ character-entities-legacy: 3.0.0
+
+ superjson@2.2.2:
+ dependencies:
+ copy-anything: 3.0.5
+
+ tabbable@6.2.0: {}
+
+ tinyexec@1.0.2: {}
+
+ trim-lines@3.0.1: {}
+
+ ufo@1.6.1: {}
+
+ unist-util-is@6.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-position@5.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-stringify-position@4.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-visit-parents@6.0.1:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.0
+
+ unist-util-visit@5.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.0
+ unist-util-visit-parents: 6.0.1
+
+ vfile-message@4.0.2:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-stringify-position: 4.0.0
+
+ vfile@6.0.3:
+ dependencies:
+ '@types/unist': 3.0.3
+ vfile-message: 4.0.2
+
+ vite@5.4.19:
+ dependencies:
+ esbuild: 0.21.5
+ postcss: 8.5.3
+ rollup: 4.40.2
+ optionalDependencies:
+ fsevents: 2.3.3
+
+ vitepress-plugin-group-icons@1.6.5(vite@5.4.19):
+ dependencies:
+ '@iconify-json/logos': 1.2.10
+ '@iconify-json/vscode-icons': 1.2.33
+ '@iconify/utils': 3.0.2
+ optionalDependencies:
+ vite: 5.4.19
+ transitivePeerDependencies:
+ - supports-color
+
+ vitepress@1.6.3(@algolia/client-search@5.25.0)(postcss@8.5.3)(search-insights@2.17.3):
+ dependencies:
+ '@docsearch/css': 3.8.2
+ '@docsearch/js': 3.8.2(@algolia/client-search@5.25.0)(search-insights@2.17.3)
+ '@iconify-json/simple-icons': 1.2.34
+ '@shikijs/core': 2.5.0
+ '@shikijs/transformers': 2.5.0
+ '@shikijs/types': 2.5.0
+ '@types/markdown-it': 14.1.2
+ '@vitejs/plugin-vue': 5.2.4(vite@5.4.19)(vue@3.5.14)
+ '@vue/devtools-api': 7.7.6
+ '@vue/shared': 3.5.14
+ '@vueuse/core': 12.8.2
+ '@vueuse/integrations': 12.8.2(focus-trap@7.6.4)
+ focus-trap: 7.6.4
+ mark.js: 8.11.1
+ minisearch: 7.1.2
+ shiki: 2.5.0
+ vite: 5.4.19
+ vue: 3.5.14
+ optionalDependencies:
+ postcss: 8.5.3
+ transitivePeerDependencies:
+ - '@algolia/client-search'
+ - '@types/node'
+ - '@types/react'
+ - async-validator
+ - axios
+ - change-case
+ - drauu
+ - fuse.js
+ - idb-keyval
+ - jwt-decode
+ - less
+ - lightningcss
+ - nprogress
+ - qrcode
+ - react
+ - react-dom
+ - sass
+ - sass-embedded
+ - search-insights
+ - sortablejs
+ - stylus
+ - sugarss
+ - terser
+ - typescript
+ - universal-cookie
+
+ vue@3.5.14:
+ dependencies:
+ '@vue/compiler-dom': 3.5.14
+ '@vue/compiler-sfc': 3.5.14
+ '@vue/runtime-dom': 3.5.14
+ '@vue/server-renderer': 3.5.14(vue@3.5.14)
+ '@vue/shared': 3.5.14
+
+ zwitch@2.0.4: {}
diff --git a/package.json b/package.json
index 6acdcda..9c788ca 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "classic-react-hooks",
- "version": "1.4.0",
+ "version": "2.0.0-canary.24",
"description": "A great collection of React utility hooks",
"keywords": [
"classic-react-hooks",
@@ -25,10 +25,12 @@
"module": "dist/index.mjs",
"typings": "dist/index.d.ts",
"files": [
- "dist"
+ "dist",
+ "src",
+ "tsup.config.ts"
],
"scripts": {
- "build": "pnpm clean && tsup",
+ "build": "tsdown",
"prepare": "pnpm build",
"release": "changeset publish",
"type-check": "tsc",
@@ -49,19 +51,19 @@
"@size-limit/preset-small-lib": "^8.2.4",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^14.0.0",
- "@types/node": "^18.15.13",
- "@types/react": "^18.0.38",
- "@types/react-dom": "^18.0.11",
+ "@types/node": "^22.17.0",
+ "@types/react": "^18.2.0",
+ "@types/react-dom": "^18.2.0",
"@types/testing-library__jest-dom": "^5.14.5",
"@vitejs/plugin-react": "^4.3.1",
- "@vitest/coverage-istanbul": "^2.0.3",
+ "@vitest/coverage-istanbul": "^3.2.4",
"jsdom": "^21.1.1",
"prettier": "^2.8.7",
"react-dom": "^18.2.0",
"size-limit": "^8.2.4",
"terser": "^5.17.1",
"ts-node": "^10.9.1",
- "tsup": "^6.7.0",
+ "tsdown": "^0.17.2",
"typescript": "^5.0.4",
"vite": "5.3.3",
"vitest": "^2.0.3"
@@ -70,7 +72,7 @@
"node": ">=16.14.0",
"pnpm": ">=8.12.0"
},
- "packageManager": "pnpm@8.12.0",
+ "packageManager": "pnpm@10.0.0",
"prettier": {
"arrowParens": "always",
"printWidth": 120,
@@ -100,7 +102,30 @@
"ws@>=8.0.0 <8.17.1": ">=8.17.1",
"word-wrap@<1.2.4": ">=1.2.4",
"tough-cookie@<4.1.3": ">=4.1.3",
- "braces@<3.0.3": ">=3.0.3"
+ "braces@<3.0.3": ">=3.0.3",
+ "micromatch@<4.0.8": ">=4.0.8",
+ "vite@>=5.3.0 <5.3.6": ">=5.3.6",
+ "vite@>=5.3.0 <=5.3.5": ">=5.3.6",
+ "rollup@>=3.0.0 <3.29.5": ">=3.29.5",
+ "rollup@>=4.0.0 <4.22.4": ">=4.22.4",
+ "nanoid@<3.3.8": ">=3.3.8",
+ "esbuild@<=0.24.2": ">=0.25.0",
+ "vitest@>=2.0.0 <2.1.9": ">=2.1.9",
+ "vite@>=5.0.0 <=5.4.11": ">=5.4.12",
+ "vite@>=5.0.0 <5.4.15": ">=5.4.15",
+ "vite@>=5.0.0 <5.4.16": ">=5.4.16",
+ "vite@>=5.0.0 <5.4.18": ">=5.4.18",
+ "@babel/runtime@<7.26.10": ">=7.26.10",
+ "@babel/helpers@<7.26.10": ">=7.26.10",
+ "vite@>=5.0.0 <=5.4.18": ">=5.4.19",
+ "vite@>=5.0.0 <5.4.17": ">=5.4.17",
+ "cross-spawn@<6.0.6": ">=6.0.6",
+ "cross-spawn@>=7.0.0 <7.0.5": ">=7.0.5",
+ "brace-expansion@>=1.0.0 <=1.1.11": ">=1.1.12",
+ "brace-expansion@>=2.0.0 <=2.0.1": ">=2.0.2",
+ "form-data@>=4.0.0 <4.0.4": ">=4.0.4",
+ "tmp@<=0.2.3": ">=0.2.4",
+ "vite@<=5.4.19": ">=5.4.20"
}
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index c2edd33..6438df8 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1,4 +1,4 @@
-lockfileVersion: '6.0'
+lockfileVersion: '9.0'
settings:
autoInstallPeers: true
@@ -13,4871 +13,4655 @@ overrides:
word-wrap@<1.2.4: '>=1.2.4'
tough-cookie@<4.1.3: '>=4.1.3'
braces@<3.0.3: '>=3.0.3'
+ micromatch@<4.0.8: '>=4.0.8'
+ vite@>=5.3.0 <5.3.6: '>=5.3.6'
+ vite@>=5.3.0 <=5.3.5: '>=5.3.6'
+ rollup@>=3.0.0 <3.29.5: '>=3.29.5'
+ rollup@>=4.0.0 <4.22.4: '>=4.22.4'
+ nanoid@<3.3.8: '>=3.3.8'
+ esbuild@<=0.24.2: '>=0.25.0'
+ vitest@>=2.0.0 <2.1.9: '>=2.1.9'
+ vite@>=5.0.0 <=5.4.11: '>=5.4.12'
+ vite@>=5.0.0 <5.4.15: '>=5.4.15'
+ vite@>=5.0.0 <5.4.16: '>=5.4.16'
+ vite@>=5.0.0 <5.4.18: '>=5.4.18'
+ '@babel/runtime@<7.26.10': '>=7.26.10'
+ '@babel/helpers@<7.26.10': '>=7.26.10'
+ vite@>=5.0.0 <=5.4.18: '>=5.4.19'
+ vite@>=5.0.0 <5.4.17: '>=5.4.17'
+ cross-spawn@<6.0.6: '>=6.0.6'
+ cross-spawn@>=7.0.0 <7.0.5: '>=7.0.5'
+ brace-expansion@>=1.0.0 <=1.1.11: '>=1.1.12'
+ brace-expansion@>=2.0.0 <=2.0.1: '>=2.0.2'
+ form-data@>=4.0.0 <4.0.4: '>=4.0.4'
+ tmp@<=0.2.3: '>=0.2.4'
+ vite@<=5.4.19: '>=5.4.20'
+
+importers:
+
+ .:
+ dependencies:
+ react:
+ specifier: ^18.2.0
+ version: 18.3.1
+ devDependencies:
+ '@changesets/cli':
+ specifier: ^2.26.1
+ version: 2.29.7(@types/node@22.18.11)
+ '@size-limit/preset-small-lib':
+ specifier: ^8.2.4
+ version: 8.2.6(size-limit@8.2.6)
+ '@testing-library/jest-dom':
+ specifier: ^5.16.5
+ version: 5.17.0
+ '@testing-library/react':
+ specifier: ^14.0.0
+ version: 14.3.1(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@types/node':
+ specifier: ^22.17.0
+ version: 22.18.11
+ '@types/react':
+ specifier: ^18.2.0
+ version: 18.3.26
+ '@types/react-dom':
+ specifier: ^18.2.0
+ version: 18.3.7(@types/react@18.3.26)
+ '@types/testing-library__jest-dom':
+ specifier: ^5.14.5
+ version: 5.14.9
+ '@vitejs/plugin-react':
+ specifier: ^4.3.1
+ version: 4.7.0(vite@7.1.11(@types/node@22.18.11)(terser@5.44.0))
+ '@vitest/coverage-istanbul':
+ specifier: ^3.2.4
+ version: 3.2.4(vitest@3.2.4(@types/node@22.18.11)(jsdom@21.1.2)(terser@5.44.0))
+ jsdom:
+ specifier: ^21.1.1
+ version: 21.1.2
+ prettier:
+ specifier: ^2.8.7
+ version: 2.8.8
+ react-dom:
+ specifier: ^18.2.0
+ version: 18.3.1(react@18.3.1)
+ size-limit:
+ specifier: ^8.2.4
+ version: 8.2.6
+ terser:
+ specifier: ^5.17.1
+ version: 5.44.0
+ ts-node:
+ specifier: ^10.9.1
+ version: 10.9.2(@types/node@22.18.11)(typescript@5.9.3)
+ tsdown:
+ specifier: ^0.17.2
+ version: 0.17.3(typescript@5.9.3)
+ typescript:
+ specifier: ^5.0.4
+ version: 5.9.3
+ vite:
+ specifier: '>=5.4.20'
+ version: 7.1.11(@types/node@22.18.11)(terser@5.44.0)
+ vitest:
+ specifier: '>=2.1.9'
+ version: 3.2.4(@types/node@22.18.11)(jsdom@21.1.2)(terser@5.44.0)
+
+packages:
+
+ '@adobe/css-tools@4.4.4':
+ resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==}
+
+ '@babel/code-frame@7.27.1':
+ resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/compat-data@7.28.4':
+ resolution: {integrity: sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/core@7.28.4':
+ resolution: {integrity: sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/generator@7.28.3':
+ resolution: {integrity: sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/generator@7.28.5':
+ resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-compilation-targets@7.27.2':
+ resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-globals@7.28.0':
+ resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-imports@7.27.1':
+ resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-transforms@7.28.3':
+ resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-plugin-utils@7.27.1':
+ resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-string-parser@7.27.1':
+ resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-identifier@7.27.1':
+ resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-identifier@7.28.5':
+ resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-option@7.27.1':
+ resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helpers@7.28.4':
+ resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/parser@7.28.4':
+ resolution: {integrity: sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
+ '@babel/parser@7.28.5':
+ resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
+ '@babel/plugin-transform-react-jsx-self@7.27.1':
+ resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-react-jsx-source@7.27.1':
+ resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/runtime@7.28.4':
+ resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/template@7.27.2':
+ resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/traverse@7.28.4':
+ resolution: {integrity: sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/types@7.28.4':
+ resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/types@7.28.5':
+ resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==}
+ engines: {node: '>=6.9.0'}
+
+ '@changesets/apply-release-plan@7.0.13':
+ resolution: {integrity: sha512-BIW7bofD2yAWoE8H4V40FikC+1nNFEKBisMECccS16W1rt6qqhNTBDmIw5HaqmMgtLNz9e7oiALiEUuKrQ4oHg==}
+
+ '@changesets/assemble-release-plan@6.0.9':
+ resolution: {integrity: sha512-tPgeeqCHIwNo8sypKlS3gOPmsS3wP0zHt67JDuL20P4QcXiw/O4Hl7oXiuLnP9yg+rXLQ2sScdV1Kkzde61iSQ==}
+
+ '@changesets/changelog-git@0.2.1':
+ resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==}
+
+ '@changesets/cli@2.29.7':
+ resolution: {integrity: sha512-R7RqWoaksyyKXbKXBTbT4REdy22yH81mcFK6sWtqSanxUCbUi9Uf+6aqxZtDQouIqPdem2W56CdxXgsxdq7FLQ==}
+ hasBin: true
+
+ '@changesets/config@3.1.1':
+ resolution: {integrity: sha512-bd+3Ap2TKXxljCggI0mKPfzCQKeV/TU4yO2h2C6vAihIo8tzseAn2e7klSuiyYYXvgu53zMN1OeYMIQkaQoWnA==}
+
+ '@changesets/errors@0.2.0':
+ resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==}
+
+ '@changesets/get-dependents-graph@2.1.3':
+ resolution: {integrity: sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ==}
+
+ '@changesets/get-release-plan@4.0.13':
+ resolution: {integrity: sha512-DWG1pus72FcNeXkM12tx+xtExyH/c9I1z+2aXlObH3i9YA7+WZEVaiHzHl03thpvAgWTRaH64MpfHxozfF7Dvg==}
+
+ '@changesets/get-version-range-type@0.4.0':
+ resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==}
+
+ '@changesets/git@3.0.4':
+ resolution: {integrity: sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==}
+
+ '@changesets/logger@0.1.1':
+ resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==}
+
+ '@changesets/parse@0.4.1':
+ resolution: {integrity: sha512-iwksMs5Bf/wUItfcg+OXrEpravm5rEd9Bf4oyIPL4kVTmJQ7PNDSd6MDYkpSJR1pn7tz/k8Zf2DhTCqX08Ou+Q==}
+
+ '@changesets/pre@2.0.2':
+ resolution: {integrity: sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==}
+
+ '@changesets/read@0.6.5':
+ resolution: {integrity: sha512-UPzNGhsSjHD3Veb0xO/MwvasGe8eMyNrR/sT9gR8Q3DhOQZirgKhhXv/8hVsI0QpPjR004Z9iFxoJU6in3uGMg==}
+
+ '@changesets/should-skip-package@0.1.2':
+ resolution: {integrity: sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==}
+
+ '@changesets/types@4.1.0':
+ resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==}
+
+ '@changesets/types@6.1.0':
+ resolution: {integrity: sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==}
+
+ '@changesets/write@0.4.0':
+ resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==}
+
+ '@cspotcode/source-map-support@0.8.1':
+ resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
+ engines: {node: '>=12'}
+
+ '@emnapi/core@1.7.1':
+ resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==}
+
+ '@emnapi/runtime@1.7.1':
+ resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==}
+
+ '@emnapi/wasi-threads@1.1.0':
+ resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==}
+
+ '@esbuild/aix-ppc64@0.25.11':
+ resolution: {integrity: sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@esbuild/android-arm64@0.25.11':
+ resolution: {integrity: sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm@0.25.11':
+ resolution: {integrity: sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-x64@0.25.11':
+ resolution: {integrity: sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/darwin-arm64@0.25.11':
+ resolution: {integrity: sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.25.11':
+ resolution: {integrity: sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/freebsd-arm64@0.25.11':
+ resolution: {integrity: sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.25.11':
+ resolution: {integrity: sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/linux-arm64@0.25.11':
+ resolution: {integrity: sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.25.11':
+ resolution: {integrity: sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.25.11':
+ resolution: {integrity: sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.25.11':
+ resolution: {integrity: sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==}
+ engines: {node: '>=18'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.25.11':
+ resolution: {integrity: sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==}
+ engines: {node: '>=18'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.25.11':
+ resolution: {integrity: sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.25.11':
+ resolution: {integrity: sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==}
+ engines: {node: '>=18'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.25.11':
+ resolution: {integrity: sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==}
+ engines: {node: '>=18'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.25.11':
+ resolution: {integrity: sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/netbsd-arm64@0.25.11':
+ resolution: {integrity: sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [netbsd]
+
+ '@esbuild/netbsd-x64@0.25.11':
+ resolution: {integrity: sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/openbsd-arm64@0.25.11':
+ resolution: {integrity: sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openbsd]
+
+ '@esbuild/openbsd-x64@0.25.11':
+ resolution: {integrity: sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/openharmony-arm64@0.25.11':
+ resolution: {integrity: sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@esbuild/sunos-x64@0.25.11':
+ resolution: {integrity: sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/win32-arm64@0.25.11':
+ resolution: {integrity: sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.25.11':
+ resolution: {integrity: sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.25.11':
+ resolution: {integrity: sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [win32]
+
+ '@inquirer/external-editor@1.0.2':
+ resolution: {integrity: sha512-yy9cOoBnx58TlsPrIxauKIFQTiyH+0MK4e97y4sV9ERbI+zDxw7i2hxHLCIEGIE/8PPvDxGhgzIOTSOWcs6/MQ==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@types/node': '>=18'
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+
+ '@isaacs/cliui@8.0.2':
+ resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
+ engines: {node: '>=12'}
+
+ '@istanbuljs/schema@0.1.3':
+ resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==}
+ engines: {node: '>=8'}
+
+ '@jest/diff-sequences@30.0.1':
+ resolution: {integrity: sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ '@jest/expect-utils@30.2.0':
+ resolution: {integrity: sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ '@jest/get-type@30.1.0':
+ resolution: {integrity: sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ '@jest/pattern@30.0.1':
+ resolution: {integrity: sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ '@jest/schemas@30.0.5':
+ resolution: {integrity: sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ '@jest/types@30.2.0':
+ resolution: {integrity: sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ '@jridgewell/gen-mapping@0.3.13':
+ resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
+
+ '@jridgewell/remapping@2.3.5':
+ resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
+
+ '@jridgewell/resolve-uri@3.1.2':
+ resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/source-map@0.3.11':
+ resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==}
+
+ '@jridgewell/sourcemap-codec@1.5.5':
+ resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
+
+ '@jridgewell/trace-mapping@0.3.31':
+ resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+
+ '@jridgewell/trace-mapping@0.3.9':
+ resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
+
+ '@manypkg/find-root@1.1.0':
+ resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==}
+
+ '@manypkg/get-packages@1.1.3':
+ resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==}
+
+ '@napi-rs/wasm-runtime@1.1.0':
+ resolution: {integrity: sha512-Fq6DJW+Bb5jaWE69/qOE0D1TUN9+6uWhCeZpdnSBk14pjLcCWR7Q8n49PTSPHazM37JqrsdpEthXy2xn6jWWiA==}
+
+ '@nodelib/fs.scandir@2.1.5':
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.stat@2.0.5':
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.walk@1.2.8':
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+
+ '@oxc-project/types@0.101.0':
+ resolution: {integrity: sha512-nuFhqlUzJX+gVIPPfuE6xurd4lST3mdcWOhyK/rZO0B9XWMKm79SuszIQEnSMmmDhq1DC8WWVYGVd+6F93o1gQ==}
+
+ '@pkgjs/parseargs@0.11.0':
+ resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
+ engines: {node: '>=14'}
+
+ '@quansync/fs@1.0.0':
+ resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==}
+
+ '@rolldown/binding-android-arm64@1.0.0-beta.53':
+ resolution: {integrity: sha512-Ok9V8o7o6YfSdTTYA/uHH30r3YtOxLD6G3wih/U9DO0ucBBFq8WPt/DslU53OgfteLRHITZny9N/qCUxMf9kjQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [android]
+
+ '@rolldown/binding-darwin-arm64@1.0.0-beta.53':
+ resolution: {integrity: sha512-yIsKqMz0CtRnVa6x3Pa+mzTihr4Ty+Z6HfPbZ7RVbk1Uxnco4+CUn7Qbm/5SBol1JD/7nvY8rphAgyAi7Lj6Vg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rolldown/binding-darwin-x64@1.0.0-beta.53':
+ resolution: {integrity: sha512-GTXe+mxsCGUnJOFMhfGWmefP7Q9TpYUseHvhAhr21nCTgdS8jPsvirb0tJwM3lN0/u/cg7bpFNa16fQrjKrCjQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rolldown/binding-freebsd-x64@1.0.0-beta.53':
+ resolution: {integrity: sha512-9Tmp7bBvKqyDkMcL4e089pH3RsjD3SUungjmqWtyhNOxoQMh0fSmINTyYV8KXtE+JkxYMPWvnEt+/mfpVCkk8w==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.53':
+ resolution: {integrity: sha512-a1y5fiB0iovuzdbjUxa7+Zcvgv+mTmlGGC4XydVIsyl48eoxgaYkA3l9079hyTyhECsPq+mbr0gVQsFU11OJAQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm]
+ os: [linux]
+
+ '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.53':
+ resolution: {integrity: sha512-bpIGX+ov9PhJYV+wHNXl9rzq4F0QvILiURn0y0oepbQx+7stmQsKA0DhPGwmhfvF856wq+gbM8L92SAa/CBcLg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rolldown/binding-linux-arm64-musl@1.0.0-beta.53':
+ resolution: {integrity: sha512-bGe5EBB8FVjHBR1mOLOPEFg1Lp3//7geqWkU5NIhxe+yH0W8FVrQ6WRYOap4SUTKdklD/dC4qPLREkMMQ855FA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rolldown/binding-linux-x64-gnu@1.0.0-beta.53':
+ resolution: {integrity: sha512-qL+63WKVQs1CMvFedlPt0U9PiEKJOAL/bsHMKUDS6Vp2Q+YAv/QLPu8rcvkfIMvQ0FPU2WL0aX4eWwF6e/GAnA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+
+ '@rolldown/binding-linux-x64-musl@1.0.0-beta.53':
+ resolution: {integrity: sha512-VGl9JIGjoJh3H8Mb+7xnVqODajBmrdOOb9lxWXdcmxyI+zjB2sux69br0hZJDTyLJfvBoYm439zPACYbCjGRmw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+
+ '@rolldown/binding-openharmony-arm64@1.0.0-beta.53':
+ resolution: {integrity: sha512-B4iIserJXuSnNzA5xBLFUIjTfhNy7d9sq4FUMQY3GhQWGVhS2RWWzzDnkSU6MUt7/aHUrep0CdQfXUJI9D3W7A==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@rolldown/binding-wasm32-wasi@1.0.0-beta.53':
+ resolution: {integrity: sha512-BUjAEgpABEJXilGq/BPh7jeU3WAJ5o15c1ZEgHaDWSz3LB881LQZnbNJHmUiM4d1JQWMYYyR1Y490IBHi2FPJg==}
+ engines: {node: '>=14.0.0'}
+ cpu: [wasm32]
+
+ '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.53':
+ resolution: {integrity: sha512-s27uU7tpCWSjHBnxyVXHt3rMrQdJq5MHNv3BzsewCIroIw3DJFjMH1dzCPPMUFxnh1r52Nf9IJ/eWp6LDoyGcw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rolldown/binding-win32-x64-msvc@1.0.0-beta.53':
+ resolution: {integrity: sha512-cjWL/USPJ1g0en2htb4ssMjIycc36RvdQAx1WlXnS6DpULswiUTVXPDesTifSKYSyvx24E0YqQkEm0K/M2Z/AA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [win32]
+
+ '@rolldown/pluginutils@1.0.0-beta.27':
+ resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==}
+
+ '@rolldown/pluginutils@1.0.0-beta.53':
+ resolution: {integrity: sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==}
+
+ '@rollup/rollup-android-arm-eabi@4.52.5':
+ resolution: {integrity: sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ==}
+ cpu: [arm]
+ os: [android]
+
+ '@rollup/rollup-android-arm64@4.52.5':
+ resolution: {integrity: sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA==}
+ cpu: [arm64]
+ os: [android]
+
+ '@rollup/rollup-darwin-arm64@4.52.5':
+ resolution: {integrity: sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rollup/rollup-darwin-x64@4.52.5':
+ resolution: {integrity: sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rollup/rollup-freebsd-arm64@4.52.5':
+ resolution: {integrity: sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA==}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@rollup/rollup-freebsd-x64@4.52.5':
+ resolution: {integrity: sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.52.5':
+ resolution: {integrity: sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm-musleabihf@4.52.5':
+ resolution: {integrity: sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-gnu@4.52.5':
+ resolution: {integrity: sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-musl@4.52.5':
+ resolution: {integrity: sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-loong64-gnu@4.52.5':
+ resolution: {integrity: sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA==}
+ cpu: [loong64]
+ os: [linux]
+
+ '@rollup/rollup-linux-ppc64-gnu@4.52.5':
+ resolution: {integrity: sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-gnu@4.52.5':
+ resolution: {integrity: sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-musl@4.52.5':
+ resolution: {integrity: sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-s390x-gnu@4.52.5':
+ resolution: {integrity: sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ==}
+ cpu: [s390x]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-gnu@4.52.5':
+ resolution: {integrity: sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-musl@4.52.5':
+ resolution: {integrity: sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-openharmony-arm64@4.52.5':
+ resolution: {integrity: sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw==}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@rollup/rollup-win32-arm64-msvc@4.52.5':
+ resolution: {integrity: sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rollup/rollup-win32-ia32-msvc@4.52.5':
+ resolution: {integrity: sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-gnu@4.52.5':
+ resolution: {integrity: sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ==}
+ cpu: [x64]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-msvc@4.52.5':
+ resolution: {integrity: sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg==}
+ cpu: [x64]
+ os: [win32]
+
+ '@sinclair/typebox@0.34.41':
+ resolution: {integrity: sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==}
+
+ '@size-limit/esbuild@8.2.6':
+ resolution: {integrity: sha512-a4c8xVDuDMYw5jF655ADjQDluw3jGPPYer6UJock5rSnUlWnIbmT/Ohud7gJGq5gqyLUQOCrBD7NB3g+mlhj4g==}
+ engines: {node: ^14.0.0 || ^16.0.0 || >=18.0.0}
+ peerDependencies:
+ size-limit: 8.2.6
+
+ '@size-limit/file@8.2.6':
+ resolution: {integrity: sha512-B7ayjxiJsbtXdIIWazJkB5gezi5WBMecdHTFPMDhI3NwEML1RVvUjAkrb1mPAAkIpt2LVHPnhdCUHjqDdjugwg==}
+ engines: {node: ^14.0.0 || ^16.0.0 || >=18.0.0}
+ peerDependencies:
+ size-limit: 8.2.6
+
+ '@size-limit/preset-small-lib@8.2.6':
+ resolution: {integrity: sha512-roanEuscDaaXDsT5Cg9agMbmsQVlMr66eRg3AwT2o4vE7WFLR8Z42p0AHZiwucW1nGpCxAh8E08Qa/yyVuj5nA==}
+ peerDependencies:
+ size-limit: 8.2.6
+
+ '@testing-library/dom@9.3.4':
+ resolution: {integrity: sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==}
+ engines: {node: '>=14'}
+
+ '@testing-library/jest-dom@5.17.0':
+ resolution: {integrity: sha512-ynmNeT7asXyH3aSVv4vvX4Rb+0qjOhdNHnO/3vuZNqPmhDpV/+rCSGwQ7bLcmU2cJ4dvoheIO85LQj0IbJHEtg==}
+ engines: {node: '>=8', npm: '>=6', yarn: '>=1'}
+
+ '@testing-library/react@14.3.1':
+ resolution: {integrity: sha512-H99XjUhWQw0lTgyMN05W3xQG1Nh4lq574D8keFf1dDoNTJgp66VbJozRaczoF+wsiaPJNt/TcnfpLGufGxSrZQ==}
+ engines: {node: '>=14'}
+ peerDependencies:
+ react: ^18.0.0
+ react-dom: ^18.0.0
+
+ '@tootallnate/once@2.0.0':
+ resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
+ engines: {node: '>= 10'}
+
+ '@tsconfig/node10@1.0.11':
+ resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==}
+
+ '@tsconfig/node12@1.0.11':
+ resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==}
+
+ '@tsconfig/node14@1.0.3':
+ resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==}
+
+ '@tsconfig/node16@1.0.4':
+ resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==}
+
+ '@tybys/wasm-util@0.10.1':
+ resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
+
+ '@types/aria-query@5.0.4':
+ resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==}
+
+ '@types/babel__core@7.20.5':
+ resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
+
+ '@types/babel__generator@7.27.0':
+ resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==}
+
+ '@types/babel__template@7.4.4':
+ resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
+
+ '@types/babel__traverse@7.28.0':
+ resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==}
+
+ '@types/chai@5.2.2':
+ resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==}
+
+ '@types/deep-eql@4.0.2':
+ resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
+
+ '@types/estree@1.0.8':
+ resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
+
+ '@types/istanbul-lib-coverage@2.0.6':
+ resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==}
+
+ '@types/istanbul-lib-report@3.0.3':
+ resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==}
+
+ '@types/istanbul-reports@3.0.4':
+ resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==}
+
+ '@types/jest@30.0.0':
+ resolution: {integrity: sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==}
+
+ '@types/node@12.20.55':
+ resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==}
+
+ '@types/node@22.18.11':
+ resolution: {integrity: sha512-Gd33J2XIrXurb+eT2ktze3rJAfAp9ZNjlBdh4SVgyrKEOADwCbdUDaK7QgJno8Ue4kcajscsKqu6n8OBG3hhCQ==}
+
+ '@types/prop-types@15.7.15':
+ resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==}
+
+ '@types/react-dom@18.3.7':
+ resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==}
+ peerDependencies:
+ '@types/react': ^18.0.0
+
+ '@types/react@18.3.26':
+ resolution: {integrity: sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==}
+
+ '@types/stack-utils@2.0.3':
+ resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==}
+
+ '@types/testing-library__jest-dom@5.14.9':
+ resolution: {integrity: sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw==}
+
+ '@types/yargs-parser@21.0.3':
+ resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==}
+
+ '@types/yargs@17.0.33':
+ resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==}
+
+ '@vitejs/plugin-react@4.7.0':
+ resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ vite: '>=5.4.20'
+
+ '@vitest/coverage-istanbul@3.2.4':
+ resolution: {integrity: sha512-IDlpuFJiWU9rhcKLkpzj8mFu/lpe64gVgnV15ZOrYx1iFzxxrxCzbExiUEKtwwXRvEiEMUS6iZeYgnMxgbqbxQ==}
+ peerDependencies:
+ vitest: 3.2.4
+
+ '@vitest/expect@3.2.4':
+ resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==}
+
+ '@vitest/mocker@3.2.4':
+ resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==}
+ peerDependencies:
+ msw: ^2.4.9
+ vite: '>=5.4.20'
+ peerDependenciesMeta:
+ msw:
+ optional: true
+ vite:
+ optional: true
+
+ '@vitest/pretty-format@3.2.4':
+ resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==}
+
+ '@vitest/runner@3.2.4':
+ resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==}
+
+ '@vitest/snapshot@3.2.4':
+ resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==}
+
+ '@vitest/spy@3.2.4':
+ resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==}
+
+ '@vitest/utils@3.2.4':
+ resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==}
+
+ abab@2.0.6:
+ resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==}
+ deprecated: Use your platform's native atob() and btoa() methods instead
+
+ acorn-globals@7.0.1:
+ resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==}
+
+ acorn-walk@8.3.4:
+ resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==}
+ engines: {node: '>=0.4.0'}
+
+ acorn@8.15.0:
+ resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+
+ agent-base@6.0.2:
+ resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
+ engines: {node: '>= 6.0.0'}
+
+ ansi-colors@4.1.3:
+ resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
+ engines: {node: '>=6'}
+
+ ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+
+ ansi-regex@6.2.2:
+ resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==}
+ engines: {node: '>=12'}
+
+ ansi-styles@4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+
+ ansi-styles@5.2.0:
+ resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
+ engines: {node: '>=10'}
+
+ ansi-styles@6.2.3:
+ resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
+ engines: {node: '>=12'}
+
+ ansis@4.2.0:
+ resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==}
+ engines: {node: '>=14'}
+
+ anymatch@3.1.3:
+ resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+ engines: {node: '>= 8'}
+
+ arg@4.1.3:
+ resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
+
+ argparse@1.0.10:
+ resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
+
+ aria-query@5.1.3:
+ resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==}
+
+ aria-query@5.3.2:
+ resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==}
+ engines: {node: '>= 0.4'}
+
+ array-buffer-byte-length@1.0.2:
+ resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==}
+ engines: {node: '>= 0.4'}
+
+ array-union@2.1.0:
+ resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
+ engines: {node: '>=8'}
+
+ assertion-error@2.0.1:
+ resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
+ engines: {node: '>=12'}
+
+ ast-kit@2.2.0:
+ resolution: {integrity: sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==}
+ engines: {node: '>=20.19.0'}
+
+ asynckit@0.4.0:
+ resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+
+ available-typed-arrays@1.0.7:
+ resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
+ engines: {node: '>= 0.4'}
+
+ balanced-match@3.0.1:
+ resolution: {integrity: sha512-vjtV3hiLqYDNRoiAv0zC4QaGAMPomEoq83PRmYIofPswwZurCeWR5LByXm7SyoL0Zh5+2z0+HC7jG8gSZJUh0w==}
+ engines: {node: '>= 16'}
+
+ baseline-browser-mapping@2.8.18:
+ resolution: {integrity: sha512-UYmTpOBwgPScZpS4A+YbapwWuBwasxvO/2IOHArSsAhL/+ZdmATBXTex3t+l2hXwLVYK382ibr/nKoY9GKe86w==}
+ hasBin: true
+
+ better-path-resolve@1.0.0:
+ resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==}
+ engines: {node: '>=4'}
+
+ binary-extensions@2.3.0:
+ resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
+ engines: {node: '>=8'}
+
+ birpc@3.0.0:
+ resolution: {integrity: sha512-by+04pHuxpCEQcucAXqzopqfhyI8TLK5Qg5MST0cB6MP+JhHna9ollrtK9moVh27aq6Q6MEJgebD0cVm//yBkg==}
+
+ brace-expansion@4.0.1:
+ resolution: {integrity: sha512-YClrbvTCXGe70pU2JiEiPLYXO9gQkyxYeKpJIQHVS/gOs6EWMQP2RYBwjFLNT322Ji8TOC3IMPfsYCedNpzKfA==}
+ engines: {node: '>= 18'}
+
+ braces@3.0.3:
+ resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
+ engines: {node: '>=8'}
+
+ browserslist@4.26.3:
+ resolution: {integrity: sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+
+ buffer-from@1.1.2:
+ resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
+
+ bytes-iec@3.1.1:
+ resolution: {integrity: sha512-fey6+4jDK7TFtFg/klGSvNKJctyU7n2aQdnM+CO0ruLPbqqMOM8Tio0Pc+deqUeVKX1tL5DQep1zQ7+37aTAsA==}
+ engines: {node: '>= 0.8'}
+
+ cac@6.7.14:
+ resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
+ engines: {node: '>=8'}
+
+ call-bind-apply-helpers@1.0.2:
+ resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
+ engines: {node: '>= 0.4'}
+
+ call-bind@1.0.8:
+ resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==}
+ engines: {node: '>= 0.4'}
+
+ call-bound@1.0.4:
+ resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
+ engines: {node: '>= 0.4'}
+
+ caniuse-lite@1.0.30001751:
+ resolution: {integrity: sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==}
+
+ chai@5.3.3:
+ resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==}
+ engines: {node: '>=18'}
+
+ chalk@3.0.0:
+ resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==}
+ engines: {node: '>=8'}
+
+ chalk@4.1.2:
+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+ engines: {node: '>=10'}
+
+ chardet@2.1.0:
+ resolution: {integrity: sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==}
+
+ check-error@2.1.1:
+ resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==}
+ engines: {node: '>= 16'}
+
+ chokidar@3.6.0:
+ resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
+ engines: {node: '>= 8.10.0'}
+
+ ci-info@3.9.0:
+ resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==}
+ engines: {node: '>=8'}
+
+ ci-info@4.3.1:
+ resolution: {integrity: sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==}
+ engines: {node: '>=8'}
+
+ color-convert@2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+
+ color-name@1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+
+ combined-stream@1.0.8:
+ resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
+ engines: {node: '>= 0.8'}
+
+ commander@2.20.3:
+ resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
+
+ convert-source-map@2.0.0:
+ resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+
+ create-require@1.1.1:
+ resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
+
+ cross-spawn@7.0.6:
+ resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
+ engines: {node: '>= 8'}
+
+ css.escape@1.5.1:
+ resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==}
+
+ cssstyle@3.0.0:
+ resolution: {integrity: sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==}
+ engines: {node: '>=14'}
+
+ csstype@3.1.3:
+ resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
+
+ data-urls@4.0.0:
+ resolution: {integrity: sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==}
+ engines: {node: '>=14'}
+
+ debug@4.4.3:
+ resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ decimal.js@10.6.0:
+ resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==}
+
+ deep-eql@5.0.2:
+ resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==}
+ engines: {node: '>=6'}
+
+ deep-equal@2.2.3:
+ resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==}
+ engines: {node: '>= 0.4'}
+
+ define-data-property@1.1.4:
+ resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
+ engines: {node: '>= 0.4'}
+
+ define-properties@1.2.1:
+ resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
+ engines: {node: '>= 0.4'}
+
+ defu@6.1.4:
+ resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
+
+ delayed-stream@1.0.0:
+ resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
+ engines: {node: '>=0.4.0'}
+
+ detect-indent@6.1.0:
+ resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
+ engines: {node: '>=8'}
+
+ diff@4.0.2:
+ resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
+ engines: {node: '>=0.3.1'}
+
+ dir-glob@3.0.1:
+ resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
+ engines: {node: '>=8'}
+
+ dom-accessibility-api@0.5.16:
+ resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==}
+
+ domexception@4.0.0:
+ resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==}
+ engines: {node: '>=12'}
+ deprecated: Use your platform's native DOMException instead
+
+ dts-resolver@2.1.3:
+ resolution: {integrity: sha512-bihc7jPC90VrosXNzK0LTE2cuLP6jr0Ro8jk+kMugHReJVLIpHz/xadeq3MhuwyO4TD4OA3L1Q8pBBFRc08Tsw==}
+ engines: {node: '>=20.19.0'}
+ peerDependencies:
+ oxc-resolver: '>=11.0.0'
+ peerDependenciesMeta:
+ oxc-resolver:
+ optional: true
+
+ dunder-proto@1.0.1:
+ resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
+ engines: {node: '>= 0.4'}
+
+ eastasianwidth@0.2.0:
+ resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+
+ electron-to-chromium@1.5.237:
+ resolution: {integrity: sha512-icUt1NvfhGLar5lSWH3tHNzablaA5js3HVHacQimfP8ViEBOQv+L7DKEuHdbTZ0SKCO1ogTJTIL1Gwk9S6Qvcg==}
+
+ emoji-regex@8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+
+ emoji-regex@9.2.2:
+ resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+
+ empathic@2.0.0:
+ resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==}
+ engines: {node: '>=14'}
+
+ enquirer@2.4.1:
+ resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==}
+ engines: {node: '>=8.6'}
+
+ entities@6.0.1:
+ resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==}
+ engines: {node: '>=0.12'}
+
+ es-define-property@1.0.1:
+ resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
+ engines: {node: '>= 0.4'}
+
+ es-errors@1.3.0:
+ resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
+ engines: {node: '>= 0.4'}
+
+ es-get-iterator@1.1.3:
+ resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==}
+
+ es-module-lexer@1.7.0:
+ resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
+
+ es-object-atoms@1.1.1:
+ resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
+ engines: {node: '>= 0.4'}
+
+ es-set-tostringtag@2.1.0:
+ resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
+ engines: {node: '>= 0.4'}
+
+ esbuild@0.25.11:
+ resolution: {integrity: sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==}
+ engines: {node: '>=18'}
+ hasBin: true
+
+ escalade@3.2.0:
+ resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
+ engines: {node: '>=6'}
+
+ escape-string-regexp@2.0.0:
+ resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==}
+ engines: {node: '>=8'}
+
+ escodegen@2.1.0:
+ resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==}
+ engines: {node: '>=6.0'}
+ hasBin: true
+
+ esprima@4.0.1:
+ resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
+ engines: {node: '>=4'}
+ hasBin: true
+
+ estraverse@5.3.0:
+ resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
+ engines: {node: '>=4.0'}
+
+ estree-walker@3.0.3:
+ resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
+
+ esutils@2.0.3:
+ resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
+ engines: {node: '>=0.10.0'}
+
+ expect-type@1.2.2:
+ resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==}
+ engines: {node: '>=12.0.0'}
+
+ expect@30.2.0:
+ resolution: {integrity: sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ extendable-error@0.1.7:
+ resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==}
+
+ fast-glob@3.3.3:
+ resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
+ engines: {node: '>=8.6.0'}
+
+ fastq@1.19.1:
+ resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==}
+
+ fdir@6.5.0:
+ resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
+ engines: {node: '>=12.0.0'}
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+
+ fill-range@7.1.1:
+ resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
+ engines: {node: '>=8'}
+
+ find-up@4.1.0:
+ resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
+ engines: {node: '>=8'}
+
+ for-each@0.3.5:
+ resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
+ engines: {node: '>= 0.4'}
+
+ foreground-child@3.3.1:
+ resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
+ engines: {node: '>=14'}
+
+ form-data@4.0.4:
+ resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==}
+ engines: {node: '>= 6'}
+
+ fs-extra@7.0.1:
+ resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==}
+ engines: {node: '>=6 <7 || >=8'}
+
+ fs-extra@8.1.0:
+ resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==}
+ engines: {node: '>=6 <7 || >=8'}
+
+ fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+
+ function-bind@1.1.2:
+ resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+
+ functions-have-names@1.2.3:
+ resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
+
+ gensync@1.0.0-beta.2:
+ resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+ engines: {node: '>=6.9.0'}
+
+ get-intrinsic@1.3.0:
+ resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
+ engines: {node: '>= 0.4'}
+
+ get-proto@1.0.1:
+ resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
+ engines: {node: '>= 0.4'}
+
+ get-tsconfig@4.13.0:
+ resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==}
+
+ glob-parent@5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+
+ glob@10.4.5:
+ resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
+ hasBin: true
+
+ globby@11.1.0:
+ resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
+ engines: {node: '>=10'}
+
+ gopd@1.2.0:
+ resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
+ engines: {node: '>= 0.4'}
+
+ graceful-fs@4.2.11:
+ resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+
+ has-bigints@1.1.0:
+ resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==}
+ engines: {node: '>= 0.4'}
+
+ has-flag@4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+
+ has-property-descriptors@1.0.2:
+ resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
+
+ has-symbols@1.1.0:
+ resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
+ engines: {node: '>= 0.4'}
+
+ has-tostringtag@1.0.2:
+ resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
+ engines: {node: '>= 0.4'}
+
+ hasown@2.0.2:
+ resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
+ engines: {node: '>= 0.4'}
+
+ hookable@5.5.3:
+ resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
+
+ html-encoding-sniffer@3.0.0:
+ resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==}
+ engines: {node: '>=12'}
+
+ html-escaper@2.0.2:
+ resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
+
+ http-proxy-agent@5.0.0:
+ resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==}
+ engines: {node: '>= 6'}
+
+ https-proxy-agent@5.0.1:
+ resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
+ engines: {node: '>= 6'}
+
+ human-id@4.1.2:
+ resolution: {integrity: sha512-v/J+4Z/1eIJovEBdlV5TYj1IR+ZiohcYGRY+qN/oC9dAfKzVT023N/Bgw37hrKCoVRBvk3bqyzpr2PP5YeTMSg==}
+ hasBin: true
+
+ iconv-lite@0.6.3:
+ resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
+ engines: {node: '>=0.10.0'}
+
+ iconv-lite@0.7.0:
+ resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==}
+ engines: {node: '>=0.10.0'}
+
+ ignore@5.3.2:
+ resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
+ engines: {node: '>= 4'}
+
+ import-without-cache@0.2.3:
+ resolution: {integrity: sha512-roCvX171VqJ7+7pQt1kSRfwaJvFAC2zhThJWXal1rN8EqzPS3iapkAoNpHh4lM8Na1BDen+n9rVfo73RN+Y87g==}
+ engines: {node: '>=20.19.0'}
+
+ indent-string@4.0.0:
+ resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
+ engines: {node: '>=8'}
+
+ internal-slot@1.1.0:
+ resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
+ engines: {node: '>= 0.4'}
+
+ is-arguments@1.2.0:
+ resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==}
+ engines: {node: '>= 0.4'}
+
+ is-array-buffer@3.0.5:
+ resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==}
+ engines: {node: '>= 0.4'}
+
+ is-bigint@1.1.0:
+ resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==}
+ engines: {node: '>= 0.4'}
+
+ is-binary-path@2.1.0:
+ resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
+ engines: {node: '>=8'}
+
+ is-boolean-object@1.2.2:
+ resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==}
+ engines: {node: '>= 0.4'}
+
+ is-callable@1.2.7:
+ resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
+ engines: {node: '>= 0.4'}
+
+ is-date-object@1.1.0:
+ resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==}
+ engines: {node: '>= 0.4'}
+
+ is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+
+ is-fullwidth-code-point@3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+
+ is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+
+ is-map@2.0.3:
+ resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==}
+ engines: {node: '>= 0.4'}
+
+ is-number-object@1.1.1:
+ resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==}
+ engines: {node: '>= 0.4'}
+
+ is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+
+ is-potential-custom-element-name@1.0.1:
+ resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
+
+ is-regex@1.2.1:
+ resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==}
+ engines: {node: '>= 0.4'}
+
+ is-set@2.0.3:
+ resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==}
+ engines: {node: '>= 0.4'}
+
+ is-shared-array-buffer@1.0.4:
+ resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==}
+ engines: {node: '>= 0.4'}
+
+ is-string@1.1.1:
+ resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==}
+ engines: {node: '>= 0.4'}
+
+ is-subdir@1.2.0:
+ resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==}
+ engines: {node: '>=4'}
+
+ is-symbol@1.1.1:
+ resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==}
+ engines: {node: '>= 0.4'}
+
+ is-weakmap@2.0.2:
+ resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==}
+ engines: {node: '>= 0.4'}
+
+ is-weakset@2.0.4:
+ resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
+ engines: {node: '>= 0.4'}
+
+ is-windows@1.0.2:
+ resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==}
+ engines: {node: '>=0.10.0'}
+
+ isarray@2.0.5:
+ resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
+
+ isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+
+ istanbul-lib-coverage@3.2.2:
+ resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==}
+ engines: {node: '>=8'}
+
+ istanbul-lib-instrument@6.0.3:
+ resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==}
+ engines: {node: '>=10'}
+
+ istanbul-lib-report@3.0.1:
+ resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==}
+ engines: {node: '>=10'}
+
+ istanbul-lib-source-maps@5.0.6:
+ resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==}
+ engines: {node: '>=10'}
+
+ istanbul-reports@3.2.0:
+ resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==}
+ engines: {node: '>=8'}
+
+ jackspeak@3.4.3:
+ resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
+
+ jest-diff@30.2.0:
+ resolution: {integrity: sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-matcher-utils@30.2.0:
+ resolution: {integrity: sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-message-util@30.2.0:
+ resolution: {integrity: sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-mock@30.2.0:
+ resolution: {integrity: sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-regex-util@30.0.1:
+ resolution: {integrity: sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-util@30.2.0:
+ resolution: {integrity: sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ js-tokens@4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+ js-tokens@9.0.1:
+ resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==}
+
+ js-yaml@3.14.1:
+ resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
+ hasBin: true
+
+ jsdom@21.1.2:
+ resolution: {integrity: sha512-sCpFmK2jv+1sjff4u7fzft+pUh2KSUbUrEHYHyfSIbGTIcmnjyp83qg6qLwdJ/I3LpTXx33ACxeRL7Lsyc6lGQ==}
+ engines: {node: '>=14'}
+ peerDependencies:
+ canvas: ^2.5.0
+ peerDependenciesMeta:
+ canvas:
+ optional: true
+
+ jsesc@3.1.0:
+ resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
+ engines: {node: '>=6'}
+ hasBin: true
+
+ json5@2.2.3:
+ resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+ engines: {node: '>=6'}
+ hasBin: true
+
+ jsonfile@4.0.0:
+ resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==}
+
+ lilconfig@2.1.0:
+ resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==}
+ engines: {node: '>=10'}
+
+ locate-path@5.0.0:
+ resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
+ engines: {node: '>=8'}
+
+ lodash.startcase@4.4.0:
+ resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==}
+
+ lodash@4.17.21:
+ resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+
+ loose-envify@1.4.0:
+ resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+ hasBin: true
+
+ loupe@3.2.1:
+ resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==}
+
+ lru-cache@10.4.3:
+ resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
+
+ lru-cache@5.1.1:
+ resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+
+ lru-cache@6.0.0:
+ resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
+ engines: {node: '>=10'}
+
+ lz-string@1.5.0:
+ resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==}
+ hasBin: true
+
+ magic-string@0.30.19:
+ resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==}
+
+ magic-string@0.30.21:
+ resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
+
+ magicast@0.3.5:
+ resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==}
+
+ make-dir@4.0.0:
+ resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
+ engines: {node: '>=10'}
+
+ make-error@1.3.6:
+ resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
+
+ math-intrinsics@1.1.0:
+ resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
+ engines: {node: '>= 0.4'}
+
+ merge2@1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+
+ micromatch@4.0.8:
+ resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
+ engines: {node: '>=8.6'}
+
+ mime-db@1.52.0:
+ resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+ engines: {node: '>= 0.6'}
+
+ mime-types@2.1.35:
+ resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+ engines: {node: '>= 0.6'}
+
+ min-indent@1.0.1:
+ resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
+ engines: {node: '>=4'}
+
+ minimatch@9.0.5:
+ resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
+ minipass@7.1.2:
+ resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
+ mri@1.2.0:
+ resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
+ engines: {node: '>=4'}
+
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+ nanoid@3.3.11:
+ resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ nanoid@5.1.6:
+ resolution: {integrity: sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==}
+ engines: {node: ^18 || >=20}
+ hasBin: true
+
+ nanospinner@1.2.2:
+ resolution: {integrity: sha512-Zt/AmG6qRU3e+WnzGGLuMCEAO/dAu45stNbHY223tUxldaDAeE+FxSPsd9Q+j+paejmm0ZbrNVs5Sraqy3dRxA==}
+
+ node-releases@2.0.25:
+ resolution: {integrity: sha512-4auku8B/vw5psvTiiN9j1dAOsXvMoGqJuKJcR+dTdqiXEK20mMTk1UEo3HS16LeGQsVG6+qKTPM9u/qQ2LqATA==}
+
+ normalize-path@3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+
+ nwsapi@2.2.22:
+ resolution: {integrity: sha512-ujSMe1OWVn55euT1ihwCI1ZcAaAU3nxUiDwfDQldc51ZXaB9m2AyOn6/jh1BLe2t/G8xd6uKG1UBF2aZJeg2SQ==}
+
+ object-inspect@1.13.4:
+ resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
+ engines: {node: '>= 0.4'}
+
+ object-is@1.1.6:
+ resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==}
+ engines: {node: '>= 0.4'}
+
+ object-keys@1.1.1:
+ resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
+ engines: {node: '>= 0.4'}
+
+ object.assign@4.1.7:
+ resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==}
+ engines: {node: '>= 0.4'}
+
+ obug@2.1.1:
+ resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==}
+
+ outdent@0.5.0:
+ resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==}
+
+ p-filter@2.1.0:
+ resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==}
+ engines: {node: '>=8'}
+
+ p-limit@2.3.0:
+ resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
+ engines: {node: '>=6'}
+
+ p-locate@4.1.0:
+ resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
+ engines: {node: '>=8'}
+
+ p-map@2.1.0:
+ resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==}
+ engines: {node: '>=6'}
+
+ p-try@2.2.0:
+ resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
+ engines: {node: '>=6'}
+
+ package-json-from-dist@1.0.1:
+ resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
+
+ package-manager-detector@0.2.11:
+ resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==}
+
+ parse5@7.3.0:
+ resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==}
+
+ path-exists@4.0.0:
+ resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+ engines: {node: '>=8'}
+
+ path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+
+ path-scurry@1.11.1:
+ resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
+ engines: {node: '>=16 || 14 >=14.18'}
+
+ path-type@4.0.0:
+ resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
+ engines: {node: '>=8'}
+
+ pathe@2.0.3:
+ resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
+
+ pathval@2.0.1:
+ resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==}
+ engines: {node: '>= 14.16'}
+
+ picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+ picomatch@2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+
+ picomatch@4.0.3:
+ resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
+ engines: {node: '>=12'}
+
+ pify@4.0.1:
+ resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
+ engines: {node: '>=6'}
+
+ possible-typed-array-names@1.1.0:
+ resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
+ engines: {node: '>= 0.4'}
+
+ postcss@8.5.6:
+ resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
+ engines: {node: ^10 || ^12 || >=14}
+
+ prettier@2.8.8:
+ resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==}
+ engines: {node: '>=10.13.0'}
+ hasBin: true
+
+ pretty-format@27.5.1:
+ resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==}
+ engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
+
+ pretty-format@30.2.0:
+ resolution: {integrity: sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ punycode@2.3.1:
+ resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+ engines: {node: '>=6'}
+
+ quansync@0.2.11:
+ resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==}
+
+ quansync@1.0.0:
+ resolution: {integrity: sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==}
+
+ queue-microtask@1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+
+ react-dom@18.3.1:
+ resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
+ peerDependencies:
+ react: ^18.3.1
+
+ react-is@17.0.2:
+ resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
+
+ react-is@18.3.1:
+ resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
+
+ react-refresh@0.17.0:
+ resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==}
+ engines: {node: '>=0.10.0'}
+
+ react@18.3.1:
+ resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
+ engines: {node: '>=0.10.0'}
+
+ read-yaml-file@1.1.0:
+ resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==}
+ engines: {node: '>=6'}
+
+ readdirp@3.6.0:
+ resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
+ engines: {node: '>=8.10.0'}
+
+ redent@3.0.0:
+ resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
+ engines: {node: '>=8'}
+
+ regexp.prototype.flags@1.5.4:
+ resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
+ engines: {node: '>= 0.4'}
+
+ resolve-from@5.0.0:
+ resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
+ engines: {node: '>=8'}
+
+ resolve-pkg-maps@1.0.0:
+ resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
+
+ reusify@1.1.0:
+ resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+
+ rolldown-plugin-dts@0.18.3:
+ resolution: {integrity: sha512-rd1LZ0Awwfyn89UndUF/HoFF4oH9a5j+2ZeuKSJYM80vmeN/p0gslYMnHTQHBEXPhUlvAlqGA3tVgXB/1qFNDg==}
+ engines: {node: '>=20.19.0'}
+ peerDependencies:
+ '@ts-macro/tsc': ^0.3.6
+ '@typescript/native-preview': '>=7.0.0-dev.20250601.1'
+ rolldown: ^1.0.0-beta.51
+ typescript: ^5.0.0
+ vue-tsc: ~3.1.0
+ peerDependenciesMeta:
+ '@ts-macro/tsc':
+ optional: true
+ '@typescript/native-preview':
+ optional: true
+ typescript:
+ optional: true
+ vue-tsc:
+ optional: true
+
+ rolldown@1.0.0-beta.53:
+ resolution: {integrity: sha512-Qd9c2p0XKZdgT5AYd+KgAMggJ8ZmCs3JnS9PTMWkyUfteKlfmKtxJbWTHkVakxwXs1Ub7jrRYVeFeF7N0sQxyw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ hasBin: true
+
+ rollup@4.52.5:
+ resolution: {integrity: sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+
+ rrweb-cssom@0.6.0:
+ resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==}
+
+ run-parallel@1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+
+ safe-regex-test@1.1.0:
+ resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
+ engines: {node: '>= 0.4'}
+
+ safer-buffer@2.1.2:
+ resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+
+ saxes@6.0.0:
+ resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
+ engines: {node: '>=v12.22.7'}
+
+ scheduler@0.23.2:
+ resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
+
+ semver@6.3.1:
+ resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+ hasBin: true
+
+ semver@7.5.3:
+ resolution: {integrity: sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ semver@7.7.3:
+ resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ set-function-length@1.2.2:
+ resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
+ engines: {node: '>= 0.4'}
+
+ set-function-name@2.0.2:
+ resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==}
+ engines: {node: '>= 0.4'}
+
+ shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+
+ shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+
+ side-channel-list@1.0.0:
+ resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
+ engines: {node: '>= 0.4'}
+
+ side-channel-map@1.0.1:
+ resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
+ engines: {node: '>= 0.4'}
+
+ side-channel-weakmap@1.0.2:
+ resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
+ engines: {node: '>= 0.4'}
+
+ side-channel@1.1.0:
+ resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
+ engines: {node: '>= 0.4'}
+
+ siginfo@2.0.0:
+ resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
+
+ signal-exit@4.1.0:
+ resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
+ engines: {node: '>=14'}
+
+ size-limit@8.2.6:
+ resolution: {integrity: sha512-zpznim/tX/NegjoQuRKgWTF4XiB0cn2qt90uJzxYNTFAqexk4b94DOAkBD3TwhC6c3kw2r0KcnA5upziVMZqDg==}
+ engines: {node: ^14.0.0 || ^16.0.0 || >=18.0.0}
+ hasBin: true
+
+ slash@3.0.0:
+ resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
+ engines: {node: '>=8'}
+
+ source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+
+ source-map-support@0.5.21:
+ resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
+
+ source-map@0.6.1:
+ resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+ engines: {node: '>=0.10.0'}
+
+ spawndamnit@3.0.1:
+ resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==}
+
+ sprintf-js@1.0.3:
+ resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
+
+ stack-utils@2.0.6:
+ resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==}
+ engines: {node: '>=10'}
+
+ stackback@0.0.2:
+ resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
+
+ std-env@3.10.0:
+ resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
+
+ stop-iteration-iterator@1.1.0:
+ resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
+ engines: {node: '>= 0.4'}
+
+ string-width@4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+
+ string-width@5.1.2:
+ resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
+ engines: {node: '>=12'}
+
+ strip-ansi@6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
+
+ strip-ansi@7.1.2:
+ resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==}
+ engines: {node: '>=12'}
+
+ strip-bom@3.0.0:
+ resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
+ engines: {node: '>=4'}
+
+ strip-indent@3.0.0:
+ resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
+ engines: {node: '>=8'}
+
+ strip-literal@3.1.0:
+ resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==}
+
+ supports-color@7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
+
+ symbol-tree@3.2.4:
+ resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
+
+ term-size@2.2.1:
+ resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==}
+ engines: {node: '>=8'}
+
+ terser@5.44.0:
+ resolution: {integrity: sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ test-exclude@7.0.1:
+ resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==}
+ engines: {node: '>=18'}
+
+ tinybench@2.9.0:
+ resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
+
+ tinyexec@0.3.2:
+ resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
+
+ tinyexec@1.0.2:
+ resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==}
+ engines: {node: '>=18'}
+
+ tinyglobby@0.2.15:
+ resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
+ engines: {node: '>=12.0.0'}
+
+ tinypool@1.1.1:
+ resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+
+ tinyrainbow@2.0.0:
+ resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==}
+ engines: {node: '>=14.0.0'}
+
+ tinyspy@4.0.4:
+ resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==}
+ engines: {node: '>=14.0.0'}
+
+ tldts-core@7.0.17:
+ resolution: {integrity: sha512-DieYoGrP78PWKsrXr8MZwtQ7GLCUeLxihtjC1jZsW1DnvSMdKPitJSe8OSYDM2u5H6g3kWJZpePqkp43TfLh0g==}
+
+ tldts@7.0.17:
+ resolution: {integrity: sha512-Y1KQBgDd/NUc+LfOtKS6mNsC9CCaH+m2P1RoIZy7RAPo3C3/t8X45+zgut31cRZtZ3xKPjfn3TkGTrctC2TQIQ==}
+ hasBin: true
+
+ to-regex-range@5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+
+ tough-cookie@6.0.0:
+ resolution: {integrity: sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==}
+ engines: {node: '>=16'}
+
+ tr46@4.1.1:
+ resolution: {integrity: sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==}
+ engines: {node: '>=14'}
+
+ tree-kill@1.2.2:
+ resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
+ hasBin: true
+
+ ts-node@10.9.2:
+ resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==}
+ hasBin: true
+ peerDependencies:
+ '@swc/core': '>=1.2.50'
+ '@swc/wasm': '>=1.2.50'
+ '@types/node': '*'
+ typescript: '>=2.7'
+ peerDependenciesMeta:
+ '@swc/core':
+ optional: true
+ '@swc/wasm':
+ optional: true
+
+ tsdown@0.17.3:
+ resolution: {integrity: sha512-bgLgTog+oyadDTr9SZ57jZtb+A4aglCjo3xgJrkCDxbzcQl2l2iDDr4b06XHSQHwyDNIhYFDgPRhuu1wL3pNsw==}
+ engines: {node: '>=20.19.0'}
+ hasBin: true
+ peerDependencies:
+ '@arethetypeswrong/core': ^0.18.1
+ '@vitejs/devtools': ^0.0.0-alpha.19
+ publint: ^0.3.0
+ typescript: ^5.0.0
+ unplugin-lightningcss: ^0.4.0
+ unplugin-unused: ^0.5.0
+ peerDependenciesMeta:
+ '@arethetypeswrong/core':
+ optional: true
+ '@vitejs/devtools':
+ optional: true
+ publint:
+ optional: true
+ typescript:
+ optional: true
+ unplugin-lightningcss:
+ optional: true
+ unplugin-unused:
+ optional: true
+
+ tslib@2.8.1:
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+
+ typescript@5.9.3:
+ resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+
+ unconfig-core@7.4.2:
+ resolution: {integrity: sha512-VgPCvLWugINbXvMQDf8Jh0mlbvNjNC6eSUziHsBCMpxR05OPrNrvDnyatdMjRgcHaaNsCqz+wjNXxNw1kRLHUg==}
+
+ undici-types@6.21.0:
+ resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
+
+ universalify@0.1.2:
+ resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
+ engines: {node: '>= 4.0.0'}
+
+ unrun@0.2.19:
+ resolution: {integrity: sha512-DbwbJ9BvPEb3BeZnIpP9S5tGLO/JIgPQ3JrpMRFIfZMZfMG19f26OlLbC2ml8RRdrI2ZA7z2t+at5tsIHbh6Qw==}
+ engines: {node: '>=20.19.0'}
+ hasBin: true
+ peerDependencies:
+ synckit: ^0.11.11
+ peerDependenciesMeta:
+ synckit:
+ optional: true
+
+ update-browserslist-db@1.1.3:
+ resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+
+ v8-compile-cache-lib@3.0.1:
+ resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
+
+ vite-node@3.2.4:
+ resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+ hasBin: true
+
+ vite@7.1.11:
+ resolution: {integrity: sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^20.19.0 || >=22.12.0
+ jiti: '>=1.21.0'
+ less: ^4.0.0
+ lightningcss: ^1.21.0
+ sass: ^1.70.0
+ sass-embedded: ^1.70.0
+ stylus: '>=0.54.8'
+ sugarss: ^5.0.0
+ terser: ^5.16.0
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ jiti:
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+
+ vitest@3.2.4:
+ resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+ hasBin: true
+ peerDependencies:
+ '@edge-runtime/vm': '*'
+ '@types/debug': ^4.1.12
+ '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
+ '@vitest/browser': 3.2.4
+ '@vitest/ui': 3.2.4
+ happy-dom: '*'
+ jsdom: '*'
+ peerDependenciesMeta:
+ '@edge-runtime/vm':
+ optional: true
+ '@types/debug':
+ optional: true
+ '@types/node':
+ optional: true
+ '@vitest/browser':
+ optional: true
+ '@vitest/ui':
+ optional: true
+ happy-dom:
+ optional: true
+ jsdom:
+ optional: true
+
+ w3c-xmlserializer@4.0.0:
+ resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==}
+ engines: {node: '>=14'}
+
+ webidl-conversions@7.0.0:
+ resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
+ engines: {node: '>=12'}
+
+ whatwg-encoding@2.0.0:
+ resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==}
+ engines: {node: '>=12'}
+
+ whatwg-mimetype@3.0.0:
+ resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==}
+ engines: {node: '>=12'}
+
+ whatwg-url@12.0.1:
+ resolution: {integrity: sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==}
+ engines: {node: '>=14'}
+
+ which-boxed-primitive@1.1.1:
+ resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
+ engines: {node: '>= 0.4'}
+
+ which-collection@1.0.2:
+ resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==}
+ engines: {node: '>= 0.4'}
+
+ which-typed-array@1.1.19:
+ resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==}
+ engines: {node: '>= 0.4'}
+
+ which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
-dependencies:
- react:
- specifier: ^18.2.0
- version: 18.2.0
-
-devDependencies:
- '@changesets/cli':
- specifier: ^2.26.1
- version: 2.26.1
- '@size-limit/preset-small-lib':
- specifier: ^8.2.4
- version: 8.2.4(size-limit@8.2.4)
- '@testing-library/jest-dom':
- specifier: ^5.16.5
- version: 5.16.5
- '@testing-library/react':
- specifier: ^14.0.0
- version: 14.0.0(react-dom@18.2.0)(react@18.2.0)
- '@types/node':
- specifier: ^18.15.13
- version: 18.15.13
- '@types/react':
- specifier: ^18.0.38
- version: 18.0.38
- '@types/react-dom':
- specifier: ^18.0.11
- version: 18.0.11
- '@types/testing-library__jest-dom':
- specifier: ^5.14.5
- version: 5.14.5
- '@vitejs/plugin-react':
- specifier: ^4.3.1
- version: 4.3.1(vite@5.3.3)
- '@vitest/coverage-istanbul':
- specifier: ^2.0.3
- version: 2.0.3(vitest@2.0.3)
- jsdom:
- specifier: ^21.1.1
- version: 21.1.1
- prettier:
- specifier: ^2.8.7
- version: 2.8.7
- react-dom:
- specifier: ^18.2.0
- version: 18.2.0(react@18.2.0)
- size-limit:
- specifier: ^8.2.4
- version: 8.2.4
- terser:
- specifier: ^5.17.1
- version: 5.17.1
- ts-node:
- specifier: ^10.9.1
- version: 10.9.1(@types/node@18.15.13)(typescript@5.0.4)
- tsup:
- specifier: ^6.7.0
- version: 6.7.0(ts-node@10.9.1)(typescript@5.0.4)
- typescript:
- specifier: ^5.0.4
- version: 5.0.4
- vite:
- specifier: 5.3.3
- version: 5.3.3(@types/node@18.15.13)(terser@5.17.1)
- vitest:
- specifier: ^2.0.3
- version: 2.0.3(@types/node@18.15.13)(jsdom@21.1.1)(terser@5.17.1)
+ why-is-node-running@2.3.0:
+ resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
+ engines: {node: '>=8'}
+ hasBin: true
-packages:
+ wrap-ansi@7.0.0:
+ resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+ engines: {node: '>=10'}
- /@adobe/css-tools@4.4.0:
- resolution: {integrity: sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==}
- dev: true
+ wrap-ansi@8.1.0:
+ resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
+ engines: {node: '>=12'}
- /@ampproject/remapping@2.3.0:
- resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
- engines: {node: '>=6.0.0'}
- dependencies:
- '@jridgewell/gen-mapping': 0.3.5
- '@jridgewell/trace-mapping': 0.3.25
- dev: true
+ ws@8.18.3:
+ resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==}
+ engines: {node: '>=10.0.0'}
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: '>=5.0.2'
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
- /@babel/code-frame@7.21.4:
- resolution: {integrity: sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==}
- engines: {node: '>=6.9.0'}
- dependencies:
- '@babel/highlight': 7.18.6
- dev: true
+ xml-name-validator@4.0.0:
+ resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==}
+ engines: {node: '>=12'}
- /@babel/code-frame@7.24.7:
- resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==}
- engines: {node: '>=6.9.0'}
- dependencies:
- '@babel/highlight': 7.24.7
- picocolors: 1.0.1
- dev: true
+ xmlchars@2.2.0:
+ resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
- /@babel/compat-data@7.24.9:
- resolution: {integrity: sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==}
- engines: {node: '>=6.9.0'}
- dev: true
+ yallist@3.1.1:
+ resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
- /@babel/core@7.24.9:
- resolution: {integrity: sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==}
- engines: {node: '>=6.9.0'}
+ yallist@4.0.0:
+ resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
+
+ yn@3.1.1:
+ resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==}
+ engines: {node: '>=6'}
+
+snapshots:
+
+ '@adobe/css-tools@4.4.4': {}
+
+ '@babel/code-frame@7.27.1':
dependencies:
- '@ampproject/remapping': 2.3.0
- '@babel/code-frame': 7.24.7
- '@babel/generator': 7.24.9
- '@babel/helper-compilation-targets': 7.24.8
- '@babel/helper-module-transforms': 7.24.9(@babel/core@7.24.9)
- '@babel/helpers': 7.24.8
- '@babel/parser': 7.24.8
- '@babel/template': 7.24.7
- '@babel/traverse': 7.24.8
- '@babel/types': 7.24.9
+ '@babel/helper-validator-identifier': 7.27.1
+ js-tokens: 4.0.0
+ picocolors: 1.1.1
+
+ '@babel/compat-data@7.28.4': {}
+
+ '@babel/core@7.28.4':
+ dependencies:
+ '@babel/code-frame': 7.27.1
+ '@babel/generator': 7.28.3
+ '@babel/helper-compilation-targets': 7.27.2
+ '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4)
+ '@babel/helpers': 7.28.4
+ '@babel/parser': 7.28.4
+ '@babel/template': 7.27.2
+ '@babel/traverse': 7.28.4
+ '@babel/types': 7.28.4
+ '@jridgewell/remapping': 2.3.5
convert-source-map: 2.0.0
- debug: 4.3.5
+ debug: 4.4.3
gensync: 1.0.0-beta.2
json5: 2.2.3
semver: 6.3.1
transitivePeerDependencies:
- supports-color
- dev: true
-
- /@babel/generator@7.24.9:
- resolution: {integrity: sha512-G8v3jRg+z8IwY1jHFxvCNhOPYPterE4XljNgdGTYfSTtzzwjIswIzIaSPSLs3R7yFuqnqNeay5rjICfqVr+/6A==}
- engines: {node: '>=6.9.0'}
- dependencies:
- '@babel/types': 7.24.9
- '@jridgewell/gen-mapping': 0.3.5
- '@jridgewell/trace-mapping': 0.3.25
- jsesc: 2.5.2
- dev: true
-
- /@babel/helper-compilation-targets@7.24.8:
- resolution: {integrity: sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==}
- engines: {node: '>=6.9.0'}
- dependencies:
- '@babel/compat-data': 7.24.9
- '@babel/helper-validator-option': 7.24.8
- browserslist: 4.23.2
- lru-cache: 5.1.1
- semver: 6.3.1
- dev: true
- /@babel/helper-environment-visitor@7.24.7:
- resolution: {integrity: sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==}
- engines: {node: '>=6.9.0'}
+ '@babel/generator@7.28.3':
dependencies:
- '@babel/types': 7.24.9
- dev: true
+ '@babel/parser': 7.28.4
+ '@babel/types': 7.28.4
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+ jsesc: 3.1.0
- /@babel/helper-function-name@7.24.7:
- resolution: {integrity: sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==}
- engines: {node: '>=6.9.0'}
+ '@babel/generator@7.28.5':
dependencies:
- '@babel/template': 7.24.7
- '@babel/types': 7.24.9
- dev: true
+ '@babel/parser': 7.28.5
+ '@babel/types': 7.28.5
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+ jsesc: 3.1.0
- /@babel/helper-hoist-variables@7.24.7:
- resolution: {integrity: sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==}
- engines: {node: '>=6.9.0'}
+ '@babel/helper-compilation-targets@7.27.2':
dependencies:
- '@babel/types': 7.24.9
- dev: true
+ '@babel/compat-data': 7.28.4
+ '@babel/helper-validator-option': 7.27.1
+ browserslist: 4.26.3
+ lru-cache: 5.1.1
+ semver: 6.3.1
- /@babel/helper-module-imports@7.24.7:
- resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==}
- engines: {node: '>=6.9.0'}
- dependencies:
- '@babel/traverse': 7.24.8
- '@babel/types': 7.24.9
- transitivePeerDependencies:
- - supports-color
- dev: true
+ '@babel/helper-globals@7.28.0': {}
- /@babel/helper-module-transforms@7.24.9(@babel/core@7.24.9):
- resolution: {integrity: sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==}
- engines: {node: '>=6.9.0'}
- peerDependencies:
- '@babel/core': ^7.0.0
+ '@babel/helper-module-imports@7.27.1':
dependencies:
- '@babel/core': 7.24.9
- '@babel/helper-environment-visitor': 7.24.7
- '@babel/helper-module-imports': 7.24.7
- '@babel/helper-simple-access': 7.24.7
- '@babel/helper-split-export-declaration': 7.24.7
- '@babel/helper-validator-identifier': 7.24.7
+ '@babel/traverse': 7.28.4
+ '@babel/types': 7.28.4
transitivePeerDependencies:
- supports-color
- dev: true
-
- /@babel/helper-plugin-utils@7.24.8:
- resolution: {integrity: sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==}
- engines: {node: '>=6.9.0'}
- dev: true
- /@babel/helper-simple-access@7.24.7:
- resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==}
- engines: {node: '>=6.9.0'}
+ '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.4)':
dependencies:
- '@babel/traverse': 7.24.8
- '@babel/types': 7.24.9
+ '@babel/core': 7.28.4
+ '@babel/helper-module-imports': 7.27.1
+ '@babel/helper-validator-identifier': 7.27.1
+ '@babel/traverse': 7.28.4
transitivePeerDependencies:
- supports-color
- dev: true
-
- /@babel/helper-split-export-declaration@7.24.7:
- resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==}
- engines: {node: '>=6.9.0'}
- dependencies:
- '@babel/types': 7.24.9
- dev: true
- /@babel/helper-string-parser@7.19.4:
- resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==}
- engines: {node: '>=6.9.0'}
- dev: true
-
- /@babel/helper-string-parser@7.24.8:
- resolution: {integrity: sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==}
- engines: {node: '>=6.9.0'}
- dev: true
+ '@babel/helper-plugin-utils@7.27.1': {}
- /@babel/helper-validator-identifier@7.19.1:
- resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==}
- engines: {node: '>=6.9.0'}
- dev: true
+ '@babel/helper-string-parser@7.27.1': {}
- /@babel/helper-validator-identifier@7.24.7:
- resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==}
- engines: {node: '>=6.9.0'}
- dev: true
+ '@babel/helper-validator-identifier@7.27.1': {}
- /@babel/helper-validator-option@7.24.8:
- resolution: {integrity: sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==}
- engines: {node: '>=6.9.0'}
- dev: true
+ '@babel/helper-validator-identifier@7.28.5': {}
- /@babel/helpers@7.24.8:
- resolution: {integrity: sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==}
- engines: {node: '>=6.9.0'}
- dependencies:
- '@babel/template': 7.24.7
- '@babel/types': 7.24.9
- dev: true
+ '@babel/helper-validator-option@7.27.1': {}
- /@babel/highlight@7.18.6:
- resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==}
- engines: {node: '>=6.9.0'}
+ '@babel/helpers@7.28.4':
dependencies:
- '@babel/helper-validator-identifier': 7.19.1
- chalk: 2.4.2
- js-tokens: 4.0.0
- dev: true
+ '@babel/template': 7.27.2
+ '@babel/types': 7.28.4
- /@babel/highlight@7.24.7:
- resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==}
- engines: {node: '>=6.9.0'}
+ '@babel/parser@7.28.4':
dependencies:
- '@babel/helper-validator-identifier': 7.24.7
- chalk: 2.4.2
- js-tokens: 4.0.0
- picocolors: 1.0.1
- dev: true
+ '@babel/types': 7.28.4
- /@babel/parser@7.24.8:
- resolution: {integrity: sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==}
- engines: {node: '>=6.0.0'}
- hasBin: true
+ '@babel/parser@7.28.5':
dependencies:
- '@babel/types': 7.21.4
- dev: true
+ '@babel/types': 7.28.5
- /@babel/plugin-transform-react-jsx-self@7.24.7(@babel/core@7.24.9):
- resolution: {integrity: sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==}
- engines: {node: '>=6.9.0'}
- peerDependencies:
- '@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.4)':
dependencies:
- '@babel/core': 7.24.9
- '@babel/helper-plugin-utils': 7.24.8
- dev: true
+ '@babel/core': 7.28.4
+ '@babel/helper-plugin-utils': 7.27.1
- /@babel/plugin-transform-react-jsx-source@7.24.7(@babel/core@7.24.9):
- resolution: {integrity: sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==}
- engines: {node: '>=6.9.0'}
- peerDependencies:
- '@babel/core': ^7.0.0-0
+ '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.4)':
dependencies:
- '@babel/core': 7.24.9
- '@babel/helper-plugin-utils': 7.24.8
- dev: true
+ '@babel/core': 7.28.4
+ '@babel/helper-plugin-utils': 7.27.1
- /@babel/runtime@7.21.0:
- resolution: {integrity: sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==}
- engines: {node: '>=6.9.0'}
- dependencies:
- regenerator-runtime: 0.13.11
- dev: true
+ '@babel/runtime@7.28.4': {}
- /@babel/template@7.24.7:
- resolution: {integrity: sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==}
- engines: {node: '>=6.9.0'}
+ '@babel/template@7.27.2':
dependencies:
- '@babel/code-frame': 7.24.7
- '@babel/parser': 7.24.8
- '@babel/types': 7.24.9
- dev: true
+ '@babel/code-frame': 7.27.1
+ '@babel/parser': 7.28.4
+ '@babel/types': 7.28.4
- /@babel/traverse@7.24.8:
- resolution: {integrity: sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==}
- engines: {node: '>=6.9.0'}
+ '@babel/traverse@7.28.4':
dependencies:
- '@babel/code-frame': 7.24.7
- '@babel/generator': 7.24.9
- '@babel/helper-environment-visitor': 7.24.7
- '@babel/helper-function-name': 7.24.7
- '@babel/helper-hoist-variables': 7.24.7
- '@babel/helper-split-export-declaration': 7.24.7
- '@babel/parser': 7.24.8
- '@babel/types': 7.24.9
- debug: 4.3.5
- globals: 11.12.0
+ '@babel/code-frame': 7.27.1
+ '@babel/generator': 7.28.3
+ '@babel/helper-globals': 7.28.0
+ '@babel/parser': 7.28.4
+ '@babel/template': 7.27.2
+ '@babel/types': 7.28.4
+ debug: 4.4.3
transitivePeerDependencies:
- supports-color
- dev: true
- /@babel/types@7.21.4:
- resolution: {integrity: sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==}
- engines: {node: '>=6.9.0'}
+ '@babel/types@7.28.4':
dependencies:
- '@babel/helper-string-parser': 7.19.4
- '@babel/helper-validator-identifier': 7.19.1
- to-fast-properties: 2.0.0
- dev: true
+ '@babel/helper-string-parser': 7.27.1
+ '@babel/helper-validator-identifier': 7.27.1
- /@babel/types@7.24.9:
- resolution: {integrity: sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==}
- engines: {node: '>=6.9.0'}
+ '@babel/types@7.28.5':
dependencies:
- '@babel/helper-string-parser': 7.24.8
- '@babel/helper-validator-identifier': 7.24.7
- to-fast-properties: 2.0.0
- dev: true
+ '@babel/helper-string-parser': 7.27.1
+ '@babel/helper-validator-identifier': 7.28.5
- /@changesets/apply-release-plan@6.1.3:
- resolution: {integrity: sha512-ECDNeoc3nfeAe1jqJb5aFQX7CqzQhD2klXRez2JDb/aVpGUbX673HgKrnrgJRuQR/9f2TtLoYIzrGB9qwD77mg==}
+ '@changesets/apply-release-plan@7.0.13':
dependencies:
- '@babel/runtime': 7.21.0
- '@changesets/config': 2.3.0
- '@changesets/get-version-range-type': 0.3.2
- '@changesets/git': 2.0.0
- '@changesets/types': 5.2.1
+ '@changesets/config': 3.1.1
+ '@changesets/get-version-range-type': 0.4.0
+ '@changesets/git': 3.0.4
+ '@changesets/should-skip-package': 0.1.2
+ '@changesets/types': 6.1.0
'@manypkg/get-packages': 1.1.3
detect-indent: 6.1.0
fs-extra: 7.0.1
lodash.startcase: 4.4.0
outdent: 0.5.0
- prettier: 2.8.7
+ prettier: 2.8.8
resolve-from: 5.0.0
- semver: 7.6.2
- dev: true
+ semver: 7.7.3
- /@changesets/assemble-release-plan@5.2.3:
- resolution: {integrity: sha512-g7EVZCmnWz3zMBAdrcKhid4hkHT+Ft1n0mLussFMcB1dE2zCuwcvGoy9ec3yOgPGF4hoMtgHaMIk3T3TBdvU9g==}
+ '@changesets/assemble-release-plan@6.0.9':
dependencies:
- '@babel/runtime': 7.21.0
- '@changesets/errors': 0.1.4
- '@changesets/get-dependents-graph': 1.3.5
- '@changesets/types': 5.2.1
+ '@changesets/errors': 0.2.0
+ '@changesets/get-dependents-graph': 2.1.3
+ '@changesets/should-skip-package': 0.1.2
+ '@changesets/types': 6.1.0
'@manypkg/get-packages': 1.1.3
- semver: 7.6.2
- dev: true
-
- /@changesets/changelog-git@0.1.14:
- resolution: {integrity: sha512-+vRfnKtXVWsDDxGctOfzJsPhaCdXRYoe+KyWYoq5X/GqoISREiat0l3L8B0a453B2B4dfHGcZaGyowHbp9BSaA==}
- dependencies:
- '@changesets/types': 5.2.1
- dev: true
-
- /@changesets/cli@2.26.1:
- resolution: {integrity: sha512-XnTa+b51vt057fyAudvDKGB0Sh72xutQZNAdXkCqPBKO2zvs2yYZx5hFZj1u9cbtpwM6Sxtcr02/FQJfZOzemQ==}
- hasBin: true
- dependencies:
- '@babel/runtime': 7.21.0
- '@changesets/apply-release-plan': 6.1.3
- '@changesets/assemble-release-plan': 5.2.3
- '@changesets/changelog-git': 0.1.14
- '@changesets/config': 2.3.0
- '@changesets/errors': 0.1.4
- '@changesets/get-dependents-graph': 1.3.5
- '@changesets/get-release-plan': 3.0.16
- '@changesets/git': 2.0.0
- '@changesets/logger': 0.0.5
- '@changesets/pre': 1.0.14
- '@changesets/read': 0.5.9
- '@changesets/types': 5.2.1
- '@changesets/write': 0.2.3
+ semver: 7.7.3
+
+ '@changesets/changelog-git@0.2.1':
+ dependencies:
+ '@changesets/types': 6.1.0
+
+ '@changesets/cli@2.29.7(@types/node@22.18.11)':
+ dependencies:
+ '@changesets/apply-release-plan': 7.0.13
+ '@changesets/assemble-release-plan': 6.0.9
+ '@changesets/changelog-git': 0.2.1
+ '@changesets/config': 3.1.1
+ '@changesets/errors': 0.2.0
+ '@changesets/get-dependents-graph': 2.1.3
+ '@changesets/get-release-plan': 4.0.13
+ '@changesets/git': 3.0.4
+ '@changesets/logger': 0.1.1
+ '@changesets/pre': 2.0.2
+ '@changesets/read': 0.6.5
+ '@changesets/should-skip-package': 0.1.2
+ '@changesets/types': 6.1.0
+ '@changesets/write': 0.4.0
+ '@inquirer/external-editor': 1.0.2(@types/node@22.18.11)
'@manypkg/get-packages': 1.1.3
- '@types/is-ci': 3.0.0
- '@types/semver': 6.2.3
ansi-colors: 4.1.3
- chalk: 2.4.2
- enquirer: 2.3.6
- external-editor: 3.1.0
+ ci-info: 3.9.0
+ enquirer: 2.4.1
fs-extra: 7.0.1
- human-id: 1.0.2
- is-ci: 3.0.1
- meow: 6.1.1
- outdent: 0.5.0
+ mri: 1.2.0
p-limit: 2.3.0
- preferred-pm: 3.0.3
+ package-manager-detector: 0.2.11
+ picocolors: 1.1.1
resolve-from: 5.0.0
- semver: 7.6.2
- spawndamnit: 2.0.0
+ semver: 7.7.3
+ spawndamnit: 3.0.1
term-size: 2.2.1
- tty-table: 4.2.1
- dev: true
+ transitivePeerDependencies:
+ - '@types/node'
- /@changesets/config@2.3.0:
- resolution: {integrity: sha512-EgP/px6mhCx8QeaMAvWtRrgyxW08k/Bx2tpGT+M84jEdX37v3VKfh4Cz1BkwrYKuMV2HZKeHOh8sHvja/HcXfQ==}
+ '@changesets/config@3.1.1':
dependencies:
- '@changesets/errors': 0.1.4
- '@changesets/get-dependents-graph': 1.3.5
- '@changesets/logger': 0.0.5
- '@changesets/types': 5.2.1
+ '@changesets/errors': 0.2.0
+ '@changesets/get-dependents-graph': 2.1.3
+ '@changesets/logger': 0.1.1
+ '@changesets/types': 6.1.0
'@manypkg/get-packages': 1.1.3
fs-extra: 7.0.1
- micromatch: 4.0.5
- dev: true
+ micromatch: 4.0.8
- /@changesets/errors@0.1.4:
- resolution: {integrity: sha512-HAcqPF7snsUJ/QzkWoKfRfXushHTu+K5KZLJWPb34s4eCZShIf8BFO3fwq6KU8+G7L5KdtN2BzQAXOSXEyiY9Q==}
+ '@changesets/errors@0.2.0':
dependencies:
extendable-error: 0.1.7
- dev: true
- /@changesets/get-dependents-graph@1.3.5:
- resolution: {integrity: sha512-w1eEvnWlbVDIY8mWXqWuYE9oKhvIaBhzqzo4ITSJY9hgoqQ3RoBqwlcAzg11qHxv/b8ReDWnMrpjpKrW6m1ZTA==}
+ '@changesets/get-dependents-graph@2.1.3':
dependencies:
- '@changesets/types': 5.2.1
+ '@changesets/types': 6.1.0
'@manypkg/get-packages': 1.1.3
- chalk: 2.4.2
- fs-extra: 7.0.1
- semver: 7.6.2
- dev: true
-
- /@changesets/get-release-plan@3.0.16:
- resolution: {integrity: sha512-OpP9QILpBp1bY2YNIKFzwigKh7Qe9KizRsZomzLe6pK8IUo8onkAAVUD8+JRKSr8R7d4+JRuQrfSSNlEwKyPYg==}
- dependencies:
- '@babel/runtime': 7.21.0
- '@changesets/assemble-release-plan': 5.2.3
- '@changesets/config': 2.3.0
- '@changesets/pre': 1.0.14
- '@changesets/read': 0.5.9
- '@changesets/types': 5.2.1
+ picocolors: 1.1.1
+ semver: 7.7.3
+
+ '@changesets/get-release-plan@4.0.13':
+ dependencies:
+ '@changesets/assemble-release-plan': 6.0.9
+ '@changesets/config': 3.1.1
+ '@changesets/pre': 2.0.2
+ '@changesets/read': 0.6.5
+ '@changesets/types': 6.1.0
'@manypkg/get-packages': 1.1.3
- dev: true
- /@changesets/get-version-range-type@0.3.2:
- resolution: {integrity: sha512-SVqwYs5pULYjYT4op21F2pVbcrca4qA/bAA3FmFXKMN7Y+HcO8sbZUTx3TAy2VXulP2FACd1aC7f2nTuqSPbqg==}
- dev: true
+ '@changesets/get-version-range-type@0.4.0': {}
- /@changesets/git@2.0.0:
- resolution: {integrity: sha512-enUVEWbiqUTxqSnmesyJGWfzd51PY4H7mH9yUw0hPVpZBJ6tQZFMU3F3mT/t9OJ/GjyiM4770i+sehAn6ymx6A==}
+ '@changesets/git@3.0.4':
dependencies:
- '@babel/runtime': 7.21.0
- '@changesets/errors': 0.1.4
- '@changesets/types': 5.2.1
+ '@changesets/errors': 0.2.0
'@manypkg/get-packages': 1.1.3
is-subdir: 1.2.0
- micromatch: 4.0.5
- spawndamnit: 2.0.0
- dev: true
+ micromatch: 4.0.8
+ spawndamnit: 3.0.1
- /@changesets/logger@0.0.5:
- resolution: {integrity: sha512-gJyZHomu8nASHpaANzc6bkQMO9gU/ib20lqew1rVx753FOxffnCrJlGIeQVxNWCqM+o6OOleCo/ivL8UAO5iFw==}
+ '@changesets/logger@0.1.1':
dependencies:
- chalk: 2.4.2
- dev: true
+ picocolors: 1.1.1
- /@changesets/parse@0.3.16:
- resolution: {integrity: sha512-127JKNd167ayAuBjUggZBkmDS5fIKsthnr9jr6bdnuUljroiERW7FBTDNnNVyJ4l69PzR57pk6mXQdtJyBCJKg==}
+ '@changesets/parse@0.4.1':
dependencies:
- '@changesets/types': 5.2.1
+ '@changesets/types': 6.1.0
js-yaml: 3.14.1
- dev: true
- /@changesets/pre@1.0.14:
- resolution: {integrity: sha512-dTsHmxQWEQekHYHbg+M1mDVYFvegDh9j/kySNuDKdylwfMEevTeDouR7IfHNyVodxZXu17sXoJuf2D0vi55FHQ==}
+ '@changesets/pre@2.0.2':
dependencies:
- '@babel/runtime': 7.21.0
- '@changesets/errors': 0.1.4
- '@changesets/types': 5.2.1
+ '@changesets/errors': 0.2.0
+ '@changesets/types': 6.1.0
'@manypkg/get-packages': 1.1.3
fs-extra: 7.0.1
- dev: true
- /@changesets/read@0.5.9:
- resolution: {integrity: sha512-T8BJ6JS6j1gfO1HFq50kU3qawYxa4NTbI/ASNVVCBTsKquy2HYwM9r7ZnzkiMe8IEObAJtUVGSrePCOxAK2haQ==}
+ '@changesets/read@0.6.5':
dependencies:
- '@babel/runtime': 7.21.0
- '@changesets/git': 2.0.0
- '@changesets/logger': 0.0.5
- '@changesets/parse': 0.3.16
- '@changesets/types': 5.2.1
- chalk: 2.4.2
+ '@changesets/git': 3.0.4
+ '@changesets/logger': 0.1.1
+ '@changesets/parse': 0.4.1
+ '@changesets/types': 6.1.0
fs-extra: 7.0.1
p-filter: 2.1.0
- dev: true
+ picocolors: 1.1.1
- /@changesets/types@4.1.0:
- resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==}
- dev: true
+ '@changesets/should-skip-package@0.1.2':
+ dependencies:
+ '@changesets/types': 6.1.0
+ '@manypkg/get-packages': 1.1.3
- /@changesets/types@5.2.1:
- resolution: {integrity: sha512-myLfHbVOqaq9UtUKqR/nZA/OY7xFjQMdfgfqeZIBK4d0hA6pgxArvdv8M+6NUzzBsjWLOtvApv8YHr4qM+Kpfg==}
- dev: true
+ '@changesets/types@4.1.0': {}
- /@changesets/write@0.2.3:
- resolution: {integrity: sha512-Dbamr7AIMvslKnNYsLFafaVORx4H0pvCA2MHqgtNCySMe1blImEyAEOzDmcgKAkgz4+uwoLz7demIrX+JBr/Xw==}
+ '@changesets/types@6.1.0': {}
+
+ '@changesets/write@0.4.0':
dependencies:
- '@babel/runtime': 7.21.0
- '@changesets/types': 5.2.1
+ '@changesets/types': 6.1.0
fs-extra: 7.0.1
- human-id: 1.0.2
- prettier: 2.8.7
- dev: true
+ human-id: 4.1.2
+ prettier: 2.8.8
- /@cspotcode/source-map-support@0.8.1:
- resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
- engines: {node: '>=12'}
+ '@cspotcode/source-map-support@0.8.1':
dependencies:
'@jridgewell/trace-mapping': 0.3.9
- dev: true
-
- /@esbuild/aix-ppc64@0.21.5:
- resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
- engines: {node: '>=12'}
- cpu: [ppc64]
- os: [aix]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/android-arm64@0.17.17:
- resolution: {integrity: sha512-jaJ5IlmaDLFPNttv0ofcwy/cfeY4bh/n705Tgh+eLObbGtQBK3EPAu+CzL95JVE4nFAliyrnEu0d32Q5foavqg==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [android]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/android-arm64@0.21.5:
- resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [android]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/android-arm@0.17.17:
- resolution: {integrity: sha512-E6VAZwN7diCa3labs0GYvhEPL2M94WLF8A+czO8hfjREXxba8Ng7nM5VxV+9ihNXIY1iQO1XxUU4P7hbqbICxg==}
- engines: {node: '>=12'}
- cpu: [arm]
- os: [android]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/android-arm@0.21.5:
- resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
- engines: {node: '>=12'}
- cpu: [arm]
- os: [android]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/android-x64@0.17.17:
- resolution: {integrity: sha512-446zpfJ3nioMC7ASvJB1pszHVskkw4u/9Eu8s5yvvsSDTzYh4p4ZIRj0DznSl3FBF0Z/mZfrKXTtt0QCoFmoHA==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [android]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/android-x64@0.21.5:
- resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [android]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/darwin-arm64@0.17.17:
- resolution: {integrity: sha512-m/gwyiBwH3jqfUabtq3GH31otL/0sE0l34XKpSIqR7NjQ/XHQ3lpmQHLHbG8AHTGCw8Ao059GvV08MS0bhFIJQ==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [darwin]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/darwin-arm64@0.21.5:
- resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [darwin]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/darwin-x64@0.17.17:
- resolution: {integrity: sha512-4utIrsX9IykrqYaXR8ob9Ha2hAY2qLc6ohJ8c0CN1DR8yWeMrTgYFjgdeQ9LIoTOfLetXjuCu5TRPHT9yKYJVg==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [darwin]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/darwin-x64@0.21.5:
- resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [darwin]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/freebsd-arm64@0.17.17:
- resolution: {integrity: sha512-4PxjQII/9ppOrpEwzQ1b0pXCsFLqy77i0GaHodrmzH9zq2/NEhHMAMJkJ635Ns4fyJPFOlHMz4AsklIyRqFZWA==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [freebsd]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/freebsd-arm64@0.21.5:
- resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [freebsd]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/freebsd-x64@0.17.17:
- resolution: {integrity: sha512-lQRS+4sW5S3P1sv0z2Ym807qMDfkmdhUYX30GRBURtLTrJOPDpoU0kI6pVz1hz3U0+YQ0tXGS9YWveQjUewAJw==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [freebsd]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/freebsd-x64@0.21.5:
- resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [freebsd]
- requiresBuild: true
- dev: true
- optional: true
-
- /@esbuild/linux-arm64@0.17.17:
- resolution: {integrity: sha512-2+pwLx0whKY1/Vqt8lyzStyda1v0qjJ5INWIe+d8+1onqQxHLLi3yr5bAa4gvbzhZqBztifYEu8hh1La5+7sUw==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [linux]
- requiresBuild: true
- dev: true
- optional: true
- /@esbuild/linux-arm64@0.21.5:
- resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@emnapi/core@1.7.1':
+ dependencies:
+ '@emnapi/wasi-threads': 1.1.0
+ tslib: 2.8.1
optional: true
- /@esbuild/linux-arm@0.17.17:
- resolution: {integrity: sha512-biDs7bjGdOdcmIk6xU426VgdRUpGg39Yz6sT9Xp23aq+IEHDb/u5cbmu/pAANpDB4rZpY/2USPhCA+w9t3roQg==}
- engines: {node: '>=12'}
- cpu: [arm]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@emnapi/runtime@1.7.1':
+ dependencies:
+ tslib: 2.8.1
optional: true
- /@esbuild/linux-arm@0.21.5:
- resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
- engines: {node: '>=12'}
- cpu: [arm]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@emnapi/wasi-threads@1.1.0':
+ dependencies:
+ tslib: 2.8.1
optional: true
- /@esbuild/linux-ia32@0.17.17:
- resolution: {integrity: sha512-IBTTv8X60dYo6P2t23sSUYym8fGfMAiuv7PzJ+0LcdAndZRzvke+wTVxJeCq4WgjppkOpndL04gMZIFvwoU34Q==}
- engines: {node: '>=12'}
- cpu: [ia32]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@esbuild/aix-ppc64@0.25.11':
optional: true
- /@esbuild/linux-ia32@0.21.5:
- resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
- engines: {node: '>=12'}
- cpu: [ia32]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@esbuild/android-arm64@0.25.11':
optional: true
- /@esbuild/linux-loong64@0.17.17:
- resolution: {integrity: sha512-WVMBtcDpATjaGfWfp6u9dANIqmU9r37SY8wgAivuKmgKHE+bWSuv0qXEFt/p3qXQYxJIGXQQv6hHcm7iWhWjiw==}
- engines: {node: '>=12'}
- cpu: [loong64]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@esbuild/android-arm@0.25.11':
optional: true
- /@esbuild/linux-loong64@0.21.5:
- resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
- engines: {node: '>=12'}
- cpu: [loong64]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@esbuild/android-x64@0.25.11':
optional: true
- /@esbuild/linux-mips64el@0.17.17:
- resolution: {integrity: sha512-2kYCGh8589ZYnY031FgMLy0kmE4VoGdvfJkxLdxP4HJvWNXpyLhjOvxVsYjYZ6awqY4bgLR9tpdYyStgZZhi2A==}
- engines: {node: '>=12'}
- cpu: [mips64el]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@esbuild/darwin-arm64@0.25.11':
optional: true
- /@esbuild/linux-mips64el@0.21.5:
- resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
- engines: {node: '>=12'}
- cpu: [mips64el]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@esbuild/darwin-x64@0.25.11':
optional: true
- /@esbuild/linux-ppc64@0.17.17:
- resolution: {integrity: sha512-KIdG5jdAEeAKogfyMTcszRxy3OPbZhq0PPsW4iKKcdlbk3YE4miKznxV2YOSmiK/hfOZ+lqHri3v8eecT2ATwQ==}
- engines: {node: '>=12'}
- cpu: [ppc64]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@esbuild/freebsd-arm64@0.25.11':
optional: true
- /@esbuild/linux-ppc64@0.21.5:
- resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
- engines: {node: '>=12'}
- cpu: [ppc64]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@esbuild/freebsd-x64@0.25.11':
optional: true
- /@esbuild/linux-riscv64@0.17.17:
- resolution: {integrity: sha512-Cj6uWLBR5LWhcD/2Lkfg2NrkVsNb2sFM5aVEfumKB2vYetkA/9Uyc1jVoxLZ0a38sUhFk4JOVKH0aVdPbjZQeA==}
- engines: {node: '>=12'}
- cpu: [riscv64]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@esbuild/linux-arm64@0.25.11':
optional: true
- /@esbuild/linux-riscv64@0.21.5:
- resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
- engines: {node: '>=12'}
- cpu: [riscv64]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@esbuild/linux-arm@0.25.11':
optional: true
- /@esbuild/linux-s390x@0.17.17:
- resolution: {integrity: sha512-lK+SffWIr0XsFf7E0srBjhpkdFVJf3HEgXCwzkm69kNbRar8MhezFpkIwpk0qo2IOQL4JE4mJPJI8AbRPLbuOQ==}
- engines: {node: '>=12'}
- cpu: [s390x]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@esbuild/linux-ia32@0.25.11':
optional: true
- /@esbuild/linux-s390x@0.21.5:
- resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
- engines: {node: '>=12'}
- cpu: [s390x]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@esbuild/linux-loong64@0.25.11':
optional: true
- /@esbuild/linux-x64@0.17.17:
- resolution: {integrity: sha512-XcSGTQcWFQS2jx3lZtQi7cQmDYLrpLRyz1Ns1DzZCtn898cWfm5Icx/DEWNcTU+T+tyPV89RQtDnI7qL2PObPg==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@esbuild/linux-mips64el@0.25.11':
optional: true
- /@esbuild/linux-x64@0.21.5:
- resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@esbuild/linux-ppc64@0.25.11':
optional: true
- /@esbuild/netbsd-x64@0.17.17:
- resolution: {integrity: sha512-RNLCDmLP5kCWAJR+ItLM3cHxzXRTe4N00TQyQiimq+lyqVqZWGPAvcyfUBM0isE79eEZhIuGN09rAz8EL5KdLA==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [netbsd]
- requiresBuild: true
- dev: true
+ '@esbuild/linux-riscv64@0.25.11':
optional: true
- /@esbuild/netbsd-x64@0.21.5:
- resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [netbsd]
- requiresBuild: true
- dev: true
+ '@esbuild/linux-s390x@0.25.11':
optional: true
- /@esbuild/openbsd-x64@0.17.17:
- resolution: {integrity: sha512-PAXswI5+cQq3Pann7FNdcpSUrhrql3wKjj3gVkmuz6OHhqqYxKvi6GgRBoaHjaG22HV/ZZEgF9TlS+9ftHVigA==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [openbsd]
- requiresBuild: true
- dev: true
+ '@esbuild/linux-x64@0.25.11':
optional: true
- /@esbuild/openbsd-x64@0.21.5:
- resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [openbsd]
- requiresBuild: true
- dev: true
+ '@esbuild/netbsd-arm64@0.25.11':
optional: true
- /@esbuild/sunos-x64@0.17.17:
- resolution: {integrity: sha512-V63egsWKnx/4V0FMYkr9NXWrKTB5qFftKGKuZKFIrAkO/7EWLFnbBZNM1CvJ6Sis+XBdPws2YQSHF1Gqf1oj/Q==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [sunos]
- requiresBuild: true
- dev: true
+ '@esbuild/netbsd-x64@0.25.11':
optional: true
- /@esbuild/sunos-x64@0.21.5:
- resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [sunos]
- requiresBuild: true
- dev: true
+ '@esbuild/openbsd-arm64@0.25.11':
optional: true
- /@esbuild/win32-arm64@0.17.17:
- resolution: {integrity: sha512-YtUXLdVnd6YBSYlZODjWzH+KzbaubV0YVd6UxSfoFfa5PtNJNaW+1i+Hcmjpg2nEe0YXUCNF5bkKy1NnBv1y7Q==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [win32]
- requiresBuild: true
- dev: true
+ '@esbuild/openbsd-x64@0.25.11':
optional: true
- /@esbuild/win32-arm64@0.21.5:
- resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [win32]
- requiresBuild: true
- dev: true
+ '@esbuild/openharmony-arm64@0.25.11':
optional: true
- /@esbuild/win32-ia32@0.17.17:
- resolution: {integrity: sha512-yczSLRbDdReCO74Yfc5tKG0izzm+lPMYyO1fFTcn0QNwnKmc3K+HdxZWLGKg4pZVte7XVgcFku7TIZNbWEJdeQ==}
- engines: {node: '>=12'}
- cpu: [ia32]
- os: [win32]
- requiresBuild: true
- dev: true
+ '@esbuild/sunos-x64@0.25.11':
optional: true
- /@esbuild/win32-ia32@0.21.5:
- resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
- engines: {node: '>=12'}
- cpu: [ia32]
- os: [win32]
- requiresBuild: true
- dev: true
+ '@esbuild/win32-arm64@0.25.11':
optional: true
- /@esbuild/win32-x64@0.17.17:
- resolution: {integrity: sha512-FNZw7H3aqhF9OyRQbDDnzUApDXfC1N6fgBhkqEO2jvYCJ+DxMTfZVqg3AX0R1khg1wHTBRD5SdcibSJ+XF6bFg==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [win32]
- requiresBuild: true
- dev: true
+ '@esbuild/win32-ia32@0.25.11':
optional: true
- /@esbuild/win32-x64@0.21.5:
- resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [win32]
- requiresBuild: true
- dev: true
+ '@esbuild/win32-x64@0.25.11':
optional: true
- /@isaacs/cliui@8.0.2:
- resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
- engines: {node: '>=12'}
+ '@inquirer/external-editor@1.0.2(@types/node@22.18.11)':
+ dependencies:
+ chardet: 2.1.0
+ iconv-lite: 0.7.0
+ optionalDependencies:
+ '@types/node': 22.18.11
+
+ '@isaacs/cliui@8.0.2':
dependencies:
string-width: 5.1.2
- string-width-cjs: /string-width@4.2.3
- strip-ansi: 7.1.0
- strip-ansi-cjs: /strip-ansi@6.0.1
+ string-width-cjs: string-width@4.2.3
+ strip-ansi: 7.1.2
+ strip-ansi-cjs: strip-ansi@6.0.1
wrap-ansi: 8.1.0
- wrap-ansi-cjs: /wrap-ansi@7.0.0
- dev: true
+ wrap-ansi-cjs: wrap-ansi@7.0.0
- /@istanbuljs/schema@0.1.3:
- resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==}
- engines: {node: '>=8'}
- dev: true
+ '@istanbuljs/schema@0.1.3': {}
- /@jest/expect-utils@29.5.0:
- resolution: {integrity: sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
- dependencies:
- jest-get-type: 29.4.3
- dev: true
+ '@jest/diff-sequences@30.0.1': {}
- /@jest/schemas@29.4.3:
- resolution: {integrity: sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ '@jest/expect-utils@30.2.0':
dependencies:
- '@sinclair/typebox': 0.25.24
- dev: true
+ '@jest/get-type': 30.1.0
- /@jest/types@29.5.0:
- resolution: {integrity: sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
- dependencies:
- '@jest/schemas': 29.4.3
- '@types/istanbul-lib-coverage': 2.0.4
- '@types/istanbul-reports': 3.0.1
- '@types/node': 18.15.13
- '@types/yargs': 17.0.24
- chalk: 4.1.2
- dev: true
+ '@jest/get-type@30.1.0': {}
- /@jridgewell/gen-mapping@0.3.3:
- resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
- engines: {node: '>=6.0.0'}
+ '@jest/pattern@30.0.1':
dependencies:
- '@jridgewell/set-array': 1.1.2
- '@jridgewell/sourcemap-codec': 1.4.15
- '@jridgewell/trace-mapping': 0.3.18
- dev: true
+ '@types/node': 22.18.11
+ jest-regex-util: 30.0.1
- /@jridgewell/gen-mapping@0.3.5:
- resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
- engines: {node: '>=6.0.0'}
+ '@jest/schemas@30.0.5':
dependencies:
- '@jridgewell/set-array': 1.2.1
- '@jridgewell/sourcemap-codec': 1.4.15
- '@jridgewell/trace-mapping': 0.3.25
- dev: true
-
- /@jridgewell/resolve-uri@3.1.0:
- resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==}
- engines: {node: '>=6.0.0'}
- dev: true
-
- /@jridgewell/set-array@1.1.2:
- resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
- engines: {node: '>=6.0.0'}
- dev: true
+ '@sinclair/typebox': 0.34.41
- /@jridgewell/set-array@1.2.1:
- resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
- engines: {node: '>=6.0.0'}
- dev: true
+ '@jest/types@30.2.0':
+ dependencies:
+ '@jest/pattern': 30.0.1
+ '@jest/schemas': 30.0.5
+ '@types/istanbul-lib-coverage': 2.0.6
+ '@types/istanbul-reports': 3.0.4
+ '@types/node': 22.18.11
+ '@types/yargs': 17.0.33
+ chalk: 4.1.2
- /@jridgewell/source-map@0.3.3:
- resolution: {integrity: sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==}
+ '@jridgewell/gen-mapping@0.3.13':
dependencies:
- '@jridgewell/gen-mapping': 0.3.3
- '@jridgewell/trace-mapping': 0.3.18
- dev: true
+ '@jridgewell/sourcemap-codec': 1.5.5
+ '@jridgewell/trace-mapping': 0.3.31
- /@jridgewell/sourcemap-codec@1.4.14:
- resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==}
- dev: true
+ '@jridgewell/remapping@2.3.5':
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
- /@jridgewell/sourcemap-codec@1.4.15:
- resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
- dev: true
+ '@jridgewell/resolve-uri@3.1.2': {}
- /@jridgewell/trace-mapping@0.3.18:
- resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==}
+ '@jridgewell/source-map@0.3.11':
dependencies:
- '@jridgewell/resolve-uri': 3.1.0
- '@jridgewell/sourcemap-codec': 1.4.14
- dev: true
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+
+ '@jridgewell/sourcemap-codec@1.5.5': {}
- /@jridgewell/trace-mapping@0.3.25:
- resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
+ '@jridgewell/trace-mapping@0.3.31':
dependencies:
- '@jridgewell/resolve-uri': 3.1.0
- '@jridgewell/sourcemap-codec': 1.4.15
- dev: true
+ '@jridgewell/resolve-uri': 3.1.2
+ '@jridgewell/sourcemap-codec': 1.5.5
- /@jridgewell/trace-mapping@0.3.9:
- resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
+ '@jridgewell/trace-mapping@0.3.9':
dependencies:
- '@jridgewell/resolve-uri': 3.1.0
- '@jridgewell/sourcemap-codec': 1.4.15
- dev: true
+ '@jridgewell/resolve-uri': 3.1.2
+ '@jridgewell/sourcemap-codec': 1.5.5
- /@manypkg/find-root@1.1.0:
- resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==}
+ '@manypkg/find-root@1.1.0':
dependencies:
- '@babel/runtime': 7.21.0
+ '@babel/runtime': 7.28.4
'@types/node': 12.20.55
find-up: 4.1.0
fs-extra: 8.1.0
- dev: true
- /@manypkg/get-packages@1.1.3:
- resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==}
+ '@manypkg/get-packages@1.1.3':
dependencies:
- '@babel/runtime': 7.21.0
+ '@babel/runtime': 7.28.4
'@changesets/types': 4.1.0
'@manypkg/find-root': 1.1.0
fs-extra: 8.1.0
globby: 11.1.0
read-yaml-file: 1.1.0
- dev: true
- /@nodelib/fs.scandir@2.1.5:
- resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
- engines: {node: '>= 8'}
+ '@napi-rs/wasm-runtime@1.1.0':
+ dependencies:
+ '@emnapi/core': 1.7.1
+ '@emnapi/runtime': 1.7.1
+ '@tybys/wasm-util': 0.10.1
+ optional: true
+
+ '@nodelib/fs.scandir@2.1.5':
dependencies:
'@nodelib/fs.stat': 2.0.5
run-parallel: 1.2.0
- dev: true
- /@nodelib/fs.stat@2.0.5:
- resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
- engines: {node: '>= 8'}
- dev: true
+ '@nodelib/fs.stat@2.0.5': {}
- /@nodelib/fs.walk@1.2.8:
- resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
- engines: {node: '>= 8'}
+ '@nodelib/fs.walk@1.2.8':
dependencies:
'@nodelib/fs.scandir': 2.1.5
- fastq: 1.15.0
- dev: true
+ fastq: 1.19.1
- /@pkgjs/parseargs@0.11.0:
- resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
- engines: {node: '>=14'}
- requiresBuild: true
- dev: true
+ '@oxc-project/types@0.101.0': {}
+
+ '@pkgjs/parseargs@0.11.0':
optional: true
- /@rollup/rollup-android-arm-eabi@4.18.1:
- resolution: {integrity: sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==}
- cpu: [arm]
- os: [android]
- requiresBuild: true
- dev: true
+ '@quansync/fs@1.0.0':
+ dependencies:
+ quansync: 1.0.0
+
+ '@rolldown/binding-android-arm64@1.0.0-beta.53':
optional: true
- /@rollup/rollup-android-arm64@4.18.1:
- resolution: {integrity: sha512-F/tkdw0WSs4ojqz5Ovrw5r9odqzFjb5LIgHdHZG65dFI1lWTWRVy32KDJLKRISHgJvqUeUhdIvy43fX41znyDg==}
- cpu: [arm64]
- os: [android]
- requiresBuild: true
- dev: true
+ '@rolldown/binding-darwin-arm64@1.0.0-beta.53':
optional: true
- /@rollup/rollup-darwin-arm64@4.18.1:
- resolution: {integrity: sha512-vk+ma8iC1ebje/ahpxpnrfVQJibTMyHdWpOGZ3JpQ7Mgn/3QNHmPq7YwjZbIE7km73dH5M1e6MRRsnEBW7v5CQ==}
- cpu: [arm64]
- os: [darwin]
- requiresBuild: true
- dev: true
+ '@rolldown/binding-darwin-x64@1.0.0-beta.53':
optional: true
- /@rollup/rollup-darwin-x64@4.18.1:
- resolution: {integrity: sha512-IgpzXKauRe1Tafcej9STjSSuG0Ghu/xGYH+qG6JwsAUxXrnkvNHcq/NL6nz1+jzvWAnQkuAJ4uIwGB48K9OCGA==}
- cpu: [x64]
- os: [darwin]
- requiresBuild: true
- dev: true
+ '@rolldown/binding-freebsd-x64@1.0.0-beta.53':
optional: true
- /@rollup/rollup-linux-arm-gnueabihf@4.18.1:
- resolution: {integrity: sha512-P9bSiAUnSSM7EmyRK+e5wgpqai86QOSv8BwvkGjLwYuOpaeomiZWifEos517CwbG+aZl1T4clSE1YqqH2JRs+g==}
- cpu: [arm]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.53':
optional: true
- /@rollup/rollup-linux-arm-musleabihf@4.18.1:
- resolution: {integrity: sha512-5RnjpACoxtS+aWOI1dURKno11d7krfpGDEn19jI8BuWmSBbUC4ytIADfROM1FZrFhQPSoP+KEa3NlEScznBTyQ==}
- cpu: [arm]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.53':
optional: true
- /@rollup/rollup-linux-arm64-gnu@4.18.1:
- resolution: {integrity: sha512-8mwmGD668m8WaGbthrEYZ9CBmPug2QPGWxhJxh/vCgBjro5o96gL04WLlg5BA233OCWLqERy4YUzX3bJGXaJgQ==}
- cpu: [arm64]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@rolldown/binding-linux-arm64-musl@1.0.0-beta.53':
optional: true
- /@rollup/rollup-linux-arm64-musl@4.18.1:
- resolution: {integrity: sha512-dJX9u4r4bqInMGOAQoGYdwDP8lQiisWb9et+T84l2WXk41yEej8v2iGKodmdKimT8cTAYt0jFb+UEBxnPkbXEQ==}
- cpu: [arm64]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@rolldown/binding-linux-x64-gnu@1.0.0-beta.53':
optional: true
- /@rollup/rollup-linux-powerpc64le-gnu@4.18.1:
- resolution: {integrity: sha512-V72cXdTl4EI0x6FNmho4D502sy7ed+LuVW6Ym8aI6DRQ9hQZdp5sj0a2usYOlqvFBNKQnLQGwmYnujo2HvjCxQ==}
- cpu: [ppc64]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@rolldown/binding-linux-x64-musl@1.0.0-beta.53':
optional: true
- /@rollup/rollup-linux-riscv64-gnu@4.18.1:
- resolution: {integrity: sha512-f+pJih7sxoKmbjghrM2RkWo2WHUW8UbfxIQiWo5yeCaCM0TveMEuAzKJte4QskBp1TIinpnRcxkquY+4WuY/tg==}
- cpu: [riscv64]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@rolldown/binding-openharmony-arm64@1.0.0-beta.53':
optional: true
- /@rollup/rollup-linux-s390x-gnu@4.18.1:
- resolution: {integrity: sha512-qb1hMMT3Fr/Qz1OKovCuUM11MUNLUuHeBC2DPPAWUYYUAOFWaxInaTwTQmc7Fl5La7DShTEpmYwgdt2hG+4TEg==}
- cpu: [s390x]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@rolldown/binding-wasm32-wasi@1.0.0-beta.53':
+ dependencies:
+ '@napi-rs/wasm-runtime': 1.1.0
optional: true
- /@rollup/rollup-linux-x64-gnu@4.18.1:
- resolution: {integrity: sha512-7O5u/p6oKUFYjRbZkL2FLbwsyoJAjyeXHCU3O4ndvzg2OFO2GinFPSJFGbiwFDaCFc+k7gs9CF243PwdPQFh5g==}
- cpu: [x64]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.53':
optional: true
- /@rollup/rollup-linux-x64-musl@4.18.1:
- resolution: {integrity: sha512-pDLkYITdYrH/9Cv/Vlj8HppDuLMDUBmgsM0+N+xLtFd18aXgM9Nyqupb/Uw+HeidhfYg2lD6CXvz6CjoVOaKjQ==}
- cpu: [x64]
- os: [linux]
- requiresBuild: true
- dev: true
+ '@rolldown/binding-win32-x64-msvc@1.0.0-beta.53':
optional: true
- /@rollup/rollup-win32-arm64-msvc@4.18.1:
- resolution: {integrity: sha512-W2ZNI323O/8pJdBGil1oCauuCzmVd9lDmWBBqxYZcOqWD6aWqJtVBQ1dFrF4dYpZPks6F+xCZHfzG5hYlSHZ6g==}
- cpu: [arm64]
- os: [win32]
- requiresBuild: true
- dev: true
+ '@rolldown/pluginutils@1.0.0-beta.27': {}
+
+ '@rolldown/pluginutils@1.0.0-beta.53': {}
+
+ '@rollup/rollup-android-arm-eabi@4.52.5':
optional: true
- /@rollup/rollup-win32-ia32-msvc@4.18.1:
- resolution: {integrity: sha512-ELfEX1/+eGZYMaCIbK4jqLxO1gyTSOIlZr6pbC4SRYFaSIDVKOnZNMdoZ+ON0mrFDp4+H5MhwNC1H/AhE3zQLg==}
- cpu: [ia32]
- os: [win32]
- requiresBuild: true
- dev: true
+ '@rollup/rollup-android-arm64@4.52.5':
optional: true
- /@rollup/rollup-win32-x64-msvc@4.18.1:
- resolution: {integrity: sha512-yjk2MAkQmoaPYCSu35RLJ62+dz358nE83VfTePJRp8CG7aMg25mEJYpXFiD+NcevhX8LxD5OP5tktPXnXN7GDw==}
- cpu: [x64]
- os: [win32]
- requiresBuild: true
- dev: true
+ '@rollup/rollup-darwin-arm64@4.52.5':
optional: true
- /@sinclair/typebox@0.25.24:
- resolution: {integrity: sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==}
- dev: true
+ '@rollup/rollup-darwin-x64@4.52.5':
+ optional: true
- /@size-limit/esbuild@8.2.4(size-limit@8.2.4):
- resolution: {integrity: sha512-kPgNfpwUvBD98s5axlf1UciFg4Ki4AYSl/cOmSyyYBuzksHiwW7Myeu0w4mTxtV9nwBFbkrrNXqszE7b+OhFLA==}
- engines: {node: ^14.0.0 || ^16.0.0 || >=18.0.0}
- peerDependencies:
- size-limit: 8.2.4
+ '@rollup/rollup-freebsd-arm64@4.52.5':
+ optional: true
+
+ '@rollup/rollup-freebsd-x64@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-arm-musleabihf@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-gnu@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-musl@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-loong64-gnu@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-ppc64-gnu@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-gnu@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-musl@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-s390x-gnu@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-x64-gnu@4.52.5':
+ optional: true
+
+ '@rollup/rollup-linux-x64-musl@4.52.5':
+ optional: true
+
+ '@rollup/rollup-openharmony-arm64@4.52.5':
+ optional: true
+
+ '@rollup/rollup-win32-arm64-msvc@4.52.5':
+ optional: true
+
+ '@rollup/rollup-win32-ia32-msvc@4.52.5':
+ optional: true
+
+ '@rollup/rollup-win32-x64-gnu@4.52.5':
+ optional: true
+
+ '@rollup/rollup-win32-x64-msvc@4.52.5':
+ optional: true
+
+ '@sinclair/typebox@0.34.41': {}
+
+ '@size-limit/esbuild@8.2.6(size-limit@8.2.6)':
dependencies:
- esbuild: 0.17.17
- nanoid: 3.3.6
- size-limit: 8.2.4
- dev: true
+ esbuild: 0.25.11
+ nanoid: 5.1.6
+ size-limit: 8.2.6
- /@size-limit/file@8.2.4(size-limit@8.2.4):
- resolution: {integrity: sha512-xLuF97W7m7lxrRJvqXRlxO/4t7cpXtfxOnjml/t4aRVUCMXLdyvebRr9OM4jjoK8Fmiz8jomCbETUCI3jVhLzA==}
- engines: {node: ^14.0.0 || ^16.0.0 || >=18.0.0}
- peerDependencies:
- size-limit: 8.2.4
+ '@size-limit/file@8.2.6(size-limit@8.2.6)':
dependencies:
- semver: 7.6.2
- size-limit: 8.2.4
- dev: true
+ semver: 7.5.3
+ size-limit: 8.2.6
- /@size-limit/preset-small-lib@8.2.4(size-limit@8.2.4):
- resolution: {integrity: sha512-AL4384oBgMcDPlNblgWHreqFSSOui0J9NbgyHhegB1h8AgRyHbdVGC3yWLpEESYQXHYnKdbNrYeRE/TclsViog==}
- peerDependencies:
- size-limit: 8.2.4
+ '@size-limit/preset-small-lib@8.2.6(size-limit@8.2.6)':
dependencies:
- '@size-limit/esbuild': 8.2.4(size-limit@8.2.4)
- '@size-limit/file': 8.2.4(size-limit@8.2.4)
- size-limit: 8.2.4
- dev: true
+ '@size-limit/esbuild': 8.2.6(size-limit@8.2.6)
+ '@size-limit/file': 8.2.6(size-limit@8.2.6)
+ size-limit: 8.2.6
- /@testing-library/dom@9.2.0:
- resolution: {integrity: sha512-xTEnpUKiV/bMyEsE5bT4oYA0x0Z/colMtxzUY8bKyPXBNLn/e0V4ZjBZkEhms0xE4pv9QsPfSRu9AWS4y5wGvA==}
- engines: {node: '>=14'}
+ '@testing-library/dom@9.3.4':
dependencies:
- '@babel/code-frame': 7.21.4
- '@babel/runtime': 7.21.0
- '@types/aria-query': 5.0.1
+ '@babel/code-frame': 7.27.1
+ '@babel/runtime': 7.28.4
+ '@types/aria-query': 5.0.4
aria-query: 5.1.3
chalk: 4.1.2
dom-accessibility-api: 0.5.16
lz-string: 1.5.0
pretty-format: 27.5.1
- dev: true
- /@testing-library/jest-dom@5.16.5:
- resolution: {integrity: sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==}
- engines: {node: '>=8', npm: '>=6', yarn: '>=1'}
+ '@testing-library/jest-dom@5.17.0':
dependencies:
- '@adobe/css-tools': 4.4.0
- '@babel/runtime': 7.21.0
- '@types/testing-library__jest-dom': 5.14.5
- aria-query: 5.1.3
+ '@adobe/css-tools': 4.4.4
+ '@babel/runtime': 7.28.4
+ '@types/testing-library__jest-dom': 5.14.9
+ aria-query: 5.3.2
chalk: 3.0.0
css.escape: 1.5.1
dom-accessibility-api: 0.5.16
lodash: 4.17.21
redent: 3.0.0
- dev: true
- /@testing-library/react@14.0.0(react-dom@18.2.0)(react@18.2.0):
- resolution: {integrity: sha512-S04gSNJbYE30TlIMLTzv6QCTzt9AqIF5y6s6SzVFILNcNvbV/jU96GeiTPillGQo+Ny64M/5PV7klNYYgv5Dfg==}
- engines: {node: '>=14'}
- peerDependencies:
- react: ^18.0.0
- react-dom: ^18.0.0
+ '@testing-library/react@14.3.1(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
- '@babel/runtime': 7.21.0
- '@testing-library/dom': 9.2.0
- '@types/react-dom': 18.0.11
- react: 18.2.0
- react-dom: 18.2.0(react@18.2.0)
- dev: true
+ '@babel/runtime': 7.28.4
+ '@testing-library/dom': 9.3.4
+ '@types/react-dom': 18.3.7(@types/react@18.3.26)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ transitivePeerDependencies:
+ - '@types/react'
- /@tootallnate/once@2.0.0:
- resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
- engines: {node: '>= 10'}
- dev: true
+ '@tootallnate/once@2.0.0': {}
- /@tsconfig/node10@1.0.9:
- resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==}
- dev: true
+ '@tsconfig/node10@1.0.11': {}
- /@tsconfig/node12@1.0.11:
- resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==}
- dev: true
+ '@tsconfig/node12@1.0.11': {}
- /@tsconfig/node14@1.0.3:
- resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==}
- dev: true
+ '@tsconfig/node14@1.0.3': {}
- /@tsconfig/node16@1.0.3:
- resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==}
- dev: true
+ '@tsconfig/node16@1.0.4': {}
- /@types/aria-query@5.0.1:
- resolution: {integrity: sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==}
- dev: true
+ '@tybys/wasm-util@0.10.1':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
- /@types/babel__core@7.20.5:
- resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
+ '@types/aria-query@5.0.4': {}
+
+ '@types/babel__core@7.20.5':
dependencies:
- '@babel/parser': 7.24.8
- '@babel/types': 7.24.9
- '@types/babel__generator': 7.6.8
+ '@babel/parser': 7.28.4
+ '@babel/types': 7.28.4
+ '@types/babel__generator': 7.27.0
'@types/babel__template': 7.4.4
- '@types/babel__traverse': 7.20.6
- dev: true
+ '@types/babel__traverse': 7.28.0
- /@types/babel__generator@7.6.8:
- resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==}
+ '@types/babel__generator@7.27.0':
dependencies:
- '@babel/types': 7.24.9
- dev: true
+ '@babel/types': 7.28.4
- /@types/babel__template@7.4.4:
- resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
+ '@types/babel__template@7.4.4':
dependencies:
- '@babel/parser': 7.24.8
- '@babel/types': 7.24.9
- dev: true
+ '@babel/parser': 7.28.4
+ '@babel/types': 7.28.4
- /@types/babel__traverse@7.20.6:
- resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==}
+ '@types/babel__traverse@7.28.0':
dependencies:
- '@babel/types': 7.24.9
- dev: true
+ '@babel/types': 7.28.4
- /@types/estree@1.0.5:
- resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
- dev: true
-
- /@types/is-ci@3.0.0:
- resolution: {integrity: sha512-Q0Op0hdWbYd1iahB+IFNQcWXFq4O0Q5MwQP7uN0souuQ4rPg1vEYcnIOfr1gY+M+6rc8FGoRaBO1mOOvL29sEQ==}
+ '@types/chai@5.2.2':
dependencies:
- ci-info: 3.8.0
- dev: true
+ '@types/deep-eql': 4.0.2
- /@types/istanbul-lib-coverage@2.0.4:
- resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==}
- dev: true
+ '@types/deep-eql@4.0.2': {}
- /@types/istanbul-lib-report@3.0.0:
- resolution: {integrity: sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==}
- dependencies:
- '@types/istanbul-lib-coverage': 2.0.4
- dev: true
+ '@types/estree@1.0.8': {}
- /@types/istanbul-reports@3.0.1:
- resolution: {integrity: sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==}
- dependencies:
- '@types/istanbul-lib-report': 3.0.0
- dev: true
+ '@types/istanbul-lib-coverage@2.0.6': {}
- /@types/jest@29.5.1:
- resolution: {integrity: sha512-tEuVcHrpaixS36w7hpsfLBLpjtMRJUE09/MHXn923LOVojDwyC14cWcfc0rDs0VEfUyYmt/+iX1kxxp+gZMcaQ==}
+ '@types/istanbul-lib-report@3.0.3':
dependencies:
- expect: 29.5.0
- pretty-format: 29.5.0
- dev: true
+ '@types/istanbul-lib-coverage': 2.0.6
- /@types/minimist@1.2.2:
- resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==}
- dev: true
+ '@types/istanbul-reports@3.0.4':
+ dependencies:
+ '@types/istanbul-lib-report': 3.0.3
- /@types/node@12.20.55:
- resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==}
- dev: true
+ '@types/jest@30.0.0':
+ dependencies:
+ expect: 30.2.0
+ pretty-format: 30.2.0
- /@types/node@18.15.13:
- resolution: {integrity: sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==}
- dev: true
+ '@types/node@12.20.55': {}
- /@types/normalize-package-data@2.4.1:
- resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==}
- dev: true
+ '@types/node@22.18.11':
+ dependencies:
+ undici-types: 6.21.0
- /@types/prop-types@15.7.5:
- resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==}
- dev: true
+ '@types/prop-types@15.7.15': {}
- /@types/react-dom@18.0.11:
- resolution: {integrity: sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==}
+ '@types/react-dom@18.3.7(@types/react@18.3.26)':
dependencies:
- '@types/react': 18.0.38
- dev: true
+ '@types/react': 18.3.26
- /@types/react@18.0.38:
- resolution: {integrity: sha512-ExsidLLSzYj4cvaQjGnQCk4HFfVT9+EZ9XZsQ8Hsrcn8QNgXtpZ3m9vSIC2MWtx7jHictK6wYhQgGh6ic58oOw==}
+ '@types/react@18.3.26':
dependencies:
- '@types/prop-types': 15.7.5
- '@types/scheduler': 0.16.3
- csstype: 3.1.2
- dev: true
-
- /@types/scheduler@0.16.3:
- resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==}
- dev: true
+ '@types/prop-types': 15.7.15
+ csstype: 3.1.3
- /@types/semver@6.2.3:
- resolution: {integrity: sha512-KQf+QAMWKMrtBMsB8/24w53tEsxllMj6TuA80TT/5igJalLI/zm0L3oXRbIAl4Ohfc85gyHX/jhMwsVkmhLU4A==}
- dev: true
+ '@types/stack-utils@2.0.3': {}
- /@types/stack-utils@2.0.1:
- resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==}
- dev: true
-
- /@types/testing-library__jest-dom@5.14.5:
- resolution: {integrity: sha512-SBwbxYoyPIvxHbeHxTZX2Pe/74F/tX2/D3mMvzabdeJ25bBojfW0TyB8BHrbq/9zaaKICJZjLP+8r6AeZMFCuQ==}
+ '@types/testing-library__jest-dom@5.14.9':
dependencies:
- '@types/jest': 29.5.1
- dev: true
+ '@types/jest': 30.0.0
- /@types/yargs-parser@21.0.0:
- resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==}
- dev: true
+ '@types/yargs-parser@21.0.3': {}
- /@types/yargs@17.0.24:
- resolution: {integrity: sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==}
+ '@types/yargs@17.0.33':
dependencies:
- '@types/yargs-parser': 21.0.0
- dev: true
+ '@types/yargs-parser': 21.0.3
- /@vitejs/plugin-react@4.3.1(vite@5.3.3):
- resolution: {integrity: sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg==}
- engines: {node: ^14.18.0 || >=16.0.0}
- peerDependencies:
- vite: ^4.2.0 || ^5.0.0
+ '@vitejs/plugin-react@4.7.0(vite@7.1.11(@types/node@22.18.11)(terser@5.44.0))':
dependencies:
- '@babel/core': 7.24.9
- '@babel/plugin-transform-react-jsx-self': 7.24.7(@babel/core@7.24.9)
- '@babel/plugin-transform-react-jsx-source': 7.24.7(@babel/core@7.24.9)
+ '@babel/core': 7.28.4
+ '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.4)
+ '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.4)
+ '@rolldown/pluginutils': 1.0.0-beta.27
'@types/babel__core': 7.20.5
- react-refresh: 0.14.2
- vite: 5.3.3(@types/node@18.15.13)(terser@5.17.1)
+ react-refresh: 0.17.0
+ vite: 7.1.11(@types/node@22.18.11)(terser@5.44.0)
transitivePeerDependencies:
- supports-color
- dev: true
- /@vitest/coverage-istanbul@2.0.3(vitest@2.0.3):
- resolution: {integrity: sha512-ewO7lSXDc/hG7vrVUh3lrpRpNZslivE92b07lW05GE+o7dkmvSheCl6oyMqa3EVU1rjbbM8dlWsfNOY4PAqasQ==}
- peerDependencies:
- vitest: 2.0.3
+ '@vitest/coverage-istanbul@3.2.4(vitest@3.2.4(@types/node@22.18.11)(jsdom@21.1.2)(terser@5.44.0))':
dependencies:
'@istanbuljs/schema': 0.1.3
- debug: 4.3.5
+ debug: 4.4.3
istanbul-lib-coverage: 3.2.2
istanbul-lib-instrument: 6.0.3
istanbul-lib-report: 3.0.1
istanbul-lib-source-maps: 5.0.6
- istanbul-reports: 3.1.7
- magicast: 0.3.4
+ istanbul-reports: 3.2.0
+ magicast: 0.3.5
test-exclude: 7.0.1
- tinyrainbow: 1.2.0
- vitest: 2.0.3(@types/node@18.15.13)(jsdom@21.1.1)(terser@5.17.1)
+ tinyrainbow: 2.0.0
+ vitest: 3.2.4(@types/node@22.18.11)(jsdom@21.1.2)(terser@5.44.0)
transitivePeerDependencies:
- supports-color
- dev: true
- /@vitest/expect@2.0.3:
- resolution: {integrity: sha512-X6AepoOYePM0lDNUPsGXTxgXZAl3EXd0GYe/MZyVE4HzkUqyUVC6S3PrY5mClDJ6/7/7vALLMV3+xD/Ko60Hqg==}
+ '@vitest/expect@3.2.4':
+ dependencies:
+ '@types/chai': 5.2.2
+ '@vitest/spy': 3.2.4
+ '@vitest/utils': 3.2.4
+ chai: 5.3.3
+ tinyrainbow: 2.0.0
+
+ '@vitest/mocker@3.2.4(vite@7.1.11(@types/node@22.18.11)(terser@5.44.0))':
dependencies:
- '@vitest/spy': 2.0.3
- '@vitest/utils': 2.0.3
- chai: 5.1.1
- tinyrainbow: 1.2.0
- dev: true
+ '@vitest/spy': 3.2.4
+ estree-walker: 3.0.3
+ magic-string: 0.30.19
+ optionalDependencies:
+ vite: 7.1.11(@types/node@22.18.11)(terser@5.44.0)
- /@vitest/pretty-format@2.0.3:
- resolution: {integrity: sha512-URM4GLsB2xD37nnTyvf6kfObFafxmycCL8un3OC9gaCs5cti2u+5rJdIflZ2fUJUen4NbvF6jCufwViAFLvz1g==}
+ '@vitest/pretty-format@3.2.4':
dependencies:
- tinyrainbow: 1.2.0
- dev: true
+ tinyrainbow: 2.0.0
- /@vitest/runner@2.0.3:
- resolution: {integrity: sha512-EmSP4mcjYhAcuBWwqgpjR3FYVeiA4ROzRunqKltWjBfLNs1tnMLtF+qtgd5ClTwkDP6/DGlKJTNa6WxNK0bNYQ==}
+ '@vitest/runner@3.2.4':
dependencies:
- '@vitest/utils': 2.0.3
- pathe: 1.1.2
- dev: true
+ '@vitest/utils': 3.2.4
+ pathe: 2.0.3
+ strip-literal: 3.1.0
- /@vitest/snapshot@2.0.3:
- resolution: {integrity: sha512-6OyA6v65Oe3tTzoSuRPcU6kh9m+mPL1vQ2jDlPdn9IQoUxl8rXhBnfICNOC+vwxWY684Vt5UPgtcA2aPFBb6wg==}
+ '@vitest/snapshot@3.2.4':
dependencies:
- '@vitest/pretty-format': 2.0.3
- magic-string: 0.30.10
- pathe: 1.1.2
- dev: true
+ '@vitest/pretty-format': 3.2.4
+ magic-string: 0.30.19
+ pathe: 2.0.3
- /@vitest/spy@2.0.3:
- resolution: {integrity: sha512-sfqyAw/ypOXlaj4S+w8689qKM1OyPOqnonqOc9T91DsoHbfN5mU7FdifWWv3MtQFf0lEUstEwR9L/q/M390C+A==}
+ '@vitest/spy@3.2.4':
dependencies:
- tinyspy: 3.0.0
- dev: true
+ tinyspy: 4.0.4
- /@vitest/utils@2.0.3:
- resolution: {integrity: sha512-c/UdELMuHitQbbc/EVctlBaxoYAwQPQdSNwv7z/vHyBKy2edYZaFgptE27BRueZB7eW8po+cllotMNTDpL3HWg==}
+ '@vitest/utils@3.2.4':
dependencies:
- '@vitest/pretty-format': 2.0.3
- estree-walker: 3.0.3
- loupe: 3.1.1
- tinyrainbow: 1.2.0
- dev: true
+ '@vitest/pretty-format': 3.2.4
+ loupe: 3.2.1
+ tinyrainbow: 2.0.0
- /abab@2.0.6:
- resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==}
- dev: true
+ abab@2.0.6: {}
- /acorn-globals@7.0.1:
- resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==}
+ acorn-globals@7.0.1:
dependencies:
- acorn: 8.8.2
- acorn-walk: 8.2.0
- dev: true
+ acorn: 8.15.0
+ acorn-walk: 8.3.4
- /acorn-walk@8.2.0:
- resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==}
- engines: {node: '>=0.4.0'}
- dev: true
+ acorn-walk@8.3.4:
+ dependencies:
+ acorn: 8.15.0
- /acorn@8.8.2:
- resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==}
- engines: {node: '>=0.4.0'}
- hasBin: true
- dev: true
+ acorn@8.15.0: {}
- /agent-base@6.0.2:
- resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
- engines: {node: '>= 6.0.0'}
+ agent-base@6.0.2:
dependencies:
- debug: 4.3.4
+ debug: 4.4.3
transitivePeerDependencies:
- supports-color
- dev: true
-
- /ansi-colors@4.1.3:
- resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
- engines: {node: '>=6'}
- dev: true
- /ansi-regex@5.0.1:
- resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
- engines: {node: '>=8'}
- dev: true
+ ansi-colors@4.1.3: {}
- /ansi-regex@6.0.1:
- resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
- engines: {node: '>=12'}
- dev: true
+ ansi-regex@5.0.1: {}
- /ansi-styles@3.2.1:
- resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
- engines: {node: '>=4'}
- dependencies:
- color-convert: 1.9.3
- dev: true
+ ansi-regex@6.2.2: {}
- /ansi-styles@4.3.0:
- resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
- engines: {node: '>=8'}
+ ansi-styles@4.3.0:
dependencies:
color-convert: 2.0.1
- dev: true
- /ansi-styles@5.2.0:
- resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
- engines: {node: '>=10'}
- dev: true
+ ansi-styles@5.2.0: {}
- /ansi-styles@6.2.1:
- resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
- engines: {node: '>=12'}
- dev: true
+ ansi-styles@6.2.3: {}
- /any-promise@1.3.0:
- resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
- dev: true
+ ansis@4.2.0: {}
- /anymatch@3.1.3:
- resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
- engines: {node: '>= 8'}
+ anymatch@3.1.3:
dependencies:
normalize-path: 3.0.0
picomatch: 2.3.1
- dev: true
- /arg@4.1.3:
- resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
- dev: true
+ arg@4.1.3: {}
- /argparse@1.0.10:
- resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
+ argparse@1.0.10:
dependencies:
sprintf-js: 1.0.3
- dev: true
- /aria-query@5.1.3:
- resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==}
+ aria-query@5.1.3:
dependencies:
- deep-equal: 2.2.0
- dev: true
+ deep-equal: 2.2.3
+
+ aria-query@5.3.2: {}
- /array-buffer-byte-length@1.0.0:
- resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==}
+ array-buffer-byte-length@1.0.2:
dependencies:
- call-bind: 1.0.2
- is-array-buffer: 3.0.2
- dev: true
+ call-bound: 1.0.4
+ is-array-buffer: 3.0.5
- /array-union@2.1.0:
- resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
- engines: {node: '>=8'}
- dev: true
+ array-union@2.1.0: {}
- /array.prototype.flat@1.3.1:
- resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==}
- engines: {node: '>= 0.4'}
- dependencies:
- call-bind: 1.0.2
- define-properties: 1.2.0
- es-abstract: 1.21.2
- es-shim-unscopables: 1.0.0
- dev: true
+ assertion-error@2.0.1: {}
- /arrify@1.0.1:
- resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==}
- engines: {node: '>=0.10.0'}
- dev: true
+ ast-kit@2.2.0:
+ dependencies:
+ '@babel/parser': 7.28.5
+ pathe: 2.0.3
- /assertion-error@2.0.1:
- resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
- engines: {node: '>=12'}
- dev: true
+ asynckit@0.4.0: {}
- /asynckit@0.4.0:
- resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
- dev: true
+ available-typed-arrays@1.0.7:
+ dependencies:
+ possible-typed-array-names: 1.1.0
- /available-typed-arrays@1.0.5:
- resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==}
- engines: {node: '>= 0.4'}
- dev: true
+ balanced-match@3.0.1: {}
- /balanced-match@1.0.2:
- resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
- dev: true
+ baseline-browser-mapping@2.8.18: {}
- /better-path-resolve@1.0.0:
- resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==}
- engines: {node: '>=4'}
+ better-path-resolve@1.0.0:
dependencies:
is-windows: 1.0.2
- dev: true
- /binary-extensions@2.2.0:
- resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
- engines: {node: '>=8'}
- dev: true
+ binary-extensions@2.3.0: {}
- /brace-expansion@1.1.11:
- resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
- dependencies:
- balanced-match: 1.0.2
- concat-map: 0.0.1
- dev: true
+ birpc@3.0.0: {}
- /brace-expansion@2.0.1:
- resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
+ brace-expansion@4.0.1:
dependencies:
- balanced-match: 1.0.2
- dev: true
+ balanced-match: 3.0.1
- /braces@3.0.3:
- resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
- engines: {node: '>=8'}
+ braces@3.0.3:
dependencies:
fill-range: 7.1.1
- dev: true
-
- /breakword@1.0.5:
- resolution: {integrity: sha512-ex5W9DoOQ/LUEU3PMdLs9ua/CYZl1678NUkKOdUSi8Aw5F1idieaiRURCBFJCwVcrD1J8Iy3vfWSloaMwO2qFg==}
- dependencies:
- wcwidth: 1.0.1
- dev: true
- /browserslist@4.23.2:
- resolution: {integrity: sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==}
- engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
- hasBin: true
+ browserslist@4.26.3:
dependencies:
- caniuse-lite: 1.0.30001642
- electron-to-chromium: 1.4.828
- node-releases: 2.0.14
- update-browserslist-db: 1.1.0(browserslist@4.23.2)
- dev: true
-
- /buffer-from@1.1.2:
- resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
- dev: true
+ baseline-browser-mapping: 2.8.18
+ caniuse-lite: 1.0.30001751
+ electron-to-chromium: 1.5.237
+ node-releases: 2.0.25
+ update-browserslist-db: 1.1.3(browserslist@4.26.3)
- /bundle-require@4.0.1(esbuild@0.17.17):
- resolution: {integrity: sha512-9NQkRHlNdNpDBGmLpngF3EFDcwodhMUuLz9PaWYciVcQF9SE4LFjM2DB/xV1Li5JiuDMv7ZUWuC3rGbqR0MAXQ==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
- peerDependencies:
- esbuild: '>=0.17'
- dependencies:
- esbuild: 0.17.17
- load-tsconfig: 0.2.5
- dev: true
+ buffer-from@1.1.2: {}
- /bytes-iec@3.1.1:
- resolution: {integrity: sha512-fey6+4jDK7TFtFg/klGSvNKJctyU7n2aQdnM+CO0ruLPbqqMOM8Tio0Pc+deqUeVKX1tL5DQep1zQ7+37aTAsA==}
- engines: {node: '>= 0.8'}
- dev: true
+ bytes-iec@3.1.1: {}
- /cac@6.7.14:
- resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
- engines: {node: '>=8'}
- dev: true
+ cac@6.7.14: {}
- /call-bind@1.0.2:
- resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==}
+ call-bind-apply-helpers@1.0.2:
dependencies:
- function-bind: 1.1.1
- get-intrinsic: 1.2.0
- dev: true
+ es-errors: 1.3.0
+ function-bind: 1.1.2
- /camelcase-keys@6.2.2:
- resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==}
- engines: {node: '>=8'}
+ call-bind@1.0.8:
dependencies:
- camelcase: 5.3.1
- map-obj: 4.3.0
- quick-lru: 4.0.1
- dev: true
+ call-bind-apply-helpers: 1.0.2
+ es-define-property: 1.0.1
+ get-intrinsic: 1.3.0
+ set-function-length: 1.2.2
- /camelcase@5.3.1:
- resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
- engines: {node: '>=6'}
- dev: true
+ call-bound@1.0.4:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ get-intrinsic: 1.3.0
- /caniuse-lite@1.0.30001642:
- resolution: {integrity: sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==}
- dev: true
+ caniuse-lite@1.0.30001751: {}
- /chai@5.1.1:
- resolution: {integrity: sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==}
- engines: {node: '>=12'}
+ chai@5.3.3:
dependencies:
assertion-error: 2.0.1
check-error: 2.1.1
deep-eql: 5.0.2
- loupe: 3.1.1
- pathval: 2.0.0
- dev: true
-
- /chalk@2.4.2:
- resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
- engines: {node: '>=4'}
- dependencies:
- ansi-styles: 3.2.1
- escape-string-regexp: 1.0.5
- supports-color: 5.5.0
- dev: true
+ loupe: 3.2.1
+ pathval: 2.0.1
- /chalk@3.0.0:
- resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==}
- engines: {node: '>=8'}
+ chalk@3.0.0:
dependencies:
ansi-styles: 4.3.0
supports-color: 7.2.0
- dev: true
- /chalk@4.1.2:
- resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
- engines: {node: '>=10'}
+ chalk@4.1.2:
dependencies:
ansi-styles: 4.3.0
supports-color: 7.2.0
- dev: true
- /chardet@0.7.0:
- resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==}
- dev: true
+ chardet@2.1.0: {}
- /check-error@2.1.1:
- resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==}
- engines: {node: '>= 16'}
- dev: true
+ check-error@2.1.1: {}
- /chokidar@3.5.3:
- resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
- engines: {node: '>= 8.10.0'}
+ chokidar@3.6.0:
dependencies:
anymatch: 3.1.3
braces: 3.0.3
glob-parent: 5.1.2
is-binary-path: 2.1.0
is-glob: 4.0.3
- normalize-path: 3.0.0
- readdirp: 3.6.0
- optionalDependencies:
- fsevents: 2.3.3
- dev: true
-
- /ci-info@3.8.0:
- resolution: {integrity: sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==}
- engines: {node: '>=8'}
- dev: true
-
- /cliui@6.0.0:
- resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==}
- dependencies:
- string-width: 4.2.3
- strip-ansi: 6.0.1
- wrap-ansi: 6.2.0
- dev: true
-
- /cliui@8.0.1:
- resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
- engines: {node: '>=12'}
- dependencies:
- string-width: 4.2.3
- strip-ansi: 6.0.1
- wrap-ansi: 7.0.0
- dev: true
+ normalize-path: 3.0.0
+ readdirp: 3.6.0
+ optionalDependencies:
+ fsevents: 2.3.3
- /clone@1.0.4:
- resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
- engines: {node: '>=0.8'}
- dev: true
+ ci-info@3.9.0: {}
- /color-convert@1.9.3:
- resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
- dependencies:
- color-name: 1.1.3
- dev: true
+ ci-info@4.3.1: {}
- /color-convert@2.0.1:
- resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
- engines: {node: '>=7.0.0'}
+ color-convert@2.0.1:
dependencies:
color-name: 1.1.4
- dev: true
-
- /color-name@1.1.3:
- resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
- dev: true
- /color-name@1.1.4:
- resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
- dev: true
+ color-name@1.1.4: {}
- /combined-stream@1.0.8:
- resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
- engines: {node: '>= 0.8'}
+ combined-stream@1.0.8:
dependencies:
delayed-stream: 1.0.0
- dev: true
-
- /commander@2.20.3:
- resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
- dev: true
-
- /commander@4.1.1:
- resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
- engines: {node: '>= 6'}
- dev: true
-
- /concat-map@0.0.1:
- resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
- dev: true
- /convert-source-map@2.0.0:
- resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
- dev: true
+ commander@2.20.3: {}
- /create-require@1.1.1:
- resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
- dev: true
+ convert-source-map@2.0.0: {}
- /cross-spawn@5.1.0:
- resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==}
- dependencies:
- lru-cache: 4.1.5
- shebang-command: 1.2.0
- which: 1.3.1
- dev: true
+ create-require@1.1.1: {}
- /cross-spawn@7.0.3:
- resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
- engines: {node: '>= 8'}
+ cross-spawn@7.0.6:
dependencies:
path-key: 3.1.1
shebang-command: 2.0.0
which: 2.0.2
- dev: true
- /css.escape@1.5.1:
- resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==}
- dev: true
+ css.escape@1.5.1: {}
- /cssstyle@3.0.0:
- resolution: {integrity: sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==}
- engines: {node: '>=14'}
+ cssstyle@3.0.0:
dependencies:
rrweb-cssom: 0.6.0
- dev: true
-
- /csstype@3.1.2:
- resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==}
- dev: true
- /csv-generate@3.4.3:
- resolution: {integrity: sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==}
- dev: true
+ csstype@3.1.3: {}
- /csv-parse@4.16.3:
- resolution: {integrity: sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==}
- dev: true
-
- /csv-stringify@5.6.5:
- resolution: {integrity: sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A==}
- dev: true
-
- /csv@5.5.3:
- resolution: {integrity: sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g==}
- engines: {node: '>= 0.1.90'}
- dependencies:
- csv-generate: 3.4.3
- csv-parse: 4.16.3
- csv-stringify: 5.6.5
- stream-transform: 2.1.3
- dev: true
-
- /data-urls@4.0.0:
- resolution: {integrity: sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==}
- engines: {node: '>=14'}
+ data-urls@4.0.0:
dependencies:
abab: 2.0.6
whatwg-mimetype: 3.0.0
whatwg-url: 12.0.1
- dev: true
-
- /debug@4.3.4:
- resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
- engines: {node: '>=6.0'}
- peerDependencies:
- supports-color: '*'
- peerDependenciesMeta:
- supports-color:
- optional: true
- dependencies:
- ms: 2.1.2
- dev: true
-
- /debug@4.3.5:
- resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==}
- engines: {node: '>=6.0'}
- peerDependencies:
- supports-color: '*'
- peerDependenciesMeta:
- supports-color:
- optional: true
- dependencies:
- ms: 2.1.2
- dev: true
- /decamelize-keys@1.1.1:
- resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==}
- engines: {node: '>=0.10.0'}
+ debug@4.4.3:
dependencies:
- decamelize: 1.2.0
- map-obj: 1.0.1
- dev: true
-
- /decamelize@1.2.0:
- resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
- engines: {node: '>=0.10.0'}
- dev: true
+ ms: 2.1.3
- /decimal.js@10.4.3:
- resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==}
- dev: true
+ decimal.js@10.6.0: {}
- /deep-eql@5.0.2:
- resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==}
- engines: {node: '>=6'}
- dev: true
+ deep-eql@5.0.2: {}
- /deep-equal@2.2.0:
- resolution: {integrity: sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==}
+ deep-equal@2.2.3:
dependencies:
- call-bind: 1.0.2
+ array-buffer-byte-length: 1.0.2
+ call-bind: 1.0.8
es-get-iterator: 1.1.3
- get-intrinsic: 1.2.0
- is-arguments: 1.1.1
- is-array-buffer: 3.0.2
- is-date-object: 1.0.5
- is-regex: 1.1.4
- is-shared-array-buffer: 1.0.2
+ get-intrinsic: 1.3.0
+ is-arguments: 1.2.0
+ is-array-buffer: 3.0.5
+ is-date-object: 1.1.0
+ is-regex: 1.2.1
+ is-shared-array-buffer: 1.0.4
isarray: 2.0.5
- object-is: 1.1.5
+ object-is: 1.1.6
object-keys: 1.1.1
- object.assign: 4.1.4
- regexp.prototype.flags: 1.5.0
- side-channel: 1.0.4
- which-boxed-primitive: 1.0.2
- which-collection: 1.0.1
- which-typed-array: 1.1.9
- dev: true
-
- /deep-is@0.1.4:
- resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
- dev: true
-
- /defaults@1.0.4:
- resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==}
- dependencies:
- clone: 1.0.4
- dev: true
-
- /define-properties@1.2.0:
- resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==}
- engines: {node: '>= 0.4'}
+ object.assign: 4.1.7
+ regexp.prototype.flags: 1.5.4
+ side-channel: 1.1.0
+ which-boxed-primitive: 1.1.1
+ which-collection: 1.0.2
+ which-typed-array: 1.1.19
+
+ define-data-property@1.1.4:
+ dependencies:
+ es-define-property: 1.0.1
+ es-errors: 1.3.0
+ gopd: 1.2.0
+
+ define-properties@1.2.1:
dependencies:
- has-property-descriptors: 1.0.0
+ define-data-property: 1.1.4
+ has-property-descriptors: 1.0.2
object-keys: 1.1.1
- dev: true
- /delayed-stream@1.0.0:
- resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
- engines: {node: '>=0.4.0'}
- dev: true
+ defu@6.1.4: {}
- /detect-indent@6.1.0:
- resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
- engines: {node: '>=8'}
- dev: true
+ delayed-stream@1.0.0: {}
- /diff-sequences@29.4.3:
- resolution: {integrity: sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
- dev: true
+ detect-indent@6.1.0: {}
- /diff@4.0.2:
- resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
- engines: {node: '>=0.3.1'}
- dev: true
+ diff@4.0.2: {}
- /dir-glob@3.0.1:
- resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
- engines: {node: '>=8'}
+ dir-glob@3.0.1:
dependencies:
path-type: 4.0.0
- dev: true
- /dom-accessibility-api@0.5.16:
- resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==}
- dev: true
+ dom-accessibility-api@0.5.16: {}
- /domexception@4.0.0:
- resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==}
- engines: {node: '>=12'}
+ domexception@4.0.0:
dependencies:
webidl-conversions: 7.0.0
- dev: true
- /eastasianwidth@0.2.0:
- resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
- dev: true
+ dts-resolver@2.1.3: {}
+
+ dunder-proto@1.0.1:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-errors: 1.3.0
+ gopd: 1.2.0
- /electron-to-chromium@1.4.828:
- resolution: {integrity: sha512-QOIJiWpQJDHAVO4P58pwb133Cwee0nbvy/MV1CwzZVGpkH1RX33N3vsaWRCpR6bF63AAq366neZrRTu7Qlsbbw==}
- dev: true
+ eastasianwidth@0.2.0: {}
- /emoji-regex@8.0.0:
- resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
- dev: true
+ electron-to-chromium@1.5.237: {}
- /emoji-regex@9.2.2:
- resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
- dev: true
+ emoji-regex@8.0.0: {}
- /enquirer@2.3.6:
- resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==}
- engines: {node: '>=8.6'}
+ emoji-regex@9.2.2: {}
+
+ empathic@2.0.0: {}
+
+ enquirer@2.4.1:
dependencies:
ansi-colors: 4.1.3
- dev: true
+ strip-ansi: 6.0.1
- /entities@4.5.0:
- resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
- engines: {node: '>=0.12'}
- dev: true
+ entities@6.0.1: {}
- /error-ex@1.3.2:
- resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
- dependencies:
- is-arrayish: 0.2.1
- dev: true
+ es-define-property@1.0.1: {}
- /es-abstract@1.21.2:
- resolution: {integrity: sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==}
- engines: {node: '>= 0.4'}
- dependencies:
- array-buffer-byte-length: 1.0.0
- available-typed-arrays: 1.0.5
- call-bind: 1.0.2
- es-set-tostringtag: 2.0.1
- es-to-primitive: 1.2.1
- function.prototype.name: 1.1.5
- get-intrinsic: 1.2.0
- get-symbol-description: 1.0.0
- globalthis: 1.0.3
- gopd: 1.0.1
- has: 1.0.3
- has-property-descriptors: 1.0.0
- has-proto: 1.0.1
- has-symbols: 1.0.3
- internal-slot: 1.0.5
- is-array-buffer: 3.0.2
- is-callable: 1.2.7
- is-negative-zero: 2.0.2
- is-regex: 1.1.4
- is-shared-array-buffer: 1.0.2
- is-string: 1.0.7
- is-typed-array: 1.1.10
- is-weakref: 1.0.2
- object-inspect: 1.12.3
- object-keys: 1.1.1
- object.assign: 4.1.4
- regexp.prototype.flags: 1.5.0
- safe-regex-test: 1.0.0
- string.prototype.trim: 1.2.7
- string.prototype.trimend: 1.0.6
- string.prototype.trimstart: 1.0.6
- typed-array-length: 1.0.4
- unbox-primitive: 1.0.2
- which-typed-array: 1.1.9
- dev: true
-
- /es-get-iterator@1.1.3:
- resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==}
+ es-errors@1.3.0: {}
+
+ es-get-iterator@1.1.3:
dependencies:
- call-bind: 1.0.2
- get-intrinsic: 1.2.0
- has-symbols: 1.0.3
- is-arguments: 1.1.1
- is-map: 2.0.2
- is-set: 2.0.2
- is-string: 1.0.7
+ call-bind: 1.0.8
+ get-intrinsic: 1.3.0
+ has-symbols: 1.1.0
+ is-arguments: 1.2.0
+ is-map: 2.0.3
+ is-set: 2.0.3
+ is-string: 1.1.1
isarray: 2.0.5
- stop-iteration-iterator: 1.0.0
- dev: true
+ stop-iteration-iterator: 1.1.0
- /es-set-tostringtag@2.0.1:
- resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==}
- engines: {node: '>= 0.4'}
- dependencies:
- get-intrinsic: 1.2.0
- has: 1.0.3
- has-tostringtag: 1.0.0
- dev: true
+ es-module-lexer@1.7.0: {}
- /es-shim-unscopables@1.0.0:
- resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==}
+ es-object-atoms@1.1.1:
dependencies:
- has: 1.0.3
- dev: true
+ es-errors: 1.3.0
- /es-to-primitive@1.2.1:
- resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==}
- engines: {node: '>= 0.4'}
+ es-set-tostringtag@2.1.0:
dependencies:
- is-callable: 1.2.7
- is-date-object: 1.0.5
- is-symbol: 1.0.4
- dev: true
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ has-tostringtag: 1.0.2
+ hasown: 2.0.2
- /esbuild@0.17.17:
- resolution: {integrity: sha512-/jUywtAymR8jR4qsa2RujlAF7Krpt5VWi72Q2yuLD4e/hvtNcFQ0I1j8m/bxq238pf3/0KO5yuXNpuLx8BE1KA==}
- engines: {node: '>=12'}
- hasBin: true
- requiresBuild: true
- optionalDependencies:
- '@esbuild/android-arm': 0.17.17
- '@esbuild/android-arm64': 0.17.17
- '@esbuild/android-x64': 0.17.17
- '@esbuild/darwin-arm64': 0.17.17
- '@esbuild/darwin-x64': 0.17.17
- '@esbuild/freebsd-arm64': 0.17.17
- '@esbuild/freebsd-x64': 0.17.17
- '@esbuild/linux-arm': 0.17.17
- '@esbuild/linux-arm64': 0.17.17
- '@esbuild/linux-ia32': 0.17.17
- '@esbuild/linux-loong64': 0.17.17
- '@esbuild/linux-mips64el': 0.17.17
- '@esbuild/linux-ppc64': 0.17.17
- '@esbuild/linux-riscv64': 0.17.17
- '@esbuild/linux-s390x': 0.17.17
- '@esbuild/linux-x64': 0.17.17
- '@esbuild/netbsd-x64': 0.17.17
- '@esbuild/openbsd-x64': 0.17.17
- '@esbuild/sunos-x64': 0.17.17
- '@esbuild/win32-arm64': 0.17.17
- '@esbuild/win32-ia32': 0.17.17
- '@esbuild/win32-x64': 0.17.17
- dev: true
-
- /esbuild@0.21.5:
- resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
- engines: {node: '>=12'}
- hasBin: true
- requiresBuild: true
+ esbuild@0.25.11:
optionalDependencies:
- '@esbuild/aix-ppc64': 0.21.5
- '@esbuild/android-arm': 0.21.5
- '@esbuild/android-arm64': 0.21.5
- '@esbuild/android-x64': 0.21.5
- '@esbuild/darwin-arm64': 0.21.5
- '@esbuild/darwin-x64': 0.21.5
- '@esbuild/freebsd-arm64': 0.21.5
- '@esbuild/freebsd-x64': 0.21.5
- '@esbuild/linux-arm': 0.21.5
- '@esbuild/linux-arm64': 0.21.5
- '@esbuild/linux-ia32': 0.21.5
- '@esbuild/linux-loong64': 0.21.5
- '@esbuild/linux-mips64el': 0.21.5
- '@esbuild/linux-ppc64': 0.21.5
- '@esbuild/linux-riscv64': 0.21.5
- '@esbuild/linux-s390x': 0.21.5
- '@esbuild/linux-x64': 0.21.5
- '@esbuild/netbsd-x64': 0.21.5
- '@esbuild/openbsd-x64': 0.21.5
- '@esbuild/sunos-x64': 0.21.5
- '@esbuild/win32-arm64': 0.21.5
- '@esbuild/win32-ia32': 0.21.5
- '@esbuild/win32-x64': 0.21.5
- dev: true
-
- /escalade@3.1.1:
- resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
- engines: {node: '>=6'}
- dev: true
-
- /escalade@3.1.2:
- resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==}
- engines: {node: '>=6'}
- dev: true
-
- /escape-string-regexp@1.0.5:
- resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
- engines: {node: '>=0.8.0'}
- dev: true
-
- /escape-string-regexp@2.0.0:
- resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==}
- engines: {node: '>=8'}
- dev: true
-
- /escodegen@2.0.0:
- resolution: {integrity: sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==}
- engines: {node: '>=6.0'}
- hasBin: true
+ '@esbuild/aix-ppc64': 0.25.11
+ '@esbuild/android-arm': 0.25.11
+ '@esbuild/android-arm64': 0.25.11
+ '@esbuild/android-x64': 0.25.11
+ '@esbuild/darwin-arm64': 0.25.11
+ '@esbuild/darwin-x64': 0.25.11
+ '@esbuild/freebsd-arm64': 0.25.11
+ '@esbuild/freebsd-x64': 0.25.11
+ '@esbuild/linux-arm': 0.25.11
+ '@esbuild/linux-arm64': 0.25.11
+ '@esbuild/linux-ia32': 0.25.11
+ '@esbuild/linux-loong64': 0.25.11
+ '@esbuild/linux-mips64el': 0.25.11
+ '@esbuild/linux-ppc64': 0.25.11
+ '@esbuild/linux-riscv64': 0.25.11
+ '@esbuild/linux-s390x': 0.25.11
+ '@esbuild/linux-x64': 0.25.11
+ '@esbuild/netbsd-arm64': 0.25.11
+ '@esbuild/netbsd-x64': 0.25.11
+ '@esbuild/openbsd-arm64': 0.25.11
+ '@esbuild/openbsd-x64': 0.25.11
+ '@esbuild/openharmony-arm64': 0.25.11
+ '@esbuild/sunos-x64': 0.25.11
+ '@esbuild/win32-arm64': 0.25.11
+ '@esbuild/win32-ia32': 0.25.11
+ '@esbuild/win32-x64': 0.25.11
+
+ escalade@3.2.0: {}
+
+ escape-string-regexp@2.0.0: {}
+
+ escodegen@2.1.0:
dependencies:
esprima: 4.0.1
estraverse: 5.3.0
esutils: 2.0.3
- optionator: 0.8.3
optionalDependencies:
source-map: 0.6.1
- dev: true
- /esprima@4.0.1:
- resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
- engines: {node: '>=4'}
- hasBin: true
- dev: true
+ esprima@4.0.1: {}
- /estraverse@5.3.0:
- resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
- engines: {node: '>=4.0'}
- dev: true
+ estraverse@5.3.0: {}
- /estree-walker@3.0.3:
- resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
+ estree-walker@3.0.3:
dependencies:
- '@types/estree': 1.0.5
- dev: true
+ '@types/estree': 1.0.8
- /esutils@2.0.3:
- resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
- engines: {node: '>=0.10.0'}
- dev: true
+ esutils@2.0.3: {}
- /execa@5.1.1:
- resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
- engines: {node: '>=10'}
- dependencies:
- cross-spawn: 7.0.3
- get-stream: 6.0.1
- human-signals: 2.1.0
- is-stream: 2.0.1
- merge-stream: 2.0.0
- npm-run-path: 4.0.1
- onetime: 5.1.2
- signal-exit: 3.0.7
- strip-final-newline: 2.0.0
- dev: true
-
- /execa@8.0.1:
- resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
- engines: {node: '>=16.17'}
- dependencies:
- cross-spawn: 7.0.3
- get-stream: 8.0.1
- human-signals: 5.0.0
- is-stream: 3.0.0
- merge-stream: 2.0.0
- npm-run-path: 5.3.0
- onetime: 6.0.0
- signal-exit: 4.1.0
- strip-final-newline: 3.0.0
- dev: true
+ expect-type@1.2.2: {}
- /expect@29.5.0:
- resolution: {integrity: sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ expect@30.2.0:
dependencies:
- '@jest/expect-utils': 29.5.0
- jest-get-type: 29.4.3
- jest-matcher-utils: 29.5.0
- jest-message-util: 29.5.0
- jest-util: 29.5.0
- dev: true
-
- /extendable-error@0.1.7:
- resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==}
- dev: true
+ '@jest/expect-utils': 30.2.0
+ '@jest/get-type': 30.1.0
+ jest-matcher-utils: 30.2.0
+ jest-message-util: 30.2.0
+ jest-mock: 30.2.0
+ jest-util: 30.2.0
- /external-editor@3.1.0:
- resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==}
- engines: {node: '>=4'}
- dependencies:
- chardet: 0.7.0
- iconv-lite: 0.4.24
- tmp: 0.0.33
- dev: true
+ extendable-error@0.1.7: {}
- /fast-glob@3.2.12:
- resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==}
- engines: {node: '>=8.6.0'}
+ fast-glob@3.3.3:
dependencies:
'@nodelib/fs.stat': 2.0.5
'@nodelib/fs.walk': 1.2.8
glob-parent: 5.1.2
merge2: 1.4.1
- micromatch: 4.0.5
- dev: true
+ micromatch: 4.0.8
- /fast-levenshtein@2.0.6:
- resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
- dev: true
-
- /fastq@1.15.0:
- resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==}
+ fastq@1.19.1:
dependencies:
- reusify: 1.0.4
- dev: true
+ reusify: 1.1.0
- /fill-range@7.1.1:
- resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
- engines: {node: '>=8'}
+ fdir@6.5.0(picomatch@4.0.3):
+ optionalDependencies:
+ picomatch: 4.0.3
+
+ fill-range@7.1.1:
dependencies:
to-regex-range: 5.0.1
- dev: true
- /find-up@4.1.0:
- resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
- engines: {node: '>=8'}
+ find-up@4.1.0:
dependencies:
locate-path: 5.0.0
path-exists: 4.0.0
- dev: true
-
- /find-up@5.0.0:
- resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
- engines: {node: '>=10'}
- dependencies:
- locate-path: 6.0.0
- path-exists: 4.0.0
- dev: true
-
- /find-yarn-workspace-root2@1.2.16:
- resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==}
- dependencies:
- micromatch: 4.0.5
- pkg-dir: 4.2.0
- dev: true
- /for-each@0.3.3:
- resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
+ for-each@0.3.5:
dependencies:
is-callable: 1.2.7
- dev: true
- /foreground-child@3.2.1:
- resolution: {integrity: sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==}
- engines: {node: '>=14'}
+ foreground-child@3.3.1:
dependencies:
- cross-spawn: 7.0.3
+ cross-spawn: 7.0.6
signal-exit: 4.1.0
- dev: true
- /form-data@4.0.0:
- resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
- engines: {node: '>= 6'}
+ form-data@4.0.4:
dependencies:
asynckit: 0.4.0
combined-stream: 1.0.8
+ es-set-tostringtag: 2.1.0
+ hasown: 2.0.2
mime-types: 2.1.35
- dev: true
- /fs-extra@7.0.1:
- resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==}
- engines: {node: '>=6 <7 || >=8'}
+ fs-extra@7.0.1:
dependencies:
graceful-fs: 4.2.11
jsonfile: 4.0.0
universalify: 0.1.2
- dev: true
- /fs-extra@8.1.0:
- resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==}
- engines: {node: '>=6 <7 || >=8'}
+ fs-extra@8.1.0:
dependencies:
graceful-fs: 4.2.11
jsonfile: 4.0.0
universalify: 0.1.2
- dev: true
-
- /fs.realpath@1.0.0:
- resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
- dev: true
- /fsevents@2.3.3:
- resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
- engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
- os: [darwin]
- requiresBuild: true
- dev: true
+ fsevents@2.3.3:
optional: true
- /function-bind@1.1.1:
- resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
- dev: true
-
- /function.prototype.name@1.1.5:
- resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==}
- engines: {node: '>= 0.4'}
- dependencies:
- call-bind: 1.0.2
- define-properties: 1.2.0
- es-abstract: 1.21.2
- functions-have-names: 1.2.3
- dev: true
-
- /functions-have-names@1.2.3:
- resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
- dev: true
-
- /gensync@1.0.0-beta.2:
- resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
- engines: {node: '>=6.9.0'}
- dev: true
+ function-bind@1.1.2: {}
- /get-caller-file@2.0.5:
- resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
- engines: {node: 6.* || 8.* || >= 10.*}
- dev: true
+ functions-have-names@1.2.3: {}
- /get-func-name@2.0.2:
- resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==}
- dev: true
+ gensync@1.0.0-beta.2: {}
- /get-intrinsic@1.2.0:
- resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==}
+ get-intrinsic@1.3.0:
dependencies:
- function-bind: 1.1.1
- has: 1.0.3
- has-symbols: 1.0.3
- dev: true
-
- /get-stream@6.0.1:
- resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
- engines: {node: '>=10'}
- dev: true
+ call-bind-apply-helpers: 1.0.2
+ es-define-property: 1.0.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ function-bind: 1.1.2
+ get-proto: 1.0.1
+ gopd: 1.2.0
+ has-symbols: 1.1.0
+ hasown: 2.0.2
+ math-intrinsics: 1.1.0
- /get-stream@8.0.1:
- resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==}
- engines: {node: '>=16'}
- dev: true
+ get-proto@1.0.1:
+ dependencies:
+ dunder-proto: 1.0.1
+ es-object-atoms: 1.1.1
- /get-symbol-description@1.0.0:
- resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==}
- engines: {node: '>= 0.4'}
+ get-tsconfig@4.13.0:
dependencies:
- call-bind: 1.0.2
- get-intrinsic: 1.2.0
- dev: true
+ resolve-pkg-maps: 1.0.0
- /glob-parent@5.1.2:
- resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
- engines: {node: '>= 6'}
+ glob-parent@5.1.2:
dependencies:
is-glob: 4.0.3
- dev: true
- /glob@10.4.5:
- resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
- hasBin: true
+ glob@10.4.5:
dependencies:
- foreground-child: 3.2.1
+ foreground-child: 3.3.1
jackspeak: 3.4.3
minimatch: 9.0.5
minipass: 7.1.2
- package-json-from-dist: 1.0.0
+ package-json-from-dist: 1.0.1
path-scurry: 1.11.1
- dev: true
-
- /glob@7.1.6:
- resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==}
- dependencies:
- fs.realpath: 1.0.0
- inflight: 1.0.6
- inherits: 2.0.4
- minimatch: 3.1.2
- once: 1.4.0
- path-is-absolute: 1.0.1
- dev: true
-
- /globals@11.12.0:
- resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
- engines: {node: '>=4'}
- dev: true
-
- /globalthis@1.0.3:
- resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==}
- engines: {node: '>= 0.4'}
- dependencies:
- define-properties: 1.2.0
- dev: true
- /globby@11.1.0:
- resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
- engines: {node: '>=10'}
+ globby@11.1.0:
dependencies:
array-union: 2.1.0
dir-glob: 3.0.1
- fast-glob: 3.2.12
- ignore: 5.2.4
+ fast-glob: 3.3.3
+ ignore: 5.3.2
merge2: 1.4.1
slash: 3.0.0
- dev: true
- /gopd@1.0.1:
- resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
- dependencies:
- get-intrinsic: 1.2.0
- dev: true
-
- /graceful-fs@4.2.11:
- resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
- dev: true
-
- /grapheme-splitter@1.0.4:
- resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==}
- dev: true
+ gopd@1.2.0: {}
- /hard-rejection@2.1.0:
- resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==}
- engines: {node: '>=6'}
- dev: true
-
- /has-bigints@1.0.2:
- resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==}
- dev: true
+ graceful-fs@4.2.11: {}
- /has-flag@3.0.0:
- resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
- engines: {node: '>=4'}
- dev: true
+ has-bigints@1.1.0: {}
- /has-flag@4.0.0:
- resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
- engines: {node: '>=8'}
- dev: true
+ has-flag@4.0.0: {}
- /has-property-descriptors@1.0.0:
- resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==}
+ has-property-descriptors@1.0.2:
dependencies:
- get-intrinsic: 1.2.0
- dev: true
-
- /has-proto@1.0.1:
- resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==}
- engines: {node: '>= 0.4'}
- dev: true
+ es-define-property: 1.0.1
- /has-symbols@1.0.3:
- resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
- engines: {node: '>= 0.4'}
- dev: true
+ has-symbols@1.1.0: {}
- /has-tostringtag@1.0.0:
- resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==}
- engines: {node: '>= 0.4'}
+ has-tostringtag@1.0.2:
dependencies:
- has-symbols: 1.0.3
- dev: true
+ has-symbols: 1.1.0
- /has@1.0.3:
- resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
- engines: {node: '>= 0.4.0'}
+ hasown@2.0.2:
dependencies:
- function-bind: 1.1.1
- dev: true
+ function-bind: 1.1.2
- /hosted-git-info@2.8.9:
- resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
- dev: true
+ hookable@5.5.3: {}
- /html-encoding-sniffer@3.0.0:
- resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==}
- engines: {node: '>=12'}
+ html-encoding-sniffer@3.0.0:
dependencies:
whatwg-encoding: 2.0.0
- dev: true
- /html-escaper@2.0.2:
- resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
- dev: true
+ html-escaper@2.0.2: {}
- /http-proxy-agent@5.0.0:
- resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==}
- engines: {node: '>= 6'}
+ http-proxy-agent@5.0.0:
dependencies:
'@tootallnate/once': 2.0.0
agent-base: 6.0.2
- debug: 4.3.4
+ debug: 4.4.3
transitivePeerDependencies:
- supports-color
- dev: true
- /https-proxy-agent@5.0.1:
- resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
- engines: {node: '>= 6'}
+ https-proxy-agent@5.0.1:
dependencies:
agent-base: 6.0.2
- debug: 4.3.4
+ debug: 4.4.3
transitivePeerDependencies:
- supports-color
- dev: true
- /human-id@1.0.2:
- resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==}
- dev: true
+ human-id@4.1.2: {}
- /human-signals@2.1.0:
- resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
- engines: {node: '>=10.17.0'}
- dev: true
-
- /human-signals@5.0.0:
- resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
- engines: {node: '>=16.17.0'}
- dev: true
-
- /iconv-lite@0.4.24:
- resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
- engines: {node: '>=0.10.0'}
+ iconv-lite@0.6.3:
dependencies:
safer-buffer: 2.1.2
- dev: true
- /iconv-lite@0.6.3:
- resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
- engines: {node: '>=0.10.0'}
+ iconv-lite@0.7.0:
dependencies:
safer-buffer: 2.1.2
- dev: true
-
- /ignore@5.2.4:
- resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==}
- engines: {node: '>= 4'}
- dev: true
-
- /indent-string@4.0.0:
- resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
- engines: {node: '>=8'}
- dev: true
- /inflight@1.0.6:
- resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
- dependencies:
- once: 1.4.0
- wrappy: 1.0.2
- dev: true
+ ignore@5.3.2: {}
- /inherits@2.0.4:
- resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
- dev: true
+ import-without-cache@0.2.3: {}
- /internal-slot@1.0.5:
- resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==}
- engines: {node: '>= 0.4'}
- dependencies:
- get-intrinsic: 1.2.0
- has: 1.0.3
- side-channel: 1.0.4
- dev: true
+ indent-string@4.0.0: {}
- /is-arguments@1.1.1:
- resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==}
- engines: {node: '>= 0.4'}
+ internal-slot@1.1.0:
dependencies:
- call-bind: 1.0.2
- has-tostringtag: 1.0.0
- dev: true
+ es-errors: 1.3.0
+ hasown: 2.0.2
+ side-channel: 1.1.0
- /is-array-buffer@3.0.2:
- resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==}
+ is-arguments@1.2.0:
dependencies:
- call-bind: 1.0.2
- get-intrinsic: 1.2.0
- is-typed-array: 1.1.10
- dev: true
+ call-bound: 1.0.4
+ has-tostringtag: 1.0.2
- /is-arrayish@0.2.1:
- resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
- dev: true
-
- /is-bigint@1.0.4:
- resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
+ is-array-buffer@3.0.5:
dependencies:
- has-bigints: 1.0.2
- dev: true
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
- /is-binary-path@2.1.0:
- resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
- engines: {node: '>=8'}
+ is-bigint@1.1.0:
dependencies:
- binary-extensions: 2.2.0
- dev: true
+ has-bigints: 1.1.0
- /is-boolean-object@1.1.2:
- resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
- engines: {node: '>= 0.4'}
+ is-binary-path@2.1.0:
dependencies:
- call-bind: 1.0.2
- has-tostringtag: 1.0.0
- dev: true
-
- /is-callable@1.2.7:
- resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
- engines: {node: '>= 0.4'}
- dev: true
+ binary-extensions: 2.3.0
- /is-ci@3.0.1:
- resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==}
- hasBin: true
+ is-boolean-object@1.2.2:
dependencies:
- ci-info: 3.8.0
- dev: true
+ call-bound: 1.0.4
+ has-tostringtag: 1.0.2
- /is-core-module@2.12.0:
- resolution: {integrity: sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==}
- dependencies:
- has: 1.0.3
- dev: true
+ is-callable@1.2.7: {}
- /is-date-object@1.0.5:
- resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
- engines: {node: '>= 0.4'}
+ is-date-object@1.1.0:
dependencies:
- has-tostringtag: 1.0.0
- dev: true
+ call-bound: 1.0.4
+ has-tostringtag: 1.0.2
- /is-extglob@2.1.1:
- resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
- engines: {node: '>=0.10.0'}
- dev: true
+ is-extglob@2.1.1: {}
- /is-fullwidth-code-point@3.0.0:
- resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
- engines: {node: '>=8'}
- dev: true
+ is-fullwidth-code-point@3.0.0: {}
- /is-glob@4.0.3:
- resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
- engines: {node: '>=0.10.0'}
+ is-glob@4.0.3:
dependencies:
is-extglob: 2.1.1
- dev: true
- /is-map@2.0.2:
- resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==}
- dev: true
-
- /is-negative-zero@2.0.2:
- resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==}
- engines: {node: '>= 0.4'}
- dev: true
+ is-map@2.0.3: {}
- /is-number-object@1.0.7:
- resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==}
- engines: {node: '>= 0.4'}
+ is-number-object@1.1.1:
dependencies:
- has-tostringtag: 1.0.0
- dev: true
-
- /is-number@7.0.0:
- resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
- engines: {node: '>=0.12.0'}
- dev: true
+ call-bound: 1.0.4
+ has-tostringtag: 1.0.2
- /is-plain-obj@1.1.0:
- resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==}
- engines: {node: '>=0.10.0'}
- dev: true
+ is-number@7.0.0: {}
- /is-potential-custom-element-name@1.0.1:
- resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
- dev: true
+ is-potential-custom-element-name@1.0.1: {}
- /is-regex@1.1.4:
- resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
- engines: {node: '>= 0.4'}
+ is-regex@1.2.1:
dependencies:
- call-bind: 1.0.2
- has-tostringtag: 1.0.0
- dev: true
+ call-bound: 1.0.4
+ gopd: 1.2.0
+ has-tostringtag: 1.0.2
+ hasown: 2.0.2
- /is-set@2.0.2:
- resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==}
- dev: true
+ is-set@2.0.3: {}
- /is-shared-array-buffer@1.0.2:
- resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==}
+ is-shared-array-buffer@1.0.4:
dependencies:
- call-bind: 1.0.2
- dev: true
-
- /is-stream@2.0.1:
- resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
- engines: {node: '>=8'}
- dev: true
-
- /is-stream@3.0.0:
- resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
- dev: true
+ call-bound: 1.0.4
- /is-string@1.0.7:
- resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==}
- engines: {node: '>= 0.4'}
+ is-string@1.1.1:
dependencies:
- has-tostringtag: 1.0.0
- dev: true
+ call-bound: 1.0.4
+ has-tostringtag: 1.0.2
- /is-subdir@1.2.0:
- resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==}
- engines: {node: '>=4'}
+ is-subdir@1.2.0:
dependencies:
better-path-resolve: 1.0.0
- dev: true
-
- /is-symbol@1.0.4:
- resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==}
- engines: {node: '>= 0.4'}
- dependencies:
- has-symbols: 1.0.3
- dev: true
- /is-typed-array@1.1.10:
- resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==}
- engines: {node: '>= 0.4'}
+ is-symbol@1.1.1:
dependencies:
- available-typed-arrays: 1.0.5
- call-bind: 1.0.2
- for-each: 0.3.3
- gopd: 1.0.1
- has-tostringtag: 1.0.0
- dev: true
-
- /is-weakmap@2.0.1:
- resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==}
- dev: true
+ call-bound: 1.0.4
+ has-symbols: 1.1.0
+ safe-regex-test: 1.1.0
- /is-weakref@1.0.2:
- resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==}
- dependencies:
- call-bind: 1.0.2
- dev: true
+ is-weakmap@2.0.2: {}
- /is-weakset@2.0.2:
- resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==}
+ is-weakset@2.0.4:
dependencies:
- call-bind: 1.0.2
- get-intrinsic: 1.2.0
- dev: true
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
- /is-windows@1.0.2:
- resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==}
- engines: {node: '>=0.10.0'}
- dev: true
+ is-windows@1.0.2: {}
- /isarray@2.0.5:
- resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
- dev: true
+ isarray@2.0.5: {}
- /isexe@2.0.0:
- resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
- dev: true
+ isexe@2.0.0: {}
- /istanbul-lib-coverage@3.2.2:
- resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==}
- engines: {node: '>=8'}
- dev: true
+ istanbul-lib-coverage@3.2.2: {}
- /istanbul-lib-instrument@6.0.3:
- resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==}
- engines: {node: '>=10'}
+ istanbul-lib-instrument@6.0.3:
dependencies:
- '@babel/core': 7.24.9
- '@babel/parser': 7.24.8
+ '@babel/core': 7.28.4
+ '@babel/parser': 7.28.4
'@istanbuljs/schema': 0.1.3
istanbul-lib-coverage: 3.2.2
- semver: 7.6.2
+ semver: 7.7.3
transitivePeerDependencies:
- supports-color
- dev: true
- /istanbul-lib-report@3.0.1:
- resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==}
- engines: {node: '>=10'}
+ istanbul-lib-report@3.0.1:
dependencies:
istanbul-lib-coverage: 3.2.2
make-dir: 4.0.0
supports-color: 7.2.0
- dev: true
- /istanbul-lib-source-maps@5.0.6:
- resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==}
- engines: {node: '>=10'}
+ istanbul-lib-source-maps@5.0.6:
dependencies:
- '@jridgewell/trace-mapping': 0.3.25
- debug: 4.3.5
+ '@jridgewell/trace-mapping': 0.3.31
+ debug: 4.4.3
istanbul-lib-coverage: 3.2.2
transitivePeerDependencies:
- supports-color
- dev: true
- /istanbul-reports@3.1.7:
- resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==}
- engines: {node: '>=8'}
+ istanbul-reports@3.2.0:
dependencies:
html-escaper: 2.0.2
istanbul-lib-report: 3.0.1
- dev: true
- /jackspeak@3.4.3:
- resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
+ jackspeak@3.4.3:
dependencies:
'@isaacs/cliui': 8.0.2
optionalDependencies:
'@pkgjs/parseargs': 0.11.0
- dev: true
- /jest-diff@29.5.0:
- resolution: {integrity: sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ jest-diff@30.2.0:
dependencies:
+ '@jest/diff-sequences': 30.0.1
+ '@jest/get-type': 30.1.0
chalk: 4.1.2
- diff-sequences: 29.4.3
- jest-get-type: 29.4.3
- pretty-format: 29.5.0
- dev: true
-
- /jest-get-type@29.4.3:
- resolution: {integrity: sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
- dev: true
+ pretty-format: 30.2.0
- /jest-matcher-utils@29.5.0:
- resolution: {integrity: sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ jest-matcher-utils@30.2.0:
dependencies:
+ '@jest/get-type': 30.1.0
chalk: 4.1.2
- jest-diff: 29.5.0
- jest-get-type: 29.4.3
- pretty-format: 29.5.0
- dev: true
-
- /jest-message-util@29.5.0:
- resolution: {integrity: sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
- dependencies:
- '@babel/code-frame': 7.21.4
- '@jest/types': 29.5.0
- '@types/stack-utils': 2.0.1
+ jest-diff: 30.2.0
+ pretty-format: 30.2.0
+
+ jest-message-util@30.2.0:
+ dependencies:
+ '@babel/code-frame': 7.27.1
+ '@jest/types': 30.2.0
+ '@types/stack-utils': 2.0.3
chalk: 4.1.2
graceful-fs: 4.2.11
- micromatch: 4.0.5
- pretty-format: 29.5.0
+ micromatch: 4.0.8
+ pretty-format: 30.2.0
slash: 3.0.0
stack-utils: 2.0.6
- dev: true
- /jest-util@29.5.0:
- resolution: {integrity: sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ jest-mock@30.2.0:
dependencies:
- '@jest/types': 29.5.0
- '@types/node': 18.15.13
+ '@jest/types': 30.2.0
+ '@types/node': 22.18.11
+ jest-util: 30.2.0
+
+ jest-regex-util@30.0.1: {}
+
+ jest-util@30.2.0:
+ dependencies:
+ '@jest/types': 30.2.0
+ '@types/node': 22.18.11
chalk: 4.1.2
- ci-info: 3.8.0
+ ci-info: 4.3.1
graceful-fs: 4.2.11
- picomatch: 2.3.1
- dev: true
+ picomatch: 4.0.3
- /joycon@3.1.1:
- resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
- engines: {node: '>=10'}
- dev: true
+ js-tokens@4.0.0: {}
- /js-tokens@4.0.0:
- resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+ js-tokens@9.0.1: {}
- /js-yaml@3.14.1:
- resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
- hasBin: true
+ js-yaml@3.14.1:
dependencies:
argparse: 1.0.10
esprima: 4.0.1
- dev: true
- /jsdom@21.1.1:
- resolution: {integrity: sha512-Jjgdmw48RKcdAIQyUD1UdBh2ecH7VqwaXPN3ehoZN6MqgVbMn+lRm1aAT1AsdJRAJpwfa4IpwgzySn61h2qu3w==}
- engines: {node: '>=14'}
- peerDependencies:
- canvas: ^2.5.0
- peerDependenciesMeta:
- canvas:
- optional: true
+ jsdom@21.1.2:
dependencies:
abab: 2.0.6
- acorn: 8.8.2
+ acorn: 8.15.0
acorn-globals: 7.0.1
cssstyle: 3.0.0
data-urls: 4.0.0
- decimal.js: 10.4.3
+ decimal.js: 10.6.0
domexception: 4.0.0
- escodegen: 2.0.0
- form-data: 4.0.0
+ escodegen: 2.1.0
+ form-data: 4.0.4
html-encoding-sniffer: 3.0.0
http-proxy-agent: 5.0.0
https-proxy-agent: 5.0.1
is-potential-custom-element-name: 1.0.1
- nwsapi: 2.2.4
- parse5: 7.1.2
+ nwsapi: 2.2.22
+ parse5: 7.3.0
rrweb-cssom: 0.6.0
saxes: 6.0.0
symbol-tree: 3.2.4
- tough-cookie: 4.1.4
+ tough-cookie: 6.0.0
w3c-xmlserializer: 4.0.0
webidl-conversions: 7.0.0
whatwg-encoding: 2.0.0
whatwg-mimetype: 3.0.0
whatwg-url: 12.0.1
- ws: 8.18.0
+ ws: 8.18.3
xml-name-validator: 4.0.0
transitivePeerDependencies:
- bufferutil
- supports-color
- utf-8-validate
- dev: true
-
- /jsesc@2.5.2:
- resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
- engines: {node: '>=4'}
- hasBin: true
- dev: true
- /json-parse-even-better-errors@2.3.1:
- resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
- dev: true
+ jsesc@3.1.0: {}
- /json5@2.2.3:
- resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
- engines: {node: '>=6'}
- hasBin: true
- dev: true
+ json5@2.2.3: {}
- /jsonfile@4.0.0:
- resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==}
+ jsonfile@4.0.0:
optionalDependencies:
graceful-fs: 4.2.11
- dev: true
-
- /kind-of@6.0.3:
- resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
- engines: {node: '>=0.10.0'}
- dev: true
-
- /kleur@4.1.5:
- resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
- engines: {node: '>=6'}
- dev: true
-
- /levn@0.3.0:
- resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==}
- engines: {node: '>= 0.8.0'}
- dependencies:
- prelude-ls: 1.1.2
- type-check: 0.3.2
- dev: true
-
- /lilconfig@2.1.0:
- resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==}
- engines: {node: '>=10'}
- dev: true
-
- /lines-and-columns@1.2.4:
- resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
- dev: true
-
- /load-tsconfig@0.2.5:
- resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
- dev: true
- /load-yaml-file@0.2.0:
- resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==}
- engines: {node: '>=6'}
- dependencies:
- graceful-fs: 4.2.11
- js-yaml: 3.14.1
- pify: 4.0.1
- strip-bom: 3.0.0
- dev: true
+ lilconfig@2.1.0: {}
- /locate-path@5.0.0:
- resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
- engines: {node: '>=8'}
+ locate-path@5.0.0:
dependencies:
p-locate: 4.1.0
- dev: true
- /locate-path@6.0.0:
- resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
- engines: {node: '>=10'}
- dependencies:
- p-locate: 5.0.0
- dev: true
-
- /lodash.sortby@4.7.0:
- resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==}
- dev: true
-
- /lodash.startcase@4.4.0:
- resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==}
- dev: true
+ lodash.startcase@4.4.0: {}
- /lodash@4.17.21:
- resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
- dev: true
+ lodash@4.17.21: {}
- /loose-envify@1.4.0:
- resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
- hasBin: true
+ loose-envify@1.4.0:
dependencies:
js-tokens: 4.0.0
- /loupe@3.1.1:
- resolution: {integrity: sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==}
- dependencies:
- get-func-name: 2.0.2
- dev: true
+ loupe@3.2.1: {}
- /lru-cache@10.4.3:
- resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
- dev: true
+ lru-cache@10.4.3: {}
- /lru-cache@4.1.5:
- resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==}
+ lru-cache@5.1.1:
dependencies:
- pseudomap: 1.0.2
- yallist: 2.1.2
- dev: true
+ yallist: 3.1.1
- /lru-cache@5.1.1:
- resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+ lru-cache@6.0.0:
dependencies:
- yallist: 3.1.1
- dev: true
+ yallist: 4.0.0
- /lz-string@1.5.0:
- resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==}
- hasBin: true
- dev: true
+ lz-string@1.5.0: {}
- /magic-string@0.30.10:
- resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==}
+ magic-string@0.30.19:
dependencies:
- '@jridgewell/sourcemap-codec': 1.4.15
- dev: true
+ '@jridgewell/sourcemap-codec': 1.5.5
- /magicast@0.3.4:
- resolution: {integrity: sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==}
+ magic-string@0.30.21:
dependencies:
- '@babel/parser': 7.24.8
- '@babel/types': 7.24.9
- source-map-js: 1.2.0
- dev: true
+ '@jridgewell/sourcemap-codec': 1.5.5
- /make-dir@4.0.0:
- resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
- engines: {node: '>=10'}
+ magicast@0.3.5:
dependencies:
- semver: 7.6.2
- dev: true
-
- /make-error@1.3.6:
- resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
- dev: true
-
- /map-obj@1.0.1:
- resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==}
- engines: {node: '>=0.10.0'}
- dev: true
-
- /map-obj@4.3.0:
- resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==}
- engines: {node: '>=8'}
- dev: true
+ '@babel/parser': 7.28.4
+ '@babel/types': 7.28.4
+ source-map-js: 1.2.1
- /meow@6.1.1:
- resolution: {integrity: sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==}
- engines: {node: '>=8'}
+ make-dir@4.0.0:
dependencies:
- '@types/minimist': 1.2.2
- camelcase-keys: 6.2.2
- decamelize-keys: 1.1.1
- hard-rejection: 2.1.0
- minimist-options: 4.1.0
- normalize-package-data: 2.5.0
- read-pkg-up: 7.0.1
- redent: 3.0.0
- trim-newlines: 3.0.1
- type-fest: 0.13.1
- yargs-parser: 18.1.3
- dev: true
+ semver: 7.7.3
- /merge-stream@2.0.0:
- resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
- dev: true
+ make-error@1.3.6: {}
- /merge2@1.4.1:
- resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
- engines: {node: '>= 8'}
- dev: true
+ math-intrinsics@1.1.0: {}
- /micromatch@4.0.5:
- resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
- engines: {node: '>=8.6'}
+ merge2@1.4.1: {}
+
+ micromatch@4.0.8:
dependencies:
braces: 3.0.3
picomatch: 2.3.1
- dev: true
- /mime-db@1.52.0:
- resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
- engines: {node: '>= 0.6'}
- dev: true
+ mime-db@1.52.0: {}
- /mime-types@2.1.35:
- resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
- engines: {node: '>= 0.6'}
+ mime-types@2.1.35:
dependencies:
mime-db: 1.52.0
- dev: true
-
- /mimic-fn@2.1.0:
- resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
- engines: {node: '>=6'}
- dev: true
-
- /mimic-fn@4.0.0:
- resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
- engines: {node: '>=12'}
- dev: true
-
- /min-indent@1.0.1:
- resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
- engines: {node: '>=4'}
- dev: true
- /minimatch@3.1.2:
- resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
- dependencies:
- brace-expansion: 1.1.11
- dev: true
-
- /minimatch@9.0.5:
- resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
- engines: {node: '>=16 || 14 >=14.17'}
- dependencies:
- brace-expansion: 2.0.1
- dev: true
-
- /minimist-options@4.1.0:
- resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==}
- engines: {node: '>= 6'}
- dependencies:
- arrify: 1.0.1
- is-plain-obj: 1.1.0
- kind-of: 6.0.3
- dev: true
+ min-indent@1.0.1: {}
- /minipass@7.1.2:
- resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
- engines: {node: '>=16 || 14 >=14.17'}
- dev: true
-
- /mixme@0.5.9:
- resolution: {integrity: sha512-VC5fg6ySUscaWUpI4gxCBTQMH2RdUpNrk+MsbpCYtIvf9SBJdiUey4qE7BXviJsJR4nDQxCZ+3yaYNW3guz/Pw==}
- engines: {node: '>= 8.0.0'}
- dev: true
-
- /ms@2.1.2:
- resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
- dev: true
-
- /mz@2.7.0:
- resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
+ minimatch@9.0.5:
dependencies:
- any-promise: 1.3.0
- object-assign: 4.1.1
- thenify-all: 1.6.0
- dev: true
-
- /nanoid@3.3.6:
- resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==}
- engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
- hasBin: true
- dev: true
+ brace-expansion: 4.0.1
- /nanoid@3.3.7:
- resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
- engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
- hasBin: true
- dev: true
+ minipass@7.1.2: {}
- /nanospinner@1.1.0:
- resolution: {integrity: sha512-yFvNYMig4AthKYfHFl1sLj7B2nkHL4lzdig4osvl9/LdGbXwrdFRoqBS98gsEsOakr0yH+r5NZ/1Y9gdVB8trA==}
- dependencies:
- picocolors: 1.0.0
- dev: true
+ mri@1.2.0: {}
- /node-releases@2.0.14:
- resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
- dev: true
+ ms@2.1.3: {}
- /normalize-package-data@2.5.0:
- resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
- dependencies:
- hosted-git-info: 2.8.9
- resolve: 1.22.2
- semver: 7.6.2
- validate-npm-package-license: 3.0.4
- dev: true
+ nanoid@3.3.11: {}
- /normalize-path@3.0.0:
- resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
- engines: {node: '>=0.10.0'}
- dev: true
+ nanoid@5.1.6: {}
- /npm-run-path@4.0.1:
- resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
- engines: {node: '>=8'}
+ nanospinner@1.2.2:
dependencies:
- path-key: 3.1.1
- dev: true
+ picocolors: 1.1.1
- /npm-run-path@5.3.0:
- resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
- dependencies:
- path-key: 4.0.0
- dev: true
+ node-releases@2.0.25: {}
- /nwsapi@2.2.4:
- resolution: {integrity: sha512-NHj4rzRo0tQdijE9ZqAx6kYDcoRwYwSYzCA8MY3JzfxlrvEU0jhnhJT9BhqhJs7I/dKcrDm6TyulaRqZPIhN5g==}
- dev: true
+ normalize-path@3.0.0: {}
- /object-assign@4.1.1:
- resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
- engines: {node: '>=0.10.0'}
- dev: true
+ nwsapi@2.2.22: {}
- /object-inspect@1.12.3:
- resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==}
- dev: true
+ object-inspect@1.13.4: {}
- /object-is@1.1.5:
- resolution: {integrity: sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==}
- engines: {node: '>= 0.4'}
+ object-is@1.1.6:
dependencies:
- call-bind: 1.0.2
- define-properties: 1.2.0
- dev: true
+ call-bind: 1.0.8
+ define-properties: 1.2.1
- /object-keys@1.1.1:
- resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
- engines: {node: '>= 0.4'}
- dev: true
+ object-keys@1.1.1: {}
- /object.assign@4.1.4:
- resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==}
- engines: {node: '>= 0.4'}
+ object.assign@4.1.7:
dependencies:
- call-bind: 1.0.2
- define-properties: 1.2.0
- has-symbols: 1.0.3
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-object-atoms: 1.1.1
+ has-symbols: 1.1.0
object-keys: 1.1.1
- dev: true
-
- /once@1.4.0:
- resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
- dependencies:
- wrappy: 1.0.2
- dev: true
- /onetime@5.1.2:
- resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
- engines: {node: '>=6'}
- dependencies:
- mimic-fn: 2.1.0
- dev: true
-
- /onetime@6.0.0:
- resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
- engines: {node: '>=12'}
- dependencies:
- mimic-fn: 4.0.0
- dev: true
-
- /optionator@0.8.3:
- resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==}
- engines: {node: '>= 0.8.0'}
- dependencies:
- deep-is: 0.1.4
- fast-levenshtein: 2.0.6
- levn: 0.3.0
- prelude-ls: 1.1.2
- type-check: 0.3.2
- word-wrap: 1.2.5
- dev: true
-
- /os-tmpdir@1.0.2:
- resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==}
- engines: {node: '>=0.10.0'}
- dev: true
+ obug@2.1.1: {}
- /outdent@0.5.0:
- resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==}
- dev: true
+ outdent@0.5.0: {}
- /p-filter@2.1.0:
- resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==}
- engines: {node: '>=8'}
+ p-filter@2.1.0:
dependencies:
p-map: 2.1.0
- dev: true
- /p-limit@2.3.0:
- resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
- engines: {node: '>=6'}
+ p-limit@2.3.0:
dependencies:
p-try: 2.2.0
- dev: true
-
- /p-limit@3.1.0:
- resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
- engines: {node: '>=10'}
- dependencies:
- yocto-queue: 0.1.0
- dev: true
- /p-locate@4.1.0:
- resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
- engines: {node: '>=8'}
+ p-locate@4.1.0:
dependencies:
p-limit: 2.3.0
- dev: true
-
- /p-locate@5.0.0:
- resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
- engines: {node: '>=10'}
- dependencies:
- p-limit: 3.1.0
- dev: true
- /p-map@2.1.0:
- resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==}
- engines: {node: '>=6'}
- dev: true
+ p-map@2.1.0: {}
- /p-try@2.2.0:
- resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
- engines: {node: '>=6'}
- dev: true
+ p-try@2.2.0: {}
- /package-json-from-dist@1.0.0:
- resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==}
- dev: true
+ package-json-from-dist@1.0.1: {}
- /parse-json@5.2.0:
- resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
- engines: {node: '>=8'}
+ package-manager-detector@0.2.11:
dependencies:
- '@babel/code-frame': 7.21.4
- error-ex: 1.3.2
- json-parse-even-better-errors: 2.3.1
- lines-and-columns: 1.2.4
- dev: true
+ quansync: 0.2.11
- /parse5@7.1.2:
- resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==}
+ parse5@7.3.0:
dependencies:
- entities: 4.5.0
- dev: true
-
- /path-exists@4.0.0:
- resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
- engines: {node: '>=8'}
- dev: true
-
- /path-is-absolute@1.0.1:
- resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
- engines: {node: '>=0.10.0'}
- dev: true
+ entities: 6.0.1
- /path-key@3.1.1:
- resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
- engines: {node: '>=8'}
- dev: true
-
- /path-key@4.0.0:
- resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==}
- engines: {node: '>=12'}
- dev: true
+ path-exists@4.0.0: {}
- /path-parse@1.0.7:
- resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
- dev: true
+ path-key@3.1.1: {}
- /path-scurry@1.11.1:
- resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
- engines: {node: '>=16 || 14 >=14.18'}
+ path-scurry@1.11.1:
dependencies:
lru-cache: 10.4.3
minipass: 7.1.2
- dev: true
-
- /path-type@4.0.0:
- resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
- engines: {node: '>=8'}
- dev: true
-
- /pathe@1.1.2:
- resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
- dev: true
-
- /pathval@2.0.0:
- resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==}
- engines: {node: '>= 14.16'}
- dev: true
- /picocolors@1.0.0:
- resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
- dev: true
+ path-type@4.0.0: {}
- /picocolors@1.0.1:
- resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==}
- dev: true
+ pathe@2.0.3: {}
- /picomatch@2.3.1:
- resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
- engines: {node: '>=8.6'}
- dev: true
+ pathval@2.0.1: {}
- /pify@4.0.1:
- resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
- engines: {node: '>=6'}
- dev: true
+ picocolors@1.1.1: {}
- /pirates@4.0.5:
- resolution: {integrity: sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==}
- engines: {node: '>= 6'}
- dev: true
+ picomatch@2.3.1: {}
- /pkg-dir@4.2.0:
- resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==}
- engines: {node: '>=8'}
- dependencies:
- find-up: 4.1.0
- dev: true
+ picomatch@4.0.3: {}
- /postcss-load-config@3.1.4(ts-node@10.9.1):
- resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==}
- engines: {node: '>= 10'}
- peerDependencies:
- postcss: '>=8.0.9'
- ts-node: '>=9.0.0'
- peerDependenciesMeta:
- postcss:
- optional: true
- ts-node:
- optional: true
- dependencies:
- lilconfig: 2.1.0
- ts-node: 10.9.1(@types/node@18.15.13)(typescript@5.0.4)
- yaml: 1.10.2
- dev: true
+ pify@4.0.1: {}
- /postcss@8.4.39:
- resolution: {integrity: sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==}
- engines: {node: ^10 || ^12 || >=14}
- dependencies:
- nanoid: 3.3.7
- picocolors: 1.0.1
- source-map-js: 1.2.0
- dev: true
+ possible-typed-array-names@1.1.0: {}
- /preferred-pm@3.0.3:
- resolution: {integrity: sha512-+wZgbxNES/KlJs9q40F/1sfOd/j7f1O9JaHcW5Dsn3aUUOZg3L2bjpVUcKV2jvtElYfoTuQiNeMfQJ4kwUAhCQ==}
- engines: {node: '>=10'}
+ postcss@8.5.6:
dependencies:
- find-up: 5.0.0
- find-yarn-workspace-root2: 1.2.16
- path-exists: 4.0.0
- which-pm: 2.0.0
- dev: true
+ nanoid: 3.3.11
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
- /prelude-ls@1.1.2:
- resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==}
- engines: {node: '>= 0.8.0'}
- dev: true
+ prettier@2.8.8: {}
- /prettier@2.8.7:
- resolution: {integrity: sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==}
- engines: {node: '>=10.13.0'}
- hasBin: true
- dev: true
-
- /pretty-format@27.5.1:
- resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==}
- engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
+ pretty-format@27.5.1:
dependencies:
ansi-regex: 5.0.1
ansi-styles: 5.2.0
react-is: 17.0.2
- dev: true
- /pretty-format@29.5.0:
- resolution: {integrity: sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ pretty-format@30.2.0:
dependencies:
- '@jest/schemas': 29.4.3
+ '@jest/schemas': 30.0.5
ansi-styles: 5.2.0
- react-is: 18.2.0
- dev: true
-
- /pseudomap@1.0.2:
- resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==}
- dev: true
+ react-is: 18.3.1
- /psl@1.9.0:
- resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==}
- dev: true
-
- /punycode@2.3.0:
- resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==}
- engines: {node: '>=6'}
- dev: true
+ punycode@2.3.1: {}
- /querystringify@2.2.0:
- resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
- dev: true
+ quansync@0.2.11: {}
- /queue-microtask@1.2.3:
- resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
- dev: true
+ quansync@1.0.0: {}
- /quick-lru@4.0.1:
- resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==}
- engines: {node: '>=8'}
- dev: true
+ queue-microtask@1.2.3: {}
- /react-dom@18.2.0(react@18.2.0):
- resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
- peerDependencies:
- react: ^18.2.0
+ react-dom@18.3.1(react@18.3.1):
dependencies:
loose-envify: 1.4.0
- react: 18.2.0
- scheduler: 0.23.0
- dev: true
+ react: 18.3.1
+ scheduler: 0.23.2
- /react-is@17.0.2:
- resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
- dev: true
+ react-is@17.0.2: {}
- /react-is@18.2.0:
- resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==}
- dev: true
+ react-is@18.3.1: {}
- /react-refresh@0.14.2:
- resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
- engines: {node: '>=0.10.0'}
- dev: true
+ react-refresh@0.17.0: {}
- /react@18.2.0:
- resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
- engines: {node: '>=0.10.0'}
+ react@18.3.1:
dependencies:
loose-envify: 1.4.0
- /read-pkg-up@7.0.1:
- resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==}
- engines: {node: '>=8'}
- dependencies:
- find-up: 4.1.0
- read-pkg: 5.2.0
- type-fest: 0.8.1
- dev: true
-
- /read-pkg@5.2.0:
- resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==}
- engines: {node: '>=8'}
- dependencies:
- '@types/normalize-package-data': 2.4.1
- normalize-package-data: 2.5.0
- parse-json: 5.2.0
- type-fest: 0.6.0
- dev: true
-
- /read-yaml-file@1.1.0:
- resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==}
- engines: {node: '>=6'}
+ read-yaml-file@1.1.0:
dependencies:
graceful-fs: 4.2.11
js-yaml: 3.14.1
pify: 4.0.1
strip-bom: 3.0.0
- dev: true
- /readdirp@3.6.0:
- resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
- engines: {node: '>=8.10.0'}
+ readdirp@3.6.0:
dependencies:
picomatch: 2.3.1
- dev: true
- /redent@3.0.0:
- resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
- engines: {node: '>=8'}
+ redent@3.0.0:
dependencies:
indent-string: 4.0.0
strip-indent: 3.0.0
- dev: true
-
- /regenerator-runtime@0.13.11:
- resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==}
- dev: true
- /regexp.prototype.flags@1.5.0:
- resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==}
- engines: {node: '>= 0.4'}
+ regexp.prototype.flags@1.5.4:
dependencies:
- call-bind: 1.0.2
- define-properties: 1.2.0
- functions-have-names: 1.2.3
- dev: true
-
- /require-directory@2.1.1:
- resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
- engines: {node: '>=0.10.0'}
- dev: true
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-errors: 1.3.0
+ get-proto: 1.0.1
+ gopd: 1.2.0
+ set-function-name: 2.0.2
- /require-main-filename@2.0.0:
- resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==}
- dev: true
+ resolve-from@5.0.0: {}
- /requires-port@1.0.0:
- resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==}
- dev: true
+ resolve-pkg-maps@1.0.0: {}
- /resolve-from@5.0.0:
- resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
- engines: {node: '>=8'}
- dev: true
+ reusify@1.1.0: {}
- /resolve@1.22.2:
- resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==}
- hasBin: true
+ rolldown-plugin-dts@0.18.3(rolldown@1.0.0-beta.53)(typescript@5.9.3):
dependencies:
- is-core-module: 2.12.0
- path-parse: 1.0.7
- supports-preserve-symlinks-flag: 1.0.0
- dev: true
-
- /reusify@1.0.4:
- resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
- engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
- dev: true
-
- /rollup@3.20.7:
- resolution: {integrity: sha512-P7E2zezKSLhWnTz46XxjSmInrbOCiul1yf+kJccMxT56vxjHwCbDfoLbiqFgu+WQoo9ij2PkraYaBstgB2prBA==}
- engines: {node: '>=14.18.0', npm: '>=8.0.0'}
- hasBin: true
+ '@babel/generator': 7.28.5
+ '@babel/parser': 7.28.5
+ '@babel/types': 7.28.5
+ ast-kit: 2.2.0
+ birpc: 3.0.0
+ dts-resolver: 2.1.3
+ get-tsconfig: 4.13.0
+ magic-string: 0.30.21
+ obug: 2.1.1
+ rolldown: 1.0.0-beta.53
optionalDependencies:
- fsevents: 2.3.3
- dev: true
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - oxc-resolver
- /rollup@4.18.1:
- resolution: {integrity: sha512-Elx2UT8lzxxOXMpy5HWQGZqkrQOtrVDDa/bm9l10+U4rQnVzbL/LgZ4NOM1MPIDyHk69W4InuYDF5dzRh4Kw1A==}
- engines: {node: '>=18.0.0', npm: '>=8.0.0'}
- hasBin: true
+ rolldown@1.0.0-beta.53:
dependencies:
- '@types/estree': 1.0.5
+ '@oxc-project/types': 0.101.0
+ '@rolldown/pluginutils': 1.0.0-beta.53
+ optionalDependencies:
+ '@rolldown/binding-android-arm64': 1.0.0-beta.53
+ '@rolldown/binding-darwin-arm64': 1.0.0-beta.53
+ '@rolldown/binding-darwin-x64': 1.0.0-beta.53
+ '@rolldown/binding-freebsd-x64': 1.0.0-beta.53
+ '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.53
+ '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.53
+ '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.53
+ '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.53
+ '@rolldown/binding-linux-x64-musl': 1.0.0-beta.53
+ '@rolldown/binding-openharmony-arm64': 1.0.0-beta.53
+ '@rolldown/binding-wasm32-wasi': 1.0.0-beta.53
+ '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.53
+ '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.53
+
+ rollup@4.52.5:
+ dependencies:
+ '@types/estree': 1.0.8
optionalDependencies:
- '@rollup/rollup-android-arm-eabi': 4.18.1
- '@rollup/rollup-android-arm64': 4.18.1
- '@rollup/rollup-darwin-arm64': 4.18.1
- '@rollup/rollup-darwin-x64': 4.18.1
- '@rollup/rollup-linux-arm-gnueabihf': 4.18.1
- '@rollup/rollup-linux-arm-musleabihf': 4.18.1
- '@rollup/rollup-linux-arm64-gnu': 4.18.1
- '@rollup/rollup-linux-arm64-musl': 4.18.1
- '@rollup/rollup-linux-powerpc64le-gnu': 4.18.1
- '@rollup/rollup-linux-riscv64-gnu': 4.18.1
- '@rollup/rollup-linux-s390x-gnu': 4.18.1
- '@rollup/rollup-linux-x64-gnu': 4.18.1
- '@rollup/rollup-linux-x64-musl': 4.18.1
- '@rollup/rollup-win32-arm64-msvc': 4.18.1
- '@rollup/rollup-win32-ia32-msvc': 4.18.1
- '@rollup/rollup-win32-x64-msvc': 4.18.1
+ '@rollup/rollup-android-arm-eabi': 4.52.5
+ '@rollup/rollup-android-arm64': 4.52.5
+ '@rollup/rollup-darwin-arm64': 4.52.5
+ '@rollup/rollup-darwin-x64': 4.52.5
+ '@rollup/rollup-freebsd-arm64': 4.52.5
+ '@rollup/rollup-freebsd-x64': 4.52.5
+ '@rollup/rollup-linux-arm-gnueabihf': 4.52.5
+ '@rollup/rollup-linux-arm-musleabihf': 4.52.5
+ '@rollup/rollup-linux-arm64-gnu': 4.52.5
+ '@rollup/rollup-linux-arm64-musl': 4.52.5
+ '@rollup/rollup-linux-loong64-gnu': 4.52.5
+ '@rollup/rollup-linux-ppc64-gnu': 4.52.5
+ '@rollup/rollup-linux-riscv64-gnu': 4.52.5
+ '@rollup/rollup-linux-riscv64-musl': 4.52.5
+ '@rollup/rollup-linux-s390x-gnu': 4.52.5
+ '@rollup/rollup-linux-x64-gnu': 4.52.5
+ '@rollup/rollup-linux-x64-musl': 4.52.5
+ '@rollup/rollup-openharmony-arm64': 4.52.5
+ '@rollup/rollup-win32-arm64-msvc': 4.52.5
+ '@rollup/rollup-win32-ia32-msvc': 4.52.5
+ '@rollup/rollup-win32-x64-gnu': 4.52.5
+ '@rollup/rollup-win32-x64-msvc': 4.52.5
fsevents: 2.3.3
- dev: true
- /rrweb-cssom@0.6.0:
- resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==}
- dev: true
+ rrweb-cssom@0.6.0: {}
- /run-parallel@1.2.0:
- resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+ run-parallel@1.2.0:
dependencies:
queue-microtask: 1.2.3
- dev: true
- /safe-regex-test@1.0.0:
- resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==}
+ safe-regex-test@1.1.0:
dependencies:
- call-bind: 1.0.2
- get-intrinsic: 1.2.0
- is-regex: 1.1.4
- dev: true
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-regex: 1.2.1
- /safer-buffer@2.1.2:
- resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
- dev: true
+ safer-buffer@2.1.2: {}
- /saxes@6.0.0:
- resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
- engines: {node: '>=v12.22.7'}
+ saxes@6.0.0:
dependencies:
xmlchars: 2.2.0
- dev: true
- /scheduler@0.23.0:
- resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==}
+ scheduler@0.23.2:
dependencies:
loose-envify: 1.4.0
- dev: true
-
- /semver@6.3.1:
- resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
- hasBin: true
- dev: true
-
- /semver@7.6.2:
- resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==}
- engines: {node: '>=10'}
- hasBin: true
- dev: true
-
- /set-blocking@2.0.0:
- resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
- dev: true
- /shebang-command@1.2.0:
- resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==}
- engines: {node: '>=0.10.0'}
- dependencies:
- shebang-regex: 1.0.0
- dev: true
+ semver@6.3.1: {}
- /shebang-command@2.0.0:
- resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
- engines: {node: '>=8'}
+ semver@7.5.3:
dependencies:
- shebang-regex: 3.0.0
- dev: true
-
- /shebang-regex@1.0.0:
- resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==}
- engines: {node: '>=0.10.0'}
- dev: true
+ lru-cache: 6.0.0
- /shebang-regex@3.0.0:
- resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
- engines: {node: '>=8'}
- dev: true
+ semver@7.7.3: {}
- /side-channel@1.0.4:
- resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
+ set-function-length@1.2.2:
dependencies:
- call-bind: 1.0.2
- get-intrinsic: 1.2.0
- object-inspect: 1.12.3
- dev: true
-
- /siginfo@2.0.0:
- resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
- dev: true
-
- /signal-exit@3.0.7:
- resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
- dev: true
+ define-data-property: 1.1.4
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+ get-intrinsic: 1.3.0
+ gopd: 1.2.0
+ has-property-descriptors: 1.0.2
- /signal-exit@4.1.0:
- resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
- engines: {node: '>=14'}
- dev: true
-
- /size-limit@8.2.4:
- resolution: {integrity: sha512-Un16nSreD1v2CYwSorattiJcHuAWqXvg4TsGgzpjnoByqQwsSfCIEQHuaD14HNStzredR8cdsO9oGH91ibypTA==}
- engines: {node: ^14.0.0 || ^16.0.0 || >=18.0.0}
- hasBin: true
+ set-function-name@2.0.2:
dependencies:
- bytes-iec: 3.1.1
- chokidar: 3.5.3
- globby: 11.1.0
- lilconfig: 2.1.0
- nanospinner: 1.1.0
- picocolors: 1.0.0
- dev: true
-
- /slash@3.0.0:
- resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
- engines: {node: '>=8'}
- dev: true
+ define-data-property: 1.1.4
+ es-errors: 1.3.0
+ functions-have-names: 1.2.3
+ has-property-descriptors: 1.0.2
- /smartwrap@2.0.2:
- resolution: {integrity: sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA==}
- engines: {node: '>=6'}
- hasBin: true
+ shebang-command@2.0.0:
dependencies:
- array.prototype.flat: 1.3.1
- breakword: 1.0.5
- grapheme-splitter: 1.0.4
- strip-ansi: 6.0.1
- wcwidth: 1.0.1
- yargs: 15.4.1
- dev: true
+ shebang-regex: 3.0.0
- /source-map-js@1.2.0:
- resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==}
- engines: {node: '>=0.10.0'}
- dev: true
+ shebang-regex@3.0.0: {}
- /source-map-support@0.5.21:
- resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
+ side-channel-list@1.0.0:
dependencies:
- buffer-from: 1.1.2
- source-map: 0.6.1
- dev: true
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
- /source-map@0.6.1:
- resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
- engines: {node: '>=0.10.0'}
- dev: true
-
- /source-map@0.8.0-beta.0:
- resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==}
- engines: {node: '>= 8'}
+ side-channel-map@1.0.1:
dependencies:
- whatwg-url: 7.1.0
- dev: true
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
- /spawndamnit@2.0.0:
- resolution: {integrity: sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA==}
+ side-channel-weakmap@1.0.2:
dependencies:
- cross-spawn: 5.1.0
- signal-exit: 3.0.7
- dev: true
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-map: 1.0.1
- /spdx-correct@3.2.0:
- resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==}
+ side-channel@1.1.0:
dependencies:
- spdx-expression-parse: 3.0.1
- spdx-license-ids: 3.0.13
- dev: true
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-list: 1.0.0
+ side-channel-map: 1.0.1
+ side-channel-weakmap: 1.0.2
- /spdx-exceptions@2.3.0:
- resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==}
- dev: true
+ siginfo@2.0.0: {}
- /spdx-expression-parse@3.0.1:
- resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==}
+ signal-exit@4.1.0: {}
+
+ size-limit@8.2.6:
dependencies:
- spdx-exceptions: 2.3.0
- spdx-license-ids: 3.0.13
- dev: true
+ bytes-iec: 3.1.1
+ chokidar: 3.6.0
+ globby: 11.1.0
+ lilconfig: 2.1.0
+ nanospinner: 1.2.2
+ picocolors: 1.1.1
- /spdx-license-ids@3.0.13:
- resolution: {integrity: sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==}
- dev: true
+ slash@3.0.0: {}
- /sprintf-js@1.0.3:
- resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
- dev: true
+ source-map-js@1.2.1: {}
- /stack-utils@2.0.6:
- resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==}
- engines: {node: '>=10'}
+ source-map-support@0.5.21:
dependencies:
- escape-string-regexp: 2.0.0
- dev: true
+ buffer-from: 1.1.2
+ source-map: 0.6.1
- /stackback@0.0.2:
- resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
- dev: true
+ source-map@0.6.1: {}
+
+ spawndamnit@3.0.1:
+ dependencies:
+ cross-spawn: 7.0.6
+ signal-exit: 4.1.0
- /std-env@3.7.0:
- resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==}
- dev: true
+ sprintf-js@1.0.3: {}
- /stop-iteration-iterator@1.0.0:
- resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==}
- engines: {node: '>= 0.4'}
+ stack-utils@2.0.6:
dependencies:
- internal-slot: 1.0.5
- dev: true
+ escape-string-regexp: 2.0.0
- /stream-transform@2.1.3:
- resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==}
+ stackback@0.0.2: {}
+
+ std-env@3.10.0: {}
+
+ stop-iteration-iterator@1.1.0:
dependencies:
- mixme: 0.5.9
- dev: true
+ es-errors: 1.3.0
+ internal-slot: 1.1.0
- /string-width@4.2.3:
- resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
- engines: {node: '>=8'}
+ string-width@4.2.3:
dependencies:
emoji-regex: 8.0.0
is-fullwidth-code-point: 3.0.0
strip-ansi: 6.0.1
- dev: true
- /string-width@5.1.2:
- resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
- engines: {node: '>=12'}
+ string-width@5.1.2:
dependencies:
eastasianwidth: 0.2.0
emoji-regex: 9.2.2
- strip-ansi: 7.1.0
- dev: true
-
- /string.prototype.trim@1.2.7:
- resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==}
- engines: {node: '>= 0.4'}
- dependencies:
- call-bind: 1.0.2
- define-properties: 1.2.0
- es-abstract: 1.21.2
- dev: true
-
- /string.prototype.trimend@1.0.6:
- resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==}
- dependencies:
- call-bind: 1.0.2
- define-properties: 1.2.0
- es-abstract: 1.21.2
- dev: true
-
- /string.prototype.trimstart@1.0.6:
- resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==}
- dependencies:
- call-bind: 1.0.2
- define-properties: 1.2.0
- es-abstract: 1.21.2
- dev: true
+ strip-ansi: 7.1.2
- /strip-ansi@6.0.1:
- resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
- engines: {node: '>=8'}
+ strip-ansi@6.0.1:
dependencies:
ansi-regex: 5.0.1
- dev: true
- /strip-ansi@7.1.0:
- resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
- engines: {node: '>=12'}
+ strip-ansi@7.1.2:
dependencies:
- ansi-regex: 6.0.1
- dev: true
-
- /strip-bom@3.0.0:
- resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
- engines: {node: '>=4'}
- dev: true
-
- /strip-final-newline@2.0.0:
- resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
- engines: {node: '>=6'}
- dev: true
+ ansi-regex: 6.2.2
- /strip-final-newline@3.0.0:
- resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==}
- engines: {node: '>=12'}
- dev: true
+ strip-bom@3.0.0: {}
- /strip-indent@3.0.0:
- resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
- engines: {node: '>=8'}
+ strip-indent@3.0.0:
dependencies:
min-indent: 1.0.1
- dev: true
- /sucrase@3.32.0:
- resolution: {integrity: sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==}
- engines: {node: '>=8'}
- hasBin: true
- dependencies:
- '@jridgewell/gen-mapping': 0.3.3
- commander: 4.1.1
- glob: 7.1.6
- lines-and-columns: 1.2.4
- mz: 2.7.0
- pirates: 4.0.5
- ts-interface-checker: 0.1.13
- dev: true
-
- /supports-color@5.5.0:
- resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
- engines: {node: '>=4'}
+ strip-literal@3.1.0:
dependencies:
- has-flag: 3.0.0
- dev: true
+ js-tokens: 9.0.1
- /supports-color@7.2.0:
- resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
- engines: {node: '>=8'}
+ supports-color@7.2.0:
dependencies:
has-flag: 4.0.0
- dev: true
-
- /supports-preserve-symlinks-flag@1.0.0:
- resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
- engines: {node: '>= 0.4'}
- dev: true
- /symbol-tree@3.2.4:
- resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
- dev: true
+ symbol-tree@3.2.4: {}
- /term-size@2.2.1:
- resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==}
- engines: {node: '>=8'}
- dev: true
+ term-size@2.2.1: {}
- /terser@5.17.1:
- resolution: {integrity: sha512-hVl35zClmpisy6oaoKALOpS0rDYLxRFLHhRuDlEGTKey9qHjS1w9GMORjuwIMt70Wan4lwsLYyWDVnWgF+KUEw==}
- engines: {node: '>=10'}
- hasBin: true
+ terser@5.44.0:
dependencies:
- '@jridgewell/source-map': 0.3.3
- acorn: 8.8.2
+ '@jridgewell/source-map': 0.3.11
+ acorn: 8.15.0
commander: 2.20.3
source-map-support: 0.5.21
- dev: true
- /test-exclude@7.0.1:
- resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==}
- engines: {node: '>=18'}
+ test-exclude@7.0.1:
dependencies:
'@istanbuljs/schema': 0.1.3
glob: 10.4.5
minimatch: 9.0.5
- dev: true
- /thenify-all@1.6.0:
- resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
- engines: {node: '>=0.8'}
- dependencies:
- thenify: 3.3.1
- dev: true
+ tinybench@2.9.0: {}
- /thenify@3.3.1:
- resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
- dependencies:
- any-promise: 1.3.0
- dev: true
+ tinyexec@0.3.2: {}
- /tinybench@2.8.0:
- resolution: {integrity: sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==}
- dev: true
+ tinyexec@1.0.2: {}
- /tinypool@1.0.0:
- resolution: {integrity: sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ==}
- engines: {node: ^18.0.0 || >=20.0.0}
- dev: true
+ tinyglobby@0.2.15:
+ dependencies:
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
- /tinyrainbow@1.2.0:
- resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==}
- engines: {node: '>=14.0.0'}
- dev: true
+ tinypool@1.1.1: {}
- /tinyspy@3.0.0:
- resolution: {integrity: sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA==}
- engines: {node: '>=14.0.0'}
- dev: true
+ tinyrainbow@2.0.0: {}
- /tmp@0.0.33:
- resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==}
- engines: {node: '>=0.6.0'}
- dependencies:
- os-tmpdir: 1.0.2
- dev: true
+ tinyspy@4.0.4: {}
- /to-fast-properties@2.0.0:
- resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
- engines: {node: '>=4'}
- dev: true
+ tldts-core@7.0.17: {}
- /to-regex-range@5.0.1:
- resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
- engines: {node: '>=8.0'}
+ tldts@7.0.17:
dependencies:
- is-number: 7.0.0
- dev: true
+ tldts-core: 7.0.17
- /tough-cookie@4.1.4:
- resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==}
- engines: {node: '>=6'}
+ to-regex-range@5.0.1:
dependencies:
- psl: 1.9.0
- punycode: 2.3.0
- universalify: 0.2.0
- url-parse: 1.5.10
- dev: true
+ is-number: 7.0.0
- /tr46@1.0.1:
- resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==}
+ tough-cookie@6.0.0:
dependencies:
- punycode: 2.3.0
- dev: true
+ tldts: 7.0.17
- /tr46@4.1.1:
- resolution: {integrity: sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==}
- engines: {node: '>=14'}
+ tr46@4.1.1:
dependencies:
- punycode: 2.3.0
- dev: true
-
- /tree-kill@1.2.2:
- resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
- hasBin: true
- dev: true
-
- /trim-newlines@3.0.1:
- resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==}
- engines: {node: '>=8'}
- dev: true
+ punycode: 2.3.1
- /ts-interface-checker@0.1.13:
- resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
- dev: true
+ tree-kill@1.2.2: {}
- /ts-node@10.9.1(@types/node@18.15.13)(typescript@5.0.4):
- resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==}
- hasBin: true
- peerDependencies:
- '@swc/core': '>=1.2.50'
- '@swc/wasm': '>=1.2.50'
- '@types/node': '*'
- typescript: '>=2.7'
- peerDependenciesMeta:
- '@swc/core':
- optional: true
- '@swc/wasm':
- optional: true
+ ts-node@10.9.2(@types/node@22.18.11)(typescript@5.9.3):
dependencies:
'@cspotcode/source-map-support': 0.8.1
- '@tsconfig/node10': 1.0.9
+ '@tsconfig/node10': 1.0.11
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
- '@tsconfig/node16': 1.0.3
- '@types/node': 18.15.13
- acorn: 8.8.2
- acorn-walk: 8.2.0
+ '@tsconfig/node16': 1.0.4
+ '@types/node': 22.18.11
+ acorn: 8.15.0
+ acorn-walk: 8.3.4
arg: 4.1.3
create-require: 1.1.1
diff: 4.0.2
make-error: 1.3.6
- typescript: 5.0.4
+ typescript: 5.9.3
v8-compile-cache-lib: 3.0.1
yn: 3.1.1
- dev: true
- /tsup@6.7.0(ts-node@10.9.1)(typescript@5.0.4):
- resolution: {integrity: sha512-L3o8hGkaHnu5TdJns+mCqFsDBo83bJ44rlK7e6VdanIvpea4ArPcU3swWGsLVbXak1PqQx/V+SSmFPujBK+zEQ==}
- engines: {node: '>=14.18'}
- hasBin: true
- peerDependencies:
- '@swc/core': ^1
- postcss: ^8.4.12
- typescript: '>=4.1.0'
- peerDependenciesMeta:
- '@swc/core':
- optional: true
- postcss:
- optional: true
- typescript:
- optional: true
+ tsdown@0.17.3(typescript@5.9.3):
dependencies:
- bundle-require: 4.0.1(esbuild@0.17.17)
+ ansis: 4.2.0
cac: 6.7.14
- chokidar: 3.5.3
- debug: 4.3.4
- esbuild: 0.17.17
- execa: 5.1.1
- globby: 11.1.0
- joycon: 3.1.1
- postcss-load-config: 3.1.4(ts-node@10.9.1)
- resolve-from: 5.0.0
- rollup: 3.20.7
- source-map: 0.8.0-beta.0
- sucrase: 3.32.0
+ defu: 6.1.4
+ empathic: 2.0.0
+ hookable: 5.5.3
+ import-without-cache: 0.2.3
+ obug: 2.1.1
+ rolldown: 1.0.0-beta.53
+ rolldown-plugin-dts: 0.18.3(rolldown@1.0.0-beta.53)(typescript@5.9.3)
+ semver: 7.7.3
+ tinyexec: 1.0.2
+ tinyglobby: 0.2.15
tree-kill: 1.2.2
- typescript: 5.0.4
+ unconfig-core: 7.4.2
+ unrun: 0.2.19
+ optionalDependencies:
+ typescript: 5.9.3
transitivePeerDependencies:
- - supports-color
- - ts-node
- dev: true
-
- /tty-table@4.2.1:
- resolution: {integrity: sha512-xz0uKo+KakCQ+Dxj1D/tKn2FSyreSYWzdkL/BYhgN6oMW808g8QRMuh1atAV9fjTPbWBjfbkKQpI/5rEcnAc7g==}
- engines: {node: '>=8.0.0'}
- hasBin: true
- dependencies:
- chalk: 4.1.2
- csv: 5.5.3
- kleur: 4.1.5
- smartwrap: 2.0.2
- strip-ansi: 6.0.1
- wcwidth: 1.0.1
- yargs: 17.7.1
- dev: true
-
- /type-check@0.3.2:
- resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==}
- engines: {node: '>= 0.8.0'}
- dependencies:
- prelude-ls: 1.1.2
- dev: true
-
- /type-fest@0.13.1:
- resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==}
- engines: {node: '>=10'}
- dev: true
-
- /type-fest@0.6.0:
- resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==}
- engines: {node: '>=8'}
- dev: true
-
- /type-fest@0.8.1:
- resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==}
- engines: {node: '>=8'}
- dev: true
+ - '@ts-macro/tsc'
+ - '@typescript/native-preview'
+ - oxc-resolver
+ - synckit
+ - vue-tsc
- /typed-array-length@1.0.4:
- resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==}
- dependencies:
- call-bind: 1.0.2
- for-each: 0.3.3
- is-typed-array: 1.1.10
- dev: true
+ tslib@2.8.1:
+ optional: true
- /typescript@5.0.4:
- resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==}
- engines: {node: '>=12.20'}
- hasBin: true
- dev: true
+ typescript@5.9.3: {}
- /unbox-primitive@1.0.2:
- resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
+ unconfig-core@7.4.2:
dependencies:
- call-bind: 1.0.2
- has-bigints: 1.0.2
- has-symbols: 1.0.3
- which-boxed-primitive: 1.0.2
- dev: true
+ '@quansync/fs': 1.0.0
+ quansync: 1.0.0
- /universalify@0.1.2:
- resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
- engines: {node: '>= 4.0.0'}
- dev: true
+ undici-types@6.21.0: {}
- /universalify@0.2.0:
- resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==}
- engines: {node: '>= 4.0.0'}
- dev: true
+ universalify@0.1.2: {}
- /update-browserslist-db@1.1.0(browserslist@4.23.2):
- resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==}
- hasBin: true
- peerDependencies:
- browserslist: '>= 4.21.0'
+ unrun@0.2.19:
dependencies:
- browserslist: 4.23.2
- escalade: 3.1.2
- picocolors: 1.0.1
- dev: true
+ rolldown: 1.0.0-beta.53
- /url-parse@1.5.10:
- resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==}
+ update-browserslist-db@1.1.3(browserslist@4.26.3):
dependencies:
- querystringify: 2.2.0
- requires-port: 1.0.0
- dev: true
+ browserslist: 4.26.3
+ escalade: 3.2.0
+ picocolors: 1.1.1
- /v8-compile-cache-lib@3.0.1:
- resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
- dev: true
-
- /validate-npm-package-license@3.0.4:
- resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
- dependencies:
- spdx-correct: 3.2.0
- spdx-expression-parse: 3.0.1
- dev: true
+ v8-compile-cache-lib@3.0.1: {}
- /vite-node@2.0.3(@types/node@18.15.13)(terser@5.17.1):
- resolution: {integrity: sha512-14jzwMx7XTcMB+9BhGQyoEAmSl0eOr3nrnn+Z12WNERtOvLN+d2scbRUvyni05rT3997Bg+rZb47NyP4IQPKXg==}
- engines: {node: ^18.0.0 || >=20.0.0}
- hasBin: true
+ vite-node@3.2.4(@types/node@22.18.11)(terser@5.44.0):
dependencies:
cac: 6.7.14
- debug: 4.3.5
- pathe: 1.1.2
- tinyrainbow: 1.2.0
- vite: 5.3.3(@types/node@18.15.13)(terser@5.17.1)
+ debug: 4.4.3
+ es-module-lexer: 1.7.0
+ pathe: 2.0.3
+ vite: 7.1.11(@types/node@22.18.11)(terser@5.44.0)
transitivePeerDependencies:
- '@types/node'
+ - jiti
- less
- lightningcss
- sass
+ - sass-embedded
- stylus
- sugarss
- supports-color
- terser
- dev: true
+ - tsx
+ - yaml
- /vite@5.3.3(@types/node@18.15.13)(terser@5.17.1):
- resolution: {integrity: sha512-NPQdeCU0Dv2z5fu+ULotpuq5yfCS1BzKUIPhNbP3YBfAMGJXbt2nS+sbTFu+qchaqWTD+H3JK++nRwr6XIcp6A==}
- engines: {node: ^18.0.0 || >=20.0.0}
- hasBin: true
- peerDependencies:
- '@types/node': ^18.0.0 || >=20.0.0
- less: '*'
- lightningcss: ^1.21.0
- sass: '*'
- stylus: '*'
- sugarss: '*'
- terser: ^5.4.0
- peerDependenciesMeta:
- '@types/node':
- optional: true
- less:
- optional: true
- lightningcss:
- optional: true
- sass:
- optional: true
- stylus:
- optional: true
- sugarss:
- optional: true
- terser:
- optional: true
+ vite@7.1.11(@types/node@22.18.11)(terser@5.44.0):
dependencies:
- '@types/node': 18.15.13
- esbuild: 0.21.5
- postcss: 8.4.39
- rollup: 4.18.1
- terser: 5.17.1
+ esbuild: 0.25.11
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+ postcss: 8.5.6
+ rollup: 4.52.5
+ tinyglobby: 0.2.15
optionalDependencies:
+ '@types/node': 22.18.11
fsevents: 2.3.3
- dev: true
-
- /vitest@2.0.3(@types/node@18.15.13)(jsdom@21.1.1)(terser@5.17.1):
- resolution: {integrity: sha512-o3HRvU93q6qZK4rI2JrhKyZMMuxg/JRt30E6qeQs6ueaiz5hr1cPj+Sk2kATgQzMMqsa2DiNI0TIK++1ULx8Jw==}
- engines: {node: ^18.0.0 || >=20.0.0}
- hasBin: true
- peerDependencies:
- '@edge-runtime/vm': '*'
- '@types/node': ^18.0.0 || >=20.0.0
- '@vitest/browser': 2.0.3
- '@vitest/ui': 2.0.3
- happy-dom: '*'
- jsdom: '*'
- peerDependenciesMeta:
- '@edge-runtime/vm':
- optional: true
- '@types/node':
- optional: true
- '@vitest/browser':
- optional: true
- '@vitest/ui':
- optional: true
- happy-dom:
- optional: true
- jsdom:
- optional: true
- dependencies:
- '@ampproject/remapping': 2.3.0
- '@types/node': 18.15.13
- '@vitest/expect': 2.0.3
- '@vitest/pretty-format': 2.0.3
- '@vitest/runner': 2.0.3
- '@vitest/snapshot': 2.0.3
- '@vitest/spy': 2.0.3
- '@vitest/utils': 2.0.3
- chai: 5.1.1
- debug: 4.3.5
- execa: 8.0.1
- jsdom: 21.1.1
- magic-string: 0.30.10
- pathe: 1.1.2
- std-env: 3.7.0
- tinybench: 2.8.0
- tinypool: 1.0.0
- tinyrainbow: 1.2.0
- vite: 5.3.3(@types/node@18.15.13)(terser@5.17.1)
- vite-node: 2.0.3(@types/node@18.15.13)(terser@5.17.1)
- why-is-node-running: 2.2.2
+ terser: 5.44.0
+
+ vitest@3.2.4(@types/node@22.18.11)(jsdom@21.1.2)(terser@5.44.0):
+ dependencies:
+ '@types/chai': 5.2.2
+ '@vitest/expect': 3.2.4
+ '@vitest/mocker': 3.2.4(vite@7.1.11(@types/node@22.18.11)(terser@5.44.0))
+ '@vitest/pretty-format': 3.2.4
+ '@vitest/runner': 3.2.4
+ '@vitest/snapshot': 3.2.4
+ '@vitest/spy': 3.2.4
+ '@vitest/utils': 3.2.4
+ chai: 5.3.3
+ debug: 4.4.3
+ expect-type: 1.2.2
+ magic-string: 0.30.19
+ pathe: 2.0.3
+ picomatch: 4.0.3
+ std-env: 3.10.0
+ tinybench: 2.9.0
+ tinyexec: 0.3.2
+ tinyglobby: 0.2.15
+ tinypool: 1.1.1
+ tinyrainbow: 2.0.0
+ vite: 7.1.11(@types/node@22.18.11)(terser@5.44.0)
+ vite-node: 3.2.4(@types/node@22.18.11)(terser@5.44.0)
+ why-is-node-running: 2.3.0
+ optionalDependencies:
+ '@types/node': 22.18.11
+ jsdom: 21.1.2
transitivePeerDependencies:
+ - jiti
- less
- lightningcss
+ - msw
- sass
+ - sass-embedded
- stylus
- sugarss
- supports-color
- terser
- dev: true
+ - tsx
+ - yaml
- /w3c-xmlserializer@4.0.0:
- resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==}
- engines: {node: '>=14'}
+ w3c-xmlserializer@4.0.0:
dependencies:
xml-name-validator: 4.0.0
- dev: true
- /wcwidth@1.0.1:
- resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
- dependencies:
- defaults: 1.0.4
- dev: true
-
- /webidl-conversions@4.0.2:
- resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==}
- dev: true
-
- /webidl-conversions@7.0.0:
- resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
- engines: {node: '>=12'}
- dev: true
+ webidl-conversions@7.0.0: {}
- /whatwg-encoding@2.0.0:
- resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==}
- engines: {node: '>=12'}
+ whatwg-encoding@2.0.0:
dependencies:
iconv-lite: 0.6.3
- dev: true
- /whatwg-mimetype@3.0.0:
- resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==}
- engines: {node: '>=12'}
- dev: true
+ whatwg-mimetype@3.0.0: {}
- /whatwg-url@12.0.1:
- resolution: {integrity: sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==}
- engines: {node: '>=14'}
+ whatwg-url@12.0.1:
dependencies:
tr46: 4.1.1
webidl-conversions: 7.0.0
- dev: true
-
- /whatwg-url@7.1.0:
- resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==}
- dependencies:
- lodash.sortby: 4.7.0
- tr46: 1.0.1
- webidl-conversions: 4.0.2
- dev: true
-
- /which-boxed-primitive@1.0.2:
- resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
- dependencies:
- is-bigint: 1.0.4
- is-boolean-object: 1.1.2
- is-number-object: 1.0.7
- is-string: 1.0.7
- is-symbol: 1.0.4
- dev: true
-
- /which-collection@1.0.1:
- resolution: {integrity: sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==}
- dependencies:
- is-map: 2.0.2
- is-set: 2.0.2
- is-weakmap: 2.0.1
- is-weakset: 2.0.2
- dev: true
-
- /which-module@2.0.1:
- resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==}
- dev: true
- /which-pm@2.0.0:
- resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==}
- engines: {node: '>=8.15'}
+ which-boxed-primitive@1.1.1:
dependencies:
- load-yaml-file: 0.2.0
- path-exists: 4.0.0
- dev: true
+ is-bigint: 1.1.0
+ is-boolean-object: 1.2.2
+ is-number-object: 1.1.1
+ is-string: 1.1.1
+ is-symbol: 1.1.1
- /which-typed-array@1.1.9:
- resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==}
- engines: {node: '>= 0.4'}
+ which-collection@1.0.2:
dependencies:
- available-typed-arrays: 1.0.5
- call-bind: 1.0.2
- for-each: 0.3.3
- gopd: 1.0.1
- has-tostringtag: 1.0.0
- is-typed-array: 1.1.10
- dev: true
+ is-map: 2.0.3
+ is-set: 2.0.3
+ is-weakmap: 2.0.2
+ is-weakset: 2.0.4
- /which@1.3.1:
- resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==}
- hasBin: true
+ which-typed-array@1.1.19:
dependencies:
- isexe: 2.0.0
- dev: true
+ available-typed-arrays: 1.0.7
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ for-each: 0.3.5
+ get-proto: 1.0.1
+ gopd: 1.2.0
+ has-tostringtag: 1.0.2
- /which@2.0.2:
- resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
- engines: {node: '>= 8'}
- hasBin: true
+ which@2.0.2:
dependencies:
isexe: 2.0.0
- dev: true
- /why-is-node-running@2.2.2:
- resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==}
- engines: {node: '>=8'}
- hasBin: true
+ why-is-node-running@2.3.0:
dependencies:
siginfo: 2.0.0
stackback: 0.0.2
- dev: true
-
- /word-wrap@1.2.5:
- resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
- engines: {node: '>=0.10.0'}
- dev: true
-
- /wrap-ansi@6.2.0:
- resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
- engines: {node: '>=8'}
- dependencies:
- ansi-styles: 4.3.0
- string-width: 4.2.3
- strip-ansi: 6.0.1
- dev: true
- /wrap-ansi@7.0.0:
- resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
- engines: {node: '>=10'}
+ wrap-ansi@7.0.0:
dependencies:
ansi-styles: 4.3.0
string-width: 4.2.3
strip-ansi: 6.0.1
- dev: true
- /wrap-ansi@8.1.0:
- resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
- engines: {node: '>=12'}
+ wrap-ansi@8.1.0:
dependencies:
- ansi-styles: 6.2.1
+ ansi-styles: 6.2.3
string-width: 5.1.2
- strip-ansi: 7.1.0
- dev: true
-
- /wrappy@1.0.2:
- resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
- dev: true
-
- /ws@8.18.0:
- resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==}
- engines: {node: '>=10.0.0'}
- peerDependencies:
- bufferutil: ^4.0.1
- utf-8-validate: '>=5.0.2'
- peerDependenciesMeta:
- bufferutil:
- optional: true
- utf-8-validate:
- optional: true
- dev: true
-
- /xml-name-validator@4.0.0:
- resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==}
- engines: {node: '>=12'}
- dev: true
-
- /xmlchars@2.2.0:
- resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
- dev: true
-
- /y18n@4.0.3:
- resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
- dev: true
-
- /y18n@5.0.8:
- resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
- engines: {node: '>=10'}
- dev: true
-
- /yallist@2.1.2:
- resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==}
- dev: true
-
- /yallist@3.1.1:
- resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
- dev: true
-
- /yaml@1.10.2:
- resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
- engines: {node: '>= 6'}
- dev: true
+ strip-ansi: 7.1.2
- /yargs-parser@18.1.3:
- resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
- engines: {node: '>=6'}
- dependencies:
- camelcase: 5.3.1
- decamelize: 1.2.0
- dev: true
+ ws@8.18.3: {}
- /yargs-parser@21.1.1:
- resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
- engines: {node: '>=12'}
- dev: true
+ xml-name-validator@4.0.0: {}
- /yargs@15.4.1:
- resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==}
- engines: {node: '>=8'}
- dependencies:
- cliui: 6.0.0
- decamelize: 1.2.0
- find-up: 4.1.0
- get-caller-file: 2.0.5
- require-directory: 2.1.1
- require-main-filename: 2.0.0
- set-blocking: 2.0.0
- string-width: 4.2.3
- which-module: 2.0.1
- y18n: 4.0.3
- yargs-parser: 18.1.3
- dev: true
+ xmlchars@2.2.0: {}
- /yargs@17.7.1:
- resolution: {integrity: sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==}
- engines: {node: '>=12'}
- dependencies:
- cliui: 8.0.1
- escalade: 3.1.1
- get-caller-file: 2.0.5
- require-directory: 2.1.1
- string-width: 4.2.3
- y18n: 5.0.8
- yargs-parser: 21.1.1
- dev: true
+ yallist@3.1.1: {}
- /yn@3.1.1:
- resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==}
- engines: {node: '>=6'}
- dev: true
+ yallist@4.0.0: {}
- /yocto-queue@0.1.0:
- resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
- engines: {node: '>=10'}
- dev: true
+ yn@3.1.1: {}
diff --git a/src/index.tsx b/src/index.tsx
index 7a25d51..a26255a 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,18 +1,29 @@
import * as React from 'react'
export { useEventListener as useEventListener } from './lib/use-event-listener'
+export { default as useWindowResize } from './lib/use-window-resize'
+export { default as useOutsideClick } from './lib/use-outside-click'
+
export { default as useCopyToClipboard, copyToClipboardFn } from './lib/use-copy-to-clipboard'
export { default as useLocalStorage } from './lib/use-local-storage'
-export { default as useOutsideClick } from './lib/use-outside-click'
+
export { default as useDebouncedFn, debouncedFnWrapper } from './lib/use-debounced-fn'
export { default as useThrottledFn, throttledFnWrapper } from './lib/use-throttled-fn'
-export { default as useIsOnline } from './lib/use-is-online'
+
+export { default as useCanReachToInternet } from './lib/use-can-reach-to-internet'
+export {
+ useCanReachToInternetCtx,
+ CanReachToInternetCtxProvider as CanReachToInternetProvider,
+} from './lib/use-can-reach-to-internet/can-reach-to-internet-context'
+
+export { default as useSyncedRef } from './lib/use-synced-ref'
+
export { default as useTimeoutEffect } from './lib/use-timeout-effect'
export { default as useIntervalEffect } from './lib/use-interval-effect'
-export { default as useSyncedRef } from './lib/use-synced-ref'
export { default as useSyncedEffect } from './lib/use-synced-effect'
export { default as useOnMountEffect } from './lib/use-on-mount-effect'
+
export { default as useCounter } from './lib/use-counter'
-export { default as useWindowResize } from './lib/use-window-resize'
export { default as useInterSectionObserver } from './lib/use-intersection-observer'
+export { default as useMultiIntersectionObserver } from './lib/use-multi-intersection-observer'
diff --git a/src/lib/use-can-reach-to-internet/can-reach-to-internet-context.tsx b/src/lib/use-can-reach-to-internet/can-reach-to-internet-context.tsx
new file mode 100644
index 0000000..d9edb78
--- /dev/null
+++ b/src/lib/use-can-reach-to-internet/can-reach-to-internet-context.tsx
@@ -0,0 +1,104 @@
+'use client'
+import type { ReactNode, Context } from 'react'
+
+import React, { createContext, useContext, useRef } from 'react'
+import useCanReachToInternet, { CanReachToInternetOptions } from '.'
+
+/**
+ * Type definition for the context values containing all return values from useCanReachToInternet hook
+ */
+type CtxValues = ReturnType
+
+/**
+ * React Context for sharing internet connectivity status across the component tree
+ *
+ * @description
+ * This context provides all the connectivity status and control methods from
+ * useCanReachToInternet hook to any component in the React component tree
+ * without prop drilling.
+ *
+ */
+let CanReachToInternetCtx: Context
+
+/**
+ * Props interface for the CanReachToInternetCtxProvider component
+ */
+interface CanReachToInternetCtxProviderProps extends CanReachToInternetOptions {
+ /** React children components that will have access to the connectivity context */
+ children: ReactNode
+}
+
+/**
+ * Context Provider component for internet connectivity monitoring
+ *
+ * @description
+ * This provider component wraps your application or component tree to provide
+ * internet connectivity status and controls to all child components. It uses
+ * the useCanReachToInternet hook internally and shares its values through React Context.
+ *
+ * The provider accepts all the same configuration options as the useCanReachToInternet
+ * hook, allowing you to configure network polling, test URLs, and polling intervals
+ * at the application level.
+ *
+ *
+ * @example
+ * // Basic usage - wrap your app with the provider
+ import { CanReachToInternetCtxProvider } from 'classic-react-hooks'
+
+ function App() {
+ return (
+
+
+
+
+
+ )
+ }
+ *
+ * */
+export function CanReachToInternetCtxProvider({ children, ...options }: CanReachToInternetCtxProviderProps) {
+ CanReachToInternetCtx = useRef(createContext({} as CtxValues)).current
+ const values = useCanReachToInternet(options)
+
+ return {children}
+}
+
+/**
+ * Custom hook to consume the internet connectivity context
+ *
+ * @description
+ * This hook provides access to all the internet connectivity status and control
+ * methods from the nearest CanReachToInternetCtxProvider in the component tree.
+ * It must be used within a component that is wrapped by CanReachToInternetCtxProvider,
+ * otherwise it will throw an error.
+ *
+ * The hook returns the same values as useCanReachToInternet, but accessed through
+ * React Context instead of being created locally in each component.
+ *
+ * @throws {Error} Throws an error if used outside of CanReachToInternetCtxProvider
+ *
+ * @example
+ * // Basic usage in a component
+ import { useCanReachToInternetCtx } from 'classic-react-hooks'
+
+ function NetworkStatusBadge() {
+ const { isFullyConnected, isCheckingConnection } = useCanReachToInternetCtx()
+
+ if (isCheckingConnection) {
+ return Checking...
+ }
+
+ return (
+
+ {isFullyConnected ? '🟢 Online' : '🔴 Offline'}
+
+ )
+ }
+ *
+ * */
+export function useCanReachToInternetCtx() {
+ if (!CanReachToInternetCtx) {
+ throw new Error('useCanReachToInternetCtx must be used within an CanReachToInternetCtxProvider')
+ }
+ return useContext(CanReachToInternetCtx)
+}
diff --git a/src/lib/use-can-reach-to-internet/index.test.tsx b/src/lib/use-can-reach-to-internet/index.test.tsx
new file mode 100644
index 0000000..aa8cf41
--- /dev/null
+++ b/src/lib/use-can-reach-to-internet/index.test.tsx
@@ -0,0 +1,395 @@
+import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
+import { renderHook, act, waitFor } from '@testing-library/react'
+import useCanReachToInternet, { type CanReachToInternetOptions } from '.'
+
+// Mock fetch
+const mockFetch = vi.fn()
+global.fetch = mockFetch
+
+// Mock navigator.onLine
+const mockNavigator = {
+ onLine: true,
+}
+Object.defineProperty(window, 'navigator', {
+ value: mockNavigator,
+ writable: true,
+})
+
+// Mock window.(add/remove)EventListener
+const mockAddEventListener = vi.fn()
+const mockRemoveEventListener = vi.fn()
+Object.defineProperty(window, 'addEventListener', {
+ value: mockAddEventListener,
+ writable: true,
+})
+Object.defineProperty(window, 'removeEventListener', {
+ value: mockRemoveEventListener,
+ writable: true,
+})
+
+describe('useCanReachToInternet', () => {
+ beforeEach(() => {
+ vi.clearAllMocks()
+ mockNavigator.onLine = true
+ mockFetch.mockClear()
+ })
+
+ afterEach(() => {
+ vi.useRealTimers()
+ vi.clearAllTimers()
+ })
+
+ describe('Initial state', () => {
+ it('should initialize with correct default values', async () => {
+ mockFetch.mockResolvedValue(new Response())
+
+ const { result } = renderHook(() => useCanReachToInternet())
+
+ expect(result.current.isOnline).toBe(true)
+ expect(result.current.canReachToInternet).toBe(false)
+ expect(result.current.isFullyConnected).toBe(false)
+ expect(result.current.isNetworkPollingEnabled).toBe(true)
+ expect(result.current.isCheckingConnection).toBe(true)
+ })
+
+ it('should prioritize custom options', () => {
+ const options: CanReachToInternetOptions = {
+ enableNetworkPolling: false,
+ networkPollingInterval: 5000,
+ testUrl: 'https://custom.test',
+ }
+
+ const { result } = renderHook(() => useCanReachToInternet(options))
+
+ expect(result.current.isNetworkPollingEnabled).toBe(false)
+ })
+ })
+
+ describe('Network connectivity checking', () => {
+ it('should set canReachToInternet to true when fetch succeeds', async () => {
+ mockFetch.mockResolvedValue(new Response())
+
+ const { result } = renderHook(() => useCanReachToInternet())
+
+ await waitFor(() => {
+ expect(result.current.isFullyConnected).toBe(true)
+ expect(result.current.canReachToInternet).toBe(true)
+ })
+ })
+
+ it('should set canReachToInternet to false when fetch fails', async () => {
+ mockFetch.mockRejectedValue(new Error('Network error'))
+
+ const { result } = renderHook(() => useCanReachToInternet())
+
+ await waitFor(() => {
+ expect(result.current.canReachToInternet).toBe(false)
+ })
+
+ expect(result.current.isFullyConnected).toBe(false)
+ expect(result.current.isCheckingConnection).toBe(false)
+ })
+
+ it('should use correct fetch options', async () => {
+ mockFetch.mockResolvedValue(new Response())
+
+ renderHook(() => useCanReachToInternet())
+
+ await waitFor(() => {
+ vi.clearAllTimers()
+ expect(mockFetch).toHaveBeenCalledWith(
+ 'https://dns.google',
+ expect.objectContaining({
+ method: 'HEAD',
+ cache: 'no-cache',
+ mode: 'no-cors',
+ headers: {
+ 'Cache-Control': 'no-cache, no-store, must-revalidate',
+ Pragma: 'no-cache',
+ },
+ signal: expect.any(AbortSignal),
+ })
+ )
+ })
+ })
+
+ it('should use custom testUrl when provided', async () => {
+ mockFetch.mockResolvedValue(new Response())
+ const customUrl = 'https://custom.test'
+
+ renderHook(() => useCanReachToInternet({ testUrl: customUrl }))
+
+ expect(mockFetch).toHaveBeenCalledWith(customUrl, expect.any(Object))
+ })
+ })
+
+ describe('Network polling', () => {
+ beforeEach(() => {
+ vi.useFakeTimers()
+ })
+ afterEach(() => {
+ vi.useRealTimers()
+ })
+
+ it('should poll network at specified intervals when enabled', async () => {
+ mockFetch.mockResolvedValue(new Response())
+
+ renderHook(() => useCanReachToInternet({ networkPollingInterval: 1000 }))
+
+ expect(mockFetch).toHaveBeenCalledTimes(1)
+
+ await vi.advanceTimersByTimeAsync(1000)
+ expect(mockFetch).toHaveBeenCalledTimes(2)
+
+ await vi.advanceTimersByTimeAsync(1000)
+ expect(mockFetch).toHaveBeenCalledTimes(3)
+
+ await vi.advanceTimersByTimeAsync(3000)
+ expect(mockFetch).toHaveBeenCalledTimes(6)
+ })
+
+ it('should not poll when network polling is disabled', async () => {
+ mockFetch.mockResolvedValue(new Response())
+
+ renderHook(() => useCanReachToInternet({ enableNetworkPolling: false }))
+
+ expect(mockFetch).toHaveBeenCalledTimes(1)
+ vi.advanceTimersByTimeAsync(1000)
+ expect(mockFetch).toHaveBeenCalledTimes(1)
+ })
+
+ it('should stop polling when stopNetworkPolling is called', async () => {
+ mockFetch.mockResolvedValue(new Response())
+
+ const { result } = renderHook(() => useCanReachToInternet({ networkPollingInterval: 1000 }))
+
+ expect(mockFetch).toHaveBeenCalledTimes(1)
+
+ act(() => {
+ result.current.stopNetworkPolling()
+ })
+ expect(result.current.isNetworkPollingEnabled).toBe(false)
+ expect(mockFetch).toHaveBeenCalledTimes(2)
+
+ vi.advanceTimersByTimeAsync(1000)
+ expect(mockFetch).toHaveBeenCalledTimes(2)
+ })
+
+ it('should start polling when startNetworkPolling is called', async () => {
+ mockFetch.mockResolvedValue(new Response())
+
+ const { result } = renderHook(() => useCanReachToInternet({ enableNetworkPolling: false }))
+
+ expect(mockFetch).toHaveBeenCalledTimes(1)
+ expect(result.current.isNetworkPollingEnabled).toBe(false)
+
+ await vi.advanceTimersByTimeAsync(3000)
+ expect(mockFetch).toHaveBeenCalledTimes(1)
+
+ act(() => {
+ result.current.startNetworkPolling()
+ })
+
+ expect(result.current.isNetworkPollingEnabled).toBe(true)
+ expect(mockFetch).toHaveBeenCalledTimes(2)
+
+ await vi.advanceTimersByTimeAsync(3000)
+ expect(mockFetch).toHaveBeenCalledTimes(3)
+
+ await vi.advanceTimersByTimeAsync(3000)
+ expect(mockFetch).toHaveBeenCalledTimes(4)
+ })
+ })
+
+ describe('Manual network checking', () => {
+ it('should check network when forceCheckNetwork is called', async () => {
+ mockFetch.mockResolvedValue(new Response())
+
+ const { result } = renderHook(() => useCanReachToInternet({ enableNetworkPolling: false }))
+
+ expect(mockFetch).toHaveBeenCalledTimes(1)
+
+ act(() => {
+ result.current.forceCheckNetwork()
+ })
+
+ expect(mockFetch).toHaveBeenCalledTimes(2)
+ })
+
+ it('should update isCheckingConnection state during manual check', async () => {
+ let resolvePromise: (value: Response) => void
+ const pendingPromise = new Promise((resolve) => {
+ resolvePromise = resolve
+ })
+ mockFetch.mockReturnValue(pendingPromise)
+
+ const { result } = renderHook(() => useCanReachToInternet({ enableNetworkPolling: false }))
+
+ act(() => {
+ result.current.forceCheckNetwork()
+ })
+
+ expect(result.current.isCheckingConnection).toBe(true)
+
+ act(() => {
+ resolvePromise(new Response())
+ })
+
+ await waitFor(() => {
+ expect(result.current.isCheckingConnection).toBe(false)
+ })
+ })
+ })
+
+ describe('Browser online/offline detection', () => {
+ it('should return false for canReachToInternet when browser is offline', async () => {
+ mockNavigator.onLine = false
+
+ const { result } = renderHook(() => useCanReachToInternet())
+
+ await waitFor(() => {
+ expect(result.current.isOnline).toBe(false)
+ expect(result.current.canReachToInternet).toBe(false)
+ expect(result.current.isFullyConnected).toBe(false)
+ })
+
+ // Should not make fetch call when offline
+ expect(mockFetch).not.toHaveBeenCalled()
+ })
+
+ it('should listen to online/offline events', () => {
+ renderHook(() => useCanReachToInternet())
+
+ expect(mockAddEventListener).toHaveBeenCalledWith('online', expect.any(Function))
+ expect(mockAddEventListener).toHaveBeenCalledWith('offline', expect.any(Function))
+ })
+
+ it('should update the state when online/offline events are triggered without polling enabled', async () => {
+ const { result, rerender } = renderHook(() => useCanReachToInternet({ enableNetworkPolling: false }))
+
+ await waitFor(() => {
+ expect(result.current.canReachToInternet).toBe(true)
+ })
+
+ // Should update the state when offline
+ await waitFor(() => {
+ mockNavigator.onLine = false
+ rerender()
+ expect(result.current.canReachToInternet).toBe(false)
+ })
+
+ // Should update the state when online
+ await waitFor(() => {
+ mockNavigator.onLine = true
+ rerender()
+ expect(result.current.canReachToInternet).toBe(true)
+ })
+ })
+ })
+
+ describe('Cleanup and abort handling', () => {
+ it('should abort pending requests on unmount', async () => {
+ mockFetch.mockImplementation(() => {
+ // Never resolving the operation for aborting at unmount phase
+ return new Promise(() => {})
+ })
+
+ const { unmount } = renderHook(() => useCanReachToInternet())
+
+ expect(mockFetch).toHaveBeenCalled()
+
+ const abortSpy = vi.spyOn(AbortController.prototype, 'abort')
+
+ unmount()
+
+ expect(abortSpy).toHaveBeenCalledWith('cleanup')
+ })
+
+ it('should not update state if request was aborted', async () => {
+ const abortError = new Error('AbortError')
+ abortError.name = 'AbortError'
+
+ mockFetch.mockRejectedValue(abortError)
+
+ const { result } = renderHook(() => useCanReachToInternet())
+
+ // The state should not be updated when request is aborted
+ await waitFor(() => {
+ expect(result.current.isCheckingConnection).toBe(false)
+ })
+ })
+ })
+
+ describe('getCanReachToInternetStatus method', () => {
+ it('should return current canReachToInternet status', async () => {
+ mockFetch.mockResolvedValue(new Response())
+
+ const { result } = renderHook(() => useCanReachToInternet())
+
+ await waitFor(() => {
+ expect(result.current.canReachToInternet).toBe(true)
+ })
+
+ expect(result.current.getCanReachToInternetStatus()).toBe(true)
+ })
+
+ it('should return false when cannot reach internet', async () => {
+ mockFetch.mockRejectedValue(new Error('Network error'))
+
+ const { result } = renderHook(() => useCanReachToInternet())
+
+ await waitFor(() => {
+ expect(result.current.canReachToInternet).toBe(false)
+ })
+
+ expect(result.current.getCanReachToInternetStatus()).toBe(false)
+ })
+ })
+
+ describe('Edge cases', () => {
+ it('should handle multiple rapid calls to forceCheckNetwork', async () => {
+ mockFetch.mockResolvedValue(new Response())
+
+ const { result } = renderHook(() => useCanReachToInternet({ enableNetworkPolling: false }))
+
+ // Make multiple rapid calls
+ act(() => {
+ result.current.forceCheckNetwork()
+ result.current.forceCheckNetwork()
+ result.current.forceCheckNetwork()
+ })
+
+ await waitFor(() => {
+ expect(result.current.isCheckingConnection).toBe(false)
+ })
+
+ // Should handle gracefully without errors
+ expect(result.current.canReachToInternet).toBe(true)
+ })
+
+ it('should handle network status changes during polling', async () => {
+ mockFetch.mockResolvedValue(new Response())
+
+ const { result, rerender } = renderHook(
+ ({ online }) => {
+ mockNavigator.onLine = online
+ return useCanReachToInternet({ networkPollingInterval: 1000 })
+ },
+ { initialProps: { online: true } }
+ )
+
+ await waitFor(() => {
+ expect(result.current.canReachToInternet).toBe(true)
+ })
+
+ // Simulate going offline
+ rerender({ online: false })
+
+ await waitFor(() => {
+ expect(result.current.isOnline).toBe(false)
+ expect(result.current.canReachToInternet).toBe(false)
+ expect(result.current.isFullyConnected).toBe(false)
+ })
+ })
+ })
+})
diff --git a/src/lib/use-can-reach-to-internet/index.tsx b/src/lib/use-can-reach-to-internet/index.tsx
new file mode 100644
index 0000000..4f2df1f
--- /dev/null
+++ b/src/lib/use-can-reach-to-internet/index.tsx
@@ -0,0 +1,223 @@
+import { useEffect, useRef, useState, useSyncExternalStore } from 'react'
+import useSyncedRef from '../use-synced-ref'
+
+export type CanReachToInternetOptions = {
+ /** Enable automatic network polling to continuously check connectivity */
+ enableNetworkPolling?: boolean
+ /** Interval in milliseconds between network polls */
+ networkPollingInterval?: number
+ /** URL to test internet connectivity against */
+ testUrl?: string
+}
+export type CanReachToInternetBoolean = boolean
+
+const DEFAULT_OPTIONS: Required = {
+ enableNetworkPolling: true,
+ networkPollingInterval: 3000,
+ testUrl: 'https://dns.google', // https://8.8.8.8
+}
+
+/**
+ * @description
+ * A comprehensive React hook for monitoring internet connectivity status that goes beyond basic online/offline detection by actually testing network reachability.
+
+ * @example
+ * import { useCanReachToInternet } from 'classic-react-hooks'
+ *
+ * function ConnectivityStatus() {
+ const {
+ isOnline,
+ canReachToInternet,
+ isFullyConnected,
+ isCheckingConnection,
+ isNetworkPollingEnabled,
+ startNetworkPolling,
+ stopNetworkPolling,
+ forceCheckNetwork
+ } = useCanReachToInternet()
+
+ return (
+
+
Connectivity Status
+
+
+
+
+ Browser Online: {isOnline ? 'Yes' : 'No'}
+
+
+
+
+ Internet Reachable: {canReachToInternet ? 'Yes' : 'No'}
+
+
+
+
+ Fully Connected: {isFullyConnected ? 'Yes' : 'No'}
+
+
+ {isCheckingConnection && (
+
Checking connectivity...
+ )}
+
+
+
+
+ Check Now
+
+
+ {isNetworkPollingEnabled ? (
+
+ Stop Polling
+
+ ) : (
+
+ Start Polling
+
+ )}
+
+
+ )
+ }
+ *
+ * @see Docs https://classic-react-hooks.vercel.app/hooks/use-can-reach-to-internet.html
+ */
+export default function useCanReachToInternet(options: CanReachToInternetOptions = {}) {
+ const config = { ...DEFAULT_OPTIONS, ...options }
+
+ // Getting browser's online/offline status
+ const isOnline = useSyncExternalStore(subscribe, getSnapshot, () => true)
+
+ const [canReachToInternet, setCanReachToInternet] = useState(false)
+ const [isNetworkPollingEnabled, setIsNetworkPollingEnabled] = useState(config.enableNetworkPolling)
+ const [isCheckingConnection, setIsCheckingConnection] = useState(false)
+ const canReachToInternetRef = useSyncedRef(canReachToInternet)
+ let isInitialCallDone = useRef(false)
+
+ // Use refs to track cleanup and prevent memory leaks
+ const abortControllerRef = useRef(null)
+ const timeoutRef = useRef(null)
+
+ const handlers = useRef({
+ clearPendingOperations: () => {
+ if (abortControllerRef.current) {
+ abortControllerRef.current.abort('cleanup')
+ abortControllerRef.current = null
+ }
+ if (timeoutRef.current) {
+ clearTimeout(timeoutRef.current)
+ timeoutRef.current = null
+ }
+ },
+ stopNetworkPolling: () => setIsNetworkPollingEnabled(false),
+ startNetworkPolling: () => setIsNetworkPollingEnabled(true),
+ getCanReachToInternetStatus: () => canReachToInternetRef.current as CanReachToInternetBoolean,
+ })
+
+ /**
+ * Performs an actual network request to test internet connectivity
+ *
+ * @description
+ * This function makes a HEAD request to the configured test URL to verify
+ * that the device can actually reach the internet, not just that the browser
+ * thinks it's online.
+ *
+ */
+ const checkIfCanReachToInternet = async (
+ { pollingEnabled }: { pollingEnabled?: boolean } = { pollingEnabled: true }
+ ) => {
+ // If offline then early return with flag update
+ if (!isOnline) {
+ setCanReachToInternet(false)
+ return
+ }
+
+ // Clear any existing operations
+ handlers.current.clearPendingOperations()
+
+ const abortController = new AbortController()
+ abortControllerRef.current = abortController
+
+ setIsCheckingConnection(true)
+
+ try {
+ // ping to dns server to check if really connected to internet
+ await fetch(config.testUrl, {
+ method: 'HEAD',
+ cache: 'no-cache',
+ mode: 'no-cors',
+ headers: {
+ 'Cache-Control': 'no-cache, no-store, must-revalidate',
+ Pragma: 'no-cache',
+ },
+ signal: abortController.signal,
+ })
+ setCanReachToInternet(true)
+ } catch (err) {
+ // Only update state if the request wasn't aborted
+ if (!abortController.signal.aborted) {
+ setCanReachToInternet(false)
+ }
+ } finally {
+ if (isNetworkPollingEnabled && !abortController.signal.aborted) {
+ if (pollingEnabled) {
+ timeoutRef.current = setTimeout(() => checkIfCanReachToInternet(), config.networkPollingInterval)
+ }
+ }
+ setIsCheckingConnection(false)
+ }
+ }
+
+ useEffect(() => {
+ // If network polling is stopped, then do not run again.
+ // Initially trigger checker function
+ if (isInitialCallDone.current && !isNetworkPollingEnabled) {
+ // Even if polling is stopped, check if the device is online.
+ // And update the state
+ if (!isOnline) {
+ setCanReachToInternet(false)
+ } else {
+ checkIfCanReachToInternet({ pollingEnabled: false })
+ }
+ return
+ }
+ isInitialCallDone.current = true
+ checkIfCanReachToInternet()
+
+ return handlers.current.clearPendingOperations
+ }, [isOnline, isNetworkPollingEnabled, config.networkPollingInterval])
+
+ return {
+ isOnline,
+ canReachToInternet,
+ isFullyConnected: isOnline && canReachToInternet,
+ isNetworkPollingEnabled,
+ isCheckingConnection,
+ stopNetworkPolling: handlers.current.stopNetworkPolling,
+ startNetworkPolling: handlers.current.startNetworkPolling,
+ getCanReachToInternetStatus: handlers.current.getCanReachToInternetStatus,
+ forceCheckNetwork: checkIfCanReachToInternet,
+ }
+}
+
+// Handler to listen "online" and "offline" events
+function subscribe(callback: () => void) {
+ window.addEventListener('online', callback)
+ window.addEventListener('offline', callback)
+
+ return () => {
+ window.removeEventListener('online', callback)
+ window.removeEventListener('offline', callback)
+ }
+}
+// getting network connection status
+const getSnapshot = () => navigator.onLine
diff --git a/src/lib/use-combined-key-event-listener/index.tsx b/src/lib/use-combined-key-event-listener/index.tsx
deleted file mode 100644
index 8bae0ad..0000000
--- a/src/lib/use-combined-key-event-listener/index.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-'use client'
-import React, { useRef } from 'react'
-import { useEventListener } from '../use-event-listener'
-
-type Options = AddEventListenerOptions & {
- preventDefault?: boolean
- shouldAddEvent?: boolean
-}
-
-export default function useCombinedKeyEventListener(
- type: K,
- keys: string[],
- handler: (event: GlobalEventHandlersEventMap[K]) => void,
- options?: boolean | Options
-) {
- const pressedKeysMap = useRef>([])
- let shouldInjectEvent: boolean | undefined = true
- let eventOptions: Options = {}
-
- if (options && options instanceof Object && !Array.isArray(options)) {
- const { shouldAddEvent, ...restOptions } = options
- eventOptions = restOptions
- shouldInjectEvent = shouldAddEvent
- }
-
- const listener = (event: GlobalEventHandlersEventMap[K]) => {
- if ('key' in event) {
- event.ctrlKey && pressedKeysMap.current.push('Control')
- event.shiftKey && pressedKeysMap.current.push('Shift')
- event.altKey && pressedKeysMap.current.push('Alt')
-
- !pressedKeysMap.current.includes(event.key) && pressedKeysMap.current.push(event.key)
-
- if (keys.toString() == pressedKeysMap.current.toString()) {
- if (eventOptions?.preventDefault) event.preventDefault()
- handler(event)
- }
- }
- }
-
- const clearPressedKey = () => {
- pressedKeysMap.current.pop()
- }
-
- useEventListener(document, type, listener, options)
-
- useEventListener(document, 'keyup', clearPressedKey, options)
- useEventListener(window, 'blur', () => (pressedKeysMap.current = []), shouldInjectEvent)
- useEventListener(window, 'contextmenu', () => (pressedKeysMap.current = []), shouldInjectEvent)
-}
diff --git a/src/lib/use-copy-to-clipboard/index.test.tsx b/src/lib/use-copy-to-clipboard/index.test.tsx
new file mode 100644
index 0000000..dcec6b8
--- /dev/null
+++ b/src/lib/use-copy-to-clipboard/index.test.tsx
@@ -0,0 +1,370 @@
+import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
+import { render, screen, fireEvent, waitFor, renderHook } from '@testing-library/react'
+import React, { useState } from 'react'
+import useCopyToClipboard, { copyToClipboardFn } from '.'
+
+describe('use-copy-to-clipboard', () => {
+ // Mock clipboard API
+ const mockWriteText = vi.fn()
+ const originalClipboard = navigator.clipboard
+
+ beforeEach(() => {
+ vi.clearAllMocks()
+
+ Object.defineProperty(navigator, 'clipboard', {
+ value: {
+ writeText: mockWriteText,
+ },
+ configurable: true,
+ })
+
+ mockWriteText.mockResolvedValue(undefined)
+ })
+
+ afterEach(() => {
+ Object.defineProperty(navigator, 'clipboard', {
+ value: originalClipboard,
+ configurable: true,
+ })
+ })
+
+ describe('Hook behavior', () => {
+ it('should return a function', () => {
+ const { result } = renderHook(() => useCopyToClipboard())
+ expect(typeof result.current).toBe('function')
+ expect(result.current.length).toBe(3)
+ })
+
+ it('should use props callbacks when provided', async () => {
+ const onSuccess = vi.fn()
+ const onError = vi.fn()
+
+ render( )
+
+ const button = screen.getByTestId('copy-button')
+ fireEvent.click(button)
+
+ await waitFor(() => {
+ expect(mockWriteText).toHaveBeenCalledWith('test data')
+ expect(onSuccess).toHaveBeenCalled()
+ })
+ })
+
+ it('should prioritize callback parameters over props', async () => {
+ const propsOnSuccess = vi.fn()
+ const overrideOnSuccess = vi.fn()
+
+ render( )
+
+ const button = screen.getByTestId('copy-button-with-callbacks')
+ fireEvent.click(button)
+
+ await waitFor(() => {
+ expect(overrideOnSuccess).toHaveBeenCalled()
+ expect(propsOnSuccess).not.toHaveBeenCalled()
+ })
+ })
+ })
+
+ describe('Successful copy scenarios', () => {
+ it('should copy text successfully and call onSuccess', async () => {
+ render( )
+
+ const button = screen.getByTestId('copy-button')
+ fireEvent.click(button)
+
+ await waitFor(() => {
+ expect(mockWriteText).toHaveBeenCalledWith('test data')
+ expect(screen.getByTestId('success-message')).toBeInTheDocument()
+ })
+ })
+
+ it('should copy different text data', async () => {
+ let customData = 'custom clipboard data'
+ const { rerender } = render( )
+
+ const button = screen.getByTestId('copy-button')
+ fireEvent.click(button)
+
+ await waitFor(() => {
+ expect(mockWriteText).toHaveBeenCalledWith(customData)
+ })
+
+ customData = 'updated text data'
+ rerender( )
+
+ fireEvent.click(button)
+
+ await waitFor(() => {
+ expect(mockWriteText).toHaveBeenCalledWith(customData)
+ })
+ })
+
+ it('should work with empty string', async () => {
+ render( )
+
+ const button = screen.getByTestId('copy-button')
+ fireEvent.click(button)
+
+ await waitFor(() => {
+ expect(mockWriteText).toHaveBeenCalledWith('')
+ })
+ })
+ })
+
+ describe('Error scenarios', () => {
+ it('should handle clipboard writeText rejection', async () => {
+ const error = new Error('Clipboard write failed')
+ mockWriteText.mockRejectedValue(error)
+
+ render( )
+
+ const button = screen.getByTestId('copy-button')
+ fireEvent.click(button)
+
+ await waitFor(() => {
+ expect(screen.getByTestId('error-message')).toHaveTextContent('Clipboard write failed')
+ })
+ })
+
+ it('should handle missing clipboard API', async () => {
+ // Removing clipboard API
+ Object.defineProperty(navigator, 'clipboard', {
+ value: undefined,
+ configurable: true,
+ })
+
+ render( )
+
+ const button = screen.getByTestId('copy-button')
+ fireEvent.click(button)
+
+ await waitFor(() => {
+ expect(screen.getByTestId('error-message')).toHaveTextContent('Cliboard not available')
+ })
+ })
+
+ it('should handle exceptions in try-catch block', async () => {
+ // Mock clipboard to throw an exception
+ Object.defineProperty(navigator, 'clipboard', {
+ get() {
+ throw new Error('Clipboard access denied')
+ },
+ configurable: true,
+ })
+
+ render( )
+
+ const button = screen.getByTestId('copy-button')
+ fireEvent.click(button)
+
+ await waitFor(() => {
+ expect(screen.getByTestId('error-message')).toHaveTextContent('Clipboard access denied')
+ })
+ })
+ })
+})
+
+// copyToClipboardFn utility function
+describe('copyToClipboardFn', () => {
+ const mockWriteText = vi.fn()
+ const originalClipboard = navigator.clipboard
+
+ beforeEach(() => {
+ vi.clearAllMocks()
+
+ Object.defineProperty(navigator, 'clipboard', {
+ value: {
+ writeText: mockWriteText,
+ },
+ configurable: true,
+ })
+
+ mockWriteText.mockResolvedValue(undefined)
+ })
+
+ afterEach(() => {
+ Object.defineProperty(navigator, 'clipboard', {
+ value: originalClipboard,
+ configurable: true,
+ })
+ })
+
+ describe('Successful operations', () => {
+ it('should copy text and call onSuccess callback', async () => {
+ const onSuccess = vi.fn()
+ const onError = vi.fn()
+
+ await copyToClipboardFn('test text', onSuccess, onError)
+
+ await waitFor(() => {
+ expect(mockWriteText).toHaveBeenCalledWith('test text')
+ expect(onSuccess).toHaveBeenCalled()
+ expect(onError).not.toHaveBeenCalled()
+ })
+ })
+
+ it('should work without callbacks', async () => {
+ await expect(copyToClipboardFn('test text')).resolves.toBeUndefined()
+ expect(mockWriteText).toHaveBeenCalledWith('test text')
+ })
+
+ it('should work with only onSuccess callback', async () => {
+ const onSuccess = vi.fn()
+
+ await copyToClipboardFn('test text', onSuccess)
+
+ await waitFor(() => {
+ expect(onSuccess).toHaveBeenCalled()
+ })
+ })
+
+ it('should work with only onError callback', async () => {
+ const onError = vi.fn()
+
+ await copyToClipboardFn('test text', undefined, onError)
+
+ await waitFor(() => {
+ expect(mockWriteText).toHaveBeenCalledWith('test text')
+ expect(onError).not.toHaveBeenCalled()
+ })
+ })
+ })
+
+ describe('Error scenarios', () => {
+ it('should call onError when writeText fails', async () => {
+ const error = new Error('Write failed')
+ mockWriteText.mockRejectedValue(error)
+
+ const onSuccess = vi.fn()
+ const onError = vi.fn()
+
+ await copyToClipboardFn('test text', onSuccess, onError)
+
+ await waitFor(() => {
+ expect(onError).toHaveBeenCalledWith(error)
+ expect(onSuccess).not.toHaveBeenCalled()
+ })
+ })
+
+ it('should handle missing clipboard API', async () => {
+ Object.defineProperty(navigator, 'clipboard', {
+ value: undefined,
+ configurable: true,
+ })
+
+ const onError = vi.fn()
+
+ await copyToClipboardFn('test text', undefined, onError)
+
+ await waitFor(() => {
+ expect(onError).toHaveBeenCalledWith(
+ expect.objectContaining({
+ message: 'Cliboard not available',
+ })
+ )
+ })
+ })
+
+ it('should handle exceptions in try block', async () => {
+ Object.defineProperty(navigator, 'clipboard', {
+ get() {
+ throw new Error('Access denied')
+ },
+ configurable: true,
+ })
+
+ const onError = vi.fn()
+
+ await copyToClipboardFn('test text', undefined, onError)
+
+ await waitFor(() => {
+ expect(onError).toHaveBeenCalledWith(
+ expect.objectContaining({
+ message: 'Access denied',
+ })
+ )
+ })
+ })
+
+ it('should not throw when onError is not provided and error occurs', async () => {
+ mockWriteText.mockRejectedValue(new Error('Write failed'))
+
+ await expect(copyToClipboardFn('test text')).resolves.toBeUndefined()
+ })
+ })
+
+ describe('Edge cases', () => {
+ it('should handle special characters', async () => {
+ const specialText = '🚀 Special chars: áéíóú ñ €$¥'
+ const onSuccess = vi.fn()
+
+ await copyToClipboardFn(specialText, onSuccess)
+
+ await waitFor(() => {
+ expect(mockWriteText).toHaveBeenCalledWith(specialText)
+ expect(onSuccess).toHaveBeenCalled()
+ })
+ })
+
+ it('should handle very long text', async () => {
+ const longText = 'a'.repeat(10000)
+ const onSuccess = vi.fn()
+
+ await copyToClipboardFn(longText, onSuccess)
+
+ await waitFor(() => {
+ expect(mockWriteText).toHaveBeenCalledWith(longText)
+ expect(onSuccess).toHaveBeenCalled()
+ })
+ })
+
+ it('should handle newlines and tabs', async () => {
+ const textWithWhitespace = 'Line 1\nLine 2\tTabbed'
+ const onSuccess = vi.fn()
+
+ await copyToClipboardFn(textWithWhitespace, onSuccess)
+
+ await waitFor(() => {
+ expect(mockWriteText).toHaveBeenCalledWith(textWithWhitespace)
+ expect(onSuccess).toHaveBeenCalled()
+ })
+ })
+ })
+})
+
+const DummyTestComponent: React.FC<{
+ onSuccess?: () => void
+ onError?: (err: Error) => void
+ overrideOnSuccess?: () => void
+ testData?: string
+}> = ({ onSuccess, overrideOnSuccess, onError, testData = 'test data' }) => {
+ const [copied, setCopied] = useState(false)
+ const [error, setError] = useState(null)
+
+ const copyToClipboard = useCopyToClipboard({
+ onSuccess: onSuccess || (() => setCopied(true)),
+ onError: onError || ((err) => setError(err.message)),
+ })
+
+ return (
+
+
copyToClipboard(testData)} data-testid='copy-button'>
+ Copy
+
+
+ copyToClipboard(testData, () => {
+ setCopied(true)
+ overrideOnSuccess?.()
+ })
+ }
+ data-testid='copy-button-with-callbacks'
+ >
+ Copy with callbacks
+
+ {copied &&
Copied!
}
+ {error &&
{error}
}
+
+ )
+}
diff --git a/src/lib/use-copy-to-clipboard/index.tsx b/src/lib/use-copy-to-clipboard/index.tsx
index 26d5a07..ec85519 100644
--- a/src/lib/use-copy-to-clipboard/index.tsx
+++ b/src/lib/use-copy-to-clipboard/index.tsx
@@ -1,4 +1,3 @@
-'use client'
import React, { useRef } from 'react'
import useSyncedRef from '../use-synced-ref'
@@ -8,7 +7,31 @@ type CopyToClipboardFn = (data: string, onSuccess?: OnSuccess, onError?: OnError
/**
* @description
- * A hook for copying the data in the clipboard with success and error callbacks.
+ * A React hook that provides simple and reliable way to copy text to the clipboard with success and error handling callbacks.
+ *
+ * @example
+ import { useState } from 'react'
+ import { useCopyToClipboard } from 'classic-react-hooks'
+
+ export default function CopyButton() {
+ const [copied, setCopied] = useState(false)
+
+ const copyToClipboard = useCopyToClipboard({
+ onSuccess: () => {
+ setCopied(true)
+ setTimeout(() => setCopied(false), 2000)
+ },
+ onError: (error) => {
+ console.error('Failed to copy:', error)
+ },
+ })
+
+ const handleCopy = () => {
+ copyToClipboard('Hello, World!')
+ }
+
+ return {copied ? 'Copied!' : 'Copy Text'}
+ }
*
* @see Docs https://classic-react-hooks.vercel.app/hooks/use-copy-to-clipboard.html
*
@@ -23,6 +46,16 @@ export default function useCopyToClipboard(props?: { onSuccess?: OnSuccess; onEr
return copyToClipboard.current
}
+/**
+ *
+ * @example
+ copyToClipboardFn(
+ 'Text to copy',
+ () => console.log('Copied successfully!'),
+ (error) => console.error('Copy failed:', error)
+ )
+ *
+ */
export async function copyToClipboardFn(data: string, onSuccess?: OnSuccess, onError?: OnError) {
try {
if (navigator.clipboard) {
diff --git a/src/lib/use-counter/index.test.tsx b/src/lib/use-counter/index.test.tsx
index b5636df..cf4535e 100644
--- a/src/lib/use-counter/index.test.tsx
+++ b/src/lib/use-counter/index.test.tsx
@@ -7,7 +7,7 @@ describe('use-counter', () => {
})
it('should return counter value of zero, incrementCounter and decrementCounter handlers with default key', () => {
- const { result } = renderHook(() => useCounter('', 1))
+ const { result } = renderHook(() => useCounter('', { initialValue: 1 }))
expect('counter' in result.current).not.toBeUndefined()
expect(result.current.counter).toBe(1)
diff --git a/src/lib/use-counter/index.tsx b/src/lib/use-counter/index.tsx
index 593df73..0670cd7 100644
--- a/src/lib/use-counter/index.tsx
+++ b/src/lib/use-counter/index.tsx
@@ -1,4 +1,3 @@
-'use client'
import type { Prettify } from '../../types'
import React, { useRef, useState } from 'react'
import { capitalizeFirstLetter } from '../../utils/capitalize-first-letter'
@@ -8,13 +7,37 @@ const LOWERCASED_COUNTER_TEXT = COUNTER_TEXT.toLowerCase() as Lowercase
+
+
decrement
+
{counter}
+
increment
+
+
+ )
+ }
*
* @see Docs https://classic-react-hooks.vercel.app/hooks/use-counter.html
*
*/
-export default function useCounter(key = '' as K, initialValue: number = 0) {
- const [counter, setCounter] = useState(initialValue)
+export default function useCounter(
+ key = '' as K,
+ options?: { initialValue?: number; stepper?: number }
+) {
+ const [counter, setCounter] = useState(options?.initialValue ?? 0)
+ let jumpBy = options?.stepper ?? 1
const capitalizedKey = capitalizeFirstLetter(key)
@@ -30,10 +53,10 @@ export default function useCounter(key = '' as K, initial
const handlers = useRef({
incrementHandler: () => {
- setCounter((c) => c + 1)
+ setCounter((c) => c + jumpBy)
},
decrementHandler: () => {
- setCounter((c) => c - 1)
+ setCounter((c) => c - jumpBy)
},
})
diff --git a/src/lib/use-debounced-fn/index.test.tsx b/src/lib/use-debounced-fn/index.test.tsx
index 8f5fce2..78067cb 100644
--- a/src/lib/use-debounced-fn/index.test.tsx
+++ b/src/lib/use-debounced-fn/index.test.tsx
@@ -1,135 +1,525 @@
import { vi } from 'vitest'
-import { renderHook } from '@testing-library/react'
+import { renderHook, act } from '@testing-library/react'
import useDebouncedFn from '.'
describe('use-debounced-fn', () => {
beforeEach(() => {
vi.useFakeTimers()
})
+
afterEach(() => {
vi.useRealTimers()
+ vi.clearAllMocks()
})
- it('should return the debounced callback', () => {
- const callback = vi.fn()
- const { result } = renderHook(() => useDebouncedFn(callback, 300))
+ describe('mounting', () => {
+ it('should return a function', () => {
+ const callback = vi.fn()
+ const { result } = renderHook(() => useDebouncedFn({ callbackToBounce: callback, delay: 300 }))
+
+ expect(typeof result.current).toBe('function')
+ })
+
+ it('should not call callback on initialization', () => {
+ const callback = vi.fn()
+ renderHook(() => useDebouncedFn({ callbackToBounce: callback, delay: 300 }))
+
+ expect(callback).not.toHaveBeenCalled()
+ })
+
+ it('should not call callback immediately when invoked', () => {
+ const callback = vi.fn()
+ const { result } = renderHook(() => useDebouncedFn({ callbackToBounce: callback, delay: 300 }))
+
+ act(() => {
+ result.current()
+ })
- expect(typeof result.current).toBe('function')
+ expect(callback).not.toHaveBeenCalled()
+ })
})
- it('should not fire callback on initialization', () => {
- const callback = vi.fn()
- renderHook(() => useDebouncedFn(callback, 300))
+ describe('unmounting', () => {
+ it('should cleanup timer on unmount', () => {
+ const callback = vi.fn()
+
+ const { result, unmount } = renderHook(() => useDebouncedFn({ callbackToBounce: callback, delay: 500 }))
+
+ act(() => {
+ result.current()
+ })
+
+ unmount()
+
+ act(() => {
+ vi.advanceTimersByTime(600)
+ })
+
+ expect(callback).not.toHaveBeenCalled()
+ })
+
+ it('should cleanup multiple pending timers on unmount', () => {
+ const callback = vi.fn()
+
+ const { result, unmount } = renderHook(() => useDebouncedFn({ callbackToBounce: callback, delay: 300 }))
+
+ act(() => {
+ result.current() // First call
+ vi.advanceTimersByTime(100)
+ result.current() // Second call (cancels first)
+ vi.advanceTimersByTime(100)
+ result.current() // Third call (cancels second)
+ })
+
+ unmount()
+
+ act(() => {
+ vi.advanceTimersByTime(500)
+ })
+
+ expect(callback).not.toHaveBeenCalled()
+ })
+
+ it('should not cause memory leaks with repeated mount/unmount', () => {
+ const callback = vi.fn()
+
+ for (let i = 0; i < 10; i++) {
+ const { result, unmount } = renderHook(() => useDebouncedFn({ callbackToBounce: callback, delay: 100 }))
+
+ act(() => {
+ result.current()
+ })
+
+ unmount()
+ }
+
+ act(() => {
+ vi.advanceTimersByTime(200)
+ })
+
+ expect(callback).not.toHaveBeenCalled()
+ })
+ })
+
+ describe('Debouncing behavior', () => {
+ it('should use default delay of 300ms', () => {
+ const callback = vi.fn()
+ const { result } = renderHook(() => useDebouncedFn({ callbackToBounce: callback }))
+
+ act(() => {
+ result.current()
+ })
+
+ act(() => {
+ vi.advanceTimersByTime(299)
+ })
+ expect(callback).not.toHaveBeenCalled()
+
+ act(() => {
+ vi.advanceTimersByTime(1) // Total 300ms
+ })
+ expect(callback).toHaveBeenCalledTimes(1)
+ })
+
+ it('should respect custom delay', () => {
+ const callback = vi.fn()
+ const customDelay = 500
+ const { result } = renderHook(() => useDebouncedFn({ callbackToBounce: callback, delay: customDelay }))
+
+ act(() => {
+ result.current()
+ })
+
+ act(() => {
+ vi.advanceTimersByTime(499)
+ })
+ expect(callback).not.toHaveBeenCalled()
+
+ act(() => {
+ vi.advanceTimersByTime(1) // Total 500ms
+ })
+ expect(callback).toHaveBeenCalledTimes(1)
+ })
+
+ it('should debounce multiple rapid calls', () => {
+ const callback = vi.fn()
+ const { result } = renderHook(() => useDebouncedFn({ callbackToBounce: callback, delay: 200 }))
+
+ act(() => {
+ result.current() // Call 1
+ result.current() // Call 2 - should reset timer
+ result.current() // Call 3 - should reset timer
+ })
+
+ act(() => {
+ vi.advanceTimersByTime(100)
+ result.current() // Call 4 - should reset timer again
+ })
+
+ act(() => {
+ vi.advanceTimersByTime(199)
+ })
+ expect(callback).not.toHaveBeenCalled()
+
+ act(() => {
+ vi.advanceTimersByTime(1) // 200ms from last call
+ })
+ expect(callback).toHaveBeenCalledTimes(1)
+ })
+
+ it('should allow multiple executions after delay periods', () => {
+ const callback = vi.fn()
+ const { result } = renderHook(() => useDebouncedFn({ callbackToBounce: callback, delay: 100 }))
+
+ // First execution
+ act(() => {
+ result.current('first')
+ })
+ act(() => {
+ vi.advanceTimersByTime(100)
+ })
+ expect(callback).toHaveBeenCalledTimes(1)
+ expect(callback).toHaveBeenNthCalledWith(1, 'first')
+
+ // Second execution
+ act(() => {
+ result.current('second')
+ })
+ act(() => {
+ vi.advanceTimersByTime(100)
+ })
+ expect(callback).toHaveBeenCalledTimes(2)
+ expect(callback).toHaveBeenNthCalledWith(2, 'second')
+ })
+ })
+
+ describe('Arugment passing to callback', () => {
+ it('should pass arguments correctly to the callback', () => {
+ const callback = vi.fn()
+ const { result } = renderHook(() => useDebouncedFn({ callbackToBounce: callback }))
+
+ act(() => {
+ result.current('arg1', 'arg2', 123)
+ })
+
+ act(() => {
+ vi.advanceTimersByTime(300)
+ })
+
+ expect(callback).toHaveBeenCalledWith('arg1', 'arg2', 123)
+ })
+
+ it('should use arguments from the latest call', () => {
+ const callback = vi.fn()
+ const { result } = renderHook(() => useDebouncedFn({ callbackToBounce: callback, delay: 200 }))
- expect(callback).not.toHaveBeenCalled()
+ act(() => {
+ result.current('first')
+ result.current('second')
+ result.current('third') // This should be the final call
+ })
+
+ act(() => {
+ vi.advanceTimersByTime(200)
+ })
+
+ expect(callback).toHaveBeenCalledTimes(1)
+ expect(callback).toHaveBeenCalledWith('third')
+ })
+
+ it('should preserve argument references', () => {
+ const callback = vi.fn()
+ const { result } = renderHook(() => useDebouncedFn({ callbackToBounce: callback }))
+
+ const originalObj = { value: 'original' }
+
+ act(() => {
+ result.current(originalObj)
+ })
+
+ // Modify the object before debounce executes
+ originalObj.value = 'modified'
+
+ act(() => {
+ vi.advanceTimersByTime(300)
+ })
+
+ expect(callback).toHaveBeenCalledWith(originalObj)
+ expect(callback.mock.calls?.[0]?.[0].value).toBe('modified')
+ })
})
- it('should return the debounced callback with default 300ms delay', async () => {
- const callback = vi.fn()
- const { result } = renderHook(() => useDebouncedFn(callback))
+ describe('Context binding', () => {
+ it('should not preserve this context (calls with null)', () => {
+ let capturedThis: any = 'not-set'
+ const testObj = {
+ name: 'test',
+ callback: function () {
+ capturedThis = this
+ },
+ }
- result.current(10)
- vi.advanceTimersByTime(100)
- expect(callback).toHaveBeenCalledTimes(0)
+ const { result } = renderHook(() => useDebouncedFn({ callbackToBounce: testObj.callback }))
- vi.advanceTimersByTime(100)
- expect(callback).toHaveBeenCalledTimes(0)
+ act(() => {
+ result.current.call(testObj) // Try to set context
+ })
- vi.advanceTimersByTime(100)
- expect(callback).toHaveBeenCalledTimes(1)
+ act(() => {
+ vi.advanceTimersByTime(300)
+ })
+
+ // Your implementation calls with null, so this should be null/undefined
+ expect(capturedThis).toBeNull()
+ })
})
- it('should call deboucnced function with given arguments', async () => {
- const callback = vi.fn()
- const { result } = renderHook(() => useDebouncedFn(callback))
+ describe('Hook updates and re-renders', () => {
+ it('should update callback when it changes', () => {
+ const callback1 = vi.fn()
+ const callback2 = vi.fn(() => 'second')
+
+ const { result, rerender } = renderHook(({ callback }) => useDebouncedFn({ callbackToBounce: callback }), {
+ initialProps: { callback: callback1 },
+ })
+
+ act(() => {
+ result.current()
+ })
+
+ // Update the callback before execution
+ rerender({ callback: callback2 })
+
+ act(() => {
+ vi.advanceTimersByTime(300)
+ })
+
+ expect(callback1).not.toHaveBeenCalled()
+ expect(callback2).toHaveBeenCalledTimes(1)
+ })
+
+ it('should update delay and cleanup previous timer', () => {
+ const callback = vi.fn()
+
+ const { result, rerender } = renderHook(({ delay }) => useDebouncedFn({ callbackToBounce: callback, delay }), {
+ initialProps: { delay: 200 },
+ })
+
+ act(() => {
+ result.current()
+ })
+
+ // Update delay - this should cleanup the existing timer
+ rerender({ delay: 500 })
+
+ act(() => {
+ vi.advanceTimersByTime(200) // Original delay time
+ })
+ expect(callback).not.toHaveBeenCalled() // Should be cancelled
+
+ // New call with updated delay
+ act(() => {
+ result.current()
+ })
+
+ act(() => {
+ vi.advanceTimersByTime(500) // New delay time
+ })
+ expect(callback).toHaveBeenCalledTimes(1)
+ })
+
+ it('should handle callback updates during pending execution', () => {
+ let message = 'original'
+ const logFn = vi.fn()
+ const createCallback = () =>
+ vi.fn(() => {
+ logFn(message)
+ return message
+ })
+
+ let callback = createCallback()
+ const { result, rerender } = renderHook(() => useDebouncedFn({ callbackToBounce: callback }))
+
+ act(() => {
+ result.current()
+ })
- result.current(10)
- vi.advanceTimersByTime(300)
- expect(callback).toHaveBeenNthCalledWith(1, 10)
+ // Update both message and callback
+ message = 'updated'
+ callback = createCallback()
+ rerender()
- result.current(30)
- vi.advanceTimersByTime(300)
- expect(callback).toHaveBeenNthCalledWith(2, 30)
+ act(() => {
+ vi.advanceTimersByTime(300)
+ })
+
+ expect(callback).toHaveBeenCalledTimes(1)
+ expect(logFn).toHaveBeenCalledTimes(1)
+ expect(logFn).toHaveBeenNthCalledWith(1, 'updated')
+ })
})
- it('should debounce the callback with custom delay', () => {
- const callback = vi.fn()
+ describe('Error handling', () => {
+ it('should handle callback that throws an error', () => {
+ const errorCallback = vi.fn(() => {
+ throw new Error('Test error')
+ })
+ const { result } = renderHook(() => useDebouncedFn({ callbackToBounce: errorCallback }))
+
+ act(() => {
+ result.current()
+ })
+
+ expect(() => {
+ act(() => {
+ vi.advanceTimersByTime(300)
+ })
+ }).toThrow('Test error')
+
+ expect(errorCallback).toHaveBeenCalledTimes(1)
+ })
+
+ it('should continue working after callback error', () => {
+ let shouldThrow = true
+ const callback = vi.fn(() => {
+ if (shouldThrow) {
+ throw new Error('Test error')
+ }
+ return 'success'
+ })
- const { result } = renderHook(() => useDebouncedFn(callback, 500))
+ const { result } = renderHook(() => useDebouncedFn({ callbackToBounce: callback }))
- result.current(2)
- vi.advanceTimersByTime(300)
- result.current(2)
- result.current(2)
- vi.advanceTimersByTime(500)
+ // First call throws
+ act(() => {
+ result.current()
+ })
- expect(callback).toHaveBeenCalledTimes(1)
- expect(callback).toHaveBeenCalledWith(2)
+ expect(() => {
+ act(() => {
+ vi.advanceTimersByTime(300)
+ })
+ }).toThrow('Test error')
- result.current(5)
- vi.advanceTimersByTime(500)
- expect(callback).toHaveBeenCalledTimes(2)
- expect(callback).toHaveBeenCalledWith(2)
+ // Second call succeeds
+ shouldThrow = false
+ act(() => {
+ result.current()
+ })
+
+ act(() => {
+ vi.advanceTimersByTime(300)
+ })
+
+ expect(callback).toHaveBeenCalledTimes(2)
+ })
})
- it('should cleanup the timers on unmount', async () => {
- const callback = vi.fn()
+ describe('Edge cases', () => {
+ it('should handle rapid delay changes', () => {
+ const callback = vi.fn()
+ const delays = [100, 200, 50, 500, 300]
+ let currentDelay = delays[0]
+
+ const { result, rerender } = renderHook(() =>
+ useDebouncedFn({ callbackToBounce: callback, delay: currentDelay })
+ )
- const { result, unmount } = renderHook(() => useDebouncedFn(callback, 500))
+ delays.forEach((delay, index) => {
+ currentDelay = delay
+ rerender()
- result.current()
- unmount()
- vi.advanceTimersByTime(600)
- expect(callback).toHaveBeenCalledTimes(0)
+ act(() => {
+ result.current(`call-${index}`)
+ })
+ })
+
+ act(() => {
+ vi.advanceTimersByTime(300) // Final delay
+ })
+
+ expect(callback).toHaveBeenCalledTimes(1)
+ expect(callback).toHaveBeenCalledWith('call-4')
+ })
})
- it('should sync with updated delay param and cleanup the timers with it', () => {
- let delay = 200
- const callback = vi.fn()
-
- const { result, rerender } = renderHook(() => useDebouncedFn(callback, delay))
- result.current()
- vi.advanceTimersByTime(200)
- expect(callback).toHaveBeenCalledTimes(1)
-
- // should run with updated timer
- delay = 500
- rerender()
- result.current()
- vi.advanceTimersByTime(200)
- expect(callback).toHaveBeenCalledTimes(1)
- vi.advanceTimersByTime(300)
- expect(callback).toHaveBeenCalledTimes(2)
-
- // should cleanup scheduled call when timer is updated
- result.current()
- delay = 1000
- rerender()
- vi.advanceTimersByTime(500)
- expect(callback).toHaveBeenCalledTimes(2)
+ describe('Performance and memory', () => {
+ it('should not create new debounced function on every render', () => {
+ const callback = vi.fn()
+ const { result, rerender } = renderHook(() => useDebouncedFn({ callbackToBounce: callback }))
+
+ const firstDebouncedFn = result.current
+ rerender()
+ const secondDebouncedFn = result.current
+
+ expect(firstDebouncedFn).toBe(secondDebouncedFn)
+ })
+
+ it('should handle many rapid calls efficiently', () => {
+ const callback = vi.fn()
+ const { result } = renderHook(() => useDebouncedFn({ callbackToBounce: callback, delay: 100 }))
+
+ act(() => {
+ // Simulate many rapid calls
+ for (let i = 0; i < 1000; i++) {
+ result.current(i)
+ }
+ })
+
+ act(() => {
+ vi.advanceTimersByTime(100)
+ })
+
+ expect(callback).toHaveBeenCalledTimes(1)
+ expect(callback).toHaveBeenCalledWith(999) // Last call's argument
+ })
})
- it('callback param should be reactive', () => {
- let tempValue = 'temp'
+ describe('Integration with React lifecycle', () => {
+ it('should work correctly with React.StrictMode (double effect execution)', () => {
+ const callback = vi.fn()
+
+ // Simulate StrictMode by manually calling effects twice
+ const { result, rerender } = renderHook(() => useDebouncedFn({ callbackToBounce: callback, delay: 200 }))
+
+ // Simulate StrictMode re-render
+ rerender()
+
+ act(() => {
+ result.current()
+ })
- vi.spyOn(console, 'log')
+ act(() => {
+ vi.advanceTimersByTime(200)
+ })
- const callback = vi.fn(() => {
- console.log(tempValue)
+ expect(callback).toHaveBeenCalledTimes(1)
})
- const { result, rerender } = renderHook(() => useDebouncedFn(callback))
+ it('should handle component re-renders during debounce period', () => {
+ const callback = vi.fn()
+ let renderCount = 0
- result.current()
- vi.advanceTimersByTime(300)
- expect(callback).toHaveBeenCalledTimes(1)
- expect(console.log).toHaveBeenCalledWith('temp')
+ const { result, rerender } = renderHook(() => {
+ renderCount++
+ return useDebouncedFn({ callbackToBounce: callback, delay: 300 })
+ })
- tempValue = 'this is temp'
- rerender()
- result.current()
- vi.advanceTimersByTime(300)
- expect(callback).toHaveBeenCalledTimes(2)
- expect(console.log).toHaveBeenCalledWith('this is temp')
+ act(() => {
+ result.current()
+ })
+
+ // Force multiple re-renders during debounce period
+ act(() => {
+ vi.advanceTimersByTime(100)
+ rerender()
+ vi.advanceTimersByTime(100)
+ rerender()
+ vi.advanceTimersByTime(100) // Total 300ms
+ })
+
+ expect(callback).toHaveBeenCalledTimes(1)
+ expect(renderCount).toBeGreaterThan(1)
+ })
})
})
diff --git a/src/lib/use-debounced-fn/index.tsx b/src/lib/use-debounced-fn/index.tsx
index b51a672..934815d 100644
--- a/src/lib/use-debounced-fn/index.tsx
+++ b/src/lib/use-debounced-fn/index.tsx
@@ -1,32 +1,78 @@
-'use client'
import React, { useEffect, useRef } from 'react'
-import useSyncedRef from '../use-synced-ref'
const DEFAULT_DELAY = 300
/**
* @description
- * A hook which returns a debounced function.
+ * A React hook that returns a debounced version of any function, delaying its execution until after a specified delay has passed since the last time it was invoked.
+ *
+ * @example
+ *
+ import React, { useState, useEffect } from 'react'
+ import { useDebouncedFn } from 'classic-react-hooks'
+
+ export default function SearchInput() {
+ const [query, setQuery] = useState('')
+ const [results, setResults] = useState([])
+
+ const debouncedSearch = useDebouncedFn({
+ callbackToBounce: async (searchTerm: string) => {
+ if (searchTerm.trim()) {
+ const response = await fetch(`https://dummyjson.com/users/search?q=${searchTerm}`)
+ const data = await response.json()
+ setResults(data.results)
+ }
+ },
+ delay: 500,
+ })
+
+ const handleInputChange = (e: React.ChangeEvent) => {
+ const value = e.target.value
+ setQuery(value)
+ debouncedSearch(value)
+ }
+
+ useEffect(() => {
+ ;(async function () {
+ const response = await fetch(`https://dummyjson.com/users`)
+ const data = await response.json()
+ setResults(data.results)
+ })()
+ }, [])
+
+ return (
+
+
+
+ {results.map((result) => (
+
{result.name}
+ ))}
+
+
+ )
+ }
*
* @see Docs https://classic-react-hooks.vercel.app/hooks/use-debounced-fn.html
*
*/
-export default function useDebouncedFn any>(cb: T, delay = DEFAULT_DELAY) {
- const paramsRef = useSyncedRef({
- cb,
+export default function useDebouncedFn any>({
+ callbackToBounce,
+ delay,
+}: {
+ callbackToBounce: T
+ delay?: number
+}) {
+ const paramsRef = useRef({
+ callbackToBounce,
delay,
})
- const timerId = useRef()
- const debouncedCb = useRef({
- fn: (...args: Parameters) => {
- if (timerId.current) {
- clearTimeout(timerId.current)
- }
- timerId.current = setTimeout(() => paramsRef.current.cb.call(null, ...args), paramsRef.current.delay)
- },
- cleanup: () => clearTimeout(timerId.current),
- })
+ // tracking props with immutable object
+ paramsRef.current.delay = delay
+ paramsRef.current.callbackToBounce = callbackToBounce
+
+ // so can access the updated props inside debouncedFnWrapper function
+ const debouncedCb = useRef(debouncedFnWrapper(paramsRef.current))
useEffect(() => {
return () => {
@@ -39,18 +85,70 @@ export default function useDebouncedFn any>(cb: T,
/**
* @description
- * A wrapper function which returns debounced version of passed callback.
- * If needed to work outside of react, then use this wrapper function.
+ * A React hook that returns a debounced version of any function, delaying its execution until after a specified delay has passed since the last time it was invoked.
+ *
+ * @example
+ import { useState, useEffect } from 'react'
+ import { useDebouncedFn } from 'classic-react-hooks'
+
+ export default function SearchInput() {
+ const [query, setQuery] = useState('')
+ const [results, setResults] = useState([])
+
+ const debouncedSearch = useDebouncedFn({
+ callbackToBounce: async (searchTerm: string) => {
+ if (searchTerm.trim()) {
+ const response = await fetch(`https://dummyjson.com/users/search?q=${searchTerm}`)
+ const data = await response.json()
+ setResults(data.results)
+ }
+ },
+ delay: 500,
+ })
+
+ const handleInputChange = (e: React.ChangeEvent) => {
+ const value = e.target.value
+ setQuery(value)
+ debouncedSearch(value)
+ }
+
+ useEffect(() => {
+ ;(async function () {
+ const response = await fetch(`https://dummyjson.com/users`)
+ const data = await response.json()
+ setResults(data.results)
+ })()
+ }, [])
+
+ return (
+
+
+
+ {results.map((result) => (
+
{result.name}
+ ))}
+
+
+ )
+ }
+ *
+ * @see Docs https://classic-react-hooks.vercel.app/hooks/use-debounced-fn.html
*/
-export function debouncedFnWrapper any>(cb: T, delay = DEFAULT_DELAY) {
+export function debouncedFnWrapper any>(props: { callbackToBounce: T; delay?: number }) {
let timerId: NodeJS.Timeout
return {
- fn: (...args: Parameters) => {
+ fn: (...args: Parameters) => {
if (timerId) {
clearTimeout(timerId)
}
- timerId = setTimeout(() => cb.call(null, ...args), delay)
+ timerId = setTimeout(() => {
+ try {
+ props.callbackToBounce.call(null, ...args)
+ } catch (err) {
+ throw err
+ }
+ }, props.delay ?? DEFAULT_DELAY)
},
cleanup: () => clearTimeout(timerId),
}
diff --git a/src/lib/use-event-listener/index.test.tsx b/src/lib/use-event-listener/index.test.tsx
index 5d4db95..463b3b5 100644
--- a/src/lib/use-event-listener/index.test.tsx
+++ b/src/lib/use-event-listener/index.test.tsx
@@ -1,99 +1,271 @@
-import { renderHook } from '@testing-library/react'
-import { vi } from 'vitest'
+import { fireEvent, render, renderHook, screen } from '@testing-library/react'
+import { expect, vi } from 'vitest'
import { useEventListener } from '.'
+import { ElementRef, useRef, useState } from 'react'
+import { EvTarget } from '../../types'
describe('use-event-listener', () => {
- it('should render', () => {
- renderHook(() => useEventListener(null, 'click', () => {}))
- })
-
- it('should add listener on-mount and remove it on un-mount', () => {
- const div = document.createElement('div')
- const addSpy = vi.spyOn(div, 'addEventListener')
- const removeSpy = vi.spyOn(div, 'removeEventListener')
-
- const { rerender, unmount } = renderHook(() => {
- useEventListener(
- () => div,
- 'resize',
- () => {},
- { passive: true }
+ describe('mounting', () => {
+ it('should render without errors', () => {
+ renderHook(() =>
+ useEventListener({
+ target: () => null,
+ event: 'click',
+ options: {},
+ })
)
+
+ // @ts-expect-error handling the edge case if target is not type of function
+ renderHook(() => useEventListener({ target: null, event: 'click' }))
+ })
+
+ it('should not add event if handler is not provided', () => {
+ const div = document.createElement('div')
+ const addSpy = vi.spyOn(div, 'addEventListener')
+ const removeSpy = vi.spyOn(div, 'removeEventListener')
+ const fn = vi.fn()
+
+ renderHook(() => {
+ useEventListener({
+ target: () => div,
+ event: 'click',
+ })
+ })
+
+ expect(addSpy).toHaveBeenCalledTimes(0)
+ expect(removeSpy).not.toHaveBeenCalled()
+
+ renderHook(() => {
+ useEventListener({
+ target: () => div,
+ event: 'click',
+ handler: fn,
+ options: { shouldInjectEvent: false },
+ })
+ })
+ expect(addSpy).toHaveBeenCalledTimes(0)
+ expect(removeSpy).not.toHaveBeenCalled()
+
+ renderHook(() => {
+ useEventListener({ target: () => null, event: 'click', handler: fn })
+ })
+ expect(addSpy).toHaveBeenCalledTimes(0)
+ expect(removeSpy).not.toHaveBeenCalled()
})
+ })
- expect(addSpy).toHaveBeenCalledTimes(1)
- expect(removeSpy).toHaveBeenCalledTimes(0)
+ describe('unmounting', () => {
+ it('should remove event on-un-mount', () => {
+ const div = document.createElement('div')
+ const addSpy = vi.spyOn(div, 'addEventListener')
+ const removeSpy = vi.spyOn(div, 'removeEventListener')
+ const fn = vi.fn()
- rerender()
- expect(addSpy).toHaveBeenCalledTimes(2)
- expect(removeSpy).toHaveBeenCalledTimes(1)
+ const { unmount } = renderHook(() => {
+ useEventListener({ target: () => div, event: 'click', handler: fn })
+ })
- unmount()
- expect(addSpy).toHaveBeenCalledTimes(2)
- expect(removeSpy).toHaveBeenCalledTimes(2)
+ unmount()
+ expect(addSpy).toHaveBeenCalledTimes(1) // should be 1 on unmount
+ expect(removeSpy).toHaveBeenCalledTimes(1)
+ })
})
- it('should work with refs', () => {
- const div = document.createElement('div')
- const addSpy = vi.spyOn(div, 'addEventListener')
- const removeSpy = vi.spyOn(div, 'removeEventListener')
+ describe('event attach', () => {
+ it('should not re-add the event if the , and props are not changed', () => {
+ const div = document.createElement('div')
+ const addSpy = vi.spyOn(div, 'addEventListener')
+ const removeSpy = vi.spyOn(div, 'removeEventListener')
+
+ const fn = vi.fn()
- const ref = { current: div }
+ const { rerender } = renderHook(() => {
+ useEventListener({ target: () => div, event: 'click', handler: fn })
+ })
- const { rerender, unmount } = renderHook(() => {
- useEventListener(ref, 'resize', () => {}, { passive: true })
+ expect(addSpy).toHaveBeenCalledTimes(1)
+ rerender()
+ expect(addSpy).toHaveBeenCalledTimes(1)
+ expect(removeSpy).not.toHaveBeenCalled()
})
- expect(addSpy).toHaveBeenCalledTimes(1)
- expect(removeSpy).toHaveBeenCalledTimes(0)
+ it('should re-run the effect if the , and props are changed', () => {
+ const div = document.createElement('div')
+ div.textContent = 'div'
+
+ const addSpy = vi.spyOn(div, 'addEventListener')
+ const removeSpy = vi.spyOn(div, 'removeEventListener')
+
+ const handler = vi.fn()
+ const t = () => div
+
+ const { rerender, unmount } = renderHook(
+ (props: {
+ capture: boolean
+ shouldInjectEvent: boolean
+ event: keyof DocumentEventMap
+ target: EvTarget
+ }) => {
+ useEventListener({
+ target: props.target,
+ event: props.event,
+ handler: handler,
+ options: {
+ capture: props.capture,
+ shouldInjectEvent: props.shouldInjectEvent,
+ },
+ })
+ },
+ { initialProps: { capture: true, target: t, event: 'click', shouldInjectEvent: true } }
+ )
+
+ expect(addSpy).toHaveBeenCalledTimes(1)
+
+ // re-render with updated options.capture prop
+ rerender({ capture: false, target: t, event: 'click', shouldInjectEvent: true })
+ expect(addSpy).toHaveBeenCalledTimes(2)
+ expect(removeSpy).toHaveBeenCalledTimes(1)
- rerender()
- expect(addSpy).toHaveBeenCalledTimes(1)
- expect(removeSpy).toHaveBeenCalledTimes(0)
+ // re-render with updated options.shouldInjectEvent prop
+ rerender({ shouldInjectEvent: false, target: t, event: 'click', capture: false })
+ expect(addSpy).toHaveBeenCalledTimes(2)
+ expect(removeSpy).toHaveBeenCalledTimes(2)
- unmount()
- expect(addSpy).toHaveBeenCalledTimes(1)
- expect(removeSpy).toHaveBeenCalledTimes(1)
+ // re-render with updated event prop
+ rerender({ event: 'mousedown', shouldInjectEvent: true, capture: false, target: t })
+ expect(addSpy).toHaveBeenCalledTimes(3)
+ expect(removeSpy).toHaveBeenCalledTimes(2)
+
+ const div2 = document.createElement('div')
+ div2.textContent = 'div2'
+ const addSpy2 = vi.spyOn(div2, 'addEventListener')
+ const removeSpy2 = vi.spyOn(div2, 'removeEventListener')
+
+ // re-render with updated target
+ rerender({ target: () => div2, capture: false, event: 'mousedown', shouldInjectEvent: true })
+ expect(addSpy2).toHaveBeenCalledTimes(1)
+ expect(removeSpy).toHaveBeenCalledTimes(3) // remove old target event
+
+ // extra re-render test same target
+ rerender({ target: () => div2, capture: false, event: 'mousedown', shouldInjectEvent: true })
+ expect(addSpy2).toHaveBeenCalledTimes(1)
+
+ // unmount
+ expect(removeSpy2).not.toHaveBeenCalled()
+ unmount()
+ expect(addSpy2).toHaveBeenCalledTimes(1)
+ expect(removeSpy2).toHaveBeenCalledTimes(1)
+ })
})
- it('should fire listener on event trigger with proper context', () => {
- const div = document.createElement('div')
- const listener = vi.fn()
- renderHook(() => {
- useEventListener(div, 'click', listener, { passive: true })
+ describe('event trigger', () => {
+ it('should trigger event with proper event context', () => {
+ const div = document.createElement('div')
+ const fn = vi.fn()
+
+ renderHook(() => useEventListener({ target: () => div, event: 'click', handler: fn }))
+
+ const ev = new Event('click')
+
+ // first trigger
+ div.dispatchEvent(ev)
+ expect(fn).toHaveBeenCalledTimes(1)
+ expect(fn).toHaveBeenCalledWith(ev)
+
+ // second trigger
+ div.dispatchEvent(ev)
+ expect(fn).toHaveBeenCalledTimes(2)
+ expect(fn).toHaveBeenCalledWith(ev)
})
- const event = new Event('click')
- div.dispatchEvent(event)
+ it('should not trigger event after unmount', () => {
+ const div = document.createElement('div')
+ const fn = vi.fn()
- expect(listener).toHaveBeenCalledTimes(1)
- expect(listener).toHaveBeenCalledWith(event)
+ // const { unmount } = renderHook(() => useEventListener(() => div, 'click', handler))
+ const { unmount } = renderHook(() => useEventListener({ target: () => div, event: 'click', handler: fn }))
- div.dispatchEvent(event)
- expect(listener).toHaveBeenCalledTimes(2)
+ // unmount
+ unmount()
+
+ // test whether it is being triggered or not
+ const ev = new Event('click')
+ div.dispatchEvent(ev)
+ expect(fn).not.toHaveBeenCalled()
+ })
})
- it('should remove listener when shouldInjectEvent becomes false', () => {
- const div = document.createElement('div')
- const removeSpy = vi.spyOn(div, 'removeEventListener')
+ describe('integration with react component', () => {
+ it('should log the latest value of counter in handler', () => {
+ const fn = vi.fn()
+ const { result } = renderHook(() => useRef>(null))
+
+ const Wrapper = () => {
+ const [counter, setCounter] = useState(0)
+ useEventListener({
+ target: () => result.current.current,
+ event: 'click',
+ handler: () => {
+ fn(counter)
+ },
+ })
+
+ return (
+
+
setCounter((c) => c + 1)}>
+ update counter {counter}
+
+
+ log value
+
+
+ )
+ }
+
+ render( )
- const listener = vi.fn()
- const { rerender } = renderHook((shouldInjectEvent: boolean = true) => {
- useEventListener(div, 'click', listener, { passive: true, shouldInjectEvent })
+ fireEvent.click(screen.getByTestId('btn'))
+ result.current.current?.click()
+ expect(fn).toHaveBeenNthCalledWith(1, 1)
+
+ fireEvent.click(screen.getByTestId('btn'))
+ result.current.current?.click()
+ expect(fn).toHaveBeenNthCalledWith(2, 2)
})
- const event = new Event('click')
- div.dispatchEvent(event)
+ it('should be able to set target using `setElementRef` function', () => {
+ const fn = vi.fn()
+
+ const Wrapper = () => {
+ const [counter, setCounter] = useState(0)
+ const { setElementRef } = useEventListener({
+ event: 'click',
+ handler: () => {
+ fn(counter)
+ },
+ })
- expect(listener).toHaveBeenCalledTimes(1)
- expect(listener).toHaveBeenCalledWith(event)
+ return (
+
+
setCounter((c) => c + 1)}>
+ update counter {counter}
+
+
+ log value
+
+
+ )
+ }
- rerender(false)
- expect(listener).toHaveBeenCalledTimes(1)
- expect(removeSpy).toHaveBeenCalledTimes(1)
+ render( )
- // check whether event is cleanup or not
- div.dispatchEvent(event)
- expect(listener).toHaveBeenCalledTimes(1)
+ fireEvent.click(screen.getByTestId('btn'))
+ fireEvent.click(screen.getByTestId('log'))
+ expect(fn).toHaveBeenNthCalledWith(1, 1)
+
+ fireEvent.click(screen.getByTestId('btn'))
+ fireEvent.click(screen.getByTestId('log'))
+ expect(fn).toHaveBeenNthCalledWith(2, 2)
+ })
})
})
diff --git a/src/lib/use-event-listener/index.tsx b/src/lib/use-event-listener/index.tsx
index cac6d67..96743d2 100644
--- a/src/lib/use-event-listener/index.tsx
+++ b/src/lib/use-event-listener/index.tsx
@@ -1,70 +1,129 @@
-'use client'
-import type { Prettify } from '../../types'
-import React, { RefObject, useEffect } from 'react'
-import useSyncedRef from '../use-synced-ref'
+import type { EvHandler, EvOptions, EvTarget, UseEventListenerReturnValues } from '../../types'
-export type Target = null | EventTarget | RefObject | (() => EventTarget | null)
-export type Options = boolean | Prettify
-export type Handler = (event: Event) => void
+import React, { useEffect, useLayoutEffect, useRef, useState } from 'react'
+import useSyncedRef from '../use-synced-ref'
/* Have taken reference from ChakraUI's use-event-listener for typing out the props in type-safe manner. */
/**
* @description
- * A hook which handles dom events in efficient and declarative manner.
+ * A React hook that makes it easy to attach DOM event listeners declaratively with automatic cleanup.
+ *
+ * @example
+ import { useEventListener } from 'classic-react-hooks'
+
+ export default function ClickExample() {
+
+ const {setElementRef} = useEventListener({
+ event: 'click',
+ handler: (e) => {
+ console.log('Button clicked!', e)
+ },
+ })
+
+ return Click me
+ }
*
* @see Docs https://classic-react-hooks.vercel.app/hooks/use-event-listener.html
*/
-export function useEventListener(
- target: Target,
- event: K,
- handler?: (event: DocumentEventMap[K]) => void,
- options?: Options
-): void
-export function useEventListener(
- target: Target,
- event: K,
- handler?: (event: WindowEventMap[K]) => void,
- options?: Options
-): void
-export function useEventListener(
- target: Target,
- event: K,
- handler?: (event: GlobalEventHandlersEventMap[K]) => void,
- options?: Options
-): void
-export function useEventListener(target: Target, event: string, handler?: Handler, options?: Options) {
+export function useEventListener({
+ target,
+ event,
+ handler,
+ options,
+ layoutEffect,
+}: {
+ target?: EvTarget
+ event: K
+ handler?: (event: DocumentEventMap[K]) => void
+ options?: EvOptions
+ layoutEffect?: boolean
+}): UseEventListenerReturnValues
+export function useEventListener({
+ target,
+ event,
+ handler,
+ options,
+ layoutEffect,
+}: {
+ target?: EvTarget
+ event: K
+ handler?: (event: WindowEventMap[K]) => void
+ options?: EvOptions
+ layoutEffect?: boolean
+}): UseEventListenerReturnValues
+export function useEventListener({
+ target,
+ event,
+ handler,
+ options,
+ layoutEffect,
+}: {
+ target?: EvTarget
+ event: K
+ handler?: (event: GlobalEventHandlersEventMap[K]) => void
+ options?: EvOptions
+ layoutEffect?: boolean
+}): UseEventListenerReturnValues
+export function useEventListener({
+ target,
+ event,
+ handler,
+ options,
+ layoutEffect,
+}: {
+ target?: EvTarget
+ event: string
+ handler?: EvHandler
+ options?: EvOptions
+ layoutEffect?: boolean
+}) {
+ // Determining which hook to use -> layout or effect
+ const useSelectedHook = layoutEffect ? useLayoutEffect : useEffect
+
+ const [elementNode, setElementNode] = useState(null)
+
+ const setElementRef = useRef((elementNode: HTMLElement | null) => {
+ setElementNode(elementNode)
+ })
+
const listener = useSyncedRef({
handler,
options,
- })
- let shouldInjectEvent = true
- if (typeof options == 'object' && 'shouldInjectEvent' in options) {
- shouldInjectEvent = !!options.shouldInjectEvent
- }
-
- useEffect(() => {
- const node = typeof target === 'function' ? target() : target
+ effectCb: () => {
+ if (!shouldInjectEvent || !listener.current.handler || !elementNode) return
- if (!listener.current.handler || !node) return
+ const callback = (e: Event) => listener.current.handler?.(e)
+ elementNode.addEventListener(event, callback, listener.current.options)
- const callback = (e: Event) => listener.current.handler?.(e)
- const options = listener.current.options
-
- if (shouldInjectEvent) {
- if ('current' in node) {
- node.current?.addEventListener(event, callback, options)
- } else {
- node.addEventListener(event, callback, options)
+ return () => {
+ elementNode.removeEventListener(event, callback, listener.current.options)
}
+ },
+ })
+ let shouldInjectEvent = true,
+ capture,
+ once,
+ passive,
+ signal
+
+ if (typeof options == 'object') {
+ if ('shouldInjectEvent' in options) {
+ shouldInjectEvent = !!options.shouldInjectEvent
}
+ capture = options.capture
+ once = options.once
+ passive = options.passive
+ signal = options.signal
+ }
- return () => {
- if ('current' in node) {
- node.current?.removeEventListener(event, callback, options)
- } else {
- node.removeEventListener(event, callback, options)
- }
+ useEffect(() => {
+ if (typeof target == 'function' && shouldInjectEvent) {
+ setElementRef.current(target() as HTMLElement)
}
- }, [event, target, shouldInjectEvent])
+ }, [target, shouldInjectEvent])
+
+ useSelectedHook(listener.current.effectCb, [elementNode, event, shouldInjectEvent, capture, once, passive, signal])
+
+ return { setElementRef: setElementRef.current }
}
diff --git a/src/lib/use-intersection-observer/index.test.tsx b/src/lib/use-intersection-observer/index.test.tsx
index 6ea0b43..789e18e 100644
--- a/src/lib/use-intersection-observer/index.test.tsx
+++ b/src/lib/use-intersection-observer/index.test.tsx
@@ -1,41 +1,409 @@
-import { renderHook } from '@testing-library/react'
-import { vi } from 'vitest'
-import useInterSectionObserver from '.'
+import { act, render, renderHook, screen } from '@testing-library/react'
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
-describe('use-intersection-observer', () => {
- const InitialObserver = global.IntersectionObserver
-
- let IntersectionObserverSpy = vi.fn(() => ({
- observe: vi.fn(),
- unobserve: vi.fn(),
- disconnect: vi.fn(),
- takeRecords: () => [],
- root: document,
- rootMargin: '0px',
- thresholds: [0],
+import useIntersectionObserver from '.'
+
+// Mock IntersectionObserver
+const mockIntersectionObserver = vi.fn()
+const mockObserve = vi.fn()
+const mockUnobserve = vi.fn()
+const mockDisconnect = vi.fn()
+
+beforeEach(() => {
+ mockIntersectionObserver.mockImplementation((callback) => ({
+ observe: mockObserve,
+ unobserve: mockUnobserve,
+ disconnect: mockDisconnect,
+ // Store callback for manual triggering
+ _callback: callback,
}))
- beforeAll(() => {
- global.IntersectionObserver = IntersectionObserverSpy
+ // Mock window.IntersectionObserver
+ Object.defineProperty(window, 'IntersectionObserver', {
+ writable: true,
+ configurable: true,
+ value: mockIntersectionObserver,
})
+})
+
+afterEach(() => {
+ vi.clearAllMocks()
+})
+
+// Helper function to trigger intersection
+const forcefullyTriggerIntersection = (entry?: Partial, mockIndex = 0) => {
+ const mockInstance = mockIntersectionObserver.mock.results[mockIndex]?.value
+ mockInstance._callback([
+ {
+ isIntersecting: !!entry?.isIntersecting,
+ target: entry?.target || document.createElement('div'),
+ },
+ ])
+}
+
+describe('use-intersection-observer', () => {
+ describe('basic functionality', () => {
+ it('should return correct default property names when no key is provided', () => {
+ const { result } = renderHook(() => useIntersectionObserver())
+
+ expect(result.current).toHaveProperty('setElementRef')
+ expect(result.current).toHaveProperty('isElementIntersecting')
+ expect(result.current).toHaveProperty('element')
+ expect(typeof result.current.setElementRef).toBe('function')
+ expect(typeof result.current.isElementIntersecting).toBe('boolean')
+ expect(result.current.element).toBeNull()
+ })
+
+ it('should return correct property names when key is provided', () => {
+ const { result } = renderHook(() => useIntersectionObserver({ key: 'hero' }))
+
+ expect(result.current).toHaveProperty('setHeroElementRef')
+ expect(result.current).toHaveProperty('isHeroElementIntersecting')
+ expect(result.current).toHaveProperty('heroElement')
+ expect(typeof result.current.setHeroElementRef).toBe('function')
+ expect(typeof result.current.isHeroElementIntersecting).toBe('boolean')
+ expect(result.current.heroElement).toBeNull()
+ })
- afterAll(() => {
- global.IntersectionObserver = InitialObserver
+ it('should initialize with default state', () => {
+ const { result } = renderHook(() => useIntersectionObserver())
+
+ expect(result.current.element).toBeNull()
+ expect(result.current.isElementIntersecting).toBe(false)
+ })
})
- it('should run without error', () => {
- const div = document.createElement('div')
+ describe('element reference management', () => {
+ it('should update element when setElementRef is called', () => {
+ const { result } = renderHook(() => useIntersectionObserver())
+ const mockElement = document.createElement('div')
+
+ act(() => {
+ result.current.setElementRef(mockElement)
+ })
+
+ expect(result.current.element).toBe(mockElement)
+ })
+
+ it('should handle null element', () => {
+ const { result } = renderHook(() => useIntersectionObserver())
+ const mockElement = document.createElement('div')
+
+ act(() => {
+ result.current.setElementRef(mockElement)
+ })
+
+ expect(result.current.element).toBe(mockElement)
- renderHook(() => useInterSectionObserver([div]))
+ act(() => {
+ result.current.setElementRef(null)
+ })
+
+ expect(result.current.element).toBeNull()
+ })
})
- it('should call disconnect on un-mount', () => {
- const div = document.createElement('div')
+ describe('IntersectionObserver integration', () => {
+ it('should not create observer when element is null', () => {
+ renderHook(() => useIntersectionObserver())
+
+ expect(mockIntersectionObserver).not.toHaveBeenCalled()
+ })
+
+ it('should create observer when element is set', () => {
+ const { result } = renderHook(() => useIntersectionObserver())
+ const mockElement = document.createElement('div')
+
+ act(() => {
+ result.current.setElementRef(mockElement)
+ })
+
+ expect(mockIntersectionObserver).toHaveBeenCalledWith(
+ expect.any(Function),
+ expect.objectContaining({
+ root: undefined,
+ rootMargin: undefined,
+ threshold: undefined,
+ })
+ )
+ expect(mockObserve).toHaveBeenCalledWith(mockElement)
+ })
+
+ it('should pass through IntersectionObserver options', () => {
+ const { result } = renderHook(() =>
+ useIntersectionObserver({
+ root: document.body,
+ rootMargin: '10px',
+ threshold: 0.5,
+ })
+ )
+ const mockElement = document.createElement('div')
+
+ act(() => {
+ result.current.setElementRef(mockElement)
+ })
+
+ expect(mockIntersectionObserver).toHaveBeenCalledWith(
+ expect.any(Function),
+ expect.objectContaining({
+ root: document.body,
+ rootMargin: '10px',
+ threshold: 0.5,
+ })
+ )
+ })
+
+ it('should update intersection state when observer triggers', () => {
+ const { result } = renderHook(() => useIntersectionObserver())
+ const mockElement = document.createElement('div')
+
+ act(() => {
+ result.current.setElementRef(mockElement)
+ })
+
+ expect(result.current.isElementIntersecting).toBe(false)
+
+ // forcefully updating the state
+ act(() => {
+ forcefullyTriggerIntersection({ isIntersecting: true })
+ })
+
+ expect(result.current.isElementIntersecting).toBe(true)
+
+ act(() => {
+ forcefullyTriggerIntersection({ isIntersecting: false })
+ })
+
+ expect(result.current.isElementIntersecting).toBe(false)
+ })
+
+ it('should disconnect observer on cleanup', () => {
+ const { result, unmount } = renderHook(() => useIntersectionObserver())
+ const mockElement = document.createElement('div')
+
+ act(() => {
+ result.current.setElementRef(mockElement)
+ })
+
+ unmount()
+
+ expect(mockDisconnect).toHaveBeenCalled()
+ })
+
+ it('should reset intersection state on cleanup', () => {
+ const { result, rerender } = renderHook(() => useIntersectionObserver())
+ const mockElement = document.createElement('div')
+
+ act(() => {
+ result.current.setElementRef(mockElement)
+ })
+
+ act(() => {
+ forcefullyTriggerIntersection({ isIntersecting: true })
+ })
+
+ expect(result.current.isElementIntersecting).toBe(true)
+
+ // Trigger cleanup by changing element
+ act(() => {
+ result.current.setElementRef(null)
+ })
+
+ rerender()
+
+ expect(result.current.isElementIntersecting).toBe(false)
+ })
+ })
+
+ describe('onIntersection callback', () => {
+ it('should call onIntersection callback when intersection occurs', () => {
+ const onIntersection = vi.fn()
+ const { result } = renderHook(() => useIntersectionObserver({ onIntersection }))
+ const mockElement = document.createElement('div')
+
+ act(() => {
+ result.current.setElementRef(mockElement)
+ })
+
+ act(() => {
+ forcefullyTriggerIntersection({ target: mockElement })
+ })
+
+ expect(onIntersection).toHaveBeenCalledWith({ target: mockElement, isIntersecting: false })
+ })
+
+ it('should handle callback updates', () => {
+ const callback1 = vi.fn()
+ const callback2 = vi.fn()
+
+ const { result, rerender } = renderHook(
+ ({ callback }) => useIntersectionObserver({ onIntersection: callback }),
+ { initialProps: { callback: callback1 } }
+ )
+
+ const mockElement = document.createElement('div')
+
+ act(() => {
+ result.current.setElementRef(mockElement)
+ })
+
+ // Update callback
+ rerender({ callback: callback2 })
+
+ act(() => {
+ forcefullyTriggerIntersection({ isIntersecting: true, target: mockElement })
+ })
+
+ expect(callback1).not.toHaveBeenCalled()
+ expect(callback2).toHaveBeenCalledWith({ target: mockElement, isIntersecting: true })
+ })
+ })
+
+ describe('onlyTriggerOnce option', () => {
+ it('should unobserve element when onlyTriggerOnce is true', () => {
+ const { result } = renderHook(() => useIntersectionObserver({ onlyTriggerOnce: true }))
+ const mockElement = document.createElement('div')
+
+ act(() => {
+ result.current.setElementRef(mockElement)
+ })
+
+ act(() => {
+ forcefullyTriggerIntersection({ isIntersecting: true, target: mockElement })
+ })
+
+ expect(mockUnobserve).toHaveBeenCalledWith(mockElement)
+ })
+
+ it('should not unobserve when onlyTriggerOnce is false', () => {
+ const { result } = renderHook(() => useIntersectionObserver({ onlyTriggerOnce: false }))
+ const mockElement = document.createElement('div')
+
+ act(() => {
+ result.current.setElementRef(mockElement)
+ })
+
+ act(() => {
+ forcefullyTriggerIntersection({ isIntersecting: true, target: mockElement })
+ })
+
+ expect(mockUnobserve).not.toHaveBeenCalled()
+ })
+ })
+
+ // gracefully handling un-availability of the API
+ describe('IntersectionObserver availability', () => {
+ it('should warn when IntersectionObserver is not available', () => {
+ const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
+
+ let copiedObserver = window.IntersectionObserver
+ // @ts-expect-error Deleting the observer
+ window.IntersectionObserver = undefined
+
+ const { result } = renderHook(() => useIntersectionObserver())
+ const mockElement = document.createElement('div')
+
+ act(() => {
+ result.current.setElementRef(mockElement)
+ })
+
+ expect(consoleSpy).toHaveBeenCalledWith('IntersectionObserver is not available.')
+
+ consoleSpy.mockRestore()
+ window.IntersectionObserver = copiedObserver
+ })
+ it('should not log out warning in Production environment', () => {
+ const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
+
+ process.env.NODE_ENV = 'production'
+
+ let copiedObserver = window.IntersectionObserver
+ // @ts-expect-error Deleting the observer
+ window.IntersectionObserver = undefined
+
+ const { result } = renderHook(() => useIntersectionObserver())
+ const mockElement = document.createElement('div')
+
+ act(() => {
+ result.current.setElementRef(mockElement)
+ })
+
+ expect(consoleSpy).not.toHaveBeenCalledWith('IntersectionObserver is not available.')
+ consoleSpy.mockRestore()
+ window.IntersectionObserver = copiedObserver
+ })
+ })
+
+ describe('TypeScript type safety', () => {
+ it('should provide correct types for different key configurations', () => {
+ // Test with no key
+ const { result: result1 } = renderHook(() => useIntersectionObserver())
+
+ // should be accessible without TypeScript errors
+ result1.current.element
+ result1.current.setElementRef
+ result1.current.isElementIntersecting
+
+ // Test with key
+ const { result: result2 } = renderHook(() => useIntersectionObserver({ key: 'header' }))
+
+ // should be accessible without TypeScript errors
+ result2.current.headerElement
+ result2.current.setHeaderElementRef
+ result2.current.isHeaderElementIntersecting
+ })
+ })
+})
+
+// Integration test component
+function TestComponent({ hookKey }: { hookKey?: string }) {
+ const observer = hookKey ? useIntersectionObserver({ key: hookKey as any }) : useIntersectionObserver()
+
+ return (
+
+
+ Observed Element
+
+
+ {hookKey
+ ? String((observer as any)[`is${hookKey.charAt(0).toUpperCase()}${hookKey.slice(1)}ElementIntersecting`])
+ : String(observer.isElementIntersecting)}
+
+
+ )
+}
+
+describe('use-intersection-observer integration tests', () => {
+ it('should work in a real component without key', () => {
+ render( )
+
+ expect(screen.getByTestId('observed-element')).toBeInTheDocument()
+ expect(screen.getByTestId('intersection-status')).toHaveTextContent('false')
+
+ act(() => {
+ forcefullyTriggerIntersection({ isIntersecting: true })
+ })
+
+ expect(screen.getByTestId('intersection-status')).toHaveTextContent('true')
+ })
+
+ it('should work in a real component with key', () => {
+ render( )
+
+ expect(screen.getByTestId('observed-element')).toBeInTheDocument()
+ expect(screen.getByTestId('intersection-status')).toHaveTextContent('false')
- const { unmount } = renderHook(() => useInterSectionObserver([div]))
+ act(() => {
+ forcefullyTriggerIntersection({ isIntersecting: true })
+ })
- expect(IntersectionObserverSpy.mock.results[0]?.value.disconnect).toHaveBeenCalledTimes(0)
- unmount()
- expect(IntersectionObserverSpy.mock.results[0]?.value.disconnect).toHaveBeenCalledTimes(1)
+ expect(screen.getByTestId('intersection-status')).toHaveTextContent('true')
})
})
diff --git a/src/lib/use-intersection-observer/index.tsx b/src/lib/use-intersection-observer/index.tsx
index 10fcfe9..ebeb458 100644
--- a/src/lib/use-intersection-observer/index.tsx
+++ b/src/lib/use-intersection-observer/index.tsx
@@ -1,93 +1,139 @@
-import type { RefObject } from 'react'
import type { Prettify } from '../../types'
-import { useState, useEffect } from 'react'
+import { useEffect, useRef, useState } from 'react'
+import { capitalizeFirstLetter } from '../../utils/capitalize-first-letter'
+import useSyncedRef from '../use-synced-ref'
-export type Target = HTMLElement | RefObject | (() => HTMLElement | null) | null
+export interface BaseIntersectionObserverOptions {
+ onIntersection?: (entry: IntersectionObserverEntry) => void
+ onlyTriggerOnce?: boolean
+}
+
+// prettier-ignore
+export interface IntersectionObserverOptions extends IntersectionObserverInit, BaseIntersectionObserverOptions {
+ key?: Key
+}
-type Options = {
- mode?: 'lazy' | 'virtualized'
-} & IntersectionObserverInit
+export type IntersectionObserverResult = Prettify<
+ {
+ [K in Key as Key extends '' ? 'element' : `${Key}Element`]: HTMLElement | null // element
+ } & {
+ [K in Key as Key extends '' ? 'setElementRef' : `set${Capitalize}ElementRef`]: (
+ elementNode: HTMLElement | null
+ ) => void // setElement
+ } & {
+ [K in Key as Key extends '' ? 'isElementIntersecting' : `is${Capitalize}ElementIntersecting`]: boolean // isElementIntersecting
+ }
+>
/**
* @description
- * A hook which provides a way for listening to the Intersection Observer event for given target.
+ * A React hook that provides a declarative way to observe element visibility using the [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) API.
*
- * It takes an array of targets and returns an array of boolean values which represents whether the targets are intersecting the screen or not.
+ * @example
+ import { useIntersectionObserver } from 'classic-react-hooks'
+
+ export default function BasicExample() {
+ const { element, setElementRef, isElementIntersecting } = useIntersectionObserver({
+ threshold: 0.5,
+ onIntersection: (entry) => {
+ console.log('Intersection changed:', entry.isIntersecting)
+ },
+ })
+
+ return (
+
+
+
+ {isElementIntersecting ? 'Visible!' : 'Not visible'}
+
+
+
+ )
+ }
*
* @see Docs https://classic-react-hooks.vercel.app/hooks/use-intersection-observer.html
*/
-export default function useInterSectionObserver(targets: Target[], options: Prettify = {}): Array {
- const [visibilityStates, setVisiblilityStates] = useState(() => {
- return new Array(targets.length).fill(false) as Array
- })
+export default function useIntersectionObserver(
+ options?: IntersectionObserverOptions
+): IntersectionObserverResult {
+ const {
+ key = '' as Key,
+ onIntersection,
+ onlyTriggerOnce = false,
+ root,
+ rootMargin,
+ threshold,
+ ...restOptions
+ } = options ?? {}
- const intersection_options: IntersectionObserverInit = {
- root: options.root,
- rootMargin: options.rootMargin,
- threshold: options.threshold,
- }
+ const [element, setElement] = useState(null)
+ const [isIntersecting, setIsIntersecting] = useState(false)
- if (!options.mode) {
- options.mode = 'lazy'
- }
+ const onIntersectionRef = useSyncedRef(onIntersection)
+ const observerOptions = useSyncedRef({
+ root,
+ rootMargin,
+ threshold,
+ ...restOptions,
+ })
+
+ const setElementRef = useRef((elementNode: HTMLElement | null) => {
+ setElement(elementNode)
+ })
useEffect(() => {
if (!window.IntersectionObserver) {
- console.warn('IntersectionObserver is not available.')
+ if (process.env.NODE_ENV !== 'production') {
+ console.warn('IntersectionObserver is not available.')
+ }
return
}
- const io = new IntersectionObserver((entries) => {
- entries.forEach((entry) => {
- const entry_idx = entry.target.getAttribute('idx')
- if (entry.isIntersecting) {
- setVisiblilityStates((_visibilityState) => {
- if (entry_idx == null) return _visibilityState
-
- _visibilityState[+entry_idx] = true
- return [..._visibilityState]
- })
- if (options.mode == 'lazy') {
- io.unobserve(entry.target)
- }
- } else {
- setVisiblilityStates((_visibilityState) => {
- if (entry_idx == null) return _visibilityState
-
- _visibilityState[+entry_idx] = false
- return [..._visibilityState]
- })
- }
- })
- }, intersection_options)
-
- targets.forEach((element, idx) => observer(element, idx))
-
- function observer(element: Target, idx: number) {
- let target: HTMLElement | null = null
-
- try {
- if (element && 'current' in element) {
- target = element.current
- } else if (typeof element == 'function') {
- const ele = element()
- target = ele
- } else {
- target = element
+
+ if (!element) {
+ return
+ }
+
+ const observer = new IntersectionObserver((entries) => {
+ for (const entry of entries) {
+ const isCurrentlyIntersecting = entry.isIntersecting
+
+ setIsIntersecting(entry.isIntersecting)
+
+ // trigger onIntersection callback after intersection/non-intersection of the element
+ if (onIntersectionRef.current) {
+ onIntersectionRef.current?.(entry)
}
- if (target) {
- target.setAttribute('idx', idx.toString())
- io.observe(target)
+
+ // handle onlyTriggerOnce
+ if (onlyTriggerOnce && isCurrentlyIntersecting) {
+ observer.unobserve(entry.target)
+ observer.disconnect()
}
- } catch (err) {
- console.warn(err)
}
- }
+ }, observerOptions.current)
+
+ observer.observe(element)
return () => {
- io.disconnect()
+ if (element) {
+ observer.unobserve(element)
+ observer.disconnect()
+ }
+ setIsIntersecting(false)
}
- }, [])
+ }, [element, onlyTriggerOnce])
+
+ const capKey = key ? capitalizeFirstLetter(key) : ''
+ const propertyNames = {
+ elementKey: key ? `${key}Element` : 'element',
+ setRefKey: key ? `set${capKey}ElementRef` : 'setElementRef',
+ isIntersectingKey: key ? `is${capKey}ElementIntersecting` : 'isElementIntersecting',
+ }
- return visibilityStates
+ return {
+ [propertyNames.setRefKey]: setElementRef.current,
+ [propertyNames.isIntersectingKey]: isIntersecting,
+ [propertyNames.elementKey]: element,
+ } as IntersectionObserverResult
}
diff --git a/src/lib/use-interval-effect/index.test.tsx b/src/lib/use-interval-effect/index.test.tsx
index a3cafdd..8355f5f 100644
--- a/src/lib/use-interval-effect/index.test.tsx
+++ b/src/lib/use-interval-effect/index.test.tsx
@@ -8,65 +8,273 @@ describe('use-interval-effect', () => {
})
afterEach(() => {
vi.useRealTimers()
- })
- afterEach(() => {
vi.clearAllTimers()
})
- it('should fire callback with default interval of 100ms after the mount', () => {
- const fn = vi.fn()
- renderHook(() => useIntervalEffect(fn))
+ describe('mounting', () => {
+ it('should fire callback with default interval of 100ms after the mount', () => {
+ const fn = vi.fn()
+ renderHook(() => useIntervalEffect({ handler: fn }))
+
+ expect(fn).not.toHaveBeenCalled()
+ vi.advanceTimersByTime(99)
+ expect(fn).not.toHaveBeenCalled()
+ vi.advanceTimersByTime(1) // Total 100ms
+ expect(fn).toHaveBeenCalledTimes(1)
+
+ vi.advanceTimersByTime(100) // Total 200ms
+ expect(fn).toHaveBeenCalledTimes(2)
+ })
+
+ it('should fire callback after the given interval', () => {
+ const fn = vi.fn()
+ renderHook(() => useIntervalEffect({ handler: fn, interval: 500 }))
+
+ expect(fn).not.toHaveBeenCalled()
+ vi.advanceTimersByTime(499)
+ expect(fn).not.toHaveBeenCalled()
+ vi.advanceTimersByTime(1) // Total 500ms
+ expect(fn).toHaveBeenCalledTimes(1)
+
+ vi.advanceTimersByTime(500) // Total 1000ms
+ expect(fn).toHaveBeenCalledTimes(2)
+ })
- expect(fn).toHaveBeenCalledTimes(0)
- vi.advanceTimersByTime(100)
- expect(fn).toHaveBeenCalledTimes(1)
+ it('should fire callback multiple times at regular intervals', () => {
+ const fn = vi.fn()
+ renderHook(() => useIntervalEffect({ handler: fn, interval: 200 }))
+
+ vi.advanceTimersByTime(200)
+ expect(fn).toHaveBeenCalledTimes(1)
+
+ vi.advanceTimersByTime(200)
+ expect(fn).toHaveBeenCalledTimes(2)
+
+ vi.advanceTimersByTime(400) // two more intervals
+ expect(fn).toHaveBeenCalledTimes(4)
+ })
})
- it('should fire callback after the given interval', () => {
- const fn = vi.fn()
- renderHook(() => useIntervalEffect(fn, 500))
+ describe('unmounting', () => {
+ it('should clear interval on unmount', () => {
+ const fn = vi.fn()
+ const { unmount } = renderHook(() => useIntervalEffect({ handler: fn, interval: 500 }))
+
+ vi.advanceTimersByTime(400) // Before first interval
+ unmount()
+ vi.advanceTimersByTime(1000) // Advance past where intervals would have fired
+ expect(fn).not.toHaveBeenCalled()
+ })
- vi.advanceTimersByTime(500)
- expect(fn).toHaveBeenCalledTimes(1)
+ it('should not interfere with callback execution if unmounted after an interval has fired', () => {
+ const fn = vi.fn()
+ const { unmount } = renderHook(() => useIntervalEffect({ handler: fn, interval: 100 }))
- vi.advanceTimersByTime(500)
- expect(fn).toHaveBeenCalledTimes(2)
+ vi.advanceTimersByTime(100)
+ expect(fn).toHaveBeenCalledTimes(1)
+
+ unmount()
+ vi.advanceTimersByTime(1000)
+ expect(fn).toHaveBeenCalledTimes(1) // Should not fire again
+ })
})
- it('should clear the interval with clearTimer', () => {
- const fn = vi.fn()
- const { result } = renderHook(() => useIntervalEffect(fn, 500))
+ describe('clearTimer functionality', () => {
+ it('should clear the interval with clearTimer', () => {
+ const fn = vi.fn()
+ const { result } = renderHook(() => useIntervalEffect({ handler: fn, interval: 500 }))
+
+ vi.advanceTimersByTime(200)
+ result.current.clearTimer()
+ vi.advanceTimersByTime(1000)
+ expect(fn).not.toHaveBeenCalled()
+ })
+
+ it('should allow clearing timer multiple times without error', () => {
+ const fn = vi.fn()
+ const { result } = renderHook(() => useIntervalEffect({ handler: fn, interval: 500 }))
- result.current.clearTimer()
- vi.advanceTimersByTime(500)
- expect(fn).not.toHaveBeenCalled()
+ result.current.clearTimer()
+ result.current.clearTimer()
+ result.current.clearTimer()
+
+ vi.advanceTimersByTime(500)
+ expect(fn).not.toHaveBeenCalled()
+ })
+
+ it('should clear the interval when prop changes', () => {
+ const fn = vi.fn()
+
+ let interval = 300
+ const { rerender } = renderHook(() => useIntervalEffect({ handler: fn, interval }))
+
+ vi.advanceTimersByTime(200)
+ expect(fn).not.toHaveBeenCalled()
+
+ // Change interval, this should clear the old one and set a new one
+ interval = 500
+ rerender()
+
+ vi.advanceTimersByTime(200) // Advance remaining time for old 300ms interval (100ms) + 100ms for new 500ms interval
+ expect(fn).not.toHaveBeenCalled() // Old 300ms interval shouldn't fire
+
+ vi.advanceTimersByTime(300) // Remaining for new 500ms interval
+ expect(fn).toHaveBeenCalledTimes(1) // New 500ms interval fires
+
+ vi.advanceTimersByTime(500)
+ expect(fn).toHaveBeenCalledTimes(2)
+ })
})
- it('should set the interval with restartTimer', () => {
- const fn = vi.fn()
- const { result } = renderHook(() => useIntervalEffect(fn, 500))
+ describe('restartTimer functionality', () => {
+ it('should restart timer with original interval', () => {
+ const fn = vi.fn()
+ const { result } = renderHook(() => useIntervalEffect({ handler: fn, interval: 500 }))
+
+ // Let original timer fire once
+ vi.advanceTimersByTime(500)
+ expect(fn).toHaveBeenCalledTimes(1)
+
+ // Clear and restart timer
+ result.current.restartTimer()
+ vi.advanceTimersByTime(500)
+ expect(fn).toHaveBeenCalledTimes(2)
+
+ // It should continue to fire
+ vi.advanceTimersByTime(500)
+ expect(fn).toHaveBeenCalledTimes(3)
+ })
+
+ it('should restart timer with new interval value provided in restartTimer function', () => {
+ const fn = vi.fn()
+ const { result } = renderHook(() => useIntervalEffect({ handler: fn, interval: 500 }))
+
+ // Restart with new interval before original fires
+ vi.advanceTimersByTime(200) // partially advance original 500ms interval
+ result.current.restartTimer(600)
- vi.advanceTimersByTime(500)
- expect(fn).toHaveBeenCalledTimes(1)
+ // Original interval should not fire at 500ms
+ vi.advanceTimersByTime(300) // This would have been 500ms for original
+ expect(fn).not.toHaveBeenCalled()
- result.current.clearTimer()
- vi.advanceTimersByTime(500)
- vi.advanceTimersByTime(500)
- vi.advanceTimersByTime(500)
- expect(fn).toHaveBeenCalledTimes(1)
+ // New 600ms interval should fire
+ vi.advanceTimersByTime(300) // 300 + 300 = 600ms for new interval
+ expect(fn).toHaveBeenCalledTimes(1)
- // restart
- result.current.restartTimer()
- vi.advanceTimersByTime(500)
- expect(fn).toHaveBeenCalledTimes(2)
+ // New 600ms interval should fire again
+ vi.advanceTimersByTime(600)
+ expect(fn).toHaveBeenCalledTimes(2)
+ })
+
+ it('should restart timer with original value after overriding with restartTimer(new_interval)', () => {
+ const fn = vi.fn()
+ const { result } = renderHook(() => useIntervalEffect({ handler: fn, interval: 500 }))
+
+ vi.advanceTimersByTime(200)
+ result.current.restartTimer(600) // Override with 600ms
+
+ vi.advanceTimersByTime(600)
+ expect(fn).toHaveBeenCalledTimes(1)
+
+ // Now restart without arguments, it should pick up the original interval (500ms)
+ result.current.restartTimer()
+
+ vi.advanceTimersByTime(500)
+ expect(fn).toHaveBeenCalledTimes(2)
+
+ vi.advanceTimersByTime(500)
+ expect(fn).toHaveBeenCalledTimes(3)
+ })
+
+ it('should cancel previous timer when restarting', () => {
+ const fn = vi.fn()
+ const { result } = renderHook(() => useIntervalEffect({ handler: fn, interval: 500 }))
+
+ // Restart before original interval
+ vi.advanceTimersByTime(200)
+ result.current.restartTimer() // Should restart with 500ms
+
+ // Advance to where original would have fired
+ vi.advanceTimersByTime(300)
+ expect(fn).not.toHaveBeenCalled() // Original 500ms interval should be cancelled
+
+ // Advance to where restarted timer should fire
+ vi.advanceTimersByTime(200) // 300 + 200 = 500ms from restart
+ expect(fn).toHaveBeenCalledTimes(1)
+ })
+
+ it('should handle restart followed by clear', () => {
+ const fn = vi.fn()
+ const { result } = renderHook(() => useIntervalEffect({ handler: fn, interval: 500 }))
+
+ result.current.restartTimer() // Starts a new 500ms interval
+ result.current.clearTimer() // Clears it immediately
+ vi.advanceTimersByTime(1000)
+ expect(fn).not.toHaveBeenCalled()
+
+ // Should be able to restart again after clearing
+ result.current.restartTimer(200)
+ vi.advanceTimersByTime(200)
+ expect(fn).toHaveBeenCalledTimes(1)
+ vi.advanceTimersByTime(200)
+ expect(fn).toHaveBeenCalledTimes(2)
+ })
})
- it('should clear interval on unmount', () => {
- const fn = vi.fn()
- const { unmount, result } = renderHook(() => useIntervalEffect(fn, 500))
- // cleanup the timer
- vi.advanceTimersByTime(400)
- unmount()
- expect(fn).toHaveBeenCalledTimes(0)
+ describe('parameter updates', () => {
+ it('should use latest handler when interval fires', () => {
+ const fn1 = vi.fn()
+ const fn2 = vi.fn()
+ let currentHandler = fn1
+
+ const { rerender } = renderHook(() => useIntervalEffect({ handler: currentHandler, interval: 500 }))
+
+ // Update handler before first interval fires
+ vi.advanceTimersByTime(200)
+ currentHandler = fn2
+ rerender()
+
+ vi.advanceTimersByTime(300) // First interval fires
+ expect(fn1).not.toHaveBeenCalled()
+ expect(fn2).toHaveBeenCalledTimes(1)
+
+ vi.advanceTimersByTime(500) // Second interval fires
+ expect(fn2).toHaveBeenCalledTimes(2)
+ })
+
+ it('should use latest interval value for restartTimer', () => {
+ const fn = vi.fn()
+ let currentInterval = 500
+
+ const { result, rerender } = renderHook(() => useIntervalEffect({ handler: fn, interval: currentInterval }))
+
+ // Update interval and restart
+ currentInterval = 200
+ rerender() // This will clear the existing interval and set up a new one with 200ms
+ result.current.restartTimer() // This should restart with the *latest* prop value (200ms)
+
+ vi.advanceTimersByTime(200)
+ expect(fn).toHaveBeenCalledTimes(1)
+
+ vi.advanceTimersByTime(200)
+ expect(fn).toHaveBeenCalledTimes(2)
+ })
+ })
+
+ describe('error handling', () => {
+ it('should not throw when handler throws an error', () => {
+ const errorHandler = vi.fn(() => {
+ throw new Error('Test error')
+ })
+
+ // Vitest's fake timers will re-throw the error when advanceTimersByTime is called
+ // if the handler within the timer throws. So we wrap it in a try/catch or expect to throw.
+ const { rerender } = renderHook(() => useIntervalEffect({ handler: errorHandler, interval: 100 }))
+
+ expect(() => {
+ vi.advanceTimersByTime(100)
+ }).toThrow('Test error')
+ expect(errorHandler).toHaveBeenCalledTimes(1)
+ })
})
})
diff --git a/src/lib/use-interval-effect/index.tsx b/src/lib/use-interval-effect/index.tsx
index ae18fdb..df2d6e8 100644
--- a/src/lib/use-interval-effect/index.tsx
+++ b/src/lib/use-interval-effect/index.tsx
@@ -1,16 +1,38 @@
-'use client'
import React, { useEffect, useRef } from 'react'
import useSyncedRef from '../use-synced-ref'
/**
* @description
- * A hook which fires the provided callback every time when the given interval is passed, just like the setInterval.
+ * A React hook that executes a callback function at regular intervals, similar to `setInterval` but with additional control methods for clearing and restarting the timer.
+ *
+ * @example
+ import { useState } from 'react'
+ import { useIntervalEffect } from 'classic-react-hooks'
+
+ export default function Counter() {
+ const [count, setCount] = useState(0)
+
+ const { clearTimer, restartTimer } = useIntervalEffect({
+ handler: () => setCount((prev) => prev + 1),
+ interval: 1000, // 1 second
+ })
+
+ return (
+
+
Count: {count}
+ Pause
+ restartTimer()}>Resume
+ restartTimer(500)}>Speed Up (500ms)
+ restartTimer(2000)}>Slow Down (2s)
+
+ )
+ }
*
* @see Docs https://classic-react-hooks.vercel.app/hooks/use-interval-effect.html
*/
-export default function useIntervalEffect(cb: () => void, interval = 100) {
+export default function useIntervalEffect({ handler, interval = 100 }: { handler: () => void; interval?: number }) {
let paramsRef = useSyncedRef({
- cb,
+ handler,
interval,
})
const intervalId = useRef()
@@ -19,14 +41,14 @@ export default function useIntervalEffect(cb: () => void, interval = 100) {
clearTimer: () => clearInterval(intervalId.current),
restartTimer: (new_interval?: number) => {
handlers.current.clearTimer()
- intervalId.current = setInterval(paramsRef.current.cb, new_interval ?? paramsRef.current.interval)
+ intervalId.current = setInterval(() => paramsRef.current.handler(), new_interval ?? paramsRef.current.interval)
},
})
useEffect(() => {
- intervalId.current = setInterval(paramsRef.current.cb, paramsRef.current.interval)
+ intervalId.current = setInterval(() => paramsRef.current.handler(), interval)
return handlers.current.clearTimer
- }, [])
+ }, [interval])
return {
clearTimer: handlers.current.clearTimer,
diff --git a/src/lib/use-is-online/index.tsx b/src/lib/use-is-online/index.tsx
deleted file mode 100644
index fb1f445..0000000
--- a/src/lib/use-is-online/index.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-'use client'
-import React, { useSyncExternalStore } from 'react'
-
-/**
- * @description
- * A simple hook for getting the network connection state.
- *
- * @see Docs https://classic-react-hooks.vercel.app/hooks/use-is-online.html
- */
-export default function useIsOnline() {
- return useSyncExternalStore(subscribe, getSnapshot, () => true)
-}
-
-function subscribe(callback: () => void) {
- window.addEventListener('online', callback)
- window.addEventListener('offline', callback)
-
- return () => {
- window.addEventListener('online', callback)
- window.addEventListener('offline', callback)
- }
-}
-const getSnapshot = () => navigator.onLine
diff --git a/src/lib/use-local-storage/index.test.tsx b/src/lib/use-local-storage/index.test.tsx
index 1a153b9..a48aa54 100644
--- a/src/lib/use-local-storage/index.test.tsx
+++ b/src/lib/use-local-storage/index.test.tsx
@@ -1,58 +1,716 @@
-import { act, renderHook } from '@testing-library/react'
-import useLocalStorage from '.'
+import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest'
+import { renderHook, act, waitFor } from '@testing-library/react'
+import useLocalStorage from '.' // adjust path as needed
+
+// Mock localStorage
+const createMockStorage = () => {
+ let store: Record = {}
+ return {
+ getItem: vi.fn((key: string) => store[key] || null),
+ setItem: vi.fn((key: string, value: string) => {
+ store[key] = value.toString()
+ }),
+ removeItem: vi.fn((key: string) => {
+ delete store[key]
+ }),
+ clear: vi.fn(() => {
+ store = {}
+ }),
+ _getStore: () => ({ ...store }),
+ _setStore: (newStore: Record) => {
+ store = { ...newStore }
+ },
+ }
+}
+
+// Mock event system
+const createMockEventSystem = () => {
+ const eventListeners: Record = {}
+
+ return {
+ addEventListener: vi.fn((event: string, callback: Function) => {
+ if (!eventListeners[event]) {
+ eventListeners[event] = []
+ }
+ eventListeners[event]?.push(callback)
+ }),
+ removeEventListener: vi.fn((event: string, callback: Function) => {
+ if (eventListeners[event]) {
+ const index = eventListeners[event]?.indexOf(callback)
+ if (index && index > -1) {
+ eventListeners[event]?.splice(index, 1)
+ }
+ }
+ }),
+ dispatchEvent: vi.fn((event: Event) => {
+ const listeners = eventListeners[event.type] || []
+ listeners.forEach((listener) => listener(event))
+ }),
+ _triggerCustomEvent: (eventType: string) => {
+ const listeners = eventListeners[eventType] || []
+ listeners.forEach((listener) => listener(new Event(eventType)))
+ },
+ _triggerStorageEvent: (key: string, newValue: string) => {
+ const listeners = eventListeners['storage'] || []
+ const event = new StorageEvent('storage', { key, newValue })
+ listeners.forEach((listener) => listener(event))
+ },
+ _getListeners: () => ({ ...eventListeners }),
+ _clearListeners: () => {
+ Object.keys(eventListeners).forEach((key) => {
+ eventListeners[key] = []
+ })
+ },
+ }
+}
+
+let mockStorage: ReturnType
+let mockEvents: ReturnType
+
+// Global setup
+beforeEach(() => {
+ mockStorage = createMockStorage()
+ mockEvents = createMockEventSystem()
+
+ Object.defineProperty(window, 'localStorage', { value: mockStorage })
+ Object.defineProperty(window, 'addEventListener', { value: mockEvents.addEventListener })
+ Object.defineProperty(window, 'removeEventListener', { value: mockEvents.removeEventListener })
+ Object.defineProperty(window, 'dispatchEvent', { value: mockEvents.dispatchEvent })
+
+ vi.clearAllMocks()
+})
+
+afterEach(() => {
+ vi.clearAllMocks()
+})
describe('use-local-storage', () => {
- afterEach(() => {
- localStorage.clear()
+ describe('Initialization Tests', () => {
+ it('should initialize with primitive value when localStorage is empty', () => {
+ const { result } = renderHook(() => useLocalStorage({ key: 'test-primitive', initialValue: 'hello' }))
+
+ expect(result.current[0]).toBe('hello')
+ expect(mockStorage.getItem).toHaveBeenCalledWith('test-primitive')
+ })
+
+ it('should initialize with ssr', () => {
+ const { result } = renderHook(() => useLocalStorage({ key: 'test-primitive', initialValue: 'hello' }), {
+ hydrate: true,
+ })
+
+ expect(result.current[0]).toBe('hello')
+ expect(mockStorage.getItem).toHaveBeenCalledWith('test-primitive')
+ })
+
+ it('should initialize with function in ssr', () => {
+ const { result } = renderHook(() => useLocalStorage({ key: 'test-primitive', initialValue: () => 'hello' }), {
+ hydrate: true,
+ })
+
+ expect(result.current[0]).toBe('hello')
+ expect(mockStorage.getItem).toHaveBeenCalledWith('test-primitive')
+ })
+
+ it('should initialize with object value when localStorage is empty', () => {
+ const initialObj = { name: 'John', age: 30 }
+ const { result } = renderHook(() => useLocalStorage({ key: 'test-object', initialValue: initialObj }))
+
+ expect(result.current[0]).toEqual(initialObj)
+ })
+
+ it('should initialize with array value when localStorage is empty', () => {
+ const initialArray = [1, 2, 3, 'test', { nested: true }]
+ const { result } = renderHook(() => useLocalStorage({ key: 'test-array', initialValue: initialArray }))
+
+ expect(result.current[0]).toEqual(initialArray)
+ })
+
+ it('should initialize with function-based value', () => {
+ const initialValueFn = vi.fn(() => ({ computed: true }))
+ const { result } = renderHook(() =>
+ useLocalStorage({ key: 'test-function-init', initialValue: initialValueFn })
+ )
+
+ expect(initialValueFn).toHaveBeenCalledOnce()
+ expect(result.current[0]).toEqual(expect.objectContaining({ computed: true }))
+ })
+
+ it('should initialize with null value', () => {
+ const { result } = renderHook(() => useLocalStorage({ key: 'test-null', initialValue: null }))
+
+ expect(result.current[0]).toBe(null)
+ })
+
+ it('should initialize with undefined value', () => {
+ const { result } = renderHook(() => useLocalStorage({ key: 'test-undefined', initialValue: undefined }))
+
+ expect(result.current[0]).toBe(undefined)
+ })
+
+ it('should initialize with boolean value', () => {
+ const { result } = renderHook(() => useLocalStorage({ key: 'test-boolean', initialValue: false }))
+
+ expect(result.current[0]).toBe(false)
+ })
+
+ it('should initialize with number value including zero', () => {
+ const { result } = renderHook(() => useLocalStorage({ key: 'test-zero', initialValue: 0 }))
+
+ expect(result.current[0]).toBe(0)
+ })
})
- it('should return state and setState', () => {
- const { result } = renderHook(() => useLocalStorage('user'))
+ describe('LocalStorage Retrieval Tests', () => {
+ it('should retrieve existing string value from localStorage', () => {
+ mockStorage._setStore({ 'existing-key': '"stored-string"' })
+
+ const { result } = renderHook(() => useLocalStorage({ key: 'existing-key', initialValue: 'default' }))
+
+ expect(result.current[0]).toBe('stored-string')
+ })
+
+ it('should retrieve existing object from localStorage', () => {
+ const storedObj = { user: 'Alice', settings: { theme: 'dark' } }
+ mockStorage._setStore({ 'obj-key': JSON.stringify(storedObj) })
- expect(result.current[0]).toBe('')
- expect(typeof result.current[1]).toBe('function')
+ const { result } = renderHook(() => useLocalStorage({ key: 'obj-key', initialValue: {} }))
+
+ expect(result.current[0]).toEqual(storedObj)
+ })
+
+ it('should retrieve existing array from localStorage', () => {
+ const storedArray = ['item1', 'item2', { nested: 'object' }]
+ mockStorage._setStore({ 'array-key': JSON.stringify(storedArray) })
+
+ const { result } = renderHook(() => useLocalStorage({ key: 'array-key', initialValue: [] }))
+
+ expect(result.current[0]).toEqual(storedArray)
+ })
+
+ it('should retrieve boolean values from localStorage', () => {
+ mockStorage._setStore({ 'bool-key': 'true' })
+
+ const { result } = renderHook(() => useLocalStorage({ key: 'bool-key', initialValue: false }))
+
+ expect(result.current[0]).toBe(true)
+ })
+
+ it('should retrieve numeric values from localStorage', () => {
+ mockStorage._setStore({ 'num-key': '42' })
+
+ const { result } = renderHook(() => useLocalStorage({ key: 'num-key', initialValue: 0 }))
+
+ expect(result.current[0]).toBe(42)
+ })
})
- it('should be able handle error when item is undefined in local-storage', () => {
- localStorage.setItem('key', '') // when getting localStorage.getItem(key) => '', it results into undefined
- const { result } = renderHook(() => useLocalStorage('key'))
- expect(result.current[0]).toBeUndefined()
+ describe('State Update Tests', () => {
+ it('should update state with primitive value', () => {
+ const { result } = renderHook(() => useLocalStorage({ key: 'update-primitive', initialValue: 'initial' }))
+
+ act(() => {
+ result.current[1]('updated')
+ })
+
+ expect(result.current[0]).toBe('updated')
+ expect(mockStorage.setItem).toHaveBeenCalledWith('update-primitive', '"updated"')
+ })
+
+ it('should update state with object value', () => {
+ const { result } = renderHook(() => useLocalStorage({ key: 'update-object', initialValue: { count: 0 } }))
+
+ const newObj = { count: 5, name: 'test' }
+ act(() => {
+ result.current[1](newObj)
+ })
+
+ expect(result.current[0]).toEqual(newObj)
+ expect(mockStorage.setItem).toHaveBeenCalledWith('update-object', JSON.stringify(newObj))
+ })
+
+ it('should update state with function-based setter', () => {
+ const { result } = renderHook(() => useLocalStorage({ key: 'update-function', initialValue: 10 }))
+
+ act(() => {
+ result.current[1]((prev) => prev * 2)
+ })
+
+ expect(result.current[0]).toBe(20)
+ expect(mockStorage.setItem).toHaveBeenCalledWith('update-function', '20')
+ })
+
+ it('should update state with complex function-based setter', () => {
+ const initialState = { items: ['a', 'b'], count: 2 }
+ const { result } = renderHook(() => useLocalStorage({ key: 'update-complex', initialValue: initialState }))
+
+ act(() => {
+ result.current[1]((prev) => ({
+ ...prev,
+ items: [...prev.items, 'c'],
+ count: prev.count + 1,
+ }))
+ })
+
+ expect(result.current[0]).toEqual({
+ items: ['a', 'b', 'c'],
+ count: 3,
+ })
+ })
+
+ it('should handle multiple rapid updates', () => {
+ const { result } = renderHook(() => useLocalStorage({ key: 'rapid-updates', initialValue: 0 }))
+
+ act(() => {
+ result.current[1](1)
+ result.current[1](2)
+ result.current[1](3)
+ })
+
+ expect(result.current[0]).toBe(3)
+ expect(mockStorage.setItem).toHaveBeenCalledTimes(3)
+ })
+
+ it('should update with null value', () => {
+ const { result } = renderHook(() => useLocalStorage({ key: 'update-null', initialValue: 'something' }))
+
+ act(() => {
+ // @ts-expect-error Forcefully passing null
+ result.current[1](null)
+ })
+
+ expect(result.current[0]).toBe(null)
+ expect(mockStorage.setItem).toHaveBeenCalledWith('update-null', 'null')
+ })
+
+ it('should update with undefined value', () => {
+ const { result } = renderHook(() => useLocalStorage({ key: 'update-undefined', initialValue: 'something' }))
+
+ act(() => {
+ // @ts-expect-error Forcefully passing undefined
+ result.current[1](undefined)
+ })
+
+ expect(result.current[0]).toBe(undefined)
+ expect(mockStorage.setItem).toHaveBeenCalledWith('update-undefined', 'null')
+ })
})
- it('should be able handle error when with default value param', () => {
- localStorage.setItem('key', '')
- const { result } = renderHook(() => useLocalStorage('key', {}))
- expect(result.current[0]).toStrictEqual({})
+ describe('Event System Tests', () => {
+ it('should set up event listeners on mount', () => {
+ renderHook(() => useLocalStorage({ key: 'event-test', initialValue: 'initial' }))
+
+ expect(mockEvents.addEventListener).toHaveBeenCalledWith('event-test', expect.any(Function))
+ expect(mockEvents.addEventListener).toHaveBeenCalledWith('storage', expect.any(Function))
+ expect(mockEvents.addEventListener).toHaveBeenCalledTimes(2)
+ })
+
+ it('should clean up event listeners on unmount', () => {
+ const { unmount } = renderHook(() => useLocalStorage({ key: 'cleanup-test', initialValue: 'initial' }))
+
+ unmount()
+
+ expect(mockEvents.removeEventListener).toHaveBeenCalledWith('cleanup-test', expect.any(Function))
+ expect(mockEvents.removeEventListener).toHaveBeenCalledWith('storage', expect.any(Function))
+ expect(mockEvents.removeEventListener).toHaveBeenCalledTimes(2)
+ })
+
+ it('should dispatch custom event on state update', () => {
+ const { result } = renderHook(() => useLocalStorage({ key: 'dispatch-test', initialValue: 'initial' }))
+
+ act(() => {
+ result.current[1]('updated')
+ })
+
+ expect(mockEvents.dispatchEvent).toHaveBeenCalledWith(
+ expect.objectContaining({
+ type: 'dispatch-test',
+ })
+ )
+ })
+
+ it('should respond to custom events from other instances', async () => {
+ const { result } = renderHook(() => useLocalStorage({ key: 'sync-test', initialValue: 'initial' }))
+
+ // Simulate external update
+ mockStorage._setStore({ 'sync-test': '"external-update"' })
+
+ // Trigger custom event
+ act(() => {
+ mockEvents._triggerCustomEvent('sync-test')
+ })
+
+ await waitFor(() => {
+ expect(result.current[0]).toBe('external-update')
+ })
+ })
+
+ it('should respond to storage events from other tabs', async () => {
+ const { result } = renderHook(() => useLocalStorage({ key: 'cross-tab-test', initialValue: 'initial' }))
+
+ // Simulate cross-tab update
+ mockStorage._setStore({ 'cross-tab-test': '"from-other-tab"' })
+
+ act(() => {
+ mockEvents._triggerStorageEvent('cross-tab-test', '"from-other-tab"')
+ })
+
+ await waitFor(() => {
+ expect(result.current[0]).toBe('from-other-tab')
+ })
+ })
+
+ it('should ignore storage events for different keys', async () => {
+ const { result } = renderHook(() => useLocalStorage({ key: 'specific-key', initialValue: 'initial' }))
+
+ act(() => {
+ mockEvents._triggerStorageEvent('different-key', '"different-value"')
+ })
+
+ // Should remain unchanged
+ expect(result.current[0]).toBe('initial')
+ })
})
- it('should set the default value', () => {
- const { result } = renderHook(() => useLocalStorage('user', { name: 'Saitama' }))
+ describe('Key Change Tests', () => {
+ it('should handle key changes and migrate data to new key', () => {
+ let key = 'original-key'
+ const { result, rerender } = renderHook(() => useLocalStorage({ key, initialValue: 'initial' }))
+
+ // Set value with original key
+ act(() => {
+ result.current[1]('value-for-original')
+ })
+
+ // Change key
+ key = 'new-key'
+ rerender()
+
+ // Should remove old key and set new key with the cached value
+ expect(mockStorage.removeItem).toHaveBeenCalledWith('original-key')
+ expect(mockStorage.setItem).toHaveBeenCalledWith('new-key', '"value-for-original"')
+ })
+
+ it('should update event listeners when key changes', () => {
+ let key = 'event-key-1'
+ const { rerender } = renderHook(() => useLocalStorage({ key, initialValue: 'initial' }))
+
+ // Change key
+ key = 'event-key-2'
+ rerender()
+
+ // Should remove old listeners and add new ones
+ expect(mockEvents.removeEventListener).toHaveBeenCalledWith('event-key-1', expect.any(Function))
+ expect(mockEvents.addEventListener).toHaveBeenCalledWith('event-key-2', expect.any(Function))
+ })
+
+ it('should handle multiple key changes', () => {
+ let key = 'key-1'
+ const { result, rerender } = renderHook(() => useLocalStorage({ key, initialValue: 0 }))
+
+ act(() => {
+ result.current[1](1)
+ })
+
+ key = 'key-2'
+ rerender()
- expect(result.current[0]).toEqual({ name: 'Saitama' })
+ act(() => {
+ result.current[1](2)
+ })
+
+ key = 'key-3'
+ rerender()
+
+ expect(mockStorage.removeItem).toHaveBeenCalledWith('key-1')
+ expect(mockStorage.removeItem).toHaveBeenCalledWith('key-2')
+ expect(mockStorage.setItem).toHaveBeenCalledWith('key-3', '2')
+ })
})
- it('should update the state in local storage', () => {
- const { result, rerender } = renderHook(() => useLocalStorage('user', { name: 'Saitama' }))
+ describe('Error Handling Tests', () => {
+ it('should handle JSON.parse errors and return initial value', () => {
+ const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
+ mockStorage.getItem.mockReturnValueOnce('invalid-json-{')
+
+ const { result } = renderHook(() => useLocalStorage({ key: 'parse-error', initialValue: 'fallback' }))
+
+ expect(result.current[0]).toBe('fallback')
+ expect(consoleSpy).toHaveBeenCalled()
+
+ consoleSpy.mockRestore()
+ })
+
+ it('should handle JSON.stringify errors gracefully', () => {
+ const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
+
+ const { result } = renderHook(() => useLocalStorage({ key: 'stringify-error', initialValue: 'initial' }))
+
+ // Create circular reference
+ const circularObj: any = { name: 'test' }
+ circularObj.self = circularObj
+
+ act(() => {
+ result.current[1](circularObj)
+ })
+
+ expect(consoleSpy).toHaveBeenCalled()
+ // State should remain unchanged due to error
+ expect(result.current[0]).toBe('initial')
+
+ consoleSpy.mockRestore()
+ })
+
+ it('should handle localStorage.setItem errors (quota exceeded)', () => {
+ const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
+ mockStorage.setItem.mockImplementationOnce(() => {
+ throw new DOMException('QuotaExceededError')
+ })
+
+ const { result } = renderHook(() => useLocalStorage({ key: 'quota-error', initialValue: 'initial' }))
+
+ act(() => {
+ result.current[1]('new-value')
+ })
+
+ expect(consoleSpy).toHaveBeenCalled()
+ consoleSpy.mockRestore()
+ })
+
+ it('should handle localStorage.getItem errors', () => {
+ const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
+ mockStorage.getItem.mockImplementationOnce(() => {
+ throw new Error('Storage access denied')
+ })
+
+ const { result } = renderHook(() => useLocalStorage({ key: 'get-error', initialValue: 'fallback' }))
+
+ expect(result.current[0]).toBe('fallback')
+ expect(consoleSpy).toHaveBeenCalled()
+
+ consoleSpy.mockRestore()
+ })
+
+ it('should handle null localStorage gracefully', () => {
+ // Simulate environment where localStorage is null
+ Object.defineProperty(window, 'localStorage', { value: null })
+
+ const { result } = renderHook(() => useLocalStorage({ key: 'no-storage', initialValue: 'fallback' }))
+
+ expect(result.current[0]).toBe('fallback')
+ })
+ })
+
+ describe('Performance Tests', () => {
+ it('should re-parse only when string value changes', () => {
+ mockStorage._setStore({ 'string-change-test': '"value1"' })
+
+ const { result } = renderHook(() => useLocalStorage({ key: 'string-change-test', initialValue: 'initial' }))
+
+ expect(result.current[0]).toBe('value1')
+
+ // Change the stored value
+ mockStorage._setStore({ 'string-change-test': '"value2"' })
+
+ // Trigger re-evaluation
+ act(() => {
+ mockEvents._triggerCustomEvent('string-change-test')
+ })
+
+ expect(result.current[0]).toBe('value2')
+ })
+
+ it('should handle rapid successive updates efficiently', () => {
+ const { result } = renderHook(() => useLocalStorage({ key: 'rapid-test', initialValue: 0 }))
+
+ // Perform many rapid updates
+ act(() => {
+ for (let i = 1; i <= 100; i++) {
+ result.current[1](i)
+ }
+ })
- act(() => {
- result.current[1]({ name: 'Genos' })
+ expect(result.current[0]).toBe(100)
+ expect(mockStorage.setItem).toHaveBeenCalledTimes(100)
+ expect(mockEvents.dispatchEvent).toHaveBeenCalledTimes(100)
})
- rerender()
- expect(result.current[0]).toEqual({ name: 'Genos' })
- expect(JSON.parse(localStorage.getItem('user')!)).toEqual({ name: 'Genos' })
})
- it('should be able to handle function in setState', () => {
- const { result, rerender } = renderHook(() => useLocalStorage('user', { name: 'Saitama' }))
+ describe('SSR Support Tests', () => {
+ it('should work with server-side rendering (no localStorage)', () => {
+ // Mock server environment
+ const originalLocalStorage = window.localStorage
+ // @ts-ignore
+ delete window.localStorage
+
+ const { result } = renderHook(() => useLocalStorage({ key: 'ssr-test', initialValue: 'server-value' }))
+
+ expect(result.current[0]).toBe('server-value')
+
+ // Restore localStorage
+ window.localStorage = originalLocalStorage
+ })
+
+ it('should handle function-based initial values in SSR', () => {
+ const originalLocalStorage = window.localStorage
+ // @ts-ignore
+ delete window.localStorage
+
+ const initialFn = vi.fn(() => ({ ssr: true, data: 'test' }))
+ const { result } = renderHook(() => useLocalStorage({ key: 'ssr-function-test', initialValue: initialFn }))
+
+ expect(result.current[0]).toEqual({ ssr: true, data: 'test' })
+
+ // Restore localStorage
+ window.localStorage = originalLocalStorage
+ })
+ })
+
+ describe('Edge Cases', () => {
+ it('should handle empty string as a valid value', () => {
+ const { result } = renderHook(() => useLocalStorage({ key: 'empty-string', initialValue: 'default' }))
+
+ act(() => {
+ result.current[1]('')
+ })
+
+ expect(result.current[0]).toBe('')
+ expect(mockStorage.setItem).toHaveBeenCalledWith('empty-string', '""')
+ })
+
+ it('should handle very large objects', () => {
+ const largeObj = {
+ data: Array(1000)
+ .fill(0)
+ .map((_, i) => ({ id: i, value: `item-${i}` })),
+ }
+
+ const { result } = renderHook(() => useLocalStorage({ key: 'large-object', initialValue: null as any }))
+
+ act(() => {
+ result.current[1](largeObj)
+ })
+
+ expect(result.current[0]).toEqual(largeObj)
+ })
+
+ it('should handle special characters in keys', () => {
+ const specialKey = 'test-key-with-special-chars-!@#$%^&*()'
+ const { result } = renderHook(() => useLocalStorage({ key: specialKey, initialValue: 'special' }))
+
+ act(() => {
+ result.current[1]('updated')
+ })
+
+ expect(result.current[0]).toBe('updated')
+ expect(mockStorage.setItem).toHaveBeenCalledWith(specialKey, '"updated"')
+ })
+
+ it('should handle Date objects', () => {
+ const testDate = new Date('2023-01-01T00:00:00Z')
+ const { result } = renderHook(() =>
+ useLocalStorage({ key: 'date-test', initialValue: null as unknown as Date })
+ )
+
+ act(() => {
+ result.current[1](testDate)
+ })
+ // Date
+ expect(result.current[0]).toBe(testDate)
+ expect(mockStorage.getItem('date-test')).toBe(JSON.stringify(testDate))
+ })
+
+ it('should handle nested objects with arrays', () => {
+ const complexObj = {
+ user: {
+ name: 'John',
+ preferences: {
+ theme: 'dark',
+ notifications: ['email', 'push'],
+ settings: {
+ autoSave: true,
+ shortcuts: { save: 'Ctrl+S', open: 'Ctrl+O' },
+ },
+ },
+ },
+ metadata: {
+ created: new Date().toISOString(),
+ version: '1.0.0',
+ },
+ }
+
+ const { result } = renderHook(() => useLocalStorage({ key: 'complex-nested', initialValue: {} }))
+
+ act(() => {
+ result.current[1](complexObj)
+ })
+
+ expect(result.current[0]).toEqual(complexObj)
+ })
+
+ it('should maintain referential integrity for objects', () => {
+ const { result } = renderHook(() => useLocalStorage({ key: 'ref-test', initialValue: { items: [] as any[] } }))
+
+ act(() => {
+ result.current[1]((prev) => ({
+ ...prev,
+ items: [...prev.items, 'new-item'],
+ }))
+ })
+
+ const state1 = result.current[0]
+
+ act(() => {
+ result.current[1]((prev) => ({
+ ...prev,
+ timestamp: Date.now(),
+ }))
+ })
+
+ const state2 = result.current[0]
+
+ expect(state1).not.toBe(state2) // Different object references
+ expect(state2.items).toContain('new-item')
+ })
+ })
+
+ describe('Multiple Instance Tests', () => {
+ it('should allow multiple instances with different keys', () => {
+ const { result: result1 } = renderHook(() => useLocalStorage({ key: 'instance-1', initialValue: 'value1' }))
+
+ const { result: result2 } = renderHook(() => useLocalStorage({ key: 'instance-2', initialValue: 'value2' }))
+
+ expect(result1.current[0]).toBe('value1')
+ expect(result2.current[0]).toBe('value2')
+
+ act(() => {
+ result1.current[1]('updated1')
+ })
+
+ act(() => {
+ result2.current[1]('updated2')
+ })
+
+ expect(result1.current[0]).toBe('updated1')
+ expect(result2.current[0]).toBe('updated2')
+ })
+
+ it('should sync multiple instances with the same key', async () => {
+ const { result: result1 } = renderHook(() => useLocalStorage({ key: 'shared-key', initialValue: 'initial' }))
+
+ const { result: result2 } = renderHook(() => useLocalStorage({ key: 'shared-key', initialValue: 'initial' }))
+
+ // Update from first instance
+ act(() => {
+ result1.current[1]('from-instance-1')
+ })
+
+ // Both should have the updated value
+ expect(result1.current[0]).toBe('from-instance-1')
- act(() => {
- result.current[1]((old_value) => {
- old_value.name = 'Blast'
- return { ...old_value }
+ // Second instance should update via event
+ await waitFor(() => {
+ expect(result2.current[0]).toBe('from-instance-1')
})
})
- rerender()
- expect(result.current[0]).toEqual({ name: 'Blast' })
- expect(JSON.parse(localStorage.getItem('user')!)).toEqual({ name: 'Blast' })
})
})
diff --git a/src/lib/use-local-storage/index.tsx b/src/lib/use-local-storage/index.tsx
index 52e9892..e8c4fb3 100644
--- a/src/lib/use-local-storage/index.tsx
+++ b/src/lib/use-local-storage/index.tsx
@@ -1,50 +1,157 @@
-'use client'
-import type { Dispatch, MutableRefObject } from 'react'
-import React, { useRef, useState } from 'react'
+import type { Dispatch, SetStateAction } from 'react'
+import React, { useRef, useCallback, useSyncExternalStore } from 'react'
/**
* @description
- * A hook for managing the states with `local-storage`.
- *
- * It working is just like the `useState`.
- *
- * It automatically updates the state in `local-storage`.
+ * A React hook that provides a seamless way to persist and synchronize state with `localStorage`, offering a `useState`-like API with cross-tab synchronization.
*
+ * @example
+ import { useLocalStorage } from 'classic-react-hooks'
+
+ function UserPreferences() {
+ const [theme, setTheme] = useLocalStorage({ key: 'theme', defaultValue: 'light' })
+ const [language, setLanguage] = useLocalStorage({ key: 'language', defaultValue: 'en' })
+
+ return (
+
+ setTheme(e.target.value)}>
+ Light
+ Dark
+
+
+ setLanguage(e.target.value)}>
+ English
+ Spanish
+ French
+
+
+ )
+ }
*
* @see Docs https://classic-react-hooks.vercel.app/hooks/use-local-storage.html
*/
-export default function useLocalStorage(key: string, defaultValue?: State) {
- const [state, setState] = useState(() => {
+export default function useLocalStorage({
+ key,
+ initialValue,
+}: {
+ key: string
+ initialValue?: State | (() => State)
+}) {
+ // Cache the last parse value to avoid unnecessary re-renders
+ const lastValueRef = useRef(null)
+ const lastStringRef = useRef(null)
+ const lastKeyRef = useRef(key)
+
+ const getStoredState = useCallback(() => {
try {
+ // Key has changed, reset cached values
+ if (lastKeyRef.current !== key) {
+ localStorage.removeItem(lastKeyRef.current)
+ localStorage.setItem(key, JSON.stringify(lastValueRef.current))
+ lastKeyRef.current = key
+ lastValueRef.current = null
+ lastStringRef.current = null
+ }
+
const item = localStorage.getItem(key)
- if (defaultValue && item == null) {
- return defaultValue
+
+ if (item != null) {
+ // Only parse if the string value has changed
+ if (lastStringRef.current !== item) {
+ lastStringRef.current = item
+ lastValueRef.current = JSON.parse(item)
+ }
+ return lastValueRef.current!
}
- const parsed_value = item == null ? '' : JSON.parse(item)
- return parsed_value
} catch (err) {
- if (defaultValue) {
- return defaultValue
- }
- return undefined
+ console.log(err)
}
- })
-
- const updateState: MutableRefObject>> = useRef(
- (value: State | ((state: State) => State)) => {
- let new_value = value
- if (typeof value == 'function') {
- setState((state) => {
- new_value = (value as (state: State) => State)(state)
- localStorage.setItem(key, JSON.stringify(new_value))
- return new_value
- })
- } else {
- setState(new_value)
- localStorage.setItem(key, JSON.stringify(new_value))
- }
+
+ // Return initial value
+ let returnVal: State
+ if (lastValueRef.current) {
+ returnVal = lastValueRef.current
+ } else if (typeof initialValue == 'function') {
+ returnVal = (initialValue as () => State)()
+ } else {
+ returnVal = initialValue as State
}
+
+ // Cache the initial value
+ lastValueRef.current = returnVal
+
+ return lastValueRef.current!
+ }, [key])
+
+ // Server-side snapshot - return initial value to avoid hydration mismatch
+ const getServerSnapshot = useCallback(() => {
+ if (lastValueRef.current) {
+ return lastValueRef.current
+ }
+ if (typeof initialValue == 'function') {
+ lastValueRef.current = (initialValue as () => State)()
+ } else {
+ lastValueRef.current = initialValue as State
+ }
+ return lastValueRef.current!
+ }, [])
+
+ const storedState = useSyncExternalStore(
+ useCallback(
+ (callback) => {
+ const handleStorageChange = (event: Event) => {
+ callback()
+ }
+
+ // Listen for our custom events
+ window.addEventListener(key, handleStorageChange)
+
+ // Also listen for storage event from other tabs
+ const handleStorageEvent = (event: StorageEvent) => {
+ if (event.key === key) {
+ callback()
+ }
+ }
+
+ window.addEventListener('storage', handleStorageEvent)
+
+ return () => {
+ window.removeEventListener(key, handleStorageChange)
+ window.removeEventListener('storage', handleStorageEvent)
+ }
+ },
+ [key]
+ ),
+ getStoredState,
+ getServerSnapshot
+ )
+
+ const updateState: Dispatch> = useCallback(
+ (state: State | ((prevState: State) => State)) => {
+ try {
+ let newValue: State
+
+ if (typeof state === 'function') {
+ newValue = (state as (state: State) => State)(storedState)
+ } else {
+ newValue = state
+ }
+
+ const serializedValue = JSON.stringify(newValue === undefined ? null : newValue)
+ localStorage.setItem(key, serializedValue)
+
+ // Update cache
+ lastStringRef.current = serializedValue
+ lastValueRef.current = newValue
+
+ // Notify subscriber
+ window.dispatchEvent(new Event(key))
+ } catch (err) {
+ console.log(err)
+ }
+ },
+ [key, storedState]
)
- return [state, updateState.current] as const
+ return [storedState, updateState] as const
}
diff --git a/src/lib/use-multi-intersection-observer/index.test.tsx b/src/lib/use-multi-intersection-observer/index.test.tsx
new file mode 100644
index 0000000..8ccfb99
--- /dev/null
+++ b/src/lib/use-multi-intersection-observer/index.test.tsx
@@ -0,0 +1,133 @@
+import { act, renderHook } from '@testing-library/react'
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
+
+import useMultipleIntersectionObserver from '.'
+
+// Mock IntersectionObserver
+const mockIntersectionObserver = vi.fn()
+const mockObserve = vi.fn()
+const mockUnobserve = vi.fn()
+const mockDisconnect = vi.fn()
+
+beforeEach(() => {
+ mockIntersectionObserver.mockImplementation((callback) => ({
+ observe: mockObserve,
+ unobserve: mockUnobserve,
+ disconnect: mockDisconnect,
+ // Store callback for manual triggering
+ _callback: callback,
+ }))
+
+ // Mock window.IntersectionObserver
+ Object.defineProperty(window, 'IntersectionObserver', {
+ writable: true,
+ configurable: true,
+ value: mockIntersectionObserver,
+ })
+})
+
+afterEach(() => {
+ vi.clearAllMocks()
+})
+
+// Helper function to trigger intersection
+const forcefullyTriggerIntersection = (entry?: Partial, mockIndex = 0) => {
+ const mockInstance = mockIntersectionObserver.mock.results[mockIndex]?.value
+ mockInstance._callback([
+ {
+ isIntersecting: !!entry?.isIntersecting,
+ target: entry?.target || document.createElement('div'),
+ },
+ ])
+}
+
+describe('use-multi-intersection-observer', () => {
+ it('creates observers for multiple keys', () => {
+ const { result } = renderHook(() => useMultipleIntersectionObserver(['header', 'footer', 'sidebar']))
+
+ expect(result.current.header).toHaveProperty('setHeaderElementRef')
+ expect(result.current.header).toHaveProperty('isHeaderElementIntersecting')
+ expect(result.current.header).toHaveProperty('headerElement')
+
+ expect(result.current.footer).toHaveProperty('setFooterElementRef')
+ expect(result.current.sidebar).toHaveProperty('setSidebarElementRef')
+ })
+
+ it('passes options to all observers', () => {
+ const onIntersection = vi.fn()
+ const { result } = renderHook(() =>
+ useMultipleIntersectionObserver(['a', 'b'], {
+ threshold: 0.8,
+ onIntersection,
+ onlyTriggerOnce: true,
+ })
+ )
+
+ const elA = document.createElement('div')
+ const elB = document.createElement('div')
+
+ act(() => {
+ result.current.a.setAElementRef(elA)
+ result.current.b.setBElementRef(elB)
+ })
+
+ expect(mockIntersectionObserver).toHaveBeenCalledWith(
+ expect.any(Function),
+ expect.objectContaining({ threshold: 0.8 })
+ )
+
+ act(() => forcefullyTriggerIntersection({ isIntersecting: true, target: elA }))
+ expect(onIntersection).toHaveBeenCalledWith({ target: elA, isIntersecting: true })
+ expect(mockUnobserve).toHaveBeenCalledWith(elA) // onlyTriggerOnce
+ })
+
+ it('handles independent intersection states', () => {
+ const { result } = renderHook(() => useMultipleIntersectionObserver(['left', 'right']))
+
+ const leftEl = document.createElement('div')
+ const rightEl = document.createElement('div')
+
+ act(() => {
+ result.current.left.setLeftElementRef(leftEl)
+ result.current.right.setRightElementRef(rightEl)
+ })
+
+ // Trigger only left intersection
+ act(() => forcefullyTriggerIntersection({ isIntersecting: true, target: leftEl }))
+
+ expect(result.current.left.isLeftElementIntersecting).toBe(true)
+ expect(result.current.right.isRightElementIntersecting).toBe(false)
+
+ // Trigger right intersection
+ act(() => forcefullyTriggerIntersection({ isIntersecting: true, target: rightEl }, 1))
+ expect(result.current.left.isLeftElementIntersecting).toBe(true)
+ expect(result.current.right.isRightElementIntersecting).toBe(true)
+
+ // Again update the status
+ act(() => forcefullyTriggerIntersection({ isIntersecting: false, target: leftEl }))
+ expect(result.current.left.isLeftElementIntersecting).toBe(false)
+ expect(result.current.right.isRightElementIntersecting).toBe(true)
+
+ act(() => forcefullyTriggerIntersection({ isIntersecting: false, target: rightEl }, 1))
+ expect(result.current.left.isLeftElementIntersecting).toBe(false)
+ expect(result.current.right.isRightElementIntersecting).toBe(false)
+ })
+
+ it('works with empty keys array', () => {
+ const { result } = renderHook(() => useMultipleIntersectionObserver([]))
+ expect(result.current).toEqual({})
+ })
+
+ it('maintains type safety for returned observers', () => {
+ const { result } = renderHook(() => useMultipleIntersectionObserver(['nav', 'main'] as const))
+
+ // These should be accessible without TypeScript errors
+ result.current.nav.navElement
+ result.current.nav.setNavElementRef
+ result.current.nav.isNavElementIntersecting
+
+ result.current.main.mainElement
+ result.current.main.setMainElementRef
+ result.current.main.isMainElementIntersecting
+ })
+})
diff --git a/src/lib/use-multi-intersection-observer/index.tsx b/src/lib/use-multi-intersection-observer/index.tsx
new file mode 100644
index 0000000..caff80c
--- /dev/null
+++ b/src/lib/use-multi-intersection-observer/index.tsx
@@ -0,0 +1,15 @@
+import type { IntersectionObserverOptions } from '../use-intersection-observer'
+
+import useIntersectionObserver from '../use-intersection-observer'
+
+export default function useMultiIntersectionObserver(
+ keys: readonly Key[],
+ options?: Omit
+) {
+ const observers = keys.reduce((acc, key) => {
+ acc[key] = useIntersectionObserver({ ...options, key })
+ return acc
+ }, {} as Record>>)
+
+ return observers
+}
diff --git a/src/lib/use-on-mount-effect/index.tsx b/src/lib/use-on-mount-effect/index.tsx
index 18faf98..cc29edb 100644
--- a/src/lib/use-on-mount-effect/index.tsx
+++ b/src/lib/use-on-mount-effect/index.tsx
@@ -1,13 +1,19 @@
-'use client'
import type { EffectCallback } from 'react'
import React, { useEffect } from 'react'
/**
* @description
- * A hooks that fires the given callback only once after the mount.
- *
- * It doesn't take any dependencies.
+ * A React hook that executes a callback function only once after the component mounts. This is a simplified wrapper around useEffect with an empty dependency array.
*
+ * @example
+ import { useOnMountEffect } from 'classic-react-hooks'
+ export default function YourComponent() {
+ useOnMountEffect(() => {
+ console.log('initial mount')
+ })
+
+ return
+ }
*
* @see Docs https://classic-react-hooks.vercel.app/hooks/use-on-mount-effect.html
*/
diff --git a/src/lib/use-outside-click/index.test.tsx b/src/lib/use-outside-click/index.test.tsx
index 2691b24..d4da0e0 100644
--- a/src/lib/use-outside-click/index.test.tsx
+++ b/src/lib/use-outside-click/index.test.tsx
@@ -3,111 +3,110 @@ import { vi } from 'vitest'
import useOutsideClick from '.'
describe('use-outside-click', () => {
- it('should render', () => {
- renderHook(() => useOutsideClick(null, () => {}))
- })
-
- it('should work when Target is null', () => {
- renderHook(() => useOutsideClick(null, () => {}, { shouldInjectEvent: true }))
-
- const event = new Event('click')
- document.dispatchEvent(event)
+ describe('mounting', () => {
+ it('should render with null as target', () => {
+ // @ts-expect-error handling the edge case if target is not type of function
+ renderHook(() => useOutsideClick({ target: null }))
+ })
})
- it('should add listener on-mount and remove it on un-mount', () => {
- const div = document.createElement('div')
- const addSpy = vi.spyOn(document, 'addEventListener')
- const removeSpy = vi.spyOn(document, 'removeEventListener')
+ describe('event trigger', () => {
+ it('should not fire listener if target is null ', () => {
+ // @ts-expect-error handling the edge case if target is not type of function
+ renderHook(() => useOutsideClick({ target: null }))
- const { rerender, unmount } = renderHook(() => {
- useOutsideClick(
- () => div,
- () => {}
- )
+ const event = new Event('click', { bubbles: true })
+ document.dispatchEvent(event)
})
- expect(addSpy).toHaveBeenCalledTimes(1)
- expect(removeSpy).toHaveBeenCalledTimes(0)
+ it('should fire listener when clicked outside of target', () => {
+ const div = document.createElement('div')
+ const ref = { current: div }
+ const fn = vi.fn()
- rerender()
- expect(addSpy).toHaveBeenCalledTimes(1)
- expect(removeSpy).toHaveBeenCalledTimes(0)
+ renderHook(() => {
+ useOutsideClick({ target: () => ref.current, handler: fn })
+ })
- unmount()
- expect(addSpy).toHaveBeenCalledTimes(1)
- expect(removeSpy).toHaveBeenCalledTimes(1)
- })
- it('should work with refs', () => {
- const div = document.createElement('div')
- const addSpy = vi.spyOn(document, 'addEventListener')
- const removeSpy = vi.spyOn(document, 'removeEventListener')
-
- const ref = { current: div }
+ const event = new Event('click', { bubbles: true })
+ document.dispatchEvent(event)
- const { rerender, unmount } = renderHook(() => {
- useOutsideClick(ref, () => {})
+ expect(fn).toHaveBeenCalledTimes(1)
+ expect(fn).toHaveBeenCalledWith(event)
})
- expect(addSpy).toHaveBeenCalledTimes(1)
- expect(removeSpy).toHaveBeenCalledTimes(0)
+ it('should fire listener when clicked outside of target, when `setElementRef` is used', () => {
+ const div = document.createElement('div')
+ document.body.append(div) // Append to body to make it part of the DOM
- rerender()
- expect(addSpy).toHaveBeenCalledTimes(1)
- expect(removeSpy).toHaveBeenCalledTimes(0)
+ const fn = vi.fn()
- unmount()
- expect(addSpy).toHaveBeenCalledTimes(1)
- expect(removeSpy).toHaveBeenCalledTimes(1)
- })
+ const { result, rerender } = renderHook(() => {
+ return useOutsideClick({ handler: fn })
+ })
+
+ result.current.setElementRef(div)
+ rerender()
- it('should fire listener when clicked outside of target element when ref is provided', () => {
- const div = document.createElement('div')
- const ref = { current: div }
- const listener = vi.fn()
+ const event = new Event('click', { bubbles: true })
+ // Simulate click outside of div
+ document.dispatchEvent(event)
- renderHook(() => {
- useOutsideClick(ref, listener)
+ expect(fn).toHaveBeenCalledTimes(1)
+ expect(fn).toHaveBeenCalledWith(event)
+
+ document.body.removeChild(div) // Clean up
})
- const event = new Event('click')
- document.dispatchEvent(event)
+ it('should not fire when clicked on target', () => {
+ const div = document.createElement('div')
- expect(listener).toHaveBeenCalledTimes(1)
- expect(listener).toHaveBeenCalledWith(event)
- })
+ document.body.append(div)
- it('should fire listener when clicked outside of target element', () => {
- const div = document.createElement('div')
+ const fn = vi.fn()
+ renderHook(() => {
+ useOutsideClick({ target: () => div, handler: fn })
+ })
- const listener = vi.fn()
- renderHook(() => {
- useOutsideClick(() => div, listener)
+ const event = new Event('click', { bubbles: true })
+ div.dispatchEvent(event)
+
+ expect(fn).toHaveBeenCalledTimes(0)
})
- const event = new Event('click')
- document.dispatchEvent(event)
+ it('should not fire when clicked inside target', () => {
+ const div = document.createElement('div')
+ const span = document.createElement('span')
- expect(listener).toHaveBeenCalledTimes(1)
- expect(listener).toHaveBeenCalledWith(event)
- })
+ div.append(span)
+ document.body.append(div)
- it('should not fire listener when clicked on target element or inside within it', () => {
- const div = document.createElement('div')
- const span = document.createElement('span')
+ const fn = vi.fn()
+ renderHook(() => {
+ useOutsideClick({ target: () => div, handler: fn })
+ })
- div.append(span)
- document.body.append(div)
+ const event = new Event('click', { bubbles: true })
+ span.dispatchEvent(event)
- const listener = vi.fn()
- renderHook(() => {
- useOutsideClick(() => div, listener)
+ expect(fn).toHaveBeenCalledTimes(0)
})
- const event = new Event('click', { bubbles: true })
- div.dispatchEvent(event)
- expect(listener).toHaveBeenCalledTimes(0)
+ it('should not fire listener when clicked on target, when `setElementRef` is used', () => {
+ const div = document.createElement('div')
- span.dispatchEvent(event)
- expect(listener).toHaveBeenCalledTimes(0)
+ document.body.append(div)
+
+ const fn = vi.fn()
+ const { result, rerender } = renderHook(() => {
+ return useOutsideClick({ handler: fn })
+ })
+ result.current.setElementRef(div)
+ rerender()
+
+ const event = new Event('click', { bubbles: true })
+ div.dispatchEvent(event)
+ expect(fn).toHaveBeenCalledTimes(0)
+ })
})
})
diff --git a/src/lib/use-outside-click/index.tsx b/src/lib/use-outside-click/index.tsx
index 9d4ea54..13c14f1 100644
--- a/src/lib/use-outside-click/index.tsx
+++ b/src/lib/use-outside-click/index.tsx
@@ -1,42 +1,90 @@
-'use client'
-import type { Target } from '../use-event-listener'
-import React, { useRef } from 'react'
+import type { EvOptions, EvTarget } from '../../types'
+
+import React, { useEffect, useRef } from 'react'
import { useEventListener } from '../use-event-listener'
-import useSyncedRef from '../use-synced-ref'
/**
* @description
- * A hook that fires the given callback when clicked outside anywhere of the given html element.
+ * A React hook that detects outside click for specified element and triggers the given callback.
+ *
+ * @example
+ import { useState } from 'react'
+ import { useOutsideClick } from 'classic-react-hooks'
+
+ function Modal() {
+ const [isOpen, setIsOpen] = useState(false)
+
+ const {setElementRef} = useOutsideClick({
+ handler: () => setIsOpen(false),
+ })
+
+ if (!isOpen) {
+ return {
+ e.stopPropagation()
+ setIsOpen(true)
+ }}>Open Modal
+ }
+
+ return (
+
+
+
Modal Title
+
Click outside this modal to close it.
+
setIsOpen(false)}>Close
+
+
+ )
+ }
*
* @see Docs https://classic-react-hooks.vercel.app/hooks/use-outside-click.html
*/
-export default function useOutsideClick(
- target: Target,
- handler: (event: DocumentEventMap['click']) => void,
- options?: { shouldInjectEvent?: boolean | any }
-) {
- const paramsRef = useSyncedRef({
- target,
- handler,
+export default function useOutsideClick({
+ target,
+ handler,
+ options,
+}: {
+ target?: EvTarget
+ handler?: (event: DocumentEventMap['click']) => void
+ options?: EvOptions
+}) {
+ const elementNode = useRef()
+ const setElementRef = useRef((node: HTMLElement | null) => {
+ elementNode.current = node
})
- let shouldInjectEvent = true
- if (typeof options == 'object' && 'shouldInjectEvent' in options) {
- shouldInjectEvent = !!options.shouldInjectEvent
- }
+ const mergedOptions: EvOptions = { shouldInjectEvent: true, ...options }
+
+ const eventCb = (event: DocumentEventMap['click']) => {
+ const node = elementNode.current // node which need to be tracked if click has occured within it or not
- const eventCb = useRef((event: DocumentEventMap['click']) => {
- const node = (typeof target == 'function' ? target() : target) ?? document
- if (event.target == node || ('current' in node && event.target == node.current)) return
+ if (!node) {
+ console.warn('Provided target element is null. Skipping the document click handler.')
+ return
+ }
+ if (event.target == node) return
- if (
- node &&
- (('contains' in node && (node as Node).contains(event.target as Node)) ||
- ('current' in node && 'contains' && (node.current as Node).contains(event.target as Node)))
- ) {
+ if ('contains' in node && (node as Node).contains(event.target as Node)) {
return
}
- paramsRef.current.handler(event)
+ handler?.(event)
+ }
+
+ useEffect(() => {
+ // Setting target inside effect, because effects run after the rendering of dom is done.
+ // Lazily setting target when prop is true
+ if (typeof target == 'function' && mergedOptions.shouldInjectEvent) {
+ setElementRef.current(target() as HTMLElement)
+ }
+ }, [target, options?.shouldInjectEvent])
+
+ useEventListener({
+ target: () => document,
+ event: 'click',
+ handler: eventCb,
+ options: {
+ capture: false, // Let the event bubble from top-to-bottom. Prevent it from user side using e.stopPropagation() on the button click
+ ...options,
+ },
})
- useEventListener(document, 'click', eventCb.current, { shouldInjectEvent: shouldInjectEvent })
+ return { setElementRef: setElementRef.current }
}
diff --git a/src/lib/use-synced-effect/index.test.tsx b/src/lib/use-synced-effect/index.test.tsx
index 06492fb..99fc4c9 100644
--- a/src/lib/use-synced-effect/index.test.tsx
+++ b/src/lib/use-synced-effect/index.test.tsx
@@ -2,53 +2,59 @@ import { renderHook } from '@testing-library/react'
import { vi } from 'vitest'
import useSyncedEffect from '.'
-describe('use-on-mount-effect', () => {
+describe('use-synced-effect', () => {
beforeEach(() => {
vi.useFakeTimers()
})
- it('should not run callback on initial the mount', () => {
- const fn = vi.fn()
- renderHook(() => useSyncedEffect(fn, []))
- expect(fn).toHaveBeenCalledTimes(0)
+ describe('mounting', () => {
+ it('should not run callback on initial the mount', () => {
+ const fn = vi.fn()
+ renderHook(() => useSyncedEffect(fn, []))
+ expect(fn).toHaveBeenCalledTimes(0)
+ })
+ it('should work without dependency passed', () => {
+ const fn = vi.fn()
+ renderHook(() => useSyncedEffect(fn))
+ expect(fn).toHaveBeenCalledTimes(0)
+ })
})
- it('should work without dependency passed', () => {
- const fn = vi.fn()
- renderHook(() => useSyncedEffect(fn))
- expect(fn).toHaveBeenCalledTimes(0)
- })
-
- it('should run callback on when dependency is changed', () => {
- const fn = vi.fn()
- let skill = 'js'
- const { rerender } = renderHook(() => useSyncedEffect(fn, [skill]))
- expect(fn).toHaveBeenCalledTimes(0)
+ describe('unmounting', () => {
+ it('should run cleanup on un-mount', () => {
+ const cleanupFn = vi.fn()
+ const fn = vi.fn(() => cleanupFn)
+ let skill = 'js'
- vi.runAllTimers()
+ const { rerender, unmount } = renderHook(() => useSyncedEffect(fn, [skill]))
+ vi.runAllTimers()
- skill = 'react'
- rerender()
- expect(fn).toHaveBeenCalledTimes(1)
+ skill = 'react'
+ rerender()
+ expect(fn).toHaveBeenCalledTimes(1)
- skill = 'typescript'
- rerender()
- expect(fn).toHaveBeenCalledTimes(2)
+ unmount()
+ expect(cleanupFn).toHaveBeenCalledTimes(1)
+ })
})
- it('should run cleanup on un-mount', () => {
- const cleanupFn = vi.fn()
- const fn = vi.fn(() => cleanupFn)
- let skill = 'js'
+ describe('Reactive behaviour', () => {
+ it('should run callback on when dependency is changed', () => {
+ const fn = vi.fn()
+ let skill = 'js'
+
+ const { rerender } = renderHook(() => useSyncedEffect(fn, [skill]))
+ expect(fn).toHaveBeenCalledTimes(0)
- const { rerender, unmount } = renderHook(() => useSyncedEffect(fn, [skill]))
- vi.runAllTimers()
+ vi.runAllTimers()
- skill = 'react'
- rerender()
- expect(fn).toHaveBeenCalledTimes(1)
+ skill = 'react'
+ rerender()
+ expect(fn).toHaveBeenCalledTimes(1)
- unmount()
- expect(cleanupFn).toHaveBeenCalledTimes(1)
+ skill = 'typescript'
+ rerender()
+ expect(fn).toHaveBeenCalledTimes(2)
+ })
})
})
diff --git a/src/lib/use-synced-effect/index.tsx b/src/lib/use-synced-effect/index.tsx
index 0be5030..50a5b6d 100644
--- a/src/lib/use-synced-effect/index.tsx
+++ b/src/lib/use-synced-effect/index.tsx
@@ -1,4 +1,3 @@
-'use client'
import type { DependencyList, EffectCallback } from 'react'
import React, { useEffect, useRef } from 'react'
@@ -6,9 +5,24 @@ const DEP: DependencyList = []
/**
* @description
- * A hooks that fires the given callback for given dependencies.
- *
- * It works exacatly like `useEffect`. But callback doesn't get fired on initial mount.
+ * A React hook that executes a callback when dependencies change, similar to `useEffect`, but skips execution on the initial mount.
+ * @example
+ import { useState } from 'react'
+ import { useSyncedEffect } from 'classic-react-hooks'
+
+ export default function YourComponent() {
+ const [counter, setCounter] = useState(0)
+
+ useSyncedEffect(() => {
+ console.log('counter changed to ', counter)
+ }, [counter])
+
+ return (
+
+ setCounter((c) => c + 1)}>increment
+
+ )
+ }
*
* @see Docs https://classic-react-hooks.vercel.app/hooks/use-synced-effect.html
*/
diff --git a/src/lib/use-synced-ref/index.tsx b/src/lib/use-synced-ref/index.tsx
index 306c8bf..c7b64b2 100644
--- a/src/lib/use-synced-ref/index.tsx
+++ b/src/lib/use-synced-ref/index.tsx
@@ -1,11 +1,33 @@
-'use client'
import React, { useRef } from 'react'
/**
* @description
- * A replacement for `useRef` hook, which automatically synces up with the given state.
+ * A React hook that creates a ref that automatically stays in sync with the provided value, ensuring you always have access to the latest state in asynchronous operations.
*
- * No need to manually update the ref.
+ * @example
+ import { useState } from 'react'
+ import { useSyncedRef } from 'classic-react-hooks'
+
+ export default function Counter() {
+ const [count, setCount] = useState(0)
+ const countRef = useSyncedRef(count)
+
+ const handleAsyncOperation = () => {
+ setTimeout(() => {
+ // countRef.current always has the latest value
+ console.log('Current count:', countRef.current)
+ alert(`Count is now: ${countRef.current}`)
+ }, 2000)
+ }
+
+ return (
+
+
Count: {count}
+
setCount((c) => c + 1)}>Increment
+
Show count after 2 seconds
+
+ )
+ }
*
* @see Docs https://classic-react-hooks.vercel.app/hooks/use-synced-ref.html
*/
diff --git a/src/lib/use-throttled-fn/index.test.tsx b/src/lib/use-throttled-fn/index.test.tsx
index 869e41f..90995aa 100644
--- a/src/lib/use-throttled-fn/index.test.tsx
+++ b/src/lib/use-throttled-fn/index.test.tsx
@@ -1,95 +1,363 @@
import { vi } from 'vitest'
-import { renderHook } from '@testing-library/react'
+import { renderHook, act } from '@testing-library/react'
import useThrottledFn from '.'
describe('use-throttled-fn', () => {
beforeEach(() => {
vi.useFakeTimers()
})
+
afterEach(() => {
vi.useRealTimers()
+ vi.clearAllMocks()
})
- it('should return the throttled callback', () => {
- const callback = vi.fn()
- const { result } = renderHook(() => useThrottledFn(callback, 300))
+ describe('mounting', () => {
+ it('should return a function', () => {
+ const callback = vi.fn()
+ const { result } = renderHook(() => useThrottledFn({ callbackToThrottle: callback }))
+
+ expect(typeof result.current).toBe('function')
+ })
+
+ it('should not call callback on initialization', () => {
+ const callback = vi.fn()
+ renderHook(() => useThrottledFn({ callbackToThrottle: callback }))
+
+ expect(callback).not.toHaveBeenCalled()
+ })
+
+ it('should call callback immediately on first invocation', () => {
+ const callback = vi.fn()
+ const { result } = renderHook(() => useThrottledFn({ callbackToThrottle: callback }))
+
+ act(() => {
+ result.current()
+ })
+
+ expect(callback).toHaveBeenCalledTimes(1)
+ })
+ })
+
+ describe('Throttling behavior', () => {
+ it('should use default delay of 300ms', () => {
+ const callback = vi.fn()
+ const { result } = renderHook(() => useThrottledFn({ callbackToThrottle: callback }))
+
+ act(() => {
+ result.current()
+ result.current() // Should be ignored
+ })
+
+ expect(callback).toHaveBeenCalledTimes(1)
+
+ act(() => {
+ vi.advanceTimersByTime(299)
+ result.current() // Should still be ignored
+ })
+
+ expect(callback).toHaveBeenCalledTimes(1)
+
+ act(() => {
+ vi.advanceTimersByTime(1) // Total 300ms
+ result.current() // Should be called
+ })
+
+ expect(callback).toHaveBeenCalledTimes(2)
+ })
+
+ it('should respect custom delay', () => {
+ const callback = vi.fn()
+ const customDelay = 500
+ const { result } = renderHook(() => useThrottledFn({ callbackToThrottle: callback, delay: customDelay }))
+
+ act(() => {
+ result.current()
+ result.current() // Should be ignored
+ })
+
+ expect(callback).toHaveBeenCalledTimes(1)
+
+ act(() => {
+ vi.advanceTimersByTime(499)
+ result.current() // Should still be ignored
+ })
+
+ expect(callback).toHaveBeenCalledTimes(1)
+
+ act(() => {
+ vi.advanceTimersByTime(1) // Total 500ms
+ result.current() // Should be called
+ })
+
+ expect(callback).toHaveBeenCalledTimes(2)
+ })
+
+ it('should throttle multiple rapid calls', () => {
+ const callback = vi.fn()
+ const { result } = renderHook(() => useThrottledFn({ callbackToThrottle: callback, delay: 100 }))
+
+ act(() => {
+ result.current() // Call 1 - should execute
+ result.current() // Call 2 - should be throttled
+ result.current() // Call 3 - should be throttled
+ result.current() // Call 4 - should be throttled
+ })
+
+ expect(callback).toHaveBeenCalledTimes(1)
+
+ act(() => {
+ vi.advanceTimersByTime(100)
+ result.current() // Call 5 - should execute
+ })
+
+ expect(callback).toHaveBeenCalledTimes(2)
+ })
+
+ it('should allow execution after delay has passed', () => {
+ const callback = vi.fn()
+ const { result } = renderHook(() => useThrottledFn({ callbackToThrottle: callback, delay: 200 }))
+
+ act(() => {
+ result.current()
+ })
+ expect(callback).toHaveBeenCalledTimes(1)
+
+ act(() => {
+ vi.advanceTimersByTime(200)
+ result.current()
+ })
+ expect(callback).toHaveBeenCalledTimes(2)
- expect(typeof result.current).toBe('function')
+ act(() => {
+ vi.advanceTimersByTime(200)
+ result.current()
+ })
+ expect(callback).toHaveBeenCalledTimes(3)
+ })
})
- it('should not fire callback on initialization', () => {
- const callback = vi.fn()
- renderHook(() => useThrottledFn(callback, 300))
+ describe('Arguments handling', () => {
+ it('should pass arguments correctly to the callback', () => {
+ const callback = vi.fn()
+ const { result } = renderHook(() => useThrottledFn({ callbackToThrottle: callback }))
- expect(callback).not.toHaveBeenCalled()
+ act(() => {
+ result.current('arg1', 'arg2', 123)
+ })
+
+ expect(callback).toHaveBeenCalledWith('arg1', 'arg2', 123)
+ })
+
+ it('should pass different arguments on subsequent calls', () => {
+ const callback = vi.fn()
+ const { result } = renderHook(() => useThrottledFn({ callbackToThrottle: callback, delay: 100 }))
+
+ act(() => {
+ result.current('first')
+ })
+ expect(callback).toHaveBeenNthCalledWith(1, 'first')
+
+ act(() => {
+ vi.advanceTimersByTime(100)
+ result.current('second')
+ })
+ expect(callback).toHaveBeenNthCalledWith(2, 'second')
+ })
})
- it('should return the throttled callback with default 300ms delay', async () => {
- const callback = vi.fn()
- const { result } = renderHook(() => useThrottledFn(callback))
+ describe('Context binding', () => {
+ it('should preserve this context when called with call()', () => {
+ let capturedThis: any = null
+ const testObj = {
+ name: 'test',
+ callback: function () {
+ capturedThis = this
+ },
+ }
- result.current(10)
- expect(callback).toHaveBeenCalledTimes(1)
+ const { result } = renderHook(() => useThrottledFn({ callbackToThrottle: testObj.callback }))
- result.current(10)
- vi.advanceTimersByTime(500)
+ act(() => {
+ result.current.call(testObj)
+ })
- result.current(10)
- expect(callback).toHaveBeenCalledTimes(2)
+ expect(capturedThis).toBe(testObj)
+ })
- result.current(10)
- vi.advanceTimersByTime(300)
- expect(callback).toHaveBeenCalledTimes(2)
+ it('should preserve this context when called with apply()', () => {
+ let capturedThis: any = null
+ const testObj = {
+ name: 'test',
+ callback: function (arg: string) {
+ capturedThis = this
+ return arg
+ },
+ }
- result.current(10)
- vi.advanceTimersByTime(1000)
- expect(callback).toHaveBeenCalledTimes(3)
+ const { result } = renderHook(() => useThrottledFn({ callbackToThrottle: testObj.callback }))
+
+ act(() => {
+ result.current.apply(testObj, ['test-arg'])
+ })
+
+ expect(capturedThis).toBe(testObj)
+ })
})
- it('should call throttled function with given arguments', async () => {
- const callback = vi.fn()
- const { result } = renderHook(() => useThrottledFn(callback))
- result.current(10)
- vi.advanceTimersByTime(300)
- expect(callback).toHaveBeenNthCalledWith(1, 10)
+ describe('Hook updates and re-renders', () => {
+ it('should update callback when it changes', () => {
+ const callback1 = vi.fn()
+ const callback2 = vi.fn()
+
+ const { result, rerender } = renderHook(({ callback }) => useThrottledFn({ callbackToThrottle: callback }), {
+ initialProps: { callback: callback1 },
+ })
+
+ act(() => {
+ result.current()
+ })
+ expect(callback1).toHaveBeenCalledTimes(1)
+ expect(callback2).not.toHaveBeenCalled()
+
+ // Update the callback
+ rerender({ callback: callback2 })
+
+ act(() => {
+ vi.advanceTimersByTime(300)
+ result.current()
+ })
+ expect(callback1).toHaveBeenCalledTimes(1)
+ expect(callback2).toHaveBeenCalledTimes(1)
+ })
+
+ it('should update delay when it changes', () => {
+ const callback = vi.fn()
+
+ const { result, rerender } = renderHook(
+ ({ delay }) => useThrottledFn({ callbackToThrottle: callback, delay }),
+ { initialProps: { delay: 100 } }
+ )
+
+ act(() => {
+ result.current()
+ })
+ expect(callback).toHaveBeenCalledTimes(1)
+
+ // Update delay
+ rerender({ delay: 500 })
+
+ act(() => {
+ vi.advanceTimersByTime(100) // Old delay
+ result.current() // Should still be throttled with new delay
+ })
+ expect(callback).toHaveBeenCalledTimes(1)
- result.current(30)
- vi.advanceTimersByTime(300)
- expect(callback).toHaveBeenNthCalledWith(2, 30)
+ act(() => {
+ vi.advanceTimersByTime(400) // Total 500ms (new delay)
+ result.current()
+ })
+ expect(callback).toHaveBeenCalledTimes(2)
+ })
+
+ it('should maintain throttle state across re-renders', () => {
+ const callback = vi.fn()
+
+ const { result, rerender } = renderHook(() => useThrottledFn({ callbackToThrottle: callback, delay: 200 }))
+
+ act(() => {
+ result.current()
+ })
+ expect(callback).toHaveBeenCalledTimes(1)
+
+ // Re-render the component
+ rerender()
+
+ act(() => {
+ result.current() // Should still be throttled
+ })
+ expect(callback).toHaveBeenCalledTimes(1)
+
+ act(() => {
+ vi.advanceTimersByTime(200)
+ result.current() // Should now execute
+ })
+ expect(callback).toHaveBeenCalledTimes(2)
+ })
})
- it('should throttle the callback with custom delay', async () => {
- const callback = vi.fn()
+ describe('Error handling', () => {
+ it('should handle callback that throws an error', () => {
+ const errorCallback = vi.fn(() => {
+ throw new Error('Test error')
+ })
+ const { result } = renderHook(() => useThrottledFn({ callbackToThrottle: errorCallback }))
- const { result } = renderHook(() => useThrottledFn(callback, 500))
+ expect(() => {
+ act(() => {
+ result.current()
+ })
+ }).toThrow('Test error')
- result.current(2)
- vi.advanceTimersByTime(300)
- result.current(2)
- result.current(2)
- vi.advanceTimersByTime(500)
+ expect(errorCallback).toHaveBeenCalledTimes(1)
- expect(callback).toHaveBeenCalledTimes(1)
- expect(callback).toHaveBeenNthCalledWith(1, 2)
+ // Should still throttle after error
+ expect(() => {
+ act(() => {
+ result.current()
+ })
+ }).not.toThrow()
- result.current(5)
- vi.advanceTimersByTime(500)
- expect(callback).toHaveBeenCalledTimes(2)
- expect(callback).toHaveBeenNthCalledWith(2, 5)
+ expect(errorCallback).toHaveBeenCalledTimes(1) // Still throttled
+ })
})
- it('should bind the this context', () => {
- let res: any = ''
- const obj = {
- details: 'this is details',
- callback: function () {
- res = this
- },
- }
+ describe('Performance and memory', () => {
+ it('should not create new throttled function on every render', () => {
+ const callback = vi.fn()
+ const { result, rerender } = renderHook(() => useThrottledFn({ callbackToThrottle: callback }))
+
+ const firstDebouncedFn = result.current
+ rerender()
+ const secondDebouncedFn = result.current
+
+ expect(firstDebouncedFn).toBe(secondDebouncedFn)
+ })
+ })
+
+ describe('Memory and performance', () => {
+ it('should not create new throttled function on every render', () => {
+ const callback = vi.fn()
+ const { result, rerender } = renderHook(() => useThrottledFn({ callbackToThrottle: callback }))
+
+ const firstThrottledFn = result.current
+ rerender()
+ const secondThrottledFn = result.current
+
+ expect(firstThrottledFn).toBe(secondThrottledFn)
+ })
+
+ it('should handle rapid successive calls efficiently', () => {
+ const callback = vi.fn()
+ const { result } = renderHook(() => useThrottledFn({ callbackToThrottle: callback, delay: 100 }))
+
+ act(() => {
+ // Simulate rapid calls
+ for (let i = 0; i < 1000; i++) {
+ result.current(i)
+ }
+ })
+
+ expect(callback).toHaveBeenCalledTimes(1)
+ expect(callback).toHaveBeenCalledWith(0) // First call's argument
- const { result } = renderHook(() => useThrottledFn(obj.callback, 500))
- result.current.call(obj)
+ act(() => {
+ vi.advanceTimersByTime(100)
+ result.current(1001)
+ })
- expect(res).toBe(obj)
+ expect(callback).toHaveBeenCalledTimes(2)
+ expect(callback).toHaveBeenNthCalledWith(2, 1001)
+ })
})
})
diff --git a/src/lib/use-throttled-fn/index.tsx b/src/lib/use-throttled-fn/index.tsx
index 591c9f6..11b7827 100644
--- a/src/lib/use-throttled-fn/index.tsx
+++ b/src/lib/use-throttled-fn/index.tsx
@@ -1,40 +1,95 @@
-'use client'
import React, { useRef } from 'react'
-import useSyncedRef from '../use-synced-ref'
const DEFAULT_DELAY = 300
/**
* @description
- * A hook which returns a throttled function.
+ * A React hook that returns a throttled version of provided function, ensuring it executes at most once per specified time interval, regardless of how frequently it's called.
+ *
+ * @example
+ import { useState } from 'react'
+ import { useThrottledFn } from 'classic-react-hooks'
+
+ export default function AutoSave() {
+ const [content, setContent] = useState('')
+ const [saving, setSaving] = useState(false)
+
+ const saveContent = useThrottledFn({
+ callbackToThrottle: async (text) => {
+ setSaving(true)
+ try {
+ await saveToAPI(text)
+ console.log('Content saved!')
+ } catch (error) {
+ console.error('Save failed:', error)
+ } finally {
+ setSaving(false)
+ }
+ },
+ delay: 2000, // Auto-save every 2 seconds at most
+ })
+
+ const handleChange = (e) => {
+ const newContent = e.target.value
+ setContent(newContent)
+ saveContent(newContent)
+ }
+
+ return (
+
+
+ {saving &&
Saving...
}
+
+ )
+ }
*
* @see Docs https://classic-react-hooks.vercel.app/hooks/use-throttled-fn.html
*
*/
-export default function useThrottledFn any>(cb: T, delay = DEFAULT_DELAY) {
- const paramsRef = useSyncedRef({
- cb,
+export default function useThrottledFn any>({
+ callbackToThrottle,
+ delay,
+}: {
+ callbackToThrottle: T
+ delay?: number
+}) {
+ const paramsRef = useRef({
+ callbackToThrottle,
delay,
})
- const throttledCb = useRef(throttledFnWrapper(paramsRef.current.cb, paramsRef.current.delay))
+ // tracking props with immutable object
+ paramsRef.current.delay = delay
+ paramsRef.current.callbackToThrottle = callbackToThrottle
+
+ // so can access the updated props inside debouncedFnWrapper function
+ const throttledCb = useRef(throttledFnWrapper(paramsRef.current))
+
return throttledCb.current
}
/**
* @description
- * A wrapper function which is used internally in `useThrttledFn` hook.
+ * A wrapper function which is used internally in `useThrottledFn` hook.
*/
-export function throttledFnWrapper any>(cb: T, delay = DEFAULT_DELAY) {
+export function throttledFnWrapper any>(props: {
+ callbackToThrottle: T
+ delay?: number
+}) {
let lastExecutionTime = 0
- return function (...args: Parameters) {
+ return function (...args: Parameters) {
const currentTime = Date.now()
- if (currentTime - lastExecutionTime >= delay) {
- // @ts-ignore
- cb.call(this, ...args)
- lastExecutionTime = currentTime
+ if (currentTime - lastExecutionTime >= (props.delay ?? DEFAULT_DELAY)) {
+ try {
+ // @ts-expect-error -> making "this" as "any" type working
+ props.callbackToThrottle.call(this, ...args)
+ } catch (err) {
+ throw err
+ } finally {
+ lastExecutionTime = currentTime
+ }
}
}
}
diff --git a/src/lib/use-timeout-effect/index.test.tsx b/src/lib/use-timeout-effect/index.test.tsx
index 131c56a..4b72191 100644
--- a/src/lib/use-timeout-effect/index.test.tsx
+++ b/src/lib/use-timeout-effect/index.test.tsx
@@ -1,82 +1,254 @@
import { vi } from 'vitest'
import { renderHook } from '@testing-library/react'
-import useTimoeoutEffect from '.'
+import useTimeoutEffect from '.'
describe('use-timeout-effect', () => {
beforeEach(() => {
vi.useFakeTimers()
})
+
afterEach(() => {
vi.useRealTimers()
- })
- afterEach(() => {
vi.clearAllTimers()
})
- it('should fire callback with default timeout of 0ms after the mount', () => {
- const fn = vi.fn()
- renderHook(() => useTimoeoutEffect(fn))
-
- expect(fn).toHaveBeenCalledTimes(0)
- vi.advanceTimersByTime(100)
- expect(fn).toHaveBeenCalledTimes(1)
+ describe('mounting', () => {
+ it('should fire callback with default timeout of 100ms after mount', () => {
+ const fn = vi.fn()
+ renderHook(() => useTimeoutEffect({ handler: fn }))
+
+ expect(fn).not.toHaveBeenCalled()
+ vi.advanceTimersByTime(99)
+ expect(fn).not.toHaveBeenCalled()
+ vi.advanceTimersByTime(1)
+ expect(fn).toHaveBeenCalledTimes(1)
+ })
+
+ it('should fire callback with specified timeout prop', () => {
+ const fn = vi.fn()
+ renderHook(() => useTimeoutEffect({ handler: fn, timeout: 500 }))
+
+ expect(fn).not.toHaveBeenCalled()
+ vi.advanceTimersByTime(499)
+ expect(fn).not.toHaveBeenCalled()
+ vi.advanceTimersByTime(1)
+ expect(fn).toHaveBeenCalledTimes(1)
+ })
+
+ it('should only fire callback once', () => {
+ const fn = vi.fn()
+ renderHook(() => useTimeoutEffect({ handler: fn, timeout: 100 }))
+
+ vi.advanceTimersByTime(100)
+ expect(fn).toHaveBeenCalledTimes(1)
+
+ // Advance more time to ensure it doesn't fire again
+ vi.advanceTimersByTime(1000)
+ expect(fn).toHaveBeenCalledTimes(1)
+ })
})
- it('should fire callback after the given timeout', () => {
- const fn = vi.fn()
- renderHook(() => useTimoeoutEffect(fn, 500))
+ describe('unmounting', () => {
+ it('should clear timeout on unmount before timeout expires', () => {
+ const fn = vi.fn()
+ const { unmount } = renderHook(() => useTimeoutEffect({ handler: fn, timeout: 500 }))
+
+ vi.advanceTimersByTime(200)
+ unmount()
+ vi.advanceTimersByTime(500)
+ expect(fn).not.toHaveBeenCalled()
+ })
- expect(fn).toHaveBeenCalledTimes(0)
- vi.advanceTimersByTime(0)
- expect(fn).toHaveBeenCalledTimes(0)
+ it('should not interfere with callback execution if unmounted after timeout', () => {
+ const fn = vi.fn()
+ const { unmount } = renderHook(() => useTimeoutEffect({ handler: fn, timeout: 100 }))
- vi.advanceTimersByTime(400)
- expect(fn).toHaveBeenCalledTimes(0)
+ vi.advanceTimersByTime(100)
+ expect(fn).toHaveBeenCalledTimes(1)
- vi.advanceTimersByTime(500)
- expect(fn).toHaveBeenCalledTimes(1)
+ unmount()
+ vi.advanceTimersByTime(1000)
+ expect(fn).toHaveBeenCalledTimes(1)
+ })
})
- it('should clear the timeout with clearTimer', () => {
- const fn = vi.fn()
- const { result } = renderHook(() => useTimoeoutEffect(fn, 500))
+ describe('clearTimer functionality', () => {
+ it('should clear the timeout when prop changes', () => {
+ const fn = vi.fn()
+
+ let timeout = 300
+ const { result, rerender } = renderHook(() => useTimeoutEffect({ handler: fn, timeout }))
+
+ vi.advanceTimersByTime(200)
+ expect(fn).not.toHaveBeenCalled()
+
+ timeout = 500
+ rerender()
+
+ vi.advanceTimersByTime(200)
+ expect(fn).not.toHaveBeenCalled()
+
+ vi.advanceTimersByTime(300)
+ expect(fn).toHaveBeenCalledTimes(1)
+ })
- result.current.clearTimer()
- vi.advanceTimersByTime(500)
- expect(fn).not.toHaveBeenCalled()
+ it('should clear the timeout with clearTimer before timeout expires', () => {
+ const fn = vi.fn()
+ const { result } = renderHook(() => useTimeoutEffect({ handler: fn, timeout: 500 }))
+
+ vi.advanceTimersByTime(200)
+ result.current.clearTimer()
+ vi.advanceTimersByTime(500)
+ expect(fn).not.toHaveBeenCalled()
+ })
+
+ it('should allow clearing timer multiple times without error', () => {
+ const fn = vi.fn()
+ const { result } = renderHook(() => useTimeoutEffect({ handler: fn, timeout: 500 }))
+
+ result.current.clearTimer()
+ result.current.clearTimer()
+ result.current.clearTimer()
+
+ vi.advanceTimersByTime(500)
+ expect(fn).not.toHaveBeenCalled()
+ })
+ })
+
+ describe('restartTimer functionality', () => {
+ it('should restart timer with original timeout', () => {
+ const fn = vi.fn()
+ const { result } = renderHook(() => useTimeoutEffect({ handler: fn, timeout: 500 }))
+
+ // Let original timer fire
+ vi.advanceTimersByTime(500)
+ expect(fn).toHaveBeenCalledTimes(1)
+
+ // Restart timer
+ result.current.restartTimer()
+ vi.advanceTimersByTime(500)
+ expect(fn).toHaveBeenCalledTimes(2)
+ })
+
+ it('should restart timer with new timeout value provided in restartTimer function', () => {
+ const fn = vi.fn()
+ const { result } = renderHook(() => useTimeoutEffect({ handler: fn, timeout: 500 }))
+
+ // Restart with new timeout before original fires
+ vi.advanceTimersByTime(200)
+ result.current.restartTimer(600)
+
+ // Original timeout should not fire
+ vi.advanceTimersByTime(500)
+ expect(fn).not.toHaveBeenCalled()
+
+ // New timeout should fire
+ vi.advanceTimersByTime(100) // 500 + 100 = 600
+ expect(fn).toHaveBeenCalledTimes(1)
+ })
+ it('should restart timer with original value after overriding of timer with restartTimer function', () => {
+ const fn = vi.fn()
+ const { result } = renderHook(() => useTimeoutEffect({ handler: fn, timeout: 500 }))
+
+ // Restart with new timeout before original fires
+ vi.advanceTimersByTime(200)
+ result.current.restartTimer(600)
+
+ // Original timeout should not fire
+ vi.advanceTimersByTime(500)
+ expect(fn).not.toHaveBeenCalled()
+
+ // New timeout should fire
+ vi.advanceTimersByTime(100) // 500 + 100 = 600
+ expect(fn).toHaveBeenCalledTimes(1)
+
+ // will pickup the original timer value = 500
+ result.current.restartTimer()
+
+ // Fire after 500ms
+ vi.advanceTimersByTime(500)
+ expect(fn).toHaveBeenCalledTimes(2)
+ })
+
+ it('should cancel previous timer when restarting', () => {
+ const fn = vi.fn()
+ const { result } = renderHook(() => useTimeoutEffect({ handler: fn, timeout: 500 }))
+
+ // Restart before original timeout
+ vi.advanceTimersByTime(200)
+ result.current.restartTimer()
+
+ // Advance to where original would have fired
+ vi.advanceTimersByTime(300)
+ expect(fn).not.toHaveBeenCalled()
+
+ // Advance to where restarted timer should fire
+ vi.advanceTimersByTime(200)
+ expect(fn).toHaveBeenCalledTimes(1)
+ })
+
+ it('should handle restart followed by clear', () => {
+ const fn = vi.fn()
+ const { result } = renderHook(() => useTimeoutEffect({ handler: fn, timeout: 500 }))
+
+ result.current.restartTimer()
+ result.current.clearTimer()
+ vi.advanceTimersByTime(1000)
+ expect(fn).not.toHaveBeenCalled()
+
+ // Should be able to restart again after clearing
+ result.current.restartTimer(200)
+ vi.advanceTimersByTime(200)
+ expect(fn).toHaveBeenCalledTimes(1)
+ })
})
- it('should set the timeout with restartTimer', () => {
- const fn = vi.fn()
- const { result } = renderHook(() => useTimoeoutEffect(fn, 500))
+ describe('parameter updates', () => {
+ it('should use latest handler when timeout fires', () => {
+ const fn1 = vi.fn()
+ const fn2 = vi.fn()
+ let currentHandler = fn1
+
+ const { rerender } = renderHook(() => useTimeoutEffect({ handler: currentHandler, timeout: 500 }))
+
+ // Update handler before timeout fires
+ vi.advanceTimersByTime(200)
+ currentHandler = fn2
+ rerender()
- vi.advanceTimersByTime(500)
- expect(fn).toHaveBeenCalled()
- expect(fn).toHaveBeenCalledTimes(1)
+ vi.advanceTimersByTime(300)
+ expect(fn1).not.toHaveBeenCalled()
+ expect(fn2).toHaveBeenCalledTimes(1)
+ })
- // restart
- result.current.restartTimer()
- vi.advanceTimersByTime(500)
- expect(fn).toHaveBeenCalledTimes(2)
+ it('should use latest timeout value for restartTimer', () => {
+ const fn = vi.fn()
+ let currentTimeout = 500
- // restart and clear and restart
- result.current.restartTimer()
- result.current.clearTimer()
- vi.advanceTimersByTime(500)
- expect(fn).toHaveBeenCalledTimes(2)
+ const { result, rerender } = renderHook(() => useTimeoutEffect({ handler: fn, timeout: currentTimeout }))
- result.current.restartTimer()
- vi.advanceTimersByTime(500)
- expect(fn).toHaveBeenCalledTimes(3)
+ // Update timeout and restart
+ currentTimeout = 200
+ rerender()
+ result.current.restartTimer()
+
+ vi.advanceTimersByTime(200)
+ expect(fn).toHaveBeenCalledTimes(1)
+ })
})
- it('should clear interval on unmount', () => {
- const fn = vi.fn()
- const { unmount } = renderHook(() => useTimoeoutEffect(fn, 500))
+ describe('error handling', () => {
+ it('should not throw when handler throws an error', () => {
+ const errorHandler = vi.fn(() => {
+ throw new Error('Test error')
+ })
+
+ expect(() => {
+ renderHook(() => useTimeoutEffect({ handler: errorHandler, timeout: 100 }))
+ vi.advanceTimersByTime(100)
+ }).toThrow('Test error')
- // cleanup the timer
- vi.advanceTimersByTime(400)
- unmount()
- expect(fn).toHaveBeenCalledTimes(0)
+ expect(errorHandler).toHaveBeenCalledTimes(1)
+ })
})
})
diff --git a/src/lib/use-timeout-effect/index.tsx b/src/lib/use-timeout-effect/index.tsx
index d63448b..7a66382 100644
--- a/src/lib/use-timeout-effect/index.tsx
+++ b/src/lib/use-timeout-effect/index.tsx
@@ -1,16 +1,32 @@
-'use client'
import React, { useEffect, useRef } from 'react'
import useSyncedRef from '../use-synced-ref'
/**
* @description
- * A hook which fires the provided callback only once when the given timeout is passed, just like the setTimeout.
+ * A React hook that fires a provided callback after a specified timeout, similar to `setTimeout`, but with additional control methods for clearing and restarting the timer.
+ *
+ * @example
+ * import { useState } from 'react'
+ import useTimeoutEffect from './useTimeoutEffect'
+
+ export default function BasicExample() {
+ const [message, setMessage] = useState('')
+
+ useTimeoutEffect({
+ handler: () => {
+ setMessage('Timer executed!')
+ },
+ timeout: 2000,
+ })
+
+ return {message}
+ }
*
* @see Docs https://classic-react-hooks.vercel.app/hooks/use-timeout-effect.html
*/
-export default function useTimeoutEffect(cb: () => void, timeout = 100) {
+export default function useTimeoutEffect({ handler, timeout = 100 }: { handler: () => void; timeout?: number }) {
let paramsRef = useSyncedRef({
- cb,
+ handler,
timeout,
})
const timeoutId = useRef()
@@ -19,14 +35,14 @@ export default function useTimeoutEffect(cb: () => void, timeout = 100) {
clearTimer: () => clearTimeout(timeoutId.current),
restartTimer: (new_interval?: number) => {
handlers.current.clearTimer()
- timeoutId.current = setTimeout(paramsRef.current.cb, new_interval ?? paramsRef.current.timeout)
+ timeoutId.current = setTimeout(() => paramsRef.current.handler(), new_interval ?? paramsRef.current.timeout)
},
})
useEffect(() => {
- timeoutId.current = setTimeout(paramsRef.current.cb, paramsRef.current.timeout)
+ timeoutId.current = setTimeout(() => paramsRef.current.handler(), timeout)
return handlers.current.clearTimer
- }, [])
+ }, [timeout])
return {
clearTimer: handlers.current.clearTimer,
diff --git a/src/lib/use-window-resize/index.test.tsx b/src/lib/use-window-resize/index.test.tsx
index c011735..1a428db 100644
--- a/src/lib/use-window-resize/index.test.tsx
+++ b/src/lib/use-window-resize/index.test.tsx
@@ -1,56 +1,158 @@
-import { renderHook } from '@testing-library/react'
+import { act, render, renderHook, screen } from '@testing-library/react'
import { vi } from 'vitest'
import useWindowResize from '.'
-import { act } from 'react-dom/test-utils'
describe('use-window-resize', () => {
- it('should run without errors', () => {
- renderHook(() => useWindowResize(() => window.innerWidth < 400))
+ describe('mounting', () => {
+ it('should render without errors', () => {
+ renderHook(() => useWindowResize({ handler: () => window.innerWidth < 400 }))
+ })
})
+ describe('unmounting', () => {
+ it('should remove event on unmount', () => {
+ vi.spyOn(window, 'removeEventListener')
- it('should return defaultValue, if defaultValue is passed', () => {
- const { result } = renderHook(() => useWindowResize(() => window.innerWidth < 400, { defaultValue: true }))
- expect(result.current).toBe(true)
- })
+ const { unmount } = renderHook(() => useWindowResize({ handler: () => window.innerWidth < 400 }))
+ expect(window.removeEventListener).not.toHaveBeenCalled()
+ unmount()
+ expect(window.removeEventListener).toHaveBeenCalledWith('resize', expect.any(Function), expect.any(Object))
+ })
+
+ it('should remove resize event when shouldInjectEvent becomes false', () => {
+ let shouldInjectEvent = true
+ const fn = vi.fn()
+ vi.spyOn(window, 'removeEventListener')
- it('should update the result when window is resized', () => {
- const { result } = renderHook(() =>
- useWindowResize(() => {
- return window.innerWidth < 400
+ const { rerender } = renderHook(() => useWindowResize({ handler: fn, options: { shouldInjectEvent } }))
+ expect(fn).toHaveBeenCalledTimes(1)
+
+ act(() => {
+ window.dispatchEvent(new Event('resize'))
})
- )
- expect(result.current).toBe(false)
+ expect(fn).toHaveBeenCalledTimes(2)
+ expect(fn).toHaveBeenCalledTimes(2)
+ expect(window.removeEventListener).not.toHaveBeenCalled()
+
+ shouldInjectEvent = false
+ rerender()
+ expect(window.removeEventListener).toHaveBeenCalledWith('resize', expect.any(Function), expect.any(Object))
- act(() => {
- window.innerWidth = 200
- window.dispatchEvent(new Event('resize'))
+ act(() => {
+ window.dispatchEvent(new Event('resize'))
+ })
+ expect(fn).toHaveBeenCalledTimes(2)
})
- expect(result.current).toBe(true)
+ })
- act(() => {
- window.innerWidth = 600
- window.dispatchEvent(new Event('resize'))
+ describe('defaultValue behavior', () => {
+ it('should return defaultValue as result if defaultValue is passed', () => {
+ const { result } = renderHook(() => useWindowResize({ handler: vi.fn(), options: { defaultValue: true } }))
+ expect(result.current).toBe(true)
})
- expect(result.current).toBe(false)
})
- it('should remove resize event when shouldInjectEvent becomes false', () => {
- let shouldInjectEvent = true
- const cb = vi.fn()
+ describe('resize event trigger', () => {
+ it('should update the result when window is resized', () => {
+ const { result } = renderHook(() =>
+ useWindowResize({
+ handler: () => {
+ return window.innerWidth < 400
+ },
+ })
+ )
+ expect(result.current).toBe(false)
+
+ act(() => {
+ window.innerWidth = 200
+ window.dispatchEvent(new Event('resize'))
+ })
+ expect(result.current).toBe(true)
+
+ act(() => {
+ window.innerWidth = 600
+ window.dispatchEvent(new Event('resize'))
+ })
+ expect(result.current).toBe(false)
+ })
+
+ it('should dynamically add and remove event listener based on shouldInjectEvent', () => {
+ let shouldInjectEvent = true
+ const handler = vi.fn(() => window.innerWidth < 400)
+
+ // Initial render with shouldInjectEvent: true
+ const { rerender } = renderHook(() =>
+ useWindowResize({
+ handler,
+ options: { shouldInjectEvent },
+ })
+ )
+ expect(handler).toHaveBeenCalledTimes(1) // Called once on initial render
- const { rerender } = renderHook(() => useWindowResize(cb, { shouldInjectEvent }))
- expect(cb).toHaveBeenCalledTimes(1)
- act(() => {
- window.dispatchEvent(new Event('resize'))
+ // Trigger resize, handler should be called
+ act(() => {
+ window.innerWidth = 300
+ window.dispatchEvent(new Event('resize'))
+ })
+ expect(handler).toHaveBeenCalledTimes(2)
+
+ // Change shouldInjectEvent to false and rerender
+ shouldInjectEvent = false
+ rerender()
+ expect(handler).toHaveBeenCalledTimes(2) // Handler not called on rerender with shouldInjectEvent: false
+
+ // Trigger resize, handler should NOT be called
+ act(() => {
+ window.innerWidth = 200
+ window.dispatchEvent(new Event('resize'))
+ })
+ expect(handler).toHaveBeenCalledTimes(2) // Still 2, event listener removed
+
+ // Change shouldInjectEvent back to true and rerender
+ shouldInjectEvent = true
+ rerender()
+ act(() => {
+ window.dispatchEvent(new Event('resize'))
+ expect(handler).toHaveBeenCalledTimes(3) // Handler called again because event listener re-added
+ })
+
+ // Trigger resize, handler should be called again
+ act(() => {
+ window.innerWidth = 100
+ window.dispatchEvent(new Event('resize'))
+ })
+ expect(handler).toHaveBeenCalledTimes(4)
})
- expect(cb).toHaveBeenCalledTimes(2)
- expect(cb).toHaveBeenCalledTimes(2)
+ })
+
+ describe('integration with React component', () => {
+ it('should update component based on window resize', () => {
+ // Initial width: Desktop View
+ window.innerWidth = 1024
+ render( )
+ expect(screen.getByText('Desktop View')).toBeInTheDocument()
+ expect(screen.queryByText('Mobile View')).not.toBeInTheDocument()
+
+ // Resize to mobile width
+ act(() => {
+ window.innerWidth = 500
+ window.dispatchEvent(new Event('resize'))
+ })
+ expect(screen.getByText('Mobile View')).toBeInTheDocument()
+ expect(screen.queryByText('Desktop View')).not.toBeInTheDocument()
- shouldInjectEvent = false
- rerender()
- act(() => {
- window.dispatchEvent(new Event('resize'))
+ // Resize back to desktop width
+ act(() => {
+ window.innerWidth = 800
+ window.dispatchEvent(new Event('resize'))
+ })
+ expect(screen.getByText('Desktop View')).toBeInTheDocument()
+ expect(screen.queryByText('Mobile View')).not.toBeInTheDocument()
})
- expect(cb).toHaveBeenCalledTimes(2)
})
})
+
+function TestComponent() {
+ const isMobile = useWindowResize({ handler: () => window.innerWidth < 768 })
+
+ return {isMobile ? 'Mobile View' : 'Desktop View'}
+}
diff --git a/src/lib/use-window-resize/index.tsx b/src/lib/use-window-resize/index.tsx
index 49d5fa7..a707825 100644
--- a/src/lib/use-window-resize/index.tsx
+++ b/src/lib/use-window-resize/index.tsx
@@ -1,17 +1,51 @@
-'use client'
import { useState } from 'react'
import { useEventListener } from '../use-event-listener'
/**
* @description
- * A hook which evaluates the passed callback on window resize event and returns the result of that callback.
+ * A React hook that evaluates provided callback function on window resize event and returns the result of it.
+ *
+ * @example
+ import { useWindowResize } from 'classic-react-hooks'
+
+ function ResponsiveComponent() {
+ const breakpoint = useWindowResize(() => {
+ const width = window.innerWidth
+ if (width < 640) return 'sm'
+ if (width < 768) return 'md'
+ if (width < 1024) return 'lg'
+ return 'xl'
+ })
+
+ return (
+
+
Current breakpoint: {breakpoint}
+ {breakpoint === 'sm' &&
}
+ {breakpoint === 'md' &&
}
+ {['lg', 'xl'].includes(breakpoint) &&
}
+
+ )
+ }
*
* @see Docs https://classic-react-hooks.vercel.app/hooks/use-window-resize.html
*/
-export default function useWindowResize(cb: () => T, options?: { defaultValue?: T; shouldInjectEvent?: boolean }) {
- const [result, setResult] = useState(options?.defaultValue ?? cb)
-
- useEventListener(window, 'resize', () => setResult(cb), { shouldInjectEvent: options?.shouldInjectEvent ?? true })
+export default function useWindowResize({
+ handler,
+ options,
+}: {
+ handler: () => T
+ options?: { defaultValue?: T; shouldInjectEvent?: boolean }
+}) {
+ const [result, setResult] = useState(options?.defaultValue ?? handler)
+ useEventListener({
+ target: () => window,
+ event: 'resize',
+ handler: () => setResult(handler),
+ options: {
+ shouldInjectEvent: options?.shouldInjectEvent ?? true,
+ },
+ layoutEffect: true,
+ })
return result
}
diff --git a/src/types/index.ts b/src/types/index.ts
index 948daa1..68e3fcf 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -1,3 +1,13 @@
export type Prettify = {
[Key in keyof K]: K[Key]
} & {}
+
+export type EvTarget = () => EventTarget | null
+export interface EvOptions extends AddEventListenerOptions {
+ shouldInjectEvent?: boolean | any
+}
+export type EvHandler = (event: Event) => void
+
+export type UseEventListenerReturnValues = {
+ setElementRef: (elementNode: HTMLElement | null) => void
+}
diff --git a/tsup.config.ts b/tsdown.config.ts
similarity index 60%
rename from tsup.config.ts
rename to tsdown.config.ts
index e59b603..e9eaf7d 100644
--- a/tsup.config.ts
+++ b/tsdown.config.ts
@@ -1,18 +1,16 @@
-import { defineConfig } from 'tsup'
+import { defineConfig } from 'tsdown'
export default defineConfig({
entry: ['src/index.tsx'],
- splitting: true,
+ platform:'neutral',
sourcemap: true,
clean: true,
dts: true,
format: ['cjs', 'esm'],
- minify: 'terser',
+ minify: true,
shims: true,
outDir: 'dist',
- target: 'es2017',
+ target: 'esnext',
treeshake: true,
- jsxFragment: 'React.Fragment',
- metafile: true,
tsconfig: './tsconfig.json',
})
diff --git a/vitest.config.mts b/vitest.config.mts
index d5adfc5..c3eb360 100644
--- a/vitest.config.mts
+++ b/vitest.config.mts
@@ -14,8 +14,9 @@ export default defineConfig({
all: true,
include: ['src/lib/**/*'],
exclude: ['src/lib/use-combined-key-event-listener'],
+ reporter:['html','text']
},
- include: ['src/lib/**/*.{test,spec}.{js,jsx,ts,tsx}'],
+ include: ['src/lib/**/*.test.{tsx,ts}'],
exclude: [
'**/node_modules/**',
'**/dist/**',