1
- import { ReactNode , useLayoutEffect , useRef , useState } from 'react'
1
+ import { isValidElement , ReactNode , useCallback , useLayoutEffect , useRef , useState } from 'react'
2
2
3
3
import { Layout , Separator , Spacer , Text } from '@/components'
4
4
import { useResizeObserver } from '@/hooks'
5
5
import { cn , wrapConditionalObjectElement } from '@/utils'
6
6
7
+ export type ViewOnlyItemData = { label : string ; value : ReactNode } | ReactNode
8
+
7
9
function splitArray < T > ( array : T [ ] ) : [ T [ ] , T [ ] ] {
8
10
if ( array . length <= 2 ) {
9
11
return [ array , [ ] ]
@@ -16,7 +18,7 @@ function splitArray<T>(array: T[]): [T[], T[]] {
16
18
return [ firstHalf , secondHalf ]
17
19
}
18
20
19
- const ViewOnlyItem = ( { label, value } : { label : string ; value : ReactNode } ) => (
21
+ export const ViewOnlyItem = ( { label, value } : { label : string ; value : ReactNode } ) => (
20
22
< Layout . Grid key = { label } flow = "row" gapX = "2xl" columns = "minmax(0, 200px) minmax(0, 1fr)" align = "start" >
21
23
< Text color = "foreground-3" as = "dt" >
22
24
{ label }
@@ -31,7 +33,7 @@ const isWideEnoughForColumns = (width: number) => width >= 800
31
33
32
34
export interface ViewOnlyProps {
33
35
title ?: string
34
- data : { label : string ; value : ReactNode } [ ]
36
+ data : ViewOnlyItemData [ ]
35
37
layout ?: 'singleColumn' | 'columns'
36
38
className ?: string
37
39
}
@@ -59,6 +61,16 @@ export const ViewOnly = ({ className, title, data, layout = 'columns' }: ViewOnl
59
61
200
60
62
)
61
63
64
+ const renderItem = useCallback ( ( item : ViewOnlyItemData ) => {
65
+ if ( item instanceof Object && 'label' in item && 'value' in item && typeof item . label === 'string' ) {
66
+ return < ViewOnlyItem key = { item . label } label = { item . label } value = { item . value } />
67
+ } else if ( isValidElement ( item ) ) {
68
+ return item
69
+ }
70
+
71
+ return null
72
+ } , [ ] )
73
+
62
74
if ( ! data || data . length === 0 ) return null
63
75
64
76
const isSeparatorVisible = isLayoutColumns && data . length > 2
@@ -77,22 +89,14 @@ export const ViewOnly = ({ className, title, data, layout = 'columns' }: ViewOnl
77
89
align = "start"
78
90
{ ...wrapConditionalObjectElement ( { columns : '1fr auto 1fr' } , isLayoutColumns ) }
79
91
>
80
- < Layout . Grid className = "gap-y-3.5" >
81
- { leftColumnData . map ( ( { label, value } ) => (
82
- < ViewOnlyItem key = { label } label = { label } value = { value } />
83
- ) ) }
84
- </ Layout . Grid >
92
+ < Layout . Grid className = "gap-y-3.5" > { leftColumnData . map ( item => renderItem ( item ) ) } </ Layout . Grid >
85
93
86
94
{ isLayoutColumns && (
87
95
< Separator orientation = "vertical" className = { cn ( 'ml-4 mr-5' , { invisible : ! isSeparatorVisible } ) } />
88
96
) }
89
97
90
98
{ ! ! rightColumnData && (
91
- < Layout . Grid className = "gap-y-3.5" >
92
- { rightColumnData . map ( ( { label, value } ) => (
93
- < ViewOnlyItem key = { label } label = { label } value = { value } />
94
- ) ) }
95
- </ Layout . Grid >
99
+ < Layout . Grid className = "gap-y-3.5" > { rightColumnData . map ( item => renderItem ( item ) ) } </ Layout . Grid >
96
100
) }
97
101
</ Layout . Grid >
98
102
0 commit comments