mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-04-18 23:58:13 +01: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:
parent
7c5fb1b697
commit
7002da0b51
@ -1,5 +1,6 @@
|
|||||||
import ko from "knockout";
|
import ko from "knockout";
|
||||||
|
|
||||||
|
import { isEnvironmentAltPressed, isEnvironmentCtrlPressed, isEnvironmentShiftPressed } from "Utils/KeyboardUtils";
|
||||||
import * as Constants from "../Constants";
|
import * as Constants from "../Constants";
|
||||||
import * as Entities from "../Entities";
|
import * as Entities from "../Entities";
|
||||||
import * as Utilities from "../Utilities";
|
import * as Utilities from "../Utilities";
|
||||||
@ -28,7 +29,7 @@ export default class DataTableOperationManager {
|
|||||||
var elem: JQuery<Element> = $(event.currentTarget);
|
var elem: JQuery<Element> = $(event.currentTarget);
|
||||||
this.updateLastSelectedItem(elem, event.shiftKey);
|
this.updateLastSelectedItem(elem, event.shiftKey);
|
||||||
|
|
||||||
if (Utilities.isEnvironmentCtrlPressed(event)) {
|
if (isEnvironmentCtrlPressed(event)) {
|
||||||
this.applyCtrlSelection(elem);
|
this.applyCtrlSelection(elem);
|
||||||
} else if (event.shiftKey) {
|
} else if (event.shiftKey) {
|
||||||
this.applyShiftSelection(elem);
|
this.applyShiftSelection(elem);
|
||||||
@ -74,9 +75,9 @@ export default class DataTableOperationManager {
|
|||||||
DataTableOperations.scrollToRowIfNeeded(dataTableRows, safeIndex, isUpArrowKey);
|
DataTableOperations.scrollToRowIfNeeded(dataTableRows, safeIndex, isUpArrowKey);
|
||||||
}
|
}
|
||||||
} else if (
|
} else if (
|
||||||
Utilities.isEnvironmentCtrlPressed(event) &&
|
isEnvironmentCtrlPressed(event) &&
|
||||||
!Utilities.isEnvironmentShiftPressed(event) &&
|
!isEnvironmentShiftPressed(event) &&
|
||||||
!Utilities.isEnvironmentAltPressed(event) &&
|
!isEnvironmentAltPressed(event) &&
|
||||||
event.keyCode === Constants.keyCodes.A
|
event.keyCode === Constants.keyCodes.A
|
||||||
) {
|
) {
|
||||||
this.applySelectAll();
|
this.applySelectAll();
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import * as _ from "underscore";
|
|
||||||
import Q from "q";
|
import Q from "q";
|
||||||
|
import * as _ from "underscore";
|
||||||
|
import * as Constants from "./Constants";
|
||||||
import * as Entities from "./Entities";
|
import * as Entities from "./Entities";
|
||||||
import { CassandraTableKey } from "./TableDataClient";
|
import { CassandraTableKey } from "./TableDataClient";
|
||||||
import * as Constants from "./Constants";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a pseudo-random GUID.
|
* Generates a pseudo-random GUID.
|
||||||
@ -180,30 +180,6 @@ export function onEsc(
|
|||||||
return onKey(event, Constants.keyCodes.Esc, action, metaKey, shiftKey, altKey);
|
return onKey(event, Constants.keyCodes.Esc, action, metaKey, shiftKey, altKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Is the environment 'ctrl' key press. This key is used for multi selection, like select one more item, select all.
|
|
||||||
* For Windows and Linux, it's ctrl. For Mac, it's command.
|
|
||||||
*/
|
|
||||||
export function isEnvironmentCtrlPressed(event: JQueryEventObject): boolean {
|
|
||||||
return isMac() ? event.metaKey : event.ctrlKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isEnvironmentShiftPressed(event: JQueryEventObject): boolean {
|
|
||||||
return event.shiftKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isEnvironmentAltPressed(event: JQueryEventObject): boolean {
|
|
||||||
return event.altKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the current platform is MacOS.
|
|
||||||
*/
|
|
||||||
export function isMac(): boolean {
|
|
||||||
var platform = navigator.platform.toUpperCase();
|
|
||||||
return platform.indexOf("MAC") >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// MAX_SAFE_INTEGER and MIN_SAFE_INTEGER will be provided by ECMAScript 6's Number
|
// MAX_SAFE_INTEGER and MIN_SAFE_INTEGER will be provided by ECMAScript 6's Number
|
||||||
export var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1;
|
export var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1;
|
||||||
export var MIN_SAFE_INTEGER = -MAX_SAFE_INTEGER;
|
export var MIN_SAFE_INTEGER = -MAX_SAFE_INTEGER;
|
||||||
|
@ -22,6 +22,9 @@ import {
|
|||||||
useTableFeatures,
|
useTableFeatures,
|
||||||
useTableSelection,
|
useTableSelection,
|
||||||
} from "@fluentui/react-components";
|
} 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 React, { useCallback, useEffect, useMemo } from "react";
|
||||||
import { FixedSizeList as List, ListChildComponentProps } from "react-window";
|
import { FixedSizeList as List, ListChildComponentProps } from "react-window";
|
||||||
|
|
||||||
@ -123,17 +126,63 @@ export const DocumentsTableComponent: React.FC<IDocumentsTableComponentProps> =
|
|||||||
[columnHeaders],
|
[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 RenderRow = ({ index, style, data }: ReactWindowRenderFnProps) => {
|
||||||
const { item, selected, appearance, onClick, onKeyDown } = data[index];
|
const { item, selected, appearance, onClick, onKeyDown } = data[index];
|
||||||
return (
|
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 && (
|
{!isSelectionDisabled && (
|
||||||
<TableSelectionCell
|
<TableSelectionCell
|
||||||
checked={selected}
|
checked={selected}
|
||||||
checkboxIndicator={{ "aria-label": "Select row" }}
|
checkboxIndicator={{ "aria-label": "Select row" }}
|
||||||
onClick={onClick}
|
onClick={(e: React.MouseEvent) => {
|
||||||
|
setSelectionStartIndex(index);
|
||||||
|
onClick(e);
|
||||||
|
}}
|
||||||
onKeyDown={onKeyDown}
|
onKeyDown={onKeyDown}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -141,8 +190,9 @@ export const DocumentsTableComponent: React.FC<IDocumentsTableComponentProps> =
|
|||||||
<TableCell
|
<TableCell
|
||||||
key={column.columnId}
|
key={column.columnId}
|
||||||
className="documentsTableCell"
|
className="documentsTableCell"
|
||||||
onClick={(/* e */) => onSelectedRowsChange(new Set<TableRowId>([index]))}
|
// When clicking on a cell with shift/ctrl key, onKeyDown is called instead of onClick.
|
||||||
onKeyDown={() => onIdClicked(index)}
|
onClick={(e: React.MouseEvent<Element, MouseEvent>) => onTableCellClicked(e, index)}
|
||||||
|
onKeyPress={(e: React.KeyboardEvent<Element>) => onIdClicked(e, index)}
|
||||||
{...columnSizing.getTableCellProps(column.columnId)}
|
{...columnSizing.getTableCellProps(column.columnId)}
|
||||||
tabIndex={column.columnId === "id" ? 0 : -1}
|
tabIndex={column.columnId === "id" ? 0 : -1}
|
||||||
>
|
>
|
||||||
@ -166,7 +216,7 @@ export const DocumentsTableComponent: React.FC<IDocumentsTableComponentProps> =
|
|||||||
[
|
[
|
||||||
useTableColumnSizing_unstable({ columnSizingOptions, onColumnResize }),
|
useTableColumnSizing_unstable({ columnSizingOptions, onColumnResize }),
|
||||||
useTableSelection({
|
useTableSelection({
|
||||||
selectionMode: "multiselect",
|
selectionMode: isSelectionDisabled ? "single" : "multiselect",
|
||||||
selectedItems: selectedRows,
|
selectedItems: selectedRows,
|
||||||
// eslint-disable-next-line react/prop-types
|
// eslint-disable-next-line react/prop-types
|
||||||
onSelectionChange: (e, data) => onSelectedRowsChange(data.selectedItems),
|
onSelectionChange: (e, data) => onSelectedRowsChange(data.selectedItems),
|
||||||
@ -207,9 +257,10 @@ export const DocumentsTableComponent: React.FC<IDocumentsTableComponentProps> =
|
|||||||
if (newActiveItemIndex !== activeItemIndex) {
|
if (newActiveItemIndex !== activeItemIndex) {
|
||||||
onItemClicked(newActiveItemIndex);
|
onItemClicked(newActiveItemIndex);
|
||||||
setActiveItemIndex(newActiveItemIndex);
|
setActiveItemIndex(newActiveItemIndex);
|
||||||
|
setSelectionStartIndex(newActiveItemIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [selectedRows, items]);
|
}, [selectedRows, items, activeItemIndex, onItemClicked]);
|
||||||
|
|
||||||
// Cell keyboard navigation
|
// Cell keyboard navigation
|
||||||
const keyboardNavAttr = useArrowNavigationGroup({ axis: "grid" });
|
const keyboardNavAttr = useArrowNavigationGroup({ axis: "grid" });
|
||||||
|
92
src/Explorer/Tabs/DocumentsTabV2/SelectionHelper.ts
Normal file
92
src/Explorer/Tabs/DocumentsTabV2/SelectionHelper.ts
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/**
|
||||||
|
* Utility class to help with selection.
|
||||||
|
* This emulates File Explorer selection behavior.
|
||||||
|
* ctrl: toggle selection of index.
|
||||||
|
* shift: select all rows between selectionStartIndex and index
|
||||||
|
* shift + ctrl: select or deselect all rows between selectionStartIndex and index depending on whether selectionStartIndex is selected
|
||||||
|
* No modifier only selects the clicked row
|
||||||
|
* ctrl: updates selection start index
|
||||||
|
* shift: do not update selection start index
|
||||||
|
*
|
||||||
|
* @param currentSelection current selection
|
||||||
|
* @param clickedIndex index of clicked row
|
||||||
|
* @param isShiftKey shift key is pressed
|
||||||
|
* @param isCtrlKey ctrl key is pressed
|
||||||
|
* @param selectionStartIndex index of current selected row
|
||||||
|
* @returns new selection and selection start
|
||||||
|
*/
|
||||||
|
export const selectionHelper = (
|
||||||
|
currentSelection: Set<number>,
|
||||||
|
clickedIndex: number,
|
||||||
|
isShiftKey: boolean,
|
||||||
|
isCtrlKey: boolean,
|
||||||
|
selectionStartIndex: number,
|
||||||
|
): {
|
||||||
|
selection: Set<number>;
|
||||||
|
selectionStartIndex: number;
|
||||||
|
} => {
|
||||||
|
if (isShiftKey) {
|
||||||
|
// Shift is about selecting range of rows
|
||||||
|
if (isCtrlKey) {
|
||||||
|
// shift + ctrl
|
||||||
|
const isSelectionStartIndexSelected = currentSelection.has(selectionStartIndex);
|
||||||
|
const min = Math.min(clickedIndex, selectionStartIndex);
|
||||||
|
const max = Math.max(clickedIndex, selectionStartIndex);
|
||||||
|
|
||||||
|
const newSelection = new Set<number>(currentSelection);
|
||||||
|
for (let i = min; i <= max; i++) {
|
||||||
|
// Select or deselect range depending on how selectionStartIndex is selected
|
||||||
|
if (isSelectionStartIndexSelected) {
|
||||||
|
// Select range
|
||||||
|
newSelection.add(i);
|
||||||
|
} else {
|
||||||
|
// Deselect range
|
||||||
|
newSelection.delete(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
selection: newSelection,
|
||||||
|
selectionStartIndex: undefined,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// shift only
|
||||||
|
// Shift only: enable everything between lastClickedIndex and clickedIndex and disable everything else
|
||||||
|
const min = Math.min(clickedIndex, selectionStartIndex);
|
||||||
|
const max = Math.max(clickedIndex, selectionStartIndex);
|
||||||
|
const newSelection = new Set<number>();
|
||||||
|
for (let i = min; i <= max; i++) {
|
||||||
|
newSelection.add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
selection: newSelection,
|
||||||
|
selectionStartIndex: undefined, // do not change selection start
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isCtrlKey) {
|
||||||
|
// Ctrl only: toggle selection where we clicked
|
||||||
|
const isNotSelected = !currentSelection.has(clickedIndex);
|
||||||
|
if (isNotSelected) {
|
||||||
|
return {
|
||||||
|
selection: new Set(currentSelection.add(clickedIndex)),
|
||||||
|
selectionStartIndex: clickedIndex,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// Remove
|
||||||
|
currentSelection.delete(clickedIndex);
|
||||||
|
return {
|
||||||
|
selection: new Set(currentSelection),
|
||||||
|
selectionStartIndex: clickedIndex,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If no modifier keys are pressed, select only the clicked row
|
||||||
|
return {
|
||||||
|
selection: new Set<number>([clickedIndex]),
|
||||||
|
selectionStartIndex: clickedIndex,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
@ -476,11 +476,13 @@ exports[`DocumentsTableComponent should not render selection column when isSelec
|
|||||||
key="1"
|
key="1"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
|
"cursor": "pointer",
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"left": 0,
|
"left": 0,
|
||||||
"position": "absolute",
|
"position": "absolute",
|
||||||
"right": undefined,
|
"right": undefined,
|
||||||
"top": 0,
|
"top": 0,
|
||||||
|
"userSelect": "none",
|
||||||
"width": "100%",
|
"width": "100%",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -492,11 +494,13 @@ exports[`DocumentsTableComponent should not render selection column when isSelec
|
|||||||
role="row"
|
role="row"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
|
"cursor": "pointer",
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"left": 0,
|
"left": 0,
|
||||||
"position": "absolute",
|
"position": "absolute",
|
||||||
"right": undefined,
|
"right": undefined,
|
||||||
"top": 0,
|
"top": 0,
|
||||||
|
"userSelect": "none",
|
||||||
"width": "100%",
|
"width": "100%",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -505,7 +509,7 @@ exports[`DocumentsTableComponent should not render selection column when isSelec
|
|||||||
className="documentsTableCell"
|
className="documentsTableCell"
|
||||||
key="id"
|
key="id"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"maxWidth": 50,
|
"maxWidth": 50,
|
||||||
@ -518,7 +522,7 @@ exports[`DocumentsTableComponent should not render selection column when isSelec
|
|||||||
<div
|
<div
|
||||||
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
role="cell"
|
role="cell"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
@ -554,7 +558,7 @@ exports[`DocumentsTableComponent should not render selection column when isSelec
|
|||||||
className="documentsTableCell"
|
className="documentsTableCell"
|
||||||
key="partitionKey"
|
key="partitionKey"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"maxWidth": 50,
|
"maxWidth": 50,
|
||||||
@ -567,7 +571,7 @@ exports[`DocumentsTableComponent should not render selection column when isSelec
|
|||||||
<div
|
<div
|
||||||
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
role="cell"
|
role="cell"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
@ -660,11 +664,13 @@ exports[`DocumentsTableComponent should not render selection column when isSelec
|
|||||||
key="2"
|
key="2"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
|
"cursor": "pointer",
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"left": 0,
|
"left": 0,
|
||||||
"position": "absolute",
|
"position": "absolute",
|
||||||
"right": undefined,
|
"right": undefined,
|
||||||
"top": 30,
|
"top": 30,
|
||||||
|
"userSelect": "none",
|
||||||
"width": "100%",
|
"width": "100%",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -676,11 +682,13 @@ exports[`DocumentsTableComponent should not render selection column when isSelec
|
|||||||
role="row"
|
role="row"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
|
"cursor": "pointer",
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"left": 0,
|
"left": 0,
|
||||||
"position": "absolute",
|
"position": "absolute",
|
||||||
"right": undefined,
|
"right": undefined,
|
||||||
"top": 30,
|
"top": 30,
|
||||||
|
"userSelect": "none",
|
||||||
"width": "100%",
|
"width": "100%",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -689,7 +697,7 @@ exports[`DocumentsTableComponent should not render selection column when isSelec
|
|||||||
className="documentsTableCell"
|
className="documentsTableCell"
|
||||||
key="id"
|
key="id"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"maxWidth": 50,
|
"maxWidth": 50,
|
||||||
@ -702,7 +710,7 @@ exports[`DocumentsTableComponent should not render selection column when isSelec
|
|||||||
<div
|
<div
|
||||||
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
role="cell"
|
role="cell"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
@ -738,7 +746,7 @@ exports[`DocumentsTableComponent should not render selection column when isSelec
|
|||||||
className="documentsTableCell"
|
className="documentsTableCell"
|
||||||
key="partitionKey"
|
key="partitionKey"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"maxWidth": 50,
|
"maxWidth": 50,
|
||||||
@ -751,7 +759,7 @@ exports[`DocumentsTableComponent should not render selection column when isSelec
|
|||||||
<div
|
<div
|
||||||
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
role="cell"
|
role="cell"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
@ -844,11 +852,13 @@ exports[`DocumentsTableComponent should not render selection column when isSelec
|
|||||||
key="3"
|
key="3"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
|
"cursor": "pointer",
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"left": 0,
|
"left": 0,
|
||||||
"position": "absolute",
|
"position": "absolute",
|
||||||
"right": undefined,
|
"right": undefined,
|
||||||
"top": 60,
|
"top": 60,
|
||||||
|
"userSelect": "none",
|
||||||
"width": "100%",
|
"width": "100%",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -860,11 +870,13 @@ exports[`DocumentsTableComponent should not render selection column when isSelec
|
|||||||
role="row"
|
role="row"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
|
"cursor": "pointer",
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"left": 0,
|
"left": 0,
|
||||||
"position": "absolute",
|
"position": "absolute",
|
||||||
"right": undefined,
|
"right": undefined,
|
||||||
"top": 60,
|
"top": 60,
|
||||||
|
"userSelect": "none",
|
||||||
"width": "100%",
|
"width": "100%",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -873,7 +885,7 @@ exports[`DocumentsTableComponent should not render selection column when isSelec
|
|||||||
className="documentsTableCell"
|
className="documentsTableCell"
|
||||||
key="id"
|
key="id"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"maxWidth": 50,
|
"maxWidth": 50,
|
||||||
@ -886,7 +898,7 @@ exports[`DocumentsTableComponent should not render selection column when isSelec
|
|||||||
<div
|
<div
|
||||||
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
role="cell"
|
role="cell"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
@ -922,7 +934,7 @@ exports[`DocumentsTableComponent should not render selection column when isSelec
|
|||||||
className="documentsTableCell"
|
className="documentsTableCell"
|
||||||
key="partitionKey"
|
key="partitionKey"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"maxWidth": 50,
|
"maxWidth": 50,
|
||||||
@ -935,7 +947,7 @@ exports[`DocumentsTableComponent should not render selection column when isSelec
|
|||||||
<div
|
<div
|
||||||
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
role="cell"
|
role="cell"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
@ -1496,11 +1508,13 @@ exports[`DocumentsTableComponent should render documents and partition keys in h
|
|||||||
key="1"
|
key="1"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
|
"cursor": "pointer",
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"left": 0,
|
"left": 0,
|
||||||
"position": "absolute",
|
"position": "absolute",
|
||||||
"right": undefined,
|
"right": undefined,
|
||||||
"top": 0,
|
"top": 0,
|
||||||
|
"userSelect": "none",
|
||||||
"width": "100%",
|
"width": "100%",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1512,11 +1526,13 @@ exports[`DocumentsTableComponent should render documents and partition keys in h
|
|||||||
role="row"
|
role="row"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
|
"cursor": "pointer",
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"left": 0,
|
"left": 0,
|
||||||
"position": "absolute",
|
"position": "absolute",
|
||||||
"right": undefined,
|
"right": undefined,
|
||||||
"top": 0,
|
"top": 0,
|
||||||
|
"userSelect": "none",
|
||||||
"width": "100%",
|
"width": "100%",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1565,7 +1581,7 @@ exports[`DocumentsTableComponent should render documents and partition keys in h
|
|||||||
className="documentsTableCell"
|
className="documentsTableCell"
|
||||||
key="id"
|
key="id"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"maxWidth": 50,
|
"maxWidth": 50,
|
||||||
@ -1578,7 +1594,7 @@ exports[`DocumentsTableComponent should render documents and partition keys in h
|
|||||||
<div
|
<div
|
||||||
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
role="cell"
|
role="cell"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
@ -1614,7 +1630,7 @@ exports[`DocumentsTableComponent should render documents and partition keys in h
|
|||||||
className="documentsTableCell"
|
className="documentsTableCell"
|
||||||
key="partitionKey"
|
key="partitionKey"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"maxWidth": 50,
|
"maxWidth": 50,
|
||||||
@ -1627,7 +1643,7 @@ exports[`DocumentsTableComponent should render documents and partition keys in h
|
|||||||
<div
|
<div
|
||||||
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
role="cell"
|
role="cell"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
@ -1720,11 +1736,13 @@ exports[`DocumentsTableComponent should render documents and partition keys in h
|
|||||||
key="2"
|
key="2"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
|
"cursor": "pointer",
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"left": 0,
|
"left": 0,
|
||||||
"position": "absolute",
|
"position": "absolute",
|
||||||
"right": undefined,
|
"right": undefined,
|
||||||
"top": 30,
|
"top": 30,
|
||||||
|
"userSelect": "none",
|
||||||
"width": "100%",
|
"width": "100%",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1736,11 +1754,13 @@ exports[`DocumentsTableComponent should render documents and partition keys in h
|
|||||||
role="row"
|
role="row"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
|
"cursor": "pointer",
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"left": 0,
|
"left": 0,
|
||||||
"position": "absolute",
|
"position": "absolute",
|
||||||
"right": undefined,
|
"right": undefined,
|
||||||
"top": 30,
|
"top": 30,
|
||||||
|
"userSelect": "none",
|
||||||
"width": "100%",
|
"width": "100%",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1789,7 +1809,7 @@ exports[`DocumentsTableComponent should render documents and partition keys in h
|
|||||||
className="documentsTableCell"
|
className="documentsTableCell"
|
||||||
key="id"
|
key="id"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"maxWidth": 50,
|
"maxWidth": 50,
|
||||||
@ -1802,7 +1822,7 @@ exports[`DocumentsTableComponent should render documents and partition keys in h
|
|||||||
<div
|
<div
|
||||||
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
role="cell"
|
role="cell"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
@ -1838,7 +1858,7 @@ exports[`DocumentsTableComponent should render documents and partition keys in h
|
|||||||
className="documentsTableCell"
|
className="documentsTableCell"
|
||||||
key="partitionKey"
|
key="partitionKey"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"maxWidth": 50,
|
"maxWidth": 50,
|
||||||
@ -1851,7 +1871,7 @@ exports[`DocumentsTableComponent should render documents and partition keys in h
|
|||||||
<div
|
<div
|
||||||
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
role="cell"
|
role="cell"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
@ -1944,11 +1964,13 @@ exports[`DocumentsTableComponent should render documents and partition keys in h
|
|||||||
key="3"
|
key="3"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
|
"cursor": "pointer",
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"left": 0,
|
"left": 0,
|
||||||
"position": "absolute",
|
"position": "absolute",
|
||||||
"right": undefined,
|
"right": undefined,
|
||||||
"top": 60,
|
"top": 60,
|
||||||
|
"userSelect": "none",
|
||||||
"width": "100%",
|
"width": "100%",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1960,11 +1982,13 @@ exports[`DocumentsTableComponent should render documents and partition keys in h
|
|||||||
role="row"
|
role="row"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
|
"cursor": "pointer",
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"left": 0,
|
"left": 0,
|
||||||
"position": "absolute",
|
"position": "absolute",
|
||||||
"right": undefined,
|
"right": undefined,
|
||||||
"top": 60,
|
"top": 60,
|
||||||
|
"userSelect": "none",
|
||||||
"width": "100%",
|
"width": "100%",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2013,7 +2037,7 @@ exports[`DocumentsTableComponent should render documents and partition keys in h
|
|||||||
className="documentsTableCell"
|
className="documentsTableCell"
|
||||||
key="id"
|
key="id"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"maxWidth": 50,
|
"maxWidth": 50,
|
||||||
@ -2026,7 +2050,7 @@ exports[`DocumentsTableComponent should render documents and partition keys in h
|
|||||||
<div
|
<div
|
||||||
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
role="cell"
|
role="cell"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
@ -2062,7 +2086,7 @@ exports[`DocumentsTableComponent should render documents and partition keys in h
|
|||||||
className="documentsTableCell"
|
className="documentsTableCell"
|
||||||
key="partitionKey"
|
key="partitionKey"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"maxWidth": 50,
|
"maxWidth": 50,
|
||||||
@ -2075,7 +2099,7 @@ exports[`DocumentsTableComponent should render documents and partition keys in h
|
|||||||
<div
|
<div
|
||||||
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
className="fui-TableCell documentsTableCell ___o2cmzw0_1ilyrce f10pi13n f1nbblvp f1vdfbxk f1ov4xf1 f1f5gg8d fz36nt7 f9znhxp fqrak0z f1o2ludy f1kjnpwc fxmnebo f1witrsb f22iagw f10tiqix f122n59 fqerorx f1neuvcm fkjuxzh f1pha7fy"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
onKeyDown={[Function]}
|
onKeyPress={[Function]}
|
||||||
role="cell"
|
role="cell"
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
|
84
src/Explorer/Tabs/DocumentsTabV2/selectionHelper.test.ts
Normal file
84
src/Explorer/Tabs/DocumentsTabV2/selectionHelper.test.ts
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import { selectionHelper } from "Explorer/Tabs/DocumentsTabV2/SelectionHelper";
|
||||||
|
|
||||||
|
describe("Selection helper", () => {
|
||||||
|
describe("when shift:off", () => {
|
||||||
|
it("ctrl:off: should return clicked items and update selection start", () => {
|
||||||
|
const currentSelection = new Set<number>([1, 2, 3]);
|
||||||
|
const clickedIndex = 4;
|
||||||
|
const isShiftKey = false;
|
||||||
|
const isCtrlKey = false;
|
||||||
|
const selectionStartIndex = 1;
|
||||||
|
const result = selectionHelper(currentSelection, clickedIndex, isShiftKey, isCtrlKey, selectionStartIndex);
|
||||||
|
expect(result.selection).toEqual(new Set<number>([4]));
|
||||||
|
expect(result.selectionStartIndex).toEqual(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("ctrl:on: should turn on selection and update selection start on not selected item", () => {
|
||||||
|
const currentSelection = new Set<number>([1, 3]);
|
||||||
|
const clickedIndex = 2;
|
||||||
|
const isShiftKey = false;
|
||||||
|
const isCtrlKey = true;
|
||||||
|
const selectionStartIndex = 1;
|
||||||
|
const result = selectionHelper(currentSelection, clickedIndex, isShiftKey, isCtrlKey, selectionStartIndex);
|
||||||
|
expect(result.selection).toEqual(new Set<number>([1, 2, 3]));
|
||||||
|
expect(result.selectionStartIndex).toEqual(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("ctrl:on: should turn off selection and update selection start on selected item", () => {
|
||||||
|
const currentSelection = new Set<number>([1, 2, 3]);
|
||||||
|
const clickedIndex = 2;
|
||||||
|
const isShiftKey = false;
|
||||||
|
const isCtrlKey = true;
|
||||||
|
const selectionStartIndex = 1;
|
||||||
|
const result = selectionHelper(currentSelection, clickedIndex, isShiftKey, isCtrlKey, selectionStartIndex);
|
||||||
|
expect(result.selection).toEqual(new Set<number>([1, 3]));
|
||||||
|
expect(result.selectionStartIndex).toEqual(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when shift:on", () => {
|
||||||
|
it("ctrl:off: should only select between selection start and clicked index (selection start < clicked index)", () => {
|
||||||
|
const currentSelection = new Set<number>([7, 8, 10]);
|
||||||
|
const clickedIndex = 9;
|
||||||
|
const isShiftKey = true;
|
||||||
|
const isCtrlKey = false;
|
||||||
|
const selectionStartIndex = 5;
|
||||||
|
const result = selectionHelper(currentSelection, clickedIndex, isShiftKey, isCtrlKey, selectionStartIndex);
|
||||||
|
expect(result.selection).toEqual(new Set<number>([5, 6, 7, 8, 9]));
|
||||||
|
expect(result.selectionStartIndex).toEqual(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("ctrl:off: should only select between selection start and clicked index (selection start > clicked index)", () => {
|
||||||
|
const currentSelection = new Set<number>([4, 6, 8]);
|
||||||
|
const clickedIndex = 2;
|
||||||
|
const isShiftKey = true;
|
||||||
|
const isCtrlKey = false;
|
||||||
|
const selectionStartIndex = 5;
|
||||||
|
const result = selectionHelper(currentSelection, clickedIndex, isShiftKey, isCtrlKey, selectionStartIndex);
|
||||||
|
expect(result.selection).toEqual(new Set<number>([2, 3, 4, 5]));
|
||||||
|
expect(result.selectionStartIndex).toEqual(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("ctrl:on: selection start on selected item should keep current selection and select range, and not update selection start", () => {
|
||||||
|
const currentSelection = new Set<number>([1, 4, 5, 7]);
|
||||||
|
const clickedIndex = 9;
|
||||||
|
const isShiftKey = true;
|
||||||
|
const isCtrlKey = true;
|
||||||
|
const selectionStartIndex = 5;
|
||||||
|
const result = selectionHelper(currentSelection, clickedIndex, isShiftKey, isCtrlKey, selectionStartIndex);
|
||||||
|
expect(result.selection).toEqual(new Set<number>([1, 4, 5, 6, 7, 8, 9]));
|
||||||
|
expect(result.selectionStartIndex).toEqual(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("ctrl:on: selection start on deselected item should deselect range, and not update selection start", () => {
|
||||||
|
const currentSelection = new Set<number>([1, 4, 6, 7, 10]);
|
||||||
|
const clickedIndex = 9;
|
||||||
|
const isShiftKey = true;
|
||||||
|
const isCtrlKey = true;
|
||||||
|
const selectionStartIndex = 5;
|
||||||
|
const result = selectionHelper(currentSelection, clickedIndex, isShiftKey, isCtrlKey, selectionStartIndex);
|
||||||
|
expect(result.selection).toEqual(new Set<number>([1, 4, 10]));
|
||||||
|
expect(result.selectionStartIndex).toEqual(undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
15
src/Utils/KeyboardUtils.ts
Normal file
15
src/Utils/KeyboardUtils.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* Is the environment 'ctrl' key press. This key is used for multi selection, like select one more item, select all.
|
||||||
|
* For Windows and Linux, it's ctrl. For Mac, it's command.
|
||||||
|
*/
|
||||||
|
export const isEnvironmentCtrlPressed = (event: JQueryEventObject | React.MouseEvent): boolean =>
|
||||||
|
isMac() ? event.metaKey : event.ctrlKey;
|
||||||
|
|
||||||
|
export const isEnvironmentShiftPressed = (event: JQueryEventObject | React.MouseEvent): boolean => event.shiftKey;
|
||||||
|
|
||||||
|
export const isEnvironmentAltPressed = (event: JQueryEventObject | React.MouseEvent): boolean => event.altKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the current platform is MacOS.
|
||||||
|
*/
|
||||||
|
export const isMac = (): boolean => navigator.platform.toUpperCase().indexOf("MAC") >= 0;
|
Loading…
x
Reference in New Issue
Block a user