<file_sep>[build]
  Command = "NODE_ENV=PRODUCTION npm run build && npm run build:lambda  && cp _redirects build/_redirects"
  Functions = "lambda"
  Publish = "build"
<file_sep>import React from 'react'
import Geolocation from 'react-geolocation'
import Result from './Components/Result'

const App = () => {
  return (
    <main className="wrapper">
      <Geolocation
        render={({ fetchingPosition, position: { coords } = {}, error, getCurrentPosition }) => (
          <Result coords={coords} error={error} getCurrentPosition={getCurrentPosition} fetching={fetchingPosition} />
        )}
      />
    </main>
  )
}

export default App
<file_sep>var requestAnimationFrame =
  window.requestAnimationFrame ||
  window.webkitRequestAnimationFrame ||
  window.mozRequestAnimationFrame ||
  window.oRequestAnimationFrame ||
  window.msRequestAnimationFrame

// Frame ticker helper module
var Ticker = (function() {
  var PUBLIC_API = {}

  // private
  var started = false
  var lastTimestamp = 0
  var listeners = []

  PUBLIC_API.addListener = function addListener(fn) {
    listeners.push(fn)

    // start frame-loop lazily
    if (!started) {
      started = true
      queueFrame()
    }
  }

  function queueFrame() {
    requestAnimationFrame(frameHandler)
  }
  function frameHandler(timestamp) {
    var frameTime = timestamp - lastTimestamp
    lastTimestamp = timestamp
    // make sure negative time isn't reported (first frame can be whacky)
    if (frameTime < 0) {
      frameTime = 17
    } else if (frameTime > 68) {
      frameTime = 68
    }

    // fire custom listeners
    for (var i = 0, len = listeners.length; i < len; i++) {
      // eslint-disable-next-line
      listeners[i].call(window, frameTime, frameTime / 16.67)
    }

    // always queue another frame
    queueFrame()
  }

  return PUBLIC_API
})()

// Animation namespace
var Animation = {
  speed: 1,
  color: {
    r: '80',
    g: '175',
    b: '255',
    a: '0.5'
  },

  // END CUSTOMIZATION
  // whether Animation is running
  started: false,
  // canvas and associated context references
  canvas: null,
  ctx: null,
  // viewport dimensions (DIPs)
  width: 0,
  height: 0,
  // devicePixelRatio alias (should only be used for rendering, physics shouldn't care)
  dpr: window.devicePixelRatio || 1,
  // time since last drop
  drop_time: 0,
  // ideal time between drops (changed with mouse/finger)
  drop_delay: 12,
  // wind applied to rain (changed with mouse/finger)
  wind: 4,
  // color of rain (set in init)
  rain_color: null,
  rain_color_clear: null,
  // rain particles
  rain: [],
  rainPool: [],
  // rain droplet (splash) particles
  drops: [],
  dropPool: []
}

// Animation initialization (should only run once)
Animation.init = function(el) {
  if (!Animation.started) {
    Animation.started = true
    Animation.canvas = el.current
    Animation.ctx = Animation.canvas.getContext('2d')
    var c = Animation.color
    Animation.rain_color = 'rgba(' + c.r + ',' + c.g + ',' + c.b + ',' + c.a + ')'
    Animation.rain_color_clear = 'rgba(' + c.r + ',' + c.g + ',' + c.b + ',0)'
    Animation.resize()
    Ticker.addListener(Animation.step)
  }
}

// (re)size canvas (clears all particles)
Animation.resize = () => {
  // localize common references
  var rain = Animation.rain
  var drops = Animation.drops
  // recycle particles
  for (var l = rain.length - 1; l >= 0; l--) {
    rain.pop().recycle()
  }
  for (var i = drops.length - 1; i >= 0; i--) {
    drops.pop().recycle()
  }
  // resize
  Animation.width = window.innerWidth
  Animation.height = window.innerHeight
  Animation.canvas.width = Animation.width * Animation.dpr
  Animation.canvas.height = Animation.height * Animation.dpr
}

