expo-linear-gradient 12.0.0 → 12.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -10,6 +10,10 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 12.0.1 — 2022-11-02
14
+
15
+ _This version does not introduce any user-facing changes._
16
+
13
17
  ## 12.0.0 — 2022-10-25
14
18
 
15
19
  ### 🐛 Bug fixes
@@ -3,7 +3,7 @@ apply plugin: 'kotlin-android'
3
3
  apply plugin: 'maven-publish'
4
4
 
5
5
  group = 'host.exp.exponent'
6
- version = '12.0.0'
6
+ version = '12.0.1'
7
7
 
8
8
  buildscript {
9
9
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
@@ -74,7 +74,7 @@ android {
74
74
  minSdkVersion safeExtGet("minSdkVersion", 21)
75
75
  targetSdkVersion safeExtGet("targetSdkVersion", 31)
76
76
  versionCode 17
77
- versionName "12.0.0"
77
+ versionName "12.0.1"
78
78
  }
79
79
  lintOptions {
80
80
  abortOnError false
@@ -6,5 +6,6 @@ export declare type NativeLinearGradientProps = ViewProps & PropsWithChildren<{
6
6
  startPoint?: NativeLinearGradientPoint | null;
7
7
  endPoint?: NativeLinearGradientPoint | null;
8
8
  }>;
9
+ export declare type getLinearGradientBackgroundImage = (colors: number[], width?: number, height?: number, locations?: number[] | null, startPoint?: NativeLinearGradientPoint | null, endPoint?: NativeLinearGradientPoint | null) => string;
9
10
  export declare type NativeLinearGradientPoint = [number, number];
10
11
  //# sourceMappingURL=NativeLinearGradient.types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"NativeLinearGradient.types.d.ts","sourceRoot":"","sources":["../src/NativeLinearGradient.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,oBAAY,yBAAyB,GAAG,SAAS,GAC/C,iBAAiB,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC9C,QAAQ,CAAC,EAAE,yBAAyB,GAAG,IAAI,CAAC;CAC7C,CAAC,CAAC;AAEL,oBAAY,yBAAyB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC"}
1
+ {"version":3,"file":"NativeLinearGradient.types.d.ts","sourceRoot":"","sources":["../src/NativeLinearGradient.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,oBAAY,yBAAyB,GAAG,SAAS,GAC/C,iBAAiB,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC9C,QAAQ,CAAC,EAAE,yBAAyB,GAAG,IAAI,CAAC;CAC7C,CAAC,CAAC;AAEL,oBAAY,gCAAgC,GAAG,CAC7C,MAAM,EAAE,MAAM,EAAE,EAChB,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAC3B,UAAU,CAAC,EAAE,yBAAyB,GAAG,IAAI,EAC7C,QAAQ,CAAC,EAAE,yBAAyB,GAAG,IAAI,KACxC,MAAM,CAAC;AAEZ,oBAAY,yBAAyB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"NativeLinearGradient.types.js","sourceRoot":"","sources":["../src/NativeLinearGradient.types.ts"],"names":[],"mappings":"","sourcesContent":["import { PropsWithChildren } from 'react';\nimport { ViewProps } from 'react-native';\n\nexport type NativeLinearGradientProps = ViewProps &\n PropsWithChildren<{\n colors: number[];\n locations?: number[] | null;\n startPoint?: NativeLinearGradientPoint | null;\n endPoint?: NativeLinearGradientPoint | null;\n }>;\n\nexport type NativeLinearGradientPoint = [number, number];\n"]}
1
+ {"version":3,"file":"NativeLinearGradient.types.js","sourceRoot":"","sources":["../src/NativeLinearGradient.types.ts"],"names":[],"mappings":"","sourcesContent":["import { PropsWithChildren } from 'react';\nimport { ViewProps } from 'react-native';\n\nexport type NativeLinearGradientProps = ViewProps &\n PropsWithChildren<{\n colors: number[];\n locations?: number[] | null;\n startPoint?: NativeLinearGradientPoint | null;\n endPoint?: NativeLinearGradientPoint | null;\n }>;\n\nexport type getLinearGradientBackgroundImage = (\n colors: number[],\n width?: number,\n height?: number,\n locations?: number[] | null,\n startPoint?: NativeLinearGradientPoint | null,\n endPoint?: NativeLinearGradientPoint | null\n) => string;\n\nexport type NativeLinearGradientPoint = [number, number];\n"]}
@@ -1,4 +1,8 @@
1
1
  import * as React from 'react';
2
- import { NativeLinearGradientProps } from './NativeLinearGradient.types';
2
+ import { NativeLinearGradientPoint, NativeLinearGradientProps } from './NativeLinearGradient.types';
3
3
  export default function NativeLinearGradient({ colors, locations, startPoint, endPoint, ...props }: NativeLinearGradientProps): React.ReactElement;
4
+ /**
5
+ * Extracted to a separate function in order to be able to test logic independently.
6
+ */
7
+ export declare function getLinearGradientBackgroundImage(colors: number[] | string[], locations?: number[] | null, startPoint?: NativeLinearGradientPoint | null, endPoint?: NativeLinearGradientPoint | null, width?: number, height?: number): string;
4
8
  //# sourceMappingURL=NativeLinearGradient.web.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"NativeLinearGradient.web.d.ts","sourceRoot":"","sources":["../src/NativeLinearGradient.web.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAA6B,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAGpG,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EAC3C,MAAM,EACN,SAAS,EACT,UAAU,EACV,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,yBAAyB,GAAG,KAAK,CAAC,YAAY,CAgFhD"}
1
+ {"version":3,"file":"NativeLinearGradient.web.d.ts","sourceRoot":"","sources":["../src/NativeLinearGradient.web.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAGpG,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EAC3C,MAAM,EACN,SAAS,EACT,UAAU,EACV,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,yBAAyB,GAAG,KAAK,CAAC,YAAY,CAsChD;AAED;;GAEG;AACH,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,EAC3B,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAC3B,UAAU,CAAC,EAAE,yBAAyB,GAAG,IAAI,EAC7C,QAAQ,CAAC,EAAE,yBAAyB,GAAG,IAAI,EAC3C,KAAK,GAAE,MAAU,EACjB,MAAM,GAAE,MAAU,UAKnB"}
@@ -4,54 +4,15 @@ import { normalizeColor } from './normalizeColor';
4
4
  export default function NativeLinearGradient({ colors, locations, startPoint, endPoint, ...props }) {
5
5
  const [layout, setLayout] = React.useState(null);
6
6
  const { width = 1, height = 1 } = layout ?? {};
7
- const pseudoAngle = React.useMemo(() => {
8
- const getControlPoints = () => {
9
- let correctedStartPoint = [0, 0];
10
- if (Array.isArray(startPoint)) {
11
- correctedStartPoint = [
12
- startPoint[0] != null ? startPoint[0] : 0.0,
13
- startPoint[1] != null ? startPoint[1] : 0.0,
14
- ];
15
- }
16
- let correctedEndPoint = [0.0, 1.0];
17
- if (Array.isArray(endPoint)) {
18
- correctedEndPoint = [
19
- endPoint[0] != null ? endPoint[0] : 0.0,
20
- endPoint[1] != null ? endPoint[1] : 1.0,
21
- ];
22
- }
23
- return [correctedStartPoint, correctedEndPoint];
24
- };
25
- const [start, end] = getControlPoints();
26
- start[0] *= width;
27
- end[0] *= width;
28
- start[1] *= height;
29
- end[1] *= height;
30
- const py = end[1] - start[1];
31
- const px = end[0] - start[0];
32
- return 90 + (Math.atan2(py, px) * 180) / Math.PI;
33
- }, [width, height, startPoint, endPoint]);
34
- const gradientColors = React.useMemo(() => {
35
- return colors.map((color, index) => {
36
- const hexColor = normalizeColor(color);
37
- let output = hexColor;
38
- if (locations && locations[index]) {
39
- const location = Math.max(0, Math.min(1, locations[index]));
40
- // Convert 0...1 to 0...100
41
- const percentage = location * 100;
42
- output += ` ${percentage}%`;
43
- }
44
- return output;
45
- });
46
- }, [colors, locations]);
47
- const colorStyle = gradientColors.join(',');
48
- const backgroundImage = `linear-gradient(${pseudoAngle}deg, ${colorStyle})`;
49
7
  // TODO(Bacon): In the future we could consider adding `backgroundRepeat: "no-repeat"`. For more
50
8
  // browser support.
9
+ const linearGradientBackgroundImage = React.useMemo(() => {
10
+ return getLinearGradientBackgroundImage(colors, locations, startPoint, endPoint, width, height);
11
+ }, [colors, locations, startPoint, endPoint, width, height]);
51
12
  return (React.createElement(View, { ...props, style: [
52
13
  props.style,
53
14
  // @ts-ignore: [ts] Property 'backgroundImage' does not exist on type 'ViewStyle'.
54
- { backgroundImage },
15
+ { backgroundImage: linearGradientBackgroundImage },
55
16
  ], onLayout: (event) => {
56
17
  const { x, y, width, height } = event.nativeEvent.layout;
57
18
  const oldLayout = layout ?? { x: 0, y: 0, width: 1, height: 1 };
@@ -67,4 +28,52 @@ export default function NativeLinearGradient({ colors, locations, startPoint, en
67
28
  }
68
29
  } }));
69
30
  }
31
+ /**
32
+ * Extracted to a separate function in order to be able to test logic independently.
33
+ */
34
+ export 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
+ }
39
+ function 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
+ }
66
+ function 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
+ }
70
79
  //# sourceMappingURL=NativeLinearGradient.web.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"NativeLinearGradient.web.js","sourceRoot":"","sources":["../src/NativeLinearGradient.web.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react';\nimport { LayoutRectangle, View } from 'react-native';\n\nimport { NativeLinearGradientPoint, NativeLinearGradientProps } from './NativeLinearGradient.types';\nimport { normalizeColor } from './normalizeColor';\n\nexport default function NativeLinearGradient({\n colors,\n locations,\n startPoint,\n endPoint,\n ...props\n}: NativeLinearGradientProps): React.ReactElement {\n const [layout, setLayout] = React.useState<LayoutRectangle | null>(null);\n\n const { width = 1, height = 1 } = layout ?? {};\n\n const pseudoAngle = React.useMemo(() => {\n const getControlPoints = (): NativeLinearGradientPoint[] => {\n let correctedStartPoint: NativeLinearGradientPoint = [0, 0];\n if (Array.isArray(startPoint)) {\n correctedStartPoint = [\n startPoint[0] != null ? startPoint[0] : 0.0,\n startPoint[1] != null ? startPoint[1] : 0.0,\n ];\n }\n let correctedEndPoint: NativeLinearGradientPoint = [0.0, 1.0];\n if (Array.isArray(endPoint)) {\n correctedEndPoint = [\n endPoint[0] != null ? endPoint[0] : 0.0,\n endPoint[1] != null ? endPoint[1] : 1.0,\n ];\n }\n return [correctedStartPoint, correctedEndPoint];\n };\n\n const [start, end] = getControlPoints();\n start[0] *= width;\n end[0] *= width;\n start[1] *= height;\n end[1] *= height;\n const py = end[1] - start[1];\n const px = end[0] - start[0];\n\n return 90 + (Math.atan2(py, px) * 180) / Math.PI;\n }, [width, height, startPoint, endPoint]);\n\n const gradientColors = React.useMemo(() => {\n return colors.map((color: number, index: number): string | void => {\n const hexColor = normalizeColor(color);\n let output = hexColor;\n if (locations && locations[index]) {\n const location = Math.max(0, Math.min(1, locations[index]));\n // Convert 0...1 to 0...100\n const percentage = location * 100;\n output += ` ${percentage}%`;\n }\n return output;\n });\n }, [colors, locations]);\n\n const colorStyle = gradientColors.join(',');\n const backgroundImage = `linear-gradient(${pseudoAngle}deg, ${colorStyle})`;\n // TODO(Bacon): In the future we could consider adding `backgroundRepeat: \"no-repeat\"`. For more\n // browser support.\n return (\n <View\n {...props}\n style={[\n props.style,\n // @ts-ignore: [ts] Property 'backgroundImage' does not exist on type 'ViewStyle'.\n { backgroundImage },\n ]}\n onLayout={(event) => {\n const { x, y, width, height } = event.nativeEvent.layout;\n const oldLayout = layout ?? { x: 0, y: 0, width: 1, height: 1 };\n // don't set new layout state unless the layout has actually changed\n if (\n x !== oldLayout.x ||\n y !== oldLayout.y ||\n width !== oldLayout.width ||\n height !== oldLayout.height\n ) {\n setLayout({ x, y, width, height });\n }\n\n if (props.onLayout) {\n props.onLayout(event);\n }\n }}\n />\n );\n}\n"]}
1
+ {"version":3,"file":"NativeLinearGradient.web.js","sourceRoot":"","sources":["../src/NativeLinearGradient.web.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react';\nimport { LayoutRectangle, View } from 'react-native';\n\nimport { NativeLinearGradientPoint, NativeLinearGradientProps } from './NativeLinearGradient.types';\nimport { normalizeColor } from './normalizeColor';\n\nexport default function NativeLinearGradient({\n colors,\n locations,\n startPoint,\n endPoint,\n ...props\n}: NativeLinearGradientProps): React.ReactElement {\n const [layout, setLayout] = React.useState<LayoutRectangle | null>(null);\n\n const { width = 1, height = 1 } = layout ?? {};\n\n // TODO(Bacon): In the future we could consider adding `backgroundRepeat: \"no-repeat\"`. For more\n // browser support.\n const linearGradientBackgroundImage = React.useMemo(() => {\n return getLinearGradientBackgroundImage(colors, locations, startPoint, endPoint, width, height);\n }, [colors, locations, startPoint, endPoint, width, height]);\n\n return (\n <View\n {...props}\n style={[\n props.style,\n // @ts-ignore: [ts] Property 'backgroundImage' does not exist on type 'ViewStyle'.\n { backgroundImage: linearGradientBackgroundImage },\n ]}\n onLayout={(event) => {\n const { x, y, width, height } = event.nativeEvent.layout;\n const oldLayout = layout ?? { x: 0, y: 0, width: 1, height: 1 };\n // don't set new layout state unless the layout has actually changed\n if (\n x !== oldLayout.x ||\n y !== oldLayout.y ||\n width !== oldLayout.width ||\n height !== oldLayout.height\n ) {\n setLayout({ x, y, width, height });\n }\n\n if (props.onLayout) {\n props.onLayout(event);\n }\n }}\n />\n );\n}\n\n/**\n * Extracted to a separate function in order to be able to test logic independently.\n */\nexport function getLinearGradientBackgroundImage(\n colors: number[] | string[],\n locations?: number[] | null,\n startPoint?: NativeLinearGradientPoint | null,\n endPoint?: NativeLinearGradientPoint | null,\n width: number = 1,\n height: number = 1\n) {\n const gradientColors = calculateGradientColors(colors, locations);\n const angle = calculatePseudoAngle(width, height, startPoint, endPoint);\n return `linear-gradient(${angle}deg, ${gradientColors.join(', ')})`;\n}\n\nfunction calculatePseudoAngle(\n width: number,\n height: number,\n startPoint?: NativeLinearGradientPoint | null,\n endPoint?: NativeLinearGradientPoint | null\n) {\n const getControlPoints = (): NativeLinearGradientPoint[] => {\n let correctedStartPoint: NativeLinearGradientPoint = [0, 0];\n if (Array.isArray(startPoint)) {\n correctedStartPoint = [\n startPoint[0] != null ? startPoint[0] : 0.0,\n startPoint[1] != null ? startPoint[1] : 0.0,\n ];\n }\n let correctedEndPoint: NativeLinearGradientPoint = [0.0, 1.0];\n if (Array.isArray(endPoint)) {\n correctedEndPoint = [\n endPoint[0] != null ? endPoint[0] : 0.0,\n endPoint[1] != null ? endPoint[1] : 1.0,\n ];\n }\n return [correctedStartPoint, correctedEndPoint];\n };\n\n const [start, end] = getControlPoints();\n start[0] *= width;\n end[0] *= width;\n start[1] *= height;\n end[1] *= height;\n const py = end[1] - start[1];\n const px = end[0] - start[0];\n\n return 90 + (Math.atan2(py, px) * 180) / Math.PI;\n}\n\nfunction calculateGradientColors(colors: number[] | string[], locations?: number[] | null) {\n return colors.map((color: number | string, index: number): string | void => {\n const hexColor = normalizeColor(color);\n let output = hexColor;\n if (locations && locations[index]) {\n const location = Math.max(0, Math.min(1, locations[index]));\n // Convert 0...1 to 0...100\n const percentage = location * 100;\n output += ` ${percentage}%`;\n }\n return output;\n });\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-linear-gradient",
3
- "version": "12.0.0",
3
+ "version": "12.0.1",
4
4
  "description": "Provides a React component that renders a gradient view.",
5
5
  "main": "build/LinearGradient.js",
6
6
  "types": "build/LinearGradient.d.ts",
@@ -20,7 +20,7 @@
20
20
  "gradient"
21
21
  ],
22
22
  "jest": {
23
- "preset": "expo-module-scripts/enzyme"
23
+ "preset": "expo-module-scripts"
24
24
  },
25
25
  "repository": {
26
26
  "type": "git",
@@ -34,10 +34,13 @@
34
34
  "license": "MIT",
35
35
  "homepage": "https://docs.expo.dev/versions/latest/sdk/linear-gradient/",
36
36
  "devDependencies": {
37
+ "@testing-library/jest-dom": "^5.16.5",
38
+ "@testing-library/react": "^13.4.0",
39
+ "@testing-library/react-native": "^11.3.0",
37
40
  "expo-module-scripts": "^3.0.0"
38
41
  },
39
42
  "peerDependencies": {
40
43
  "expo": "*"
41
44
  },
42
- "gitHead": "eab2b09c735fb0fc2bf734a3f29a6593adba3838"
45
+ "gitHead": "1a87dcc55895a9e16e3d4fd0fa78f2244c1d961f"
43
46
  }
@@ -9,4 +9,13 @@ export type NativeLinearGradientProps = ViewProps &
9
9
  endPoint?: NativeLinearGradientPoint | null;
10
10
  }>;
11
11
 
12
+ export type getLinearGradientBackgroundImage = (
13
+ colors: number[],
14
+ width?: number,
15
+ height?: number,
16
+ locations?: number[] | null,
17
+ startPoint?: NativeLinearGradientPoint | null,
18
+ endPoint?: NativeLinearGradientPoint | null
19
+ ) => string;
20
+
12
21
  export type NativeLinearGradientPoint = [number, number];
@@ -15,61 +15,19 @@ export default function NativeLinearGradient({
15
15
 
16
16
  const { width = 1, height = 1 } = layout ?? {};
17
17
 
18
- const pseudoAngle = React.useMemo(() => {
19
- const getControlPoints = (): NativeLinearGradientPoint[] => {
20
- let correctedStartPoint: NativeLinearGradientPoint = [0, 0];
21
- if (Array.isArray(startPoint)) {
22
- correctedStartPoint = [
23
- startPoint[0] != null ? startPoint[0] : 0.0,
24
- startPoint[1] != null ? startPoint[1] : 0.0,
25
- ];
26
- }
27
- let correctedEndPoint: NativeLinearGradientPoint = [0.0, 1.0];
28
- if (Array.isArray(endPoint)) {
29
- correctedEndPoint = [
30
- endPoint[0] != null ? endPoint[0] : 0.0,
31
- endPoint[1] != null ? endPoint[1] : 1.0,
32
- ];
33
- }
34
- return [correctedStartPoint, correctedEndPoint];
35
- };
36
-
37
- const [start, end] = getControlPoints();
38
- start[0] *= width;
39
- end[0] *= width;
40
- start[1] *= height;
41
- end[1] *= height;
42
- const py = end[1] - start[1];
43
- const px = end[0] - start[0];
44
-
45
- return 90 + (Math.atan2(py, px) * 180) / Math.PI;
46
- }, [width, height, startPoint, endPoint]);
47
-
48
- const gradientColors = React.useMemo(() => {
49
- return colors.map((color: number, index: number): string | void => {
50
- const hexColor = normalizeColor(color);
51
- let output = hexColor;
52
- if (locations && locations[index]) {
53
- const location = Math.max(0, Math.min(1, locations[index]));
54
- // Convert 0...1 to 0...100
55
- const percentage = location * 100;
56
- output += ` ${percentage}%`;
57
- }
58
- return output;
59
- });
60
- }, [colors, locations]);
61
-
62
- const colorStyle = gradientColors.join(',');
63
- const backgroundImage = `linear-gradient(${pseudoAngle}deg, ${colorStyle})`;
64
18
  // TODO(Bacon): In the future we could consider adding `backgroundRepeat: "no-repeat"`. For more
65
19
  // browser support.
20
+ const linearGradientBackgroundImage = React.useMemo(() => {
21
+ return getLinearGradientBackgroundImage(colors, locations, startPoint, endPoint, width, height);
22
+ }, [colors, locations, startPoint, endPoint, width, height]);
23
+
66
24
  return (
67
25
  <View
68
26
  {...props}
69
27
  style={[
70
28
  props.style,
71
29
  // @ts-ignore: [ts] Property 'backgroundImage' does not exist on type 'ViewStyle'.
72
- { backgroundImage },
30
+ { backgroundImage: linearGradientBackgroundImage },
73
31
  ]}
74
32
  onLayout={(event) => {
75
33
  const { x, y, width, height } = event.nativeEvent.layout;
@@ -91,3 +49,68 @@ export default function NativeLinearGradient({
91
49
  />
92
50
  );
93
51
  }
52
+
53
+ /**
54
+ * Extracted to a separate function in order to be able to test logic independently.
55
+ */
56
+ export function getLinearGradientBackgroundImage(
57
+ colors: number[] | string[],
58
+ locations?: number[] | null,
59
+ startPoint?: NativeLinearGradientPoint | null,
60
+ endPoint?: NativeLinearGradientPoint | null,
61
+ width: number = 1,
62
+ height: number = 1
63
+ ) {
64
+ const gradientColors = calculateGradientColors(colors, locations);
65
+ const angle = calculatePseudoAngle(width, height, startPoint, endPoint);
66
+ return `linear-gradient(${angle}deg, ${gradientColors.join(', ')})`;
67
+ }
68
+
69
+ function calculatePseudoAngle(
70
+ width: number,
71
+ height: number,
72
+ startPoint?: NativeLinearGradientPoint | null,
73
+ endPoint?: NativeLinearGradientPoint | null
74
+ ) {
75
+ const getControlPoints = (): NativeLinearGradientPoint[] => {
76
+ let correctedStartPoint: NativeLinearGradientPoint = [0, 0];
77
+ if (Array.isArray(startPoint)) {
78
+ correctedStartPoint = [
79
+ startPoint[0] != null ? startPoint[0] : 0.0,
80
+ startPoint[1] != null ? startPoint[1] : 0.0,
81
+ ];
82
+ }
83
+ let correctedEndPoint: NativeLinearGradientPoint = [0.0, 1.0];
84
+ if (Array.isArray(endPoint)) {
85
+ correctedEndPoint = [
86
+ endPoint[0] != null ? endPoint[0] : 0.0,
87
+ endPoint[1] != null ? endPoint[1] : 1.0,
88
+ ];
89
+ }
90
+ return [correctedStartPoint, correctedEndPoint];
91
+ };
92
+
93
+ const [start, end] = getControlPoints();
94
+ start[0] *= width;
95
+ end[0] *= width;
96
+ start[1] *= height;
97
+ end[1] *= height;
98
+ const py = end[1] - start[1];
99
+ const px = end[0] - start[0];
100
+
101
+ return 90 + (Math.atan2(py, px) * 180) / Math.PI;
102
+ }
103
+
104
+ function calculateGradientColors(colors: number[] | string[], locations?: number[] | null) {
105
+ return colors.map((color: number | string, index: number): string | void => {
106
+ const hexColor = normalizeColor(color);
107
+ let output = hexColor;
108
+ if (locations && locations[index]) {
109
+ const location = Math.max(0, Math.min(1, locations[index]));
110
+ // Convert 0...1 to 0...100
111
+ const percentage = location * 100;
112
+ output += ` ${percentage}%`;
113
+ }
114
+ return output;
115
+ });
116
+ }
package/.babelrc DELETED
@@ -1,3 +0,0 @@
1
- {
2
- "presets": ["babel-preset-expo"]
3
- }