@feedlog/widget

中文文档
0.2.0发布于 2026/10/16MITTypeScriptES Module零依赖近 30 天下载 2489

零运行时间依赖的 FeedLog 可嵌入反馈部件 .

中文使用文档
文档目录17 节
  1. 安装
  2. 使用量
  3. 公共 API
  4. 初始化选项
  5. 运行时间更新
  6. 主题和堆叠顺序
  7. 启动器交互
  8. 主机登录生命周期
  9. 认证
  10. 浏览器支持
  11. 类型
  12. 如何运作
  13. 捐款
  14. 测试环境
  15. 许可证
  16. 代理页面上下文
  17. 移动面板行为

@ feedlog/ 部件

主机侧 SDK 用于 种子日志 反馈部件。 它使一个启动器和一个iframe中托管反馈接口,零运行时依赖性以及约11个KB gziped的无害环境管理捆绑.

安装

pnpm add @feedlog/widget

使用量

import { createWidget } from '@feedlog/widget'

createWidget({
  baseUrl: 'https://acme.feedlog.ai',
  auth: {
    getToken: async () => {
      const res = await fetch('/api/feedlog-token')
      if (!res.ok) throw new Error('Could not fetch the feedback token')
      return (await res.json()).token ?? null
    },
    login: () => new Promise<void>((resolve) => {
      openYourLoginModal({ onClose: resolve })
    }),
  },
  theme: 'auto',
})

openYourLoginModal 是您的应用程序的功能。 内容 onClose 操作员必须在每个出口运行,包括取消。 返回一个承诺,只有当它代表整个互动,而不仅仅是打开模式.

没有用户系统的产品可以省略 auth数字 :

createWidget({ baseUrl: 'https://acme.feedlog.ai' })

启用 来宾职位 在 FeedLog 中允许这些访客不签名就提交. 由于访客发送已禁用且没有主机认证, 部件无法满足登录请求 .

公共 API

套件输出了四个函数 。 全部返回 void; 没有实例或 destroy 方法.

函数效果
createWidget(options: WidgetOptions)每页初始化一次 。 重复的电话发出警告并被忽略.
openWidget()打开反馈面板而不改变发射装置状态或提示登录.
closeWidget()关闭面板而不破坏面板、清理其草稿或将焦点移出主机对话框.
updateWidget(options: WidgetDisplayOptions)更新主题, 启动器位置/ 状态或堆放顺序 。 它不打开或关闭面板.

打电话 createWidget 首先在正常的整合。 控制不需要等待初始化或iframe准备:最后的开放/关闭指令被保留并按字段显示更新合并. 初始化前的呼叫也被保留,但从未初始化SDK本身. 服务器端的电话什么都不做。 被禁用的工作空间不会产生任何效果,即使之后 openWidget()。 。 。 .

初始化选项

选项说明
baseUrl需要 FeedLog 工作空间 URL .
auth可选主机身份整合.
auth.getToken要求为 auth数字 : () => Promise<string | null>返回已签名的 JWT 或 null 签字后 暂时失败,不会让访客退出.
auth.login可选 () => void | Promise<void>打开你的签名UI。 身份在返回或定居后再次检查.
themelight, (中文(简体) ), dark 或者说 auto (默认). auto 操作系统.
launcher以下列举的可选领域. 丢失的放置场使用仪表板默认.
zIndex0至2147483647的整数;默认值 第40条适用于发射装置和相板.
embedPath默认为 /widget/embed。一个自定义建筑的同源绝对路径嵌入;它不能指另一个来源.
onUnreadChange可选 (count: number) => void 对于自定义条目的未读指标.

baseUrl, (中文(简体) ), auth, (中文(简体) ), embedPath 财务报告和审定财务报表 onUnreadChange 选项。 通话 createWidget 也不再更新它们.

运行时间更新

import { createWidget, openWidget, closeWidget, updateWidget } from '@feedlog/widget'

createWidget({
  baseUrl: 'https://acme.feedlog.ai',
  launcher: { state: 'hidden' },
})

document.querySelector('#help')?.addEventListener('click', openWidget)

updateWidget({ theme: 'dark' })
updateWidget({ zIndex: 40 })
updateWidget({ launcher: { alignment: 'left', bottomOffset: 80 } })
updateWidget({ launcher: { state: 'tab' } })
updateWidget({ launcher: { state: 'button' } })

// A host modal needs the panel closed; the launcher is controlled separately.
closeWidget()
updateWidget({ launcher: { state: 'hidden' } })

WidgetDisplayOptions 仅接受 theme, (中文(简体) ), zIndex 财务报告和审定财务报表 launcher。更新合并各个字段,包括其中的字段 launcher一、导 言 undefined 字段保留其现有价值。 无效提供的显示值 TypeError。更新不会改变仪表板设置.

启动器选项 :

外地数值
alignmentleft 或者说 right默认为 right。 。 。 .
bottomOffset非负式安全整数以像素表示. 默认为 20。 。 。 .
sideOffset非负式安全整数以像素表示. 默认为 20。 。 。 .
statebutton, (中文(简体) ), tab 或者说 hidden。初始化时省略,恢复访客保存的状态,否则显示按钮.

没有固定的冲抵限额。 在不改变配置值的情况下被限制在视图端口,并自动添加设备安全区设置. 桌面和移动共享相同的配置.

在初始化时,被保存的访客安置比SDK和仪表板默认优先. 明确的运行时位置更新可以替换保存拖放并保存其他当前放置字段. 状态,主题和z-index更新使位置保持完整. 明确状态更新超越了访客的偏好,独立于仪表板的访客关闭政策.

主题和堆叠顺序

updateWidget({ theme }) 更改发射装置、面板外壳和iframe内容而无需重新装入帧。 它保留了对话,起草,滚动位置和开放/封闭状态. 带有自己的主题切换的应用程序应该通过 light 或者说 dark; SDK不检查主机的CSS课.

Iframe发布现场主题支持广告. 随着一个更古老或自定义的嵌入到缺少它的地方,当前 shell 和 iframe 主题被保留,而 SDK 记录一个警告. 所请求的主题将适用于随后创建的框架;SDK从不重装活动的框架,只是为了改变其主题.

默认 Z 索引是 第40条,在诸如 50。主机堆放上下文仍然决定最后顺序。 覆盖 zIndex 初始化时或通过初始化 updateWidget 当应用程序的分层尺度不同时.

启动器交互

访客可以用鼠标,笔或触摸来拖动按钮或帮助标签. 移动超过8px开始拖动;释放到最近的左/右边缘. 箭头键还会移动焦点发射器;出逃或被中断的手势会取消拖放. 拖曳不会打开面板或更改发射器形式 .

按钮保留了20px边距并加上拖放后的安全区域. 概述的“帮助”标签在取景口边缘上被冲出,而不论侧面是否抵消。 它的可见大小为22×56px,至少有一个44px命中目标. 形状过渡超过220ms,尊重减动偏好. 单击标签可恢复按钮并打开反馈.

拖曳后,发射器使用与更接近的上下边缘的固定距离. 折叠并恢复 维护垂直锚。 移动浏览器工具栏和键盘高度变化不重新计算所保存的拖放比例;旋转设备或调整桌面窗口的大小可以恢复其相对位置. 反馈面板仍然分别适应可见的取景口.

板子关闭行为 none, (中文(简体) ), collapse (违约)或 hide。按钮的相近控制在桌面悬浮/焦点上可见,在触摸设备上总是可见。 当关闭被关闭,面板被打开,或者发射装置被倒塌或被拖走时,它就不存在了. 反馈面板内部没有发射装置控制.

按钮/ tab 状态并拖曳位置使用 sessionStorage,范围为主机和 FeedLog URL。 他们活下来了 重新装入同一个标签。 隐藏状态只持续当前页面并清除所保存的标签状态 。 初始化为 state: 'hidden' 明确将发射器再次隐藏在每一个负载上。 存储受限制的浏览器只保留内存中的偏好. 盘子 none 在下一个负载上重置旧访问者崩溃偏好,但明确提供的SDK状态仍然适用.

在桌面上,在至少480px适合时,面板更倾向于在发射器上方打开,再放在下方,再放在旁边。 它更喜欢内向的一面,在需要的时候尝试另一面,否则就适合在取景口内,而不会将对话挤入狭长的一带. 它保持了空间允许的16px发射机间隙和12px取景外接安全区域,最高可达680px高. 小屏幕使用全屏面板. 隐藏发射器为自定义主机条目打开的面板保留了锚.

主机登录生命周期

SDK电话 auth.login() 只有在明确签名和沉默之后 getToken() 检查。 返回的"承诺"隐藏了面板和发射器,直到互动结束,身份再次被检查. 拒绝也结束了等待,不自动重试登录. 没有强制暂停.

不保证的返回使部件保持可见,并立即再次检查身份。 不需要填写回调或单独的填写方法。 使用承诺自动避免模式, 或协调主机的z索引本身。 静态认证不隐藏部件 .

使用相容的iframe,身份更改保留了同一访客的视图,对话,草稿,上传的附件引用和滚动位置. 国家不能由不同的注册账户继承。 全页重定向使用5分钟回程标记和1个使用会话存储快照;存储限制会阻碍草稿在整个导航中恢复. 会话符号只在 Iframe URL 碎片中行走 .

