rewrite form controls with react

This commit is contained in:
Val Erastov 2018-01-16 19:39:12 -08:00 committed by xibyte
parent b7be796a5f
commit 4214715fd6
22 changed files with 243 additions and 66 deletions

View file

@ -1,7 +1,4 @@
.root {
color: #eee;
font: 11px 'Lucida Grande', sans-serif;
background-color: #1a1a1a;
}
.title {

View file

@ -0,0 +1,15 @@
import React from 'react';
import ls from './Stack.less'
export default function Stack({children}) {
return <div className={ls.root}>{children}</div>
}
Window.defaultProps = {
type: 'neutral',
};

View file

@ -0,0 +1,9 @@
@import '../styles/theme';
@import '../styles/mixins';
.root > * {
border-bottom: 1px solid @border-color;
padding: 0.3em 0.5em;
}

View file

@ -6,21 +6,23 @@ import Fa from "./Fa";
export default class Window extends React.Component {
constructor({initWidth}) {
constructor({initWidth, initLeft, initTop}) {
super();
this.state = {
width: initWidth
width: initWidth,
left: initLeft,
top: initTop
}
}
render() {
let {children, title, minimizable } = this.props;
let {children, title, minimizable, onClose} = this.props;
return <div className={ls.root} style={this.getStyle()}>
<div className={ls.bar}>
{title}
<div className={ls.bar + ' disable-selection'}>
<div><b>{title.toUpperCase()}</b></div>
<div className={ls.controlButtons}>
{minimizable && <span className={ls.button}>_</span>}
<span className={ls.button}><Fa icon='close' /></span>
<span className={ls.button} onClick={onClose}><Fa fw icon='close' /></span>
</div>
</div>
{children}
@ -30,10 +32,10 @@ export default class Window extends React.Component {
getStyle() {
return {
width: toPx(this.state.width),
height: toPx(this.state.height),
left: toPx(this.state.left),
top: toPx(this.state.top)
width: this.state.width,
height: this.state.height,
left: this.state.left,
top: this.state.top
}
}
}
@ -42,7 +44,4 @@ Window.defaultProps = {
minimizable: false,
};
function toPx(val) {
return val === undefined ? undefined : val + 'px';
}

View file

@ -1,8 +1,24 @@
@import '../styles/theme';
@import '../styles/mixins';
.root {
position: absolute;
background-color: @bg-color-alt;
}
.bar {
display: flex;
align-items: baseline;
justify-content: space-between;
background-color: @bg-color;
line-height: 1;
cursor: default;
border-bottom: 1px solid @border-color;
padding-left: 0.5em;
}
.button {
display: inline-block;
padding: 0.5em 0.5em 0.6em 0.5em;
.button-behavior(@color-danger);
}

View file

@ -2,8 +2,16 @@ import React from 'react';
import ls from './Button.less'
export default function Button({text}) {
export default function Button({text, type}) {
return <span>{text}</span>
return <button className={ls[type]}>{text}</button>
}
Button.defaultProps = {
type: 'neutral',
};

View file

@ -0,0 +1,18 @@
@import '../../styles/theme';
@import '../../styles/mixins';
.neutral, .accent, .danger {
background-color: darken(@color-neutral, 10%);
}
.neutral {
.button-behavior(@color-neutral)
}
.accent {
.button-behavior(@color-accent)
}
.danger {
.button-behavior(@color-danger)
}

View file

@ -4,6 +4,6 @@ import ls from './ButtonGroup.less'
export default function ButtonGroup({children}) {
return <div>{children}</div>
return <div className={ls.root}>{children}</div>
}

View file

@ -0,0 +1,8 @@
.root {
display: flex;
justify-content: flex-end;
& > * {
margin-left: 0.5em;
}
}

View file

@ -1,12 +1,10 @@
import React from 'react';
import ls from './Label.less'
import ls from './Field.less'
export default function Field({children}) {
return <div className={ls.root}>
{children[0]} {children[1]}
{children}
</div>;
}

View file

@ -0,0 +1,5 @@
.root {
display: flex;
justify-content: space-between;
align-items: baseline;
}

View file

@ -0,0 +1,23 @@
import React from 'react';
import PropTypes from 'prop-types';
import ls from './InputControl.less'
export default class InputControl extends React.Component {
render() {
let {type, inputRef, ...props} = this.props;
return <div className={ls[type]}>
<input type='text' ref={inputRef} {...props} spellcheck='false' />
</div>;
}
}
InputControl.propTypes = {
type: PropTypes.oneOf(['number', 'text']),
};
InputControl.defaultProps = {
type: 'text'
};

View file

@ -0,0 +1,20 @@
@import '../../styles/theme';
.number input {
.colorStyling(@control-color-number, @control-bg);
}
.text input {
.colorStyling(@control-color-text, @control-bg);
}
.colorStyling(@color, @bg) {
color: @color;
background: @bg;
outline: none;
border: @bg 1px solid;
padding: 0.2em;
&:focus {
border: #444 1px solid;
}
}

View file

@ -1,19 +1,16 @@
import React from 'react';
import PropTypes from 'prop-types';
import InputControl from './InputControl';
import ls from './NumberControl.less'
export default class NumberControl extends React.Component{
export default class NumberControl extends React.Component {
render() {
let {initValue, } = this.props;
return <div className={ls.root}>
<input type='text' defaultValue={initValue}
ref={(input) => this.input = input}
onWheel={this.onWheel}
onChange={e => onChange(e.target.value)} />
</div>;
let {onChange, initValue} = this.props;
return <InputControl type='number'
onWheel={this.onWheel}
defaultValue={initValue}
onChange={e => onChange(e.target.value)}
inputRef={input => this.input = input} />
}
onWheel = (e) => {

View file

@ -0,0 +1,29 @@
import React from 'react';
import PropTypes from 'prop-types';
import InputControl from './InputControl';
export default class TextControl extends React.Component {
render() {
let {onChange, initValue} = this.props;
return <InputControl type='text'
defaultValue={initValue}
onChange={e => onChange(e.target.value)} />
}
}
TextControl.propTypes = {
baseStep: PropTypes.number,
round: PropTypes.number,
min: PropTypes.number,
max: PropTypes.number,
accelerator: PropTypes.number,
initValue: PropTypes.number.isRequired,
onChange: PropTypes.func.isRequired
};
TextControl.defaultProps = {
baseStep: 1,
round: 0,
accelerator: 100
};

View file

@ -1,4 +1,5 @@
@import "../theme";
@import "../mixins";
body {
background-color: @bg-color;
@ -15,14 +16,16 @@ iframe {
}
:global(.disable-selection) {
user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
.no-selection();
}
:global(.compact-font) {
font-family: 'Helvetica Neue Light', HelveticaNeue-Light, 'Helvetica Neue', Helvetica, sans-serif;
}
button {
border: 0;
background-color: inherit;
color: inherit;
}

View file

@ -0,0 +1,21 @@
.no-selection() {
user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
}
.button-behavior(@color) {
&:hover {
background-color: @color;
}
&:active {
background-color: darken(@color, 20%);
}
}
.row() {
border-bottom: 1px solid @border-color;
}

View file

@ -9,12 +9,19 @@
@border-color: #2c2c2c;
@control-color-number: #2fa1d6;
@control-color-text: #9cdaf7;
@control-bg: #303030;
@work-area-color: #808080;
@work-area-control-bar-bg-color: rgba(0, 0, 0, 0.5);
@work-area-control-bar-bg-color-active: #555;
@work-area-control-bar-font-color: @font-color-minor;
@color-danger: #b00;
@color-accent: #2B7D2B;
@color-neutral: #66727d;
//@work-area-toolbar-bg-color: ;
//@work-area-toolbar-font-color: ;

View file

@ -14,7 +14,7 @@
.button {
cursor: pointer;
padding: 0.4em 0.5em;
padding: 0.5em 0.5em 0.35em 0.5em;
&:hover {
background-color: @work-area-control-bar-bg-color-active;

View file

@ -14,6 +14,17 @@ import MenuHolder from "../menu/MenuHolder";
import {TOKENS as MENU_TOKENS} from '../menu/menuPlugin';
import WindowSystem from 'ui/WindowSystem';
import Window from "ui/components/Window";
import Stack from "ui/components/Stack";
import Field from "ui/components/controls/Field";
import Label from "ui/components/controls/Label";
import NumberControl from "ui/components/controls/NumberControl";
import ButtonGroup from "ui/components/controls/ButtonGroup";
import Button from "ui/components/controls/Button";
import TextControl from './../../../../../modules/ui/components/controls/TextControl';
export default class View3d extends React.PureComponent {
render() {
@ -35,6 +46,25 @@ export default class View3d extends React.PureComponent {
<PlugableToolbarRight />
</Abs>
<PlugableControlBar />
<WindowSystem />
<Window initWidth={250} initLeft={500} title="Test">
<Stack >
<Field>
<Label>Width</Label>
<NumberControl initValue={5} onChange={val => console.log(val)}/>
</Field>
<Field>
<Label>Face</Label>
<TextControl initValue='face1' onChange={val => console.log(val)}/>
</Field>
<ButtonGroup>
<Button text='Cancel' />
<Button text='OK' type='accent' />
</ButtonGroup>
</Stack>
</Window>
</div>
</div>
}

View file

@ -7,15 +7,6 @@ import '../../../../css/app3d-legacy.less';
import View3d from './View3d';
import WindowSystem from 'ui/WindowSystem';
import Window from "ui/components/Window";
import Folder from "ui/components/Folder";
import Field from "ui/components/controls/Field";
import Label from "ui/components/controls/Label";
import NumberControl from "ui/components/controls/NumberControl";
import ButtonGroup from "ui/components/controls/ButtonGroup";
import Button from "ui/components/controls/Button";
import ls from './WebApplication.less';
import TabSwitcher, {Tab} from 'ui/components/TabSwticher';
import Card from 'ui/components/Card';
@ -54,23 +45,6 @@ export default class WebApplication extends React.Component {
onSwitch={this.switchTab} />)}
</TabSwitcher>
<a id='downloader' style={{display: 'none'}}/>
{/*<WindowSystem /> */}
{/*<Window initWith={250} >*/}
{/*<Folder title="Test">*/}
{/*<Field>*/}
{/*<Label>Width</Label>*/}
{/*<NumberControl initValue={5} onChange={val => console.log(val)}/>*/}
{/*</Field>*/}
{/*<Field>*/}
{/*<Label>Width</Label>*/}
{/*<NumberControl initValue={6} onChange={val => console.log(val)}/>*/}
{/*</Field>*/}
{/*<ButtonGroup>*/}
{/*<Button text='Cancel' />*/}
{/*<Button text='OK' />*/}
{/*</ButtonGroup>*/}
{/*</Folder>*/}
{/*</Window>*/}
</div>
}