import type { JSONArray, JSONObject, JSONValue } from "@vertesia/json";
import { DotBadge } from "@vertesia/ui/core";
import clsx from "clsx";
import { ReactNode } from "react";
import { computeTitleFromName } from "../form/ManagedObject.js";
interface JSONViewProps {
value: JSONObject;
}
export function JSONView({ value }: JSONViewProps) {
return
{
Object.entries(value).map(([key, value]) =>
)
}
}
interface PropertyTitleProps {
name: string;
}
function PropertyTitle({ name }: PropertyTitleProps) {
return (
{computeTitleFromName(name)}
)
}
interface BlockElementProps {
children: ReactNode | ReactNode[];
className?: string;
}
function BlockElement({ children, className }: BlockElementProps) {
return (
{children}
)
}
interface PropertyElementProps {
name: string;
value: JSONValue;
}
function PropertyElement({ name, value }: PropertyElementProps) {
const info = getValueInfo(value);
switch (info.type) {
case ValueType.Inline:
return ()
case ValueType.Paragraph:
return ()
case ValueType.Prose:
return ()
case ValueType.Array:
return (
)
case ValueType.Object:
return (
{
Object.entries(value as JSONObject).map(([key, value]) => )
}
)
}
}
interface ArrayPropertyProps {
name?: string,
value: JSONArray;
}
function ArrayProperty({ name, value }: ArrayPropertyProps) {
const inlineLength = value.join(' ').length;
const itemMediumLength = inlineLength / value.length;
const isInline = (typeof value[0] === 'string') && (inlineLength < 80 || inlineLength < 400 && itemMediumLength < 32);
const useBullet = value.length > 9;
return isInline ? (
{name &&
}
{value.map((item, index) =>
{String(item)})}
) : (
{name &&
}
{
(value as JSONArray).map((value, index) => )
}
)
}
interface ItemPropertyProps {
index: number;
value: JSONValue;
useBullet?: boolean;
}
function ItemProperty({ index, value, useBullet }: ItemPropertyProps) {
const bullet = useBullet ? • : {index + 1}.
const info = getValueInfo(value);
let content;
switch (info.type) {
case ValueType.Object:
content =
{
Object.entries(value as JSONObject).map(([key, value]) => )
}
break;
case ValueType.Array:
content = ;
break;
case ValueType.Prose: content = {info.value}
break;
default: content = {info.value}
break;
}
return (
)
}
enum ValueType {
Inline,
Paragraph,
Prose,
Array,
Object
}
function getValueInfo(value: JSONValue): { value: any, type: ValueType } {
if (value == null) {
return {
value: '-',
type: ValueType.Inline
}
}
if (Array.isArray(value)) {
return {
value,
type: ValueType.Array
}
}
const type = typeof value;
if (type === 'string') {
const len = (value as string).length;
let type;
if (len < 80) {
type = ValueType.Inline;
} else if (len > 400) {
type = ValueType.Prose;
} else {
type = ValueType.Paragraph;
value = (value as string).replace(/(?:\n\n)+/g, '\n\n')
}
return { type, value };
} else if (type === 'number' || type === 'boolean') {
return {
value: String(value),
type: ValueType.Inline
}
} else {
return {
value,
type: ValueType.Object
}
}
}