mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-15 18:39:40 +02:00
- Add InputBarContextMenu with settings toggles (syntax highlighting, auto-focus) - Add InputBarHelpModal for keyboard shortcuts and syntax help - Add inputBarSettings store with localStorage persistence - Add recentInputHistory store for tracking used tags/references - Integrate context menu in calendar app with default calendar selection - Right-click on InputBar opens settings menu 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
167 lines
4 KiB
TypeScript
167 lines
4 KiB
TypeScript
/**
|
|
* Recent Input History Store
|
|
*
|
|
* Tracks recently used tags (#) and references (@) for quick access in the InputBar context menu.
|
|
* Persists to localStorage for cross-session retention.
|
|
*/
|
|
|
|
const STORAGE_KEY_TAGS = 'inputbar-recent-tags';
|
|
const STORAGE_KEY_REFS = 'inputbar-recent-references';
|
|
const MAX_ITEMS = 10;
|
|
|
|
/**
|
|
* Get recent tags from localStorage
|
|
*/
|
|
export function getRecentTags(): string[] {
|
|
if (typeof window === 'undefined') return [];
|
|
try {
|
|
const stored = localStorage.getItem(STORAGE_KEY_TAGS);
|
|
return stored ? JSON.parse(stored) : [];
|
|
} catch {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get recent references from localStorage
|
|
*/
|
|
export function getRecentReferences(): string[] {
|
|
if (typeof window === 'undefined') return [];
|
|
try {
|
|
const stored = localStorage.getItem(STORAGE_KEY_REFS);
|
|
return stored ? JSON.parse(stored) : [];
|
|
} catch {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add a tag to recent history
|
|
* @param tag - The tag to add (with or without #)
|
|
*/
|
|
export function addRecentTag(tag: string): void {
|
|
if (typeof window === 'undefined') return;
|
|
|
|
// Normalize tag (ensure it starts with #)
|
|
const normalizedTag = tag.startsWith('#') ? tag : `#${tag}`;
|
|
|
|
try {
|
|
const current = getRecentTags();
|
|
// Remove if already exists (will be re-added at front)
|
|
const filtered = current.filter((t) => t.toLowerCase() !== normalizedTag.toLowerCase());
|
|
// Add to front, limit to MAX_ITEMS
|
|
const updated = [normalizedTag, ...filtered].slice(0, MAX_ITEMS);
|
|
localStorage.setItem(STORAGE_KEY_TAGS, JSON.stringify(updated));
|
|
} catch {
|
|
// Ignore storage errors
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add a reference to recent history
|
|
* @param reference - The reference to add (with or without @)
|
|
*/
|
|
export function addRecentReference(reference: string): void {
|
|
if (typeof window === 'undefined') return;
|
|
|
|
// Normalize reference (ensure it starts with @)
|
|
const normalizedRef = reference.startsWith('@') ? reference : `@${reference}`;
|
|
|
|
try {
|
|
const current = getRecentReferences();
|
|
// Remove if already exists (will be re-added at front)
|
|
const filtered = current.filter((r) => r.toLowerCase() !== normalizedRef.toLowerCase());
|
|
// Add to front, limit to MAX_ITEMS
|
|
const updated = [normalizedRef, ...filtered].slice(0, MAX_ITEMS);
|
|
localStorage.setItem(STORAGE_KEY_REFS, JSON.stringify(updated));
|
|
} catch {
|
|
// Ignore storage errors
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Extract and save tags and references from input text
|
|
* Call this when user creates an item to track their usage patterns
|
|
* @param text - The input text to parse
|
|
*/
|
|
export function extractAndSaveFromInput(text: string): void {
|
|
if (!text) return;
|
|
|
|
// Extract tags (#word)
|
|
const tagMatches = text.match(/#\w+/g);
|
|
if (tagMatches) {
|
|
tagMatches.forEach((tag) => addRecentTag(tag));
|
|
}
|
|
|
|
// Extract references (@word)
|
|
const refMatches = text.match(/@\w+/g);
|
|
if (refMatches) {
|
|
refMatches.forEach((ref) => addRecentReference(ref));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear all recent history
|
|
*/
|
|
export function clearRecentHistory(): void {
|
|
if (typeof window === 'undefined') return;
|
|
try {
|
|
localStorage.removeItem(STORAGE_KEY_TAGS);
|
|
localStorage.removeItem(STORAGE_KEY_REFS);
|
|
} catch {
|
|
// Ignore storage errors
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a reactive store for use in Svelte 5 components
|
|
* Returns reactive state that updates when history changes
|
|
*/
|
|
export function createRecentInputHistoryStore() {
|
|
let tags = $state<string[]>(getRecentTags());
|
|
let references = $state<string[]>(getRecentReferences());
|
|
|
|
// Refresh from localStorage
|
|
function refresh() {
|
|
tags = getRecentTags();
|
|
references = getRecentReferences();
|
|
}
|
|
|
|
// Add tag and refresh
|
|
function addTag(tag: string) {
|
|
addRecentTag(tag);
|
|
refresh();
|
|
}
|
|
|
|
// Add reference and refresh
|
|
function addReference(ref: string) {
|
|
addRecentReference(ref);
|
|
refresh();
|
|
}
|
|
|
|
// Extract from text and refresh
|
|
function extractAndSave(text: string) {
|
|
extractAndSaveFromInput(text);
|
|
refresh();
|
|
}
|
|
|
|
// Clear and refresh
|
|
function clear() {
|
|
clearRecentHistory();
|
|
refresh();
|
|
}
|
|
|
|
return {
|
|
get tags() {
|
|
return tags;
|
|
},
|
|
get references() {
|
|
return references;
|
|
},
|
|
addTag,
|
|
addReference,
|
|
extractAndSave,
|
|
clear,
|
|
refresh,
|
|
};
|
|
}
|