one-design-next 0.0.32 → 0.0.34

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.
@@ -1,5 +1,10 @@
1
1
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
2
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
3
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
6
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
7
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
3
8
  function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
4
9
  function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
5
10
  function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
@@ -17,7 +22,6 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
17
22
  import { useState, useRef, useCallback, useEffect, useLayoutEffect, useMemo, forwardRef, useImperativeHandle } from 'react';
18
23
  import HoverFill from "../hover-fill";
19
24
  import Icon from "../icon";
20
- import Image from "../image";
21
25
  import Popover from "../popover";
22
26
  import Attachments from "../attachments";
23
27
  import { Message } from "../message";
@@ -40,6 +44,31 @@ function createInvocationChipData(skill) {
40
44
  };
41
45
  }
42
46
  var TOOL_BTN_ACTIVE = 'color-mix(in srgb, var(--odn-color-brand-6) 10%, transparent)';
47
+ var DEFAULT_ACCEPT = 'image/*,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.md,.csv,.json,.xml,.html,.css,.js,.ts,.jsx,.tsx,.py,.java,.go,.rs,.c,.cpp,.zip,.rar,.7z';
48
+ function formatSizeMb(bytes) {
49
+ return "".concat(Math.max(1, Math.round(bytes / 1024 / 1024)), "MB");
50
+ }
51
+ function getFileExt(name) {
52
+ var _name$split$pop;
53
+ var ext = (_name$split$pop = name.split('.').pop()) === null || _name$split$pop === void 0 ? void 0 : _name$split$pop.trim().toLowerCase();
54
+ return ext ? ".".concat(ext) : '';
55
+ }
56
+ function isFileAccepted(file, accept) {
57
+ var rules = accept.split(',').map(function (s) {
58
+ return s.trim().toLowerCase();
59
+ }).filter(Boolean);
60
+ if (rules.length === 0) return true;
61
+ var mime = (file.type || '').toLowerCase();
62
+ var ext = getFileExt(file.name);
63
+ return rules.some(function (rule) {
64
+ if (rule.startsWith('.')) return ext === rule;
65
+ if (rule.endsWith('/*')) {
66
+ var prefix = rule.slice(0, -2);
67
+ return !!mime && mime.startsWith("".concat(prefix, "/"));
68
+ }
69
+ return !!mime && mime === rule;
70
+ });
71
+ }
43
72
  var DEFAULT_TOOLS = ['attachment', 'webSearch', 'skill'];
44
73
  export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
45
74
  var _paramEdit$chipId;
@@ -75,12 +104,16 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
75
104
  onAttachmentsChange = _ref.onAttachmentsChange,
76
105
  onAttachFiles = _ref.onAttachFiles,
77
106
  onAttachmentRemove = _ref.onAttachmentRemove,
107
+ onAttachmentRetry = _ref.onAttachmentRetry,
78
108
  _ref$attachmentsDisab = _ref.attachmentsDisabled,
79
109
  attachmentsDisabled = _ref$attachmentsDisab === void 0 ? false : _ref$attachmentsDisab,
80
110
  _ref$maxFileCount = _ref.maxFileCount,
81
111
  maxFileCount = _ref$maxFileCount === void 0 ? 5 : _ref$maxFileCount,
82
112
  _ref$maxFileSize = _ref.maxFileSize,
83
113
  maxFileSize = _ref$maxFileSize === void 0 ? 20 * 1024 * 1024 : _ref$maxFileSize,
114
+ maxTotalSize = _ref.maxTotalSize,
115
+ _ref$accept = _ref.accept,
116
+ accept = _ref$accept === void 0 ? DEFAULT_ACCEPT : _ref$accept,
84
117
  renderParamPanel = _ref.renderParamPanel,
85
118
  className = _ref.className,
86
119
  style = _ref.style;
@@ -299,29 +332,38 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
299
332
  }
300
333
  return _context.abrupt("return");
301
334
  case 2:
335
+ if (!attachments.some(function (a) {
336
+ var _a$status;
337
+ return ((_a$status = a.status) !== null && _a$status !== void 0 ? _a$status : 'done') === 'uploading';
338
+ })) {
339
+ _context.next = 4;
340
+ break;
341
+ }
342
+ return _context.abrupt("return");
343
+ case 4:
302
344
  chips = (_editorRef$current$ge2 = (_editorRef$current10 = editorRef.current) === null || _editorRef$current10 === void 0 ? void 0 : _editorRef$current10.getChips()) !== null && _editorRef$current$ge2 !== void 0 ? _editorRef$current$ge2 : [];
