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

84 lines 6.35 kB
import { __rest } from "tslib"; // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 import React, { useImperativeHandle, useRef, useState } from 'react'; import clsx from 'clsx'; import { InternalButton } from '../button/internal'; import { getBaseProps } from '../internal/base-component'; import { matchBreakpointMapping } from '../internal/breakpoints'; import { useContainerBreakpoints } from '../internal/hooks/container-queries'; import { useMergeRefs } from '../internal/hooks/use-merge-refs'; import { usePrevious } from '../internal/hooks/use-previous'; import { useUniqueId } from '../internal/hooks/use-unique-id'; import InternalLiveRegion from '../live-region/internal'; import { AdditionalInfo } from './additional-info'; import { gridDefaults } from './grid-defaults'; import { Row } from './row'; import { getGridTemplateColumns } from './utils'; import styles from './styles.css.js'; const InternalAttributeEditor = React.forwardRef((_a, ref) => { var { additionalInfo, disableAddButton, definition = [{}], gridLayout, items, isItemRemovable = () => true, empty, addButtonText, addButtonVariant = 'normal', removeButtonText, removeButtonAriaLabel, customRowActions, i18nStrings, onAddButtonClick, onRemoveButtonClick, __internalRootRef = null } = _a, props = __rest(_a, ["additionalInfo", "disableAddButton", "definition", "gridLayout", "items", "isItemRemovable", "empty", "addButtonText", "addButtonVariant", "removeButtonText", "removeButtonAriaLabel", "customRowActions", "i18nStrings", "onAddButtonClick", "onRemoveButtonClick", "__internalRootRef"]); const removeButtonRefs = useRef([]); const addButtonRef = useRef(null); const wasNonEmpty = useRef(false); const [removalAnnouncement, setRemovalAnnouncement] = useState(''); const baseProps = getBaseProps(props); const isEmpty = items && items.length === 0; wasNonEmpty.current = wasNonEmpty.current || !isEmpty; useImperativeHandle(ref, () => ({ focusRemoveButton(rowIndex) { var _a; (_a = removeButtonRefs.current[rowIndex]) === null || _a === void 0 ? void 0 : _a.focus(); }, focusAddButton() { var _a; (_a = addButtonRef.current) === null || _a === void 0 ? void 0 : _a.focus(); }, })); const additionalInfoId = useUniqueId('attribute-editor-info'); const infoAriaDescribedBy = additionalInfo ? additionalInfoId : undefined; const prevItemsLength = usePrevious(items.length); React.useEffect(() => { if (prevItemsLength && prevItemsLength > items.length && (i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.itemRemovedAriaLive)) { setRemovalAnnouncement(i18nStrings.itemRemovedAriaLive); } else { setRemovalAnnouncement(''); } // we only want to announce when the number of items decreases (i.e. when an item is removed) // eslint-disable-next-line react-hooks/exhaustive-deps }, [items, i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.itemRemovedAriaLive]); if (!gridLayout) { gridLayout = gridDefaults[definition.length]; if (!gridLayout) { console.warn('AttributeEditor', '`gridLayout` is required for more than 6 attributes. Cannot render.'); gridLayout = []; } } const gridLayoutBreakpoints = gridLayout.reduce((acc, layout) => (Object.assign(Object.assign({}, acc), { [layout.breakpoint || 'default']: layout })), {}); const [breakpoint, breakpointRef] = useContainerBreakpoints(Object.keys(gridLayoutBreakpoints)); const mergedRef = useMergeRefs(breakpointRef, __internalRootRef); const gridLayoutForBreakpoint = matchBreakpointMapping(gridLayoutBreakpoints, breakpoint || 'default'); if (!gridLayoutForBreakpoint) { console.warn('AttributeEditor', `No \`gridLayout\` entry found for breakpoint ${breakpoint}. Cannot render.`); return React.createElement("div", null); } const totalColumnsInLayout = gridLayoutForBreakpoint.rows.reduce((total, columns) => total + columns.length, 0); if (totalColumnsInLayout !== definition.length) { console.warn('AttributeEditor', `Incorrect number of columns in layout (${totalColumnsInLayout}) for definition (${definition.length}). Cannot render.`); return React.createElement("div", null); } return (React.createElement("div", Object.assign({}, baseProps, { ref: mergedRef, className: clsx(baseProps.className, styles.root), style: { gridTemplateColumns: getGridTemplateColumns(gridLayoutForBreakpoint) } }), isEmpty && React.createElement("div", { className: clsx(styles.empty, wasNonEmpty.current && styles['empty-appear']) }, empty), items.map((item, index) => (React.createElement(Row, { key: index, index: index, breakpoint: breakpoint, layout: gridLayoutForBreakpoint, item: item, definition: definition, i18nStrings: i18nStrings, removable: isItemRemovable(item), removeButtonText: removeButtonText, removeButtonRefs: removeButtonRefs.current, customRowActions: customRowActions, onRemoveButtonClick: onRemoveButtonClick, removeButtonAriaLabel: removeButtonAriaLabel }))), React.createElement("div", { className: styles['add-row'] }, React.createElement(InternalButton, { className: styles['add-button'], disabled: disableAddButton, // Using aria-disabled="true" and tabindex="-1" instead of "disabled" // because focus can be dynamically moved to this button by calling // `focusAddButton()` on the ref. __nativeAttributes: disableAddButton ? { tabIndex: -1 } : {}, __focusable: true, onClick: onAddButtonClick, formAction: "none", ref: addButtonRef, ariaDescribedby: infoAriaDescribedBy, variant: addButtonVariant, iconName: addButtonVariant === 'inline-link' ? 'add-plus' : undefined }, addButtonText), React.createElement(InternalLiveRegion, { "data-testid": "removal-announcement", tagName: "span", hidden: true, delay: 5, key: items.length }, removalAnnouncement), !!additionalInfo && React.createElement(AdditionalInfo, { id: infoAriaDescribedBy }, additionalInfo)))); }); export default InternalAttributeEditor; //# sourceMappingURL=internal.js.map