@cmsgov/design-system-core
Advanced tools
Comparing version 3.1.1 to 3.2.0
@@ -142,3 +142,4 @@ 'use strict'; | ||
uncheckedChildren = _props.uncheckedChildren, | ||
inputProps = _objectWithoutProperties(_props, ['checkedChildren', 'children', 'className', 'hint', 'inversed', 'inputPlacement', 'inputClassName', 'requirementLabel', 'size', 'uncheckedChildren']); | ||
inputRef = _props.inputRef, | ||
inputProps = _objectWithoutProperties(_props, ['checkedChildren', 'children', 'className', 'hint', 'inversed', 'inputPlacement', 'inputClassName', 'requirementLabel', 'size', 'uncheckedChildren', 'inputRef']); | ||
@@ -169,2 +170,5 @@ var inputClasses = (0, _classnames2.default)(inputClassName, 'ds-c-choice', { | ||
_this2.input = input; | ||
if (inputRef) { | ||
inputRef(input); | ||
} | ||
} | ||
@@ -228,2 +232,6 @@ }, inputProps)), | ||
/** | ||
* Access a reference to the `input` element | ||
*/ | ||
inputRef: _propTypes2.default.func, | ||
/** | ||
* Additional hint text to display below the choice's label | ||
@@ -230,0 +238,0 @@ */ |
@@ -51,3 +51,3 @@ 'use strict'; | ||
/** | ||
* A `ChoiceList` component can be used to render a select menu, radio | ||
* A `ChoiceList` component can be used to render a radio | ||
* button group, or checkbox group. | ||
@@ -63,15 +63,20 @@ * | ||
function ChoiceList() { | ||
function ChoiceList(props) { | ||
_classCallCheck(this, ChoiceList); | ||
return _possibleConstructorReturn(this, (ChoiceList.__proto__ || Object.getPrototypeOf(ChoiceList)).apply(this, arguments)); | ||
var _this = _possibleConstructorReturn(this, (ChoiceList.__proto__ || Object.getPrototypeOf(ChoiceList)).call(this, props)); | ||
_this.handleBlur = _this.handleBlur.bind(_this); | ||
_this.choiceRefs = []; | ||
return _this; | ||
} | ||
/** | ||
* Creates the field component(s) based on the type of field we've determined | ||
* it should be. | ||
*/ | ||
_createClass(ChoiceList, [{ | ||
key: 'field', | ||
/** | ||
* Creates the field component(s) based on the type of field we've determined | ||
* it should be. | ||
*/ | ||
value: function field() { | ||
@@ -103,5 +108,8 @@ var _this2 = this; | ||
props.name = _this2.props.name; | ||
props.onBlur = _this2.props.onBlur; | ||
props.onBlur = (_this2.props.onBlur || _this2.props.onComponentBlur) && _this2.handleBlur; | ||
props.onChange = _this2.props.onChange; | ||
props.type = type; | ||
props.inputRef = function (ref) { | ||
_this2.choiceRefs.push(ref); | ||
}; | ||
} | ||
@@ -193,2 +201,27 @@ | ||
}, { | ||
key: 'handleBlur', | ||
value: function handleBlur(evt) { | ||
if (this.props.onBlur) { | ||
this.props.onBlur(evt); | ||
} | ||
if (this.props.onComponentBlur) { | ||
this.handleComponentBlur(evt); | ||
} | ||
} | ||
}, { | ||
key: 'handleComponentBlur', | ||
value: function handleComponentBlur(evt) { | ||
var _this3 = this; | ||
// The active element is always the document body during a focus | ||
// transition, so in order to check if the newly focused element | ||
// is one of our choices, we're going to have to wait a bit. | ||
setTimeout(function () { | ||
if (!_this3.choiceRefs.includes(document.activeElement)) { | ||
_this3.props.onComponentBlur(evt); | ||
} | ||
}, 20); | ||
} | ||
}, { | ||
key: 'render', | ||
@@ -277,3 +310,12 @@ value: function render() { | ||
name: _propTypes2.default.string.isRequired, | ||
/** | ||
* Called anytime any choice is blurred | ||
*/ | ||
onBlur: _propTypes2.default.func, | ||
/** | ||
* Called when any choice is blurred and the focus does not land on one | ||
* of the other choices inside this component (i.e., when the whole | ||
* component loses focus) | ||
*/ | ||
onComponentBlur: _propTypes2.default.func, | ||
onChange: _propTypes2.default.func, | ||
@@ -280,0 +322,0 @@ /** |
@@ -118,4 +118,4 @@ 'use strict'; | ||
), | ||
this.errorMessage(), | ||
this.hint() | ||
this.hint(), | ||
this.errorMessage() | ||
); | ||
@@ -122,0 +122,0 @@ } |
@@ -29,12 +29,4 @@ 'use strict'; | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /* | ||
Masked field | ||
A masked field is an enhanced input field that provides visual and non-visual | ||
cues to a user about the expected value. | ||
Style guide: components.masked-field | ||
*/ | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } | ||
// Deliminate chunks of integers | ||
@@ -172,16 +164,2 @@ var deliminatedMaskRegex = { | ||
/* | ||
`<TextField mask={...}>` | ||
Passing a `mask` prop into the `TextField` component with a valid value will | ||
enable formatting to occur when the field is blurred. To "unmask" the | ||
value, you can import and call the `unmaskValue` method. | ||
@react-component TextField | ||
@react-example Mask | ||
Style guide: components.masked-field.react | ||
*/ | ||
/** | ||
@@ -188,0 +166,0 @@ * A Mask component renders a controlled input field. When the |
{ | ||
"name": "@cmsgov/design-system-core", | ||
"version": "3.1.1", | ||
"version": "3.2.0", | ||
"publishConfig": { | ||
@@ -12,3 +12,3 @@ "access": "public" | ||
"dependencies": { | ||
"@cmsgov/design-system-support": "^3.1.1", | ||
"@cmsgov/design-system-support": "^3.2.0", | ||
"classnames": "^2.2.5", | ||
@@ -15,0 +15,0 @@ "core-js": "^2.5.3", |
@@ -12,3 +12,3 @@ /* global driver */ | ||
const successURL = `${ROOT_URL}/example/components.button..ds-c-button--success/`; | ||
const disabledURL = `${ROOT_URL}/example/components.button.disabled/`; | ||
const disabledURL = `${ROOT_URL}/example/components.button..ds-c-button--disabled/`; | ||
@@ -15,0 +15,0 @@ describe('Button component', () => { |
@@ -93,2 +93,3 @@ import EvEmitter from 'ev-emitter'; | ||
uncheckedChildren, | ||
inputRef, | ||
...inputProps | ||
@@ -120,2 +121,5 @@ } = this.props; | ||
this.input = input; | ||
if (inputRef) { | ||
inputRef(input); | ||
} | ||
}} | ||
@@ -176,2 +180,6 @@ {...inputProps} | ||
/** | ||
* Access a reference to the `input` element | ||
*/ | ||
inputRef: PropTypes.func, | ||
/** | ||
* Additional hint text to display below the choice's label | ||
@@ -178,0 +186,0 @@ */ |
@@ -10,3 +10,3 @@ import Choice from './Choice'; | ||
/** | ||
* A `ChoiceList` component can be used to render a select menu, radio | ||
* A `ChoiceList` component can be used to render a radio | ||
* button group, or checkbox group. | ||
@@ -20,2 +20,8 @@ * | ||
export class ChoiceList extends React.PureComponent { | ||
constructor(props) { | ||
super(props); | ||
this.handleBlur = this.handleBlur.bind(this); | ||
this.choiceRefs = []; | ||
} | ||
/** | ||
@@ -46,5 +52,9 @@ * Creates the field component(s) based on the type of field we've determined | ||
props.name = this.props.name; | ||
props.onBlur = this.props.onBlur; | ||
props.onBlur = | ||
(this.props.onBlur || this.props.onComponentBlur) && this.handleBlur; | ||
props.onChange = this.props.onChange; | ||
props.type = type; | ||
props.inputRef = ref => { | ||
this.choiceRefs.push(ref); | ||
}; | ||
} | ||
@@ -128,2 +138,23 @@ | ||
handleBlur(evt) { | ||
if (this.props.onBlur) { | ||
this.props.onBlur(evt); | ||
} | ||
if (this.props.onComponentBlur) { | ||
this.handleComponentBlur(evt); | ||
} | ||
} | ||
handleComponentBlur(evt) { | ||
// The active element is always the document body during a focus | ||
// transition, so in order to check if the newly focused element | ||
// is one of our choices, we're going to have to wait a bit. | ||
setTimeout(() => { | ||
if (!this.choiceRefs.includes(document.activeElement)) { | ||
this.props.onComponentBlur(evt); | ||
} | ||
}, 20); | ||
} | ||
render() { | ||
@@ -211,3 +242,12 @@ const type = this.type(); | ||
name: PropTypes.string.isRequired, | ||
/** | ||
* Called anytime any choice is blurred | ||
*/ | ||
onBlur: PropTypes.func, | ||
/** | ||
* Called when any choice is blurred and the focus does not land on one | ||
* of the other choices inside this component (i.e., when the whole | ||
* component loses focus) | ||
*/ | ||
onComponentBlur: PropTypes.func, | ||
onChange: PropTypes.func, | ||
@@ -214,0 +254,0 @@ /** |
@@ -169,3 +169,3 @@ import ChoiceList from './ChoiceList'; | ||
expect(onChange.mock.calls.length).toBe(1); | ||
expect(onChange).toHaveBeenCalled(); | ||
}); | ||
@@ -175,3 +175,4 @@ | ||
const onBlur = jest.fn(); | ||
const data = shallowRender({ onBlur }); | ||
const onComponentBlur = jest.fn(); | ||
const data = shallowRender({ onBlur, onComponentBlur }); | ||
data.wrapper | ||
@@ -182,4 +183,23 @@ .find('Choice') | ||
expect(onBlur.mock.calls.length).toBe(1); | ||
expect(onBlur).toHaveBeenCalled(); | ||
// Enzyme simulated `blur` event will automatically focus on the next choice element | ||
setTimeout(() => { | ||
expect(onComponentBlur).not.toHaveBeenCalled(); | ||
}, 20); | ||
}); | ||
it('calls onComponentBlur', () => { | ||
const onBlur = jest.fn(); | ||
const onComponentBlur = jest.fn(); | ||
const data = shallowRender({ onBlur, onComponentBlur }); | ||
data.wrapper | ||
.find('Choice') | ||
.last() | ||
.simulate('blur'); | ||
expect(onBlur).toHaveBeenCalled(); | ||
setTimeout(() => { | ||
expect(onComponentBlur).toHaveBeenCalled(); | ||
}, 20); | ||
}); | ||
}); | ||
@@ -292,3 +312,3 @@ | ||
expect(onChange.mock.calls.length).toBe(1); | ||
expect(onChange).toHaveBeenCalled(); | ||
}); | ||
@@ -305,3 +325,3 @@ | ||
expect(onBlur.mock.calls.length).toBe(1); | ||
expect(onBlur).toHaveBeenCalled(); | ||
}); | ||
@@ -308,0 +328,0 @@ }); |
@@ -71,4 +71,4 @@ import PropTypes from 'prop-types'; | ||
<span className={labelTextClasses}>{children}</span> | ||
{this.hint()} | ||
{this.errorMessage()} | ||
{this.hint()} | ||
</ComponentType> | ||
@@ -75,0 +75,0 @@ ); |
@@ -1,9 +0,1 @@ | ||
/* | ||
Masked field | ||
A masked field is an enhanced input field that provides visual and non-visual | ||
cues to a user about the expected value. | ||
Style guide: components.masked-field | ||
*/ | ||
import 'core-js/fn/array/includes'; | ||
@@ -142,16 +134,2 @@ import PropTypes from 'prop-types'; | ||
/* | ||
`<TextField mask={...}>` | ||
Passing a `mask` prop into the `TextField` component with a valid value will | ||
enable formatting to occur when the field is blurred. To "unmask" the | ||
value, you can import and call the `unmaskValue` method. | ||
@react-component TextField | ||
@react-example Mask | ||
Style guide: components.masked-field.react | ||
*/ | ||
/** | ||
@@ -158,0 +136,0 @@ * A Mask component renders a controlled input field. When the |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1758953
357
13951