@lacspace/hooks 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -112,12 +112,22 @@ function Share({ url }: { url: string }) {
112
112
 
113
113
  ## Licensing
114
114
 
115
- Free under the **[Lacspace Free Licence](https://lacspace.com/licenses/lacspace-free-1.0)** — MIT-equivalent freedoms. Use it in personal and commercial projects at no cost; just keep the notice. See the **[Lacspace Licence Centre](https://lacspace.com/licenses)**.
115
+ Free under the **[Lacspace Free Licence](https://lacspace.com/licenses/lacspace-free-1.0)** — permissive freedoms. Use it in personal and commercial projects at no cost; just keep the notice. See the **[Lacspace Licence Centre](https://lacspace.com/licenses)**.
116
+
117
+ <!-- LACSPACE-DEV-PLATFORM -->
116
118
 
117
119
  ---
118
120
 
119
- **Part of the Lacspace ecosystem — zero-dependency, isomorphic TypeScript packages.**
121
+ ## The Lacspace Developer Platform
122
+
123
+ `@lacspace/hooks` is part of **63 zero-dependency, isomorphic TypeScript packages** — one standard library for the modern web. Explore the ecosystem:
124
+
125
+ - 📦 **This package, documented** — https://developer.lacspace.com/packages/hooks
126
+ - 🗂️ **All 63 packages** — https://developer.lacspace.com/packages
127
+ - 🧭 **Developer handbook** — guides & runnable recipes — https://developer.lacspace.com/handbook
128
+ - 🧪 **Live playground** — run any package in your browser — https://developer.lacspace.com/playground
129
+ - 🖥️ **Finished app templates** — https://templates.lacspace.com
130
+ - 🚀 **Scaffold a full app** — `npm create lacspace-app@latest`
120
131
 
121
- [All packages ↗](https://lacspace.com/packages) · [npm org ](https://www.npmjs.com/org/lacspace) · [Licence Centre ↗](https://lacspace.com/licenses) · [GitHub ↗](https://github.com/lacspace/npm-packages)
132
+ Free under the **[Lacspace Free Licence](https://lacspace.com/licenses/lacspace-free-1.0)** a permissive, free-to-use licence.
122
133
 
123
- <div align="center"><sub>Built with care by <a href="https://lacspace.com">Lacspace</a> · Lacspace Free Licence · <a href="https://github.com/lacspace/npm-packages">source</a></sub></div>
package/dist/index.cjs CHANGED
@@ -277,7 +277,7 @@ function useHover() {
277
277
  node.removeEventListener("mouseenter", onEnter);
278
278
  node.removeEventListener("mouseleave", onLeave);
279
279
  };
280
- });
280
+ }, []);
281
281
  return [ref, hovered];
282
282
  }
283
283
  function useIntersectionObserver(options) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":["useLayoutEffect","useEffect","useRef","useCallback","useState"],"mappings":"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","file":"index.cjs","sourcesContent":["import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type DependencyList,\n type EffectCallback,\n type RefObject,\n} from \"react\";\n\nconst isBrowser = typeof window !== \"undefined\";\n\n/* -------------------------------------------------------------------------- */\n/* Lifecycle & effect helpers */\n/* -------------------------------------------------------------------------- */\n\n/**\n * `useLayoutEffect` on the client, `useEffect` on the server. Prevents the\n * \"useLayoutEffect does nothing on the server\" warning during SSR.\n *\n * @example\n * useIsomorphicLayoutEffect(() => { el.current?.focus(); }, []);\n */\nexport const useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : useEffect;\n\n/**\n * Returns a stable getter that reports whether the component is still mounted.\n * Useful to guard async state updates.\n *\n * @example\n * const isMounted = useIsMounted();\n * fetchData().then((d) => { if (isMounted()) setData(d); });\n */\nexport function useIsMounted(): () => boolean {\n const mounted = useRef(false);\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n return useCallback(() => mounted.current, []);\n}\n\n/**\n * Runs an effect exactly once, on mount.\n *\n * @example\n * useMountEffect(() => console.log(\"mounted\"));\n */\nexport function useMountEffect(effect: EffectCallback): void {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useEffect(effect, []);\n}\n\n/**\n * Like `useEffect`, but skips the first (mount) run and only fires on updates.\n *\n * @example\n * useUpdateEffect(() => console.log(\"value changed\", value), [value]);\n */\nexport function useUpdateEffect(effect: EffectCallback, deps?: DependencyList): void {\n const isFirst = useRef(true);\n useEffect(() => {\n if (isFirst.current) {\n isFirst.current = false;\n return;\n }\n return effect();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps);\n}\n\n/**\n * Returns the value from the previous render (`undefined` on first render).\n *\n * @example\n * const prevCount = usePrevious(count);\n */\nexport function usePrevious<T>(value: T): T | undefined {\n const ref = useRef<T | undefined>(undefined);\n useEffect(() => {\n ref.current = value;\n }, [value]);\n return ref.current;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Storage */\n/* -------------------------------------------------------------------------- */\n\ntype SetValue<T> = (value: T | ((prev: T) => T)) => void;\n\nfunction useStorage<T>(\n storageArea: \"localStorage\" | \"sessionStorage\",\n key: string,\n initialValue: T,\n): [T, SetValue<T>, () => void] {\n const readValue = useCallback((): T => {\n if (!isBrowser) return initialValue;\n try {\n const raw = window[storageArea].getItem(key);\n return raw === null ? initialValue : (JSON.parse(raw) as T);\n } catch {\n return initialValue;\n }\n }, [initialValue, key, storageArea]);\n\n const [storedValue, setStoredValue] = useState<T>(initialValue);\n\n // Hydrate from storage after mount (keeps server & first client render in sync).\n useEffect(() => {\n setStoredValue(readValue());\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [key]);\n\n const setValue = useCallback<SetValue<T>>(\n (value) => {\n setStoredValue((prev) => {\n const next = value instanceof Function ? value(prev) : value;\n if (isBrowser) {\n try {\n window[storageArea].setItem(key, JSON.stringify(next));\n window.dispatchEvent(\n new StorageEvent(\"storage\", { key, newValue: JSON.stringify(next) }),\n );\n } catch {\n /* ignore write errors (quota, private mode, etc.) */\n }\n }\n return next;\n });\n },\n [key, storageArea],\n );\n\n const remove = useCallback(() => {\n if (isBrowser) {\n try {\n window[storageArea].removeItem(key);\n window.dispatchEvent(new StorageEvent(\"storage\", { key, newValue: null }));\n } catch {\n /* ignore */\n }\n }\n setStoredValue(initialValue);\n }, [initialValue, key, storageArea]);\n\n // Sync across tabs / other hook instances.\n useEffect(() => {\n if (!isBrowser) return;\n const onStorage = (e: StorageEvent) => {\n if (e.key !== null && e.key !== key) return;\n setStoredValue(readValue());\n };\n window.addEventListener(\"storage\", onStorage);\n return () => window.removeEventListener(\"storage\", onStorage);\n }, [key, readValue]);\n\n return [storedValue, setValue, remove];\n}\n\n/**\n * Persistent state backed by `localStorage`, JSON-serialized and SSR-safe.\n * Returns the initial value on the server, hydrates on mount, syncs across tabs,\n * and `remove()` clears the key.\n *\n * @example\n * const [theme, setTheme, clearTheme] = useLocalStorage(\"theme\", \"light\");\n */\nexport function useLocalStorage<T>(\n key: string,\n initialValue: T,\n): [T, SetValue<T>, () => void] {\n return useStorage(\"localStorage\", key, initialValue);\n}\n\n/**\n * Same contract as {@link useLocalStorage}, backed by `sessionStorage`.\n *\n * @example\n * const [draft, setDraft, clearDraft] = useSessionStorage(\"draft\", \"\");\n */\nexport function useSessionStorage<T>(\n key: string,\n initialValue: T,\n): [T, SetValue<T>, () => void] {\n return useStorage(\"sessionStorage\", key, initialValue);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Timing: debounce / throttle / interval / timeout */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Returns a debounced copy of `value` that only updates after `delayMs` of quiet.\n *\n * @example\n * const debounced = useDebounce(query, 300);\n */\nexport function useDebounce<T>(value: T, delayMs: number): T {\n const [debounced, setDebounced] = useState<T>(value);\n useEffect(() => {\n const id = setTimeout(() => setDebounced(value), delayMs);\n return () => clearTimeout(id);\n }, [value, delayMs]);\n return debounced;\n}\n\n/**\n * Returns a debounced callback. The returned function is stable and carries a\n * `.cancel()` method to drop any pending invocation.\n *\n * @example\n * const save = useDebouncedCallback((v: string) => api.save(v), 500);\n */\nexport function useDebouncedCallback<A extends unknown[]>(\n fn: (...args: A) => void,\n delayMs: number,\n): ((...args: A) => void) & { cancel: () => void } {\n const fnRef = useRef(fn);\n useIsomorphicLayoutEffect(() => {\n fnRef.current = fn;\n }, [fn]);\n\n const timeout = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const cancel = useCallback(() => {\n if (timeout.current !== null) {\n clearTimeout(timeout.current);\n timeout.current = null;\n }\n }, []);\n\n useEffect(() => cancel, [cancel]);\n\n const debounced = useCallback(\n (...args: A) => {\n if (timeout.current !== null) clearTimeout(timeout.current);\n timeout.current = setTimeout(() => {\n timeout.current = null;\n fnRef.current(...args);\n }, delayMs);\n },\n [delayMs],\n ) as ((...args: A) => void) & { cancel: () => void };\n\n debounced.cancel = cancel;\n return debounced;\n}\n\n/**\n * Returns a throttled copy of `value` that updates at most once per `ms`.\n *\n * @example\n * const throttled = useThrottle(scrollY, 100);\n */\nexport function useThrottle<T>(value: T, ms: number): T {\n const [throttled, setThrottled] = useState<T>(value);\n const lastRan = useRef<number>(isBrowser ? Date.now() : 0);\n\n useEffect(() => {\n const remaining = ms - (Date.now() - lastRan.current);\n if (remaining <= 0) {\n setThrottled(value);\n lastRan.current = Date.now();\n return;\n }\n const id = setTimeout(() => {\n setThrottled(value);\n lastRan.current = Date.now();\n }, remaining);\n return () => clearTimeout(id);\n }, [value, ms]);\n\n return throttled;\n}\n\n/**\n * Runs `callback` every `delayMs`. Pass `null` to pause. Uses a latest-ref so\n * the callback never goes stale.\n *\n * @example\n * useInterval(() => tick(), running ? 1000 : null);\n */\nexport function useInterval(callback: () => void, delayMs: number | null): void {\n const saved = useRef(callback);\n useIsomorphicLayoutEffect(() => {\n saved.current = callback;\n }, [callback]);\n\n useEffect(() => {\n if (delayMs === null) return;\n const id = setInterval(() => saved.current(), delayMs);\n return () => clearInterval(id);\n }, [delayMs]);\n}\n\n/**\n * Runs `callback` once after `delayMs`. Pass `null` to cancel/disable.\n *\n * @example\n * useTimeout(() => setVisible(false), 3000);\n */\nexport function useTimeout(callback: () => void, delayMs: number | null): void {\n const saved = useRef(callback);\n useIsomorphicLayoutEffect(() => {\n saved.current = callback;\n }, [callback]);\n\n useEffect(() => {\n if (delayMs === null) return;\n const id = setTimeout(() => saved.current(), delayMs);\n return () => clearTimeout(id);\n }, [delayMs]);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Simple state helpers */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Boolean state with convenient controls.\n *\n * @example\n * const [on, { toggle, off }] = useToggle();\n */\nexport function useToggle(\n initial = false,\n): [boolean, { toggle: () => void; on: () => void; off: () => void; set: (v: boolean) => void }] {\n const [value, setValue] = useState(initial);\n const toggle = useCallback(() => setValue((v) => !v), []);\n const on = useCallback(() => setValue(true), []);\n const off = useCallback(() => setValue(false), []);\n const set = useCallback((v: boolean) => setValue(v), []);\n return [value, { toggle, on, off, set }];\n}\n\n/**\n * Numeric counter with increment/decrement/set/reset controls.\n *\n * @example\n * const { count, inc, dec, reset } = useCounter(0);\n */\nexport function useCounter(initial = 0): {\n count: number;\n inc: (step?: number) => void;\n dec: (step?: number) => void;\n set: (n: number) => void;\n reset: () => void;\n} {\n const [count, setCount] = useState(initial);\n const inc = useCallback((step = 1) => setCount((c) => c + step), []);\n const dec = useCallback((step = 1) => setCount((c) => c - step), []);\n const set = useCallback((n: number) => setCount(n), []);\n const reset = useCallback(() => setCount(initial), [initial]);\n return { count, inc, dec, set, reset };\n}\n\n/**\n * Open/close state, ideal for modals, drawers and menus.\n *\n * @example\n * const { isOpen, open, close } = useDisclosure();\n */\nexport function useDisclosure(initial = false): {\n isOpen: boolean;\n open: () => void;\n close: () => void;\n toggle: () => void;\n} {\n const [isOpen, setOpen] = useState(initial);\n const open = useCallback(() => setOpen(true), []);\n const close = useCallback(() => setOpen(false), []);\n const toggle = useCallback(() => setOpen((v) => !v), []);\n return { isOpen, open, close, toggle };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Browser / DOM environment */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Tracks a CSS media query. SSR-safe: returns `false` on the server, then the\n * real match after mount.\n *\n * @example\n * const isDark = useMediaQuery(\"(prefers-color-scheme: dark)\");\n */\nexport function useMediaQuery(query: string): boolean {\n const [matches, setMatches] = useState(false);\n\n useEffect(() => {\n if (!isBrowser || typeof window.matchMedia !== \"function\") return;\n const mql = window.matchMedia(query);\n const onChange = () => setMatches(mql.matches);\n onChange();\n mql.addEventListener(\"change\", onChange);\n return () => mql.removeEventListener(\"change\", onChange);\n }, [query]);\n\n return matches;\n}\n\n/**\n * Current viewport size. SSR-safe: returns `{ width: 0, height: 0 }` on server.\n *\n * @example\n * const { width } = useWindowSize();\n */\nexport function useWindowSize(): { width: number; height: number } {\n const [size, setSize] = useState<{ width: number; height: number }>({\n width: 0,\n height: 0,\n });\n\n useEffect(() => {\n if (!isBrowser) return;\n const onResize = () =>\n setSize({ width: window.innerWidth, height: window.innerHeight });\n onResize();\n window.addEventListener(\"resize\", onResize);\n return () => window.removeEventListener(\"resize\", onResize);\n }, []);\n\n return size;\n}\n\n/**\n * Current window scroll position. SSR-safe: `{ x: 0, y: 0 }` on server.\n *\n * @example\n * const { y } = useScrollPosition();\n */\nexport function useScrollPosition(): { x: number; y: number } {\n const [pos, setPos] = useState<{ x: number; y: number }>({ x: 0, y: 0 });\n\n useEffect(() => {\n if (!isBrowser) return;\n const onScroll = () => setPos({ x: window.scrollX, y: window.scrollY });\n onScroll();\n window.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => window.removeEventListener(\"scroll\", onScroll);\n }, []);\n\n return pos;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Event listener (overloaded) */\n/* -------------------------------------------------------------------------- */\n\n/** Attach a `window` event listener. */\nexport function useEventListener<K extends keyof WindowEventMap>(\n type: K,\n handler: (event: WindowEventMap[K]) => void,\n element?: undefined,\n options?: boolean | AddEventListenerOptions,\n): void;\n/** Attach a `document` event listener. */\nexport function useEventListener<K extends keyof DocumentEventMap>(\n type: K,\n handler: (event: DocumentEventMap[K]) => void,\n element: RefObject<Document | null> | Document,\n options?: boolean | AddEventListenerOptions,\n): void;\n/** Attach an event listener to an element referenced by a ref. */\nexport function useEventListener<\n K extends keyof HTMLElementEventMap,\n T extends HTMLElement,\n>(\n type: K,\n handler: (event: HTMLElementEventMap[K]) => void,\n element: RefObject<T | null> | T,\n options?: boolean | AddEventListenerOptions,\n): void;\n/**\n * Adds an event listener to `window` (default), `document`, or a ref/element,\n * using a latest-ref so the handler never goes stale.\n *\n * @example\n * useEventListener(\"keydown\", (e) => e.key === \"Escape\" && close());\n */\nexport function useEventListener(\n type: string,\n handler: (event: Event) => void,\n element?: RefObject<EventTarget | null> | EventTarget,\n options?: boolean | AddEventListenerOptions,\n): void {\n const savedHandler = useRef(handler);\n useIsomorphicLayoutEffect(() => {\n savedHandler.current = handler;\n }, [handler]);\n\n useEffect(() => {\n if (!isBrowser) return;\n const target: EventTarget | null =\n element == null\n ? window\n : \"current\" in element\n ? element.current\n : element;\n if (target == null || typeof target.addEventListener !== \"function\") return;\n\n const listener = (event: Event) => savedHandler.current(event);\n target.addEventListener(type, listener, options);\n return () => target.removeEventListener(type, listener, options);\n }, [type, element, options]);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Element interactions */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Calls `handler` when a pointer event occurs outside the referenced element.\n *\n * @example\n * useOnClickOutside(ref, () => setOpen(false));\n */\nexport function useOnClickOutside<T extends HTMLElement>(\n ref: RefObject<T | null>,\n handler: (event: MouseEvent | TouchEvent) => void,\n): void {\n const savedHandler = useRef(handler);\n useIsomorphicLayoutEffect(() => {\n savedHandler.current = handler;\n }, [handler]);\n\n useEffect(() => {\n if (!isBrowser) return;\n const listener = (event: MouseEvent | TouchEvent) => {\n const el = ref.current;\n const target = event.target as Node | null;\n if (el == null || target == null || el.contains(target)) return;\n savedHandler.current(event);\n };\n document.addEventListener(\"mousedown\", listener);\n document.addEventListener(\"touchstart\", listener, { passive: true });\n return () => {\n document.removeEventListener(\"mousedown\", listener);\n document.removeEventListener(\"touchstart\", listener);\n };\n }, [ref]);\n}\n\n/**\n * Tracks hover state of an element. Returns a ref to attach and the boolean.\n *\n * @example\n * const [ref, hovered] = useHover<HTMLButtonElement>();\n */\nexport function useHover<T extends HTMLElement>(): [RefObject<T | null>, boolean] {\n const ref = useRef<T | null>(null);\n const [hovered, setHovered] = useState(false);\n\n useEffect(() => {\n const node = ref.current;\n if (node == null) return;\n const onEnter = () => setHovered(true);\n const onLeave = () => setHovered(false);\n node.addEventListener(\"mouseenter\", onEnter);\n node.addEventListener(\"mouseleave\", onLeave);\n return () => {\n node.removeEventListener(\"mouseenter\", onEnter);\n node.removeEventListener(\"mouseleave\", onLeave);\n };\n });\n\n return [ref, hovered];\n}\n\n/**\n * Observes an element's intersection with the viewport. Returns the ref to\n * attach, a boolean `isIntersecting`, and the raw entry.\n *\n * @example\n * const [ref, visible] = useIntersectionObserver<HTMLDivElement>({ threshold: 0.5 });\n */\nexport function useIntersectionObserver<T extends Element>(\n options?: IntersectionObserverInit,\n): [RefObject<T | null>, boolean, IntersectionObserverEntry | null] {\n const ref = useRef<T | null>(null);\n const [entry, setEntry] = useState<IntersectionObserverEntry | null>(null);\n\n const { root, rootMargin, threshold } = options ?? {};\n\n useEffect(() => {\n const node = ref.current;\n if (!isBrowser || typeof IntersectionObserver !== \"function\" || node == null) {\n return;\n }\n const observer = new IntersectionObserver(\n (entries) => {\n const first = entries[0];\n if (first) setEntry(first);\n },\n { root, rootMargin, threshold },\n );\n observer.observe(node);\n return () => observer.disconnect();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [root, rootMargin, JSON.stringify(threshold)]);\n\n return [ref, entry?.isIntersecting ?? false, entry];\n}\n\n/**\n * Returns `true` while the given key is pressed.\n *\n * @example\n * const shiftHeld = useKeyPress(\"Shift\");\n */\nexport function useKeyPress(targetKey: string): boolean {\n const [pressed, setPressed] = useState(false);\n\n useEffect(() => {\n if (!isBrowser) return;\n const down = (e: KeyboardEvent) => {\n if (e.key === targetKey) setPressed(true);\n };\n const up = (e: KeyboardEvent) => {\n if (e.key === targetKey) setPressed(false);\n };\n window.addEventListener(\"keydown\", down);\n window.addEventListener(\"keyup\", up);\n return () => {\n window.removeEventListener(\"keydown\", down);\n window.removeEventListener(\"keyup\", up);\n };\n }, [targetKey]);\n\n return pressed;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Misc utilities */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Copies text to the clipboard. Returns the last-copied value and an async\n * `copy` function resolving to a success boolean. Falls back to `execCommand`.\n *\n * @example\n * const [copied, copy] = useCopyToClipboard();\n * await copy(\"hello\");\n */\nexport function useCopyToClipboard(): [string | null, (text: string) => Promise<boolean>] {\n const [copied, setCopied] = useState<string | null>(null);\n\n const copy = useCallback(async (text: string): Promise<boolean> => {\n if (!isBrowser) return false;\n try {\n if (navigator.clipboard && typeof navigator.clipboard.writeText === \"function\") {\n await navigator.clipboard.writeText(text);\n setCopied(text);\n return true;\n }\n } catch {\n /* fall through to legacy path */\n }\n try {\n const el = document.createElement(\"textarea\");\n el.value = text;\n el.setAttribute(\"readonly\", \"\");\n el.style.position = \"absolute\";\n el.style.left = \"-9999px\";\n document.body.appendChild(el);\n el.select();\n const ok = document.execCommand(\"copy\");\n document.body.removeChild(el);\n if (ok) {\n setCopied(text);\n return true;\n }\n } catch {\n /* ignore */\n }\n setCopied(null);\n return false;\n }, []);\n\n return [copied, copy];\n}\n\n/**\n * Sets `document.title` while mounted (no-op on the server).\n *\n * @example\n * useDocumentTitle(`Inbox (${unread})`);\n */\nexport function useDocumentTitle(title: string): void {\n useIsomorphicLayoutEffect(() => {\n if (!isBrowser) return;\n document.title = title;\n }, [title]);\n}\n\n/**\n * Tracks the browser's online/offline status. SSR-safe: `true` on the server.\n *\n * @example\n * const online = useOnlineStatus();\n */\nexport function useOnlineStatus(): boolean {\n const [online, setOnline] = useState(true);\n\n useEffect(() => {\n if (!isBrowser) return;\n const update = () => setOnline(navigator.onLine);\n update();\n window.addEventListener(\"online\", update);\n window.addEventListener(\"offline\", update);\n return () => {\n window.removeEventListener(\"online\", update);\n window.removeEventListener(\"offline\", update);\n };\n }, []);\n\n return online;\n}\n\n/**\n * Returns `true` after `ms` of no user activity (mouse, keyboard, touch, scroll).\n *\n * @example\n * const idle = useIdle(60_000);\n */\nexport function useIdle(ms: number): boolean {\n const [idle, setIdle] = useState(false);\n\n useEffect(() => {\n if (!isBrowser) return;\n let timer: ReturnType<typeof setTimeout>;\n const reset = () => {\n setIdle(false);\n clearTimeout(timer);\n timer = setTimeout(() => setIdle(true), ms);\n };\n const events: Array<keyof WindowEventMap> = [\n \"mousemove\",\n \"mousedown\",\n \"keydown\",\n \"touchstart\",\n \"scroll\",\n \"wheel\",\n ];\n events.forEach((e) => window.addEventListener(e, reset, { passive: true }));\n reset();\n return () => {\n clearTimeout(timer);\n events.forEach((e) => window.removeEventListener(e, reset));\n };\n }, [ms]);\n\n return idle;\n}\n\n/**\n * Locks `document.body` scrolling while `locked` is true, restoring the prior\n * overflow on cleanup.\n *\n * @example\n * useLockBodyScroll(isModalOpen);\n */\nexport function useLockBodyScroll(locked = true): void {\n useIsomorphicLayoutEffect(() => {\n if (!isBrowser || !locked) return;\n const original = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = original;\n };\n }, [locked]);\n}\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":["useLayoutEffect","useEffect","useRef","useCallback","useState"],"mappings":";;;;;AAWA,IAAM,SAAA,GAAY,OAAO,MAAA,KAAW,WAAA;AAa7B,IAAM,yBAAA,GAA4B,YAAYA,qBAAA,GAAkBC;AAUhE,SAAS,YAAA,GAA8B;AAC5C,EAAA,MAAM,OAAA,GAAUC,aAAO,KAAK,CAAA;AAC5B,EAAAD,eAAA,CAAU,MAAM;AACd,IAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAClB,IAAA,OAAO,MAAM;AACX,MAAA,OAAA,CAAQ,OAAA,GAAU,KAAA;AAAA,IACpB,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AACL,EAAA,OAAOE,iBAAA,CAAY,MAAM,OAAA,CAAQ,OAAA,EAAS,EAAE,CAAA;AAC9C;AAQO,SAAS,eAAe,MAAA,EAA8B;AAE3D,EAAAF,eAAA,CAAU,MAAA,EAAQ,EAAE,CAAA;AACtB;AAQO,SAAS,eAAA,CAAgB,QAAwB,IAAA,EAA6B;AACnF,EAAA,MAAM,OAAA,GAAUC,aAAO,IAAI,CAAA;AAC3B,EAAAD,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,QAAQ,OAAA,EAAS;AACnB,MAAA,OAAA,CAAQ,OAAA,GAAU,KAAA;AAClB,MAAA;AAAA,IACF;AACA,IAAA,OAAO,MAAA,EAAO;AAAA,EAEhB,GAAG,IAAI,CAAA;AACT;AAQO,SAAS,YAAe,KAAA,EAAyB;AACtD,EAAA,MAAM,GAAA,GAAMC,aAAsB,MAAS,CAAA;AAC3C,EAAAD,eAAA,CAAU,MAAM;AACd,IAAA,GAAA,CAAI,OAAA,GAAU,KAAA;AAAA,EAChB,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AACV,EAAA,OAAO,GAAA,CAAI,OAAA;AACb;AAQA,SAAS,UAAA,CACP,WAAA,EACA,GAAA,EACA,YAAA,EAC8B;AAC9B,EAAA,MAAM,SAAA,GAAYE,kBAAY,MAAS;AACrC,IAAA,IAAI,CAAC,WAAW,OAAO,YAAA;AACvB,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,MAAA,CAAO,WAAW,CAAA,CAAE,QAAQ,GAAG,CAAA;AAC3C,MAAA,OAAO,GAAA,KAAQ,IAAA,GAAO,YAAA,GAAgB,IAAA,CAAK,MAAM,GAAG,CAAA;AAAA,IACtD,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,YAAA;AAAA,IACT;AAAA,EACF,CAAA,EAAG,CAAC,YAAA,EAAc,GAAA,EAAK,WAAW,CAAC,CAAA;AAEnC,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAIC,eAAY,YAAY,CAAA;AAG9D,EAAAH,eAAA,CAAU,MAAM;AACd,IAAA,cAAA,CAAe,WAAW,CAAA;AAAA,EAE5B,CAAA,EAAG,CAAC,GAAG,CAAC,CAAA;AAER,EAAA,MAAM,QAAA,GAAWE,iBAAA;AAAA,IACf,CAAC,KAAA,KAAU;AACT,MAAA,cAAA,CAAe,CAAC,IAAA,KAAS;AACvB,QAAA,MAAM,IAAA,GAAO,KAAA,YAAiB,QAAA,GAAW,KAAA,CAAM,IAAI,CAAA,GAAI,KAAA;AACvD,QAAA,IAAI,SAAA,EAAW;AACb,UAAA,IAAI;AACF,YAAA,MAAA,CAAO,WAAW,CAAA,CAAE,OAAA,CAAQ,KAAK,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA;AACrD,YAAA,MAAA,CAAO,aAAA;AAAA,cACL,IAAI,YAAA,CAAa,SAAA,EAAW,EAAE,GAAA,EAAK,UAAU,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,EAAG;AAAA,aACrE;AAAA,UACF,CAAA,CAAA,MAAQ;AAAA,UAER;AAAA,QACF;AACA,QAAA,OAAO,IAAA;AAAA,MACT,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,IACA,CAAC,KAAK,WAAW;AAAA,GACnB;AAEA,EAAA,MAAM,MAAA,GAASA,kBAAY,MAAM;AAC/B,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,IAAI;AACF,QAAA,MAAA,CAAO,WAAW,CAAA,CAAE,UAAA,CAAW,GAAG,CAAA;AAClC,QAAA,MAAA,CAAO,aAAA,CAAc,IAAI,YAAA,CAAa,SAAA,EAAW,EAAE,GAAA,EAAK,QAAA,EAAU,IAAA,EAAM,CAAC,CAAA;AAAA,MAC3E,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AACA,IAAA,cAAA,CAAe,YAAY,CAAA;AAAA,EAC7B,CAAA,EAAG,CAAC,YAAA,EAAc,GAAA,EAAK,WAAW,CAAC,CAAA;AAGnC,EAAAF,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,SAAA,EAAW;AAChB,IAAA,MAAM,SAAA,GAAY,CAAC,CAAA,KAAoB;AACrC,MAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,IAAA,IAAQ,CAAA,CAAE,QAAQ,GAAA,EAAK;AACrC,MAAA,cAAA,CAAe,WAAW,CAAA;AAAA,IAC5B,CAAA;AACA,IAAA,MAAA,CAAO,gBAAA,CAAiB,WAAW,SAAS,CAAA;AAC5C,IAAA,OAAO,MAAM,MAAA,CAAO,mBAAA,CAAoB,SAAA,EAAW,SAAS,CAAA;AAAA,EAC9D,CAAA,EAAG,CAAC,GAAA,EAAK,SAAS,CAAC,CAAA;AAEnB,EAAA,OAAO,CAAC,WAAA,EAAa,QAAA,EAAU,MAAM,CAAA;AACvC;AAUO,SAAS,eAAA,CACd,KACA,YAAA,EAC8B;AAC9B,EAAA,OAAO,UAAA,CAAW,cAAA,EAAgB,GAAA,EAAK,YAAY,CAAA;AACrD;AAQO,SAAS,iBAAA,CACd,KACA,YAAA,EAC8B;AAC9B,EAAA,OAAO,UAAA,CAAW,gBAAA,EAAkB,GAAA,EAAK,YAAY,CAAA;AACvD;AAYO,SAAS,WAAA,CAAe,OAAU,OAAA,EAAoB;AAC3D,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIG,eAAY,KAAK,CAAA;AACnD,EAAAH,eAAA,CAAU,MAAM;AACd,IAAA,MAAM,KAAK,UAAA,CAAW,MAAM,YAAA,CAAa,KAAK,GAAG,OAAO,CAAA;AACxD,IAAA,OAAO,MAAM,aAAa,EAAE,CAAA;AAAA,EAC9B,CAAA,EAAG,CAAC,KAAA,EAAO,OAAO,CAAC,CAAA;AACnB,EAAA,OAAO,SAAA;AACT;AASO,SAAS,oBAAA,CACd,IACA,OAAA,EACiD;AACjD,EAAA,MAAM,KAAA,GAAQC,aAAO,EAAE,CAAA;AACvB,EAAA,yBAAA,CAA0B,MAAM;AAC9B,IAAA,KAAA,CAAM,OAAA,GAAU,EAAA;AAAA,EAClB,CAAA,EAAG,CAAC,EAAE,CAAC,CAAA;AAEP,EAAA,MAAM,OAAA,GAAUA,aAA6C,IAAI,CAAA;AAEjE,EAAA,MAAM,MAAA,GAASC,kBAAY,MAAM;AAC/B,IAAA,IAAI,OAAA,CAAQ,YAAY,IAAA,EAAM;AAC5B,MAAA,YAAA,CAAa,QAAQ,OAAO,CAAA;AAC5B,MAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAAA,IACpB;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAAF,eAAA,CAAU,MAAM,MAAA,EAAQ,CAAC,MAAM,CAAC,CAAA;AAEhC,EAAA,MAAM,SAAA,GAAYE,iBAAA;AAAA,IAChB,IAAI,IAAA,KAAY;AACd,MAAA,IAAI,OAAA,CAAQ,OAAA,KAAY,IAAA,EAAM,YAAA,CAAa,QAAQ,OAAO,CAAA;AAC1D,MAAA,OAAA,CAAQ,OAAA,GAAU,WAAW,MAAM;AACjC,QAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAClB,QAAA,KAAA,CAAM,OAAA,CAAQ,GAAG,IAAI,CAAA;AAAA,MACvB,GAAG,OAAO,CAAA;AAAA,IACZ,CAAA;AAAA,IACA,CAAC,OAAO;AAAA,GACV;AAEA,EAAA,SAAA,CAAU,MAAA,GAAS,MAAA;AACnB,EAAA,OAAO,SAAA;AACT;AAQO,SAAS,WAAA,CAAe,OAAU,EAAA,EAAe;AACtD,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIC,eAAY,KAAK,CAAA;AACnD,EAAA,MAAM,UAAUF,YAAA,CAAe,SAAA,GAAY,IAAA,CAAK,GAAA,KAAQ,CAAC,CAAA;AAEzD,EAAAD,eAAA,CAAU,MAAM;AACd,IAAA,MAAM,SAAA,GAAY,EAAA,IAAM,IAAA,CAAK,GAAA,KAAQ,OAAA,CAAQ,OAAA,CAAA;AAC7C,IAAA,IAAI,aAAa,CAAA,EAAG;AAClB,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,OAAA,CAAQ,OAAA,GAAU,KAAK,GAAA,EAAI;AAC3B,MAAA;AAAA,IACF;AACA,IAAA,MAAM,EAAA,GAAK,WAAW,MAAM;AAC1B,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,OAAA,CAAQ,OAAA,GAAU,KAAK,GAAA,EAAI;AAAA,IAC7B,GAAG,SAAS,CAAA;AACZ,IAAA,OAAO,MAAM,aAAa,EAAE,CAAA;AAAA,EAC9B,CAAA,EAAG,CAAC,KAAA,EAAO,EAAE,CAAC,CAAA;AAEd,EAAA,OAAO,SAAA;AACT;AASO,SAAS,WAAA,CAAY,UAAsB,OAAA,EAA8B;AAC9E,EAAA,MAAM,KAAA,GAAQC,aAAO,QAAQ,CAAA;AAC7B,EAAA,yBAAA,CAA0B,MAAM;AAC9B,IAAA,KAAA,CAAM,OAAA,GAAU,QAAA;AAAA,EAClB,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEb,EAAAD,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,YAAY,IAAA,EAAM;AACtB,IAAA,MAAM,KAAK,WAAA,CAAY,MAAM,KAAA,CAAM,OAAA,IAAW,OAAO,CAAA;AACrD,IAAA,OAAO,MAAM,cAAc,EAAE,CAAA;AAAA,EAC/B,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AACd;AAQO,SAAS,UAAA,CAAW,UAAsB,OAAA,EAA8B;AAC7E,EAAA,MAAM,KAAA,GAAQC,aAAO,QAAQ,CAAA;AAC7B,EAAA,yBAAA,CAA0B,MAAM;AAC9B,IAAA,KAAA,CAAM,OAAA,GAAU,QAAA;AAAA,EAClB,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEb,EAAAD,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,YAAY,IAAA,EAAM;AACtB,IAAA,MAAM,KAAK,UAAA,CAAW,MAAM,KAAA,CAAM,OAAA,IAAW,OAAO,CAAA;AACpD,IAAA,OAAO,MAAM,aAAa,EAAE,CAAA;AAAA,EAC9B,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AACd;AAYO,SAAS,SAAA,CACd,UAAU,KAAA,EACqF;AAC/F,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIG,eAAS,OAAO,CAAA;AAC1C,EAAA,MAAM,MAAA,GAASD,iBAAA,CAAY,MAAM,QAAA,CAAS,CAAC,MAAM,CAAC,CAAC,CAAA,EAAG,EAAE,CAAA;AACxD,EAAA,MAAM,KAAKA,iBAAA,CAAY,MAAM,SAAS,IAAI,CAAA,EAAG,EAAE,CAAA;AAC/C,EAAA,MAAM,MAAMA,iBAAA,CAAY,MAAM,SAAS,KAAK,CAAA,EAAG,EAAE,CAAA;AACjD,EAAA,MAAM,GAAA,GAAMA,kBAAY,CAAC,CAAA,KAAe,SAAS,CAAC,CAAA,EAAG,EAAE,CAAA;AACvD,EAAA,OAAO,CAAC,KAAA,EAAO,EAAE,QAAQ,EAAA,EAAI,GAAA,EAAK,KAAK,CAAA;AACzC;AAQO,SAAS,UAAA,CAAW,UAAU,CAAA,EAMnC;AACA,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIC,eAAS,OAAO,CAAA;AAC1C,EAAA,MAAM,GAAA,GAAMD,iBAAA,CAAY,CAAC,IAAA,GAAO,CAAA,KAAM,QAAA,CAAS,CAAC,CAAA,KAAM,CAAA,GAAI,IAAI,CAAA,EAAG,EAAE,CAAA;AACnE,EAAA,MAAM,GAAA,GAAMA,iBAAA,CAAY,CAAC,IAAA,GAAO,CAAA,KAAM,QAAA,CAAS,CAAC,CAAA,KAAM,CAAA,GAAI,IAAI,CAAA,EAAG,EAAE,CAAA;AACnE,EAAA,MAAM,GAAA,GAAMA,kBAAY,CAAC,CAAA,KAAc,SAAS,CAAC,CAAA,EAAG,EAAE,CAAA;AACtD,EAAA,MAAM,KAAA,GAAQA,kBAAY,MAAM,QAAA,CAAS,OAAO,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAC5D,EAAA,OAAO,EAAE,KAAA,EAAO,GAAA,EAAK,GAAA,EAAK,KAAK,KAAA,EAAM;AACvC;AAQO,SAAS,aAAA,CAAc,UAAU,KAAA,EAKtC;AACA,EAAA,MAAM,CAAC,MAAA,EAAQ,OAAO,CAAA,GAAIC,eAAS,OAAO,CAAA;AAC1C,EAAA,MAAM,OAAOD,iBAAA,CAAY,MAAM,QAAQ,IAAI,CAAA,EAAG,EAAE,CAAA;AAChD,EAAA,MAAM,QAAQA,iBAAA,CAAY,MAAM,QAAQ,KAAK,CAAA,EAAG,EAAE,CAAA;AAClD,EAAA,MAAM,MAAA,GAASA,iBAAA,CAAY,MAAM,OAAA,CAAQ,CAAC,MAAM,CAAC,CAAC,CAAA,EAAG,EAAE,CAAA;AACvD,EAAA,OAAO,EAAE,MAAA,EAAQ,IAAA,EAAM,KAAA,EAAO,MAAA,EAAO;AACvC;AAaO,SAAS,cAAc,KAAA,EAAwB;AACpD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIC,eAAS,KAAK,CAAA;AAE5C,EAAAH,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,SAAA,IAAa,OAAO,MAAA,CAAO,eAAe,UAAA,EAAY;AAC3D,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,UAAA,CAAW,KAAK,CAAA;AACnC,IAAA,MAAM,QAAA,GAAW,MAAM,UAAA,CAAW,GAAA,CAAI,OAAO,CAAA;AAC7C,IAAA,QAAA,EAAS;AACT,IAAA,GAAA,CAAI,gBAAA,CAAiB,UAAU,QAAQ,CAAA;AACvC,IAAA,OAAO,MAAM,GAAA,CAAI,mBAAA,CAAoB,QAAA,EAAU,QAAQ,CAAA;AAAA,EACzD,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAEV,EAAA,OAAO,OAAA;AACT;AAQO,SAAS,aAAA,GAAmD;AACjE,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIG,cAAA,CAA4C;AAAA,IAClE,KAAA,EAAO,CAAA;AAAA,IACP,MAAA,EAAQ;AAAA,GACT,CAAA;AAED,EAAAH,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,SAAA,EAAW;AAChB,IAAA,MAAM,QAAA,GAAW,MACf,OAAA,CAAQ,EAAE,KAAA,EAAO,OAAO,UAAA,EAAY,MAAA,EAAQ,MAAA,CAAO,WAAA,EAAa,CAAA;AAClE,IAAA,QAAA,EAAS;AACT,IAAA,MAAA,CAAO,gBAAA,CAAiB,UAAU,QAAQ,CAAA;AAC1C,IAAA,OAAO,MAAM,MAAA,CAAO,mBAAA,CAAoB,QAAA,EAAU,QAAQ,CAAA;AAAA,EAC5D,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,IAAA;AACT;AAQO,SAAS,iBAAA,GAA8C;AAC5D,EAAA,MAAM,CAAC,GAAA,EAAK,MAAM,CAAA,GAAIG,cAAA,CAAmC,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA;AAEvE,EAAAH,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,SAAA,EAAW;AAChB,IAAA,MAAM,QAAA,GAAW,MAAM,MAAA,CAAO,EAAE,CAAA,EAAG,OAAO,OAAA,EAAS,CAAA,EAAG,MAAA,CAAO,OAAA,EAAS,CAAA;AACtE,IAAA,QAAA,EAAS;AACT,IAAA,MAAA,CAAO,iBAAiB,QAAA,EAAU,QAAA,EAAU,EAAE,OAAA,EAAS,MAAM,CAAA;AAC7D,IAAA,OAAO,MAAM,MAAA,CAAO,mBAAA,CAAoB,QAAA,EAAU,QAAQ,CAAA;AAAA,EAC5D,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,GAAA;AACT;AAqCO,SAAS,gBAAA,CACd,IAAA,EACA,OAAA,EACA,OAAA,EACA,OAAA,EACM;AACN,EAAA,MAAM,YAAA,GAAeC,aAAO,OAAO,CAAA;AACnC,EAAA,yBAAA,CAA0B,MAAM;AAC9B,IAAA,YAAA,CAAa,OAAA,GAAU,OAAA;AAAA,EACzB,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAAD,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,SAAA,EAAW;AAChB,IAAA,MAAM,SACJ,OAAA,IAAW,IAAA,GACP,SACA,SAAA,IAAa,OAAA,GACX,QAAQ,OAAA,GACR,OAAA;AACR,IAAA,IAAI,MAAA,IAAU,IAAA,IAAQ,OAAO,MAAA,CAAO,qBAAqB,UAAA,EAAY;AAErE,IAAA,MAAM,QAAA,GAAW,CAAC,KAAA,KAAiB,YAAA,CAAa,QAAQ,KAAK,CAAA;AAC7D,IAAA,MAAA,CAAO,gBAAA,CAAiB,IAAA,EAAM,QAAA,EAAU,OAAO,CAAA;AAC/C,IAAA,OAAO,MAAM,MAAA,CAAO,mBAAA,CAAoB,IAAA,EAAM,UAAU,OAAO,CAAA;AAAA,EACjE,CAAA,EAAG,CAAC,IAAA,EAAM,OAAA,EAAS,OAAO,CAAC,CAAA;AAC7B;AAYO,SAAS,iBAAA,CACd,KACA,OAAA,EACM;AACN,EAAA,MAAM,YAAA,GAAeC,aAAO,OAAO,CAAA;AACnC,EAAA,yBAAA,CAA0B,MAAM;AAC9B,IAAA,YAAA,CAAa,OAAA,GAAU,OAAA;AAAA,EACzB,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAAD,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,SAAA,EAAW;AAChB,IAAA,MAAM,QAAA,GAAW,CAAC,KAAA,KAAmC;AACnD,MAAA,MAAM,KAAK,GAAA,CAAI,OAAA;AACf,MAAA,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,MAAA,IAAI,MAAM,IAAA,IAAQ,MAAA,IAAU,QAAQ,EAAA,CAAG,QAAA,CAAS,MAAM,CAAA,EAAG;AACzD,MAAA,YAAA,CAAa,QAAQ,KAAK,CAAA;AAAA,IAC5B,CAAA;AACA,IAAA,QAAA,CAAS,gBAAA,CAAiB,aAAa,QAAQ,CAAA;AAC/C,IAAA,QAAA,CAAS,iBAAiB,YAAA,EAAc,QAAA,EAAU,EAAE,OAAA,EAAS,MAAM,CAAA;AACnE,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,CAAS,mBAAA,CAAoB,aAAa,QAAQ,CAAA;AAClD,MAAA,QAAA,CAAS,mBAAA,CAAoB,cAAc,QAAQ,CAAA;AAAA,IACrD,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,GAAG,CAAC,CAAA;AACV;AAQO,SAAS,QAAA,GAAkE;AAChF,EAAA,MAAM,GAAA,GAAMC,aAAiB,IAAI,CAAA;AACjC,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIE,eAAS,KAAK,CAAA;AAE5C,EAAAH,eAAA,CAAU,MAAM;AACd,IAAA,MAAM,OAAO,GAAA,CAAI,OAAA;AACjB,IAAA,IAAI,QAAQ,IAAA,EAAM;AAClB,IAAA,MAAM,OAAA,GAAU,MAAM,UAAA,CAAW,IAAI,CAAA;AACrC,IAAA,MAAM,OAAA,GAAU,MAAM,UAAA,CAAW,KAAK,CAAA;AACtC,IAAA,IAAA,CAAK,gBAAA,CAAiB,cAAc,OAAO,CAAA;AAC3C,IAAA,IAAA,CAAK,gBAAA,CAAiB,cAAc,OAAO,CAAA;AAC3C,IAAA,OAAO,MAAM;AACX,MAAA,IAAA,CAAK,mBAAA,CAAoB,cAAc,OAAO,CAAA;AAC9C,MAAA,IAAA,CAAK,mBAAA,CAAoB,cAAc,OAAO,CAAA;AAAA,IAChD,CAAA;AAAA,EAGF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,CAAC,KAAK,OAAO,CAAA;AACtB;AASO,SAAS,wBACd,OAAA,EACkE;AAClE,EAAA,MAAM,GAAA,GAAMC,aAAiB,IAAI,CAAA;AACjC,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIE,eAA2C,IAAI,CAAA;AAEzE,EAAA,MAAM,EAAE,IAAA,EAAM,UAAA,EAAY,SAAA,EAAU,GAAI,WAAW,EAAC;AAEpD,EAAAH,eAAA,CAAU,MAAM;AACd,IAAA,MAAM,OAAO,GAAA,CAAI,OAAA;AACjB,IAAA,IAAI,CAAC,SAAA,IAAa,OAAO,oBAAA,KAAyB,UAAA,IAAc,QAAQ,IAAA,EAAM;AAC5E,MAAA;AAAA,IACF;AACA,IAAA,MAAM,WAAW,IAAI,oBAAA;AAAA,MACnB,CAAC,OAAA,KAAY;AACX,QAAA,MAAM,KAAA,GAAQ,QAAQ,CAAC,CAAA;AACvB,QAAA,IAAI,KAAA,WAAgB,KAAK,CAAA;AAAA,MAC3B,CAAA;AAAA,MACA,EAAE,IAAA,EAAM,UAAA,EAAY,SAAA;AAAU,KAChC;AACA,IAAA,QAAA,CAAS,QAAQ,IAAI,CAAA;AACrB,IAAA,OAAO,MAAM,SAAS,UAAA,EAAW;AAAA,EAEnC,CAAA,EAAG,CAAC,IAAA,EAAM,UAAA,EAAY,KAAK,SAAA,CAAU,SAAS,CAAC,CAAC,CAAA;AAEhD,EAAA,OAAO,CAAC,GAAA,EAAA,CAAK,KAAA,IAAA,IAAA,GAAA,MAAA,GAAA,KAAA,CAAO,cAAA,KAAkB,OAAO,KAAK,CAAA;AACpD;AAQO,SAAS,YAAY,SAAA,EAA4B;AACtD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIG,eAAS,KAAK,CAAA;AAE5C,EAAAH,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,SAAA,EAAW;AAChB,IAAA,MAAM,IAAA,GAAO,CAAC,CAAA,KAAqB;AACjC,MAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,SAAA,EAAW,UAAA,CAAW,IAAI,CAAA;AAAA,IAC1C,CAAA;AACA,IAAA,MAAM,EAAA,GAAK,CAAC,CAAA,KAAqB;AAC/B,MAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,SAAA,EAAW,UAAA,CAAW,KAAK,CAAA;AAAA,IAC3C,CAAA;AACA,IAAA,MAAA,CAAO,gBAAA,CAAiB,WAAW,IAAI,CAAA;AACvC,IAAA,MAAA,CAAO,gBAAA,CAAiB,SAAS,EAAE,CAAA;AACnC,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,mBAAA,CAAoB,WAAW,IAAI,CAAA;AAC1C,MAAA,MAAA,CAAO,mBAAA,CAAoB,SAAS,EAAE,CAAA;AAAA,IACxC,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAEd,EAAA,OAAO,OAAA;AACT;AAcO,SAAS,kBAAA,GAA0E;AACxF,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAIG,eAAwB,IAAI,CAAA;AAExD,EAAA,MAAM,IAAA,GAAOD,iBAAA,CAAY,OAAO,IAAA,KAAmC;AACjE,IAAA,IAAI,CAAC,WAAW,OAAO,KAAA;AACvB,IAAA,IAAI;AACF,MAAA,IAAI,UAAU,SAAA,IAAa,OAAO,SAAA,CAAU,SAAA,CAAU,cAAc,UAAA,EAAY;AAC9E,QAAA,MAAM,SAAA,CAAU,SAAA,CAAU,SAAA,CAAU,IAAI,CAAA;AACxC,QAAA,SAAA,CAAU,IAAI,CAAA;AACd,QAAA,OAAO,IAAA;AAAA,MACT;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,IAAI;AACF,MAAA,MAAM,EAAA,GAAK,QAAA,CAAS,aAAA,CAAc,UAAU,CAAA;AAC5C,MAAA,EAAA,CAAG,KAAA,GAAQ,IAAA;AACX,MAAA,EAAA,CAAG,YAAA,CAAa,YAAY,EAAE,CAAA;AAC9B,MAAA,EAAA,CAAG,MAAM,QAAA,GAAW,UAAA;AACpB,MAAA,EAAA,CAAG,MAAM,IAAA,GAAO,SAAA;AAChB,MAAA,QAAA,CAAS,IAAA,CAAK,YAAY,EAAE,CAAA;AAC5B,MAAA,EAAA,CAAG,MAAA,EAAO;AACV,MAAA,MAAM,EAAA,GAAK,QAAA,CAAS,WAAA,CAAY,MAAM,CAAA;AACtC,MAAA,QAAA,CAAS,IAAA,CAAK,YAAY,EAAE,CAAA;AAC5B,MAAA,IAAI,EAAA,EAAI;AACN,QAAA,SAAA,CAAU,IAAI,CAAA;AACd,QAAA,OAAO,IAAA;AAAA,MACT;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,SAAA,CAAU,IAAI,CAAA;AACd,IAAA,OAAO,KAAA;AAAA,EACT,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,CAAC,QAAQ,IAAI,CAAA;AACtB;AAQO,SAAS,iBAAiB,KAAA,EAAqB;AACpD,EAAA,yBAAA,CAA0B,MAAM;AAC9B,IAAA,IAAI,CAAC,SAAA,EAAW;AAChB,IAAA,QAAA,CAAS,KAAA,GAAQ,KAAA;AAAA,EACnB,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AACZ;AAQO,SAAS,eAAA,GAA2B;AACzC,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAIC,eAAS,IAAI,CAAA;AAEzC,EAAAH,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,SAAA,EAAW;AAChB,IAAA,MAAM,MAAA,GAAS,MAAM,SAAA,CAAU,SAAA,CAAU,MAAM,CAAA;AAC/C,IAAA,MAAA,EAAO;AACP,IAAA,MAAA,CAAO,gBAAA,CAAiB,UAAU,MAAM,CAAA;AACxC,IAAA,MAAA,CAAO,gBAAA,CAAiB,WAAW,MAAM,CAAA;AACzC,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,mBAAA,CAAoB,UAAU,MAAM,CAAA;AAC3C,MAAA,MAAA,CAAO,mBAAA,CAAoB,WAAW,MAAM,CAAA;AAAA,IAC9C,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,MAAA;AACT;AAQO,SAAS,QAAQ,EAAA,EAAqB;AAC3C,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIG,eAAS,KAAK,CAAA;AAEtC,EAAAH,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,SAAA,EAAW;AAChB,IAAA,IAAI,KAAA;AACJ,IAAA,MAAM,QAAQ,MAAM;AAClB,MAAA,OAAA,CAAQ,KAAK,CAAA;AACb,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,KAAA,GAAQ,UAAA,CAAW,MAAM,OAAA,CAAQ,IAAI,GAAG,EAAE,CAAA;AAAA,IAC5C,CAAA;AACA,IAAA,MAAM,MAAA,GAAsC;AAAA,MAC1C,WAAA;AAAA,MACA,WAAA;AAAA,MACA,SAAA;AAAA,MACA,YAAA;AAAA,MACA,QAAA;AAAA,MACA;AAAA,KACF;AACA,IAAA,MAAA,CAAO,OAAA,CAAQ,CAAC,CAAA,KAAM,MAAA,CAAO,gBAAA,CAAiB,CAAA,EAAG,KAAA,EAAO,EAAE,OAAA,EAAS,IAAA,EAAM,CAAC,CAAA;AAC1E,IAAA,KAAA,EAAM;AACN,IAAA,OAAO,MAAM;AACX,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,MAAA,CAAO,QAAQ,CAAC,CAAA,KAAM,OAAO,mBAAA,CAAoB,CAAA,EAAG,KAAK,CAAC,CAAA;AAAA,IAC5D,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,EAAE,CAAC,CAAA;AAEP,EAAA,OAAO,IAAA;AACT;AASO,SAAS,iBAAA,CAAkB,SAAS,IAAA,EAAY;AACrD,EAAA,yBAAA,CAA0B,MAAM;AAC9B,IAAA,IAAI,CAAC,SAAA,IAAa,CAAC,MAAA,EAAQ;AAC3B,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,IAAA,CAAK,KAAA,CAAM,QAAA;AACrC,IAAA,QAAA,CAAS,IAAA,CAAK,MAAM,QAAA,GAAW,QAAA;AAC/B,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,CAAS,IAAA,CAAK,MAAM,QAAA,GAAW,QAAA;AAAA,IACjC,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AACb","file":"index.cjs","sourcesContent":["import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type DependencyList,\n type EffectCallback,\n type RefObject,\n} from \"react\";\n\nconst isBrowser = typeof window !== \"undefined\";\n\n/* -------------------------------------------------------------------------- */\n/* Lifecycle & effect helpers */\n/* -------------------------------------------------------------------------- */\n\n/**\n * `useLayoutEffect` on the client, `useEffect` on the server. Prevents the\n * \"useLayoutEffect does nothing on the server\" warning during SSR.\n *\n * @example\n * useIsomorphicLayoutEffect(() => { el.current?.focus(); }, []);\n */\nexport const useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : useEffect;\n\n/**\n * Returns a stable getter that reports whether the component is still mounted.\n * Useful to guard async state updates.\n *\n * @example\n * const isMounted = useIsMounted();\n * fetchData().then((d) => { if (isMounted()) setData(d); });\n */\nexport function useIsMounted(): () => boolean {\n const mounted = useRef(false);\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n return useCallback(() => mounted.current, []);\n}\n\n/**\n * Runs an effect exactly once, on mount.\n *\n * @example\n * useMountEffect(() => console.log(\"mounted\"));\n */\nexport function useMountEffect(effect: EffectCallback): void {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useEffect(effect, []);\n}\n\n/**\n * Like `useEffect`, but skips the first (mount) run and only fires on updates.\n *\n * @example\n * useUpdateEffect(() => console.log(\"value changed\", value), [value]);\n */\nexport function useUpdateEffect(effect: EffectCallback, deps?: DependencyList): void {\n const isFirst = useRef(true);\n useEffect(() => {\n if (isFirst.current) {\n isFirst.current = false;\n return;\n }\n return effect();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps);\n}\n\n/**\n * Returns the value from the previous render (`undefined` on first render).\n *\n * @example\n * const prevCount = usePrevious(count);\n */\nexport function usePrevious<T>(value: T): T | undefined {\n const ref = useRef<T | undefined>(undefined);\n useEffect(() => {\n ref.current = value;\n }, [value]);\n return ref.current;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Storage */\n/* -------------------------------------------------------------------------- */\n\ntype SetValue<T> = (value: T | ((prev: T) => T)) => void;\n\nfunction useStorage<T>(\n storageArea: \"localStorage\" | \"sessionStorage\",\n key: string,\n initialValue: T,\n): [T, SetValue<T>, () => void] {\n const readValue = useCallback((): T => {\n if (!isBrowser) return initialValue;\n try {\n const raw = window[storageArea].getItem(key);\n return raw === null ? initialValue : (JSON.parse(raw) as T);\n } catch {\n return initialValue;\n }\n }, [initialValue, key, storageArea]);\n\n const [storedValue, setStoredValue] = useState<T>(initialValue);\n\n // Hydrate from storage after mount (keeps server & first client render in sync).\n useEffect(() => {\n setStoredValue(readValue());\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [key]);\n\n const setValue = useCallback<SetValue<T>>(\n (value) => {\n setStoredValue((prev) => {\n const next = value instanceof Function ? value(prev) : value;\n if (isBrowser) {\n try {\n window[storageArea].setItem(key, JSON.stringify(next));\n window.dispatchEvent(\n new StorageEvent(\"storage\", { key, newValue: JSON.stringify(next) }),\n );\n } catch {\n /* ignore write errors (quota, private mode, etc.) */\n }\n }\n return next;\n });\n },\n [key, storageArea],\n );\n\n const remove = useCallback(() => {\n if (isBrowser) {\n try {\n window[storageArea].removeItem(key);\n window.dispatchEvent(new StorageEvent(\"storage\", { key, newValue: null }));\n } catch {\n /* ignore */\n }\n }\n setStoredValue(initialValue);\n }, [initialValue, key, storageArea]);\n\n // Sync across tabs / other hook instances.\n useEffect(() => {\n if (!isBrowser) return;\n const onStorage = (e: StorageEvent) => {\n if (e.key !== null && e.key !== key) return;\n setStoredValue(readValue());\n };\n window.addEventListener(\"storage\", onStorage);\n return () => window.removeEventListener(\"storage\", onStorage);\n }, [key, readValue]);\n\n return [storedValue, setValue, remove];\n}\n\n/**\n * Persistent state backed by `localStorage`, JSON-serialized and SSR-safe.\n * Returns the initial value on the server, hydrates on mount, syncs across tabs,\n * and `remove()` clears the key.\n *\n * @example\n * const [theme, setTheme, clearTheme] = useLocalStorage(\"theme\", \"light\");\n */\nexport function useLocalStorage<T>(\n key: string,\n initialValue: T,\n): [T, SetValue<T>, () => void] {\n return useStorage(\"localStorage\", key, initialValue);\n}\n\n/**\n * Same contract as {@link useLocalStorage}, backed by `sessionStorage`.\n *\n * @example\n * const [draft, setDraft, clearDraft] = useSessionStorage(\"draft\", \"\");\n */\nexport function useSessionStorage<T>(\n key: string,\n initialValue: T,\n): [T, SetValue<T>, () => void] {\n return useStorage(\"sessionStorage\", key, initialValue);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Timing: debounce / throttle / interval / timeout */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Returns a debounced copy of `value` that only updates after `delayMs` of quiet.\n *\n * @example\n * const debounced = useDebounce(query, 300);\n */\nexport function useDebounce<T>(value: T, delayMs: number): T {\n const [debounced, setDebounced] = useState<T>(value);\n useEffect(() => {\n const id = setTimeout(() => setDebounced(value), delayMs);\n return () => clearTimeout(id);\n }, [value, delayMs]);\n return debounced;\n}\n\n/**\n * Returns a debounced callback. The returned function is stable and carries a\n * `.cancel()` method to drop any pending invocation.\n *\n * @example\n * const save = useDebouncedCallback((v: string) => api.save(v), 500);\n */\nexport function useDebouncedCallback<A extends unknown[]>(\n fn: (...args: A) => void,\n delayMs: number,\n): ((...args: A) => void) & { cancel: () => void } {\n const fnRef = useRef(fn);\n useIsomorphicLayoutEffect(() => {\n fnRef.current = fn;\n }, [fn]);\n\n const timeout = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const cancel = useCallback(() => {\n if (timeout.current !== null) {\n clearTimeout(timeout.current);\n timeout.current = null;\n }\n }, []);\n\n useEffect(() => cancel, [cancel]);\n\n const debounced = useCallback(\n (...args: A) => {\n if (timeout.current !== null) clearTimeout(timeout.current);\n timeout.current = setTimeout(() => {\n timeout.current = null;\n fnRef.current(...args);\n }, delayMs);\n },\n [delayMs],\n ) as ((...args: A) => void) & { cancel: () => void };\n\n debounced.cancel = cancel;\n return debounced;\n}\n\n/**\n * Returns a throttled copy of `value` that updates at most once per `ms`.\n *\n * @example\n * const throttled = useThrottle(scrollY, 100);\n */\nexport function useThrottle<T>(value: T, ms: number): T {\n const [throttled, setThrottled] = useState<T>(value);\n const lastRan = useRef<number>(isBrowser ? Date.now() : 0);\n\n useEffect(() => {\n const remaining = ms - (Date.now() - lastRan.current);\n if (remaining <= 0) {\n setThrottled(value);\n lastRan.current = Date.now();\n return;\n }\n const id = setTimeout(() => {\n setThrottled(value);\n lastRan.current = Date.now();\n }, remaining);\n return () => clearTimeout(id);\n }, [value, ms]);\n\n return throttled;\n}\n\n/**\n * Runs `callback` every `delayMs`. Pass `null` to pause. Uses a latest-ref so\n * the callback never goes stale.\n *\n * @example\n * useInterval(() => tick(), running ? 1000 : null);\n */\nexport function useInterval(callback: () => void, delayMs: number | null): void {\n const saved = useRef(callback);\n useIsomorphicLayoutEffect(() => {\n saved.current = callback;\n }, [callback]);\n\n useEffect(() => {\n if (delayMs === null) return;\n const id = setInterval(() => saved.current(), delayMs);\n return () => clearInterval(id);\n }, [delayMs]);\n}\n\n/**\n * Runs `callback` once after `delayMs`. Pass `null` to cancel/disable.\n *\n * @example\n * useTimeout(() => setVisible(false), 3000);\n */\nexport function useTimeout(callback: () => void, delayMs: number | null): void {\n const saved = useRef(callback);\n useIsomorphicLayoutEffect(() => {\n saved.current = callback;\n }, [callback]);\n\n useEffect(() => {\n if (delayMs === null) return;\n const id = setTimeout(() => saved.current(), delayMs);\n return () => clearTimeout(id);\n }, [delayMs]);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Simple state helpers */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Boolean state with convenient controls.\n *\n * @example\n * const [on, { toggle, off }] = useToggle();\n */\nexport function useToggle(\n initial = false,\n): [boolean, { toggle: () => void; on: () => void; off: () => void; set: (v: boolean) => void }] {\n const [value, setValue] = useState(initial);\n const toggle = useCallback(() => setValue((v) => !v), []);\n const on = useCallback(() => setValue(true), []);\n const off = useCallback(() => setValue(false), []);\n const set = useCallback((v: boolean) => setValue(v), []);\n return [value, { toggle, on, off, set }];\n}\n\n/**\n * Numeric counter with increment/decrement/set/reset controls.\n *\n * @example\n * const { count, inc, dec, reset } = useCounter(0);\n */\nexport function useCounter(initial = 0): {\n count: number;\n inc: (step?: number) => void;\n dec: (step?: number) => void;\n set: (n: number) => void;\n reset: () => void;\n} {\n const [count, setCount] = useState(initial);\n const inc = useCallback((step = 1) => setCount((c) => c + step), []);\n const dec = useCallback((step = 1) => setCount((c) => c - step), []);\n const set = useCallback((n: number) => setCount(n), []);\n const reset = useCallback(() => setCount(initial), [initial]);\n return { count, inc, dec, set, reset };\n}\n\n/**\n * Open/close state, ideal for modals, drawers and menus.\n *\n * @example\n * const { isOpen, open, close } = useDisclosure();\n */\nexport function useDisclosure(initial = false): {\n isOpen: boolean;\n open: () => void;\n close: () => void;\n toggle: () => void;\n} {\n const [isOpen, setOpen] = useState(initial);\n const open = useCallback(() => setOpen(true), []);\n const close = useCallback(() => setOpen(false), []);\n const toggle = useCallback(() => setOpen((v) => !v), []);\n return { isOpen, open, close, toggle };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Browser / DOM environment */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Tracks a CSS media query. SSR-safe: returns `false` on the server, then the\n * real match after mount.\n *\n * @example\n * const isDark = useMediaQuery(\"(prefers-color-scheme: dark)\");\n */\nexport function useMediaQuery(query: string): boolean {\n const [matches, setMatches] = useState(false);\n\n useEffect(() => {\n if (!isBrowser || typeof window.matchMedia !== \"function\") return;\n const mql = window.matchMedia(query);\n const onChange = () => setMatches(mql.matches);\n onChange();\n mql.addEventListener(\"change\", onChange);\n return () => mql.removeEventListener(\"change\", onChange);\n }, [query]);\n\n return matches;\n}\n\n/**\n * Current viewport size. SSR-safe: returns `{ width: 0, height: 0 }` on server.\n *\n * @example\n * const { width } = useWindowSize();\n */\nexport function useWindowSize(): { width: number; height: number } {\n const [size, setSize] = useState<{ width: number; height: number }>({\n width: 0,\n height: 0,\n });\n\n useEffect(() => {\n if (!isBrowser) return;\n const onResize = () =>\n setSize({ width: window.innerWidth, height: window.innerHeight });\n onResize();\n window.addEventListener(\"resize\", onResize);\n return () => window.removeEventListener(\"resize\", onResize);\n }, []);\n\n return size;\n}\n\n/**\n * Current window scroll position. SSR-safe: `{ x: 0, y: 0 }` on server.\n *\n * @example\n * const { y } = useScrollPosition();\n */\nexport function useScrollPosition(): { x: number; y: number } {\n const [pos, setPos] = useState<{ x: number; y: number }>({ x: 0, y: 0 });\n\n useEffect(() => {\n if (!isBrowser) return;\n const onScroll = () => setPos({ x: window.scrollX, y: window.scrollY });\n onScroll();\n window.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => window.removeEventListener(\"scroll\", onScroll);\n }, []);\n\n return pos;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Event listener (overloaded) */\n/* -------------------------------------------------------------------------- */\n\n/** Attach a `window` event listener. */\nexport function useEventListener<K extends keyof WindowEventMap>(\n type: K,\n handler: (event: WindowEventMap[K]) => void,\n element?: undefined,\n options?: boolean | AddEventListenerOptions,\n): void;\n/** Attach a `document` event listener. */\nexport function useEventListener<K extends keyof DocumentEventMap>(\n type: K,\n handler: (event: DocumentEventMap[K]) => void,\n element: RefObject<Document | null> | Document,\n options?: boolean | AddEventListenerOptions,\n): void;\n/** Attach an event listener to an element referenced by a ref. */\nexport function useEventListener<\n K extends keyof HTMLElementEventMap,\n T extends HTMLElement,\n>(\n type: K,\n handler: (event: HTMLElementEventMap[K]) => void,\n element: RefObject<T | null> | T,\n options?: boolean | AddEventListenerOptions,\n): void;\n/**\n * Adds an event listener to `window` (default), `document`, or a ref/element,\n * using a latest-ref so the handler never goes stale.\n *\n * @example\n * useEventListener(\"keydown\", (e) => e.key === \"Escape\" && close());\n */\nexport function useEventListener(\n type: string,\n handler: (event: Event) => void,\n element?: RefObject<EventTarget | null> | EventTarget,\n options?: boolean | AddEventListenerOptions,\n): void {\n const savedHandler = useRef(handler);\n useIsomorphicLayoutEffect(() => {\n savedHandler.current = handler;\n }, [handler]);\n\n useEffect(() => {\n if (!isBrowser) return;\n const target: EventTarget | null =\n element == null\n ? window\n : \"current\" in element\n ? element.current\n : element;\n if (target == null || typeof target.addEventListener !== \"function\") return;\n\n const listener = (event: Event) => savedHandler.current(event);\n target.addEventListener(type, listener, options);\n return () => target.removeEventListener(type, listener, options);\n }, [type, element, options]);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Element interactions */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Calls `handler` when a pointer event occurs outside the referenced element.\n *\n * @example\n * useOnClickOutside(ref, () => setOpen(false));\n */\nexport function useOnClickOutside<T extends HTMLElement>(\n ref: RefObject<T | null>,\n handler: (event: MouseEvent | TouchEvent) => void,\n): void {\n const savedHandler = useRef(handler);\n useIsomorphicLayoutEffect(() => {\n savedHandler.current = handler;\n }, [handler]);\n\n useEffect(() => {\n if (!isBrowser) return;\n const listener = (event: MouseEvent | TouchEvent) => {\n const el = ref.current;\n const target = event.target as Node | null;\n if (el == null || target == null || el.contains(target)) return;\n savedHandler.current(event);\n };\n document.addEventListener(\"mousedown\", listener);\n document.addEventListener(\"touchstart\", listener, { passive: true });\n return () => {\n document.removeEventListener(\"mousedown\", listener);\n document.removeEventListener(\"touchstart\", listener);\n };\n }, [ref]);\n}\n\n/**\n * Tracks hover state of an element. Returns a ref to attach and the boolean.\n *\n * @example\n * const [ref, hovered] = useHover<HTMLButtonElement>();\n */\nexport function useHover<T extends HTMLElement>(): [RefObject<T | null>, boolean] {\n const ref = useRef<T | null>(null);\n const [hovered, setHovered] = useState(false);\n\n useEffect(() => {\n const node = ref.current;\n if (node == null) return;\n const onEnter = () => setHovered(true);\n const onLeave = () => setHovered(false);\n node.addEventListener(\"mouseenter\", onEnter);\n node.addEventListener(\"mouseleave\", onLeave);\n return () => {\n node.removeEventListener(\"mouseenter\", onEnter);\n node.removeEventListener(\"mouseleave\", onLeave);\n };\n // `ref` is a stable object and the node is read from `ref.current` (attached\n // before effects run), so subscribe once on mount instead of every render.\n }, []);\n\n return [ref, hovered];\n}\n\n/**\n * Observes an element's intersection with the viewport. Returns the ref to\n * attach, a boolean `isIntersecting`, and the raw entry.\n *\n * @example\n * const [ref, visible] = useIntersectionObserver<HTMLDivElement>({ threshold: 0.5 });\n */\nexport function useIntersectionObserver<T extends Element>(\n options?: IntersectionObserverInit,\n): [RefObject<T | null>, boolean, IntersectionObserverEntry | null] {\n const ref = useRef<T | null>(null);\n const [entry, setEntry] = useState<IntersectionObserverEntry | null>(null);\n\n const { root, rootMargin, threshold } = options ?? {};\n\n useEffect(() => {\n const node = ref.current;\n if (!isBrowser || typeof IntersectionObserver !== \"function\" || node == null) {\n return;\n }\n const observer = new IntersectionObserver(\n (entries) => {\n const first = entries[0];\n if (first) setEntry(first);\n },\n { root, rootMargin, threshold },\n );\n observer.observe(node);\n return () => observer.disconnect();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [root, rootMargin, JSON.stringify(threshold)]);\n\n return [ref, entry?.isIntersecting ?? false, entry];\n}\n\n/**\n * Returns `true` while the given key is pressed.\n *\n * @example\n * const shiftHeld = useKeyPress(\"Shift\");\n */\nexport function useKeyPress(targetKey: string): boolean {\n const [pressed, setPressed] = useState(false);\n\n useEffect(() => {\n if (!isBrowser) return;\n const down = (e: KeyboardEvent) => {\n if (e.key === targetKey) setPressed(true);\n };\n const up = (e: KeyboardEvent) => {\n if (e.key === targetKey) setPressed(false);\n };\n window.addEventListener(\"keydown\", down);\n window.addEventListener(\"keyup\", up);\n return () => {\n window.removeEventListener(\"keydown\", down);\n window.removeEventListener(\"keyup\", up);\n };\n }, [targetKey]);\n\n return pressed;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Misc utilities */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Copies text to the clipboard. Returns the last-copied value and an async\n * `copy` function resolving to a success boolean. Falls back to `execCommand`.\n *\n * @example\n * const [copied, copy] = useCopyToClipboard();\n * await copy(\"hello\");\n */\nexport function useCopyToClipboard(): [string | null, (text: string) => Promise<boolean>] {\n const [copied, setCopied] = useState<string | null>(null);\n\n const copy = useCallback(async (text: string): Promise<boolean> => {\n if (!isBrowser) return false;\n try {\n if (navigator.clipboard && typeof navigator.clipboard.writeText === \"function\") {\n await navigator.clipboard.writeText(text);\n setCopied(text);\n return true;\n }\n } catch {\n /* fall through to legacy path */\n }\n try {\n const el = document.createElement(\"textarea\");\n el.value = text;\n el.setAttribute(\"readonly\", \"\");\n el.style.position = \"absolute\";\n el.style.left = \"-9999px\";\n document.body.appendChild(el);\n el.select();\n const ok = document.execCommand(\"copy\");\n document.body.removeChild(el);\n if (ok) {\n setCopied(text);\n return true;\n }\n } catch {\n /* ignore */\n }\n setCopied(null);\n return false;\n }, []);\n\n return [copied, copy];\n}\n\n/**\n * Sets `document.title` while mounted (no-op on the server).\n *\n * @example\n * useDocumentTitle(`Inbox (${unread})`);\n */\nexport function useDocumentTitle(title: string): void {\n useIsomorphicLayoutEffect(() => {\n if (!isBrowser) return;\n document.title = title;\n }, [title]);\n}\n\n/**\n * Tracks the browser's online/offline status. SSR-safe: `true` on the server.\n *\n * @example\n * const online = useOnlineStatus();\n */\nexport function useOnlineStatus(): boolean {\n const [online, setOnline] = useState(true);\n\n useEffect(() => {\n if (!isBrowser) return;\n const update = () => setOnline(navigator.onLine);\n update();\n window.addEventListener(\"online\", update);\n window.addEventListener(\"offline\", update);\n return () => {\n window.removeEventListener(\"online\", update);\n window.removeEventListener(\"offline\", update);\n };\n }, []);\n\n return online;\n}\n\n/**\n * Returns `true` after `ms` of no user activity (mouse, keyboard, touch, scroll).\n *\n * @example\n * const idle = useIdle(60_000);\n */\nexport function useIdle(ms: number): boolean {\n const [idle, setIdle] = useState(false);\n\n useEffect(() => {\n if (!isBrowser) return;\n let timer: ReturnType<typeof setTimeout>;\n const reset = () => {\n setIdle(false);\n clearTimeout(timer);\n timer = setTimeout(() => setIdle(true), ms);\n };\n const events: Array<keyof WindowEventMap> = [\n \"mousemove\",\n \"mousedown\",\n \"keydown\",\n \"touchstart\",\n \"scroll\",\n \"wheel\",\n ];\n events.forEach((e) => window.addEventListener(e, reset, { passive: true }));\n reset();\n return () => {\n clearTimeout(timer);\n events.forEach((e) => window.removeEventListener(e, reset));\n };\n }, [ms]);\n\n return idle;\n}\n\n/**\n * Locks `document.body` scrolling while `locked` is true, restoring the prior\n * overflow on cleanup.\n *\n * @example\n * useLockBodyScroll(isModalOpen);\n */\nexport function useLockBodyScroll(locked = true): void {\n useIsomorphicLayoutEffect(() => {\n if (!isBrowser || !locked) return;\n const original = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = original;\n };\n }, [locked]);\n}\n"]}
