1import { 2 ImageContentFit, 3 ImageContentPosition, 4 ImageContentPositionObject, 5 ImageContentPositionString, 6 ImageProps, 7 ImageTransition, 8} from './Image.types'; 9 10let loggedResizeModeDeprecationWarning = false; 11let loggedRepeatDeprecationWarning = false; 12let loggedFadeDurationDeprecationWarning = false; 13 14/** 15 * If the `contentFit` is not provided, it's resolved from the equivalent `resizeMode` prop 16 * that we support to provide compatibility with React Native Image. 17 */ 18export function resolveContentFit( 19 contentFit?: ImageContentFit, 20 resizeMode?: ImageProps['resizeMode'] 21): ImageContentFit { 22 if (contentFit) { 23 return contentFit; 24 } 25 if (resizeMode) { 26 if (!loggedResizeModeDeprecationWarning) { 27 console.log('[expo-image]: Prop "resizeMode" is deprecated, use "contentFit" instead'); 28 loggedResizeModeDeprecationWarning = true; 29 } 30 31 switch (resizeMode) { 32 case 'contain': 33 case 'cover': 34 return resizeMode; 35 case 'stretch': 36 return 'fill'; 37 case 'center': 38 return 'scale-down'; 39 case 'repeat': 40 if (!loggedRepeatDeprecationWarning) { 41 console.log('[expo-image]: Resize mode "repeat" is no longer supported'); 42 loggedRepeatDeprecationWarning = true; 43 } 44 } 45 } 46 return 'cover'; 47} 48 49/** 50 * It resolves a stringified form of the `contentPosition` prop to an object, 51 * which is the only form supported in the native code. 52 */ 53export function resolveContentPosition( 54 contentPosition?: ImageContentPosition 55): ImageContentPositionObject { 56 if (typeof contentPosition === 'string') { 57 const contentPositionStringMappings: Record< 58 ImageContentPositionString, 59 ImageContentPositionObject 60 > = { 61 center: { top: '50%', left: '50%' }, 62 top: { top: 0, left: '50%' }, 63 right: { top: '50%', right: 0 }, 64 bottom: { bottom: 0, left: '50%' }, 65 left: { top: '50%', left: 0 }, 66 'top center': { top: 0, left: '50%' }, 67 'top right': { top: 0, right: 0 }, 68 'top left': { top: 0, left: 0 }, 69 'right center': { top: '50%', right: 0 }, 70 'right top': { top: 0, right: 0 }, 71 'right bottom': { bottom: 0, right: 0 }, 72 'bottom center': { bottom: 0, left: '50%' }, 73 'bottom right': { bottom: 0, right: 0 }, 74 'bottom left': { bottom: 0, left: 0 }, 75 'left center': { top: '50%', left: 0 }, 76 'left top': { top: 0, left: 0 }, 77 'left bottom': { bottom: 0, left: 0 }, 78 }; 79 const contentPositionObject = contentPositionStringMappings[contentPosition]; 80 81 if (!contentPositionObject) { 82 console.warn(`[expo-image]: Content position "${contentPosition}" is invalid`); 83 return contentPositionStringMappings.center; 84 } 85 return contentPositionObject; 86 } 87 return contentPosition ?? { top: '50%', left: '50%' }; 88} 89 90/** 91 * If `transition` or `fadeDuration` is a number, it's resolved to a cross dissolve transition with the given duration. 92 * When `fadeDuration` is used, it logs an appropriate deprecation warning. 93 */ 94export function resolveTransition( 95 transition?: ImageProps['transition'], 96 fadeDuration?: ImageProps['fadeDuration'] 97): ImageTransition | null { 98 if (typeof transition === 'number') { 99 return { duration: transition }; 100 } 101 if (!transition && typeof fadeDuration === 'number') { 102 if (!loggedFadeDurationDeprecationWarning) { 103 console.warn('[expo-image]: Prop "fadeDuration" is deprecated, use "transition" instead'); 104 loggedFadeDurationDeprecationWarning = true; 105 } 106 return { duration: fadeDuration }; 107 } 108 return transition ?? null; 109} 110