Merge branch 'dev' of https://github.com/react-toolbox/react-toolbox into input-required

# Conflicts:
#	components/input/Input.jsx
#	components/input/style.scss
old
Keren Chandran 2016-03-17 20:54:29 -04:00
commit a022b2060a
16 changed files with 80 additions and 29 deletions

View File

@ -149,7 +149,9 @@
"no-undefined": [0],
"no-underscore-dangle": [0],
"no-unreachable": [2],
"no-unused-expressions": [2],
"no-unused-expressions": [2, {
"allowShortCircuit": true
}],
"no-unused-vars": [1, {
"vars": "all",
"args": "after-used"

View File

@ -40,13 +40,13 @@ class Calendar extends React.Component {
}
handleDayClick = (day) => {
this.props.onChange(time.setDay(this.state.viewDate, day));
this.props.onChange(time.setDay(this.state.viewDate, day), true);
};
handleYearClick = (year) => {
const viewDate = time.setYear(this.props.selectedDate, year);
this.setState({viewDate});
this.props.onChange(viewDate);
this.props.onChange(viewDate, false);
};
changeViewMonth = (direction, step) => {

View File

@ -7,6 +7,7 @@ import time from '../utils/time';
class DatePicker extends React.Component {
static propTypes = {
autoOk: React.PropTypes.boolean,
className: React.PropTypes.string,
error: React.PropTypes.string,
inputFormat: React.PropTypes.func,
@ -52,6 +53,7 @@ class DatePicker extends React.Component {
value={date}
/>
<DatePickerDialog
autoOk={this.props.autoOk}
active={this.state.active}
className={this.props.className}
maxDate={this.props.maxDate}

View File

@ -8,6 +8,7 @@ import time from '../utils/time';
class CalendarDialog extends React.Component {
static propTypes = {
active: React.PropTypes.bool,
autoOk: React.PropTypes.bool,
className: React.PropTypes.string,
maxDate: React.PropTypes.object,
minDate: React.PropTypes.object,
@ -27,12 +28,15 @@ class CalendarDialog extends React.Component {
display: 'months'
};
handleCalendarChange = (value) => {
handleCalendarChange = (value, dayClick) => {
const state = {display: 'months', date: value};
if (time.dateOutOfRange(value, this.props.minDate, this.props.maxDate)) {
state.date = this.props.maxDate || this.props.minDate;
}
this.setState(state);
if (dayClick && this.props.autoOk && this.props.onSelect) {
this.props.onSelect(value);
}
};
handleSelect = (event) => {

View File

@ -34,6 +34,7 @@ class DatePickerTest extends React.Component {
| Name | Type | Default | Description|
|:-----|:-----|:-----|:-----|
| `autoOk` | `boolean` | false | Automatically selects a date upon clicking on a day|
| `className` | `String` | | This class will be placed at the top of the `DatePickerDialog` component so you can provide custom styles.|
| `label` | `String` | | The text string to use for the floating label element in the input component.|
| `maxDate` | `Date` | | Date object with the maximum selectable date. |

View File

@ -42,8 +42,8 @@ Dialog.propTypes = {
className: React.PropTypes.string,
onOverlayClick: React.PropTypes.func,
onOverlayMouseDown: React.PropTypes.func,
onOverlayMouseUp: React.PropTypes.func,
onOverlayMouseMove: React.PropTypes.func,
onOverlayMouseUp: React.PropTypes.func,
title: React.PropTypes.string,
type: React.PropTypes.string
};

View File

@ -10,6 +10,7 @@ class Input extends React.Component {
disabled: React.PropTypes.bool,
error: React.PropTypes.node,
floating: React.PropTypes.bool,
hint: React.PropTypes.string,
icon: React.PropTypes.any,
label: React.PropTypes.string,
maxLength: React.PropTypes.number,
@ -25,6 +26,7 @@ class Input extends React.Component {
static defaultProps = {
className: '',
hint: '',
disabled: false,
floating: true,
multiline: false,
@ -45,7 +47,7 @@ class Input extends React.Component {
}
render () {
const { children, disabled, error, floating, icon,
const { children, disabled, error, floating, hint, icon,
label: labelText, maxLength, multiline, required,
type, value, ...others} = this.props;
const length = maxLength && value ? value.length : 0;
@ -82,6 +84,7 @@ class Input extends React.Component {
{labelText}
{required ? <span className={style.required}> * </span> : null}
</label> : null}
{hint ? <span className={style.hint}>{hint}</span> : null}
{error ? <span className={style.error}>{error}</span> : null}
{maxLength ? <span className={style.counter}>{length}/{maxLength}</span> : null}
{children}

View File

@ -17,3 +17,4 @@ $input-icon-font-size: 2.4 * $unit;
$input-icon-size: 2 * $input-icon-font-size;
$input-icon-offset: 1.6 * $unit;
$input-chevron-offset: .8 * $unit;
$input-hint-opacity: 1 !default;

View File

@ -20,6 +20,7 @@ class InputTest extends React.Component {
<Input type='text' label='Disabled field' disabled />
<Input type='email' label='Email address' icon='email' value={this.state.email} onChange={this.handleChange.bind(this, 'email')} />
<Input type='tel' label='Phone' name='phone' icon='phone' value={this.state.phone} onChange={this.handleChange.bind(this, 'phone')} />
<Input type='text' value={this.state.withHintCustomIcon} label='With Hint Text Icon' hint='Hint Text' onChange={this.handleChange.bind(this, 'withHintCustomIcon')} icon={<span>J</span>} />
</section>
);
}
@ -33,6 +34,7 @@ class InputTest extends React.Component {
| `className` | `String` |`''` | Sets a class name to give custom styles.|
| `disabled` | `Boolean` | `false` | If true, component will be disabled.|
| `error` | `String` | | Give an error string to display under the field.|
| `hint` | `String` |`''` | The text string to use for hint text element.|
| `icon` | `String` | | Name of an icon to use as a label for the input.|
| `floating` | `Boolean` | `true` | Indicates if the label is floating in the input field or not.|
| `label` | `String` | | The text string to use for the floating label element.|

View File

@ -43,6 +43,9 @@
~ .label > .required {
color: $input-text-required-color;
}
~ .hint {
opacity: $input-hint-opacity;
}
~ .icon {
color: $input-text-highlight-color;
}
@ -53,7 +56,7 @@
font-size: $input-label-font-size;
}
}
&.filled ~ .label.fixed {
&.filled ~ .label.fixed, &.filled ~ .hint {
display: none;
}
}
@ -69,6 +72,23 @@
transition-timing-function: $animation-curve-default;
transition-duration: $animation-duration;
transition-property: top, font-size, color;
&.fixed ~ .hint {
display: none
}
}
.hint {
position: absolute;
top: $input-padding + (1.5 * $input-field-padding);
left: 0;
font-size: $input-field-font-size;
line-height: $input-field-font-size;
color: $input-text-label-color;
pointer-events: none;
opacity: 0;
transition-timing-function: $animation-curve-default;
transition-duration: $animation-duration;
transition-property: opacity;
}
.bar {
@ -116,14 +136,6 @@
> .input {
margin-top: 1px;
border-bottom-color: $input-text-error-color;
&:focus {
~ .label:not(.fixed) {
color: $input-text-error-color;
}
~ .bar:before, ~ .bar:after {
background-color: $input-text-error-color;
}
}
}
> .counter, > .label {
color: $input-text-error-color;

View File

@ -5,6 +5,7 @@ import style from './style';
class TabHeader extends React.Component {
static propTypes = {
active: React.PropTypes.bool,
activeClassName: React.PropTypes.string,
className: React.PropTypes.string,
disabled: React.PropTypes.bool,
hidden: React.PropTypes.bool,
@ -36,7 +37,8 @@ class TabHeader extends React.Component {
const className = ClassNames(style.label, {
[style.active]: this.props.active,
[style.hidden]: this.props.hidden,
[style.disabled]: this.props.disabled
[style.disabled]: this.props.disabled,
[this.props.activeClassName]: this.props.active
}, this.props.className);
return (

View File

@ -7,6 +7,7 @@ class Tabs extends React.Component {
static propTypes = {
children: React.PropTypes.node,
className: React.PropTypes.string,
disableAnimatedBottomBorder: React.PropTypes.bool,
index: React.PropTypes.number,
onChange: React.PropTypes.func
};
@ -20,11 +21,17 @@ class Tabs extends React.Component {
};
componentDidMount () {
this.updatePointer(this.props.index);
!this.props.disableAnimatedBottomBorder &&
this.updatePointer(this.props.index);
}
componentWillReceiveProps (nextProps) {
this.updatePointer(nextProps.index);
!this.props.disableAnimatedBottomBorder &&
this.updatePointer(nextProps.index);
}
componentWillUnmount () {
clearTimeout(this.pointerTimeout);
}
handleHeaderClick = (idx) => {
@ -50,7 +57,8 @@ class Tabs extends React.Component {
}
updatePointer (idx) {
setTimeout(() => {
clearTimeout(this.pointerTimeout);
this.pointerTimeout = setTimeout(() => {
const startPoint = this.refs.tabs.getBoundingClientRect().left;
const label = this.refs.navigation.children[idx].getBoundingClientRect();
this.setState({

View File

@ -39,9 +39,10 @@ This component acts as the wrapper and the main controller of the content that i
| Name | Type | Default | Description|
|:-----|:-----|:-----|:-----|
| `className` | `String` | `''` | Additional class name to provide custom styling.|
| `index` | `Number` | `0` | Current <Tab> |
| `onChange` | `Function` | | Callback function that is fired when the tab changes.
| `className` | `String` | `''` | Additional class name to provide custom styling.|
| `index` | `Number` | `0` | Current <Tab> |
| `onChange` | `Function` | | Callback function that is fired when the tab changes.|
| `disableAnimatedBottomBorder` | `Boolean` | `false` | Disable the animation below the active tab
## Tab
@ -49,9 +50,10 @@ Represent a single tab element and it should include some properties to describe
| Name | Type | Default | Description|
|:-----|:-----|:-----|:-----|
| `active` | `Boolean` | `false` | If true, the current component is visible.|
| `className` | `String` | `''` | Additional class name to provide custom styling.|
| `disabled` | `Boolean` | `false` | If true, the current component is not clickable.|
| `hidden` | `Boolean` | `false` | If true, the current component is not visible.|
| `label` | `String` | | Label text for navigation header |
| `onActive` | `Function` | | Callback function that is fired when the tab is activated. |
| `active` | `Boolean` | `false` | If true, the current component is visible.|
| `activeClassName` | `String` | `''` | Additional class name to provide custom styling for the active tab.|
| `className` | `String` | `''` | Additional class name to provide custom styling for each tab.|
| `disabled` | `Boolean` | `false` | If true, the current component is not clickable.|
| `hidden` | `Boolean` | `false` | If true, the current component is not visible.|
| `label` | `String` | | Label text for navigation header |
| `onActive` | `Function` | | Callback function that is fired when the tab is activated. |

View File

@ -29,6 +29,7 @@ class DatePickerTest extends React.Component {
<DatePicker
label='Formatted Date'
autoOk
inputFormat={(value) => `${value.getDate()}/${value.getMonth()}/${value.getFullYear()}`}
onChange={this.handleChange.bind(this, 'date3')}
value={this.state.date3}

View File

@ -6,7 +6,9 @@ class InputTest extends React.Component {
normal: 'Tony Stark',
fixedLabel: '',
withIcon: '',
withCustomIcon: ''
withCustomIcon: '',
withHintCustomIcon: '',
multilineHint: 'Long Description here'
};
handleChange = (name, value) => {
@ -26,9 +28,11 @@ class InputTest extends React.Component {
/>
<Input type='email' value={this.state.fixedLabel} label='Label fixed' floating={false} onChange={this.handleChange.bind(this, 'fixedLabel')} />
<Input type='text' value='Read only' readOnly label='Phone Number' />
<Input type='email' value={this.state.multilineHint} label='Description' hint='Enter Description' multiline onChange={this.handleChange.bind(this, 'multilineHint')} />
<Input type='text' label='Disabled field' disabled />
<Input type='tel' value={this.state.withIcon} required label='With icon' onChange={this.handleChange.bind(this, 'withIcon')} icon='phone' />
<Input type='tel' value={this.state.withCustomIcon} label='With custom icon' onChange={this.handleChange.bind(this, 'withCustomIcon')} icon={<span>P</span>} />
<Input type='text' value={this.state.withHintCustomIcon} label='With Hint Text Icon' hint='Hint Text' onChange={this.handleChange.bind(this, 'withHintCustomIcon')} icon={<span>J</span>} />
</section>
);
}

View File

@ -48,6 +48,13 @@ class PickersTest extends React.Component {
value={this.state.date3}
/>
<DatePicker
label='Auto Picker'
autoOk
onChange={this.handleChange.bind(this, 'date4')}
value={this.state.date4}
/>
<TimePicker
label='Start time'
onChange={this.handleChange.bind(this, 'time1')}