chore: update Angular cache and TypeScript build info
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
<div class="flex items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-primary"
|
||||
class="btn-standard-sm"
|
||||
(click)="createGroup()"
|
||||
title="Créer un groupe">
|
||||
+ Group
|
||||
@@ -29,7 +29,7 @@
|
||||
@if (searchTerm()) {
|
||||
<button
|
||||
(click)="onSearchChange('')"
|
||||
class="absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
|
||||
class="btn-standard-icon absolute right-2 top-1/2 -translate-y-1/2"
|
||||
title="Clear search">
|
||||
✕
|
||||
</button>
|
||||
@@ -51,7 +51,7 @@
|
||||
<span class="text-sm text-red-700 dark:text-red-300 flex-1">{{ error() }}</span>
|
||||
<button
|
||||
(click)="clearError()"
|
||||
class="text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-200"
|
||||
class="btn-standard-icon !text-red-600 dark:!text-red-400 hover:!text-red-800 dark:hover:!text-red-200"
|
||||
title="Dismiss">
|
||||
✕
|
||||
</button>
|
||||
@@ -132,12 +132,12 @@
|
||||
<div class="flex gap-3">
|
||||
<button
|
||||
(click)="resolveConflictReload()"
|
||||
class="flex-1 px-4 py-2 text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 rounded-md transition-colors">
|
||||
class="btn-standard-primary flex-1">
|
||||
Reload from file
|
||||
</button>
|
||||
<button
|
||||
(click)="resolveConflictOverwrite()"
|
||||
class="flex-1 px-4 py-2 text-sm font-medium text-white bg-red-600 hover:bg-red-700 rounded-md transition-colors">
|
||||
class="btn-standard-danger flex-1">
|
||||
Overwrite file
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -130,17 +130,7 @@ interface AccordionSection {
|
||||
}
|
||||
</cdk-accordion>
|
||||
|
||||
<!-- Optional: Collapse All / Expand All Toggle -->
|
||||
@if (showCollapseToggle()) {
|
||||
<div class="collapse-toggle-container">
|
||||
<button
|
||||
type="button"
|
||||
class="collapse-toggle-button"
|
||||
(click)="toggleAll()">
|
||||
{{ allExpanded() ? 'Collapse all' : 'Expand all' }}
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
`,
|
||||
styles: [`
|
||||
/* Container */
|
||||
@@ -155,7 +145,8 @@ interface AccordionSection {
|
||||
border-radius: 1rem;
|
||||
border: 1px solid rgba(113, 113, 122, 0.3);
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
overflow: hidden;
|
||||
/* Important: allow inner popovers (search options) to overflow */
|
||||
overflow: visible;
|
||||
transition: border-color 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
@@ -260,17 +251,27 @@ interface AccordionSection {
|
||||
.accordion-panel {
|
||||
display: grid;
|
||||
grid-template-rows: 0fr;
|
||||
/* Keep hidden while collapsed to preserve animation */
|
||||
overflow: hidden;
|
||||
transition: grid-template-rows 0.2s ease-out;
|
||||
}
|
||||
|
||||
.accordion-panel-expanded {
|
||||
grid-template-rows: 1fr;
|
||||
/* Critical: allow popovers to escape the panel box */
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/* Allow popovers to extend outside the panel when expanded */
|
||||
.accordion-panel-expanded .accordion-panel-inner {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.accordion-panel-inner {
|
||||
min-height: 0;
|
||||
padding: 0 1.25rem;
|
||||
/* Ensure inner content doesn't clip popovers */
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.accordion-panel-expanded .accordion-panel-inner {
|
||||
@@ -288,35 +289,6 @@ interface AccordionSection {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.collapse-toggle-button {
|
||||
padding: 0.5rem 1rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
color: #6b7280;
|
||||
background: transparent;
|
||||
border: 1px solid rgba(113, 113, 122, 0.3);
|
||||
border-radius: 0.5rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.collapse-toggle-button:hover {
|
||||
color: #374151;
|
||||
border-color: rgba(113, 113, 122, 0.5);
|
||||
background: rgba(249, 250, 251, 0.5);
|
||||
}
|
||||
|
||||
:host-context(.dark) .collapse-toggle-button {
|
||||
color: #9ca3af;
|
||||
border-color: rgba(82, 82, 91, 0.5);
|
||||
}
|
||||
|
||||
:host-context(.dark) .collapse-toggle-button:hover {
|
||||
color: #d1d5db;
|
||||
border-color: rgba(113, 113, 122, 0.6);
|
||||
background: rgba(39, 39, 42, 0.5);
|
||||
}
|
||||
`]
|
||||
})
|
||||
export class GraphSettingsAccordionComponent {
|
||||
@@ -329,7 +301,7 @@ export class GraphSettingsAccordionComponent {
|
||||
/** Animate requested output */
|
||||
animateRequested = output<void>();
|
||||
|
||||
/** Show collapse/expand all toggle */
|
||||
/** Show collapse/expand all toggle (no longer used in UI) */
|
||||
showCollapseToggle = input<boolean>(false);
|
||||
|
||||
private settingsService = inject(GraphSettingsService);
|
||||
@@ -424,24 +396,28 @@ export class GraphSettingsAccordionComponent {
|
||||
|
||||
if (shouldExpandAll) {
|
||||
// Expand all
|
||||
const allIds = new Set(sections.map(s => s.id));
|
||||
this.openSectionsSet.set(allIds);
|
||||
|
||||
// Persist all as expanded
|
||||
sections.forEach(section => {
|
||||
this.persistState(section.id, true);
|
||||
});
|
||||
this.expandAll();
|
||||
} else {
|
||||
// Collapse all
|
||||
this.openSectionsSet.set(new Set());
|
||||
|
||||
// Persist all as collapsed
|
||||
sections.forEach(section => {
|
||||
this.persistState(section.id, false);
|
||||
});
|
||||
this.collapseAll();
|
||||
}
|
||||
}
|
||||
|
||||
/** Expand all sections */
|
||||
expandAll(): void {
|
||||
const sections = this.sections();
|
||||
const allIds = new Set(sections.map(s => s.id));
|
||||
this.openSectionsSet.set(allIds);
|
||||
sections.forEach(section => this.persistState(section.id, true));
|
||||
}
|
||||
|
||||
/** Collapse all sections */
|
||||
collapseAll(): void {
|
||||
const sections = this.sections();
|
||||
this.openSectionsSet.set(new Set());
|
||||
sections.forEach(section => this.persistState(section.id, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Persist section state to GraphSettingsService
|
||||
*/
|
||||
|
||||
@@ -67,9 +67,7 @@ import { SearchOptions } from '../../core/search/search-parser.types';
|
||||
(click)="toggleCaseSensitivity()"
|
||||
[class.bg-accent]="caseSensitive()"
|
||||
[class.text-white]="caseSensitive()"
|
||||
[class.hover:bg-bg-muted]="!caseSensitive()"
|
||||
[class.dark:hover:bg-gray-700]="!caseSensitive()"
|
||||
class="px-2 py-1 rounded text-xs font-semibold transition-colors border border-border dark:border-gray-600"
|
||||
class="btn-standard-xs"
|
||||
[title]="caseSensitive() ? 'Case sensitive' : 'Case insensitive'"
|
||||
aria-label="Toggle case sensitivity"
|
||||
>
|
||||
@@ -82,9 +80,7 @@ import { SearchOptions } from '../../core/search/search-parser.types';
|
||||
(click)="toggleRegexMode()"
|
||||
[class.bg-accent]="regexMode()"
|
||||
[class.text-white]="regexMode()"
|
||||
[class.hover:bg-bg-muted]="!regexMode()"
|
||||
[class.dark:hover:bg-gray-700]="!regexMode()"
|
||||
class="px-2 py-1 rounded text-xs font-mono transition-colors border border-border dark:border-gray-600"
|
||||
class="btn-standard-xs font-mono"
|
||||
[title]="regexMode() ? 'Regex mode enabled' : 'Regex mode disabled'"
|
||||
aria-label="Toggle regex mode"
|
||||
>
|
||||
@@ -96,10 +92,10 @@ import { SearchOptions } from '../../core/search/search-parser.types';
|
||||
*ngIf="query"
|
||||
type="button"
|
||||
(click)="clear()"
|
||||
class="p-1 rounded-full hover:bg-bg-muted dark:hover:bg-gray-700 transition-colors"
|
||||
class="btn-standard-icon"
|
||||
aria-label="Clear search"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-text-muted dark:text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<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="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
@@ -36,6 +36,7 @@ type NavigationItem =
|
||||
<div
|
||||
#popover
|
||||
class="absolute top-full left-0 right-0 mt-1 bg-bg-primary dark:bg-gray-800 border border-border dark:border-gray-700 rounded-xl shadow-2xl z-50 overflow-hidden max-h-[360px]"
|
||||
style="z-index: 9999;"
|
||||
(click)="$event.stopPropagation()"
|
||||
>
|
||||
<!-- Search Options -->
|
||||
|
||||
@@ -71,7 +71,7 @@ type SortOption = 'relevance' | 'name' | 'modified';
|
||||
<!-- Expand/Collapse all -->
|
||||
<button
|
||||
(click)="toggleAllGroups()"
|
||||
class="text-xs px-2 py-1 rounded hover:bg-bg-muted dark:hover:bg-gray-700 text-text-muted dark:text-gray-400"
|
||||
class="btn-standard-xs"
|
||||
title="Expand/Collapse all"
|
||||
>
|
||||
{{ allExpanded() ? 'Collapse all' : 'Expand all' }}
|
||||
@@ -134,7 +134,7 @@ type SortOption = 'relevance' | 'name' | 'modified';
|
||||
<!-- Open button -->
|
||||
<button
|
||||
(click)="openNote(group.noteId, $event)"
|
||||
class="ml-2 p-1.5 rounded hover:bg-bg-primary dark:hover:bg-gray-700 text-text-muted dark:text-gray-400"
|
||||
class="btn-standard-icon ml-2"
|
||||
title="Open note"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
|
||||
@@ -15,6 +15,7 @@ import { CommonModule } from '@angular/common';
|
||||
import { Note } from '../../../types';
|
||||
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
||||
import { NotePreviewService, PreviewData } from '../../../services/note-preview.service';
|
||||
import { Subscription } from 'rxjs';
|
||||
import mermaid from 'mermaid';
|
||||
|
||||
type MermaidLib = typeof mermaid;
|
||||
@@ -131,7 +132,7 @@ interface MetadataEntry {
|
||||
|
||||
@if (metadataEntries().length > maxMetadataPreviewItems) {
|
||||
<div class="mt-3">
|
||||
<button type="button" class="btn btn-secondary" (click)="toggleMetadataPanel()">
|
||||
<button type="button" class="btn-standard-sm" (click)="toggleMetadataPanel()">
|
||||
{{ metadataExpanded() ? translate('metadata.collapse') : translate('metadata.showAll') }}
|
||||
</button>
|
||||
</div>
|
||||
@@ -201,6 +202,8 @@ export class NoteViewerComponent implements OnDestroy {
|
||||
private readonly metadataKeysToExclude = new Set(['tags', 'tag', 'keywords']);
|
||||
private attachmentErrorCleanup: (() => void) | null = null;
|
||||
private attachmentHandlersScheduled = false;
|
||||
private wikiLinkHandlersScheduled = false;
|
||||
private previewOpenSub: Subscription | null = null;
|
||||
|
||||
readonly metadataExpanded = signal(false);
|
||||
readonly maxMetadataPreviewItems = 3;
|
||||
@@ -265,6 +268,7 @@ export class NoteViewerComponent implements OnDestroy {
|
||||
this.scheduleMermaidRender();
|
||||
this.scheduleAttachmentHandlers();
|
||||
this.scheduleMathRender();
|
||||
this.scheduleWikiLinkHoverHandlers();
|
||||
});
|
||||
|
||||
afterNextRender(() => {
|
||||
@@ -320,7 +324,8 @@ export class NoteViewerComponent implements OnDestroy {
|
||||
this.scheduleMermaidRender();
|
||||
this.scheduleAttachmentHandlers();
|
||||
this.scheduleMathRender();
|
||||
this.setupWikiLinkHoverHandlers();
|
||||
this.scheduleWikiLinkHoverHandlers();
|
||||
this.subscribeToPreviewOpens();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -333,37 +338,77 @@ export class NoteViewerComponent implements OnDestroy {
|
||||
this.attachmentErrorCleanup?.();
|
||||
this.attachmentErrorCleanup = null;
|
||||
this.previewService.hidePreviewImmediately();
|
||||
this.previewOpenSub?.unsubscribe();
|
||||
this.previewOpenSub = null;
|
||||
}
|
||||
|
||||
private subscribeToPreviewOpens(): void {
|
||||
if (this.previewOpenSub) return;
|
||||
this.previewOpenSub = this.previewService.openNoteRequested$.subscribe(noteId => {
|
||||
if (!noteId) return;
|
||||
console.log('[NoteViewer] Preview open requested for note:', noteId);
|
||||
this.noteLinkClicked.emit(noteId);
|
||||
});
|
||||
}
|
||||
|
||||
private setupWikiLinkHoverHandlers(): void {
|
||||
const hostElement = this.elementRef.nativeElement as HTMLElement;
|
||||
const wikiLinks = hostElement.querySelectorAll<HTMLAnchorElement>('a.md-wiki-link');
|
||||
|
||||
console.log('[NoteViewer] Setting up hover handlers for', wikiLinks.length, 'wiki links');
|
||||
|
||||
wikiLinks.forEach(link => {
|
||||
if (link.dataset.previewHoverBound === 'true') {
|
||||
console.log('[NoteViewer] Link already bound, skipping:', link.textContent);
|
||||
return;
|
||||
}
|
||||
link.dataset.previewHoverBound = 'true';
|
||||
|
||||
link.addEventListener('mouseenter', () => {
|
||||
const targetValue = link.getAttribute('data-target') ?? '';
|
||||
console.log('[NoteViewer] Mouse enter on link:', targetValue);
|
||||
const previewData = this.buildPreviewData(targetValue);
|
||||
|
||||
|
||||
if (previewData) {
|
||||
console.log('[NoteViewer] Showing preview for:', targetValue, previewData);
|
||||
this.previewService.showPreview(targetValue, link, previewData);
|
||||
} else {
|
||||
console.warn('[NoteViewer] No preview data found for:', targetValue);
|
||||
}
|
||||
});
|
||||
|
||||
link.addEventListener('mouseleave', () => {
|
||||
console.log('[NoteViewer] Mouse leave, hiding preview');
|
||||
this.previewService.hidePreview();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private scheduleWikiLinkHoverHandlers(): void {
|
||||
if (this.wikiLinkHandlersScheduled) return;
|
||||
this.wikiLinkHandlersScheduled = true;
|
||||
queueMicrotask(() => {
|
||||
this.wikiLinkHandlersScheduled = false;
|
||||
this.setupWikiLinkHoverHandlers();
|
||||
});
|
||||
}
|
||||
|
||||
private buildPreviewData(noteTarget: string): PreviewData | null {
|
||||
const allNotes = this.allNotes();
|
||||
console.log('[NoteViewer] Building preview for target:', noteTarget, 'from', allNotes.length, 'notes');
|
||||
|
||||
const targetNote = allNotes.find(n =>
|
||||
n.id.toLowerCase() === noteTarget.toLowerCase() ||
|
||||
n.title.toLowerCase() === noteTarget.toLowerCase() ||
|
||||
n.fileName?.replace(/\.md$/, '').toLowerCase() === noteTarget.toLowerCase()
|
||||
);
|
||||
|
||||
if (!targetNote) return null;
|
||||
if (!targetNote) {
|
||||
console.warn('[NoteViewer] Target note not found:', noteTarget);
|
||||
return null;
|
||||
}
|
||||
|
||||
console.log('[NoteViewer] Found target note:', targetNote.title);
|
||||
|
||||
// Extraire un extrait (3-5 premières lignes)
|
||||
const lines = targetNote.content.split('\n').filter(line => line.trim());
|
||||
|
||||
@@ -54,13 +54,34 @@ interface TagSection {
|
||||
:host-context(.dark) .custom-scrollbar::-webkit-scrollbar-thumb {
|
||||
background-color: var(--tv-scroll-thumb-dark);
|
||||
}
|
||||
|
||||
/* Remove blue focus rectangle and native search decorations */
|
||||
#tag-search,
|
||||
#tag-search:focus,
|
||||
#tag-search:focus-visible {
|
||||
outline: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
#tag-search {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
input[type='search']::-webkit-search-decoration,
|
||||
input[type='search']::-webkit-search-cancel-button,
|
||||
input[type='search']::-webkit-search-results-button,
|
||||
input[type='search']::-webkit-search-results-decoration {
|
||||
display: none;
|
||||
}
|
||||
`,
|
||||
],
|
||||
template: `
|
||||
<div class="flex h-full flex-col gap-4 p-3 bg-card">
|
||||
<div class="rounded-xl border border-border bg-card px-3 py-2 shadow-subtle">
|
||||
<div class="w-full rounded-full border border-border bg-card px-3 py-1.5 shadow-subtle focus-within:outline-none focus-within:ring-0">
|
||||
<label class="sr-only" for="tag-search">Rechercher des tags</label>
|
||||
<div class="flex items-center gap-2 text-text-muted">
|
||||
<div class="flex items-center gap-2.5 text-text-muted">
|
||||
<svg class="h-4 w-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-5.2-5.2m0 0A7 7 0 105.8 5.8a7 7 0 0010 10z" />
|
||||
</svg>
|
||||
@@ -70,20 +91,8 @@ interface TagSection {
|
||||
[value]="searchTerm()"
|
||||
(input)="onSearchChange($event.target?.value ?? '')"
|
||||
placeholder="Rechercher un tag..."
|
||||
class="w-full bg-transparent text-sm text-text-main placeholder:text-text-muted focus:outline-none"
|
||||
class="w-full border-0 bg-transparent text-sm text-text-main placeholder:text-text-muted outline-none focus:outline-none focus:ring-0 focus-visible:outline-none focus-visible:ring-0"
|
||||
/>
|
||||
@if (searchTerm(); as value) {
|
||||
@if (value.length > 0) {
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-ghost px-2 py-1 text-xs"
|
||||
aria-label="Effacer la recherche"
|
||||
(click)="clearSearch()"
|
||||
>
|
||||
Effacer
|
||||
</button>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -105,7 +114,7 @@ interface TagSection {
|
||||
@for (tag of section.tags; track tag.name) {
|
||||
<button
|
||||
type="button"
|
||||
class="chip justify-between px-3 py-1.5 text-sm"
|
||||
class="chip justify-between px-2 py-0.5 text-[0.7rem]"
|
||||
(click)="tagSelected.emit(tag.name)"
|
||||
>
|
||||
<span class="flex items-center gap-2 text-text-main">
|
||||
@@ -124,7 +133,7 @@ interface TagSection {
|
||||
Aucun tag ne correspond à votre recherche.
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="custom-scrollbar sticky top-0 flex h-full w-12 flex-col items-center justify-start gap-2 self-start rounded-lg border border-border bg-card px-2 py-3 text-[0.7rem] font-medium text-text-muted shadow-subtle overflow-y-auto">
|
||||
<span class="text-[0.6rem] uppercase tracking-wide text-text-muted/70">A–Z</span>
|
||||
|
||||
Reference in New Issue
Block a user