@qilin-agent/client-ui-attachment 0.0.0-stage → 3.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 kkutysllb
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,46 @@
1
+ # Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
2
+ # section, a hash of its English and Chinese blocks outside code blocks and generated regions.
3
+ # After editing either side, bring the other along and re-record with:
4
+ # pnpm run verify-translation-pairing --write packages/client/ui-attachment/README.md
5
+ /:
6
+ en: 414cbe20f39f7a82
7
+ zh: f56ebf03129a29b8
8
+ /qilin-client-ui-attachment:
9
+ en: 04c911a0b242adb8
10
+ zh: 136a2c1c545d6b13
11
+ /qilin-client-ui-attachment/summary:
12
+ en: f36aa7a85597dd66
13
+ zh: f7e87849791fe89a
14
+ /qilin-client-ui-attachment/table-of-contents:
15
+ en: d152484eb41ac6b4
16
+ zh: 09388d293f9be9cb
17
+ /qilin-client-ui-attachment/use-this-package:
18
+ en: bab9cd061b0f9d65
19
+ zh: 69ba5823cb391e85
20
+ /qilin-client-ui-attachment/use-this-package/draft-attachments:
21
+ en: a77c8ec48e219aec
22
+ zh: 756d4fe881403006
23
+ /qilin-client-ui-attachment/use-this-package/message-images-and-the-lightbox:
24
+ en: 8b3d7729152d8060
25
+ zh: 815f932ccc9653f5
26
+ /qilin-client-ui-attachment/use-this-package/drop-overlay:
27
+ en: b9e22124f6688c37
28
+ zh: aa3918291aef3f17
29
+ /qilin-client-ui-attachment/understand-the-implementation:
30
+ en: 415bd2b09bb84b6b
31
+ zh: 2e49a39fb3957b4f
32
+ /qilin-client-ui-attachment/further-exploration:
33
+ en: 2b0ff44fc5abbce1
34
+ zh: faeec6dbc0c56fe8
35
+ /qilin-client-ui-attachment/model-experience:
36
+ en: 25566605d7b38667
37
+ zh: 927d3ea272893296
38
+ /qilin-client-ui-attachment/model-experience/kv-cache-effect:
39
+ en: ca75c51c89c2c9b0
40
+ zh: de54f3467ef3b9be
41
+ /qilin-client-ui-attachment/known-limitations-and-deferred-work:
42
+ en: 9a16cb4f174464cf
43
+ zh: 3de4b8288a74c594
44
+ /qilin-client-ui-attachment/known-limitations-and-deferred-work/dev-note:
45
+ en: e67f633dc6fe7773
46
+ zh: 3bb0c20c93f16f98
package/README.md CHANGED
@@ -1,3 +1,106 @@
1
- # Temporary Holding Version
1
+ ---
2
+ description: "Attachment presentation for the conversation UI: mixed draft-attachment rail, document drop target, history-image gallery, and original-image lightbox; for users and maintainers of the Web attachment experience."
3
+ kind: "package-reference"
4
+ ---
2
5
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
6
+ # @qilin-agent/client-ui-attachment
7
+
8
+ English | [中文](README.zh.md)
9
+
10
+ ## Summary
11
+
12
+ This package renders everything the conversation UI shows about attachments: one ordered draft rail under the composer, a full-viewport drop invitation, durable images in Chat, Trajectory, and Tool results, and a lightbox for the original image. Attachment data, upload state, image loading, and callbacks come from the declared slot owners. Choose it for the DeepSeek Chat-style attachment experience.
13
+
14
+ ## Table of Contents
15
+
16
+ - [Use this package](#use-this-package)
17
+ - [Understand the implementation](#understand-the-implementation)
18
+ - [Further Exploration](#further-exploration)
19
+ - [Model Experience](#model-experience)
20
+ - [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
21
+ - [Dev Note](#dev-note)
22
+
23
+ -----
24
+
25
+ <a id="use-this-package"></a>
26
+ ## Use this package
27
+
28
+ Mount this plugin alongside [`ui-conversation`](../ui-conversation/README.md) and [`ui-tool`](../ui-tool/README.md) when tool results need an image gallery. It waits for their slot declarations and registers its components into them. Users then see the mixed draft-attachment rail, DeepSeek Web file cards with upload controls, the drop overlay with its limits line, message images sized by count, the tool card's gallery, and the Escape/mask/close lightbox.
29
+
30
+ ### Draft attachments
31
+
32
+ Images and generic files retain pick order in one non-wrapping horizontal rail. Every item is 64px high: an image is a 64px square thumbnail, while a generic file is a 240px-wide DeepSeek Web card with a 16px radius, blue gradient document glyph, filename, and uppercase extension plus byte size. Edge arrows page hidden overflow, the scrollbar stays hidden, and a newly added item is revealed at the rail's end. Uploading replaces a file glyph with a spinner and shows byte progress when the carrier reports it, with an indeterminate bar before the first report; failure shows retry, and removal controls appear on hover or keyboard focus while remaining visible on touch devices. Clicking an image opens the original.
33
+
34
+ ### Message images and the lightbox
35
+
36
+ In Chat, one user message presents files and images in a right-aligned wrapping flow that preserves source order. A lone image without another attachment renders at 240px on its longer edge (aspect clamped to [0.25, 4], never upscaled); when the message has more than one attachment, each image is a fixed 64px square beside 240×64px file cards. A loaded image opens the document-level lightbox on click; a failed load shows a retry control instead. The lightbox closes on Escape, a mask press, or its close control, and restores focus to its opener.
37
+
38
+ Trajectory attachment rows request 48px square thumbnails that contain the complete image without cropping. Loading and retry icons keep the same box, with localized tooltips and accessible names; the image opens the same lightbox. A slot owner may supply a presentation-only image label for the thumbnail and lightbox without changing the durable reference or the cache lookup.
39
+
40
+ ### Drop overlay
41
+
42
+ While a file drag is over the page, the full-viewport overlay announces the drop: illustration, title, and a limits line when drops are accepted. The overlay only shows state — the owner's document-level listeners decide accept or reject.
43
+
44
+ -----
45
+
46
+ <a id="understand-the-implementation"></a>
47
+ ## Understand the implementation
48
+
49
+ <details>
50
+ <summary>Implementation internals — click to expand</summary>
51
+
52
+ The plugin waits for `conversation.input.attachments`, `conversation.message.images`, `conversation.trajectory.images`, and `tool.call.images` through `ctx.slots.inject`. It then registers the composer rail, document drop target, shared history gallery for Chat, Trajectory, and Tool results, and original-image lightbox. The presentation components are driven entirely by props: the slot owner supplies attachment data, image loading, callbacks, and the locale translator; the package entry exports no components.
53
+
54
+ | File | Role |
55
+ |---|---|
56
+ | [`src/client/ComposerAttachments.tsx`](src/client/ComposerAttachments.tsx) | Ordered image/file rail + drop overlay assembly |
57
+ | [`src/client/drop-events.ts`](src/client/drop-events.ts) | Document drag-and-drop listeners installed by each mounted attachment view's effect |
58
+ | [`src/AttachmentRail.tsx`](src/AttachmentRail.tsx) | Horizontal attachment overflow, wheel translation, edge arrows |
59
+ | [`src/client/MessageImages.tsx`](src/client/MessageImages.tsx) | Per-message gallery + lightbox assembly |
60
+ | [`src/MessageImage.tsx`](src/MessageImage.tsx) | Single image sizing, load/retry, click-to-open; local submission-echo previews render their object URL directly |
61
+ | [`ImageLightbox`](../ui-primitives/src/ImageLightbox.tsx) | Document-level modal preview over the shared mask |
62
+ | [`src/DropOverlay.tsx`](src/DropOverlay.tsx) | Pointer-inert drag invitation portal |
63
+
64
+ </details>
65
+
66
+ -----
67
+
68
+ <a id="further-exploration"></a>
69
+ ## Further Exploration
70
+
71
+ Read these pages when the attachment surface is not enough. They move from the slots this package fills to the conversation shell that owns the input flow.
72
+
73
+ - [ui-conversation](../ui-conversation/README.md) — declares the attachment slots and owns the composer and image intake.
74
+ - [Web client architecture](../../../.agents/notes/implemented/architecture/2026-07-19-gui-web-client-architecture.md) — how browser plugin rows load and register slots.
75
+ - [Client package map](../README.md) — adjacent browser UI packages.
76
+
77
+ -----
78
+
79
+ <a id="model-experience"></a>
80
+ ## Model Experience
81
+
82
+ None, as the plugin only renders attachment state supplied by the conversation UI and contributes no model-visible input.
83
+
84
+ #### KV Cache effect
85
+
86
+ None; this package neither assembles nor sends a provider request.
87
+
88
+ ## Known Limitations and Deferred Work
89
+
90
+ <a id="known-limitations-and-deferred-work"></a>
91
+
92
+
93
+ These limits define the current attachment surface. They are package constraints, not a general image-viewer comparison or a task backlog.
94
+
95
+ - **No zoom or download in the lightbox** — the preview renders the original at fit-to-viewport size only.
96
+ - **The lightbox does not trap focus** — it sets `aria-modal` and restores focus on close, but Tab can reach the page behind it.
97
+
98
+ <a id="dev-note"></a>
99
+ ### Dev Note
100
+
101
+ <details>
102
+ <summary>Working context for maintainers — click to expand</summary>
103
+
104
+ None.
105
+
106
+ </details>
package/README.zh.md ADDED
@@ -0,0 +1,106 @@
1
+ ---
2
+ description: "对话 UI 的附件呈现:混合草稿附件栏、文档拖放目标、历史图片画廊与原图灯箱;供 Web 附件体验的用户与维护者阅读。"
3
+ kind: "package-reference"
4
+ ---
5
+
6
+ # @qilin-agent/client-ui-attachment
7
+
8
+ [English](README.md) | 中文
9
+
10
+ ## 概述
11
+
12
+ 本包渲染对话 UI 中与附件相关的一切:composer 下的一条有序草稿附件栏、全视口拖放提示层、Chat、Trajectory 与工具结果中的长期保留的图片,以及查看原图的灯箱。附件数据、上传状态、图片加载与回调来自声明这些 slot 的持有方。需要 DeepSeek Chat 风格的附件体验时选择它。
13
+
14
+ ## 目录
15
+
16
+ - [使用本包](#use-this-package)
17
+ - [理解实现](#understand-the-implementation)
18
+ - [进一步探索](#further-exploration)
19
+ - [模型体验](#model-experience)
20
+ - [已知限制与延期工作](#known-limitations-and-deferred-work)
21
+ - [开发备注](#dev-note)
22
+
23
+ -----
24
+
25
+ <a id="use-this-package"></a>
26
+ ## 使用本包
27
+
28
+ 与 [`ui-conversation`](../ui-conversation/README.zh.md) 一起挂载本插件,工具结果需要图片图库时也要挂载 [`ui-tool`](../ui-tool/README.zh.md)。插件等待这些 slot 的声明,并把组件注册进去。用户会看到混合草稿附件栏、带上传控件的 DeepSeek Web 文件卡、带限制说明的拖放遮罩、按数量定尺寸的消息图片、工具卡片图库,以及支持 Escape、遮罩和关闭按钮的灯箱。
29
+
30
+ ### 草稿附件
31
+
32
+ 图片与通用文件按选择顺序进入同一条不换行的横向附件栏。所有条目均为 64px 高:图片是 64px 方形缩略图,通用文件是 240px 宽的 DeepSeek Web 卡片,带 16px 圆角、蓝色渐变文档图标、文件名,以及大写扩展名与字节大小。溢出隐藏时由边缘箭头翻页,滚动条保持隐藏,新增条目会滚动到栏尾展示。文件上传时图标位置显示 spinner,传输层报告字节时显示进度,首次报告前使用不定态进度条;失败时显示重试。移除按钮在悬停或键盘聚焦时出现,在触摸设备上保持可见。单击图片会打开原图。
33
+
34
+ ### 消息图片与灯箱
35
+
36
+ Chat 中的一条用户消息把文件与图片放在同一个靠右、可换行的排列中,并保持来源顺序。消息仅有一张图片且没有其他附件时,图片按长边 240px 渲染(宽高比钳制在 [0.25, 4],从不放大);消息有多个附件时,每张图片显示为固定 64px 方块,与 240×64px 文件卡同排。加载完成的图片单击打开文档级灯箱;加载失败则显示重试控件。灯箱按 Escape、按下遮罩或点关闭按钮关闭,并把焦点还给打开者。
37
+
38
+ Trajectory 附件行使用 48px 方形缩略图,完整缩放图片而不裁剪。加载与重试图标保持相同尺寸,提供本地化的工具提示和可访问名称;图片打开同一个灯箱。插槽持有方可以为缩略图与灯箱提供仅用于展示的图片名称,而不改变持久化引用或缓存查询。
39
+
40
+ ### 拖放遮罩
41
+
42
+ 文件拖到页面上方时,全视口遮罩显示拖放提示,包括插画和标题;接受拖放时还会显示一行限制说明。遮罩只呈现状态——是否接受由持有方的文档级监听器决定。
43
+
44
+ -----
45
+
46
+ <a id="understand-the-implementation"></a>
47
+ ## 理解实现
48
+
49
+ <details>
50
+ <summary>实现细节——点击展开</summary>
51
+
52
+ 插件通过 `ctx.slots.inject` 等待 `conversation.input.attachments`、`conversation.message.images`、`conversation.trajectory.images` 与 `tool.call.images`。随后它注册 composer rail、文档拖放目标、供 Chat、Trajectory 与工具结果共用的历史图片 gallery,以及原图灯箱。呈现组件仅依赖 props:slot 持有方提供附件数据、图片加载、回调与语言包翻译器;包入口不导出任何组件。
53
+
54
+ | 文件 | 职责 |
55
+ |---|---|
56
+ | [`src/client/ComposerAttachments.tsx`](src/client/ComposerAttachments.tsx) | 有序图片/文件栏+拖放遮罩的组装 |
57
+ | [`src/client/drop-events.ts`](src/client/drop-events.ts) | 每个已挂载附件视图的 effect 安装的 document 拖放监听 |
58
+ | [`src/AttachmentRail.tsx`](src/AttachmentRail.tsx) | 附件横向溢出、滚轮转换、边缘箭头 |
59
+ | [`src/client/MessageImages.tsx`](src/client/MessageImages.tsx) | 每消息画廊+灯箱的组装 |
60
+ | [`src/MessageImage.tsx`](src/MessageImage.tsx) | 单图尺寸、加载/重试、点击打开;本地提交回显预览直接显示其 object URL |
61
+ | [`ImageLightbox`](../ui-primitives/src/ImageLightbox.tsx) | 铺在共享遮罩上的文档级模态预览 |
62
+ | [`src/DropOverlay.tsx`](src/DropOverlay.tsx) | 不接收指针事件的拖放提示 portal |
63
+
64
+ </details>
65
+
66
+ -----
67
+
68
+ <a id="further-exploration"></a>
69
+ ## 进一步探索
70
+
71
+ 如果附件界面本身还不够,请阅读以下页面。这些页面从本包填充的 slot 讲到负责输入流程的会话外壳。
72
+
73
+ - [ui-conversation](../ui-conversation/README.zh.md)——声明附件 slot,并负责 composer 与图片接收。
74
+ - [Web 客户端架构](../../../.agents/notes/implemented/architecture/2026-07-19-gui-web-client-architecture.zh.md)——浏览器插件行如何加载并注册 slot。
75
+ - [客户端包映射](../README.zh.md)——相邻的浏览器 UI 包。
76
+
77
+ -----
78
+
79
+ <a id="model-experience"></a>
80
+ ## 模型体验
81
+
82
+ 无,因为该插件只渲染由对话 UI 提供的附件状态,不贡献模型可见输入。
83
+
84
+ #### KV Cache 影响
85
+
86
+ 无;该包既不组装也不发送提供方请求。
87
+
88
+ ## 已知限制与延期工作
89
+
90
+ <a id="known-limitations-and-deferred-work"></a>
91
+
92
+
93
+ 这些限制界定了当前附件功能范围。它们是包约束,不是通用图片查看器对比或任务积压。
94
+
95
+ - **灯箱无缩放与下载**——预览仅以适配视口的尺寸渲染原图。
96
+ - **灯箱不锁定焦点**——它设置 `aria-modal` 并在关闭时归还焦点,但 Tab 仍可移动到背后的页面。
97
+
98
+ <a id="dev-note"></a>
99
+ ### 开发备注
100
+
101
+ <details>
102
+ <summary>维护者的工作上下文——点击展开</summary>
103
+
104
+ 无。
105
+
106
+ </details>