package/dist/index.js CHANGED
@@ -275,7 +275,7 @@ function useHover() {
275
275
  node.removeEventListener("mouseenter", onEnter);
276
276
  node.removeEventListener("mouseleave", onLeave);
277
277
  };
278
- });
278
+ }, []);
279
279
  return [ref, hovered];
280
280
  }
281
281
  function useIntersectionObserver(options) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type DependencyList,\n type EffectCallback,\n type RefObject,\n} from \"react\";\n\nconst isBrowser = typeof window !== \"undefined\";\n\n/* -------------------------------------------------------------------------- */\n/* Lifecycle & effect helpers */\n/* -------------------------------------------------------------------------- */\n\n/**\n * `useLayoutEffect` on the client, `useEffect` on the server. Prevents the\n * \"useLayoutEffect does nothing on the server\" warning during SSR.\n *\n * @example\n * useIsomorphicLayoutEffect(() => { el.current?.focus(); }, []);\n */\nexport const useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : useEffect;\n\n/**\n * Returns a stable getter that reports whether the component is still mounted.\n * Useful to guard async state updates.\n *\n * @example\n * const isMounted = useIsMounted();\n * fetchData().then((d) => { if (isMounted()) setData(d); });\n */\nexport function useIsMounted(): () => boolean {\n const mounted = useRef(false);\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n return useCallback(() => mounted.current, []);\n}\n\n/**\n * Runs an effect exactly once, on mount.\n *\n * @example\n * useMountEffect(() => console.log(\"mounted\"));\n */\nexport function useMountEffect(effect: EffectCallback): void {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useEffect(effect, []);\n}\n\n/**\n * Like `useEffect`, but skips the first (mount) run and only fires on updates.\n *\n * @example\n * useUpdateEffect(() => console.log(\"value changed\", value), [value]);\n */\nexport function useUpdateEffect(effect: EffectCallback, deps?: DependencyList): void {\n const isFirst = useRef(true);\n useEffect(() => {\n if (isFirst.current) {\n isFirst.current = false;\n return;\n }\n return effect();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps);\n}\n\n/**\n * Returns the value from the previous render (`undefined` on first render).\n *\n * @example\n * const prevCount = usePrevious(count);\n */\nexport function usePrevious<T>(value: T): T | undefined {\n const ref = useRef<T | undefined>(undefined);\n useEffect(() => {\n ref.current = value;\n }, [value]);\n return ref.current;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Storage */\n/* -------------------------------------------------------------------------- */\n\ntype SetValue<T> = (value: T | ((prev: T) => T)) => void;\n\nfunction useStorage<T>(\n storageArea: \"localStorage\" | \"sessionStorage\",\n key: string,\n initialValue: T,\n): [T, SetValue<T>, () => void] {\n const readValue = useCallback((): T => {\n if (!isBrowser) return initialValue;\n try {\n const raw = window[storageArea].getItem(key);\n return raw === null ? initialValue : (JSON.parse(raw) as T);\n } catch {\n return initialValue;\n }\n }, [initialValue, key, storageArea]);\n\n const [storedValue, setStoredValue] = useState<T>(initialValue);\n\n // Hydrate from storage after mount (keeps server & first client render in sync).\n useEffect(() => {\n setStoredValue(readValue());\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [key]);\n\n const setValue = useCallback<SetValue<T>>(\n (value) => {\n setStoredValue((prev) => {\n const next = value instanceof Function ? value(prev) : value;\n if (isBrowser) {\n try {\n window[storageArea].setItem(key, JSON.stringify(next));\n window.dispatchEvent(\n new StorageEvent(\"storage\", { key, newValue: JSON.stringify(next) }),\n );\n } catch {\n /* ignore write errors (quota, private mode, etc.) */\n }\n }\n return next;\n });\n },\n [key, storageArea],\n );\n\n const remove = useCallback(() => {\n if (isBrowser) {\n try {\n window[storageArea].removeItem(key);\n window.dispatchEvent(new StorageEvent(\"storage\", { key, newValue: null }));\n } catch {\n /* ignore */\n }\n }\n setStoredValue(initialValue);\n }, [initialValue, key, storageArea]);\n\n // Sync across tabs / other hook instances.\n useEffect(() => {\n if (!isBrowser) return;\n const onStorage = (e: StorageEvent) => {\n if (e.key !== null && e.key !== key) return;\n setStoredValue(readValue());\n };\n window.addEventListener(\"storage\", onStorage);\n return () => window.removeEventListener(\"storage\", onStorage);\n }, [key, readValue]);\n\n return [storedValue, setValue, remove];\n}\n\n/**\n * Persistent state backed by `localStorage`, JSON-serialized and SSR-safe.\n * Returns the initial value on the server, hydrates on mount, syncs across tabs,\n * and `remove()` clears the key.\n *\n * @example\n * const [theme, setTheme, clearTheme] = useLocalStorage(\"theme\", \"light\");\n */\nexport function useLocalStorage<T>(\n key: string,\n initialValue: T,\n): [T, SetValue<T>, () => void] {\n return useStorage(\"localStorage\", key, initialValue);\n}\n\n/**\n * Same contract as {@link useLocalStorage}, backed by `sessionStorage`.\n *\n * @example\n * const [draft, setDraft, clearDraft] = useSessionStorage(\"draft\", \"\");\n */\nexport function useSessionStorage<T>(\n key: string,\n initialValue: T,\n): [T, SetValue<T>, () => void] {\n return useStorage(\"sessionStorage\", key, initialValue);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Timing: debounce / throttle / interval / timeout */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Returns a debounced copy of `value` that only updates after `delayMs` of quiet.\n *\n * @example\n * const debounced = useDebounce(query, 300);\n */\nexport function useDebounce<T>(value: T, delayMs: number): T {\n const [debounced, setDebounced] = useState<T>(value);\n useEffect(() => {\n const id = setTimeout(() => setDebounced(value), delayMs);\n return () => clearTimeout(id);\n }, [value, delayMs]);\n return debounced;\n}\n\n/**\n * Returns a debounced callback. The returned function is stable and carries a\n * `.cancel()` method to drop any pending invocation.\n *\n * @example\n * const save = useDebouncedCallback((v: string) => api.save(v), 500);\n */\nexport function useDebouncedCallback<A extends unknown[]>(\n fn: (...args: A) => void,\n delayMs: number,\n): ((...args: A) => void) & { cancel: () => void } {\n const fnRef = useRef(fn);\n useIsomorphicLayoutEffect(() => {\n fnRef.current = fn;\n }, [fn]);\n\n const timeout = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const cancel = useCallback(() => {\n if (timeout.current !== null) {\n clearTimeout(timeout.current);\n timeout.current = null;\n }\n }, []);\n\n useEffect(() => cancel, [cancel]);\n\n const debounced = useCallback(\n (...args: A) => {\n if (timeout.current !== null) clearTimeout(timeout.current);\n timeout.current = setTimeout(() => {\n timeout.current = null;\n fnRef.current(...args);\n }, delayMs);\n },\n [delayMs],\n ) as ((...args: A) => void) & { cancel: () => void };\n\n debounced.cancel = cancel;\n return debounced;\n}\n\n/**\n * Returns a throttled copy of `value` that updates at most once per `ms`.\n *\n * @example\n * const throttled = useThrottle(scrollY, 100);\n */\nexport function useThrottle<T>(value: T, ms: number): T {\n const [throttled, setThrottled] = useState<T>(value);\n const lastRan = useRef<number>(isBrowser ? Date.now() : 0);\n\n useEffect(() => {\n const remaining = ms - (Date.now() - lastRan.current);\n if (remaining <= 0) {\n setThrottled(value);\n lastRan.current = Date.now();\n return;\n }\n const id = setTimeout(() => {\n setThrottled(value);\n lastRan.current = Date.now();\n }, remaining);\n return () => clearTimeout(id);\n }, [value, ms]);\n\n return throttled;\n}\n\n/**\n * Runs `callback` every `delayMs`. Pass `null` to pause. Uses a latest-ref so\n * the callback never goes stale.\n *\n * @example\n * useInterval(() => tick(), running ? 1000 : null);\n */\nexport function useInterval(callback: () => void, delayMs: number | null): void {\n const saved = useRef(callback);\n useIsomorphicLayoutEffect(() => {\n saved.current = callback;\n }, [callback]);\n\n useEffect(() => {\n if (delayMs === null) return;\n const id = setInterval(() => saved.current(), delayMs);\n return () => clearInterval(id);\n }, [delayMs]);\n}\n\n/**\n * Runs `callback` once after `delayMs`. Pass `null` to cancel/disable.\n *\n * @example\n * useTimeout(() => setVisible(false), 3000);\n */\nexport function useTimeout(callback: () => void, delayMs: number | null): void {\n const saved = useRef(callback);\n useIsomorphicLayoutEffect(() => {\n saved.current = callback;\n }, [callback]);\n\n useEffect(() => {\n if (delayMs === null) return;\n const id = setTimeout(() => saved.current(), delayMs);\n return () => clearTimeout(id);\n }, [delayMs]);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Simple state helpers */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Boolean state with convenient controls.\n *\n * @example\n * const [on, { toggle, off }] = useToggle();\n */\nexport function useToggle(\n initial = false,\n): [boolean, { toggle: () => void; on: () => void; off: () => void; set: (v: boolean) => void }] {\n const [value, setValue] = useState(initial);\n const toggle = useCallback(() => setValue((v) => !v), []);\n const on = useCallback(() => setValue(true), []);\n const off = useCallback(() => setValue(false), []);\n const set = useCallback((v: boolean) => setValue(v), []);\n return [value, { toggle, on, off, set }];\n}\n\n/**\n * Numeric counter with increment/decrement/set/reset controls.\n *\n * @example\n * const { count, inc, dec, reset } = useCounter(0);\n */\nexport function useCounter(initial = 0): {\n count: number;\n inc: (step?: number) => void;\n dec: (step?: number) => void;\n set: (n: number) => void;\n reset: () => void;\n} {\n const [count, setCount] = useState(initial);\n const inc = useCallback((step = 1) => setCount((c) => c + step), []);\n const dec = useCallback((step = 1) => setCount((c) => c - step), []);\n const set = useCallback((n: number) => setCount(n), []);\n const reset = useCallback(() => setCount(initial), [initial]);\n return { count, inc, dec, set, reset };\n}\n\n/**\n * Open/close state, ideal for modals, drawers and menus.\n *\n * @example\n * const { isOpen, open, close } = useDisclosure();\n */\nexport function useDisclosure(initial = false): {\n isOpen: boolean;\n open: () => void;\n close: () => void;\n toggle: () => void;\n} {\n const [isOpen, setOpen] = useState(initial);\n const open = useCallback(() => setOpen(true), []);\n const close = useCallback(() => setOpen(false), []);\n const toggle = useCallback(() => setOpen((v) => !v), []);\n return { isOpen, open, close, toggle };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Browser / DOM environment */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Tracks a CSS media query. SSR-safe: returns `false` on the server, then the\n * real match after mount.\n *\n * @example\n * const isDark = useMediaQuery(\"(prefers-color-scheme: dark)\");\n */\nexport function useMediaQuery(query: string): boolean {\n const [matches, setMatches] = useState(false);\n\n useEffect(() => {\n if (!isBrowser || typeof window.matchMedia !== \"function\") return;\n const mql = window.matchMedia(query);\n const onChange = () => setMatches(mql.matches);\n onChange();\n mql.addEventListener(\"change\", onChange);\n return () => mql.removeEventListener(\"change\", onChange);\n }, [query]);\n\n return matches;\n}\n\n/**\n * Current viewport size. SSR-safe: returns `{ width: 0, height: 0 }` on server.\n *\n * @example\n * const { width } = useWindowSize();\n */\nexport function useWindowSize(): { width: number; height: number } {\n const [size, setSize] = useState<{ width: number; height: number }>({\n width: 0,\n height: 0,\n });\n\n useEffect(() => {\n if (!isBrowser) return;\n const onResize = () =>\n setSize({ width: window.innerWidth, height: window.innerHeight });\n onResize();\n window.addEventListener(\"resize\", onResize);\n return () => window.removeEventListener(\"resize\", onResize);\n }, []);\n\n return size;\n}\n\n/**\n * Current window scroll position. SSR-safe: `{ x: 0, y: 0 }` on server.\n *\n * @example\n * const { y } = useScrollPosition();\n */\nexport function useScrollPosition(): { x: number; y: number } {\n const [pos, setPos] = useState<{ x: number; y: number }>({ x: 0, y: 0 });\n\n useEffect(() => {\n if (!isBrowser) return;\n const onScroll = () => setPos({ x: window.scrollX, y: window.scrollY });\n onScroll();\n window.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => window.removeEventListener(\"scroll\", onScroll);\n }, []);\n\n return pos;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Event listener (overloaded) */\n/* -------------------------------------------------------------------------- */\n\n/** Attach a `window` event listener. */\nexport function useEventListener<K extends keyof WindowEventMap>(\n type: K,\n handler: (event: WindowEventMap[K]) => void,\n element?: undefined,\n options?: boolean | AddEventListenerOptions,\n): void;\n/** Attach a `document` event listener. */\nexport function useEventListener<K extends keyof DocumentEventMap>(\n type: K,\n handler: (event: DocumentEventMap[K]) => void,\n element: RefObject<Document | null> | Document,\n options?: boolean | AddEventListenerOptions,\n): void;\n/** Attach an event listener to an element referenced by a ref. */\nexport function useEventListener<\n K extends keyof HTMLElementEventMap,\n T extends HTMLElement,\n>(\n type: K,\n handler: (event: HTMLElementEventMap[K]) => void,\n element: RefObject<T | null> | T,\n options?: boolean | AddEventListenerOptions,\n): void;\n/**\n * Adds an event listener to `window` (default), `document`, or a ref/element,\n * using a latest-ref so the handler never goes stale.\n *\n * @example\n * useEventListener(\"keydown\", (e) => e.key === \"Escape\" && close());\n */\nexport function useEventListener(\n type: string,\n handler: (event: Event) => void,\n element?: RefObject<EventTarget | null> | EventTarget,\n options?: boolean | AddEventListenerOptions,\n): void {\n const savedHandler = useRef(handler);\n useIsomorphicLayoutEffect(() => {\n savedHandler.current = handler;\n }, [handler]);\n\n useEffect(() => {\n if (!isBrowser) return;\n const target: EventTarget | null =\n element == null\n ? window\n : \"current\" in element\n ? element.current\n : element;\n if (target == null || typeof target.addEventListener !== \"function\") return;\n\n const listener = (event: Event) => savedHandler.current(event);\n target.addEventListener(type, listener, options);\n return () => target.removeEventListener(type, listener, options);\n }, [type, element, options]);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Element interactions */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Calls `handler` when a pointer event occurs outside the referenced element.\n *\n * @example\n * useOnClickOutside(ref, () => setOpen(false));\n */\nexport function useOnClickOutside<T extends HTMLElement>(\n ref: RefObject<T | null>,\n handler: (event: MouseEvent | TouchEvent) => void,\n): void {\n const savedHandler = useRef(handler);\n useIsomorphicLayoutEffect(() => {\n savedHandler.current = handler;\n }, [handler]);\n\n useEffect(() => {\n if (!isBrowser) return;\n const listener = (event: MouseEvent | TouchEvent) => {\n const el = ref.current;\n const target = event.target as Node | null;\n if (el == null || target == null || el.contains(target)) return;\n savedHandler.current(event);\n };\n document.addEventListener(\"mousedown\", listener);\n document.addEventListener(\"touchstart\", listener, { passive: true });\n return () => {\n document.removeEventListener(\"mousedown\", listener);\n document.removeEventListener(\"touchstart\", listener);\n };\n }, [ref]);\n}\n\n/**\n * Tracks hover state of an element. Returns a ref to attach and the boolean.\n *\n * @example\n * const [ref, hovered] = useHover<HTMLButtonElement>();\n */\nexport function useHover<T extends HTMLElement>(): [RefObject<T | null>, boolean] {\n const ref = useRef<T | null>(null);\n const [hovered, setHovered] = useState(false);\n\n useEffect(() => {\n const node = ref.current;\n if (node == null) return;\n const onEnter = () => setHovered(true);\n const onLeave = () => setHovered(false);\n node.addEventListener(\"mouseenter\", onEnter);\n node.addEventListener(\"mouseleave\", onLeave);\n return () => {\n node.removeEventListener(\"mouseenter\", onEnter);\n node.removeEventListener(\"mouseleave\", onLeave);\n };\n });\n\n return [ref, hovered];\n}\n\n/**\n * Observes an element's intersection with the viewport. Returns the ref to\n * attach, a boolean `isIntersecting`, and the raw entry.\n *\n * @example\n * const [ref, visible] = useIntersectionObserver<HTMLDivElement>({ threshold: 0.5 });\n */\nexport function useIntersectionObserver<T extends Element>(\n options?: IntersectionObserverInit,\n): [RefObject<T | null>, boolean, IntersectionObserverEntry | null] {\n const ref = useRef<T | null>(null);\n const [entry, setEntry] = useState<IntersectionObserverEntry | null>(null);\n\n const { root, rootMargin, threshold } = options ?? {};\n\n useEffect(() => {\n const node = ref.current;\n if (!isBrowser || typeof IntersectionObserver !== \"function\" || node == null) {\n return;\n }\n const observer = new IntersectionObserver(\n (entries) => {\n const first = entries[0];\n if (first) setEntry(first);\n },\n { root, rootMargin, threshold },\n );\n observer.observe(node);\n return () => observer.disconnect();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [root, rootMargin, JSON.stringify(threshold)]);\n\n return [ref, entry?.isIntersecting ?? false, entry];\n}\n\n/**\n * Returns `true` while the given key is pressed.\n *\n * @example\n * const shiftHeld = useKeyPress(\"Shift\");\n */\nexport function useKeyPress(targetKey: string): boolean {\n const [pressed, setPressed] = useState(false);\n\n useEffect(() => {\n if (!isBrowser) return;\n const down = (e: KeyboardEvent) => {\n if (e.key === targetKey) setPressed(true);\n };\n const up = (e: KeyboardEvent) => {\n if (e.key === targetKey) setPressed(false);\n };\n window.addEventListener(\"keydown\", down);\n window.addEventListener(\"keyup\", up);\n return () => {\n window.removeEventListener(\"keydown\", down);\n window.removeEventListener(\"keyup\", up);\n };\n }, [targetKey]);\n\n return pressed;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Misc utilities */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Copies text to the clipboard. Returns the last-copied value and an async\n * `copy` function resolving to a success boolean. Falls back to `execCommand`.\n *\n * @example\n * const [copied, copy] = useCopyToClipboard();\n * await copy(\"hello\");\n */\nexport function useCopyToClipboard(): [string | null, (text: string) => Promise<boolean>] {\n const [copied, setCopied] = useState<string | null>(null);\n\n const copy = useCallback(async (text: string): Promise<boolean> => {\n if (!isBrowser) return false;\n try {\n if (navigator.clipboard && typeof navigator.clipboard.writeText === \"function\") {\n await navigator.clipboard.writeText(text);\n setCopied(text);\n return true;\n }\n } catch {\n /* fall through to legacy path */\n }\n try {\n const el = document.createElement(\"textarea\");\n el.value = text;\n el.setAttribute(\"readonly\", \"\");\n el.style.position = \"absolute\";\n el.style.left = \"-9999px\";\n document.body.appendChild(el);\n el.select();\n const ok = document.execCommand(\"copy\");\n document.body.removeChild(el);\n if (ok) {\n setCopied(text);\n return true;\n }\n } catch {\n /* ignore */\n }\n setCopied(null);\n return false;\n }, []);\n\n return [copied, copy];\n}\n\n/**\n * Sets `document.title` while mounted (no-op on the server).\n *\n * @example\n * useDocumentTitle(`Inbox (${unread})`);\n */\nexport function useDocumentTitle(title: string): void {\n useIsomorphicLayoutEffect(() => {\n if (!isBrowser) return;\n document.title = title;\n }, [title]);\n}\n\n/**\n * Tracks the browser's online/offline status. SSR-safe: `true` on the server.\n *\n * @example\n * const online = useOnlineStatus();\n */\nexport function useOnlineStatus(): boolean {\n const [online, setOnline] = useState(true);\n\n useEffect(() => {\n if (!isBrowser) return;\n const update = () => setOnline(navigator.onLine);\n update();\n window.addEventListener(\"online\", update);\n window.addEventListener(\"offline\", update);\n return () => {\n window.removeEventListener(\"online\", update);\n window.removeEventListener(\"offline\", update);\n };\n }, []);\n\n return online;\n}\n\n/**\n * Returns `true` after `ms` of no user activity (mouse, keyboard, touch, scroll).\n *\n * @example\n * const idle = useIdle(60_000);\n */\nexport function useIdle(ms: number): boolean {\n const [idle, setIdle] = useState(false);\n\n useEffect(() => {\n if (!isBrowser) return;\n let timer: ReturnType<typeof setTimeout>;\n const reset = () => {\n setIdle(false);\n clearTimeout(timer);\n timer = setTimeout(() => setIdle(true), ms);\n };\n const events: Array<keyof WindowEventMap> = [\n \"mousemove\",\n \"mousedown\",\n \"keydown\",\n \"touchstart\",\n \"scroll\",\n \"wheel\",\n ];\n events.forEach((e) => window.addEventListener(e, reset, { passive: true }));\n reset();\n return () => {\n clearTimeout(timer);\n events.forEach((e) => window.removeEventListener(e, reset));\n };\n }, [ms]);\n\n return idle;\n}\n\n/**\n * Locks `document.body` scrolling while `locked` is true, restoring the prior\n * overflow on cleanup.\n *\n * @example\n * useLockBodyScroll(isModalOpen);\n */\nexport function useLockBodyScroll(locked = true): void {\n useIsomorphicLayoutEffect(() => {\n if (!isBrowser || !locked) return;\n const original = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = original;\n };\n }, [locked]);\n}\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type DependencyList,\n type EffectCallback,\n type RefObject,\n} from \"react\";\n\nconst isBrowser = typeof window !== \"undefined\";\n\n/* -------------------------------------------------------------------------- */\n/* Lifecycle & effect helpers */\n/* -------------------------------------------------------------------------- */\n\n/**\n * `useLayoutEffect` on the client, `useEffect` on the server. Prevents the\n * \"useLayoutEffect does nothing on the server\" warning during SSR.\n *\n * @example\n * useIsomorphicLayoutEffect(() => { el.current?.focus(); }, []);\n */\nexport const useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : useEffect;\n\n/**\n * Returns a stable getter that reports whether the component is still mounted.\n * Useful to guard async state updates.\n *\n * @example\n * const isMounted = useIsMounted();\n * fetchData().then((d) => { if (isMounted()) setData(d); });\n */\nexport function useIsMounted(): () => boolean {\n const mounted = useRef(false);\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n return useCallback(() => mounted.current, []);\n}\n\n/**\n * Runs an effect exactly once, on mount.\n *\n * @example\n * useMountEffect(() => console.log(\"mounted\"));\n */\nexport function useMountEffect(effect: EffectCallback): void {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useEffect(effect, []);\n}\n\n/**\n * Like `useEffect`, but skips the first (mount) run and only fires on updates.\n *\n * @example\n * useUpdateEffect(() => console.log(\"value changed\", value), [value]);\n */\nexport function useUpdateEffect(effect: EffectCallback, deps?: DependencyList): void {\n const isFirst = useRef(true);\n useEffect(() => {\n if (isFirst.current) {\n isFirst.current = false;\n return;\n }\n return effect();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps);\n}\n\n/**\n * Returns the value from the previous render (`undefined` on first render).\n *\n * @example\n * const prevCount = usePrevious(count);\n */\nexport function usePrevious<T>(value: T): T | undefined {\n const ref = useRef<T | undefined>(undefined);\n useEffect(() => {\n ref.current = value;\n }, [value]);\n return ref.current;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Storage */\n/* -------------------------------------------------------------------------- */\n\ntype SetValue<T> = (value: T | ((prev: T) => T)) => void;\n\nfunction useStorage<T>(\n storageArea: \"localStorage\" | \"sessionStorage\",\n key: string,\n initialValue: T,\n): [T, SetValue<T>, () => void] {\n const readValue = useCallback((): T => {\n if (!isBrowser) return initialValue;\n try {\n const raw = window[storageArea].getItem(key);\n return raw === null ? initialValue : (JSON.parse(raw) as T);\n } catch {\n return initialValue;\n }\n }, [initialValue, key, storageArea]);\n\n const [storedValue, setStoredValue] = useState<T>(initialValue);\n\n // Hydrate from storage after mount (keeps server & first client render in sync).\n useEffect(() => {\n setStoredValue(readValue());\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [key]);\n\n const setValue = useCallback<SetValue<T>>(\n (value) => {\n setStoredValue((prev) => {\n const next = value instanceof Function ? value(prev) : value;\n if (isBrowser) {\n try {\n window[storageArea].setItem(key, JSON.stringify(next));\n window.dispatchEvent(\n new StorageEvent(\"storage\", { key, newValue: JSON.stringify(next) }),\n );\n } catch {\n /* ignore write errors (quota, private mode, etc.) */\n }\n }\n return next;\n });\n },\n [key, storageArea],\n );\n\n const remove = useCallback(() => {\n if (isBrowser) {\n try {\n window[storageArea].removeItem(key);\n window.dispatchEvent(new StorageEvent(\"storage\", { key, newValue: null }));\n } catch {\n /* ignore */\n }\n }\n setStoredValue(initialValue);\n }, [initialValue, key, storageArea]);\n\n // Sync across tabs / other hook instances.\n useEffect(() => {\n if (!isBrowser) return;\n const onStorage = (e: StorageEvent) => {\n if (e.key !== null && e.key !== key) return;\n setStoredValue(readValue());\n };\n window.addEventListener(\"storage\", onStorage);\n return () => window.removeEventListener(\"storage\", onStorage);\n }, [key, readValue]);\n\n return [storedValue, setValue, remove];\n}\n\n/**\n * Persistent state backed by `localStorage`, JSON-serialized and SSR-safe.\n * Returns the initial value on the server, hydrates on mount, syncs across tabs,\n * and `remove()` clears the key.\n *\n * @example\n * const [theme, setTheme, clearTheme] = useLocalStorage(\"theme\", \"light\");\n */\nexport function useLocalStorage<T>(\n key: string,\n initialValue: T,\n): [T, SetValue<T>, () => void] {\n return useStorage(\"localStorage\", key, initialValue);\n}\n\n/**\n * Same contract as {@link useLocalStorage}, backed by `sessionStorage`.\n *\n * @example\n * const [draft, setDraft, clearDraft] = useSessionStorage(\"draft\", \"\");\n */\nexport function useSessionStorage<T>(\n key: string,\n initialValue: T,\n): [T, SetValue<T>, () => void] {\n return useStorage(\"sessionStorage\", key, initialValue);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Timing: debounce / throttle / interval / timeout */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Returns a debounced copy of `value` that only updates after `delayMs` of quiet.\n *\n * @example\n * const debounced = useDebounce(query, 300);\n */\nexport function useDebounce<T>(value: T, delayMs: number): T {\n const [debounced, setDebounced] = useState<T>(value);\n useEffect(() => {\n const id = setTimeout(() => setDebounced(value), delayMs);\n return () => clearTimeout(id);\n }, [value, delayMs]);\n return debounced;\n}\n\n/**\n * Returns a debounced callback. The returned function is stable and carries a\n * `.cancel()` method to drop any pending invocation.\n *\n * @example\n * const save = useDebouncedCallback((v: string) => api.save(v), 500);\n */\nexport function useDebouncedCallback<A extends unknown[]>(\n fn: (...args: A) => void,\n delayMs: number,\n): ((...args: A) => void) & { cancel: () => void } {\n const fnRef = useRef(fn);\n useIsomorphicLayoutEffect(() => {\n fnRef.current = fn;\n }, [fn]);\n\n const timeout = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const cancel = useCallback(() => {\n if (timeout.current !== null) {\n clearTimeout(timeout.current);\n timeout.current = null;\n }\n }, []);\n\n useEffect(() => cancel, [cancel]);\n\n const debounced = useCallback(\n (...args: A) => {\n if (timeout.current !== null) clearTimeout(timeout.current);\n timeout.current = setTimeout(() => {\n timeout.current = null;\n fnRef.current(...args);\n }, delayMs);\n },\n [delayMs],\n ) as ((...args: A) => void) & { cancel: () => void };\n\n debounced.cancel = cancel;\n return debounced;\n}\n\n/**\n * Returns a throttled copy of `value` that updates at most once per `ms`.\n *\n * @example\n * const throttled = useThrottle(scrollY, 100);\n */\nexport function useThrottle<T>(value: T, ms: number): T {\n const [throttled, setThrottled] = useState<T>(value);\n const lastRan = useRef<number>(isBrowser ? Date.now() : 0);\n\n useEffect(() => {\n const remaining = ms - (Date.now() - lastRan.current);\n if (remaining <= 0) {\n setThrottled(value);\n lastRan.current = Date.now();\n return;\n }\n const id = setTimeout(() => {\n setThrottled(value);\n lastRan.current = Date.now();\n }, remaining);\n return () => clearTimeout(id);\n }, [value, ms]);\n\n return throttled;\n}\n\n/**\n * Runs `callback` every `delayMs`. Pass `null` to pause. Uses a latest-ref so\n * the callback never goes stale.\n *\n * @example\n * useInterval(() => tick(), running ? 1000 : null);\n */\nexport function useInterval(callback: () => void, delayMs: number | null): void {\n const saved = useRef(callback);\n useIsomorphicLayoutEffect(() => {\n saved.current = callback;\n }, [callback]);\n\n useEffect(() => {\n if (delayMs === null) return;\n const id = setInterval(() => saved.current(), delayMs);\n return () => clearInterval(id);\n }, [delayMs]);\n}\n\n/**\n * Runs `callback` once after `delayMs`. Pass `null` to cancel/disable.\n *\n * @example\n * useTimeout(() => setVisible(false), 3000);\n */\nexport function useTimeout(callback: () => void, delayMs: number | null): void {\n const saved = useRef(callback);\n useIsomorphicLayoutEffect(() => {\n saved.current = callback;\n }, [callback]);\n\n useEffect(() => {\n if (delayMs === null) return;\n const id = setTimeout(() => saved.current(), delayMs);\n return () => clearTimeout(id);\n }, [delayMs]);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Simple state helpers */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Boolean state with convenient controls.\n *\n * @example\n * const [on, { toggle, off }] = useToggle();\n */\nexport function useToggle(\n initial = false,\n): [boolean, { toggle: () => void; on: () => void; off: () => void; set: (v: boolean) => void }] {\n const [value, setValue] = useState(initial);\n const toggle = useCallback(() => setValue((v) => !v), []);\n const on = useCallback(() => setValue(true), []);\n const off = useCallback(() => setValue(false), []);\n const set = useCallback((v: boolean) => setValue(v), []);\n return [value, { toggle, on, off, set }];\n}\n\n/**\n * Numeric counter with increment/decrement/set/reset controls.\n *\n * @example\n * const { count, inc, dec, reset } = useCounter(0);\n */\nexport function useCounter(initial = 0): {\n count: number;\n inc: (step?: number) => void;\n dec: (step?: number) => void;\n set: (n: number) => void;\n reset: () => void;\n} {\n const [count, setCount] = useState(initial);\n const inc = useCallback((step = 1) => setCount((c) => c + step), []);\n const dec = useCallback((step = 1) => setCount((c) => c - step), []);\n const set = useCallback((n: number) => setCount(n), []);\n const reset = useCallback(() => setCount(initial), [initial]);\n return { count, inc, dec, set, reset };\n}\n\n/**\n * Open/close state, ideal for modals, drawers and menus.\n *\n * @example\n * const { isOpen, open, close } = useDisclosure();\n */\nexport function useDisclosure(initial = false): {\n isOpen: boolean;\n open: () => void;\n close: () => void;\n toggle: () => void;\n} {\n const [isOpen, setOpen] = useState(initial);\n const open = useCallback(() => setOpen(true), []);\n const close = useCallback(() => setOpen(false), []);\n const toggle = useCallback(() => setOpen((v) => !v), []);\n return { isOpen, open, close, toggle };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Browser / DOM environment */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Tracks a CSS media query. SSR-safe: returns `false` on the server, then the\n * real match after mount.\n *\n * @example\n * const isDark = useMediaQuery(\"(prefers-color-scheme: dark)\");\n */\nexport function useMediaQuery(query: string): boolean {\n const [matches, setMatches] = useState(false);\n\n useEffect(() => {\n if (!isBrowser || typeof window.matchMedia !== \"function\") return;\n const mql = window.matchMedia(query);\n const onChange = () => setMatches(mql.matches);\n onChange();\n mql.addEventListener(\"change\", onChange);\n return () => mql.removeEventListener(\"change\", onChange);\n }, [query]);\n\n return matches;\n}\n\n/**\n * Current viewport size. SSR-safe: returns `{ width: 0, height: 0 }` on server.\n *\n * @example\n * const { width } = useWindowSize();\n */\nexport function useWindowSize(): { width: number; height: number } {\n const [size, setSize] = useState<{ width: number; height: number }>({\n width: 0,\n height: 0,\n });\n\n useEffect(() => {\n if (!isBrowser) return;\n const onResize = () =>\n setSize({ width: window.innerWidth, height: window.innerHeight });\n onResize();\n window.addEventListener(\"resize\", onResize);\n return () => window.removeEventListener(\"resize\", onResize);\n }, []);\n\n return size;\n}\n\n/**\n * Current window scroll position. SSR-safe: `{ x: 0, y: 0 }` on server.\n *\n * @example\n * const { y } = useScrollPosition();\n */\nexport function useScrollPosition(): { x: number; y: number } {\n const [pos, setPos] = useState<{ x: number; y: number }>({ x: 0, y: 0 });\n\n useEffect(() => {\n if (!isBrowser) return;\n const onScroll = () => setPos({ x: window.scrollX, y: window.scrollY });\n onScroll();\n window.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => window.removeEventListener(\"scroll\", onScroll);\n }, []);\n\n return pos;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Event listener (overloaded) */\n/* -------------------------------------------------------------------------- */\n\n/** Attach a `window` event listener. */\nexport function useEventListener<K extends keyof WindowEventMap>(\n type: K,\n handler: (event: WindowEventMap[K]) => void,\n element?: undefined,\n options?: boolean | AddEventListenerOptions,\n): void;\n/** Attach a `document` event listener. */\nexport function useEventListener<K extends keyof DocumentEventMap>(\n type: K,\n handler: (event: DocumentEventMap[K]) => void,\n element: RefObject<Document | null> | Document,\n options?: boolean | AddEventListenerOptions,\n): void;\n/** Attach an event listener to an element referenced by a ref. */\nexport function useEventListener<\n K extends keyof HTMLElementEventMap,\n T extends HTMLElement,\n>(\n type: K,\n handler: (event: HTMLElementEventMap[K]) => void,\n element: RefObject<T | null> | T,\n options?: boolean | AddEventListenerOptions,\n): void;\n/**\n * Adds an event listener to `window` (default), `document`, or a ref/element,\n * using a latest-ref so the handler never goes stale.\n *\n * @example\n * useEventListener(\"keydown\", (e) => e.key === \"Escape\" && close());\n */\nexport function useEventListener(\n type: string,\n handler: (event: Event) => void,\n element?: RefObject<EventTarget | null> | EventTarget,\n options?: boolean | AddEventListenerOptions,\n): void {\n const savedHandler = useRef(handler);\n useIsomorphicLayoutEffect(() => {\n savedHandler.current = handler;\n }, [handler]);\n\n useEffect(() => {\n if (!isBrowser) return;\n const target: EventTarget | null =\n element == null\n ? window\n : \"current\" in element\n ? element.current\n : element;\n if (target == null || typeof target.addEventListener !== \"function\") return;\n\n const listener = (event: Event) => savedHandler.current(event);\n target.addEventListener(type, listener, options);\n return () => target.removeEventListener(type, listener, options);\n }, [type, element, options]);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Element interactions */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Calls `handler` when a pointer event occurs outside the referenced element.\n *\n * @example\n * useOnClickOutside(ref, () => setOpen(false));\n */\nexport function useOnClickOutside<T extends HTMLElement>(\n ref: RefObject<T | null>,\n handler: (event: MouseEvent | TouchEvent) => void,\n): void {\n const savedHandler = useRef(handler);\n useIsomorphicLayoutEffect(() => {\n savedHandler.current = handler;\n }, [handler]);\n\n useEffect(() => {\n if (!isBrowser) return;\n const listener = (event: MouseEvent | TouchEvent) => {\n const el = ref.current;\n const target = event.target as Node | null;\n if (el == null || target == null || el.contains(target)) return;\n savedHandler.current(event);\n };\n document.addEventListener(\"mousedown\", listener);\n document.addEventListener(\"touchstart\", listener, { passive: true });\n return () => {\n document.removeEventListener(\"mousedown\", listener);\n document.removeEventListener(\"touchstart\", listener);\n };\n }, [ref]);\n}\n\n/**\n * Tracks hover state of an element. Returns a ref to attach and the boolean.\n *\n * @example\n * const [ref, hovered] = useHover<HTMLButtonElement>();\n */\nexport function useHover<T extends HTMLElement>(): [RefObject<T | null>, boolean] {\n const ref = useRef<T | null>(null);\n const [hovered, setHovered] = useState(false);\n\n useEffect(() => {\n const node = ref.current;\n if (node == null) return;\n const onEnter = () => setHovered(true);\n const onLeave = () => setHovered(false);\n node.addEventListener(\"mouseenter\", onEnter);\n node.addEventListener(\"mouseleave\", onLeave);\n return () => {\n node.removeEventListener(\"mouseenter\", onEnter);\n node.removeEventListener(\"mouseleave\", onLeave);\n };\n // `ref` is a stable object and the node is read from `ref.current` (attached\n // before effects run), so subscribe once on mount instead of every render.\n }, []);\n\n return [ref, hovered];\n}\n\n/**\n * Observes an element's intersection with the viewport. Returns the ref to\n * attach, a boolean `isIntersecting`, and the raw entry.\n *\n * @example\n * const [ref, visible] = useIntersectionObserver<HTMLDivElement>({ threshold: 0.5 });\n */\nexport function useIntersectionObserver<T extends Element>(\n options?: IntersectionObserverInit,\n): [RefObject<T | null>, boolean, IntersectionObserverEntry | null] {\n const ref = useRef<T | null>(null);\n const [entry, setEntry] = useState<IntersectionObserverEntry | null>(null);\n\n const { root, rootMargin, threshold } = options ?? {};\n\n useEffect(() => {\n const node = ref.current;\n if (!isBrowser || typeof IntersectionObserver !== \"function\" || node == null) {\n return;\n }\n const observer = new IntersectionObserver(\n (entries) => {\n const first = entries[0];\n if (first) setEntry(first);\n },\n { root, rootMargin, threshold },\n );\n observer.observe(node);\n return () => observer.disconnect();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [root, rootMargin, JSON.stringify(threshold)]);\n\n return [ref, entry?.isIntersecting ?? false, entry];\n}\n\n/**\n * Returns `true` while the given key is pressed.\n *\n * @example\n * const shiftHeld = useKeyPress(\"Shift\");\n */\nexport function useKeyPress(targetKey: string): boolean {\n const [pressed, setPressed] = useState(false);\n\n useEffect(() => {\n if (!isBrowser) return;\n const down = (e: KeyboardEvent) => {\n if (e.key === targetKey) setPressed(true);\n };\n const up = (e: KeyboardEvent) => {\n if (e.key === targetKey) setPressed(false);\n };\n window.addEventListener(\"keydown\", down);\n window.addEventListener(\"keyup\", up);\n return () => {\n window.removeEventListener(\"keydown\", down);\n window.removeEventListener(\"keyup\", up);\n };\n }, [targetKey]);\n\n return pressed;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Misc utilities */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Copies text to the clipboard. Returns the last-copied value and an async\n * `copy` function resolving to a success boolean. Falls back to `execCommand`.\n *\n * @example\n * const [copied, copy] = useCopyToClipboard();\n * await copy(\"hello\");\n */\nexport function useCopyToClipboard(): [string | null, (text: string) => Promise<boolean>] {\n const [copied, setCopied] = useState<string | null>(null);\n\n const copy = useCallback(async (text: string): Promise<boolean> => {\n if (!isBrowser) return false;\n try {\n if (navigator.clipboard && typeof navigator.clipboard.writeText === \"function\") {\n await navigator.clipboard.writeText(text);\n setCopied(text);\n return true;\n }\n } catch {\n /* fall through to legacy path */\n }\n try {\n const el = document.createElement(\"textarea\");\n el.value = text;\n el.setAttribute(\"readonly\", \"\");\n el.style.position = \"absolute\";\n el.style.left = \"-9999px\";\n document.body.appendChild(el);\n el.select();\n const ok = document.execCommand(\"copy\");\n document.body.removeChild(el);\n if (ok) {\n setCopied(text);\n return true;\n }\n } catch {\n /* ignore */\n }\n setCopied(null);\n return false;\n }, []);\n\n return [copied, copy];\n}\n\n/**\n * Sets `document.title` while mounted (no-op on the server).\n *\n * @example\n * useDocumentTitle(`Inbox (${unread})`);\n */\nexport function useDocumentTitle(title: string): void {\n useIsomorphicLayoutEffect(() => {\n if (!isBrowser) return;\n document.title = title;\n }, [title]);\n}\n\n/**\n * Tracks the browser's online/offline status. SSR-safe: `true` on the server.\n *\n * @example\n * const online = useOnlineStatus();\n */\nexport function useOnlineStatus(): boolean {\n const [online, setOnline] = useState(true);\n\n useEffect(() => {\n if (!isBrowser) return;\n const update = () => setOnline(navigator.onLine);\n update();\n window.addEventListener(\"online\", update);\n window.addEventListener(\"offline\", update);\n return () => {\n window.removeEventListener(\"online\", update);\n window.removeEventListener(\"offline\", update);\n };\n }, []);\n\n return online;\n}\n\n/**\n * Returns `true` after `ms` of no user activity (mouse, keyboard, touch, scroll).\n *\n * @example\n * const idle = useIdle(60_000);\n */\nexport function useIdle(ms: number): boolean {\n const [idle, setIdle] = useState(false);\n\n useEffect(() => {\n if (!isBrowser) return;\n let timer: ReturnType<typeof setTimeout>;\n const reset = () => {\n setIdle(false);\n clearTimeout(timer);\n timer = setTimeout(() => setIdle(true), ms);\n };\n const events: Array<keyof WindowEventMap> = [\n \"mousemove\",\n \"mousedown\",\n \"keydown\",\n \"touchstart\",\n \"scroll\",\n \"wheel\",\n ];\n events.forEach((e) => window.addEventListener(e, reset, { passive: true }));\n reset();\n return () => {\n clearTimeout(timer);\n events.forEach((e) => window.removeEventListener(e, reset));\n };\n }, [ms]);\n\n return idle;\n}\n\n/**\n * Locks `document.body` scrolling while `locked` is true, restoring the prior\n * overflow on cleanup.\n *\n * @example\n * useLockBodyScroll(isModalOpen);\n */\nexport function useLockBodyScroll(locked = true): void {\n useIsomorphicLayoutEffect(() => {\n if (!isBrowser || !locked) return;\n const original = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = original;\n };\n }, [locked]);\n}\n"]}
