Added keyboard navigation

This commit is contained in:
Eugene 2023-07-21 18:32:38 +03:00
parent 8aad89631b
commit 29b95c6b73
6 changed files with 70 additions and 11 deletions

View File

@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + TS</title>
<title>Spreadsheet example</title>
</head>
<body>
<div id="spreadsheet"></div>

View File

@ -18,6 +18,9 @@ export class Editor {
this.element.classList.add('hide')
this.element.blur()
window.removeEventListener('click', this.handleClickOutside)
this.element.removeEventListener('keydown', this.handleKeydown)
this.root.focusTable()
}
show(position: Position) {

View File

@ -12,7 +12,7 @@ export class Scroller {
private verticalScroller: HTMLDivElement
private horizontalScroller: HTMLDivElement
private root: Spreadsheet
private isSelecting = false
constructor(root: Spreadsheet) {
@ -24,6 +24,7 @@ export class Scroller {
this.element.style.height = this.root.config.view.height + 'px'
this.element.style.width = this.root.config.view.width + 'px'
this.element.tabIndex = -1
this.updateScrollerSize() //* Init size set
@ -31,10 +32,10 @@ export class Scroller {
this.element.addEventListener('mousedown', this.handleClick)
this.element.addEventListener('mousemove', event => {
if(!this.isSelecting) return;
const {offsetX, offsetY} = event
if (!this.isSelecting) return;
const { offsetX, offsetY } = event
const lastSelectedCell = this.root.getCellByCoords(offsetX, offsetY)
if(this.root.selection.selectedRange) {
if (this.root.selection.selectedRange) {
this.root.selection.selectedRange.to = lastSelectedCell
}
this.root.renderSheet()
@ -49,18 +50,64 @@ export class Scroller {
this.root.showEditor(position)
})
this.element.addEventListener('keydown', this.handleKeydown)
}
private handleKeydown = (event: KeyboardEvent) => {
event.preventDefault()
console.log(event.key)
//* Navigation
if (['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(event.key)) {
this.root.selection.selectedRange = null
switch (event.key) {
case 'ArrowLeft': {
if (this.root.selection.selectedCell && this.root.selection.selectedCell.column > 0) {
console.log('tick')
this.root.selection.selectedCell.column -= 1
this.root.renderSheet()
}
break;
}
case 'ArrowRight': {
if (this.root.selection.selectedCell && this.root.selection.selectedCell.column < this.root.config.columns.length - 1) {
this.root.selection.selectedCell.column += 1
this.root.renderSheet()
}
break;
}
case 'ArrowUp': {
if (this.root.selection.selectedCell && this.root.selection.selectedCell.row > 0) {
this.root.selection.selectedCell.row -= 1
this.root.renderSheet()
}
break;
}
case 'ArrowDown': {
if (this.root.selection.selectedCell && this.root.selection.selectedCell.row < this.root.config.rows.length - 1) {
this.root.selection.selectedCell.row += 1
this.root.renderSheet()
}
break;
}
}
}
if(event.key === 'F2') {
if(!this.root.selection.selectedCell) return;
this.root.showEditor(this.root.selection.selectedCell)
}
}
private handleClick = (event: MouseEvent) => {
if(event.button !== 0) return; // Left mouse button
const {offsetX, offsetY} = event
if (event.button !== 0) return; // Left mouse button
const { offsetX, offsetY } = event
const clickedCell = this.root.getCellByCoords(offsetX, offsetY)
this.isSelecting = true
this.root.selection.selectedRange = {
from: clickedCell,
to: clickedCell
}
this.root.selection.selectedCell = clickedCell
this.root.selection.selectedCell = clickedCell
this.root.renderSheet()
}

View File

@ -59,13 +59,11 @@ export class Sheet {
const firstColIdx = this.root.viewport.firstCol
for(let row = firstRowIdx; row <= lastRowIdx; row++) {
for(let col = firstColIdx; col <= lastColIdx; col++ ) {
if(!this.root.config.columns[col] || !this.root.config.rows[row]) break; //* Prevent read undefined
this.renderCell({column: col, row})
}
}
}

View File

@ -67,11 +67,13 @@ export class Spreadsheet {
}
private buildComponent(): void {
const content = document.createElement('div') //* Abstract
content.classList.add('content')
content.appendChild(this.header.element)
content.appendChild(this.sheet.element)
content.classList.add('content')
this.table.element.appendChild(this.toolbar.element)
this.table.element.appendChild(content)
this.table.element.appendChild(this.scroller.element)
@ -97,6 +99,10 @@ export class Spreadsheet {
return this.config.view
}
focusTable() {
this.scroller.element.focus()
}
getCellByCoords(x: number, y: number) {
return this.sheet.getCellByCoords(x, y)
}

View File

@ -10,6 +10,8 @@
position: relative;
isolation: isolate;
border: 2px solid black;
}
.sheet{
@ -21,6 +23,9 @@
overflow: scroll;
box-sizing: border-box;
transform: translateZ(0);
&:focus {
outline: none;
}
}
.editor {