public onKeyDown()

in frontend/libs/spreadsheet/src/lib/grid/selection/selectionService.ts [199:417]


  public onKeyDown(event: KeyboardEvent): void {
    if (
      !isSpreadsheetTarget(event) ||
      isModalOpen() ||
      isNoteOpen() ||
      this.isPointClickMode
    )
      return;

    const isSelectAll = shortcutApi.is(Shortcut.SelectAll, event);

    // avoid browser default selection in all cases
    if (isSelectAll) {
      event.preventDefault();
    }

    if (
      !this._selection ||
      isCellEditorOpen() ||
      isContextMenuOpen() ||
      isMonacoEditorEvent(event)
    )
      return;
    // conflicts with other shortcuts that uses alt key
    if (event.altKey) return;

    let colDelta = 0;
    let rowDelta = 0;

    if (isSelectAll) {
      this.shortcuts$.next({ type: GridSelectionShortcutType.SelectAll });

      return;
    }

    if (event.key === 'Escape') {
      if (this.moveParams && this._selection) {
        this.updateSelection({
          updatedSelection: {
            ...this._selection,
            endRow: this._selection.startRow,
            endCol: this._selection.startCol,
          },
        });
        this.stopMoveMode();
      }

      return;
    }
    if (shortcutApi.is(Shortcut.SelectColumn, event)) {
      this.shortcuts$.next({ type: GridSelectionShortcutType.SelectColumn });

      return;
    }
    if (shortcutApi.is(Shortcut.SelectRow, event)) {
      this.shortcuts$.next({ type: GridSelectionShortcutType.SelectRow });

      return;
    }
    if (
      shortcutApi.is(Shortcut.ExtendRangeSelectionUp, event) ||
      shortcutApi.is(Shortcut.ExtendRangeSelectionDown, event) ||
      shortcutApi.is(Shortcut.ExtendRangeSelectionLeft, event) ||
      shortcutApi.is(Shortcut.ExtendRangeSelectionRight, event)
    ) {
      this.shortcuts$.next({
        type: GridSelectionShortcutType.ExtendRangeSelection,
        direction: event.key,
      });

      return;
    }

    if (
      shortcutApi.is(Shortcut.MoveSelectionNextAvailableDown, event) ||
      shortcutApi.is(Shortcut.MoveSelectionNextAvailableUp, event) ||
      shortcutApi.is(Shortcut.MoveSelectionNextAvailableLeft, event) ||
      shortcutApi.is(Shortcut.MoveSelectionNextAvailableRight, event)
    ) {
      return;
    }

    switch (event.key) {
      case KeyboardCode.ArrowDown: {
        rowDelta = 1;
        break;
      }
      case KeyboardCode.ArrowUp: {
        rowDelta = -1;
        break;
      }
      case KeyboardCode.ArrowLeft: {
        colDelta = -1;
        break;
      }
      case KeyboardCode.ArrowRight: {
        colDelta = 1;
        break;
      }
      case KeyboardCode.Tab: {
        event.preventDefault();
        this.shortcuts$.next({
          type: GridSelectionShortcutType.TabNavigation,
        });

        return;
      }
      case KeyboardCode.Enter: {
        rowDelta = 1;
        if (this.moveParams) {
          this.shortcuts$.next({
            type: GridSelectionShortcutType.MoveSelectAll,
            ...this.moveParams,
          });
          this.stopMoveMode();

          return;
        }
        break;
      }
      case KeyboardCode.Home: {
        this.shortcuts$.next({
          type: GridSelectionShortcutType.SelectionToRowEdge,
          direction: KeyboardCode.ArrowLeft,
        });
        break;
      }
      case KeyboardCode.End: {
        this.shortcuts$.next({
          type: GridSelectionShortcutType.SelectionToRowEdge,
          direction: KeyboardCode.ArrowRight,
        });
        break;
      }
      default: {
        return;
      }
    }

    if (
      this.moveParams &&
      this._selection.startCol + colDelta >= 1 &&
      this._selection.startRow + rowDelta >= 1
    ) {
      this.moveParams.colDelta += colDelta;
      this.moveParams.rowDelta += rowDelta;
      this.updateSelection({
        updatedSelection: {
          startCol: this._selection.startCol + colDelta,
          startRow: this._selection.startRow + rowDelta,
          endRow: this._selection.endRow + rowDelta,
          endCol: this._selection.endCol + colDelta,
        },
      });

      moveViewport(
        event.key,
        this._selection.startCol + colDelta,
        this._selection.startRow + rowDelta,
        this.dataView.currentZoom
      );

      return;
    }

    const colDirection =
      (colDelta && (colDelta > 0 ? 'right' : 'left')) || undefined;
    const rowDirection =
      (rowDelta && (rowDelta > 0 ? 'bottom' : 'top')) || undefined;
    let newSelection: GridSelection;

    if (event.shiftKey) {
      const nextCell = this.api.getNextCell({
        col: this._selection.endCol,
        row: this._selection.endRow,
        colDirection,
        rowDirection,
      });

      newSelection = {
        startCol: this._selection.startCol,
        startRow: this._selection.startRow,
        endCol: nextCell.col,
        endRow: nextCell.row,
      };
    } else {
      const nextCell = this.api.getNextCell({
        col:
          colDirection === 'right'
            ? this._selection.endCol
            : this._selection.startCol,
        row:
          rowDirection === 'bottom'
            ? this._selection.endRow
            : this._selection.startRow,
        colDirection,
        rowDirection,
      });

      const { cols, rows } = defaults.viewport;

      const updatedCol = Math.min(cols, Math.max(1, nextCell.col));
      const updatedRow = Math.min(rows, Math.max(1, nextCell.row));

      newSelection = {
        startCol: updatedCol,
        startRow: updatedRow,
        endCol: updatedCol,
        endRow: updatedRow,
      };
    }

    this.updateSelection({
      updatedSelection: newSelection,
      quiet: false,
      key: event.key,
    });
    this.moveViewportToSelection(newSelection.endCol, newSelection.endRow);
  }