Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(mixed): handle properly refs on third-party components #3471

Merged
merged 1 commit into from
Mar 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions src/addons/TextArea/TextArea.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import _ from 'lodash'
import PropTypes from 'prop-types'
import React, { Component, createRef } from 'react'

import Ref from '../../addons/Ref'
import { customPropTypes, getElementType, getUnhandledProps } from '../../lib'

/**
Expand Down Expand Up @@ -61,14 +62,15 @@ class TextArea extends Component {
const ElementType = getElementType(TextArea, this.props)

return (
<ElementType
{...rest}
onChange={this.handleChange}
onInput={this.handleInput}
ref={this.ref}
rows={rows}
value={value}
/>
<Ref innerRef={this.ref}>
<ElementType
{...rest}
onChange={this.handleChange}
onInput={this.handleInput}
rows={rows}
value={value}
/>
</Ref>
)
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/behaviors/Visibility/Visibility.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import _ from 'lodash'
import PropTypes from 'prop-types'
import React, { Component, createRef } from 'react'

import Ref from '../../addons/Ref'
import {
eventStack,
customPropTypes,
Expand Down Expand Up @@ -406,9 +407,9 @@ export default class Visibility extends Component {
const rest = getUnhandledProps(Visibility, this.props)

return (
<ElementType {...rest} ref={this.ref}>
{children}
</ElementType>
<Ref innerRef={this.ref}>
<ElementType {...rest}>{children}</ElementType>
</Ref>
)
}
}
49 changes: 26 additions & 23 deletions src/elements/Button/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import _ from 'lodash'
import PropTypes from 'prop-types'
import React, { Component, createRef } from 'react'

import Ref from '../../addons/Ref'
import {
childrenUtils,
customPropTypes,
Expand Down Expand Up @@ -266,15 +267,16 @@ class Button extends Component {
return (
<ElementType {...rest} className={containerClasses} onClick={this.handleClick}>
{labelPosition === 'left' && labelElement}
<button
className={buttonClasses}
aria-pressed={toggle ? !!active : undefined}
disabled={disabled}
ref={this.ref}
tabIndex={tabIndex}
>
{Icon.create(icon, { autoGenerateKey: false })} {content}
</button>
<Ref innerRef={this.ref}>
<button
className={buttonClasses}
aria-pressed={toggle ? !!active : undefined}
disabled={disabled}
tabIndex={tabIndex}
>
{Icon.create(icon, { autoGenerateKey: false })} {content}
</button>
</Ref>
{(labelPosition === 'right' || !labelPosition) && labelElement}
</ElementType>
)
Expand All @@ -285,20 +287,21 @@ class Button extends Component {
const role = this.computeButtonAriaRole(ElementType)

return (
<ElementType
{...rest}
className={classes}
aria-pressed={toggle ? !!active : undefined}
disabled={(disabled && ElementType === 'button') || undefined}
onClick={this.handleClick}
ref={this.ref}
role={role}
tabIndex={tabIndex}
>
{hasChildren && children}
{!hasChildren && Icon.create(icon, { autoGenerateKey: false })}
{!hasChildren && content}
</ElementType>
<Ref innerRef={this.ref}>
<ElementType
{...rest}
className={classes}
aria-pressed={toggle ? !!active : undefined}
disabled={(disabled && ElementType === 'button') || undefined}
onClick={this.handleClick}
role={role}
tabIndex={tabIndex}
>
{hasChildren && children}
{!hasChildren && Icon.create(icon, { autoGenerateKey: false })}
{!hasChildren && content}
</ElementType>
</Ref>
)
}
}
Expand Down
44 changes: 23 additions & 21 deletions src/modules/Checkbox/Checkbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import _ from 'lodash'
import PropTypes from 'prop-types'
import React, { createRef } from 'react'

import Ref from '../../addons/Ref'
import {
AutoControlledComponent as Component,
createHTMLLabel,
Expand Down Expand Up @@ -261,6 +262,13 @@ export default class Checkbox extends Component {
const ElementType = getElementType(Checkbox, this.props)
const [htmlInputProps, rest] = partitionHTMLProps(unhandled, { htmlProps: htmlInputAttrs })

// Heads Up!
// Do not remove empty labels, they are required by SUI CSS
const labelElement = createHTMLLabel(label, {
defaultProps: { htmlFor: id },
autoGenerateKey: false,
}) || <label htmlFor={id} />

return (
<ElementType
{...rest}
Expand All @@ -270,27 +278,21 @@ export default class Checkbox extends Component {
onMouseDown={this.handleMouseDown}
onMouseUp={this.handleMouseUp}
>
<input
{...htmlInputProps}
checked={checked}
className='hidden'
disabled={disabled}
id={id}
name={name}
readOnly
ref={this.inputRef}
tabIndex={this.computeTabIndex()}
type={type}
value={value}
/>
{/*
Heads Up!
Do not remove empty labels, they are required by SUI CSS
*/}
{createHTMLLabel(label, {
defaultProps: { htmlFor: id, ref: this.labelRef },
autoGenerateKey: false,
}) || <label htmlFor={id} ref={this.labelRef} />}
<Ref innerRef={this.inputRef}>
<input
{...htmlInputProps}
checked={checked}
className='hidden'
disabled={disabled}
id={id}
name={name}
readOnly
tabIndex={this.computeTabIndex()}
type={type}
value={value}
/>
</Ref>
<Ref innerRef={this.labelRef}>{labelElement}</Ref>
</ElementType>
)
}
Expand Down
17 changes: 10 additions & 7 deletions src/modules/Dimmer/DimmerInner.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import _ from 'lodash'
import PropTypes from 'prop-types'
import React, { Component, createRef } from 'react'

import Ref from '../../addons/Ref'
import {
childrenUtils,
customPropTypes,
Expand Down Expand Up @@ -135,13 +136,15 @@ export default class DimmerInner extends Component {
const childrenContent = childrenUtils.isNil(children) ? content : children

return (
<ElementType {...rest} className={classes} onClick={this.handleClick} ref={this.containerRef}>
{childrenContent && (
<div className='content' ref={this.contentRef}>
{childrenContent}
</div>
)}
</ElementType>
<Ref innerRef={this.containerRef}>
<ElementType {...rest} className={classes} onClick={this.handleClick}>
{childrenContent && (
<div className='content' ref={this.contentRef}>
{childrenContent}
</div>
)}
</ElementType>
</Ref>
)
}
}
63 changes: 32 additions & 31 deletions src/modules/Dropdown/Dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -1353,37 +1353,38 @@ export default class Dropdown extends Component {
const ariaOptions = this.getDropdownAriaOptions(ElementType, this.props)

return (
<ElementType
{...rest}
{...ariaOptions}
className={classes}
onBlur={this.handleBlur}
onClick={this.handleClick}
onMouseDown={this.handleMouseDown}
onFocus={this.handleFocus}
onChange={this.handleChange}
tabIndex={this.computeTabIndex()}
ref={this.ref}
>
{this.renderLabels()}
{this.renderSearchInput()}
{this.renderSearchSizer()}
{trigger || this.renderText()}
{Icon.create(icon, {
overrideProps: this.handleIconOverrides,
autoGenerateKey: false,
})}
{this.renderMenu()}

{open && <EventStack name='keydown' on={this.closeOnEscape} />}
{open && <EventStack name='keydown' on={this.moveSelectionOnKeyDown} />}
{open && <EventStack name='click' on={this.closeOnDocumentClick} />}
{open && <EventStack name='keydown' on={this.selectItemOnEnter} />}

{focus && <EventStack name='keydown' on={this.removeItemOnBackspace} />}
{focus && !open && <EventStack name='keydown' on={this.openOnArrow} />}
{focus && !open && <EventStack name='keydown' on={this.openOnSpace} />}
</ElementType>
<Ref innerRef={this.ref}>
<ElementType
{...rest}
{...ariaOptions}
className={classes}
onBlur={this.handleBlur}
onClick={this.handleClick}
onMouseDown={this.handleMouseDown}
onFocus={this.handleFocus}
onChange={this.handleChange}
tabIndex={this.computeTabIndex()}
>
{this.renderLabels()}
{this.renderSearchInput()}
{this.renderSearchSizer()}
{trigger || this.renderText()}
{Icon.create(icon, {
overrideProps: this.handleIconOverrides,
autoGenerateKey: false,
})}
{this.renderMenu()}

{open && <EventStack name='keydown' on={this.closeOnEscape} />}
{open && <EventStack name='keydown' on={this.moveSelectionOnKeyDown} />}
{open && <EventStack name='click' on={this.closeOnDocumentClick} />}
{open && <EventStack name='keydown' on={this.selectItemOnEnter} />}

{focus && <EventStack name='keydown' on={this.removeItemOnBackspace} />}
{focus && !open && <EventStack name='keydown' on={this.openOnArrow} />}
{focus && !open && <EventStack name='keydown' on={this.openOnSpace} />}
</ElementType>
</Ref>
)
}
}
14 changes: 9 additions & 5 deletions src/modules/Popup/Popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
isRefObject,
} from '../../lib'
import Portal from '../../addons/Portal'
import Ref from '../../addons/Ref'
import PopupContent from './PopupContent'
import PopupHeader from './PopupHeader'

