1- import { Component , isValidElement } from 'react' ;
1+ import { Component , isValidElement , ReactNode } from 'react' ;
22import classNames from 'classnames' ;
33import { createIcon } from '@alilc/lowcode-utils' ;
4- import { TitleContent , isI18nData } from '@alilc/lowcode-types' ;
4+ import { TitleContent , isI18nData , I18nData } from '@alilc/lowcode-types' ;
55import { intl } from '../../intl' ;
66import { Tip } from '../tip' ;
77import './title.less' ;
88
9- export class Title extends Component < { title : TitleContent ; className ?: string ; onClick ?: ( ) => void } > {
9+ /**
10+ * 根据 keywords 将 label 分割成文字片段
11+ * 示例:title = '自定义页面布局',keywords = '页面',返回结果为 ['自定义', '页面', '布局']
12+ * @param label title
13+ * @param keywords 关键字
14+ * @returns 文字片段列表
15+ */
16+ function splitLabelByKeywords ( label : string , keywords : string ) : string [ ] {
17+ const len = keywords . length ;
18+ const fragments = [ ] ;
19+ let str = label ;
20+
21+ while ( str . length > 0 ) {
22+ const index = str . indexOf ( keywords ) ;
23+
24+ if ( index === 0 ) {
25+ fragments . push ( keywords ) ;
26+ str = str . slice ( len ) ;
27+ } else if ( index < 0 ) {
28+ fragments . push ( str ) ;
29+ str = '' ;
30+ } else {
31+ fragments . push ( str . slice ( 0 , index ) ) ;
32+ str = str . slice ( index ) ;
33+ }
34+ }
35+
36+ return fragments ;
37+ }
38+
39+ export class Title extends Component < {
40+ title : TitleContent ;
41+ className ?: string ;
42+ onClick ?: ( ) => void ;
43+ match ?: boolean ;
44+ keywords ?: string ;
45+ } > {
1046 constructor ( props : any ) {
1147 super ( props ) ;
1248 this . handleClick = this . handleClick . bind ( this ) ;
@@ -24,6 +60,32 @@ export class Title extends Component<{ title: TitleContent; className?: string;
2460 onClick && onClick ( e ) ;
2561 }
2662
63+ renderLabel = ( label : string | I18nData | ReactNode ) => {
64+ let { match, keywords } = this . props ;
65+
66+ if ( ! label ) {
67+ return null ;
68+ }
69+
70+ const intlLabel = intl ( label ) ;
71+
72+ if ( typeof intlLabel !== 'string' ) {
73+ return < span className = "lc-title-txt" > { intlLabel } </ span > ;
74+ }
75+
76+ let labelToRender : ReactNode = intlLabel ;
77+
78+ if ( match && keywords ) {
79+ const fragments = splitLabelByKeywords ( intlLabel as string , keywords ) ;
80+
81+ labelToRender = fragments . map ( f => < span style = { { color : f === keywords ? 'red' : 'inherit' } } > { f } </ span > ) ;
82+ }
83+
84+ return (
85+ < span className = "lc-title-txt" > { labelToRender } </ span >
86+ ) ;
87+ } ;
88+
2789 render ( ) {
2890 // eslint-disable-next-line prefer-const
2991 let { title, className } = this . props ;
@@ -61,7 +123,7 @@ export class Title extends Component<{ title: TitleContent; className?: string;
61123 onClick = { this . handleClick }
62124 >
63125 { icon ? < b className = "lc-title-icon" > { icon } </ b > : null }
64- { title . label ? < span className = "lc-title-txt" > { intl ( title . label ) } </ span > : null }
126+ { this . renderLabel ( title . label ) }
65127 { tip }
66128 </ span >
67129 ) ;
0 commit comments