feat: IconGridSelect, CrossLink, SearchPalette components + entity crosslinks

New components:
- IconGridSelect: Visual grid selector replacing <select> dropdowns,
  with icon + label cells, fixed-position popup, smart placement
- CrossLink: Inline clickable badge for cross-entity navigation,
  hover highlights primary, used on entity cards
- SearchPalette: Ctrl+K global command palette, searches all entity
  types via cached data, grouped results, keyboard navigation

Integration:
- Targets: type selector uses IconGridSelect (4-column grid with icons)
- Targets: bot crosslink on telegram/email/matrix target cards
- Command Trackers: provider and config badges → CrossLinks
- Command Trackers: listener bot name → CrossLink
- Command Configs: template config shown as CrossLink on card
- Notification Trackers: provider CrossLink added to card
- Layout: SearchPalette mounted globally

Infrastructure:
- Added CommandConfig, CommandTemplateConfig, CommandTracker types
- Added notificationTrackersCache, commandTrackersCache to caches
- Added allCaches map and fetchAllCaches() for search palette
- Added searchPalette i18n keys (EN/RU)
This commit is contained in:
2026-03-21 23:44:12 +03:00
parent 563716fa76
commit 06b24638cb
12 changed files with 764 additions and 26 deletions
@@ -0,0 +1,50 @@
<script lang="ts">
import { goto } from '$app/navigation';
import MdiIcon from './MdiIcon.svelte';
let {
href,
icon = 'mdiLink',
label,
title = '',
}: {
href: string;
icon?: string;
label: string;
title?: string;
} = $props();
function navigate(e: MouseEvent) {
e.preventDefault();
e.stopPropagation();
goto(href);
}
</script>
<a {href} class="crosslink" title={title || label} onclick={navigate}>
<MdiIcon name={icon} size={12} />
<span>{label}</span>
</a>
<style>
.crosslink {
display: inline-flex;
align-items: center;
gap: 0.25rem;
font-size: 0.65rem;
font-weight: 500;
padding: 0.1rem 0.4rem;
border-radius: 9999px;
background: var(--color-muted);
color: var(--color-muted-foreground);
text-decoration: none;
cursor: pointer;
transition: all 0.15s;
white-space: nowrap;
font-family: var(--font-mono);
}
.crosslink:hover {
background: var(--color-primary);
color: var(--color-primary-foreground);
}
</style>