npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

floatball-widget

v0.1.0

Published

Floating chat widget as Web Component

Readme

Floatball 集成文档(React / Vue)

本文说明如何在 React 应用和 Vue 应用中集成 floatball 悬浮球聊天组件。

1. 组件能力说明

  • 悬浮球通过 React 渲染,支持拖拽、点击打开聊天窗。
  • 聊天窗支持流式消息、历史会话、附件选择。
  • 支持通过运行时注入方式配置接口信息(推荐,且可避免敏感信息进入 dist)。

2. 运行时配置(推荐,适用于对外分发 dist)

2.1 通过全局变量注入(推荐)

在加载/初始化浮球之前设置:

window.__FLOATBALL_WIDGET_CONFIG__ = {
  proxyApiUrl: 'https://your-host/v1/chat-messages',
  apiKey: 'app-xxxxxxxxxxxxxxxx',
}

apiKey 属于敏感信息:不要写死在源码里,也不要在构建时通过环境变量注入到 dist。

2.2 通过元素属性注入(简单)

<floatball-widget
  api-url="https://your-host/v1/chat-messages"
  api-key="app-xxxxxxxxxxxxxxxx"
></floatball-widget>

3. 对外发布接入(npm 包:floatball-widget

下面是外部企业在其项目中接入已编译产物dist)的最小步骤:不需要导入 src,只需引入 npm 包并使用 <floatball-widget /> 标签即可。

3.1 安装包

npm i floatball-widget

3.2 在应用入口加载一次(完成 custom element 注册)

在宿主项目的入口文件(例如 main.js/main.tsindex.tsx)增加:

import 'floatball-widget'

注意:仅在页面里写 <floatball-widget /> 可能不会自动注册元素;务必在入口 import 'floatball-widget'

3.3 注入运行时配置(建议在 import 之前)

方式 A:全局变量注入(推荐)

在入口文件尽早加入:

window.__FLOATBALL_WIDGET_CONFIG__ = {
  proxyApiUrl: 'https://your-host/v1/chat-messages',
  apiKey: 'app-xxxxxxxxxxxxxxxx',
}

import 'floatball-widget'

方式 B:元素属性注入(简单)

<floatball-widget
  api-url="https://your-host/v1/chat-messages"
  api-key="app-xxxxxxxxxxxxxxxx"
></floatball-widget>

apiKey 属于敏感信息:如可行,建议由你们后端侧做鉴权/代理,前端仅拿短期 token 或会话标识。

3.4 Vue / React 页面使用

Vue(任意版本,只要支持 Web Components 标签即可):

<floatball-widget />

React:

return <floatball-widget />

3.5 Vue2(Webpack)补充:忽略自定义元素警告

在入口(main.js)中加入:

import Vue from 'vue'
Vue.config.ignoredElements = ['floatball-widget']
import 'floatball-widget'

3.6 Vue3(Vite)补充:声明自定义元素

// build/plugin/index.js
vue({
  template: {
    compilerOptions: {
      isCustomElement: (tag) => tag.startsWith('floatball-'),
    },
  },
})

4. Vue 应用集成(推荐使用 Web Component,源码接入/调试示例)

4.1 在入口注册自定义元素

src/main.js 中引入一次:

import '../floatball/src/web-component'

4.2 在页面中直接使用标签

src/App.vue(或任意页面)中加入:

<floatball-widget />

4.3 Vite 配置(必须)

如果是 Vue + Vite,需要告诉编译器这是自定义元素,否则会被当成 Vue 组件解析:

// build/plugin/index.js
vue({
  template: {
    compilerOptions: {
      isCustomElement: (tag) => tag.startsWith('floatball-'),
    },
  },
})

5. Vue2(Webpack)最小接入示例(源码接入/调试示例)

如果你的宿主项目是 Vue2 + Webpack,推荐同样用 Web Component 方式接入。

5.1 入口引入(src/main.js

import Vue from 'vue'
import App from './App.vue'

// 告诉 Vue2:floatball-widget 是自定义元素,不当作 Vue 组件解析
Vue.config.ignoredElements = ['floatball-widget']

// 注册 floatball 自定义元素(路径按你的项目实际位置调整)
import '../floatball/src/web-component'

new Vue({
  render: (h) => h(App),
}).$mount('#app')

5.2 页面使用(src/App.vue

<template>
  <div id="app">
    <h1>Vue2 页面</h1>
    <floatball-widget />
  </div>
</template>

5.3 可选:老浏览器 polyfill

如果需要兼容不支持 Web Components 的老浏览器(例如 IE),请额外引入 polyfill。

npm i @webcomponents/webcomponentsjs

然后在入口尽早引入:

import '@webcomponents/webcomponentsjs/webcomponents-bundle'

6. React 应用集成(源码接入/调试示例)

React 中有两种方式:Web Component 方式和 JS API 方式。

6.1 方式 A:Web Component(简单,推荐)

在应用入口(如 src/main.tsxsrc/index.tsx)引入注册文件:

import '../floatball/src/web-component'

在页面中使用:

export default function Page() {
  return <floatball-widget />
}

如果是 TypeScript,建议补充自定义元素声明(避免 TS 报错):

declare global {
  namespace JSX {
    interface IntrinsicElements {
      'floatball-widget': React.DetailedHTMLProps<
        React.HTMLAttributes<HTMLElement>,
        HTMLElement
      >
    }
  }
}

6.2 方式 B:JS API(需要手动控制生命周期)

floatball/src/index.ts 暴露了四个方法:

  • init():创建并挂载浮球
  • open():打开聊天窗口
  • close():关闭聊天窗口
  • destroy():销毁浮球

React 示例:

import { useEffect } from 'react'
import { init, destroy } from '../floatball/src'

export default function App() {
  useEffect(() => {
    init()
    return () => destroy()
  }, [])

  return <div>your page</div>
}

7. 常见问题排查

7.1 页面没有看到悬浮球

优先检查:

  1. 是否已在入口执行 import 'floatball-widget'(或内部调试时的 web-component 注册文件)
  2. 页面中是否真的渲染了 <floatball-widget />
  3. Vue 项目是否配置了 isCustomElement
  4. React 版本是否使用 createRoot 挂载(当前代码已适配)
  5. 控制台是否有运行时错误(如环境变量、接口跨域等)

7.2 报错 process is not defined

浏览器端应使用 import.meta.env,不要使用 process.env

7.4 报错 “未配置 Floatball API_KEY”

这是预期行为:为避免敏感信息进入 dist,组件不会内置 apiKey。 请按本文第 2 节通过 window.__FLOATBALL_WIDGET_CONFIG__ 或元素属性注入。

7.3 样式被宿主应用影响

浮球主体运行在 Shadow DOM 内,一般不会被外部污染;聊天弹层通过 portal 挂到 document.body,若视觉异常,重点检查宿主全局样式(z-indextransformoverflow)。


8. 推荐接入方式

  • Vue 项目:优先用 Web Component
  • React 项目:也优先 Web Component,只有在需要更强控制时再改用 JS API

这样可保持接入路径一致、维护成本最低。