one-design-next 0.0.59 → 0.0.61

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,4 +1,5 @@
1
1
  /// <reference types="react" />
2
+ import type { IconName } from '../icon';
2
3
  import type { Attachment, ComposerSegment, SkillGroup, SkillItem, SendMeta } from '../_genui-types';
3
4
  import type { ChipData } from '../_genui-types';
4
5
  import type { ComposerParamPanelContext } from './param-panel';
@@ -7,6 +8,20 @@ export type { ComposerParamPanelContext } from './param-panel';
7
8
  export type ComposerTool = 'attachment' | 'webSearch' | 'skill';
8
9
  export type ComposerVariant = 'full' | 'lite';
9
10
  export type SubmitType = 'enter' | 'shiftEnter';
11
+ /**
12
+ * 工具按钮的自定义配置。
13
+ * - `icon`:图标名称(Icon 组件的 name),字段不传则不渲染图标。
14
+ * - `label`:按钮文字,字段不传则不渲染文字。
15
+ * - 整个配置对象不传(key 不存在于 `toolConfigs`)时使用内置默认值。
16
+ * - 传了配置对象但 icon / label 字段都未设置时,兜底显示工具英文名
17
+ * (如 "attachment" / "webSearch" / "skill")作为 label,无图标,
18
+ * 方便开发者一眼看出配置遗漏。
19
+ */
20
+ export interface ComposerToolConfig {
21
+ /** 图标名称,类型与 Icon 组件的 name 一致 */
22
+ icon?: IconName | (string & {});
23
+ label?: string;
24
+ }
10
25
  export interface ComposerRef {
11
26
  /** 聚焦输入框 */
12
27
  focus: (options?: FocusOptions) => void;
@@ -102,6 +117,28 @@ export interface ComposerProps {
102
117
  * @default true
103
118
  */
104
119
  toolsLabeled?: boolean;
120
+ /**
121
+ * 各工具按钮的自定义配置(icon / label)。按 `ComposerTool` 类型做 key:
122
+ * - `attachment`:附件按钮
123
+ * - `webSearch`:联网按钮
124
+ * - `skill`:技能按钮
125
+ *
126
+ * **语义约定**:
127
+ * - key 不存在于 `toolConfigs` → 使用内置默认值(如附件 = paperclip + '附件')
128
+ * - key 存在但配置对象中只有 `icon` → 只渲染图标
129
+ * - key 存在但配置对象中只有 `label` → 只渲染文字
130
+ * - key 存在但配置对象为空 `{}` → 兜底显示工具英文名(如 "attachment")作为 label,无图标
131
+ *
132
+ * @example
133
+ * ```tsx
134
+ * toolConfigs={{
135
+ * attachment: { icon: 'paperclip', label: '上传' },
136
+ * webSearch: { label: '搜索' }, // 仅文字
137
+ * skill: { icon: 'command' }, // 仅图标
138
+ * }}
139
+ * ```
140
+ */
141
+ toolConfigs?: Partial<Record<ComposerTool, ComposerToolConfig>>;
105
142
  /** 技能列表;当 tools 包含 'skill' 时生效 */
106
143
  skills?: SkillItem[];
107
144
  /**
@@ -55,7 +55,32 @@ function isFileAccepted(file, accept) {
55
55
  return !!mime && mime === rule;
56
56
  });
57
57
  }
58
+
59
+ /**
60
+ * 工具按钮的自定义配置。
61
+ * - `icon`:图标名称(Icon 组件的 name),字段不传则不渲染图标。
62
+ * - `label`:按钮文字,字段不传则不渲染文字。
63
+ * - 整个配置对象不传(key 不存在于 `toolConfigs`)时使用内置默认值。
64
+ * - 传了配置对象但 icon / label 字段都未设置时,兜底显示工具英文名
65
+ * (如 "attachment" / "webSearch" / "skill")作为 label,无图标,
66
+ * 方便开发者一眼看出配置遗漏。
67
+ */
68
+
58
69
  var DEFAULT_TOOLS = ['attachment', 'webSearch', 'skill'];
70
+ var DEFAULT_TOOL_CONFIGS = {
71
+ attachment: {
72
+ icon: 'paperclip',
73
+ label: '附件'
74
+ },
75
+ webSearch: {
76
+ icon: 'globe',
77
+ label: '联网'
78
+ },
79
+ skill: {
80
+ icon: 'command',
81
+ label: '技能'
82
+ }
83
+ };
59
84
  export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
60
85
  var _paramEdit$chipId;
61
86
  var valueProp = _ref.value,
@@ -80,6 +105,7 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
80
105
  tools = _ref$tools === void 0 ? DEFAULT_TOOLS : _ref$tools,
81
106
  _ref$toolsLabeled = _ref.toolsLabeled,
82
107
  toolsLabeled = _ref$toolsLabeled === void 0 ? true : _ref$toolsLabeled,
108
+ toolConfigs = _ref.toolConfigs,
83
109
  skills = _ref.skills,
84
110
  skillGroups = _ref.skillGroups,
85
111
  onManageSkills = _ref.onManageSkills,
@@ -640,6 +666,26 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
640
666
  var effectiveLabeled = isLite ? false : toolsLabeled;
641
667
  // lite 模式下仅允许一个工具按钮(数量在两态下保持恒定)
642
668
  var effectiveTools = isLite ? tools.slice(0, 1) : tools;
669
+
670
+ /* 统一解析 toolConfigs:
671
+ * - 不传 toolConfigs → 全部用 DEFAULT_TOOL_CONFIGS
672
+ * - 传了 toolConfigs → 每个 key 看用户配置:有 icon 或 label 就用它,否则兜底 { label: key }
673
+ */
674
+ var resolvedToolConfigs = function () {
675
+ if (!toolConfigs) return DEFAULT_TOOL_CONFIGS;
676
+ var resolve = function resolve(key) {
677
+ var cfg = toolConfigs[key];
678
+ if (cfg && (cfg.icon || cfg.label)) return cfg;
679
+ return {
680
+ label: key
681
+ };
682
+ };
683
+ return {
684
+ attachment: resolve('attachment'),
685
+ webSearch: resolve('webSearch'),
686
+ skill: resolve('skill')
687
+ };
688
+ }();
643
689
  if (process.env.NODE_ENV !== 'production' && isLite && tools.length > 1) {
644
690
  // eslint-disable-next-line no-console
645
691
  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"));
@@ -652,6 +698,11 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
652
698
  * skill 的 Popover 在 disabled 时禁用 trigger,避免弹出菜单。 */
653
699
  var renderAttachmentBtn = function renderAttachmentBtn() {
654
700
  var btnDisabled = disabled || attachmentsDisabled;
701
+ var _resolvedToolConfigs$ = resolvedToolConfigs.attachment,
702
+ icon = _resolvedToolConfigs$.icon,
703
+ label = _resolvedToolConfigs$.label;
704
+ var showIcon = !!icon;
705
+ var showLabel = effectiveLabeled && !!label;
655
706
  return /*#__PURE__*/React.createElement(HoverFill, {
656
707
  key: "attachment",
657
708
  "data-odn-composer-tool-btn-wrap": true,
@@ -672,17 +723,22 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
672
723
  },
673
724
  disabled: btnDisabled,
674
725
  "data-odn-composer-tool-btn": true,
675
- "data-odn-composer-tool-iconic": !effectiveLabeled || undefined,
726
+ "data-odn-composer-tool-iconic": !showLabel || undefined,
676
727
  "data-odn-composer-tool-disabled": btnDisabled || undefined,
677
- "aria-label": "\u9644\u4EF6",
728
+ "aria-label": label || 'attachment',
678
729
  "aria-disabled": btnDisabled || undefined,
679
- title: effectiveLabeled ? undefined : '附件'
680
- }, /*#__PURE__*/React.createElement(Icon, {
681
- name: "paperclip",
730
+ title: showLabel ? undefined : label || 'attachment'
731
+ }, showIcon && /*#__PURE__*/React.createElement(Icon, {
732
+ name: icon,
682
733
  size: 16
683
- }), effectiveLabeled && /*#__PURE__*/React.createElement("span", null, "\u9644\u4EF6")));
734
+ }), showLabel && /*#__PURE__*/React.createElement("span", null, label)));
684
735
  };