Animation.step = (time, lag) => {
  const { width, height, speed, rain, drops, wind, rainPool } = Animation

  // multiplier for physics
  var multiplier = speed * lag

  // spawn drops
  Animation.drop_time += time * speed
  while (Animation.drop_time > Animation.drop_delay) {
    Animation.drop_time -= Animation.drop_delay
    var newRain = rainPool.pop() || new Rain()
    newRain.init()
    var windExpand = Math.abs((height / newRain.speed) * wind) // expand spawn width as wind increases
    var spawnX = Math.random() * (width + windExpand)
    if (wind > 0) spawnX -= windExpand
    newRain.x = spawnX
    rain.push(newRain)
  }

  // rain physics
  for (var i = rain.length - 1; i >= 0; i--) {
    var r = rain[i]
    r.y += r.speed * r.z * multiplier
    r.x += r.z * wind * multiplier
    // remove rain when out of view
    if (r.y > height) {
      // if rain reached bottom of view, show a splash
      r.splash()
    }
    // recycle rain
    if (r.y > height + Rain.height * r.z || (wind < 0 && r.x < wind) || (wind > 0 && r.x > width + wind)) {
      r.recycle()
      rain.splice(i, 1)
    }
  }

  // splash drop physics
  var dropMaxSpeed = Drop.max_speed
  for (var x = drops.length - 1; x >= 0; x--) {
    var d = drops[x]
    d.x += d.speed_x * multiplier
    d.y += d.speed_y * multiplier
    // apply gravity - magic number 0.3 represents a faked gravity constant
    d.speed_y += 0.3 * multiplier
    // apply wind (but scale back the force)
    d.speed_x += (wind / 25) * multiplier
    if (d.speed_x < -dropMaxSpeed) {
      d.speed_x = -dropMaxSpeed
    } else if (d.speed_x > dropMaxSpeed) {
      d.speed_x = dropMaxSpeed
    }
    // recycle
    if (d.y > height + d.radius) {
      d.recycle()
      drops.splice(x, 1)
    }
  }

  Animation.draw()
}

Animation.draw = () => {
  const { width, height, dpr, rain, drops, ctx } = Animation

  // start fresh
  ctx.clearRect(0, 0, width * dpr, height * dpr)

  // draw rain (trace all paths first, then stroke once)
  ctx.beginPath()
  var rainHeight = Rain.height * dpr
  for (var h = rain.length - 1; h >= 0; h--) {
    var r = rain[h]
    var realX = r.x * dpr
    var realY = r.y * dpr
    ctx.moveTo(realX, realY)
    // magic number 1.5 compensates for lack of trig in drawing angled rain
    ctx.lineTo(realX - Animation.wind * r.z * dpr * 1.5, realY - rainHeight * r.z)
  }
  ctx.lineWidth = Rain.width * dpr
  ctx.strokeStyle = Animation.rain_color
  ctx.stroke()

  // draw splash drops (just copy pre-rendered canvas)
  for (var i = drops.length - 1; i >= 0; i--) {
    var d = drops[i]
    var realX2 = d.x * dpr - d.radius
    var realY2 = d.y * dpr - d.radius
    ctx.drawImage(d.canvas, realX2, realY2)
  }
}

// Rain definition
function Rain() {
  this.x = 0
  this.y = 0
  this.z = 0
  this.speed = 25
  this.splashed = false
}
Rain.width = 2
Rain.height = 40
Rain.prototype.init = function() {
  this.y = Math.random() * -100
  this.z = Math.random() * 0.5 + 0.5
  this.splashed = false
}
Rain.prototype.recycle = function() {
  Animation.rainPool.push(this)
}
// recycle rain particle and create a burst of droplets
Rain.prototype.splash = function() {
  if (!this.splashed) {
    this.splashed = true
    var drops = Animation.drops
    var dropPool = Animation.dropPool

    for (var i = 0; i < 16; i++) {
      var drop = dropPool.pop() || new Drop()
      drops.push(drop)
      drop.init(this.x)
    }
  }
}

// Droplet definition
function Drop() {
  this.x = 0
  this.y = 0
  this.radius = Math.round(Math.random() * 2 + 1) * Animation.dpr
  this.speed_x = 0
  this.speed_y = 0
  this.canvas = document.createElement('canvas')
  this.ctx = this.canvas.getContext('2d')

  // render once and cache
  var diameter = this.radius * 2
  this.canvas.width = diameter
  this.canvas.height = diameter

  var grd = this.ctx.createRadialGradient(this.radius, this.radius, 1, this.radius, this.radius, this.radius)
  grd.addColorStop(0, Animation.rain_color)
  grd.addColorStop(1, Animation.rain_color_clear)
  this.ctx.fillStyle = grd
  this.ctx.fillRect(0, 0, diameter, diameter)
}

Drop.max_speed = 5

Drop.prototype.init = function(x) {
  this.x = x
  this.y = Animation.height
  var angle = Math.random() * Math.PI - Math.PI * 0.5
  var speed = Math.random() * Drop.max_speed
  this.speed_x = Math.sin(angle) * speed
  this.speed_y = -Math.cos(angle) * speed
}
Drop.prototype.recycle = function() {
  Animation.dropPool.push(this)
}

export default Animation
<file_sep>import React, { useEffect, useRef } from 'react'
import Animation from './rainAnimation'

export default () => {
  const Canvas = useRef(null)

  useEffect(() => {
    Animation.init(Canvas)
  }, [])

  return (
    <canvas ref={Canvas} width="1024" height="768">
      Canvas Not Supported! Please Update Your Browser to the Latest Version.
    </canvas>
  )
}
<file_sep># Is it Raining Outside?

Simple app that tells you if it's raining outside so you never have to get up again
