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

ai-sheet-sdk

v0.1.11

Published

基于 [Univer](https://github.com/dream-num/univer) 的在线表格 SDK,提供可编辑和只读预览两种模式。通过 IR(Intermediate Representation)中间格式与后端交互,支持懒加载、自动保存、增量保存和 RTL 文本。

Readme

AI Sheet SDK

基于 Univer 的在线表格 SDK,提供可编辑和只读预览两种模式。通过 IR(Intermediate Representation)中间格式与后端交互,支持懒加载、自动保存、增量保存和 RTL 文本。

目录结构

src/
├── sdk/                        # SDK 入口 & 对外组件
│   ├── index.ts                # 导出入口
│   ├── AISheet.tsx             # 可编辑表格组件
│   ├── AISheetPreview.tsx      # 只读预览组件
│   ├── createDefaultProvider.ts # 默认 HTTP DataProvider
│   └── types.ts                # 对外类型定义
├── ir/                         # IR 中间表示层
│   ├── types.ts                # IR 类型定义(与后端 DTO 对齐)
│   ├── univerTransform.ts      # IR ↔ Univer 双向转换
│   ├── univerTransform.test.ts
│   ├── diffCompute.ts          # 增量保存 diff 计算
│   └── diffCompute.test.ts
├── components/                 # Univer 底层封装
│   ├── UniverSheet.tsx         # 可编辑 Univer 实例
│   └── UniverPreviewSheet.tsx  # 只读 Univer 实例
├── api/
│   └── irApi.ts                # 内部 API 层(demo 页面使用)
├── pages/                      # Demo 页面
│   ├── HomePage.tsx
│   ├── SheetPage.tsx
│   ├── SheetPreviewPage.tsx
│   └── MockSheetPage.tsx
└── mock/
    └── rtl-mock-data.ts        # RTL 演示数据

快速开始

安装依赖

pnpm install

本地开发

pnpm dev

开发服务器在 http://localhost:7091 启动,/api 代理到 http://localhost:8080(需后端服务运行)。

Demo 页面路由:

| 路径 | 说明 | |------|------| | / | 首页,输入 fileId 跳转 | | /sheet/:fileId | 可编辑表格 | | /sheet/:fileId/preview | 只读预览 | | /mock | RTL 演示(纯前端 mock 数据) |

构建 SDK

pnpm build:sdk

产物输出到 dist/,包含 ai-sheet-sdk.jsai-sheet-sdk.css

运行测试

pnpm test          # 单次运行
pnpm test:watch    # 监听模式

作为 SDK 使用

安装

pnpm add ai-sheet-sdk

Peer 依赖:react ^18 || ^19react-dom ^18 || ^19

基本用法

import { AISheet, createDefaultProvider } from 'ai-sheet-sdk';
import 'ai-sheet-sdk/style.css';

const provider = createDefaultProvider('/api/sheet/ir', 'your-token');

function MySheet() {
  return (
    <AISheet
      fileId="01KJ9Y71S0MD68JCF8FYWXNRM5"
      dataProvider={provider}
      onReady={(api) => console.log('ready', api)}
      onSave={(status) => console.log('save:', status)}
    />
  );
}

只读预览

import { AISheetPreview, createDefaultProvider } from 'ai-sheet-sdk';
import 'ai-sheet-sdk/style.css';

const provider = createDefaultProvider('/api/sheet/ir');

function MyPreview() {
  return (
    <AISheetPreview
      fileId="01KJ9Y71S0MD68JCF8FYWXNRM5"
      dataProvider={provider}
    />
  );
}

在 Vue 项目中嵌入

通过 createRoot 桥接 React 组件:

<script setup lang="ts">
import { AISheet, createDefaultProvider } from 'ai-sheet-sdk';
import 'ai-sheet-sdk/style.css';
import React from 'react';
import { createRoot } from 'react-dom/client';
import { onMounted, onUnmounted, ref } from 'vue';

const container = ref<HTMLDivElement>();
let root: ReturnType<typeof createRoot>;

onMounted(() => {
  root = createRoot(container.value!);
  const provider = createDefaultProvider('/api/sheet/ir', 'token');
  root.render(
    React.createElement(AISheet, {
      fileId: 'your-file-id',
      dataProvider: provider,
    })
  );
});

onUnmounted(() => root?.unmount());
</script>

<template>
  <div ref="container" style="width: 100%; height: 100%" />
</template>

核心概念

DataProvider

数据源通过 DataProvider 接口抽象,宿主应用可以使用内置的 createDefaultProvider(基于 axios 的 REST 实现),也可以自行实现:

interface DataProvider {
  // 必选
  getMeta(fileId: string): Promise<WorkbookMeta>;
  getStyles(fileId: string): Promise<StylePalette>;
  getCells(fileId, sheet, r0, r1, c0, c1): Promise<CellRangeResponse>;

  // 可选 — 提供后启用保存功能
  saveIR?(fileId, request: SaveIRRequest): Promise<SaveResponse>;
  diffSaveIR?(fileId, request: DiffSaveRequest): Promise<SaveResponse>;
  evaluateFormulas?(fileId: string): Promise<void>;
}

createDefaultProvider(apiBaseUrl, token?) 对应的后端接口:

| 方法 | 路径 | 说明 | |------|------|------| | GET | /{fileId}/meta | 获取工作簿元数据 | | GET | /{fileId}/styles | 获取样式表 | | GET | /{fileId}/cells?sheet&r0&r1&c0&c1 | 获取单元格范围 | | POST | /{fileId}/save | 全量保存 | | PATCH | /{fileId}/diff-save | 增量保存 | | POST | /{fileId}/evaluate | 触发服务端公式计算 |

后端响应格式为 { code: number, data: T, message?: string },SDK 自动解包。

IR 数据格式

IR(Intermediate Representation)是前后端之间的数据协议:

WorkbookMeta — 工作簿元数据

{
  fileId: string;
  fileName: string;
  fileSize: number;
  sheets: SheetMeta[];
  version?: number;       // 用于增量保存的乐观锁
}

SheetMeta — 工作表元数据

{
  index: number;
  name: string;
  rowCount: number;
  colCount: number;
  colWidths: Record<number, number>;   // 列宽(Excel 字符宽度,非像素)
  rowHeights: Record<number, number>;  // 行高(磅值,非像素)
  mergedCells: MergedRegion[];
}

IRCellData — 单元格

{
  row: number;
  col: number;
  value: string | number | boolean;
  type: 'STRING' | 'NUMERIC' | 'BOOLEAN' | 'FORMULA' | 'BLANK';
  formulaValue?: string;   // type 为 FORMULA 时的公式表达式
  styleIndex: number;       // 引用 StylePalette.styles 的索引,-1 表示无样式
}

StylePalette — 样式表

{
  styles: CellStyleDef[];   // 索引式样式数组
}

IR ↔ Univer 转换规则

| IR 属性 | 方向 | Univer 属性 | 转换公式 | |---------|------|------------|---------| | colWidths (字符宽度) | → | columnData[col].w (像素) | × 8 | | rowHeights (磅) | → | rowData[row].h (像素) | × 1.33 | | CellStyleDef.bold | ↔ | IStyleData.bl | BooleanNumber.TRUE / FALSE | | CellStyleDef.fontSize | ↔ | IStyleData.fs | 直接映射 | | CellStyleDef.fontColor | ↔ | IStyleData.cl.rgb | 直接映射 | | CellStyleDef.bgColor | ↔ | IStyleData.bg.rgb | 直接映射 | | CellStyleDef.numberFormat | ↔ | IStyleData.n.pattern | 直接映射 |

组件 Props 参考

AISheet

| Prop | 类型 | 默认值 | 说明 | |------|------|--------|------| | fileId | string | — | 文件 ID(必填) | | dataProvider | DataProvider | — | 数据源(必填) | | readonly | boolean | false | 只读模式 | | autoSaveDelay | number | 3000 | 自动保存防抖延迟(ms) | | onReady | (api: FUniver) => void | — | Univer 初始化完成回调 | | onSave | (status) => void | — | 保存状态回调:'saving' / 'saved' / 'error' | | onError | (error: Error) => void | — | 加载错误回调 | | ref | Ref<AISheetRef> | — | 通过 ref.getUniverAPI() 获取底层 API |

AISheetPreview

| Prop | 类型 | 默认值 | 说明 | |------|------|--------|------| | fileId | string | — | 文件 ID(必填) | | dataProvider | DataProvider | — | 数据源(必填) | | onReady | (api: FUniver) => void | — | 初始化完成回调 | | onError | (error: Error) => void | — | 加载错误回调 | | ref | Ref<AISheetRef> | — | 通过 ref.getUniverAPI() 获取底层 API |

技术栈

  • 表格引擎Univer ^0.15.5
  • 框架:React 18/19
  • HTTP:axios
  • 构建:Vite(库模式)
  • 测试:Vitest + Testing Library
  • 类型:TypeScript 5.9