685
736
  var renderWebSearchBtn = function renderWebSearchBtn() {
737
+ var _resolvedToolConfigs$2 = resolvedToolConfigs.webSearch,
738
+ icon = _resolvedToolConfigs$2.icon,
739
+ label = _resolvedToolConfigs$2.label;
740
+ var showIcon = !!icon;
741
+ var showLabel = effectiveLabeled && !!label;
686
742
  return /*#__PURE__*/React.createElement(HoverFill, {
687
743
  key: "webSearch",
688
744
  "data-odn-composer-tool-btn-wrap": true,
@@ -703,23 +759,28 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
703
759
  },
704
760
  disabled: disabled,
705
761
  "data-odn-composer-tool-btn": true,
706
- "data-odn-composer-tool-iconic": !effectiveLabeled || undefined,
762
+ "data-odn-composer-tool-iconic": !showLabel || undefined,
707
763
  "data-odn-composer-tool-active": webSearch || undefined,
708
764
  "data-odn-composer-tool-disabled": disabled || undefined,
709
- "aria-label": "\u8054\u7F51",
765
+ "aria-label": label || 'webSearch',
710
766
  "aria-pressed": webSearch,
711
767
  "aria-disabled": disabled || undefined,
712
- title: effectiveLabeled ? undefined : '联网'
713
- }, /*#__PURE__*/React.createElement(Icon, {
714
- name: "globe",
768
+ title: showLabel ? undefined : label || 'webSearch'
769
+ }, showIcon && /*#__PURE__*/React.createElement(Icon, {
770
+ name: icon,
715
771
  size: 16
716
- }), effectiveLabeled && /*#__PURE__*/React.createElement("span", null, "\u8054\u7F51")));
772
+ }), showLabel && /*#__PURE__*/React.createElement("span", null, label)));
717
773
  };
