@@ -2,11 +2,13 @@ import { For, Match, Show, Switch, createSignal } from 'solid-js'
22import clsx from 'clsx'
33import { css , useStyles } from '../styles/use-styles'
44import { CopiedCopier , Copier , ErrorCopier } from './icons'
5+ import type { CollapsiblePaths } from '../utils/deep-keys'
56
6- export function JsonTree ( props : {
7- value : any
7+ export function JsonTree < TData , TName extends CollapsiblePaths < TData > > ( props : {
8+ value : TData
89 copyable ?: boolean
910 defaultExpansionDepth ?: number
11+ collapsePaths ?: Array < TName >
1012} ) {
1113 return (
1214 < JsonValue
@@ -15,6 +17,8 @@ export function JsonTree(props: {
1517 copyable = { props . copyable }
1618 depth = { 0 }
1719 defaultExpansionDepth = { props . defaultExpansionDepth ?? 1 }
20+ path = ""
21+ collapsePaths = { props . collapsePaths }
1822 />
1923 )
2024}
@@ -25,8 +29,12 @@ function JsonValue(props: {
2529 isRoot ?: boolean
2630 isLastKey ?: boolean
2731 copyable ?: boolean
32+
2833 defaultExpansionDepth : number
2934 depth : number
35+
36+ collapsePaths ?: Array < string >
37+ path : string
3038} ) {
3139 const {
3240 value,
@@ -36,6 +44,8 @@ function JsonValue(props: {
3644 copyable,
3745 defaultExpansionDepth,
3846 depth,
47+ collapsePaths,
48+ path,
3949 } = props
4050 const styles = useStyles ( )
4151
@@ -75,6 +85,8 @@ function JsonValue(props: {
7585 copyable = { copyable }
7686 keyName = { keyName }
7787 value = { value }
88+ collapsePaths = { collapsePaths }
89+ path = { path }
7890 />
7991 )
8092 }
@@ -86,6 +98,8 @@ function JsonValue(props: {
8698 copyable = { copyable }
8799 keyName = { keyName }
88100 value = { value }
101+ collapsePaths = { collapsePaths }
102+ path = { path }
89103 />
90104 )
91105 }
@@ -107,15 +121,22 @@ const ArrayValue = ({
107121 copyable,
108122 defaultExpansionDepth,
109123 depth,
124+ collapsePaths,
125+ path,
110126} : {
111127 value : Array < any >
112128 copyable ?: boolean
113129 keyName ?: string
114130 defaultExpansionDepth : number
115131 depth : number
132+ collapsePaths ?: Array < string >
133+ path : string
116134} ) => {
117135 const styles = useStyles ( )
118- const [ expanded , setExpanded ] = createSignal ( depth <= defaultExpansionDepth )
136+
137+ const [ expanded , setExpanded ] = createSignal (
138+ depth <= defaultExpansionDepth && ! collapsePaths ?. includes ( path ) ,
139+ )
119140
120141 if ( value . length === 0 ) {
121142 return (
@@ -125,6 +146,7 @@ const ArrayValue = ({
125146 "{ keyName } ":{ ' ' }
126147 </ span >
127148 ) }
149+
128150 < span class = { styles ( ) . tree . valueBraces } > []</ span >
129151 </ span >
130152 )
@@ -135,6 +157,7 @@ const ArrayValue = ({
135157 onClick = { ( ) => setExpanded ( ! expanded ( ) ) }
136158 expanded = { expanded ( ) }
137159 />
160+
138161 { keyName && (
139162 < span
140163 onclick = { ( e ) => {
@@ -148,7 +171,9 @@ const ArrayValue = ({
148171 < span class = { styles ( ) . tree . info } > { value . length } items</ span >
149172 </ span >
150173 ) }
174+
151175 < span class = { styles ( ) . tree . valueBraces } > [</ span >
176+
152177 < Show when = { expanded ( ) } >
153178 < span class = { styles ( ) . tree . expandedLine ( Boolean ( keyName ) ) } >
154179 < For each = { value } >
@@ -161,12 +186,15 @@ const ArrayValue = ({
161186 isLastKey = { isLastKey }
162187 defaultExpansionDepth = { defaultExpansionDepth }
163188 depth = { depth + 1 }
189+ collapsePaths = { collapsePaths }
190+ path = { path ? `${ path } [${ i ( ) } ]` : `[${ i ( ) } ]` }
164191 />
165192 )
166193 } }
167194 </ For >
168195 </ span >
169196 </ Show >
197+
170198 < Show when = { ! expanded ( ) } >
171199 < span
172200 onClick = { ( e ) => {
@@ -190,15 +218,23 @@ const ObjectValue = ({
190218 copyable,
191219 defaultExpansionDepth,
192220 depth,
221+ collapsePaths,
222+ path,
193223} : {
194224 value : Record < string , any >
195225 keyName ?: string
196226 copyable ?: boolean
197227 defaultExpansionDepth : number
198228 depth : number
229+ collapsePaths ?: Array < string >
230+ path : string
199231} ) => {
200232 const styles = useStyles ( )
201- const [ expanded , setExpanded ] = createSignal ( depth <= defaultExpansionDepth )
233+
234+ const [ expanded , setExpanded ] = createSignal (
235+ depth <= defaultExpansionDepth && ! collapsePaths ?. includes ( path ) ,
236+ )
237+
202238 const keys = Object . keys ( value )
203239 const lastKeyName = keys [ keys . length - 1 ]
204240
@@ -210,10 +246,12 @@ const ObjectValue = ({
210246 "{ keyName } ":{ ' ' }
211247 </ span >
212248 ) }
249+
213250 < span class = { styles ( ) . tree . valueBraces } > { '{}' } </ span >
214251 </ span >
215252 )
216253 }
254+
217255 return (
218256 < span class = { styles ( ) . tree . expanderContainer } >
219257 { keyName && (
@@ -222,6 +260,7 @@ const ObjectValue = ({
222260 expanded = { expanded ( ) }
223261 />
224262 ) }
263+
225264 { keyName && (
226265 < span
227266 onClick = { ( e ) => {
@@ -235,7 +274,9 @@ const ObjectValue = ({
235274 < span class = { styles ( ) . tree . info } > { keys . length } items</ span >
236275 </ span >
237276 ) }
277+
238278 < span class = { styles ( ) . tree . valueBraces } > { '{' } </ span >
279+
239280 < Show when = { expanded ( ) } >
240281 < span class = { styles ( ) . tree . expandedLine ( Boolean ( keyName ) ) } >
241282 < For each = { keys } >
@@ -248,12 +289,15 @@ const ObjectValue = ({
248289 copyable = { copyable }
249290 defaultExpansionDepth = { defaultExpansionDepth }
250291 depth = { depth + 1 }
292+ collapsePaths = { collapsePaths }
293+ path = { `${ path } ${ path ? '.' : '' } ${ k } ` }
251294 />
252295 </ >
253296 ) }
254297 </ For >
255298 </ span >
256299 </ Show >
300+
257301 < Show when = { ! expanded ( ) } >
258302 < span
259303 onClick = { ( e ) => {
@@ -266,6 +310,7 @@ const ObjectValue = ({
266310 { `...` }
267311 </ span >
268312 </ Show >
313+
269314 < span class = { styles ( ) . tree . valueBraces } > { '}' } </ span >
270315 </ span >
271316 )
0 commit comments