303
345
  segments = rawValueToSegments(text, chips);
304
346
  hasAttachments = attachments.length > 0;
305
347
  if (!(!segmentsHasContent(segments) && !hasAttachments)) {
306
- _context.next = 7;
348
+ _context.next = 9;
307
349
  break;
308
350
  }
309
351
  return _context.abrupt("return");
310
- case 7:
352
+ case 9:
311
353
  meta = {};
312
354
  if (hasAttachments) meta.attachments = attachments;
313
355
  if (webSearch) meta.webSearch = true;
314
356
  hasMeta = hasAttachments || webSearch;
315
- _context.next = 13;
357
+ _context.next = 15;
316
358
  return onSend(segments, hasMeta ? meta : undefined);
317
- case 13:
359
+ case 15:
318
360
  result = _context.sent;
319
361
  if (!(result === false)) {
320
- _context.next = 16;
362
+ _context.next = 18;
321
363
  break;
322
364
  }
323
365
  return _context.abrupt("return");
324
- case 16:
366
+ case 18:
325
367
  closeParamPanel();
326
368
  if (valueProp === undefined) {
327
369
  (_editorRef$current11 = editorRef.current) === null || _editorRef$current11 === void 0 || _editorRef$current11.clear();
@@ -330,7 +372,7 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
330
372
  setAttachments([]);
331
373
  }
332
374
  setWebSearch(false);
333
- case 20:
375
+ case 22:
334
376
  case "end":
335
377
  return _context.stop();
336
378
  }
@@ -350,24 +392,28 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
350
392
  if (fileArray.length === 0) return;
351
393
  var remaining = maxFileCount - attachments.length;
352
394
  if (remaining <= 0) {
353
- Message.warning("\u81F3\u591A\u652F\u6301\u6DFB\u52A0 ".concat(maxFileCount, " \u4E2A\u6587\u4EF6"));
395
+ Message.warning("\u6700\u591A\u652F\u6301\u540C\u65F6\u4E0A\u4F20 ".concat(maxFileCount, " \u4E2A\u6587\u4EF6"));
396
+ return;
397
+ }
398
+ if (fileArray.length > remaining) {
399
+ Message.warning("\u6700\u591A\u652F\u6301\u540C\u65F6\u4E0A\u4F20 ".concat(maxFileCount, " \u4E2A\u6587\u4EF6"));
354
400
  return;
355
401
  }
356
402
  var acceptedFiles = [];
357
- var oversized = 0;
403
+ var unsupportedExt = '';
404
+ var oversizedName = '';
358
405
  var duplicated = 0;
359
- var overCount = 0;
360
406
  var _iterator = _createForOfIteratorHelper(fileArray),
361
407
  _step;
