iter(g238): 新增 highlight 关键词高亮,命中片段包 mark 并随信号实时联动(75 组件)

This commit is contained in:
HIsheR
2026-10-26 21:35:18 +08:00
parent 5f150dccaa
commit 226271986e
12 changed files with 150 additions and 10 deletions
+30
View File
@@ -0,0 +1,30 @@
import { effect, h, type Signal } from '@ui-arch/frame';
import type { HighlightProps } from './types.js';
/*** 作用:读信号或原始值(string | Signal<string> 统一取值) ***/
const read = (v: string | Signal<string>): string => (typeof v === 'function' ? v() : v);
/*** 关键词高亮:命中片段包进 mark(大小写不敏感、全部命中),text / keyword 均支持信号响应式刷新,空关键词原样展示 ***/
export function highlight(props: HighlightProps): HTMLSpanElement {
const root = h('span', { class: 'ua-highlight' }) as HTMLSpanElement;
/*** 作用:按当前 text / keyword 重画内容:命中段包 mark,未命中段原样拼接(effect 追踪两个信号,任一变化重画) ***/
const render = (): void => {
const text = read(props.text);
const kw = read(props.keyword).trim();
root.textContent = '';
if (!kw) { root.textContent = text; return; } // 空关键词不高亮
const lower = text.toLowerCase();
const k = kw.toLowerCase();
let cursor = 0;
for (let idx = lower.indexOf(k); idx !== -1; idx = lower.indexOf(k, cursor)) {
if (idx > cursor) root.append(text.slice(cursor, idx)); // 命中前缀原样
root.append(h('mark', { class: 'ua-highlight-mark' }, text.slice(idx, idx + k.length))); // 命中段包 mark
cursor = idx + k.length;
}
if (cursor < text.length) root.append(text.slice(cursor)); // 尾段原样
};
effect(render);
return root;
}
+1
View File
@@ -74,3 +74,4 @@ export { pinInput } from './pinInput.js';
export { copyButton } from './copyButton.js';
export { countdown } from './countdown.js';
export { kbd } from './kbd.js';
export { highlight } from './highlight.js';
+6
View File
@@ -286,6 +286,12 @@ export interface KbdProps {
keys: string | string[]; // 按键内容:单键字符串或多键组合数组(组合以 + 连接展示)
}
/*** 关键词高亮入参 ***/
export interface HighlightProps {
text: string | Signal<string>; // 原文;传信号则响应式刷新
keyword: string | Signal<string>; // 关键词(大小写不敏感、全部命中,首尾空白忽略);空串不高亮
}
/*** 空状态入参 ***/
export interface EmptyProps {
title?: string; // 主标题;缺省不渲染
+27 -1
View File
@@ -88,7 +88,8 @@
"pinInput(props):验证码输入,N 格单字符数字输入,输入自动进格、退格回删、方向键移格、粘贴自动分发,value 信号双向绑定,mask 可密文显示",
"copyButton(props):复制按钮,点击把 text 写入剪贴板并短暂显示已复制,text 可传函数取实时值,clipboard API 不可用时降级 execCommand",
"countdown(props):倒计时,秒级递减到 0 自动停表并触发 onFinish,缺省 mm:ss 展示,返回句柄 start/stop/reset",
"kbd(props):键盘按键标记,键帽样式展示单个按键或组合键(多键以 + 连接),用于快捷键提示"
"kbd(props):键盘按键标记,键帽样式展示单个按键或组合键(多键以 + 连接),用于快捷键提示",
"highlight(props):关键词高亮,命中片段包 mark(大小写不敏感全部命中),text / keyword 支持信号响应式刷新"
],
"keyTypes": [
"ButtonProps",
@@ -3866,6 +3867,31 @@
"传数组展示组合键:kbd({ keys: [\"Ctrl\", \"K\"] }),键帽之间以弱化的 + 连接(+ 对读屏隐藏)",
"常与提示文案混排:行内 baseline 对齐,键帽底边加厚一线出立体感"
]
},
{
"id": "highlight",
"title": "关键词高亮 Highlight",
"demo": "sec-highlight",
"props": [
{
"n": "text",
"t": "string | Signal<string>",
"r": 1,
"d": "原文;传信号则随信号变化响应式重画"
},
{
"n": "keyword",
"t": "string | Signal<string>",
"r": 1,
"d": "关键词(大小写不敏感、全部命中,首尾空白忽略);空串不高亮、原样展示"
}
],
"example": "highlight({ text: 'Alpha Beta', keyword: 'beta' })",
"steps": [
"传 text + keyword 即可,命中片段以淡黄 mark 底展示,适合搜索结果 / 补全列表的匹配说明",
"两个入参都接受信号:搜索框输入实时联动高亮,无需手动重渲染",
"大小写不敏感且全部命中(非只第一处);关键词两侧空白自动忽略"
]
}
]
}
+9
View File
@@ -5229,3 +5229,12 @@ h5.ua-type-title { font-size: var(--ua-font-size-md); }
color: var(--ua-color-text-muted);
font-size: var(--ua-font-size-xs);
}
/* ---- 关键词高亮(highlight) ---- */
.ua-highlight-mark {
padding: 0 var(--ua-space-05);
border-radius: var(--ua-radius-sm);
background: color-mix(in srgb, var(--ua-color-warning) var(--ua-alpha-tint), transparent); /* 高亮淡底:警示黄浅混,不抢正文 */
color: inherit;
font-weight: var(--ua-weight-medium);
}