Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/vantui-demo/src/app.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export default {
'pages/image-cropper/index',
'pages/default-props/index',
'pages/count-up/index',
'pages/highlight/index',
],
window: {
navigationBarBackgroundColor: '#f8f8f8',
Expand Down
4 changes: 4 additions & 0 deletions packages/vantui-demo/src/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,10 @@
"path": "empty",
"title": "Empty 空状态"
},
{
"path": "highlight",
"title": "Highlight 高亮文本"
},
{
"path": "ellipsis",
"title": "Ellipsis 文本省略"
Expand Down
4 changes: 4 additions & 0 deletions packages/vantui-demo/src/pages/highlight/index.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export default {
navigationBarTitleText: 'Highlight 高亮文本',
enableShareAppMessage: true,
}
5 changes: 5 additions & 0 deletions packages/vantui-demo/src/pages/highlight/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Demo from '../../../../vantui/src/highlight/demo/index'

export default function Index() {
return <Demo />
}
4 changes: 4 additions & 0 deletions packages/vantui/antm.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,10 @@ function getMenus() {
path: 'empty',
title: 'Empty 空状态',
},
{
path: 'highlight',
title: 'Highlight 高亮文本',
},
{
path: 'result',
title: 'Result 操作结果',
Expand Down
2 changes: 1 addition & 1 deletion packages/vantui/src/count-up/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

### 介绍

一般用于需要滚动数字到某一个值的场景。
一般用于需要滚动数字到某一个值的场景。请升级 `@antmjs/vant` 到 `>= 3.6.3` 版本来使用该组件。

### 引入

Expand Down
52 changes: 52 additions & 0 deletions packages/vantui/src/highlight/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Highlight 高亮文本

### 介绍

高亮指定文本内容。请升级 `@antmjs/vant` 到 `>= 3.6.6` 版本来使用该组件。

### 引入

在 Taro 文件中引入组件

```js
import { Highlight } from '@antmjs/vantui'
```

## 代码演示

### 基础用法

你可以通过 `keywords` 指定需要高亮的关键字,通过 `sourceString` 指定源文本。

::: $demo1 :::

### 多字符匹配

如果需要指定多个关键字,可以以数组的形式传入 `keywords`。

::: $demo2 :::

### 设置高亮标签类名

通过 `highlightClass` 可以设置高亮标签的类名,以便自定义样式。

::: $demo3 :::

### HighlightProps [[详情]](https://github.com/AntmJS/vantui/tree/main/packages/vantui/types/highlight.d.ts)

| 参数 | 说明 | 类型 | 默认值 | 必填 |
| ---------------- | ---------------- | ----------------------------------------------------- | ------ | ------- |
| autoEscape | 是否自动转义 | _&nbsp;&nbsp;boolean<br/>_ | true | `false` |
| caseSensitive | 是否区分大小写 | _&nbsp;&nbsp;boolean<br/>_ | false | `false` |
| highlightClass | 高亮元素的类名 | _&nbsp;&nbsp;string<br/>_ | - | `false` |
| keywords | 期望高亮的文本 | _&nbsp;&nbsp;string&nbsp;&brvbar;&nbsp;string[]<br/>_ | - | `true` |
| sourceString | 源文本 | _&nbsp;&nbsp;string<br/>_ | - | `true` |
| unhighlightClass | 非高亮元素的类名 | _&nbsp;&nbsp;string<br/>_ | - | `false` |

### 样式变量

组件提供了下列 CSS 变量,可用于自定义样式,使用方法请参考[ConfigProvider 组件](https://antmjs.github.io/vantui/#/config-provider)

| 名称 | 默认值 |
| ---------------------- | ------------------------ |
| --highlight-text-color | ` var(--primary-color);` |
3 changes: 3 additions & 0 deletions packages/vantui/src/highlight/demo/demo.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.demo-custom-highlight-class {
color: #ff0000;
}
9 changes: 9 additions & 0 deletions packages/vantui/src/highlight/demo/demo1.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* eslint-disable */
import { Highlight } from '@antmjs/vantui'

export default function Demo() {
const text = '慢慢来,不要急,生活给你出了难题,可也终有一天会给出答案。'
const keywords = '难题'

return <Highlight keywords={keywords} sourceString={text} />
}
9 changes: 9 additions & 0 deletions packages/vantui/src/highlight/demo/demo2.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* eslint-disable */
import { Highlight } from '@antmjs/vantui'

export default function Demo() {
const text = '慢慢来,不要急,生活给你出了难题,可也终有一天会给出答案。'
const keywords = ['难题', '终有一天', '答案']

return <Highlight keywords={keywords} sourceString={text} />
}
16 changes: 16 additions & 0 deletions packages/vantui/src/highlight/demo/demo3.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* eslint-disable */
import { Highlight } from '@antmjs/vantui'
import './demo.less'

export default function Demo() {
const text = '慢慢来,不要急,生活给你出了难题,可也终有一天会给出答案。'
const keywords = '生活'

return (
<Highlight
keywords={keywords}
sourceString={text}
highlightClass="demo-custom-highlight-class"
/>
)
}
28 changes: 28 additions & 0 deletions packages/vantui/src/highlight/demo/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* eslint-disable */

import { Component } from 'react'
import DemoPage from '../../../../vantui-demo/src/components/demo-page/index'
import DemoBlock from '../../../../vantui-demo/src/components/demo-block/index'
import Demo1 from './demo1'
import Demo2 from './demo2'
import Demo3 from './demo3'

export default class Index extends Component {
render() {
return (
<DemoPage title="Highlight 高亮文本" className="pages-count-up-index">
<DemoBlock title="基础用法" padding>
<Demo1 />
</DemoBlock>

<DemoBlock title="多字符匹配" padding>
<Demo2 />
</DemoBlock>

<DemoBlock title="设置高亮标签类名" padding>
<Demo3 />
</DemoBlock>
</DemoPage>
)
}
}
5 changes: 5 additions & 0 deletions packages/vantui/src/highlight/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@import '../style/var.less';

.van-highlight {
.theme(color, '@highlight-text-color');
}
139 changes: 139 additions & 0 deletions packages/vantui/src/highlight/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import { View, Text } from '@tarojs/components'
import { useMemo } from 'react'
import classNames from 'classnames'
import { HighlightProps } from '../../types/highlight'
import * as utils from '../wxs/utils'
import './index.less'

interface Chunk {
start: number
end: number
highlight: boolean
}

export function Highlight(props: HighlightProps) {
const { autoEscape, caseSensitive, keywords, sourceString } = props

const highlightChunks = useMemo(() => {
// 是否区分大小写
const flags = caseSensitive ? 'g' : 'gi'
// 转数组
const _keywords = Array.isArray(keywords) ? keywords : [keywords]

// 生成分组
let chunks = _keywords
.filter((keyword) => keyword)
.reduce((chunks: Chunk[], keyword) => {
// 是否自动转义
if (autoEscape) {
keyword = keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
}

// 用正则匹配
const regex = new RegExp(keyword, flags)

// 遍历关键词匹配值,最后生成 [{start, end, highlight: false}] 开始和结束值,高亮与否的数组
let match
while ((match = regex.exec(sourceString))) {
const start = match.index
const end = regex.lastIndex

if (start >= end) {
regex.lastIndex++
continue
}

chunks.push({
start,
end,
highlight: true,
})
}

return chunks
}, [])

// 合并分组
chunks = chunks
.sort((a, b) => a.start - b.start)
.reduce((chunks: Chunk[], currentChunk) => {
const prevChunk = chunks[chunks.length - 1]

if (!prevChunk || currentChunk.start > prevChunk.end) {
const unhighlightStart = prevChunk ? prevChunk.end : 0
const unhighlightEnd = currentChunk.start

if (unhighlightStart !== unhighlightEnd) {
chunks.push({
start: unhighlightStart,
end: unhighlightEnd,
highlight: false,
})
}

chunks.push(currentChunk)
} else {
prevChunk.end = Math.max(prevChunk.end, currentChunk.end)
}

return chunks
}, [])

const lastChunk = chunks[chunks.length - 1]

// 没有关键词时,没匹配到 chunks 的时候
if (!lastChunk) {
chunks.push({
start: 0,
end: sourceString.length,
highlight: false,
})
}

if (lastChunk && lastChunk.end < sourceString.length) {
chunks.push({
start: lastChunk.end,
end: sourceString.length,
highlight: false,
})
}

return chunks
}, [autoEscape, caseSensitive, keywords, sourceString])

const renderContent = () => {
const {
sourceString,
// 高亮和非高亮样式名和标签名
highlightClass,
unhighlightClass,
} = props

return highlightChunks.map((chunk, index) => {
const { start, end, highlight } = chunk
// 取出文本
const text = sourceString.slice(start, end)

if (highlight) {
return (
<Text
className={classNames(utils.bem('highlight'), highlightClass)}
key={index}
>
{text}
</Text>
)
}

return (
<Text className={unhighlightClass} key={index}>
{text}
</Text>
)
})
}

return <View>{renderContent()}</View>
}

export default Highlight
3 changes: 3 additions & 0 deletions packages/vantui/src/style/var.less
Original file line number Diff line number Diff line change
Expand Up @@ -820,3 +820,6 @@ page {
@check-list-placeholder-color: @placeholder-color;
@check-list-item-padding: 20px 0px;
@check-list-item-border: 1px solid #e9e9f1;

// highlight
@highlight-text-color: var(--primary-color);
37 changes: 37 additions & 0 deletions packages/vantui/types/highlight.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { FunctionComponent } from 'react'
import { ViewProps } from '@tarojs/components'
/**
* @description Highlight Props
*/
export interface HighlightProps extends ViewProps {
/**
* @description 是否自动转义
* @default true
*/
autoEscape?: boolean
/**
* @description 是否区分大小写
* @default false
*/
caseSensitive?: boolean
/**
* @description 高亮元素的类名
*/
highlightClass?: string
/**
* @description 期望高亮的文本
*/
keywords: string | string[]
/**
* @description 源文本
*/
sourceString: string
/**
* @description 非高亮元素的类名
*/
unhighlightClass?: string
}

declare const Highlight: FunctionComponent<HighlightProps>

export { Highlight }
1 change: 1 addition & 0 deletions packages/vantui/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,5 @@ export * from './image-viewer'
export * from './badge'
export * from './check-list'
export * from './image-cropper'
export * from './highlight'
export * from './default-props'
Loading