packages/docusaurus-theme-common/src/contexts/tabGroupChoice.tsx (56 lines of code) (raw):

/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import React, { useState, useCallback, useEffect, useMemo, useContext, type ReactNode, } from 'react'; import {createStorageSlot, listStorageKeys} from '../utils/storageUtils'; import {ReactContextError} from '../utils/reactUtils'; const TAB_CHOICE_PREFIX = 'docusaurus.tab.'; type ContextValue = { /** A map from `groupId` to the `value` of the saved choice. */ readonly tabGroupChoices: {readonly [groupId: string]: string}; /** Set the new choice value of a group. */ readonly setTabGroupChoices: (groupId: string, newChoice: string) => void; }; const Context = React.createContext<ContextValue | undefined>(undefined); function useContextValue(): ContextValue { const [tabGroupChoices, setChoices] = useState<{ readonly [groupId: string]: string; }>({}); const setChoiceSyncWithLocalStorage = useCallback((groupId, newChoice) => { createStorageSlot(`${TAB_CHOICE_PREFIX}${groupId}`).set(newChoice); }, []); useEffect(() => { try { const localStorageChoices: {[groupId: string]: string} = {}; listStorageKeys().forEach((storageKey) => { if (storageKey.startsWith(TAB_CHOICE_PREFIX)) { const groupId = storageKey.substring(TAB_CHOICE_PREFIX.length); localStorageChoices[groupId] = createStorageSlot(storageKey).get()!; } }); setChoices(localStorageChoices); } catch (err) { console.error(err); } }, []); const setTabGroupChoices = useCallback( (groupId: string, newChoice: string) => { setChoices((oldChoices) => ({...oldChoices, [groupId]: newChoice})); setChoiceSyncWithLocalStorage(groupId, newChoice); }, [setChoiceSyncWithLocalStorage], ); return useMemo( () => ({tabGroupChoices, setTabGroupChoices}), [tabGroupChoices, setTabGroupChoices], ); } export function TabGroupChoiceProvider({ children, }: { children: ReactNode; }): JSX.Element { const value = useContextValue(); return <Context.Provider value={value}>{children}</Context.Provider>; } export function useTabGroupChoice(): ContextValue { const context = useContext(Context); if (context == null) { throw new ReactContextError('TabGroupChoiceProvider'); } return context; }