22  TODO: write tests (lazy) like always right? <3 
33*/ 
44const  parser  =  require ( "gradient-parser" ) ; 
5+ const  memoize  =  require ( "fast-memoize" ) ; 
56
67const  getColor  =  color  =>  { 
78  switch  ( color . type )  { 
@@ -14,27 +15,23 @@ const getColor = color => {
1415  } 
1516} ; 
1617
17- const  getColorsAndLocations  =  ( colorStops ,  maxWidth )  => 
18+ const  getColorsAndLocations  =  memoize ( ( colorStops ,  maxWidth )  => 
1819  colorStops . reduce ( 
1920    ( acc ,  color ,  index )  =>  { 
2021      acc . colors  =  [ ...acc . colors ,  getColor ( color ) ] ; 
2122
2223      // PX value for location will break! 
2324      // TODO Make it happen for px + repeat? 
24-       const  locationValue  =  getPixelsForColor ( 
25-         color , 
26-         colorStops . length , 
27-         index , 
28-         maxWidth 
29-       ) ; 
25+       const  locationValue  =  getPixelsForColor ( color ,  colorStops . length ,  index ,  maxWidth ) ; 
3026      acc [ "locations" ]  =  [ ...acc . locations ,  locationValue ] ; 
3127
3228      return  acc ; 
3329    } , 
3430    {  colors : [ ] ,  locations : [ ]  } 
35-   ) ; 
31+   ) 
32+ ) ; 
3633
37- const  getPixelsForColor  =  ( color ,  colorsLength ,  index ,  maxWidth )  =>  { 
34+ const  getPixelsForColor  =  memoize ( ( color ,  colorsLength ,  index ,  maxWidth )  =>  { 
3835  const  {  length }  =  color ; 
3936  if  ( ! length )  { 
4037    return  ( 1  /  ( colorsLength  -  1 ) )  *  index ; 
@@ -49,33 +46,30 @@ const getPixelsForColor = (color, colorsLength, index, maxWidth) => {
4946      return  length . value  /  100 ; 
5047    } 
5148  } 
52- } ; 
49+ } ) ; 
50+ 
5351const  getRepeatingColorsAndLocations  =  ( colorStops ,  sizes )  =>  { 
5452  const  {  width : maxWidth ,  height : maxHeight  }  =  sizes ; 
55- 
56-   if  ( ! maxWidth  &&  ! maxHeight )  { 
57-     throw  new  Error ( 
58-       "You have to define width and height for repeating gradient to work" 
59-     ) ; 
60-   } 
61- 
62-   const  { 
63-     colors : initialColors , 
64-     locations : initialLocations 
65-   }  =  getColorsAndLocations ( colorStops ,  maxWidth ) ; 
53+   const  {  colors : initialColors ,  locations : initialLocations  }  =  getColorsAndLocations ( colorStops ,  maxWidth ) ; 
6654  const  maxValue  =  parseFloat ( initialLocations . slice ( - 1 ) [ 0 ] ) ; 
6755  const  increment  =  maxValue  /  maxWidth ; 
68-   const  maxChunks  =  Math . round ( maxWidth  /  maxValue )  +  1 ; 
56+   // we need to add +1 but this is breaking LinearGradient, maybe can't render 
57+   // it outside the viewport. 
58+   const  maxChunks  =  Math . round ( maxWidth  /  maxValue ) ; 
6959  const  locations  =  [ ...Array ( maxChunks ) . keys ( ) ] . reduce ( ( acc ,  i )  =>  { 
70-     return  [ ...acc ,  ...initialLocations . map ( j  =>  j  /  maxWidth  +  increment  *  i ) ] ; 
60+     return  [ 
61+       ...acc , 
62+       ...initialLocations . map ( j  =>  { 
63+         return  j  /  maxWidth  +  increment  *  i ; 
64+       } ) 
65+     ] ; 
7166  } ,  [ ] ) ; 
72-   const  colors  =  locations . map ( 
73-     ( _ ,  i )  =>  initialColors [ i  %  initialColors . length ] 
74-   ) ; 
67+   const  colors  =  locations . map ( ( _ ,  i )  =>  initialColors [ i  %  initialColors . length ] ) ; 
7568
76-   return  {  locations ,  colors  } ; 
69+   return  {  colors ,  locations  } ; 
7770} ; 
78- const  getVectorsByDirection  =  direction  =>  { 
71+ 
72+ const  getVectorsByDirection  =  memoize ( direction  =>  { 
7973  switch  ( direction )  { 
8074    case  "top" :
8175      return  getVectorsByAngle ( 0 ) ; 
@@ -94,35 +88,39 @@ const getVectorsByDirection = direction => {
9488    case  "right bottom" :
9589      return  getVectorsByAngle ( 90  +  45 ) ; 
9690  } 
97- } ; 
98- const   round   =   number   =>   Math . round ( number   *   1000 )   /   1000 ; 
99- const  degreesToRadians  =  function ( degrees )   { 
100-    return   ( degrees  *  Math . PI )  /  180 ; 
101- } ; 
102- const  getVectorsByAngle  =  alfa  =>  { 
91+ } ) ; 
92+ 
93+ const  round  =  memoize ( number   =>   Math . round ( number   *   10000 )   /   10000 ) ; 
94+ const   degreesToRadians   =   memoize ( degrees  =>   ( degrees   *  Math . PI )  /  180 ) ; 
95+ 
96+ const  getVectorsByAngle  =  memoize ( alfa  =>  { 
10397  const  angle  =  degreesToRadians ( alfa ) ; 
10498
105-   let  gradientLineLength  =  round ( 
106-     Math . abs ( Math . sin ( angle ) )  +  Math . abs ( Math . cos ( angle ) ) 
107-   ) ; 
99+   let  gradientLineLength  =  round ( Math . abs ( Math . sin ( angle ) )  +  Math . abs ( Math . cos ( angle ) ) ) ; 
108100  let  center  =  {  x : 0.5 ,  y : 0.5  } ; 
109101
110102  let  yDiff  =  ( Math . sin ( angle  -  Math . PI  /  2 )  *  gradientLineLength )  /  2 ; 
111103  let  xDiff  =  ( Math . cos ( angle  -  Math . PI  /  2 )  *  gradientLineLength )  /  2 ; 
112104
113105  return  { 
114-     start : [ center . x  -  xDiff ,  center . y  -  yDiff ] , 
115-     end : [ center . x  +  xDiff ,  center . y  +  yDiff ] 
106+     start : { 
107+       x : center . x  -  xDiff , 
108+       y : center . y  -  yDiff 
109+     } , 
110+     end : { 
111+       x : center . x  +  xDiff , 
112+       y : center . y  +  yDiff 
113+     } 
116114  } ; 
117- } ; 
115+ } ) ; 
118116
119117const  getVectorsByOrientation  =  orientation  =>  { 
120118  return  orientation . type  ===  "directional" 
121119    ? getVectorsByDirection ( orientation . value ) 
122120    : getVectorsByAngle ( orientation . value ) ; 
123121} ; 
124122
125- const  generateGradient  =  ( gradient ,  sizes )  =>  { 
123+ const  generateGradient  =  memoize ( ( gradient ,  sizes )  =>  { 
126124  return  parser . parse ( gradient ) . map ( ( {  type,  colorStops,  orientation } )  =>  { 
127125    // YOLO: Radial gradients <3 
128126    if  ( type  ===  "radial-gradient" )  { 
@@ -138,6 +136,6 @@ const generateGradient = (gradient, sizes) => {
138136      ...getVectorsByOrientation ( orientation ) 
139137    } ; 
140138  } ) ; 
141- } ; 
139+ } ) ; 
142140
143141export  default  generateGradient ; 
0 commit comments