UNPKG

@awsui/components-react

Version:

On July 19th, 2022, we launched [Cloudscape Design System](https://cloudscape.design). Cloudscape is an evolution of AWS-UI. It consists of user interface guidelines, front-end components, design resources, and development tools for building intuitive, en

81 lines 5.8 kB
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 import React, { useEffect, useRef, useState } from 'react'; import clsx from 'clsx'; import { useSingleTabStopNavigation } from '@awsui/component-toolkit/internal'; import { useInternalI18n } from '../../i18n/context'; import Icon from '../../icon/internal'; import { usePrevious } from '../../internal/hooks/use-previous'; import InternalLiveRegion from '../../live-region/internal'; import { DisabledInlineEditor } from './disabled-inline-editor'; import { InlineEditor } from './inline-editor'; import { TableTdElement } from './td-element'; import styles from './styles.css.js'; const submitHandlerFallback = () => { throw new Error('The function `handleSubmit` is required for editable columns'); }; function TableCellEditable({ item, column, isEditing, onEditStart, onEditEnd, submitEdit, ariaLabels, successfulEdit = false, ...rest }) { var _a, _b, _c; const i18n = useInternalI18n('table'); const editActivateRef = useRef(null); const tdNativeAttributes = { 'data-inline-editing-active': isEditing.toString(), }; const isFocusMoveNeededRef = useRef(false); const isExpandableColumn = rest.level !== undefined; useEffect(() => { if (!isEditing && editActivateRef.current && isFocusMoveNeededRef.current) { isFocusMoveNeededRef.current = false; editActivateRef.current.focus(); } }, [isEditing]); // To improve the initial page render performance we only show the edit icon when necessary. const [hasFocus, setHasFocus] = useState(false); const prevSuccessfulEdit = usePrevious(successfulEdit); const prevHasFocus = usePrevious(hasFocus); const [showSuccessIcon, setShowSuccessIcon] = useState(false); useEffect(() => { // Hide the success icon after a successful edit, when cell loses focus. if (successfulEdit && prevSuccessfulEdit && !hasFocus && prevHasFocus) { setShowSuccessIcon(false); } // Show success icon right after a successful edit, when `successfulEdit` switches to true. if (successfulEdit && !prevSuccessfulEdit) { setShowSuccessIcon(true); } }, [hasFocus, successfulEdit, prevHasFocus, prevSuccessfulEdit]); const { tabIndex: editActivateTabIndex } = useSingleTabStopNavigation(editActivateRef); return (React.createElement(TableTdElement, { ...rest, nativeAttributes: tdNativeAttributes, isEditing: isEditing, hasSuccessIcon: showSuccessIcon && hasFocus, onClick: !isEditing && !isExpandableColumn ? onEditStart : undefined, onFocus: () => setHasFocus(true), onBlur: () => setHasFocus(false) }, isEditing && column.editConfig ? (React.createElement(InlineEditor, { ariaLabels: ariaLabels, column: column, item: item, onEditEnd: options => { setShowSuccessIcon(false); isFocusMoveNeededRef.current = options.refocusCell; onEditEnd(options.cancelled); }, submitEdit: submitEdit !== null && submitEdit !== void 0 ? submitEdit : submitHandlerFallback })) : (React.createElement(React.Fragment, null, column.cell(item), showSuccessIcon && hasFocus && (React.createElement(React.Fragment, null, React.createElement("span", { className: styles['body-cell-success'], onMouseDown: e => { // Prevent the editor's Button blur event to be fired when clicking the success icon. // This prevents unfocusing the button and triggers the `TableTdElement` onClick event which initiates the edit mode. e.preventDefault(); } }, React.createElement(Icon, { name: "status-positive", variant: "success", ariaLabel: (_a = ariaLabels === null || ariaLabels === void 0 ? void 0 : ariaLabels.successfulEditLabel) === null || _a === void 0 ? void 0 : _a.call(ariaLabels, column) })), React.createElement(InternalLiveRegion, { tagName: "span", hidden: true }, i18n('ariaLabels.successfulEditLabel', (_b = ariaLabels === null || ariaLabels === void 0 ? void 0 : ariaLabels.successfulEditLabel) === null || _b === void 0 ? void 0 : _b.call(ariaLabels, column))))), React.createElement("div", { className: styles['body-cell-editor-wrapper'] }, React.createElement("button", { className: clsx(styles['body-cell-editor'], isExpandableColumn && styles['body-cell-editor-focusable']), "aria-label": (_c = ariaLabels === null || ariaLabels === void 0 ? void 0 : ariaLabels.activateEditLabel) === null || _c === void 0 ? void 0 : _c.call(ariaLabels, column, item), ref: editActivateRef, onClick: !isEditing && isExpandableColumn ? onEditStart : undefined, tabIndex: editActivateTabIndex }, React.createElement("span", { className: styles['body-cell-editor-icon'] }, React.createElement(Icon, { name: "edit" })))))))); } export function TableBodyCell(props) { var _a, _b; const editDisabledReason = (_b = (_a = props.column.editConfig) === null || _a === void 0 ? void 0 : _a.disabledReason) === null || _b === void 0 ? void 0 : _b.call(_a, props.item); // Inline editing is deactivated for expandable column because editable cells are interactive // and cannot include interactive content such as expand toggles. if (editDisabledReason) { return React.createElement(DisabledInlineEditor, { editDisabledReason: editDisabledReason, ...props }); } if (props.isEditable || props.isEditing) { return React.createElement(TableCellEditable, { ...props }); } const { column, item } = props; return (React.createElement(TableTdElement, { ...props, isEditable: false }, column.cell(item))); } //# sourceMappingURL=index.js.map