UNPKG

seitu

Version:
61 lines (60 loc) • 1.82 kB
import { createReadableSubscription, createSubscription } from "../../core/subscription/index.mjs"; //#region src/web/media-query/index.ts /** * Reactive media query. On the server, `get()` and the SSR snapshot are * `defaultMatches` (`false`). * * @example Vanilla * ```ts twoslash title="media-query.ts" * import { createMediaQuery } from 'seitu/web' * import { useSubscription } from 'seitu/react' * * const isDesktop = createMediaQuery({ query: '(min-width: 768px)' }) * * isDesktop.subscribe(matches => { * console.log(matches) * }) * * const state = isDesktop.get() * console.log(state) * ``` * * @example React * ```tsx twoslash title="page.tsx" * import { createMediaQuery } from 'seitu/web' * import { useSubscription } from 'seitu/react' * * const isDesktop = createMediaQuery({ query: '(min-width: 768px)' }) * * function Layout() { * const matches = useSubscription(isDesktop) * return matches ? 'i am desktop' : 'i am mobile' * } * ``` * * @example Errors * ```tsx twoslash * import { createMediaQuery } from 'seitu/web' * import { useSubscription } from 'seitu/react' * * // @errors: 2362 2322 1109 * createMediaQuery({ query: '(min-width: ' }) * * // @errors: 2362 2322 2820 * createMediaQuery({ query: '(min-width: 768' }) * ``` */ function createMediaQuery(options) { const match = typeof window === "undefined" ? null : window.matchMedia(options.query); const { subscribe, notify } = createSubscription({ onFirstSubscribe: () => { match?.addEventListener("change", notify); return () => { match?.removeEventListener("change", notify); }; } }); const defaultMatches = options.defaultMatches ?? false; const get = () => match?.matches ?? defaultMatches; return createReadableSubscription(get, subscribe, notify, () => defaultMatches); } //#endregion export { createMediaQuery };