Table Index

@if (familyFilters.Count > 1) {
@foreach (var family in familyFilters) { var isAllFilter = string.IsNullOrEmpty(family); var label = isAllFilter ? "All families" : family; }
}
@if (pinnedTables.Count > 0) {

Pinned

@pinnedTables.Count
@foreach (var table in pinnedTables) { @RenderTableOption(table) }
} @if (recentTables.Count > 0) {

Recent

@recentTables.Count
@foreach (var table in recentTables) { @RenderTableOption(table) }
}

All tables

@filteredTables.Count
@if (filteredTables.Count == 0) {
No tables match the current search.
} else {
@foreach (var table in filteredTables) { @RenderTableOption(table) }
}
@code { private readonly List familyFilters = new(); private readonly List filteredTables = new(); private readonly List pinnedTables = new(); private readonly List recentTables = new(); private readonly List keyboardOptions = new(); private string searchText = string.Empty; private string selectedFamily = string.Empty; private string? activeOptionSlug; [Parameter] public IReadOnlyList Tables { get; set; } = Array.Empty(); [Parameter] public string SelectedTableSlug { get; set; } = string.Empty; [Parameter] public IReadOnlyList PinnedTableSlugs { get; set; } = Array.Empty(); [Parameter] public IReadOnlyList RecentTableSlugs { get; set; } = Array.Empty(); [Parameter] public Func? IsPinned { get; set; } [Parameter] public EventCallback OnSelectTable { get; set; } protected override void OnParametersSet() { BuildFamilyFilters(); BuildSections(); EnsureActiveOption(); } private bool GetIsPinned(string tableSlug) => IsPinned?.Invoke(tableSlug) ?? false; private void BuildFamilyFilters() { familyFilters.Clear(); familyFilters.Add(string.Empty); foreach (var family in Tables.Select(table => table.Family).Where(family => !string.IsNullOrWhiteSpace(family)).Distinct(StringComparer.OrdinalIgnoreCase).OrderBy(family => family, StringComparer.OrdinalIgnoreCase)) { familyFilters.Add(family); } } private void BuildSections() { filteredTables.Clear(); pinnedTables.Clear(); recentTables.Clear(); keyboardOptions.Clear(); foreach (var table in Tables) { if (!MatchesFilters(table)) { continue; } filteredTables.Add(table); } foreach (var slug in PinnedTableSlugs) { var table = filteredTables.FirstOrDefault(item => string.Equals(item.Key, slug, StringComparison.OrdinalIgnoreCase)); if (table is not null) { pinnedTables.Add(table); } } foreach (var slug in RecentTableSlugs) { var table = filteredTables.FirstOrDefault(item => string.Equals(item.Key, slug, StringComparison.OrdinalIgnoreCase)); if (table is not null && pinnedTables.All(item => !string.Equals(item.Key, table.Key, StringComparison.OrdinalIgnoreCase))) { recentTables.Add(table); } } foreach (var table in pinnedTables) { AddKeyboardOption(table); } foreach (var table in recentTables) { AddKeyboardOption(table); } foreach (var table in filteredTables) { AddKeyboardOption(table); } } private void AddKeyboardOption(CriticalTableReference table) { if (keyboardOptions.Any(item => string.Equals(item.Key, table.Key, StringComparison.OrdinalIgnoreCase))) { return; } keyboardOptions.Add(table); } private bool MatchesFilters(CriticalTableReference table) { if (!string.IsNullOrEmpty(selectedFamily) && !string.Equals(table.Family, selectedFamily, StringComparison.OrdinalIgnoreCase)) { return false; } if (string.IsNullOrWhiteSpace(searchText)) { return true; } return table.Label.Contains(searchText, StringComparison.OrdinalIgnoreCase) || table.Key.Contains(searchText, StringComparison.OrdinalIgnoreCase) || table.Family.Contains(searchText, StringComparison.OrdinalIgnoreCase); } private void HandleSearchInput(ChangeEventArgs args) { searchText = args.Value?.ToString()?.Trim() ?? string.Empty; BuildSections(); EnsureActiveOption(); } private void SelectFamilyFilter(string family) { selectedFamily = family; BuildSections(); EnsureActiveOption(); } private bool IsFamilyFilterSelected(string family) => string.Equals(selectedFamily, family, StringComparison.OrdinalIgnoreCase); private string GetFamilyFilterCssClass(string family) => IsFamilyFilterSelected(family) ? "tables-family-filter is-selected" : "tables-family-filter"; private void HandleRailKeyDown(KeyboardEventArgs args) { if (keyboardOptions.Count == 0) { return; } if (string.Equals(args.Key, "ArrowDown", StringComparison.Ordinal)) { MoveActiveOption(1); return; } if (string.Equals(args.Key, "ArrowUp", StringComparison.Ordinal)) { MoveActiveOption(-1); return; } if (string.Equals(args.Key, "Home", StringComparison.Ordinal)) { MoveActiveOptionToBoundary(useLast: false); return; } if (string.Equals(args.Key, "End", StringComparison.Ordinal)) { MoveActiveOptionToBoundary(useLast: true); return; } if (string.Equals(args.Key, "Enter", StringComparison.Ordinal) && !string.IsNullOrWhiteSpace(activeOptionSlug)) { _ = OnSelectTable.InvokeAsync(activeOptionSlug); } } private void MoveActiveOption(int offset) { if (keyboardOptions.Count == 0) { activeOptionSlug = null; return; } var currentIndex = keyboardOptions.FindIndex(item => string.Equals(item.Key, activeOptionSlug, StringComparison.OrdinalIgnoreCase)); if (currentIndex < 0) { currentIndex = keyboardOptions.FindIndex(item => string.Equals(item.Key, SelectedTableSlug, StringComparison.OrdinalIgnoreCase)); } var nextIndex = currentIndex < 0 ? 0 : Math.Clamp(currentIndex + offset, 0, keyboardOptions.Count - 1); activeOptionSlug = keyboardOptions[nextIndex].Key; } private void MoveActiveOptionToBoundary(bool useLast) { if (keyboardOptions.Count == 0) { activeOptionSlug = null; return; } activeOptionSlug = useLast ? keyboardOptions[^1].Key : keyboardOptions[0].Key; } private void EnsureActiveOption() { if (keyboardOptions.Count == 0) { activeOptionSlug = null; return; } if (!string.IsNullOrWhiteSpace(activeOptionSlug) && keyboardOptions.Any(item => string.Equals(item.Key, activeOptionSlug, StringComparison.OrdinalIgnoreCase))) { return; } if (!string.IsNullOrWhiteSpace(SelectedTableSlug)) { var selectedOption = keyboardOptions.FirstOrDefault(item => string.Equals(item.Key, SelectedTableSlug, StringComparison.OrdinalIgnoreCase)); if (selectedOption is not null) { activeOptionSlug = selectedOption.Key; return; } } activeOptionSlug = keyboardOptions[0].Key; } private string GetCurationTone(CriticalTableReference table) => table.CurationPercentage >= 100 ? "success" : "warning"; private string GetTableOptionCssClass(CriticalTableReference table) { var classes = new List(); if (string.Equals(table.Key, SelectedTableSlug, StringComparison.OrdinalIgnoreCase)) { classes.Add("is-selected"); } if (string.Equals(table.Key, activeOptionSlug, StringComparison.OrdinalIgnoreCase)) { classes.Add("is-active"); } classes.Add(table.CurationPercentage >= 100 ? "is-curated" : "needs-curation"); return string.Join(' ', classes); } private void SetActiveOption(string tableSlug) => activeOptionSlug = tableSlug; private RenderFragment RenderTableOption(CriticalTableReference table) => @; }