Expand Down Expand Up @@ -427,11 +428,14 @@ export default class Popup extends Component {
const ElementType = getElementType(Popup, this.props)

const popupJSX = (
<ElementType {...rest} className={classes} style={style} ref={this.handlePopupRef}>
{children}
{childrenUtils.isNil(children) && PopupHeader.create(header, { autoGenerateKey: false })}
{childrenUtils.isNil(children) && PopupContent.create(content, { autoGenerateKey: false })}
</ElementType>
<Ref innerRef={this.handlePopupRef}>
<ElementType {...rest} className={classes} style={style}>
{children}
{childrenUtils.isNil(children) && PopupHeader.create(header, { autoGenerateKey: false })}
{childrenUtils.isNil(children) &&
PopupContent.create(content, { autoGenerateKey: false })}
</ElementType>
</Ref>
)

const mergedPortalProps = { ...this.getPortalProps(), ...portalProps }
Expand Down
4 changes: 3 additions & 1 deletion test/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import Adapter from 'enzyme-adapter-react-16'
import dirtyChai from 'dirty-chai'
import sinonChai from 'sinon-chai'

import nestedShallow from './utils/nestedShallow'

// ----------------------------------------
// Enzyme
// ----------------------------------------
global.enzyme = enzyme
global.shallow = enzyme.shallow
global.shallow = nestedShallow
global.render = enzyme.render
global.mount = enzyme.mount

Expand Down
2 changes: 2 additions & 0 deletions test/specs/addons/Confirm/Confirm-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ describe('Confirm', () => {
.find('Button')
.first()
.shallow()
.childAt(0)
.should.have.text('foo')
})
})
Expand All @@ -82,6 +83,7 @@ describe('Confirm', () => {
shallow(<Confirm confirmButton='foo' />)
.find('Button[primary]')
.shallow()
.childAt(0)
.should.have.text('foo')
})
})
Expand Down
4 changes: 2 additions & 2 deletions test/specs/addons/TextArea/TextArea-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,11 @@ describe('TextArea', () => {

describe('rows', () => {
it('has default value', () => {
shallow(<TextArea />).should.have.prop('rows', 3)
shallow(<TextArea />, { autoNesting: true }).should.have.prop('rows', 3)
})

it('sets prop', () => {
shallow(<TextArea rows={1} />).should.have.prop('rows', 1)
shallow(<TextArea rows={1} />, { autoNesting: true }).should.have.prop('rows', 1)
})
})
})
Loading