Skip to content

Commit

Permalink
fix(Checkbox): onFocus and onBlur events (#1361)
Browse files Browse the repository at this point in the history
* fix(Checkbox): added onFocus prop

* fix(Checkbox): added handleFocus callback to be triggered

* fix(Checkbox): added onMouseDown event to invoke focus event

* fix: call user onMouseDown prop when onMouseDown event is trigger

* style: added onMouseDown to component propTypes

* Update Checkbox.js

* test: potential fix for checkbox test

* fix(Checkbox): onFocus and onBlur events
  • Loading branch information
tarang9211 authored and levithomason committed Mar 24, 2017
1 parent a325294 commit f048cb5
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 10 deletions.
12 changes: 10 additions & 2 deletions src/modules/Checkbox/Checkbox.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,23 @@ export interface CheckboxProps {
* @param {SyntheticEvent} event - React's original SyntheticEvent.
* @param {object} data - All props and proposed checked/indeterminate state.
*/
onChange?: (event: React.FormEvent<HTMLInputElement>, data: this) => void;
onChange?: (event: React.FormEvent<HTMLInputElement>, data: CheckboxProps) => void;

/**
* Called when the checkbox or label is clicked.
*
* @param {SyntheticEvent} event - React's original SyntheticEvent.
* @param {object} data - All props and current checked/indeterminate state.
*/
onClick?: (event: React.MouseEvent<HTMLInputElement>, data: this) => void;
onClick?: (event: React.MouseEvent<HTMLInputElement>, data: CheckboxProps) => void;

/**
* Called when the user presses down on the mouse.
*
* @param {SyntheticEvent} event - React's original SyntheticEvent.
* @param {object} data - All props and current checked/indeterminate state.
*/
onMouseDown?: (event: React.MouseEvent<HTMLInputElement>, data: CheckboxProps) => void;

/** Format as a radio element. This means it is an exclusive option. */
radio?: boolean;
Expand Down
44 changes: 36 additions & 8 deletions src/modules/Checkbox/Checkbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ export default class Checkbox extends Component {
*/
onClick: PropTypes.func,

/**
* Called when the user presses down on the mouse.
*
* @param {SyntheticEvent} event - React's original SyntheticEvent.
* @param {object} data - All props and current checked/indeterminate state.
*/
onMouseDown: PropTypes.func,

/** Format as a radio element. This means it is an exclusive option. */
radio: customPropTypes.every([
PropTypes.bool,
Expand Down Expand Up @@ -132,10 +140,18 @@ export default class Checkbox extends Component {
return !disabled && !readOnly && !(radio && checked)
}

computeTabIndex = () => {
const { disabled, tabIndex } = this.props

if (!_.isNil(tabIndex)) return tabIndex
return disabled ? -1 : 0
}

handleInputRef = c => (this.inputRef = c)

handleClick = (e) => {
handleClick = e => {
debug('handleClick()')

const { onChange, onClick } = this.props
const { checked, indeterminate } = this.state

Expand All @@ -147,11 +163,22 @@ export default class Checkbox extends Component {
}
}

handleMouseDown = e => {
debug('handleMouseDown()')

const { onMouseDown } = this.props
const { checked, indeterminate } = this.state

_.invoke('focus', this.inputRef)
if (onMouseDown) onMouseDown(e, { ...this.props, checked: !!checked, indeterminate: !!indeterminate })
}

// Note: You can't directly set the indeterminate prop on the input, so we
// need to maintain a ref to the input and set it manually whenever the
// component updates.
setIndeterminate = () => {
const { indeterminate } = this.state

if (this.inputRef) this.inputRef.indeterminate = !!indeterminate
}

Expand All @@ -164,7 +191,6 @@ export default class Checkbox extends Component {
radio,
readOnly,
slider,
tabIndex,
toggle,
type,
value,
Expand All @@ -189,19 +215,21 @@ export default class Checkbox extends Component {
const rest = getUnhandledProps(Checkbox, this.props)
const ElementType = getElementType(Checkbox, this.props)

let computedTabIndex
if (!_.isNil(tabIndex)) computedTabIndex = tabIndex
else computedTabIndex = disabled ? -1 : 0

return (
<ElementType {...rest} className={classes} onClick={this.handleClick} onChange={this.handleClick}>
<ElementType
{...rest}
className={classes}
onChange={this.handleClick}
onClick={this.handleClick}
onMouseDown={this.handleMouseDown}
>
<input
checked={checked}
className='hidden'
name={name}
readOnly
ref={this.handleInputRef}
tabIndex={computedTabIndex}
tabIndex={this.computeTabIndex()}
type={type}
value={value}
/>
Expand Down
16 changes: 16 additions & 0 deletions test/specs/modules/Checkbox/Checkbox-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,22 @@ describe('Checkbox', () => {
})
})

describe('onMouseDown', () => {
it('sets focus to container', () => {
const mountNode = document.createElement('div')
document.body.appendChild(mountNode)

const wrapper = mount(<Checkbox />, { attachTo: mountNode })
const input = document.querySelector('.ui.checkbox input')

wrapper.simulate('mousedown')
document.activeElement.should.equal(input)

wrapper.detach()
document.body.removeChild(mountNode)
})
})

describe('readOnly', () => {
it('cannot be checked', () => {
shallow(<Checkbox readOnly />)
Expand Down

0 comments on commit f048cb5

Please sign in to comment.