# @exponential\_app/eui-element 中文文档

规范地址：https://npmcn.com/package/%40exponential_app/eui-element/

版本：0\.21\.0
npm 元数据更新时间：2026-11-10T08:34:58.064Z
中文译文更新时间：2026-11-14T05:56:27.197Z
软件包许可：Apache-2\.0

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

原始 npm 页面：https://www.npmjs.com/package/%40exponential_app/eui-element
原文对照：https://npmcn.com/package/%40exponential_app/eui-element/?lang=original
项目主页：https://exponential.at/ui/
源码仓库：https://github.com/Niach/exponential

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

- 包体积（解压后）：5.5 MB，21 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：3 个
- 首次发布：2026-10-30T07:42:55.638Z
- 最新版本发布：2026-11-10T08:34:57.627Z
- 近 30 天下载量：5450（2026-10-14 至 2026-11-12，npm 官方下载统计）
- 已发布版本数：29（近 12 个月 29 个）

## 中文简介

genUI作为一个自定义元素:在主机页面上画出一个没有框架的核心 A2UI 表面,在 Solid 画像和共享的网页层上,其DOM,编译的样式表和运行时的主题与 React 渲染相同

## 安装

```sh
npm install @exponential_app/eui-element
```

也可以使用：`pnpm add @exponential_app/eui-element`、`yarn add @exponential_app/eui-element`、`bun add @exponential_app/eui-element`

## README

# `@exponential_app/eui-element`: genUI 作为自定义元素

`<exponential-surface>` 在核心目录中绘制 A2UI 表面 (单位:千美元)`@exponential_app/eui`)在任意一页,没有框架(FEED-130)。 没有 有个自己的画家 它能搭载固体制造器 (单位:千美元)`@exponential_app/eui-solid`里面,你得到一个画家和两个 进入点。 元素使用光 DOM 并且是 `display: contents` 结束 一个共享的零特性规则 `define()` 安装( e)`:where(exponential-surface){display:contents}`, (中文(简体) ), 所以,你的任何规则 赢了,所以表面的 `.xui-surface` 根为框, 同一地点的 React的DIV会是。 一个任务中附加的元素挂起 一起:第一个一次,剩下的在一个批次内的微任务中.

## 变化者

对于每个表面,元素 精确地描绘什么反应渲染器 油漆:相同的元素、属性, `<style data-xui-style>` 床单, 层和运行时间主题. `src/parity.test.ts` 比较元素的 `.xui-surface` 子树对 `@exponential_app/eui-react` 在jsdom中,使用 软件包 `serializeDom` 财务报告和审定财务报表 `renderReact`。 。 。 .

```html
<script type="module">
  import "@exponential_app/eui-element/define"   // or the self-contained ./standalone bundle
</script>

<exponential-surface theme="orange" mode="system" src="/ui/stream" post="/ui/events"></exponential-surface>

<script type="module">
  const el = document.querySelector("exponential-surface")
  el.addEventListener("xui-action", (e) => e.detail.waitUntil(fetch("/save", { method: "POST", body: JSON.stringify(e.detail.context) })))
</script>
```

没有服务器,就打电话 `apply()` 输入 A2UI v0.9 信件 :

```js
const el = document.createElement("exponential-surface")
document.body.append(el)
el.apply({ createSurface: { surfaceId: "main", catalogId } })
el.apply({ updateComponents: { surfaceId: "main", components } })
```

## API 密码

