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

@studio-lumio/hooks

v0.1.46

Published

a compilation of react hooks we use to make our magic

Readme

HOOKS

@studio-lumio/hooks

A comprehensive collection of React hooks used at Studio Lumio to enhance development workflow and productivity.

🚩 Note: The API may be changed without prior notice.

Installation

# Using npm
npm install @studio-lumio/hooks

# Using yarn
yarn add @studio-lumio/hooks

# Using pnpm
pnpm add @studio-lumio/hooks

Table of Contents


DOM & Browser Hooks

useDebug

Returns true if #debug is present in the URL.

const debug = useDebug()

useDocumentReadyState

Returns true if the document is ready.

const ready = useDocumentReadyState()

useDocumentTitle

Dynamically sets the document title.

useDocumentTitle('My Page Title')

useFavicon

Dynamically sets the favicon URL.

useFavicon('https://example.com/favicon.ico')

useIsClient

Returns true if running in a client environment (window is defined).

const isClient = useIsClient()

useIsTouchDevice

Returns true if the client is using a touch-capable device.

const isTouch = useIsTouchDevice()

useScript

Dynamically loads an external script.

useScript('https://example.com/script.js')

useOrientation

Returns the current device orientation.

const orientation = useOrientation()

usePageLeave

Triggers a callback when the user's cursor leaves the page.

usePageLeave(() => {
  console.log('User left the page')
})

usePageVisibility

Returns true when the page is visible, false when the user switches to a different tab or window.

const isVisible = usePageVisibility()

useEffect(() => {
  if (!isVisible) {
    console.log('User switched away from this tab')
  }
}, [isVisible])

useIdle

Detects when the user has been idle for a specified duration (default: 1 minute).

const idle = useIdle(5000) // 5 seconds

useIOSToolbarState

Detects whether the iOS Safari toolbar is visible.

const { isVisible } = useIOSToolbarState()

useFoucFix

Temporary fix for Flash of Unstyled Content (FOUC) bug from Next.js.

useFoucFix()

Event Hooks

useOnClickOutside

Triggers a callback when the user clicks outside a referenced element.

const ref = useRef()
useOnClickOutside(ref, () => console.log('Clicked outside'))

useEventListener

Attaches an event listener to a target (window, document, or element).

const elRef = useRef < HTMLElement > null
const documentRef = useRef < Document > document

// Window event
useEventListener('scroll', () => console.log('Scrolled'))

// Document event
useEventListener('visibilitychange', () => console.log('Visibility changed'), documentRef)

// Element event
useEventListener('click', () => console.log('Element clicked'), elRef)

useHover

Detects hover state on an element.

const [ref, hovering] = useHover()

return <div ref={ref}>IsHovering? {hovering ? 'Yes' : 'No'}</div>

useKeySequence

Executes a callback when a specific key sequence is typed.

useKeySequence({
  sequence: 'lumio',
  callback: () => console.log('Secret code entered!'),
})

State Management Hooks

useCopyToClipboard

Provides a method to copy text to the clipboard and tracks the copied value.

const [value, copy] = useCopyToClipboard()

const handleClick = () => {
  copy('Text to copy', () => console.log('Copied!'))
}

useCookie

Manages browser cookies with get, update, and delete functionality.

const [value, updateCookie, deleteCookie] = useCookie('myCookie')

useList

Provides advanced array state management with helper methods.

const [list, { set, push, removeAt, insertAt, updateAt, clear }] = useList(['one', 'two', 'three'])

// Available methods
set(['new', 'array'])
push('four')
removeAt(1)
insertAt(1, 'inserted')
updateAt(1, 'updated')
clear()

useLazyState

Lazy state management with a callback on state updates.

Parameters:

  • initialValue: Initial state value
  • callback: Function called on state change (newValue, oldValue) => void

Returns:

  • get: Function to get current state
  • set: Function to set state
const [getState, setState] = useLazyState(0, (newValue, oldValue) => {
  console.log(`State changed from ${oldValue} to ${newValue}`)
})

setState(1)
const currentState = getState()

Performance Hooks

useDebounce

Debounces a value to prevent excessive re-renders.

const [value, setValue] = useState('')
const debouncedValue = useDebounce(value, 500)

useDebounceFn

Debounces a function execution.

const debouncedFn = useDebounceFn(() => {
  console.log('This function is debounced!')
}, 500)

useThrottle

Throttles value updates to prevent excessive re-renders.

const throttledValue = useThrottle(value, 200)

useFrame

Runs a callback on every animation frame.

useFrame(() => {
  // Runs on every frame
})

useTimeout

Executes a callback after a specified delay.

useTimeout(() => console.log('Executed after 1 second'), 1000)

useInterval

Creates and manages intervals.

useInterval(() => {
  setCount(count + 1)
}, 1000)
// Pass null as delay to stop the interval

