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

122 lines • 8.8 kB
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 import React, { useEffect, useImperativeHandle, useRef, useState } from 'react'; import clsx from 'clsx'; import { useMergeRefs } from '@awsui/component-toolkit/internal'; import { getAnalyticsMetadataAttribute } from '@awsui/component-toolkit/internal/analytics-metadata'; import { InternalButton } from '../button/internal'; import { useInternalI18n } from '../i18n/context'; import InternalIcon from '../icon/internal'; import { DATA_ATTR_ANALYTICS_ALERT } from '../internal/analytics/selectors'; import { getBaseProps } from '../internal/base-component'; import VisualContext from '../internal/components/visual-context'; import { LinkDefaultVariantContext } from '../internal/context/link-default-variant-context'; import { fireNonCancelableEvent } from '../internal/events'; import { useVisualRefresh } from '../internal/hooks/use-visual-mode'; import { persistAlertDismiss, retrieveAlertDismiss } from '../internal/persistence'; import { awsuiPluginsInternal } from '../internal/plugins/api'; import { createUseDiscoveredAction, createUseDiscoveredContent } from '../internal/plugins/helpers'; import useContainerWidth from '../internal/utils/use-container-width'; import { ActionsWrapper } from './actions-wrapper'; import { getAlertStyles, getDismissButtonStyles, getIconStyles } from './style'; import analyticsSelectors from './analytics-metadata/styles.css.js'; import styles from './styles.css.js'; const typeToIcon = { error: 'status-negative', warning: 'status-warning', success: 'status-positive', info: 'status-info', }; const useDiscoveredAction = createUseDiscoveredAction(awsuiPluginsInternal.alert.onActionRegistered); const useDiscoveredContent = createUseDiscoveredContent('alert', awsuiPluginsInternal.alertContent); const InternalAlert = React.forwardRef(({ type, i18nStrings, visible = true, dismissible, children, header, buttonText, action, onDismiss, onButtonClick, __internalRootRef, statusIconAriaLabel: deprecatedStatusIconAriaLabel, dismissAriaLabel: deprecatedDismissAriaLabel, messageSlotId, style, persistenceConfig, ...rest }, ref) => { var _a, _b; const baseProps = getBaseProps(rest); const i18n = useInternalI18n('alert'); const focusRef = useRef(null); useImperativeHandle(ref, () => ({ focus: () => { if (focusRef.current) { focusRef.current.tabIndex = -1; focusRef.current.focus(); } }, })); const handleBlur = () => { if (focusRef.current) { focusRef.current.removeAttribute('tabindex'); } }; const { discoveredActions, headerRef: headerRefAction, contentRef: contentRefAction } = useDiscoveredAction(type); const { initialHidden, headerReplacementType, contentReplacementType, headerRef: headerRefContent, contentRef: contentRefContent, replacementHeaderRef, replacementContentRef, } = useDiscoveredContent({ type, header, children }); const [containerWidth, containerMeasureRef] = useContainerWidth(); const containerRef = useMergeRefs(containerMeasureRef, __internalRootRef); const headerRef = useMergeRefs(headerRefAction, headerRefContent); const contentRef = useMergeRefs(contentRefAction, contentRefContent); const [isPersistentlyDismissed, setIsPersistentlyDismissed] = useState(!!(persistenceConfig && persistenceConfig.uniqueKey)); const isRefresh = useVisualRefresh(); const size = isRefresh ? 'normal' : headerReplacementType !== 'remove' && header && contentReplacementType !== 'remove' && children ? 'big' : 'normal'; const hasAction = Boolean(action || buttonText || discoveredActions.length); const analyticsAttributes = { [DATA_ATTR_ANALYTICS_ALERT]: type, }; const statusIconAriaLabel = i18n(`i18nStrings.${type}IconAriaLabel`, (_a = i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings[`${type}IconAriaLabel`]) !== null && _a !== void 0 ? _a : deprecatedStatusIconAriaLabel); const dismissAriaLabel = i18n('i18nStrings.dismissAriaLabel', (_b = i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.dismissAriaLabel) !== null && _b !== void 0 ? _b : i18n('dismissAriaLabel', deprecatedDismissAriaLabel)); useEffect(() => { let isMounted = true; if (persistenceConfig === null || persistenceConfig === void 0 ? void 0 : persistenceConfig.uniqueKey) { retrieveAlertDismiss(persistenceConfig) .then(dismissed => { if (isMounted) { setIsPersistentlyDismissed(!!dismissed); } }) .catch(() => { if (isMounted) { setIsPersistentlyDismissed(false); } }); } return () => { isMounted = false; }; // Only track specific properties to avoid re-running when persistenceConfig object reference changes // eslint-disable-next-line react-hooks/exhaustive-deps }, [persistenceConfig === null || persistenceConfig === void 0 ? void 0 : persistenceConfig.uniqueKey, persistenceConfig === null || persistenceConfig === void 0 ? void 0 : persistenceConfig.crossServicePersistence]); const dismiss = () => { fireNonCancelableEvent(onDismiss); if (persistenceConfig === null || persistenceConfig === void 0 ? void 0 : persistenceConfig.uniqueKey) { persistAlertDismiss(persistenceConfig); } }; if (isPersistentlyDismissed) { return null; } return (React.createElement("div", { ...baseProps, ...analyticsAttributes, "aria-hidden": !visible, className: clsx(styles.root, { [styles.hidden]: !visible, [styles['initial-hidden']]: initialHidden }, baseProps.className), ref: containerRef }, React.createElement(LinkDefaultVariantContext.Provider, { value: { defaultVariant: 'primary' } }, React.createElement(VisualContext, { contextName: "alert" }, React.createElement("div", { className: clsx(styles.alert, styles[`type-${type}`], styles[`icon-size-${size}`], hasAction && styles['with-action'], dismissible && styles['with-dismiss']), style: getAlertStyles(style) }, React.createElement("div", { className: styles['alert-wrapper'] }, React.createElement("div", { className: styles['alert-focus-wrapper'], ref: focusRef, role: "group", onBlur: handleBlur }, React.createElement("div", { className: clsx(styles.icon, styles.text), style: getIconStyles(style) }, React.createElement(InternalIcon, { name: typeToIcon[type], size: size, ariaLabel: statusIconAriaLabel })), React.createElement("div", { className: clsx(styles.message, styles.text), id: messageSlotId }, React.createElement("div", { className: clsx(header && styles.header, headerReplacementType !== 'original' ? styles.hidden : analyticsSelectors.header), ref: headerRef }, header), React.createElement("div", { className: clsx(styles['header-replacement'], headerReplacementType !== 'replaced' ? styles.hidden : analyticsSelectors.header), ref: replacementHeaderRef }), React.createElement("div", { className: clsx(styles.content, contentReplacementType !== 'original' && styles.hidden), ref: contentRef }, children), React.createElement("div", { className: clsx(styles['content-replacement'], contentReplacementType !== 'replaced' && styles.hidden), ref: replacementContentRef }))), React.createElement(ActionsWrapper, { className: styles.action, testUtilClasses: { actionSlot: styles['action-slot'], actionButton: styles['action-button'], }, action: action, discoveredActions: discoveredActions, buttonText: buttonText, onButtonClick: () => fireNonCancelableEvent(onButtonClick), containerWidth: containerWidth, wrappedClass: styles['action-wrapped'] })), dismissible && (React.createElement("div", { className: styles.dismiss, ...getAnalyticsMetadataAttribute({ action: 'dismiss', }) }, React.createElement(InternalButton, { className: styles['dismiss-button'], variant: "icon", iconName: "close", formAction: "none", ariaLabel: dismissAriaLabel, onClick: dismiss, style: getDismissButtonStyles(style) })))))))); }); export default InternalAlert; //# sourceMappingURL=internal.js.map