CLLLEANED the forms, inputs, buttons, labels and form/button groups

This commit is contained in:
2018-10-25 06:46:38 +11:00
parent 13aaccdd84
commit bccbd1cff1
25 changed files with 294 additions and 334 deletions

View File

@ -23,12 +23,14 @@
import React from 'react';
import Styles from './Input.scss';
import Keyboard from '@public/keyboard/Keyboard';
import Button from './button/Button';
import ButtonGroup from './button/ButtonGroup';
import Form, { FormManager } from './form/Form';
import InputGroup from './group/InputGroup';
import Form, { FormManager, FormGroup } from './form/Form';
import Label from './label/Label';
import Keyboard from '@public/keyboard/Keyboard';
export default class Input extends React.Component {
constructor(props) {
@ -45,7 +47,8 @@ export default class Input extends React.Component {
}
componentDidMount() {
if(this.props.manager) this.props.manager.addInput(this);
let { manager } = this.props;
if(manager) manager.addInput(this);
Keyboard.addListener(this);
}
@ -85,49 +88,44 @@ export default class Input extends React.Component {
}
render() {
let ElementType = "input";
let type = "text";
let value;
let newProps = {...this.props};
let {
value, className, type, children, style, error, danger, primary,
warning, manager
} = newProps;
//Clear bad props
[
"error", "danger", "primary", "warning", "manager", "style", "children"
].forEach(e => delete newProps[e]);
//Prop defaults
type = type || "text";
//Gen classes
let clazzes = "o-input";
let innerClazzes = "o-input__inner";
let style;
let props = Object.assign({}, this.props);
//Determining
if(props.type) type = props.type;
//Values
if(props.value) {
value = props.value;
} else {
value = props.children;
}
value = stateValue || value || children;
//Style
if(props.style) {
style = props.style;
} else if(props.error || props.danger) {
style = "danger";
} else if(props.warning) {
style = "warning";
} else if(props.primary) {
style = "primary";
}
if(primary) style = "primary";
if(warning) style = "warning";
if(error || danger) style = "danger";
//Classes
clazzes += " is-"+type;
clazzes += ` is-${type}`;
if(style) {
clazzes += " o-input--style-"+style;
innerClazzes += " o-input--style-"+style+"__inner";
}
if(props.className) {
clazzes += " " + props.className;
innerClazzes += " " + props.className + "-element";
clazzes += ` o-input--style-${style}`;
innerClazzes += ` o-input--style-${style}__inner`;
}
//Clear junk props
delete props.manager;
if(className) {
clazzes += ` ${className}`;
innerClazzes += ` ${className}-element`;
}
//Now create the element
let element;
@ -139,27 +137,15 @@ export default class Input extends React.Component {
className={props.className}
value={this.state.value}
/>);
}
} else if(type == "textarea") {
element = (<textarea
{...props}
className={innerClazzes}
onChange={this.onChange.bind(this)}
onFocus={this.onFocus.bind(this)}
onBlur={this.onBlur.bind(this)}
>{ this.state.value }</textarea>
);
[ "onChange", "onFocus", "onBlur"].forEach(e => newProps[e] = this[e]);
//Text areas are slightly different
if(type == "textarea") {
element = <textarea {...newProps} className={innerClazzes} children={value} />
} else {
element = (<ElementType
{...props}
onChange={this.onChange.bind(this)}
onFocus={this.onFocus.bind(this)}
onBlur={this.onBlur.bind(this)}
type={type}
value={ this.state.value }
className={innerClazzes}
/>);
element = <input {...newProps} type={type} value={ value } className={innerClazzes} />;
}
return (
@ -179,7 +165,7 @@ export {
ButtonGroup,
Form,
FormManager,
InputGroup,
FormGroup,
TextArea,
Label
};

View File

@ -0,0 +1,29 @@
/*
* Input
* Contains styles for input and input elements.
*
* Dependencies:
* styles/tools/_input.scss
*
*
* Version:
* 1.0.0 - 2018/05/13
*/
@import '~@styles/global';
.o-input {
@include t-input--style-dp();
width: 100%;
&__inner {
//Textarea
margin: 0;//For some reason textareas have a 1px margin
max-width: 100%;
min-width: 100%;
}
}
.o-label {
display: none;
visibility: hidden;
}

View File

@ -24,81 +24,61 @@
import React from 'react';
import { NavLink } from 'react-router-dom';
export default class Button extends React.Component {
constructor(props) {
super(props);
import Styles from './Button.scss';
export default props => {
let newProps = {...props};
let {
className, href, to, style, type, value, children,
error, danger, primary, warning, manager
} = newProps;
[
"style", "value", "href", "to", "children", "error", "danger", "primary",
"warning", "manager"
].forEach(e => delete newProps[e]);
type = type || "button";
children = children || value;
if(primary) style = "primary";
if(warning) style = "warning";
if(error || danger) style = "danger";
let ElementType = "button";//Upper Camel-Case because of react requriements
let clazzes = "o-btn";
//Basic Element Determining
if(type) {
//Buttons and Input Buttons
clazzes += " is-button";
} else if(href) {
//Anchor Tags!
ElementType = "a";
clazzes += " is-link is-anchor";
newProps.href = to || href;
} else if(to) {
ElementType = NavLink;
clazzes += " is-link is-nav-link";
newProps.to = to || href;
} else {
//Everything Else (button without a type);
clazzes += " is-not-button";
}
render() {
let ElementType = "button";//Upper Camel-Case because of react requriements
let clazzes = "o-btn";
let type = "button";
let contents;
let href;
let to;
let activeClassName;
let style;
if(style) clazzes += ` o-btn--style-${style}`;
if(className) clazzes += ` ${className}`;
//Basic Element Determining
if(this.props.type) {
//Buttons and Input Buttons
type = this.props.type;
clazzes += " is-button";
} else if(this.props.href) {
//Anchor Tags1
ElementType = "a";
href = this.props.href;
clazzes += " is-link is-anchor";
} else if(this.props.to) {
//React NavLink/Link
to = this.props.to;
ElementType = NavLink;
clazzes += " is-link is-nav-link";
activeClassName = "is-active";
} else {
//Everything Else (button without a type);
clazzes += " is-not-button";
}
if(this.props.value) {
contents = this.props.value;
} else {
contents = this.props.children;
}
//Determine Style
if(this.props.primary) {
style = "primary"
} else if(this.props.secondary) {
style = "secondary";
} else if(this.props.danger) {
style = "danger";
} else if(this.props.warning) {
style = "warning";
} else if(this.props.style) {
style = this.props.style;
}
//Style Clazzes
if(style) {
clazzes += " o-btn--style-"+style;
}
//Determine extra clazzes
if(this.props.className) this.clazzes += " "+this.props.className;
return (
<ElementType
{...this.props}
type={type}
className={clazzes}
href={href}
to={to}
>
<span className={ "o-btn__inner" + (style ? " o-btn--style-" + style + "__inner" : "") }>
{contents}
</span>
</ElementType>
);
}
return (
<ElementType {...newProps} className={clazzes}>
<span className={"o-btn__inner"+(style?` o-btn--style-${style}__inner`:"")}>
{contents}
</span>
</ElementType>
);
}

View File

@ -0,0 +1,48 @@
/*
* Button
* Clicky Tappy Touchy Buttons!
*
* Dependencies:
* styles/settings/animation.scss
* styles/settings/colors.scss
* styles/tools/_box-shadow.scss
*
*
* Version:
* 1.0.1 - 2018/05/14
*/
@import '~@styles/global';
//Default Button (applies to all styles)
.o-btn {
cursor: pointer;
@include t-input--style-dp();
&__inner {
padding: ( $t-input--style-dp__padding / 2 ) $t-input--style-dp__padding;
}
&:hover {
text-decoration: none;/* Override Standard Link Underline */
}
}
//Button Group
.o-btn-group {
.o-btn + .o-btn {
margin-left: 1em;
}
}
/*** Custom Button Styles ***/
@mixin o-basic-button-design($top, $bottom) {
&::before,
&:active &__inner {
background: $bottom;
}
&__inner {
background: $top;
}
}

View File

@ -23,10 +23,9 @@
import React from 'react';
export default function(props) {
export default props => {
let { className } = props;
return (
<div {...props} className={"o-btn-group" + (props.className ? " "+props.className : "")}>
{props.children}
</div>
<div {...props} className={"o-btn-group" + (className?` ${className}`:"")} />
);
}

View File

@ -22,47 +22,54 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import React from 'react';
import Styles from './Form.scss';
import FormGroup from './group/FormGroup';
import Loader, { LoaderBackdrop } from '@objects/loading/Loader';
import Input, { InputGroup, TextArea } from './../Input';
import Input, { TextArea } from './../Input';
export default class Form extends React.Component {
constructor(props) {
super(props);
//Prepare our initial state
let s = {
ajax: props.ajax || false,
loader: props.loader || false,
loading: false,
onSubmit: props.onSubmit,
contentType: props.contentType || props.encType || "application/x-www-form-urlencoded",
manager: props.manager
};
let {
ajax, loader, onSubmit, contentType, encType, manager, action, method,
get, post
} = props;
contentType = contentType || encType || "application/x-www-form-urlencoded";
//Determine action and method based off the internals
if(props.action) s.action = props.action;
if(props.method) s.method = props.method;
if(props.get) {
s.action = props.get;
s.method = "GET";
if(get) {
action = get;
method = "GET";
}
if(props.post) {
s.action = props.post;
s.method = "POST";
if(post) {
action = post;
method = "POST";
}
//Write our state to the component
this.state = s;
//Prepare our initial state
this.state = {
ajax,
loader,
loading: false,
onSubmit,
contentType,
manager
};
}
componentDidMount() {
if(this.props.manager) this.props.manager.addForm(this);
let { manager } = this.props;
if(manager) manager.addForm(this);
}
componentWillUnmount() {
if(this.props.manager) this.props.manager.removeForm(this);
let { manager } = this.props;
if(manager) manager.removeForm(this);
}
submit() {
@ -70,14 +77,19 @@ export default class Form extends React.Component {
}
onSubmit(e) {
let {
ajax, onSubmit, action, submitting, method, mode, contentType
} = this.state;
let { manager } = this.props;
//Is Ajax?
if(!this.state.ajax) {
return this.state.onSubmit ? this.state.onSubmit(e) : true;
if(!ajax) {
return onSubmit ? onSubmit(e) : true;
}
if(e) e.preventDefault();
if(!this.state.action) return console.warning("This form has no action.");
if(this.state.submitting) return false;//Already submitting?
if(e && e.preventDefault) e.preventDefault();
if(!action) return console.warning("This form has no action.");
if(submitting) return false;//Already submitting?
//Start submitting!
this.setState({
@ -87,30 +99,26 @@ export default class Form extends React.Component {
//Prepare our data
let data;
if(this.props.manager) {
data = this.props.manager.getFormData();
}
if(manager) data = manager.getFormData();
data = data || {};
if(this.state.contentType == "application/json") {
if(contentType == "application/json") {
let dataJson = {};
data.forEach(function(value, key) {
data.forEach((value, key) => {
dataJson[key] = value;
});
data = JSON.stringify(dataJson);
}
//Prepare our request.
fetch(this.state.action, {
method: this.state.method,
mode: this.state.mode,
fetch(action, {
method: method,
mode: mode,
body: data,
headers: {
"Content-Type": this.state.contentType
"Content-Type": contentType
}
})
.then(this.onSubmitted.bind(this))
.catch(this.onError.bind(this))
;
}).then(resp => this.onSubmitted(resp)).catch((e,a,b) => this.onError(e,a,b));
return false;
}
@ -124,20 +132,19 @@ export default class Form extends React.Component {
let is4xx = Math.floor(response.status / 400) === 1;
if(is4xx) {
return response[method]()
.then(this.onErrorText.bind(this))
.catch(this.onError.bind(this))
.then((e,a,b) => this.onErrorText(e,a,b))
.catch((e,a,b) => this.onError(e,a,b))
;
} else {
throw Error(response.statusText);
}
throw Error(response.statusText);
}
if(this.props.onData) return this.props.onData(response);
//Handle the old fashioned way (expect json)
response[method]()
.then(this.onData.bind(this))
.catch(this.onError.bind(this))
.then(resp => this.onData(resp))
.catch((e,a,b) => this.onError(e,a,b))
;
}
@ -163,13 +170,16 @@ export default class Form extends React.Component {
}
render() {
let { className, children } = this.props;
let { loader, loading } = this.state;
let clazz = "o-form";
if(this.props.className) clazz += " " + this.props.className;
if(className) clazz += ` ${className}`
//Do I need a loader?
let loader;
if(this.state.loader && this.state.loading) {
loader = (
let loaderElement;
if(loader && loading) {
loaderElement = (
<LoaderBackdrop className="o-form__loader">
<Loader className="o-form__loader-spinner" />
</LoaderBackdrop>
@ -178,15 +188,14 @@ export default class Form extends React.Component {
return (
<form
{...this.props}
ref="formDOM"
className={clazz}
className={ clazz }
method={ this.state.method }
autoComplete={ this.props.autoComplete }
target={ this.props.target }
onSubmit={ this.onSubmit.bind(this) }
onSubmit={ (e) => this.onSubmit(e) }
>
{ this.props.children }
{ loader }
{ children }
{ loaderElement }
</form>
);
}
@ -235,5 +244,6 @@ class FormManager {
}
export {
FormManager
FormManager,
FormGroup
};

View File

@ -0,0 +1,21 @@
/*
* Form
* Forms
*
* Dependencies:
*
*
* Version:
* 1.0.0 - 2018/05/13
*/
@import '~@styles/global';
.o-form {
position: relative;
}
.o-form__group {
+ .o-btn-group,
+ .o-form__group {
margin-top: 1em;
}
}

View File

@ -23,14 +23,11 @@
import React from 'react';
export default function(props) {
export default props => {
let clazzes = "o-form__group";
if(props.className) clazzes += " " + props.className;
if(props.className) clazzes += ` ${props.className}`;
return (
<div className={clazzes}>
{ props.children }
</div>
<div {...props} className={clazzes} />
);
}

View File

@ -23,13 +23,9 @@
import React from 'react';
export default function(props) {
export default props => {
let clazz = "o-label";
if(props.className) clazz += " " + props.className;
if(props.className) clazz += ` ${props.className}`;
return (
<label htmlFor={ props.htmlFor } className={clazz}>
{ props.children }
</label>
);
return <label {...props} className={clazz} />;
}