Match-id-aaa8982a24dc5c6e6acb2ddf6410625f0628b112
This commit is contained in:
parent
13e08a8d1b
commit
0475c8f8c0
|
@ -1,7 +1,19 @@
|
|||
import styles from './Search.less';
|
||||
|
||||
export default function Search() {
|
||||
interface SearchProps {
|
||||
onChange: (event: any) => void,
|
||||
}
|
||||
|
||||
export default function Search(props: SearchProps) {
|
||||
const { onChange } = props;
|
||||
const handleChange = (event) => {
|
||||
onChange(event.target.value);
|
||||
}
|
||||
return (
|
||||
<input className={styles.search} placeholder={'Search (text or /regex/)'}/>
|
||||
<input
|
||||
onChange={handleChange}
|
||||
className={styles.search}
|
||||
placeholder={'Search (text or /regex/)'}
|
||||
/>
|
||||
)
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
import { useState } from 'horizon';
|
||||
import styles from './VTree.less';
|
||||
import Arrow from '../svgs/Arrow';
|
||||
import { createRegExp } from './../utils';
|
||||
|
||||
export interface IData {
|
||||
id: string;
|
||||
|
@ -16,6 +17,7 @@ type IItem = {
|
|||
onClick: (id: string) => void,
|
||||
isCollapsed: boolean,
|
||||
isSelect: boolean,
|
||||
highlightValue: string,
|
||||
} & IData
|
||||
|
||||
// TODO: 计算可以展示的最多数量,并且监听显示器高度变化修改数值
|
||||
|
@ -35,6 +37,7 @@ function Item(props: IItem) {
|
|||
indentation,
|
||||
onClick,
|
||||
isSelect,
|
||||
highlightValue,
|
||||
} = props;
|
||||
const isShowKey = userKey !== '';
|
||||
const showIcon = hasChild ? <Arrow director={isCollapsed ? 'right' : 'down'} /> : '';
|
||||
|
@ -49,13 +52,30 @@ function Item(props: IItem) {
|
|||
itemAttr.tabIndex = 0;
|
||||
itemAttr.className = styles.treeItem + ' ' + styles.select
|
||||
}
|
||||
const reg = createRegExp(highlightValue);
|
||||
const heightCharacters = name.match(reg);
|
||||
let showName;
|
||||
if (heightCharacters) {
|
||||
let cutName = name;
|
||||
showName = [];
|
||||
// 高亮第一次匹配即可
|
||||
const char = heightCharacters[0];
|
||||
let index = name.search(char);
|
||||
const notHighlightStr = cutName.slice(0, index);
|
||||
showName.push(notHighlightStr);
|
||||
showName.push(<mark>{char}</mark>);
|
||||
cutName = cutName.slice(index + char.length);
|
||||
showName.push(cutName);
|
||||
} else {
|
||||
showName = name;
|
||||
}
|
||||
return (
|
||||
<div {...itemAttr}>
|
||||
<div style={{ marginLeft: indentation * indentationLength }} className={styles.treeIcon} onClick={handleClickCollapse} >
|
||||
{showIcon}
|
||||
</div>
|
||||
<span className={styles.componentName} >
|
||||
{name}
|
||||
{showName}
|
||||
</span>
|
||||
{isShowKey && (
|
||||
<>
|
||||
|
@ -73,7 +93,7 @@ function Item(props: IItem) {
|
|||
)
|
||||
}
|
||||
|
||||
function VTree({ data }: { data: IData[] }) {
|
||||
function VTree({ data, highlightValue }: { data: IData[], highlightValue: string }) {
|
||||
const [scrollTop, setScrollTop] = useState(0);
|
||||
const [collapseNode, setCollapseNode] = useState(new Set<string>());
|
||||
const [selectItem, setSelectItem] = useState();
|
||||
|
@ -124,6 +144,7 @@ function VTree({ data }: { data: IData[] }) {
|
|||
onClick={handleClickItem}
|
||||
isCollapsed={isCollapsed}
|
||||
isSelect={id === selectItem}
|
||||
highlightValue={highlightValue}
|
||||
{...item} />
|
||||
)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import { mockParsedVNodeData, parsedMockState } from '../devtools/mock';
|
|||
function App() {
|
||||
const [parsedVNodeData, setParsedVNodeData] = useState([]);
|
||||
const [componentInfo, setComponentInfo] = useState({name: null, attrs: {}});
|
||||
const [filterValue, setFilterValue] = useState('');
|
||||
useEffect(() => {
|
||||
if (isDev) {
|
||||
setParsedVNodeData(mockParsedVNodeData);
|
||||
|
@ -42,6 +43,11 @@ function App() {
|
|||
};
|
||||
data.push(item);
|
||||
}
|
||||
|
||||
const handleSearchChange = (str: string) => {
|
||||
setFilterValue(str);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.app}>
|
||||
<div className={styles.left}>
|
||||
|
@ -51,11 +57,11 @@ function App() {
|
|||
</div>
|
||||
<div className={styles.divider} />
|
||||
<div className={styles.search}>
|
||||
<Search />
|
||||
<Search onChange={handleSearchChange}/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.left_bottom}>
|
||||
<VTree data={data} />
|
||||
<VTree data={data} highlightValue={filterValue}/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.right}>
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
export function createRegExp(expression: string){
|
||||
let str = expression;
|
||||
if (str[0] === '/') {
|
||||
str = str.slice(1);
|
||||
}
|
||||
if (str[str.length - 1] === '/') {
|
||||
str = str.slice(0, str.length - 1);
|
||||
}
|
||||
try {
|
||||
return new RegExp(str, 'i');
|
||||
}catch(err) {
|
||||
return null;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue