@@ -11,6 +11,9 @@ import { PropsWithChildren, ReactNode } from "react";
1111import { Codesnippet } from "./CodeSnippet" ;
1212import { CollapsibleCard } from "./CollapsibleCard" ;
1313import { KeyValue } from "./KeyValue" ;
14+ import { CopyMetadataButton } from "./copy-metadata-button" ;
15+
16+ const regex = / ^ < c l a s s \s + ' .* ' > $ / ;
1417
1518type Props = {
1619 intent ?: CollapsibleHeaderProps [ "intent" ] ;
@@ -33,7 +36,6 @@ export function NestedCollapsible({
3336 const objects : { [ key : string ] : Record < string , unknown > } = { } ;
3437 const nonObjects : { [ key : string ] : unknown } = { } ;
3538 const arrays : { [ key : string ] : unknown [ ] } = { } ;
36- const regex = / ^ < c l a s s \s + ' .* ' > $ / ;
3739
3840 for ( const [ key , value ] of Object . entries ( data || { } ) ) {
3941 if ( isObject ( value ) ) {
@@ -48,15 +50,19 @@ export function NestedCollapsible({
4850 const values = Object . entries ( nonObjects ) ;
4951 values . sort ( ( a , b ) => a [ 0 ] . localeCompare ( b [ 0 ] ) ) ;
5052
53+ const hasNoData = Object . keys ( data || { } ) . length === 0 ;
54+
5155 return (
5256 < CollapsibleCard
5357 contentClassName = { contentClassName }
5458 className = { className }
5559 initialOpen = { isInitialOpen }
5660 intent = { intent }
5761 title = { title }
62+ headerClassName = "flex items-center gap-2"
63+ headerChildren = { hasNoData ? null : < CopyMetadataButton copyText = { JSON . stringify ( data ) } /> }
5864 >
59- { Object . keys ( data || { } ) . length === 0 ? (
65+ { hasNoData ? (
6066 < p > Not available</ p >
6167 ) : (
6268 < div className = "flex flex-col gap-3" >
@@ -72,28 +78,7 @@ export function NestedCollapsible({
7278 </ Tooltip >
7379 </ TooltipProvider >
7480 }
75- value = {
76- < >
77- { isString ( value ) && regex . test ( value ) ? (
78- < Codesnippet className = "py-1" highlightCode code = { value } />
79- ) : value === null ? (
80- < div > null</ div >
81- ) : isString ( value ) && isUrl ( value ) ? (
82- < a
83- className = "underline transition-all duration-200 hover:decoration-transparent"
84- href = { value }
85- target = "_blank"
86- rel = "noopener noreferrer"
87- >
88- { value }
89- </ a >
90- ) : (
91- < div className = "whitespace-normal" >
92- { isString ( value ) ? value : JSON . stringify ( value ) }
93- </ div >
94- ) }
95- </ >
96- }
81+ value = { < RenderSimpleValue value = { value } /> }
9782 />
9883 ) ) }
9984 </ dl >
@@ -118,43 +103,21 @@ function RenderArray({ title, value }: { title: string; value: unknown[] }) {
118103
119104 return (
120105 < >
121- < CollapsibleCard intent = "secondary" key = { title } title = { title } >
106+ < CollapsibleCard
107+ headerClassName = "flex items-center gap-2"
108+ headerChildren = { < CopyMetadataButton copyText = { JSON . stringify ( value ) } /> }
109+ intent = "secondary"
110+ key = { title }
111+ title = { title }
112+ >
122113 { simpleValues . length > 0 && (
123- < dl className = "grid grid-cols-1 gap-x-[10px] gap-y-2 truncate md:grid-cols-3 md:gap-y-4" >
124- { Object . entries ( simpleValues ) . map ( ( [ key , value ] ) => (
125- < KeyValue
126- key = { key }
127- label = {
128- < TooltipProvider >
129- < Tooltip >
130- < TooltipTrigger className = "cursor-default truncate" > { key } </ TooltipTrigger >
131- < TooltipContent className = "max-w-[480px]" > { key } </ TooltipContent >
132- </ Tooltip >
133- </ TooltipProvider >
134- }
135- value = {
136- < div className = "py-1" >
137- { value === null ? (
138- < div > null</ div >
139- ) : isString ( value ) && isUrl ( value ) ? (
140- < a
141- className = "underline transition-all duration-200 hover:decoration-transparent"
142- href = { value }
143- target = "_blank"
144- rel = "noopener noreferrer"
145- >
146- { value }
147- </ a >
148- ) : (
149- < div className = "whitespace-normal" >
150- { isString ( value ) ? value : JSON . stringify ( value ) }
151- </ div >
152- ) }
153- </ div >
154- }
155- />
114+ < ul className = "space-y-2 md:space-y-4" >
115+ { simpleValues . map ( ( val , index ) => (
116+ < li key = { index } >
117+ < RenderSimpleValue value = { val } />
118+ </ li >
156119 ) ) }
157- </ dl >
120+ </ ul >
158121 ) }
159122 { nestedValues . length > 0 && (
160123 < ul className = "space-y-4" >
@@ -174,3 +137,28 @@ function RenderArray({ title, value }: { title: string; value: unknown[] }) {
174137 </ >
175138 ) ;
176139}
140+
141+ function RenderSimpleValue ( { value } : { value : unknown } ) {
142+ if ( isString ( value ) && regex . test ( value ) ) {
143+ return < Codesnippet highlightCode code = { value } /> ;
144+ }
145+
146+ if ( value === null ) {
147+ return < div > null</ div > ;
148+ }
149+
150+ if ( isString ( value ) && isUrl ( value ) ) {
151+ return (
152+ < a
153+ className = "underline transition-all duration-200 hover:decoration-transparent"
154+ href = { value }
155+ target = "_blank"
156+ rel = "noopener noreferrer"
157+ >
158+ { value }
159+ </ a >
160+ ) ;
161+ }
162+
163+ return < div className = "whitespace-normal" > { isString ( value ) ? value : JSON . stringify ( value ) } </ div > ;
164+ }
0 commit comments