1import * as React from 'react'; 2import { View } from 'react-native'; 3import { normalizeColor } from './normalizeColor'; 4export default function NativeLinearGradient({ colors, locations, startPoint, endPoint, ...props }) { 5 const [layout, setLayout] = React.useState(null); 6 const { width = 1, height = 1 } = layout ?? {}; 7 // TODO(Bacon): In the future we could consider adding `backgroundRepeat: "no-repeat"`. For more 8 // browser support. 9 const linearGradientBackgroundImage = React.useMemo(() => { 10 return getLinearGradientBackgroundImage(colors, locations, startPoint, endPoint, width, height); 11 }, [colors, locations, startPoint, endPoint, width, height]); 12 return (React.createElement(View, { ...props, style: [ 13 props.style, 14 // @ts-ignore: [ts] Property 'backgroundImage' does not exist on type 'ViewStyle'. 15 { backgroundImage: linearGradientBackgroundImage }, 16 ], onLayout: (event) => { 17 const { x, y, width, height } = event.nativeEvent.layout; 18 const oldLayout = layout ?? { x: 0, y: 0, width: 1, height: 1 }; 19 // don't set new layout state unless the layout has actually changed 20 if (x !== oldLayout.x || 21 y !== oldLayout.y || 22 width !== oldLayout.width || 23 height !== oldLayout.height) { 24 setLayout({ x, y, width, height }); 25 } 26 if (props.onLayout) { 27 props.onLayout(event); 28 } 29 } })); 30} 31/** 32 * Extracted to a separate function in order to be able to test logic independently. 33 */ 34export function getLinearGradientBackgroundImage(colors, locations, startPoint, endPoint, width = 1, height = 1) { 35 const gradientColors = calculateGradientColors(colors, locations); 36 const angle = calculatePseudoAngle(width, height, startPoint, endPoint); 37 return `linear-gradient(${angle}deg, ${gradientColors.join(', ')})`; 38} 39function calculatePseudoAngle(width, height, startPoint, endPoint) { 40 const getControlPoints = () => { 41 let correctedStartPoint = [0, 0]; 42 if (Array.isArray(startPoint)) { 43 correctedStartPoint = [ 44 startPoint[0] != null ? startPoint[0] : 0.0, 45 startPoint[1] != null ? startPoint[1] : 0.0, 46 ]; 47 } 48 let correctedEndPoint = [0.0, 1.0]; 49 if (Array.isArray(endPoint)) { 50 correctedEndPoint = [ 51 endPoint[0] != null ? endPoint[0] : 0.0, 52 endPoint[1] != null ? endPoint[1] : 1.0, 53 ]; 54 } 55 return [correctedStartPoint, correctedEndPoint]; 56 }; 57 const [start, end] = getControlPoints(); 58 start[0] *= width; 59 end[0] *= width; 60 start[1] *= height; 61 end[1] *= height; 62 const py = end[1] - start[1]; 63 const px = end[0] - start[0]; 64 return 90 + (Math.atan2(py, px) * 180) / Math.PI; 65} 66function calculateGradientColors(colors, locations) { 67 return colors.map((color, index) => { 68 const hexColor = normalizeColor(color); 69 let output = hexColor; 70 if (locations && locations[index]) { 71 const location = Math.max(0, Math.min(1, locations[index])); 72 // Convert 0...1 to 0...100 73 const percentage = location * 100; 74 output += ` ${percentage}%`; 75 } 76 return output; 77 }); 78} 79//# sourceMappingURL=NativeLinearGradient.web.js.map