@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
98 lines • 6.68 kB
JavaScript
import { __awaiter } from "tslib";
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React, { useEffect, useRef, useState } from 'react';
import { useCollection } from '@awsui/collection-hooks';
import { useStableCallback } from '@awsui/component-toolkit/internal';
import { InternalButton } from '../../button/internal';
import InternalHeader from '../../header/internal';
import useForwardFocus from '../../internal/hooks/forward-focus';
import formatDateLocalized from '../../internal/utils/date-time/format-date-localized';
import InternalLiveRegion from '../../live-region/internal';
import InternalPagination from '../../pagination/internal';
import InternalSpaceBetween from '../../space-between/internal';
import InternalTable from '../../table/internal';
import InternalTextFilter from '../../text-filter/internal';
import { EmptyState } from './empty-state';
import styles from './styles.css.js';
export function getSharedI18Strings(i18n, i18nStrings) {
return {
filteringCounterText: i18n('i18nStrings.filteringCounterText', i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.filteringCounterText, format => count => format({ count })),
labelRefresh: i18n('i18nStrings.labelRefresh', i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.labelRefresh),
labelsPagination: i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.labelsPagination,
noMatchTitle: i18n('i18nStrings.filteringNoMatches', i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.filteringNoMatches),
noMatchSubtitle: i18n('i18nStrings.filteringCantFindMatch', i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.filteringCantFindMatch),
clearFilterButtonText: i18n('i18nStrings.clearFilterButtonText', i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.clearFilterButtonText),
filteringClearAriaLabel: i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.labelClearFilter,
lastUpdatedText: i18n('i18nStrings.modalLastUpdatedText', i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.modalLastUpdatedText),
};
}
export function BasicS3Table({ forwardFocusRef, columnDefinitions, fetchData, trackBy, i18nStrings = {}, isVisualRefresh, visibleColumns, isItemDisabled, onSelect, }) {
var _a;
const [loading, setLoading] = useState(false);
const [allItems, setAllItems] = useState([]);
const [lastUpdated, setLastUpdated] = useState();
const textFilterRef = useRef(null);
const onSelectLatest = useStableCallback(onSelect);
function loadData() {
setLoading(true);
return fetchData()
.then(items => {
setAllItems(items);
setLoading(false);
})
.catch(() => {
// error handling should happen on the customer side, outside of this component
setLoading(false);
});
}
function reloadData() {
return __awaiter(this, void 0, void 0, function* () {
yield loadData();
setLastUpdated(new Date());
});
}
useEffect(() => {
loadData();
// Data loading is only happening on initial render, or via refresh button
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useForwardFocus(forwardFocusRef, textFilterRef);
const { items, filteredItemsCount, collectionProps, filterProps, paginationProps, actions } = useCollection(allItems, {
selection: { trackBy },
filtering: {
empty: i18nStrings.emptyText,
noMatch: (React.createElement(EmptyState, { title: i18nStrings.noMatchTitle, subtitle: i18nStrings.noMatchSubtitle, action: React.createElement(InternalButton, { onClick: () => actions.setFiltering('') }, i18nStrings.clearFilterButtonText) })),
},
pagination: {},
sorting: {},
});
const selectedItem = (_a = collectionProps.selectedItems) === null || _a === void 0 ? void 0 : _a[0];
// selectedItem can change internally inside the hook after pagination or filtering
// useEffect will capture all possible changes
useEffect(() => {
onSelectLatest(selectedItem);
}, [selectedItem, onSelectLatest]);
return (React.createElement(InternalTable, Object.assign({ variant: isVisualRefresh ? 'borderless' : 'container' }, collectionProps, { header: React.createElement(InternalHeader, { variant: isVisualRefresh ? 'h3' : 'h2', headingTagOverride: 'h3', actions: React.createElement(InternalHeaderActions, { reloadData: reloadData, i18nStrings: i18nStrings, lastUpdated: lastUpdated }), counter: selectedItem ? `(1/${allItems.length})` : `(${allItems.length})` }, i18nStrings.header), trackBy: trackBy, filter: React.createElement(InternalTextFilter, Object.assign({}, filterProps, { ref: textFilterRef, filteringAriaLabel: i18nStrings.filteringAriaLabel, filteringClearAriaLabel: i18nStrings.filteringClearAriaLabel, filteringPlaceholder: i18nStrings.filteringPlaceholder, countText: i18nStrings.filteringCounterText ? i18nStrings.filteringCounterText(filteredItemsCount) : '' })), pagination: React.createElement(InternalPagination, Object.assign({}, paginationProps, { ariaLabels: i18nStrings.labelsPagination })), selectionType: "single", ariaLabels: i18nStrings.selectionLabels, loading: loading, loadingText: i18nStrings.loadingText, items: items, visibleColumns: visibleColumns, isItemDisabled: isItemDisabled, columnDefinitions: columnDefinitions, enableKeyboardNavigation: true })));
}
function InternalHeaderActions({ i18nStrings, reloadData, lastUpdated }) {
function getLastUpdated() {
if (!lastUpdated || !i18nStrings.lastUpdatedText) {
return null;
}
const formattedDate = formatDateLocalized({
date: lastUpdated.toString(),
isDateOnly: false,
isMonthOnly: false,
});
return (React.createElement("div", { className: styles['last-updated-caption'] },
i18nStrings.lastUpdatedText,
React.createElement("br", null),
formattedDate,
React.createElement(InternalLiveRegion, { tagName: "span", sources: [i18nStrings.lastUpdatedText, formattedDate] })));
}
return (React.createElement(InternalSpaceBetween, { size: "s", direction: "horizontal", alignItems: "center" },
getLastUpdated(),
React.createElement(InternalButton, { iconName: "refresh", ariaLabel: i18nStrings.labelRefresh, onClick: reloadData })));
}
//# sourceMappingURL=basic-table.js.map