diff --git a/packages/frontend-core/src/components/grid/cells/DataCell.svelte b/packages/frontend-core/src/components/grid/cells/DataCell.svelte
index ba9dc60a26..800d612824 100644
--- a/packages/frontend-core/src/components/grid/cells/DataCell.svelte
+++ b/packages/frontend-core/src/components/grid/cells/DataCell.svelte
@@ -11,7 +11,7 @@
menu,
config,
validation,
- cellSelection,
+ selectedCells,
} = getContext("grid")
export let highlighted
@@ -28,14 +28,12 @@
export let contentLines = 1
export let hidden = false
export let isSelectingCells = false
- export let selectedCells = {}
+ export let cellSelected = false
const emptyError = writable(null)
let api
- $: cellSelected = selectedCells[cellId]
-
// Get the error for this cell if the cell is focused or selected
$: error = getErrorStore(rowFocused || cellSelected, cellId)
@@ -89,16 +87,16 @@
return
}
// focusedCellId.set(cellId)
- cellSelection.actions.start(cellId)
+ selectedCells.actions.start(cellId)
}
const updateSelection = e => {
focusedCellId.set(null)
- cellSelection.actions.update(cellId)
+ selectedCells.actions.update(cellId)
}
const stopSelection = e => {
- cellSelection.actions.stop()
+ selectedCells.actions.stop()
}
diff --git a/packages/frontend-core/src/components/grid/layout/GridRow.svelte b/packages/frontend-core/src/components/grid/layout/GridRow.svelte
index 6b05565f0e..a01d9de7df 100644
--- a/packages/frontend-core/src/components/grid/layout/GridRow.svelte
+++ b/packages/frontend-core/src/components/grid/layout/GridRow.svelte
@@ -48,6 +48,7 @@
{row}
{rowFocused}
{rowSelected}
+ cellSelected={$selectedCells[cellId]}
highlighted={rowHovered || rowFocused || reorderSource === column.name}
rowIdx={row.__idx}
topRow={top}
@@ -57,7 +58,6 @@
contentLines={$contentLines}
hidden={!$columnRenderMap[column.name]}
isSelectingCells={$isSelectingCells}
- selectedCells={$selectedCells}
/>
{/each}
diff --git a/packages/frontend-core/src/components/grid/layout/GridScrollWrapper.svelte b/packages/frontend-core/src/components/grid/layout/GridScrollWrapper.svelte
index 763b01dd84..e1f3339169 100644
--- a/packages/frontend-core/src/components/grid/layout/GridScrollWrapper.svelte
+++ b/packages/frontend-core/src/components/grid/layout/GridScrollWrapper.svelte
@@ -5,7 +5,7 @@
const {
rowHeight,
scroll,
- focusedCellId,
+ ui,
renderedRows,
maxScrollTop,
maxScrollLeft,
@@ -108,7 +108,7 @@
on:wheel={attachHandlers ? handleWheel : null}
on:touchstart={attachHandlers ? handleTouchStart : null}
on:touchmove={attachHandlers ? handleTouchMove : null}
- on:click|self={() => ($focusedCellId = null)}
+ on:click|self={ui.actions.blur}
>
diff --git a/packages/frontend-core/src/components/grid/layout/StickyColumn.svelte b/packages/frontend-core/src/components/grid/layout/StickyColumn.svelte
index d98c1d3d25..d9b3af9436 100644
--- a/packages/frontend-core/src/components/grid/layout/StickyColumn.svelte
+++ b/packages/frontend-core/src/components/grid/layout/StickyColumn.svelte
@@ -91,6 +91,7 @@
{cellId}
{rowFocused}
{rowSelected}
+ cellSelected={$selectedCells[cellId]}
highlighted={rowHovered || rowFocused}
rowIdx={row.__idx}
topRow={idx === 0}
@@ -100,7 +101,6 @@
column={$stickyColumn}
contentLines={$contentLines}
isSelectingCells={$isSelectingCells}
- selectedCells={$selectedCells}
/>
{/if}
diff --git a/packages/frontend-core/src/components/grid/stores/index.js b/packages/frontend-core/src/components/grid/stores/index.js
index cb7f5b1106..8e4414e363 100644
--- a/packages/frontend-core/src/components/grid/stores/index.js
+++ b/packages/frontend-core/src/components/grid/stores/index.js
@@ -20,7 +20,6 @@ import * as Table from "./datasources/table"
import * as ViewV2 from "./datasources/viewV2"
import * as NonPlus from "./datasources/nonPlus"
import * as Cache from "./cache"
-import * as Selection from "./selection"
const DependencyOrderedStores = [
Sort,
@@ -41,7 +40,6 @@ const DependencyOrderedStores = [
Users,
Menu,
Pagination,
- Selection,
Clipboard,
Config,
Notifications,
diff --git a/packages/frontend-core/src/components/grid/stores/selection.js b/packages/frontend-core/src/components/grid/stores/selection.js
deleted file mode 100644
index bcbdd50079..0000000000
--- a/packages/frontend-core/src/components/grid/stores/selection.js
+++ /dev/null
@@ -1,135 +0,0 @@
-import { derived, writable, get } from "svelte/store"
-import { getCellID, parseCellID } from "../lib/utils"
-
-export const createStores = () => {
- const cellSelection = writable({
- active: false,
- sourceCellId: null,
- targetCellId: null,
- })
-
- return {
- cellSelection,
- }
-}
-
-export const deriveStores = context => {
- const {
- cellSelection,
- rowLookupMap,
- columnLookupMap,
- rows,
- allVisibleColumns,
- } = context
-
- const isSelectingCells = derived(cellSelection, $cellSelection => {
- return $cellSelection.active
- })
-
- const selectedCells = derived(
- [cellSelection, rowLookupMap, columnLookupMap],
- ([$cellSelection, $rowLookupMap, $columnLookupMap]) => {
- const { sourceCellId, targetCellId } = $cellSelection
- if (!sourceCellId || !targetCellId || sourceCellId === targetCellId) {
- return {}
- }
- const $rows = get(rows)
- const $allVisibleColumns = get(allVisibleColumns)
-
- // Get source and target row and column indices
- const sourceInfo = parseCellID(sourceCellId)
- const targetInfo = parseCellID(targetCellId)
-
- // Row indices
- const sourceRowIndex = $rowLookupMap[sourceInfo.id]
- const targetRowIndex = $rowLookupMap[targetInfo.id]
- const lowerRowIndex = Math.min(sourceRowIndex, targetRowIndex)
- const upperRowIndex = Math.max(sourceRowIndex, targetRowIndex)
-
- // Column indices
- const sourceColIndex = $columnLookupMap[sourceInfo.field]
- const targetColIndex = $columnLookupMap[targetInfo.field]
- const lowerColIndex = Math.min(sourceColIndex, targetColIndex)
- const upperColIndex = Math.max(sourceColIndex, targetColIndex)
-
- // Build map of all cells inside these bounds
- let map = {}
- let rowId, colName, cellId
- for (let rowIdx = lowerRowIndex; rowIdx <= upperRowIndex; rowIdx++) {
- for (let colIdx = lowerColIndex; colIdx <= upperColIndex; colIdx++) {
- rowId = $rows[rowIdx]._id
- colName = $allVisibleColumns[colIdx].name
- cellId = getCellID(rowId, colName)
- map[cellId] = { rowIdx, colIdx }
- }
- }
- return map
- }
- )
-
- const selectedCellCount = derived(selectedCells, $selectedCells => {
- return Object.keys($selectedCells).length
- })
-
- return {
- isSelectingCells,
- selectedCells,
- selectedCellCount,
- }
-}
-
-export const createActions = context => {
- const { cellSelection } = context
-
- const startCellSelection = sourceCellId => {
- cellSelection.set({
- active: true,
- sourceCellId,
- targetCellId: sourceCellId,
- })
- }
-
- const updateCellSelection = targetCellId => {
- cellSelection.update(state => ({
- ...state,
- targetCellId,
- }))
- }
-
- const stopCellSelection = () => {
- cellSelection.update(state => ({
- ...state,
- active: false,
- }))
- }
-
- const clearCellSelection = () => {
- cellSelection.set({
- active: false,
- sourceCellId: null,
- targetCellId: null,
- })
- }
-
- return {
- cellSelection: {
- ...cellSelection,
- actions: {
- start: startCellSelection,
- update: updateCellSelection,
- stop: stopCellSelection,
- clear: clearCellSelection,
- },
- },
- }
-}
-
-export const initialise = context => {
- const { selectedCellCount, selectedRowCount, selectedRows } = context
-
- selectedCellCount.subscribe($selectedCellCount => {
- if ($selectedCellCount && get(selectedRowCount)) {
- selectedRows.set({})
- }
- })
-}
diff --git a/packages/frontend-core/src/components/grid/stores/ui.js b/packages/frontend-core/src/components/grid/stores/ui.js
index 3aeb278c89..f3858b5ede 100644
--- a/packages/frontend-core/src/components/grid/stores/ui.js
+++ b/packages/frontend-core/src/components/grid/stores/ui.js
@@ -7,7 +7,7 @@ import {
MediumRowHeight,
NewRowID,
} from "../lib/constants"
-import { parseCellID } from "../lib/utils"
+import { getCellID, parseCellID } from "../lib/utils"
export const createStores = context => {
const { props } = context
@@ -22,6 +22,11 @@ export const createStores = context => {
const keyboardBlocked = writable(false)
const isDragging = writable(false)
const buttonColumnWidth = writable(0)
+ const cellSelection = writable({
+ active: false,
+ sourceCellId: null,
+ targetCellId: null,
+ })
return {
focusedCellId,
@@ -35,6 +40,7 @@ export const createStores = context => {
isDragging,
buttonColumnWidth,
selectedRows,
+ cellSelection,
}
}
@@ -47,6 +53,9 @@ export const deriveStores = context => {
stickyColumn,
width,
selectedRows,
+ cellSelection,
+ columnLookupMap,
+ allVisibleColumns,
} = context
// Derive the current focused row ID
@@ -89,12 +98,67 @@ export const deriveStores = context => {
return Object.keys($selectedRows).length
})
+ // Derive whether or not we're actively selecting cells
+ const isSelectingCells = derived(cellSelection, $cellSelection => {
+ return $cellSelection.active
+ })
+
+ // Derive the full extent of all selected cells
+ const selectedCells = derived(
+ [cellSelection, rowLookupMap, columnLookupMap],
+ ([$cellSelection, $rowLookupMap, $columnLookupMap]) => {
+ const { sourceCellId, targetCellId } = $cellSelection
+ if (!sourceCellId || !targetCellId || sourceCellId === targetCellId) {
+ return {}
+ }
+ const $rows = get(rows)
+ const $allVisibleColumns = get(allVisibleColumns)
+
+ // Get source and target row and column indices
+ const sourceInfo = parseCellID(sourceCellId)
+ const targetInfo = parseCellID(targetCellId)
+
+ // Row indices
+ const sourceRowIndex = $rowLookupMap[sourceInfo.id]
+ const targetRowIndex = $rowLookupMap[targetInfo.id]
+ const lowerRowIndex = Math.min(sourceRowIndex, targetRowIndex)
+ const upperRowIndex = Math.max(sourceRowIndex, targetRowIndex)
+
+ // Column indices
+ const sourceColIndex = $columnLookupMap[sourceInfo.field]
+ const targetColIndex = $columnLookupMap[targetInfo.field]
+ const lowerColIndex = Math.min(sourceColIndex, targetColIndex)
+ const upperColIndex = Math.max(sourceColIndex, targetColIndex)
+
+ // Build map of all cells inside these bounds
+ let map = {}
+ let rowId, colName, cellId
+ for (let rowIdx = lowerRowIndex; rowIdx <= upperRowIndex; rowIdx++) {
+ for (let colIdx = lowerColIndex; colIdx <= upperColIndex; colIdx++) {
+ rowId = $rows[rowIdx]._id
+ colName = $allVisibleColumns[colIdx].name
+ cellId = getCellID(rowId, colName)
+ map[cellId] = { rowIdx, colIdx }
+ }
+ }
+ return map
+ }
+ )
+
+ // Derive the count of the selected cells
+ const selectedCellCount = derived(selectedCells, $selectedCells => {
+ return Object.keys($selectedCells).length
+ })
+
return {
focusedRowId,
focusedRow,
contentLines,
compact,
selectedRowCount,
+ isSelectingCells,
+ selectedCells,
+ selectedCellCount,
}
}
@@ -106,6 +170,8 @@ export const createActions = context => {
rowLookupMap,
rows,
selectedRowCount,
+ cellSelection,
+ selectedCells,
} = context
// Keep the last selected index to use with bulk selection
let lastSelectedIndex = null
@@ -114,6 +180,7 @@ export const createActions = context => {
const blur = () => {
focusedCellId.set(null)
hoveredRowId.set(null)
+ clearCellSelection()
}
// Toggles whether a certain row ID is selected or not
@@ -159,6 +226,36 @@ export const createActions = context => {
})
}
+ const startCellSelection = sourceCellId => {
+ cellSelection.set({
+ active: true,
+ sourceCellId,
+ targetCellId: sourceCellId,
+ })
+ }
+
+ const updateCellSelection = targetCellId => {
+ cellSelection.update(state => ({
+ ...state,
+ targetCellId,
+ }))
+ }
+
+ const stopCellSelection = () => {
+ cellSelection.update(state => ({
+ ...state,
+ active: false,
+ }))
+ }
+
+ const clearCellSelection = () => {
+ cellSelection.set({
+ active: false,
+ sourceCellId: null,
+ targetCellId: null,
+ })
+ }
+
return {
ui: {
actions: {
@@ -172,6 +269,15 @@ export const createActions = context => {
bulkSelectRows,
},
},
+ selectedCells: {
+ ...selectedCells,
+ actions: {
+ start: startCellSelection,
+ update: updateCellSelection,
+ stop: stopCellSelection,
+ clear: clearCellSelection,
+ },
+ },
}
}
@@ -189,8 +295,8 @@ export const initialise = context => {
fixedRowHeight,
selectedRowCount,
menu,
- cellSelection,
selectedCellCount,
+ selectedCells,
} = context
// Ensure we clear invalid rows from state if they disappear
@@ -254,7 +360,7 @@ export const initialise = context => {
// Clear cell selection when focusing a cell
if (id && get(selectedCellCount)) {
- cellSelection.actions.clear()
+ selectedCells.actions.clear()
}
// Close the menu if it was open
@@ -284,8 +390,15 @@ export const initialise = context => {
focusedCellId.set(null)
}
if (get(selectedCellCount)) {
- cellSelection.actions.clear()
+ selectedCells.actions.clear()
}
}
})
+
+ // Clear selected rows when selecting cells
+ selectedCellCount.subscribe($selectedCellCount => {
+ if ($selectedCellCount && get(selectedRowCount)) {
+ selectedRows.set({})
+ }
+ })
}