@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
JavaScript
// 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