Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Search whole tree #287

Open
marchingband opened this issue Oct 16, 2023 · 5 comments
Open

Search whole tree #287

marchingband opened this issue Oct 16, 2023 · 5 comments
Assignees

Comments

@marchingband
Copy link

The search bar does not search collapsed parts of the tree.
I would like an optiion to search the whole tree, and automatically expand any parents to show all the matching items.

@lukasbach
Copy link
Owner

Searching through closed items isn't really the scope of the search bar, it's mostly intended as an accessibility feature to more quickly traverse the tree DOM. Finding a specific item in the tree structure depends on the way how the tree data is structured, and this structure can vary greatly between use cases.

However, I added a function "tree.expandSubsequently" that can be used to expand a path of folders, to be able to more easily expand to a certain item. With that, and custom search implementation, something like this shouldn't be that hard to implement. I built a sample in the documentation, alongside an explanation of the idea: https://rct.lukasbach.com/docs/guides/search#finding-items-that-are-not-loaded-in

@marchingband
Copy link
Author

marchingband commented Nov 27, 2023

I manually wrote a workaround, that essentially does this.
My 2cents is that the ideal API would be to optionally search the whole tree and auto expand any branches that contain matches, and then as the search changes, close any branches that were auto-opened, should they no longer contain a match ... this is what I built, as it works for my personal use case, for accessibility, and I am just guessing that it would be a common one. I will look at what you added, thank you very much! I appreciate the response and effort!

@lukasbach
Copy link
Owner

Yes I agree. I might add a more direct interface for directly finding items in the future, but as I mentioned the kind of data structure can vary by use case, and the user can essentially provide an incomplete tree, though I guess this would still be doable with the onMissingItems handler. But maybe this new handler makes building a custom search easy enough.

@justchaying
Copy link

This feature would be extremely useful. In fact that's how I thought search would work by default.

@marchingband Would it be possible for you to share the workaround you implemented?

@marchingband
Copy link
Author

@justchaying Here is a snippet, I basically manually do a search:

    const handleChangeSearch = useCallback(search=>{
        console.log(search.length)
        setSearchText(search)
        if(!search.length) return
        const files = Object.values(items)
        const children = files.filter(item=>(item.data.name || "").includes(search.toLowerCase())).map(item=>item.index)
        // const parents = files.filter(item=>item.children.some(c=>children.includes(c))).map(item=>item.index)
        const parents = files.filter(item=>hasDescendantIn(item, files, children)).map(item=>item.index)
        setExpandedItems([...expandedItems, ...parents])
    }, [expandedItems, searchText, items])

and update expandedItems in the viewState.

               <ControlledTreeEnvironment
                   ...
                    viewState={{
                        ["tree-1"]: {
                            focusedItem,
                            expandedItems : expandedItems,
                            // expandedItems: [...expandedItems, ...expandedInSearch],
                            selectedItems
                        }
                    }}
                    ...
                >

And I have a custom search bar to do the work

const Search = ({ props, handleChangeSearch, close }) => {
    console.log(props)
    const [text, setText] = useState()
    const dummy = useRef()
    return(
        <div className={'search-input-container'}>
        {/* <div className={'rct-tree-search-input-container'}> */}
            {/* <span className="rct-tree-input-icon" /> */}
            <input 
                {...props} 
                value={text}
                className={'rct-tree-search-input'} 
                onChange={e=>{
                    handleChangeSearch(e.target.value)
                    props.onChange(e)
                    setText(e.target.value)
                }}
                onBlur={()=>{
                    setTimeout(()=>{
                        handleChangeSearch("")
                        props.onBlur()
                    }, 100)
                    close()
                }}
            />
        </div>
    )
}

I don't know if that will help but good luck.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants