import * as React from 'react'; import { useState } from 'react'; import { useDefaultSkinToneConfig } from '../../config/useConfig'; import { DataEmoji } from '../../dataUtils/DataTypes'; import { alphaNumericEmojiIndex } from '../../dataUtils/alphaNumericEmojiIndex'; import { useDebouncedState } from '../../hooks/useDebouncedState'; import { useDisallowedEmojis } from '../../hooks/useDisallowedEmojis'; import { FilterDict } from '../../hooks/useFilter'; import { useMarkInitialLoad } from '../../hooks/useInitialLoad'; import { SkinTones } from '../../types/exposedTypes'; export function PickerContextProvider({ children }: Props) { const disallowedEmojis = useDisallowedEmojis(); const defaultSkinTone = useDefaultSkinToneConfig(); // Initialize the filter with the inititial dictionary const filterRef = React.useRef(alphaNumericEmojiIndex); const disallowClickRef = React.useRef(false); const disallowMouseRef = React.useRef(false); const disallowedEmojisRef = React.useRef>( disallowedEmojis ); const suggestedUpdateState = useDebouncedState(Date.now(), 200); const searchTerm = useDebouncedState('', 100); const skinToneFanOpenState = useState(false); const activeSkinTone = useState(defaultSkinTone); const activeCategoryState = useState(null); const emojisThatFailedToLoadState = useState>(new Set()); const emojiVariationPickerState = useState(null); const [isPastInitialLoad, setIsPastInitialLoad] = useState(false); useMarkInitialLoad(setIsPastInitialLoad); return ( {children} ); } type ReactState = [T, React.Dispatch>]; const PickerContext = React.createContext<{ searchTerm: [string, (term: string) => Promise]; suggestedUpdateState: [number, (term: number) => void]; activeCategoryState: ReactState; activeSkinTone: ReactState; emojisThatFailedToLoadState: ReactState>; isPastInitialLoad: boolean; emojiVariationPickerState: ReactState; skinToneFanOpenState: ReactState; filterRef: React.MutableRefObject; disallowClickRef: React.MutableRefObject; disallowMouseRef: React.MutableRefObject; disallowedEmojisRef: React.MutableRefObject>; }>({ activeCategoryState: [null, () => {}], activeSkinTone: [SkinTones.NEUTRAL, () => {}], disallowClickRef: { current: false }, disallowMouseRef: { current: false }, disallowedEmojisRef: { current: {} }, emojiVariationPickerState: [null, () => {}], emojisThatFailedToLoadState: [new Set(), () => {}], filterRef: { current: {} }, isPastInitialLoad: true, searchTerm: ['', () => new Promise(() => undefined)], skinToneFanOpenState: [false, () => {}], suggestedUpdateState: [Date.now(), () => {}] }); type Props = Readonly<{ children: React.ReactNode; }>; export function useFilterRef() { const { filterRef } = React.useContext(PickerContext); return filterRef; } export function useDisallowClickRef() { const { disallowClickRef } = React.useContext(PickerContext); return disallowClickRef; } export function useDisallowMouseRef() { const { disallowMouseRef } = React.useContext(PickerContext); return disallowMouseRef; } export function useSearchTermState() { const { searchTerm } = React.useContext(PickerContext); return searchTerm; } export function useActiveSkinToneState(): [ SkinTones, (skinTone: SkinTones) => void ] { const { activeSkinTone } = React.useContext(PickerContext); return activeSkinTone; } export function useEmojisThatFailedToLoadState() { const { emojisThatFailedToLoadState } = React.useContext(PickerContext); return emojisThatFailedToLoadState; } export function useIsPastInitialLoad(): boolean { const { isPastInitialLoad } = React.useContext(PickerContext); return isPastInitialLoad; } export function useEmojiVariationPickerState() { const { emojiVariationPickerState } = React.useContext(PickerContext); return emojiVariationPickerState; } export function useSkinToneFanOpenState() { const { skinToneFanOpenState } = React.useContext(PickerContext); return skinToneFanOpenState; } export function useDisallowedEmojisRef() { const { disallowedEmojisRef } = React.useContext(PickerContext); return disallowedEmojisRef; } export function useUpdateSuggested(): [number, () => void] { const { suggestedUpdateState } = React.useContext(PickerContext); const [suggestedUpdated, setsuggestedUpdate] = suggestedUpdateState; return [ suggestedUpdated, function updateSuggested() { setsuggestedUpdate(Date.now()); } ]; } export type FilterState = Record; type ActiveCategoryState = null | string;