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'
+}