1 import * as React from 'react';
3 import { c, msgid } from 'ttag';
5 import { Checkbox, Icon, Loader, TableHeaderCell, TableRowSticky, Tooltip } from '@proton/components';
6 import { SORT_DIRECTION } from '@proton/shared/lib/constants';
7 import { getNumAccessesTooltipMessage } from '@proton/shared/lib/drive/translations';
8 import clsx from '@proton/utils/clsx';
10 import { stopPropagation } from '../../../utils/stopPropagation';
11 import { SelectionState } from '../hooks/useSelectionControls';
12 import type { SortParams } from '../interface';
13 import { useSelection } from '../state/useSelection';
16 scrollAreaRef: React.RefObject<HTMLDivElement>;
17 sortParams?: SortParams<T>;
20 onSort?: (params: SortParams<T>) => void;
22 isMultiSelectionDisabled?: boolean;
25 enum HeaderCellsPresets {
30 const HeaderCell = <T,>({
36 isMultiSelectionDisabled,
41 onSort: (key: T) => void;
42 sortParams?: SortParams<T>;
43 isMultiSelectionDisabled?: boolean;
45 const selection = useSelection();
46 const selectedCount = selection?.selectedItemIds.length;
47 if (item.type === HeaderCellsPresets.Checkbox && selection) {
49 <TableHeaderCell className="file-browser-header-checkbox-cell">
50 <div role="presentation" key="select-all" className="flex pl-2" onClick={stopPropagation}>
52 indeterminate={selection.selectionState === SelectionState.SOME}
53 className="expand-click-area mr-1"
55 checked={selection?.selectionState !== SelectionState.NONE}
57 selection?.selectionState === SelectionState.SOME
58 ? selection.clearSelections
59 : selection.toggleAllSelected
61 data-testid="checkbox-select-all"
63 {selectedCount && selection?.selectionState !== SelectionState.NONE ? (
64 <span className="ml-2">
66 msgid`${selectedCount} selected`,
67 `${selectedCount} selected`,
73 {selection?.selectionState !== SelectionState.NONE && isLoading ? (
74 <Loader className="flex shrink-0" />
81 if (!isMultiSelectionDisabled && selection?.selectionState !== SelectionState.NONE) {
85 if (item.type === HeaderCellsPresets.Placeholder) {
88 className={clsx(['file-browser-list--icon-column', item.props?.className])}
89 style={item.props.style}
94 const getSortDirectionForKey = (key: T) => (sortParams?.sortField === key ? sortParams.sortOrder : undefined);
98 className={item.props?.className}
99 direction={getSortDirectionForKey(item.type)}
100 onSort={item.sorting ? () => onSort?.(item.type) : undefined}
101 isLoading={isLoading && sortParams?.sortField === item.type}
102 data-testid="sort-by"
105 {item.type === 'numAccesses' && (
106 <Tooltip className="pl-1" title={getNumAccessesTooltipMessage()}>
107 <Icon name="info-circle" size={3.5} alt={getNumAccessesTooltipMessage()} />
114 const ListHeader = <T,>({
121 isMultiSelectionDisabled,
123 const handleSort = (key: T) => {
124 if (!sortParams || !onSort) {
129 sortParams.sortField === key && sortParams.sortOrder === SORT_DIRECTION.ASC
130 ? SORT_DIRECTION.DESC
131 : SORT_DIRECTION.ASC;
133 onSort({ sortField: key, sortOrder: direction });
137 <thead onContextMenu={(e) => e.stopPropagation()}>
138 <TableRowSticky scrollAreaRef={scrollAreaRef}>
139 {items.map((item, index) => (
142 isLoading={isLoading}
143 sortParams={sortParams}
145 itemCount={itemCount}
147 isMultiSelectionDisabled={isMultiSelectionDisabled}
155 export default ListHeader;