Add bulk cell selection using shift+keyboard
This commit is contained in:
parent
3a4b3e8c42
commit
4ec6a22e42
|
@ -105,7 +105,7 @@
|
|||
const handleClick = e => {
|
||||
if (e.shiftKey && $focusedCellId) {
|
||||
// If we have a focused cell, select the range from that cell to here
|
||||
selectedCells.actions.setRange($focusedCellId, cellId)
|
||||
selectedCells.actions.selectRange($focusedCellId, cellId)
|
||||
} else if (e.shiftKey && $selectedCellCount) {
|
||||
// If we already have a selected range of cell, update it
|
||||
selectedCells.actions.updateTarget(cellId)
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
<script>
|
||||
import { getContext, onMount } from "svelte"
|
||||
import { debounce } from "../../../utils/utils"
|
||||
import { NewRowID } from "../lib/constants"
|
||||
import { getCellID, parseCellID } from "../lib/utils"
|
||||
|
||||
const {
|
||||
rows,
|
||||
focusedCellId,
|
||||
visibleColumns,
|
||||
focusedRow,
|
||||
rowLookupMap,
|
||||
stickyColumn,
|
||||
focusedCellAPI,
|
||||
dispatch,
|
||||
|
@ -17,6 +16,11 @@
|
|||
menu,
|
||||
gridFocused,
|
||||
keyboardBlocked,
|
||||
selectedCellCount,
|
||||
selectedCells,
|
||||
cellSelection,
|
||||
columnLookupMap,
|
||||
allVisibleColumns,
|
||||
} = getContext("grid")
|
||||
|
||||
const ignoredOriginSelectors = [
|
||||
|
@ -62,6 +66,26 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Handle certain key presses if we have cells selected
|
||||
if ($selectedCellCount) {
|
||||
e.preventDefault()
|
||||
switch (e.key) {
|
||||
case "ArrowLeft":
|
||||
changeFocusedColumn(-1, e.shiftKey)
|
||||
break
|
||||
case "ArrowRight":
|
||||
changeFocusedColumn(1, e.shiftKey)
|
||||
break
|
||||
case "ArrowUp":
|
||||
changeFocusedRow(-1, e.shiftKey)
|
||||
break
|
||||
case "ArrowDown":
|
||||
changeFocusedRow(1, e.shiftKey)
|
||||
break
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// If nothing selected avoid processing further key presses
|
||||
if (!$focusedCellId) {
|
||||
if (e.key === "Tab" || e.key?.startsWith("Arrow")) {
|
||||
|
@ -111,16 +135,16 @@
|
|||
} else {
|
||||
switch (e.key) {
|
||||
case "ArrowLeft":
|
||||
changeFocusedColumn(-1)
|
||||
changeFocusedColumn(-1, e.shiftKey)
|
||||
break
|
||||
case "ArrowRight":
|
||||
changeFocusedColumn(1)
|
||||
changeFocusedColumn(1, e.shiftKey)
|
||||
break
|
||||
case "ArrowUp":
|
||||
changeFocusedRow(-1)
|
||||
changeFocusedRow(-1, e.shiftKey)
|
||||
break
|
||||
case "ArrowDown":
|
||||
changeFocusedRow(1)
|
||||
changeFocusedRow(1, e.shiftKey)
|
||||
break
|
||||
case "Delete":
|
||||
case "Backspace":
|
||||
|
@ -153,38 +177,82 @@
|
|||
}
|
||||
|
||||
// Changes the focused cell by moving it left or right to a different column
|
||||
const changeFocusedColumn = delta => {
|
||||
if (!$focusedCellId) {
|
||||
const changeFocusedColumn = (delta, shiftKey) => {
|
||||
// Determine which cell we are working with
|
||||
let sourceCellId = $focusedCellId
|
||||
if (shiftKey && $selectedCellCount) {
|
||||
sourceCellId = $cellSelection.targetCellId
|
||||
}
|
||||
if (!sourceCellId) {
|
||||
return
|
||||
}
|
||||
const cols = $visibleColumns
|
||||
const { rowId, field: columnName } = parseCellID($focusedCellId)
|
||||
let newColumnName
|
||||
if (columnName === $stickyColumn?.name) {
|
||||
const index = delta - 1
|
||||
newColumnName = cols[index]?.name
|
||||
} else {
|
||||
const index = cols.findIndex(col => col.name === columnName) + delta
|
||||
if (index === -1) {
|
||||
newColumnName = $stickyColumn?.name
|
||||
} else {
|
||||
newColumnName = cols[index]?.name
|
||||
}
|
||||
|
||||
// Determine the new position for this cell
|
||||
const { rowId, field } = parseCellID(sourceCellId)
|
||||
const colIdx = $columnLookupMap[field]
|
||||
const nextColumn = $allVisibleColumns[colIdx + delta]
|
||||
if (!nextColumn) {
|
||||
return
|
||||
}
|
||||
if (newColumnName) {
|
||||
$focusedCellId = getCellID(rowId, newColumnName)
|
||||
const targetCellId = getCellID(rowId, nextColumn.name)
|
||||
|
||||
// Apply change
|
||||
if (shiftKey) {
|
||||
if ($selectedCellCount) {
|
||||
// We have selected cells and still are holding shift - update selection
|
||||
selectedCells.actions.updateTarget(targetCellId)
|
||||
|
||||
// Restore focused cell if this removes the selection
|
||||
if (!$selectedCellCount) {
|
||||
focusedCellId.set(targetCellId)
|
||||
}
|
||||
} else {
|
||||
// We have no selection but are holding shift - select these cells
|
||||
selectedCells.actions.selectRange(sourceCellId, targetCellId)
|
||||
}
|
||||
} else {
|
||||
// We aren't holding shift - just focus this cell
|
||||
focusedCellId.set(targetCellId)
|
||||
}
|
||||
}
|
||||
|
||||
// Changes the focused cell by moving it up or down to a new row
|
||||
const changeFocusedRow = delta => {
|
||||
if (!$focusedRow) {
|
||||
const changeFocusedRow = (delta, shiftKey) => {
|
||||
// Determine which cell we are working with
|
||||
let sourceCellId = $focusedCellId
|
||||
if (shiftKey && $selectedCellCount) {
|
||||
sourceCellId = $cellSelection.targetCellId
|
||||
}
|
||||
if (!sourceCellId) {
|
||||
return
|
||||
}
|
||||
const newRow = $rows[$focusedRow.__idx + delta]
|
||||
if (newRow) {
|
||||
const { field } = parseCellID($focusedCellId)
|
||||
$focusedCellId = getCellID(newRow._id, field)
|
||||
|
||||
// Determine the new position for this cell
|
||||
const { rowId, field } = parseCellID(sourceCellId)
|
||||
const rowIdx = $rowLookupMap[rowId]
|
||||
const newRow = $rows[rowIdx + delta]
|
||||
if (!newRow) {
|
||||
return
|
||||
}
|
||||
const targetCellId = getCellID(newRow._id, field)
|
||||
|
||||
// Apply change
|
||||
if (shiftKey) {
|
||||
if ($selectedCellCount) {
|
||||
// We have selected cells and still are holding shift - update selection
|
||||
selectedCells.actions.updateTarget(targetCellId)
|
||||
|
||||
// Restore focused cell if this removes the selection
|
||||
if (!$selectedCellCount) {
|
||||
focusedCellId.set(targetCellId)
|
||||
}
|
||||
} else {
|
||||
// We have no selection but are holding shift - select these cells
|
||||
selectedCells.actions.selectRange(sourceCellId, targetCellId)
|
||||
}
|
||||
} else {
|
||||
// We aren't holding shift - just focus this cell
|
||||
focusedCellId.set(targetCellId)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -260,7 +260,7 @@ export const createActions = context => {
|
|||
}))
|
||||
}
|
||||
|
||||
const setCellSelectionRange = (source, target) => {
|
||||
const selectCellRange = (source, target) => {
|
||||
cellSelection.set({
|
||||
active: false,
|
||||
sourceCellId: source,
|
||||
|
@ -295,7 +295,7 @@ export const createActions = context => {
|
|||
startSelecting: startCellSelection,
|
||||
updateTarget: updateCellSelection,
|
||||
stopSelecting: stopCellSelection,
|
||||
setRange: setCellSelectionRange,
|
||||
selectRange: selectCellRange,
|
||||
clear: clearCellSelection,
|
||||
},
|
||||
},
|
||||
|
@ -318,6 +318,7 @@ export const initialise = context => {
|
|||
menu,
|
||||
selectedCellCount,
|
||||
selectedCells,
|
||||
cellSelection,
|
||||
} = context
|
||||
|
||||
// Ensure we clear invalid rows from state if they disappear
|
||||
|
@ -422,9 +423,17 @@ export const initialise = context => {
|
|||
if (get(selectedRowCount)) {
|
||||
selectedRows.set({})
|
||||
}
|
||||
if (get(focusedCellId)) {
|
||||
focusedCellId.set(null)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Ensure the source of cell selection is focused
|
||||
cellSelection.subscribe(async ({ sourceCellId, targetCellId }) => {
|
||||
if (
|
||||
sourceCellId &&
|
||||
sourceCellId !== targetCellId &&
|
||||
get(focusedCellId) !== sourceCellId
|
||||
) {
|
||||
focusedCellId.set(sourceCellId)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue