文档/Widget API
通用开发

Widget API

Widget API

概述

Widgets 是插件在 CoreBox 或 DivisionBox 中渲染的轻量 UI 组件。

介绍

在 manifest 中声明 widget,并在插件目录提供对应的渲染入口。

支持的文件类型

扩展名说明处理器
.vueVue 单文件组件WidgetVueProcessor
.tsxTypeScript JSXWidgetTsxProcessor
.jsxJavaScript JSXWidgetTsxProcessor
.ts纯 TypeScriptWidgetScriptProcessor
.js纯 JavaScriptWidgetScriptProcessor
.cjs预编译 CommonJSWidgetScriptProcessor

Widget 类型

类型使用场景
面板型固定在 Workspace,展示复杂 UI
浮动型悬浮窗,适合快速操作
通知中心型以卡片形式展示摘要

Manifest 配置

EXAMPLE.JSON
{
  "type": "widget",
  "id": "todo.widget",
  "title": "任务面板",
  "size": { "width": 4, "height": 3 },
  "interaction": {
    "type": "widget",
    "path": "todo-panel.vue"
  }
}

文件结构

EXAMPLE.VUE
my-plugin/
├── widgets/
│   ├── todo-panel.vue      # Vue SFC
│   ├── quick-action.tsx    # TSX component
│   └── helper.ts           # Plain TS module
├── manifest.json
└── index.js

Vue Widget 示例

widgets/todo-panel.vue

EXAMPLE.VUE
<template>
  <div class="todo-panel">
    <h3>{{ title }}</h3>
    <ul>
      <li v-for="item in items" :key="item.id">{{ item.text }}</li>
    </ul>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { usePluginContext } from '@talex-touch/utils/plugin/sdk'

const ctx = usePluginContext()
const title = ref('My Tasks')
const items = ref([{ id: 1, text: 'Learn Widgets' }])
</script>

<style scoped>
.todo-panel { padding: 16px; }
</style>

TSX Widget 示例

widgets/quick-action.tsx

EXAMPLE.TSX
import { defineComponent, ref } from 'vue'

export default defineComponent({
  setup() {
    const count = ref(0)
    return () => (
      <div class="action-panel">
        <button onClick={() => count.value++}>
          Clicked {count.value} times
        </button>
      </div>
    )
  }
})

允许的依赖

Widgets 运行在受控环境,仅允许以下包:

  • vue
  • @talex-touch/utils
  • @talex-touch/utils/plugin
  • @talex-touch/utils/plugin/sdk
  • @talex-touch/utils/core-box
  • @talex-touch/utils/transport
  • @talex-touch/utils/common
  • @talex-touch/utils/types

通信

  • 使用 TuffTransport 进行类型安全的 IPC 通信
  • ctx.widget.send 与宿主交换尺寸、主题等信息
  • 可通过 ctx.storage 访问插件存储

失败态与诊断

Widget 注册失败时,CoreBox 会在原位置显示明确状态,不再只显示空白或调试文本。常见状态包括:

  • Widget 加载中:renderer 正在等待注册。
  • Widget renderer 未注册:宿主尚未收到可用 renderer。
  • Widget 编译失败:源码编译或运行时编译器不可用,消息中会展示失败原因。
  • Widget 渲染失败:组件已注册但渲染阶段抛错。

主进程会将 widget 失败写入插件 issue,并附带 pluginNamefeatureIdwidgetIdfilePathhashcauseCode 诊断字段。WIDGET_COMPILER_BINARY_UNAVAILABLE 表示运行时 esbuild 平台二进制缺失、位于 app.asar 内或不可执行;普通源码语法、依赖与编译错误仍使用 WIDGET_COMPILE_FAILED 或对应的依赖/路径 issue code。

最佳实践

  • UI 与交互遵循系统暗/亮模式
  • 避免复杂动画,确保在 16ms 内完成重绘
  • 提供空状态与错误提示,保持体验一致
  • 优先使用 @talex-touch/utils 的 hooks

Dev 模式(远程源码)

dev.enabledev.source 为 true 时,Widget 源码从 dev server 拉取,而不是本地 widgets/ 目录。解析规则为:

{dev.address}/widgets/{interaction.path}(未提供扩展名时默认 .vue)。

EXAMPLE.JSON
{
  "dev": {
    "enable": true,
    "source": true,
    "address": "http://localhost:5173/"
  }
}

远程源码会在每次触发时拉取;文件监听只对本地路径生效。

技术说明

  • Widget 运行在渲染进程的沙箱环境,依赖受限。
  • 文件处理由 Widget processor 负责。