File

src/lib/components/spatial-search-keyboard-ui-behavior/spatial-search-keyboard-ui-behavior.component.ts

Description

Position

Index

Properties

Properties

x
x: number
Type : number

X coordinate

y
y: number
Type : number

Y coordinate

z
z: number
Type : number

Z coordinate

import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { injectFeaturePath, injectLogEvent } from '@hra-ui/common/analytics';
import { CoreEvents } from '@hra-ui/common/analytics/events';

/** Position */
export interface Position {
  /** X coordinate */
  x: number;
  /** Y coordinate */
  y: number;
  /** Z coordinate */
  z: number;
}

/** Direction multipliers for each key */
const DIRECTION_FACTORS: Record<string, number[]> = {
  q: [0, 0, 1],
  e: [0, 0, -1],
  w: [0, 1, 0],
  s: [0, -1, 0],
  a: [-1, 0, 0],
  d: [1, 0, 0],
};

/** Set of direction keys */
const DIRECTION_KEYS = new Set(Object.keys(DIRECTION_FACTORS));

/**
 * Behavioral component for spatial search keyboard UI
 */
@Component({
  selector: 'ccf-spatial-search-keyboard-ui-behavior',
  standalone: false,
  templateUrl: './spatial-search-keyboard-ui-behavior.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
  host: {
    '(document:keydown)': 'handleKey($event)',
    '(document:keyup)': 'keyUp($event)',
  },
})
export class SpatialSearchKeyboardUIBehaviorComponent {
  /** Amount the position shifts for each key press */
  @Input() delta = 1;

  /** Input of spatial search keyboard uibehavior component */
  @Input() shiftDelta = 2;

  /** Current position of spatial search */
  @Input() position!: Position;

  /** Disable position changes */
  @Input() disablePositionChange = false;

  /** Emits when position changes */
  @Output() readonly changePosition = new EventEmitter<Position>();

  /** Current key being pressed/clicked */
  currentKey?: string;

  /** Current delta */
  currentDelta!: number;

  /** True while shift key is pressed */
  shiftPressed = false;

  private readonly featurePath = injectFeaturePath();

  private readonly logEvent = injectLogEvent();

  /**
   * Shifts position based on key
   * @param key Key value
   */
  updatePosition(key: string): void {
    this.currentDelta = this.shiftPressed ? this.shiftDelta : this.delta;
    this.currentKey = key.toLowerCase();
    const factors = DIRECTION_FACTORS[this.currentKey];
    if (factors !== undefined) {
      const { x, y, z } = this.position;
      const delta = this.currentDelta;
      this.position = {
        x: x + factors[0] * delta,
        y: y + factors[1] * delta,
        z: z + factors[2] * delta,
      };

      this.changePosition.emit(this.position);
    }
  }

  /**
   * Listens for keydown keyboard event and updates the position
   * @param target Keyboard event
   */
  handleKey(target: KeyboardEvent): void {
    if (
      this.disablePositionChange ||
      !DIRECTION_KEYS.has(target.key.toLowerCase()) ||
      target.target instanceof HTMLInputElement
    ) {
      return;
    }
    if (target.shiftKey) {
      this.shiftPressed = true;
    }
    target.preventDefault();
    this.logEvent(CoreEvents.Keyboard, {
      path: `${this.featurePath()}.keyboard.${target.key}`,
      trigger: 'keydown',
      triggerData: target,
    });
    this.updatePosition(target.key);
  }

  /**
   * Listens for keyup keyboard event and updates currentKey / shiftPressed
   * @param target Keyboard event
   */
  keyUp(target: KeyboardEvent): void {
    if (target.key === 'Shift') {
      this.shiftPressed = false;
    } else {
      this.currentKey = undefined;
    }
  }

  /**
   * Updates the position when a key is clicked
   * @param key Key value
   */
  keyClick(key: string): void {
    this.updatePosition(key);
  }

  /**
   * Updates current key when a key is hovered over
   * @param key Key value
   */
  keyHover(key?: string): void {
    this.currentKey = key;
  }
}

results matching ""

    No results matching ""