原文定位
原文定位查看器 .kb-passage(右侧抽屉,滑入不打断对话):open(citation) 渲染来源标题 + KbLocation 三分型位置徽标(第 N 页 / 块 a–b / 字符 a–b),getDocument 同异步取 { content, loc, contextBefore, contextAfter },缺席回落 citedText → snippet;highlight(terms) 纯文本遍历 <mark> 多词轮转分色(data-hit 0|1|2);expand() 展开上下文;受限权限正文 blur 打码 + 申请访问(派 icen:kb-source-open)。Esc 关闭 / Tab 圈禁 / 焦点还原,跳转派 icen:kb-passage-jump,关闭派 icen:kb-passage-close。
右侧滑入抽屉(Esc 关闭,焦点还原触发前元素)
事件日志:等待交互
<div class="toolbar" style="margin-bottom:10px"> <button class="btn btn-sm btn-primary" type="button" id="demo-kb-passage-open">打开可读来源(第 3 页)</button> <button class="btn btn-sm" type="button" id="demo-kb-passage-restricted">打开受限来源(打码 + 申请访问)</button> <button class="btn btn-sm" type="button" id="demo-kb-passage-highlight">highlight 多词分色</button> <button class="btn btn-sm" type="button" id="demo-kb-passage-expand">expand 上下文</button> <button class="btn btn-sm" type="button" id="demo-kb-passage-close">close</button></div><p class="demo-label" style="margin:0 0 8px">右侧滑入抽屉(Esc 关闭,焦点还原触发前元素)</p><div id="demo-kb-passage-host"></div><p class="demo-label" id="demo-kb-passage-log" style="margin-top:8px">事件日志:等待交互</p> 安装
bun add @icen.ai/ui pnpm add @icen.ai/ui npm install @icen.ai/ui yarn add @icen.ai/ui 一行引入该组件(CSS 与 behavior 自动带上,无需关心内部 CSS 文件名):
import '@icen.ai/ui/kit/kb-passage'; 也可以用脚手架直接打印引入行:
bunx --bun @icen.ai/ui add kb-passage
Astro 项目注意:kit 入口里的 CSS import 在页面 <script> 里会被 Astro 的 client bundle 摇掉——请改在布局 frontmatter 里引 CSS(import '@icen.ai/ui/components/kb-ground.css';),JS 行为仍可走 kit。Vite SPA / webpack 项目无此问题。
用法
import { createKbPassage } from '@icen.ai/ui/kit/kb-passage';const viewer = createKbPassage(hostEl, { getDocument: (citation) => fetch('/api/docs/' + citation.documentId).then((r) => r.json()), // 返回 { content, loc?, contextBefore?, contextAfter? };未提供 / 落空回落 citedText → snippet // anchor: anchorEl, // 提供后 open 时滚动定位容器内 [data-kb-loc](精确匹配 → loc.start 最近匹配) onJump: (citation) => console.log('jump', citation.title),});viewer.open({ id: 'c1', title: '供应商准入手册 v3.2', kind: 'wiki', documentId: 'doc-vendor-32', loc: { kind: 'page', start: 3, end: 3 }, // KbLocation 三分型:char | page | block citedText: '评分低于 60 分不予通过' });viewer.highlight(['供应商', '验厂']); // <mark class="kb-passage-hit" data-hit="0|1|2"> 多词轮转分色viewer.expand(); // 展示 contextBefore / contextAfter(一层,幂等)viewer.close(); // 派 icen:kb-passage-close,焦点还原// 受限来源(permission ≠ readable)正文自动打码 +「申请访问」→ icen:kb-source-open// 事件:icen:kb-passage-jump { citation } / icen:kb-passage-close {}