chore: update TypeScript build info cache
This commit is contained in:
@@ -0,0 +1,326 @@
|
||||
import { Component, ChangeDetectionStrategy, output, signal } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
export interface GraphFilters {
|
||||
showTags: boolean;
|
||||
showAttachments: boolean;
|
||||
existingFilesOnly: boolean;
|
||||
showOrphans: boolean;
|
||||
searchQuery: string;
|
||||
}
|
||||
|
||||
export interface GraphDisplay {
|
||||
showArrows: boolean;
|
||||
textFadeThreshold: number;
|
||||
nodeSize: number;
|
||||
linkThickness: number;
|
||||
}
|
||||
|
||||
export interface GraphForces {
|
||||
chargeStrength: number;
|
||||
linkDistance: number;
|
||||
centerStrength: number;
|
||||
}
|
||||
|
||||
export interface GraphOptions {
|
||||
filters: GraphFilters;
|
||||
display: GraphDisplay;
|
||||
forces: GraphForces;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-graph-options-panel',
|
||||
standalone: true,
|
||||
imports: [CommonModule, FormsModule],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: `
|
||||
<div class="graph-options-panel bg-white dark:bg-gray-800 border-l border-gray-200 dark:border-gray-700 h-full overflow-y-auto">
|
||||
<div class="p-4 space-y-6">
|
||||
|
||||
<!-- Filters Section -->
|
||||
<section>
|
||||
<h3 class="text-sm font-semibold text-gray-900 dark:text-gray-100 mb-3 flex items-center gap-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" />
|
||||
</svg>
|
||||
Filters
|
||||
</h3>
|
||||
|
||||
<div class="space-y-2">
|
||||
<label class="flex items-center gap-2 cursor-pointer group">
|
||||
<input
|
||||
type="checkbox"
|
||||
[(ngModel)]="filters().showTags"
|
||||
(change)="emitOptionsChange()"
|
||||
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700">
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300 group-hover:text-gray-900 dark:group-hover:text-gray-100">Tags</span>
|
||||
</label>
|
||||
|
||||
<label class="flex items-center gap-2 cursor-pointer group">
|
||||
<input
|
||||
type="checkbox"
|
||||
[(ngModel)]="filters().showAttachments"
|
||||
(change)="emitOptionsChange()"
|
||||
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700">
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300 group-hover:text-gray-900 dark:group-hover:text-gray-100">Attachments</span>
|
||||
</label>
|
||||
|
||||
<label class="flex items-center gap-2 cursor-pointer group">
|
||||
<input
|
||||
type="checkbox"
|
||||
[(ngModel)]="filters().existingFilesOnly"
|
||||
(change)="emitOptionsChange()"
|
||||
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700">
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300 group-hover:text-gray-900 dark:group-hover:text-gray-100">Existing files only</span>
|
||||
</label>
|
||||
|
||||
<label class="flex items-center gap-2 cursor-pointer group">
|
||||
<input
|
||||
type="checkbox"
|
||||
[(ngModel)]="filters().showOrphans"
|
||||
(change)="emitOptionsChange()"
|
||||
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700">
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300 group-hover:text-gray-900 dark:group-hover:text-gray-100">Orphans</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
<input
|
||||
type="text"
|
||||
[(ngModel)]="filters().searchQuery"
|
||||
(ngModelChange)="emitOptionsChange()"
|
||||
placeholder="🔍 Search files…"
|
||||
class="w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-500 dark:placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500">
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Groups Section -->
|
||||
<section>
|
||||
<h3 class="text-sm font-semibold text-gray-900 dark:text-gray-100 mb-3 flex items-center gap-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
|
||||
</svg>
|
||||
Groups
|
||||
</h3>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="w-full px-3 py-2 text-sm bg-purple-600 hover:bg-purple-700 text-white rounded-md transition-colors">
|
||||
New group
|
||||
</button>
|
||||
</section>
|
||||
|
||||
<!-- Display Section -->
|
||||
<section>
|
||||
<h3 class="text-sm font-semibold text-gray-900 dark:text-gray-100 mb-3 flex items-center gap-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
|
||||
</svg>
|
||||
Display
|
||||
</h3>
|
||||
|
||||
<div class="space-y-4">
|
||||
<label class="flex items-center gap-2 cursor-pointer group">
|
||||
<input
|
||||
type="checkbox"
|
||||
[(ngModel)]="display().showArrows"
|
||||
(change)="emitOptionsChange()"
|
||||
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700">
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300 group-hover:text-gray-900 dark:group-hover:text-gray-100">Arrows</span>
|
||||
</label>
|
||||
|
||||
<div>
|
||||
<label class="flex items-center justify-between text-sm text-gray-700 dark:text-gray-300 mb-1">
|
||||
<span>Text fade threshold</span>
|
||||
<span class="font-mono text-xs">{{ display().textFadeThreshold }}</span>
|
||||
</label>
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max="100"
|
||||
[(ngModel)]="display().textFadeThreshold"
|
||||
(input)="emitOptionsChange()"
|
||||
class="w-full h-2 bg-gray-200 dark:bg-gray-700 rounded-lg appearance-none cursor-pointer accent-blue-600">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="flex items-center justify-between text-sm text-gray-700 dark:text-gray-300 mb-1">
|
||||
<span>Node size</span>
|
||||
<span class="font-mono text-xs">{{ display().nodeSize }}</span>
|
||||
</label>
|
||||
<input
|
||||
type="range"
|
||||
min="1"
|
||||
max="20"
|
||||
[(ngModel)]="display().nodeSize"
|
||||
(input)="emitOptionsChange()"
|
||||
class="w-full h-2 bg-gray-200 dark:bg-gray-700 rounded-lg appearance-none cursor-pointer accent-blue-600">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="flex items-center justify-between text-sm text-gray-700 dark:text-gray-300 mb-1">
|
||||
<span>Link thickness</span>
|
||||
<span class="font-mono text-xs">{{ display().linkThickness }}</span>
|
||||
</label>
|
||||
<input
|
||||
type="range"
|
||||
min="1"
|
||||
max="10"
|
||||
[(ngModel)]="display().linkThickness"
|
||||
(input)="emitOptionsChange()"
|
||||
class="w-full h-2 bg-gray-200 dark:bg-gray-700 rounded-lg appearance-none cursor-pointer accent-blue-600">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
(click)="animateRequested.emit()"
|
||||
class="w-full mt-3 px-3 py-2 text-sm bg-purple-600 hover:bg-purple-700 text-white rounded-md transition-colors">
|
||||
Animate
|
||||
</button>
|
||||
</section>
|
||||
|
||||
<!-- Forces Section (Collapsible) -->
|
||||
<section>
|
||||
<button
|
||||
type="button"
|
||||
(click)="forcesExpanded.set(!forcesExpanded())"
|
||||
class="w-full flex items-center justify-between text-sm font-semibold text-gray-900 dark:text-gray-100 mb-3">
|
||||
<span class="flex items-center gap-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
|
||||
</svg>
|
||||
Forces
|
||||
</span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-4 transition-transform"
|
||||
[class.rotate-180]="forcesExpanded()"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
@if (forcesExpanded()) {
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label class="flex items-center justify-between text-sm text-gray-700 dark:text-gray-300 mb-1">
|
||||
<span>Charge</span>
|
||||
<span class="font-mono text-xs">{{ forces().chargeStrength }}</span>
|
||||
</label>
|
||||
<input
|
||||
type="range"
|
||||
min="-200"
|
||||
max="0"
|
||||
[(ngModel)]="forces().chargeStrength"
|
||||
(input)="emitOptionsChange()"
|
||||
class="w-full h-2 bg-gray-200 dark:bg-gray-700 rounded-lg appearance-none cursor-pointer accent-blue-600">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="flex items-center justify-between text-sm text-gray-700 dark:text-gray-300 mb-1">
|
||||
<span>Link distance</span>
|
||||
<span class="font-mono text-xs">{{ forces().linkDistance }}</span>
|
||||
</label>
|
||||
<input
|
||||
type="range"
|
||||
min="10"
|
||||
max="500"
|
||||
[(ngModel)]="forces().linkDistance"
|
||||
(input)="emitOptionsChange()"
|
||||
class="w-full h-2 bg-gray-200 dark:bg-gray-700 rounded-lg appearance-none cursor-pointer accent-blue-600">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="flex items-center justify-between text-sm text-gray-700 dark:text-gray-300 mb-1">
|
||||
<span>Center strength</span>
|
||||
<span class="font-mono text-xs">{{ forces().centerStrength.toFixed(2) }}</span>
|
||||
</label>
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max="1"
|
||||
step="0.01"
|
||||
[(ngModel)]="forces().centerStrength"
|
||||
(input)="emitOptionsChange()"
|
||||
class="w-full h-2 bg-gray-200 dark:bg-gray-700 rounded-lg appearance-none cursor-pointer accent-blue-600">
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
styles: [`
|
||||
.graph-options-panel {
|
||||
width: 300px;
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.graph-options-panel {
|
||||
width: 100%;
|
||||
min-width: 100%;
|
||||
border-left: none;
|
||||
border-top: 1px solid;
|
||||
}
|
||||
}
|
||||
|
||||
input[type="range"]::-webkit-slider-thumb {
|
||||
appearance: none;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
background: currentColor;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type="range"]::-moz-range-thumb {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
background: currentColor;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
}
|
||||
`]
|
||||
})
|
||||
export class GraphOptionsPanelComponent {
|
||||
filters = signal<GraphFilters>({
|
||||
showTags: true,
|
||||
showAttachments: true,
|
||||
existingFilesOnly: true,
|
||||
showOrphans: true,
|
||||
searchQuery: ''
|
||||
});
|
||||
|
||||
display = signal<GraphDisplay>({
|
||||
showArrows: true,
|
||||
textFadeThreshold: 50,
|
||||
nodeSize: 5,
|
||||
linkThickness: 1
|
||||
});
|
||||
|
||||
forces = signal<GraphForces>({
|
||||
chargeStrength: -100,
|
||||
linkDistance: 100,
|
||||
centerStrength: 0.05
|
||||
});
|
||||
|
||||
forcesExpanded = signal(false);
|
||||
|
||||
optionsChanged = output<GraphOptions>();
|
||||
animateRequested = output<void>();
|
||||
|
||||
emitOptionsChange(): void {
|
||||
this.optionsChanged.emit({
|
||||
filters: this.filters(),
|
||||
display: this.display(),
|
||||
forces: this.forces()
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user