@ui5/webcomponents-react
Version:
React Wrapper for UI5 Web Components and additional components
149 lines • 6.02 kB
JavaScript
import { AnalyticalTablePopinDisplay } from '../../../enums/AnalyticalTablePopinDisplay.js';
import { AnalyticalTableSelectionBehavior } from '../../../enums/AnalyticalTableSelectionBehavior.js';
import { AnalyticalTableSelectionMode } from '../../../enums/AnalyticalTableSelectionMode.js';
const setCellProps = (cellProps, {
cell,
instance
}) => {
const {
column,
row,
value
} = cell;
const columnIndex = instance.visibleColumns.findIndex(({
id
}) => id === column.id);
const {
alwaysShowSubComponent,
renderRowSubComponent,
selectionMode,
selectionBehavior,
a11yElementIds,
uniqueId,
canUseVoiceOver
} = instance.webComponentsReactProperties;
const updatedCellProps = {
// aria index is 1 based, not 0
'aria-colindex': columnIndex + 1,
role: 'gridcell',
// header label
'aria-labelledby': `${uniqueId}${column.id}${row.id}` + (canUseVoiceOver ? ` ${uniqueId}${column.id}` : '')
};
const RowSubComponent = typeof renderRowSubComponent === 'function' ? renderRowSubComponent(row) : undefined;
const rowIsExpandable = row.canExpand || RowSubComponent && !alwaysShowSubComponent;
const userCols = instance.visibleColumns.filter(({
id
}) => id !== '__ui5wcr__internal_selection_column' && id !== '__ui5wcr__internal_highlight_column' && id !== '__ui5wcr__internal_navigation_column');
const isFirstUserCol = userCols[0]?.id === column.id || userCols[0]?.accessor === column.accessor;
updatedCellProps['data-is-first-column'] = isFirstUserCol;
const {
popInColumns
} = instance.state;
if (isFirstUserCol && popInColumns?.length && !row.isGrouped) {
if (canUseVoiceOver) {
// For VoiceOver: put column header before value for context when pop-in content follows
updatedCellProps['aria-labelledby'] = `${uniqueId}${column.id} ${uniqueId}${column.id}${row.id}`;
}
let popInLabelledBy = '';
for (const popInCol of popInColumns) {
if (popInCol.popinDisplay !== AnalyticalTablePopinDisplay.WithoutHeader && popInCol.column?.Header) {
popInLabelledBy += ` ${uniqueId}popin-h-${popInCol.id}-${row.id}`;
}
popInLabelledBy += ` ${uniqueId}popin-v-${popInCol.id}-${row.id}`;
}
updatedCellProps['aria-labelledby'] += popInLabelledBy;
}
if (isFirstUserCol && rowIsExpandable || row.isGrouped && row.canExpand) {
updatedCellProps.onKeyDown = row.getToggleRowExpandedProps?.()?.onKeyDown;
if (row.isExpanded) {
updatedCellProps['aria-expanded'] = 'true';
updatedCellProps['aria-describedby'] = ' ' + a11yElementIds.cellCollapseDescId;
} else {
updatedCellProps['aria-expanded'] = 'false';
updatedCellProps['aria-describedby'] = ' ' + a11yElementIds.cellExpandDescId;
}
} else if (selectionMode !== AnalyticalTableSelectionMode.None && selectionBehavior !== AnalyticalTableSelectionBehavior.RowSelector && !row.isGrouped || column.id === '__ui5wcr__internal_selection_column') {
if (row.isSelected) {
updatedCellProps['aria-selected'] = 'true';
updatedCellProps['aria-describedby'] = ' ' + a11yElementIds.cellUnselectDescId;
} else {
updatedCellProps['aria-selected'] = 'false';
updatedCellProps['aria-describedby'] = ' ' + a11yElementIds.cellSelectDescId;
}
}
const {
cellLabel
} = cell.column;
if (typeof cellLabel === 'function') {
const cellHeaderLabel = column.headerLabel || (typeof column.Header === 'string' ? column.Header : '');
const cellValueLabel = value || value === 0 ? `${value} ` : '';
cell.cellLabel = `${cellHeaderLabel} ${cellValueLabel}`;
updatedCellProps['aria-label'] = cellLabel({
cell,
instance
});
updatedCellProps['aria-labelledby'] = undefined;
}
return [cellProps, updatedCellProps];
};
const setHeaderProps = (headerProps, {
column,
instance
}) => {
const {
translatableTexts,
selectionMode,
a11yElementIds
} = instance.webComponentsReactProperties;
if (!column) {
return headerProps;
}
const isFiltered = column?.filterValue && column?.filterValue.length > 0;
const updatedProps = {};
updatedProps['aria-label'] = column.headerLabel ??= '';
if (updatedProps['aria-label']) {
updatedProps['aria-label'] += ' ';
}
if (column.isSorted) {
updatedProps['aria-sort'] = column.isSortedDesc ? 'descending' : 'ascending';
}
if (isFiltered) {
updatedProps['aria-label'] += translatableTexts.filteredA11yText;
}
if (column.isGrouped) {
if (updatedProps['aria-label']) {
updatedProps['aria-label'] += ` ${translatableTexts.groupedA11yText}`;
} else {
updatedProps['aria-label'] += translatableTexts.groupedA11yText;
}
}
if (selectionMode === AnalyticalTableSelectionMode.Multiple && column.id === '__ui5wcr__internal_selection_column') {
// aria-describedby so body cells don't inherit it via aria-labelledby
updatedProps['aria-describedby'] = instance.isAllRowsSelected ? a11yElementIds.headerDeselectAllDescId : a11yElementIds.headerSelectAllDescId;
}
if (column.id === '__ui5wcr__internal_selection_column') {
updatedProps['aria-label'] += (updatedProps['aria-label'] ? ' ' : '') + translatableTexts.selectionHeaderCellText;
}
if (column.id === '__ui5wcr__internal_highlight_column') {
updatedProps['aria-label'] += (updatedProps['aria-label'] ? ' ' : '') + translatableTexts.highlightHeaderCellText;
}
if (column.id === '__ui5wcr__internal_navigation_column') {
updatedProps['aria-label'] += (updatedProps['aria-label'] ? ' ' : '') + translatableTexts.navigationHeaderCellText;
}
updatedProps['aria-label'] ||= undefined;
return [headerProps, {
isFiltered,
...updatedProps
}];
};
const setHeaderGroupProps = props => {
return [props, {
'aria-rowindex': 1
}];
};
export const useA11y = hooks => {
hooks.getCellProps.push(setCellProps);
hooks.getHeaderProps.push(setHeaderProps);
hooks.getHeaderGroupProps.push(setHeaderGroupProps);
};
useA11y.pluginName = 'useA11y';