"use client"; import { useCallback, useState } from "react"; import { useSsr } from "./SsrProvider.js"; import { type ElementSize } from "./types.js"; import { type ResizeListenerOptions, useResizeListener, } from "./useResizeListener.js"; /** * @since 6.0.0 */ export interface WindowSizeOptions extends Omit< ResizeListenerOptions, "disabled" | "onUpdate" > { /** * The default value to use in SSR environments for the window's height. * * @defaultValue `0` */ ssrHeight?: number; /** * The default value to use in SSR environments for the window's width. * * @defaultValue `0` */ ssrWidth?: number; /** * Set this to `true` to ignore resize events that only updated the height. * The hook can be disabled by setting this and {@link disableWidth} to * `true`. * * @defaultValue `false` */ disableHeight?: boolean; /** * Set this to `true` to ignore resize events that only updated the width. * The hook can be disabled by setting this and {@link disableHeight} to * `true`. * * @defaultValue `false` */ disableWidth?: boolean; } /** * This is just a convenience wrapper around the {@link useResizeListener}. * * @example Simple Example * ```tsx * import { useWindowSize } from "@react-md/core/useWindowSize"; * import type { ReactElement } from "react"; * import { useState } from "react"; * * function Example(): ReactElement { * const { height, width } = useWindowSize(); * * return ( * <> * The current window size: *
{JSON.stringify(size, null, 2)}
* * ); * } * ``` * * @since 6.0.0 */ export function useWindowSize(options: WindowSizeOptions = {}): ElementSize { const { once, signal, capture, passive, throttle, ssrHeight = 0, ssrWidth = 0, disableWidth, disableHeight, } = options; const ssr = useSsr(); const [size, setSize] = useState(() => { if (globalThis.window === undefined || ssr) { return { height: ssrHeight, width: ssrWidth, }; } return { height: window.innerHeight, width: window.innerWidth, }; }); useResizeListener({ once, signal, capture, passive, throttle, disabled: disableHeight && disableWidth, onUpdate: useCallback(() => { setSize((prevSize) => { const nextSize: ElementSize = { height: window.innerHeight, width: window.innerWidth, }; const isHeightChange = !disableHeight && prevSize.height !== nextSize.height; const isWidthChange = !disableWidth && prevSize.width !== nextSize.width; return isHeightChange || isWidthChange ? nextSize : prevSize; }); }, [disableHeight, disableWidth]), }); return size; }