UNPKG

@redocly/theme

Version:

Shared UI components lib

84 lines (63 loc) 2.13 kB
import { useCallback, useSyncExternalStore } from 'react'; import { isBrowser } from '@redocly/theme/core/utils'; const RECENT_SEARCHES_KEY = 'recentSearches'; const RECENT_SEARCHES_LIMIT = 5; const createRecentSearchesStore = () => { const subscribers = new Set<() => void>(); let cachedSnapshot: string[]; const getSnapshot = (): string[] => { if (!isBrowser()) return []; if (cachedSnapshot) return cachedSnapshot; try { const stored = localStorage.getItem(RECENT_SEARCHES_KEY); cachedSnapshot = stored ? JSON.parse(stored) : []; return cachedSnapshot; } catch (e) { cachedSnapshot = []; return cachedSnapshot; } }; const updateItems = (value: string, isAdd: boolean) => { if (!isBrowser()) return; const currentItems = getSnapshot(); const valueIndex = currentItems.indexOf(value); if (valueIndex !== -1) { currentItems.splice(valueIndex, 1); } if (isAdd) { currentItems.unshift(value); } const limitedItems = currentItems.slice(0, RECENT_SEARCHES_LIMIT); localStorage.setItem(RECENT_SEARCHES_KEY, JSON.stringify(limitedItems)); cachedSnapshot = limitedItems; subscribers.forEach((callback) => callback()); }; const subscribe = (callback: () => void) => { subscribers.add(callback); return () => subscribers.delete(callback); }; return { getSnapshot, subscribe, updateItems, }; }; const recentSearchesStore = createRecentSearchesStore(); export const useRecentSearches = (): { items: string[]; addSearchHistoryItem: (value: string) => void; removeSearchHistoryItem: (value: string) => void; } => { const items = useSyncExternalStore( recentSearchesStore.subscribe, recentSearchesStore.getSnapshot, () => [], ); const addSearchHistoryItem = useCallback((value: string) => { recentSearchesStore.updateItems(value, true); }, []); const removeSearchHistoryItem = useCallback((value: string) => { recentSearchesStore.updateItems(value, false); }, []); return { items, addSearchHistoryItem, removeSearchHistoryItem }; };