mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-22 19:46:42 +02:00
refactor(shared-ui): extract search-core for highlight + debounce
Both QuickInputBar (InputBar.svelte), CommandBar.svelte, and GlobalSpotlight were duplicating syntax highlighting and the 150ms search debounce. Pull these into a new `packages/shared-ui/src/search-core/` module so the two input surfaces stay in sync on feel and matching rules. - search-core/highlight.ts — HighlightPattern type, locale-aware getHighlightPatterns(), and the shared highlightText() (HTML-escape + span wrap). Patterns were previously in quick-input/highlightPatterns.ts + inline in CommandBar.svelte. - search-core/config.ts — SEARCH_DEBOUNCE_MS = 150. Used from InputBar, CommandBar, GlobalSpotlight, and apps/mana web SearchEngine. - quick-input/highlightPatterns.ts + types.ts become thin back-compat re-exports. - Public surface: @mana/shared-ui now exports getHighlightPatterns, highlightText, SEARCH_DEBOUNCE_MS, and the HighlightPattern type. No UX change. UIs still live in their own files (per earlier split recommendation: shared backend, separate surfaces). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ad1659f036
commit
24eb8b3b7f
10 changed files with 161 additions and 204 deletions
|
|
@ -1,29 +1,15 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { slide } from 'svelte/transition';
|
||||
import type { QuickInputItem, CreatePreview, HighlightPattern } from './types';
|
||||
import type { QuickInputItem, CreatePreview } from './types';
|
||||
import InputBarContextMenu from './InputBarContextMenu.svelte';
|
||||
import { getInputBarSettingsStore } from './inputBarSettings.svelte';
|
||||
import { getHighlightPatterns } from './highlightPatterns';
|
||||
import { getHighlightPatterns, highlightText, SEARCH_DEBOUNCE_MS } from '../search-core';
|
||||
import type { HighlightPattern } from '../search-core';
|
||||
|
||||
// Settings store
|
||||
const settingsStore = getInputBarSettingsStore();
|
||||
|
||||
function highlightText(text: string, patterns: HighlightPattern[]): string {
|
||||
if (!text) return '';
|
||||
|
||||
let result = text;
|
||||
// Escape HTML first
|
||||
result = result.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
||||
|
||||
// Apply highlights (process in order, avoiding double-highlighting)
|
||||
for (const { pattern, className } of patterns) {
|
||||
result = result.replace(pattern, (match) => `<span class="${className}">${match}</span>`);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
interface DefaultOption {
|
||||
id: string;
|
||||
label: string;
|
||||
|
|
@ -242,7 +228,7 @@
|
|||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
}, 150);
|
||||
}, SEARCH_DEBOUNCE_MS);
|
||||
}
|
||||
|
||||
async function triggerDeferredSearch() {
|
||||
|
|
@ -669,25 +655,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.app-icon.success-icon {
|
||||
color: hsl(var(--color-success, 142 71% 45%));
|
||||
animation: success-check 0.4s ease-out;
|
||||
}
|
||||
|
||||
@keyframes success-check {
|
||||
0% {
|
||||
transform: scale(0.5);
|
||||
opacity: 0;
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.left-action,
|
||||
.right-action {
|
||||
display: flex;
|
||||
|
|
@ -696,13 +663,6 @@
|
|||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.app-icon {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
color: hsl(var(--color-muted-foreground));
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue