UNPKG

@primer/react

Version:

An implementation of GitHub's Primer Design System using React

48 lines (47 loc) 1.85 kB
import { useMedia } from "./useMedia.js"; //#region src/hooks/useResponsiveValue.ts const viewportRanges = { narrow: "(max-width: calc(768px - 0.02px))", regular: "(min-width: 768px)", wide: "(min-width: 1400px)" }; /** * Flattens all possible value types into single union type * For example, if `T` is `'none' | 'line' | Responsive<'none' | 'line' | 'filled'>`, * `FlattenResponsiveValue<T>` will be `'none' | 'line' | 'filled'` */ /** * Checks if the value is a responsive value. * In other words, is it an object with viewport range keys? */ function isResponsiveValue(value) { return typeof value === "object" && Object.keys(value).some((key) => [ "narrow", "regular", "wide" ].includes(key)); } /** * Resolves responsive values based on the current viewport width. * For example, if the current viewport width is narrow (less than 768px), the value of `{regular: 'foo', narrow: 'bar'}` will resolve to `'bar'`. * * @deprecated Prefer responsive data attributes with `getResponsiveAttributes` and CSS media queries instead. * * @example * const value = useResponsiveValue({regular: 'foo', narrow: 'bar'}) * console.log(value) // 'bar' */ function useResponsiveValue(value, fallback) { const isNarrowViewport = useMedia(viewportRanges.narrow, false); const isRegularViewport = useMedia(viewportRanges.regular, false); const isWideViewport = useMedia(viewportRanges.wide, false); if (isResponsiveValue(value)) { const responsiveValue = value; if (isNarrowViewport && "narrow" in responsiveValue) return responsiveValue.narrow; else if (isWideViewport && "wide" in responsiveValue) return responsiveValue.wide; else if (isRegularViewport && "regular" in responsiveValue) return responsiveValue.regular; else return fallback; } else return value; } //#endregion export { isResponsiveValue, useResponsiveValue, viewportRanges };