1import { ImageStyle as RNImageStyle, ViewProps, StyleProp, ViewStyle } from 'react-native'; 2 3export type ImageSource = { 4 /** 5 * A string representing the resource identifier for the image, 6 * which could be an http address, a local file path, or the name of a static image resource. 7 */ 8 uri?: string; 9 /** 10 * An object representing the HTTP headers to send along with the request for a remote image. 11 * @platform android 12 * @platform ios 13 */ 14 headers?: Record<string, string>; 15 /** 16 * Can be specified if known at build time, in which case the value 17 * will be used to set the default `<Image/>` component dimension 18 */ 19 width?: number; 20 /** 21 * Can be specified if known at build time, in which case the value 22 * will be used to set the default `<Image/>` component dimension 23 */ 24 height?: number; 25 26 /** 27 * The blurhash string to use to generate the image. You can read more about the blurhash 28 * on [`woltapp/blurhash`](https://github.com/woltapp/blurhash) repo. Ignored when `uri` is provided. 29 * When using the blurhash, you should also provide `width` and `height` (higher values reduce performance), 30 * otherwise their default value is `16`. 31 */ 32 blurhash?: string; 33 34 /** 35 * The thumbhash string to use to generate the image placeholder. You can read more about thumbhash 36 * on the [`thumbhash website`](https://evanw.github.io/thumbhash/). Ignored when `uri` is provided. 37 */ 38 thumbhash?: string; 39 40 /** 41 * The cache key used to query and store this specific image. 42 * If not provided, the `uri` is used also as the cache key. 43 */ 44 cacheKey?: string; 45 /** 46 * The max width of the viewport for which this source should be selected. 47 * Has no effect if `source` prop is not an array or has only 1 element. 48 * Has no effect if `responsivePolicy` is not set to `static`. 49 * Ignored if `blurhash` or `thumbhash` is provided (image hashes are never selected if passed in an array). 50 * @platform web 51 */ 52 webMaxViewportWidth?: number; 53}; 54 55/** 56 * @hidden 57 */ 58export type ImageStyle = RNImageStyle; 59 60/** 61 * Determines how the image should be resized to fit its container. 62 * @hidden Described in the {@link ImageProps['contentFit']} 63 */ 64export type ImageContentFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'; 65 66/** 67 * Some props are from React Native Image that Expo Image supports (more or less) for easier migration, 68 * but all of them are deprecated and might be removed in the future. 69 */ 70export interface ImageProps extends ViewProps { 71 /** @hidden */ 72 style?: StyleProp<RNImageStyle>; 73 74 /** 75 * The image source, either a remote URL, a local file resource or a number that is the result of the `require()` function. 76 * When provided as an array of sources, the source that fits best into the container size and is closest to the screen scale 77 * will be chosen. In this case it is important to provide `width`, `height` and `scale` properties. 78 */ 79 source?: ImageSource | string | number | ImageSource[] | string[] | null; 80 81 /** 82 * An image to display while loading the proper image and no image has been displayed yet or the source is unset. 83 */ 84 placeholder?: ImageSource | string | number | ImageSource[] | string[] | null; 85 86 /** 87 * Determines how the image should be resized to fit its container. This property tells the image to fill the container 88 * in a variety of ways; such as "preserve that aspect ratio" or "stretch up and take up as much space as possible". 89 * It mirrors the CSS [`object-fit`](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) property. 90 * 91 * - `'cover'` - The image is sized to maintain its aspect ratio while filling the container box. 92 * If the image's aspect ratio does not match the aspect ratio of its box, then the object will be clipped to fit. 93 * 94 * - `'contain'` - The image is scaled down or up to maintain its aspect ratio while fitting within the container box. 95 * 96 * - `'fill'` - The image is sized to entirely fill the container box. If necessary, the image will be stretched or squished to fit. 97 * 98 * - `'none'` - The image is not resized and is centered by default. 99 * When specified, the exact position can be controlled with [`contentPosition`](#contentposition) prop. 100 * 101 * - `'scale-down'` - The image is sized as if `none` or `contain` were specified, whichever would result in a smaller concrete image size. 102 * 103 * @default 'cover' 104 */ 105 contentFit?: ImageContentFit; 106 107 /** 108 * Determines how the placeholder should be resized to fit its container 109 * @hidden Described in the {@link ImageProps['contentFit']} 110 * @default 'scale-down' 111 */ 112 placeholderContentFit?: ImageContentFit; 113 114 /** 115 * It is used together with [`contentFit`](#contentfit) to specify how the image should be positioned with x/y coordinates inside its own container. 116 * An equivalent of the CSS [`object-position`](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position) property. 117 * @default 'center' 118 */ 119 contentPosition?: ImageContentPosition; 120 121 /** 122 * Describes how the image view should transition the contents when switching the image source.\ 123 * If provided as a number, it is the duration in milliseconds of the `'cross-dissolve'` effect. 124 */ 125 transition?: ImageTransition | number | null; 126 127 /** 128 * The radius of the blur in points, `0` means no blur effect. 129 * This effect is not applied to placeholders. 130 * @default 0 131 */ 132 blurRadius?: number; 133 134 /** 135 * A color used to tint template images (a bitmap image where only the opacity matters). 136 * The color is applied to every non-transparent pixel, causing the image’s shape to adopt that color. 137 * This effect is not applied to placeholders. 138 * @default null 139 */ 140 tintColor?: string | null; 141 142 /** 143 * Priorities for completing loads. If more than one load is queued at a time, 144 * the load with the higher priority will be started first. 145 * Priorities are considered best effort, there are no guarantees about the order in which loads will start or finish. 146 * @default 'normal' 147 */ 148 priority?: 'low' | 'normal' | 'high' | null; 149 150 /** 151 * Determines whether to cache the image and where: on the disk, in the memory or both. 152 * 153 * - `'none'` - Image is not cached at all. 154 * 155 * - `'disk'` - Image is queried from the disk cache if exists, otherwise it's downloaded and then stored on the disk. 156 * 157 * - `'memory'` - Image is cached in memory. Might be useful when you render a high-resolution picture many times. 158 * Memory cache may be purged very quickly to prevent high memory usage and the risk of out of memory exceptions. 159 * 160 * - `'memory-disk'` - Image is cached in memory, but with a fallback to the disk cache. 161 * 162 * @default 'disk' 163 */ 164 cachePolicy?: 'none' | 'disk' | 'memory' | 'memory-disk' | /** @hidden */ null; 165 166 /** 167 * Controls the selection of the image source based on the container or viewport size on the web. 168 * 169 * If set to `'static'`, the browser selects the correct source based on user's viewport width. Works with static rendering. 170 * Make sure to set the `'webMaxViewportWidth'` property on each source for best results. 171 * For example, if an image occupies 1/3 of the screen width, set the `'webMaxViewportWidth'` to 3x the image width. 172 * The source with the largest `'webMaxViewportWidth'` is used even for larger viewports. 173 * 174 * If set to `'initial'`, the component will select the correct source during mount based on container size. Does not work with static rendering. 175 * 176 * If set to `'live'`, the component will select the correct source on every resize based on container size. Does not work with static rendering. 177 * 178 * @default 'static' 179 * @platform web 180 */ 181 responsivePolicy?: 'live' | 'initial' | 'static'; 182 183 /** 184 * Changing this prop resets the image view content to blank or a placeholder before loading and rendering the final image. 185 * This is especially useful for any kinds of recycling views like [FlashList](https://github.com/shopify/flash-list) 186 * to prevent showing the previous source before the new one fully loads. 187 * @default null 188 * @platform android 189 * @platform ios 190 */ 191 recyclingKey?: string | null; 192 193 /** 194 * Called when the image starts to load. 195 */ 196 onLoadStart?: () => void; 197 198 /** 199 * Called when the image load completes successfully. 200 */ 201 onLoad?: (event: ImageLoadEventData) => void; 202 203 /** 204 * Called when the image is loading. Can be called multiple times before the image has finished loading. 205 * The event object provides details on how many bytes were loaded so far and what's the expected total size. 206 */ 207 onProgress?: (event: ImageProgressEventData) => void; 208 209 /** 210 * Called on an image fetching error. 211 */ 212 onError?: (event: ImageErrorEventData) => void; 213 214 /** 215 * Called when the image load either succeeds or fails. 216 */ 217 onLoadEnd?: () => void; 218 219 // DEPRECATED 220 221 /** 222 * @deprecated Provides compatibility for [`defaultSource` from React Native Image](https://reactnative.dev/docs/image#defaultsource). 223 * Use [`placeholder`](#placeholder) prop instead. 224 */ 225 defaultSource?: ImageSource | null; 226 227 /** 228 * @deprecated Provides compatibility for [`loadingIndicatorSource` from React Native Image](https://reactnative.dev/docs/image#loadingindicatorsource). 229 * Use [`placeholder`](#placeholder) prop instead. 230 */ 231 loadingIndicatorSource?: ImageSource | null; 232 233 /** 234 * @deprecated Provides compatibility for [`resizeMode` from React Native Image](https://reactnative.dev/docs/image#resizemode). 235 * Note that `"repeat"` option is not supported at all. 236 * Use the more powerful [`contentFit`](#contentfit) and [`contentPosition`](#contentposition) props instead. 237 */ 238 resizeMode?: 'cover' | 'contain' | 'stretch' | 'repeat' | 'center'; 239 240 /** 241 * @deprecated Provides compatibility for [`fadeDuration` from React Native Image](https://reactnative.dev/docs/image#fadeduration-android). 242 * Instead use [`transition`](#transition) with the provided duration. 243 */ 244 fadeDuration?: number; 245 246 /** 247 * Whether this View should be focusable with a non-touch input device and receive focus with a hardware keyboard. 248 * @default false 249 * @platform android 250 */ 251 focusable?: boolean; 252 253 /** 254 * When true, indicates that the view is an accessibility element. 255 * When a view is an accessibility element, it groups its children into a single selectable component. 256 * 257 * On Android, the `accessible` property will be translated into the native `isScreenReaderFocusable`, 258 * so it's only affecting the screen readers behaviour. 259 * @default false 260 * @platform android 261 * @platform ios 262 */ 263 accessible?: boolean; 264 265 /** 266 * The text that's read by the screen reader when the user interacts with the image. Sets the the `alt` tag on web which is used for web crawlers and link traversal. 267 * @default undefined 268 */ 269 accessibilityLabel?: string; 270 271 /** 272 * The text that's read by the screen reader when the user interacts with the image. Sets the the `alt` tag on web which is used for web crawlers and link traversal. Is an alias for `accessibilityLabel`. 273 * 274 * @alias accessibilityLabel 275 * @default undefined 276 */ 277 alt?: string; 278 279 /** 280 * Enables Live Text interaction with the image. Check official [Apple documentation](https://developer.apple.com/documentation/visionkit/enabling_live_text_interactions_with_images) for more details. 281 * @default false 282 * @platform ios 16.0+ 283 */ 284 enableLiveTextInteraction?: boolean; 285 286 /** 287 * Whether the image should be downscaled to match the size of the view container. 288 * Turning off this functionality could negatively impact the application's performance, particularly when working with large assets. 289 * However, it would result in smoother image resizing, and end-users would always have access to the highest possible asset quality. 290 * 291 * Downscaling is never used when the `contentFit` prop is set to `none` or `fill`. 292 * @default true 293 * @platform android 294 */ 295 allowDownscaling?: boolean; 296} 297 298/** 299 * It narrows down some props to types expected by the native/web side. 300 * @hidden 301 */ 302export interface ImageNativeProps extends ImageProps { 303 style?: RNImageStyle; 304 source?: ImageSource[]; 305 placeholder?: ImageSource[]; 306 contentPosition?: ImageContentPositionObject; 307 transition?: ImageTransition | null; 308} 309 310/** 311 * A value that represents the relative position of a single axis. 312 * 313 * If `number`, it is a distance in points (logical pixels) from the respective edge.\ 314 * If `string`, it must be a percentage value where `'100%'` is the difference in size between the container and the image along the respective axis, 315 * or `'center'` which is an alias for `'50%'` that is the default value. You can read more regarding percentages on the MDN docs for 316 * [`background-position`](https://developer.mozilla.org/en-US/docs/Web/CSS/background-position#regarding_percentages) that describes this concept well. 317 */ 318export type ImageContentPositionValue = number | string | `${number}%` | `${number}` | 'center'; 319 320// eslint-disable 321// prettier-ignore 322/** 323 * Specifies the position of the image inside its container. One value controls the x-axis and the second value controls the y-axis. 324 * 325 * Additionally, it supports stringified shorthand form that specifies the edges to which to align the image content:\ 326 * `'center'`, `'top'`, `'right'`, `'bottom'`, `'left'`, `'top center'`, `'top right'`, `'top left'`, `'right center'`, `'right top'`, 327 * `'right bottom'`, `'bottom center'`, `'bottom right'`, `'bottom left'`, `'left center'`, `'left top'`, `'left bottom'`.\ 328 * If only one keyword is provided, then the other dimension is set to `'center'` (`'50%'`), so the image is placed in the middle of the specified edge.\ 329 * As an example, `'top right'` is the same as `{ top: 0, right: 0 }` and `'bottom'` is the same as `{ bottom: 0, left: '50%' }`. 330 */ 331export type ImageContentPosition = 332 /** 333 * An object that positions the image relatively to the top-right corner. 334 */ 335 { 336 top?: ImageContentPositionValue; 337 right?: ImageContentPositionValue; 338 } | 339 /** 340 * An object that positions the image relatively to the top-left corner. 341 */ 342 { 343 top?: ImageContentPositionValue; 344 left?: ImageContentPositionValue; 345 } | 346 /** 347 * An object that positions the image relatively to the bottom-right corner. 348 */ 349 { 350 bottom?: ImageContentPositionValue; 351 right?: ImageContentPositionValue; 352 } | 353 /** 354 * An object that positions the image relatively to the bottom-left corner. 355 */ 356 { 357 bottom?: ImageContentPositionValue; 358 left?: ImageContentPositionValue; 359 } 360 | ImageContentPositionString; 361// eslint-enable 362 363export interface ImageBackgroundProps extends Omit<ImageProps, 'style'> { 364 /** The style of the image container */ 365 style?: StyleProp<ViewStyle> | undefined; 366 /** Style object for the image */ 367 imageStyle?: StyleProp<RNImageStyle> | undefined; 368 /** @hidden */ 369 children?: React.ReactNode | undefined; 370} 371 372/** 373 * @hidden It's described as part of {@link ImageContentPosition}. 374 */ 375export type ImageContentPositionString = 376 | 'center' 377 | 'top' 378 | 'right' 379 | 'bottom' 380 | 'left' 381 | 'top center' 382 | 'top right' 383 | 'top left' 384 | 'right center' 385 | 'right top' 386 | 'right bottom' 387 | 'bottom center' 388 | 'bottom right' 389 | 'bottom left' 390 | 'left center' 391 | 'left top' 392 | 'left bottom'; 393 394type OnlyObject<T> = T extends object ? T : never; 395 396/** 397 * @hidden It's a conditional type that matches only objects of {@link ImageContentPosition}. 398 */ 399export type ImageContentPositionObject = OnlyObject<ImageContentPosition>; 400 401/** 402 * An object that describes the smooth transition when switching the image source. 403 */ 404export type ImageTransition = { 405 /** 406 * The duration of the transition in milliseconds. 407 * @default 0 408 */ 409 duration?: number; 410 411 /** 412 * Specifies the speed curve of the transition effect and how intermediate values are calculated. 413 * @default 'ease-in-out' 414 */ 415 timing?: 'ease-in-out' | 'ease-in' | 'ease-out' | 'linear'; 416 417 /** 418 * An animation effect used for transition. 419 * @default 'cross-dissolve' 420 * 421 * On Android, only `'cross-dissolve'` is supported. 422 * On Web, `'curl-up'` and `'curl-down'` effects are not supported. 423 */ 424 effect?: 425 | 'cross-dissolve' 426 | 'flip-from-top' 427 | 'flip-from-right' 428 | 'flip-from-bottom' 429 | 'flip-from-left' 430 | 'curl-up' 431 | 'curl-down' 432 | null; 433}; 434 435export type ImageLoadEventData = { 436 cacheType: 'none' | 'disk' | 'memory'; 437 source: { 438 url: string; 439 width: number; 440 height: number; 441 mediaType: string | null; 442 }; 443}; 444 445export type ImageProgressEventData = { 446 loaded: number; 447 total: number; 448}; 449 450export type ImageErrorEventData = { 451 error: string; 452}; 453