@react-spectrum/s2
Version:
Spectrum 2 UI components in React
1 lines • 15.4 kB
Source Map (JSON)
{"mappings":"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","sources":["packages/@react-spectrum/s2/src/Image.tsx"],"sourcesContent":["import {ColorSchemeContext} from './Provider';\nimport {ContextValue, SlotProps} from 'react-aria-components';\nimport {createContext, ForwardedRef, forwardRef, HTMLAttributeReferrerPolicy, JSX, ReactNode, useCallback, useContext, useMemo, useReducer, useRef, version} from 'react';\nimport {DefaultImageGroup, ImageGroup} from './ImageCoordinator';\nimport {loadingStyle, useIsSkeleton, useLoadingAnimation} from './Skeleton';\nimport {mergeStyles} from '../style/runtime';\nimport {style} from '../style' with {type: 'macro'};\nimport {StyleString} from '../style/types';\nimport {UnsafeStyles} from './style-utils';\nimport {useLayoutEffect} from '@react-aria/utils';\nimport {useSpectrumContextProps} from './useSpectrumContextProps';\n\nexport interface ImageSource {\n /**\n * A comma-separated list of image URLs and descriptors.\n * [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/source#srcset).\n */\n srcSet?: string | undefined,\n /**\n * The color scheme for this image source. Unlike `media`, this respects the `Provider` color scheme setting.\n */\n colorScheme?: 'light' | 'dark',\n /**\n * A media query describing when the source should render.\n * [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/source#media).\n */\n media?: string | undefined,\n /**\n * A list of source sizes that describe the final rendered width of the image.\n * [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/source#sizes).\n */\n sizes?: string | undefined,\n /**\n * The mime type of the image.\n * [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/source#type).\n */\n type?: string | undefined,\n /**\n * The intrinsic width of the image.\n * [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/source#width).\n */\n width?: number,\n /**\n * The intrinsic height of the image.\n * [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/source#height).\n */\n height?: number\n}\n\nexport interface ImageProps extends UnsafeStyles, SlotProps {\n /** The URL of the image or a list of conditional sources. */\n src?: string | ImageSource[],\n // TODO\n // srcSet?: string,\n // sizes?: string,\n /** Accessible alt text for the image. */\n alt?: string,\n /**\n * Indicates if the fetching of the image must be done using a CORS request.\n * [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin).\n */\n crossOrigin?: 'anonymous' | 'use-credentials',\n /**\n * Whether the browser should decode images synchronously or asynchronously.\n * [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#decoding).\n */\n decoding?: 'async' | 'auto' | 'sync',\n /**\n * Provides a hint of the relative priority to use when fetching the image.\n * [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#fetchpriority).\n */\n fetchPriority?: 'high' | 'low' | 'auto',\n /**\n * Whether the image should be loaded immediately or lazily when scrolled into view.\n * [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#loading).\n */\n loading?: 'eager' | 'lazy',\n /**\n * A string indicating which referrer to use when fetching the resource.\n * [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#referrerpolicy).\n */\n referrerPolicy?: HTMLAttributeReferrerPolicy,\n /**\n * The intrinsic width of the image.\n * [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/img#width).\n */\n width?: number,\n /**\n * The intrinsic height of the image.\n * [See MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/img#height).\n */\n height?: number,\n /** Spectrum-defined styles, returned by the `style()` macro. */\n styles?: StyleString,\n /** A function that is called to render a fallback when the image fails to load. */\n renderError?: () => ReactNode,\n /**\n * A group of images to coordinate between, matching the group passed to the `<ImageCoordinator>` component.\n * If not provided, the default image group is used.\n */\n group?: ImageGroup,\n /**\n * Associates the image with a microdata object.\n * See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/itemprop).\n */\n itemProp?: string\n}\n\ninterface ImageContextValue extends ImageProps {\n hidden?: boolean\n}\n\nexport const ImageContext = createContext<ContextValue<Partial<ImageContextValue>, HTMLDivElement>>(null);\n\ntype ImageState = 'loading' | 'loaded' | 'revealed' | 'error';\ninterface State {\n state: ImageState,\n src: string,\n startTime: number,\n loadTime: number\n}\n\ntype Action = \n | {type: 'update', src: string}\n | {type: 'loaded'}\n | {type: 'revealed'}\n | {type: 'error'};\n\nfunction createState(src: string): State {\n return {\n state: 'loading',\n src,\n startTime: Date.now(),\n loadTime: 0\n };\n}\n\nfunction reducer(state: State, action: Action): State {\n switch (action.type) {\n case 'update': {\n return {\n state: 'loading',\n src: action.src,\n startTime: Date.now(),\n loadTime: 0\n };\n }\n case 'loaded':\n case 'error': {\n return {\n ...state,\n state: action.type\n };\n }\n case 'revealed': {\n return {\n ...state,\n state: 'revealed',\n loadTime: Date.now() - state.startTime\n };\n }\n default:\n return state;\n }\n}\n\nconst wrapperStyles = style({\n backgroundColor: 'gray-100',\n overflow: 'hidden'\n});\n\nconst imgStyles = style({\n display: 'block',\n width: 'full',\n height: 'full',\n objectFit: 'inherit',\n objectPosition: 'inherit',\n opacity: {\n default: 0,\n isRevealed: 1\n },\n transition: {\n default: 'none',\n isTransitioning: 'opacity'\n },\n transitionDuration: 500\n});\n\n/**\n * An image with support for skeleton loading and custom error states.\n */\nexport const Image = forwardRef(function Image(props: ImageProps, domRef: ForwardedRef<HTMLDivElement>): JSX.Element | null {\n [props, domRef] = useSpectrumContextProps(props, domRef, ImageContext);\n\n let {\n src: srcProp = '',\n styles,\n UNSAFE_className = '',\n UNSAFE_style,\n renderError,\n group = DefaultImageGroup,\n // TODO\n // srcSet,\n // sizes,\n alt,\n crossOrigin,\n decoding,\n fetchPriority,\n loading,\n referrerPolicy,\n slot,\n width,\n height,\n itemProp\n } = props;\n let hidden = (props as ImageContextValue).hidden;\n let colorScheme = useContext(ColorSchemeContext);\n let cacheKey = useMemo(() => typeof srcProp === 'object' ? JSON.stringify(srcProp) : srcProp, [srcProp]);\n \n let {revealAll, register, unregister, load} = useContext(group);\n let [{state, src: lastCacheKey, loadTime}, dispatch] = useReducer(reducer, cacheKey, createState);\n\n if (cacheKey !== lastCacheKey && !hidden) {\n dispatch({type: 'update', src: cacheKey});\n }\n\n if (state === 'loaded' && revealAll && !hidden) {\n dispatch({type: 'revealed'});\n }\n\n let imgRef = useRef<HTMLImageElement | null>(null);\n useLayoutEffect(() => {\n if (hidden) {\n return;\n }\n\n register(cacheKey);\n return () => {\n unregister(cacheKey);\n };\n }, [hidden, register, unregister, cacheKey]);\n\n let onLoad = useCallback(() => {\n load(cacheKey);\n dispatch({type: 'loaded'});\n }, [load, cacheKey]);\n\n let onError = useCallback(() => {\n dispatch({type: 'error'});\n unregister(cacheKey);\n }, [unregister, cacheKey]);\n\n let isSkeleton = useIsSkeleton();\n let isAnimating = isSkeleton || state === 'loading' || state === 'loaded';\n let animation = useLoadingAnimation(isAnimating);\n useLayoutEffect(() => {\n if (hidden) {\n return;\n }\n\n // In React act environments, run immediately.\n // @ts-ignore\n let isTestEnv = typeof IS_REACT_ACT_ENVIRONMENT === 'boolean' ? IS_REACT_ACT_ENVIRONMENT : typeof jest !== 'undefined';\n let runTask = isTestEnv ? fn => fn() : queueMicrotask;\n\n // If the image is already loaded, update state immediately instead of waiting for onLoad.\n let img = imgRef.current;\n if (state === 'loading' && img?.complete) {\n if (img.naturalWidth === 0 && img.naturalHeight === 0) {\n // Queue a microtask so we don't hit React's update limit.\n // TODO: is this necessary?\n runTask(onError);\n } else {\n runTask(onLoad);\n }\n }\n\n animation(domRef.current);\n });\n\n if (props.alt == null && process.env.NODE_ENV !== 'production') {\n console.warn(\n 'The `alt` prop was not provided to an image. ' +\n 'Add `alt` text for screen readers, or set `alt=\"\"` prop to indicate that the image ' +\n 'is decorative or redundant with displayed text and should not be announced by screen readers.'\n );\n }\n\n let errorState = !isSkeleton && state === 'error' && renderError?.();\n let isRevealed = state === 'revealed' && !isSkeleton;\n let isTransitioning = isRevealed && loadTime > 200;\n return useMemo(() => {\n let img = (\n <img\n {...getFetchPriorityProp(fetchPriority)}\n src={typeof srcProp === 'string' && srcProp ? srcProp : undefined}\n alt={alt}\n crossOrigin={crossOrigin}\n decoding={decoding}\n loading={loading}\n referrerPolicy={referrerPolicy}\n width={width}\n height={height}\n ref={imgRef}\n itemProp={itemProp}\n onLoad={onLoad}\n onError={onError}\n className={imgStyles({isRevealed, isTransitioning})} />\n );\n\n if (Array.isArray(srcProp)) {\n img = (\n <picture className={style({objectFit: 'inherit', objectPosition: 'inherit'})}>\n {srcProp.map((source, i) => {\n let {colorScheme: sourceColorScheme, ...sourceProps} = source;\n if (sourceColorScheme) {\n if (!colorScheme || colorScheme === 'light dark') {\n return (\n <source\n key={i}\n {...sourceProps}\n media={`${source.media ? `${source.media} and ` : ''}(prefers-color-scheme: ${sourceColorScheme})`} />\n );\n }\n\n return sourceColorScheme === colorScheme\n ? <source key={i} {...sourceProps} />\n : null;\n } else {\n return <source key={i} {...sourceProps} />;\n }\n })}\n {img}\n </picture>\n );\n }\n\n return hidden ? null : (\n <div\n ref={domRef}\n slot={slot || undefined}\n style={UNSAFE_style}\n className={UNSAFE_className + mergeStyles(wrapperStyles, styles) + ' ' + (isAnimating ? loadingStyle : '')}>\n {errorState}\n {!errorState && img}\n </div>\n );\n }, [slot, hidden, domRef, UNSAFE_style, UNSAFE_className, styles, isAnimating, errorState, alt, crossOrigin, decoding, fetchPriority, loading, referrerPolicy, width, height, onLoad, onError, isRevealed, isTransitioning, srcProp, itemProp, colorScheme]);\n});\n\nfunction getFetchPriorityProp(fetchPriority?: 'high' | 'low' | 'auto'): Record<string, string | undefined> {\n const pieces = version.split('.');\n const major = parseInt(pieces[0], 10);\n if (major >= 19) {\n return {fetchPriority};\n }\n return {fetchpriority: fetchPriority};\n}\n"],"names":[],"version":3,"file":"Image.mjs.map"}