diff --git a/desktop/flipper-plugin/src/ui/data-table/DataTable.tsx b/desktop/flipper-plugin/src/ui/data-table/DataTable.tsx index cfe740f65..eaf641cf4 100644 --- a/desktop/flipper-plugin/src/ui/data-table/DataTable.tsx +++ b/desktop/flipper-plugin/src/ui/data-table/DataTable.tsx @@ -188,9 +188,9 @@ export function DataTable( if (e.ctrlKey || e.metaKey) { tableManager.addRangeToSelection(index, index, true); } else if (e.shiftKey) { - tableManager.selectItem(index, true); + tableManager.selectItem(index, true, true); } else { - tableManager.selectItem(index); + tableManager.selectItem(index, false, true); } dragging.current = true; diff --git a/desktop/flipper-plugin/src/ui/data-table/DataTableManager.tsx b/desktop/flipper-plugin/src/ui/data-table/DataTableManager.tsx index 8db6be00c..f619952f2 100644 --- a/desktop/flipper-plugin/src/ui/data-table/DataTableManager.tsx +++ b/desktop/flipper-plugin/src/ui/data-table/DataTableManager.tsx @@ -59,6 +59,7 @@ type DataManagerActions = { nextIndex: number | ((currentIndex: number) => number); addToSelection?: boolean; + allowUnselect?: boolean; } > | Action< @@ -161,9 +162,14 @@ export const dataTableManagerReducer = produce< break; } case 'selectItem': { - const {nextIndex, addToSelection} = action; + const {nextIndex, addToSelection, allowUnselect} = action; draft.selection = castDraft( - computeSetSelection(draft.selection, nextIndex, addToSelection), + computeSetSelection( + draft.selection, + nextIndex, + addToSelection, + allowUnselect, + ), ); break; } @@ -252,6 +258,7 @@ export type DataTableManager = { selectItem( index: number | ((currentSelection: number) => number), addToSelection?: boolean, + allowUnselect?: boolean, ): void; addRangeToSelection( start: number, @@ -276,8 +283,13 @@ export function createDataTableManager( reset() { dispatch({type: 'reset'}); }, - selectItem(index: number, addToSelection = false) { - dispatch({type: 'selectItem', nextIndex: index, addToSelection}); + selectItem(index: number, addToSelection = false, allowUnselect = false) { + dispatch({ + type: 'selectItem', + nextIndex: index, + addToSelection, + allowUnselect, + }); }, selectItemById(id, addToSelection = false) { dispatch({type: 'selectItemById', id, addToSelection}); @@ -517,11 +529,17 @@ export function computeSetSelection( base: Selection, nextIndex: number | ((currentIndex: number) => number), addToSelection?: boolean, + allowUnselect?: boolean, ): Selection { const newIndex = typeof nextIndex === 'number' ? nextIndex : nextIndex(base.current); // special case: toggle existing selection off - if (!addToSelection && base.items.size === 1 && base.current === newIndex) { + if ( + !addToSelection && + allowUnselect && + base.items.size === 1 && + base.current === newIndex + ) { return emptySelection; } if (newIndex < 0) { diff --git a/desktop/flipper-plugin/src/ui/data-table/__tests__/DataTableManager.node.tsx b/desktop/flipper-plugin/src/ui/data-table/__tests__/DataTableManager.node.tsx index afe7f1247..c6a6b361c 100644 --- a/desktop/flipper-plugin/src/ui/data-table/__tests__/DataTableManager.node.tsx +++ b/desktop/flipper-plugin/src/ui/data-table/__tests__/DataTableManager.node.tsx @@ -61,6 +61,20 @@ test('computeSetSelection', () => { items: new Set([5]), }); + // single item existing selection, no selection toggle + expect( + computeSetSelection( + { + current: 4, + items: new Set([4]), + }, + 4, + ), + ).toEqual({ + current: 4, + items: new Set([4]), + }); + // single item existing selection, toggle item off expect( computeSetSelection( @@ -69,6 +83,8 @@ test('computeSetSelection', () => { items: new Set([4]), }, 4, + false, + true, ), ).toEqual({ current: -1,