Refactor and code designing

This commit is contained in:
2026-03-02 03:30:22 +01:00
parent 6d7465ff18
commit e231f4ed05
80 changed files with 6690 additions and 4670 deletions

View File

@@ -0,0 +1,77 @@
import { Component, input, output, HostListener } from '@angular/core';
/**
* Generic positioned context-menu overlay.
*
* Usage:
* ```html
* @if (showMenu()) {
* <app-context-menu [x]="menuX()" [y]="menuY()" (closed)="closeMenu()" [width]="'w-48'">
* <button (click)="doSomething()" class="context-menu-item">Action</button>
* </app-context-menu>
* }
* ```
*
* Built-in item classes are available via the host styles:
* - `.context-menu-item` — normal item
* - `.context-menu-item-danger` — destructive (red) item
* - `.context-menu-divider` — horizontal separator
*/
@Component({
selector: 'app-context-menu',
standalone: true,
template: `
<!-- Invisible backdrop that captures clicks outside -->
<div class="fixed inset-0 z-40" (click)="closed.emit()"></div>
<!-- Positioned menu panel -->
<div
class="fixed z-50 bg-card border border-border rounded-lg shadow-lg py-1"
[class]="width()"
[style.left.px]="x()"
[style.top.px]="y()"
>
<ng-content />
</div>
`,
styles: [
`
:host {
display: contents;
}
/* Convenience classes consumers can use on projected buttons */
:host ::ng-deep .context-menu-item {
@apply w-full text-left px-3 py-1.5 text-sm hover:bg-secondary transition-colors text-foreground;
}
:host ::ng-deep .context-menu-item-danger {
@apply w-full text-left px-3 py-1.5 text-sm hover:bg-secondary transition-colors text-destructive;
}
:host ::ng-deep .context-menu-item-icon {
@apply w-full text-left px-3 py-2 text-sm hover:bg-secondary transition-colors text-foreground flex items-center gap-2;
}
:host ::ng-deep .context-menu-item-icon-danger {
@apply w-full text-left px-3 py-2 text-sm hover:bg-destructive/10 transition-colors text-destructive flex items-center gap-2;
}
:host ::ng-deep .context-menu-divider {
@apply border-t border-border my-1;
}
:host ::ng-deep .context-menu-empty {
@apply px-3 py-1.5 text-sm text-muted-foreground;
}
`,
],
})
export class ContextMenuComponent {
/** Horizontal position (px from left). */
x = input.required<number>();
/** Vertical position (px from top). */
y = input.required<number>();
/** Tailwind width class for the panel (default `w-48`). */
width = input<string>('w-48');
/** Emitted when the menu should close (backdrop click or Escape). */
closed = output<void>();
@HostListener('document:keydown.escape')
onEscape(): void {
this.closed.emit();
}
}