@lacspace/hooks 1.0.0
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/LICENSE +51 -0
- package/README.md +123 -0
- package/dist/index.cjs +444 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +236 -0
- package/dist/index.d.ts +236 -0
- package/dist/index.js +415 -0
- package/dist/index.js.map +1 -0
- package/package.json +23 -0
|
@@ -0,0 +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"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { RefObject, useLayoutEffect, EffectCallback, DependencyList } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `useLayoutEffect` on the client, `useEffect` on the server. Prevents the
|
|
5
|
+
* "useLayoutEffect does nothing on the server" warning during SSR.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* useIsomorphicLayoutEffect(() => { el.current?.focus(); }, []);
|
|
9
|
+
*/
|
|
10
|
+
declare const useIsomorphicLayoutEffect: typeof useLayoutEffect;
|
|
11
|
+
/**
|
|
12
|
+
* Returns a stable getter that reports whether the component is still mounted.
|
|
13
|
+
* Useful to guard async state updates.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* const isMounted = useIsMounted();
|
|
17
|
+
* fetchData().then((d) => { if (isMounted()) setData(d); });
|
|
18
|
+
*/
|
|
19
|
+
declare function useIsMounted(): () => boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Runs an effect exactly once, on mount.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* useMountEffect(() => console.log("mounted"));
|
|
25
|
+
*/
|
|
26
|
+
declare function useMountEffect(effect: EffectCallback): void;
|
|
27
|
+
/**
|
|
28
|
+
* Like `useEffect`, but skips the first (mount) run and only fires on updates.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* useUpdateEffect(() => console.log("value changed", value), [value]);
|
|
32
|
+
*/
|
|
33
|
+
declare function useUpdateEffect(effect: EffectCallback, deps?: DependencyList): void;
|
|
34
|
+
/**
|
|
35
|
+
* Returns the value from the previous render (`undefined` on first render).
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* const prevCount = usePrevious(count);
|
|
39
|
+
*/
|
|
40
|
+
declare function usePrevious<T>(value: T): T | undefined;
|
|
41
|
+
type SetValue<T> = (value: T | ((prev: T) => T)) => void;
|
|
42
|
+
/**
|
|
43
|
+
* Persistent state backed by `localStorage`, JSON-serialized and SSR-safe.
|
|
44
|
+
* Returns the initial value on the server, hydrates on mount, syncs across tabs,
|
|
45
|
+
* and `remove()` clears the key.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* const [theme, setTheme, clearTheme] = useLocalStorage("theme", "light");
|
|
49
|
+
*/
|
|
50
|
+
declare function useLocalStorage<T>(key: string, initialValue: T): [T, SetValue<T>, () => void];
|
|
51
|
+
/**
|
|
52
|
+
* Same contract as {@link useLocalStorage}, backed by `sessionStorage`.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* const [draft, setDraft, clearDraft] = useSessionStorage("draft", "");
|
|
56
|
+
*/
|
|
57
|
+
declare function useSessionStorage<T>(key: string, initialValue: T): [T, SetValue<T>, () => void];
|
|
58
|
+
/**
|
|
59
|
+
* Returns a debounced copy of `value` that only updates after `delayMs` of quiet.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* const debounced = useDebounce(query, 300);
|
|
63
|
+
*/
|
|
64
|
+
declare function useDebounce<T>(value: T, delayMs: number): T;
|
|
65
|
+
/**
|
|
66
|
+
* Returns a debounced callback. The returned function is stable and carries a
|
|
67
|
+
* `.cancel()` method to drop any pending invocation.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* const save = useDebouncedCallback((v: string) => api.save(v), 500);
|
|
71
|
+
*/
|
|
72
|
+
declare function useDebouncedCallback<A extends unknown[]>(fn: (...args: A) => void, delayMs: number): ((...args: A) => void) & {
|
|
73
|
+
cancel: () => void;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Returns a throttled copy of `value` that updates at most once per `ms`.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* const throttled = useThrottle(scrollY, 100);
|
|
80
|
+
*/
|
|
81
|
+
declare function useThrottle<T>(value: T, ms: number): T;
|
|
82
|
+
/**
|
|
83
|
+
* Runs `callback` every `delayMs`. Pass `null` to pause. Uses a latest-ref so
|
|
84
|
+
* the callback never goes stale.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* useInterval(() => tick(), running ? 1000 : null);
|
|
88
|
+
*/
|
|
89
|
+
declare function useInterval(callback: () => void, delayMs: number | null): void;
|
|
90
|
+
/**
|
|
91
|
+
* Runs `callback` once after `delayMs`. Pass `null` to cancel/disable.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* useTimeout(() => setVisible(false), 3000);
|
|
95
|
+
*/
|
|
96
|
+
declare function useTimeout(callback: () => void, delayMs: number | null): void;
|
|
97
|
+
/**
|
|
98
|
+
* Boolean state with convenient controls.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* const [on, { toggle, off }] = useToggle();
|
|
102
|
+
*/
|
|
103
|
+
declare function useToggle(initial?: boolean): [boolean, {
|
|
104
|
+
toggle: () => void;
|
|
105
|
+
on: () => void;
|
|
106
|
+
off: () => void;
|
|
107
|
+
set: (v: boolean) => void;
|
|
108
|
+
}];
|
|
109
|
+
/**
|
|
110
|
+
* Numeric counter with increment/decrement/set/reset controls.
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* const { count, inc, dec, reset } = useCounter(0);
|
|
114
|
+
*/
|
|
115
|
+
declare function useCounter(initial?: number): {
|
|
116
|
+
count: number;
|
|
117
|
+
inc: (step?: number) => void;
|
|
118
|
+
dec: (step?: number) => void;
|
|
119
|
+
set: (n: number) => void;
|
|
120
|
+
reset: () => void;
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* Open/close state, ideal for modals, drawers and menus.
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* const { isOpen, open, close } = useDisclosure();
|
|
127
|
+
*/
|
|
128
|
+
declare function useDisclosure(initial?: boolean): {
|
|
129
|
+
isOpen: boolean;
|
|
130
|
+
open: () => void;
|
|
131
|
+
close: () => void;
|
|
132
|
+
toggle: () => void;
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Tracks a CSS media query. SSR-safe: returns `false` on the server, then the
|
|
136
|
+
* real match after mount.
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* const isDark = useMediaQuery("(prefers-color-scheme: dark)");
|
|
140
|
+
*/
|
|
141
|
+
declare function useMediaQuery(query: string): boolean;
|
|
142
|
+
/**
|
|
143
|
+
* Current viewport size. SSR-safe: returns `{ width: 0, height: 0 }` on server.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* const { width } = useWindowSize();
|
|
147
|
+
*/
|
|
148
|
+
declare function useWindowSize(): {
|
|
149
|
+
width: number;
|
|
150
|
+
height: number;
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* Current window scroll position. SSR-safe: `{ x: 0, y: 0 }` on server.
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* const { y } = useScrollPosition();
|
|
157
|
+
*/
|
|
158
|
+
declare function useScrollPosition(): {
|
|
159
|
+
x: number;
|
|
160
|
+
y: number;
|
|
161
|
+
};
|
|
162
|
+
/** Attach a `window` event listener. */
|
|
163
|
+
declare function useEventListener<K extends keyof WindowEventMap>(type: K, handler: (event: WindowEventMap[K]) => void, element?: undefined, options?: boolean | AddEventListenerOptions): void;
|
|
164
|
+
/** Attach a `document` event listener. */
|
|
165
|
+
declare function useEventListener<K extends keyof DocumentEventMap>(type: K, handler: (event: DocumentEventMap[K]) => void, element: RefObject<Document | null> | Document, options?: boolean | AddEventListenerOptions): void;
|
|
166
|
+
/** Attach an event listener to an element referenced by a ref. */
|
|
167
|
+
declare function useEventListener<K extends keyof HTMLElementEventMap, T extends HTMLElement>(type: K, handler: (event: HTMLElementEventMap[K]) => void, element: RefObject<T | null> | T, options?: boolean | AddEventListenerOptions): void;
|
|
168
|
+
/**
|
|
169
|
+
* Calls `handler` when a pointer event occurs outside the referenced element.
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* useOnClickOutside(ref, () => setOpen(false));
|
|
173
|
+
*/
|
|
174
|
+
declare function useOnClickOutside<T extends HTMLElement>(ref: RefObject<T | null>, handler: (event: MouseEvent | TouchEvent) => void): void;
|
|
175
|
+
/**
|
|
176
|
+
* Tracks hover state of an element. Returns a ref to attach and the boolean.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* const [ref, hovered] = useHover<HTMLButtonElement>();
|
|
180
|
+
*/
|
|
181
|
+
declare function useHover<T extends HTMLElement>(): [RefObject<T | null>, boolean];
|
|
182
|
+
/**
|
|
183
|
+
* Observes an element's intersection with the viewport. Returns the ref to
|
|
184
|
+
* attach, a boolean `isIntersecting`, and the raw entry.
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* const [ref, visible] = useIntersectionObserver<HTMLDivElement>({ threshold: 0.5 });
|
|
188
|
+
*/
|
|
189
|
+
declare function useIntersectionObserver<T extends Element>(options?: IntersectionObserverInit): [RefObject<T | null>, boolean, IntersectionObserverEntry | null];
|
|
190
|
+
/**
|
|
191
|
+
* Returns `true` while the given key is pressed.
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* const shiftHeld = useKeyPress("Shift");
|
|
195
|
+
*/
|
|
196
|
+
declare function useKeyPress(targetKey: string): boolean;
|
|
197
|
+
/**
|
|
198
|
+
* Copies text to the clipboard. Returns the last-copied value and an async
|
|
199
|
+
* `copy` function resolving to a success boolean. Falls back to `execCommand`.
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* const [copied, copy] = useCopyToClipboard();
|
|
203
|
+
* await copy("hello");
|
|
204
|
+
*/
|
|
205
|
+
declare function useCopyToClipboard(): [string | null, (text: string) => Promise<boolean>];
|
|
206
|
+
/**
|
|
207
|
+
* Sets `document.title` while mounted (no-op on the server).
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* useDocumentTitle(`Inbox (${unread})`);
|
|
211
|
+
*/
|
|
212
|
+
declare function useDocumentTitle(title: string): void;
|
|
213
|
+
/**
|
|
214
|
+
* Tracks the browser's online/offline status. SSR-safe: `true` on the server.
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* const online = useOnlineStatus();
|
|
218
|
+
*/
|
|
219
|
+
declare function useOnlineStatus(): boolean;
|
|
220
|
+
/**
|
|
221
|
+
* Returns `true` after `ms` of no user activity (mouse, keyboard, touch, scroll).
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* const idle = useIdle(60_000);
|
|
225
|
+
*/
|
|
226
|
+
declare function useIdle(ms: number): boolean;
|
|
227
|
+
/**
|
|
228
|
+
* Locks `document.body` scrolling while `locked` is true, restoring the prior
|
|
229
|
+
* overflow on cleanup.
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* useLockBodyScroll(isModalOpen);
|
|
233
|
+
*/
|
|
234
|
+
declare function useLockBodyScroll(locked?: boolean): void;
|
|
235
|
+
|
|
236
|
+
export { useCopyToClipboard, useCounter, useDebounce, useDebouncedCallback, useDisclosure, useDocumentTitle, useEventListener, useHover, useIdle, useIntersectionObserver, useInterval, useIsMounted, useIsomorphicLayoutEffect, useKeyPress, useLocalStorage, useLockBodyScroll, useMediaQuery, useMountEffect, useOnClickOutside, useOnlineStatus, usePrevious, useScrollPosition, useSessionStorage, useThrottle, useTimeout, useToggle, useUpdateEffect, useWindowSize };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { RefObject, useLayoutEffect, EffectCallback, DependencyList } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `useLayoutEffect` on the client, `useEffect` on the server. Prevents the
|
|
5
|
+
* "useLayoutEffect does nothing on the server" warning during SSR.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* useIsomorphicLayoutEffect(() => { el.current?.focus(); }, []);
|
|
9
|
+
*/
|
|
10
|
+
declare const useIsomorphicLayoutEffect: typeof useLayoutEffect;
|
|
11
|
+
/**
|
|
12
|
+
* Returns a stable getter that reports whether the component is still mounted.
|
|
13
|
+
* Useful to guard async state updates.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* const isMounted = useIsMounted();
|
|
17
|
+
* fetchData().then((d) => { if (isMounted()) setData(d); });
|
|
18
|
+
*/
|
|
19
|
+
declare function useIsMounted(): () => boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Runs an effect exactly once, on mount.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* useMountEffect(() => console.log("mounted"));
|
|
25
|
+
*/
|
|
26
|
+
declare function useMountEffect(effect: EffectCallback): void;
|
|
27
|
+
/**
|
|
28
|
+
* Like `useEffect`, but skips the first (mount) run and only fires on updates.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* useUpdateEffect(() => console.log("value changed", value), [value]);
|
|
32
|
+
*/
|
|
33
|
+
declare function useUpdateEffect(effect: EffectCallback, deps?: DependencyList): void;
|
|
34
|
+
/**
|
|
35
|
+
* Returns the value from the previous render (`undefined` on first render).
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* const prevCount = usePrevious(count);
|
|
39
|
+
*/
|
|
40
|
+
declare function usePrevious<T>(value: T): T | undefined;
|
|
41
|
+
type SetValue<T> = (value: T | ((prev: T) => T)) => void;
|
|
42
|
+
/**
|
|
43
|
+
* Persistent state backed by `localStorage`, JSON-serialized and SSR-safe.
|
|
44
|
+
* Returns the initial value on the server, hydrates on mount, syncs across tabs,
|
|
45
|
+
* and `remove()` clears the key.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* const [theme, setTheme, clearTheme] = useLocalStorage("theme", "light");
|
|
49
|
+
*/
|
|
50
|
+
declare function useLocalStorage<T>(key: string, initialValue: T): [T, SetValue<T>, () => void];
|
|
51
|
+
/**
|
|
52
|
+
* Same contract as {@link useLocalStorage}, backed by `sessionStorage`.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* const [draft, setDraft, clearDraft] = useSessionStorage("draft", "");
|
|
56
|
+
*/
|
|
57
|
+
declare function useSessionStorage<T>(key: string, initialValue: T): [T, SetValue<T>, () => void];
|
|
58
|
+
/**
|
|
59
|
+
* Returns a debounced copy of `value` that only updates after `delayMs` of quiet.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* const debounced = useDebounce(query, 300);
|
|
63
|
+
*/
|
|
64
|
+
declare function useDebounce<T>(value: T, delayMs: number): T;
|
|
65
|
+
/**
|
|
66
|
+
* Returns a debounced callback. The returned function is stable and carries a
|
|
67
|
+
* `.cancel()` method to drop any pending invocation.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* const save = useDebouncedCallback((v: string) => api.save(v), 500);
|
|
71
|
+
*/
|
|
72
|
+
declare function useDebouncedCallback<A extends unknown[]>(fn: (...args: A) => void, delayMs: number): ((...args: A) => void) & {
|
|
73
|
+
cancel: () => void;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Returns a throttled copy of `value` that updates at most once per `ms`.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* const throttled = useThrottle(scrollY, 100);
|
|
80
|
+
*/
|
|
81
|
+
declare function useThrottle<T>(value: T, ms: number): T;
|
|
82
|
+
/**
|
|
83
|
+
* Runs `callback` every `delayMs`. Pass `null` to pause. Uses a latest-ref so
|
|
84
|
+
* the callback never goes stale.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* useInterval(() => tick(), running ? 1000 : null);
|
|
88
|
+
*/
|
|
89
|
+
declare function useInterval(callback: () => void, delayMs: number | null): void;
|
|
90
|
+
/**
|
|
91
|
+
* Runs `callback` once after `delayMs`. Pass `null` to cancel/disable.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* useTimeout(() => setVisible(false), 3000);
|
|
95
|
+
*/
|
|
96
|
+
declare function useTimeout(callback: () => void, delayMs: number | null): void;
|
|
97
|
+
/**
|
|
98
|
+
* Boolean state with convenient controls.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* const [on, { toggle, off }] = useToggle();
|
|
102
|
+
*/
|
|
103
|
+
declare function useToggle(initial?: boolean): [boolean, {
|
|
104
|
+
toggle: () => void;
|
|
105
|
+
on: () => void;
|
|
106
|
+
off: () => void;
|
|
107
|
+
set: (v: boolean) => void;
|
|
108
|
+
}];
|
|
109
|
+
/**
|
|
110
|
+
* Numeric counter with increment/decrement/set/reset controls.
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* const { count, inc, dec, reset } = useCounter(0);
|
|
114
|
+
*/
|
|
115
|
+
declare function useCounter(initial?: number): {
|
|
116
|
+
count: number;
|
|
117
|
+
inc: (step?: number) => void;
|
|
118
|
+
dec: (step?: number) => void;
|
|
119
|
+
set: (n: number) => void;
|
|
120
|
+
reset: () => void;
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* Open/close state, ideal for modals, drawers and menus.
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* const { isOpen, open, close } = useDisclosure();
|
|
127
|
+
*/
|
|
128
|
+
declare function useDisclosure(initial?: boolean): {
|
|
129
|
+
isOpen: boolean;
|
|
130
|
+
open: () => void;
|
|
131
|
+
close: () => void;
|
|
132
|
+
toggle: () => void;
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Tracks a CSS media query. SSR-safe: returns `false` on the server, then the
|
|
136
|
+
* real match after mount.
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* const isDark = useMediaQuery("(prefers-color-scheme: dark)");
|
|
140
|
+
*/
|
|
141
|
+
declare function useMediaQuery(query: string): boolean;
|
|
142
|
+
/**
|
|
143
|
+
* Current viewport size. SSR-safe: returns `{ width: 0, height: 0 }` on server.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* const { width } = useWindowSize();
|
|
147
|
+
*/
|
|
148
|
+
declare function useWindowSize(): {
|
|
149
|
+
width: number;
|
|
150
|
+
height: number;
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* Current window scroll position. SSR-safe: `{ x: 0, y: 0 }` on server.
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* const { y } = useScrollPosition();
|
|
157
|
+
*/
|
|
158
|
+
declare function useScrollPosition(): {
|
|
159
|
+
x: number;
|
|
160
|
+
y: number;
|
|
161
|
+
};
|
|
162
|
+
/** Attach a `window` event listener. */
|
|
163
|
+
declare function useEventListener<K extends keyof WindowEventMap>(type: K, handler: (event: WindowEventMap[K]) => void, element?: undefined, options?: boolean | AddEventListenerOptions): void;
|
|
164
|
+
/** Attach a `document` event listener. */
|
|
165
|
+
declare function useEventListener<K extends keyof DocumentEventMap>(type: K, handler: (event: DocumentEventMap[K]) => void, element: RefObject<Document | null> | Document, options?: boolean | AddEventListenerOptions): void;
|
|
166
|
+
/** Attach an event listener to an element referenced by a ref. */
|
|
167
|
+
declare function useEventListener<K extends keyof HTMLElementEventMap, T extends HTMLElement>(type: K, handler: (event: HTMLElementEventMap[K]) => void, element: RefObject<T | null> | T, options?: boolean | AddEventListenerOptions): void;
|
|
168
|
+
/**
|
|
169
|
+
* Calls `handler` when a pointer event occurs outside the referenced element.
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* useOnClickOutside(ref, () => setOpen(false));
|
|
173
|
+
*/
|
|
174
|
+
declare function useOnClickOutside<T extends HTMLElement>(ref: RefObject<T | null>, handler: (event: MouseEvent | TouchEvent) => void): void;
|
|
175
|
+
/**
|
|
176
|
+
* Tracks hover state of an element. Returns a ref to attach and the boolean.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* const [ref, hovered] = useHover<HTMLButtonElement>();
|
|
180
|
+
*/
|
|
181
|
+
declare function useHover<T extends HTMLElement>(): [RefObject<T | null>, boolean];
|
|
182
|
+
/**
|
|
183
|
+
* Observes an element's intersection with the viewport. Returns the ref to
|
|
184
|
+
* attach, a boolean `isIntersecting`, and the raw entry.
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* const [ref, visible] = useIntersectionObserver<HTMLDivElement>({ threshold: 0.5 });
|
|
188
|
+
*/
|
|
189
|
+
declare function useIntersectionObserver<T extends Element>(options?: IntersectionObserverInit): [RefObject<T | null>, boolean, IntersectionObserverEntry | null];
|
|
190
|
+
/**
|
|
191
|
+
* Returns `true` while the given key is pressed.
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* const shiftHeld = useKeyPress("Shift");
|
|
195
|
+
*/
|
|
196
|
+
declare function useKeyPress(targetKey: string): boolean;
|
|
197
|
+
/**
|
|
198
|
+
* Copies text to the clipboard. Returns the last-copied value and an async
|
|
199
|
+
* `copy` function resolving to a success boolean. Falls back to `execCommand`.
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* const [copied, copy] = useCopyToClipboard();
|
|
203
|
+
* await copy("hello");
|
|
204
|
+
*/
|
|
205
|
+
declare function useCopyToClipboard(): [string | null, (text: string) => Promise<boolean>];
|
|
206
|
+
/**
|
|
207
|
+
* Sets `document.title` while mounted (no-op on the server).
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* useDocumentTitle(`Inbox (${unread})`);
|
|
211
|
+
*/
|
|
212
|
+
declare function useDocumentTitle(title: string): void;
|
|
213
|
+
/**
|
|
214
|
+
* Tracks the browser's online/offline status. SSR-safe: `true` on the server.
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* const online = useOnlineStatus();
|
|
218
|
+
*/
|
|
219
|
+
declare function useOnlineStatus(): boolean;
|
|
220
|
+
/**
|
|
221
|
+
* Returns `true` after `ms` of no user activity (mouse, keyboard, touch, scroll).
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* const idle = useIdle(60_000);
|
|
225
|
+
*/
|
|
226
|
+
declare function useIdle(ms: number): boolean;
|
|
227
|
+
/**
|
|
228
|
+
* Locks `document.body` scrolling while `locked` is true, restoring the prior
|
|
229
|
+
* overflow on cleanup.
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* useLockBodyScroll(isModalOpen);
|
|
233
|
+
*/
|
|
234
|
+
declare function useLockBodyScroll(locked?: boolean): void;
|
|
235
|
+
|
|
236
|
+
export { useCopyToClipboard, useCounter, useDebounce, useDebouncedCallback, useDisclosure, useDocumentTitle, useEventListener, useHover, useIdle, useIntersectionObserver, useInterval, useIsMounted, useIsomorphicLayoutEffect, useKeyPress, useLocalStorage, useLockBodyScroll, useMediaQuery, useMountEffect, useOnClickOutside, useOnlineStatus, usePrevious, useScrollPosition, useSessionStorage, useThrottle, useTimeout, useToggle, useUpdateEffect, useWindowSize };
|