@elastic/eui
Version:
Elastic UI Component Library
390 lines (387 loc) • 19.2 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.SMALL_SIZE_FORM = exports.MEDIUM_SIZE_FORM = exports.EuiInlineEditForm = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _react = _interopRequireWildcard(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _classnames = _interopRequireDefault(require("classnames"));
var _form = require("../form");
var _form2 = require("../form/form.styles");
var _button = require("../button");
var _flex = require("../flex");
var _skeleton = require("../skeleton");
var _services = require("../../services");
var _i18n = require("../i18n");
var _accessibility = require("../../services/accessibility");
var _inline_edit_form = require("./inline_edit_form.styles");
var _react2 = require("@emotion/react");
var _excluded = ["className", "children", "sizes", "defaultValue", "value", "onChange", "onCancel", "placeholder", "inputAriaLabel", "startWithEditOpen", "readModeProps", "editModeProps", "isLoading", "isInvalid", "onSave", "isReadOnly"];
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
// Props shared between the internal form component as well as consumer-facing components
// Internal-only props, passed by the consumer-facing components
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
var SMALL_SIZE_FORM = exports.SMALL_SIZE_FORM = {
iconSize: 's',
compressed: true,
buttonSize: 's'
};
var MEDIUM_SIZE_FORM = exports.MEDIUM_SIZE_FORM = {
iconSize: 'm',
compressed: false,
buttonSize: 'm'
};
var EuiInlineEditForm = exports.EuiInlineEditForm = function EuiInlineEditForm(_ref) {
var _editModeProps$inputP, _editModeProps$formRo, _editModeProps$inputP6;
var className = _ref.className,
children = _ref.children,
sizes = _ref.sizes,
_ref$defaultValue = _ref.defaultValue,
defaultValue = _ref$defaultValue === void 0 ? '' : _ref$defaultValue,
_ref$value = _ref.value,
controlledValue = _ref$value === void 0 ? '' : _ref$value,
_onChange = _ref.onChange,
onCancel = _ref.onCancel,
_ref$placeholder = _ref.placeholder,
placeholder = _ref$placeholder === void 0 ? '' : _ref$placeholder,
inputAriaLabel = _ref.inputAriaLabel,
startWithEditOpen = _ref.startWithEditOpen,
readModeProps = _ref.readModeProps,
editModeProps = _ref.editModeProps,
_ref$isLoading = _ref.isLoading,
isLoading = _ref$isLoading === void 0 ? false : _ref$isLoading,
isInvalid = _ref.isInvalid,
onSave = _ref.onSave,
isReadOnly = _ref.isReadOnly,
rest = (0, _objectWithoutProperties2.default)(_ref, _excluded);
var classes = (0, _classnames.default)('euiInlineEdit', className);
var euiTheme = (0, _services.useEuiTheme)();
var _euiFormVariables = (0, _form2.euiFormVariables)(euiTheme),
controlHeight = _euiFormVariables.controlHeight,
controlCompressedHeight = _euiFormVariables.controlCompressedHeight;
var loadingSkeletonSize = sizes.compressed ? controlCompressedHeight : controlHeight;
var defaultSaveButtonAriaLabel = (0, _i18n.useEuiI18n)('euiInlineEditForm.saveButtonAriaLabel', 'Save edit');
var defaultCancelButtonAriaLabel = (0, _i18n.useEuiI18n)('euiInlineEditForm.cancelButtonAriaLabel', 'Cancel edit');
var readModeDescribedById = (0, _accessibility.useGeneratedHtmlId)({
prefix: 'inlineEdit'
});
var editModeDescribedById = (0, _accessibility.useGeneratedHtmlId)({
prefix: 'inlineEdit'
});
var readModeFocusRef = (0, _react.useRef)(null);
var editModeFocusRef = (0, _react.useRef)(null);
var setReadModeRefs = (0, _services.useCombinedRefs)([readModeFocusRef, readModeProps === null || readModeProps === void 0 ? void 0 : readModeProps.buttonRef]);
var setEditModeRefs = (0, _services.useCombinedRefs)([editModeFocusRef, editModeProps === null || editModeProps === void 0 || (_editModeProps$inputP = editModeProps.inputProps) === null || _editModeProps$inputP === void 0 ? void 0 : _editModeProps$inputP.inputRef]);
var _useState = (0, _react.useState)(false || startWithEditOpen),
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
isEditing = _useState2[0],
setIsEditing = _useState2[1];
var _useState3 = (0, _react.useState)(defaultValue),
_useState4 = (0, _slicedToArray2.default)(_useState3, 2),
editModeValue = _useState4[0],
setEditModeValue = _useState4[1];
// readModeValue accepts controlledValue here to provide a reliable backup for the onCancel callback
var _useState5 = (0, _react.useState)(controlledValue || defaultValue),
_useState6 = (0, _slicedToArray2.default)(_useState5, 2),
readModeValue = _useState6[0],
setReadModeValue = _useState6[1];
var value = (0, _react.useMemo)(function () {
if (controlledValue) {
return controlledValue;
} else {
return isEditing ? editModeValue : readModeValue || placeholder;
}
}, [controlledValue, editModeValue, readModeValue, isEditing, placeholder]);
var readModeStyles = (0, _inline_edit_form.euiInlineEditReadModeStyles)(euiTheme);
var readModeCssStyles = [readModeStyles.euiInlineEditReadMode, isReadOnly && readModeStyles.isReadOnly, placeholder && !readModeValue && readModeStyles.hasPlaceholder];
var activateEditMode = function activateEditMode() {
setIsEditing(true);
// Waits a tick for state to settle and the focus target to render
requestAnimationFrame(function () {
var _editModeFocusRef$cur;
return (_editModeFocusRef$cur = editModeFocusRef.current) === null || _editModeFocusRef$cur === void 0 ? void 0 : _editModeFocusRef$cur.focus();
});
};
var cancelInlineEdit = function cancelInlineEdit() {
setEditModeValue(readModeValue);
onCancel === null || onCancel === void 0 || onCancel(readModeValue);
setIsEditing(false);
requestAnimationFrame(function () {
var _readModeFocusRef$cur;
return (_readModeFocusRef$cur = readModeFocusRef.current) === null || _readModeFocusRef$cur === void 0 ? void 0 : _readModeFocusRef$cur.focus();
});
};
var saveInlineEditValue = /*#__PURE__*/function () {
var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
var onSaveReturn, awaitedReturn;
return _regenerator.default.wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
if (!onSave) {
_context.next = 12;
break;
}
onSaveReturn = onSave(value);
if (!(onSaveReturn instanceof Promise)) {
_context.next = 8;
break;
}
_context.next = 5;
return onSaveReturn;
case 5:
_context.t0 = _context.sent;
_context.next = 9;
break;
case 8:
_context.t0 = onSaveReturn;
case 9:
awaitedReturn = _context.t0;
if (!(awaitedReturn === false)) {
_context.next = 12;
break;
}
return _context.abrupt("return");
case 12:
setReadModeValue(editModeValue);
setIsEditing(false);
requestAnimationFrame(function () {
var _readModeFocusRef$cur2;
return (_readModeFocusRef$cur2 = readModeFocusRef.current) === null || _readModeFocusRef$cur2 === void 0 ? void 0 : _readModeFocusRef$cur2.focus();
});
case 15:
case "end":
return _context.stop();
}
}, _callee);
}));
return function saveInlineEditValue() {
return _ref2.apply(this, arguments);
};
}();
var editModeInputOnKeyDown = function editModeInputOnKeyDown(event) {
switch (event.key) {
case _services.keys.ENTER:
event.preventDefault(); // Enter keypresses will not proceed otherwise on webkit browsers & screen readers
saveInlineEditValue();
break;
case _services.keys.ESCAPE:
cancelInlineEdit();
break;
}
};
// If the state of isReadOnly changes while in edit mode, switch back to read mode
(0, _react.useEffect)(function () {
if (isReadOnly) {
setIsEditing(false);
}
}, [isReadOnly]);
var editModeForm = (0, _react2.jsx)(_flex.EuiFlexGroup, {
gutterSize: "s",
responsive: false
}, (0, _react2.jsx)(_flex.EuiFlexItem, null, (0, _react2.jsx)(_form.EuiFormRow, (0, _extends2.default)({
fullWidth: true,
isInvalid: isInvalid,
error: isInvalid && (editModeProps === null || editModeProps === void 0 || (_editModeProps$formRo = editModeProps.formRowProps) === null || _editModeProps$formRo === void 0 ? void 0 : _editModeProps$formRo.error)
}, editModeProps === null || editModeProps === void 0 ? void 0 : editModeProps.formRowProps), (0, _react2.jsx)(_form.EuiFieldText, (0, _extends2.default)({
fullWidth: true,
value: value,
"aria-label": inputAriaLabel,
compressed: sizes.compressed,
isInvalid: isInvalid,
isLoading: isLoading,
"data-test-subj": "euiInlineEditModeInput",
placeholder: placeholder || undefined // Opt not to render the prop entirely if an empty string is passed
}, editModeProps === null || editModeProps === void 0 ? void 0 : editModeProps.inputProps, {
inputRef: setEditModeRefs,
onChange: function onChange(e) {
var _editModeProps$inputP2, _editModeProps$inputP3;
setEditModeValue(e.target.value);
_onChange === null || _onChange === void 0 || _onChange(e);
editModeProps === null || editModeProps === void 0 || (_editModeProps$inputP2 = editModeProps.inputProps) === null || _editModeProps$inputP2 === void 0 || (_editModeProps$inputP3 = _editModeProps$inputP2.onChange) === null || _editModeProps$inputP3 === void 0 || _editModeProps$inputP3.call(_editModeProps$inputP2, e);
},
onKeyDown: function onKeyDown(e) {
var _editModeProps$inputP4, _editModeProps$inputP5;
editModeInputOnKeyDown(e);
editModeProps === null || editModeProps === void 0 || (_editModeProps$inputP4 = editModeProps.inputProps) === null || _editModeProps$inputP4 === void 0 || (_editModeProps$inputP5 = _editModeProps$inputP4.onKeyDown) === null || _editModeProps$inputP5 === void 0 || _editModeProps$inputP5.call(_editModeProps$inputP4, e);
},
"aria-describedby": (0, _classnames.default)(editModeDescribedById, editModeProps === null || editModeProps === void 0 || (_editModeProps$inputP6 = editModeProps.inputProps) === null || _editModeProps$inputP6 === void 0 ? void 0 : _editModeProps$inputP6['aria-describedby'])
}))), (0, _react2.jsx)("span", {
id: editModeDescribedById,
hidden: true
}, (0, _react2.jsx)(_i18n.EuiI18n, {
token: "euiInlineEditForm.inputKeyboardInstructions",
default: "Press Enter to save your edited text. Press Escape to cancel your edit."
}))), (0, _react2.jsx)(_flex.EuiFlexItem, {
grow: false
}, (0, _react2.jsx)(_skeleton.EuiSkeletonLoading, {
isLoading: isLoading,
announceLoadingStatus: true,
announceLoadedStatus: false,
loadingContent: (0, _react2.jsx)(_flex.EuiFlexGroup, {
gutterSize: "s"
}, (0, _react2.jsx)(_skeleton.EuiSkeletonRectangle, {
height: loadingSkeletonSize,
width: loadingSkeletonSize,
borderRadius: "m"
}), (0, _react2.jsx)(_skeleton.EuiSkeletonRectangle, {
height: loadingSkeletonSize,
width: loadingSkeletonSize,
borderRadius: "m"
})),
loadedContent: (0, _react2.jsx)(_flex.EuiFlexGroup, {
gutterSize: "s"
}, (0, _react2.jsx)(_button.EuiButtonIcon, (0, _extends2.default)({
iconType: "check",
"aria-label": defaultSaveButtonAriaLabel,
color: "success",
display: "base",
size: sizes.buttonSize,
iconSize: sizes.iconSize,
"data-test-subj": "euiInlineEditModeSaveButton"
}, editModeProps === null || editModeProps === void 0 ? void 0 : editModeProps.saveButtonProps, {
onClick: function onClick(e) {
var _editModeProps$saveBu, _editModeProps$saveBu2;
saveInlineEditValue();
editModeProps === null || editModeProps === void 0 || (_editModeProps$saveBu = editModeProps.saveButtonProps) === null || _editModeProps$saveBu === void 0 || (_editModeProps$saveBu2 = _editModeProps$saveBu.onClick) === null || _editModeProps$saveBu2 === void 0 || _editModeProps$saveBu2.call(_editModeProps$saveBu, e);
}
})), (0, _react2.jsx)(_button.EuiButtonIcon, (0, _extends2.default)({
iconType: "cross",
"aria-label": defaultCancelButtonAriaLabel,
color: "danger",
display: "base",
size: sizes.buttonSize,
iconSize: sizes.iconSize,
"data-test-subj": "euiInlineEditModeCancelButton"
}, editModeProps === null || editModeProps === void 0 ? void 0 : editModeProps.cancelButtonProps, {
onClick: function onClick(e) {
var _editModeProps$cancel, _editModeProps$cancel2;
cancelInlineEdit();
editModeProps === null || editModeProps === void 0 || (_editModeProps$cancel = editModeProps.cancelButtonProps) === null || _editModeProps$cancel === void 0 || (_editModeProps$cancel2 = _editModeProps$cancel.onClick) === null || _editModeProps$cancel2 === void 0 || _editModeProps$cancel2.call(_editModeProps$cancel, e);
}
})))
})));
var readModeElement = (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)(_button.EuiButtonEmpty, (0, _extends2.default)({
color: "text",
iconType: isReadOnly ? undefined : 'pencil',
iconSide: "right",
flush: "both",
iconSize: sizes.iconSize,
size: sizes.buttonSize,
"data-test-subj": "euiInlineReadModeButton",
disabled: isReadOnly,
css: readModeCssStyles,
title: value
}, readModeProps, {
buttonRef: setReadModeRefs,
"aria-describedby": (0, _classnames.default)(readModeDescribedById, readModeProps === null || readModeProps === void 0 ? void 0 : readModeProps['aria-describedby']),
onClick: function onClick(e) {
var _readModeProps$onClic;
activateEditMode();
readModeProps === null || readModeProps === void 0 || (_readModeProps$onClic = readModeProps.onClick) === null || _readModeProps$onClic === void 0 || _readModeProps$onClic.call(readModeProps, e);
}
}), children(value)), (0, _react2.jsx)("span", {
id: readModeDescribedById,
hidden: true
}, !isReadOnly && (0, _react2.jsx)(_i18n.EuiI18n, {
token: "euiInlineEditForm.activateEditModeDescription",
default: "Click to edit this text inline."
})));
return (0, _react2.jsx)("div", (0, _extends2.default)({
className: classes
}, rest), isEditing ? editModeForm : readModeElement);
};
EuiInlineEditForm.propTypes = {
className: _propTypes.default.string,
"aria-label": _propTypes.default.string,
"data-test-subj": _propTypes.default.string,
css: _propTypes.default.any,
placeholder: _propTypes.default.string,
/**
* Callback that fires when a user clicks the save button.
* Passes the current edited text value as an argument.
*
* To validate the value of the edited text, pass back a boolean flag.
* If `false`, EuiInlineEdit will remain in edit mode, where loading or invalid states can be set.
* If `true`, EuiInlineEdit will return to read mode.
*/
onSave: _propTypes.default.func,
/**
* Form label that appears above the form control.
* This is required for accessibility because there is no visual label on the input.
*/
inputAriaLabel: _propTypes.default.string.isRequired,
/**
* Starts the component in edit mode
*/
startWithEditOpen: _propTypes.default.bool,
/**
* Props that will be applied directly to the `EuiEmptyButton` displayed in read mode
*/
readModeProps: _propTypes.default.any,
/**
* Multiple props objects that can be applied directly to various child components displayed in edit mode.
* - `formRowProps` will be passed to `EuiFormRow`
* - `inputProps` will be passed to `EuiFieldText`
* - `saveButtonProps` & `cancelButtonProps` will be passed to their respective `EuiIconButton`s
*/
editModeProps: _propTypes.default.shape({
formRowProps: _propTypes.default.any,
inputProps: _propTypes.default.any,
saveButtonProps: _propTypes.default.any,
cancelButtonProps: _propTypes.default.any
}),
/**
* Loading state - only displayed in edit mode
*/
isLoading: _propTypes.default.bool,
/**
* Invalid state - only displayed edit mode
*/
isInvalid: _propTypes.default.bool,
/**
* Locks inline edit in read mode and displays the text value
*/
isReadOnly: _propTypes.default.bool,
/**
* Initial inline edit text value
*/
defaultValue: _propTypes.default.string,
/**
* To use inline edit as a controlled component, continuously pass the value via this prop
*/
value: _propTypes.default.string,
/**
* Callback required to receive and update `value` based on user input
*/
onChange: _propTypes.default.func,
/**
* Callback required to reset `value` to the previous read mode text value.
*/
onCancel: _propTypes.default.func,
/**
* Form sizes
*/
sizes: _propTypes.default.shape({
compressed: _propTypes.default.bool.isRequired,
buttonSize: _propTypes.default.any.isRequired,
iconSize: _propTypes.default.any.isRequired
}).isRequired,
/**
* Render prop that returns the read mode value as an arg
*/
children: _propTypes.default.func.isRequired
};