react-edit-text
Version:
Simple editable text component for React
501 lines (438 loc) • 18.7 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('classnames'), require('react'), require('react/jsx-runtime'), require('prop-types')) :
typeof define === 'function' && define.amd ? define(['exports', 'classnames', 'react', 'react/jsx-runtime', 'prop-types'], factory) :
(global = global || self, factory(global.reactEditText = {}, global.classnames, global.react, global.jsxRuntime, global.propTypes));
})(this, (function (exports, classnames, React, jsxRuntime, PropTypes) {
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var classnames__default = /*#__PURE__*/_interopDefaultLegacy(classnames);
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes);
function _extends() {
_extends = Object.assign ? Object.assign.bind() : 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;
};
return _extends.apply(this, arguments);
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
var EditIcon = function EditIcon() {
return /*#__PURE__*/jsxRuntime.jsx("svg", {
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0 0 512 512",
children: /*#__PURE__*/jsxRuntime.jsx("path", {
d: "M421.7 220.3L188.5 453.4L154.6 419.5L158.1 416H112C103.2 416 96 408.8 96 400V353.9L92.51 357.4C87.78 362.2 84.31 368 82.42 374.4L59.44 452.6L137.6 429.6C143.1 427.7 149.8 424.2 154.6 419.5L188.5 453.4C178.1 463.8 165.2 471.5 151.1 475.6L30.77 511C22.35 513.5 13.24 511.2 7.03 504.1C.8198 498.8-1.502 489.7 .976 481.2L36.37 360.9C40.53 346.8 48.16 333.9 58.57 323.5L291.7 90.34L421.7 220.3zM492.7 58.75C517.7 83.74 517.7 124.3 492.7 149.3L444.3 197.7L314.3 67.72L362.7 19.32C387.7-5.678 428.3-5.678 453.3 19.32L492.7 58.75z"
})
});
};
var styles = {"label":"_4GdcU","textareaView":"_G0k44","shared":"_i5--j","placeholder":"_TDklp","inline":"_gmkRL","readonly":"_-wzeg","displayContainer":"_IYz6Z","editButton":"_NGZSv"};
var _excluded$1 = ["props", "inputRef", "handleBlur", "handleKeydown", "handleFocus", "inputClassName"];
var Input = function Input(_ref) {
var _classnames;
var _ref$props = _ref.props,
id = _ref$props.id,
inline = _ref$props.inline,
style = _ref$props.style,
type = _ref$props.type,
name = _ref$props.name,
inputRef = _ref.inputRef,
handleBlur = _ref.handleBlur,
handleKeydown = _ref.handleKeydown,
handleFocus = _ref.handleFocus,
inputClassName = _ref.inputClassName,
rest = _objectWithoutPropertiesLoose(_ref, _excluded$1);
return /*#__PURE__*/jsxRuntime.jsx("input", _extends({
id: id,
className: classnames__default["default"](styles.shared, inputClassName, (_classnames = {}, _classnames[styles.inline] = inline, _classnames)),
style: style,
ref: inputRef,
type: type,
name: name,
onBlur: handleBlur,
onKeyDown: handleKeydown,
autoFocus: true,
onFocus: handleFocus
}, rest));
};
var sharedPropTypes = {
id: PropTypes__default["default"].string,
name: PropTypes__default["default"].string,
className: PropTypes__default["default"].string,
value: PropTypes__default["default"].string,
formatDisplayText: PropTypes__default["default"].func,
defaultValue: PropTypes__default["default"].string,
placeholder: PropTypes__default["default"].string,
onSave: PropTypes__default["default"].func,
onChange: PropTypes__default["default"].func,
onEditMode: PropTypes__default["default"].func,
onBlur: PropTypes__default["default"].func,
style: PropTypes__default["default"].oneOfType([PropTypes__default["default"].object, PropTypes__default["default"].array]),
readonly: PropTypes__default["default"].bool,
inputClassName: PropTypes__default["default"].string
};
var EditTextPropTypes = _extends({}, sharedPropTypes, {
type: PropTypes__default["default"].string,
inline: PropTypes__default["default"].bool,
showEditButton: PropTypes__default["default"].bool,
editButtonContent: PropTypes__default["default"].any,
editButtonProps: PropTypes__default["default"].object
});
var EditTextareaPropTypes = _extends({}, sharedPropTypes, {
rows: PropTypes__default["default"].oneOfType([PropTypes__default["default"].number, PropTypes__default["default"].oneOf(['auto'])])
});
function EditText(_ref) {
var id = _ref.id,
name = _ref.name,
className = _ref.className,
_ref$placeholder = _ref.placeholder,
placeholder = _ref$placeholder === void 0 ? '' : _ref$placeholder,
_ref$inline = _ref.inline,
inline = _ref$inline === void 0 ? false : _ref$inline,
_ref$style = _ref.style,
style = _ref$style === void 0 ? {} : _ref$style,
_ref$readonly = _ref.readonly,
readonly = _ref$readonly === void 0 ? false : _ref$readonly,
_ref$type = _ref.type,
type = _ref$type === void 0 ? 'text' : _ref$type,
value = _ref.value,
defaultValue = _ref.defaultValue,
_ref$formatDisplayTex = _ref.formatDisplayText,
formatDisplayText = _ref$formatDisplayTex === void 0 ? function (x) {
return x;
} : _ref$formatDisplayTex,
_ref$onEditMode = _ref.onEditMode,
onEditMode = _ref$onEditMode === void 0 ? function () {} : _ref$onEditMode,
_ref$onChange = _ref.onChange,
_onChange = _ref$onChange === void 0 ? function () {} : _ref$onChange,
_ref$onSave = _ref.onSave,
onSave = _ref$onSave === void 0 ? function () {} : _ref$onSave,
_ref$onBlur = _ref.onBlur,
onBlur = _ref$onBlur === void 0 ? function () {} : _ref$onBlur,
_ref$showEditButton = _ref.showEditButton,
showEditButton = _ref$showEditButton === void 0 ? false : _ref$showEditButton,
_ref$editButtonConten = _ref.editButtonContent,
editButtonContent = _ref$editButtonConten === void 0 ? /*#__PURE__*/jsxRuntime.jsx(EditIcon, {}) : _ref$editButtonConten,
_ref$editButtonProps = _ref.editButtonProps,
editButtonProps = _ref$editButtonProps === void 0 ? {} : _ref$editButtonProps,
inputClassName = _ref.inputClassName;
var inputRef = React__default["default"].useRef(null);
var _React$useState = React__default["default"].useState({}),
changeEvent = _React$useState[0],
setChangeEvent = _React$useState[1];
var _React$useState2 = React__default["default"].useState(''),
previousValue = _React$useState2[0],
setPreviousValue = _React$useState2[1];
var _React$useState3 = React__default["default"].useState(''),
savedText = _React$useState3[0],
setSavedText = _React$useState3[1];
var _React$useState4 = React__default["default"].useState(false),
editMode = _React$useState4[0],
setEditMode = _React$useState4[1];
React__default["default"].useEffect(function () {
if (defaultValue !== undefined) {
setPreviousValue(defaultValue);
setSavedText(defaultValue);
}
}, [defaultValue]);
React__default["default"].useEffect(function () {
if (value !== undefined) {
setSavedText(value);
if (!editMode) {
setPreviousValue(value);
}
}
}, [value, editMode]);
var handleClickDisplay = function handleClickDisplay() {
if (readonly || showEditButton) return;
setEditMode(true);
onEditMode();
};
var handleClickEditButton = function handleClickEditButton() {
setEditMode(true);
onEditMode();
};
var handleBlur = function handleBlur(save) {
if (save === void 0) {
save = true;
}
if (inputRef.current) {
var _inputRef$current = inputRef.current,
inputName = _inputRef$current.name,
inputValue = _inputRef$current.value;
if (save && previousValue !== inputValue) {
onSave({
name: inputName,
value: inputValue,
previousValue: previousValue
});
setSavedText(inputValue);
setPreviousValue(inputValue);
} else if (!save) {
_onChange(_extends({}, changeEvent, {
target: changeEvent.target ? _extends({}, changeEvent.target, {
value: previousValue
}) : {
value: previousValue
}
}));
}
setEditMode(false);
onBlur();
}
};
var handleKeydown = function handleKeydown(e) {
if (e.keyCode === 13 || e.charCode === 13) {
handleBlur();
} else if (e.keyCode === 27 || e.charCode === 27) {
handleBlur(false);
}
};
var handleFocus = function handleFocus(e) {
if (type === 'text') {
e.currentTarget.setSelectionRange(e.currentTarget.value.length, e.currentTarget.value.length);
}
};
var renderDisplayMode = function renderDisplayMode() {
var _classnames, _classnames2;
return /*#__PURE__*/jsxRuntime.jsxs("div", {
className: classnames__default["default"](styles.displayContainer, (_classnames = {}, _classnames[styles.inline] = inline, _classnames)),
children: [/*#__PURE__*/jsxRuntime.jsx("div", {
id: id,
className: classnames__default["default"](styles.label, styles.shared, (_classnames2 = {}, _classnames2[styles.placeholder] = placeholder && !savedText, _classnames2[styles.inline] = inline, _classnames2[styles.readonly] = readonly || showEditButton, _classnames2), className),
onClick: handleClickDisplay,
style: style,
"aria-label": "display component",
children: formatDisplayText(savedText) || placeholder
}), showEditButton && !readonly && /*#__PURE__*/jsxRuntime.jsx("button", _extends({
type: "button",
className: styles.editButton
}, editButtonProps, {
onClick: handleClickEditButton,
children: editButtonContent
}))]
});
};
var renderEditMode = function renderEditMode(controlled) {
var _sharedProps;
var sharedProps = (_sharedProps = {
inputRef: inputRef,
handleBlur: handleBlur,
handleKeydown: handleKeydown,
handleFocus: handleFocus,
props: {
id: id,
inline: inline,
style: style,
type: type,
name: name
}
}, _sharedProps['aria-label'] = 'input component', _sharedProps);
return controlled ? /*#__PURE__*/jsxRuntime.jsx(Input, _extends({}, sharedProps, {
value: value,
onChange: function onChange(e) {
setChangeEvent(e);
_onChange(e);
},
inputClassName: inputClassName
})) : /*#__PURE__*/jsxRuntime.jsx(Input, _extends({}, sharedProps, {
defaultValue: savedText,
inputClassName: inputClassName
}));
};
return !readonly && editMode ? renderEditMode(value !== undefined && _onChange !== undefined) : renderDisplayMode();
}
EditText.propTypes = EditTextPropTypes;
var _excluded = ["props", "inputRef", "handleBlur", "handleKeydown", "inputClassName"];
var Textarea = function Textarea(_ref) {
var _ref$props = _ref.props,
id = _ref$props.id,
rows = _ref$props.rows,
style = _ref$props.style,
name = _ref$props.name,
inputRef = _ref.inputRef,
handleBlur = _ref.handleBlur,
handleKeydown = _ref.handleKeydown,
inputClassName = _ref.inputClassName,
rest = _objectWithoutPropertiesLoose(_ref, _excluded);
return /*#__PURE__*/jsxRuntime.jsx("textarea", _extends({
id: id,
className: classnames__default["default"](styles.shared, inputClassName),
style: style,
ref: inputRef,
rows: rows,
name: name,
onBlur: handleBlur,
onKeyDown: handleKeydown,
autoFocus: true,
onFocus: function onFocus(e) {
return e.currentTarget.setSelectionRange(e.currentTarget.value.length, e.currentTarget.value.length);
}
}, rest));
};
var splitLines = function splitLines(val) {
return val ? val.split(/\r?\n/) : [];
};
function EditTextarea(_ref) {
var id = _ref.id,
_ref$rows = _ref.rows,
rows = _ref$rows === void 0 ? 3 : _ref$rows,
name = _ref.name,
className = _ref.className,
_ref$placeholder = _ref.placeholder,
placeholder = _ref$placeholder === void 0 ? '' : _ref$placeholder,
_ref$style = _ref.style,
style = _ref$style === void 0 ? {} : _ref$style,
_ref$readonly = _ref.readonly,
readonly = _ref$readonly === void 0 ? false : _ref$readonly,
value = _ref.value,
defaultValue = _ref.defaultValue,
_ref$formatDisplayTex = _ref.formatDisplayText,
formatDisplayText = _ref$formatDisplayTex === void 0 ? function (x) {
return x;
} : _ref$formatDisplayTex,
_ref$onEditMode = _ref.onEditMode,
onEditMode = _ref$onEditMode === void 0 ? function () {} : _ref$onEditMode,
_ref$onChange = _ref.onChange,
_onChange = _ref$onChange === void 0 ? function () {} : _ref$onChange,
_ref$onSave = _ref.onSave,
onSave = _ref$onSave === void 0 ? function () {} : _ref$onSave,
_ref$onBlur = _ref.onBlur,
onBlur = _ref$onBlur === void 0 ? function () {} : _ref$onBlur,
inputClassName = _ref.inputClassName;
var inputRef = React__default["default"].useRef(null);
var _React$useState = React__default["default"].useState({}),
changeEvent = _React$useState[0],
setChangeEvent = _React$useState[1];
var _React$useState2 = React__default["default"].useState(''),
previousValue = _React$useState2[0],
setPreviousValue = _React$useState2[1];
var _React$useState3 = React__default["default"].useState(''),
savedText = _React$useState3[0],
setSavedText = _React$useState3[1];
var _React$useState4 = React__default["default"].useState(false),
editMode = _React$useState4[0],
setEditMode = _React$useState4[1];
React__default["default"].useEffect(function () {
if (defaultValue !== undefined) {
setPreviousValue(defaultValue);
setSavedText(defaultValue);
}
}, [defaultValue]);
React__default["default"].useEffect(function () {
if (value !== undefined) {
setSavedText(value);
if (!editMode) {
setPreviousValue(value);
}
}
}, [value, editMode]);
var handleClick = function handleClick() {
if (readonly) return;
setEditMode(true);
onEditMode();
};
var handleBlur = function handleBlur(save) {
if (save === void 0) {
save = true;
}
if (inputRef.current) {
var _inputRef$current = inputRef.current,
inputName = _inputRef$current.name,
inputValue = _inputRef$current.value;
if (save && previousValue !== inputValue) {
onSave({
name: inputName,
value: inputValue,
previousValue: previousValue
});
setSavedText(inputValue);
setPreviousValue(inputValue);
} else if (!save) {
_onChange(_extends({}, changeEvent, {
target: changeEvent.target ? _extends({}, changeEvent.target, {
value: previousValue
}) : {
value: previousValue
}
}));
}
setEditMode(false);
onBlur();
}
};
var handleKeydown = function handleKeydown(e) {
if (e.keyCode === 27 || e.charCode === 27) {
handleBlur(false);
}
};
var renderDisplayMode = function renderDisplayMode() {
var _classnames;
var textLines = splitLines(formatDisplayText(savedText));
return /*#__PURE__*/jsxRuntime.jsx("div", {
id: id,
className: classnames__default["default"](styles.shared, styles.textareaView, (_classnames = {}, _classnames[styles.placeholder] = placeholder && !savedText, _classnames[styles.readonly] = readonly, _classnames), className),
onClick: handleClick,
style: _extends({}, style, {
height: rows === 'auto' ? 'auto' : rows * 24 + 16 + "px"
}),
"aria-label": "display component",
children: textLines.length > 0 ? textLines.map(function (text, index) {
return /*#__PURE__*/jsxRuntime.jsxs(React__default["default"].Fragment, {
children: [/*#__PURE__*/jsxRuntime.jsx("span", {
children: text
}), /*#__PURE__*/jsxRuntime.jsx("br", {})]
}, index);
}) : /*#__PURE__*/jsxRuntime.jsx("span", {
children: placeholder
})
});
};
var renderEditMode = function renderEditMode(controlled) {
var _sharedProps;
var sharedProps = (_sharedProps = {
inputRef: inputRef,
handleBlur: handleBlur,
handleKeydown: handleKeydown,
props: {
id: id,
rows: rows,
style: style,
name: name
}
}, _sharedProps['aria-label'] = 'textarea component', _sharedProps);
return controlled ? /*#__PURE__*/jsxRuntime.jsx(Textarea, _extends({}, sharedProps, {
value: value,
onChange: function onChange(e) {
setChangeEvent(e);
_onChange(e);
},
inputClassName: inputClassName
})) : /*#__PURE__*/jsxRuntime.jsx(Textarea, _extends({}, sharedProps, {
defaultValue: savedText,
inputClassName: inputClassName
}));
};
return !readonly && editMode ? renderEditMode(value !== undefined && _onChange !== undefined) : renderDisplayMode();
}
EditTextarea.propTypes = EditTextareaPropTypes;
exports.EditText = EditText;
exports.EditTextarea = EditTextarea;
}));
//# sourceMappingURL=index.umd.js.map