362
408
  try {
363
409
  var _loop = function _loop() {
364
410
  var f = _step.value;
365
- if (acceptedFiles.length >= remaining) {
366
- overCount++;
411
+ if (!isFileAccepted(f, accept)) {
412
+ unsupportedExt = getFileExt(f.name) || f.type || '该类型';
367
413
  return 0; // continue
368
414
  }
369
415
  if (f.size > maxFileSize) {
370
- oversized++;
416
+ oversizedName = f.name;
371
417
  return 0; // continue
372
418
  }
373
419
  if (attachments.some(function (a) {
@@ -390,11 +436,27 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
390
436
  } finally {
391
437
  _iterator.f();
392
438
  }
393
- var sizeLabel = "".concat(Math.round(maxFileSize / 1024 / 1024), "MB");
394
- if (oversized > 0) Message.warning("\u6587\u4EF6\u5927\u5C0F\u81F3\u591A\u4E3A ".concat(sizeLabel));
439
+ if (unsupportedExt) {
440
+ Message.warning("\u4E0D\u652F\u6301\u300C".concat(unsupportedExt.replace(/^\./, '').toUpperCase(), "\u300D\u683C\u5F0F"));
441
+ }
442
+ if (oversizedName) {
443
+ Message.warning("\u300C".concat(oversizedName, "\u300D\u8D85\u8FC7 ").concat(formatSizeMb(maxFileSize), "\uFF0C\u8BF7\u538B\u7F29\u540E\u91CD\u8BD5"));
444
+ }
395
445
  if (duplicated > 0) Message.warning('请不要重复添加文件');
396
- if (overCount > 0) Message.warning("\u81F3\u591A\u652F\u6301\u6DFB\u52A0 ".concat(maxFileCount, " \u4E2A\u6587\u4EF6"));
397
446
  if (acceptedFiles.length === 0) return;
447
+ if (maxTotalSize !== undefined) {
448
+ var existingSize = attachments.reduce(function (sum, a) {
449
+ var _a$size;
450
+ return sum + ((_a$size = a.size) !== null && _a$size !== void 0 ? _a$size : 0);
451
+ }, 0);
452
+ var incomingSize = acceptedFiles.reduce(function (sum, f) {
453
+ return sum + f.size;
454
+ }, 0);
455
+ if (existingSize + incomingSize > maxTotalSize) {
456
+ Message.warning("\u672C\u6B21\u6587\u4EF6\u603B\u5927\u5C0F\u8D85\u8FC7 ".concat(formatSizeMb(maxTotalSize), "\uFF0C\u8BF7\u51CF\u5C11\u540E\u91CD\u8BD5"));
457
+ return;
458
+ }
459
+ }
398
460
  if (onAttachFiles) {
399
461
  onAttachFiles(acceptedFiles);
400
462
  return;
@@ -406,11 +468,12 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
406
468
  name: f.name,
407
469
  type: f.type,
408
470
  size: f.size,
409
- url: url
471
+ url: url,
472
+ status: 'done'
410
473
  };
411
474
  });
412
475
  updateAttachments([].concat(_toConsumableArray(attachments), _toConsumableArray(accepted)));
413
- }, [attachments, attachmentsDisabled, disabled, maxFileCount, maxFileSize, onAttachFiles, updateAttachments]);
476
+ }, [accept, attachments, attachmentsDisabled, disabled, maxFileCount, maxFileSize, maxTotalSize, onAttachFiles, updateAttachments]);
414
477
  var handleFileChange = function handleFileChange(e) {
415
478
  var files = e.target.files;
416
479
  if (!files) return;
@@ -424,6 +487,7 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
424
487
  var composerBoxFileDragAttrs = fileDragOver ? {
425
488
  'data-odn-composer-file-drag': ''
426
489
  } : {};
490
+ var showFileDragOverlay = fileDragOver && !disabled && !attachmentsDisabled;
427
491
  var handleComposerDragEnter = function handleComposerDragEnter(e) {
428
492
  e.preventDefault();
429
493
  if (disabled || attachmentsDisabled) return;
@@ -547,7 +611,11 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
547
611
  }, [triggerInfo]);
548
612
 
549
613
  /* ---- Derived ---- */
550
- var canSend = text.trim() || attachments.length > 0;
614
+ var hasUploadingAttachment = attachments.some(function (a) {
615
+ var _a$status2;
616
+ return ((_a$status2 = a.status) !== null && _a$status2 !== void 0 ? _a$status2 : 'done') === 'uploading';
617
+ });
618
+ var canSend = !hasUploadingAttachment && (text.trim() || attachments.length > 0);
551
619
  var isLite = variant === 'lite';
552
620
  // lite 单行态:未主动升格即为单行(附件不触发升格,仅撑高 box 容纳附件条)
553
621
  var isInlineLite = isLite && !expanded;
@@ -676,24 +744,18 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
676
744
  var hasTools = toolNodes.length > 0;
677
745
 
