1import * as React from 'react'; 2import { Platform, processColor, ViewProps } from 'react-native'; 3 4import NativeLinearGradient from './NativeLinearGradient'; 5import { NativeLinearGradientPoint } from './NativeLinearGradient.types'; 6 7// @needsAudit 8/** 9 * An object `{ x: number; y: number }` or array `[x, y]` that represents the point 10 * at which the gradient starts or ends, as a fraction of the overall size of the gradient ranging 11 * from `0` to `1`, inclusive. 12 */ 13export type LinearGradientPoint = 14 | { 15 /** 16 * A number ranging from `0` to `1`, representing the position of gradient transformation. 17 */ 18 x: number; 19 /** 20 * A number ranging from `0` to `1`, representing the position of gradient transformation. 21 */ 22 y: number; 23 } 24 | NativeLinearGradientPoint; 25 26// @needsAudit 27export type LinearGradientProps = ViewProps & { 28 /** 29 * An array of colors that represent stops in the gradient. At least two colors are required 30 * (for a single-color background, use the `style.backgroundColor` prop on a `View` component). 31 */ 32 colors: string[]; 33 /** 34 * An array that contains `number`s ranging from `0` to `1`, inclusive, and is the same length as the `colors` property. 35 * Each number indicates a color-stop location where each respective color should be located. 36 * 37 * For example, `[0.5, 0.8]` would render: 38 * - the first color, solid, from the beginning of the gradient view to 50% through (the middle); 39 * - a gradient from the first color to the second from the 50% point to the 80% point; and 40 * - the second color, solid, from the 80% point to the end of the gradient view. 41 * 42 * > The color-stop locations must be ascending from least to greatest. 43 */ 44 locations?: number[] | null; 45 /** 46 * For example, `{ x: 0.1, y: 0.2 }` means that the gradient will start `10%` from the left and `20%` from the top. 47 * 48 * **On web**, this only changes the angle of the gradient because CSS gradients don't support changing the starting position. 49 */ 50 start?: LinearGradientPoint | null; 51 /** 52 * For example, `{ x: 0.1, y: 0.2 }` means that the gradient will end `10%` from the left and `20%` from the bottom. 53 * 54 * **On web**, this only changes the angle of the gradient because CSS gradients don't support changing the end position. 55 */ 56 end?: LinearGradientPoint | null; 57}; 58 59/** 60 * Renders a native view that transitions between multiple colors in a linear direction. 61 */ 62export class LinearGradient extends React.Component<LinearGradientProps> { 63 render() { 64 const { colors, locations, start, end, ...props } = this.props; 65 let resolvedLocations = locations; 66 if (locations && colors.length !== locations.length) { 67 console.warn('LinearGradient colors and locations props should be arrays of the same length'); 68 resolvedLocations = locations.slice(0, colors.length); 69 } 70 71 return ( 72 <NativeLinearGradient 73 {...props} 74 colors={Platform.select({ 75 web: colors as any, 76 default: colors.map(processColor), 77 })} 78 locations={resolvedLocations} 79 startPoint={_normalizePoint(start)} 80 endPoint={_normalizePoint(end)} 81 /> 82 ); 83 } 84} 85 86function _normalizePoint( 87 point: LinearGradientPoint | null | undefined 88): NativeLinearGradientPoint | undefined { 89 if (!point) { 90 return undefined; 91 } 92 93 if (Array.isArray(point) && point.length !== 2) { 94 console.warn('start and end props for LinearGradient must be of the format [x,y] or {x, y}'); 95 return undefined; 96 } 97 98 return Array.isArray(point) ? point : [point.x, point.y]; 99} 100