Rift.IO OSM R1 Initial Submission

Signed-off-by: Jeremy Mordkoff <jeremy.mordkoff@riftio.com>
diff --git a/skyquake/framework/widgets/button/button.scss b/skyquake/framework/widgets/button/button.scss
new file mode 100644
index 0000000..c972e14
--- /dev/null
+++ b/skyquake/framework/widgets/button/button.scss
@@ -0,0 +1,270 @@
+
+/*
+ * 
+ *   Copyright 2016 RIFT.IO Inc
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+@import '../../style/_colors.scss';
+@import '../../style/variables.scss';
+
+button{
+    color: #000000;
+    display: inline-block;
+    font-size: 0.75rem;
+    padding: 0.75rem 3rem;
+    text-decoration: none;
+    text-transform: uppercase;
+    box-shadow: 2px 2px rgba(0, 0, 0, 0.15);
+    cursor: pointer;
+    margin:0 1rem;
+  &.light {
+    background-color: #ffffff;
+    border: 1px solid #cccccc;
+    border-top: 0;
+    &.small {
+      padding:0.25rem 1rem;
+    }
+  }
+
+  &.dark {
+    background-color: #333333;
+    border: 1px solid #000000;
+    border-top: 0;
+    color: #ffffff;
+    &:hover,&:active {
+      background: #00acee;
+      color: #ffffff;
+    }
+  }
+
+
+}
+
+/* IMPORTS
+############################################################################ */
+
+
+
+
+/* BUTTON
+############################################################################ */
+
+.SqButton {
+  align-items: center;
+  border-style: solid;
+  border-radius: 3px;
+  border-width: 0px;
+  cursor: pointer;
+  display: inline-flex;
+  font-size: 1rem;
+  height: 50px;
+  justify-content: center;
+  margin: 0 10px;
+  outline: none;
+  padding: 0 15px;
+  text-transform: uppercase;
+  transition: $transition;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  -webkit-touch-callout: none;
+  -webkit-user-select: none;
+  user-select: none;
+
+  /* Button Content */
+  &-content {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    transition: $transition;
+    white-space: nowrap;
+  }
+
+  /* Button Icon */
+  &-icon {
+    transition: $transition;
+  }
+
+  /* Spacing between content and icon when icon is on the right */
+  &-icon + &-content {
+    margin-left: 10px;
+  }
+
+  /* Spacing between content and icon when icon is on the left */
+  &-content + &-icon {
+    margin-left: 10px;
+  }
+
+  /* Focus */
+  &:focus {
+    // box-shadow: $focus-shadow;
+    border: 1px solid red;
+  }
+
+  /* SIZES
+  ############################################################################ */
+
+  &--large {
+    width: 250px;
+  }
+
+  &--medium {
+    width: 175px;
+  }
+
+  &--small {
+    width: 85px;
+  }
+
+  /* NORMAL
+  ############################################################################ */
+
+  /* Base */
+  &--normal {
+    background: $normalBackground;
+    border-color: darken($normalBackground, 10%);
+
+    .SqButton-content {
+      color: $normalForeground;
+    }
+
+    .SqButton-icon {
+      fill: $normalForeground;
+    }
+  }
+
+  /* Hover */
+  &--normal:hover {
+    background: $normalHoverBackground;
+    border-color: darken($normalHoverBackground, 10%);
+
+    .SqButton-content {
+      color: $normalHoverForeground;
+    }
+
+    .SqButton-icon {
+      fill: $normalHoverForeground;
+    }
+  }
+
+  /* Active */
+  &--normal:active {
+    background: $normalActiveBackground;
+    border-color: darken($normalActiveBackground, 10%);
+
+    .SqButton-content {
+      color: $normalActiveForeground;
+    }
+
+    .SqButton-icon {
+      fill: $normalActiveForeground;
+    }
+  }
+
+  /* Disabled */
+  &--normal.is-disabled {
+    cursor: default;
+    opacity: .55;
+  }
+
+  &--normal:hover.is-disabled,
+  &--normal:active.is-disabled {
+    background: $normalBackground;
+    border-color: darken($normalBackground, 10%);
+
+    .SqButton-content {
+      color: $normalForeground;
+    }
+
+    .SqButton-icon {
+      fill: $normalForeground;
+    }
+  }
+
+
+  /* PRIMARY
+  ############################################################################ */
+
+  /* Base */
+  &--primary {
+    background: $primaryBackground;
+    border-color: darken($primaryBackground, 10%);
+
+    .SqButton-content {
+      color: $primaryForeground;
+    }
+
+    .SqButton-icon {
+      fill: $primaryForeground;
+    }
+  }
+
+  /* Hover */
+  &--primary:hover {
+    background: $primaryHoverBackground;
+    border-color: darken($primaryHoverBackground, 10%);
+
+    .SqButton-content {
+      color: $primaryHoverForeground;
+    }
+
+    .SqButton-icon {
+      fill: $primaryHoverForeground;
+    }
+  }
+
+  /* Active */
+  &--primary:active {
+    background: $primaryActiveBackground;
+    border-color: darken($primaryActiveBackground, 10%);
+
+    .SqButton-content {
+      color: $primaryActiveForeground;
+    }
+
+    .SqButton-icon {
+      fill: $primaryActiveForeground;
+    }
+  }
+
+  /* Disabled */
+  &--primary.is-disabled {
+    cursor: default;
+    opacity: .55;
+  }
+
+  &--primary:hover.is-disabled,
+  &--primary:active.is-disabled {
+    background: $primaryBackground;
+    border-color: darken($primaryBackground, 10%);
+
+    .SqButton-content {
+      color: $primaryForeground;
+    }
+
+    .SqButton-icon {
+      fill: $primaryForeground;
+    }
+  }
+
+
+}
+
+
+
+
+
+
+
+
+
diff --git a/skyquake/framework/widgets/button/rw.button.js b/skyquake/framework/widgets/button/rw.button.js
new file mode 100644
index 0000000..41730eb
--- /dev/null
+++ b/skyquake/framework/widgets/button/rw.button.js
@@ -0,0 +1,261 @@
+
+/*
+ * 
+ *   Copyright 2016 RIFT.IO Inc
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+import './button.scss';
+import Loader from '../loading-indicator/loadingIndicator.jsx';
+var React = require('react');
+var ButtonEventListenerMixin = require('../mixins/ButtonEventListener.js');
+
+
+/**
+ *  A generic button component.
+ *  It's props values and a brief description below
+ *
+ *  Label: The label of the button. What it displays at any given time.
+ *  Icon: A url for an icon that will be displayed on the button.  Leave blank if no icon required.
+ *  Class: Css Classes applied to the element.
+ *  sizeOfButton: The preset sizes for the button (small, default, large, xlarge, expand).
+ *  minWidth: Minimum Width of the button.
+ *  maxWidth: Maximum Width of the button.
+ **/
+module.exports = React.createClass({
+  displayName: "Button",
+  mixins:[ButtonEventListenerMixin],
+  propTypes: {
+    label:           React.PropTypes.string,
+    icon:            React.PropTypes.array,
+    className:       React.PropTypes.string,
+    //sizeOfButton:    React.PropTypes.string,
+    minWidth:        React.PropTypes.string,
+    maxWidth:        React.PropTypes.string,
+    //isActive:        React.PropTypes.bool,
+    //isFocused:       React.PropTypes.bool,
+    //isHovered:       React.PropTypes.bool,
+    isDisabled:      React.PropTypes.bool
+  },
+
+
+  /**
+   * Defines default state.
+   * sizeOfButton: See Prop type definitions.
+   * class: See Prop type definitions.
+   * label: See Prop type definitions.
+   * isActive: Boolean to indicate if button is active.
+   * isHovered: Boolean to indicate if the button is being hovered over.
+   * isFocused: Boolean to indicate if the button has been focused.
+   * isDisabled: Boolean to indicate if button has been disabled.
+   * @returns {{sizeOfButton: (*|string), class: *, isActive: boolean, isHovered: boolean,
+   *            isFocused: boolean, isDisabled: (*|boolean), label: *}}
+   */
+  getInitialState: function() {
+    return {
+      //sizeOfButton:   this.props.size || '',  //There is no Medium value in CSS, default size is the absence of a value
+      className:      this.props.className || 'rw-button-primary', //Default value is 'rw-button-primary' which is the primary one
+      label:          this.props.label,
+      isActive:       false,
+      isHovered:      false,
+      isFocused:      false,
+      isLoading:      this.props.isLoading || false,
+      isDisabled:     this.props.isDisabled || false
+    }
+  },
+
+
+  /**
+   * If any of the state variables have changed, the component should update.
+   * "nextProps" and "nextState" hold the state and property variables as they will be after the update.
+   * "this.props" and "this.state" hold the state and property variables as they were before the update.
+   * returns true if the state have changed. Otherwise returns false.
+   * @param nextProps
+   * @param nextState
+   * @returns {boolean}
+   */
+  shouldComponentUpdate: function(nextProps, nextState) {
+    var currentStateString = this.state.label + this.state.isDisabled + this.state.isActive + this.state.isFocused +
+      this.state.isHovered + this.props.isLoading;
+    var nextStateString = nextState.label + nextState.isDisabled + nextState.isActive + nextState.isFocused +
+      nextState.isHovered + nextProps.isLoading;
+
+    if (currentStateString == nextStateString) {
+      return false;
+    }
+    return true;
+  },
+
+
+  /**
+   * Returns a string reflecting the current state of the button.
+   * If the button state "isDisabled" is true, returns a string "disabled".
+   * Otherwise returns a string containing a word for each state that has been set to true.
+   * (ie "active focused" if the states active and focused are true, but hovered is false).
+   * @returns {string}
+   */
+  setButtonState: function() {
+    var ret = "";
+    if (this.state.isDisabled) {
+      return "disabled";
+    }
+    if (this.state.isActive) {
+      ret += "active ";
+    }
+    if (this.state.isHovered) {
+      ret += "hovered ";
+    }
+    if (this.state.isFocused) {
+      ret += "focused ";
+    }
+    return ret;
+  },
+
+
+
+  /**
+   * Track the width if set and write into markup using Style attribute
+   * Returns the minWidth and maxWidth prop in a string
+   * @returns {{}}
+   */
+  setButtonWidth:function(){

+    var width = {};


+
+    if (this.props.minWidth) {

+      width.minWidth = String(this.props.minWidth);

+    }

+    if (this.props.maxWidth) {

+      width.maxWidth = String(this.props.maxWidth);

+    }

+
+    return width;

+  },
+
+
+
+  /**
+   * Apply the size of the button to the icon directly
+   * Returns a string indicating the icon size.
+   * @returns {string}
+   */
+  /*
+  setIconSize:function(){
+
+    var iconClass = "rw-icon";
+
+    if(this.props.size){
+      iconClass += "-" + this.props.size;
+    }
+    return iconClass;
+  },
+  */
+
+
+
+  /**
+   * Builds the list of classes.
+   * Returns a string holding each class seperated by a space.
+   * @returns {string}
+   */
+  /*
+  setButtonClass:function() {
+    var buttonClass = "";
+    var buttonClassType = "rw-button-primary";
+    // If the size is declared, add it in
+    if (this.state.sizeOfButton) {
+      buttonClass += this.state.sizeOfButton;
+    }
+    //
+    if (typeof(this.props.className) != "undefined") {
+      this.props.className.push("rw-button-secondary");
+
+      // Run through the array and check all the values
+      for (var i = 0; i < this.props.className.length; i++) {
+
+        if (this.props.className[i].indexOf("secondary") > -1) {
+          buttonClassType = "rw-button-secondary";  // If the value of the array is equal to the string "secondary", add a predefined string
+        } else {
+          buttonClass += " " + this.props.className[i];  // Else just write the value of the array
+        }
+      }
+    }
+    buttonClass += " " + buttonClassType;  //Add the button style type either primary or secondary
+    return buttonClass;
+  },
+  */
+
+  /**
+   * Builds an array of html elements for the icons and returns them.
+   * @returns {Array}
+   */
+  setIconElement: function() {
+    var button_icon = [];
+
+    if (typeof(this.props.icon) != "undefined") {
+      for (var i = 0; i < this.props.icon.length; i++) {
+        button_icon.push(React.createElement('svg', {
+          className: "rw-button__icon",
+          key: i,
+          dangerouslySetInnerHTML: {__html: '<use xlink:href="#' + this.props.icon[i] + '" />'}  //Using a React method to drop in a hack since React does not support xlink:href yet
+        }));
+      }
+    }
+    return button_icon;
+  },
+
+  /**
+   * Renders the Button Component
+   * Returns a react component that constructs the html that houses the button component.
+   * @returns {*}
+   */
+  render: function() {
+    var button = null;
+    var button_style = this.setButtonWidth();
+    var button_state = this.setButtonState();
+    var button_class = this.state.className;
+    var button_icon = this.setIconElement();
+    var display = this.state.label;
+    if (this.props.isLoading) {
+      display = React.createElement(Loader, {show: true, size: '1rem', color: this.props.loadingColor});
+    }
+
+    button = React.createElement("button", {
+        className:         button_class,
+        "data-state":      button_state,
+        style:             button_style,
+
+        // onClick:           this.onClick,
+        onClick:           this.props.onClick,
+        onMouseUp:         this.onMouseUp,
+        onMouseDown:       this.onMouseDown,
+        onMouseOver:       this.onMouseOver,
+        onMouseEnter:      this.onMouseEnter,
+        onMouseLeave:      this.onMouseLeave,
+        onMouseOut:        this.onMouseOut,
+        onTouchCancel:     this.onTouchCancel,
+        onTouchEnd:        this.onTouchEnd,
+        onTouchMove:       this.onTouchMove,
+        onTouchStart:      this.onTouchStart,
+        onKeyDown:         this.onKeyDown,
+        onKeyPress:        this.onKeyPress,
+        onKeyUp:           this.onKeyUp,
+        onFocus:           this.onFocus,
+        onBlur:            this.onBlur
+      },
+      button_icon,
+      React.createElement("span", {className: "rw-button__label"}, display)
+    );
+    return button;
+  }
+});
diff --git a/skyquake/framework/widgets/button/sq-button.jsx b/skyquake/framework/widgets/button/sq-button.jsx
new file mode 100644
index 0000000..ae93128
--- /dev/null
+++ b/skyquake/framework/widgets/button/sq-button.jsx
@@ -0,0 +1,55 @@
+import React from 'react';
+
+import 'style/base.scss';
+import './button.scss';
+
+const icons = {
+    check: require("style/icons/svg-sprite-navigation-symbol.svg")  + "#ic_check_24px"
+}
+
+export default class SqButton extends React.Component {
+    constructor(props) {
+        super(props);
+    }
+    render() {
+        let {icon, primary, size, disabled, label, ...props} = this.props;
+        let svgHTML = null;
+        let Class = "SqButton";
+        if(icon) {
+            svgHTML = <svg className="svg-24px SqButton-icon">
+            <use xlinkHref={icons[icon]}></use></svg>;
+        }
+        if(primary) {
+            Class += " SqButton--primary";
+        } else {
+            Class += " SqButton--normal";
+        }
+        if(size && (
+                size == 'small'
+                || size == 'medium'
+                || size == 'large'
+                )
+            ) {
+            Class += " SqButton--" + size;
+        }
+        if(disabled) {
+            Class += " is-disabled";
+        }
+        return (
+                <div style={{display: 'flex'}}>
+            <div className={Class} tabIndex="0">
+            {svgHTML}
+              <div className="SqButton-content">{label}</div>
+            </div>
+            </div>
+        )
+    }
+}
+
+SqButton.defaultProps = {
+    icon: false,
+    primary: false,
+    disabled: false,
+    size: false, // 'small', 'medium', 'large'
+    label: 'Submit'
+}