forked from nosferatu500/react-sortable-tree
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
default-handlers.ts
104 lines (86 loc) · 2.4 KB
/
default-handlers.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import { ReactNode } from 'react'
export interface GetTreeItemChildren {
done: (children: TreeItem[]) => void
node: TreeItem
path: number[]
lowerSiblingCounts: number[]
treeIndex: number
}
export type GetTreeItemChildrenFn = (data: GetTreeItemChildren) => void
export type GetNodeKeyFunction = (data: TreeIndex & TreeNode) => string | number
export interface TreeItem {
title?: ReactNode | undefined
subtitle?: ReactNode | undefined
expanded?: boolean | undefined
children?: TreeItem[] | GetTreeItemChildrenFn | undefined
[x: string]: any
}
export interface TreeNode {
node: TreeItem
}
export interface TreePath {
path: number[]
}
export interface TreeIndex {
treeIndex: number
}
export interface FullTree {
treeData: TreeItem[] | undefined
}
export interface NodeData extends TreeNode, TreePath, TreeIndex {}
export interface SearchData extends NodeData {
searchQuery: string
}
export const defaultGetNodeKey = ({ treeIndex }: TreeIndex) => treeIndex
// Cheap hack to get the text of a react object
const getReactElementText = (parent: any) => {
if (typeof parent === 'string') {
return parent
}
if (
parent === undefined ||
typeof parent !== 'object' ||
!parent.props ||
!parent.props.children ||
(typeof parent.props.children !== 'string' &&
typeof parent.props.children !== 'object')
) {
return ''
}
if (typeof parent.props.children === 'string') {
return parent.props.children
}
return parent.props.children
.map((child: any) => getReactElementText(child))
.join('')
}
// Search for a query string inside a node property
const stringSearch = (
key: string,
searchQuery: string,
node: TreeItem,
path: number[],
treeIndex: number
) => {
if (typeof node[key] === 'function') {
// Search within text after calling its function to generate the text
return String(node[key]({ node, path, treeIndex })).includes(searchQuery)
}
if (typeof node[key] === 'object') {
// Search within text inside react elements
return getReactElementText(node[key]).includes(searchQuery)
}
// Search within string
return node[key] && String(node[key]).includes(searchQuery)
}
export const defaultSearchMethod = ({
node,
path,
treeIndex,
searchQuery,
}: SearchData): boolean => {
return (
stringSearch('title', searchQuery, node, path, treeIndex) ||
stringSearch('subtitle', searchQuery, node, path, treeIndex)
)
}