# Fuzzy Search Filter System

## Overview

The calendar includes a powerful fuzzy search filter system that allows users to quickly find events by typing partial matches of event titles or descriptions. The system dims non-matching events while keeping matching events fully visible, providing instant visual feedback.

## Features

- **Real-time fuzzy search** using Fuse.js library
- **Visual filtering** with opacity-based dimming (0.2 for non-matches, 1.0 for matches)
- **Minimum character threshold** (2 characters) handled by Fuse.js configuration
- **Cross-navigation persistence** - filter applies to pre-rendered grids during navigation
- **Escape key support** for quick filter clearing
- **Performance optimized** with requestAnimationFrame debouncing

## Architecture

### Core Components

#### EventFilterManager (`src/managers/EventFilterManager.ts`)
Central component responsible for:
- Managing search input event listeners
- Performing fuzzy search with Fuse.js
- Coordinating visual updates across all event containers
- Emitting filter change events via EventBus

#### CSS-based Visual System
```css
/* Dim all events when filter is active */
swp-events-layer[data-filter-active="true"] swp-event {
  opacity: 0.2;
  transition: opacity 200ms ease;
}

/* Keep matching events fully visible */
swp-events-layer[data-filter-active="true"] swp-event[data-matches="true"] {
  opacity: 1;
}
```

#### Pre-rendered Grid Support
- NavigationManager listens for `FILTER_CHANGED` events
- NavigationRenderer applies filter state to all grid containers
- Ensures filter persists when navigating between time periods

### Event Flow

1. **User Input** → Search field receives input
2. **Debounced Processing** → RequestAnimationFrame prevents excessive filtering
3. **Fuzzy Search** → Fuse.js performs search against event titles/descriptions
4. **DOM Updates** → Matching events marked with `data-matches="true"`
5. **CSS Application** → Non-matching events automatically dimmed via CSS rules
6. **Cross-Grid Sync** → Filter applied to all pre-rendered grids

## Configuration

### Fuse.js Settings
```typescript
const fuseOptions = {
  keys: ['title', 'description'],     // Search in title and description
  threshold: 0.3,                     // 0 = exact match, 1 = match anything
  includeScore: true,                 // Include relevance scores
  minMatchCharLength: 2,              // Minimum 2 characters for match
  shouldSort: true,                   // Sort by relevance
  ignoreLocation: true                // Search anywhere in string
};
```

### CSS Variables
```css
:root {
  --filter-dimmed-opacity: 0.2;      /* Opacity for non-matching events */
  --filter-transition: 200ms ease;    /* Smooth opacity transitions */
}
```

## Integration Points

### CalendarManager
```typescript
// EventFilterManager is initialized in CalendarManager constructor
this.eventFilterManager = new EventFilterManager();
```

### EventRenderer
```typescript
// Events emit EVENTS_RENDERED for filter system to track
this.eventBus.emit(CoreEvents.EVENTS_RENDERED, {
  events: events,
  container: context.container
});
```

### HTML Structure
```html
<swp-search-container>
  <input type="search" placeholder="Search events..." />
</swp-search-container>
```

## User Experience

### Search Behavior
- **No input**: All events visible at full opacity
- **1 character**: Filter active, but Fuse.js won't return matches (by design)
- **2+ characters**: Real-time fuzzy matching with visual feedback
- **Empty field**: Filter cleared, all events return to normal
- **Escape key**: Immediate filter clearing

### Visual Feedback
- **Search field styling**: Border color changes when filter is active
- **Event dimming**: Non-matching events fade to 20% opacity
- **Smooth transitions**: 200ms ease transitions for polished feel

## Performance Considerations

### Optimization Strategies
1. **RequestAnimationFrame debouncing** prevents excessive search operations
2. **CSS-based visual updates** leverage browser's rendering pipeline
3. **Event delegation** avoids per-event listener overhead
4. **Efficient DOM queries** using attribute selectors

### Memory Management
- Event listeners properly scoped to component lifecycle
- Fuse.js instance recreated only when event data changes
- Minimal DOM manipulation through attribute-based CSS rules

## Error Handling

### Graceful Degradation
- System continues to function if Fuse.js fails to load
- Search input remains functional for basic text entry
- Console warnings for debugging (removed in production)

### Edge Cases
- **No events to search**: Filter system remains inactive
- **Empty search results**: All events dimmed (expected behavior)
- **DOM timing issues**: Waits for DOM readiness before initialization

## Future Enhancements

### Potential Improvements
- **Search result highlighting** within event text
- **Advanced filters** (date range, event type, etc.)
- **Search history** with dropdown suggestions
- **Keyboard navigation** through search results
- **Search analytics** for usage insights

### Performance Optimizations
- **Virtual scrolling** for large event sets
- **Search index caching** for repeated queries
- **Web Workers** for heavy search operations

## Dependencies

### External Libraries
- **Fuse.js** (v7.x) - Fuzzy search library
  - License: Apache 2.0
  - File: `wwwroot/js/lib/fuse.min.mjs`
  - Import: ES module format

### Internal Dependencies
- **EventBus** - Inter-component communication
- **CoreEvents** - Centralized event type definitions
- **CalendarEvent** - Event data type definitions

## Testing Considerations

### Test Scenarios
1. **Basic search functionality** - Verify fuzzy matching works
2. **Performance testing** - Large event sets (1000+ events)
3. **Cross-navigation** - Filter persistence during navigation
4. **Edge cases** - Empty results, special characters, very long queries
5. **Accessibility** - Screen reader compatibility, keyboard navigation

### Browser Compatibility
- **Modern browsers** with ES modules support
- **CSS custom properties** support required
- **requestAnimationFrame** API required

## Maintenance Notes

### Code Organization
- **Single responsibility** - EventFilterManager handles only filtering
- **Event-driven** - Loose coupling via EventBus
- **CSS-first** - Visual logic in stylesheets, not JavaScript
- **Type-safe** - Full TypeScript implementation

### Common Issues
- **Timing**: Ensure EventFilterManager initializes after DOM ready
- **Event data**: Verify EVENTS_RENDERED events are emitted correctly
- **CSS specificity**: Filter styles must override existing event styles
- **Memory leaks**: Properly clean up event listeners in destroy()

This fuzzy search filter system provides an intuitive and performant way for users to quickly locate specific events within the calendar interface.