@salesforce/design-system-react
Version:
Salesforce Lightning Design System for React
333 lines (286 loc) • 12.3 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /* Copyright (c) 2015-present, salesforce.com, inc. All rights reserved */
/* Licensed under BSD 3-Clause - see LICENSE.txt or git.io/sfdc-license */
// # Input Component
// Implements the [Input design pattern](https://lightningdesignsystem.com/components/forms/#flavor-input) in React. Does not yet implement [fixed text](https://lightningdesignsystem.com/components/forms/#flavor-input-input-fixed-text).
// Based on SLDS v2.2.1
//
// ### React
// ### classNames
// [github.com/JedWatson/classnames](https://github.com/JedWatson/classnames)
// This project uses `classnames`, "a simple javascript utility for conditionally
// joining classNames together."
// ### shortid
// [npmjs.com/package/shortid](https://www.npmjs.com/package/shortid)
// shortid is a short, non-sequential, url-friendly, unique id generator
// ## Children
// This component's `checkProps` which issues warnings to developers about properties when in development mode (similar to React's built in development tools)
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _createReactClass = require('create-react-class');
var _createReactClass2 = _interopRequireDefault(_createReactClass);
var _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _airbnbPropTypes = require('airbnb-prop-types');
var _classnames = require('classnames');
var _classnames2 = _interopRequireDefault(_classnames);
var _shortid = require('shortid');
var _shortid2 = _interopRequireDefault(_shortid);
var _inputIcon = require('../../icon/input-icon');
var _inputIcon2 = _interopRequireDefault(_inputIcon);
var _innerInput = require('./private/inner-input');
var _innerInput2 = _interopRequireDefault(_innerInput);
var _label = require('../private/label');
var _label2 = _interopRequireDefault(_label);
var _checkProps = require('./check-props');
var _checkProps2 = _interopRequireDefault(_checkProps);
var _constants = require('../../../utilities/constants');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// ## InputDefinition
var Input = (0, _createReactClass2.default)({
// ### Display Name
// Always use the canonical component name as the React display name.
displayName: _constants.FORMS_INPUT,
// ### Prop Types
propTypes: {
'aria-activedescendant': _propTypes2.default.string,
'aria-autocomplete': _propTypes2.default.string,
/**
* An HTML ID that is shared with ARIA-supported devices with the
* `aria-controls` attribute in order to relate the input with
* another region of the page. An example would be a select box
* that shows or hides a panel.
*/
'aria-controls': _propTypes2.default.string,
'aria-describedby': _propTypes2.default.string,
'aria-expanded': _propTypes2.default.bool,
'aria-haspopup': _propTypes2.default.bool,
'aria-labelledby': _propTypes2.default.string,
/**
* An HTML ID that is shared with ARIA-supported devices with the
* `aria-controls` attribute in order to relate the input with
* another region of the page. An example would be a search field
* that shows search results.
*/
'aria-owns': _propTypes2.default.string,
'aria-required': _propTypes2.default.bool,
/**
* **Assistive text for accessibility**
* * `label`: Visually hidden label but read out loud by screen readers.
* * `spinner`: Text for loading spinner icon.
*/
assistiveText: (0, _airbnbPropTypes.shape)({
label: _propTypes2.default.string,
spinner: _propTypes2.default.string
}),
children: _propTypes2.default.node,
/**
* Class names to be added to the outer container of the input.
*/
className: _propTypes2.default.oneOfType([_propTypes2.default.array, _propTypes2.default.object, _propTypes2.default.string]),
/**
* Disables the input and prevents editing the contents.
*/
disabled: _propTypes2.default.bool,
/**
* Message to display when the input is in an error state. When this is present, also visually highlights the component as in error.
*/
errorText: _propTypes2.default.string,
/**
* Displays text or node to the left of the input. This follows the fixed text input UX pattern.
*/
fixedTextLeft: _propTypes2.default.oneOfType([_propTypes2.default.node, _propTypes2.default.string]),
/**
* Displays text or node to the right of the input. This follows the fixed text input UX pattern.
*/
fixedTextRight: _propTypes2.default.oneOfType([_propTypes2.default.node, _propTypes2.default.string]),
/**
* If true, loading spinner appears inside input on right hand side.
*/
hasSpinner: _propTypes2.default.bool,
/**
* Left aligned icon, must be instace of `design-system-react/components/icon/input-icon`
*/
iconLeft: _propTypes2.default.node,
/**
* Right aligned icon, must be instace of `design-system-react/components/icon/input-icon`
*/
iconRight: _propTypes2.default.node,
/**
* Every input must have a unique ID in order to support keyboard navigation and ARIA support.
*/
id: _propTypes2.default.string,
/**
* This callback exposes the input reference / DOM node to parent components. `<Parent inputRef={(inputComponent) => this.input = inputComponent} />
*/
inputRef: _propTypes2.default.func,
/**
* Displays the value of the input statically. This follows the static input UX pattern.
*/
isStatic: _propTypes2.default.bool,
/**
* This label appears above the input.
*/
label: _propTypes2.default.string,
onBlur: _propTypes2.default.func,
/**
* This callback fires when the input changes. The synthetic React event will be the first parameter to the callback. You will probably want to reference `event.target.value` in your callback. No custom data object is provided.
*/
onChange: _propTypes2.default.func,
/**
* This event fires when the input is clicked.
*/
onClick: _propTypes2.default.func,
onFocus: _propTypes2.default.func,
onInput: _propTypes2.default.func,
onInvalid: _propTypes2.default.func,
onKeyDown: _propTypes2.default.func,
onKeyPress: _propTypes2.default.func,
onKeyUp: _propTypes2.default.func,
onSelect: _propTypes2.default.func,
onSubmit: _propTypes2.default.func,
/**
* Text that will appear in an empty input.
*/
placeholder: _propTypes2.default.string,
minLength: _propTypes2.default.string,
maxLength: _propTypes2.default.string,
/**
* Name of the submitted form parameter.
*/
name: _propTypes2.default.string,
/**
* Displays the value of the input as readOnly.
*/
readOnly: _propTypes2.default.bool,
/**
* Highlights the input as a required field (does not perform any validation).
*/
required: _propTypes2.default.bool,
/**
* The `<Input>` element includes support for all HTML5 types.
*/
type: _propTypes2.default.oneOf(['text', 'password', 'datetime', 'datetime-local', 'date', 'month', 'time', 'week', 'number', 'email', 'url', 'search', 'tel', 'color']),
/**
* The input is a controlled component, and will always display this value.
*/
value: _propTypes2.default.string,
iconPosition: _propTypes2.default.string,
inlineEditTrigger: _propTypes2.default.node,
role: _propTypes2.default.string
},
getDefaultProps: function getDefaultProps() {
return {
type: 'text'
};
},
componentWillMount: function componentWillMount() {
// `checkProps` issues warnings to developers about properties (similar to React's built in development tools)
(0, _checkProps2.default)(_constants.FORMS_INPUT, this.props);
this.generatedId = _shortid2.default.generate();
if (this.props.errorText) {
this.generatedErrorId = _shortid2.default.generate();
}
},
getId: function getId() {
return this.props.id || this.generatedId;
},
getErrorId: function getErrorId() {
return this.props['aria-describedby'] || this.generatedErrorId;
},
// This is convuluted to maintain backwards compatibility. Please remove deprecatedProps on next breaking change.
getIconRender: function getIconRender(position, iconPositionProp) {
var icon = void 0;
/* eslint-disable react/prop-types */
var deprecatedProps = {
assistiveText: this.props[iconPositionProp] && this.props[iconPositionProp].props.assistiveText || this.props.iconAssistiveText,
category: this.props[iconPositionProp] && this.props[iconPositionProp].props.category || this.props.iconCategory,
name: this.props[iconPositionProp] && this.props[iconPositionProp].props.name || this.props.iconName,
onClick: this.props[iconPositionProp] && this.props[iconPositionProp].props.onClick || this.props.onIconClick
};
/* eslint-enable react/prop-types */
if (this.props[iconPositionProp] && position && this.props[iconPositionProp]) {
icon = _react2.default.cloneElement(this.props[iconPositionProp], {
iconPosition: '' + position
});
} else if (deprecatedProps.name) {
icon = _react2.default.createElement(_inputIcon2.default, _extends({ iconPosition: position }, deprecatedProps));
}
return icon;
},
// ### Render
render: function render() {
// this is a hack to make left the default prop unless overwritten by `iconPosition="right"`
var hasLeftIcon = !!this.props.iconLeft || (this.props.iconPosition === 'left' || this.props.iconPosition === undefined) && !!this.props.iconName;
var hasRightIcon = !!this.props.iconRight || this.props.iconPosition === 'right' && !!this.props.iconName;
return _react2.default.createElement(
'div',
{
className: (0, _classnames2.default)('slds-form-element', {
'slds-has-error': this.props.errorText
}, this.props.className)
},
_react2.default.createElement(_label2.default, {
assistiveText: this.props.assistiveText,
htmlFor: this.props.isStatic ? undefined : this.getId(),
label: this.props.label,
required: this.props.required,
variant: this.props.isStatic ? 'static' : 'base'
}),
_react2.default.createElement(_innerInput2.default, {
'aria-activedescendant': this.props['aria-activedescendant'],
'aria-autocomplete': this.props['aria-autocomplete'],
'aria-controls': this.props['aria-controls'],
'aria-labelledby': this.props['aria-labelledby'],
'aria-describedby': this.getErrorId(),
'aria-expanded': this.props['aria-expanded'],
'aria-owns': this.props['aria-owns'],
'aria-required': this.props['aria-required'],
containerProps: {
className: 'slds-form-element__control'
},
disabled: this.props.disabled,
fixedTextLeft: this.props.fixedTextLeft,
fixedTextRight: this.props.fixedTextRight,
hasSpinner: this.props.hasSpinner,
id: this.getId(),
iconLeft: hasLeftIcon ? this.getIconRender('left', 'iconLeft') : null,
iconRight: hasRightIcon ? this.getIconRender('right', 'iconRight') : null,
inlineEditTrigger: this.props.inlineEditTrigger,
isStatic: this.props.isStatic,
minLength: this.props.minLength,
maxLength: this.props.maxLength,
name: this.props.name,
onBlur: this.props.onBlur,
onChange: this.props.onChange,
onClick: this.props.onClick,
onFocus: this.props.onFocus,
onInput: this.props.onInput,
onInvalid: this.props.onInvalid,
onKeyDown: this.props.onKeyDown,
onKeyPress: this.props.onKeyPress,
onKeyUp: this.props.onKeyUp,
onSelect: this.props.onSelect,
onSubmit: this.props.onSubmit,
placeholder: this.props.placeholder,
inputRef: this.props.inputRef,
readOnly: this.props.readOnly,
required: this.props.required,
role: this.props.role,
spinnerAssistiveText: this.props.assistiveText && this.props.assistiveText.spinner,
type: this.props.type,
value: this.props.value
}),
this.props.errorText && _react2.default.createElement(
'div',
{ id: this.getErrorId(), className: 'slds-form-element__help' },
this.props.errorText
),
this.props.children
);
}
});
exports.default = Input;