package/package.json CHANGED
@@ -1,23 +1,69 @@
1
1
  {
2
2
  "name": "@lacspace/hooks",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Essential, SSR-safe React hooks — useLocalStorage, useDebounce, useMediaQuery, useOnClickOutside, useCopyToClipboard and 20+ more. Zero-dependency, fully typed, isomorphic.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
7
7
  "module": "./dist/index.js",
8
8
  "types": "./dist/index.d.ts",
9
- "exports": { ".": { "import": { "types": "./dist/index.d.ts", "default": "./dist/index.js" }, "require": { "types": "./dist/index.d.cts", "default": "./dist/index.cjs" } } },
10
- "files": ["dist"],
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ }
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
11
24
  "sideEffects": false,
12
- "scripts": { "build": "tsup", "prepublishOnly": "npm run build" },
13
- "keywords": ["react","react-hooks","hooks","uselocalstorage","usedebounce","usemediaquery","useonclickoutside","usecopytoclipboard","ssr","typescript","zero-dependency","isomorphic","react-use","usehooks"],
25
+ "scripts": {
26
+ "build": "tsup",
27
+ "prepublishOnly": "npm run build"
28
+ },
29
+ "keywords": [
30
+ "react",
31
+ "react-hooks",
32
+ "hooks",
33
+ "uselocalstorage",
34
+ "usedebounce",
35
+ "usemediaquery",
36
+ "useonclickoutside",
37
+ "usecopytoclipboard",
38
+ "ssr",
39
+ "typescript",
40
+ "zero-dependency",
41
+ "isomorphic",
42
+ "react-use",
43
+ "usehooks"
44
+ ],
14
45
  "author": "Lacspace <contact@lacspace.com>",
15
46
  "license": "SEE LICENSE IN LICENSE",
16
- "homepage": "https://lacspace.com/packages",
17
- "repository": { "type": "git", "url": "git+https://github.com/lacspace/npm-packages.git", "directory": "hooks" },
18
- "bugs": { "url": "https://github.com/lacspace/npm-packages/issues" },
19
- "engines": { "node": ">=18" },
20
- "peerDependencies": { "react": ">=18" },
21
- "devDependencies": { "@types/react": "^18.3.12", "react": "^18.3.1" },
22
- "publishConfig": { "access": "public" }
47
+ "homepage": "https://developer.lacspace.com/packages/hooks",
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "git+https://github.com/lacspace/npm-packages.git",
51
+ "directory": "hooks"
52
+ },
53
+ "bugs": {
54
+ "url": "https://github.com/lacspace/npm-packages/issues"
55
+ },
56
+ "engines": {
57
+ "node": ">=18"
58
+ },
59
+ "peerDependencies": {
60
+ "react": ">=18"
61
+ },
62
+ "devDependencies": {
63
+ "@types/react": "^18.3.12",
64
+ "react": "^18.3.1"
65
+ },
66
+ "publishConfig": {
67
+ "access": "public"
68
+ }
23
69
  }