@helpscout/hsds-react
Version:
React component library for Help Scout's Design System
436 lines (375 loc) • 16.5 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.default = exports.EditableFieldInput = void 0;
var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose"));
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
var _react = _interopRequireWildcard(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _EditableField = require("./EditableField.css");
var _DropList = _interopRequireDefault(require("../DropList"));
var _Icon = _interopRequireDefault(require("../Icon"));
var _Tooltip = _interopRequireDefault(require("../Tooltip"));
var _Truncate = _interopRequireDefault(require("../Truncate"));
var _getValidProps = _interopRequireDefault(require("@helpscout/react-utils/dist/getValidProps"));
var _EditableField2 = require("./EditableField.constants");
var _EditableField3 = require("./EditableField.utils");
var _classnames = _interopRequireDefault(require("classnames"));
var _Keys = require("../../constants/Keys");
var _fastDeepEqual = _interopRequireDefault(require("fast-deep-equal"));
var _jsxRuntime = require("react/jsx-runtime");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function noop() {}
var Toggler = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
var _ref$disabled = _ref.disabled,
disabled = _ref$disabled === void 0 ? false : _ref$disabled,
_ref$isActive = _ref.isActive,
isActive = _ref$isActive === void 0 ? false : _ref$isActive,
_ref$onBlur = _ref.onBlur,
onBlur = _ref$onBlur === void 0 ? noop : _ref$onBlur,
_ref$onClick = _ref.onClick,
onClick = _ref$onClick === void 0 ? noop : _ref$onClick,
_ref$onFocus = _ref.onFocus,
onFocus = _ref$onFocus === void 0 ? noop : _ref$onFocus,
fieldValue = _ref.fieldValue,
rest = (0, _objectWithoutPropertiesLoose2.default)(_ref, ["disabled", "isActive", "onBlur", "onClick", "onFocus", "fieldValue"]);
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_EditableField.TriggerUI, (0, _extends2.default)({
"aria-label": "toggle menu",
"aria-haspopup": "true",
"aria-expanded": isActive,
"data-cy": "EditableFieldOptionsTrigger",
disabled: disabled,
onClick: onClick,
onFocus: onFocus,
onBlur: onBlur,
ref: ref,
type: "button"
}, rest, {
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_EditableField.OptionsDropdownUI, {
className: (0, _classnames.default)(_EditableField3.INPUT_CLASSNAMES.optionsDropdown, isActive && 'menu-open'),
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Truncate.default, {
className: _EditableField3.INPUT_CLASSNAMES.selectedOption,
children: fieldValue.option
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.default, {
name: _EditableField2.ACTION_ICONS.valueOption
})]
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_EditableField.FocusIndicatorUI, {
className: _EditableField3.INPUT_CLASSNAMES.focusIndicator
})]
}));
});
var EditableFieldInput = /*#__PURE__*/function (_React$Component) {
(0, _inheritsLoose2.default)(EditableFieldInput, _React$Component);
function EditableFieldInput() {
var _this;
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = _React$Component.call.apply(_React$Component, [this].concat(args)) || this;
_this.inputRef = void 0;
_this.inputWrapperRef = /*#__PURE__*/_react.default.createRef();
_this._isMounted = false;
_this.state = {
isDropListOpen: false
};
_this.setInputNode = function (node) {
_this.inputRef = node;
};
_this.setInputTitle = function () {
var fieldValue = _this.props.fieldValue;
var inputNode = _this.inputRef;
var parentNode = (0, _EditableField3.findParentByClassName)(inputNode, _EditableField3.EDITABLEFIELD_CLASSNAMES.field);
if (!parentNode) return;
var contentNode = parentNode.querySelector("." + _EditableField3.MASK_CLASSNAMES.value + " ." + _EditableField3.OTHERCOMPONENTS_CLASSNAMES.truncateContent);
var firstChunkNode = parentNode.querySelector("." + _EditableField3.MASK_CLASSNAMES.value + " ." + _EditableField3.TRUNCATED_CLASSNAMES.firstChunk);
if ((0, _EditableField3.isEllipsisActive)(contentNode) || (0, _EditableField3.isEllipsisActive)(firstChunkNode)) {
inputNode && inputNode.setAttribute('title', fieldValue.value);
}
};
_this.handleInputFocus = function (event) {
var _this$props = _this.props,
name = _this$props.name,
onInputFocus = _this$props.onInputFocus;
onInputFocus({
name: name,
event: event
});
};
_this.handleInputBlur = function (event) {
var _this$props2 = _this.props,
name = _this$props2.name,
onInputBlur = _this$props2.onInputBlur,
valueOptions = _this$props2.valueOptions; // Lots of async stuff happening that need this event as is
// so allow references to it to be maintained
event && event.persist && event.persist();
if (valueOptions) {
setTimeout(function () {
if (!_this.state.isDropListOpen) {
onInputBlur({
name: name,
event: event
});
}
}, 100);
} else {
onInputBlur({
name: name,
event: event
});
}
};
_this.handleOptionFocus = function (event) {
var _this$props3 = _this.props,
disabled = _this$props3.disabled,
name = _this$props3.name,
onOptionFocus = _this$props3.onOptionFocus;
if (!disabled) {
onOptionFocus({
name: name,
event: event
});
}
};
_this.handleChange = function (event) {
var onChange = _this.props.onChange;
onChange({
inputValue: event.currentTarget.value,
name: _this.props.name,
event: event
});
};
_this.handleKeyDown = function (event) {
var isEnter = event.key === _Keys.key.ENTER;
var isDropdownTrigger = event.target.classList.contains(_EditableField3.OTHERCOMPONENTS_CLASSNAMES.dropdownTrigger);
if (isEnter && isDropdownTrigger) {
return;
}
var _this$props4 = _this.props,
name = _this$props4.name,
onKeyDown = _this$props4.onKeyDown;
var inputNode = _this.inputRef;
onKeyDown({
event: event,
name: name
}).then(function () {
// In case the value is longer than the width of the input
// lets move the cursor to the very beginning
// when clicking the input the cursor will be at the expected position :)
if (inputNode && inputNode.setSelectionRange) {
inputNode.setSelectionRange(0, 0);
}
}).catch(function (err) {// Do nothing
});
};
_this.handleKeyPress = function (event) {
var _this$props5 = _this.props,
name = _this$props5.name,
onKeyPress = _this$props5.onKeyPress;
onKeyPress({
event: event,
name: name
});
};
_this.handleKeyUp = function (event) {
var _this$props6 = _this.props,
name = _this$props6.name,
onKeyUp = _this$props6.onKeyUp;
onKeyUp({
event: event,
name: name
});
};
_this.handleDropdownSelect = function (selection) {
var _this$props7 = _this.props,
name = _this$props7.name,
onOptionSelection = _this$props7.onOptionSelection;
onOptionSelection({
name: name,
selection: selection
});
};
_this.handleOpenCloseDropList = function (isOpen) {
if (_this._isMounted) {
_this.setState({
isDropListOpen: isOpen
});
}
};
_this.renderOptions = function () {
var _this$props8 = _this.props,
disabled = _this$props8.disabled,
fieldValue = _this$props8.fieldValue,
valueOptions = _this$props8.valueOptions;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_EditableField.OptionsWrapperUI, {
className: _EditableField3.INPUT_CLASSNAMES.optionsWrapper,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_DropList.default, {
className: _EditableField3.INPUT_CLASSNAMES.dropdown,
items: valueOptions,
onSelect: _this.handleDropdownSelect,
onOpenedStateChange: _this.handleOpenCloseDropList,
toggler: /*#__PURE__*/(0, _jsxRuntime.jsx)(Toggler, {
className: _EditableField3.INPUT_CLASSNAMES.optionsTrigger,
disabled: disabled,
fieldValue: fieldValue,
onFocus: _this.handleOptionFocus
}),
tippyOptions: {
appendTo: function appendTo(reference) {
return reference.closest('.EditableField__field.has-options');
},
offset: [0, 10]
}
})
});
};
_this.renderValidationInfo = function () {
var _this$props9 = _this.props,
name = _this$props9.name,
validationInfo = _this$props9.validationInfo;
if (!validationInfo) return null;
if (name !== validationInfo.name) return null;
var DEFAULT_ICON = 'alert-small';
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_EditableField.ValidationIconUI, {
className: _EditableField3.INPUT_CLASSNAMES.validation,
color: (0, _EditableField3.getValidationColor)(validationInfo),
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.default, {
animationDelay: 0,
animationDuration: 0,
display: "block",
placement: "top-end",
title: validationInfo.message,
appendTo: _this.inputWrapperRef.current,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.default, {
name: validationInfo.icon || DEFAULT_ICON,
size: 24
})
})
});
};
return _this;
}
var _proto = EditableFieldInput.prototype;
_proto.componentDidMount = function componentDidMount() {
this._isMounted = true;
var isActive = this.props.isActive;
this.setInputTitle();
if (isActive) {
var inputNode = this.inputRef;
inputNode && inputNode.focus();
}
};
_proto.componentWillUnmount = function componentWillUnmount() {
this._isMounted = false;
};
_proto.shouldComponentUpdate = function shouldComponentUpdate(nextProps) {
if (!(0, _fastDeepEqual.default)(this.props.fieldValue, nextProps.fieldValue)) {
return true;
}
if (this.props.isActive !== nextProps.isActive) {
return true;
}
if (this.props.disabled !== nextProps.disabled) {
return true;
}
if (!(0, _fastDeepEqual.default)(this.props.validationInfo, nextProps.validationInfo)) {
return true;
}
return false;
};
_proto.componentDidUpdate = function componentDidUpdate() {
this.setInputTitle();
};
_proto.render = function render() {
var _this$props10 = this.props,
disabled = _this$props10.disabled,
fieldValue = _this$props10.fieldValue,
isActive = _this$props10.isActive,
inline = _this$props10.inline,
name = _this$props10.name,
placeholder = _this$props10.placeholder,
type = _this$props10.type,
validationInfo = _this$props10.validationInfo,
valueOptions = _this$props10.valueOptions,
rest = (0, _objectWithoutPropertiesLoose2.default)(_this$props10, ["disabled", "fieldValue", "isActive", "inline", "name", "placeholder", "type", "validationInfo", "valueOptions"]);
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_EditableField.EditableFieldInputUI, {
className: (0, _classnames.default)(_EditableField3.INPUT_CLASSNAMES.content, inline && _EditableField3.STATES_CLASSNAMES.isInline, disabled && _EditableField3.STATES_CLASSNAMES.isDisabled, validationInfo && name === validationInfo.name && _EditableField3.STATES_CLASSNAMES.withValidation),
children: [valueOptions ? this.renderOptions() : null, /*#__PURE__*/(0, _jsxRuntime.jsxs)(_EditableField.InputWrapperUI, {
className: _EditableField3.INPUT_CLASSNAMES.inputWrapper,
withPlaceholder: placeholder,
value: fieldValue.value,
ref: this.inputWrapperRef,
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_EditableField.InputUI, (0, _extends2.default)({}, (0, _getValidProps.default)(rest), {
className: _EditableField3.INPUT_CLASSNAMES.input,
id: name,
ref: this.setInputNode,
name: name,
placeholder: placeholder,
type: type === 'password' ? type : 'text',
value: fieldValue.value,
onBlur: this.handleInputBlur,
onChange: this.handleChange,
onFocus: this.handleInputFocus,
onKeyDown: this.handleKeyDown
})), this.renderValidationInfo(), /*#__PURE__*/(0, _jsxRuntime.jsx)(_EditableField.FocusIndicatorUI, {
className: _EditableField3.INPUT_CLASSNAMES.focusIndicator,
color: (0, _EditableField3.getValidationColor)(validationInfo)
})]
})]
});
};
return EditableFieldInput;
}(_react.default.Component);
exports.EditableFieldInput = EditableFieldInput;
EditableFieldInput.className = _EditableField3.INPUT_CLASSNAMES.component;
EditableFieldInput.defaultProps = {
'data-cy': 'EditableFieldInput',
disabled: false,
fieldValue: '',
isActive: false,
inline: false,
placeholder: '',
type: _EditableField2.FIELDTYPES.text,
innerRef: noop,
onInputFocus: noop,
onInputBlur: noop,
onOptionFocus: noop,
onOptionSelection: noop,
onOptionBlur: noop,
onChange: noop,
onKeyDown: noop,
onKeyPress: noop,
onKeyUp: noop,
deleteAction: noop,
customAction: noop
};
EditableFieldInput.propTypes = {
actions: _propTypes.default.arrayOf(_propTypes.default.object),
className: _propTypes.default.string,
/** Data attr for Cypress tests. */
'data-cy': _propTypes.default.string,
disabled: _propTypes.default.bool,
fieldValue: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.object]),
inline: _propTypes.default.bool,
isActive: _propTypes.default.bool,
name: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]),
placeholder: _propTypes.default.string,
type: _propTypes.default.string,
validationInfo: _propTypes.default.object,
valueOptions: _propTypes.default.arrayOf(_propTypes.default.object),
innerRef: _propTypes.default.func,
onInputFocus: _propTypes.default.func,
onInputBlur: _propTypes.default.func,
onOptionFocus: _propTypes.default.func,
onOptionBlur: _propTypes.default.func,
onOptionSelection: _propTypes.default.func,
onChange: _propTypes.default.func,
onKeyDown: _propTypes.default.func,
onKeyPress: _propTypes.default.func,
onKeyUp: _propTypes.default.func,
deleteAction: _propTypes.default.func,
customAction: _propTypes.default.func
};
var _default = EditableFieldInput;
exports.default = _default;