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';
export interface Position {
x: number;
y: number;
z: number;
}
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],
};
const DIRECTION_KEYS = new Set(Object.keys(DIRECTION_FACTORS));
@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 {
@Input() delta = 1;
@Input() shiftDelta = 2;
@Input() position!: Position;
@Input() disablePositionChange = false;
@Output() readonly changePosition = new EventEmitter<Position>();
currentKey?: string;
currentDelta!: number;
shiftPressed = false;
private readonly featurePath = injectFeaturePath();
private readonly logEvent = injectLogEvent();
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);
}
}
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);
}
keyUp(target: KeyboardEvent): void {
if (target.key === 'Shift') {
this.shiftPressed = false;
} else {
this.currentKey = undefined;
}
}
keyClick(key: string): void {
this.updatePosition(key);
}
keyHover(key?: string): void {
this.currentKey = key;
}
}