Add basic keyboard interactions to dataspaces
This commit is contained in:
parent
045d0c89af
commit
48309349ae
|
@ -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>
|
|
@ -9,7 +9,7 @@
|
||||||
import { createColumnsStores } from "./stores/columns"
|
import { createColumnsStores } from "./stores/columns"
|
||||||
import { createScrollStores } from "./stores/scroll"
|
import { createScrollStores } from "./stores/scroll"
|
||||||
import { createBoundsStores } from "./stores/bounds"
|
import { createBoundsStores } from "./stores/bounds"
|
||||||
import { createInterfaceStores } from "./stores/interface"
|
import { createUIStores } from "./stores/ui"
|
||||||
export { createUserStores } from "./stores/users"
|
export { createUserStores } from "./stores/users"
|
||||||
import { createWebsocket } from "./websocket"
|
import { createWebsocket } from "./websocket"
|
||||||
import { createUserStores } from "./stores/users"
|
import { createUserStores } from "./stores/users"
|
||||||
|
@ -23,6 +23,8 @@
|
||||||
import MenuOverlay from "./MenuOverlay.svelte"
|
import MenuOverlay from "./MenuOverlay.svelte"
|
||||||
import StickyColumn from "./StickyColumn.svelte"
|
import StickyColumn from "./StickyColumn.svelte"
|
||||||
import UserAvatars from "./UserAvatars.svelte"
|
import UserAvatars from "./UserAvatars.svelte"
|
||||||
|
import KeyboardManager from "./KeyboardManager.svelte"
|
||||||
|
import { clickOutside } from "@budibase/bbui"
|
||||||
|
|
||||||
export let API
|
export let API
|
||||||
export let tableId
|
export let tableId
|
||||||
|
@ -60,12 +62,12 @@
|
||||||
context = { ...context, ...createScrollStores(context) }
|
context = { ...context, ...createScrollStores(context) }
|
||||||
context = { ...context, ...createViewportStores(context) }
|
context = { ...context, ...createViewportStores(context) }
|
||||||
context = { ...context, ...createReorderStores(context) }
|
context = { ...context, ...createReorderStores(context) }
|
||||||
context = { ...context, ...createInterfaceStores(context) }
|
context = { ...context, ...createUIStores(context) }
|
||||||
context = { ...context, ...createUserStores(context) }
|
context = { ...context, ...createUserStores(context) }
|
||||||
context = { ...context, ...createMenuStores(context) }
|
context = { ...context, ...createMenuStores(context) }
|
||||||
|
|
||||||
// Reference some stores for local use
|
// Reference some stores for local use
|
||||||
const { isResizing, isReordering } = context
|
const { isResizing, isReordering, ui } = context
|
||||||
|
|
||||||
// Keep config store up to date
|
// Keep config store up to date
|
||||||
$: config.set({
|
$: config.set({
|
||||||
|
@ -88,10 +90,11 @@
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="sheet"
|
class="sheet"
|
||||||
|
id="sheet-{rand}"
|
||||||
class:is-resizing={$isResizing}
|
class:is-resizing={$isResizing}
|
||||||
class:is-reordering={$isReordering}
|
class:is-reordering={$isReordering}
|
||||||
|
use:clickOutside={ui.actions.blur}
|
||||||
style="--cell-height:{cellHeight}px;"
|
style="--cell-height:{cellHeight}px;"
|
||||||
id="sheet-{rand}"
|
|
||||||
>
|
>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<div class="controls-left">
|
<div class="controls-left">
|
||||||
|
@ -112,6 +115,7 @@
|
||||||
<ScrollOverlay />
|
<ScrollOverlay />
|
||||||
<MenuOverlay />
|
<MenuOverlay />
|
||||||
</div>
|
</div>
|
||||||
|
<KeyboardManager />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
value={row[column.name]}
|
value={row[column.name]}
|
||||||
schema={column.schema}
|
schema={column.schema}
|
||||||
selected={$selectedCellId === cellId}
|
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}
|
readonly={column.schema.autocolumn}
|
||||||
/>
|
/>
|
||||||
</SheetCell>
|
</SheetCell>
|
||||||
|
|
|
@ -134,7 +134,7 @@
|
||||||
schema={$stickyColumn.schema}
|
schema={$stickyColumn.schema}
|
||||||
selected={$selectedCellId === cellId}
|
selected={$selectedCellId === cellId}
|
||||||
onChange={val =>
|
onChange={val =>
|
||||||
rows.actions.updateRow(row._id, $stickyColumn, val)}
|
rows.actions.updateRow(row._id, $stickyColumn.name, val)}
|
||||||
readonly={$stickyColumn.schema.autocolumn}
|
readonly={$stickyColumn.schema.autocolumn}
|
||||||
/>
|
/>
|
||||||
</SheetCell>
|
</SheetCell>
|
||||||
|
|
|
@ -169,12 +169,12 @@ export const createRowsStore = context => {
|
||||||
const $rows = get(rows)
|
const $rows = get(rows)
|
||||||
const index = $rows.findIndex(x => x._id === rowId)
|
const index = $rows.findIndex(x => x._id === rowId)
|
||||||
const row = $rows[index]
|
const row = $rows[index]
|
||||||
if (index === -1 || row?.[column.name] === value) {
|
if (index === -1 || row?.[column] === value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Immediately update state so that the change is reflected
|
// Immediately update state so that the change is reflected
|
||||||
let newRow = { ...row, [column.name]: value }
|
let newRow = { ...row, [column]: value }
|
||||||
rows.update(state => {
|
rows.update(state => {
|
||||||
state[index] = { ...newRow }
|
state[index] = { ...newRow }
|
||||||
return state
|
return state
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { writable, get, derived } from "svelte/store"
|
import { writable, get, derived } from "svelte/store"
|
||||||
|
|
||||||
export const createInterfaceStores = context => {
|
export const createUIStores = context => {
|
||||||
const { rows, rowLookupMap } = context
|
const { rows, rowLookupMap } = context
|
||||||
const selectedCellId = writable(null)
|
const selectedCellId = writable(null)
|
||||||
const selectedRows = writable({})
|
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,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue