A React component library for rendering common AT Protocol records for applications such as Bluesky and Leaflet.
1import React from 'react'; 2import { useAtProtoRecord } from '../hooks/useAtProtoRecord'; 3 4interface AtProtoRecordRenderProps<T> { 5 renderer?: React.ComponentType<{ record: T; loading: boolean; error?: Error }>; 6 fallback?: React.ReactNode; 7 loadingIndicator?: React.ReactNode; 8} 9 10type AtProtoRecordFetchProps<T> = AtProtoRecordRenderProps<T> & { 11 did: string; 12 collection: string; 13 rkey: string; 14 record?: undefined; 15}; 16 17type AtProtoRecordProvidedRecordProps<T> = AtProtoRecordRenderProps<T> & { 18 record: T; 19 did?: string; 20 collection?: string; 21 rkey?: string; 22}; 23 24export type AtProtoRecordProps<T = unknown> = AtProtoRecordFetchProps<T> | AtProtoRecordProvidedRecordProps<T>; 25 26export function AtProtoRecord<T = unknown>(props: AtProtoRecordProps<T>) { 27 const { renderer: Renderer, fallback = null, loadingIndicator = 'Loading…' } = props; 28 const hasProvidedRecord = 'record' in props; 29 const providedRecord = hasProvidedRecord ? props.record : undefined; 30 31 const { record: fetchedRecord, error, loading } = useAtProtoRecord<T>({ 32 did: hasProvidedRecord ? undefined : props.did, 33 collection: hasProvidedRecord ? undefined : props.collection, 34 rkey: hasProvidedRecord ? undefined : props.rkey, 35 }); 36 37 const record = providedRecord ?? fetchedRecord; 38 const isLoading = loading && !providedRecord; 39 40 if (error && !record) return <>{fallback}</>; 41 if (!record) return <>{isLoading ? loadingIndicator : fallback}</>; 42 if (Renderer) return <Renderer record={record} loading={isLoading} error={error} />; 43 return <pre style={{ fontSize: 12, padding: 8, background: '#f5f5f5', overflow: 'auto' }}>{JSON.stringify(record, null, 2)}</pre>; 44}