89 lines
2.2 KiB
TypeScript
89 lines
2.2 KiB
TypeScript
|
|
import {
|
||
|
|
Directive,
|
||
|
|
ElementRef,
|
||
|
|
EventEmitter,
|
||
|
|
OnDestroy,
|
||
|
|
Output,
|
||
|
|
Input,
|
||
|
|
} from '@angular/core';
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Long-Press Directive — CUB-26
|
||
|
|
// Emits after a sustained press (500ms default).
|
||
|
|
// Used on agent cards to bypass the drawer and open Session Log directly.
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
@Directive({
|
||
|
|
selector: '[appLongPress]',
|
||
|
|
standalone: true,
|
||
|
|
host: {
|
||
|
|
'(mousedown)': 'onMouseDown($event)',
|
||
|
|
'(mouseup)': 'onMouseUp()',
|
||
|
|
'(mouseleave)': 'onMouseLeave()',
|
||
|
|
'(touchstart)': 'onTouchStart($event)',
|
||
|
|
'(touchend)': 'onTouchEnd()',
|
||
|
|
'(touchmove)': 'onTouchMove()',
|
||
|
|
'(contextmenu)': 'onContextMenu($event)',
|
||
|
|
},
|
||
|
|
})
|
||
|
|
export class LongPressDirective implements OnDestroy {
|
||
|
|
/** Duration in ms before a press counts as a long press. */
|
||
|
|
@Input() appLongPressDuration = 500;
|
||
|
|
|
||
|
|
/** Emits when a long press is detected. Payload is the original event. */
|
||
|
|
@Output() readonly appLongPress = new EventEmitter<MouseEvent | TouchEvent>();
|
||
|
|
|
||
|
|
private timer: ReturnType<typeof setTimeout> | null = null;
|
||
|
|
private isLongPress = false;
|
||
|
|
|
||
|
|
onMouseDown(event: MouseEvent): void {
|
||
|
|
this.isLongPress = false;
|
||
|
|
this.timer = setTimeout(() => {
|
||
|
|
this.isLongPress = true;
|
||
|
|
this.appLongPress.emit(event);
|
||
|
|
}, this.appLongPressDuration);
|
||
|
|
}
|
||
|
|
|
||
|
|
onMouseUp(): void {
|
||
|
|
this.clearTimer();
|
||
|
|
}
|
||
|
|
|
||
|
|
onMouseLeave(): void {
|
||
|
|
this.clearTimer();
|
||
|
|
}
|
||
|
|
|
||
|
|
onTouchStart(event: TouchEvent): void {
|
||
|
|
this.isLongPress = false;
|
||
|
|
this.timer = setTimeout(() => {
|
||
|
|
this.isLongPress = true;
|
||
|
|
this.appLongPress.emit(event);
|
||
|
|
}, this.appLongPressDuration);
|
||
|
|
}
|
||
|
|
|
||
|
|
onTouchEnd(): void {
|
||
|
|
this.clearTimer();
|
||
|
|
}
|
||
|
|
|
||
|
|
onTouchMove(): void {
|
||
|
|
// Cancel on touch move (finger moved)
|
||
|
|
this.clearTimer();
|
||
|
|
}
|
||
|
|
|
||
|
|
onContextMenu(event: MouseEvent): void {
|
||
|
|
// Prevent native context menu on long press
|
||
|
|
if (this.isLongPress) {
|
||
|
|
event.preventDefault();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
ngOnDestroy(): void {
|
||
|
|
this.clearTimer();
|
||
|
|
}
|
||
|
|
|
||
|
|
private clearTimer(): void {
|
||
|
|
if (this.timer !== null) {
|
||
|
|
clearTimeout(this.timer);
|
||
|
|
this.timer = null;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|