ldx-widgets
Version:
widgets
134 lines (94 loc) • 3.26 kB
text/coffeescript
React = require 'react'
createClass = require 'create-react-class'
clone = require 'lodash/clone'
Animation = require 'ainojs-animation'
easing = require 'ainojs-easing'
{svg, path, div} = require 'react-dom-factories'
###&
@props.onClick - OPTIONAL - [Function]
handle click events
@props.positionClass - OPTIONAL - [String]
add a CSS class to adjust element positioning
@props.invertOnClick - OPTIONAL - [Boolean]
determines whether or not the element is inverted on click event
@props.defaultOrientation - OPTIONAL - [String]
Accepts values `up`, `left`, `down`, or `right` to set the default direction
@props.isInverted - OPTIONAL - [Boolean]
determines whether or not the chevron is in an inverted state
@props.animationDuration - OPTIONAL [Number]
duration in milliseconds determining how long the animation takes to complete
@props.color - OPTIONAL [String]
hex/rgba color to fill the chevron
&###
Chevron = createClass
displayName: 'Chevron'
getDefaultProps: ->
{
onClick: -> # method to handle clicks
positionClass: null # and additionaly class to add for positioning the element
invertOnClick: no # whether or not to invert to the opposite position on clicks
defaultOrientation: 'down' # or 'up, 'left, 'right' - which way the chevron points by default
isInverted: no # tells the widget to invert, either on mount or afterwards
animationDuration: 200
color: "#37BAC4"
}
default:
d1: 4
d2: -4
d3: 6
d4: -4
d5: 0
d6: 4
inverted:
d1: 0
d2: 4
d3: 2
d4: 4
d5: 4
d6: -4
render: ->
{positionClass, onClick, defaultOrientation, color} = @props
{d1, d2, d3, d4, d5, d6} = @state
dAttr = "M4 #{d1}l5 #{d2}v2L4 #{d3}l-5 #{d4}V#{d5}l5 #{d6}z"
className = 'chevron'
className += " #{defaultOrientation}"
className += " #{positionClass}" if positionClass?
div {
className: className
onClick: @handleClick
}, svg {
className: 'chevron-svg'
width: "10"
height: "6"
viewBox:"-1 0 10 6"
}, path {fill: color, d: dAttr}
getInitialState: ->
@isInverted = @props.isInverted
if @isInverted then @inverted
else @default
componentDidMount: ->
@animation = new Animation
duration: @props.animationDuration
easing: easing 'linear'
.on('frame', @onFrame)
componentWillReceiveProps: (nextProps) ->
if nextProps.isInverted isnt @isInverted
@animate() if @props.invertOnClick
componentWillUnmount: ->
@animation.end() if @animation?.isAnimating()
@animation.destroy()
onFrame: (e) ->
@setState e.values
handleClick: (e) ->
e.stopPropagation()
@props.onClick?()
@animate() if @props.invertOnClick
animate: ->
@isInverted = not @isInverted
# Note: need to clone here so animate class does not alter initial values
stateStart = clone(@state)
stateEnd = clone(if @isInverted then @inverted else @default)
# Note: Not feeding init @state directly, because that will clobber @state properties not being animated
@animation.init stateStart
@animation.animateTo stateEnd
module.exports = Chevron