认证

FeedLog 重新使用您产品的现有身份 产品SSO。您的后端已经知道是谁签名的; 部件只需要一个短暂的、签名的特征断言 .

auth.getToken 必须返回 JWT 由您的后端签名 带着你的一个半兽人的秘密(HS256),或者 null 当没有人签字。 在 FeedLog 下生成 SSO 机密 开发者 — SSO同样的秘密已经赋予了产品 SSO的交接权, 所以大多数集成器重用它们已经拥有的代码.

法定和任择索赔:

索赔需求页:1
email对身份钥匙.
exp对过期. 出站时间不得超过24小时;一个小时是好的默认时间.
name没有显示名称 .
picture没有阿凡达URL.

SDK 将此 JWT 交换为 FeedLog 会话符, 每封电子邮件缓存它 localStorage,然后通过 URL 片段将其交给 Iframe。 签名必须在您的服务器上进行—— 永远不要将 SSO 秘密传送给浏览器 .

浏览器支持

在所有当前常绿浏览器(Chrome,Firefox,Safari,Edge)中工作. 建筑目标为ES2020 并依赖于Shadow DOM, fetch,和 Web 存储——支持的浏览器不需要多填充.

类型

货船 .d.ts 声明. WidgetOptions, (中文(简体) ), WidgetDisplayOptions, (中文(简体) ), LauncherOptions, (中文(简体) ), LauncherPlacement, (中文(简体) ), LauncherState, (中文(简体) ), WidgetAuth,以及 WidgetTheme 从软件包根导出,并附带四个函数.

如何运作

SDK只做无法从跨源iframe内部完成的事情:使发射器和未读徽章,拥有面板和iframe寿命周期,呼叫您 getToken 编号 : login,并接收iframe的信息。 其他一切——反馈UI和所有商业API的调用——发生在FeedLog托管的iframe内部.

几个值得了解的变量,如果您正在读取源或调试:

  • 两端都验证出源和源. 版本一信息带有准备状态,主题更新,页面上下文和临时恢复状态. 发射装置状态仍在SDK中. 未知类型会被忽略用于转发相容性;一个旧的iframe不会收到不支持的恢复数据.
  • 会话符只在 URL 片段中行走 (单位:千美元)#token=…),从未在查询字符串中和从未结束 postMessage。碎片不发送到服务器上,所以该符号不包含访问日志和 Referer 头; Iframe 把它从装入的地址栏上擦去. 新会话到达iframe的唯一方式是用新的片段重建.
  • 信使缓存通过电子邮件键入 . A 类 null 从 getToken() 立即清除缓存,一个不同的电子邮件丢弃它——因此共享的计算机不会将一个人的会话泄露给下一个人. A 类 401 在放弃之前 触发一次无声的再交换.
  • auth-requested 总是重复 getToken() 安静的先 (用户可能在另一个标签上签名). 仅 reason: 'user' 可能会升级为 auth.login()· ; reason: 'expired' 从来没有打开一个弹出自己.
  • 嵌入的 URL 携带 ?origin=<your page's origin>。 。 。 . Iframe把它当作 postMessage 目标来源,它无法可靠地从中获取(Firefox没有 location.ancestorOrigins,而裁判员政策可以剥去裁判员. 伪造它无益:如果真正的母源不匹配,浏览器拒绝发送消息.

捐款

pnpm install
pnpm build        # tsup -> dist/index.js + dist/index.d.ts
pnpm typecheck
pnpm test
pnpm size         # report the bundle size

来源布局 :

src/
  index.ts          public controls, single-call initialization and pending instructions
  display.ts        display defaults, partial updates and option validation
  position.ts       visitor docking and viewport-constrained panel placement
  widget.ts         orchestration: boot, open/close, iframe lifecycle, postMessage dispatch
  auth.ts           the auth flow, with single-flight de-duplication
  session-cache.ts  session-token cache in localStorage, keyed by email
  unread.ts         badge count (unread endpoint + 60s sessionStorage cache)
  api.ts            fetch wrappers for the three widget endpoints
  jwt.ts            reads the email claim from a JWT (base64 decode only, no verification)
  login-marker.ts   sessionStorage marker for redirect-style login (~5 min expiry)
  storage.ts        localStorage / sessionStorage with an in-memory fallback
  ui.ts             launcher / badge / panel / loading, all inside a shadow root
  types.ts          public types + the postMessage protocol types

测试环境

