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 /** Optional renderer override for custom presentation. */
15 renderer?: React.ComponentType<TangledStringRendererInjectedProps>;
16 /** Fallback node displayed before loading begins. */
17 fallback?: React.ReactNode;
18 /** Indicator node shown while data is loading. */
19 loadingIndicator?: React.ReactNode;
20 /** Preferred color scheme for theming. */
21 colorScheme?: "light" | "dark" | "system";
22}
23
24/**
25 * Values injected into custom Tangled String renderer implementations.
26 */
27export type TangledStringRendererInjectedProps = {
28 /** Loaded Tangled String record value. */
29 record: TangledStringRecord;
30 /** Indicates whether the record is currently loading. */
31 loading: boolean;
32 /** Fetch error, if any. */
33 error?: Error;
34 /** Preferred color scheme for downstream components. */
35 colorScheme?: "light" | "dark" | "system";
36 /** DID associated with the record. */
37 did: string;
38 /** Record key for the string. */
39 rkey: string;
40 /** Canonical external URL for linking to the string. */
41 canonicalUrl: string;
42};
43
44/** NSID for Tangled String records. */
45export const TANGLED_COLLECTION = "sh.tangled.string";
46
47/**
48 * Resolves a Tangled String record and renders it with optional overrides while computing a canonical link.
49 *
50 * @param did - DID whose Tangled String should be fetched.
51 * @param rkey - Record key within the Tangled String collection.
52 * @param renderer - Optional component override that will receive injected props.
53 * @param fallback - Node rendered before the first load begins.
54 * @param loadingIndicator - Node rendered while the Tangled String is loading.
55 * @param colorScheme - Preferred color scheme for theming the renderer.
56 * @returns A JSX subtree representing the Tangled String record with loading states handled.
57 */
58export const TangledString: React.FC<TangledStringProps> = ({
59 did,
60 rkey,
61 renderer,
62 fallback,
63 loadingIndicator,
64 colorScheme,
65}) => {
66 const Comp: React.ComponentType<TangledStringRendererInjectedProps> =
67 renderer ?? ((props) => <TangledStringRenderer {...props} />);
68 const Wrapped: React.FC<{
69 record: TangledStringRecord;
70 loading: boolean;
71 error?: Error;
72 }> = (props) => (
73 <Comp
74 {...props}
75 colorScheme={colorScheme}
76 did={did}
77 rkey={rkey}
78 canonicalUrl={`https://tangled.org/strings/${did}/${encodeURIComponent(rkey)}`}
79 />
80 );
81 return (
82 <AtProtoRecord<TangledStringRecord>
83 did={did}
84 collection={TANGLED_COLLECTION}
85 rkey={rkey}
86 renderer={Wrapped}
87 fallback={fallback}
88 loadingIndicator={loadingIndicator}
89 />
90 );
91};
92
93export default TangledString;