| 属性/ 属性 | 什麽 |
| --- | --- |
| `theme` | 内置标识( 属性) 。 属性还取一个主题 JSON 或 a `ResolvedTheme`; 对象不反映。 一个无法使用的主题从不扔出:默认的主题画和 `xui-theme-issues` 火灾. |
| `mode` | `light`, (中文(简体) ), `dark` 或者说 `system` (默认者,按住) |
| `density`, (中文(简体) ), `contrast` | `compact`, (中文(简体) ), `default` 或者说 `comfortable`· ; `normal`, (中文(简体) ), `high` 或者说 `system` |
| `locale`, (中文(简体) ), `time-zone` (单位:千美元)`timeZone`(中文(简体) ) | BCP 47 地块( 默认) `en-US`)和IANA时区(默认站台) |
| `direction` | `ltr` 或者说 `rtl` (默认: 语区方向) |
| `form-factor` (单位:千美元)`formFactor`(中文(简体) ) | `phone` 或者说 `wide`: 主机的形式因子,什么 `@media (form-factor: …)` 匹配( 默认: 取自表面宽度, `phone` 主题以下 `$breakpoint.md`(中文(简体) ) |
| `width`, (中文(简体) ), `height` | 数字字符串表示px;任何其他字符串都是CSS长度. 明确 `height` 是高度条件的取景口. |
| `surface-id` (单位:千美元)`surfaceId`(中文(简体) ) | 表面 ID( 默认) `main`: `xui-s-<id>` 班级,商店 `apply()` 造作,而宿主所画的表面 |
| `src`, (中文(简体) ), `post`, (中文(简体) ), `transport` | 主办方API(见下文) |
| `surface` | A 类 `createSurface` 存储( 相对于其他来源优先) |
| `root`, (中文(简体) ), `templates`, (中文(简体) ), `data` | Fixture 模式:一个正态树,它的被升起的模板和一个数据模型 |
| `host` | 一个 `ExponentialHost` 替换为 `src` |
| `plugin` | A 类 `HostPlugin`:图标, `Markdown`、URL和媒体政策, `optionSource`, (中文(简体) ), `mediaRequest`, (中文(简体) ), `mediaStreamUrl`, (中文(简体) ), `resolveUrl`, (中文(简体) ), `functions`, (中文(简体) ), `qrScanner` (QrScanner相机,下面),和回调 |
| `extensions`, (中文(简体) ), `strings`, (中文(简体) ), `states`, (中文(简体) ), `measure`, (中文(简体) ), `viewportHeight` | 和固体道具一样 |

字符串属性反映它们的属性. 将财产设定为 `null` 删除它的属性。 元素附加前设置的属性 (或在升级之前)仍然适用.

只读属性 :

-   `handle`页:1 `SurfaceHandle`,或 `null` 直到第一幅画.
-   `issues`:活动商店减少问题.
-   `status`运输状况; `statusDetail`: 细节( 错误, 或 URL 政策拒绝的原因) `src`编号 :`post`) (中文(简体) ).
-   `surfaceState`页:1 `SurfaceState` 被画.

方法:

-   `apply(message)` 发送消息到 `surface` 属性,其他为主机(`receive`),否则,到一款初用时创建的商店.
-   `setData(pointer, value)` 写活动商店。 在固定模式下,它设置了新的 `data`。 。 。 .
-   `reset()` 重置活动商店 .
-   `run(command)`, (中文(简体) ), `focus(id)`, (中文(简体) ), `announce(text, live?)`, (中文(简体) ), `scrollIntoView(id)` 财务报告和审定财务报表 `scrollToIndex(id, index, align?)` 穿过把手 在第一次油漆之前,他们回来 `false` 或无所事事。 不带字符串的号码, `focus()` 财务报告和审定财务报表 `scrollIntoView()` 保持他们的常态 `HTMLElement` 意为.

分离元素处理所涂 DOM. 重新装入画作 每一个财产都活下来了 随函附上任何儿童 作者放入元素内.

### QrScanner相机

A 类 `QrScanner` 只画取景器;相机是页面的,通过 `plugin.qrScanner` (固体制造器的钩子,VAPP-162):

```js
el.plugin = {
  qrScanner: {
    // feed: an empty element filling the viewfinder (append a <video>);
    // formats: default ["qr"]; call onValue per decoded string; return the stop.
    start(feed, formats, onValue) {
      const video = feed.appendChild(document.createElement("video"))
      // … getUserMedia + a decoder calling onValue(text) …
      return () => video.srcObject?.getTracks().forEach((t) => t.stop())
    },
  },
}
el.addEventListener("xui-action", (e) => e.detail.event === "scanned" && pair(e.detail.payload.value))
```

一个值点火节点 `scanned` 处理器( e)`xui-action`,以及 `plugin.onAction`)一次,按不同价值计算。 无 `qrScanner` (或何时) `start` 返回时 `false`)扫描仪显示 `Camera unavailable`。 。 。 .

### 卡鲁塞尔缩略图

第6轮(EXP-1495)通过"固体"画家:一款有"自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自 `counter: true` 显示 `i / n` 药和一 `thumbnails: [url…]` 在页下显示条(两个或两个以上页)。 缩略图按键页面 一个点,所以页面得到 `xui-action` 与 `event: "change"` 财务报告和审定财务报表 `payload.page`。 。 。 .

## 活动

