# @ai-matrx/canvas 中文文档

规范地址：https://npmcn.com/package/%40ai-matrx/canvas/

版本：0\.10\.91
npm 元数据更新时间：2026-10-27T22:10:39.789Z
中文译文更新时间：2026-11-05T18:32:58.142Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40ai-matrx/canvas
原文对照：https://npmcn.com/package/%40ai-matrx/canvas/?lang=original
项目主页：https://github.com/AI-Matrix-Engine/aidream#readme
源码仓库：https://github.com/AI-Matrix-Engine/aidream

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：2.1 MB，22 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- Node.js 要求：\>=20
- 运行依赖：3 个
- peer 依赖：react \>=18\.0\.0，react-dom \>=18\.0\.0
- 首次发布：2026-10-02T13:59:04.632Z
- 最新版本发布：2026-10-27T22:10:39.521Z
- 近 30 天下载量：65606（2026-10-05 至 2026-11-03，npm 官方下载统计）
- 已发布版本数：120（近 12 个月 120 个）

## 中文简介

AI Matrx画布:一个对接的右侧列,有分页板,分页板,全屏,等式注册,Redux相容状态和持久性.

## 安装

```sh
npm install @ai-matrx/canvas
```

也可以使用：`pnpm add @ai-matrx/canvas`、`yarn add @ai-matrx/canvas`、`bun add @ai-matrx/canvas`

## README

# @ai- matrx/ 扫描

一个对接的右侧帆布列有分页,分页,分页,扩展,以身份为基础的分页,坚持布局和ONE平板铬. 核心状态是框架独立的(它运行在电子主过程); 反应组件飞船通过 `./react`。 。 。 .

```tsx
import "@ai-matrx/canvas/styles.css";
import "@ai-matrx/canvas/tokens.css"; // follows a design-system theme; else built-in light/dark values
import { CanvasProvider, CanvasFrame, CanvasToggle, registerCanvasKind, defineCanvasKind } from "@ai-matrx/canvas/react";

registerCanvasKind(defineCanvasKind({ id: "note", label: "Note", icon: NoteIcon, load: () => import("./NoteView") }));

<CanvasProvider>
  <CanvasFrame><App header={<CanvasToggle />} /></CanvasFrame>
</CanvasProvider>
```

`NoteIcon`, (中文(简体) ), `NoteView` 财务报告和审定财务报表 `App` 是您的主机组件 。 Redux 主机通行证 `store={bindCanvasToReduxStore(store, (s) => s.canvasHost)}` 挂起后 `canvasReducer`。主机拥有身份、导航、放置和符号值;软件包拥有布局、光栅/塔布行为、铬和还原。 项目数据必须是简单的JSON;失败通过报告 `onError`。 。 。 .

条目:核心(`.`),反应(`./react`)),结构CSS(`./styles.css`)和默认主题值(`./tokens.css`) (中文(简体) ).

## 一个

```tsx
defineCanvasKind<{ sessionKey: string }>({
  id: "terminal",
  label: "Terminal",
  icon: TerminalIcon,
  load: () => import("./TerminalView"),
  restore: "session",          // closing detaches; a restore or a move reattaches
  onAttach: ({ sessionKey, reason }) => attach(sessionKey, reason),
  onDetach: ({ sessionKey }) => detach(sessionKey), // never kill here
  HeaderLeading: NewTerminalButton, // "+ new terminal", a browser bar…
  HeaderAction: ClearButton,
  unavailable: () => (backendUp() ? null : "Terminal · next release"),
});
```

`body: "native"` 使身体成为主机接收到的框架(下方)的占位符.

## 尸体从不下山

每个开口物品的躯体一次被制成, 在柱子的体层中, 用测量的矩形把它放在它的面板上. 切换分页会隐藏它;拆分,将分页之间移动分页,拖放宽度,扩展并放出画布只可重置或隐藏. 反应状态,焦点和卷轴在除关闭分页之外的一切幸存. 身体在第一次显示时就挂起. `isVisible` 告诉它是否在屏幕上(在假投票时暂停投票); `unmountWhenHidden: true` 选择一个真正的重体出.

## 了解其形状的内容

```tsx
function GraphView({ presentation }: CanvasKindProps) {   // or useCanvasPresentation() anywhere inside the body
  return <Graph direction={preferredFlowDirection(presentation) === "vertical" ? "TB" : "LR"} />;
}
```

`presentation = { host: "canvas", width, height, orientation: "portrait" | "landscape" | "square", isNarrow, isFullscreen, paneCount }`现场直播. `useCanvasPresentation()` 返回到任何嵌入组件中 `null` 在画布外 当您拥有大量垂直空间和小水平空间时, 调整: 设置图表, 时间表和卡片行从上到下, 堆放并列, 缩短工具栏 .

## 标签, 新建标签并返回

每个平面头有"+"(一个发射器标签). 在发射装置中选择标签的NAVIGATES,所以信头提供回. 做同样从一种:

```ts
canvas.navigate(item.id, { kind: "doc", key: docId, data: { docId } }); // records history; Back returns
canvas.back(item.id);
canvas.forward(item.id); // after Back: the same live body Back left
```

导航到其它地方已经打开的东西将它聚焦在那里(一个启动器标签关闭;任何其他标签保存它显示的内容). 历史是简单的JSON并持续存在。 作为标题显示的单独标签保持了自己的接近.

**后从不舍一身而去.** 最新的 `CANVAS_KEEP_ALIVE_DEPTH` (5) 退后可以达到,5个最新内容退后`item.kept`把尸体挂起来藏起来 后回 SAME活体;选择内容后左(从发射台再快速聊天)会使其活体复活——打出草稿仍然在那里. 旧的台阶仍然有效,但新上架。 关闭标签处理所有保存的尸体.

**前进.** 后页头也显示前进( A)`selectCanvasCanGoForward`)它返回同样的活体后向左. 航向新的地方 结束了前进的道路。 快捷键数据 `canvas.back` 编号 : `canvas.forward` (qq\[/⌘\])是用于桌面主机;浏览器拥有这些密钥.

**条子** (克罗梅的模型). 标签平均分享条状物——每块有12个雷姆与房间——并缩到一可读地上,图标+~10个字母+"......"(.)`CANVAS_TAB_MIN_WIDTH`, 120px);切口名称总是以椭圆结尾,每个标签的工具提示是其全名. 在地板上, 条条只绘制符合 WALE 的标签, 运行到当前标签的周围, 尽可能少移动( WHLE) `fitCanvasTabWindow`),而"All tabs (N)"列出每个标签,并显示有多少个出条-一个标签从不从边缘切入(JetBrains的单行标签;一个滚动条,如VS代码或Firefox中,在两个边缘都留下了半个标签). 箭头键走每个分页。 标签从不收缩到图标 sliver , 标题中没有任何内容与另一个控件相重叠 .

**分出诸相.** 分页画布将 One 窗口宽的标签条保留在窗帘上方(`CanvasWindowTabs`),从不为每个平面画出一幅:每个平面的分页都在其中,平面的可见分页被画出为"ONE会合分页"(焦点分页有一半最强; `planCanvasTabStrip`),而其"+"在焦相窗格中打开. 每个面板头保留着自己的后向/前向,标题,类型控制和菜单. 侧向分拆,其平面比 `paneMinWidth` (网络: `CANVAS_PANE_MIN_WIDTH`, 280px)使堆放在同一条条下;树不变. 每个窗帘都保留着 `paneMinHeight` (单位:千美元)`CANVAS_PANE_MIN_HEIGHT`, 200px): 拆分时不会缩短子女(`fitCanvasSplitSizes`),且新的分块不能让两个相片最小值进入到另一个相片轴上,或者新的分页加入焦点相片 (`fitCanvasSplit`; 窗格菜单只提供适合的分块).

**电话** (单位:千美元)`CANVAS_PHONE_MAX_WIDTH`, 767px): 栏中呈现出 ONE 面板——当它持有标签时的焦点, 否则是第一个( )`selectCanvasPresentedPaneId`) ——其条带了每一个被子的分页;从另一个被子的分页中选择一个被子呈现出被子的分页. 窗格菜单不提供分块。 布局树没有被破坏,所以一个更宽的屏幕会得到它的分出回.

## 一个面板菜单

窗帘有一个菜单: `menuItems`,然后身体提供现在, 然后东道主的 `itemActions`,然后拆分/弹出/关闭。 一个机构会增加自己的动作——从头里没有第二个外溢按钮:

```tsx
useCanvasMenuItems(item.id, [{ id: "next", label: "Next record", onSelect: goNext }]);
```

一种类型的 `HeaderAction` 坐在坚固的窗格页眉上:绘制自带目标按钮 `TapTargetButtonTransparent` (只有玻璃会浮出水面).

## 一页自己的发射器条目

```tsx
useCanvasLauncherEntry({ kind: "documents", key: conversationId, data: { conversationId }, title: "This chat's documents" });
```

在调用组件挂载时先显示("在本页").

## 打开新项目的地方

```tsx
defineCanvasKind({ id: "notifications", preferredTarget: "split-down", /* … */ });
```

虽然画布已经显示一些东西, 这样的新项目会在下面打开( 版式规则的分出份额, 70/ 30) 或旁边; 一个已经显示它取入的面板 。 明确 `target` 赢了. `open` 财务报告和审定财务报表 `toggleKind` 敬礼.

## 窗帘头内的控制器, "这里没有帆布"

一种类型的 `HeaderAction` 可能会是 `KindHeaderSlot`;然后其正文将控件画入标题中 `<KindHeaderPortal itemId={item.id}>` (文字保留; `useKindPaneHeaderWidth` 报告页眉宽度. 将一个浸入的取景器包入 `<CanvasUnavailableBoundary>`内: `useCanvasIsPresented()` 是虚假的.

## 标题工具图标

```tsx
<CanvasKindIcons kinds={["terminal", "review", { kind: "browser", label: "Browser" }]} variant="glass" />
```

每个图标切换或聚焦其类型,并在项目在前面时被按下.

## 动议

列动画显示其宽度 `--mxc-motion-duration` 编号 : `--mxc-motion-ease` (tokens.css: 600ms,(英语:, `cubic-bezier(0.4, 0, 0.2, 1)`),其内容保持了宽度,使其滑出. 一个在它旁边的回流主机在同一对上以锁步移动:

```css
.app-shell { right: var(--canvas-w); transition: right var(--mxc-motion-duration) var(--mxc-motion-ease); }
:root[data-mxc-resizing] .app-shell { transition: none; }               /* the edge is being dragged */
@media (prefers-reduced-motion: reduce) { .app-shell { transition: none; } }
```

`<CanvasFrame>` 不需要 : 它的主要区域是柔韧的兄弟姐妹, 并遵循每个边框的列.

## 标题下的一个工具栏行

一种类型的 `Toolbar` 在窗格头和正文之间为活动者制作 项(浏览器栏)。 它是DOM, 并且一个原生的身体的框被测量到下面.

## 工具栏图标:切换或聚焦一类

```tsx
const terminal = useCanvasKindToggle({ kind: "terminal" });
<button aria-pressed={terminal.isVisible} onClick={terminal.toggle}>…</button>
// outside React (Electron main, a menu handler):
toggleKind(controller, { kind: "terminal" }); // absent → open · behind → focus · in front → close
```

`whenVisible: "hide"` 将画布收起,而不是关闭标签.

## 面板的色调本身为主机框架

`CanvasPanel` (标题或 `header`, (中文(简体) ), `leading`, (中文(简体) ), `actions`, (中文(简体) ), `renderMenu`, (中文(简体) ), `onToggleExpand`, (中文(简体) ), `onClose`, (中文(简体) ), `CanvasPanelEmpty`, (中文(简体) ), `CanvasHeaderButton`, (中文(简体) ), `CanvasTab`, (中文(简体) ), `BrowserTabs`, (中文(简体) ), `BrowserBar` – – – – – – – – – – – – – – – – – – – – – – – , – – – – – – – – – , – – , – , – , – , – , – – , – , – , – , – – , – , – , – , – , – , – , – – , – , – , – , , – , – , – , , – , , – , – , – , – , – , , – – , – , – , – , , , , – , – – – , , , – , , – , , , – 它们也会在供货商之外产生.

## 马可斯的表情

`<CanvasProvider look="mac">` 将每个窗格画为Mac 窗口的一段而不是卡片: 柱子冲到一个发线后面的窗边,被发线分割的窗子,每个窗子 标出统一工具栏的带头( u)`--mxc-toolbar-h`,默认52px) — 活动标签的标题居中 以粗体表示,其类型的图标为代理图标(Terminal, Finder),或者该类型的图标 `Toolbar` 改为: (Safari的地址栏). “ +” 与跟踪控件同坐; 两个或多个标签得到 macOS 标签栏 在乐队下。 将信头置于自己的窗口按钮设置下的主机 `--mxc-header-inset-start` 在专栏。 默认 `look="card"` 保留 Claude 桌面/ 代码卡.

## 布局规则

```tsx
<CanvasProvider layoutRules={CANVAS_DESKTOP_LAYOUT_RULES} regionWidth={windowWidth - railAndSidebar}>
```

| 规则 | Web( 默认) | 桌面 |
| --- | --- | --- |
| `defaultWidth` | 640号 | `{ fraction: 0.36 }` |
| `minWidth` | 360 (中文(简体) ) | 360 (中文(简体) ) |
| `centreMinWidth` (画布先收缩) | 600个 | 第520条 |
| `stackSplit` (分出: 第一张平板电脑份额) | 0.7 (简体中文) | 0.7 (简体中文) |
| `sideSplit` | 0.5 (韩语) | 0.5 (韩语) |
| `paneMinWidth` (更窄相接的平板叠) | 280号 | 360 (中文(简体) ) |
| `paneMinHeight` (没有更短的窗帘;无法匹配的分页或打开标签) | 200个 | 200个 |

扩展为每个窗口一面旗;它会填充主机所设置的列(`useCanvasColumnWidth()` 返回时 `null`) (中文(简体) ).

## 电子

主进程为一商店;每个窗口的渲染器都是客户端.

```ts
// main
import { createCanvasStore, createCanvasController, createKeyValueCanvasPersistence, isCanvasAction,
  CANVAS_DESKTOP_LAYOUT_RULES, CANVAS_SHORTCUTS, runCanvasCommand } from "@ai-matrx/canvas";

const store = createCanvasStore();
const canvas = createCanvasController({
  store,
  persistence: createKeyValueCanvasPersistence({ get: (k) => kv.get(k), set: (k, v) => kv.set(k, v) }),
  layoutRules: CANVAS_DESKTOP_LAYOUT_RULES,
  isRestorable: (kind) => kind !== "browser", // main has no kind registry: name the kinds that never come back
});
canvas.start(); // hydrates, then autosaves

ipcMain.handle("canvas:get", () => store.getState());
ipcMain.handle("canvas:dispatch", (_e, action: unknown) => { if (isCanvasAction(action)) store.dispatch(action); });
store.subscribe(() => { for (const w of BrowserWindow.getAllWindows()) w.webContents.send("canvas:snapshot", store.getState()); });

// Shortcuts as data: bind them where keys inside native views still arrive.
for (const s of CANVAS_SHORTCUTS) { /* menu accelerator or before-input-event → */ runCanvasCommand(canvas.forWindow(windowIdOf(win)), s.id); }
// A BrowserWindow that closes: its tabs go home.
win.on("closed", () => canvas.closeWindow(windowIdOf(win)));
```

```tsx
// renderer (one per window)
import { createRemoteCanvasStore } from "@ai-matrx/canvas";

const store = createRemoteCanvasStore({
  initialSnapshot: await ipcRenderer.invoke("canvas:get"),
  dispatch: (action) => ipcRenderer.invoke("canvas:dispatch", action),
  subscribe: (onSnapshot) => {
    const on = (_e: unknown, s: CanvasState) => onSnapshot(s);
    ipcRenderer.on("canvas:snapshot", on);
    return () => ipcRenderer.off("canvas:snapshot", on);
  },
});

<CanvasProvider
  store={store}                    // remote: the main process hydrates and saves
  windowId={myWindowId}            // "main" for the first window
  layoutRules={CANVAS_DESKTOP_LAYOUT_RULES}
  regionWidth={rightOfSidebar}
  hotkeys={false}                  // main binds CANVAS_SHORTCUTS
  onNativeBodyFrame={(itemId, rect, { visible }) => ipc.send("view:place", itemId, visible ? rect : null)}
  showMenu={(entries, anchor) => ipc.invoke("menu:popup", entries, anchor)}   // Menu.popup → chosen id
  overlay={{ show: (el) => { ipc.send("overlay:show", el); return () => ipc.send("overlay:hide", el); } }}
  popOut={(item) => ipc.invoke("canvas:pop-out", item.id)}                    // → { windowId } of a new BrowserWindow
>
  <CanvasColumn />  {/* a pop-out window renders <CanvasColumn placement="fill" /> */}
</CanvasProvider>
```

矩形是窗口 CSS 像素,带有 `devicePixelRatio`,框中报告布局已改变(放电效果+调整观察员大小)。 打电话 `useCanvasNativeBodies().remeasure()` 每个动画框,而主机动画则自行布局. `visible: false` 指包 DOM 在视图上浮起(一个 DOM 菜单或标签拖放):隐藏它,从而看到并接收了 DOM .

## 网络弹出

```tsx
popOut={async (item) => { const id = `pop-${item.id}`; openFloatingPanel(id); return { windowId: id }; }}
// the floating panel:
<CanvasWindowScope windowId={id}><CanvasColumn placement="fill" /></CanvasWindowScope>
```

当弹出窗口消失时 `state.windows` 关闭面板.

麻省理工学院.

## 常见问题

### @ai-matrx/canvas 是什么？

AI Matrx画布:一个对接的右侧列,有分页板,分页板,全屏,等式注册,Redux相容状态和持久性\.

### 如何安装 @ai-matrx/canvas？

在项目目录运行 npm install @ai-matrx/canvas，或使用 pnpm add / yarn add / bun add。

### @ai-matrx/canvas 支持 TypeScript 吗？

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

### @ai-matrx/canvas 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @ai-matrx/canvas 需要什么版本的 Node\.js？

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

### @ai-matrx/canvas 可以商用吗？

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

### @ai-matrx/canvas 的下载量有多少？

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

### @ai-matrx/canvas 还在维护吗？

最新版本 0\.10\.91 发布于 2026/10/28（9 天前）；至今共发布 120 个版本，其中过去 12 个月发布了 120 个；首次发布于 2026/10/02。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

