ObsiViewer/src/app/graph/ui/settings-panel.component.ts

181 lines
5.4 KiB
TypeScript

import { Component, ChangeDetectionStrategy, input, output, inject, effect } from '@angular/core';
import { CommonModule } from '@angular/common';
import { GraphConfig } from '../graph-settings.types';
import { GraphSettingsService } from '../graph-settings.service';
import { GraphSettingsAccordionComponent } from '../../../components/graph-settings/graph-settings-accordion.component';
@Component({
selector: 'app-graph-settings-panel',
standalone: true,
imports: [
CommonModule,
GraphSettingsAccordionComponent
],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="settings-panel">
@if (isOpen()) {
<div class="backdrop" (click)="close.emit()"></div>
<div class="panel-content">
<div class="panel-header">
<h2 class="text-lg font-semibold text-gray-900 dark:text-gray-100">Graph settings</h2>
<div class="flex items-center gap-2">
<!-- Expand all -->
<button
type="button"
class="btn-standard-icon"
title="Expand all"
(click)="accordion?.expandAll()">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 12h16M12 4v16" />
</svg>
</button>
<!-- Collapse all -->
<button
type="button"
class="btn-standard-icon"
title="Collapse all"
(click)="accordion?.collapseAll()">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 12h16" />
</svg>
</button>
<button
type="button"
(click)="onResetAll()"
class="btn-standard-icon"
title="Reset all settings">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</svg>
</button>
<button
type="button"
(click)="close.emit()"
(keydown.escape)="close.emit()"
class="btn-standard-icon"
aria-label="Close settings"
title="Close">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</div>
<div class="panel-body">
<ov-graph-settings-accordion
#accordion
[config]="config()"
(configChange)="onConfigChange($event)"
(animateRequested)="animateRequested.emit()">
</ov-graph-settings-accordion>
</div>
</div>
}
</div>
`,
styles: [`
.settings-panel {
position: fixed;
inset: 0;
z-index: 2000;
pointer-events: none;
}
.backdrop {
position: fixed;
inset: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1990;
pointer-events: auto;
}
.panel-content {
position: fixed;
top: 0;
right: 0;
bottom: 0;
width: 100%;
max-width: 400px;
background-color: white;
box-shadow: -4px 0 6px -1px rgba(0, 0, 0, 0.1), -2px 0 4px -1px rgba(0, 0, 0, 0.06);
display: flex;
flex-direction: column;
z-index: 2001;
transform: translateX(0);
pointer-events: auto;
}
:host-context(.dark) .panel-content {
background-color: #1F2937;
}
.panel-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem 1.5rem;
border-bottom: 1px solid #E5E7EB;
}
:host-context(.dark) .panel-header {
border-bottom-color: #374151;
}
.panel-body {
flex: 1;
overflow-y: auto;
padding: 1rem;
}
@media (max-width: 768px) {
.panel-content {
max-width: 100%;
}
}
`]
})
export class GraphSettingsPanelComponent {
isOpen = input.required<boolean>();
close = output<void>();
animateRequested = output<void>();
private settingsService = inject(GraphSettingsService);
config = this.settingsService.config;
constructor() {
// Listen to Escape key globally when panel is open
effect(() => {
if (!this.isOpen()) {
return;
}
const handler = (e: KeyboardEvent) => {
if (e.key === 'Escape') {
this.close.emit();
}
};
document.addEventListener('keydown', handler);
return () => document.removeEventListener('keydown', handler);
});
}
onConfigChange(patch: Partial<GraphConfig>): void {
this.settingsService.save(patch);
}
onResetAll(): void {
if (confirm('Reset all graph settings to defaults?')) {
this.settingsService.resetToDefaults();
}
}
}