one-design-next 0.0.77 → 0.0.80
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-inline-ref.d.ts +11 -0
- package/dist/_genui-inline-ref.js +22 -0
- package/dist/artifact/actions.d.ts +7 -0
- package/dist/artifact/actions.js +29 -6
- package/dist/artifact/index.d.ts +2 -2
- package/dist/artifact/index.js +5 -7
- package/dist/artifact/style/index.css +16 -4
- package/dist/chat-list/index.d.ts +6 -1
- package/dist/chat-list/index.js +21 -18
- package/dist/chat-list/style/index.css +12 -6
- package/dist/clarify-dock/style/index.css +4 -2
- package/dist/composer/editor.d.ts +2 -0
- package/dist/composer/editor.js +43 -29
- package/dist/composer/hooks/useChipManager.d.ts +2 -0
- package/dist/composer/hooks/useChipManager.js +8 -0
- package/dist/composer/index.d.ts +8 -3
- package/dist/composer/index.js +56 -39
- package/dist/composer/inline-ref.d.ts +2 -0
- package/dist/composer/inline-ref.js +11 -0
- package/dist/composer/send-meta.js +1 -1
- package/dist/composer/style/index.css +9 -14
- package/dist/index.d.ts +4 -4
- package/dist/index.js +1 -1
- package/dist/invocation/index.js +42 -32
- package/dist/invocation/style/index.css +45 -23
- package/dist/mention/index.js +53 -34
- package/dist/mention/style/index.css +48 -12
- package/dist/preview-panel/index.d.ts +26 -1
- package/dist/preview-panel/index.js +154 -32
- package/dist/preview-panel/style/index.css +109 -51
- package/dist/user-bubble/style/index.css +1 -1
- package/dist/virtual-list/index.d.ts +5 -1
- package/dist/virtual-list/index.js +7 -8
- package/dist/virtual-list/style/index.css +54 -0
- package/package.json +1 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 内联引用 chip 的品类 icon。
|
|
3
|
+
*
|
|
4
|
+
* chip 视觉锚点按「类型」而非条目:skill 一律跟 Composer 技能按钮同源,
|
|
5
|
+
* 不使用 SkillItem.icon(那只服务技能菜单辨识)。
|
|
6
|
+
*/
|
|
7
|
+
export declare const SKILL_CATEGORY_ICON = "wand-sparkles";
|
|
8
|
+
/** skill / 未标明的 invocation 通道 → 技能品类 icon;其它 kind 回退 data.icon */
|
|
9
|
+
export declare function resolveInvocationCategoryIcon(kind?: string, fallback?: string): string | undefined;
|
|
10
|
+
/** mention 按 kind 给品类 icon;未知 kind 回退 data.icon */
|
|
11
|
+
export declare function resolveMentionCategoryIcon(kind?: string, fallback?: string): string | undefined;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 内联引用 chip 的品类 icon。
|
|
3
|
+
*
|
|
4
|
+
* chip 视觉锚点按「类型」而非条目:skill 一律跟 Composer 技能按钮同源,
|
|
5
|
+
* 不使用 SkillItem.icon(那只服务技能菜单辨识)。
|
|
6
|
+
*/
|
|
7
|
+
export var SKILL_CATEGORY_ICON = 'wand-sparkles';
|
|
8
|
+
|
|
9
|
+
/** skill / 未标明的 invocation 通道 → 技能品类 icon;其它 kind 回退 data.icon */
|
|
10
|
+
export function resolveInvocationCategoryIcon(kind, fallback) {
|
|
11
|
+
if (!kind || kind === 'skill' || kind === 'invocation') {
|
|
12
|
+
return SKILL_CATEGORY_ICON;
|
|
13
|
+
}
|
|
14
|
+
return fallback;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** mention 按 kind 给品类 icon;未知 kind 回退 data.icon */
|
|
18
|
+
export function resolveMentionCategoryIcon(kind, fallback) {
|
|
19
|
+
if (kind === 'file') return 'file-text';
|
|
20
|
+
if (kind === 'user' || kind === 'mention') return 'user';
|
|
21
|
+
return fallback;
|
|
22
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { IconName } from '../icon';
|
|
2
|
+
import type { ArtifactFileIconType } from './icons';
|
|
2
3
|
/** 点击产物时的预期行为类型。 */
|
|
3
4
|
export type ArtifactActionKind = 'preview' | 'download';
|
|
4
5
|
export interface ArtifactAction {
|
|
@@ -10,3 +11,9 @@ export interface ArtifactAction {
|
|
|
10
11
|
}
|
|
11
12
|
/** 根据 actionKind 返回对应的 ArtifactAction(label + icon)。 */
|
|
12
13
|
export declare function getArtifactActionFromKind(kind: ArtifactActionKind): ArtifactAction;
|
|
14
|
+
/**
|
|
15
|
+
* 按文件类型给出点击预期(业务方可据此决定 `actionKind`):
|
|
16
|
+
* - html / md / csv / file → 预览(arrow-right)
|
|
17
|
+
* - pdf / xlsx / docx / pptx → 下载(arrow-down-to-line)
|
|
18
|
+
*/
|
|
19
|
+
export declare function getArtifactAction(fileType: ArtifactFileIconType): ArtifactAction;
|
package/dist/artifact/actions.js
CHANGED
|
@@ -3,17 +3,40 @@
|
|
|
3
3
|
/** 根据 actionKind 返回对应的 ArtifactAction(label + icon)。 */
|
|
4
4
|
export function getArtifactActionFromKind(kind) {
|
|
5
5
|
switch (kind) {
|
|
6
|
-
case 'preview':
|
|
7
|
-
return {
|
|
8
|
-
kind: 'preview',
|
|
9
|
-
label: '预览详情',
|
|
10
|
-
icon: 'arrow-right'
|
|
11
|
-
};
|
|
12
6
|
case 'download':
|
|
13
7
|
return {
|
|
14
8
|
kind: 'download',
|
|
15
9
|
label: '下载导出',
|
|
16
10
|
icon: 'arrow-down-to-line'
|
|
17
11
|
};
|
|
12
|
+
case 'preview':
|
|
13
|
+
default:
|
|
14
|
+
return {
|
|
15
|
+
kind: 'preview',
|
|
16
|
+
label: '预览详情',
|
|
17
|
+
icon: 'arrow-right'
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 按文件类型给出点击预期(业务方可据此决定 `actionKind`):
|
|
24
|
+
* - html / md / csv / file → 预览(arrow-right)
|
|
25
|
+
* - pdf / xlsx / docx / pptx → 下载(arrow-down-to-line)
|
|
26
|
+
*/
|
|
27
|
+
export function getArtifactAction(fileType) {
|
|
28
|
+
switch (fileType) {
|
|
29
|
+
case 'html':
|
|
30
|
+
case 'md':
|
|
31
|
+
case 'csv':
|
|
32
|
+
case 'file':
|
|
33
|
+
return getArtifactActionFromKind('preview');
|
|
34
|
+
case 'pdf':
|
|
35
|
+
case 'xlsx':
|
|
36
|
+
case 'docx':
|
|
37
|
+
case 'pptx':
|
|
38
|
+
return getArtifactActionFromKind('download');
|
|
39
|
+
default:
|
|
40
|
+
return getArtifactActionFromKind('preview');
|
|
18
41
|
}
|
|
19
42
|
}
|
package/dist/artifact/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { type CSSProperties } from 'react';
|
|
|
2
2
|
import { type ArtifactActionKind } from './actions';
|
|
3
3
|
import { type ArtifactFileIconType } from './icons';
|
|
4
4
|
import './style';
|
|
5
|
-
export { getArtifactActionFromKind, type ArtifactAction, type ArtifactActionKind, } from './actions';
|
|
5
|
+
export { getArtifactAction, getArtifactActionFromKind, type ArtifactAction, type ArtifactActionKind, } from './actions';
|
|
6
6
|
export { ARTIFACT_FILE_GLOW_COLORS, getArtifactGlowColor } from './glow';
|
|
7
7
|
export { ARTIFACT_DEDICATED_FILE_ICON_TYPES, ARTIFACT_FILE_ICON_MEDIUM_SIZE, ARTIFACT_FILE_ICON_MEDIUM_VIEWBOX, ARTIFACT_FILE_ICON_SMALL_SIZE, ARTIFACT_FILE_ICON_SMALL_VIEWBOX, ARTIFACT_FILE_ICON_TYPES, ArtifactFileIcon, artifactFileIcons, artifactFileIconsMedium, artifactFileIconsSmall, getArtifactFileIconUrl, } from './icons';
|
|
8
8
|
export type { ArtifactFileIconProps, ArtifactFileIconSize, ArtifactFileIconType, } from './icons';
|
|
@@ -40,7 +40,7 @@ export interface ArtifactProps {
|
|
|
40
40
|
/**
|
|
41
41
|
* 对话流内的产物:
|
|
42
42
|
* - medium / Card:左 Icon + 右标题 / 大小·日期;可点 hover 时 Icon 后退缩小、文案左移遮罩,右侧浮出操作预期
|
|
43
|
-
* - small / Small:无底色/描边;hover 用 HoverFill
|
|
43
|
+
* - small / Small:无底色/描边;hover 用 HoverFill(Navi 默认色);不可预览类型额外浮出下载 Icon
|
|
44
44
|
*/
|
|
45
45
|
export declare function Artifact({ title, actionKind, fileType, fileSize, date, size, status, onOpen, className, style, }: ArtifactProps): import("react").JSX.Element;
|
|
46
46
|
export declare namespace Artifact {
|
package/dist/artifact/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { getArtifactActionFromKind } from "./actions";
|
|
|
10
10
|
import { getArtifactGlowColor } from "./glow";
|
|
11
11
|
import { ARTIFACT_DEDICATED_FILE_ICON_TYPES, ArtifactFileIcon } from "./icons";
|
|
12
12
|
import "./style";
|
|
13
|
-
export { getArtifactActionFromKind } from "./actions";
|
|
13
|
+
export { getArtifactAction, getArtifactActionFromKind } from "./actions";
|
|
14
14
|
export { ARTIFACT_FILE_GLOW_COLORS, getArtifactGlowColor } from "./glow";
|
|
15
15
|
export { ARTIFACT_DEDICATED_FILE_ICON_TYPES, ARTIFACT_FILE_ICON_MEDIUM_SIZE, ARTIFACT_FILE_ICON_MEDIUM_VIEWBOX, ARTIFACT_FILE_ICON_SMALL_SIZE, ARTIFACT_FILE_ICON_SMALL_VIEWBOX, ARTIFACT_FILE_ICON_TYPES, ArtifactFileIcon, artifactFileIcons, artifactFileIconsMedium, artifactFileIconsSmall, getArtifactFileIconUrl } from "./icons";
|
|
16
16
|
|
|
@@ -73,7 +73,7 @@ function ArtifactActionCue(_ref) {
|
|
|
73
73
|
/**
|
|
74
74
|
* 对话流内的产物:
|
|
75
75
|
* - medium / Card:左 Icon + 右标题 / 大小·日期;可点 hover 时 Icon 后退缩小、文案左移遮罩,右侧浮出操作预期
|
|
76
|
-
* - small / Small:无底色/描边;hover 用 HoverFill
|
|
76
|
+
* - small / Small:无底色/描边;hover 用 HoverFill(Navi 默认色);不可预览类型额外浮出下载 Icon
|
|
77
77
|
*/
|
|
78
78
|
export function Artifact(_ref2) {
|
|
79
79
|
var title = _ref2.title,
|
|
@@ -115,8 +115,8 @@ export function Artifact(_ref2) {
|
|
|
115
115
|
// Small 形态只展示 Icon + 标题;Card(medium)保留大小 / 日期(或 Generating 文案)
|
|
116
116
|
var showMeta = size !== 'small';
|
|
117
117
|
var metaParts = !showMeta ? [] : isGenerating ? ['生成中'] : [fileSize, date].filter(Boolean);
|
|
118
|
-
//
|
|
119
|
-
var showAction = size !== 'small'
|
|
118
|
+
// Card:预览 / 下载均可点时展示操作预期;Small:仅不可预览(下载)类型 hover 出下载 Icon
|
|
119
|
+
var showAction = isInteractive && (size !== 'small' || action.kind === 'download');
|
|
120
120
|
var handleClick = function handleClick() {
|
|
121
121
|
onOpen === null || onOpen === void 0 || onOpen();
|
|
122
122
|
};
|
|
@@ -191,13 +191,11 @@ export function Artifact(_ref2) {
|
|
|
191
191
|
onClick: handleClick
|
|
192
192
|
}), content) : /*#__PURE__*/React.createElement("div", sharedProps, content);
|
|
193
193
|
|
|
194
|
-
// Small:默认透明;可点时用 HoverFill
|
|
194
|
+
// Small:默认透明;可点时用 HoverFill(颜色对齐 Navi / HoverFill 默认值)
|
|
195
195
|
if (size === 'small') {
|
|
196
196
|
return /*#__PURE__*/React.createElement(HoverFill, {
|
|
197
197
|
"data-odn-artifact-small-wrap": true,
|
|
198
198
|
bgClassName: "odn-artifact-small-bg",
|
|
199
|
-
hoverColor: "var(--odn-color-black-4)",
|
|
200
|
-
activeColor: "var(--odn-color-black-5)",
|
|
201
199
|
disabled: !isInteractive,
|
|
202
200
|
className: className,
|
|
203
201
|
style: style
|
|
@@ -12,7 +12,8 @@ html {
|
|
|
12
12
|
--odn-artifact-icon-height: 36px;
|
|
13
13
|
--odn-artifact-min-height: 68px;
|
|
14
14
|
--odn-artifact-title-size: var(--odn-font-size-text-md);
|
|
15
|
-
|
|
15
|
+
/* 文件名行高用全局 default(非 text-md 固定 22px) */
|
|
16
|
+
--odn-artifact-title-leading: var(--odn-line-height);
|
|
16
17
|
--odn-artifact-meta-size: var(--odn-font-size-text-mn);
|
|
17
18
|
--odn-artifact-meta-leading: var(--odn-font-leading-text-mn);
|
|
18
19
|
/* Card hover:对齐即梦 banner 卡(0.3s / ease-out) */
|
|
@@ -65,7 +66,8 @@ html {
|
|
|
65
66
|
--odn-artifact-icon-height: 16px;
|
|
66
67
|
--odn-artifact-min-height: 0;
|
|
67
68
|
--odn-artifact-title-size: var(--odn-font-size-text-sm);
|
|
68
|
-
|
|
69
|
+
/* 行高用全局 default(非 text-sm 固定 22px) */
|
|
70
|
+
--odn-artifact-title-leading: var(--odn-line-height);
|
|
69
71
|
border: none;
|
|
70
72
|
background: transparent;
|
|
71
73
|
box-shadow: none;
|
|
@@ -117,7 +119,8 @@ button[data-odn-artifact] {
|
|
|
117
119
|
margin: 0;
|
|
118
120
|
font-size: var(--odn-artifact-title-size);
|
|
119
121
|
line-height: var(--odn-artifact-title-leading);
|
|
120
|
-
|
|
122
|
+
/* Card / Small 默认 Regular;Small 选中态由使用方(如 PreviewPanel 列表)加粗 */
|
|
123
|
+
font-weight: 400;
|
|
121
124
|
color: var(--odn-color-black-12);
|
|
122
125
|
white-space: nowrap;
|
|
123
126
|
}
|
|
@@ -241,7 +244,7 @@ button[data-odn-artifact] {
|
|
|
241
244
|
transform: translateX(calc(-1 * var(--odn-artifact-hover-shift)));
|
|
242
245
|
}
|
|
243
246
|
|
|
244
|
-
/*
|
|
247
|
+
/* 操作预期仅 Icon;Card 右侧间距 20,Small 对齐自身 padding-x 12 */
|
|
245
248
|
[data-odn-artifact-action] {
|
|
246
249
|
position: absolute;
|
|
247
250
|
right: 20px;
|
|
@@ -260,12 +263,21 @@ button[data-odn-artifact] {
|
|
|
260
263
|
transition: opacity var(--odn-artifact-hover-duration) var(--odn-artifact-hover-ease), transform var(--odn-artifact-hover-duration) var(--odn-artifact-hover-ease);
|
|
261
264
|
}
|
|
262
265
|
|
|
266
|
+
[data-odn-artifact][data-odn-artifact-size=small] > [data-odn-artifact-action] {
|
|
267
|
+
right: 12px;
|
|
268
|
+
}
|
|
269
|
+
|
|
263
270
|
[data-odn-artifact][data-odn-artifact-clickable]:hover > [data-odn-artifact-action],
|
|
264
271
|
[data-odn-artifact][data-odn-artifact-clickable]:focus-visible > [data-odn-artifact-action] {
|
|
265
272
|
opacity: 1;
|
|
266
273
|
transform: translate(0, -50%);
|
|
267
274
|
}
|
|
268
275
|
|
|
276
|
+
/* Small 下载态:标题给右侧 Icon 让出空间,避免叠字 */
|
|
277
|
+
[data-odn-artifact][data-odn-artifact-size=small][data-odn-artifact-action-kind=download] [data-odn-artifact-copy] {
|
|
278
|
+
padding-right: 20px;
|
|
279
|
+
}
|
|
280
|
+
|
|
269
281
|
[data-odn-artifact][data-odn-artifact-status=Generating] {
|
|
270
282
|
opacity: 0.85;
|
|
271
283
|
}
|
|
@@ -49,12 +49,17 @@ export interface ChatListProps {
|
|
|
49
49
|
onDelete?: ChatItemProps['onDelete'];
|
|
50
50
|
/** 自定义行渲染。默认渲染 ChatItem。 */
|
|
51
51
|
renderItem?: (item: ChatListItem, node: ReactNode) => ReactNode;
|
|
52
|
+
/**
|
|
53
|
+
* 将「最近」列表包进自定义滚动容器。
|
|
54
|
+
* 标题栏与置顶区始终留在外侧,不进入该容器。
|
|
55
|
+
*/
|
|
56
|
+
renderRestScroll?: (content: ReactNode) => ReactNode;
|
|
52
57
|
}
|
|
53
58
|
/** 按时间筛选项判断会话是否命中。无有效 `time` 时仅在「全部」下保留。 */
|
|
54
59
|
export declare function matchChatListFilterTime(time: ChatListItem['time'], filter: ChatListFilterTime, now?: number): boolean;
|
|
55
60
|
/** 按类型筛选项判断会话是否命中。缺省 `type` 视为 `'ai'`。 */
|
|
56
61
|
export declare function matchChatListFilterType(type: ChatListItem['type'], filter: ChatListFilterType): boolean;
|
|
57
|
-
export declare function ChatList({ items, title, pinnedSectionTitle, recentSectionTitle, filterTime: filterTimeProp, defaultFilterTime, onFilterTimeChange, filterType: filterTypeProp, defaultFilterType, onFilterTypeChange, filterOpen: filterOpenProp, defaultFilterOpen, onFilterOpenChange, empty, actionMenuZIndex, filterMenuZIndex, className, onItemClick, onRename, onPin, onDelete, renderItem, }: ChatListProps): import("react").JSX.Element;
|
|
62
|
+
export declare function ChatList({ items, title, pinnedSectionTitle, recentSectionTitle, filterTime: filterTimeProp, defaultFilterTime, onFilterTimeChange, filterType: filterTypeProp, defaultFilterType, onFilterTypeChange, filterOpen: filterOpenProp, defaultFilterOpen, onFilterOpenChange, empty, actionMenuZIndex, filterMenuZIndex, className, onItemClick, onRename, onPin, onDelete, renderItem, renderRestScroll, }: ChatListProps): import("react").JSX.Element;
|
|
58
63
|
export declare namespace ChatList {
|
|
59
64
|
var displayName: string;
|
|
60
65
|
}
|
package/dist/chat-list/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
2
|
-
import { useMemo, useState } from 'react';
|
|
3
2
|
import clsx from 'clsx';
|
|
3
|
+
import { useMemo, useState } from 'react';
|
|
4
4
|
import ChatItem from "../chat-item";
|
|
5
5
|
import Dropdown from "../dropdown";
|
|
6
6
|
import Icon from "../icon";
|
|
@@ -34,7 +34,7 @@ var TYPE_OPTIONS = [{
|
|
|
34
34
|
label: '人工客服'
|
|
35
35
|
}];
|
|
36
36
|
function parseItemTime(time) {
|
|
37
|
-
if (time
|
|
37
|
+
if (time === null || time === undefined) return null;
|
|
38
38
|
var t = typeof time === 'number' ? time : time instanceof Date ? time.getTime() : Date.parse(time);
|
|
39
39
|
return Number.isFinite(t) ? t : null;
|
|
40
40
|
}
|
|
@@ -49,7 +49,7 @@ export function matchChatListFilterTime(time, filter) {
|
|
|
49
49
|
var now = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : Date.now();
|
|
50
50
|
if (filter === 'all') return true;
|
|
51
51
|
var t = parseItemTime(time);
|
|
52
|
-
if (t
|
|
52
|
+
if (t === null || t === undefined) return false;
|
|
53
53
|
if (t > now) return false;
|
|
54
54
|
if (filter === 'today') return t >= startOfLocalDay(now);
|
|
55
55
|
if (filter === '7d') return t >= now - 7 * 86400000;
|
|
@@ -144,7 +144,8 @@ export function ChatList(_ref) {
|
|
|
144
144
|
onPin = _ref.onPin,
|
|
145
145
|
onDelete = _ref.onDelete,
|
|
146
146
|
_ref$renderItem = _ref.renderItem,
|
|
147
|
-
renderItem = _ref$renderItem === void 0 ? defaultRenderItem : _ref$renderItem
|
|
147
|
+
renderItem = _ref$renderItem === void 0 ? defaultRenderItem : _ref$renderItem,
|
|
148
|
+
renderRestScroll = _ref.renderRestScroll;
|
|
148
149
|
var _useControllable = useControllable(filterTimeProp, defaultFilterTime, onFilterTimeChange),
|
|
149
150
|
_useControllable2 = _slicedToArray(_useControllable, 2),
|
|
150
151
|
filterTime = _useControllable2[0],
|
|
@@ -196,6 +197,20 @@ export function ChatList(_ref) {
|
|
|
196
197
|
}, renderItem(item, node));
|
|
197
198
|
};
|
|
198
199
|
var hasContent = pinnedItems.length > 0 || restItems.length > 0;
|
|
200
|
+
var pinnedSection = pinnedItems.length > 0 ? /*#__PURE__*/React.createElement("div", {
|
|
201
|
+
"data-odn-chat-list-pinned": true
|
|
202
|
+
}, pinnedSectionTitle !== null && pinnedSectionTitle !== undefined ? /*#__PURE__*/React.createElement("div", {
|
|
203
|
+
"data-odn-chat-list-pinned-title": true
|
|
204
|
+
}, pinnedSectionTitle) : null, /*#__PURE__*/React.createElement("div", {
|
|
205
|
+
"data-odn-chat-list-pinned-body": true
|
|
206
|
+
}, pinnedItems.map(renderChatItem))) : null;
|
|
207
|
+
var restSection = restItems.length > 0 ? /*#__PURE__*/React.createElement("div", {
|
|
208
|
+
"data-odn-chat-list-rest": true
|
|
209
|
+
}, pinnedItems.length > 0 && recentSectionTitle !== null && recentSectionTitle !== undefined ? /*#__PURE__*/React.createElement("div", {
|
|
210
|
+
"data-odn-chat-list-recent-title": true
|
|
211
|
+
}, recentSectionTitle) : null, /*#__PURE__*/React.createElement("div", {
|
|
212
|
+
"data-odn-chat-list-rest-body": true
|
|
213
|
+
}, restItems.map(renderChatItem))) : null;
|
|
199
214
|
return /*#__PURE__*/React.createElement("div", {
|
|
200
215
|
"data-odn-chat-list": true,
|
|
201
216
|
className: clsx(className)
|
|
@@ -236,21 +251,9 @@ export function ChatList(_ref) {
|
|
|
236
251
|
size: 16
|
|
237
252
|
}))))), !hasContent ? /*#__PURE__*/React.createElement("div", {
|
|
238
253
|
"data-odn-chat-list-empty": true
|
|
239
|
-
}, empty !== null && empty !== void 0 ? empty : null) : /*#__PURE__*/React.createElement("div", {
|
|
254
|
+
}, empty !== null && empty !== void 0 ? empty : null) : renderRestScroll ? /*#__PURE__*/React.createElement(React.Fragment, null, pinnedSection, restSection ? renderRestScroll(restSection) : null) : /*#__PURE__*/React.createElement("div", {
|
|
240
255
|
"data-odn-chat-list-body": true
|
|
241
|
-
},
|
|
242
|
-
"data-odn-chat-list-pinned": true
|
|
243
|
-
}, pinnedSectionTitle != null ? /*#__PURE__*/React.createElement("div", {
|
|
244
|
-
"data-odn-chat-list-pinned-title": true
|
|
245
|
-
}, pinnedSectionTitle) : null, /*#__PURE__*/React.createElement("div", {
|
|
246
|
-
"data-odn-chat-list-pinned-body": true
|
|
247
|
-
}, pinnedItems.map(renderChatItem))) : null, restItems.length > 0 ? /*#__PURE__*/React.createElement("div", {
|
|
248
|
-
"data-odn-chat-list-rest": true
|
|
249
|
-
}, pinnedItems.length > 0 && recentSectionTitle != null ? /*#__PURE__*/React.createElement("div", {
|
|
250
|
-
"data-odn-chat-list-recent-title": true
|
|
251
|
-
}, recentSectionTitle) : null, /*#__PURE__*/React.createElement("div", {
|
|
252
|
-
"data-odn-chat-list-rest-body": true
|
|
253
|
-
}, restItems.map(renderChatItem))) : null));
|
|
256
|
+
}, pinnedSection, restSection));
|
|
254
257
|
}
|
|
255
258
|
ChatList.displayName = 'ChatList';
|
|
256
259
|
export default ChatList;
|
|
@@ -9,19 +9,21 @@
|
|
|
9
9
|
|
|
10
10
|
[data-odn-chat-list-toolbar] {
|
|
11
11
|
display: flex;
|
|
12
|
+
flex-shrink: 0;
|
|
12
13
|
align-items: center;
|
|
13
14
|
justify-content: space-between;
|
|
14
15
|
gap: 8px;
|
|
15
16
|
min-height: 32px;
|
|
16
17
|
min-width: 0;
|
|
17
|
-
|
|
18
|
+
/* 与 ChatItem / 分区标题左缘统一 12px */
|
|
19
|
+
padding: 0 12px;
|
|
18
20
|
background: transparent;
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
[data-odn-chat-list-title] {
|
|
22
24
|
flex: 1 1 auto;
|
|
23
25
|
min-width: 0;
|
|
24
|
-
padding: 0
|
|
26
|
+
padding: 0;
|
|
25
27
|
color: var(--odn-color-black-9);
|
|
26
28
|
font-size: 14px;
|
|
27
29
|
font-weight: 400;
|
|
@@ -110,14 +112,18 @@
|
|
|
110
112
|
[data-odn-chat-list-rest] {
|
|
111
113
|
display: flex;
|
|
112
114
|
flex-direction: column;
|
|
113
|
-
gap:
|
|
115
|
+
gap: 4px;
|
|
114
116
|
min-width: 0;
|
|
115
117
|
}
|
|
116
118
|
|
|
117
|
-
|
|
119
|
+
[data-odn-chat-list-pinned] {
|
|
120
|
+
flex-shrink: 0;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* 置顶 / 最近分区头:视觉同组标题,无折叠 / 菜单等交互;左缘同标题栏 / ChatItem */
|
|
118
124
|
[data-odn-chat-list-pinned-title],
|
|
119
125
|
[data-odn-chat-list-recent-title] {
|
|
120
|
-
padding: 4px
|
|
126
|
+
padding: 4px 12px 2px;
|
|
121
127
|
color: var(--odn-color-black-9);
|
|
122
128
|
font-size: 12px;
|
|
123
129
|
font-weight: 400;
|
|
@@ -130,6 +136,6 @@
|
|
|
130
136
|
[data-odn-chat-list-rest-body] {
|
|
131
137
|
display: flex;
|
|
132
138
|
flex-direction: column;
|
|
133
|
-
gap:
|
|
139
|
+
gap: 4px;
|
|
134
140
|
min-width: 0;
|
|
135
141
|
}
|
|
@@ -545,13 +545,15 @@ div[data-odn-clarify-dock] [data-odn-clarify-dock-body] {
|
|
|
545
545
|
div[data-odn-clarify-dock] [data-odn-date-picker-container]:not([data-odn-date-picker-container-range]) {
|
|
546
546
|
display: inline-block;
|
|
547
547
|
box-sizing: border-box;
|
|
548
|
-
|
|
548
|
+
font-size: var(--odn-font-size-text-sm);
|
|
549
|
+
width: calc(10ch + 10px + 32px + 2px);
|
|
549
550
|
}
|
|
550
551
|
|
|
551
552
|
div[data-odn-clarify-dock] [data-odn-date-picker-container-range] {
|
|
552
553
|
display: inline-block;
|
|
553
554
|
box-sizing: border-box;
|
|
554
|
-
|
|
555
|
+
font-size: var(--odn-font-size-text-sm);
|
|
556
|
+
width: calc(21ch + 10px + 32px + 2px);
|
|
555
557
|
}
|
|
556
558
|
|
|
557
559
|
div[data-odn-clarify-dock] [data-odn-date-picker-input] {
|
|
@@ -41,6 +41,8 @@ export interface ComposerEditorProps {
|
|
|
41
41
|
defaultValue?: string;
|
|
42
42
|
/** 值变化回调;参数是 raw string,含 marker。 */
|
|
43
43
|
onChange?: (value: string) => void;
|
|
44
|
+
/** 与 defaultValue / 首次受控 value 配套,把 marker 还原成 chip。 */
|
|
45
|
+
defaultChips?: ChipData[];
|
|
44
46
|
placeholder?: string;
|
|
45
47
|
autoSize?: ComposerEditorAutoSize;
|
|
46
48
|
/**
|
package/dist/composer/editor.js
CHANGED
|
@@ -22,13 +22,13 @@ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
|
22
22
|
|
|
23
23
|
import { forwardRef, useCallback, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState } from 'react';
|
|
24
24
|
import { createPortal } from 'react-dom';
|
|
25
|
+
import ScrollArea from "../scroll-area";
|
|
26
|
+
import { findChipHostBeforeCaret, mergeLineIntoPreviousAtCaretStart, normalizeCollapsedCaretAtChipBoundary, resolveCaretMove, splitLineAt } from "./caret";
|
|
25
27
|
import { buildClipboardPayload, COMPOSER_CLIPBOARD_MIME, parseClipboardPayload, plainTextFromClipboardPayload, remapClipboardPayload } from "./clipboard";
|
|
26
28
|
import { useChipManager } from "./hooks/useChipManager";
|
|
27
29
|
import { useChipSelectionMarker } from "./hooks/useChipSelectionMarker";
|
|
30
|
+
import { chipHasEditableParams, ComposerInlineRef } from "./inline-ref";
|
|
28
31
|
import { createLineRoot, createLineRootWithText, ensureLineRoots, getPlainText, isEditorEmpty, LINE_ATTR_NAME, normalizeEditorDom, probeTrigger } from "./utils";
|
|
29
|
-
import { findChipHostBeforeCaret, mergeLineIntoPreviousAtCaretStart, normalizeCollapsedCaretAtChipBoundary, resolveCaretMove, splitLineAt } from "./caret";
|
|
30
|
-
import { ComposerInlineRef } from "./inline-ref";
|
|
31
|
-
import ScrollArea from "../scroll-area";
|
|
32
32
|
|
|
33
33
|
/** Composer editor 触发态对外信号——告诉父组件该弹浮层选 skill 了。 */
|
|
34
34
|
|
|
@@ -83,6 +83,7 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
83
83
|
var valueProp = _ref.value,
|
|
84
84
|
_ref$defaultValue = _ref.defaultValue,
|
|
85
85
|
defaultValue = _ref$defaultValue === void 0 ? '' : _ref$defaultValue,
|
|
86
|
+
defaultChips = _ref.defaultChips,
|
|
86
87
|
onChange = _ref.onChange,
|
|
87
88
|
placeholder = _ref.placeholder,
|
|
88
89
|
autoSize = _ref.autoSize,
|
|
@@ -113,7 +114,7 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
113
114
|
var minRows = (_autoSize$minRows = autoSize === null || autoSize === void 0 ? void 0 : autoSize.minRows) !== null && _autoSize$minRows !== void 0 ? _autoSize$minRows : 1;
|
|
114
115
|
var maxRows = autoSize === null || autoSize === void 0 ? void 0 : autoSize.maxRows;
|
|
115
116
|
var minHeightPx = minRows * LINE_HEIGHT + PADDING_Y * 2;
|
|
116
|
-
var maxHeightPx = maxRows
|
|
117
|
+
var maxHeightPx = maxRows !== undefined ? maxRows * LINE_HEIGHT + PADDING_Y * 2 : undefined;
|
|
117
118
|
|
|
118
119
|
/** 当前活动 trigger probe;null 表示无触发态。 */
|
|
119
120
|
var triggerRef = useRef(null);
|
|
@@ -182,8 +183,8 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
182
183
|
var el = editorRef.current;
|
|
183
184
|
if (!el) return;
|
|
184
185
|
var natural = Math.ceil(el.scrollHeight);
|
|
185
|
-
var clamped = Math.max(minHeightPx, maxHeightPx
|
|
186
|
-
var overflow = maxHeightPx
|
|
186
|
+
var clamped = Math.max(minHeightPx, maxHeightPx !== undefined ? Math.min(natural, maxHeightPx) : natural);
|
|
187
|
+
var overflow = maxHeightPx !== undefined && natural > maxHeightPx + 1;
|
|
187
188
|
setScrollHeight(function (prev) {
|
|
188
189
|
return prev === clamped ? prev : clamped;
|
|
189
190
|
});
|
|
@@ -203,7 +204,7 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
203
204
|
}, []);
|
|
204
205
|
var scheduleControlledSync = useCallback(function () {
|
|
205
206
|
if (!isControlled) return;
|
|
206
|
-
if (controlledSyncRafRef.current
|
|
207
|
+
if (controlledSyncRafRef.current !== null) {
|
|
207
208
|
cancelAnimationFrame(controlledSyncRafRef.current);
|
|
208
209
|
}
|
|
209
210
|
controlledSyncRafRef.current = requestAnimationFrame(function () {
|
|
@@ -215,7 +216,7 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
215
216
|
}, [isControlled]);
|
|
216
217
|
useEffect(function () {
|
|
217
218
|
return function () {
|
|
218
|
-
if (controlledSyncRafRef.current
|
|
219
|
+
if (controlledSyncRafRef.current !== null) {
|
|
219
220
|
cancelAnimationFrame(controlledSyncRafRef.current);
|
|
220
221
|
}
|
|
221
222
|
};
|
|
@@ -241,9 +242,10 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
241
242
|
/* ─────────────────────────────────────
|
|
242
243
|
* chip 管理
|
|
243
244
|
* ───────────────────────────────────── */
|
|
245
|
+
var recomputeTriggerRef = useRef(function () {});
|
|
244
246
|
var _useChipManager = useChipManager(function () {
|
|
245
247
|
fireChange();
|
|
246
|
-
|
|
248
|
+
recomputeTriggerRef.current();
|
|
247
249
|
}),
|
|
248
250
|
chips = _useChipManager.chips,
|
|
249
251
|
_insertChip = _useChipManager.insertChip,
|
|
@@ -252,8 +254,11 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
252
254
|
removeChip = _useChipManager.removeChip,
|
|
253
255
|
updateChipData = _useChipManager.updateChipData,
|
|
254
256
|
getChipHost = _useChipManager.getChipHost,
|
|
257
|
+
getChips = _useChipManager.getChips,
|
|
255
258
|
resetChips = _useChipManager.resetChips;
|
|
256
259
|
useChipSelectionMarker(editorRef, chips);
|
|
260
|
+
var insertSerializedAtRangeRef = useRef(insertSerializedAtRange);
|
|
261
|
+
insertSerializedAtRangeRef.current = insertSerializedAtRange;
|
|
257
262
|
|
|
258
263
|
/* ─────────────────────────────────────
|
|
259
264
|
* Trigger 探测
|
|
@@ -282,6 +287,7 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
282
287
|
triggerRef.current = next;
|
|
283
288
|
onTriggerChange === null || onTriggerChange === void 0 || onTriggerChange(next ? probeToInfo(next) : null);
|
|
284
289
|
}, [triggers, onTriggerChange, probeToInfo]);
|
|
290
|
+
recomputeTriggerRef.current = recomputeTrigger;
|
|
285
291
|
|
|
286
292
|
/* ─────────────────────────────────────
|
|
287
293
|
* ref 命令式 API
|
|
@@ -363,18 +369,14 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
363
369
|
},
|
|
364
370
|
/* chips 快照:按 DOM 实际出现顺序输出(chips state 维护时已经有序)。
|
|
365
371
|
* 不直接返回 chips 引用,避免外部 mutate 弄花内部 state。 */
|
|
366
|
-
getChips:
|
|
367
|
-
return chips.map(function (c) {
|
|
368
|
-
return c.data;
|
|
369
|
-
});
|
|
370
|
-
},
|
|
372
|
+
getChips: getChips,
|
|
371
373
|
updateChipData: updateChipData,
|
|
372
374
|
getChipHost: getChipHost,
|
|
373
375
|
get nativeElement() {
|
|
374
376
|
return editorRef.current;
|
|
375
377
|
}
|
|
376
378
|
};
|
|
377
|
-
}, [onChange, _insertChip, removeChip, resetChips, onTriggerChange,
|
|
379
|
+
}, [onChange, _insertChip, removeChip, resetChips, onTriggerChange, getChips, updateChipData, getChipHost]);
|
|
378
380
|
|
|
379
381
|
/* ─────────────────────────────────────
|
|
380
382
|
* 监听 selection 变化:方向键 / 鼠标点击移位都要重算 trigger
|
|
@@ -431,22 +433,34 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
431
433
|
var el = editorRef.current;
|
|
432
434
|
if (!el) return;
|
|
433
435
|
var initial = isControlled ? valueProp !== null && valueProp !== void 0 ? valueProp : '' : defaultValue;
|
|
436
|
+
var initialChips = defaultChips !== null && defaultChips !== void 0 ? defaultChips : [];
|
|
434
437
|
if (el.childNodes.length === 0) {
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
438
|
+
if (initialChips.length > 0) {
|
|
439
|
+
el.appendChild(createLineRoot());
|
|
440
|
+
var firstLine = el.firstChild;
|
|
441
|
+
if (firstLine) {
|
|
442
|
+
var range = document.createRange();
|
|
443
|
+
range.selectNodeContents(firstLine);
|
|
444
|
+
range.collapse(true);
|
|
445
|
+
insertSerializedAtRangeRef.current(initial, initialChips, range, el);
|
|
443
446
|
}
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
_iterator
|
|
447
|
+
} else {
|
|
448
|
+
var lines = (initial !== null && initial !== void 0 ? initial : '').split('\n');
|
|
449
|
+
var frag = document.createDocumentFragment();
|
|
450
|
+
var _iterator = _createForOfIteratorHelper(lines),
|
|
451
|
+
_step;
|
|
452
|
+
try {
|
|
453
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
454
|
+
var line = _step.value;
|
|
455
|
+
frag.appendChild(createLineRootWithText(line));
|
|
456
|
+
}
|
|
457
|
+
} catch (err) {
|
|
458
|
+
_iterator.e(err);
|
|
459
|
+
} finally {
|
|
460
|
+
_iterator.f();
|
|
461
|
+
}
|
|
462
|
+
el.appendChild(frag);
|
|
448
463
|
}
|
|
449
|
-
el.appendChild(frag);
|
|
450
464
|
if (initial && initial.length > 0) setEmpty(false);
|
|
451
465
|
}
|
|
452
466
|
// 仅初始化一次;后续受控同步走下方 effect
|
|
@@ -793,7 +807,7 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
793
807
|
return /*#__PURE__*/createPortal( /*#__PURE__*/React.createElement(ComposerInlineRef, {
|
|
794
808
|
data: chip.data,
|
|
795
809
|
active: paramEditChipId === chip.data.id,
|
|
796
|
-
onClick: onInlineRefClick ? function (anchor) {
|
|
810
|
+
onClick: onInlineRefClick && chipHasEditableParams(chip.data) ? function (anchor) {
|
|
797
811
|
return onInlineRefClick(chip.data.id, anchor);
|
|
798
812
|
} : undefined
|
|
799
813
|
}), chip.host, chip.data.id);
|
|
@@ -39,6 +39,8 @@ export interface UseChipManagerReturn {
|
|
|
39
39
|
updateChipData: (id: string, patch: Partial<ChipData>) => void;
|
|
40
40
|
/** 按 id 取 chip host(参数面板 anchor)。 */
|
|
41
41
|
getChipHost: (id: string) => HTMLSpanElement | null;
|
|
42
|
+
/** 当前 chip 快照(读 ref,插入后同步 onChange 时可用)。 */
|
|
43
|
+
getChips: () => ChipData[];
|
|
42
44
|
/** 清空所有 chip 的 React 状态(DOM 由调用方 editor.innerHTML='' 一并处理)。 */
|
|
43
45
|
resetChips: () => void;
|
|
44
46
|
}
|
|
@@ -388,6 +388,13 @@ onAfterMutate) {
|
|
|
388
388
|
return c.data.id === id;
|
|
389
389
|
})) === null || _chipsRef$current$fin2 === void 0 ? void 0 : _chipsRef$current$fin2.host) !== null && _chipsRef$current$fin !== void 0 ? _chipsRef$current$fin : null;
|
|
390
390
|
}, []);
|
|
391
|
+
|
|
392
|
+
/** 读 ref,插入后同步 onChange 时 state 可能还没 flush。 */
|
|
393
|
+
var getChips = useCallback(function () {
|
|
394
|
+
return chipsRef.current.map(function (c) {
|
|
395
|
+
return c.data;
|
|
396
|
+
});
|
|
397
|
+
}, []);
|
|
391
398
|
var resetChips = useCallback(function () {
|
|
392
399
|
setChips([]);
|
|
393
400
|
chipsRef.current = [];
|
|
@@ -401,6 +408,7 @@ onAfterMutate) {
|
|
|
401
408
|
removeChip: removeChip,
|
|
402
409
|
updateChipData: updateChipData,
|
|
403
410
|
getChipHost: getChipHost,
|
|
411
|
+
getChips: getChips,
|
|
404
412
|
resetChips: resetChips
|
|
405
413
|
};
|
|
406
414
|
}
|
package/dist/composer/index.d.ts
CHANGED
|
@@ -66,8 +66,10 @@ export interface ComposerProps {
|
|
|
66
66
|
value?: string;
|
|
67
67
|
/** 输入框非受控默认值 */
|
|
68
68
|
defaultValue?: string;
|
|
69
|
-
/**
|
|
70
|
-
|
|
69
|
+
/** 与 defaultValue 配套,首次挂载时把 marker 还原成 chip。 */
|
|
70
|
+
defaultChips?: ChipData[];
|
|
71
|
+
/** 输入框值变化回调。第二参是当前 chip 快照,旧调用方忽略即可。 */
|
|
72
|
+
onChange?: (value: string, chips?: ChipData[]) => void;
|
|
71
73
|
/**
|
|
72
74
|
* 发送回调。
|
|
73
75
|
*
|
|
@@ -176,6 +178,8 @@ export interface ComposerProps {
|
|
|
176
178
|
* - 不传则非受控,组件内部自管,沿用 `URL.createObjectURL(f)` 生成 blob url 的旧行为(向后兼容)。
|
|
177
179
|
*/
|
|
178
180
|
attachments?: Attachment[];
|
|
181
|
+
/** 非受控附件初始值,随组件挂载(如 `key` 切换会话)生效。 */
|
|
182
|
+
defaultAttachments?: Attachment[];
|
|
179
183
|
/**
|
|
180
184
|
* 附件数组变化时触发(新增、删除、外部回写都会调)。
|
|
181
185
|
* 受控模式下与 `attachments` 配合形成 React 标准受控形态。
|
|
@@ -235,7 +239,8 @@ export interface ComposerProps {
|
|
|
235
239
|
*/
|
|
236
240
|
fileRejectMessage?: (ext: string) => string;
|
|
237
241
|
/**
|
|
238
|
-
*
|
|
242
|
+
* 参数面板内容渲染。提供后,**待补充 / 已填参数** 的 invocation chip
|
|
243
|
+
* 可点击打开面板;无参数 skill 无 hover、不可点。
|
|
239
244
|
* `SkillItem.initialState='pending'` 插入后会自动打开。
|
|
240
245
|
*/
|
|
241
246
|
renderParamPanel?: (ctx: ComposerParamPanelContext) => React.ReactNode;
|