Add basic keyboard interactions to dataspaces

This commit is contained in:
Andrew Kingston 2023-03-08 08:32:03 +00:00
parent 045d0c89af
commit 48309349ae
6 changed files with 99 additions and 10 deletions

View File

@ -0,0 +1,68 @@
<script>
import { getContext, onMount } from "svelte"
const { rows, selectedCellId, columns, selectedCellRow } = getContext("sheet")
const handleKeyDown = e => {
switch (e.key) {
case "ArrowLeft":
changeSelectedColumn(-1)
break
case "ArrowRight":
changeSelectedColumn(1)
break
case "ArrowUp":
changeSelectedRow(-1)
break
case "ArrowDown":
changeSelectedRow(1)
break
case "Delete":
deleteSelectedCell()
break
}
}
const changeSelectedColumn = delta => {
const cellId = $selectedCellId
if (!cellId) {
return
}
const cols = $columns
const split = cellId.split("-")
const columnName = split[1]
const column = cols.findIndex(col => col.name === columnName)
const newColumn = cols[column + delta]
if (newColumn) {
$selectedCellId = `${split[0]}-${newColumn.name}`
}
}
const changeSelectedRow = delta => {
const row = $selectedCellRow
const cellId = $selectedCellId
if (!row) {
return
}
const newRow = $rows[row.__idx + delta]
if (newRow) {
const split = cellId.split("-")
$selectedCellId = `${newRow._id}-${split[1]}`
}
}
const deleteSelectedCell = () => {
if (!$selectedCellId) {
return
}
const [rowId, column] = $selectedCellId.split("-")
rows.actions.updateRow(rowId, column, null)
}
onMount(() => {
document.addEventListener("keydown", handleKeyDown)
return () => {
document.removeEventListener("keydown", handleKeyDown)
}
})
</script>

View File

@ -9,7 +9,7 @@
import { createColumnsStores } from "./stores/columns"
import { createScrollStores } from "./stores/scroll"
import { createBoundsStores } from "./stores/bounds"
import { createInterfaceStores } from "./stores/interface"
import { createUIStores } from "./stores/ui"
export { createUserStores } from "./stores/users"
import { createWebsocket } from "./websocket"
import { createUserStores } from "./stores/users"
@ -23,6 +23,8 @@
import MenuOverlay from "./MenuOverlay.svelte"
import StickyColumn from "./StickyColumn.svelte"
import UserAvatars from "./UserAvatars.svelte"
import KeyboardManager from "./KeyboardManager.svelte"
import { clickOutside } from "@budibase/bbui"
export let API
export let tableId
@ -60,12 +62,12 @@
context = { ...context, ...createScrollStores(context) }
context = { ...context, ...createViewportStores(context) }
context = { ...context, ...createReorderStores(context) }
context = { ...context, ...createInterfaceStores(context) }
context = { ...context, ...createUIStores(context) }
context = { ...context, ...createUserStores(context) }
context = { ...context, ...createMenuStores(context) }
// Reference some stores for local use
const { isResizing, isReordering } = context
const { isResizing, isReordering, ui } = context
// Keep config store up to date
$: config.set({
@ -88,10 +90,11 @@
<div
class="sheet"
id="sheet-{rand}"
class:is-resizing={$isResizing}
class:is-reordering={$isReordering}
use:clickOutside={ui.actions.blur}
style="--cell-height:{cellHeight}px;"
id="sheet-{rand}"
>
<div class="controls">
<div class="controls-left">
@ -112,6 +115,7 @@
<ScrollOverlay />
<MenuOverlay />
</div>
<KeyboardManager />
</div>
<style>

View File

@ -48,7 +48,7 @@
value={row[column.name]}
schema={column.schema}
selected={$selectedCellId === cellId}
onChange={val => rows.actions.updateRow(row._id, column, val)}
onChange={val => rows.actions.updateRow(row._id, column.name, val)}
readonly={column.schema.autocolumn}
/>
</SheetCell>

View File

@ -134,7 +134,7 @@
schema={$stickyColumn.schema}
selected={$selectedCellId === cellId}
onChange={val =>
rows.actions.updateRow(row._id, $stickyColumn, val)}
rows.actions.updateRow(row._id, $stickyColumn.name, val)}
readonly={$stickyColumn.schema.autocolumn}
/>
</SheetCell>

View File

@ -169,12 +169,12 @@ export const createRowsStore = context => {
const $rows = get(rows)
const index = $rows.findIndex(x => x._id === rowId)
const row = $rows[index]
if (index === -1 || row?.[column.name] === value) {
if (index === -1 || row?.[column] === value) {
return
}
// Immediately update state so that the change is reflected
let newRow = { ...row, [column.name]: value }
let newRow = { ...row, [column]: value }
rows.update(state => {
state[index] = { ...newRow }
return state

View File

@ -1,6 +1,6 @@
import { writable, get, derived } from "svelte/store"
export const createInterfaceStores = context => {
export const createUIStores = context => {
const { rows, rowLookupMap } = context
const selectedCellId = writable(null)
const selectedRows = writable({})
@ -62,5 +62,22 @@ export const createInterfaceStores = context => {
}
})
return { selectedCellId, selectedRows, hoveredRowId, selectedCellRow }
// Callback when leaving the sheet, deselecting all focussed or selected items
const blur = () => {
selectedCellId.set(null)
selectedRows.set({})
hoveredRowId.set(null)
}
return {
selectedCellId,
selectedRows,
hoveredRowId,
selectedCellRow,
ui: {
actions: {
blur,
},
},
}
}