"use client" import { InformationCircleSolid } from "@medusajs/icons" import { PropData, PropDataMap, PropSpecType } from "@/types/ui" import { useCallback, useMemo } from "react" import { InlineCode, MarkdownContent, Table, Tooltip } from "docs-ui" type PropTableProps = { props: PropDataMap } const PropTable = ({ props }: PropTableProps) => { return ( Prop Type Default {Object.entries(props).map(([propName, propData]) => ( ))}
) } type RowProps = { propName: string propData: PropData } type TypeNode = { text: string tooltipContent?: string canBeCopied?: boolean } const Row = ({ propName, propData: { tsType: tsType, defaultValue, description }, }: RowProps) => { const normalizeRaw = (str: string): string => { return str .replaceAll("\\|", "|") .replaceAll("<", "<") .replaceAll(">", ">") } const getTypeRaw = useCallback((type: PropSpecType): string => { let raw = "raw" in type ? type.raw || type.name : type.name if ("type" in type) { if (type.type === "object") { raw = `{\n ${type.signature.properties .map((property) => `${property.key}: ${property.value.name}`) .join("\n ")}\n}` } else { raw = type.raw } } else if (type.name === "Array" && "elements" in type) { raw = type.elements.map((element) => getTypeRaw(element)).join(" | ") } else if (raw.startsWith("React.")) { return "" } return normalizeRaw(raw) }, []) const getTypeText = useCallback((type: PropSpecType): string => { if (type?.name === "signature" && "type" in type) { return type.type } else if (type?.name === "Array" && type.raw) { return normalizeRaw(type.raw) || "array" } else if ("raw" in type && type.raw?.startsWith("React.")) { return type.name.replace(/^React/, "") } return type.name || "" }, []) const getTypeTooltipContent = useCallback( (type: PropSpecType): string | undefined => { if ( (type?.name === "signature" && "type" in type) || (type?.name === "Array" && type.raw) || ("raw" in type && type.raw) ) { return getTypeRaw(type) } return undefined }, [getTypeRaw] ) const typeNodes = useMemo((): TypeNode[] => { const typeNodes: TypeNode[] = [] if (tsType?.name === "union" && "elements" in tsType) { tsType.elements.forEach((element) => { if ( ("elements" in element && element.elements.length) || "signature" in element ) { const elementTypeText = getTypeText(element) const elementTooltipContent = getTypeTooltipContent(element) typeNodes.push({ text: elementTypeText, tooltipContent: elementTypeText !== elementTooltipContent ? elementTooltipContent : undefined, }) } else if ("value" in element) { typeNodes.push({ text: element.value, canBeCopied: true, }) } else if ("raw" in element) { typeNodes.push({ text: getTypeText(element), tooltipContent: getTypeTooltipContent(element), }) } else { typeNodes.push({ text: element.name, }) } }) } else if (tsType) { typeNodes.push({ text: getTypeText(tsType), tooltipContent: getTypeTooltipContent(tsType), }) } return typeNodes }, [tsType, getTypeText, getTypeTooltipContent]) const defaultVal: string | undefined = defaultValue?.value as string return (
{propName} {description && ( {description} } > )}
{typeNodes.map((typeNode, index) => (
{index > 0 && |} {typeNode.tooltipContent && ( {typeNode.tooltipContent}} className="font-mono !max-w-none" tooltipClassName="!text-left" >
{typeNode.text}
)} {!typeNode.tooltipContent && ( <> {typeNode.canBeCopied && ( {typeNode.text} )} {!typeNode.canBeCopied && {typeNode.text}} )}
))}
{defaultVal && {defaultVal}} {!defaultVal && " - "}
) } export { PropTable }