{"_id":"@booga/vhooks","name":"@booga/vhooks","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@booga/vhooks","version":"0.1.0","description":"React hooks for state and UI mechanics. Viewport, breakpoints, media queries, gestures, controlled/uncontrolled bridges, persistent state. Composable, SSR-safe, dependency-free beyond React.","type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./useSafeLayoutEffect":{"types":"./dist/useSafeLayoutEffect.d.ts","import":"./dist/useSafeLayoutEffect.js","require":"./dist/useSafeLayoutEffect.cjs"},"./useMediaQuery":{"types":"./dist/useMediaQuery.d.ts","import":"./dist/useMediaQuery.js","require":"./dist/useMediaQuery.cjs"},"./useBreakpoint":{"types":"./dist/useBreakpoint.d.ts","import":"./dist/useBreakpoint.js","require":"./dist/useBreakpoint.cjs"},"./useViewport":{"types":"./dist/useViewport.d.ts","import":"./dist/useViewport.js","require":"./dist/useViewport.cjs"},"./useIntersection":{"types":"./dist/useIntersection.d.ts","import":"./dist/useIntersection.js","require":"./dist/useIntersection.cjs"},"./useResizeObserver":{"types":"./dist/useResizeObserver.d.ts","import":"./dist/useResizeObserver.js","require":"./dist/useResizeObserver.cjs"},"./useDebouncedValue":{"types":"./dist/useDebouncedValue.d.ts","import":"./dist/useDebouncedValue.js","require":"./dist/useDebouncedValue.cjs"},"./useThrottledValue":{"types":"./dist/useThrottledValue.d.ts","import":"./dist/useThrottledValue.js","require":"./dist/useThrottledValue.cjs"},"./useControllableState":{"types":"./dist/useControllableState.d.ts","import":"./dist/useControllableState.js","require":"./dist/useControllableState.cjs"},"./useLocalStorage":{"types":"./dist/useLocalStorage.d.ts","import":"./dist/useLocalStorage.js","require":"./dist/useLocalStorage.cjs"},"./useEventListener":{"types":"./dist/useEventListener.d.ts","import":"./dist/useEventListener.js","require":"./dist/useEventListener.cjs"},"./useKeyPress":{"types":"./dist/useKeyPress.d.ts","import":"./dist/useKeyPress.js","require":"./dist/useKeyPress.cjs"},"./useClickOutside":{"types":"./dist/useClickOutside.d.ts","import":"./dist/useClickOutside.js","require":"./dist/useClickOutside.cjs"},"./useFocusTrap":{"types":"./dist/useFocusTrap.d.ts","import":"./dist/useFocusTrap.js","require":"./dist/useFocusTrap.cjs"}},"sideEffects":false,"scripts":{"build":"tsup","typecheck":"tsc --noEmit","lint":"eslint src tests --ext .ts,.tsx","test":"vitest run --coverage","test:watch":"vitest"},"peerDependencies":{"react":"^18.0.0"},"devDependencies":{"@testing-library/react":"^14.0.0","@types/node":"^25.6.2","@types/react":"^18.0.0","@typescript-eslint/eslint-plugin":"^7.0.0","@typescript-eslint/parser":"^7.0.0","@vitest/coverage-v8":"^1.0.0","eslint":"^8.0.0","jsdom":"^24.0.0","react":"^18.0.0","react-dom":"^18.0.0","tsup":"^8.0.0","typescript":"^5.0.0","vitest":"^1.0.0"},"_id":"@booga/vhooks@0.1.0","gitHead":"f25b5f44bca1c55f72db3204d4f2994cf16d3c52","_nodeVersion":"22.19.0","_npmVersion":"10.9.3","dist":{"integrity":"sha512-vCskDaf1itqoxOsnb7ketvFAmycNUBFSIkL4efYNvdhhUoc4noXpEUQb0vLs2gQf/6IZ3BsmlXaELAst6YZfRg==","shasum":"9e844db814ed75abf532592f26e012b37393da2f","tarball":"https://registry.npmjs.org/@booga/vhooks/-/vhooks-0.1.0.tgz","fileCount":159,"unpackedSize":120142,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIG2uCacgDVpDEcbBaSOPC/geo+YmmC6y9ZhUSUuD+yW5AiBd9ojIGHYm1jZgH5ES7Bu/sql0T1QuCzVO9QrmES8X8g=="}]},"_npmUser":{"name":"dreaktor","email":"me@dreaktor.com"},"directories":{},"maintainers":[{"name":"dreaktor","email":"me@dreaktor.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/vhooks_0.1.0_1778493108427_0.9634953604384169"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-11T09:51:48.340Z","0.1.0":"2026-05-11T09:51:48.596Z","modified":"2026-05-11T09:51:48.819Z"},"maintainers":[{"name":"dreaktor","email":"me@dreaktor.com"}],"description":"React hooks for state and UI mechanics. Viewport, breakpoints, media queries, gestures, controlled/uncontrolled bridges, persistent state. Composable, SSR-safe, dependency-free beyond React.","readme":"# vHooks\n\nReact hooks for state and UI mechanics. Viewport observation, breakpoint detection, media queries, gesture primitives, controlled/uncontrolled bridges, persistent state. One hook per concern, composable, dependency-free beyond React 18.\n\n## Hooks\n\n| Hook | Returns |\n|------|---------|\n| `useMediaQuery(q)` | `boolean` — tracks `window.matchMedia(q)`, SSR-safe |\n| `useBreakpoint()` | `\"sm\" \\| \"md\" \\| \"lg\" \\| \"xl\" \\| \"2xl\"` — vTheme breakpoint resolution |\n| `useViewport()` | `{ width, height }` — resize-observed window dimensions |\n| `useIntersection(ref, opts?)` | `IntersectionObserverEntry \\| null` |\n| `useResizeObserver(ref)` | `{ width, height }` — element box size |\n| `useDebouncedValue(v, ms)` | `T` — deferred by ms after last change |\n| `useThrottledValue(v, ms)` | `T` — leading + trailing throttle |\n| `useControllableState({ prop, defaultProp, onChange })` | `[T \\| undefined, SetFn<T>]` — Radix-pattern bridge |\n| `useLocalStorage(key, initial)` | `[T, (v: T) => void]` — persisted, namespaced `v:key` |\n| `useEventListener(target, event, handler, opts?)` | `void` — attaches with cleanup |\n| `useKeyPress(combo, handler)` | `void` — e.g. `\"ctrl+k\"`, `\"shift+enter\"` |\n| `useClickOutside(ref, handler)` | `void` — mousedown + touchstart |\n| `useFocusTrap(ref, active)` | `void` — traps Tab focus, restores on deactivate |\n| `useSafeLayoutEffect` | `useLayoutEffect` on client, `useEffect` on server |\n\n## Install\n\n```sh\nnpm install @booga/vhooks\n```\n\nPeer dependency: `react ^18`.\n\n## Usage\n\n```ts\nimport { useBreakpoint, useLocalStorage, useControllableState } from \"@booga/vhooks\";\n\nconst bp = useBreakpoint(); // \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\"\n\nconst [theme, setTheme] = useLocalStorage(\"theme\", \"light\");\n\nconst [open, setOpen] = useControllableState({\n  prop: controlledOpen,\n  defaultProp: false,\n  onChange: onOpenChange,\n});\n```\n\n## SSR\n\nAll hooks guard browser API access — safe to import in Node/SSR environments. Server returns sensible defaults: `false`, `{ width: 0, height: 0 }`, `null`.\n\n## Code of conduct\n\n[Contributor Covenant 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct/)\n\n## License\n\nMIT © 2026 bvasilenko\n","readmeFilename":"README.md","_rev":"1-2f84df498856c94a6e279b0cfa94f576"}