@amazon-devices/expo-linear-gradient 2.0.1758683737

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.
Files changed (69) hide show
  1. package/.eslintrc.js +2 -0
  2. package/CHANGELOG.md +209 -0
  3. package/CMakeLists.txt +52 -0
  4. package/LICENSE +7 -0
  5. package/README.kepler.md +69 -0
  6. package/README.md +41 -0
  7. package/THIRD_PARTY_NOTICES.txt +24 -0
  8. package/android/build.gradle +107 -0
  9. package/android/src/main/AndroidManifest.xml +3 -0
  10. package/android/src/main/java/expo/modules/lineargradient/LinearGradientModule.kt +36 -0
  11. package/android/src/main/java/expo/modules/lineargradient/LinearGradientView.java +117 -0
  12. package/build/LinearGradient.d.ts +60 -0
  13. package/build/LinearGradient.d.ts.map +1 -0
  14. package/build/LinearGradient.js +31 -0
  15. package/build/LinearGradient.js.map +1 -0
  16. package/build/NativeLinearGradient.android.d.ts +4 -0
  17. package/build/NativeLinearGradient.android.d.ts.map +1 -0
  18. package/build/NativeLinearGradient.android.js +27 -0
  19. package/build/NativeLinearGradient.android.js.map +1 -0
  20. package/build/NativeLinearGradient.d.ts +4 -0
  21. package/build/NativeLinearGradient.d.ts.map +1 -0
  22. package/build/NativeLinearGradient.ios.d.ts +5 -0
  23. package/build/NativeLinearGradient.ios.d.ts.map +1 -0
  24. package/build/NativeLinearGradient.ios.js +4 -0
  25. package/build/NativeLinearGradient.ios.js.map +1 -0
  26. package/build/NativeLinearGradient.js +10 -0
  27. package/build/NativeLinearGradient.js.map +1 -0
  28. package/build/NativeLinearGradient.kepler.d.ts +23 -0
  29. package/build/NativeLinearGradient.kepler.d.ts.map +1 -0
  30. package/build/NativeLinearGradient.kepler.js +23 -0
  31. package/build/NativeLinearGradient.kepler.js.map +1 -0
  32. package/build/NativeLinearGradient.types.d.ts +11 -0
  33. package/build/NativeLinearGradient.types.d.ts.map +1 -0
  34. package/build/NativeLinearGradient.types.js +2 -0
  35. package/build/NativeLinearGradient.types.js.map +1 -0
  36. package/build/NativeLinearGradient.web.d.ts +8 -0
  37. package/build/NativeLinearGradient.web.d.ts.map +1 -0
  38. package/build/NativeLinearGradient.web.js +79 -0
  39. package/build/NativeLinearGradient.web.js.map +1 -0
  40. package/build/normalizeColor.d.ts +2 -0
  41. package/build/normalizeColor.d.ts.map +1 -0
  42. package/build/normalizeColor.js +29 -0
  43. package/build/normalizeColor.js.map +1 -0
  44. package/expo-module.config.json +10 -0
  45. package/ios/ExpoLinearGradient.podspec +32 -0
  46. package/ios/LinearGradientLayer.swift +107 -0
  47. package/ios/LinearGradientModule.swift +28 -0
  48. package/ios/LinearGradientView.swift +14 -0
  49. package/kepler/ExpoLinearGradientDrawableLayer.cpp +85 -0
  50. package/kepler/ExpoLinearGradientDrawableLayer.h +81 -0
  51. package/kepler/ExpoLinearGradientView.cpp +92 -0
  52. package/kepler/ExpoLinearGradientView.h +37 -0
  53. package/kepler/ExpoLinearGradientViewManager.cpp +28 -0
  54. package/kepler/ExpoLinearGradientViewManager.h +19 -0
  55. package/kepler/KeplerInit.cpp +28 -0
  56. package/kepler/test/ExpoLinearGradientDrawableLayer.cpp +134 -0
  57. package/kepler/test/ExpoLinearGradientView.cpp +86 -0
  58. package/kepler/test/ExpoLinearGradientViewManager.cpp +37 -0
  59. package/package.json +1 -0
  60. package/react-native.config.js +21 -0
  61. package/src/LinearGradient.tsx +103 -0
  62. package/src/NativeLinearGradient.android.tsx +49 -0
  63. package/src/NativeLinearGradient.ios.tsx +10 -0
  64. package/src/NativeLinearGradient.kepler.tsx +36 -0
  65. package/src/NativeLinearGradient.tsx +12 -0
  66. package/src/NativeLinearGradient.types.ts +21 -0
  67. package/src/NativeLinearGradient.web.tsx +115 -0
  68. package/src/normalizeColor.ts +32 -0
  69. package/tsconfig.json +9 -0
