···11import React from "react";
22import { useAtProtoRecord } from "../hooks/useAtProtoRecord";
3344+/**
55+ * Common rendering customization props for AT Protocol records.
66+ */
47interface AtProtoRecordRenderProps<T> {
88+ /** Custom renderer component that receives the fetched record and loading state. */
59 renderer?: React.ComponentType<{
610 record: T;
711 loading: boolean;
812 error?: Error;
913 }>;
1414+ /** React node displayed when no record is available (after error or before load). */
1015 fallback?: React.ReactNode;
1616+ /** React node shown while the record is being fetched. */
1117 loadingIndicator?: React.ReactNode;
1218}
13192020+/**
2121+ * Props for fetching an AT Protocol record from the network.
2222+ */
1423type AtProtoRecordFetchProps<T> = AtProtoRecordRenderProps<T> & {
2424+ /** Repository DID that owns the record. */
1525 did: string;
2626+ /** NSID collection containing the record. */
1627 collection: string;
2828+ /** Record key identifying the specific record. */
1729 rkey: string;
3030+ /** Must be undefined when fetching (discriminates the union type). */
1831 record?: undefined;
1932};
20333434+/**
3535+ * Props for rendering a prefetched AT Protocol record.
3636+ */
2137type AtProtoRecordProvidedRecordProps<T> = AtProtoRecordRenderProps<T> & {
3838+ /** Prefetched record value to render (skips network fetch). */
2239 record: T;
4040+ /** Optional DID for context (not used for fetching). */
2341 did?: string;
4242+ /** Optional collection for context (not used for fetching). */
2443 collection?: string;
4444+ /** Optional rkey for context (not used for fetching). */
2545 rkey?: string;
2646};
27474848+/**
4949+ * Union type for AT Protocol record props - supports both fetching and prefetched records.
5050+ */
2851export type AtProtoRecordProps<T = unknown> =
2952 | AtProtoRecordFetchProps<T>
3053 | AtProtoRecordProvidedRecordProps<T>;
31545555+/**
5656+ * Core component for fetching and rendering AT Protocol records with customizable presentation.
5757+ *
5858+ * Supports two modes:
5959+ * 1. **Fetch mode**: Provide `did`, `collection`, and `rkey` to fetch the record from the network
6060+ * 2. **Prefetch mode**: Provide a `record` directly to skip fetching (useful for SSR/caching)
6161+ *
6262+ * When no custom renderer is provided, displays the record as formatted JSON.
6363+ *
6464+ * @example
6565+ * ```tsx
6666+ * // Fetch mode - retrieves record from network
6767+ * <AtProtoRecord
6868+ * did="did:plc:example"
6969+ * collection="app.bsky.feed.post"
7070+ * rkey="3k2aexample"
7171+ * renderer={MyCustomRenderer}
7272+ * />
7373+ * ```
7474+ *
7575+ * @example
7676+ * ```tsx
7777+ * // Prefetch mode - uses provided record
7878+ * <AtProtoRecord
7979+ * record={myPrefetchedRecord}
8080+ * renderer={MyCustomRenderer}
8181+ * />
8282+ * ```
8383+ *
8484+ * @param props - Either fetch props (did/collection/rkey) or prefetch props (record).
8585+ * @returns A rendered AT Protocol record with loading/error states handled.
8686+ */
3287export function AtProtoRecord<T = unknown>(props: AtProtoRecordProps<T>) {
3388 const {
3489 renderer: Renderer,
+67
lib/providers/AtProtoProvider.tsx
···88import { ServiceResolver, normalizeBaseUrl } from "../utils/atproto-client";
99import { BlobCache, DidCache } from "../utils/cache";
10101111+/**
1212+ * Props for the AT Protocol context provider.
1313+ */
1114export interface AtProtoProviderProps {
1515+ /** Child components that will have access to the AT Protocol context. */
1216 children: React.ReactNode;
1717+ /** Optional custom PLC directory URL. Defaults to https://plc.directory */
1318 plcDirectory?: string;
1419}
15202121+/**
2222+ * Internal context value shared across all AT Protocol hooks.
2323+ */
1624interface AtProtoContextValue {
2525+ /** Service resolver for DID resolution and PDS endpoint discovery. */
1726 resolver: ServiceResolver;
2727+ /** Normalized PLC directory base URL. */
1828 plcDirectory: string;
2929+ /** Cache for DID documents and handle mappings. */
1930 didCache: DidCache;
3131+ /** Cache for fetched blob data. */
2032 blobCache: BlobCache;
2133}
2234···2436 undefined,
2537);
26383939+/**
4040+ * Context provider that supplies AT Protocol infrastructure to all child components.
4141+ *
4242+ * This provider initializes and shares:
4343+ * - Service resolver for DID and PDS endpoint resolution
4444+ * - DID cache for identity resolution
4545+ * - Blob cache for efficient media handling
4646+ *
4747+ * All AT Protocol components (`BlueskyPost`, `LeafletDocument`, etc.) must be wrapped
4848+ * in this provider to function correctly.
4949+ *
5050+ * @example
5151+ * ```tsx
5252+ * import { AtProtoProvider, BlueskyPost } from 'atproto-ui';
5353+ *
5454+ * function App() {
5555+ * return (
5656+ * <AtProtoProvider>
5757+ * <BlueskyPost did="did:plc:example" rkey="3k2aexample" />
5858+ * </AtProtoProvider>
5959+ * );
6060+ * }
6161+ * ```
6262+ *
6363+ * @example
6464+ * ```tsx
6565+ * // Using a custom PLC directory
6666+ * <AtProtoProvider plcDirectory="https://custom-plc.example.com">
6767+ * <YourComponents />
6868+ * </AtProtoProvider>
6969+ * ```
7070+ *
7171+ * @param children - Child components to render within the provider.
7272+ * @param plcDirectory - Optional PLC directory override (defaults to https://plc.directory).
7373+ * @returns Provider component that enables AT Protocol functionality.
7474+ */
2775export function AtProtoProvider({
2876 children,
2977 plcDirectory,
···69117 );
70118}
71119120120+/**
121121+ * Hook that accesses the AT Protocol context provided by `AtProtoProvider`.
122122+ *
123123+ * This hook exposes the service resolver, DID cache, and blob cache for building
124124+ * custom AT Protocol functionality.
125125+ *
126126+ * @throws {Error} When called outside of an `AtProtoProvider`.
127127+ * @returns {AtProtoContextValue} Object containing resolver, caches, and PLC directory URL.
128128+ *
129129+ * @example
130130+ * ```tsx
131131+ * import { useAtProto } from 'atproto-ui';
132132+ *
133133+ * function MyCustomComponent() {
134134+ * const { resolver, didCache, blobCache } = useAtProto();
135135+ * // Use the resolver and caches for custom AT Protocol operations
136136+ * }
137137+ * ```
138138+ */
72139export function useAtProto() {
73140 const ctx = useContext(AtProtoContext);
74141 if (!ctx) throw new Error("useAtProto must be used within AtProtoProvider");