@redocly/theme
Version:
Shared UI components lib
84 lines (63 loc) • 2.13 kB
text/typescript
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 };
};