Added keyboard navigation
This commit is contained in:
parent
8aad89631b
commit
29b95c6b73
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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,11 +50,57 @@ 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 = {
|
||||
|
|
|
|||
|
|
@ -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})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue