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

@caikengren/tang-svg-editor

v0.1.0

Published

A host-agnostic multi-page SVG editor for React

Readme

@caikengren/tang-svg-editor

面向浏览器的多页 SVG 编辑器(React 组件)。它只负责 SVG 文档的编辑、标注、导入、撤销重做和显式保存;文件系统、持久化、路由和发布流程由宿主应用负责。

特性

  • 多页 SVG 编辑:页面新增、复制、删除、重排;viewBox 作为画布尺寸事实源。
  • 完整编辑能力:撤销/重做、复制/剪切/粘贴/重复、全选、组合/取消组合、对齐、图层与页面操作。
  • 元素标注:绑定到一个或多个有 ID 的 SVG 元素,随文档导出为 data-edit-target / data-edit-annotation
  • 原子多 SVG 导入:按自然文件名排序,任一文件无效时整批不提交。
  • 安全清洗:导入、素材与 AI 结果统一经过 sanitizeSvg / normalizeSvgForEditing,移除脚本、事件属性与危险 URL。
  • SVG/PNG 导出exportPageSvgexportPagePngrenderSvgToPngBlob
  • 宿主无关:通过 AssetAdapter / AIAdapter / ExportAdapter 和 feature flags 对接宿主能力,不绑定具体平台。
  • 零构建接入./browser 入口支持 import map + 公共 CDN 直接使用。

安装

npm install @caikengren/tang-svg-editor
# 或
pnpm add @caikengren/tang-svg-editor
# 或
yarn add @caikengren/tang-svg-editor

React 接入

import { useState } from 'react'
import {
  TangSvgEditor,
  createBlankDocument,
  type TangSvgDocument,
} from '@caikengren/tang-svg-editor'
import '@caikengren/tang-svg-editor/style.css'

export function EditorPage() {
  const [document, setDocument] = useState<TangSvgDocument>(() => createBlankDocument())

  return (
    <div style={{ height: '100vh' }}>
      <TangSvgEditor
        value={document}
        onChange={(next, change) => {
          setDocument(next)
          console.log(change.source, change.operations)
        }}
        onSave={async (snapshot, intent) => {
          await saveCompleteDocument(snapshot)
          return {
            status: 'saved',
            savedRevision: intent.revision,
            savedAt: Date.now(),
            message: '保存成功',
          }
        }}
      />
    </div>
  )
}

容器必须有明确高度。onChange 在一次用户操作提交后触发一次,参数同时包含完整文档与精确的 operations;拖拽在释放时提交,不逐帧通知宿主。

onSave 只由保存按钮、Ctrl/Cmd+S 或命令式 save() 触发。它收到全部页面的完整 SVG;编辑器会移除内部 data-svg-editor-* 属性,并保留 data-edit-targetdata-edit-annotation。保存期间又发生修改时,较旧的保存响应不会清除新 dirty 状态。

常用 props

| 属性 | 作用 | | --- | --- | | value / defaultValue | 受控 / 非受控文档,二选一 | | onChange(value, change) | 每个可撤销 transaction 提交后回调完整快照 | | onSave(value, intent) | 保存按钮或快捷键触发的显式保存意图 | | onBack() / onError(error) | 可选宿主返回行为与标准化错误 | | features | 隐藏 assets / ai / import / export 内建能力 | | headerActions | 自定义 header 按钮 | | readOnly | 禁用写操作,保留预览、缩放和导出 | | uiTheme | lightdarksystem | | assets / ai / exporter | 可选宿主能力适配器 |

受控宿主原样回传最近一次 onChange 的对象时,编辑器保留本地历史;传入其他对象被视为外部替换,会清理选择并重置历史。

Header 按钮配置

tse-header 默认按 撤销 → 重做 → 保存 → 导入 SVG 渲染,对应 DEFAULT_EDITOR_HEADER_ACTIONS['undo', 'redo', 'save', 'import'])。传入 headerActions 会完整替换默认配置;内置动作可按 ID 复用,也可插入宿主按钮:

import {
  DEFAULT_EDITOR_HEADER_ACTIONS,
  TangSvgEditor,
} from '@caikengren/tang-svg-editor'

const actions = [
  ...DEFAULT_EDITOR_HEADER_ACTIONS.filter((action) => action !== 'import'),
  {
    id: 'exit-preview',
    label: '退出预览',
    onClick: stopPreview,
  },
] as const

<TangSvgEditor headerActions={actions} />

自定义按钮支持 ariaLabeltitledisabledclassName,以及 defaultprimaryicon 三种 appearance。自定义 onClick 可以返回 Promise;失败会通过 onErrorheader-action-failed 上报。保存和导入动作仍会根据 onSave、feature flags 与只读状态自动判断是否可用。

标注与导入

  • 标注绑定到一个或多个有 ID 的 SVG 元素,说明上限为 10,000 字符。
  • 标注保存为 data-edit-target="true"data-edit-annotation="..."
  • “导入 SVG”支持多选,按包含数字的自然文件名顺序处理。
  • 同名文件替换现有页面;任一文件无效时整批不提交。
  • 可通过 feature flags 禁用页面新增、复制、删除和手动重排。

Browser ESM / CDN 接入

dist/tang-svg-editor.browser.js 是浏览器原生 ESM 入口:它包含编辑器运行时依赖与 CSS,但把 React、ReactDOM 保留为外部依赖。通过 import map 保证宿主和编辑器共享同一份 React:

<div id="editor-root" style="height:100vh"></div>
<script type="importmap">
{
  "imports": {
    "react": "https://esm.sh/[email protected]",
    "react/jsx-runtime": "https://esm.sh/[email protected]/jsx-runtime",
    "react-dom": "https://esm.sh/[email protected]?external=react",
    "react-dom/client": "https://esm.sh/[email protected]/client?external=react",
    "@caikengren/tang-svg-editor/browser": "https://cdn.jsdelivr.net/npm/@caikengren/[email protected]/dist/tang-svg-editor.browser.js"
  }
}
</script>
<script type="module">
  const { mount } = await import('@caikengren/tang-svg-editor/browser')
  const editor = mount(document.getElementById('editor-root'), { value: documentData })
</script>

npm 发布后 jsDelivr/unpkg 会自动镜像文件。生产页面应固定完整版本号,不要引用 @latest

Standalone API

./browser 入口同时导出 mount()versionDEFAULT_EDITOR_HEADER_ACTIONScreateBlankDocumentnormalizeSvgForEditingsanitizeSvg

import { mount, version, createBlankDocument } from '@caikengren/tang-svg-editor/browser'

mount() 返回的 controller 提供 getDocumentsetDocumentsavefocusundoredoselectPagedestroy。同一页面可以挂载多个实例;样式只注入一次。页面卸载时应调用 destroy()

快捷键

  • Ctrl/Cmd+S:保存
  • Ctrl/Cmd+Z:撤销
  • Ctrl/Cmd+Shift+ZCtrl/Cmd+Y:重做
  • Ctrl/Cmd+C/X/V/D:复制、剪切、粘贴、重复元素
  • Ctrl/Cmd+A/G/Shift+G:全选、组合、取消组合
  • Delete/Backspace:删除选择
  • PageUp/PageDown:切换页面

兼容性

  • React >=18.2 <20(peer dependency,React 18.2 与 19.x 均已验证)。
  • 常规 npm 入口把 React 与 ReactDOM 作为 peer dependencies;Browser ESM 由 import map 提供 React。
  • 组件依赖 DOMParser、XMLSerializer、Canvas、Blob 与浏览器事件,不支持服务端渲染;Next.js 应放在 Client Component 中,或使用关闭 SSR 的动态导入。
  • 宿主必须导入 style.css,所有选择器与变量使用 .tang-svg-editor.tang-svg-editor-portal--tse-* 命名空间,不输出全局 reset。

开发与发布

# 构建(产出 ESM/CJS + 类型声明 + 浏览器 ESM)
pnpm --filter @caikengren/tang-svg-editor build

# 发布前门禁:tarball 内容、publint、Are The Types Wrong、consumer smoke
pnpm pack:check
pnpm consumer:check

发布(Changesets)

pnpm changeset           # 1. 记录本次变更类型(patch / minor / major)
pnpm changeset version   # 2. 依据 changeset 提升版本号并生成 CHANGELOG(不自动提交)
pnpm release             # 3. package:check + consumer:check + changeset publish

prepublishOnly 会在 changeset publish 前自动执行 pnpm build,确保发布物是最新构建;发布前记得把第 2 步的版本号变更提交到 git。

License

MIT