@awsui/components-react
Version:
AWS UI is a collection of [React](https://reactjs.org/) components that help create intuitive, responsive, and accessible user experiences for web applications. It is developed by Amazon Web Services (AWS). This work is available under the terms of the [A
121 lines (120 loc) • 10.6 kB
JavaScript
import { __assign, __rest } from "tslib";
import clsx from 'clsx';
import React, { useImperativeHandle, useRef } from 'react';
import Container from '../container/internal';
import { getBaseProps } from '../internal/base-component';
import ToolsHeader from './tools-header';
import Thead from './thead';
import StatusIndicator from '../status-indicator';
import { useContainerQuery } from '../internal/hooks/container-queries';
import { useTelemetry } from '../internal/hooks/use-telemetry';
import { supportsStickyPosition } from '../internal/utils/dom';
import SelectionControl from './selection-control';
import { getColumnKey, getItemKey } from './utils';
import { useRowEvents } from './use-row-events';
import { useFocusMove, useSelection, focusMarkers } from './use-selection';
import { useStickyHeader } from './use-sticky-header';
import { fireNonCancelableEvent } from '../internal/events';
import { isDevelopment } from '../internal/is-development';
import { useStickyScrollbar } from './use-sticky-scrollbar';
import { checkColumnWidths, ColumnWidthsProvider, DEFAULT_WIDTH } from './use-column-widths';
import { useAppLayoutContext } from '../internal/context/app-layout-context';
import { useScrollSync } from '../internal/hooks/use-scroll-sync';
import { ResizeTracker } from './resizer';
import styles from './styles.css.js';
var Table = React.forwardRef(function (_a, ref) {
var header = _a.header, footer = _a.footer, empty = _a.empty, filter = _a.filter, pagination = _a.pagination, preferences = _a.preferences, _b = _a.items, items = _b === void 0 ? [] : _b, columnDefinitions = _a.columnDefinitions, trackBy = _a.trackBy, loading = _a.loading, loadingText = _a.loadingText, selectionType = _a.selectionType, _c = _a.selectedItems, selectedItems = _c === void 0 ? [] : _c, isItemDisabled = _a.isItemDisabled, ariaLabels = _a.ariaLabels, onSelectionChange = _a.onSelectionChange, onSortingChange = _a.onSortingChange, sortingColumn = _a.sortingColumn, sortingDescending = _a.sortingDescending, sortingDisabled = _a.sortingDisabled, visibleColumns = _a.visibleColumns, stickyHeader = _a.stickyHeader, stickyHeaderVerticalOffset = _a.stickyHeaderVerticalOffset, onRowClick = _a.onRowClick, onRowContextMenu = _a.onRowContextMenu, wrapLines = _a.wrapLines, resizableColumns = _a.resizableColumns, onColumnWidthsChange = _a.onColumnWidthsChange, rest = __rest(_a, ["header", "footer", "empty", "filter", "pagination", "preferences", "items", "columnDefinitions", "trackBy", "loading", "loadingText", "selectionType", "selectedItems", "isItemDisabled", "ariaLabels", "onSelectionChange", "onSortingChange", "sortingColumn", "sortingDescending", "sortingDisabled", "visibleColumns", "stickyHeader", "stickyHeaderVerticalOffset", "onRowClick", "onRowContextMenu", "wrapLines", "resizableColumns", "onColumnWidthsChange"]);
useTelemetry('Table');
var _d = useContainerQuery(function (rect) { return rect.width; }), containerWidth = _d[0], wrapperRef = _d[1];
var baseProps = getBaseProps(rest);
var _e = useFocusMove(selectionType, items.length), moveFocusDown = _e.moveFocusDown, moveFocusUp = _e.moveFocusUp, moveFocus = _e.moveFocus;
var _f = useRowEvents({ onRowClick: onRowClick, onRowContextMenu: onRowContextMenu }), onRowClickHandler = _f.onRowClickHandler, onRowContextMenuHandler = _f.onRowContextMenuHandler;
var visibleColumnDefinitions = visibleColumns
? columnDefinitions.filter(function (column) { return column.id && visibleColumns.indexOf(column.id) !== -1; })
: columnDefinitions;
var _g = useSelection({
items: items,
trackBy: trackBy,
selectedItems: selectedItems,
selectionType: selectionType,
isItemDisabled: isItemDisabled,
onSelectionChange: onSelectionChange,
ariaLabels: ariaLabels
}), isItemSelected = _g.isItemSelected, selectAllProps = _g.selectAllProps, getItemSelectionProps = _g.getItemSelectionProps, updateShiftToggle = _g.updateShiftToggle;
if (loading) {
selectAllProps.disabled = true;
}
stickyHeader = stickyHeader && supportsStickyPosition();
var theadRef = useRef(null);
var secondaryTheadRef = useRef(null);
var secondaryTableRef = useRef(null);
var secondaryWrapperRef = useRef(null);
var _h = useStickyHeader(theadRef, secondaryTheadRef, secondaryTableRef, wrapperRef, stickyHeader), scrollToRow = _h.scrollToRow, scrollToTop = _h.scrollToTop;
useImperativeHandle(ref, function () { return ({ scrollToTop: scrollToTop }); });
var scrollbarRef = React.useRef(null);
var scrollbarContentRef = React.useRef(null);
var tableRef = React.useRef(null);
var stickyOffsetBottom = useAppLayoutContext().stickyOffsetBottom;
useStickyScrollbar(scrollbarRef, scrollbarContentRef, tableRef, wrapperRef, stickyOffsetBottom);
useScrollSync([wrapperRef, scrollbarRef, secondaryWrapperRef], !supportsStickyPosition());
if (isDevelopment && resizableColumns) {
checkColumnWidths(columnDefinitions);
}
var theadProps = {
containerWidth: containerWidth,
selectionType: selectionType,
selectAllProps: selectAllProps,
columnDefinitions: visibleColumnDefinitions,
wrapLines: wrapLines,
resizableColumns: resizableColumns,
sortingColumn: sortingColumn,
sortingDisabled: sortingDisabled,
sortingDescending: sortingDescending,
onSortingChange: onSortingChange,
onFocusMove: moveFocus,
onResizeFinish: function (newWidth) {
var widthsDetail = columnDefinitions.map(function (column, index) { return newWidth[getColumnKey(column, index)] || column.width || DEFAULT_WIDTH; });
var widthsChanged = widthsDetail.some(function (width, index) { return columnDefinitions[index].width !== width; });
if (widthsChanged) {
fireNonCancelableEvent(onColumnWidthsChange, { widths: widthsDetail });
}
}
};
return (React.createElement(ColumnWidthsProvider, { tableRef: tableRef, visibleColumnDefinitions: visibleColumnDefinitions, resizableColumns: resizableColumns, hasSelection: !!selectionType },
React.createElement(Container, __assign({}, baseProps, { className: clsx(baseProps.className, styles.root), header: React.createElement("div", null,
(header || filter || pagination || preferences) && (React.createElement("div", { className: styles['header-controls'] },
React.createElement(ToolsHeader, { header: header, filter: filter, pagination: pagination, preferences: preferences }))),
stickyHeader && (React.createElement("div", { className: styles['header-secondary'], ref: secondaryWrapperRef },
React.createElement("table", { "aria-hidden": true, className: clsx(styles.table, resizableColumns && styles['table-layout-fixed']), role: "table", ref: secondaryTableRef },
React.createElement(Thead, __assign({ ref: secondaryTheadRef, sticky: true }, theadProps)))))), disableHeaderPaddings: true, disableContentPaddings: true, footer: footer, __stickyHeader: stickyHeader, __stickyOffset: stickyHeaderVerticalOffset }, focusMarkers.root),
React.createElement("div", null,
React.createElement("div", { ref: wrapperRef, className: styles.wrapper },
React.createElement("table", { ref: tableRef, className: clsx(styles.table, resizableColumns && styles['table-layout-fixed']), role: "table" },
React.createElement(Thead, __assign({ ref: theadRef, hidden: stickyHeader }, theadProps)),
React.createElement("tbody", null, loading || items.length === 0 ? (React.createElement("tr", null,
React.createElement("td", { colSpan: selectionType ? visibleColumnDefinitions.length + 1 : visibleColumnDefinitions.length, className: styles['cell-merged'] },
React.createElement("div", { className: styles['cell-merged-content'], style: {
width: (supportsStickyPosition() && containerWidth && Math.floor(containerWidth)) || undefined
} }, loading ? (React.createElement(StatusIndicator, { type: "loading", className: styles.loading }, loadingText)) : (React.createElement("div", { className: styles.empty }, empty)))))) : (items.map(function (item, rowIndex) {
var _a;
var isSelected = selectionType && isItemSelected(item);
return (React.createElement("tr", __assign({ key: getItemKey(trackBy, item, rowIndex), className: clsx(styles.row, (_a = {},
_a[styles['row-selected']] = isSelected,
_a)), onFocus: function (_a) {
var currentTarget = _a.currentTarget;
return scrollToRow(currentTarget);
} }, focusMarkers.item, { onClick: onRowClickHandler && onRowClickHandler.bind(null, rowIndex, item), onContextMenu: onRowContextMenuHandler && onRowContextMenuHandler.bind(null, rowIndex, item) }),
selectionType !== undefined && (React.createElement(SelectionControl, __assign({ className: clsx(styles.cell, styles['body-cell'], styles['selection-control']), onFocusDown: moveFocusDown, onFocusUp: moveFocusUp, onShiftToggle: updateShiftToggle }, getItemSelectionProps(item)))),
visibleColumnDefinitions.map(function (column, colIndex) { return (React.createElement("td", { key: getColumnKey(column, colIndex), style: resizableColumns
? {}
: {
width: column.width,
minWidth: column.minWidth,
maxWidth: column.maxWidth
}, className: clsx(styles.cell, styles['body-cell'], wrapLines && styles['body-cell-wrap']) }, column.cell(item))); })));
})))),
resizableColumns && React.createElement(ResizeTracker, null)),
React.createElement("div", { ref: scrollbarRef, className: styles['sticky-scrollbar'] },
React.createElement("div", { ref: scrollbarContentRef, className: styles['sticky-scrollbar-content'] }))))));
});
export default Table;