import { CoID, JsonValue, LocalNode, RawCoValue } from "cojson"; import { styled } from "goober"; import React, { useState } from "react"; import { Button } from "../ui/button.js"; import { Icon } from "../ui/icon.js"; import { Text } from "../ui/text.js"; import { isCoId } from "./types.js"; import { isBrowserImage, useResolvedCoValue } from "./use-resolve-covalue.js"; const LinkContainer = styled("span")` display: inline-flex; gap: 0.25rem; align-items: center; `; const BooleanText = styled("span")<{ value: boolean }>` font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; ${(props) => props.value ? ` color: var(--j-success-color); ` : ` color: var(--j-destructive-color); `} `; const ObjectContent = styled("pre")` margin-top: 0.375rem; font-size: 0.875rem; white-space: pre-wrap; `; const PreviewContainer = styled("div")` font-size: 0.875rem; display: flex; flex-direction: column; gap: 0.5rem; align-items: flex-start; `; const PreviewGrid = styled("div")` display: grid; grid-template-columns: auto 1fr; gap: 0.5rem; `; const PreviewMoreText = styled(Text)` text-align: left; margin-top: 0.5rem; `; const ImagePreviewContainer = styled("div")` display: flex; flex-direction: column; align-items: flex-start; `; const PreviewImage = styled("img")` width: 2rem; height: 2rem; border: 2px solid white; box-shadow: var(--j-shadow-sm); margin: 0.5rem 0; `; const RecordText = styled("div")` display: flex; align-items: center; gap: 0.25rem; `; const ListText = styled("div")` display: flex; align-items: center; gap: 0.25rem; `; // Is there a chance we can pass the actual CoValue here? export function ValueRenderer({ json, onCoIDClick, compact, }: { json: JsonValue | undefined; onCoIDClick?: (childNode: CoID) => void; compact?: boolean; }) { const [isExpanded, setIsExpanded] = useState(false); if (typeof json === "undefined" || json === undefined) { return undefined; } if (json === null) { return null; } if (typeof json === "string" && isCoId(json)) { const content = ( <> {json} {onCoIDClick && } ); if (onCoIDClick) { return ( ); } return {content}; } if (typeof json === "string") { return {json}; } if (typeof json === "number") { return {json}; } if (typeof json === "boolean") { return {json.toString()}; } const longJson = JSON.stringify(json, null, 2); const shortJson = longJson .split("\n") .slice(0, compact ? 3 : 8) .join("\n"); // Check if collapsed differs from full const hasDifference = longJson !== shortJson; if (typeof json === "object") { return ( <>

{Array.isArray(json) ? <>Array ({json.length}) : <>Object}

{isExpanded ? longJson : shortJson} {hasDifference && !isExpanded ? "\n ..." : null} {!compact && hasDifference ? ( ) : null} ); } return {String(json)}; } export const CoMapPreview = ({ coId, node, limit = 6, }: { coId: CoID; node: LocalNode; limit?: number; }) => { const { value, snapshot, type, extendedType } = useResolvedCoValue( coId, node, ); if (!snapshot) { return (
{" "}
); } if (snapshot === "unavailable" && !value) { return ( Unavailable ); } if (type === "coplaintext") { return <>{value.toString()}; } if (extendedType === "image" && isBrowserImage(snapshot)) { return ( {snapshot.originalSize[0]} x {snapshot.originalSize[1]} ); } if (extendedType === "record") { return ( Record{" "} ({Object.keys(snapshot).length}) ); } if (type === "colist") { return ( List{" "} ({(snapshot as unknown as []).length}) ); } const properties = Object.entries(snapshot); const limitedProperties = extendedType === "account" ? properties .filter( ([key]) => !key.startsWith("key_z") && !key.startsWith("sealer_z") && key !== "readKey", ) .slice(0, limit) : properties.slice(0, limit); return ( {limitedProperties.map(([key, value]) => ( {key}: ))} {properties.length > limit && ( {properties.length - limit} more )} ); };