A React component library for rendering common AT Protocol records for applications such as Bluesky and Leaflet.
1/* eslint-disable react-refresh/only-export-components */ 2import React, { createContext, useContext, useMemo, useRef } from 'react'; 3import { ServiceResolver, normalizeBaseUrl } from '../utils/atproto-client'; 4import { BlobCache, DidCache } from '../utils/cache'; 5 6export interface AtProtoProviderProps { 7 children: React.ReactNode; 8 plcDirectory?: string; 9} 10 11interface AtProtoContextValue { 12 resolver: ServiceResolver; 13 plcDirectory: string; 14 didCache: DidCache; 15 blobCache: BlobCache; 16} 17 18const AtProtoContext = createContext<AtProtoContextValue | undefined>(undefined); 19 20export function AtProtoProvider({ children, plcDirectory }: AtProtoProviderProps) { 21 const normalizedPlc = useMemo(() => normalizeBaseUrl(plcDirectory && plcDirectory.trim() ? plcDirectory : 'https://plc.directory'), [plcDirectory]); 22 const resolver = useMemo(() => new ServiceResolver({ plcDirectory: normalizedPlc }), [normalizedPlc]); 23 const cachesRef = useRef<{ didCache: DidCache; blobCache: BlobCache } | null>(null); 24 if (!cachesRef.current) { 25 cachesRef.current = { didCache: new DidCache(), blobCache: new BlobCache() }; 26 } 27 const value = useMemo<AtProtoContextValue>(() => ({ 28 resolver, 29 plcDirectory: normalizedPlc, 30 didCache: cachesRef.current!.didCache, 31 blobCache: cachesRef.current!.blobCache, 32 }), [resolver, normalizedPlc]); 33 return <AtProtoContext.Provider value={value}>{children}</AtProtoContext.Provider>; 34} 35 36export function useAtProto() { 37 const ctx = useContext(AtProtoContext); 38 if (!ctx) throw new Error('useAtProto must be used within AtProtoProvider'); 39 return ctx; 40}