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

86 lines 4.72 kB
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 import React, { useLayoutEffect, useRef } from 'react'; import clsx from 'clsx'; import { getAnalyticsMetadataAttribute } from '@awsui/component-toolkit/internal/analytics-metadata'; import { useVisualRefresh } from '../../../internal/hooks/use-visual-mode'; import { getBaseProps } from '../../base-component'; import { getAnalyticsSelectActionMetadata } from './analytics-metadata/utils'; import analyticsSelectors from './analytics-metadata/styles.css.js'; import styles from './styles.css.js'; const SelectableItem = ({ children: content, ariaSelected, ariaChecked, selected, highlighted, disabled, hasBackground, isParent, isChild, isSelectAll, virtualPosition, padBottom, isNextSelected, isPreviousSelected, useInteractiveGroups, screenReaderContent, ariaPosinset, ariaSetsize, highlightType, value, sticky, afterHeader, withScrollbar, ...restProps }, ref) => { const isVisualRefresh = useVisualRefresh(); const { className, ...rest } = getBaseProps(restProps); const classNames = clsx(className, styles['selectable-item'], { [styles.selected]: selected, [styles.highlighted]: highlighted, [styles['has-background']]: hasBackground, [styles.parent]: isParent, [analyticsSelectors.parent]: isParent, [styles.child]: isChild, [styles['select-all']]: isSelectAll, [styles['is-keyboard']]: highlightType === 'keyboard', [styles.disabled]: disabled, [styles.virtual]: virtualPosition !== undefined && !sticky, [styles['pad-bottom']]: padBottom, [styles['next-item-selected']]: isNextSelected, [styles['previous-item-selected']]: isPreviousSelected, [styles.interactiveGroups]: useInteractiveGroups, [styles.sticky]: sticky, [styles['after-header']]: !!afterHeader, [styles['with-scrollbar']]: withScrollbar, [styles['visual-refresh']]: isVisualRefresh, }); const contentRef = useRef(null); const screenReaderContentRef = useRef(null); useLayoutEffect(() => { // the state of aria-hidden and announcement is not set back because NVDA+Firefox would announce // the item which lost highlight // set aria-hidden true when there is announcement content, so that screen reader still announce // meaningful content when navigate with screen reader cursor // imperatively update to avoid announcement made multiple times when content updates if (highlighted && screenReaderContent) { if (contentRef.current) { contentRef.current.setAttribute('aria-hidden', 'true'); } if (screenReaderContentRef.current) { screenReaderContentRef.current.textContent = screenReaderContent; } } }, [highlighted, screenReaderContent, contentRef, screenReaderContentRef]); const style = virtualPosition !== undefined ? { transform: `translateY(${virtualPosition}px)`, } : undefined; const a11yProperties = {}; if (isParent && ariaChecked === undefined) { a11yProperties.role = 'presentation'; } else { a11yProperties.role = 'option'; a11yProperties['aria-disabled'] = disabled; if (ariaSelected !== undefined) { a11yProperties['aria-selected'] = ariaSelected; } // Safari+VO needs aria-checked for multi-selection. Otherwise it only announces selected option even though another option is highlighted. if (ariaChecked !== undefined) { a11yProperties['aria-checked'] = ariaChecked; } if (ariaPosinset && ariaSetsize) { a11yProperties['aria-posinset'] = ariaPosinset; a11yProperties['aria-setsize'] = ariaSetsize; } if (restProps.ariaDescribedby) { a11yProperties['aria-describedby'] = restProps.ariaDescribedby; } } return (React.createElement("div", { className: classNames, style: style, ...a11yProperties, ...rest, ...(isParent || disabled ? {} : getAnalyticsMetadataAttribute(getAnalyticsSelectActionMetadata({ isChild, value, ...restProps }))) }, React.createElement("div", { className: clsx(styles['option-content'], analyticsSelectors['option-content']), ref: contentRef }, content), React.createElement("div", { className: styles['measure-strut'], ref: ref }), React.createElement("div", { className: styles['screenreader-content'], ref: screenReaderContentRef }))); }; export default React.forwardRef(SelectableItem); //# sourceMappingURL=index.js.map