iter(g238): 新增 highlight 关键词高亮,命中片段包 mark 并随信号实时联动(75 组件)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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';
|
||||
|
||||
@@ -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; // 主标题;缺省不渲染
|
||||
|
||||
@@ -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 底展示,适合搜索结果 / 补全列表的匹配说明",
|
||||
"两个入参都接受信号:搜索框输入实时联动高亮,无需手动重渲染",
|
||||
"大小写不敏感且全部命中(非只第一处);关键词两侧空白自动忽略"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user