UNPKG

spicyhooks

Version:

A collection of spicy React hooks

256 lines (246 loc) 8.77 kB
interface InViewElement { id: string; element: Element | null; } interface InViewElementOptions { options?: IntersectionObserverInit; baseOn?: 'id' | 'class'; } /** * Custom React hook that tracks which element is currently intersecting the viewport * using the IntersectionObserver API. * * It observes all elements in the document that possess a specific attribute (defaulting to 'id'). * When an element enters the viewport according to the specified threshold, the hook updates * its state to reflect that element. Only the *first* element found to be intersecting * in any observation callback cycle is considered "in view". * * @param {InViewElementOptions} [config={}] - Optional configuration object. * @param {IntersectionObserverInit} [config.options={ threshold: 0.9 }] - Options to pass directly to the IntersectionObserver constructor (e.g., `threshold`, `root`, `rootMargin`). Defaults to detecting intersection when 90% of the element is visible. * @param {string} [config.baseOn='id'] - The HTML attribute name used to query for elements to observe. Defaults to 'id'. Any element with this attribute will be observed. * * @returns {InViewElement} An object containing the currently "in view" element and its ID. * - `element`: The DOM element currently intersecting the viewport based on the options, or `null` if none is actively intersecting or initially. * - `id`: The value of the `id` attribute of the intersecting element, or an empty string (`''`) if no element is intersecting or initially. * * @example * * const MyComponent = () => { * const inViewElement = useInViewElement(); * return ( * <section className='space-x-6'> * {navbarRoutes.map((route, i) => { * const elementId = route.href.replace('#', ''); * const isInView = inViewElement.id === elementId; * return ( * <Link * key={i} * href={route.href} * className={cn( * 'rounded-md px-2 py-1', * isInView && 'bg-dark', * 'hover:bg-dark/50' * )} * > * {route.title} * </Link> * ); * })} * </section> * ); // This example shows how to highlight the active navigation link based on which section is in view * }; * */ declare function useInViewElement({ options, baseOn, }?: InViewElementOptions): InViewElement; interface ScreenSize { width: number; height: number; } /** * A custom React hook that tracks the current inner dimensions (width and height) of the browser window. * * It attaches a 'resize' event listener to the window and updates the returned dimensions * whenever the window size changes. The hook automatically handles setting the initial dimensions * on mount and cleaning up the event listener on unmount. * * @returns {ScreenSize} An object containing the current screen dimensions: * - `width` (number): The current inner width of the window in pixels (`window.innerWidth`). * - `height` (number): The current inner height of the window in pixels (`window.innerHeight`). * * @example * function ResponsiveLayout() { * const { width, height } = useScreenSize(); * * const isSmallScreen = width < 600; * * return ( * <div> * <p>Current window size: {width}px x {height}px</p> * <p>{isSmallScreen && "Mobile"}</p> * </div> * ); * } */ declare function useScreenSize(): ScreenSize; /** * A custom React hook for managing a counter state. * * Provides the current count and memoized functions to increment, decrement, * and reset the count to its initial value. * * @param {number} [initialValue=0] - The starting value for the counter. Defaults to 0 if not provided. * @returns {{ * count: number; * increment: () => void; * decrement: () => void; * reset: () => void; * }} An object containing: * - `count`: The current state of the counter. * - `increment`: A memoized function that increases the count by 1. * - `decrement`: A memoized function that decreases the count by 1. * - `reset`: A memoized function that resets the count to the `initialValue`. * * @example * const { count, increment, decrement, reset } = useCounter(); * * @example * const { count: score, increment: increaseScore, decrement: decreaseScore } = useCounter(100); * * @example * function MyCounterComponent() { * const { count, increment, decrement, reset } = useCounter(5); * * return ( * <section> * <h2>Counter</h2> * <p>Current Count: {count}</p> * <button onClick={increment}>+</button> * <button onClick={decrement}>-</button> * <button onClick={reset}>Reset to 5</button> * </section> * ); * } */ declare function useCounter(initialValue?: number): { count: number; increment: () => void; decrement: () => void; reset: () => void; }; /** * A custom React hook that returns the value of a variable from the previous render cycle. * * This hook is useful for comparing props or state between renders, for example, * to trigger effects only when a specific value has changed. * * It works by storing the current value in a ref after the component renders, * so on the next render, the ref still holds the value from the previous cycle. * * @template T The type of the value being tracked. Can be any type. * * @param {T} value The value whose previous instance you want to track. * This would typically be a prop or state variable. * * @returns {T | null} The value from the previous render. * Returns `null` on the initial render, as there's no "previous" value yet. * * @example * function Counter() { * const [count, setCount] = useState(0); * * const prevCount = usePrevious(count); * * return ( * <section> * <button onClick={() => setCount((prev) => prev + 1)}>+</button> * <p>prev:{prevCount}</p> * <p>current: {count}</p> * </section> * ); * } */ declare function usePrevious<T>(value: T): T | null; /** * A custom React hook for managing a boolean (on/off) toggle state. * * Provides the current state (`isOn`) and memoized functions to control the state: * `toggle` (flips the state), `setOn` (sets state to true), and `setOff` (sets state to false). * Useful for managing UI elements like checkboxes, modals, dropdowns, etc. * * @param {boolean} [initialValue=false] - The initial state of the toggle. Defaults to `false` (off). * @returns {{ * isOn: boolean; * toggle: () => void; * setOn: () => void; * setOff: () => void; * }} An object containing: * - `isOn`: The current boolean state (`true` or `false`). * - `toggle`: A memoized function to invert the state (true -> false, false -> true). * - `setOn`: A memoized function to explicitly set the state to `true`. * - `setOff`: A memoized function to explicitly set the state to `false`. * * @example * const { isOn, toggle } = useToggle(); * console.log(isOn); // false * toggle(); // Sets isOn to true * * @example * const { isOn: isVisible, toggle: toggleVisibility, setOn: show, setOff: hide } = useToggle(true); * console.log(isVisible); // true * hide(); // Sets isVisible to false * show(); // Sets isVisible to true * * @example * function ModalExample() { * const { isOn: isModalOpen, toggle: toggleModal, setOff: closeModal } = useToggle(false); * * return ( * <section> * <button onClick={toggleModal}>Open Modal</button> * * {isModalOpen && ( * <div className="modal-backdrop"> * <div className="modal-content"> * <p>This is the modal content!</p> * <button onClick={closeModal}>Close</button> {* Using setOff *} * </div> * </div> * )} * </section> * ); * } */ declare function useToggle(initialValue?: boolean): { isOn: boolean; toggle: () => void; setOn: () => void; setOff: () => void; }; /** * A custom React hook that debounces a value. * * This hook delays updating the value until a specified time has elapsed since the last change. * Useful for delaying expensive operations like API calls based on rapidly changing input (e.g., search box). * * @template T The type of the value being debounced. * @param {T} value The value to debounce. * @param {number} delay The delay in milliseconds before the debounced value is updated. * @returns {T} The debounced value. * * @example * function CounterComponent() { * const [count, setCount] = useState(0); * * const debounceCount = useDebounce(count, 3000); * * return ( * <section> * <button onClick={() => setCount((prev) => prev + 1)}>+</button> * <p>Instant Count: {count}</p> * <p>Debounced Count: {debounceCount}</p> * </section> * ); * } */ declare function useDebounce<T>(value: T, delay: number): T; export { useCounter, useDebounce, useInViewElement, usePrevious, useScreenSize, useToggle };