mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-22 02:11:29 +00:00
Implement ctrl-shift click to select multiple documents (#1851)
* Initial implementation of shift and ctrl click to select * Implement shift-ctrl selection * Fix snapshot, update selectionHelper comment * Fix missing type * Properly disable cursor selection * Update snapshots * Do not enable (multiselect) if readonly * Consider meta key for mac and ctrl for everything else
This commit is contained in:
@@ -22,6 +22,9 @@ import {
|
||||
useTableFeatures,
|
||||
useTableSelection,
|
||||
} from "@fluentui/react-components";
|
||||
import { NormalizedEventKey } from "Common/Constants";
|
||||
import { selectionHelper } from "Explorer/Tabs/DocumentsTabV2/SelectionHelper";
|
||||
import { isEnvironmentCtrlPressed, isEnvironmentShiftPressed } from "Utils/KeyboardUtils";
|
||||
import React, { useCallback, useEffect, useMemo } from "react";
|
||||
import { FixedSizeList as List, ListChildComponentProps } from "react-window";
|
||||
|
||||
@@ -123,17 +126,63 @@ export const DocumentsTableComponent: React.FC<IDocumentsTableComponentProps> =
|
||||
[columnHeaders],
|
||||
);
|
||||
|
||||
const onIdClicked = useCallback((index: number) => onSelectedRowsChange(new Set([index])), [onSelectedRowsChange]);
|
||||
const [selectionStartIndex, setSelectionStartIndex] = React.useState<number>(undefined);
|
||||
const onTableCellClicked = useCallback(
|
||||
(e: React.MouseEvent, index: number) => {
|
||||
if (isSelectionDisabled) {
|
||||
// Only allow click
|
||||
onSelectedRowsChange(new Set<TableRowId>([index]));
|
||||
setSelectionStartIndex(index);
|
||||
return;
|
||||
}
|
||||
|
||||
const result = selectionHelper(
|
||||
selectedRows as Set<number>,
|
||||
index,
|
||||
isEnvironmentShiftPressed(e),
|
||||
isEnvironmentCtrlPressed(e),
|
||||
selectionStartIndex,
|
||||
);
|
||||
onSelectedRowsChange(result.selection);
|
||||
if (result.selectionStartIndex !== undefined) {
|
||||
setSelectionStartIndex(result.selectionStartIndex);
|
||||
}
|
||||
},
|
||||
[isSelectionDisabled, selectedRows, selectionStartIndex, onSelectedRowsChange],
|
||||
);
|
||||
|
||||
/**
|
||||
* Callback for when:
|
||||
* - a key has been pressed on the cell
|
||||
* - a key is down and the cell is clicked by the mouse
|
||||
*/
|
||||
const onIdClicked = useCallback(
|
||||
(e: React.KeyboardEvent<Element>, index: number) => {
|
||||
if (e.key === NormalizedEventKey.Enter || e.key === NormalizedEventKey.Space) {
|
||||
onSelectedRowsChange(new Set<TableRowId>([index]));
|
||||
}
|
||||
},
|
||||
[onSelectedRowsChange],
|
||||
);
|
||||
|
||||
const RenderRow = ({ index, style, data }: ReactWindowRenderFnProps) => {
|
||||
const { item, selected, appearance, onClick, onKeyDown } = data[index];
|
||||
return (
|
||||
<TableRow aria-rowindex={index + 2} style={style} key={item.id} aria-selected={selected} appearance={appearance}>
|
||||
<TableRow
|
||||
aria-rowindex={index + 2}
|
||||
style={{ ...style, cursor: "pointer", userSelect: "none" }}
|
||||
key={item.id}
|
||||
aria-selected={selected}
|
||||
appearance={appearance}
|
||||
>
|
||||
{!isSelectionDisabled && (
|
||||
<TableSelectionCell
|
||||
checked={selected}
|
||||
checkboxIndicator={{ "aria-label": "Select row" }}
|
||||
onClick={onClick}
|
||||
onClick={(e: React.MouseEvent) => {
|
||||
setSelectionStartIndex(index);
|
||||
onClick(e);
|
||||
}}
|
||||
onKeyDown={onKeyDown}
|
||||
/>
|
||||
)}
|
||||
@@ -141,8 +190,9 @@ export const DocumentsTableComponent: React.FC<IDocumentsTableComponentProps> =
|
||||
<TableCell
|
||||
key={column.columnId}
|
||||
className="documentsTableCell"
|
||||
onClick={(/* e */) => onSelectedRowsChange(new Set<TableRowId>([index]))}
|
||||
onKeyDown={() => onIdClicked(index)}
|
||||
// When clicking on a cell with shift/ctrl key, onKeyDown is called instead of onClick.
|
||||
onClick={(e: React.MouseEvent<Element, MouseEvent>) => onTableCellClicked(e, index)}
|
||||
onKeyPress={(e: React.KeyboardEvent<Element>) => onIdClicked(e, index)}
|
||||
{...columnSizing.getTableCellProps(column.columnId)}
|
||||
tabIndex={column.columnId === "id" ? 0 : -1}
|
||||
>
|
||||
@@ -166,7 +216,7 @@ export const DocumentsTableComponent: React.FC<IDocumentsTableComponentProps> =
|
||||
[
|
||||
useTableColumnSizing_unstable({ columnSizingOptions, onColumnResize }),
|
||||
useTableSelection({
|
||||
selectionMode: "multiselect",
|
||||
selectionMode: isSelectionDisabled ? "single" : "multiselect",
|
||||
selectedItems: selectedRows,
|
||||
// eslint-disable-next-line react/prop-types
|
||||
onSelectionChange: (e, data) => onSelectedRowsChange(data.selectedItems),
|
||||
@@ -207,9 +257,10 @@ export const DocumentsTableComponent: React.FC<IDocumentsTableComponentProps> =
|
||||
if (newActiveItemIndex !== activeItemIndex) {
|
||||
onItemClicked(newActiveItemIndex);
|
||||
setActiveItemIndex(newActiveItemIndex);
|
||||
setSelectionStartIndex(newActiveItemIndex);
|
||||
}
|
||||
}
|
||||
}, [selectedRows, items]);
|
||||
}, [selectedRows, items, activeItemIndex, onItemClicked]);
|
||||
|
||||
// Cell keyboard navigation
|
||||
const keyboardNavAttr = useArrowNavigationGroup({ axis: "grid" });
|
||||
|
||||
Reference in New Issue
Block a user