@elastic/eui
Version:
Elastic UI Component Library
300 lines (295 loc) • 14.5 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
var _excluded = ["className", "children", "sizes", "defaultValue", "value", "onChange", "onCancel", "placeholder", "inputAriaLabel", "startWithEditOpen", "readModeProps", "editModeProps", "isLoading", "isInvalid", "onSave", "isReadOnly"];
import _regeneratorRuntime from "@babel/runtime/regenerator";
/*
* 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.
*/
import React, { useState, useRef, useEffect, useMemo } from 'react';
import classNames from 'classnames';
import { EuiFormRow, EuiFieldText } from '../form';
import { euiFormVariables } from '../form/form.styles';
import { EuiButtonIcon, EuiButtonEmpty } from '../button';
import { EuiFlexGroup, EuiFlexItem } from '../flex';
import { EuiSkeletonLoading, EuiSkeletonRectangle } from '../skeleton';
import { useEuiMemoizedStyles, useCombinedRefs, keys } from '../../services';
import { EuiI18n, useEuiI18n } from '../i18n';
import { useGeneratedHtmlId } from '../../services/accessibility';
import { euiInlineEditReadModeStyles } from './inline_edit_form.styles';
// Props shared between the internal form component as well as consumer-facing components
// Internal-only props, passed by the consumer-facing components
import { jsx as ___EmotionJSX } from "@emotion/react";
export var SMALL_SIZE_FORM = {
iconSize: 's',
compressed: true,
buttonSize: 's'
};
export var MEDIUM_SIZE_FORM = {
iconSize: 'm',
compressed: false,
buttonSize: 'm'
};
export var 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 = _objectWithoutProperties(_ref, _excluded);
var classes = classNames('euiInlineEdit', className);
var _useEuiMemoizedStyles = useEuiMemoizedStyles(euiFormVariables),
controlHeight = _useEuiMemoizedStyles.controlHeight,
controlCompressedHeight = _useEuiMemoizedStyles.controlCompressedHeight;
var loadingSkeletonSize = sizes.compressed ? controlCompressedHeight : controlHeight;
var defaultSaveButtonAriaLabel = useEuiI18n('euiInlineEditForm.saveButtonAriaLabel', 'Save edit');
var defaultCancelButtonAriaLabel = useEuiI18n('euiInlineEditForm.cancelButtonAriaLabel', 'Cancel edit');
var readModeDescribedById = useGeneratedHtmlId({
prefix: 'inlineEdit'
});
var editModeDescribedById = useGeneratedHtmlId({
prefix: 'inlineEdit'
});
var readModeFocusRef = useRef(null);
var editModeFocusRef = useRef(null);
var setReadModeRefs = useCombinedRefs([readModeFocusRef, readModeProps === null || readModeProps === void 0 ? void 0 : readModeProps.buttonRef]);
var setEditModeRefs = useCombinedRefs([editModeFocusRef, editModeProps === null || editModeProps === void 0 || (_editModeProps$inputP = editModeProps.inputProps) === null || _editModeProps$inputP === void 0 ? void 0 : _editModeProps$inputP.inputRef]);
var _useState = useState(false || startWithEditOpen),
_useState2 = _slicedToArray(_useState, 2),
isEditing = _useState2[0],
setIsEditing = _useState2[1];
var _useState3 = useState(defaultValue),
_useState4 = _slicedToArray(_useState3, 2),
editModeValue = _useState4[0],
setEditModeValue = _useState4[1];
// readModeValue accepts controlledValue here to provide a reliable backup for the onCancel callback
var _useState5 = useState(controlledValue || defaultValue),
_useState6 = _slicedToArray(_useState5, 2),
readModeValue = _useState6[0],
setReadModeValue = _useState6[1];
var value = useMemo(function () {
if (controlledValue) {
return controlledValue;
} else {
return isEditing ? editModeValue : readModeValue || placeholder;
}
}, [controlledValue, editModeValue, readModeValue, isEditing, placeholder]);
var readModeStyles = useEuiMemoizedStyles(euiInlineEditReadModeStyles);
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 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
var onSaveReturn, awaitedReturn;
return _regeneratorRuntime.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 keys.ENTER:
event.preventDefault(); // Enter keypresses will not proceed otherwise on webkit browsers & screen readers
saveInlineEditValue();
break;
case keys.ESCAPE:
cancelInlineEdit();
break;
}
};
// If the state of isReadOnly changes while in edit mode, switch back to read mode
useEffect(function () {
if (isReadOnly) {
setIsEditing(false);
}
}, [isReadOnly]);
var editModeForm = ___EmotionJSX(EuiFlexGroup, {
gutterSize: "s",
responsive: false
}, ___EmotionJSX(EuiFlexItem, null, ___EmotionJSX(EuiFormRow, _extends({
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), ___EmotionJSX(EuiFieldText, _extends({
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": classNames(editModeDescribedById, editModeProps === null || editModeProps === void 0 || (_editModeProps$inputP6 = editModeProps.inputProps) === null || _editModeProps$inputP6 === void 0 ? void 0 : _editModeProps$inputP6['aria-describedby'])
}))), ___EmotionJSX("span", {
id: editModeDescribedById,
hidden: true
}, ___EmotionJSX(EuiI18n, {
token: "euiInlineEditForm.inputKeyboardInstructions",
default: "Press Enter to save your edited text. Press Escape to cancel your edit."
}))), ___EmotionJSX(EuiFlexItem, {
grow: false
}, ___EmotionJSX(EuiSkeletonLoading, {
isLoading: isLoading,
announceLoadingStatus: true,
announceLoadedStatus: false,
loadingContent: ___EmotionJSX(EuiFlexGroup, {
gutterSize: "s"
}, ___EmotionJSX(EuiSkeletonRectangle, {
height: loadingSkeletonSize,
width: loadingSkeletonSize,
borderRadius: "m"
}), ___EmotionJSX(EuiSkeletonRectangle, {
height: loadingSkeletonSize,
width: loadingSkeletonSize,
borderRadius: "m"
})),
loadedContent: ___EmotionJSX(EuiFlexGroup, {
gutterSize: "s"
}, ___EmotionJSX(EuiButtonIcon, _extends({
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);
}
})), ___EmotionJSX(EuiButtonIcon, _extends({
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 = ___EmotionJSX(React.Fragment, null, ___EmotionJSX(EuiButtonEmpty, _extends({
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": classNames(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)), ___EmotionJSX("span", {
id: readModeDescribedById,
hidden: true
}, !isReadOnly && ___EmotionJSX(EuiI18n, {
token: "euiInlineEditForm.activateEditModeDescription",
default: "Click to edit this text inline."
})));
return ___EmotionJSX("div", _extends({
className: classes
}, rest), isEditing ? editModeForm : readModeElement);
};