678
746
  /* ---- Slots ----
679
- * 待发送区按 type 分流:
680
- * - 图片(image/* + url)→ Image leaf + 72×72 cover wrap,输入态用模板
681
- * 驱动尺寸(整齐划一比保留长宽比要紧)
682
- * - 其他附件 Attachments,保持原 file-card 渲染
747
+ * 待发送区图片与文件「同源不分流」:统一走一个 <Attachments>。
748
+ * - 图片(image/* + url)映射到 variant='image-thumb':大缩略方块
749
+ * - 文件:默认 file-card
750
+ * 两者共享 Attachments 内的三态机 / remove 角标 / fresh-done,不再各写一套。
683
751
  *
684
752
  * 删除:按 internalBlobUrlsRef 判断是否需要 revoke,避免误 revoke 业务方
685
753
  * 的云端 url;同时派发 onAttachmentRemove(语义钩子,便于业务调"服务端
686
754
  * 删文件")与 onAttachmentsChange。
687
- *
688
- * 分流子集与原 attachments 的 index 不一致,对外回调(onAttachmentRemove)
689
- * 用 attachments.indexOf 拿到原始 index,保持业务方语义。 */
755
+ */
690
756
  var isImageAttachment = function isImageAttachment(a) {
691
757
  return a.type.startsWith('image/') && !!a.url;
692
758
  };
693
- var composerImages = attachments.filter(isImageAttachment);
694
- var composerFiles = attachments.filter(function (a) {
695
- return !isImageAttachment(a);
696
- });
697
759
  var removeAttachmentAt = function removeAttachmentAt(i) {
698
760
  var removed = attachments[i];
699
761
  if (removed !== null && removed !== void 0 && removed.url && internalBlobUrlsRef.current.has(removed.url)) {
@@ -706,27 +768,23 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
706
768
  if (removed) onAttachmentRemove === null || onAttachmentRemove === void 0 || onAttachmentRemove(i, removed);
707
769
  updateAttachments(next);
708
770
  };
771
+
772
+ /* 图片映射到 image-thumb 变体;其余原样。索引与 attachments 1:1 对齐,
773
+ * 故 onRemove(i) / onRetry(i) 可直接回指 attachments[i]。
774
+ * 业务已自带 variant(如 thumb-card)时不覆盖。 */
775
+ var composerAttachments = attachments.map(function (a) {
776
+ return isImageAttachment(a) && !a.variant ? _objectSpread(_objectSpread({}, a), {}, {
777
+ variant: 'image-thumb'
778
+ }) : a;
779
+ });
709
780
  var attachmentsSlot = attachments.length > 0 ? /*#__PURE__*/React.createElement("div", {
710
781
  "data-odn-composer-attachments": true
711
- }, composerImages.length > 0 && /*#__PURE__*/React.createElement("div", {
712
- "data-odn-composer-images": true
713
- }, composerImages.map(function (img) {
714
- var realIdx = attachments.indexOf(img);
715
- return /*#__PURE__*/React.createElement("div", {
716
- key: "".concat(img.name, "-").concat(realIdx),
717
- "data-odn-composer-image-thumb": true
718
- }, /*#__PURE__*/React.createElement(Image, {
719
- url: img.url,
720
- alt: img.name,
721
- onRemove: function onRemove() {
722
- return removeAttachmentAt(realIdx);
723
- }
724
- }));
725
- })), composerFiles.length > 0 && /*#__PURE__*/React.createElement(Attachments, {
726
- attachments: composerFiles,
727
- onRemove: function onRemove(i) {
728
- return removeAttachmentAt(attachments.indexOf(composerFiles[i]));
729
- }
782
+ }, /*#__PURE__*/React.createElement(Attachments, {
783
+ attachments: composerAttachments,
784
+ onRemove: removeAttachmentAt,
785
+ onRetry: onAttachmentRetry ? function (i) {
786
+ return onAttachmentRetry(i, attachments[i]);
787
+ } : undefined
730
788
  })) : null;
731
789
 
732
790
  /* 状态优先级:disabled > isGenerating > canSend
@@ -764,7 +822,7 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
764
822
  ref: fileInputRef,
765
823
  type: "file",
766
824
  multiple: true,
767
- accept: "image/*,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.md,.csv,.json,.xml,.html,.css,.js,.ts,.jsx,.tsx,.py,.java,.go,.rs,.c,.cpp,.zip,.rar,.7z",
825
+ accept: accept,
768
826
  "data-odn-composer-file-input": true,
769
827
  onChange: handleFileChange
770
828
  });
@@ -903,7 +961,13 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
903
961
  "data-odn-composer-lite-tools": true
904
962
  }, toolNodes), isLite && /*#__PURE__*/React.createElement("div", {
905
963
  "data-odn-composer-lite-send": true
906
- }, sendOrStopButton)), hint && /*#__PURE__*/React.createElement("p", {
964
+ }, sendOrStopButton), showFileDragOverlay && /*#__PURE__*/React.createElement("div", {
965
+ "data-odn-composer-file-drag-overlay": true,
966
+ "aria-hidden": true
967
+ }, /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement(Icon, {
968
+ name: "paperclip",
969
+ size: 14
970
+ }), "\u62D6\u653E\u6587\u4EF6\u5230\u6B64\u5904\u4E0A\u4F20"))), hint && /*#__PURE__*/React.createElement("p", {
907
971
  "data-odn-composer-hint": true
908
972
  }, submitType === 'enter' ? 'Enter 发送 · Shift+Enter 换行 · 可拖入或粘贴文件' : 'Shift+Enter 发送 · Enter 换行 · 可拖入或粘贴文件')));
909
973
  });
@@ -14,6 +14,7 @@
14
14
  }
15
15
 
16
16
  [data-odn-composer-box] {
17
+ position: relative;
17
18
  display: flex;
18
19
  flex-direction: column;
19
20
  /* gap:在 box 三个 flex item(attachments / editor / toolbar)之间统一垂直留白;
@@ -34,6 +35,42 @@
34
35
  background: color-mix(in srgb, var(--odn-color-brand-6) 6%, var(--odn-color-bg-elevated));
35
36
  }
36
37
 
38
+ [data-odn-composer-file-drag-overlay] {
39
+ position: absolute;
40
+ inset: 0;
41
+ border-radius: inherit;
42
+ background: color-mix(in srgb, var(--odn-color-brand-6) 8%, transparent);
43
+ backdrop-filter: blur(4px);
44
+ -webkit-backdrop-filter: blur(4px);
45
+ display: flex;
46
+ align-items: center;
47
+ justify-content: center;
48
+ pointer-events: none;
49
+ z-index: 4;
50
+ }
51
+ [data-odn-composer-file-drag-overlay] span {
52
+ display: inline-flex;
53
+ align-items: center;
54
+ gap: 6px;
55
+ color: var(--odn-color-brand-6);
56
+ font-size: 14px;
57
+ line-height: 24px;
58
+ font-weight: 600;
59
+ }
60
+
61
+ /* 拖放蒙层出现时,冻结内部交互样式事件;保留 box 自身 drop 能力。 */
62
+ [data-odn-composer-box][data-odn-composer-file-drag] [data-odn-composer-editor],
63
+ [data-odn-composer-box][data-odn-composer-file-drag] [data-odn-composer-toolbar],
64
+ [data-odn-composer-box][data-odn-composer-file-drag] [data-odn-composer-lite-tools],
65
+ [data-odn-composer-box][data-odn-composer-file-drag] [data-odn-composer-lite-send],
66
+ [data-odn-composer-box][data-odn-composer-file-drag] [data-odn-composer-attachments] {
67
+ pointer-events: none !important;
68
+ }
69
+ [data-odn-composer-box][data-odn-composer-file-drag] [data-odn-composer-editor] {
70
+ caret-color: transparent;
71
+ user-select: none;
72
+ }
73
+
37
74
  /* ------------------------------------------------------------------
38
75
  * lite variant:
39
76
  * tools 和 send 按钮 absolute 在 box 的左下/右下;
@@ -428,32 +465,30 @@ p[data-odn-composer-hint] {
428
465
  }
429
466
 
430
467
  /* ------------------------------------------------------------------
431
- * 待发送区图片缩略
432
- * 待发送态用模板驱动尺寸(72×72 cover),与 MessageImage 消息态的
433
- * 数据驱动尺寸(单图 max 280×360 contain)形成对比:
434
- * - 输入态用户聚焦于"我加了哪些",整齐划一比保留长宽比要紧
435
- * - 模板尺寸还能让多图横排清爽不参差
436
- * 通过给 Image leaf 容器套尺寸 + 内部 img 用 cover 实现。
468
+ * 待发送区附件
469
+ * 图片与文件同源不分流:统一由 <Attachments> 渲染(图片走 image-thumb
470
+ * 变体、文件走 file-card)。本处只负责"同一行流式排列 + 统一高度",
471
+ * 三态机 / remove 角标 / fresh-done 全部下沉到 Attachments 组件。
437
472
  * ----------------------------------------------------------------- */
438
- [data-odn-composer-images] {
473
+ [data-odn-composer-attachments] {
474
+ --odn-composer-attachment-h: 42px;
439
475
  display: flex;
440
476
  flex-wrap: wrap;
477
+ align-items: flex-start;
441
478
  gap: 6px;
479
+ /* 文件卡 / 缩略卡高度;宽度沿用各自原规则。 */
442
480
  }
443
-
444
- [data-odn-composer-image-thumb] {
445
- width: 72px;
446
- height: 72px;
447
- border-radius: 6px;
448
- overflow: hidden;
481
+ [data-odn-composer-attachments] [data-odn-attachments-card],
482
+ [data-odn-composer-attachments] [data-odn-attachments-thumb-card] {
483
+ min-height: var(--odn-composer-attachment-h);
449
484
  }
450
- [data-odn-composer-image-thumb] [data-odn-image] {
451
- display: block;
452
- width: 100%;
453
- height: 100%;
485
+ [data-odn-composer-attachments] {
486
+ /* 图片缩略图高度跟随文件卡——同一变量驱动,与文件卡同行等高。 */
454
487
  }
455
- [data-odn-composer-image-thumb] [data-odn-image] img {
456
- width: 100%;
457
- height: 100%;
458
- object-fit: cover;
488
+ [data-odn-composer-attachments] [data-odn-attachments-image-thumb] {
489
+ width: var(--odn-composer-attachment-h);
490
+ height: var(--odn-composer-attachment-h);
491
+ }
492
+ [data-odn-composer-attachments] [data-odn-attachments] {
493
+ gap: 6px;
459
494
  }
package/dist/index.d.ts CHANGED
@@ -72,6 +72,7 @@ export { default as PreviewPanel, type PreviewPanelProps } from './preview-panel
72
72
  export { default as Sources, type SourcesProps } from './sources';
73
73
  export { default as Provenance, type ProvenanceProps, type ProvenanceType } from './provenance';
74
74
  export { default as StreamText, type StreamTextProps, type TypographyOverrides } from './stream-text';
75
+ export { default as StreamPulse, type StreamPulseProps } from './stream-pulse';
75
76
  export { default as Suggestions, type SuggestionsProps } from './suggestions';
76
77
  export { default as UserBubble, type UserBubbleProps } from './user-bubble';
77
78
  export { default as Welcome, type WelcomeProps } from './welcome';
package/dist/index.js CHANGED
@@ -77,6 +77,7 @@ export { default as PreviewPanel } from "./preview-panel";
77
77
  export { default as Sources } from "./sources";
78
78
  export { default as Provenance } from "./provenance";
79
79
  export { default as StreamText } from "./stream-text";
80
+ export { default as StreamPulse } from "./stream-pulse";
80
81
  export { default as Suggestions } from "./suggestions";
81
82
  export { default as UserBubble } from "./user-bubble";
82
83
  export { default as Welcome } from "./welcome";
@@ -0,0 +1,16 @@
1
+ import type { HTMLAttributes } from 'react';
2
+ import './style';
3
+ export interface StreamPulseProps extends HTMLAttributes<HTMLDivElement> {
4
+ size?: number;
5
+ /** ActionBar 锚点模式:保留 min-height 32px,与 ActionBar 高度对齐 */
6
+ anchor?: boolean;
7
+ }
8
+ /**
9
+ * StreamPulse —— 流式生成中的风车旋转锚点。
10
+ * 几何来自 lucide loader 8 射线;CSS 线性旋转,零 JS 驱动。
11
+ */
12
+ export declare function StreamPulse({ size, anchor, 'aria-label': ariaLabel, ...props }: StreamPulseProps): import("react").JSX.Element;
13
+ export declare namespace StreamPulse {
14
+ var displayName: string;
15
+ }
16
+ export default StreamPulse;
@@ -0,0 +1,44 @@
1
+ var _excluded = ["size", "anchor", "aria-label"];
2
+ function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
3
+ function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
4
+ function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
5
+ import "./style";
6
+ var PULSE_PATHS = ['M12 2v4', 'm16.2 7.8 2.9-2.9', 'M18 12h4', 'm16.2 16.2 2.9 2.9', 'M12 18v4', 'm4.9 19.1 2.9-2.9', 'M2 12h4', 'm4.9 4.9 2.9 2.9'];
7
+
8
+ /**
9
+ * StreamPulse —— 流式生成中的风车旋转锚点。
10
+ * 几何来自 lucide loader 8 射线;CSS 线性旋转,零 JS 驱动。
11
+ */
12
+ export function StreamPulse(_ref) {
13
+ var _ref$size = _ref.size,
14
+ size = _ref$size === void 0 ? 16 : _ref$size,
15
+ _ref$anchor = _ref.anchor,
16
+ anchor = _ref$anchor === void 0 ? false : _ref$anchor,
17
+ _ref$ariaLabel = _ref['aria-label'],
18
+ ariaLabel = _ref$ariaLabel === void 0 ? '正在生成回复' : _ref$ariaLabel,
19
+ props = _objectWithoutProperties(_ref, _excluded);
20
+ return /*#__PURE__*/React.createElement("div", _extends({
21
+ "data-odn-stream-pulse": true,
22
+ "data-odn-stream-pulse-anchor": anchor || undefined,
23
+ role: "status",
24
+ "aria-label": ariaLabel
25
+ }, props), /*#__PURE__*/React.createElement("svg", {
26
+ xmlns: "http://www.w3.org/2000/svg",
27
+ width: size,
28
+ height: size,
29
+ viewBox: "0 0 24 24",
30
+ fill: "none",
31
+ stroke: "currentColor",
32
+ strokeWidth: "2",
33
+ strokeLinecap: "round",
34
+ strokeLinejoin: "round",
35
+ "aria-hidden": "true"
36
+ }, PULSE_PATHS.map(function (d) {
37
+ return /*#__PURE__*/React.createElement("path", {
38
+ key: d,
39
+ d: d
40
+ });
41
+ })));
42
+ }
43
+ StreamPulse.displayName = 'StreamPulse';
44
+ export default StreamPulse;
@@ -0,0 +1,18 @@
1
+ [data-odn-stream-pulse] {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ justify-content: center;
5
+ color: var(--odn-color-black-9);
6
+ transform-origin: center;
7
+ animation: odn-stream-pulse-spin 1.5s linear infinite;
8
+ }
9
+ [data-odn-stream-pulse][data-odn-stream-pulse-anchor] {
10
+ justify-content: flex-start;
11
+ min-height: 32px;
12
+ }
13
+
14
+ @keyframes odn-stream-pulse-spin {
15
+ to {
16
+ transform: rotate(360deg);
17
+ }
18
+ }
@@ -0,0 +1,2 @@
1
+ import '../../style';
2
+ import './index.scss';
@@ -0,0 +1,2 @@
1
+ import "../../style";
2
+ import "./index.css";
@@ -20,6 +20,7 @@ export interface TreeSelectProps extends Omit<RcTreeSelectProps, 'treeData'> {
20
20
  showInnerSearch?: boolean;
21
21
  light?: boolean;
22
22
  popupRender?: (menu: React.ReactElement) => React.ReactElement;
23
+ checkStrictly?: boolean;
23
24
  }
24
25
  declare const TreeSelect: React.FC<TreeSelectProps>;
25
26
  export default TreeSelect;
@@ -1,5 +1,4 @@
1
- function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
- var _excluded = ["mode", "suffixIcon", "visible", "onVisibleChange", "treeCheckable", "className", "showInnerSearch", "light", "popupRender", "searchValue", "onSearch"];
1
+ var _excluded = ["mode", "suffixIcon", "visible", "onVisibleChange", "treeCheckable", "className", "showInnerSearch", "light", "popupRender", "searchValue", "onSearch", "checkStrictly", "value", "defaultValue", "onChange"];
3
2
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
4
3
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
5
4
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
@@ -14,13 +13,31 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
14
13
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
15
14
  function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
16
15
  function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
16
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
17
17
  import clsx from 'clsx';
18
18
  import RcTreeSelect from 'rc-tree-select';
19
- import React, { useEffect, useRef, useState } from 'react';
19
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
20
20
  import Icon from "../icon";
21
21
  import "../select/style";
22
22
  import useIcons from "../select/useIcons";
23
23
  import "./style";
24
+ function toLabelInValue(val) {
25
+ if (val === undefined || val === null) return undefined;
26
+ var arr = Array.isArray(val) ? val : [val];
27
+ return arr.map(function (v) {
28
+ return _typeof(v) === 'object' && v !== null && 'value' in v ? v : {
29
+ value: v,
30
+ label: v
31
+ };
32
+ });
33
+ }
34
+ function toSimpleValues(val) {
35
+ if (val === undefined || val === null) return [];
36
+ var arr = Array.isArray(val) ? val : [val];
37
+ return arr.map(function (v) {
38
+ return v.value;
39
+ });
40
+ }
24
41
  var TreeSelect = function TreeSelect(_ref) {
25
42
  var mode = _ref.mode,
26
43
  _ref$suffixIcon = _ref.suffixIcon,
@@ -39,8 +56,31 @@ var TreeSelect = function TreeSelect(_ref) {
39
56
  popupRender = _ref.popupRender,
40
57
  searchValueProp = _ref.searchValue,
41
58
  onSearch = _ref.onSearch,
59
+ _ref$checkStrictly = _ref.checkStrictly,
60
+ checkStrictly = _ref$checkStrictly === void 0 ? false : _ref$checkStrictly,
61
+ valueProp = _ref.value,
62
+ defaultValueProp = _ref.defaultValue,
63
+ onChangeProp = _ref.onChange,
42
64
  rest = _objectWithoutProperties(_ref, _excluded);
43
65
  var isMultiple = mode === 'multiple';
66
+ var rcValue = useMemo(function () {
67
+ return checkStrictly ? toLabelInValue(valueProp) : valueProp;
68
+ }, [checkStrictly, valueProp]);
69
+ var rcDefaultValue = useMemo(function () {
70
+ return checkStrictly ? toLabelInValue(defaultValueProp) : defaultValueProp;
71
+ }, [checkStrictly, defaultValueProp]);
72
+ var rcOnChange = useCallback(function () {
73
+ if (!onChangeProp) return;
74
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
75
+ args[_key] = arguments[_key];
76
+ }
77
+ if (checkStrictly) {
78
+ var simpleValues = toSimpleValues(args[0]);
79
+ onChangeProp(simpleValues, args[1], args[2]);
80
+ } else {
81
+ onChangeProp.apply(void 0, args);
82
+ }
83
+ }, [checkStrictly, onChangeProp]);
44
84
  var _useIcons = useIcons(_objectSpread(_objectSpread({}, rest), {}, {
45
85
  multiple: isMultiple,
46
86
  hasFeedback: false,
@@ -102,7 +142,8 @@ var TreeSelect = function TreeSelect(_ref) {
102
142
  treeCheckable: isMultiple ? treeCheckable ? /*#__PURE__*/React.createElement("span", {
103
143
  className: "odn-select-tree-checkbox-inner"
104
144
  }) : treeCheckable : false,
105
- showCheckedStrategy: "SHOW_PARENT",
145
+ treeCheckStrictly: checkStrictly,
146
+ showCheckedStrategy: checkStrictly ? 'SHOW_ALL' : 'SHOW_PARENT',
106
147
  searchValue: searchValue,
107
148
  dropdownRender: function dropdownRender(menu) {
108
149
  var searchNode = showInnerSearch ? /*#__PURE__*/React.createElement("div", {
@@ -133,7 +174,10 @@ var TreeSelect = function TreeSelect(_ref) {
133
174
  var content = /*#__PURE__*/React.createElement(React.Fragment, null, searchNode, menu);
134
175
  return popupRender ? popupRender(content) : content;
135
176
  },
136
- notFoundContent: "\u65E0\u5339\u914D\u7ED3\u679C"
177
+ notFoundContent: "\u65E0\u5339\u914D\u7ED3\u679C",
178
+ value: rcValue,
179
+ defaultValue: rcDefaultValue,
180
+ onChange: rcOnChange
137
181
  }, rest));
138
182
  };
139
183
  TreeSelect.displayName = 'TreeSelect';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "one-design-next",
3
- "version": "0.0.32",
3
+ "version": "0.0.34",
4
4
  "description": "One Design Next from TAD@tencent.com",
5
5
  "packageManager": "pnpm@10.33.0",
6
6
  "module": "dist/index.js",