playground/demo-host.html 是测试环境:一个单一的自成一体的文件——一个将部件嵌入的实事求是的(小说)SaaS登陆页,其中有一个模拟的登录和可拖动的控制面板,用于 baseUrl,嵌入路径,Org SSO秘密,和主题. SDK作为全球建筑的内入 build:demo。 。 。 .

Demo控制 → 发射器转换 提供 显示已崩溃的标签, (中文(简体) ), 显示启动器,以及 左停靠/ 右停靠 尝试过渡。 将标签从边上拖出以查看其浮动形状,然后放出以停靠. 概述的"帮助"分页为22×56px,不包括安全区垫地,其内侧有至少44px宽的命中目标.

pnpm demo          # build the inline SDK once, then serve at http://localhost:5173/demo-host.html
pnpm dev:demo      # same server, plus re-inline the SDK on every src/ change (refresh the browser)

二者在开始时打印 URL; PORT=xxxx 超过端口。 使用 demo 只要点击它, dev:demo 一边在SDK本身上行走.

指着面板 baseUrl 运行中的 FeedLog 实例( 默认) http://localhost:3000并粘贴Org的SSO秘密。 页面在每页的 JWT 客户端上签名 getToken() ——所以它代表着没有自己一个客户后端的客户,一个坚持不变的秘密永远不会消失. 面板配置( baseUrl, 嵌入路径, 秘密, 主题, 登录状态) 坚持跨重载, 由页面来源键入 .

永久航行 帮助 菜单调用 openWidget() 打开反馈或 updateWidget({ launcher: { state: 'button' } }) 以恢复浮动按钮。 发射机的关闭按钮遵循了仪表板的关闭行为.

客户端签名仅仅是一个演示快捷键 . 在制作中,SSO的秘密生活于  服务器和标志 JWTs 在那里——它绝不能到达浏览器. 面板的字段模型是开发者配置的值;它模拟的签名是您后端的工作.

交出来 网页没有 file://(单位:千美元) file:// 页面报告a null 源,它打破了部件的跨源后Message + CORS(登陆页、登录和面板仍在工作,但使用通知跳过活的部件).

活的部件需要一个可达到的 FeedLog 后端 —— 没有捆绑的模拟器, 所以在 at baseUrl。 。 。 .

许可证

麻省理工学院

代理页面上下文

对于每个消息,信任的iframe通过请求ID请求页面上下文. SDK以当前路径名,文档响应. 标题和元描述(截至2000/500/2000字符)。 查询参数、碎片和页面正文不包括在内。 双方检查消息的来源和来源. 这在没有额外选择的情况下可以跨越SPA导航. 更古老的 SDK 发行版仍然可以无页面上下文地聊天.

SDK对iframe的响应 ready 一个版本的事件 -- 1个 init 包含信件 payload.capabilities.pageContext: true。iframe仅在此声明之后请求页面上下文。 更古老的 SDKs 省略了它,所以 Iframe 跳过收藏而不等待;一个声明的能力仍然有500ms的响应超时.

移动面板行为

在宽至520px的屏幕上,打开全屏面板会隐藏发射装置. 关闭面板恢复其先前的按钮/tab/隐藏状态. 通过面板关闭 UI 返回焦点到可见的启动器或主机条目; 程序 closeWidget() 离开主机焦点。 装入和出错屏幕包括一个独立的关闭按钮. 更宽的屏幕保留着一个浮出水面的面板,其高度符合可用的取景口;一个短的取景口单独不会触发全屏模式.

版本与发布记录

@feedlog/widget 共发布 9 个版本,首次发布于 2026/07/28;过去 12 个月发布了 9 个版本。

版本发布日期距今
0.2.0latest2026/10/1629 天前
0.1.12026/09/301 个月前
0.1.02026/09/291 个月前
0.0.62026/09/221 个月前
0.0.52026/09/201 个月前
0.0.42026/08/242 个月前

关于 @feedlog/widget 的常见问题

@feedlog/widget 是什么?

零运行时间依赖的 FeedLog 可嵌入反馈部件 .

如何安装 @feedlog/widget?

在项目目录运行 npm install @feedlog/widget,或使用 pnpm add / yarn add / bun add。

@feedlog/widget 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@feedlog/widget 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@feedlog/widget 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@feedlog/widget 可以商用吗?

@feedlog/widget 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@feedlog/widget 的下载量有多少?

根据 npm 官方下载统计,@feedlog/widget 在 2026/10/15 – 2026/11/13 这 30 天内被下载 2,489 次,日均约 83 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@feedlog/widget 还在维护吗?

最新版本 0.2.0 发布于 2026/10/16(29 天前);至今共发布 9 个版本,其中过去 12 个月发布了 9 个;首次发布于 2026/07/28。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。