每个事件都是 `CustomEvent` 气泡和构成。 当有的时候 一个匹配 `plugin` 召回,召回 和事件起火。 在一个 承诺涉及,结果被加入: 控制直到 他们都安顿下来了.

| 事件 | 细节 |
| --- | --- |
| `xui-action` | `SurfaceActionEvent` + 键 `waitUntil(promise)`按钮待处理(`aria-busy="true"` 财务报告和审定财务报表 `disabled` 一次; `data-pending="true"` 之后 `PENDING_DELAY_MS`直到承诺达成为止. |
| `xui-input` | `SurfaceInputEvent` + 键 `waitUntil`在承诺达成时,将确认修订内容. |
| `xui-function-call` | `{ call, respond(value) }`。第一个 `respond` 赢了 没有回应, 插件的 `onFunctionCall` 使用结果. |
| `xui-open-url` | `{ url }`,在 URL 策略通过之后。 可取消 : 如果没有取消, 则改为 `plugin.openUrl`,则 `window.open(url, "_blank", "noopener,noreferrer")`。 。 。 . |
| `xui-upload` | `{ files, target: { nodeId, name }, waitUntil }` |
| `xui-paint-error` | `{ error }` |
| `xui-theme-issues` | `{ issues }` |
| `xui-unknown` | `{ node }` |
| `xui-status` | `{ status, detail? }` |
| `xui-ready` | `{ handle }`。每个挂载一次起火,在手柄到达之后的微工作表中,所以听众在紧接着添加 `appendChild` 还得到它. |

`HTMLElementEventMap` 财务报告和审定财务报表 `HTMLElementTagNameMap` 被扩充,所以 `addEventListener("xui-action", …)` 财务报告和审定财务报表 `document.createElement("exponential-surface")` 输入.

## 主持人 API

何时 `src` 设置和否 `host` 属性, 元素构建 `new ExponentialHost({ transport })` 这些运输工具之一:

-   `WebSocketTransport` 何时 `src` 是一个 `ws:`编号 :`wss:` URL 或 网络 `transport="ws"`。 。 。 .
-   `SseTransport` 何时 `transport="sse"`。 。 。 .
-   `JsonlStreamTransport` 否则.

客户端消息被 POSTD 到 `post` (默认) `src`) (中文(简体) ). 元素连接 它在连接时建造的宿主,在分离时关闭并重建它 何时 `src`, (中文(简体) ), `post` 或者说 `transport` 变化。 一个主机表面的画什么也没有 直到主机有一个表面 `surface-id`。动作、功能、 URL 和 通过主机的媒体路由( r)`hostPlugin`) (中文(简体) ). `xui-open-url` 继续放火 在主机打开 URL 之前.

A 类 `host` 属性属于页面。 元素只连接它 拥有运输工具,从未连接过(`status === "closed"`)),以及该词 从来没有关闭它.

`src` 财务报告和审定财务报表 `post` 通过该页面的 URL 策略( R)`plugin.urls`,每个 在建造运输工具之前(`decideTransport`一个私人, 回放或链接- 本地主机( l)`10.0.0.5`, (中文(简体) ), `localhost`, (中文(简体) ), `*.local`, (中文(简体) ), `169.254.169.254`, (中文(简体) ), `::1`,十进制和IPv4-mapped literals)被拒绝,除非 `plugin.urls.allowPrivate` 选入(该页面的私人来源是,所以) 本地主机流上的 dev 服务器; a `hosts` 许可名单搁置; `schemes: ["https"]` 仅指https + wss; `javascript:`, (中文(简体) ), `file:`, (中文(简体) ), `data:` 从不连接。 A 类 `ws:`编号 :`wss:` url 被确定为 http(s) 双子 。 拒绝 `src` 或者说 `post` 不创建主机并获取任何信息 : `status` 实值 `closed`, (中文(简体) ), `statusDetail` 说为什么(`src denied by the URL policy (private)`和 `xui-status` 开火一次。 独立的捆绑带同样的过滤器.

## 扩展

```js
import { defineElementExtension } from "@exponential_app/eui-element"

el.extensions = [defineElementExtension({
  catalog,                                    // defineExtension(...) or its JSON
  components: {
    Gauge: (ctx) => {
      const div = document.createElement("div")
      ctx.applyRootProps(div)                   // class, data-xui-id, data-xui-c, data-r-*, aria, dir, style
      div.textContent = `${ctx.props.value}`
      div.append(...ctx.children())             // ctx.slot("header") for a slot
      div.onclick = () => ctx.emit("press")
      return div
    },
  },
})]
```

画家是一个简单的功能: `ElementPaintContext` 进去,一个DOM 元素出来了。 它在节点、道具、主题、模式或根时再次运行 属性变化,新元素替换了旧元素。 画的 每个再油漆上的孩子和插槽都是相同的节点. `registerExtension(ext)` 为页面上的每个表面登记一个。 A 类 `components` 键 核心原生超过它的画家。 一个主机从 `src` 学习 分类 `el.extensions` 当它建成时: 在 元素附加( 或之前) `src`) (中文(简体) ).

## 无框架主机的图标

```js
el.plugin = { icons: iconsFromSvg((name) => sprite[name]) }   // SVG markup strings
```

每个标记字符串都成为图标组件,每相隔间创建一次 绳子。 一个没有标记的名字 回到了制造者自己的Lucide 甘草(变种). 包装器装在 `<svg>` 根何为清晰反应的根 携带其收到的道具:

-   `width`编号 :`height` =: `width` ? `size` \* 24岁.
-   `class` =标本自班 +画家班.
-   `aria-hidden="true"`,除非通过 aria-\*/作用/标题道具.
-   `stroke` =: `color`, (中文(简体) ), `stroke-width` =: `strokeWidth`。 。 。 .
-   给定的所有其他字符串或数字属性( E)`data-icon`(......) (中文(简体) ).

标记是可信的,但 `<script>`, (中文(简体) ), `foreignObject`, (中文(简体) ), `on*` 属性 财务报告和审定财务报表 `javascript:` 链接已被删除 .

## 条目

| 条目 | 什麽 |
| --- | --- |
| `@exponential_app/eui-element` | 没有副作用:, `TAG`, (中文(简体) ), `define(tag?)`、帮助者和再出口 `createSurface`, (中文(简体) ), `registerExtension` 财务报告和审定财务报表 `defineSolidExtension` |
| `@exponential_app/eui-element/define` | 电话 `define()` 导入时( 偶数; 由其它类丢入的标签; 另外一个标签获得自己的子类) |
| `@exponential_app/eui-element/standalone` | 同样的自成一体(Solid和内含的渲染器)装入一个ES模块 |

## 版式

| 路径 | 什麽 |
| --- | --- |
| `src/element.ts` | `ExponentialSurfaceElement`:信号、属性和属性、源顺序、合并插件、挂起 |
| `src/events.ts` | 事件名称、详细类型、全球扩增、 `waitUntil` 加入时 |
| `src/transport.ts` | `src`编号 :`post`编号 :`transport` - 一个 `ExponentialHost` |
| `src/extensions.ts` | `defineElementExtension`, (中文(简体) ), `registerExtension`, (中文(简体) ), `applyRootProps` |
| `src/icons.ts` | `iconsFromSvg`, (中文(简体) ), `svgIcon` |
| `src/index.ts`, (中文(简体) ), `define.ts`, (中文(简体) ), `standalone.ts` | 条目 |
| `src/*.test.ts` | jsdom套房:元素、事件、传输、扩展、DOM与React的等同 |

## 图标

```bash
bun run --filter @exponential_app/eui-element typecheck
bun run --filter @exponential_app/eui-element test
```

## 常见问题

### @exponential\_app/eui-element 是什么？

genUI作为一个自定义元素:在主机页面上画出一个没有框架的核心 A2UI 表面,在 Solid 画像和共享的网页层上,其DOM,编译的样式表和运行时的主题与 React 渲染相同

### 如何安装 @exponential\_app/eui-element？

在项目目录运行 npm install @exponential\_app/eui-element，或使用 pnpm add / yarn add / bun add。

### @exponential\_app/eui-element 支持 TypeScript 吗？

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

### @exponential\_app/eui-element 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @exponential\_app/eui-element 可以商用吗？

@exponential\_app/eui-element 使用 Apache-2\.0 许可。宽松许可：允许商业使用、修改和再分发，并附带明确的专利授权；分发时需保留许可与 NOTICE 文件，修改过的文件要注明改动。以上为概括，不构成法律意见，请以许可原文为准。

### @exponential\_app/eui-element 的下载量有多少？

根据 npm 官方下载统计，@exponential\_app/eui-element 在 2026/10/14 – 2026/11/12 这 30 天内被下载 5,450 次，日均约 182 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @exponential\_app/eui-element 还在维护吗？

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

