Match-id-aaa8982a24dc5c6e6acb2ddf6410625f0628b112
This commit is contained in:
parent
13e08a8d1b
commit
0475c8f8c0
|
@ -1,7 +1,19 @@
|
||||||
import styles from './Search.less';
|
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 (
|
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 { useState } from 'horizon';
|
||||||
import styles from './VTree.less';
|
import styles from './VTree.less';
|
||||||
import Arrow from '../svgs/Arrow';
|
import Arrow from '../svgs/Arrow';
|
||||||
|
import { createRegExp } from './../utils';
|
||||||
|
|
||||||
export interface IData {
|
export interface IData {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -16,6 +17,7 @@ type IItem = {
|
||||||
onClick: (id: string) => void,
|
onClick: (id: string) => void,
|
||||||
isCollapsed: boolean,
|
isCollapsed: boolean,
|
||||||
isSelect: boolean,
|
isSelect: boolean,
|
||||||
|
highlightValue: string,
|
||||||
} & IData
|
} & IData
|
||||||
|
|
||||||
// TODO: 计算可以展示的最多数量,并且监听显示器高度变化修改数值
|
// TODO: 计算可以展示的最多数量,并且监听显示器高度变化修改数值
|
||||||
|
@ -35,6 +37,7 @@ function Item(props: IItem) {
|
||||||
indentation,
|
indentation,
|
||||||
onClick,
|
onClick,
|
||||||
isSelect,
|
isSelect,
|
||||||
|
highlightValue,
|
||||||
} = props;
|
} = props;
|
||||||
const isShowKey = userKey !== '';
|
const isShowKey = userKey !== '';
|
||||||
const showIcon = hasChild ? <Arrow director={isCollapsed ? 'right' : 'down'} /> : '';
|
const showIcon = hasChild ? <Arrow director={isCollapsed ? 'right' : 'down'} /> : '';
|
||||||
|
@ -49,13 +52,30 @@ function Item(props: IItem) {
|
||||||
itemAttr.tabIndex = 0;
|
itemAttr.tabIndex = 0;
|
||||||
itemAttr.className = styles.treeItem + ' ' + styles.select
|
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 (
|
return (
|
||||||
<div {...itemAttr}>
|
<div {...itemAttr}>
|
||||||
<div style={{ marginLeft: indentation * indentationLength }} className={styles.treeIcon} onClick={handleClickCollapse} >
|
<div style={{ marginLeft: indentation * indentationLength }} className={styles.treeIcon} onClick={handleClickCollapse} >
|
||||||
{showIcon}
|
{showIcon}
|
||||||
</div>
|
</div>
|
||||||
<span className={styles.componentName} >
|
<span className={styles.componentName} >
|
||||||
{name}
|
{showName}
|
||||||
</span>
|
</span>
|
||||||
{isShowKey && (
|
{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 [scrollTop, setScrollTop] = useState(0);
|
||||||
const [collapseNode, setCollapseNode] = useState(new Set<string>());
|
const [collapseNode, setCollapseNode] = useState(new Set<string>());
|
||||||
const [selectItem, setSelectItem] = useState();
|
const [selectItem, setSelectItem] = useState();
|
||||||
|
@ -124,6 +144,7 @@ function VTree({ data }: { data: IData[] }) {
|
||||||
onClick={handleClickItem}
|
onClick={handleClickItem}
|
||||||
isCollapsed={isCollapsed}
|
isCollapsed={isCollapsed}
|
||||||
isSelect={id === selectItem}
|
isSelect={id === selectItem}
|
||||||
|
highlightValue={highlightValue}
|
||||||
{...item} />
|
{...item} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { mockParsedVNodeData, parsedMockState } from '../devtools/mock';
|
||||||
function App() {
|
function App() {
|
||||||
const [parsedVNodeData, setParsedVNodeData] = useState([]);
|
const [parsedVNodeData, setParsedVNodeData] = useState([]);
|
||||||
const [componentInfo, setComponentInfo] = useState({name: null, attrs: {}});
|
const [componentInfo, setComponentInfo] = useState({name: null, attrs: {}});
|
||||||
|
const [filterValue, setFilterValue] = useState('');
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isDev) {
|
if (isDev) {
|
||||||
setParsedVNodeData(mockParsedVNodeData);
|
setParsedVNodeData(mockParsedVNodeData);
|
||||||
|
@ -42,6 +43,11 @@ function App() {
|
||||||
};
|
};
|
||||||
data.push(item);
|
data.push(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleSearchChange = (str: string) => {
|
||||||
|
setFilterValue(str);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.app}>
|
<div className={styles.app}>
|
||||||
<div className={styles.left}>
|
<div className={styles.left}>
|
||||||
|
@ -51,11 +57,11 @@ function App() {
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.divider} />
|
<div className={styles.divider} />
|
||||||
<div className={styles.search}>
|
<div className={styles.search}>
|
||||||
<Search />
|
<Search onChange={handleSearchChange}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.left_bottom}>
|
<div className={styles.left_bottom}>
|
||||||
<VTree data={data} />
|
<VTree data={data} highlightValue={filterValue}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.right}>
|
<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