Skip to content

Commit

Permalink
refactor: Componentizes table cell types and adds permutations
Browse files Browse the repository at this point in the history
  • Loading branch information
pan-kot committed Nov 15, 2024
1 parent 9ab7368 commit 972263b
Show file tree
Hide file tree
Showing 12 changed files with 681 additions and 96 deletions.
495 changes: 495 additions & 0 deletions pages/table/cell-permutations.page.tsx

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion src/table/body-cell/disabled-inline-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Portal from '../../internal/components/portal';
import { useSingleTabStopNavigation } from '../../internal/context/single-tab-stop-navigation-context';
import useHiddenDescription from '../../internal/hooks/use-hidden-description';
import { usePortalModeClasses } from '../../internal/hooks/use-portal-mode-classes';
import { useVisualRefresh } from '../../internal/hooks/use-visual-mode';
import InternalLiveRegion from '../../live-region/internal';
import Arrow from '../../popover/arrow';
import PopoverBody from '../../popover/body';
Expand All @@ -31,10 +32,10 @@ export function DisabledInlineEditor<ItemType>({
onEditStart,
onEditEnd,
editDisabledReason,
isVisualRefresh,
resizableColumns = false,
...rest
}: DisabledInlineEditorProps<ItemType>) {
const isVisualRefresh = useVisualRefresh();
const clickAwayRef = useClickAway(() => {
if (isEditing) {
onEditEnd(true);
Expand Down
8 changes: 4 additions & 4 deletions src/table/body-cell/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useInternalI18n } from '../../i18n/context';
import Icon from '../../icon/internal';
import { useSingleTabStopNavigation } from '../../internal/context/single-tab-stop-navigation-context.js';
import { usePrevious } from '../../internal/hooks/use-previous';
import { useVisualRefresh } from '../../internal/hooks/use-visual-mode';
import InternalLiveRegion from '../../live-region/internal';
import { TableProps } from '../interfaces';
import { DisabledInlineEditor } from './disabled-inline-editor';
Expand Down Expand Up @@ -40,12 +41,12 @@ function TableCellEditable<ItemType>({
onEditEnd,
submitEdit,
ariaLabels,
isVisualRefresh,
resizableColumns = false,
successfulEdit = false,
...rest
}: TableBodyCellProps<ItemType>) {
const i18n = useInternalI18n('table');
const isVisualRefresh = useVisualRefresh();
const editActivateRef = useRef<HTMLButtonElement>(null);
const tdNativeAttributes = {
'data-inline-editing-active': isEditing.toString(),
Expand Down Expand Up @@ -155,15 +156,14 @@ export function TableBodyCell<ItemType>({
isEditable,
...rest
}: TableBodyCellProps<ItemType> & { isEditable: boolean }) {
const isExpandableColumnCell = rest.level !== undefined;
const editDisabledReason = rest.column.editConfig?.disabledReason?.(rest.item);

// Inline editing is deactivated for expandable column because editable cells are interactive
// and cannot include interactive content such as expand toggles.
if (editDisabledReason && !isExpandableColumnCell) {
if (editDisabledReason) {
return <DisabledInlineEditor editDisabledReason={editDisabledReason} {...rest} />;
}
if ((isEditable || rest.isEditing) && !isExpandableColumnCell) {
if (isEditable || rest.isEditing) {
return <TableCellEditable {...rest} />;
}

Expand Down
4 changes: 2 additions & 2 deletions src/table/body-cell/td-element.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { copyAnalyticsMetadataAttribute } from '@cloudscape-design/component-too

import { useSingleTabStopNavigation } from '../../internal/context/single-tab-stop-navigation-context';
import { useMergeRefs } from '../../internal/hooks/use-merge-refs';
import { useVisualRefresh } from '../../internal/hooks/use-visual-mode';
import { ExpandToggleButton } from '../expandable-rows/expand-toggle-button';
import { TableProps } from '../interfaces.js';
import { StickyColumnsModel, useStickyCellStyles } from '../sticky-columns';
Expand Down Expand Up @@ -40,7 +41,6 @@ export interface TableTdElementProps {
columnId: PropertyKey;
colIndex: number;
stickyState: StickyColumnsModel;
isVisualRefresh?: boolean;
tableRole: TableRole;
level?: number;
isExpandable?: boolean;
Expand Down Expand Up @@ -70,7 +70,6 @@ export const TableTdElement = React.forwardRef<HTMLTableCellElement, TableTdElem
onMouseLeave,
isEvenRow,
stripedRows,
isVisualRefresh,
hasSelection,
hasFooter,
columnId,
Expand All @@ -89,6 +88,7 @@ export const TableTdElement = React.forwardRef<HTMLTableCellElement, TableTdElem
ref
) => {
const Element = isRowHeader ? 'th' : 'td';
const isVisualRefresh = useVisualRefresh();

nativeAttributes = { ...nativeAttributes, ...getTableCellRoleProps({ tableRole, isRowHeader, colIndex }) };

Expand Down
12 changes: 12 additions & 0 deletions src/table/header-cell/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ export interface TableHeaderCellProps<ItemType> {
sortingDescending?: boolean;
sortingDisabled?: boolean;
wrapLines?: boolean;
stuck?: boolean;
sticky?: boolean;
hidden?: boolean;
stripedRows?: boolean;
onClick(detail: TableProps.SortingState<any>): void;
onResizeFinish: () => void;
colIndex: number;
Expand All @@ -47,6 +50,7 @@ export interface TableHeaderCellProps<ItemType> {
resizerRoleDescription?: string;
isExpandable?: boolean;
hasDynamicContent?: boolean;
variant: TableProps.Variant;
}

export function TableHeaderCell<ItemType>({
Expand All @@ -59,7 +63,10 @@ export function TableHeaderCell<ItemType>({
sortingDisabled,
wrapLines,
focusedComponent,
stuck,
sticky,
hidden,
stripedRows,
onClick,
colIndex,
updateColumn,
Expand All @@ -73,6 +80,7 @@ export function TableHeaderCell<ItemType>({
resizerRoleDescription,
isExpandable,
hasDynamicContent,
variant,
}: TableHeaderCellProps<ItemType>) {
const i18n = useInternalI18n('table');
const sortable = !!column.sortingComparator || !!column.sortingField;
Expand Down Expand Up @@ -120,11 +128,15 @@ export function TableHeaderCell<ItemType>({
sortingStatus={sortingStatus}
sortingDisabled={sortingDisabled}
focusedComponent={focusedComponent}
stuck={stuck}
sticky={sticky}
hidden={hidden}
stripedRows={stripedRows}
colIndex={colIndex}
columnId={columnId}
stickyState={stickyState}
tableRole={tableRole}
variant={variant}
{...(sortingDisabled
? {}
: getAnalyticsMetadataAttribute({
Expand Down
20 changes: 19 additions & 1 deletion src/table/header-cell/th-element.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,32 @@ import { copyAnalyticsMetadataAttribute } from '@cloudscape-design/component-too

import { useSingleTabStopNavigation } from '../../internal/context/single-tab-stop-navigation-context';
import { useMergeRefs } from '../../internal/hooks/use-merge-refs';
import { useVisualRefresh } from '../../internal/hooks/use-visual-mode';
import { TableProps } from '../interfaces';
import { StickyColumnsModel, useStickyCellStyles } from '../sticky-columns';
import { getTableColHeaderRoleProps, TableRole } from '../table-role';
import { getStickyClassNames } from '../utils';
import { SortingStatus } from './utils';

import styles from './styles.css.js';

interface TableThElementProps {
export interface TableThElementProps {
className?: string;
style?: React.CSSProperties;
sortingStatus?: SortingStatus;
sortingDisabled?: boolean;
focusedComponent?: null | string;
stuck?: boolean;
sticky?: boolean;
hidden?: boolean;
stripedRows?: boolean;
colIndex: number;
columnId: PropertyKey;
stickyState: StickyColumnsModel;
cellRef?: React.RefCallback<HTMLElement> | null;
tableRole: TableRole;
children: React.ReactNode;
variant: TableProps.Variant;
}

export function TableThElement({
Expand All @@ -35,15 +41,21 @@ export function TableThElement({
sortingStatus,
sortingDisabled,
focusedComponent,
stuck,
sticky,
hidden,
stripedRows,
colIndex,
columnId,
stickyState,
cellRef,
tableRole,
children,
variant,
...props
}: TableThElementProps) {
const isVisualRefresh = useVisualRefresh();

const stickyStyles = useStickyCellStyles({
stickyColumns: stickyState,
columnId,
Expand All @@ -58,6 +70,12 @@ export function TableThElement({
<th
data-focus-id={`header-${String(columnId)}`}
className={clsx(
styles['header-cell'],
styles[`header-cell-variant-${variant}`],
sticky && styles['header-cell-sticky'],
stuck && styles['header-cell-stuck'],
stripedRows && styles['has-striped-rows'],
isVisualRefresh && styles['is-visual-refresh'],
className,
{
[styles['header-cell-fake-focus']]: focusedComponent === `header-${String(columnId)}`,
Expand Down
60 changes: 21 additions & 39 deletions src/table/internal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ import { SomeRequired } from '../internal/types';
import InternalLiveRegion from '../live-region/internal';
import { GeneratedAnalyticsMetadataTableComponent } from './analytics-metadata/interfaces';
import { TableBodyCell } from './body-cell';
import { TableTdElement } from './body-cell/td-element';
import { checkColumnWidths } from './column-widths-utils';
import { useExpandableTableProps } from './expandable-rows/expandable-rows-utils';
import { TableForwardRefType, TableProps, TableRow } from './interfaces';
import { NoDataCell } from './no-data-cell';
import { ItemsLoader } from './progressive-loading/items-loader';
import { TableLoaderCell } from './progressive-loading/loader-cell';
import { useProgressiveLoadingProps } from './progressive-loading/progressive-loading-utils';
import { ResizeTracker } from './resizer';
import { focusMarkers, SelectionControl, useSelection, useSelectionFocusMove } from './selection';
import { focusMarkers, useSelection, useSelectionFocusMove } from './selection';
import { TableBodySelectionCell } from './selection/selection-cells';

Check failure on line 43 in src/table/internal.tsx

View workflow job for this annotation

GitHub Actions / build / build

Cannot find module './selection/selection-cells' or its corresponding type declarations.

Check failure on line 43 in src/table/internal.tsx

View workflow job for this annotation

GitHub Actions / dry-run / Build components

Cannot find module './selection/selection-cells' or its corresponding type declarations.
import { useStickyColumns } from './sticky-columns';
import StickyHeader, { StickyHeaderRef } from './sticky-header';
import { StickyScrollbar } from './sticky-scrollbar';
Expand Down Expand Up @@ -550,7 +550,6 @@ const InternalTable = React.forwardRef(
});
const getTableItemKey = (item: T) => getItemKey(trackBy, item, rowIndex);
const sharedCellProps = {
isVisualRefresh,
isFirstRow,
isLastRow,
isSelected: hasSelection && isRowSelected(row),
Expand Down Expand Up @@ -584,21 +583,17 @@ const InternalTable = React.forwardRef(
{...rowRoleProps}
>
{getItemSelectionProps && (
<TableTdElement
<TableBodySelectionCell
{...sharedCellProps}
className={styles['selection-control']}
wrapLines={false}
columnId={selectionColumnId}
colIndex={0}
>
<SelectionControl
onFocusDown={moveFocusDown}
onFocusUp={moveFocusUp}
{...getItemSelectionProps(row.item)}
rowIndex={rowIndex}
itemKey={`${getTableItemKey(row.item)}`}
/>
</TableTdElement>
selectionControlProps={{
...getItemSelectionProps(row.item),
onFocusDown: moveFocusDown,
onFocusUp: moveFocusUp,
rowIndex,
itemKey: `${getTableItemKey(row.item)}`,
}}
/>
)}

{visibleColumnDefinitions.map((column, colIndex) => {
Expand Down Expand Up @@ -667,37 +662,24 @@ const InternalTable = React.forwardRef(
{...rowRoleProps}
>
{getItemSelectionProps && (
<TableTdElement
{...sharedCellProps}
className={styles['selection-control']}
wrapLines={false}
columnId={selectionColumnId}
colIndex={0}
>
{null}
</TableTdElement>
<TableBodySelectionCell {...sharedCellProps} columnId={selectionColumnId} />
)}
{visibleColumnDefinitions.map((column, colIndex) => (
<TableTdElement
<TableLoaderCell
key={getColumnKey(column, colIndex)}
{...sharedCellProps}
wrapLines={false}
columnId={column.id ?? colIndex}
colIndex={colIndex + colIndexOffset}
isRowHeader={colIndex === 0}
level={row.level}
>
{colIndex === 0 ? (
<ItemsLoader
item={row.item}
loadingStatus={row.status}
renderLoaderPending={renderLoaderPending}
renderLoaderLoading={renderLoaderLoading}
renderLoaderError={renderLoaderError}
trackBy={trackBy}
/>
) : null}
</TableTdElement>
item={row.item}
loadingStatus={row.status}
renderLoaderPending={renderLoaderPending}
renderLoaderLoading={renderLoaderLoading}
renderLoaderError={renderLoaderError}
trackBy={trackBy}
/>
))}
</tr>
);
Expand Down
2 changes: 1 addition & 1 deletion src/table/no-data-cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import InternalStatusIndicator from '../status-indicator/internal';

import styles from './styles.css.js';

interface NoDataCellProps {
export interface NoDataCellProps {
totalColumnsCount: number;
hasFooter: boolean;
loading?: boolean;
Expand Down
2 changes: 1 addition & 1 deletion src/table/progressive-loading/items-loader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { applyTrackBy } from '../utils';

import styles from './styles.css.js';

interface ItemsLoaderProps<T> {
export interface ItemsLoaderProps<T> {
item: null | T;
loadingStatus: TableProps.LoadingStatus;
renderLoaderPending?: (detail: TableProps.RenderLoaderDetail<T>) => React.ReactNode;
Expand Down
34 changes: 34 additions & 0 deletions src/table/progressive-loading/loader-cell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import React from 'react';

import { TableTdElement, TableTdElementProps } from '../body-cell/td-element';
import { ItemsLoader, ItemsLoaderProps } from './items-loader';

export interface TableLoaderCellProps<ItemType> extends TableTdElementProps, ItemsLoaderProps<ItemType> {}

export function TableLoaderCell<ItemType>({
item,
loadingStatus,
renderLoaderPending,
renderLoaderLoading,
renderLoaderError,
trackBy,
...props
}: TableLoaderCellProps<ItemType>) {
return (
<TableTdElement {...props}>
{props.isRowHeader ? (
<ItemsLoader
item={item}
loadingStatus={loadingStatus}
renderLoaderPending={renderLoaderPending}
renderLoaderLoading={renderLoaderLoading}
renderLoaderError={renderLoaderError}
trackBy={trackBy}
/>
) : null}
</TableTdElement>
);
}
Loading

0 comments on commit 972263b

Please sign in to comment.