718
774
  var renderSkillBtn = function renderSkillBtn() {
719
775
  var hasAnySkills = skills && skills.length > 0 || skillGroups && skillGroups.some(function (g) {
720
776
  return g.skills.length > 0;
721
777
  });
722
778
  if (!hasAnySkills) return null;
779
+ var _resolvedToolConfigs$3 = resolvedToolConfigs.skill,
780
+ icon = _resolvedToolConfigs$3.icon,
781
+ label = _resolvedToolConfigs$3.label;
782
+ var showIcon = !!icon;
783
+ var showLabel = effectiveLabeled && !!label;
723
784
  return /*#__PURE__*/React.createElement(Popover, {
724
785
  key: "skill",
725
786
  trigger: "click",
@@ -759,16 +820,16 @@ export var Composer = /*#__PURE__*/forwardRef(function Composer(_ref, ref) {
759
820
  return e.preventDefault();
760
821
  },
761
822
  "data-odn-composer-tool-btn": true,
762
- "data-odn-composer-tool-iconic": !effectiveLabeled || undefined,
823
+ "data-odn-composer-tool-iconic": !showLabel || undefined,
763
824
  "data-odn-composer-tool-active": toolMenuOpen || undefined,
764
825
  "data-odn-composer-tool-disabled": disabled || undefined,
765
- "aria-label": "\u6280\u80FD",
826
+ "aria-label": label || 'skill',
766
827
  "aria-disabled": disabled || undefined,
767
- title: effectiveLabeled ? undefined : '技能'
768
- }, /*#__PURE__*/React.createElement(Icon, {
769
- name: "command",
828
+ title: showLabel ? undefined : label || 'skill'
829
+ }, showIcon && /*#__PURE__*/React.createElement(Icon, {
830
+ name: icon,
770
831
  size: 16
771
- }), effectiveLabeled && /*#__PURE__*/React.createElement("span", null, "\u6280\u80FD"))));
832
+ }), showLabel && /*#__PURE__*/React.createElement("span", null, label))));
772
833
  };
773
834
  var toolNodes = effectiveTools.map(function (t) {
774
835
  if (t === 'attachment') return renderAttachmentBtn();
package/dist/index.d.ts CHANGED
@@ -61,7 +61,7 @@ export { ClarifyDockPanel, ClarifyDockTrigger, useClarifyDockState, clarifyDockL
61
61
  export { default as Artifact, type ArtifactProps } from './artifact';
62
62
  export { default as Attachments, type AttachmentsProps } from './attachments';
63
63
  export { default as CodeBlock, type CodeBlockProps } from './code-block';
64
- export { default as Composer, type ComposerProps, type ComposerRef } from './composer';
64
+ export { default as Composer, type ComposerProps, type ComposerRef, type ComposerToolConfig, type ComposerTool } from './composer';
65
65
  export { default as Invocation, InvocationParamPopover, type InvocationProps, type InvocationParamPopoverProps, } from './invocation';
66
66
  export { type ComposerParamPanelContext } from './composer/param-panel';
67
67
  export { default as Mention, type MentionProps } from './mention';
@@ -70,7 +70,7 @@ export { default as SkillSlot, type SkillSlotHandle, type SkillSlotProps } from
70
70
  export { default as ErrorBlock, type ErrorBlockProps } from './error-block';
71
71
  export { default as Fab, type FabProps } from './fab';
72
72
  export { default as MessageImage, type MessageImageProps, type MessageImageItem } from './message-image';
73
- export { default as PreviewPanel, type PreviewPanelProps } from './preview-panel';
73
+ export { default as PreviewPanel, type PreviewPanelProps, type PreviewPanelActionTooltips } from './preview-panel';
74
74
  export { default as Sources, type SourcesProps } from './sources';
75
75
  export { default as Provenance, type ProvenanceProps, type ProvenanceType } from './provenance';
76
76
  export { default as StreamText, type StreamTextProps, type TypographyOverrides } from './stream-text';
@@ -1,6 +1,16 @@
1
1
  /// <reference types="react" />
2
2
  import type { PreviewTab } from '../_genui-types';
3
3
  import './style';
4
+ export interface PreviewPanelActionTooltips {
5
+ /** "在浏览器打开"按钮的 tooltip 文案 */
6
+ openInBrowser?: React.ReactNode;
7
+ /** "下载"按钮的 tooltip 文案 */
8
+ download?: React.ReactNode;
9
+ /** "收起预览"按钮的 tooltip 文案 */
10
+ closeAll?: React.ReactNode;
11
+ /** "关闭抽屉"按钮的 tooltip 文案 */
12
+ closeContainer?: React.ReactNode;
13
+ }
4
14
  export interface PreviewPanelProps {
5
15
  tabs: PreviewTab[];
6
16
  activeTabId?: string | null;
@@ -32,8 +42,13 @@ export interface PreviewPanelProps {
32
42
  * fill:展开时占满父容器宽度(用于 Drawer 内固定像素侧栏等场景)
33
43
  */
34
44
  widthMode?: 'half' | 'fill';
45
+ /**
46
+ * 操作按钮的 Tooltip 文案配置。传入对应字段时,hover 按钮会展示黑色 Tooltip;
47
+ * 未传则不渲染 Tooltip(向后兼容)。
48
+ */
49
+ actionTooltips?: PreviewPanelActionTooltips;
35
50
  }
36
- export declare function PreviewPanel({ tabs, activeTabId, onTabChange, onTabClose, onCloseAll, onCloseContainer, onDownload, onOpenInBrowser, open, emptyTitle, emptyDescription, widthMode, }: PreviewPanelProps): import("react").JSX.Element;
51
+ export declare function PreviewPanel({ tabs, activeTabId, onTabChange, onTabClose, onCloseAll, onCloseContainer, onDownload, onOpenInBrowser, open, emptyTitle, emptyDescription, widthMode, actionTooltips, }: PreviewPanelProps): import("react").JSX.Element;
37
52
  export declare namespace PreviewPanel {
38
53
  var displayName: string;
39
54
  }
@@ -1,29 +1,50 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
3
+ var _excluded = ["tooltip"];
1
4
  import { useRef } from 'react';
2
5
  import Button from "../button";
3
6
  import Icon from "../icon";
7
+ import Tooltip from "../tooltip";
4
8
  import StreamText from "../stream-text";
5
9
  import { OdnOverlayVerticalScrollbar, useOverlayScrollbarReveal } from "../overlay-vertical-scrollbar";
6
10
  import "./style";
7
- export function PreviewPanel(_ref) {
8
- var _ref2, _tabs$find;
9
- var tabs = _ref.tabs,
10
- activeTabId = _ref.activeTabId,
11
- onTabChange = _ref.onTabChange,
12
- onTabClose = _ref.onTabClose,
13
- onCloseAll = _ref.onCloseAll,
14
- onCloseContainer = _ref.onCloseContainer,
15
- onDownload = _ref.onDownload,
16
- onOpenInBrowser = _ref.onOpenInBrowser,
17
- open = _ref.open,
18
- _ref$emptyTitle = _ref.emptyTitle,
19
- emptyTitle = _ref$emptyTitle === void 0 ? '暂无附件' : _ref$emptyTitle,
20
- _ref$emptyDescription = _ref.emptyDescription,
21
- emptyDescription = _ref$emptyDescription === void 0 ? '对话生成的附件会显示在这里' : _ref$emptyDescription,
22
- _ref$widthMode = _ref.widthMode,
23
- widthMode = _ref$widthMode === void 0 ? 'half' : _ref$widthMode;
24
- var activeTab = (_ref2 = (_tabs$find = tabs.find(function (t) {
11
+ /** 内部辅助:有 tooltip 文案时包裹 Tooltip,否则仅渲染按钮 */
12
+ function ActionButton(_ref) {
13
+ var tooltip = _ref.tooltip,
14
+ btnProps = _objectWithoutProperties(_ref, _excluded);
15
+ var btn = /*#__PURE__*/React.createElement(Button, _extends({
16
+ light: true,
17
+ size: "medium"
18
+ }, btnProps));
19
+ if (tooltip) {
20
+ return /*#__PURE__*/React.createElement(Tooltip, {
21
+ placement: "bottom",
22
+ popup: tooltip
23
+ }, btn);
24
+ }
25
+ return btn;
26
+ }
27
+ export function PreviewPanel(_ref2) {
28
+ var _ref3, _tabs$find;
29
+ var tabs = _ref2.tabs,
30
+ activeTabId = _ref2.activeTabId,
31
+ onTabChange = _ref2.onTabChange,
32
+ onTabClose = _ref2.onTabClose,
33
+ onCloseAll = _ref2.onCloseAll,
34
+ onCloseContainer = _ref2.onCloseContainer,
35
+ onDownload = _ref2.onDownload,
36
+ onOpenInBrowser = _ref2.onOpenInBrowser,
37
+ open = _ref2.open,
38
+ _ref2$emptyTitle = _ref2.emptyTitle,
39
+ emptyTitle = _ref2$emptyTitle === void 0 ? '暂无附件' : _ref2$emptyTitle,
40
+ _ref2$emptyDescriptio = _ref2.emptyDescription,
41
+ emptyDescription = _ref2$emptyDescriptio === void 0 ? '对话生成的附件会显示在这里' : _ref2$emptyDescriptio,
42
+ _ref2$widthMode = _ref2.widthMode,
43
+ widthMode = _ref2$widthMode === void 0 ? 'half' : _ref2$widthMode,
44
+ actionTooltips = _ref2.actionTooltips;
45
+ var activeTab = (_ref3 = (_tabs$find = tabs.find(function (t) {
25
46
  return t.id === activeTabId;
26
- })) !== null && _tabs$find !== void 0 ? _tabs$find : tabs[0]) !== null && _ref2 !== void 0 ? _ref2 : null;
47
+ })) !== null && _tabs$find !== void 0 ? _tabs$find : tabs[0]) !== null && _ref3 !== void 0 ? _ref3 : null;
27
48
  var isOpen = open !== null && open !== void 0 ? open : tabs.length > 0;
28
49
  var isEmpty = tabs.length === 0;
29
50
  var previewScrollRef = useRef(null);
@@ -102,44 +123,36 @@ export function PreviewPanel(_ref) {
102
123
  })));
103
124
  })), /*#__PURE__*/React.createElement("div", {
104
125
  "data-odn-preview-panel-actions": true
105
- }, /*#__PURE__*/React.createElement(Button, {
106
- light: true,
107
- size: "medium",
126
+ }, /*#__PURE__*/React.createElement(ActionButton, {
127
+ tooltip: actionTooltips === null || actionTooltips === void 0 ? void 0 : actionTooltips.openInBrowser,
108
128
  icon: "arrow-up-right",
109
129
  onClick: handleOpenInBrowser,
110
130
  disabled: !activeTab,
111
131
  "data-odn-preview-panel-open-browser": true,
112
- title: "\u5728\u6D4F\u89C8\u5668\u6253\u5F00",
113
132
  "aria-label": "\u5728\u6D4F\u89C8\u5668\u6253\u5F00"
114
- }), onDownload && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
115
- light: true,
116
- size: "medium",
133
+ }), onDownload && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ActionButton, {
134
+ tooltip: actionTooltips === null || actionTooltips === void 0 ? void 0 : actionTooltips.download,
117
135
  icon: "download-2",
118
136
  onClick: function onClick() {
119
137
  return activeTab && onDownload(activeTab);
120
138
  },
121
139
  disabled: !activeTab,
122
140
  "data-odn-preview-panel-download": true,
123
- title: "\u4E0B\u8F7D",
124
141
  "aria-label": "\u4E0B\u8F7D"
125
142
  }), /*#__PURE__*/React.createElement("span", {
126
143
  "data-odn-preview-panel-action-divider": true,
127
144
  "aria-hidden": true
128
- })), /*#__PURE__*/React.createElement(Button, {
129
- light: true,
130
- size: "medium",
145
+ })), /*#__PURE__*/React.createElement(ActionButton, {
146
+ tooltip: actionTooltips === null || actionTooltips === void 0 ? void 0 : actionTooltips.closeAll,
131
147
  icon: "panel-right",
132
148
  onClick: onCloseAll,
133
149
  "data-odn-preview-panel-close-all": true,
134
- title: "\u6536\u8D77\u9884\u89C8",
135
150
  "aria-label": "\u6536\u8D77\u9884\u89C8"
136
- }), onCloseContainer && /*#__PURE__*/React.createElement(Button, {
137
- light: true,
138
- size: "medium",
151
+ }), onCloseContainer && /*#__PURE__*/React.createElement(ActionButton, {
152
+ tooltip: actionTooltips === null || actionTooltips === void 0 ? void 0 : actionTooltips.closeContainer,
139
153
  icon: "cancel",
140
154
  onClick: onCloseContainer,
141
155
  "data-odn-preview-panel-close-container": true,
142
- title: "\u5173\u95ED\u62BD\u5C49",
143
156
  "aria-label": "\u5173\u95ED\u62BD\u5C49"
144
157
  }))), isEmpty ? /*#__PURE__*/React.createElement("div", {
145
158
  "data-odn-preview-panel-empty-state": true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "one-design-next",
3
- "version": "0.0.59",
3
+ "version": "0.0.61",
4
4
  "description": "One Design Next from TAD@tencent.com",
5
5
  "packageManager": "pnpm@11.8.0",
6
6
  "module": "dist/index.js",