Source generators for Blazor AutoComplete providing AOT/trimming compatibility via build-time property accessor generation and expression validation (EBDAC001-003 diagnostics). Development dependency with zero runtime overhead.
$ dotnet add package EasyAppDev.Blazor.AutoComplete.GeneratorsA high-performance, feature-rich AutoComplete component for Blazor applications with AI-powered semantic search capabilities.
dotnet add package EasyAppDev.Blazor.AutoCompleteAdd references to wwwroot/index.html:
<head>
<!-- AutoComplete Base CSS - Structural styles (always loaded) -->
<link href="_content/EasyAppDev.Blazor.AutoComplete/styles/autocomplete.base.css" rel="stylesheet" />
<!-- AutoComplete Theme Loader Script - Dynamically loads theme presets -->
<script src="_content/EasyAppDev.Blazor.AutoComplete/scripts/theme-loader.js"></script>
<!-- Theme CSS files load automatically when ThemePreset parameter is set -->
</head>Add references to Components/App.razor (or App.razor depending on your project structure):
<head>
<!-- AutoComplete Base CSS - Structural styles (always loaded) -->
<link href="_content/EasyAppDev.Blazor.AutoComplete/styles/autocomplete.base.css" rel="stylesheet" />
<!-- AutoComplete Theme Loader Script - Dynamically loads theme presets -->
<script src="_content/EasyAppDev.Blazor.AutoComplete/scripts/theme-loader.js"></script>
<!-- Theme CSS files load automatically when ThemePreset parameter is set -->
</head>Notes:
ThemePreset parameter, resulting in optimal bundle size (~10KB total for base + one theme)..Client project, ensure the package is referenced in both the server and client projects.@using EasyAppDev.Blazor.AutoComplete
<AutoComplete TItem="Product"
Items="@products"
TextField="@(p => p.Name)"
@bind-Value="@selectedProduct"
Placeholder="Search products..." />
@code {
private List<Product> products = new()
{
new Product { Id = 1, Name = "Apple" },
new Product { Id = 2, Name = "Banana" },
new Product { Id = 3, Name = "Cherry" }
};
private Product? selectedProduct;
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
}Search across multiple properties simultaneously with ANY filter strategy (StartsWith, Contains, Fuzzy):
<AutoComplete TItem="Product"
Items="@products"
SearchFields="@(p => new[] { p.Name, p.Description, p.Category, p.Tags })"
FilterStrategy="FilterStrategy.Contains"
@bind-Value="@selectedProduct" />How it works:
Eliminate 10-20 lines of repetitive ItemTemplate markup with 7 built-in display modes:
@using EasyAppDev.Blazor.AutoComplete.Options
<!-- Simple (default) - Just the title -->
<AutoComplete TItem="Product"
Items="@products"
TextField="@(p => p.Name)"
DisplayMode="ItemDisplayMode.Simple"
@bind-Value="@selectedProduct" />
<!-- Title + Description -->
<AutoComplete TItem="Product"
Items="@products"
TextField="@(p => p.Name)"
DescriptionField="@(p => p.Category)"
DisplayMode="ItemDisplayMode.TitleWithDescription"
@bind-Value="@selectedProduct" />
<!-- Title + Badge (e.g., price, status) -->
<AutoComplete TItem="Product"
Items="@products"
TextField="@(p => p.Name)"
BadgeField="@(p => $"${p.Price}")"
BadgeClass="badge bg-success"
DisplayMode="ItemDisplayMode.TitleWithBadge"
@bind-Value="@selectedProduct" />
<!-- Icon + Title + Description -->
<AutoComplete TItem="Product"
Items="@products"
TextField="@(p => p.Name)"
IconField="@(p => p.Emoji)"
DescriptionField="@(p => p.Category)"
DisplayMode="ItemDisplayMode.IconTitleDescription"
@bind-Value="@selectedProduct" />
<!-- Card mode (all fields) -->
<AutoComplete TItem="Product"
Items="@products"
TextField="@(p => p.Name)"
IconField="@(p => p.Emoji)"
SubtitleField="@(p => p.Category)"
DescriptionField="@(p => p.Description)"
BadgeField="@(p => $"${p.Price}")"
BadgeClass="badge bg-success"
DisplayMode="ItemDisplayMode.Card"
@bind-Value="@selectedProduct" />Available Display Modes:
Note: When DisplayMode is set to Custom (default), the component uses ItemTemplate if provided, otherwise falls back to Simple mode.
Three built-in filter strategies with multi-field support:
<!-- StartsWith (default) - Fastest, prefix matching -->
<AutoComplete FilterStrategy="FilterStrategy.StartsWith" ... />
<!-- Contains - Substring matching anywhere -->
<AutoComplete FilterStrategy="FilterStrategy.Contains" ... />
<!-- Fuzzy - Typo-tolerant with Levenshtein distance -->
<AutoComplete FilterStrategy="FilterStrategy.Fuzzy" ... />
<!-- Custom - Provide your own IFilterEngine<TItem> -->
<AutoComplete FilterStrategy="FilterStrategy.Custom"
CustomFilter="@myCustomFilter" ... />Filter Performance (100K items):
Fuzzy Filter Features:
Build complex configurations with method chaining:
var config = AutoCompleteConfig<Product>.Create()
.WithItems(products)
.WithTextField(p => p.Name)
.WithSearchFields(p => new[] { p.Name, p.Description, p.Category })
.WithTheme(Theme.Auto)
.WithBootstrapTheme(BootstrapTheme.Primary)
.WithDisplayMode(ItemDisplayMode.TitleWithDescription)
.WithTitleAndDescription(p => p.Description)
.WithVirtualization(threshold: 1000, itemHeight: 45)
.WithGrouping(p => p.Category)
.WithDebounce(500)
.Build();Usage:
<AutoComplete TItem="Product" Config="@config" />Benefits:
Note: The Config parameter relies on a source generator (ConfigurationApplierGenerator) that may not always generate code correctly. If you encounter issues where the fluent configuration doesn't work (no results shown), use individual parameters instead as a workaround. See [Issue #TBD] for more details.
Group items by any property with custom headers:
<AutoComplete TItem="Product"
Items="@products"
TextField="@(p => p.Name)"
GroupBy="@(p => p.Category)"
@bind-Value="@selectedProduct">
<GroupTemplate Context="group">
<strong>@group.Key</strong> <span class="badge">@group.Count()</span>
</GroupTemplate>
</AutoComplete>Features:
Handle massive datasets (100K+ items) with ease:
<AutoComplete TItem="Product"
Items="@largeDataset"
TextField="@(p => p.Name)"
Virtualize="true"
VirtualizationThreshold="1000"
ItemHeight="45"
@bind-Value="@selectedProduct" />Performance Benefits:
<Virtualize> componentFetch data from remote APIs with cancellation support:
<AutoComplete TItem="Product"
DataSource="@productDataSource"
TextField="@(p => p.Name)"
@bind-Value="@selectedProduct" />
@code {
private IAutoCompleteDataSource<Product> productDataSource = new RemoteDataSource<Product>(
async (query, ct) =>
{
var response = await httpClient.GetFromJsonAsync<List<Product>>(
$"/api/products?q={query}", ct);
return response ?? Enumerable.Empty<Product>();
}
);
}Features:
CancellationToken support (cancels old searches when user types rapidly)DebounceMs)LoadingTemplateOverride default rendering with custom templates:
<AutoComplete TItem="Product"
Items="@products"
TextField="@(p => p.Name)"
@bind-Value="@selectedProduct">
<ItemTemplate Context="product">
<div class="product-item">
<img src="@product.ImageUrl" alt="@product.Name" />
<div>
<strong>@product.Name</strong>
<span class="price">$@product.Price</span>
<small class="text-muted">@product.Category</small>
</div>
</div>
</ItemTemplate>
<NoResultsTemplate>
<div class="text-center py-3">
<i class="bi bi-search"></i>
<p>No products found. Try a different search term.</p>
</div>
</NoResultsTemplate>
<LoadingTemplate>
<div class="text-center py-3">
<div class="spinner-border text-primary" role="status"></div>
<p>Searching products...</p>
</div>
</LoadingTemplate>
</AutoComplete>Available Templates:
Add intelligent semantic search that understands meaning, not just keywords. Users can search using natural language, synonyms, and concepts - perfect for technical documentation, product catalogs, and knowledge bases.
The AI package is optional and separate from the core component:
# Core component (required)
dotnet add package EasyAppDev.Blazor.AutoComplete
# AI semantic search (optional - includes core automatically)
dotnet add package EasyAppDev.Blazor.AutoComplete.AINote: Installing the AI package automatically installs the core package as a dependency.
| Provider | Status | Setup Method | Cost | Privacy |
|---|---|---|---|---|
| OpenAI | ✅ Built-in | AddAutoCompleteSemanticSearch() | $ | Cloud |
| Azure OpenAI | ✅ Built-in | AddAutoCompleteSemanticSearchWithAzure() | $ | Azure Cloud |
| Ollama | ⚠️ Manual setup | Custom IEmbeddingGenerator | Free | 100% Local |
| Custom | ✅ Supported | Any IEmbeddingGenerator<string, Embedding<float>> | Varies | Varies |
1. Get an OpenAI API Key
sk-)2. Configure API Key (3 options)
Option A: appsettings.json (Recommended)
{
"OpenAI": {
"ApiKey": "sk-proj-...",
"Model": "text-embedding-3-small"
}
}// Program.cs
builder.Services.AddAutoCompleteSemanticSearch(builder.Configuration);Option B: User Secrets (Development)
dotnet user-secrets init
dotnet user-secrets set "OpenAI:ApiKey" "sk-proj-..."
dotnet user-secrets set "OpenAI:Model" "text-embedding-3-small"// Program.cs
builder.Services.AddAutoCompleteSemanticSearch(builder.Configuration);Option C: Direct API Key (Quick Testing)
// Program.cs
builder.Services.AddAutoCompleteSemanticSearch(
apiKey: "sk-proj-...",
model: "text-embedding-3-small"); // Optional, defaults to "text-embedding-3-small"3. Use in Component
@using EasyAppDev.Blazor.AutoComplete.AI
<SemanticAutoComplete TItem="TechDoc"
Items="@docs"
SearchFields="@(d => new[] { d.Title, d.Description, d.Tags })"
TextField="@(d => d.Title)"
SimilarityThreshold="0.15"
@bind-Value="@selectedDoc"
Placeholder="Search by meaning..." />
@code {
private List<TechDoc> docs = new()
{
new TechDoc { Title = "Authentication Best Practices", Description = "OAuth2, JWT, and API security" },
new TechDoc { Title = "React Native Tutorial", Description = "Build mobile apps with React" },
new TechDoc { Title = "Async/Await Patterns", Description = "Asynchronous programming in C#" }
};
private TechDoc? selectedDoc;
}
public class TechDoc
{
public string Title { get; set; } = "";
public string Description { get; set; } = "";
public string Tags { get; set; } = "";
}1. Create Azure OpenAI Resource
text-embedding-ada-002)2. Get Credentials
https://YOUR-RESOURCE-NAME.openai.azure.com/3. Configure
// Program.cs
builder.Services.AddAutoCompleteSemanticSearchWithAzure(
endpoint: "https://my-resource.openai.azure.com/",
apiKey: "your-azure-api-key",
deploymentName: "text-embedding-ada-002");For 100% local/offline semantic search with no API costs:
1. Install Ollama
# macOS/Linux
curl -fsSL https://ollama.com/install.sh | sh
# Windows: Download from https://ollama.com/download2. Pull Embedding Model
ollama pull nomic-embed-text3. Install OllamaSharp
dotnet add package OllamaSharp4. Configure Custom Provider
// Program.cs
using OllamaSharp;
using Microsoft.Extensions.AI;
var ollamaClient = new OllamaApiClient("http://localhost:11434");
builder.Services.AddSingleton<IEmbeddingGenerator<string, Embedding<float>>>(
ollamaClient.AsEmbeddingGenerator("nomic-embed-text"));See samples/AI-Examples/OllamaExample.cs for complete example.
OpenAI Models:
text-embedding-3-small (1536 dimensions) - Recommended - Best price/performancetext-embedding-3-large (3072 dimensions) - Highest qualitytext-embedding-ada-002 (1536 dimensions) - Legacy, still supportedAzure OpenAI Models:
Ollama Models (Local):
nomic-embed-text - Recommended - 768 dimensions, optimized for retrievalall-minilm - 384 dimensions, smaller/fastermxbai-embed-large - 1024 dimensions, higher qualityTraditional Text Search:
Query: "mobile apps"
Matches: Items containing exact words "mobile" OR "apps"
Semantic Search:
Query: "mobile apps"
Matches:
- "React Native Tutorial" (mentions mobile development)
- "Flutter Guide" (mobile framework)
- "Progressive Web Apps" (web-based mobile)
- "iOS Development" (mobile platform)
Behind the Scenes:
Cache Tuning for Large Datasets:
<SemanticAutoComplete TItem="Product"
Items="@products"
SearchFields="@(p => new[] { p.Name, p.Description, p.Category })"
@* Cache Configuration *@
ItemCacheDuration="TimeSpan.FromHours(2)"
QueryCacheDuration="TimeSpan.FromMinutes(30)"
MaxItemCacheSize="20000"
MaxQueryCacheSize="2000"
@* Pre-warming (generate all embeddings on load) *@
PreWarmCache="true"
ShowCacheStatus="true" @* Shows "Cached: 1234/5000 (75% hit rate)" *@
@* Search Tuning *@
SimilarityThreshold="0.15" @* Lower = more results (0.0-1.0) *@
MinSearchLength="3" @* Min chars before semantic search *@
DebounceMs="500" @* Wait time before API call *@
@bind-Value="@selectedProduct" />Performance Metrics:
"Missing embedding generator" Error:
Error: Add services.AddAutoCompleteSemanticSearch(configuration) to Program.cs
Solution: Ensure you've registered the embedding service in Program.cs:
builder.Services.AddAutoCompleteSemanticSearch(builder.Configuration);No Results Returned:
SimilarityThreshold (try 0.1 instead of 0.15)ShowCacheStatus="true" to monitor cacheAPI Rate Limits:
ItemCacheDuration="TimeSpan.FromHours(1)"DebounceMs="800"Query: "password security" Finds: "Authentication Best Practices", "OAuth Implementation", "JWT Tokens", "API Security"
Query: "mobile development" Finds: "React Native", "Flutter", "Progressive Web Apps", "iOS Development", "Android SDK"
Query: "async code" Finds: "Async/Await Patterns", "Task Parallel Library", "Asynchronous Programming", "Background Workers"
Query: "database optimization" Finds: "SQL Performance Tuning", "Index Optimization", "Query Optimization", "Database Caching"
Theme your autocomplete component without writing any CSS:
@using EasyAppDev.Blazor.AutoComplete.Options
<!-- Material Design theme -->
<AutoComplete ThemePreset="ThemePreset.Material"
Items="@countries"
@bind-Value="selectedCountry" />
<!-- Custom theme without CSS -->
<AutoComplete PrimaryColor="#FF6B6B"
BorderRadius="8px"
FontFamily="Inter, sans-serif"
Items="@countries"
@bind-Value="selectedCountry" />Choose from 4 professionally designed theme presets with dynamic CSS loading (~2KB each, loaded on-demand):
| Preset | Design System | Primary Color | Features |
|---|---|---|---|
| Material | Google Material Design 3 | Purple (#6200EE) | Elevation, Purple accent, Roboto font |
| Fluent | Microsoft Fluent Design | Blue (#0078D4) | Acrylic, Sharp corners, Segoe UI font |
| Modern | Minimal/Clean | Blue (#2563EB) | Flat, No shadows, System fonts |
| Bootstrap | Bootstrap 5 | Blue (#0D6EFD) | Familiar, rem units, Bootstrap colors |
@using EasyAppDev.Blazor.AutoComplete.Options
<!-- Material Design 3 (Google) -->
<AutoComplete ThemePreset="ThemePreset.Material"
Items="@products"
TextField="@(p => p.Name)"
@bind-Value="@selectedProduct" />
<!-- Fluent Design (Microsoft Windows 11) -->
<AutoComplete ThemePreset="ThemePreset.Fluent"
Items="@products"
TextField="@(p => p.Name)"
@bind-Value="@selectedProduct" />Key Features:
@media (prefers-color-scheme: dark)ThemePreset parameter9 color variants for Bootstrap 5 integration:
<!-- Primary (blue) -->
<AutoComplete BootstrapTheme="BootstrapTheme.Primary" ... />
<!-- Success (green) -->
<AutoComplete BootstrapTheme="BootstrapTheme.Success" ... />
<!-- Danger (red) -->
<AutoComplete BootstrapTheme="BootstrapTheme.Danger" ... />
<!-- Warning (yellow) -->
<AutoComplete BootstrapTheme="BootstrapTheme.Warning" ... />Available Variants: Default, Primary, Secondary, Success, Danger, Warning, Info, Light, Dark
<!-- Light mode -->
<AutoComplete Theme="Theme.Light" ... />
<!-- Dark mode -->
<AutoComplete Theme="Theme.Dark" ... />
<!-- Auto (follows system preference) -->
<AutoComplete Theme="Theme.Auto" ... />Switch themes dynamically with smooth transitions:
<AutoComplete TItem="Product"
ThemePreset="@currentTheme"
EnableThemeTransitions="true"
Items="@products"
TextField="@(p => p.Name)" />
<div class="theme-switcher">
<button @onclick="() => currentTheme = ThemePreset.Material">Material</button>
<button @onclick="() => currentTheme = ThemePreset.Fluent">Fluent</button>
<button @onclick="() => currentTheme = ThemePreset.Modern">Modern</button>
<button @onclick="() => currentTheme = ThemePreset.Bootstrap">Bootstrap</button>
</div>
@code {
private ThemePreset currentTheme = ThemePreset.Material;
}Override 51 individual properties without writing CSS:
<!-- Preset + Custom Overrides -->
<AutoComplete ThemePreset="ThemePreset.Material"
PrimaryColor="#FF6B6B"
BorderRadius="8px"
FontFamily="Inter, sans-serif"
Items="@products"
@bind-Value="@selectedProduct" />
<!-- Fully Custom (No Preset) - Smallest Bundle (8KB base only) -->
<AutoComplete PrimaryColor="#6200EE"
BackgroundColor="#FFFFFF"
TextColor="#1C1B1F"
BorderColor="#79747E"
BorderRadius="4px"
InputPadding="12px 16px"
FontFamily="Roboto, sans-serif"
FontSize="14px"
DropdownShadow="0 2px 8px rgba(0,0,0,0.15)"
Items="@products"
@bind-Value="@selectedProduct" />Available Properties (51 total):
@using EasyAppDev.Blazor.AutoComplete.Options
<!-- Compact (25% smaller spacing) -->
<AutoComplete Size="ComponentSize.Compact" ... />
<!-- Default (standard spacing) -->
<AutoComplete Size="ComponentSize.Default" ... />
<!-- Large (25% larger spacing) -->
<AutoComplete Size="ComponentSize.Large" ... />WCAG 2.1 AA Compliant (~95%) - Full ARIA 1.2 Combobox pattern with comprehensive screen reader support.
| Key | Action |
|---|---|
| ArrowDown/Up | Navigate items |
| Enter | Select item |
| Escape | Close dropdown |
| Home/End | First/last item |
| Tab | Close and move focus |
Screen Reader Support:
Label Association:
<label for="search">Search:</label>
<AutoComplete InputId="search" Items="@items" ... />Form Validation:
<EditForm Model="@model">
<AutoComplete @bind-Value="@model.Country"
ValueExpression="@(() => model.Country)" />
<!-- Errors announced automatically -->
</EditForm>Visual Accessibility:
:focus-visible for keyboard-only navigation<ul>, <li>, <button>)Compliance:
Full Native AOT support with zero runtime reflection:
// ✅ VALID: Simple property access
<AutoComplete TextField="@(p => p.Name)" ... />
// ❌ INVALID: Method call - triggers EBDAC001 error
<AutoComplete TextField="@(p => p.Name.ToUpper())" ... />
// ❌ INVALID: String interpolation - triggers EBDAC001 error
<AutoComplete TextField="@(p => $\"{p.Name}\")" ... />Diagnostic Codes:
dotnet publish -c Release /p:PublishAot=trueAOT-Safe Features:
Expression.Compile() callsIsTrimmable=true| Parameter | Type | Default | Description |
|---|---|---|---|
Config | AutoCompleteConfig<TItem>? | null | Fluent configuration object (when provided, takes precedence over individual parameters) |
Items | IEnumerable<TItem>? | null | Collection of items to display |
DataSource | IAutoCompleteDataSource<TItem>? | null | Async data source for remote data |
Value | TItem? | null | Currently selected value (two-way binding) |
TextField | Expression<Func<TItem, string>>? | null | Expression to extract display text |
SearchFields | Expression<Func<TItem, string[]>>? | null | Multi-field search expression (takes precedence over TextField) |
Placeholder | string? | null | Input placeholder text |
MinSearchLength | int | 1 | Minimum characters before searching |
MaxDisplayedItems | int | 100 | Maximum items to display |
AllowClear | bool | true | Show clear button |
Disabled | bool | false | Disable the component |
DebounceMs | int | 300 | Debounce delay in milliseconds |
CloseOnSelect | bool | true | Close dropdown on selection |
AriaLabel | string? | null | ARIA label for accessibility |
InputId | string? | null | Explicit ID for input element (for label association) |
| Parameter | Type | Default | Description |
|---|---|---|---|
FilterStrategy | FilterStrategy | StartsWith | Filtering strategy (StartsWith, Contains, Fuzzy, Custom) |
CustomFilter | IFilterEngine<TItem>? | null | Custom filter engine when FilterStrategy.Custom |
| Parameter | Type | Default | Description |
|---|---|---|---|
DisplayMode | ItemDisplayMode | Custom | Built-in display mode (Simple, TitleWithDescription, TitleWithBadge, TitleDescriptionBadge, IconWithTitle, IconTitleDescription, Card, Custom) |
DescriptionField | Expression<Func<TItem, string>>? | null | Property for description text |
BadgeField | Expression<Func<TItem, string>>? | null | Property for badge text |
IconField | Expression<Func<TItem, string>>? | null | Property for icon/emoji |
SubtitleField | Expression<Func<TItem, string>>? | null | Property for subtitle (Card mode) |
BadgeClass | string | "badge bg-primary" | CSS class for badge styling |
| Parameter | Type | Default | Description |
|---|---|---|---|
Theme | Theme | Auto | Color theme (Auto, Light, Dark) |
ThemePreset | ThemePreset | None | Design system preset (Material, Fluent, Modern, Bootstrap) |
BootstrapTheme | BootstrapTheme | Default | Bootstrap color variant (9 options) |
Size | ComponentSize | Default | Component size (Compact, Default, Large) |
EnableThemeTransitions | bool | true | Smooth theme transitions |
RightToLeft | bool | false | RTL text direction |
ThemeOverrides | ThemeOptions? | null | Structured theme customization |
PrimaryColor | string? | null | Individual color override |
BackgroundColor | string? | null | Individual color override |
TextColor | string? | null | Individual color override |
BorderColor | string? | null | Individual color override |
HoverColor | string? | null | Individual color override |
SelectedColor | string? | null | Individual color override |
BorderRadius | string? | null | Individual spacing override |
FontFamily | string? | null | Individual typography override |
FontSize | string? | null | Individual typography override |
DropdownShadow | string? | null | Individual effect override |
| Parameter | Type | Default | Description |
|---|---|---|---|
Virtualize | bool | false | Enable virtualization for large datasets |
VirtualizationThreshold | int | 100 | Minimum items before virtualization activates |
ItemHeight | float | 40 | Item height in pixels (required for virtualization) |
| Parameter | Type | Default | Description |
|---|---|---|---|
GroupBy | Expression<Func<TItem, object>>? | null | Expression to group items by property |
GroupTemplate | RenderFragment<IGrouping<object, TItem>>? | null | Custom group header template |
| Template | Type | Description |
|---|---|---|
ItemTemplate | RenderFragment<TItem>? | Custom item rendering |
NoResultsTemplate | RenderFragment? | Custom no results message |
LoadingTemplate | RenderFragment? | Custom loading indicator |
HeaderTemplate | RenderFragment? | Header above list |
FooterTemplate | RenderFragment? | Footer below list |
GroupTemplate | RenderFragment<IGrouping<object, TItem>>? | Group header rendering |
| Event | Type | Description |
|---|---|---|
ValueChanged | EventCallback<TItem?> | Fired when selection changes (two-way binding) |
| Parameter | Type | Description |
|---|---|---|
ValueExpression | Expression<Func<TItem?>>? | Expression for validation integration |
EditContext | EditContext? | Cascading EditContext for form validation |
| Package | Version | Description | Size |
|---|---|---|---|
EasyAppDev.Blazor.AutoComplete | Core component | 32KB Brotli / 41KB Gzip (inlined when trimmed) | |
EasyAppDev.Blazor.AutoComplete.Generators | Source generators | 0KB runtime | |
EasyAppDev.Blazor.AutoComplete.AI | AI integration | ~25KB (estimated) |
The component follows SOLID principles with service-based architecture:
IFilterEngine<TItem>, all data sources implement IAutoCompleteDataSource<TItem>Three source generators ensure AOT compatibility and developer productivity:
Contributions are welcome! Please read our Contributing Guide for details.
This project is licensed under the MIT License - see the LICENSE file for details.
Built with:
Made with ❤️ by EasyAppDev