one-design-next 0.0.11 → 0.0.13
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/dist/_genui-types.d.ts +45 -10
- package/dist/attachments/index.js +67 -10
- package/dist/attachments/style/index.css +86 -14
- package/dist/collapse/primitive.d.ts +1 -1
- package/dist/composer/chip.d.ts +4 -4
- package/dist/composer/clipboard.d.ts +12 -0
- package/dist/composer/clipboard.js +84 -0
- package/dist/composer/editor.d.ts +9 -1
- package/dist/composer/editor.js +70 -14
- package/dist/composer/hooks/useChipManager.d.ts +6 -1
- package/dist/composer/hooks/useChipManager.js +76 -27
- package/dist/composer/hooks/useChipSelectionMarker.d.ts +7 -0
- package/dist/composer/hooks/useChipSelectionMarker.js +66 -0
- package/dist/composer/index.d.ts +58 -1
- package/dist/composer/index.js +219 -102
- package/dist/composer/inline-ref.d.ts +9 -0
- package/dist/composer/inline-ref.js +21 -0
- package/dist/composer/send-meta.d.ts +6 -0
- package/dist/composer/send-meta.js +67 -0
- package/dist/composer/style/index.css +48 -53
- package/dist/composer/utils.d.ts +9 -0
- package/dist/composer/utils.js +43 -2
- package/dist/fab/index.js +3 -16
- package/dist/fab/style/index.css +1 -3
- package/dist/icon/svg-data.d.ts +4 -0
- package/dist/icon/svg-data.js +1 -1
- package/dist/icon/types.d.ts +1 -1
- package/dist/image/index.d.ts +43 -0
- package/dist/image/index.js +51 -0
- package/dist/image/style/index.css +59 -0
- package/dist/image/style/index.d.ts +2 -0
- package/dist/image/style/index.js +2 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +4 -0
- package/dist/invocation/index.d.ts +17 -0
- package/dist/invocation/index.js +84 -0
- package/dist/invocation/style/index.css +58 -0
- package/dist/invocation/style/index.d.ts +2 -0
- package/dist/invocation/style/index.js +2 -0
- package/dist/mention/index.d.ts +17 -0
- package/dist/mention/index.js +90 -0
- package/dist/mention/style/index.css +58 -0
- package/dist/mention/style/index.d.ts +2 -0
- package/dist/mention/style/index.js +2 -0
- package/dist/message-image/index.d.ts +42 -0
- package/dist/message-image/index.js +46 -0
- package/dist/message-image/style/index.css +60 -0
- package/dist/message-image/style/index.d.ts +2 -0
- package/dist/message-image/style/index.js +2 -0
- package/dist/preview-panel/index.d.ts +5 -1
- package/dist/preview-panel/index.js +27 -2
- package/dist/user-bubble/index.d.ts +11 -1
- package/dist/user-bubble/index.js +30 -5
- package/dist/user-bubble/style/index.css +6 -0
- package/package.json +2 -3
package/dist/composer/index.js
CHANGED
|
@@ -13,12 +13,14 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
|
13
13
|
import { useState, useRef, useCallback, useEffect, useLayoutEffect, useMemo, forwardRef, useImperativeHandle } from 'react';
|
|
14
14
|
import HoverFill from "../hover-fill";
|
|
15
15
|
import Icon from "../icon";
|
|
16
|
+
import Image from "../image";
|
|
16
17
|
import Popover from "../popover";
|
|
17
18
|
import Attachments from "../attachments";
|
|
18
19
|
import { Message } from "../message";
|
|
19
20
|
import SkillSlot from "../skill-slot";
|
|
20
21
|
import useControlledState from "../_util/useControlledState";
|
|
21
22
|
import { ComposerEditor } from "./editor";
|
|
23
|
+
import { buildSendMetaFromChips } from "./send-meta";
|
|
22
24
|
import { stripMarkers } from "./utils";
|
|
23
25
|
import "./style";
|
|
24
26
|
var TOOL_BTN_ACTIVE = 'color-mix(in srgb, var(--odn-color-cyan-5) 10%, transparent)';
|
|
@@ -32,6 +34,8 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
32
34
|
onStop = _ref.onStop,
|
|
33
35
|
_ref$isGenerating = _ref.isGenerating,
|
|
34
36
|
isGenerating = _ref$isGenerating === void 0 ? false : _ref$isGenerating,
|
|
37
|
+
_ref$disabled = _ref.disabled,
|
|
38
|
+
disabled = _ref$disabled === void 0 ? false : _ref$disabled,
|
|
35
39
|
_ref$placeholder = _ref.placeholder,
|
|
36
40
|
placeholder = _ref$placeholder === void 0 ? '发送消息…' : _ref$placeholder,
|
|
37
41
|
_ref$spacing = _ref.spacing,
|
|
@@ -48,57 +52,67 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
48
52
|
_ref$submitType = _ref.submitType,
|
|
49
53
|
submitType = _ref$submitType === void 0 ? 'enter' : _ref$submitType,
|
|
50
54
|
onEnter = _ref.onEnter,
|
|
55
|
+
attachmentsProp = _ref.attachments,
|
|
56
|
+
onAttachmentsChange = _ref.onAttachmentsChange,
|
|
57
|
+
onAttachFiles = _ref.onAttachFiles,
|
|
58
|
+
onAttachmentRemove = _ref.onAttachmentRemove,
|
|
59
|
+
_ref$attachmentsDisab = _ref.attachmentsDisabled,
|
|
60
|
+
attachmentsDisabled = _ref$attachmentsDisab === void 0 ? false : _ref$attachmentsDisab,
|
|
61
|
+
_ref$maxFileCount = _ref.maxFileCount,
|
|
62
|
+
maxFileCount = _ref$maxFileCount === void 0 ? 5 : _ref$maxFileCount,
|
|
63
|
+
_ref$maxFileSize = _ref.maxFileSize,
|
|
64
|
+
maxFileSize = _ref$maxFileSize === void 0 ? 20 * 1024 * 1024 : _ref$maxFileSize,
|
|
51
65
|
className = _ref.className,
|
|
52
66
|
style = _ref.style;
|
|
53
67
|
var _useControlledState = useControlledState(defaultValue, valueProp),
|
|
54
68
|
_useControlledState2 = _slicedToArray(_useControlledState, 2),
|
|
55
69
|
text = _useControlledState2[0],
|
|
56
70
|
setText = _useControlledState2[1];
|
|
57
|
-
var
|
|
71
|
+
var _useControlledState3 = useControlledState([], attachmentsProp),
|
|
72
|
+
_useControlledState4 = _slicedToArray(_useControlledState3, 2),
|
|
73
|
+
attachments = _useControlledState4[0],
|
|
74
|
+
setAttachments = _useControlledState4[1];
|
|
75
|
+
var _useState = useState(false),
|
|
58
76
|
_useState2 = _slicedToArray(_useState, 2),
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
var _useState3 = useState(false),
|
|
62
|
-
_useState4 = _slicedToArray(_useState3, 2),
|
|
63
|
-
webSearch = _useState4[0],
|
|
64
|
-
setWebSearch = _useState4[1];
|
|
77
|
+
webSearch = _useState2[0],
|
|
78
|
+
setWebSearch = _useState2[1];
|
|
65
79
|
/**
|
|
66
80
|
* 工具栏「技能」按钮触发的 menu 显隐。
|
|
67
81
|
* 跟 trigger 触发的 menu 共用 SkillSlot 渲染,但 anchor / 关闭路径不同。
|
|
68
82
|
*/
|
|
69
|
-
var
|
|
70
|
-
|
|
71
|
-
toolMenuOpen =
|
|
72
|
-
setToolMenuOpen =
|
|
83
|
+
var _useState3 = useState(false),
|
|
84
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
85
|
+
toolMenuOpen = _useState4[0],
|
|
86
|
+
setToolMenuOpen = _useState4[1];
|
|
73
87
|
/**
|
|
74
88
|
* editor 内 `@` / `/` 触发态的实时信号。null 表示无活动 trigger。
|
|
75
89
|
* 由 editor 的 onTriggerChange 写入;选定 chip 或 cancelTrigger 后置 null。
|
|
76
90
|
*/
|
|
77
|
-
var
|
|
78
|
-
|
|
79
|
-
triggerInfo =
|
|
80
|
-
setTriggerInfo =
|
|
91
|
+
var _useState5 = useState(null),
|
|
92
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
|
93
|
+
triggerInfo = _useState6[0],
|
|
94
|
+
setTriggerInfo = _useState6[1];
|
|
81
95
|
/** trigger 浮层内键盘高亮项 index;query 变化或 menu 关闭时复位 0。 */
|
|
82
|
-
var
|
|
83
|
-
|
|
84
|
-
triggerActiveIndex =
|
|
85
|
-
setTriggerActiveIndex =
|
|
96
|
+
var _useState7 = useState(0),
|
|
97
|
+
_useState8 = _slicedToArray(_useState7, 2),
|
|
98
|
+
triggerActiveIndex = _useState8[0],
|
|
99
|
+
setTriggerActiveIndex = _useState8[1];
|
|
86
100
|
/** lite 模式下由单行升格到多行布局;粘性:只在 text 清空时复位 */
|
|
87
|
-
var
|
|
88
|
-
|
|
89
|
-
expanded =
|
|
90
|
-
setExpanded =
|
|
101
|
+
var _useState9 = useState(false),
|
|
102
|
+
_useState10 = _slicedToArray(_useState9, 2),
|
|
103
|
+
expanded = _useState10[0],
|
|
104
|
+
setExpanded = _useState10[1];
|
|
91
105
|
/** ComposerEditor 反馈的 editor 自然高度(offsetHeight,未 clamp),用于 lite 升格判断 */
|
|
92
|
-
var
|
|
93
|
-
|
|
94
|
-
editorHeight =
|
|
95
|
-
setEditorHeight =
|
|
106
|
+
var _useState11 = useState(0),
|
|
107
|
+
_useState12 = _slicedToArray(_useState11, 2),
|
|
108
|
+
editorHeight = _useState12[0],
|
|
109
|
+
setEditorHeight = _useState12[1];
|
|
96
110
|
/** editor 内容是否真正达到 maxRows 触顶——配合 SCSS 控制 viewport overflow,
|
|
97
111
|
* 阻止升格 transition / 换行未触顶时的 scrollbar 闪现 */
|
|
98
|
-
var
|
|
99
|
-
|
|
100
|
-
atMax =
|
|
101
|
-
setAtMax =
|
|
112
|
+
var _useState13 = useState(false),
|
|
113
|
+
_useState14 = _slicedToArray(_useState13, 2),
|
|
114
|
+
atMax = _useState14[0],
|
|
115
|
+
setAtMax = _useState14[1];
|
|
102
116
|
var fileInputRef = useRef(null);
|
|
103
117
|
var editorRef = useRef(null);
|
|
104
118
|
|
|
@@ -127,7 +141,7 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
127
141
|
skillId: skill.id,
|
|
128
142
|
label: skill.label,
|
|
129
143
|
icon: skill.icon,
|
|
130
|
-
kind: '
|
|
144
|
+
kind: 'invocation'
|
|
131
145
|
};
|
|
132
146
|
(_editorRef$current4 = editorRef.current) === null || _editorRef$current4 === void 0 || _editorRef$current4.insertChip(data);
|
|
133
147
|
(_editorRef$current5 = editorRef.current) === null || _editorRef$current5 === void 0 || _editorRef$current5.focus();
|
|
@@ -143,17 +157,34 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
143
157
|
onChangeProp === null || onChangeProp === void 0 || onChangeProp(v);
|
|
144
158
|
}, [setText, onChangeProp]);
|
|
145
159
|
|
|
146
|
-
/* ----
|
|
147
|
-
|
|
148
|
-
|
|
160
|
+
/* ---- Attachments controlled writer ----
|
|
161
|
+
* useControlledState 只做"value vs innerValue"合流;onAttachmentsChange 需要手动派发。
|
|
162
|
+
* 模式与上面 updateText 一致:内部 set + 对外 callback。 */
|
|
163
|
+
var updateAttachments = useCallback(function (next) {
|
|
164
|
+
setAttachments(next);
|
|
165
|
+
onAttachmentsChange === null || onAttachmentsChange === void 0 || onAttachmentsChange(next);
|
|
166
|
+
}, [setAttachments, onAttachmentsChange]);
|
|
167
|
+
|
|
168
|
+
/* ---- 内部生成的 blob url 记账 ----
|
|
169
|
+
* 仅"非受控 + 未传 onAttachFiles"路径会 createObjectURL;这些 url 由我们负责 revoke。
|
|
170
|
+
* 受控模式下,attachments 里的 url 归业务方所有(如企点 / OSS 云端 url),不能被组件 revoke。
|
|
171
|
+
* 用 Set 当账本,删除/卸载时按 has 判断是否动手。 */
|
|
172
|
+
var internalBlobUrlsRef = useRef(new Set());
|
|
149
173
|
useEffect(function () {
|
|
150
174
|
return function () {
|
|
151
|
-
|
|
152
|
-
|
|
175
|
+
internalBlobUrlsRef.current.forEach(function (url) {
|
|
176
|
+
return URL.revokeObjectURL(url);
|
|
153
177
|
});
|
|
178
|
+
internalBlobUrlsRef.current.clear();
|
|
154
179
|
};
|
|
155
180
|
}, []);
|
|
156
181
|
|
|
182
|
+
/* ---- 受控模式校验:受控但没接 onAttachFiles 时,组件无路径塞文件进 attachments ---- */
|
|
183
|
+
if (process.env.NODE_ENV !== 'production' && attachmentsProp !== undefined && !onAttachFiles) {
|
|
184
|
+
// eslint-disable-next-line no-console
|
|
185
|
+
console.warn('[Composer] 检测到受控 attachments,但未提供 onAttachFiles。' + '内置文件入口(按钮 / 拖入 / 粘贴)将无法把文件写入 attachments。' + '若需让用户继续添加附件,请传入 onAttachFiles 接管 File → Attachment 转换。');
|
|
186
|
+
}
|
|
187
|
+
|
|
157
188
|
/* ---- lite 升格判断 ----
|
|
158
189
|
* 基准 32px = lite 单行 SCSS 锁定的 min-height(与 ComposerEditor minRows=1
|
|
159
190
|
* 算出的 minHeightPx 一致)。直接用常量当基准,不依赖 ResizeObserver 第一次
|
|
@@ -181,34 +212,45 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
181
212
|
/* ---- Send ----
|
|
182
213
|
* 内部 text 是 raw value(chip 序列化为不可见 marker 字符)。对外 onSend:
|
|
183
214
|
* - text 给 stripMarkers 之后的纯文本(旧业务收到的字符串保持纯净)
|
|
184
|
-
* -
|
|
185
|
-
*
|
|
215
|
+
* - invocations / mentions 从 editor.getChips() 经 buildSendMetaFromChips 拆分;
|
|
216
|
+
* chips 仍双写(deprecated)
|
|
217
|
+
*
|
|
218
|
+
* 发送后内部状态全部清空:text、attachments、webSearch——与 ChatGPT / Claude /
|
|
219
|
+
* iMessage 等业界对话产品一致。attachments 不 revoke blob URL:业务方在 onSend
|
|
220
|
+
* 回调里可能仍持有 url(消息记录、本地预览等),由消费方负责回收。 */
|
|
186
221
|
var handleSend = useCallback(function () {
|
|
187
|
-
var _editorRef$current$ge, _editorRef$current7;
|
|
222
|
+
var _editorRef$current$ge, _editorRef$current7, _editorRef$current8;
|
|
223
|
+
if (disabled) return;
|
|
188
224
|
var plain = stripMarkers(text).trim();
|
|
189
225
|
if (!plain && attachments.length === 0) return;
|
|
190
226
|
var chips = (_editorRef$current$ge = (_editorRef$current7 = editorRef.current) === null || _editorRef$current7 === void 0 ? void 0 : _editorRef$current7.getChips()) !== null && _editorRef$current$ge !== void 0 ? _editorRef$current$ge : [];
|
|
191
|
-
var meta = {
|
|
227
|
+
var meta = buildSendMetaFromChips(chips, {
|
|
192
228
|
attachments: attachments.length > 0 ? attachments : undefined,
|
|
193
|
-
webSearch: webSearch || undefined
|
|
194
|
-
|
|
195
|
-
};
|
|
229
|
+
webSearch: webSearch || undefined
|
|
230
|
+
});
|
|
196
231
|
onSend(plain, meta);
|
|
232
|
+
(_editorRef$current8 = editorRef.current) === null || _editorRef$current8 === void 0 || _editorRef$current8.clear();
|
|
233
|
+
setAttachments([]);
|
|
234
|
+
setWebSearch(false);
|
|
197
235
|
}, [text, attachments, webSearch, onSend]);
|
|
198
236
|
|
|
199
|
-
/* ---- File upload ----
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
237
|
+
/* ---- File upload ----
|
|
238
|
+
* 三入口(按钮 / 拖入 / 粘贴)共用此函数。先做内置校验(数量、单文件体积、重名),
|
|
239
|
+
* 再分两条路径派发:
|
|
240
|
+
* - 传了 onAttachFiles:把通过校验的原生 File[] 交给业务方,组件不再 createObjectURL,
|
|
241
|
+
* 也不入栈。业务方负责上传并通过 onAttachmentsChange 回写 attachments。
|
|
242
|
+
* - 未传 onAttachFiles:沿用旧路径(createObjectURL → updateAttachments),保持
|
|
243
|
+
* demo 与历史业务零改动。生成的 blob url 记入 internalBlobUrlsRef,仅这些会被
|
|
244
|
+
* 组件 revoke。 */
|
|
204
245
|
var addFilesFromList = useCallback(function (fileArray) {
|
|
246
|
+
if (disabled || attachmentsDisabled) return;
|
|
205
247
|
if (fileArray.length === 0) return;
|
|
206
|
-
var remaining =
|
|
248
|
+
var remaining = maxFileCount - attachments.length;
|
|
207
249
|
if (remaining <= 0) {
|
|
208
|
-
Message.warning(
|
|
250
|
+
Message.warning("\u81F3\u591A\u652F\u6301\u6DFB\u52A0 ".concat(maxFileCount, " \u4E2A\u6587\u4EF6"));
|
|
209
251
|
return;
|
|
210
252
|
}
|
|
211
|
-
var
|
|
253
|
+
var acceptedFiles = [];
|
|
212
254
|
var oversized = 0;
|
|
213
255
|
var duplicated = 0;
|
|
214
256
|
var overCount = 0;
|
|
@@ -217,28 +259,23 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
217
259
|
try {
|
|
218
260
|
var _loop = function _loop() {
|
|
219
261
|
var f = _step.value;
|
|
220
|
-
if (
|
|
262
|
+
if (acceptedFiles.length >= remaining) {
|
|
221
263
|
overCount++;
|
|
222
264
|
return 0; // continue
|
|
223
265
|
}
|
|
224
|
-
if (f.size >
|
|
266
|
+
if (f.size > maxFileSize) {
|
|
225
267
|
oversized++;
|
|
226
268
|
return 0; // continue
|
|
227
269
|
}
|
|
228
270
|
if (attachments.some(function (a) {
|
|
229
271
|
return a.name === f.name && a.size === f.size;
|
|
230
|
-
}) ||
|
|
231
|
-
return
|
|
272
|
+
}) || acceptedFiles.some(function (af) {
|
|
273
|
+
return af.name === f.name && af.size === f.size;
|
|
232
274
|
})) {
|
|
233
275
|
duplicated++;
|
|
234
276
|
return 0; // continue
|
|
235
277
|
}
|
|
236
|
-
|
|
237
|
-
name: f.name,
|
|
238
|
-
type: f.type,
|
|
239
|
-
size: f.size,
|
|
240
|
-
url: URL.createObjectURL(f)
|
|
241
|
-
});
|
|
278
|
+
acceptedFiles.push(f);
|
|
242
279
|
},
|
|
243
280
|
_ret;
|
|
244
281
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
@@ -250,32 +287,48 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
250
287
|
} finally {
|
|
251
288
|
_iterator.f();
|
|
252
289
|
}
|
|
253
|
-
|
|
290
|
+
var sizeLabel = "".concat(Math.round(maxFileSize / 1024 / 1024), "MB");
|
|
291
|
+
if (oversized > 0) Message.warning("\u6587\u4EF6\u5927\u5C0F\u81F3\u591A\u4E3A ".concat(sizeLabel));
|
|
254
292
|
if (duplicated > 0) Message.warning('请不要重复添加文件');
|
|
255
|
-
if (overCount > 0) Message.warning(
|
|
256
|
-
if (
|
|
257
|
-
|
|
293
|
+
if (overCount > 0) Message.warning("\u81F3\u591A\u652F\u6301\u6DFB\u52A0 ".concat(maxFileCount, " \u4E2A\u6587\u4EF6"));
|
|
294
|
+
if (acceptedFiles.length === 0) return;
|
|
295
|
+
if (onAttachFiles) {
|
|
296
|
+
onAttachFiles(acceptedFiles);
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
var accepted = acceptedFiles.map(function (f) {
|
|
300
|
+
var url = URL.createObjectURL(f);
|
|
301
|
+
internalBlobUrlsRef.current.add(url);
|
|
302
|
+
return {
|
|
303
|
+
name: f.name,
|
|
304
|
+
type: f.type,
|
|
305
|
+
size: f.size,
|
|
306
|
+
url: url
|
|
307
|
+
};
|
|
258
308
|
});
|
|
259
|
-
|
|
309
|
+
updateAttachments([].concat(_toConsumableArray(attachments), _toConsumableArray(accepted)));
|
|
310
|
+
}, [attachments, attachmentsDisabled, disabled, maxFileCount, maxFileSize, onAttachFiles, updateAttachments]);
|
|
260
311
|
var handleFileChange = function handleFileChange(e) {
|
|
261
312
|
var files = e.target.files;
|
|
262
313
|
if (!files) return;
|
|
263
314
|
addFilesFromList(Array.from(files));
|
|
264
315
|
e.target.value = '';
|
|
265
316
|
};
|
|
266
|
-
var
|
|
267
|
-
|
|
268
|
-
fileDragOver =
|
|
269
|
-
setFileDragOver =
|
|
317
|
+
var _useState15 = useState(false),
|
|
318
|
+
_useState16 = _slicedToArray(_useState15, 2),
|
|
319
|
+
fileDragOver = _useState16[0],
|
|
320
|
+
setFileDragOver = _useState16[1];
|
|
270
321
|
var composerBoxFileDragAttrs = fileDragOver ? {
|
|
271
322
|
'data-odn-composer-file-drag': ''
|
|
272
323
|
} : {};
|
|
273
324
|
var handleComposerDragEnter = function handleComposerDragEnter(e) {
|
|
274
325
|
e.preventDefault();
|
|
326
|
+
if (disabled || attachmentsDisabled) return;
|
|
275
327
|
if (!_toConsumableArray(e.dataTransfer.types).includes('Files')) return;
|
|
276
328
|
setFileDragOver(true);
|
|
277
329
|
};
|
|
278
330
|
var handleComposerDragOver = function handleComposerDragOver(e) {
|
|
331
|
+
if (disabled || attachmentsDisabled) return;
|
|
279
332
|
if (!_toConsumableArray(e.dataTransfer.types).includes('Files')) return;
|
|
280
333
|
e.preventDefault();
|
|
281
334
|
e.dataTransfer.dropEffect = 'copy';
|
|
@@ -288,6 +341,7 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
288
341
|
var _dt$files;
|
|
289
342
|
e.preventDefault();
|
|
290
343
|
setFileDragOver(false);
|
|
344
|
+
if (disabled || attachmentsDisabled) return;
|
|
291
345
|
var dt = e.dataTransfer;
|
|
292
346
|
if (!((_dt$files = dt.files) !== null && _dt$files !== void 0 && _dt$files.length)) return;
|
|
293
347
|
addFilesFromList(Array.from(dt.files));
|
|
@@ -303,17 +357,17 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
303
357
|
skillId: skill.id,
|
|
304
358
|
label: skill.label,
|
|
305
359
|
icon: skill.icon,
|
|
306
|
-
kind: '
|
|
360
|
+
kind: 'invocation'
|
|
307
361
|
};
|
|
308
362
|
if (source === 'trigger') {
|
|
309
|
-
var _editorRef$
|
|
310
|
-
(_editorRef$
|
|
363
|
+
var _editorRef$current9;
|
|
364
|
+
(_editorRef$current9 = editorRef.current) === null || _editorRef$current9 === void 0 || _editorRef$current9.replaceTriggerWithChip(data);
|
|
311
365
|
setTriggerInfo(null);
|
|
312
366
|
} else {
|
|
313
|
-
var _editorRef$
|
|
314
|
-
(_editorRef$
|
|
367
|
+
var _editorRef$current10, _editorRef$current11;
|
|
368
|
+
(_editorRef$current10 = editorRef.current) === null || _editorRef$current10 === void 0 || _editorRef$current10.insertChip(data);
|
|
315
369
|
setToolMenuOpen(false);
|
|
316
|
-
(_editorRef$
|
|
370
|
+
(_editorRef$current11 = editorRef.current) === null || _editorRef$current11 === void 0 || _editorRef$current11.focus();
|
|
317
371
|
}
|
|
318
372
|
}, []);
|
|
319
373
|
|
|
@@ -363,9 +417,9 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
363
417
|
return true;
|
|
364
418
|
}
|
|
365
419
|
if (e.key === 'Escape') {
|
|
366
|
-
var _editorRef$
|
|
420
|
+
var _editorRef$current12;
|
|
367
421
|
e.preventDefault();
|
|
368
|
-
(_editorRef$
|
|
422
|
+
(_editorRef$current12 = editorRef.current) === null || _editorRef$current12 === void 0 || _editorRef$current12.cancelTrigger();
|
|
369
423
|
setTriggerInfo(null);
|
|
370
424
|
return true;
|
|
371
425
|
}
|
|
@@ -396,22 +450,31 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
396
450
|
console.warn("[Composer] variant=\"lite\" \u4EC5\u652F\u6301\u4E00\u4E2A\u5DE5\u5177\u6309\u94AE\uFF0C\u5DF2\u5FFD\u7565\u5176\u4F59 ".concat(tools.length - 1, " \u4E2A\u3002\u82E5\u9700\u8981\u591A\u4E2A\u5DE5\u5177\u6309\u94AE\uFF0C\u8BF7\u4F7F\u7528 variant=\"full\"\u3002"));
|
|
397
451
|
}
|
|
398
452
|
|
|
399
|
-
/* ---- Tool buttons ----
|
|
453
|
+
/* ---- Tool buttons ----
|
|
454
|
+
* disabled(整体禁用)合并到各按钮的 disabled 状态:
|
|
455
|
+
* - attachment:disabled || attachmentsDisabled
|
|
456
|
+
* - webSearch / skill:disabled(attachmentsDisabled 不影响这两个)
|
|
457
|
+
* skill 的 Popover 在 disabled 时禁用 trigger,避免弹出菜单。 */
|
|
400
458
|
var renderAttachmentBtn = function renderAttachmentBtn() {
|
|
459
|
+
var btnDisabled = disabled || attachmentsDisabled;
|
|
401
460
|
return /*#__PURE__*/React.createElement(HoverFill, {
|
|
402
461
|
key: "attachment",
|
|
403
462
|
"data-odn-composer-tool-btn-wrap": true,
|
|
404
463
|
bgClassName: "odn-composer-tool-btn-bg",
|
|
405
|
-
activeColor: TOOL_BTN_ACTIVE
|
|
464
|
+
activeColor: TOOL_BTN_ACTIVE,
|
|
465
|
+
disabled: btnDisabled
|
|
406
466
|
}, /*#__PURE__*/React.createElement("button", {
|
|
407
467
|
type: "button",
|
|
408
468
|
onClick: function onClick() {
|
|
409
469
|
var _fileInputRef$current;
|
|
410
470
|
return (_fileInputRef$current = fileInputRef.current) === null || _fileInputRef$current === void 0 ? void 0 : _fileInputRef$current.click();
|
|
411
471
|
},
|
|
472
|
+
disabled: btnDisabled,
|
|
412
473
|
"data-odn-composer-tool-btn": true,
|
|
413
474
|
"data-odn-composer-tool-iconic": !effectiveLabeled || undefined,
|
|
475
|
+
"data-odn-composer-tool-disabled": btnDisabled || undefined,
|
|
414
476
|
"aria-label": "\u9644\u4EF6",
|
|
477
|
+
"aria-disabled": btnDisabled || undefined,
|
|
415
478
|
title: effectiveLabeled ? undefined : '附件'
|
|
416
479
|
}, /*#__PURE__*/React.createElement(Icon, {
|
|
417
480
|
name: "paperclip",
|
|
@@ -424,7 +487,7 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
424
487
|
"data-odn-composer-tool-btn-wrap": true,
|
|
425
488
|
bgClassName: "odn-composer-tool-btn-bg",
|
|
426
489
|
activeColor: TOOL_BTN_ACTIVE,
|
|
427
|
-
disabled: webSearch
|
|
490
|
+
disabled: disabled || webSearch
|
|
428
491
|
}, /*#__PURE__*/React.createElement("button", {
|
|
429
492
|
type: "button",
|
|
430
493
|
onClick: function onClick() {
|
|
@@ -432,11 +495,14 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
432
495
|
return !v;
|
|
433
496
|
});
|
|
434
497
|
},
|
|
498
|
+
disabled: disabled,
|
|
435
499
|
"data-odn-composer-tool-btn": true,
|
|
436
500
|
"data-odn-composer-tool-iconic": !effectiveLabeled || undefined,
|
|
437
501
|
"data-odn-composer-tool-active": webSearch || undefined,
|
|
502
|
+
"data-odn-composer-tool-disabled": disabled || undefined,
|
|
438
503
|
"aria-label": "\u8054\u7F51",
|
|
439
504
|
"aria-pressed": webSearch,
|
|
505
|
+
"aria-disabled": disabled || undefined,
|
|
440
506
|
title: effectiveLabeled ? undefined : '联网'
|
|
441
507
|
}, /*#__PURE__*/React.createElement(Icon, {
|
|
442
508
|
name: "globe",
|
|
@@ -451,8 +517,11 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
451
517
|
arrowed: false,
|
|
452
518
|
placement: "topLeft",
|
|
453
519
|
offset: 4,
|
|
454
|
-
visible: toolMenuOpen,
|
|
455
|
-
onVisibleChange:
|
|
520
|
+
visible: !disabled && toolMenuOpen,
|
|
521
|
+
onVisibleChange: function onVisibleChange(v) {
|
|
522
|
+
if (disabled) return;
|
|
523
|
+
setToolMenuOpen(v);
|
|
524
|
+
},
|
|
456
525
|
popupClassName: "odn-composer-skill-popup",
|
|
457
526
|
popup: /*#__PURE__*/React.createElement(SkillSlot, {
|
|
458
527
|
variant: "menu",
|
|
@@ -465,13 +534,16 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
465
534
|
"data-odn-composer-tool-btn-wrap": true,
|
|
466
535
|
bgClassName: "odn-composer-tool-btn-bg",
|
|
467
536
|
activeColor: TOOL_BTN_ACTIVE,
|
|
468
|
-
disabled: toolMenuOpen
|
|
537
|
+
disabled: disabled || toolMenuOpen
|
|
469
538
|
}, /*#__PURE__*/React.createElement("button", {
|
|
470
539
|
type: "button",
|
|
540
|
+
disabled: disabled,
|
|
471
541
|
"data-odn-composer-tool-btn": true,
|
|
472
542
|
"data-odn-composer-tool-iconic": !effectiveLabeled || undefined,
|
|
473
543
|
"data-odn-composer-tool-active": toolMenuOpen || undefined,
|
|
544
|
+
"data-odn-composer-tool-disabled": disabled || undefined,
|
|
474
545
|
"aria-label": "\u6280\u80FD",
|
|
546
|
+
"aria-disabled": disabled || undefined,
|
|
475
547
|
title: effectiveLabeled ? undefined : '技能'
|
|
476
548
|
}, /*#__PURE__*/React.createElement(Icon, {
|
|
477
549
|
name: "puzzle",
|
|
@@ -486,22 +558,64 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
486
558
|
}).filter(Boolean);
|
|
487
559
|
var hasTools = toolNodes.length > 0;
|
|
488
560
|
|
|
489
|
-
/* ---- Slots ----
|
|
561
|
+
/* ---- Slots ----
|
|
562
|
+
* 待发送区按 type 分流:
|
|
563
|
+
* - 图片(image/* + url)→ Image leaf + 72×72 cover wrap,输入态用模板
|
|
564
|
+
* 驱动尺寸(整齐划一比保留长宽比要紧)
|
|
565
|
+
* - 其他附件 → 走 Attachments,保持原 file-card 渲染
|
|
566
|
+
*
|
|
567
|
+
* 删除:按 internalBlobUrlsRef 判断是否需要 revoke,避免误 revoke 业务方
|
|
568
|
+
* 的云端 url;同时派发 onAttachmentRemove(语义钩子,便于业务调"服务端
|
|
569
|
+
* 删文件")与 onAttachmentsChange。
|
|
570
|
+
*
|
|
571
|
+
* 分流子集与原 attachments 的 index 不一致,对外回调(onAttachmentRemove)
|
|
572
|
+
* 用 attachments.indexOf 拿到原始 index,保持业务方语义。 */
|
|
573
|
+
var isImageAttachment = function isImageAttachment(a) {
|
|
574
|
+
return a.type.startsWith('image/') && !!a.url;
|
|
575
|
+
};
|
|
576
|
+
var composerImages = attachments.filter(isImageAttachment);
|
|
577
|
+
var composerFiles = attachments.filter(function (a) {
|
|
578
|
+
return !isImageAttachment(a);
|
|
579
|
+
});
|
|
580
|
+
var removeAttachmentAt = function removeAttachmentAt(i) {
|
|
581
|
+
var removed = attachments[i];
|
|
582
|
+
if (removed !== null && removed !== void 0 && removed.url && internalBlobUrlsRef.current.has(removed.url)) {
|
|
583
|
+
URL.revokeObjectURL(removed.url);
|
|
584
|
+
internalBlobUrlsRef.current.delete(removed.url);
|
|
585
|
+
}
|
|
586
|
+
var next = attachments.filter(function (_, idx) {
|
|
587
|
+
return idx !== i;
|
|
588
|
+
});
|
|
589
|
+
if (removed) onAttachmentRemove === null || onAttachmentRemove === void 0 || onAttachmentRemove(i, removed);
|
|
590
|
+
updateAttachments(next);
|
|
591
|
+
};
|
|
490
592
|
var attachmentsSlot = attachments.length > 0 ? /*#__PURE__*/React.createElement("div", {
|
|
491
593
|
"data-odn-composer-attachments": true
|
|
492
|
-
}, /*#__PURE__*/React.createElement(
|
|
493
|
-
|
|
594
|
+
}, composerImages.length > 0 && /*#__PURE__*/React.createElement("div", {
|
|
595
|
+
"data-odn-composer-images": true
|
|
596
|
+
}, composerImages.map(function (img) {
|
|
597
|
+
var realIdx = attachments.indexOf(img);
|
|
598
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
599
|
+
key: "".concat(img.name, "-").concat(realIdx),
|
|
600
|
+
"data-odn-composer-image-thumb": true
|
|
601
|
+
}, /*#__PURE__*/React.createElement(Image, {
|
|
602
|
+
url: img.url,
|
|
603
|
+
alt: img.name,
|
|
604
|
+
onRemove: function onRemove() {
|
|
605
|
+
return removeAttachmentAt(realIdx);
|
|
606
|
+
}
|
|
607
|
+
}));
|
|
608
|
+
})), composerFiles.length > 0 && /*#__PURE__*/React.createElement(Attachments, {
|
|
609
|
+
attachments: composerFiles,
|
|
494
610
|
onRemove: function onRemove(i) {
|
|
495
|
-
|
|
496
|
-
if (removed !== null && removed !== void 0 && removed.url) URL.revokeObjectURL(removed.url);
|
|
497
|
-
setAttachments(function (prev) {
|
|
498
|
-
return prev.filter(function (_, idx) {
|
|
499
|
-
return idx !== i;
|
|
500
|
-
});
|
|
501
|
-
});
|
|
611
|
+
return removeAttachmentAt(attachments.indexOf(composerFiles[i]));
|
|
502
612
|
}
|
|
503
613
|
})) : null;
|
|
504
|
-
|
|
614
|
+
|
|
615
|
+
/* 状态优先级:disabled > isGenerating > canSend
|
|
616
|
+
* disabled 时永远呈现发送按钮(仅置灰),不切到中止——
|
|
617
|
+
* 因为整体禁用语义包含"现在什么都不能做",包括中断。 */
|
|
618
|
+
var sendOrStopButton = !disabled && isGenerating ? /*#__PURE__*/React.createElement("button", {
|
|
505
619
|
type: "button",
|
|
506
620
|
onClick: onStop,
|
|
507
621
|
"data-odn-composer-stop-btn": true,
|
|
@@ -512,10 +626,10 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
512
626
|
})) : /*#__PURE__*/React.createElement("button", {
|
|
513
627
|
type: "button",
|
|
514
628
|
onClick: handleSend,
|
|
515
|
-
disabled: !canSend,
|
|
629
|
+
disabled: disabled || !canSend,
|
|
516
630
|
"data-odn-composer-send-btn": true,
|
|
517
|
-
"data-odn-composer-send-disabled": !canSend || undefined,
|
|
518
|
-
title:
|
|
631
|
+
"data-odn-composer-send-disabled": disabled || !canSend || undefined,
|
|
632
|
+
title: disabled ? undefined : '发送'
|
|
519
633
|
}, /*#__PURE__*/React.createElement(Icon, {
|
|
520
634
|
name: "arrow-up",
|
|
521
635
|
size: 18
|
|
@@ -549,7 +663,8 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
549
663
|
},
|
|
550
664
|
placeholder: placeholder,
|
|
551
665
|
value: text,
|
|
552
|
-
onChange: updateText
|
|
666
|
+
onChange: updateText,
|
|
667
|
+
disabled: disabled
|
|
553
668
|
/* 本轮只接 `/`,`@` 留给业务接 mention 搜索时再加 */,
|
|
554
669
|
triggers: ['/'],
|
|
555
670
|
onTriggerChange: setTriggerInfo,
|
|
@@ -590,8 +705,8 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
590
705
|
visible: triggerMenuVisible,
|
|
591
706
|
onVisibleChange: function onVisibleChange(v) {
|
|
592
707
|
if (!v) {
|
|
593
|
-
var _editorRef$
|
|
594
|
-
(_editorRef$
|
|
708
|
+
var _editorRef$current13;
|
|
709
|
+
(_editorRef$current13 = editorRef.current) === null || _editorRef$current13 === void 0 || _editorRef$current13.cancelTrigger();
|
|
595
710
|
setTriggerInfo(null);
|
|
596
711
|
}
|
|
597
712
|
},
|
|
@@ -624,7 +739,9 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
|
|
|
624
739
|
"data-odn-composer-variant": variant,
|
|
625
740
|
"data-odn-composer-expanded": liteExpanded ? '' : undefined,
|
|
626
741
|
"data-odn-composer-atmax": atMax ? '' : undefined,
|
|
742
|
+
"data-odn-composer-disabled": disabled || undefined,
|
|
627
743
|
"data-odn-composer-spacing": spacing === 'drawer' ? 'drawer' : undefined,
|
|
744
|
+
"aria-disabled": disabled || undefined,
|
|
628
745
|
className: className !== null && className !== void 0 ? className : spacing === 'drawer' ? 'shrink-0' : undefined,
|
|
629
746
|
style: style
|
|
630
747
|
}, /*#__PURE__*/React.createElement("div", {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { ChipData } from './chip';
|
|
3
|
+
export declare function isMentionChip(chip: ChipData): boolean;
|
|
4
|
+
export interface ComposerInlineRefProps {
|
|
5
|
+
data: ChipData;
|
|
6
|
+
}
|
|
7
|
+
/** Composer 内联引用视觉:按 kind 派发 Invocation(/)或 Mention(@)。 */
|
|
8
|
+
export declare function ComposerInlineRef({ data }: ComposerInlineRefProps): import("react").JSX.Element;
|
|
9
|
+
export default ComposerInlineRef;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Invocation } from "../invocation";
|
|
2
|
+
import { Mention } from "../mention";
|
|
3
|
+
import { chipToInvocationData, chipToMentionData } from "./send-meta";
|
|
4
|
+
export function isMentionChip(chip) {
|
|
5
|
+
return chip.kind === 'mention';
|
|
6
|
+
}
|
|
7
|
+
/** Composer 内联引用视觉:按 kind 派发 Invocation(/)或 Mention(@)。 */
|
|
8
|
+
export function ComposerInlineRef(_ref) {
|
|
9
|
+
var data = _ref.data;
|
|
10
|
+
if (isMentionChip(data)) {
|
|
11
|
+
return /*#__PURE__*/React.createElement(Mention, {
|
|
12
|
+
data: chipToMentionData(data),
|
|
13
|
+
interactive: true
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return /*#__PURE__*/React.createElement(Invocation, {
|
|
17
|
+
data: chipToInvocationData(data),
|
|
18
|
+
interactive: true
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export default ComposerInlineRef;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { InvocationData, MentionData, SendMeta } from '../_genui-types';
|
|
2
|
+
import type { ChipData } from './chip';
|
|
3
|
+
export declare function chipToInvocationData(chip: ChipData): InvocationData;
|
|
4
|
+
export declare function chipToMentionData(chip: ChipData): MentionData;
|
|
5
|
+
/** 从 editor chip 列表构建 SendMeta(含 invocations / mentions + chips 兼容字段)。 */
|
|
6
|
+
export declare function buildSendMetaFromChips(chips: ChipData[], base?: Omit<SendMeta, 'chips' | 'invocations' | 'mentions'>): SendMeta;
|