diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000..0c7b638
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,12 @@
+# These are supported funding model platforms
+
+github: catalinmiron # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
+patreon: catalinmiron # Replace with a single Patreon username
+open_collective: # Replace with a single Open Collective username
+ko_fi: # Replace with a single Ko-fi username
+tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
+community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
+liberapay: # Replace with a single Liberapay username
+issuehunt: # Replace with a single IssueHunt username
+otechie: # Replace with a single Otechie username
+custom: http://buymeacoffee.com/catalinmiron # Replace with a single custom sponsorship URL
diff --git a/README.md b/README.md
index b75d67e..c5f033c 100644
--- a/README.md
+++ b/README.md
@@ -23,11 +23,13 @@ Supported backgrounds:
### Usage
-```
-import Gradient from 'react-native-css-gradient`;
+```js
+import Gradient from 'react-native-css-gradient';
render() {
- const gradient = `linear-gradient(-225deg, #231557 0%, #44107A 29%, #FF1361 67%, #FFF800 100%), repeating-linear-gradient(-115deg, transparent, transparent 20px, rgba(255,255,255,0.1) 20px, rgba(255,255,255,0.1) 40px), repeating-linear-gradient(115deg, transparent, transparent 20px, rgba(255,255,255,0.1) 20px, rgba(255,255,255,0.1) 40px)`;
+ const gradient = `linear-gradient(-225deg, #231557 0%, #44107A 29%, #FF1361 67%, #FFF800 100%),
+ repeating-linear-gradient(-115deg, transparent, transparent 20px, rgba(255,255,255,0.1) 20px, rgba(255,255,255,0.1) 40px),
+ repeating-linear-gradient(115deg, transparent, transparent 20px, rgba(255,255,255,0.1) 20px, rgba(255,255,255,0.1) 40px)`;
return
}
diff --git a/generator.js b/generator.js
index 9f45edc..6a37ca4 100755
--- a/generator.js
+++ b/generator.js
@@ -2,6 +2,7 @@
TODO: write tests (lazy) like always right? <3
*/
const parser = require("gradient-parser");
+const memoize = require("fast-memoize");
const getColor = color => {
switch (color.type) {
@@ -14,27 +15,23 @@ const getColor = color => {
}
};
-const getColorsAndLocations = (colorStops, maxWidth) =>
+const getColorsAndLocations = memoize((colorStops, maxWidth) =>
colorStops.reduce(
(acc, color, index) => {
acc.colors = [...acc.colors, getColor(color)];
// PX value for location will break!
// TODO Make it happen for px + repeat?
- const locationValue = getPixelsForColor(
- color,
- colorStops.length,
- index,
- maxWidth
- );
+ const locationValue = getPixelsForColor(color, colorStops.length, index, maxWidth);
acc["locations"] = [...acc.locations, locationValue];
return acc;
},
{ colors: [], locations: [] }
- );
+ )
+);
-const getPixelsForColor = (color, colorsLength, index, maxWidth) => {
+const getPixelsForColor = memoize((color, colorsLength, index, maxWidth) => {
const { length } = color;
if (!length) {
return (1 / (colorsLength - 1)) * index;
@@ -49,33 +46,30 @@ const getPixelsForColor = (color, colorsLength, index, maxWidth) => {
return length.value / 100;
}
}
-};
+});
+
const getRepeatingColorsAndLocations = (colorStops, sizes) => {
const { width: maxWidth, height: maxHeight } = sizes;
-
- if (!maxWidth && !maxHeight) {
- throw new Error(
- "You have to define width and height for repeating gradient to work"
- );
- }
-
- const {
- colors: initialColors,
- locations: initialLocations
- } = getColorsAndLocations(colorStops, maxWidth);
+ const { colors: initialColors, locations: initialLocations } = getColorsAndLocations(colorStops, maxWidth);
const maxValue = parseFloat(initialLocations.slice(-1)[0]);
const increment = maxValue / maxWidth;
- const maxChunks = Math.round(maxWidth / maxValue) + 1;
+ // we need to add +1 but this is breaking LinearGradient, maybe can't render
+ // it outside the viewport.
+ const maxChunks = Math.round(maxWidth / maxValue);
const locations = [...Array(maxChunks).keys()].reduce((acc, i) => {
- return [...acc, ...initialLocations.map(j => j / maxWidth + increment * i)];
+ return [
+ ...acc,
+ ...initialLocations.map(j => {
+ return j / maxWidth + increment * i;
+ })
+ ];
}, []);
- const colors = locations.map(
- (_, i) => initialColors[i % initialColors.length]
- );
+ const colors = locations.map((_, i) => initialColors[i % initialColors.length]);
- return { locations, colors };
+ return { colors, locations };
};
-const getVectorsByDirection = direction => {
+
+const getVectorsByDirection = memoize(direction => {
switch (direction) {
case "top":
return getVectorsByAngle(0);
@@ -94,27 +88,31 @@ const getVectorsByDirection = direction => {
case "right bottom":
return getVectorsByAngle(90 + 45);
}
-};
-const round = number => Math.round(number * 1000) / 1000;
-const degreesToRadians = function(degrees) {
- return (degrees * Math.PI) / 180;
-};
-const getVectorsByAngle = alfa => {
+});
+
+const round = memoize(number => Math.round(number * 10000) / 10000);
+const degreesToRadians = memoize(degrees => (degrees * Math.PI) / 180);
+
+const getVectorsByAngle = memoize(alfa => {
const angle = degreesToRadians(alfa);
- let gradientLineLength = round(
- Math.abs(Math.sin(angle)) + Math.abs(Math.cos(angle))
- );
+ let gradientLineLength = round(Math.abs(Math.sin(angle)) + Math.abs(Math.cos(angle)));
let center = { x: 0.5, y: 0.5 };
let yDiff = (Math.sin(angle - Math.PI / 2) * gradientLineLength) / 2;
let xDiff = (Math.cos(angle - Math.PI / 2) * gradientLineLength) / 2;
return {
- start: [center.x - xDiff, center.y - yDiff],
- end: [center.x + xDiff, center.y + yDiff]
+ start: {
+ x: center.x - xDiff,
+ y: center.y - yDiff
+ },
+ end: {
+ x: center.x + xDiff,
+ y: center.y + yDiff
+ }
};
-};
+});
const getVectorsByOrientation = orientation => {
return orientation.type === "directional"
@@ -122,7 +120,7 @@ const getVectorsByOrientation = orientation => {
: getVectorsByAngle(orientation.value);
};
-const generateGradient = (gradient, sizes) => {
+const generateGradient = memoize((gradient, sizes) => {
return parser.parse(gradient).map(({ type, colorStops, orientation }) => {
// YOLO: Radial gradients <3
if (type === "radial-gradient") {
@@ -138,6 +136,6 @@ const generateGradient = (gradient, sizes) => {
...getVectorsByOrientation(orientation)
};
});
-};
+});
export default generateGradient;
diff --git a/index.js b/index.js
index c4f3e6f..26835af 100755
--- a/index.js
+++ b/index.js
@@ -5,7 +5,11 @@ import generateGradient from "./generator";
export { generateGradient };
export default ({ gradient, children, style }) => {
- const LinearGradient = require("expo").LinearGradient;
+ // Avoid breaking this when people are not using expo :)
+ // find a better solution to expose either expo-linear-gradient or
+ // react-native-linear-gradient.
+ const { LinearGradient } = require("expo-linear-gradient");
+
const generated = generateGradient(gradient, {
width: style.width,
height: style.height
@@ -20,6 +24,7 @@ export default ({ gradient, children, style }) => {
);
}
+
return (
{children || null}
diff --git a/package-lock.json b/package-lock.json
index 4233d02..5f066f4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,9 +1,14 @@
{
"name": "react-native-css-gradient",
- "version": "0.3.0",
+ "version": "0.3.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
+ "fast-memoize": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.1.tgz",
+ "integrity": "sha512-xdmw296PCL01tMOXx9mdJSmWY29jQgxyuZdq0rEHMu+Tpe1eOEtCycoG6chzlcrWsNgpZP7oL8RiQr7+G6Bl6g=="
+ },
"gradient-parser": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/gradient-parser/-/gradient-parser-0.1.5.tgz",
diff --git a/package.json b/package.json
index 2a90c2c..0f0d772 100755
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-native-css-gradient",
- "version": "0.3.1",
+ "version": "0.4.0",
"description": "CSS Gradient for LinearGradient component.",
"author": "Catalin Miron",
"license": "MIT",
@@ -14,10 +14,12 @@
"homepage": "https://github.com/catalinmiron/react-native-css-gradient#readme",
"main": "index.js",
"dependencies": {
+ "fast-memoize": "^2.5.1",
"gradient-parser": "0.1.5"
},
"peerDependencies": {
"expo": "*",
+ "expo-linear-gradient": "*",
"react": "*",
"react-native": "*"
}