66 lines
1.7 KiB
TypeScript
66 lines
1.7 KiB
TypeScript
import { NgClass } from '@angular/common';
|
|
import {
|
|
ChangeDetectionStrategy,
|
|
Component,
|
|
ElementRef,
|
|
computed,
|
|
input,
|
|
output,
|
|
viewChild,
|
|
} from '@angular/core';
|
|
|
|
import { ModalSize } from '../../../core/services/modal.service';
|
|
|
|
@Component({
|
|
selector: 'app-modal-shell',
|
|
imports: [NgClass],
|
|
templateUrl: './modal-shell.component.html',
|
|
styleUrl: './modal-shell.component.scss',
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
})
|
|
export class ModalShellComponent {
|
|
private readonly panel = viewChild.required<ElementRef<HTMLElement>>('panel');
|
|
|
|
readonly title = input<string | undefined>();
|
|
readonly size = input<ModalSize>('md');
|
|
readonly showCloseButton = input(true);
|
|
|
|
readonly backdropClick = output<void>();
|
|
readonly closeRequested = output<void>();
|
|
|
|
protected readonly dialogClass = computed(() => {
|
|
const size = this.size();
|
|
|
|
return {
|
|
'modal-shell__dialog--qr': size === 'qr',
|
|
'modal-sm': size === 'sm',
|
|
'modal-lg': size === 'lg',
|
|
'modal-xl': size === 'xl',
|
|
'modal-shell__dialog--full': size === 'full',
|
|
};
|
|
});
|
|
|
|
protected readonly titleId = `modal-title-${Math.random().toString(36).slice(2, 9)}`;
|
|
|
|
protected get ariaLabelledBy(): string | null {
|
|
return this.title() ? this.titleId : null;
|
|
}
|
|
|
|
focusInitialElement(): void {
|
|
const panel = this.panel().nativeElement;
|
|
const focusTarget = panel.querySelector<HTMLElement>(
|
|
[
|
|
'[autofocus]',
|
|
'button:not([disabled])',
|
|
'[href]',
|
|
'input:not([disabled])',
|
|
'select:not([disabled])',
|
|
'textarea:not([disabled])',
|
|
'[tabindex]:not([tabindex="-1"])',
|
|
].join(', '),
|
|
);
|
|
|
|
(focusTarget ?? panel).focus();
|
|
}
|
|
}
|