@@ -0,0 +1,60 @@
1
+ import * as React from 'react';
2
+ import { ViewProps } from 'react-native';
3
+ import { NativeLinearGradientPoint } from './NativeLinearGradient.types';
4
+ /**
5
+ * An object `{ x: number; y: number }` or array `[x, y]` that represents the point
6
+ * at which the gradient starts or ends, as a fraction of the overall size of the gradient ranging
7
+ * from `0` to `1`, inclusive.
8
+ */
9
+ export type LinearGradientPoint = {
10
+ /**
11
+ * A number ranging from `0` to `1`, representing the position of gradient transformation.
12
+ */
13
+ x: number;
14
+ /**
15
+ * A number ranging from `0` to `1`, representing the position of gradient transformation.
16
+ */
17
+ y: number;
18
+ } | NativeLinearGradientPoint;
19
+ export type LinearGradientProps = ViewProps & {
20
+ /**
21
+ * An array of colors that represent stops in the gradient. At least two colors are required
22
+ * (for a single-color background, use the `style.backgroundColor` prop on a `View` component).
23
+ */
24
+ colors: string[];
25
+ /**
26
+ * An array that contains `number`s ranging from `0` to `1`, inclusive, and is the same length as the `colors` property.
27
+ * Each number indicates a color-stop location where each respective color should be located.
28
+ * If not specified, the colors will be distributed evenly across the gradient.
29
+ *
30
+ * For example, `[0.5, 0.8]` would render:
31
+ * - the first color, solid, from the beginning of the gradient view to 50% through (the middle);
32
+ * - a gradient from the first color to the second from the 50% point to the 80% point; and
33
+ * - the second color, solid, from the 80% point to the end of the gradient view.
34
+ *
35
+ * > The color-stop locations must be ascending from least to greatest.
36
+ * @default []
37
+ */
38
+ locations?: number[] | null;
39
+ /**
40
+ * For example, `{ x: 0.1, y: 0.2 }` means that the gradient will start `10%` from the left and `20%` from the top.
41
+ *
42
+ * **On web**, this only changes the angle of the gradient because CSS gradients don't support changing the starting position.
43
+ * @default { x: 0.5, y: 0.0 }
44
+ */
45
+ start?: LinearGradientPoint | null;
46
+ /**
47
+ * For example, `{ x: 0.1, y: 0.2 }` means that the gradient will end `10%` from the left and `20%` from the bottom.
48
+ *
49
+ * **On web**, this only changes the angle of the gradient because CSS gradients don't support changing the end position.
50
+ * @default { x: 0.5, y: 1.0 }
51
+ */
52
+ end?: LinearGradientPoint | null;
53
+ };
54
+ /**
55
+ * Renders a native view that transitions between multiple colors in a linear direction.
56
+ */
57
+ export declare class LinearGradient extends React.Component<LinearGradientProps> {
58
+ render(): React.JSX.Element;
59
+ }
60
+ //# sourceMappingURL=LinearGradient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinearGradient.d.ts","sourceRoot":"","sources":["../src/LinearGradient.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAA0B,SAAS,EAAE,MAAM,cAAc,CAAC;AAGjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAGzE;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAC3B;IACE;;OAEG;IACH,CAAC,EAAE,MAAM,CAAC;IACV;;OAEG;IACH,CAAC,EAAE,MAAM,CAAC;CACX,GACD,yBAAyB,CAAC;AAG9B,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG;IAC5C;;;OAGG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC5B;;;;;OAKG;IACH,KAAK,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACnC;;;;;OAKG;IACH,GAAG,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;CAClC,CAAC;AAEF;;GAEG;AACH,qBAAa,cAAe,SAAQ,KAAK,CAAC,SAAS,CAAC,mBAAmB,CAAC;IACtE,MAAM;CAqBP"}
@@ -0,0 +1,31 @@
1
+ import * as React from 'react';
2
+ import { Platform, processColor } from 'react-native';
3
+ import NativeLinearGradient from './NativeLinearGradient';
4
+ /**
5
+ * Renders a native view that transitions between multiple colors in a linear direction.
6
+ */
7
+ export class LinearGradient extends React.Component {
8
+ render() {
9
+ const { colors, locations, start, end, ...props } = this.props;
10
+ let resolvedLocations = locations;
11
+ if (locations && colors.length !== locations.length) {
12
+ console.warn('LinearGradient colors and locations props should be arrays of the same length');
13
+ resolvedLocations = locations.slice(0, colors.length);
14
+ }
15
+ return (<NativeLinearGradient {...props} colors={Platform.select({
16
+ web: colors,
17
+ default: colors.map(processColor),
18
+ })} locations={resolvedLocations} startPoint={_normalizePoint(start)} endPoint={_normalizePoint(end)}/>);
19
+ }
20
+ }
21
+ function _normalizePoint(point) {
22
+ if (!point) {
23
+ return undefined;
24
+ }
25
+ if (Array.isArray(point) && point.length !== 2) {
26
+ console.warn('start and end props for LinearGradient must be of the format [x,y] or {x, y}');
27
+ return undefined;
28
+ }
29
+ return Array.isArray(point) ? point : [point.x, point.y];
30
+ }
31
+ //# sourceMappingURL=LinearGradient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinearGradient.js","sourceRoot":"","sources":["../src/LinearGradient.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAa,MAAM,cAAc,CAAC;AAEjE,OAAO,oBAAoB,MAAM,wBAAwB,CAAC;AA2D1D;;GAEG;AACH,MAAM,OAAO,cAAe,SAAQ,KAAK,CAAC,SAA8B;IACtE,MAAM;QACJ,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;QAC/D,IAAI,iBAAiB,GAAG,SAAS,CAAC;QAClC,IAAI,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,MAAM,EAAE,CAAC;YACpD,OAAO,CAAC,IAAI,CAAC,+EAA+E,CAAC,CAAC;YAC9F,iBAAiB,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,CACL,CAAC,oBAAoB,CACnB,IAAI,KAAK,CAAC,CACV,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;gBACtB,GAAG,EAAE,MAAa;gBAClB,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC;aAClC,CAAC,CAAC,CACH,SAAS,CAAC,CAAC,iBAAiB,CAAC,CAC7B,UAAU,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CACnC,QAAQ,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,EAC/B,CACH,CAAC;IACJ,CAAC;CACF;AAED,SAAS,eAAe,CACtB,KAA6C;IAE7C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/C,OAAO,CAAC,IAAI,CAAC,8EAA8E,CAAC,CAAC;QAC7F,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;AAC3D,CAAC","sourcesContent":["import * as React from 'react';\nimport { Platform, processColor, ViewProps } from 'react-native';\n\nimport NativeLinearGradient from './NativeLinearGradient';\nimport { NativeLinearGradientPoint } from './NativeLinearGradient.types';\n\n// @needsAudit\n/**\n * An object `{ x: number; y: number }` or array `[x, y]` that represents the point\n * at which the gradient starts or ends, as a fraction of the overall size of the gradient ranging\n * from `0` to `1`, inclusive.\n */\nexport type LinearGradientPoint =\n | {\n /**\n * A number ranging from `0` to `1`, representing the position of gradient transformation.\n */\n x: number;\n /**\n * A number ranging from `0` to `1`, representing the position of gradient transformation.\n */\n y: number;\n }\n | NativeLinearGradientPoint;\n\n// @needsAudit\nexport type LinearGradientProps = ViewProps & {\n /**\n * An array of colors that represent stops in the gradient. At least two colors are required\n * (for a single-color background, use the `style.backgroundColor` prop on a `View` component).\n */\n colors: string[];\n /**\n * An array that contains `number`s ranging from `0` to `1`, inclusive, and is the same length as the `colors` property.\n * Each number indicates a color-stop location where each respective color should be located.\n * If not specified, the colors will be distributed evenly across the gradient.\n *\n * For example, `[0.5, 0.8]` would render:\n * - the first color, solid, from the beginning of the gradient view to 50% through (the middle);\n * - a gradient from the first color to the second from the 50% point to the 80% point; and\n * - the second color, solid, from the 80% point to the end of the gradient view.\n *\n * > The color-stop locations must be ascending from least to greatest.\n * @default []\n */\n locations?: number[] | null;\n /**\n * For example, `{ x: 0.1, y: 0.2 }` means that the gradient will start `10%` from the left and `20%` from the top.\n *\n * **On web**, this only changes the angle of the gradient because CSS gradients don't support changing the starting position.\n * @default { x: 0.5, y: 0.0 }\n */\n start?: LinearGradientPoint | null;\n /**\n * For example, `{ x: 0.1, y: 0.2 }` means that the gradient will end `10%` from the left and `20%` from the bottom.\n *\n * **On web**, this only changes the angle of the gradient because CSS gradients don't support changing the end position.\n * @default { x: 0.5, y: 1.0 }\n */\n end?: LinearGradientPoint | null;\n};\n\n/**\n * Renders a native view that transitions between multiple colors in a linear direction.\n */\nexport class LinearGradient extends React.Component<LinearGradientProps> {\n render() {\n const { colors, locations, start, end, ...props } = this.props;\n let resolvedLocations = locations;\n if (locations && colors.length !== locations.length) {\n console.warn('LinearGradient colors and locations props should be arrays of the same length');\n resolvedLocations = locations.slice(0, colors.length);\n }\n\n return (\n <NativeLinearGradient\n {...props}\n colors={Platform.select({\n web: colors as any,\n default: colors.map(processColor),\n })}\n locations={resolvedLocations}\n startPoint={_normalizePoint(start)}\n endPoint={_normalizePoint(end)}\n />\n );\n }\n}\n\nfunction _normalizePoint(\n point: LinearGradientPoint | null | undefined\n): NativeLinearGradientPoint | undefined {\n if (!point) {\n return undefined;\n }\n\n if (Array.isArray(point) && point.length !== 2) {\n console.warn('start and end props for LinearGradient must be of the format [x,y] or {x, y}');\n return undefined;\n }\n\n return Array.isArray(point) ? point : [point.x, point.y];\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import * as React from 'react';
2
+ import { NativeLinearGradientProps } from './NativeLinearGradient.types';
3
+ export default function NativeLinearGradient({ colors, locations, startPoint, endPoint, children, style, ...props }: NativeLinearGradientProps): React.ReactElement;
4
+ //# sourceMappingURL=NativeLinearGradient.android.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeLinearGradient.android.d.ts","sourceRoot":"","sources":["../src/NativeLinearGradient.android.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAEzE,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EAC3C,MAAM,EACN,SAAS,EACT,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,KAAK,EACL,GAAG,KAAK,EACT,EAAE,yBAAyB,GAAG,KAAK,CAAC,YAAY,CAgChD"}
@@ -0,0 +1,27 @@
1
+ import { requireNativeViewManager } from 'expo-modules-core';
2
+ import * as React from 'react';
3
+ import { StyleSheet, View } from 'react-native';
4
+ export default function NativeLinearGradient({ colors, locations, startPoint, endPoint, children, style, ...props }) {
5
+ // TODO: revisit whether we need to inherit the container's borderRadius since this issue has
6
+ // been resolved: https://github.com/facebook/react-native/issues/3198
7
+ const flatStyle = StyleSheet.flatten(style) ?? {};
8
+ const borderRadius = flatStyle.borderRadius ?? 0;
9
+ // This is the format from:
10
+ // https://developer.android.com/reference/android/graphics/Path.html#addRoundRect(android.graphics.RectF,%20float[],%20android.graphics.Path.Direction)
11
+ const borderRadiiPerCorner = [
12
+ flatStyle.borderTopLeftRadius ?? borderRadius,
13
+ flatStyle.borderTopLeftRadius ?? borderRadius,
14
+ flatStyle.borderTopRightRadius ?? borderRadius,
15
+ flatStyle.borderTopRightRadius ?? borderRadius,
16
+ flatStyle.borderBottomRightRadius ?? borderRadius,
17
+ flatStyle.borderBottomRightRadius ?? borderRadius,
18
+ flatStyle.borderBottomLeftRadius ?? borderRadius,
19
+ flatStyle.borderBottomLeftRadius ?? borderRadius,
20
+ ];
21
+ return (<View {...props} style={style}>
22
+ <BaseNativeLinearGradient style={StyleSheet.absoluteFill} colors={colors} startPoint={startPoint} endPoint={endPoint} locations={locations} borderRadii={borderRadiiPerCorner}/>
23
+ {children}
24
+ </View>);
25
+ }
26
+ const BaseNativeLinearGradient = requireNativeViewManager('ExpoLinearGradient');
27
+ //# sourceMappingURL=NativeLinearGradient.android.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeLinearGradient.android.js","sourceRoot":"","sources":["../src/NativeLinearGradient.android.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAIhD,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EAC3C,MAAM,EACN,SAAS,EACT,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,KAAK,EACL,GAAG,KAAK,EACkB;IAC1B,6FAA6F;IAC7F,sEAAsE;IACtE,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAClD,MAAM,YAAY,GAAG,SAAS,CAAC,YAAY,IAAI,CAAC,CAAC;IAEjD,2BAA2B;IAC3B,wJAAwJ;IACxJ,MAAM,oBAAoB,GAAG;QAC3B,SAAS,CAAC,mBAAmB,IAAI,YAAY;QAC7C,SAAS,CAAC,mBAAmB,IAAI,YAAY;QAC7C,SAAS,CAAC,oBAAoB,IAAI,YAAY;QAC9C,SAAS,CAAC,oBAAoB,IAAI,YAAY;QAC9C,SAAS,CAAC,uBAAuB,IAAI,YAAY;QACjD,SAAS,CAAC,uBAAuB,IAAI,YAAY;QACjD,SAAS,CAAC,sBAAsB,IAAI,YAAY;QAChD,SAAS,CAAC,sBAAsB,IAAI,YAAY;KACjD,CAAC;IAEF,OAAO,CACL,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAC5B;MAAA,CAAC,wBAAwB,CACvB,KAAK,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,CAC/B,MAAM,CAAC,CAAC,MAAM,CAAC,CACf,UAAU,CAAC,CAAC,UAAU,CAAC,CACvB,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,SAAS,CAAC,CAAC,SAAS,CAAC,CACrB,WAAW,CAAC,CAAC,oBAAoB,CAAC,EAEpC;MAAA,CAAC,QAAQ,CACX;IAAA,EAAE,IAAI,CAAC,CACR,CAAC;AACJ,CAAC;AAED,MAAM,wBAAwB,GAAG,wBAAwB,CAAC,oBAAoB,CAAC,CAAC","sourcesContent":["import { requireNativeViewManager } from 'expo-modules-core';\nimport * as React from 'react';\nimport { StyleSheet, View } from 'react-native';\n\nimport { NativeLinearGradientProps } from './NativeLinearGradient.types';\n\nexport default function NativeLinearGradient({\n colors,\n locations,\n startPoint,\n endPoint,\n children,\n style,\n ...props\n}: NativeLinearGradientProps): React.ReactElement {\n // TODO: revisit whether we need to inherit the container's borderRadius since this issue has\n // been resolved: https://github.com/facebook/react-native/issues/3198\n const flatStyle = StyleSheet.flatten(style) ?? {};\n const borderRadius = flatStyle.borderRadius ?? 0;\n\n // This is the format from:\n // https://developer.android.com/reference/android/graphics/Path.html#addRoundRect(android.graphics.RectF,%20float[],%20android.graphics.Path.Direction)\n const borderRadiiPerCorner = [\n flatStyle.borderTopLeftRadius ?? borderRadius,\n flatStyle.borderTopLeftRadius ?? borderRadius,\n flatStyle.borderTopRightRadius ?? borderRadius,\n flatStyle.borderTopRightRadius ?? borderRadius,\n flatStyle.borderBottomRightRadius ?? borderRadius,\n flatStyle.borderBottomRightRadius ?? borderRadius,\n flatStyle.borderBottomLeftRadius ?? borderRadius,\n flatStyle.borderBottomLeftRadius ?? borderRadius,\n ];\n\n return (\n <View {...props} style={style}>\n <BaseNativeLinearGradient\n style={StyleSheet.absoluteFill}\n colors={colors}\n startPoint={startPoint}\n endPoint={endPoint}\n locations={locations}\n borderRadii={borderRadiiPerCorner}\n />\n {children}\n </View>\n );\n}\n\nconst BaseNativeLinearGradient = requireNativeViewManager('ExpoLinearGradient');\n"]}
@@ -0,0 +1,4 @@
1
+ import * as React from 'react';
2
+ import { NativeLinearGradientProps } from './NativeLinearGradient.types';
3
+ export default function NativeLinearGradient(props: NativeLinearGradientProps): React.ReactElement;
4
+ //# sourceMappingURL=NativeLinearGradient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeLinearGradient.d.ts","sourceRoot":"","sources":["../src/NativeLinearGradient.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAIzE,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,GAAG,KAAK,CAAC,YAAY,CAIjG"}
@@ -0,0 +1,5 @@
1
+ import * as React from 'react';
2
+ import { NativeLinearGradientProps } from './NativeLinearGradient.types';
3
+ declare const NativeLinearGradient: React.FC<NativeLinearGradientProps>;
4
+ export default NativeLinearGradient;
5
+ //# sourceMappingURL=NativeLinearGradient.ios.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeLinearGradient.ios.d.ts","sourceRoot":"","sources":["../src/NativeLinearGradient.ios.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAEzE,QAAA,MAAM,oBAAoB,EAErB,KAAK,CAAC,EAAE,CAAC,yBAAyB,CAAC,CAAC;AAEzC,eAAe,oBAAoB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { requireNativeViewManager } from 'expo-modules-core';
2
+ const NativeLinearGradient = requireNativeViewManager('ExpoLinearGradient');
3
+ export default NativeLinearGradient;
4
+ //# sourceMappingURL=NativeLinearGradient.ios.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeLinearGradient.ios.js","sourceRoot":"","sources":["../src/NativeLinearGradient.ios.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAK7D,MAAM,oBAAoB,GAAG,wBAAwB,CACnD,oBAAoB,CACkB,CAAC;AAEzC,eAAe,oBAAoB,CAAC","sourcesContent":["import { requireNativeViewManager } from 'expo-modules-core';\nimport * as React from 'react';\n\nimport { NativeLinearGradientProps } from './NativeLinearGradient.types';\n\nconst NativeLinearGradient = requireNativeViewManager(\n 'ExpoLinearGradient'\n) as React.FC<NativeLinearGradientProps>;\n\nexport default NativeLinearGradient;\n"]}
@@ -0,0 +1,10 @@
1
+ import * as React from 'react';
2
+ import { View } from 'react-native';
3
+ // This is a shim view for platforms that aren't supported by Expo.
4
+ // The component and prop types should match all of the other platform variations.
5
+ export default function NativeLinearGradient(props) {
6
+ const { colors, locations, startPoint, endPoint, ...viewProps } = props;
7
+ console.warn('LinearGradient is not available on this platform');
8
+ return <View {...viewProps}/>;
9
+ }
10
+ //# sourceMappingURL=NativeLinearGradient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeLinearGradient.js","sourceRoot":"","sources":["../src/NativeLinearGradient.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAIpC,mEAAmE;AACnE,kFAAkF;AAClF,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,KAAgC;IAC3E,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,SAAS,EAAE,GAAG,KAAK,CAAC;IACxE,OAAO,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;IACjE,OAAO,CAAC,IAAI,CAAC,IAAK,SAAiB,CAAC,EAAG,CAAC;AAC1C,CAAC","sourcesContent":["import * as React from 'react';\nimport { View } from 'react-native';\n\nimport { NativeLinearGradientProps } from './NativeLinearGradient.types';\n\n// This is a shim view for platforms that aren't supported by Expo.\n// The component and prop types should match all of the other platform variations.\nexport default function NativeLinearGradient(props: NativeLinearGradientProps): React.ReactElement {\n const { colors, locations, startPoint, endPoint, ...viewProps } = props;\n console.warn('LinearGradient is not available on this platform');\n return <View {...(viewProps as any)} />;\n}\n"]}
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import { ViewProps, ColorValue } from 'react-native';
3
+ interface NativeProps extends ViewProps {
4
+ colors: (number | ColorValue)[];
5
+ startPoint?: {
6
+ x: number;
7
+ y: number;
8
+ };
9
+ endPoint?: {
10
+ x: number;
11
+ y: number;
12
+ };
13
+ locations?: number[];
14
+ }
15
+ /**
16
+ * This responsive component displays native React View that transitions between multiple colours along the respective dimensions.
17
+ * You can pass different colors, angles, locations etc. to communicate different visuals of gradient.
18
+ * @param props The properties passed to this component for rendering
19
+ * @constructor
20
+ */
21
+ export default function (props: NativeProps): React.JSX.Element;
22
+ export {};
23
+ //# sourceMappingURL=NativeLinearGradient.kepler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeLinearGradient.kepler.d.ts","sourceRoot":"","sources":["../src/NativeLinearGradient.kepler.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAOrD,UAAU,WAAY,SAAQ,SAAS;IACrC,MAAM,EAAE,CAAC,MAAM,GAAG,UAAU,CAAC,EAAE,CAAC;IAChC,UAAU,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,QAAQ,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAcD;;;;;GAKG;AACH,MAAM,CAAC,OAAO,WAAW,KAAK,EAAE,WAAW,qBAE1C"}
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ // @ts-ignore
3
+ import register from 'react-native/Libraries/Utilities/registerGeneratedViewConfig';
4
+ const NativeComponent = 'ExpoLinearGradient';
5
+ register(NativeComponent, {
6
+ uiViewClassName: NativeComponent,
7
+ validAttributes: {
8
+ colors: true,
9
+ startPoint: true,
10
+ endPoint: true,
11
+ locations: true,
12
+ },
13
+ });
14
+ /**
15
+ * This responsive component displays native React View that transitions between multiple colours along the respective dimensions.
16
+ * You can pass different colors, angles, locations etc. to communicate different visuals of gradient.
17
+ * @param props The properties passed to this component for rendering
18
+ * @constructor
19
+ */
20
+ export default function (props) {
21
+ return <NativeComponent {...props}/>;
22
+ }
23
+ //# sourceMappingURL=NativeLinearGradient.kepler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeLinearGradient.kepler.js","sourceRoot":"","sources":["../src/NativeLinearGradient.kepler.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,aAAa;AACb,OAAO,QAAQ,MAAM,8DAA8D,CAAC;AAYpF,MAAM,eAAe,GAAG,oBAA6D,CAAC;AAEtF,QAAQ,CAAC,eAAe,EAAE;IACxB,eAAe,EAAE,eAAe;IAChC,eAAe,EAAE;QACf,MAAM,EAAE,IAAI;QACZ,UAAU,EAAE,IAAI;QAChB,QAAQ,EAAE,IAAI;QACd,SAAS,EAAE,IAAI;KAChB;CACF,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,CAAC,OAAO,WAAW,KAAkB;IACzC,OAAO,CAAC,eAAe,CAAC,IAAI,KAAK,CAAC,EAAG,CAAC;AACxC,CAAC","sourcesContent":["import React from 'react'\nimport { ViewProps, ColorValue } from 'react-native';\n// @ts-ignore\nimport register from 'react-native/Libraries/Utilities/registerGeneratedViewConfig';\nimport {\n HostComponent,\n} from 'react-native';\n\ninterface NativeProps extends ViewProps {\n colors: (number | ColorValue)[];\n startPoint?: { x: number; y: number };\n endPoint?: { x: number; y: number };\n locations?: number[];\n}\n\nconst NativeComponent = 'ExpoLinearGradient' as unknown as HostComponent<NativeProps>;\n\nregister(NativeComponent, {\n uiViewClassName: NativeComponent,\n validAttributes: {\n colors: true,\n startPoint: true,\n endPoint: true,\n locations: true,\n },\n});\n\n/**\n * This responsive component displays native React View that transitions between multiple colours along the respective dimensions.\n * You can pass different colors, angles, locations etc. to communicate different visuals of gradient.\n * @param props The properties passed to this component for rendering\n * @constructor\n */\nexport default function (props: NativeProps) {\n return <NativeComponent {...props} />;\n}\n"]}
@@ -0,0 +1,11 @@
1
+ import { PropsWithChildren } from 'react';
2
+ import { ViewProps } from 'react-native';
3
+ export type NativeLinearGradientProps = ViewProps & PropsWithChildren<{
4
+ colors: number[];
5
+ locations?: number[] | null;
6
+ startPoint?: NativeLinearGradientPoint | null;
7
+ endPoint?: NativeLinearGradientPoint | null;
8
+ }>;
9
+ export type getLinearGradientBackgroundImage = (colors: number[], width?: number, height?: number, locations?: number[] | null, startPoint?: NativeLinearGradientPoint | null, endPoint?: NativeLinearGradientPoint | null) => string;
10
+ export type NativeLinearGradientPoint = [number, number];
11
+ //# sourceMappingURL=NativeLinearGradient.types.d.ts.map
@@ -0,0 +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,MAAM,MAAM,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,MAAM,MAAM,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,MAAM,MAAM,yBAAyB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=NativeLinearGradient.types.js.map
@@ -0,0 +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 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"]}
@@ -0,0 +1,8 @@
1
+ import * as React from 'react';
2
+ import { NativeLinearGradientPoint, NativeLinearGradientProps } from './NativeLinearGradient.types';
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;
8
+ //# sourceMappingURL=NativeLinearGradient.web.d.ts.map
@@ -0,0 +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,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"}
@@ -0,0 +1,79 @@
1
+ import * as React from 'react';
2
+ import { View } from 'react-native';
3
+ import { normalizeColor } from './normalizeColor';
4
+ export default function NativeLinearGradient({ colors, locations, startPoint, endPoint, ...props }) {
5
+ const [{ height, width }, setLayout] = React.useState({
6
+ height: 1,
7
+ width: 1,
8
+ });
9
+ // TODO(Bacon): In the future we could consider adding `backgroundRepeat: "no-repeat"`. For more
10
+ // browser support.
11
+ const linearGradientBackgroundImage = React.useMemo(() => {
12
+ return getLinearGradientBackgroundImage(colors, locations, startPoint, endPoint, width, height);
13
+ }, [colors, locations, startPoint, endPoint, width, height]);
14
+ return (<View {...props} style={[
15
+ props.style,
16
+ // @ts-ignore: [ts] Property 'backgroundImage' does not exist on type 'ViewStyle'.
17
+ { backgroundImage: linearGradientBackgroundImage },
18
+ ]} onLayout={(event) => {
19
+ const { width, height } = event.nativeEvent.layout;
20
+ setLayout((oldLayout) => {
21
+ // don't set new layout state unless the layout has actually changed
22
+ if (width !== oldLayout.width || height !== oldLayout.height) {
23
+ return { height, width };
24
+ }
25
+ return oldLayout;
26
+ });
27
+ if (props.onLayout) {
28
+ props.onLayout(event);
29
+ }
30
+ }}/>);
31
+ }
32
+ /**
33
+ * Extracted to a separate function in order to be able to test logic independently.
34
+ */
35
+ export function getLinearGradientBackgroundImage(colors, locations, startPoint, endPoint, width = 1, height = 1) {
36
+ const gradientColors = calculateGradientColors(colors, locations);
37
+ const angle = calculatePseudoAngle(width, height, startPoint, endPoint);
38
+ return `linear-gradient(${angle}deg, ${gradientColors.join(', ')})`;
39
+ }
40
+ function calculatePseudoAngle(width, height, startPoint, endPoint) {
41
+ const getControlPoints = () => {
42
+ let correctedStartPoint = [0, 0];
43
+ if (Array.isArray(startPoint)) {
44
+ correctedStartPoint = [
45
+ startPoint[0] != null ? startPoint[0] : 0.0,
46
+ startPoint[1] != null ? startPoint[1] : 0.0,
47
+ ];
48
+ }
49
+ let correctedEndPoint = [0.0, 1.0];
50
+ if (Array.isArray(endPoint)) {
51
+ correctedEndPoint = [
52
+ endPoint[0] != null ? endPoint[0] : 0.0,
53
+ endPoint[1] != null ? endPoint[1] : 1.0,
54
+ ];
55
+ }
56
+ return [correctedStartPoint, correctedEndPoint];
57
+ };
58
+ const [start, end] = getControlPoints();
59
+ start[0] *= width;
60
+ end[0] *= width;
61
+ start[1] *= height;
62
+ end[1] *= height;
63
+ const py = end[1] - start[1];
64
+ const px = end[0] - start[0];
65
+ return 90 + (Math.atan2(py, px) * 180) / Math.PI;
66
+ }
67
+ function calculateGradientColors(colors, locations) {
68
+ return colors.map((color, index) => {
69
+ const output = normalizeColor(color);
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
+ return `${output} ${percentage}%`;
75
+ }
76
+ return output;
77
+ });
78
+ }
79
+ //# sourceMappingURL=NativeLinearGradient.web.js.map
@@ -0,0 +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 { 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 [{ height, width }, setLayout] = React.useState({\n height: 1,\n width: 1,\n });\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 { width, height } = event.nativeEvent.layout;\n\n setLayout((oldLayout) => {\n // don't set new layout state unless the layout has actually changed\n if (width !== oldLayout.width || height !== oldLayout.height) {\n return { height, width };\n }\n\n return oldLayout;\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 output = normalizeColor(color);\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 return `${output} ${percentage}%`;\n }\n return output;\n });\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export declare function normalizeColor(color?: number | string, opacity?: number): void | string;
2
+ //# sourceMappingURL=normalizeColor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizeColor.d.ts","sourceRoot":"","sources":["../src/normalizeColor.ts"],"names":[],"mappings":"AAeA,wBAAgB,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,GAAE,MAAU,GAAG,IAAI,GAAG,MAAM,CAgB1F"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Copyright (c) Expo.
3
+ * Copyright (c) Nicolas Gallagher.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ import { processColor } from 'react-native';
9
+ const isWebColor = (color) => color === 'currentcolor' ||
10
+ color === 'currentColor' ||
11
+ color === 'inherit' ||
12
+ color.indexOf('var(') === 0;
13
+ export function normalizeColor(color, opacity = 1) {
14
+ if (color == null)
15
+ return;
16
+ if (typeof color === 'string' && isWebColor(color)) {
17
+ return color;
18
+ }
19
+ const colorInt = processColor(color);
20
+ if (colorInt != null) {
21
+ const r = (colorInt >> 16) & 255;
22
+ const g = (colorInt >> 8) & 255;
23
+ const b = colorInt & 255;
24
+ const a = ((colorInt >> 24) & 255) / 255;
25
+ const alpha = (a * opacity).toFixed(2);
26
+ return `rgba(${r},${g},${b},${alpha})`;
27
+ }
28
+ }
29
+ //# sourceMappingURL=normalizeColor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizeColor.js","sourceRoot":"","sources":["../src/normalizeColor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,UAAU,GAAG,CAAC,KAAa,EAAW,EAAE,CAC5C,KAAK,KAAK,cAAc;IACxB,KAAK,KAAK,cAAc;IACxB,KAAK,KAAK,SAAS;IACnB,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAE9B,MAAM,UAAU,cAAc,CAAC,KAAuB,EAAE,UAAkB,CAAC;IACzE,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO;IAE1B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACnD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAuB,CAAC;IAC3D,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;QACrB,MAAM,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,GAAG,GAAG,CAAC;QACjC,MAAM,CAAC,GAAG,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC;QAChC,MAAM,CAAC,GAAG,QAAQ,GAAG,GAAG,CAAC;QACzB,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;QACzC,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACvC,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,GAAG,CAAC;IACzC,CAAC;AACH,CAAC","sourcesContent":["/**\n * Copyright (c) Expo.\n * Copyright (c) Nicolas Gallagher.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\nimport { processColor } from 'react-native';\n\nconst isWebColor = (color: string): boolean =>\n color === 'currentcolor' ||\n color === 'currentColor' ||\n color === 'inherit' ||\n color.indexOf('var(') === 0;\n\nexport function normalizeColor(color?: number | string, opacity: number = 1): void | string {\n if (color == null) return;\n\n if (typeof color === 'string' && isWebColor(color)) {\n return color;\n }\n\n const colorInt = processColor(color) as number | undefined;\n if (colorInt != null) {\n const r = (colorInt >> 16) & 255;\n const g = (colorInt >> 8) & 255;\n const b = colorInt & 255;\n const a = ((colorInt >> 24) & 255) / 255;\n const alpha = (a * opacity).toFixed(2);\n return `rgba(${r},${g},${b},${alpha})`;\n }\n}\n"]}
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "expo-linear-gradient",
3
+ "platforms": ["ios", "android"],
4
+ "ios": {
5
+ "modulesClassNames": ["LinearGradientModule"]
6
+ },
7
+ "android": {
8
+ "modulesClassNames": ["expo.modules.lineargradient.LinearGradientModule"]
9
+ }
10
+ }
@@ -0,0 +1,32 @@
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = 'ExpoLinearGradient'
7
+ s.version = package['version']
8
+ s.summary = package['description']
9
+ s.description = package['description']
10
+ s.license = package['license']
11
+ s.author = package['author']
12
+ s.homepage = package['homepage']
13
+ s.platform = :ios, '13.0'
14
+ s.swift_version = '5.4'
15
+ s.source = { git: 'https://github.com/expo/expo.git' }
16
+ s.static_framework = true
17
+
18
+ s.dependency 'ExpoModulesCore'
19
+
20
+ # Swift/Objective-C compatibility
21
+ s.pod_target_xcconfig = {
22
+ 'DEFINES_MODULE' => 'YES',
23
+ 'SWIFT_COMPILATION_MODE' => 'wholemodule'
24
+ }
25
+
26
+ if !$ExpoUseSources&.include?(package['name']) && ENV['EXPO_USE_SOURCE'].to_i == 0 && File.exist?("#{s.name}.xcframework") && Gem::Version.new(Pod::VERSION) >= Gem::Version.new('1.10.0')
27
+ s.source_files = "**/*.h"
28
+ s.vendored_frameworks = "#{s.name}.xcframework"
29
+ else
30
+ s.source_files = "**/*.{h,m,swift}"
31
+ end
32
+ end
@@ -0,0 +1,107 @@
1
+ // Copyright 2021-present 650 Industries. All rights reserved.
2
+
3
+ import QuartzCore
4
+ import CoreGraphics
5
+
6
+ var defaultStartPoint = CGPoint(x: 0.5, y: 0.0)
7
+ var defaultEndPoint = CGPoint(x: 0.5, y: 1.0)
8
+ var defaultLocations: [CGFloat] = []
9
+
10
+ final class LinearGradientLayer: CALayer {
11
+ var colors = [CGColor]()
12
+ var startPoint = defaultStartPoint
13
+ var endPoint = defaultEndPoint
14
+ var locations = defaultLocations
15
+
16
+ override init() {
17
+ super.init()
18
+ self.needsDisplayOnBoundsChange = true
19
+ self.masksToBounds = true
20
+ }
21
+
22
+ override init(layer: Any) {
23
+ super.init(layer: layer)
24
+ self.needsDisplayOnBoundsChange = true
25
+ self.masksToBounds = true
26
+ }
27
+
28
+ required init?(coder: NSCoder) {
29
+ fatalError("init(coder:) has not been implemented")
30
+ }
31
+
32
+ func setColors(_ colors: [CGColor]) {
33
+ self.colors = colors
34
+ setNeedsDisplay()
35
+ }
36
+
37
+ func setStartPoint(_ startPoint: CGPoint?) {
38
+ self.startPoint = startPoint ?? defaultStartPoint
39
+ setNeedsDisplay()
40
+ }
41
+
42
+ func setEndPoint(_ endPoint: CGPoint?) {
43
+ self.endPoint = endPoint ?? defaultEndPoint
44
+ setNeedsDisplay()
45
+ }
46
+
47
+ func setLocations(_ locations: [CGFloat]?) {
48
+ self.locations = locations ?? defaultLocations
49
+ setNeedsDisplay()
50
+ }
51
+
52
+ override func display() {
53
+ super.display()
54
+
55
+ if colors.isEmpty || bounds.size.width.isZero || bounds.size.height.isZero {
56
+ return
57
+ }
58
+ let hasAlpha = colors.reduce(false) { result, color in
59
+ return result || color.alpha < 1.0
60
+ }
61
+
62
+ UIGraphicsBeginImageContextWithOptions(bounds.size, !hasAlpha, 0.0)
63
+
64
+ guard let contextRef = UIGraphicsGetCurrentContext() else {
65
+ return
66
+ }
67
+
68
+ draw(in: contextRef)
69
+
70
+ guard let image = UIGraphicsGetImageFromCurrentImageContext() else {
71
+ return
72
+ }
73
+
74
+ self.contents = image.cgImage
75
+ self.contentsScale = image.scale
76
+
77
+ UIGraphicsEndImageContext()
78
+ }
79
+
80
+ override func draw(in ctx: CGContext) {
81
+ super.draw(in: ctx)
82
+
83
+ ctx.saveGState()
84
+
85
+ let colorSpace = CGColorSpaceCreateDeviceRGB()
86
+ let locations = colors.enumerated().map { (offset: Int, _: CGColor) -> CGFloat in
87
+ if self.locations.count > offset {
88
+ return self.locations[offset]
89
+ } else {
90
+ return CGFloat(offset) / CGFloat(colors.count - 1)
91
+ }
92
+ }
93
+
94
+ if let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: locations) {
95
+ let size = bounds.size
96
+
97
+ ctx.drawLinearGradient(
98
+ gradient,
99
+ start: CGPoint(x: startPoint.x * size.width, y: startPoint.y * size.height),
100
+ end: CGPoint(x: endPoint.x * size.width, y: endPoint.y * size.height),
101
+ options: [.drawsBeforeStartLocation, .drawsAfterEndLocation]
102
+ )
103
+ }
104
+
105
+ ctx.restoreGState()
106
+ }
107
+ }
@@ -0,0 +1,28 @@
1
+ // Copyright 2021-present 650 Industries. All rights reserved.
2
+
3
+ import CoreGraphics
4
+ import ExpoModulesCore
5
+
6
+ public class LinearGradientModule: Module {
7
+ public func definition() -> ModuleDefinition {
8
+ Name("ExpoLinearGradient")
9
+
10
+ View(LinearGradientView.self) {
11
+ Prop("colors") { (view: LinearGradientView, colors: [CGColor]) in
12
+ view.gradientLayer.setColors(colors)
13
+ }
14
+
15
+ Prop("startPoint") { (view: LinearGradientView, startPoint: CGPoint?) in
16
+ view.gradientLayer.setStartPoint(startPoint)
17
+ }
18
+
19
+ Prop("endPoint") { (view: LinearGradientView, endPoint: CGPoint?) in
20
+ view.gradientLayer.setEndPoint(endPoint)
21
+ }
22
+
23
+ Prop("locations") { (view: LinearGradientView, locations: [CGFloat]?) in
24
+ view.gradientLayer.setLocations(locations)
25
+ }
26
+ }
27
+ }
28
+ }