Skip to content

Commit

Permalink
feat: ✨新增 LHighlightText 组件与 LSkeleton组件
Browse files Browse the repository at this point in the history
  • Loading branch information
llq0802 committed Sep 30, 2024
1 parent 6f3def6 commit 4a49fa4
Show file tree
Hide file tree
Showing 14 changed files with 386 additions and 26 deletions.
2 changes: 1 addition & 1 deletion .dumirc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default defineConfig({
link: 'https://github.com/llq0802/lighting-design/tree/v2',
},
{
title: '*更新日志 - V2.1.34',
title: '*更新日志 - V2.1.35',
link: 'https://github.com/llq0802/lighting-design/releases',
},
],
Expand Down
8 changes: 8 additions & 0 deletions sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@ export default {
title: 'LEllipsisText-文本省略',
link: '/components/Ellipsis-Text',
},
{
title: 'LHighlightText-文本高亮',
link: '/components/Highlight-Text',
},
{
title: 'LSkeleton-高级骨架屏',
link: '/components/Skeleton',
},
],
},
{
Expand Down
14 changes: 14 additions & 0 deletions src/HighlightText/demos/demo1.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { LHighlightText } from 'lighting-design';

const text = 'Helloworld, welcome to the wonderful world of React!';
const keywords = ['world', 'react'];

const demo1 = () => {
return (
<div>
<LHighlightText text={text} highlightWords={keywords} />
</div>
);
};

export default demo1;
26 changes: 26 additions & 0 deletions src/HighlightText/demos/demo2.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { LHighlightText } from 'lighting-design';

const text = 'Helloworld, welcome to the wonderful world of React!';
const keywords = ['world', 'react'];

const demo2 = () => {
return (
<div>
<LHighlightText
text={text}
highlightWords={keywords}
caseSensitive
highlightTag="span"
highlightStyle={{
padding: '0 4px',
textDecoration: 'underline',
color: '#209cee',
fontWeight: 600,
transition: `all .3s`,
}}
/>
</div>
);
};

export default demo2;
8 changes: 8 additions & 0 deletions src/HighlightText/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@


@prefix-cls: ~'lightd-highlight-text';

.@{prefix-cls}{
display: inline-block;
width:auto;
}
38 changes: 38 additions & 0 deletions src/HighlightText/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: LHighlightText
toc: content
---

# LHighlightText

文字高亮组件

## 代码演示

### 基础用法

<code src="./demos/demo1.tsx" ></code>

### 区分大小写以及自定义样式

<code src="./demos/demo2.tsx" ></code>

## API

```ts
import { LEllipsisText } from 'lighting-design';
```

除了以下属性 其余跟原生 `span` 标签属性方法一样

| 参数 | 说明 | 类型 | 默认值 |
| :----------------: | :--------------------------------------------: | :---------------------------: | :-----: |
| className | 容器类名 | `string` | `-` |
| style | 容器样式 | `CSSProperties` | `-` |
| autoEscape | 是否自动转义 | `boolean` | `true` |
| caseSensitive | 是否区分大小写 | `boolean` | `false` |
| highlightClassName | 自定义高亮类名 | `string` | `-` |
| highlightStyle | 自定义高亮样式 | `CSSProperties` | `true` |
| highlightTag | 自定义高亮标签, 例如: span | `CSSProperties` | `mark` |
| highlightWords | 要高亮的文本数组, 例如: ['lighting', 'design'] | `string[]` | `-` |
| renderHighlight | 重新渲染高亮的文本内容 | `(text: string) => ReactNode` | `-` |
93 changes: 93 additions & 0 deletions src/HighlightText/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import clsx from 'classnames';
import { emptyArray } from 'lighting-design/constants';
import React, { useMemo } from 'react';
import './index.less';
import type { LHighlightTextProps } from './interface';

const prefixCls = 'lightd-highlight-text';

const escapeRegExp = (text: string): string => text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');

// function splitAndMarkByRegex(
// str: string,
// regex: RegExp,
// ): Array<{
// text: string;
// isMatch: boolean;
// }> {
// const result = [];
// let lastIndex = 0;
// let match;

// // eslint-disable-next-line no-cond-assign
// while ((match = regex.exec(str)) !== null) {
// if (match.index > lastIndex) {
// result.push({
// text: str.slice(lastIndex, match.index),
// isMatch: false,
// });
// }

// result.push({
// text: match[0],
// isMatch: true,
// });

// lastIndex = regex.lastIndex;

// if (!regex.global) {
// break;
// }
// }

// if (lastIndex < str.length) {
// result.push({
// text: str.slice(lastIndex),
// isMatch: false,
// });
// }

// return result;
// }

const LHighlightText: React.FC<LHighlightTextProps> = ({
className,
style,
autoEscape = true,
caseSensitive = false,
text = '',
highlightWords = emptyArray,
highlightClassName,
highlightTag = 'mark',
highlightStyle,
renderHighlight,
}) => {
const parts = useMemo(() => {
const pattern = highlightWords.map((word) => escapeRegExp(autoEscape ? word : String(word))).join('|');
const regex = new RegExp(`(${pattern})`, caseSensitive ? 'g' : 'gi'); // 添加 'i' 标志以忽略大小写
const parts = text.split(regex);
// const parts = splitAndMarkByRegex(text, regex);
return parts;
}, [highlightWords?.join(), caseSensitive, autoEscape, text]);

const dom = (
<span className={clsx(prefixCls, className)} style={style}>
{parts.map((part, i) => {
return (
<React.Fragment key={i}>
{highlightWords.includes(part.toLowerCase())
? renderHighlight
? renderHighlight?.(part)
: React.createElement(highlightTag, { className: highlightClassName, style: highlightStyle }, part)
: part}
</React.Fragment>
);
})}
</span>
);

return dom;
};
export * from './interface';

export default React.memo(LHighlightText);
45 changes: 45 additions & 0 deletions src/HighlightText/interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
export interface LHighlightTextProps extends React.HTMLAttributes<HTMLSpanElement> {
className?: string;
style?: React.CSSProperties;
/**
*是否自动转义
*@see 官网 https://llq0802.github.io/lighting-design/latest LHighlightTextProps
*/
autoEscape?: boolean; //
/**
*是否区分大小写
*@see 官网 https://llq0802.github.io/lighting-design/latest LHighlightTextProps
*/
caseSensitive?: boolean;
/**
*自定义高亮类名
*@see 官网 https://llq0802.github.io/lighting-design/latest LHighlightTextProps
*/
highlightClassName?: string;
/**
*自定义高亮样式
*@see 官网 https://llq0802.github.io/lighting-design/latest LHighlightTextProps
*/
highlightStyle?: React.CSSProperties;
/**
*自定义高亮标签, 例如: span
@default mark
*@see 官网 https://llq0802.github.io/lighting-design/latest LHighlightTextProps
*/
highlightTag?: string;
/**
*展示的文本内容
*@see 官网 https://llq0802.github.io/lighting-design/latest LHighlightTextProps
*/
text: string;
/**
*要高亮的文本数组, 例如: ['lighting', 'design'] 支持动态更新
*@see 官网 https://llq0802.github.io/lighting-design/latest LHighlightTextProps
*/
highlightWords: string[];
/**
*重新渲染高亮的文本内容
*@see 官网 https://llq0802.github.io/lighting-design/latest LHighlightTextProps
*/
renderHighlight?: (text: string) => React.ReactNode;
}
21 changes: 21 additions & 0 deletions src/Skeleton/demos/demo1.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { LSkeleton } from 'lighting-design';

const demo1 = () => {
return (
<div>
<LSkeleton
vertical={false}
topSkeleton={{
margin: '0 0 16px 0',
justify: 'center',
width: 200,
height: 50,
}}
bottomSkeleton
itemHeight={100}
></LSkeleton>
</div>
);
};

export default demo1;
16 changes: 4 additions & 12 deletions src/Skeleton/index.less
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
// .a_skeleton {
// width: auto;
// :global {
// .ant-skeleton-content .ant-skeleton-title {
// }
@prefixCls: ~'lightd-skeleton';

// .ant-skeleton-content .ant-skeleton-paragraph > li {
// }

// .ant-skeleton-content .ant-skeleton-paragraph > li + li {
// }
// }
// }
.@{prefixCls} {
width: auto;
}
36 changes: 36 additions & 0 deletions src/Skeleton/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
title: LSkeleton
toc: content
---

# LSkeleton

文字高亮组件

## 代码演示

### 基础用法

<code src="./demos/demo1.tsx" ></code>

### 区分大小写以及自定义样式

<!-- <code src="./demos/demo2.tsx" ></code> -->

## API

```ts
import { LEllipsisText } from 'lighting-design';
```

除了以下属性 其余跟原生 `span` 标签属性方法一样

| 参数 | 说明 | 类型 | 默认值 |
| :-------: | :-------------------------: | :----------------------------------------------------------------------------------------------------------------: | :----: |
| className | 容器类名 | `string` | `-` |
| style | 容器样式 | `CSSProperties` | `-` |
| maxLength | 最大字符串长度 | `number` | `-` |
| maxWidth | 最大元素宽度 | `number\|string` | `-` |
| emptyText | 自定义空文本的节点 | `ReactNode` | `-` |
| tooltip | 提示属性 默认开启为原始文本 | `boolean` \| [TooltipProps](https://ant-design.antgroup.com/components/tooltip-cn#%E5%85%B1%E5%90%8C%E7%9A%84-api) | `true` |
| chilren | 文本 | `string` | `-` |
Loading

0 comments on commit 4a49fa4

Please sign in to comment.