{"_id":"@ariefsn/svelte-use","_rev":"4-4d5a6121400b99966e8d4611ed321f18","name":"@ariefsn/svelte-use","dist-tags":{"latest":"1.2.1"},"versions":{"1.0.0":{"name":"@ariefsn/svelte-use","version":"1.0.0","keywords":["svelte","svelte5","svelte-use","composables","hooks","utilities","reactivity","browser","intersection-observer","resize-observer","localstorage","sessionstorage","clipboard","geolocation","websocket","indexeddb","animation","virtual-list","debounce","throttle","countdown","scroll","drag-and-drop","vueuse-inspired"],"license":"MIT","_id":"@ariefsn/svelte-use@1.0.0","maintainers":[{"name":"ariefsn","email":"ayiexz22@gmail.com"}],"dist":{"shasum":"0e38f7eec9c3d4f0635a588e03acff2f240cd10d","tarball":"https://registry.npmjs.org/@ariefsn/svelte-use/-/svelte-use-1.0.0.tgz","fileCount":125,"integrity":"sha512-iW2jboKhK3WbgY/XwBS59JanTF0Mb+q7olzUMDLR/1p6zzStTUEPQAVhcKotgscJ7PxAldrxgbVfzezwobR36g==","signatures":[{"sig":"MEQCIG+9nS2gYB4TQSDZoEYEXztz0z7WLtB2yIr6EC16o2nYAiAcjO7R1d5NABCzt1tzDLV7a5aZMscR9PICLKN+VCKQgQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":241474},"type":"module","types":"./dist/index.d.ts","svelte":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","svelte":"./dist/index.js"},"./*":{"types":"./dist/*.d.ts","svelte":"./dist/*.js","default":"./dist/*.js"}},"gitHead":"acb17613c9ab68984c0cd623e534baec22afc268","scripts":{"dev":"vite dev","lint":"prettier --check . && eslint .","test":"npm run test:unit -- --run && npm run test:e2e","build":"vite build && npm run prepack","check":"svelte-kit sync && svelte-check --tsconfig ./tsconfig.json","format":"prettier --write .","prepack":"svelte-kit sync && svelte-package && publint","prepare":"svelte-kit sync || echo ''","preview":"vite preview","test:e2e":"playwright test","test:unit":"vitest","check:watch":"svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"},"_npmUser":{"name":"ariefsn","email":"ayiexz22@gmail.com"},"_npmVersion":"10.9.3","description":"Collection of reactive utility composables for Svelte 5 inspired by VueUse.","directories":{},"sideEffects":["**/*.css"],"_nodeVersion":"22.20.0","_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.1","eslint":"^9.39.2","svelte":"^5.51.0","vitest":"^4.0.18","globals":"^17.3.0","publint":"^0.3.17","prettier":"^3.8.1","@eslint/js":"^9.39.2","playwright":"^1.58.1","typescript":"^5.9.3","@types/node":"^22","svelte-check":"^4.3.6","@sveltejs/kit":"^2.50.2","@eslint/compat":"^2.0.2","@playwright/test":"^1.58.1","@sveltejs/package":"^2.5.7","typescript-eslint":"^8.54.0","eslint-plugin-svelte":"^3.14.0","vitest-browser-svelte":"^2.0.2","@sveltejs/adapter-auto":"^7.0.0","eslint-config-prettier":"^10.1.8","prettier-plugin-svelte":"^3.4.1","@sveltejs/adapter-static":"^3.0.10","@vitest/browser-playwright":"^4.0.18","@sveltejs/vite-plugin-svelte":"^6.2.4"},"peerDependencies":{"svelte":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/svelte-use_1.0.0_1772240399134_0.7009648523165339","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@ariefsn/svelte-use","version":"1.1.0","keywords":["svelte","svelte5","svelte-use","svelte-hooks","svelte-utilities","svelte-composables","composables","hooks","use-hooks","utilities","runes","reactive","reactivity","state","ssr-safe","typescript","tree-shakable","auto-cleanup","browser","intersection-observer","resize-observer","mutation-observer","localstorage","sessionstorage","clipboard","geolocation","websocket","fetch","indexeddb","animation","virtual-list","debounce","throttle","countdown","scroll","drag-and-drop","undo-redo","history","watch","async-state","gestures","swipe","long-press","eye-dropper","web-share","vibration","notifications","wake-lock","permissions","device-motion","device-orientation","battery","network","breakpoints","focus","idle","vueuse-inspired"],"license":"MIT","_id":"@ariefsn/svelte-use@1.1.0","maintainers":[{"name":"ariefsn","email":"ayiexz22@gmail.com"}],"dist":{"shasum":"11806c4dca559bb5b7a26c3a7feccf095bfe0a46","tarball":"https://registry.npmjs.org/@ariefsn/svelte-use/-/svelte-use-1.1.0.tgz","fileCount":183,"integrity":"sha512-WQR+nJ4EjgeMa2Jtoyda/CSVuvek2GUqG0mmWl+5sZ8vB4pWNZltxkBrTlriLBT98cbSivpp74gwrxIA3jCCsg==","signatures":[{"sig":"MEUCIQDGE40Cpod7aHmt9XIa78qlcLEB/qDi8gfEOFFzKUjR8gIgB3dF18nlqfuCpC1S6J9wW62PTZWVnKkFQ9Ljx4kMW04=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":312043},"type":"module","types":"./dist/index.d.ts","svelte":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","svelte":"./dist/index.js"},"./*":{"types":"./dist/*.d.ts","svelte":"./dist/*.js","default":"./dist/*.js"}},"gitHead":"acb17613c9ab68984c0cd623e534baec22afc268","scripts":{"dev":"vite dev","lint":"prettier --check . && eslint .","test":"npm run test:unit -- --run && npm run test:e2e","build":"vite build && npm run prepack","check":"svelte-kit sync && svelte-check --tsconfig ./tsconfig.json","format":"prettier --write .","prepack":"svelte-kit sync && svelte-package && publint","prepare":"svelte-kit sync || echo ''","preview":"vite preview","test:e2e":"playwright test","test:unit":"vitest","check:watch":"svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"},"_npmUser":{"name":"ariefsn","email":"ayiexz22@gmail.com"},"_npmVersion":"10.9.3","description":"Collection of reactive utility composables for Svelte 5 inspired by VueUse.","directories":{},"sideEffects":["**/*.css"],"_nodeVersion":"22.20.0","_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.1","eslint":"^9.39.2","svelte":"^5.51.0","vitest":"^4.0.18","globals":"^17.3.0","publint":"^0.3.17","prettier":"^3.8.1","@eslint/js":"^9.39.2","playwright":"^1.58.1","typescript":"^5.9.3","@types/node":"^22","svelte-check":"^4.3.6","@sveltejs/kit":"^2.50.2","@eslint/compat":"^2.0.2","@playwright/test":"^1.58.1","@sveltejs/package":"^2.5.7","typescript-eslint":"^8.54.0","eslint-plugin-svelte":"^3.14.0","vitest-browser-svelte":"^2.0.2","@sveltejs/adapter-auto":"^7.0.0","eslint-config-prettier":"^10.1.8","prettier-plugin-svelte":"^3.4.1","@sveltejs/adapter-static":"^3.0.10","@vitest/browser-playwright":"^4.0.18","@sveltejs/vite-plugin-svelte":"^6.2.4"},"peerDependencies":{"svelte":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/svelte-use_1.1.0_1773830222547_0.276261528345207","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@ariefsn/svelte-use","version":"1.2.0","keywords":["svelte","svelte5","svelte-use","svelte-hooks","svelte-utilities","svelte-composables","composables","hooks","use-hooks","utilities","runes","reactive","reactivity","state","ssr-safe","typescript","tree-shakable","auto-cleanup","browser","intersection-observer","resize-observer","mutation-observer","localstorage","sessionstorage","clipboard","geolocation","websocket","fetch","indexeddb","animation","virtual-list","debounce","throttle","countdown","scroll","drag-and-drop","undo-redo","history","watch","async-state","gestures","swipe","long-press","eye-dropper","web-share","vibration","notifications","wake-lock","permissions","device-motion","device-orientation","battery","network","breakpoints","focus","idle","vueuse-inspired","seo","open-graph","meta-tags","dark-mode","color-mode","theme","media-query","web-worker","state-machine","fullscreen","gamepad","speech-synthesis","text-to-speech","media-devices","webcam","screen-capture","broadcast-channel","server-sent-events","infinite-scroll","pagination","memoize","file-system-access"],"license":"MIT","_id":"@ariefsn/svelte-use@1.2.0","maintainers":[{"name":"ariefsn","email":"ayiexz22@gmail.com"}],"homepage":"https://svelte-use.ariefsn.dev","bugs":{"url":"https://github.com/ariefsn/svelte-use/issues"},"dist":{"shasum":"d8bd934d310c16b036cf1a5a5ae3b25615944f51","tarball":"https://registry.npmjs.org/@ariefsn/svelte-use/-/svelte-use-1.2.0.tgz","fileCount":281,"integrity":"sha512-Mq1OsffXRTBVfUVUH7mW+7Ilz2CLHtMdp1lvonF+FBFY2XxYuWh9OOIOMDVbsGUZDslEfVOPBF6p0GedYs+Gtw==","signatures":[{"sig":"MEYCIQDFudlTDqVLK1kb03udzWNd898DVm8WbgghGv0UCqZzwAIhAO2aTVoHnJBdekrGhZ6KfJiIrp/HAKTxjuYIAbmKW67C","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIAoWgQJQam9GhS7LMygG+ILAb/OJgp1L/7lUisUMxELlAiA/Scxmzq8UnCWbjhUdvnXxhNa9XMJqVIHI0dANPYwKpg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ariefsn%2fsvelte-use@1.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":397320},"type":"module","types":"./dist/index.d.ts","svelte":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","svelte":"./dist/index.js"},"./*":{"types":"./dist/*.d.ts","svelte":"./dist/*.js","default":"./dist/*.js"},"./Seo.svelte":{"types":"./dist/seo/Seo.svelte.d.ts","svelte":"./dist/seo/Seo.svelte","default":"./dist/seo/Seo.svelte"}},"gitHead":"2cf908caef65f68d8b21f8aee190383197961727","scripts":{"dev":"vite dev","lint":"prettier --check . && eslint . && node scripts/check-effects.mjs","test":"npm run test:unit -- --run && npm run test:e2e","build":"vite build && npm run prepack","check":"svelte-kit sync && svelte-check --tsconfig ./tsconfig.json","format":"prettier --write .","prepack":"svelte-kit sync && svelte-package && publint","prepare":"svelte-kit sync || echo ''","preview":"vite preview","test:e2e":"playwright test","test:unit":"vitest","check:watch":"svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch","lint:effects":"node scripts/check-effects.mjs","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:e54654fd-19ee-457d-b74e-1e225ab77a40"}},"repository":{"url":"git+https://github.com/ariefsn/svelte-use.git","type":"git"},"_npmVersion":"11.19.0","description":"Collection of reactive utility composables for Svelte 5 inspired by VueUse.","directories":{},"sideEffects":["**/*.css"],"_nodeVersion":"24.21.0","_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.1","eslint":"^9.39.2","svelte":"^5.51.0","vitest":"^4.0.18","globals":"^17.3.0","publint":"^0.3.17","prettier":"^3.8.1","@eslint/js":"^9.39.2","playwright":"^1.63.0","typescript":"^5.9.3","@types/node":"^22","tailwindcss":"^4.3.3","svelte-check":"^4.3.6","@sveltejs/kit":"^2.50.2","@eslint/compat":"^2.0.2","@playwright/test":"^1.63.0","@sveltejs/package":"^2.5.7","@tailwindcss/vite":"^4.3.3","typescript-eslint":"^8.54.0","@vitest/coverage-v8":"4.0.18","eslint-plugin-svelte":"^3.14.0","vitest-browser-svelte":"^2.0.2","@sveltejs/adapter-auto":"^7.0.0","eslint-config-prettier":"^10.1.8","prettier-plugin-svelte":"^3.4.1","@sveltejs/adapter-static":"^3.0.10","@vitest/browser-playwright":"^4.0.18","@sveltejs/vite-plugin-svelte":"^6.2.4"},"peerDependencies":{"svelte":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/svelte-use_1.2.0_1790505932059_0.7488578258456142","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"_id":"@ariefsn/svelte-use@1.2.1","bugs":{"url":"https://github.com/ariefsn/svelte-use/issues"},"dist":{"shasum":"584fdae955bc5c50125dc4019ecd479cf14a34cd","tarball":"https://registry.npmjs.org/@ariefsn/svelte-use/-/svelte-use-1.2.1.tgz","fileCount":281,"integrity":"sha512-kFPqX7SLSlp9PRvHSaAEHpw97j+wrKXkR2FCZBnY1XnlyZMoUTgXJoKNnq9I7GJ8y18SCzd/cPr8Di0do5Jz6w==","signatures":[{"sig":"MEUCICwwRSf9FC8chYfY5e6WCz6QgOuA4GqtSc5vHDGoaLyPAiEA+RcTPw/7m0d2j5c7CN4JzC+fGkpZF3jzviJngBs6VcU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIB/CJdVwOuRcaVMqAUu2d+bvCElk6X2RB9SgksJ0y55CAiEAjUWNByW0QjtBKBAhGVK8GOqves1Dl2UApjqcqDVt+Hk="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ariefsn%2fsvelte-use@1.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":398323},"name":"@ariefsn/svelte-use","type":"module","types":"./dist/index.d.ts","svelte":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","svelte":"./dist/index.js"},"./*":{"types":"./dist/*.d.ts","svelte":"./dist/*.js","default":"./dist/*.js"},"./Seo.svelte":{"types":"./dist/seo/Seo.svelte.d.ts","svelte":"./dist/seo/Seo.svelte","default":"./dist/seo/Seo.svelte"}},"gitHead":"35294c71f416e0e78ddd7970f2e866c634e1bb2b","license":"MIT","scripts":{"dev":"vite dev","lint":"prettier --check . && eslint . && node scripts/check-effects.mjs","test":"npm run test:unit -- --run && npm run test:e2e","build":"vite build && npm run prepack","check":"svelte-kit sync && svelte-check --tsconfig ./tsconfig.json","format":"prettier --write .","prepack":"svelte-kit sync && svelte-package && publint","prepare":"svelte-kit sync || echo ''","preview":"vite preview","test:e2e":"playwright test","test:unit":"vitest","check:watch":"svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch","lint:effects":"node scripts/check-effects.mjs","test:coverage":"vitest run --coverage"},"version":"1.2.1","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:e54654fd-19ee-457d-b74e-1e225ab77a40"}},"homepage":"https://svelte-use.ariefsn.dev","keywords":["svelte","svelte5","svelte-use","svelte-hooks","svelte-utilities","svelte-composables","composables","hooks","use-hooks","utilities","runes","reactive","reactivity","state","ssr-safe","typescript","tree-shakable","auto-cleanup","browser","intersection-observer","resize-observer","mutation-observer","localstorage","sessionstorage","clipboard","geolocation","websocket","fetch","indexeddb","animation","virtual-list","debounce","throttle","countdown","scroll","drag-and-drop","undo-redo","history","watch","async-state","gestures","swipe","long-press","eye-dropper","web-share","vibration","notifications","wake-lock","permissions","device-motion","device-orientation","battery","network","breakpoints","focus","idle","vueuse-inspired","seo","open-graph","meta-tags","dark-mode","color-mode","theme","media-query","web-worker","state-machine","fullscreen","gamepad","speech-synthesis","text-to-speech","media-devices","webcam","screen-capture","broadcast-channel","server-sent-events","infinite-scroll","pagination","memoize","file-system-access"],"repository":{"url":"git+https://github.com/ariefsn/svelte-use.git","type":"git"},"_npmVersion":"11.19.0","description":"Collection of reactive utility composables for Svelte 5 inspired by VueUse.","directories":{},"maintainers":[{"name":"ariefsn","email":"ayiexz22@gmail.com"}],"sideEffects":["**/*.css"],"_nodeVersion":"24.21.0","_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.1","eslint":"^9.39.2","svelte":"^5.51.0","vitest":"^4.0.18","globals":"^17.3.0","publint":"^0.3.17","prettier":"^3.8.1","@eslint/js":"^9.39.2","playwright":"^1.63.0","typescript":"^5.9.3","@types/node":"^22","tailwindcss":"^4.3.3","svelte-check":"^4.3.6","@sveltejs/kit":"^2.50.2","@eslint/compat":"^2.0.2","@playwright/test":"^1.63.0","@sveltejs/package":"^2.5.7","@tailwindcss/vite":"^4.3.3","typescript-eslint":"^8.54.0","@vitest/coverage-v8":"4.0.18","eslint-plugin-svelte":"^3.14.0","vitest-browser-svelte":"^2.0.2","@sveltejs/adapter-auto":"^7.0.0","eslint-config-prettier":"^10.1.8","prettier-plugin-svelte":"^3.4.1","@sveltejs/adapter-static":"^3.0.10","@vitest/browser-playwright":"^4.0.18","@sveltejs/vite-plugin-svelte":"^6.2.4"},"peerDependencies":{"svelte":"^5.0.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/svelte-use_1.2.1_1790606767243_0.10295490338738089"}}},"time":{"created":"2026-02-28T00:59:59.039Z","modified":"2026-09-28T14:46:07.717Z","1.0.0":"2026-02-28T00:59:59.335Z","1.1.0":"2026-03-18T10:37:02.706Z","1.2.0":"2026-09-27T10:45:32.155Z","1.2.1":"2026-09-28T14:46:07.341Z"},"bugs":{"url":"https://github.com/ariefsn/svelte-use/issues"},"license":"MIT","homepage":"https://svelte-use.ariefsn.dev","keywords":["svelte","svelte5","svelte-use","svelte-hooks","svelte-utilities","svelte-composables","composables","hooks","use-hooks","utilities","runes","reactive","reactivity","state","ssr-safe","typescript","tree-shakable","auto-cleanup","browser","intersection-observer","resize-observer","mutation-observer","localstorage","sessionstorage","clipboard","geolocation","websocket","fetch","indexeddb","animation","virtual-list","debounce","throttle","countdown","scroll","drag-and-drop","undo-redo","history","watch","async-state","gestures","swipe","long-press","eye-dropper","web-share","vibration","notifications","wake-lock","permissions","device-motion","device-orientation","battery","network","breakpoints","focus","idle","vueuse-inspired","seo","open-graph","meta-tags","dark-mode","color-mode","theme","media-query","web-worker","state-machine","fullscreen","gamepad","speech-synthesis","text-to-speech","media-devices","webcam","screen-capture","broadcast-channel","server-sent-events","infinite-scroll","pagination","memoize","file-system-access"],"repository":{"url":"git+https://github.com/ariefsn/svelte-use.git","type":"git"},"description":"Collection of reactive utility composables for Svelte 5 inspired by VueUse.","maintainers":[{"name":"ariefsn","email":"ayiexz22@gmail.com"}],"readme":"<div align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/ariefsn/svelte-use/main/static/logo.svg\" alt=\"svelte-use logo\" width=\"120\" height=\"120\" />\n\n  <h1>@ariefsn/svelte-use</h1>\n\n  <p>A collection of <strong>100+</strong> Svelte 5 runes-first utility composables.<br/>No stores. No external dependencies. SSR-safe. Fully typed.</p>\n\n  <p>\n    <a href=\"https://github.com/ariefsn/svelte-use\">\n      <img src=\"https://img.shields.io/badge/GitHub-ariefsn%2Fsvelte--use-181717?logo=github&logoColor=white\" alt=\"GitHub\" />\n    </a>\n    <a href=\"https://www.npmjs.com/package/@ariefsn/svelte-use\">\n      <img src=\"https://img.shields.io/npm/v/@ariefsn/svelte-use?color=a78bfa&logo=npm&logoColor=white\" alt=\"npm version\" />\n    </a>\n    <a href=\"https://www.npmjs.com/package/@ariefsn/svelte-use\">\n      <img src=\"https://img.shields.io/npm/dm/@ariefsn/svelte-use?color=a78bfa\" alt=\"npm downloads\" />\n    </a>\n    <img src=\"https://img.shields.io/badge/Svelte-5-FF3E00?logo=svelte&logoColor=white\" alt=\"Svelte 5\" />\n    <img src=\"https://img.shields.io/badge/TypeScript-first-3178C6?logo=typescript&logoColor=white\" alt=\"TypeScript\" />\n  </p>\n</div>\n\n---\n\n## Features\n\n|                       |                                                       |\n| --------------------- | ----------------------------------------------------- |\n| ⚡ **Svelte 5 Runes** | Built for `$state`, `$derived`, `$effect` — no stores |\n| 🌲 **Tree-shakable**  | Import only what you use                              |\n| 🔒 **Fully typed**    | First-class TypeScript, no `any`                      |\n| 🌐 **SSR safe**       | All browser APIs are guarded                          |\n| 📦 **Zero deps**      | No runtime dependencies                               |\n| 🧹 **Auto cleanup**   | Listeners removed on component destroy                |\n\n---\n\n## Installation\n\n```sh\nnpm install @ariefsn/svelte-use\n# or\npnpm add @ariefsn/svelte-use\n# or\nbun add @ariefsn/svelte-use\n```\n\n> Requires **Svelte 5** as a peer dependency.\n\n---\n\n## Utilities\n\n### Animation\n\n| Composable      | Description                                     |\n| --------------- | ----------------------------------------------- |\n| `useAnimate`    | Reactive Web Animations API wrapper             |\n| `useRafFn`      | Run a callback on every animation frame         |\n| `useParallax`   | Parallax effect based on pointer or device tilt |\n| `useTransition` | Animated numeric transitions with easing        |\n\n### Async\n\n| Composable            | Description                                          |\n| --------------------- | ---------------------------------------------------- |\n| `useFetch`            | Reactive fetch with loading/error state              |\n| `useWebSocket`        | Reactive WebSocket with auto-reconnect               |\n| `useAsyncState`       | Reactive async/promise state with loading/error      |\n| `useEventSource`      | Server-sent events; the browser handles reconnection |\n| `useBroadcastChannel` | Cross-tab messaging by structured clone              |\n| `useAsyncQueue`       | Run async tasks with bounded concurrency             |\n\n### Time\n\n| Composable       | Description                                  |\n| ---------------- | -------------------------------------------- |\n| `useInterval`    | Reactive interval counter                    |\n| `useIntervalFn`  | Run a callback on an interval                |\n| `useNow`         | Reactive current Date                        |\n| `useTimeout`     | Reactive timeout flag                        |\n| `useTimeoutFn`   | Run a callback after a delay                 |\n| `useTimeoutPoll` | Poll a callback with timeout-based intervals |\n| `useTimestamp`   | Reactive current timestamp (ms)              |\n\n### State\n\n| Composable            | Description                                            |\n| --------------------- | ------------------------------------------------------ |\n| `useToggle`           | Reactive boolean toggle                                |\n| `useCounter`          | Reactive counter with inc/dec/reset                    |\n| `usePrevious`         | Track previous value of any reactive getter            |\n| `useSorted`           | Reactive sorted copy of an array                       |\n| `useCycleList`        | Cycle through a list reactively                        |\n| `useCountdown`        | Countdown timer with start/stop/reset                  |\n| `useTimeAgo`          | Human-readable relative time string                    |\n| `useAutoResetState`   | State that auto-resets to default after delay          |\n| `useDefaultState`     | State with fallback for null/undefined                 |\n| `useLastChanged`      | Timestamp of last reactive value change                |\n| `useTrackHistory`     | Undo/redo history for reactive values                  |\n| `useHistoryState`     | State with built-in undo/redo history                  |\n| `useStateMachine`     | Typed finite state machine, inferred from the config   |\n| `useOffsetPagination` | Pagination state that self-corrects when totals shrink |\n| `useConfirmDialog`    | Confirmation flow as a single `await`                  |\n\n### Reactivity\n\n| Composable    | Description                                      |\n| ------------- | ------------------------------------------------ |\n| `useDebounce` | Debounce any reactive getter                     |\n| `useWatch`    | Watch reactive values with current/previous args |\n| `useWhenever` | Watch that fires only when value becomes truthy  |\n| `useUntil`    | Await a reactive value reaching a condition      |\n| `useCloned`   | Deep copy of a reactive value, for edit buffers  |\n\n### Browser – Keyboard & Scroll\n\n| Composable          | Description                                               |\n| ------------------- | --------------------------------------------------------- |\n| `useMagicKeys`      | Reactive keyboard state via Proxy — single keys or combos |\n| `useKeyModifier`    | Track Ctrl/Shift/Alt/Meta state                           |\n| `useScroll`         | Scroll position, direction, edge arrival                  |\n| `useScrollLock`     | Lock/unlock body scroll                                   |\n| `useInfiniteScroll` | Load more content as a container nears its edge           |\n\n### Browser – Pointer & Drag\n\n| Composable          | Description                                        |\n| ------------------- | -------------------------------------------------- |\n| `useMouse`          | Viewport-relative pointer position                 |\n| `useMousePressed`   | Detect mouse button press state                    |\n| `useMouseInElement` | Pointer position relative to an element            |\n| `useDraggable`      | Full-featured draggable with axis, bounds, handles |\n\n### Browser – Observers\n\n| Composable                | Description                                    |\n| ------------------------- | ---------------------------------------------- |\n| `useElementSize`          | Reactive element dimensions via ResizeObserver |\n| `useElementBounding`      | Reactive full bounding box, position included  |\n| `useIntersectionObserver` | Visibility detection via IntersectionObserver  |\n| `useResizeObserver`       | Raw ResizeObserver with callback               |\n| `useMutationObserver`     | DOM mutation observation                       |\n\n### Browser – Sensors\n\n| Composable              | Description                                            |\n| ----------------------- | ------------------------------------------------------ |\n| `useMediaQuery`         | Reactively track whether a CSS media query matches     |\n| `useWindowSize`         | Reactive viewport dimensions                           |\n| `useIdle`               | Detect user idle state                                 |\n| `useNetwork`            | Network Information API (downlink, RTT, effectiveType) |\n| `useGeolocation`        | Reactive geolocation via watchPosition                 |\n| `useBreakpoints`        | Reactive responsive breakpoints                        |\n| `useBrowserLocation`    | Reactive browser location (URL, hash, search)          |\n| `useNavigatorLanguage`  | Reactive navigator language                            |\n| `useOnline`             | Reactive online/offline status                         |\n| `usePageLeave`          | Detect when user leaves the page                       |\n| `useDocumentVisibility` | Reactive document visibility state                     |\n| `useWindowFocus`        | Track whether browser window is focused                |\n| `useDeviceMotion`       | Device acceleration and rotation data                  |\n| `useDeviceOrientation`  | Device physical orientation (alpha/beta/gamma)         |\n| `useDevicePixelRatio`   | Reactive device pixel ratio for Retina detection       |\n| `useScreenOrientation`  | Screen orientation and angle, with locking             |\n| `useGamepad`            | Gamepad state, polled only while one is connected      |\n| `useScrollbarWidth`     | Measure scrollbar width of an element                  |\n\n### Browser – Storage\n\n| Composable          | Description                             |\n| ------------------- | --------------------------------------- |\n| `useStorage`        | Reactive Web Storage (local or session) |\n| `useLocalStorage`   | Reactive localStorage with SSR safety   |\n| `useIndexedDB`      | Reactive IndexedDB with CRUD & querying |\n| `useBase64`         | Reactive Base64 encode/decode           |\n| `useObjectUrl`      | Reactive object URL from Blob/File      |\n| `useSessionStorage` | Reactive sessionStorage with SSR safety |\n\n### Browser – Interaction\n\n| Composable            | Description                               |\n| --------------------- | ----------------------------------------- |\n| `useClickOutside`     | Detect clicks outside an element          |\n| `useDropZone`         | Drag-and-drop zone with file/data support |\n| `useElementHover`     | Detect hover state of an element          |\n| `useFocus`            | Reactive focus state of an element        |\n| `useActiveElement`    | Track currently focused element globally  |\n| `useLongPress`        | Long press gesture detection              |\n| `useStartTyping`      | Detect typing on non-editable elements    |\n| `useTextareaAutosize` | Grow a textarea to fit its content        |\n| `useSwipe`            | Touch swipe gesture detection             |\n\n### Performance\n\n| Composable       | Description                                           |\n| ---------------- | ----------------------------------------------------- |\n| `useFps`         | Reactive frames-per-second counter                    |\n| `useThrottleFn`  | Throttle any function                                 |\n| `useDebounceFn`  | Debounce any function                                 |\n| `useWebWorkerFn` | Run a self-contained function off the main thread     |\n| `useMemoize`     | Cache a function's results by its arguments, with LRU |\n\n### Virtualization\n\n| Composable       | Description                      |\n| ---------------- | -------------------------------- |\n| `useVirtualList` | Efficient virtual list rendering |\n\n### Web APIs\n\n| Composable             | Description                                      |\n| ---------------------- | ------------------------------------------------ |\n| `useClipboard`         | Reactive clipboard read/write                    |\n| `useBattery`           | Reactive Battery Status API                      |\n| `useSpeechRecognition` | Reactive Web Speech Recognition API              |\n| `useEyeDropper`        | EyeDropper API for color picking                 |\n| `useFileDialog`        | Programmatic file input dialog                   |\n| `useShare`             | Native Web Share API                             |\n| `useVibrate`           | Vibration API                                    |\n| `useWebNotification`   | Desktop notifications API                        |\n| `usePermission`        | Browser Permissions API                          |\n| `useWakeLock`          | Screen Wake Lock API                             |\n| `useFullscreen`        | Display any element fullscreen, Escape-aware     |\n| `useImage`             | Preload an image and track its load state        |\n| `useSpeechSynthesis`   | Text-to-speech, with async voice loading handled |\n| `useFileSystemAccess`  | Read **and write** real files (Chromium only)    |\n| `useSupported`         | SSR-safe one-shot feature detection              |\n| `useEventListener`     | Generic event listener with cleanup              |\n| `useTextDirection`     | Track/set text directionality                    |\n| `useTextSelection`     | Track text selection                             |\n\n### Browser – Appearance\n\n| Composable                  | Description                                              |\n| --------------------------- | -------------------------------------------------------- |\n| `useColorMode`              | Colour mode with `auto` resolution, persistence and sync |\n| `usePreferredDark`          | Whether the OS requests a dark colour scheme             |\n| `usePreferredColorScheme`   | OS colour scheme as `dark` / `light` / `no-preference`   |\n| `usePreferredReducedMotion` | Whether the OS requests reduced motion                   |\n| `usePreferredContrast`      | OS contrast preference, including forced colours         |\n| `useCssVar`                 | Read and write a CSS custom property                     |\n\n### Browser – Document\n\n| Composable     | Description                                             |\n| -------------- | ------------------------------------------------------- |\n| `useTitle`     | Read and write `document.title`, restored on destroy    |\n| `useFavicon`   | Read and write the favicon, adopting an existing link   |\n| `useStyleTag`  | Inject a `<style>` element, deduplicated by id          |\n| `useScriptTag` | Load an external script, deduplicated across call sites |\n\n### Browser – Media\n\n| Composable        | Description                                                        |\n| ----------------- | ------------------------------------------------------------------ |\n| `useUserMedia`    | Camera and microphone capture, device switching, preview mirroring |\n| `useDisplayMedia` | Screen capture that notices the browser's \"Stop sharing\"           |\n| `useDevicesList`  | Media devices grouped by kind, refreshed on `devicechange`         |\n\n### Head & SEO\n\n| Composable | Description                                                      |\n| ---------- | ---------------------------------------------------------------- |\n| `useSeo`   | Layered SEO metadata as a builder, rendered into `<svelte:head>` |\n| `Seo`      | Component that renders `useSeo` output — the only component here |\n\n### Browser – Navigation\n\n| Composable           | Description                                                   |\n| -------------------- | ------------------------------------------------------------- |\n| `useNavigationGuard` | Navigation guard with confirm/cancel — **requires SvelteKit** |\n| `useUrlSearchParams` | Reactive URL query parameters, with history and hash modes    |\n\n> **Note:** `useNavigationGuard` is the only composable here that is not\n> plain-Svelte. It imports `beforeNavigate` and `goto` from `$app/navigation`,\n> so it works in SvelteKit apps only; `@sveltejs/kit` is not a declared peer\n> dependency. Every other composable in this library runs in any Svelte 5 app.\n\n---\n\n## Composable Reference\n\n### `useToggle`\n\nReactive boolean toggle.\n\n```ts\nimport { useToggle } from '@ariefsn/svelte-use';\n\nconst { value, toggle, set } = useToggle();\n// value → false\ntoggle(); // value → true\nset(false); // value → false\n```\n\n| Return   | Type                   | Description               |\n| -------- | ---------------------- | ------------------------- |\n| `value`  | `boolean` (reactive)   | Current boolean state     |\n| `toggle` | `() => void`           | Flips the value           |\n| `set`    | `(v: boolean) => void` | Sets the value explicitly |\n\n---\n\n### `useCounter`\n\nReactive counter with increment, decrement, and reset.\n\n```ts\nimport { useCounter } from '@ariefsn/svelte-use';\n\nconst { value, inc, dec, reset } = useCounter(0);\ninc(); // value → 1\ninc(5); // value → 6\ndec(3); // value → 3\nreset(); // value → 0\n```\n\n| Return  | Type                       | Description                      |\n| ------- | -------------------------- | -------------------------------- |\n| `value` | `number` (reactive)        | Current counter value            |\n| `inc`   | `(delta?: number) => void` | Increment by `delta` (default 1) |\n| `dec`   | `(delta?: number) => void` | Decrement by `delta` (default 1) |\n| `reset` | `() => void`               | Reset to initial value           |\n\n---\n\n### `usePrevious`\n\nTracks the previous value of any reactive getter. Returns `undefined` until the tracked value changes for the first time.\n\n```ts\nimport { usePrevious } from '@ariefsn/svelte-use';\n\nlet count = $state(0);\nconst prev = usePrevious(() => count);\n// prev() → undefined\ncount = 1;\n// prev() → 0\ncount = 2;\n// prev() → 1\n```\n\n| Parameter | Type      | Description                         |\n| --------- | --------- | ----------------------------------- |\n| `getter`  | `() => T` | Reactive getter function to observe |\n\nReturns a `() => T | undefined` getter.\n\n---\n\n### `useDebounce`\n\nDelays a reactive value until the source stops changing for the specified duration.\n\n```ts\nimport { useDebounce } from '@ariefsn/svelte-use';\n\nlet query = $state('');\nconst debounced = useDebounce(() => query, 500);\n// debounced() updates only after 500 ms of inactivity\n```\n\n| Parameter | Type      | Default | Description                 |\n| --------- | --------- | ------- | --------------------------- |\n| `getter`  | `() => T` | —       | Reactive getter to debounce |\n| `delay`   | `number`  | `300`   | Delay in milliseconds       |\n\nReturns a `() => T` getter.\n\n---\n\n### `useLocalStorage`\n\nReactive `localStorage` with SSR safety. Values are serialised with `JSON.stringify` / `JSON.parse`. Falls back to `initial` in non-browser environments or on parse errors.\n\n```ts\nimport { useLocalStorage } from '@ariefsn/svelte-use';\n\nconst theme = useLocalStorage<'light' | 'dark'>('theme', 'light');\ntheme.set('dark'); // persists to localStorage\ntheme.value; // 'dark'\n```\n\n| Parameter | Type     | Description                           |\n| --------- | -------- | ------------------------------------- |\n| `key`     | `string` | `localStorage` key                    |\n| `initial` | `T`      | Fallback when key is absent or in SSR |\n\n| Return  | Type             | Description                  |\n| ------- | ---------------- | ---------------------------- |\n| `value` | `T` (reactive)   | Current stored value         |\n| `set`   | `(v: T) => void` | Update and persist the value |\n\n---\n\n### `useIndexedDB`\n\nReactive IndexedDB utility with full CRUD, querying, and filtering. SSR-safe — all operations are no-ops on the server. Values survive page refreshes and browser restarts.\n\n```ts\nimport { useIndexedDB } from '@ariefsn/svelte-use';\n\ninterface Note {\n\tid?: number;\n\ttext: string;\n\tdone: boolean;\n}\n\nconst db = useIndexedDB<Note>('my-app', 'notes');\n\n// CRUD\nawait db.add({ text: 'Buy milk', done: false }); // returns generated key\nawait db.get(1); // Note | undefined\nawait db.getAll(); // Note[]\nawait db.update({ id: 1, text: 'Buy milk', done: true });\nawait db.remove(1);\nawait db.clear(); // delete all records\n\n// Reactive state (updated automatically after every mutation)\ndb.items; // Note[]   — all records\ndb.loading; // boolean\ndb.error; // Error | null\n\n// Filtering\nconst pending = await db.query((n) => !n.done); // Note[]\n```\n\n**Options**\n\n| Parameter               | Type      | Default | Description                           |\n| ----------------------- | --------- | ------- | ------------------------------------- |\n| `dbName`                | `string`  | —       | IndexedDB database name               |\n| `storeName`             | `string`  | —       | Object store name                     |\n| `options.version`       | `number`  | `1`     | Schema version (increment to migrate) |\n| `options.keyPath`       | `string`  | `'id'`  | Primary key field name                |\n| `options.autoIncrement` | `boolean` | `true`  | Auto-generate numeric keys            |\n\n**Returns**\n\n| Property / Method | Type                                | Description                                                  |\n| ----------------- | ----------------------------------- | ------------------------------------------------------------ |\n| `items`           | `T[]` (reactive)                    | All stored records; refreshed after every mutation           |\n| `loading`         | `boolean` (reactive)                | `true` while an async operation is in flight                 |\n| `error`           | `Error \\| null` (reactive)          | Last error, or `null`                                        |\n| `add(record)`     | `Promise<IDBValidKey \\| undefined>` | Insert record; returns generated key                         |\n| `get(key)`        | `Promise<T \\| undefined>`           | Fetch single record by primary key                           |\n| `getAll()`        | `Promise<T[]>`                      | Fetch all records and sync `items`                           |\n| `update(record)`  | `Promise<void>`                     | Replace record (must include key field)                      |\n| `remove(key)`     | `Promise<void>`                     | Delete record by primary key                                 |\n| `query(filter)`   | `Promise<T[]>`                      | Return records matching a predicate (doesn't modify `items`) |\n| `clear()`         | `Promise<void>`                     | Delete all records                                           |\n\n---\n\n### `useSorted`\n\nReturns a reactive sorted copy of an array. Never mutates the source.\n\n```ts\nimport { useSorted } from '@ariefsn/svelte-use';\n\nlet items = $state([3, 1, 4, 1, 5]);\nconst sorted = useSorted(() => items);\n// sorted() → [1, 1, 3, 4, 5]\n\nconst desc = useSorted(\n\t() => items,\n\t(a, b) => b - a\n);\n```\n\n---\n\n### `useCycleList`\n\nCycle through a list reactively. Wraps around at both ends.\n\n```ts\nimport { useCycleList } from '@ariefsn/svelte-use';\n\nconst cycle = useCycleList(['light', 'dark', 'system']);\ncycle.state(); // → 'light'\ncycle.next(); // → 'dark'\ncycle.prev(); // → 'light'\ncycle.setIndex(2);\n```\n\n---\n\n### `useCountdown`\n\nCountdown timer with start/stop/reset.\n\n```ts\nimport { useCountdown } from '@ariefsn/svelte-use';\n\nconst timer = useCountdown(60); // 60s at 1s intervals\ntimer.start();\ntimer.count(); // → 60, 59, …, 0\ntimer.isActive(); // → true\ntimer.stop();\ntimer.reset();\n```\n\n---\n\n### `useTimeAgo`\n\nReactive human-readable relative time string.\n\n```ts\nimport { useTimeAgo } from '@ariefsn/svelte-use';\n\nconst ago = useTimeAgo(() => new Date('2024-01-01'));\nago(); // → \"1 year ago\"\n```\n\n---\n\n### `useMagicKeys`\n\nTrack any key or combination via a Proxy.\n\n```ts\nimport { useMagicKeys } from '@ariefsn/svelte-use';\n\nconst keys = useMagicKeys();\nkeys['ctrl+s'](); // → true while Ctrl+S is held\nkeys['shift'](); // → true while Shift is held\n```\n\n---\n\n### `useKeyModifier`\n\nTrack a specific modifier key state.\n\n```ts\nimport { useKeyModifier } from '@ariefsn/svelte-use';\n\nconst ctrl = useKeyModifier('ctrl'); // 'ctrl' | 'shift' | 'alt' | 'meta'\nctrl(); // → true while Ctrl is held\n```\n\n---\n\n### `useScroll`\n\nScroll position, direction flags, edge detection for any scrollable element or `window`.\n\n```ts\nimport { useScroll } from '@ariefsn/svelte-use';\n\nconst scroll = useScroll(); // window\nconst elScroll = useScroll(() => myEl, { offset: { bottom: 20 } });\n\nscroll.y(); // → number\nscroll.isScrolling(); // → boolean\nscroll.arrivedState.bottom(); // → boolean\nscroll.directions.down(); // → boolean\nscroll.scrollTo({ top: 0 });\n```\n\n---\n\n### `useMouse`\n\nTracks viewport-relative pointer position.\n\n```ts\nimport { useMouse } from '@ariefsn/svelte-use';\n\nconst mouse = useMouse();\nmouse.x(); // → number\nmouse.y(); // → number\nmouse.sourceType(); // → 'mouse' | 'touch' | null\n```\n\n---\n\n### `useMousePressed`\n\nDetects whether any mouse button is held.\n\n```ts\nimport { useMousePressed } from '@ariefsn/svelte-use';\n\nconst pressed = useMousePressed();\npressed(); // → boolean\n```\n\n---\n\n### `useDraggable`\n\nFull-featured draggable with axis constraints, bounds, handles, and callbacks.\n\n```ts\nimport { useDraggable } from '@ariefsn/svelte-use';\n\nconst drag = useDraggable(() => el, {\n\taxis: 'x',\n\tinitialValue: { x: 100, y: 100 },\n\tonEnd: (pos) => console.log(pos)\n});\n\ndrag.x(); // → number\ndrag.isDragging(); // → boolean\ndrag.style(); // → \"transform: translate(100px, 0px);\"\n```\n\n---\n\n### `useElementSize`\n\nReactively tracks element dimensions via `ResizeObserver`.\n\n```ts\nimport { useElementSize } from '@ariefsn/svelte-use';\n\nconst size = useElementSize(() => el);\nsize.width(); // → number\nsize.height(); // → number\n```\n\n---\n\n### `useIntersectionObserver`\n\nViewport visibility detection.\n\n```ts\nimport { useIntersectionObserver } from '@ariefsn/svelte-use';\n\nconst { isIntersecting, stop } = useIntersectionObserver(() => el, { threshold: 0.5 });\nisIntersecting(); // → boolean\n```\n\n---\n\n### `useResizeObserver`\n\nRaw `ResizeObserver` wrapper with automatic cleanup.\n\n```ts\nimport { useResizeObserver } from '@ariefsn/svelte-use';\n\nconst { stop } = useResizeObserver(\n\t() => el,\n\t(entry) => {\n\t\tconsole.log(entry.contentRect.width);\n\t}\n);\n```\n\n---\n\n### `useMutationObserver`\n\nObserves DOM mutations on any node.\n\n```ts\nimport { useMutationObserver } from '@ariefsn/svelte-use';\n\nconst { stop } = useMutationObserver(\n\t() => el,\n\t(mutations) => {\n\t\tfor (const m of mutations) console.log(m.type);\n\t},\n\t{ childList: true, subtree: true }\n);\n```\n\n---\n\n### `useIdle`\n\nDetect user inactivity.\n\n```ts\nimport { useIdle } from '@ariefsn/svelte-use';\n\nconst { isIdle, reset } = useIdle(5000); // idle after 5s\nisIdle(); // → boolean\n```\n\n---\n\n### `useNetwork`\n\nReactive Network Information API.\n\n```ts\nimport { useNetwork } from '@ariefsn/svelte-use';\n\nconst net = useNetwork();\nnet.effectiveType(); // → '4g' | '3g' | undefined\nnet.downlink(); // → Mbps | undefined\nnet.saveData(); // → boolean | undefined\n```\n\n---\n\n### `useGeolocation`\n\nReactive geolocation via `watchPosition`.\n\n```ts\nimport { useGeolocation } from '@ariefsn/svelte-use';\n\nconst geo = useGeolocation({ enableHighAccuracy: true });\ngeo.coords()?.latitude; // → number | null\ngeo.error(); // → GeolocationPositionError | null\ngeo.isSupported(); // → boolean\n```\n\n---\n\n### `useFetch`\n\nReactive fetch wrapper with loading/error state.\n\n```ts\nimport { useFetch } from '@ariefsn/svelte-use';\n\nconst { data, loading, error, execute } = useFetch<User[]>('/api/users');\n// data() → User[] | null\n// loading() → boolean\n// error() → Error | null\n```\n\n---\n\n### `useWebSocket`\n\nReactive WebSocket with auto-reconnect.\n\n```ts\nimport { useWebSocket } from '@ariefsn/svelte-use';\n\nconst ws = useWebSocket('wss://echo.example.com');\nws.send('hello');\nws.data(); // → last received message\nws.status(); // → 'OPEN' | 'CLOSED' | 'CONNECTING'\n```\n\n---\n\n### `useAnimate`\n\nReactive Web Animations API wrapper.\n\n```ts\nimport { useAnimate } from '@ariefsn/svelte-use';\n\nconst { animate, stop } = useAnimate(() => el);\nanimate([{ opacity: 0 }, { opacity: 1 }], { duration: 300 });\n```\n\n---\n\n### `useParallax`\n\nParallax effect based on pointer position or device tilt.\n\n```ts\nimport { useParallax } from '@ariefsn/svelte-use';\n\nconst { tilt, roll } = useParallax(() => containerEl);\n// tilt() → number  (−0.5 to 0.5)\n// roll() → number  (−0.5 to 0.5)\n```\n\n---\n\n### `useTransition`\n\nAnimated numeric transitions with easing.\n\n```ts\nimport { useTransition } from '@ariefsn/svelte-use';\n\nlet target = $state(0);\nconst animated = useTransition(() => target, { duration: 500 });\n// animated() smoothly interpolates to target\n```\n\n---\n\n### `useInterval`\n\nReactive interval counter.\n\n```ts\nimport { useInterval } from '@ariefsn/svelte-use';\n\nconst { counter, pause, resume } = useInterval(1000);\ncounter(); // → increments every second\n```\n\n---\n\n### `useNow`\n\nReactive current `Date`.\n\n```ts\nimport { useNow } from '@ariefsn/svelte-use';\n\nconst now = useNow();\nnow(); // → Date (updated every second by default)\n```\n\n---\n\n### `useTimestamp`\n\nReactive current timestamp in milliseconds.\n\n```ts\nimport { useTimestamp } from '@ariefsn/svelte-use';\n\nconst ts = useTimestamp();\nts(); // → number (ms since epoch)\n```\n\n---\n\n### `useBreakpoints`\n\nReactive responsive breakpoints.\n\n```ts\nimport { useBreakpoints } from '@ariefsn/svelte-use';\n\nconst bp = useBreakpoints({ sm: 640, md: 768, lg: 1024 });\nbp.lg(); // → true if viewport ≥ 1024px\nbp.between('sm', 'lg')(); // → boolean\n```\n\n---\n\n### `useClipboard`\n\nReactive clipboard read/write.\n\n```ts\nimport { useClipboard } from '@ariefsn/svelte-use';\n\nconst { text, copy, copied } = useClipboard();\ncopy('Hello!');\ncopied(); // → true for 1.5s after copy\n```\n\n---\n\n### `useBattery`\n\nReactive Battery Status API.\n\n```ts\nimport { useBattery } from '@ariefsn/svelte-use';\n\nconst battery = useBattery();\nbattery.level(); // → 0–1\nbattery.charging(); // → boolean\n```\n\n---\n\n### `useVirtualList`\n\nEfficient virtual list rendering for large datasets.\n\n```ts\nimport { useVirtualList } from '@ariefsn/svelte-use';\n\nconst { list, containerProps, wrapperProps } = useVirtualList(items, { itemHeight: 40 });\n// list() → only the visible slice of items\n```\n\n---\n\n## Developing\n\n```sh\nbun install\nbun run dev\n```\n\nTo run tests:\n\n```sh\nbun run test\n```\n\n## Building & Publishing\n\n```sh\n# build the library\nbun run build\n\n# publish to npm\nnpm publish --access public\n```\n\n## Links\n\n- 📦 **npm**: https://www.npmjs.com/package/@ariefsn/svelte-use\n- 🐙 **GitHub**: https://github.com/ariefsn/svelte-use\n\n## Star History\n\n<p align=\"center\">\n  <a href=\"https://star-history.dera.page/#ariefsn/svelte-use\">\n    <img src=\"https://star-history.dera.page/svg?repos=ariefsn/svelte-use\" alt=\"Star History Chart\" width=\"800\" />\n  </a>\n</p>\n\n## License\n\n[MIT](./LICENSE.md)\n","readmeFilename":"README.md"}