Restructures project with feature-based organization
Refactors project structure to support modular, feature-driven development Introduces comprehensive language localization support Adds menu management with role-based access control Implements dynamic sidebar and theme switching capabilities Enhances project scalability and maintainability
This commit is contained in:
parent
fac7754d7a
commit
d7f3c55a2a
60 changed files with 3214 additions and 20 deletions
106
app/wwwroot/ts/modules/search.ts
Normal file
106
app/wwwroot/ts/modules/search.ts
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/**
|
||||
* Search Controller
|
||||
*
|
||||
* Handles global search functionality and keyboard shortcuts
|
||||
*/
|
||||
|
||||
export class SearchController {
|
||||
private input: HTMLInputElement | null = null;
|
||||
private container: HTMLElement | null = null;
|
||||
|
||||
constructor() {
|
||||
this.input = document.getElementById('globalSearch') as HTMLInputElement | null;
|
||||
this.container = document.querySelector<HTMLElement>('swp-topbar-search');
|
||||
|
||||
this.setupListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current search value
|
||||
*/
|
||||
get value(): string {
|
||||
return this.input?.value ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set search value
|
||||
*/
|
||||
set value(val: string) {
|
||||
if (this.input) {
|
||||
this.input.value = val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus the search input
|
||||
*/
|
||||
focus(): void {
|
||||
this.input?.focus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Blur the search input
|
||||
*/
|
||||
blur(): void {
|
||||
this.input?.blur();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the search input
|
||||
*/
|
||||
clear(): void {
|
||||
this.value = '';
|
||||
}
|
||||
|
||||
private setupListeners(): void {
|
||||
// Keyboard shortcuts
|
||||
document.addEventListener('keydown', (e) => this.handleKeyboard(e));
|
||||
|
||||
// Input handlers
|
||||
if (this.input) {
|
||||
this.input.addEventListener('input', (e) => this.handleInput(e));
|
||||
|
||||
// Prevent form submission if wrapped in form
|
||||
const form = this.input.closest('form');
|
||||
form?.addEventListener('submit', (e) => this.handleSubmit(e));
|
||||
}
|
||||
}
|
||||
|
||||
private handleKeyboard(e: KeyboardEvent): void {
|
||||
// Cmd/Ctrl + K to focus search
|
||||
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
|
||||
e.preventDefault();
|
||||
this.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
// Escape to blur search when focused
|
||||
if (e.key === 'Escape' && document.activeElement === this.input) {
|
||||
this.blur();
|
||||
}
|
||||
}
|
||||
|
||||
private handleInput(e: Event): void {
|
||||
const target = e.target as HTMLInputElement;
|
||||
const query = target.value.trim();
|
||||
|
||||
// Emit custom event for search
|
||||
document.dispatchEvent(new CustomEvent('app:search', {
|
||||
detail: { query },
|
||||
bubbles: true
|
||||
}));
|
||||
}
|
||||
|
||||
private handleSubmit(e: Event): void {
|
||||
e.preventDefault();
|
||||
|
||||
const query = this.value.trim();
|
||||
if (!query) return;
|
||||
|
||||
// Emit custom event for search submit
|
||||
document.dispatchEvent(new CustomEvent('app:search-submit', {
|
||||
detail: { query },
|
||||
bubbles: true
|
||||
}));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue