@@ -14,6 +14,7 @@ import { Box, Button, Collapse, Typography } from "@mui/material";
1414import { Tooltip , IconButton } from "@mui/material" ;
1515import { Colors } from "design/theme" ;
1616import React , { useState } from "react" ;
17+ import { Color } from "three" ;
1718
1819// show more / show less button for long string
1920const LeafString : React . FC < { value : string } > = ( { value } ) => {
@@ -80,11 +81,11 @@ const LeafString: React.FC<{ value: string }> = ({ value }) => {
8081type Props = {
8182 node : TreeNode ;
8283 level : number ;
83-
8484 // src is either an external URL(string) or the internal object
8585 onPreview : ( src : string | any , index : number , isInternal ?: boolean ) => void ;
8686 getInternalByPath : ( path : string ) => { data : any ; index : number } | undefined ;
8787 getJsonByPath ?: ( path : string ) => any ;
88+ highlightText ?: string ;
8889} ;
8990
9091// copy helper function
@@ -112,6 +113,7 @@ const FileTreeRow: React.FC<Props> = ({
112113 onPreview,
113114 getInternalByPath,
114115 getJsonByPath,
116+ highlightText,
115117} ) => {
116118 const [ open , setOpen ] = useState ( false ) ;
117119 const [ copied , setCopied ] = useState ( false ) ;
@@ -120,6 +122,34 @@ const FileTreeRow: React.FC<Props> = ({
120122 const internal = getInternalByPath ( node . path ) ;
121123 const externalUrl = node . link ?. url ;
122124
125+ const rowRef = React . useRef < HTMLDivElement | null > ( null ) ;
126+ // Highlight only if this row is exactly the subject folder (e.g., "sub-04")
127+ const isSubjectFolder =
128+ node . kind === "folder" && / ^ s u b - [ A - Z a - z 0 - 9 ] + $ / i. test ( node . name ) ;
129+ const isExactHit =
130+ ! ! highlightText &&
131+ isSubjectFolder &&
132+ node . name . toLowerCase ( ) === highlightText . toLowerCase ( ) ;
133+
134+ React . useEffect ( ( ) => {
135+ if ( isExactHit && rowRef . current ) {
136+ rowRef . current . scrollIntoView ( { behavior : "smooth" , block : "center" } ) ;
137+ // subtle flash
138+ // rowRef.current.animate(
139+ // [
140+ // { backgroundColor: `${Colors.yellow}`, offset: 0 }, // turn yellow
141+ // { backgroundColor: `${Colors.yellow}`, offset: 0.85 }, // stay yellow 85% of time
142+ // { backgroundColor: "transparent", offset: 1 }, // then fade out
143+ // ],
144+ // { duration: 8000, easing: "ease", fill: "forwards" }
145+ // );
146+ }
147+ } , [ isExactHit ] ) ;
148+
149+ const rowHighlightSx = isExactHit
150+ ? { backgroundColor : `${ Colors . yellow } ` , borderRadius : 4 }
151+ : { } ;
152+
123153 const handleCopy = async ( e : React . MouseEvent ) => {
124154 e . stopPropagation ( ) ; // prevent expand/ collapse from firing when click the copy button
125155 const json = getJsonByPath ?.( node . path ) ; // call getJsonByPath(node.path)
@@ -136,13 +166,15 @@ const FileTreeRow: React.FC<Props> = ({
136166 return (
137167 < >
138168 < Box
169+ ref = { rowRef }
139170 sx = { {
140171 display : "flex" ,
141172 alignItems : "flex-start" ,
142173 gap : 1 ,
143174 py : 0.5 ,
144175 px : 1 ,
145176 cursor : "pointer" ,
177+ ...rowHighlightSx ,
146178 "&:hover" : { backgroundColor : "rgba(0,0,0,0.04)" } ,
147179 } }
148180 onClick = { ( ) => setOpen ( ( o ) => ! o ) }
@@ -252,6 +284,7 @@ const FileTreeRow: React.FC<Props> = ({
252284 onPreview = { onPreview }
253285 getInternalByPath = { getInternalByPath }
254286 getJsonByPath = { getJsonByPath }
287+ highlightText = { highlightText } // for subject highlight
255288 />
256289 ) ) }
257290 </ Collapse >
@@ -308,31 +341,6 @@ const FileTreeRow: React.FC<Props> = ({
308341 : formatLeafValue ( node . value ) }
309342 </ Typography >
310343 ) ) }
311-
312- { /* {!node.link && node.value !== undefined && (
313- <Typography
314- title={
315- node.name === "_ArrayZipData_"
316- ? "[compressed data]"
317- : typeof node.value === "string"
318- ? node.value
319- : JSON.stringify(node.value)
320- }
321- sx={{
322- fontFamily: "monospace",
323- fontSize: "0.85rem",
324- color: "text.secondary",
325- whiteSpace: "nowrap",
326- overflow: "hidden",
327- textOverflow: "ellipsis",
328- mt: 0.25,
329- }}
330- >
331- {node.name === "_ArrayZipData_"
332- ? "[compressed data]"
333- : formatLeafValue(node.value)}
334- </Typography>
335- )} */ }
336344 </ Box >
337345 { /* ALWAYS show copy for files, even when no external/internal */ }
338346 < Box sx = { { alignSelf : "flex-start" } } >
0 commit comments