Lifecycle Hooks

useEffectOnce

Executes an effect only once on component mount.

useEffectOnce(() => {
  console.log('Triggered only on mount')
})

useUpdateEffect

Like useEffect, but skips the first invocation (on mount).

useUpdateEffect(() => {
  console.log('Skips on mount', data)
}, [data])

useUnmount

Runs a function when the component unmounts.

useUnmount(() => console.log('Component unmounted'))

useIsMounted

Returns a callback that returns true if the component is mounted.

const isMounted = useIsMounted()

useFirstMountState

Returns true if the component is on its first mount.

const isFirstMount = useFirstMountState()

useIsomorphicLayoutEffect

Identical to useEffect, but fires synchronously after all DOM mutations (uses useLayoutEffect on client, useEffect on server).

useIsomorphicLayoutEffect(() => {
  // Synchronous after DOM mutations
}, [])

Utility Hooks

useSlots

Extracts children of specified component types from a component's children.

Parameters:

  • types: Array of component types to extract (default: [])
  • children: Children to extract from (default: [])

Returns:

  • Array of children of the specified component types
const Header = ({ children }) => <header>{children}</header>
const Footer = ({ children }) => <footer>{children}</footer>

const MyComponent = ({ children }) => {
  const [headerContent, footerContent] = useSlots([Header, Footer], children)

  return (
    <div>
      <div className="header-content">{headerContent || 'Default Header Content'}</div>
      <div className="footer-content">{footerContent || 'Default Footer Content'}</div>
    </div>
  )
}

const App = () => (
  <MyComponent>
    <Header>My Header</Header>
    <Footer>My Footer</Footer>
  </MyComponent>
)

Viewport & Layout Hooks

useMediaQuery

CSS-like media query support in JavaScript.

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

useWindowSize

Returns current window dimensions.

const { width, height } = useWindowSize()

useRealViewport

Sets CSS variables for accurate viewport units across different browsers.

CSS Variables:

  • --vw: Viewport width
  • --dvh: Dynamic viewport height
  • --svh: Small viewport height
  • --lvh: Logical viewport height (1vh)
const App = () => {
  useRealViewport()
  return <YourComponent />
}

useRect

Gets the getBoundingClientRect() values of an element.

const { top, bottom, left, right, width, height } = useRect(elRef)

useObjectFit

Calculates scale factors for CSS object-fit behavior.

const [scaleX, scaleY] = useObjectFit(parentWidth, parentHeight, childWidth, childHeight, 'cover')

useIsVisible

Returns true if a referenced element is in the viewport.

Parameters:

  • threshold: Visibility threshold (0 to 1)
  • once: Disconnect observer after first intersection
  • rootMargin: Margin around the root
  • root: Viewport for checking visibility
const { ref, inView } = useIsVisible({
  threshold: 0.5,
  once: true,
  rootMargin: '0px',
  root: null,
})

useIntersectionObserver

Observes element visibility using the IntersectionObserver API.

Parameters:

  • root: Viewport for checking visibility (default: null)
  • rootMargin: Margin around the root (default: '0px')
  • threshold: Visibility threshold 0-1 (default: 0)
  • once: Disconnect after first intersection (default: false)
  • lazy: Update state lazily (default: false)
  • callback: Function called on visibility change

Returns:

  • [setElement, entry]: Ref setter and IntersectionObserver entry
const [setElement, entry] = useIntersectionObserver({
  threshold: 0.5,
  callback: (entry) => {
    console.log('Visibility changed:', entry)
  },
})

return <div ref={setElement}>Observe me</div>

useResizeObserver

Observes element dimensions using ResizeObserver, with optional debouncing and lazy state updates.

Parameters:

  • lazy: If true, returns a getter for the current entry instead of state (default: false)
  • debounce: Delay in ms between resize events (default: 500)
  • box: Box model to observe - 'border-box' or 'content-box' (default: 'border-box')
  • callback: Called on resize with ResizeObserverEntry (default: () => {})

Returns:

  • [setElement, entry]: Ref setter and ResizeObserver entry
const [setElement, entry] = useResizeObserver({
  debounce: 300,
  callback: (entry) => {
    console.log('Resized:', entry)
  },
})

useEffect(() => {
  if (entry) {
    console.log('Current entry:', entry)
  }
}, [entry])

return (
  <div ref={setElement} style={{ resize: 'both', overflow: 'auto', width: 200, height: 200 }}>
    Resize me!
  </div>
)

Storage Hooks

useLocalStorage

Manages localStorage with a useState-like API.

Returns:

  • [value, setValue, removeValue]
const [value, setValue, removeValue] = useLocalStorage('myKey', [])

useSessionStorage

Manages sessionStorage with a useState-like API.

const [value, setValue, removeValue] = useSessionStorage('myKey', [])

Authors

License

MIT (c) Studio Lumio.