@blocz/react-responsive
Version:
🔍 <Only /> displays some contents for a specific screen size
1 lines • 15.1 kB
Source Map (JSON)
{"version":3,"file":"react-responsive.cjs","names":["React","React","React","React","React","React"],"sources":["../src/sanitize.ts","../src/defaultMediaRanges.ts","../src/MediaRangesContext.tsx","../src/fromMediaRangeToMedia.ts","../src/mediaQueryBuilder.ts","../src/useMediaQuery.ts","../src/_useInternalMediaRange.ts","../src/useMediaRange.ts","../src/Only.tsx","../src/createMediaRanges.tsx"],"sourcesContent":["export type Units =\n | \"em\"\n | \"ex\"\n | \"%\"\n | \"px\"\n | \"cm\"\n | \"mm\"\n | \"in\"\n | \"pt\"\n | \"pc\"\n | \"ch\"\n | \"rem\"\n | \"vh\"\n | \"vw\"\n | \"vmin\"\n | \"vmax\";\n\nconst listOfSupportedUnits: Units[] = [\n \"em\",\n \"ex\",\n \"%\",\n \"px\",\n \"cm\",\n \"mm\",\n \"in\",\n \"pt\",\n \"pc\",\n \"ch\",\n \"rem\",\n \"vh\",\n \"vw\",\n \"vmin\",\n \"vmax\",\n];\n\ntype Directions = \"width\" | \"height\";\n\nconst listOfSupportedDirections: Directions[] = [\n \"width\",\n \"height\",\n];\n\nexport type ExposedMediaRange =\n | [number, number]\n | [number, number, Units]\n | [\n number,\n number,\n { unit?: Units; direction?: Directions },\n ];\n\nexport interface ExposedMediaRanges {\n [key: string]: ExposedMediaRange;\n}\n\nexport type MediaRange = [\n number,\n number,\n Units,\n Directions,\n];\n\nexport interface MediaRanges {\n [mediaRange: string]: MediaRange;\n}\n\nexport function sanitize(\n inMediaRanges: ExposedMediaRanges,\n): MediaRanges {\n return Object.keys(inMediaRanges).reduce<MediaRanges>(\n (mediaRanges, mediaRangeName) => {\n const mediaRange = inMediaRanges[mediaRangeName];\n\n if (\n !Array.isArray(mediaRange) ||\n mediaRange.length <= 1\n ) {\n return mediaRanges;\n }\n\n const [supposedMin, supposedMax, options, ...rest] =\n mediaRange;\n if (rest.length > 0) {\n const error = new Error(\n `The following fields \"${rest}\" have been ignored`,\n );\n console.error(error);\n }\n\n if (\n typeof supposedMin !== \"number\" ||\n typeof supposedMax !== \"number\"\n ) {\n return mediaRanges;\n }\n\n let supposedUnit: Units | undefined = undefined;\n let supposedDirection: Directions | undefined =\n undefined;\n if (typeof options === \"string\") {\n supposedUnit = options;\n } else if (typeof options === \"object\") {\n supposedDirection = options.direction;\n supposedUnit = options.unit;\n }\n\n const min = Math.min(supposedMin, supposedMax);\n const max = Math.max(supposedMin, supposedMax);\n const unit =\n supposedUnit &&\n listOfSupportedUnits.includes(supposedUnit)\n ? supposedUnit\n : \"px\";\n const direction =\n supposedDirection &&\n listOfSupportedDirections.includes(\n supposedDirection,\n )\n ? supposedDirection\n : \"width\";\n\n mediaRanges[mediaRangeName] = [\n min,\n max,\n unit,\n direction,\n ];\n mediaRanges[`${mediaRangeName}Up`] = [\n min,\n Infinity,\n unit,\n direction,\n ];\n mediaRanges[`${mediaRangeName}Down`] = [\n 0,\n max,\n unit,\n direction,\n ];\n\n return mediaRanges;\n },\n {},\n );\n}\n\n/** @deprecated Use {@link ExposedMediaRange} instead. */\nexport type ExposedBreakpoint = ExposedMediaRange;\n/** @deprecated Use {@link ExposedMediaRanges} instead. */\nexport type ExposedBreakpoints = ExposedMediaRanges;\n/** @deprecated Use {@link MediaRange} instead. */\nexport type Breakpoint = MediaRange;\n/** @deprecated Use {@link MediaRanges} instead. */\nexport type Breakpoints = MediaRanges;\n","import type { ExposedMediaRange } from \"./sanitize\";\n\nexport const DEFAULT_MEDIA_RANGES: {\n xs: ExposedMediaRange;\n sm: ExposedMediaRange;\n md: ExposedMediaRange;\n lg: ExposedMediaRange;\n xl: ExposedMediaRange;\n} = {\n xs: [0, 575, \"px\"], // Extra small devices (portrait phones)\n sm: [576, 767, \"px\"], // Small devices (landscape phones)\n md: [768, 991, \"px\"], // Medium devices (tablets)\n lg: [992, 1199, \"px\"], // Large devices (desktops)\n xl: [1200, Infinity, \"px\"], // Extra large devices (large desktops)\n};\n","import * as React from \"react\";\n\nimport type {\n ExposedMediaRanges,\n MediaRanges,\n} from \"./sanitize\";\nimport { sanitize } from \"./sanitize\";\nimport { DEFAULT_MEDIA_RANGES } from \"./defaultMediaRanges\";\n\n/**\n * @deprecated Use {@link createMediaRanges} instead. `MediaRangesContext` will be removed in\n * the next major together with {@link MediaRangesProvider}.\n */\nexport const MediaRangesContext: React.Context<MediaRanges> =\n React.createContext<MediaRanges>(\n sanitize(DEFAULT_MEDIA_RANGES),\n );\n\ninterface MediaRangesProviderProps {\n mediaRanges?: ExposedMediaRanges;\n additionalMediaRanges?: ExposedMediaRanges;\n}\n\n/** @deprecated Use {@link createMediaRanges} instead. `MediaRangesProvider` will be removed in the next major. */\nexport function MediaRangesProvider({\n mediaRanges = DEFAULT_MEDIA_RANGES,\n additionalMediaRanges,\n children,\n}: React.PropsWithChildren<MediaRangesProviderProps>): React.ReactElement {\n const value = React.useMemo(\n () =>\n sanitize({\n ...mediaRanges,\n ...additionalMediaRanges,\n }),\n [mediaRanges, additionalMediaRanges],\n );\n return (\n <MediaRangesContext.Provider value={value}>\n {children}\n </MediaRangesContext.Provider>\n );\n}\n\n/** @deprecated Use {@link MediaRangesContext} instead. */\nexport const BreakpointsContext: React.Context<MediaRanges> =\n MediaRangesContext;\n\ninterface BreakpointsProviderProps {\n /** @deprecated Use `mediaRanges` on `MediaRangesProvider` instead. */\n breakpoints?: ExposedMediaRanges;\n /** @deprecated Use `additionalMediaRanges` on `MediaRangesProvider` instead. */\n additionalBreakpoints?: ExposedMediaRanges;\n}\n\n/** @deprecated Use {@link MediaRangesProvider} instead. */\nexport function BreakpointsProvider({\n breakpoints,\n additionalBreakpoints,\n children,\n}: React.PropsWithChildren<BreakpointsProviderProps>): React.ReactElement {\n return (\n <MediaRangesProvider\n mediaRanges={breakpoints}\n additionalMediaRanges={additionalBreakpoints}\n >\n {children}\n </MediaRangesProvider>\n );\n}\n","import type { MediaRange } from \"./sanitize\";\n\nexport function fromMediaRangeToMedia(\n mediaRange: MediaRange,\n): string {\n const mediaList: string[] = [];\n const [minValue, maxValue, unit, direction] = mediaRange;\n\n // Min value\n if (minValue !== 0) {\n mediaList.push(`(min-${direction}:${minValue}${unit})`);\n }\n\n // Max value\n if (maxValue !== Infinity) {\n mediaList.push(`(max-${direction}:${maxValue}${unit})`);\n }\n\n return ` ${mediaList.join(\" and \")}`;\n}\n","import type { MediaRanges } from \"./sanitize\";\nimport { fromMediaRangeToMedia } from \"./fromMediaRangeToMedia\";\n\nexport function mediaQueryBuilder(\n mediaRanges: MediaRanges,\n) {\n return function toMediaQuery(on = \"\"): string {\n if (!on) {\n return \"\";\n }\n const rawMediaRangeNames = on.split(\" \");\n const filteredMediaRanges = rawMediaRangeNames\n .map((mediaRangeName) => mediaRanges[mediaRangeName])\n .filter(Boolean);\n const mediaQuery = filteredMediaRanges\n .map((mediaRange) =>\n fromMediaRangeToMedia(mediaRange),\n )\n .filter(Boolean)\n .join(\",\");\n if (!mediaQuery) {\n const isUniqMediaRange =\n rawMediaRangeNames.length === 1;\n console.error(\n `\"${rawMediaRangeNames.join('\", \"')}\" ${isUniqMediaRange ? \"is\" : \"are\"}n't ${\n isUniqMediaRange ? \"a \" : \"\"\n }valid media range${isUniqMediaRange ? \"\" : \"s\"}`,\n );\n }\n return mediaQuery;\n };\n}\n","import * as React from \"react\";\n\nexport function useMediaQuery(mediaQuery: string): boolean {\n const mediaQueryList = React.useMemo(\n () => matchMedia(mediaQuery),\n [mediaQuery],\n );\n\n // Those are important updates, so we don't want to use transitions on them\n return React.useSyncExternalStore(\n React.useCallback(\n (callback) => {\n // cannot use addEventListener for IE 11 and safari 13-\n mediaQueryList.addListener(callback);\n return () =>\n mediaQueryList.removeListener(callback);\n },\n [mediaQueryList],\n ),\n () => mediaQueryList.matches,\n () => mediaQueryList.matches,\n );\n}\n","import * as React from \"react\";\n\nimport type { MediaRanges } from \"./sanitize\";\nimport { mediaQueryBuilder } from \"./mediaQueryBuilder\";\nimport { useMediaQuery } from \"./useMediaQuery\";\n\nexport function useInternalMediaRange(\n mediaRanges: MediaRanges,\n on: string | undefined,\n): boolean {\n const toMediaQuery = React.useMemo(\n () => mediaQueryBuilder(mediaRanges),\n [mediaRanges],\n );\n const mediaQuery = React.useMemo(\n () => toMediaQuery(on),\n [toMediaQuery, on],\n );\n return useMediaQuery(mediaQuery || \"-\");\n}\n","import * as React from \"react\";\n\nimport { MediaRangesContext } from \"./MediaRangesContext\";\nimport { useInternalMediaRange } from \"./_useInternalMediaRange\";\n\nexport function useMediaRange(on?: string): boolean {\n const mediaRanges = React.useContext(MediaRangesContext);\n return useInternalMediaRange(mediaRanges, on);\n}\n\n/** @deprecated Use {@link useMediaRange} instead. */\nexport const useBreakpoint: (on?: string) => boolean =\n useMediaRange;\n","import * as React from \"react\";\n\nimport { useMediaRange } from \"./useMediaRange\";\nimport { useMediaQuery } from \"./useMediaQuery\";\n\nexport type OnlyProps<\n OtherProps = { [prop: string]: never },\n> = OtherProps & {\n matchMedia?: string;\n on?: string;\n as?: string | React.ComponentType<OtherProps>;\n};\n\nexport function Only<\n OtherProps = { [prop: string]: never },\n>({\n matchMedia,\n on,\n as,\n children,\n ...props\n}: React.PropsWithChildren<\n OnlyProps<OtherProps>\n>): React.ReactElement | null {\n const matchOn = useMediaRange(on);\n const matchQuery = useMediaQuery(matchMedia || \"-\");\n const isShown = matchOn || matchQuery;\n\n if (!isShown) {\n return null;\n }\n\n return React.createElement(\n // @ts-expect-error – this is a complex type\n as || React.Fragment,\n as ? (props as OtherProps) : undefined,\n children,\n );\n}\n","import * as React from \"react\";\n\nimport type {\n ExposedMediaRanges,\n MediaRanges,\n} from \"./sanitize\";\nimport { sanitize } from \"./sanitize\";\nimport type { ValidatedMediaRangeString } from \"./_validateMediaRanges\";\nimport { useInternalMediaRange } from \"./_useInternalMediaRange\";\nimport { useMediaQuery } from \"./useMediaQuery\";\n\ninterface OnlyProps<\n T extends ExposedMediaRanges,\n S extends string,\n> {\n matchMedia?: string;\n on?: ValidatedMediaRangeString<T, S>;\n}\n\ninterface CustomMediaRanges<T extends ExposedMediaRanges> {\n useMediaRange: <S extends string>(\n on: ValidatedMediaRangeString<T, S>,\n ) => boolean;\n Only: <S extends string>(\n props: React.PropsWithChildren<OnlyProps<T, S>>,\n ) => React.ReactElement | null;\n}\n\nexport function createMediaRanges<\n T extends ExposedMediaRanges,\n>(mediaRanges: T): CustomMediaRanges<T> {\n const sanitized: MediaRanges = sanitize(mediaRanges);\n\n const useMediaRange: CustomMediaRanges<T>[\"useMediaRange\"] =\n (on) => useInternalMediaRange(sanitized, on);\n\n const Only: CustomMediaRanges<T>[\"Only\"] = ({\n matchMedia,\n on,\n children,\n }) => {\n const matchOn = useInternalMediaRange(sanitized, on);\n const matchQuery = useMediaQuery(matchMedia || \"-\");\n const isShown = matchOn || matchQuery;\n\n if (!isShown) {\n return null;\n }\n\n return <React.Fragment>{children}</React.Fragment>;\n };\n\n return { useMediaRange, Only };\n}\n"],"mappings":"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"}