A React component library for rendering common AT Protocol records for applications such as Bluesky and Leaflet.
at main 4.4 kB view raw
1import React from "react"; 2import { AtProtoRecord } from "../core/AtProtoRecord"; 3import { TangledRepoRenderer } from "../renderers/TangledRepoRenderer"; 4import type { TangledRepoRecord } from "../types/tangled"; 5import { useAtProto } from "../providers/AtProtoProvider"; 6 7/** 8 * Props for rendering Tangled Repo records. 9 */ 10export interface TangledRepoProps { 11 /** DID of the repository that stores the repo record. */ 12 did: string; 13 /** Record key within the `sh.tangled.repo` collection. */ 14 rkey: string; 15 /** Prefetched Tangled Repo record. When provided, skips fetching from the network. */ 16 record?: TangledRepoRecord; 17 /** Optional renderer override for custom presentation. */ 18 renderer?: React.ComponentType<TangledRepoRendererInjectedProps>; 19 /** Fallback node displayed before loading begins. */ 20 fallback?: React.ReactNode; 21 /** Indicator node shown while data is loading. */ 22 loadingIndicator?: React.ReactNode; 23 /** Preferred color scheme for theming. */ 24 colorScheme?: "light" | "dark" | "system"; 25 /** Whether to show star count from backlinks. Defaults to true. */ 26 showStarCount?: boolean; 27 /** Branch to query for language information. Defaults to trying "main", then "master". */ 28 branch?: string; 29 /** Prefetched language names (e.g., ['TypeScript', 'React']). When provided, skips fetching languages from the knot server. */ 30 languages?: string[]; 31} 32 33/** 34 * Values injected into custom Tangled Repo renderer implementations. 35 */ 36export type TangledRepoRendererInjectedProps = { 37 /** Loaded Tangled Repo record value. */ 38 record: TangledRepoRecord; 39 /** Indicates whether the record is currently loading. */ 40 loading: boolean; 41 /** Fetch error, if any. */ 42 error?: Error; 43 /** Preferred color scheme for downstream components. */ 44 colorScheme?: "light" | "dark" | "system"; 45 /** DID associated with the record. */ 46 did: string; 47 /** Record key for the repo. */ 48 rkey: string; 49 /** Canonical external URL for linking to the repo. */ 50 canonicalUrl: string; 51 /** Whether to show star count from backlinks. */ 52 showStarCount?: boolean; 53 /** Branch to query for language information. */ 54 branch?: string; 55 /** Prefetched language names. */ 56 languages?: string[]; 57}; 58 59/** NSID for Tangled Repo records. */ 60export const TANGLED_REPO_COLLECTION = "sh.tangled.repo"; 61 62/** 63 * Resolves a Tangled Repo record and renders it with optional overrides while computing a canonical link. 64 * 65 * @param did - DID whose Tangled Repo should be fetched. 66 * @param rkey - Record key within the Tangled Repo collection. 67 * @param renderer - Optional component override that will receive injected props. 68 * @param fallback - Node rendered before the first load begins. 69 * @param loadingIndicator - Node rendered while the Tangled Repo is loading. 70 * @param colorScheme - Preferred color scheme for theming the renderer. 71 * @param showStarCount - Whether to show star count from backlinks. Defaults to true. 72 * @param branch - Branch to query for language information. Defaults to trying "main", then "master". 73 * @param languages - Prefetched language names (e.g., ['TypeScript', 'React']). When provided, skips fetching languages from the knot server. 74 * @returns A JSX subtree representing the Tangled Repo record with loading states handled. 75 */ 76export const TangledRepo: React.FC<TangledRepoProps> = React.memo(({ 77 did, 78 rkey, 79 record, 80 renderer, 81 fallback, 82 loadingIndicator, 83 colorScheme, 84 showStarCount = true, 85 branch, 86 languages, 87}) => { 88 const { tangledBaseUrl } = useAtProto(); 89 const Comp: React.ComponentType<TangledRepoRendererInjectedProps> = 90 renderer ?? ((props) => <TangledRepoRenderer {...props} />); 91 const Wrapped: React.FC<{ 92 record: TangledRepoRecord; 93 loading: boolean; 94 error?: Error; 95 }> = (props) => ( 96 <Comp 97 {...props} 98 colorScheme={colorScheme} 99 did={did} 100 rkey={rkey} 101 canonicalUrl={`${tangledBaseUrl}/${did}/${encodeURIComponent(props.record.name)}`} 102 showStarCount={showStarCount} 103 branch={branch} 104 languages={languages} 105 /> 106 ); 107 108 if (record !== undefined) { 109 return ( 110 <AtProtoRecord<TangledRepoRecord> 111 record={record} 112 renderer={Wrapped} 113 fallback={fallback} 114 loadingIndicator={loadingIndicator} 115 /> 116 ); 117 } 118 119 return ( 120 <AtProtoRecord<TangledRepoRecord> 121 did={did} 122 collection={TANGLED_REPO_COLLECTION} 123 rkey={rkey} 124 renderer={Wrapped} 125 fallback={fallback} 126 loadingIndicator={loadingIndicator} 127 /> 128 ); 129}); 130 131export default TangledRepo;