@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 +21 -0
- package/README.i18n.yaml +46 -0
- package/README.md +105 -2
- package/README.zh.md +106 -0
- package/lib/client.js +878 -0
- package/lib/index.js +6 -0
- package/lib/types/AttachmentRail.d.ts +39 -0
- package/lib/types/DropOverlay.d.ts +24 -0
- package/lib/types/FileCard.d.ts +26 -0
- package/lib/types/MessageImage.d.ts +64 -0
- package/lib/types/client/ComposerAttachments.d.ts +4 -0
- package/lib/types/client/MessageImages.d.ts +4 -0
- package/lib/types/client/drop-events.d.ts +14 -0
- package/lib/types/client/index.d.ts +7 -0
- package/lib/types/client/labels.d.ts +43 -0
- package/lib/types/index.d.ts +4 -0
- package/package.json +69 -3
package/lib/client.js
ADDED
|
@@ -0,0 +1,878 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "@qilin-agent/client-ui-attachment",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
|
+
let react = require("react");
|
|
9
|
+
let _qilin_agent_client_ui_primitives = require("@qilin-agent/client-ui-primitives");
|
|
10
|
+
let react_dom = require("react-dom");
|
|
11
|
+
//#region ../../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
|
|
12
|
+
function r(e) {
|
|
13
|
+
var t, f, n = "";
|
|
14
|
+
if ("string" == typeof e || "number" == typeof e) n += e;
|
|
15
|
+
else if ("object" == typeof e) if (Array.isArray(e)) {
|
|
16
|
+
var o = e.length;
|
|
17
|
+
for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
|
|
18
|
+
} else for (f in e) e[f] && (n && (n += " "), n += f);
|
|
19
|
+
return n;
|
|
20
|
+
}
|
|
21
|
+
function clsx() {
|
|
22
|
+
for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
|
|
23
|
+
return n;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region \0qilin-css:/home/runner/work/QiLin/QiLin/packages/client/ui-attachment/src/AttachmentRail.module.css.mjs
|
|
27
|
+
const css$4 = ".tsmrHq_root{min-width:0;position:relative}.tsmrHq_rail{scrollbar-width:none;--qilin-scrollbar-thumb:var(--qilin-alias-scrollbar-bg-l2);--qilin-scrollbar-thumb-hover:var(--qilin-alias-scrollbar-hover-l2);align-items:stretch;gap:10px;display:flex;overflow:auto hidden}.tsmrHq_rail::-webkit-scrollbar{display:none}.tsmrHq_item{flex:none;height:64px}.tsmrHq_thumbnail{border:.5px solid var(--qilin-alias-border-l2-darkmode-thin);background:var(--qilin-alias-interactive-bg-hover);cursor:zoom-in;border-radius:16px;width:64px;height:64px;padding:0;overflow:hidden}.tsmrHq_thumbnail img{object-fit:cover;width:100%;height:100%;display:block}.tsmrHq_remove{z-index:1;corner-shape:round;background:var(--qilin-alias-button-contrast-fill);width:18px;height:18px;color:var(--qilin-alias-label-primary-inverted);cursor:pointer;opacity:0;border:none;border-radius:50%;place-items:center;padding:0;transition:opacity .2s ease-in-out;display:grid;position:absolute;top:4px;right:4px}.tsmrHq_item:hover .tsmrHq_remove,.tsmrHq_remove:focus-visible{opacity:1}@media (pointer:coarse){.tsmrHq_remove{opacity:1}}@media (prefers-reduced-motion:reduce){.tsmrHq_remove{transition:none}}.tsmrHq_arrow{z-index:2;--qilin-elevation-stroke-color:var(--qilin-alias-border-l2-darkmode-thin);corner-shape:round;background:var(--qilin-specific-input-major);width:24px;height:24px;color:var(--qilin-alias-label-secondary);box-shadow:var(--qilin-elevation-panel);cursor:pointer;border:0;border-radius:999px;place-items:center;padding:0;display:grid;position:absolute;top:50%;transform:translateY(-50%)}.tsmrHq_arrow:hover{background:var(--qilin-alias-interactive-bg-hover-solid)}.tsmrHq_arrowLeft{left:4px}.tsmrHq_arrowRight{right:4px}";
|
|
28
|
+
const tagId$4 = "@qilin-agent/client-ui-attachment/AttachmentRail.module.css";
|
|
29
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
|
|
30
|
+
const tag = document.createElement("style");
|
|
31
|
+
tag.dataset.plugin = "@qilin-agent/client-ui-attachment";
|
|
32
|
+
tag.dataset.pluginCss = tagId$4;
|
|
33
|
+
tag.textContent = css$4;
|
|
34
|
+
document.head.appendChild(tag);
|
|
35
|
+
}
|
|
36
|
+
var AttachmentRail_module_css_default = {
|
|
37
|
+
"arrow": "tsmrHq_arrow",
|
|
38
|
+
"arrowLeft": "tsmrHq_arrowLeft",
|
|
39
|
+
"arrowRight": "tsmrHq_arrowRight",
|
|
40
|
+
"item": "tsmrHq_item",
|
|
41
|
+
"rail": "tsmrHq_rail",
|
|
42
|
+
"remove": "tsmrHq_remove",
|
|
43
|
+
"root": "tsmrHq_root",
|
|
44
|
+
"thumbnail": "tsmrHq_thumbnail"
|
|
45
|
+
};
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region lib/types/AttachmentRail.js
|
|
48
|
+
/** Draft-attachment rail: scrollbar-less horizontal overflow paged by edge arrows. */
|
|
49
|
+
/** Approximate pixels per wheel step for `deltaMode` LINE deltas (Firefox
|
|
50
|
+
* notch wheels report lines, not pixels). */
|
|
51
|
+
const WHEEL_LINE_PX = 16;
|
|
52
|
+
/** Smooth paging unless the user asked for reduced motion. */
|
|
53
|
+
function pageBehavior() {
|
|
54
|
+
const matchMedia = window.matchMedia;
|
|
55
|
+
return matchMedia?.("(prefers-reduced-motion: reduce)").matches ? "auto" : "smooth";
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Horizontal rail over the caller's ordered draft attachments.
|
|
59
|
+
*
|
|
60
|
+
* The rail scrolls with its scrollbar hidden; overflow is announced by edge
|
|
61
|
+
* arrows recomputed from scroll geometry on scroll, item-count changes, and
|
|
62
|
+
* rail size changes (a ResizeObserver on the rail element, so sidebar or
|
|
63
|
+
* panel resizes count, not only window resizes). A vertical wheel pans the
|
|
64
|
+
* rail horizontally and is consumed exclusively (non-passive listener), a
|
|
65
|
+
* newly added item is revealed at the rail's end while a rail that mounts
|
|
66
|
+
* over an existing draft keeps its start position. The owner renders each
|
|
67
|
+
* item and decides mounting; it renders the rail only while items exist.
|
|
68
|
+
*
|
|
69
|
+
* @param props.items - attachments in draft order.
|
|
70
|
+
* @param props.labels - rail-level strings (group name and paging arrows).
|
|
71
|
+
* @param props.renderItem - render one attachment card in draft order.
|
|
72
|
+
* @returns the rail group with its paging arrows.
|
|
73
|
+
*/
|
|
74
|
+
function AttachmentRail({ items, labels, renderItem }) {
|
|
75
|
+
const railRef = (0, react.useRef)(null);
|
|
76
|
+
const countRef = (0, react.useRef)(null);
|
|
77
|
+
const [edges, setEdges] = (0, react.useState)({
|
|
78
|
+
left: false,
|
|
79
|
+
right: false
|
|
80
|
+
});
|
|
81
|
+
const updateEdges = (0, react.useCallback)(() => {
|
|
82
|
+
const el = railRef.current;
|
|
83
|
+
/* v8 ignore next -- defensive: every caller runs while the rail element is mounted. */
|
|
84
|
+
if (el === null) return;
|
|
85
|
+
const left = el.scrollLeft > 1;
|
|
86
|
+
const right = el.scrollLeft < el.scrollWidth - el.clientWidth - 1;
|
|
87
|
+
setEdges((prev) => prev.left === left && prev.right === right ? prev : {
|
|
88
|
+
left,
|
|
89
|
+
right
|
|
90
|
+
});
|
|
91
|
+
}, []);
|
|
92
|
+
(0, react.useLayoutEffect)(() => {
|
|
93
|
+
const grew = countRef.current !== null && items.length > countRef.current;
|
|
94
|
+
countRef.current = items.length;
|
|
95
|
+
const el = railRef.current;
|
|
96
|
+
/* v8 ignore next -- defensive: the rail div renders unconditionally, so the layout effect always finds it. */
|
|
97
|
+
if (el === null) return;
|
|
98
|
+
if (grew) el.scrollLeft = el.scrollWidth - el.clientWidth;
|
|
99
|
+
updateEdges();
|
|
100
|
+
}, [items.length, updateEdges]);
|
|
101
|
+
(0, react.useEffect)(() => {
|
|
102
|
+
const el = railRef.current;
|
|
103
|
+
/* v8 ignore next -- defensive: the rail div renders unconditionally, so the mount effect always finds it. */
|
|
104
|
+
if (el === null) return;
|
|
105
|
+
let disconnect = () => {};
|
|
106
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
107
|
+
const observer = new ResizeObserver(updateEdges);
|
|
108
|
+
observer.observe(el);
|
|
109
|
+
disconnect = () => {
|
|
110
|
+
observer.disconnect();
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
const onWheel = (event) => {
|
|
114
|
+
if (event.deltaY === 0) return;
|
|
115
|
+
const scale = event.deltaMode === WheelEvent.DOM_DELTA_LINE ? WHEEL_LINE_PX : event.deltaMode === WheelEvent.DOM_DELTA_PAGE ? el.clientWidth : 1;
|
|
116
|
+
event.preventDefault();
|
|
117
|
+
el.scrollBy({
|
|
118
|
+
left: event.deltaX !== 0 ? event.deltaX * scale : Math.sign(event.deltaY) * Math.min(Math.abs(event.deltaY) * scale, 60),
|
|
119
|
+
behavior: "auto"
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
el.addEventListener("wheel", onWheel, { passive: false });
|
|
123
|
+
return () => {
|
|
124
|
+
disconnect();
|
|
125
|
+
el.removeEventListener("wheel", onWheel);
|
|
126
|
+
};
|
|
127
|
+
}, [updateEdges]);
|
|
128
|
+
const page = (direction) => {
|
|
129
|
+
const el = railRef.current;
|
|
130
|
+
/* v8 ignore next -- defensive: the arrows render only while the rail is mounted, so a click cannot find a null ref. */
|
|
131
|
+
if (el === null) return;
|
|
132
|
+
el.scrollBy({
|
|
133
|
+
left: direction * Math.max(el.clientWidth - 64, 200),
|
|
134
|
+
behavior: pageBehavior()
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
138
|
+
className: AttachmentRail_module_css_default.root,
|
|
139
|
+
children: [
|
|
140
|
+
edges.left && (0, react_jsx_runtime.jsx)("button", {
|
|
141
|
+
type: "button",
|
|
142
|
+
className: clsx(AttachmentRail_module_css_default.arrow, AttachmentRail_module_css_default.arrowLeft),
|
|
143
|
+
"aria-label": labels.scrollLeft,
|
|
144
|
+
onClick: () => {
|
|
145
|
+
page(-1);
|
|
146
|
+
},
|
|
147
|
+
children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronLeftOutline14, {})
|
|
148
|
+
}),
|
|
149
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
150
|
+
ref: railRef,
|
|
151
|
+
className: AttachmentRail_module_css_default.rail,
|
|
152
|
+
role: "group",
|
|
153
|
+
"aria-label": labels.group,
|
|
154
|
+
onScroll: updateEdges,
|
|
155
|
+
children: items.map((item) => (0, react_jsx_runtime.jsx)("div", {
|
|
156
|
+
className: AttachmentRail_module_css_default.item,
|
|
157
|
+
children: renderItem(item)
|
|
158
|
+
}, item.id))
|
|
159
|
+
}),
|
|
160
|
+
edges.right && (0, react_jsx_runtime.jsx)("button", {
|
|
161
|
+
type: "button",
|
|
162
|
+
className: clsx(AttachmentRail_module_css_default.arrow, AttachmentRail_module_css_default.arrowRight),
|
|
163
|
+
"aria-label": labels.scrollRight,
|
|
164
|
+
onClick: () => {
|
|
165
|
+
page(1);
|
|
166
|
+
},
|
|
167
|
+
children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronRightOutline14, {})
|
|
168
|
+
})
|
|
169
|
+
]
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
//#endregion
|
|
173
|
+
//#region \0qilin-css:/home/runner/work/QiLin/QiLin/packages/client/ui-attachment/src/DropOverlay.module.css.mjs
|
|
174
|
+
const css$3 = ".KHNZRG_mask{z-index:1000;pointer-events:none;background-color:var(--qilin-alias-bg-mask-drop);backdrop-filter:blur(10px);justify-content:center;align-items:center;animation:.16s ease-out KHNZRG_fade-in;display:flex;position:fixed;inset:0}@keyframes KHNZRG_fade-in{0%{opacity:0}to{opacity:1}}@media (prefers-reduced-motion:reduce){.KHNZRG_mask{animation:none}}.KHNZRG_wrap{color:var(--qilin-alias-label-primary);text-align:center;flex-direction:column;align-items:center;margin-top:-3%;padding:0 40px;display:flex}.KHNZRG_illustration{width:115px;height:84px}.KHNZRG_title{font:var(--qilin-font-l-20);margin-top:16px}.KHNZRG_desc{font:var(--qilin-font-s-14);color:var(--qilin-alias-label-tertiary);white-space:pre-wrap;margin-top:16px}";
|
|
175
|
+
const tagId$3 = "@qilin-agent/client-ui-attachment/DropOverlay.module.css";
|
|
176
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
|
|
177
|
+
const tag = document.createElement("style");
|
|
178
|
+
tag.dataset.plugin = "@qilin-agent/client-ui-attachment";
|
|
179
|
+
tag.dataset.pluginCss = tagId$3;
|
|
180
|
+
tag.textContent = css$3;
|
|
181
|
+
document.head.appendChild(tag);
|
|
182
|
+
}
|
|
183
|
+
var DropOverlay_module_css_default = {
|
|
184
|
+
"desc": "KHNZRG_desc",
|
|
185
|
+
"fade-in": "KHNZRG_fade-in",
|
|
186
|
+
"illustration": "KHNZRG_illustration",
|
|
187
|
+
"mask": "KHNZRG_mask",
|
|
188
|
+
"title": "KHNZRG_title",
|
|
189
|
+
"wrap": "KHNZRG_wrap"
|
|
190
|
+
};
|
|
191
|
+
//#endregion
|
|
192
|
+
//#region lib/types/DropOverlay.js
|
|
193
|
+
/**
|
|
194
|
+
* Full-viewport invitation shown while a file drag is over the page
|
|
195
|
+
* (DeepSeek Chat's DragMask). Decoration only: `pointer-events: none` keeps
|
|
196
|
+
* drag targeting on the page below, so the owner's document-level listeners
|
|
197
|
+
* keep an accurate enter/leave count and own accept/reject. Rendered through
|
|
198
|
+
* a body portal for the same transformed-ancestor reason as the lightbox.
|
|
199
|
+
*
|
|
200
|
+
* @param props.disabled - drops are currently refused; renders the blocked
|
|
201
|
+
* illustration and drops the desc line.
|
|
202
|
+
* @param props.labels - resolved title and limits strings.
|
|
203
|
+
* @returns the overlay layer.
|
|
204
|
+
*/
|
|
205
|
+
function DropOverlay({ disabled, labels }) {
|
|
206
|
+
return (0, react_dom.createPortal)((0, react_jsx_runtime.jsx)("div", {
|
|
207
|
+
className: DropOverlay_module_css_default.mask,
|
|
208
|
+
role: "status",
|
|
209
|
+
children: (0, react_jsx_runtime.jsxs)("div", {
|
|
210
|
+
className: DropOverlay_module_css_default.wrap,
|
|
211
|
+
children: [
|
|
212
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
213
|
+
className: DropOverlay_module_css_default.illustration,
|
|
214
|
+
"aria-hidden": "true",
|
|
215
|
+
children: disabled ? (0, react_jsx_runtime.jsx)(UploadDisabledIllustration, {}) : (0, react_jsx_runtime.jsx)(UploadIllustration, {})
|
|
216
|
+
}),
|
|
217
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
218
|
+
className: DropOverlay_module_css_default.title,
|
|
219
|
+
children: labels.title
|
|
220
|
+
}),
|
|
221
|
+
!disabled && labels.desc !== void 0 && (0, react_jsx_runtime.jsx)("div", {
|
|
222
|
+
className: DropOverlay_module_css_default.desc,
|
|
223
|
+
children: labels.desc
|
|
224
|
+
})
|
|
225
|
+
]
|
|
226
|
+
})
|
|
227
|
+
}), document.body);
|
|
228
|
+
}
|
|
229
|
+
/** Tilted photo-and-note cards (DeepSeek Chat upload illustration). */
|
|
230
|
+
const UploadIllustration = () => (0, react_jsx_runtime.jsxs)("svg", {
|
|
231
|
+
width: "115",
|
|
232
|
+
height: "84",
|
|
233
|
+
viewBox: "0 0 115 84",
|
|
234
|
+
fill: "none",
|
|
235
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
236
|
+
children: [(0, react_jsx_runtime.jsxs)("g", {
|
|
237
|
+
clipPath: "url(#qilinDropOverlayClip)",
|
|
238
|
+
children: [
|
|
239
|
+
(0, react_jsx_runtime.jsx)("rect", {
|
|
240
|
+
y: "17.0742",
|
|
241
|
+
width: "44.1832",
|
|
242
|
+
height: "43.6431",
|
|
243
|
+
rx: "12",
|
|
244
|
+
transform: "rotate(-22.7338 0 17.0742)",
|
|
245
|
+
fill: "#9CE5ED"
|
|
246
|
+
}),
|
|
247
|
+
(0, react_jsx_runtime.jsx)("rect", {
|
|
248
|
+
x: "73.4043",
|
|
249
|
+
y: "8.54297",
|
|
250
|
+
width: "43.7267",
|
|
251
|
+
height: "50.5284",
|
|
252
|
+
rx: "8",
|
|
253
|
+
transform: "rotate(17.403 73.4043 8.54297)",
|
|
254
|
+
fill: "#679EFE"
|
|
255
|
+
}),
|
|
256
|
+
(0, react_jsx_runtime.jsx)("path", {
|
|
257
|
+
d: "M30.4917 28.1369L40.8865 33.4564L37.2232 34.9524L29.5302 31.0159L26.7919 39.2122L23.1285 40.7082L26.8287 29.6338L16.8967 24.5516L20.5601 23.0556L27.7902 26.7549L30.3639 19.052L34.0273 17.556L30.4917 28.1369Z",
|
|
258
|
+
fill: "white"
|
|
259
|
+
}),
|
|
260
|
+
(0, react_jsx_runtime.jsx)("path", {
|
|
261
|
+
d: "M77.5088 26.3047L101.057 33.7966",
|
|
262
|
+
stroke: "white",
|
|
263
|
+
strokeWidth: "3"
|
|
264
|
+
}),
|
|
265
|
+
(0, react_jsx_runtime.jsx)("path", {
|
|
266
|
+
d: "M72.2646 42.7871L86.3938 47.2823",
|
|
267
|
+
stroke: "white",
|
|
268
|
+
strokeWidth: "3"
|
|
269
|
+
}),
|
|
270
|
+
(0, react_jsx_runtime.jsx)("path", {
|
|
271
|
+
d: "M74.8867 34.5469L98.4353 42.0388",
|
|
272
|
+
stroke: "white",
|
|
273
|
+
strokeWidth: "3"
|
|
274
|
+
}),
|
|
275
|
+
(0, react_jsx_runtime.jsx)("rect", {
|
|
276
|
+
x: "31.583",
|
|
277
|
+
y: "38.6641",
|
|
278
|
+
width: "44.9157",
|
|
279
|
+
height: "44.3666",
|
|
280
|
+
rx: "12",
|
|
281
|
+
transform: "rotate(-0.134233 31.583 38.6641)",
|
|
282
|
+
fill: "#3964FE"
|
|
283
|
+
}),
|
|
284
|
+
(0, react_jsx_runtime.jsx)("path", {
|
|
285
|
+
d: "M38.9521 73.0337C39.6129 71.7086 41.7113 66.0937 43.5113 61.1663C44.1607 59.3885 46.7484 59.3923 47.4591 61.1465C48.9728 64.8828 50.7969 68.6922 51.9988 69.1925C54.2946 70.1482 57.9854 59.3573 68.0064 70.1801",
|
|
286
|
+
stroke: "white",
|
|
287
|
+
strokeWidth: "3"
|
|
288
|
+
}),
|
|
289
|
+
(0, react_jsx_runtime.jsx)("circle", {
|
|
290
|
+
cx: "60.6157",
|
|
291
|
+
cy: "52.247",
|
|
292
|
+
r: "4.38794",
|
|
293
|
+
transform: "rotate(22.5996 60.6157 52.247)",
|
|
294
|
+
fill: "white"
|
|
295
|
+
})
|
|
296
|
+
]
|
|
297
|
+
}), (0, react_jsx_runtime.jsx)("defs", { children: (0, react_jsx_runtime.jsx)("clipPath", {
|
|
298
|
+
id: "qilinDropOverlayClip",
|
|
299
|
+
children: (0, react_jsx_runtime.jsx)("rect", {
|
|
300
|
+
width: "115",
|
|
301
|
+
height: "84",
|
|
302
|
+
fill: "white"
|
|
303
|
+
})
|
|
304
|
+
}) })]
|
|
305
|
+
});
|
|
306
|
+
/** Greyed cards with a blocked badge (DeepSeek Chat disabled illustration). */
|
|
307
|
+
const UploadDisabledIllustration = () => (0, react_jsx_runtime.jsxs)("svg", {
|
|
308
|
+
width: "115",
|
|
309
|
+
height: "84",
|
|
310
|
+
viewBox: "0 0 115 84",
|
|
311
|
+
fill: "none",
|
|
312
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
313
|
+
children: [
|
|
314
|
+
(0, react_jsx_runtime.jsx)("path", {
|
|
315
|
+
d: "M29.6829 4.63701L11.0677 12.4368C4.95519 14.998 2.07624 22.0294 4.6374 28.1419L12.2285 46.259C14.7896 52.3715 21.8211 55.2505 27.9336 52.6893L46.5488 44.8895C52.6613 42.3283 55.5403 35.2969 52.9791 29.1844L45.388 11.0673C42.8269 4.9548 35.7954 2.07585 29.6829 4.63701Z",
|
|
316
|
+
fill: "#979DA6"
|
|
317
|
+
}),
|
|
318
|
+
(0, react_jsx_runtime.jsx)("path", {
|
|
319
|
+
d: "M30.4915 28.1375L40.8863 33.4569L37.223 34.9529L29.53 31.0165L26.7917 39.2128L23.1283 40.7088L26.8285 29.6344L16.8965 24.5522L20.5599 23.0562L27.79 26.7555L30.3637 19.0526L34.0271 17.5566L30.4915 28.1375Z",
|
|
320
|
+
fill: "white"
|
|
321
|
+
}),
|
|
322
|
+
(0, react_jsx_runtime.jsx)("path", {
|
|
323
|
+
d: "M107.496 19.2285L81.0381 10.9357C76.8221 9.61423 72.333 11.9607 71.0116 16.1768L60.6844 49.1246C59.363 53.3406 61.7095 57.8297 65.9255 59.1511L92.383 67.4439C96.599 68.7654 101.088 66.4189 102.41 62.2029L112.737 29.255C114.058 25.039 111.712 20.55 107.496 19.2285Z",
|
|
324
|
+
fill: "#979DA6"
|
|
325
|
+
}),
|
|
326
|
+
(0, react_jsx_runtime.jsx)("path", {
|
|
327
|
+
d: "M77.5088 26.3047L101.057 33.7967",
|
|
328
|
+
stroke: "white",
|
|
329
|
+
strokeWidth: "3"
|
|
330
|
+
}),
|
|
331
|
+
(0, react_jsx_runtime.jsx)("path", {
|
|
332
|
+
d: "M72.2646 42.7871L86.3938 47.2823",
|
|
333
|
+
stroke: "white",
|
|
334
|
+
strokeWidth: "3"
|
|
335
|
+
}),
|
|
336
|
+
(0, react_jsx_runtime.jsx)("path", {
|
|
337
|
+
d: "M74.8867 34.5469L98.4353 42.0388",
|
|
338
|
+
stroke: "white",
|
|
339
|
+
strokeWidth: "3"
|
|
340
|
+
}),
|
|
341
|
+
(0, react_jsx_runtime.jsx)("path", {
|
|
342
|
+
d: "M66.5798 30.1418L41.481 30.2006C33.5281 30.2193 27.0962 36.6815 27.1148 44.6343L27.172 69.0742C27.1907 77.0271 33.6529 83.459 41.6057 83.4404L66.7045 83.3816C74.6574 83.363 81.0894 76.9008 81.0707 68.9479L81.0135 44.5081C80.9949 36.5552 74.5327 30.1232 66.5798 30.1418Z",
|
|
343
|
+
fill: "#F59E0B"
|
|
344
|
+
}),
|
|
345
|
+
(0, react_jsx_runtime.jsx)("path", {
|
|
346
|
+
d: "M54 70.7969C61.732 70.7969 68 64.5289 68 56.7969C68 49.0649 61.732 42.7969 54 42.7969C46.268 42.7969 40 49.0649 40 56.7969C40 64.5289 46.268 70.7969 54 70.7969Z",
|
|
347
|
+
stroke: "white",
|
|
348
|
+
strokeWidth: "3.5"
|
|
349
|
+
}),
|
|
350
|
+
(0, react_jsx_runtime.jsx)("path", {
|
|
351
|
+
d: "M44 46.7969L64 66.7969",
|
|
352
|
+
stroke: "white",
|
|
353
|
+
strokeWidth: "3.5",
|
|
354
|
+
strokeLinecap: "round"
|
|
355
|
+
})
|
|
356
|
+
]
|
|
357
|
+
});
|
|
358
|
+
//#endregion
|
|
359
|
+
//#region \0qilin-css:/home/runner/work/QiLin/QiLin/packages/client/ui-attachment/src/FileCard.module.css.mjs
|
|
360
|
+
const css$2 = ".LBRGAa_card{border:.5px solid var(--qilin-alias-border-l2,#0000001f);background:var(--qilin-specific-input-major,transparent);box-sizing:border-box;text-align:left;border-radius:16px;align-items:center;gap:10px;width:240px;height:64px;padding:0 12px;display:inline-flex;position:relative}.LBRGAa_failed{border-color:var(--qilin-alias-state-error-primary,#d54941)}.LBRGAa_icon{flex:none;justify-content:center;align-items:center;width:28px;height:28px;display:inline-flex}.LBRGAa_spinner{corner-shape:round;border:2px solid;border-top-color:#0000;border-radius:50%;width:20px;height:20px;animation:.8s linear infinite LBRGAa_file-card-spin}@keyframes LBRGAa_file-card-spin{to{transform:rotate(360deg)}}.LBRGAa_body{flex-direction:column;flex:1;min-width:0;padding:8px 0;display:flex}.LBRGAa_retry{color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;padding:0}.LBRGAa_name{white-space:nowrap;text-overflow:ellipsis;color:var(--qilin-alias-label-primary);font-size:14px;font-weight:500;line-height:22px;overflow:hidden}.LBRGAa_meta{white-space:nowrap;text-overflow:ellipsis;color:var(--qilin-alias-label-tertiary,#00000073);font-size:12px;line-height:15px;overflow:hidden}.LBRGAa_metaFailed{color:var(--qilin-alias-state-error-primary,#d54941)}.LBRGAa_remove{corner-shape:round;background:var(--qilin-alias-button-contrast-fill,#000000b8);width:18px;height:18px;color:var(--qilin-alias-label-primary-inverted,#fff);opacity:0;cursor:pointer;border:none;border-radius:50%;justify-content:center;align-items:center;padding:0;transition:opacity .2s ease-in-out;display:inline-flex;position:absolute;top:6px;right:6px}.LBRGAa_card:hover .LBRGAa_remove,.LBRGAa_remove:focus-visible{opacity:1}@media (pointer:coarse){.LBRGAa_remove{opacity:1}}@media (prefers-reduced-motion:reduce){.LBRGAa_remove{transition:none}}.LBRGAa_card:hover .LBRGAa_name,.LBRGAa_card:focus-within .LBRGAa_name{padding-right:18px}.LBRGAa_removeFailed{background:var(--qilin-alias-state-error-primary,#d54941);color:#fff;opacity:1}.LBRGAa_progressTrack{background:var(--qilin-alias-fill-tertiary,#00000014);border-radius:1px;height:2px;position:absolute;bottom:5px;left:12px;right:12px;overflow:hidden}.LBRGAa_progressBar{border-radius:inherit;background:var(--qilin-alias-brand-primary,#4d6bfe);width:35%;height:100%;animation:1.2s ease-in-out infinite alternate LBRGAa_file-card-progress;display:block}.LBRGAa_progressBar[style]{animation:none}@keyframes LBRGAa_file-card-progress{0%{transform:translate(-70%)}to{transform:translate(220%)}}@media (pointer:coarse){.LBRGAa_remove{opacity:1}}";
|
|
361
|
+
const tagId$2 = "@qilin-agent/client-ui-attachment/FileCard.module.css";
|
|
362
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
|
|
363
|
+
const tag = document.createElement("style");
|
|
364
|
+
tag.dataset.plugin = "@qilin-agent/client-ui-attachment";
|
|
365
|
+
tag.dataset.pluginCss = tagId$2;
|
|
366
|
+
tag.textContent = css$2;
|
|
367
|
+
document.head.appendChild(tag);
|
|
368
|
+
}
|
|
369
|
+
var FileCard_module_css_default = {
|
|
370
|
+
"body": "LBRGAa_body",
|
|
371
|
+
"card": "LBRGAa_card",
|
|
372
|
+
"failed": "LBRGAa_failed",
|
|
373
|
+
"file-card-progress": "LBRGAa_file-card-progress",
|
|
374
|
+
"file-card-spin": "LBRGAa_file-card-spin",
|
|
375
|
+
"icon": "LBRGAa_icon",
|
|
376
|
+
"meta": "LBRGAa_meta",
|
|
377
|
+
"metaFailed": "LBRGAa_metaFailed",
|
|
378
|
+
"name": "LBRGAa_name",
|
|
379
|
+
"progressBar": "LBRGAa_progressBar",
|
|
380
|
+
"progressTrack": "LBRGAa_progressTrack",
|
|
381
|
+
"remove": "LBRGAa_remove",
|
|
382
|
+
"removeFailed": "LBRGAa_removeFailed",
|
|
383
|
+
"retry": "LBRGAa_retry",
|
|
384
|
+
"spinner": "LBRGAa_spinner"
|
|
385
|
+
};
|
|
386
|
+
//#endregion
|
|
387
|
+
//#region lib/types/FileCard.js
|
|
388
|
+
/** One pending file card: type glyph, name, size or upload status, remove, retry. */
|
|
389
|
+
function FileCard({ name, bytes, state, progress, labels, onRemove, onRetry }) {
|
|
390
|
+
const extension = (0, _qilin_agent_client_ui_primitives.fileExtension)(name).toUpperCase().slice(0, 8);
|
|
391
|
+
const meta = state === "uploading" ? labels.uploading : state === "error" ? labels.failed : [extension, (0, _qilin_agent_client_ui_primitives.fileSizeText)(bytes)].filter((part) => part !== "").join(" ");
|
|
392
|
+
const retryable = state === "error";
|
|
393
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
394
|
+
className: `${FileCard_module_css_default.card}${retryable ? ` ${FileCard_module_css_default.failed}` : ""}`,
|
|
395
|
+
title: name,
|
|
396
|
+
children: [
|
|
397
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
398
|
+
className: FileCard_module_css_default.icon,
|
|
399
|
+
"aria-hidden": true,
|
|
400
|
+
children: state === "uploading" ? (0, react_jsx_runtime.jsx)("span", { className: FileCard_module_css_default.spinner }) : (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.FileTypeIcon, { path: name })
|
|
401
|
+
}),
|
|
402
|
+
retryable ? (0, react_jsx_runtime.jsxs)("button", {
|
|
403
|
+
type: "button",
|
|
404
|
+
className: `${FileCard_module_css_default.body} ${FileCard_module_css_default.retry}`,
|
|
405
|
+
"aria-label": labels.retry,
|
|
406
|
+
onClick: onRetry,
|
|
407
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
408
|
+
className: FileCard_module_css_default.name,
|
|
409
|
+
children: name
|
|
410
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
411
|
+
className: `${FileCard_module_css_default.meta} ${FileCard_module_css_default.metaFailed}`,
|
|
412
|
+
children: meta
|
|
413
|
+
})]
|
|
414
|
+
}) : (0, react_jsx_runtime.jsxs)("span", {
|
|
415
|
+
className: FileCard_module_css_default.body,
|
|
416
|
+
"aria-label": labels.label,
|
|
417
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
418
|
+
className: FileCard_module_css_default.name,
|
|
419
|
+
children: name
|
|
420
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
421
|
+
className: FileCard_module_css_default.meta,
|
|
422
|
+
children: meta
|
|
423
|
+
})]
|
|
424
|
+
}),
|
|
425
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
426
|
+
type: "button",
|
|
427
|
+
className: retryable ? `${FileCard_module_css_default.remove} ${FileCard_module_css_default.removeFailed}` : FileCard_module_css_default.remove,
|
|
428
|
+
"aria-label": labels.remove,
|
|
429
|
+
onClick: onRemove,
|
|
430
|
+
children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconCloseFill14, { size: 12 })
|
|
431
|
+
}),
|
|
432
|
+
state === "uploading" && (0, react_jsx_runtime.jsx)("span", {
|
|
433
|
+
className: FileCard_module_css_default.progressTrack,
|
|
434
|
+
"aria-hidden": true,
|
|
435
|
+
children: (0, react_jsx_runtime.jsx)("span", {
|
|
436
|
+
className: FileCard_module_css_default.progressBar,
|
|
437
|
+
style: progress === void 0 ? void 0 : { width: `${String(Math.min(1, Math.max(0, progress)) * 100)}%` }
|
|
438
|
+
})
|
|
439
|
+
})
|
|
440
|
+
]
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
//#endregion
|
|
444
|
+
//#region lib/types/client/labels.js
|
|
445
|
+
/**
|
|
446
|
+
* Resolve original-image lightbox strings from the conversation namespace.
|
|
447
|
+
* @param t - conversation namespace translator.
|
|
448
|
+
* @returns translated lightbox labels.
|
|
449
|
+
*/
|
|
450
|
+
function lightboxLabels(t) {
|
|
451
|
+
return {
|
|
452
|
+
dialog: t("image.preview"),
|
|
453
|
+
close: t("image.closePreview")
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Resolve historical message-image strings from the conversation namespace.
|
|
458
|
+
* @param t - conversation namespace translator.
|
|
459
|
+
* @returns translated message-image labels.
|
|
460
|
+
*/
|
|
461
|
+
function messageImageLabels(t) {
|
|
462
|
+
return {
|
|
463
|
+
image: t("image.label"),
|
|
464
|
+
open: t("image.openOriginal"),
|
|
465
|
+
openNamed: (label) => t("image.openOriginalLabel", { label }),
|
|
466
|
+
loading: t("image.loading"),
|
|
467
|
+
loadFailed: t("image.loadFailed"),
|
|
468
|
+
lightbox: lightboxLabels(t)
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Resolve the document-level drop invitation and its optional limits line.
|
|
473
|
+
* @param t - conversation namespace translator.
|
|
474
|
+
* @param accepting - whether the composer can accept dropped files.
|
|
475
|
+
* @param limits - optional translated count and size values.
|
|
476
|
+
* @returns translated drop-overlay labels.
|
|
477
|
+
*/
|
|
478
|
+
function dropOverlayLabels(t, accepting, limits) {
|
|
479
|
+
if (!accepting) return { title: t("attachment.dropBlocked") };
|
|
480
|
+
return {
|
|
481
|
+
title: t("attachment.dropTitle"),
|
|
482
|
+
desc: limits === void 0 ? void 0 : t("attachment.dropDesc", limits)
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Resolve pending-file card strings from the conversation namespace.
|
|
487
|
+
* @param t - conversation namespace translator.
|
|
488
|
+
* @param name - browser file name interpolated into remove/retry labels.
|
|
489
|
+
* @returns translated file-card labels.
|
|
490
|
+
*/
|
|
491
|
+
function fileCardLabels(t, name) {
|
|
492
|
+
return {
|
|
493
|
+
label: t("file.pending"),
|
|
494
|
+
remove: t("file.remove", { name }),
|
|
495
|
+
uploading: t("file.uploading"),
|
|
496
|
+
failed: t("file.uploadFailed"),
|
|
497
|
+
retry: t("file.retry", { name })
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Resolve the mixed draft-attachment rail strings from the conversation namespace.
|
|
502
|
+
* @param t - conversation namespace translator.
|
|
503
|
+
* @returns translated attachment-rail labels.
|
|
504
|
+
*/
|
|
505
|
+
function attachmentRailLabels(t) {
|
|
506
|
+
return {
|
|
507
|
+
group: t("attachment.pending"),
|
|
508
|
+
scrollLeft: t("attachment.scrollLeft"),
|
|
509
|
+
scrollRight: t("attachment.scrollRight")
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
//#endregion
|
|
513
|
+
//#region lib/types/client/drop-events.js
|
|
514
|
+
/**
|
|
515
|
+
* Install one attachment view's file-drop listeners.
|
|
516
|
+
* @param canAcceptDrop - whether this view accepts the dropped files.
|
|
517
|
+
* @param onAddFiles - attachment intake callback.
|
|
518
|
+
* @param dragDepth - the view's retained nested-drag counter.
|
|
519
|
+
* @param setDragActive - publish whether a file drag is active.
|
|
520
|
+
* @returns cleanup for exactly these listeners.
|
|
521
|
+
*/
|
|
522
|
+
function installDocumentDropEvents(canAcceptDrop, onAddFiles, dragDepth, setDragActive) {
|
|
523
|
+
const fileTransfer = (event) => {
|
|
524
|
+
const dataTransfer = event.dataTransfer;
|
|
525
|
+
if (dataTransfer === null || !dataTransfer.types.includes("Files")) return null;
|
|
526
|
+
return dataTransfer;
|
|
527
|
+
};
|
|
528
|
+
const reset = () => {
|
|
529
|
+
dragDepth.current = 0;
|
|
530
|
+
setDragActive(false);
|
|
531
|
+
};
|
|
532
|
+
const onDragEnter = (event) => {
|
|
533
|
+
if (fileTransfer(event) === null) return;
|
|
534
|
+
event.preventDefault();
|
|
535
|
+
dragDepth.current += 1;
|
|
536
|
+
setDragActive(true);
|
|
537
|
+
};
|
|
538
|
+
const onDragOver = (event) => {
|
|
539
|
+
const dataTransfer = fileTransfer(event);
|
|
540
|
+
if (dataTransfer === null) return;
|
|
541
|
+
event.preventDefault();
|
|
542
|
+
dataTransfer.dropEffect = canAcceptDrop ? "copy" : "none";
|
|
543
|
+
};
|
|
544
|
+
const onDragLeave = (event) => {
|
|
545
|
+
if (fileTransfer(event) === null) return;
|
|
546
|
+
dragDepth.current = Math.max(0, dragDepth.current - 1);
|
|
547
|
+
if (dragDepth.current === 0) setDragActive(false);
|
|
548
|
+
const leftViewport = event.clientX <= 0 || event.clientY <= 0 || event.clientX >= window.innerWidth || event.clientY >= window.innerHeight;
|
|
549
|
+
if ((event.target === document.documentElement || event.target === document.body) && leftViewport) reset();
|
|
550
|
+
};
|
|
551
|
+
const onDrop = (event) => {
|
|
552
|
+
const dataTransfer = fileTransfer(event);
|
|
553
|
+
if (dataTransfer === null) return;
|
|
554
|
+
event.preventDefault();
|
|
555
|
+
reset();
|
|
556
|
+
if (canAcceptDrop) onAddFiles([...dataTransfer.files]);
|
|
557
|
+
};
|
|
558
|
+
document.addEventListener("dragenter", onDragEnter);
|
|
559
|
+
document.addEventListener("dragover", onDragOver);
|
|
560
|
+
document.addEventListener("dragleave", onDragLeave);
|
|
561
|
+
document.addEventListener("drop", onDrop);
|
|
562
|
+
window.addEventListener("dragend", reset);
|
|
563
|
+
return () => {
|
|
564
|
+
document.removeEventListener("dragenter", onDragEnter);
|
|
565
|
+
document.removeEventListener("dragover", onDragOver);
|
|
566
|
+
document.removeEventListener("dragleave", onDragLeave);
|
|
567
|
+
document.removeEventListener("drop", onDrop);
|
|
568
|
+
window.removeEventListener("dragend", reset);
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
//#endregion
|
|
572
|
+
//#region \0qilin-css:/home/runner/work/QiLin/QiLin/packages/client/ui-attachment/src/client/ComposerAttachments.module.css.mjs
|
|
573
|
+
const css$1 = ".z3i06q_rail{min-width:0;margin-bottom:-6px;padding:2px 10px 0}.z3i06q_imageItem{width:64px;height:64px;position:relative}.z3i06q_thumbnail{border:.5px solid var(--qilin-alias-border-l2-darkmode-thin);background:var(--qilin-alias-interactive-bg-hover);cursor:zoom-in;border-radius:16px;width:64px;height:64px;padding:0;overflow:hidden}.z3i06q_thumbnail img{object-fit:cover;width:100%;height:100%;display:block}.z3i06q_remove{z-index:1;corner-shape:round;background:var(--qilin-alias-button-contrast-fill);width:18px;height:18px;color:var(--qilin-alias-label-primary-inverted);cursor:pointer;opacity:0;border:none;border-radius:50%;place-items:center;padding:0;transition:opacity .2s ease-in-out;display:grid;position:absolute;top:4px;right:4px}.z3i06q_imageItem:hover .z3i06q_remove,.z3i06q_remove:focus-visible{opacity:1}@media (pointer:coarse){.z3i06q_remove{opacity:1}}@media (prefers-reduced-motion:reduce){.z3i06q_remove{transition:none}}";
|
|
574
|
+
const tagId$1 = "@qilin-agent/client-ui-attachment/ComposerAttachments.module.css";
|
|
575
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
576
|
+
const tag = document.createElement("style");
|
|
577
|
+
tag.dataset.plugin = "@qilin-agent/client-ui-attachment";
|
|
578
|
+
tag.dataset.pluginCss = tagId$1;
|
|
579
|
+
tag.textContent = css$1;
|
|
580
|
+
document.head.appendChild(tag);
|
|
581
|
+
}
|
|
582
|
+
var ComposerAttachments_module_css_default = {
|
|
583
|
+
"imageItem": "z3i06q_imageItem",
|
|
584
|
+
"rail": "z3i06q_rail",
|
|
585
|
+
"remove": "z3i06q_remove",
|
|
586
|
+
"thumbnail": "z3i06q_thumbnail"
|
|
587
|
+
};
|
|
588
|
+
//#endregion
|
|
589
|
+
//#region lib/types/client/ComposerAttachments.js
|
|
590
|
+
/** Draft image previews, pending-file cards, drop target, and original-image preview. */
|
|
591
|
+
function ComposerAttachments({ attachments, canAcceptDrop, onAddFiles, onRemoveAttachment, uploads, onRetryFile, dropLimits, t }) {
|
|
592
|
+
const [preview, setPreview] = (0, react.useState)(null);
|
|
593
|
+
const [dragActive, setDragActive] = (0, react.useState)(false);
|
|
594
|
+
const dragDepth = (0, react.useRef)(0);
|
|
595
|
+
const closePreview = (0, react.useCallback)(() => {
|
|
596
|
+
setPreview(null);
|
|
597
|
+
}, []);
|
|
598
|
+
(0, react.useEffect)(() => {
|
|
599
|
+
if (preview !== null && !attachments.some((attachment) => attachment.id === preview.id)) setPreview(null);
|
|
600
|
+
}, [attachments, preview]);
|
|
601
|
+
(0, react.useEffect)(() => {
|
|
602
|
+
return installDocumentDropEvents(canAcceptDrop, onAddFiles, dragDepth, setDragActive);
|
|
603
|
+
}, [canAcceptDrop, onAddFiles]);
|
|
604
|
+
const railItems = (0, react.useMemo)(() => attachments.map((attachment) => ({
|
|
605
|
+
id: attachment.id,
|
|
606
|
+
attachment
|
|
607
|
+
})), [attachments]);
|
|
608
|
+
return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
609
|
+
dragActive && (0, react_jsx_runtime.jsx)(DropOverlay, {
|
|
610
|
+
disabled: !canAcceptDrop,
|
|
611
|
+
labels: dropOverlayLabels(t, canAcceptDrop, dropLimits)
|
|
612
|
+
}),
|
|
613
|
+
railItems.length > 0 && (0, react_jsx_runtime.jsx)("div", {
|
|
614
|
+
className: ComposerAttachments_module_css_default.rail,
|
|
615
|
+
children: (0, react_jsx_runtime.jsx)(AttachmentRail, {
|
|
616
|
+
items: railItems,
|
|
617
|
+
labels: attachmentRailLabels(t),
|
|
618
|
+
renderItem: (item) => {
|
|
619
|
+
const attachment = item.attachment;
|
|
620
|
+
if (attachment.kind === "file") {
|
|
621
|
+
const upload = uploads[attachment.id];
|
|
622
|
+
return (0, react_jsx_runtime.jsx)(FileCard, {
|
|
623
|
+
name: attachment.file.name || t("file.label"),
|
|
624
|
+
bytes: attachment.file.size,
|
|
625
|
+
state: upload === void 0 || upload.status === "uploading" ? "uploading" : upload.status === "ready" ? "ready" : "error",
|
|
626
|
+
...upload?.status === "uploading" && upload.total !== void 0 && upload.total > 0 ? { progress: upload.loaded / upload.total } : {},
|
|
627
|
+
labels: fileCardLabels(t, attachment.file.name),
|
|
628
|
+
onRemove: () => {
|
|
629
|
+
onRemoveAttachment(attachment.id);
|
|
630
|
+
},
|
|
631
|
+
onRetry: () => {
|
|
632
|
+
onRetryFile(attachment.id);
|
|
633
|
+
}
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
637
|
+
className: ComposerAttachments_module_css_default.imageItem,
|
|
638
|
+
children: [(0, react_jsx_runtime.jsx)("button", {
|
|
639
|
+
type: "button",
|
|
640
|
+
className: ComposerAttachments_module_css_default.thumbnail,
|
|
641
|
+
title: t("image.openOriginal"),
|
|
642
|
+
onClick: () => {
|
|
643
|
+
setPreview(attachment);
|
|
644
|
+
},
|
|
645
|
+
children: (0, react_jsx_runtime.jsx)("img", {
|
|
646
|
+
src: attachment.previewUrl,
|
|
647
|
+
alt: attachment.file.name || t("image.pending")
|
|
648
|
+
})
|
|
649
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
650
|
+
type: "button",
|
|
651
|
+
className: ComposerAttachments_module_css_default.remove,
|
|
652
|
+
"aria-label": t("image.remove", { name: attachment.file.name }),
|
|
653
|
+
onClick: () => {
|
|
654
|
+
onRemoveAttachment(attachment.id);
|
|
655
|
+
},
|
|
656
|
+
children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconCloseFill14, { size: 12 })
|
|
657
|
+
})]
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
})
|
|
661
|
+
}),
|
|
662
|
+
preview !== null && (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.ImageLightbox, {
|
|
663
|
+
src: preview.previewUrl,
|
|
664
|
+
alt: preview.file.name || t("image.original"),
|
|
665
|
+
labels: lightboxLabels(t),
|
|
666
|
+
onClose: closePreview
|
|
667
|
+
})
|
|
668
|
+
] });
|
|
669
|
+
}
|
|
670
|
+
//#endregion
|
|
671
|
+
//#region \0qilin-css:/home/runner/work/QiLin/QiLin/packages/client/ui-attachment/src/MessageImage.module.css.mjs
|
|
672
|
+
const css = ".AdZSYG_gallery{flex-wrap:wrap;gap:10px;max-width:100%;display:flex}.AdZSYG_gallery[data-align=end]{justify-content:flex-end;align-self:flex-end}.AdZSYG_gallery[data-align=start]{justify-content:flex-start;align-self:flex-start}.AdZSYG_frame{border:.5px solid var(--qilin-alias-border-l2-darkmode-thin);background:var(--qilin-alias-interactive-bg-hover);cursor:zoom-in;border-radius:16px;flex:none;place-items:center;min-width:44px;min-height:44px;padding:0;display:grid;overflow:hidden}.AdZSYG_frame[data-variant=tile]{width:64px;min-width:64px;height:64px;min-height:64px}.AdZSYG_frame img{object-fit:cover;width:100%;height:100%;display:block}.AdZSYG_loading,.AdZSYG_error{color:var(--qilin-alias-label-tertiary);font-size:12px;line-height:18px}.AdZSYG_error{border:.5px solid var(--qilin-alias-border-l2-darkmode-thin);background:var(--qilin-alias-interactive-bg-hover-danger);cursor:pointer;border-radius:10px;max-width:240px;padding:10px 12px}.AdZSYG_error[data-variant=tile]{border-radius:16px;width:64px;height:64px;padding:4px;overflow:hidden}.AdZSYG_frame[data-variant=thumbnail],.AdZSYG_error[data-variant=thumbnail]{box-sizing:border-box;border-radius:8px;place-items:center;width:48px;min-width:48px;height:48px;min-height:48px;padding:2px;display:grid;overflow:hidden}.AdZSYG_frame[data-variant=thumbnail] img{object-fit:contain}.AdZSYG_spinner{animation:.9s linear infinite AdZSYG_spinner-rotate}@keyframes AdZSYG_spinner-rotate{to{transform:rotate(360deg)}}@media (prefers-reduced-motion:reduce){.AdZSYG_spinner{animation:none}}.AdZSYG_frame:focus-visible,.AdZSYG_error:focus-visible{outline:var(--qilin-focus-ring-width) solid var(--qilin-focus-ring-color,var(--qilin-alias-state-business-primary));outline-offset:2px}";
|
|
673
|
+
const tagId = "@qilin-agent/client-ui-attachment/MessageImage.module.css";
|
|
674
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
675
|
+
const tag = document.createElement("style");
|
|
676
|
+
tag.dataset.plugin = "@qilin-agent/client-ui-attachment";
|
|
677
|
+
tag.dataset.pluginCss = tagId;
|
|
678
|
+
tag.textContent = css;
|
|
679
|
+
document.head.appendChild(tag);
|
|
680
|
+
}
|
|
681
|
+
var MessageImage_module_css_default = {
|
|
682
|
+
"error": "AdZSYG_error",
|
|
683
|
+
"frame": "AdZSYG_frame",
|
|
684
|
+
"gallery": "AdZSYG_gallery",
|
|
685
|
+
"loading": "AdZSYG_loading",
|
|
686
|
+
"spinner": "AdZSYG_spinner",
|
|
687
|
+
"spinner-rotate": "AdZSYG_spinner-rotate"
|
|
688
|
+
};
|
|
689
|
+
//#endregion
|
|
690
|
+
//#region lib/types/MessageImage.js
|
|
691
|
+
/** Display box for a lone image (DeepSeek Chat rule): long edge 240px with
|
|
692
|
+
* the rendered aspect ratio clamped to [0.25, 4] — the overflow is cropped by
|
|
693
|
+
* `object-fit: cover` — and never upscaled past the image's natural size. The
|
|
694
|
+
* crop anchor keeps the top of very tall images and the left of very wide
|
|
695
|
+
* ones, where the informative content usually starts. */
|
|
696
|
+
function singleFit(dimensions) {
|
|
697
|
+
const natural = dimensions.width / dimensions.height;
|
|
698
|
+
const ratio = Math.min(4, Math.max(.25, natural));
|
|
699
|
+
const box = ratio >= 1 ? {
|
|
700
|
+
width: 240,
|
|
701
|
+
height: 240 / ratio
|
|
702
|
+
} : {
|
|
703
|
+
width: 240 * ratio,
|
|
704
|
+
height: 240
|
|
705
|
+
};
|
|
706
|
+
const scale = Math.min(1, dimensions.width / box.width, dimensions.height / box.height);
|
|
707
|
+
return {
|
|
708
|
+
width: Math.max(1, Math.round(box.width * scale)),
|
|
709
|
+
height: Math.max(1, Math.round(box.height * scale)),
|
|
710
|
+
objectPosition: natural < .25 ? "center top" : natural > 4 ? "left center" : "center"
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
/** Intrinsic dimensions of one gallery entry; a preview's stay unknown until its intake probe resolved. */
|
|
714
|
+
function dimensionsOf(image) {
|
|
715
|
+
if ("attachment" in image) return image.attachment;
|
|
716
|
+
return image.preview.width !== void 0 && image.preview.height !== void 0 ? {
|
|
717
|
+
width: image.preview.width,
|
|
718
|
+
height: image.preview.height
|
|
719
|
+
} : void 0;
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* Compact history renderer with retryable loading and click-to-open original
|
|
723
|
+
* preview. A lone image renders at its `singleFit` size; an image among
|
|
724
|
+
* several renders as a fixed 64px square tile. The preview arm displays its
|
|
725
|
+
* local URL directly — no loader round-trip, no failure/retry surface.
|
|
726
|
+
* List thumbnails use status icons with localized tooltips and accessible names.
|
|
727
|
+
*
|
|
728
|
+
* @param props.image - the durable reference to load, or the local preview to display.
|
|
729
|
+
* @param props.load - session-authorized URL loader for the durable arm.
|
|
730
|
+
* @param props.variant - lone image, cropped gallery tile, or uncropped list thumbnail.
|
|
731
|
+
* @param props.labels - resolved strings (tooltip, loading, retry, lightbox).
|
|
732
|
+
* @returns the bounded thumbnail button, or the retry control on failure.
|
|
733
|
+
*/
|
|
734
|
+
function MessageImage({ image, load, variant, labels }) {
|
|
735
|
+
const preview = "preview" in image ? image.preview : void 0;
|
|
736
|
+
const attachment = "attachment" in image ? image.attachment : void 0;
|
|
737
|
+
const [loaded, setLoaded] = (0, react.useState)(() => attachment === void 0 ? null : load.peek?.(attachment) ?? null);
|
|
738
|
+
const [error, setError] = (0, react.useState)(false);
|
|
739
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
740
|
+
const [attempt, setAttempt] = (0, react.useState)(0);
|
|
741
|
+
const request = (0, react.useCallback)(() => {
|
|
742
|
+
setAttempt((a) => a + 1);
|
|
743
|
+
}, []);
|
|
744
|
+
const close = (0, react.useCallback)(() => {
|
|
745
|
+
setOpen(false);
|
|
746
|
+
}, []);
|
|
747
|
+
const dimensions = (0, react.useMemo)(() => dimensionsOf(image), [image]);
|
|
748
|
+
const fit = (0, react.useMemo)(() => {
|
|
749
|
+
if (variant !== "single") return void 0;
|
|
750
|
+
return dimensions === void 0 ? {
|
|
751
|
+
width: 240,
|
|
752
|
+
height: 240,
|
|
753
|
+
objectPosition: "center"
|
|
754
|
+
} : singleFit(dimensions);
|
|
755
|
+
}, [dimensions, variant]);
|
|
756
|
+
(0, react.useEffect)(() => {
|
|
757
|
+
if (attachment === void 0) return;
|
|
758
|
+
let live = true;
|
|
759
|
+
setError(false);
|
|
760
|
+
setLoaded(load.peek?.(attachment) ?? null);
|
|
761
|
+
load(attachment).then((url) => {
|
|
762
|
+
if (live) setLoaded(url);
|
|
763
|
+
}).catch(() => {
|
|
764
|
+
if (live) setError(true);
|
|
765
|
+
});
|
|
766
|
+
return () => {
|
|
767
|
+
live = false;
|
|
768
|
+
};
|
|
769
|
+
}, [
|
|
770
|
+
attachment,
|
|
771
|
+
load,
|
|
772
|
+
attempt
|
|
773
|
+
]);
|
|
774
|
+
const src = preview?.url ?? loaded;
|
|
775
|
+
const label = ("attachment" in image ? image.label : void 0) ?? preview?.name ?? attachment?.name ?? labels.image;
|
|
776
|
+
const loadingThumbnail = variant === "thumbnail" && src === null;
|
|
777
|
+
if (error) return (0, react_jsx_runtime.jsx)("button", {
|
|
778
|
+
type: "button",
|
|
779
|
+
className: MessageImage_module_css_default.error,
|
|
780
|
+
"data-variant": variant,
|
|
781
|
+
title: variant === "thumbnail" ? labels.loadFailed : void 0,
|
|
782
|
+
"aria-label": variant === "thumbnail" ? labels.loadFailed : void 0,
|
|
783
|
+
onClick: request,
|
|
784
|
+
children: variant === "thumbnail" ? (0, react_jsx_runtime.jsx)("span", {
|
|
785
|
+
"aria-hidden": "true",
|
|
786
|
+
children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconRefreshOutline16, {})
|
|
787
|
+
}) : labels.loadFailed
|
|
788
|
+
});
|
|
789
|
+
return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("button", {
|
|
790
|
+
type: "button",
|
|
791
|
+
className: MessageImage_module_css_default.frame,
|
|
792
|
+
"data-variant": variant,
|
|
793
|
+
style: fit === void 0 ? void 0 : {
|
|
794
|
+
width: fit.width,
|
|
795
|
+
height: fit.height
|
|
796
|
+
},
|
|
797
|
+
title: loadingThumbnail ? labels.loading : labels.open,
|
|
798
|
+
"aria-label": loadingThumbnail ? labels.loading : labels.openNamed(label),
|
|
799
|
+
"aria-busy": loadingThumbnail || void 0,
|
|
800
|
+
onClick: () => {
|
|
801
|
+
if (src !== null) setOpen(true);
|
|
802
|
+
},
|
|
803
|
+
children: src === null ? (0, react_jsx_runtime.jsx)("span", {
|
|
804
|
+
className: MessageImage_module_css_default.loading,
|
|
805
|
+
"aria-hidden": loadingThumbnail || void 0,
|
|
806
|
+
children: loadingThumbnail ? (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconLoadingOutline16, { className: MessageImage_module_css_default.spinner }) : labels.loading
|
|
807
|
+
}) : (0, react_jsx_runtime.jsx)("img", {
|
|
808
|
+
src,
|
|
809
|
+
alt: label,
|
|
810
|
+
style: fit === void 0 ? void 0 : { objectPosition: fit.objectPosition }
|
|
811
|
+
})
|
|
812
|
+
}), open && src !== null && (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.ImageLightbox, {
|
|
813
|
+
src,
|
|
814
|
+
alt: label,
|
|
815
|
+
labels: labels.lightbox,
|
|
816
|
+
onClose: close
|
|
817
|
+
})] });
|
|
818
|
+
}
|
|
819
|
+
/** Wrapping image group shared by user and assistant history: a lone image
|
|
820
|
+
* renders large unless its owner requests compact tiles or contained list thumbnails. */
|
|
821
|
+
function ImageGallery({ images, load, align, compact = false, thumbnail = false, labels }) {
|
|
822
|
+
if (images.length === 0) return null;
|
|
823
|
+
const variant = thumbnail ? "thumbnail" : compact || images.length > 1 ? "tile" : "single";
|
|
824
|
+
return (0, react_jsx_runtime.jsx)("div", {
|
|
825
|
+
className: MessageImage_module_css_default.gallery,
|
|
826
|
+
"data-align": align,
|
|
827
|
+
children: images.map((image, index) => (0, react_jsx_runtime.jsx)(MessageImage, {
|
|
828
|
+
image,
|
|
829
|
+
load,
|
|
830
|
+
variant,
|
|
831
|
+
labels
|
|
832
|
+
}, `${"attachment" in image ? image.attachment.attachmentId : image.preview.url}:${index}`))
|
|
833
|
+
});
|
|
834
|
+
}
|
|
835
|
+
//#endregion
|
|
836
|
+
//#region lib/types/client/MessageImages.js
|
|
837
|
+
/** Historical message-image slot entry. */
|
|
838
|
+
function MessageImages({ images, loadImage, align, compact = false, thumbnail = false, t }) {
|
|
839
|
+
return (0, react_jsx_runtime.jsx)(ImageGallery, {
|
|
840
|
+
images,
|
|
841
|
+
load: loadImage,
|
|
842
|
+
align,
|
|
843
|
+
compact,
|
|
844
|
+
thumbnail,
|
|
845
|
+
labels: messageImageLabels(t)
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
//#endregion
|
|
849
|
+
//#region lib/types/client/index.js
|
|
850
|
+
/** Slot registry required by this presentation plugin. */
|
|
851
|
+
const inject = ["slots"];
|
|
852
|
+
/** Register attachment presentation without exporting React components as package values. */
|
|
853
|
+
function apply(ctx) {
|
|
854
|
+
ctx.slots.inject("conversation.input.attachments", () => ctx.slots.register({
|
|
855
|
+
name: "conversation.input.attachments",
|
|
856
|
+
locale: "conversation"
|
|
857
|
+
}, ComposerAttachments));
|
|
858
|
+
ctx.slots.inject("conversation.message.images", () => ctx.slots.register({
|
|
859
|
+
name: "conversation.message.images",
|
|
860
|
+
locale: "conversation"
|
|
861
|
+
}, MessageImages));
|
|
862
|
+
ctx.slots.inject("conversation.trajectory.images", () => ctx.slots.register({
|
|
863
|
+
name: "conversation.trajectory.images",
|
|
864
|
+
locale: "conversation"
|
|
865
|
+
}, MessageImages));
|
|
866
|
+
ctx.slots.inject("tool.call.images", () => ctx.slots.register({
|
|
867
|
+
name: "tool.call.images",
|
|
868
|
+
locale: "conversation"
|
|
869
|
+
}, MessageImages));
|
|
870
|
+
}
|
|
871
|
+
//#endregion
|
|
872
|
+
exports.apply = apply;
|
|
873
|
+
exports.inject = inject;
|
|
874
|
+
return module.exports;
|
|
875
|
+
}
|
|
876
|
+
});
|
|
877
|
+
|
|
878
|
+
//# sourceMappingURL=client.js.map
|