A React component library for rendering common AT Protocol records for applications such as Bluesky and Leaflet.
1import React from "react"; 2import { AtProtoRecord } from "../core/AtProtoRecord"; 3import { TangledStringRenderer } from "../renderers/TangledStringRenderer"; 4import type { TangledStringRecord } from "../renderers/TangledStringRenderer"; 5 6/** 7 * Props for rendering Tangled String records. 8 */ 9export interface TangledStringProps { 10 /** DID of the repository that stores the string record. */ 11 did: string; 12 /** Record key within the `sh.tangled.string` collection. */ 13 rkey: string; 14 /** Prefetched Tangled String record. When provided, skips fetching from the network. */ 15 record?: TangledStringRecord; 16 /** Optional renderer override for custom presentation. */ 17 renderer?: React.ComponentType<TangledStringRendererInjectedProps>; 18 /** Fallback node displayed before loading begins. */ 19 fallback?: React.ReactNode; 20 /** Indicator node shown while data is loading. */ 21 loadingIndicator?: React.ReactNode; 22 /** Preferred color scheme for theming. */ 23 colorScheme?: "light" | "dark" | "system"; 24} 25 26/** 27 * Values injected into custom Tangled String renderer implementations. 28 */ 29export type TangledStringRendererInjectedProps = { 30 /** Loaded Tangled String record value. */ 31 record: TangledStringRecord; 32 /** Indicates whether the record is currently loading. */ 33 loading: boolean; 34 /** Fetch error, if any. */ 35 error?: Error; 36 /** Preferred color scheme for downstream components. */ 37 colorScheme?: "light" | "dark" | "system"; 38 /** DID associated with the record. */ 39 did: string; 40 /** Record key for the string. */ 41 rkey: string; 42 /** Canonical external URL for linking to the string. */ 43 canonicalUrl: string; 44}; 45 46/** NSID for Tangled String records. */ 47export const TANGLED_COLLECTION = "sh.tangled.string"; 48 49/** 50 * Resolves a Tangled String record and renders it with optional overrides while computing a canonical link. 51 * 52 * @param did - DID whose Tangled String should be fetched. 53 * @param rkey - Record key within the Tangled String collection. 54 * @param renderer - Optional component override that will receive injected props. 55 * @param fallback - Node rendered before the first load begins. 56 * @param loadingIndicator - Node rendered while the Tangled String is loading. 57 * @param colorScheme - Preferred color scheme for theming the renderer. 58 * @returns A JSX subtree representing the Tangled String record with loading states handled. 59 */ 60export const TangledString: React.FC<TangledStringProps> = React.memo(({ 61 did, 62 rkey, 63 record, 64 renderer, 65 fallback, 66 loadingIndicator, 67 colorScheme, 68}) => { 69 const Comp: React.ComponentType<TangledStringRendererInjectedProps> = 70 renderer ?? ((props) => <TangledStringRenderer {...props} />); 71 const Wrapped: React.FC<{ 72 record: TangledStringRecord; 73 loading: boolean; 74 error?: Error; 75 }> = (props) => ( 76 <Comp 77 {...props} 78 colorScheme={colorScheme} 79 did={did} 80 rkey={rkey} 81 canonicalUrl={`https://tangled.org/strings/${did}/${encodeURIComponent(rkey)}`} 82 /> 83 ); 84 85 if (record !== undefined) { 86 return ( 87 <AtProtoRecord<TangledStringRecord> 88 record={record} 89 renderer={Wrapped} 90 fallback={fallback} 91 loadingIndicator={loadingIndicator} 92 /> 93 ); 94 } 95 96 return ( 97 <AtProtoRecord<TangledStringRecord> 98 did={did} 99 collection={TANGLED_COLLECTION} 100 rkey={rkey} 101 renderer={Wrapped} 102 fallback={fallback} 103 loadingIndicator={loadingIndicator} 104 /> 105 ); 106}); 107 108export default TangledString;