npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@vitus-labs/hooks

v2.6.1

Published

Universal styles

Readme

@vitus-labs/hooks

28 React hooks for UI interactions, state management, DOM observation, accessibility, and theming. 2.15KB gzipped.

npm license

Installation

npm install @vitus-labs/hooks

Hooks

Primitives

useLatest

Returns a ref that always holds the latest value. Avoids stale closures in callbacks and effects.

const ref = useLatest(callback)
// ref.current is always the latest callback

useToggle

Boolean state with toggle, setTrue, and setFalse helpers.

const [isOpen, toggle, open, close] = useToggle(false)

usePrevious

Returns the value from the previous render.

const prev = usePrevious(count)
// undefined on first render, then the previous value

Callbacks

useDebouncedCallback

Stable debounced function with .cancel() and .flush().

const search = useDebouncedCallback((query: string) => {
  fetchResults(query)
}, 300)

search('hello') // fires after 300ms of inactivity
search.cancel()  // cancel pending
search.flush()   // fire immediately

useThrottledCallback

Stable throttled function with .cancel(). Uses throttle from @vitus-labs/core.

const handleScroll = useThrottledCallback(() => {
  updatePosition()
}, 100)

State

useDebouncedValue

Returns a debounced version of the value that only updates after delay ms of inactivity.

const [search, setSearch] = useState('')
const debouncedSearch = useDebouncedValue(search, 300)

useControllableState

Unified controlled/uncontrolled state pattern.

const [value, setValue] = useControllableState({
  value: props.value,       // controlled (optional)
  defaultValue: '',         // uncontrolled fallback
  onChange: props.onChange,  // fires in both modes
})

Effects

useUpdateEffect

Like useEffect but skips the initial mount.

useUpdateEffect(() => {
  // only fires on updates, not on mount
  saveToStorage(value)
}, [value])

useIsomorphicLayoutEffect

useLayoutEffect on the client, useEffect on the server. Avoids SSR warnings.

useIsomorphicLayoutEffect(() => {
  measureElement()
}, [])

useInterval

Declarative setInterval with auto-cleanup. Pass null to pause.

useInterval(() => tick(), 1000)     // every second
useInterval(() => tick(), null)      // paused

useTimeout

Declarative setTimeout with reset and clear controls.

const { reset, clear } = useTimeout(() => {
  showNotification()
}, 5000)

DOM & Observers

useElementSize

Tracks element width and height via ResizeObserver.

const [ref, { width, height }] = useElementSize()
return <div ref={ref}>Size: {width}x{height}</div>

useIntersection

IntersectionObserver wrapper for visibility detection.

const [ref, entry] = useIntersection({ threshold: 0.5 })
const isVisible = entry?.isIntersecting
return <div ref={ref}>{isVisible ? 'Visible' : 'Hidden'}</div>

Interaction

useHover

Tracks hover state with stable callback references.

const { hover, onMouseEnter, onMouseLeave } = useHover()

useFocus

Tracks focus state with stable callback references.

const { focused, onFocus, onBlur } = useFocus()

useClickOutside

Calls handler when a click occurs outside the referenced element.

const ref = useRef<HTMLDivElement>(null)
useClickOutside(ref, () => setOpen(false))

useScrollLock

Locks page scroll by setting overflow: hidden on document.body.

useScrollLock(isModalOpen)

useKeyboard

Listens for a specific keyboard key.

useKeyboard('Escape', () => setOpen(false))

useFocusTrap

Traps Tab/Shift+Tab focus within a container. Essential for modals and dialogs.

const ref = useRef<HTMLDivElement>(null)
useFocusTrap(ref, isOpen)

Responsive

useMediaQuery

Subscribes to a CSS media query and returns whether it matches.

const isDesktop = useMediaQuery('(min-width: 1024px)')

useBreakpoint

Returns the currently active breakpoint name from the theme context.

const bp = useBreakpoint() // "xs" | "sm" | "md" | "lg" | "xl" | undefined

useColorScheme

Returns the user's preferred color scheme. Pairs with rocketstyle's mode.

const scheme = useColorScheme() // "light" | "dark"

useReducedMotion

Returns true when the user prefers reduced motion.

const reduced = useReducedMotion()
const duration = reduced ? 0 : 300

Theme & Styling

useThemeValue

Deep-reads a value from the current theme by dot-separated path.

const primary = useThemeValue<string>('colors.primary')
const columns = useThemeValue<number>('grid.columns')

useRootSize

Returns rootSize from the theme with px/rem conversion utilities.

const { rootSize, pxToRem, remToPx } = useRootSize()
pxToRem(32) // "2rem"
remToPx(2)  // 32

useSpacing

Returns a spacing function based on the theme's root size.

const spacing = useSpacing()
spacing(1)   // "8px"
spacing(2)   // "16px"
spacing(0.5) // "4px"

Composition

useMergedRef

Merges multiple refs (callback or object) into a single stable callback ref.

const Component = forwardRef((props, ref) => {
  const localRef = useRef(null)
  const merged = useMergedRef(ref, localRef)
  return <div ref={merged} />
})

Viewport

useWindowResize

Tracks viewport dimensions with throttled updates.

const { width, height } = useWindowResize({ throttleDelay: 300 })

Peer Dependencies

| Package | Version | | ------- | ------- | | react | >= 19 | | @vitus-labs/core | * |

License

MIT