one-design-next 0.0.12 → 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 +36 -10
- package/dist/attachments/index.js +66 -16
- package/dist/attachments/style/index.css +86 -37
- 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 +3 -1
- package/dist/composer/editor.js +65 -13
- 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.js +73 -32
- 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 +39 -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/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/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 -2
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
[data-odn-mention] {
|
|
2
|
+
display: inline-flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
white-space: nowrap;
|
|
5
|
+
word-break: keep-all;
|
|
6
|
+
overflow-wrap: normal;
|
|
7
|
+
margin: 0;
|
|
8
|
+
padding: 0 4px;
|
|
9
|
+
border-radius: 6px;
|
|
10
|
+
background: transparent;
|
|
11
|
+
color: var(--odn-color-cyan-6, var(--odn-color-cyan-5));
|
|
12
|
+
font-weight: 500;
|
|
13
|
+
font-size: inherit;
|
|
14
|
+
line-height: inherit;
|
|
15
|
+
cursor: default;
|
|
16
|
+
user-select: none;
|
|
17
|
+
-webkit-user-select: none;
|
|
18
|
+
transition: background-color 0.15s;
|
|
19
|
+
}
|
|
20
|
+
[data-odn-mention][data-state=active], [data-odn-mention]:hover {
|
|
21
|
+
background: color-mix(in srgb, var(--odn-color-cyan-5) 12%, transparent);
|
|
22
|
+
}
|
|
23
|
+
[data-odn-mention][data-clickable] {
|
|
24
|
+
cursor: pointer;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
[data-odn-mention-at] {
|
|
28
|
+
opacity: 0.7;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
[data-odn-mention-popover-inner] {
|
|
32
|
+
display: flex;
|
|
33
|
+
flex-direction: column;
|
|
34
|
+
gap: 6px;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
[data-odn-mention-popover-title] {
|
|
38
|
+
display: inline-flex;
|
|
39
|
+
align-items: center;
|
|
40
|
+
gap: 1px;
|
|
41
|
+
font-weight: 500;
|
|
42
|
+
color: var(--odn-color-cyan-6, var(--odn-color-cyan-5));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
[data-odn-mention-popover-at] {
|
|
46
|
+
opacity: 0.7;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
[data-odn-mention-popover-summary] {
|
|
50
|
+
display: inline-block;
|
|
51
|
+
align-self: flex-start;
|
|
52
|
+
padding: 2px 6px;
|
|
53
|
+
border-radius: 4px;
|
|
54
|
+
background: color-mix(in srgb, var(--odn-color-cyan-5) 10%, transparent);
|
|
55
|
+
color: var(--odn-color-cyan-6, var(--odn-color-cyan-5));
|
|
56
|
+
font-size: 12px;
|
|
57
|
+
line-height: 1.4;
|
|
58
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import './style';
|
|
3
|
+
/**
|
|
4
|
+
* MessageImage 渲染的图片项。
|
|
5
|
+
* 与 `Attachment` 不同:图片消息的「主体」就是图本身,不需要 name / type / size 等
|
|
6
|
+
* 文件元信息——展示文件名只会变成 `/qidian/im/image/3c87...` 这种对用户无意义的服务端路径。
|
|
7
|
+
*/
|
|
8
|
+
export interface MessageImageItem {
|
|
9
|
+
url: string;
|
|
10
|
+
alt?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface MessageImageProps {
|
|
13
|
+
/** 待渲染的图片列表。 */
|
|
14
|
+
images: MessageImageItem[];
|
|
15
|
+
/**
|
|
16
|
+
* 点击图片回调,传入图片 index。组件不内置大图查看器,业务方按需对接
|
|
17
|
+
* `PreviewPanel` / 自己实现的 lightbox。
|
|
18
|
+
*/
|
|
19
|
+
onPreview?: (index: number) => void;
|
|
20
|
+
/**
|
|
21
|
+
* 删除按钮点击回调,传入图片 index。本期 MessageImage 主要承载消息态展示,
|
|
22
|
+
* 该回调主要为未来扩展(如撤回未发送消息中的图)保留。
|
|
23
|
+
*/
|
|
24
|
+
onRemove?: (index: number) => void;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 用户消息中的图片附件渲染组件——`Image` leaf 之上的「消息态」语义包装。
|
|
28
|
+
*
|
|
29
|
+
* 两态:
|
|
30
|
+
* - 单图:数据驱动尺寸,max 280×360 contain,保留原图长宽比
|
|
31
|
+
* - 多图:模板驱动尺寸,每张 88×88 cover,横向 flex + wrap
|
|
32
|
+
* 与单图差异化是为了多图场景下「整齐成组」比「逐张完整」更重要——
|
|
33
|
+
* 业界共识(微信 / iMessage / Telegram 多图均为统一缩略 + 点开看大图)
|
|
34
|
+
*
|
|
35
|
+
* Composer 待发送态等其他场景**不应消费此组件**——那是输入态语义,
|
|
36
|
+
* 应直接用 `Image` leaf + 自己的尺寸 wrap。
|
|
37
|
+
*/
|
|
38
|
+
export declare function MessageImage({ images, onPreview, onRemove }: MessageImageProps): import("react").JSX.Element | null;
|
|
39
|
+
export declare namespace MessageImage {
|
|
40
|
+
var displayName: string;
|
|
41
|
+
}
|
|
42
|
+
export default MessageImage;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import Image from "../image";
|
|
2
|
+
import "./style";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* MessageImage 渲染的图片项。
|
|
6
|
+
* 与 `Attachment` 不同:图片消息的「主体」就是图本身,不需要 name / type / size 等
|
|
7
|
+
* 文件元信息——展示文件名只会变成 `/qidian/im/image/3c87...` 这种对用户无意义的服务端路径。
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 用户消息中的图片附件渲染组件——`Image` leaf 之上的「消息态」语义包装。
|
|
12
|
+
*
|
|
13
|
+
* 两态:
|
|
14
|
+
* - 单图:数据驱动尺寸,max 280×360 contain,保留原图长宽比
|
|
15
|
+
* - 多图:模板驱动尺寸,每张 88×88 cover,横向 flex + wrap
|
|
16
|
+
* 与单图差异化是为了多图场景下「整齐成组」比「逐张完整」更重要——
|
|
17
|
+
* 业界共识(微信 / iMessage / Telegram 多图均为统一缩略 + 点开看大图)
|
|
18
|
+
*
|
|
19
|
+
* Composer 待发送态等其他场景**不应消费此组件**——那是输入态语义,
|
|
20
|
+
* 应直接用 `Image` leaf + 自己的尺寸 wrap。
|
|
21
|
+
*/
|
|
22
|
+
export function MessageImage(_ref) {
|
|
23
|
+
var images = _ref.images,
|
|
24
|
+
onPreview = _ref.onPreview,
|
|
25
|
+
onRemove = _ref.onRemove;
|
|
26
|
+
if (images.length === 0) return null;
|
|
27
|
+
var isMulti = images.length > 1;
|
|
28
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
29
|
+
"data-odn-message-image": true,
|
|
30
|
+
"data-odn-message-image-multi": isMulti || undefined
|
|
31
|
+
}, images.map(function (img, i) {
|
|
32
|
+
return /*#__PURE__*/React.createElement(Image, {
|
|
33
|
+
key: i,
|
|
34
|
+
url: img.url,
|
|
35
|
+
alt: img.alt,
|
|
36
|
+
onPreview: onPreview ? function () {
|
|
37
|
+
return onPreview(i);
|
|
38
|
+
} : undefined,
|
|
39
|
+
onRemove: onRemove ? function () {
|
|
40
|
+
return onRemove(i);
|
|
41
|
+
} : undefined
|
|
42
|
+
});
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
MessageImage.displayName = 'MessageImage';
|
|
46
|
+
export default MessageImage;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
@charset "UTF-8";
|
|
2
|
+
/* MessageImage 尺寸 token(业务方按需 cascade 覆盖):
|
|
3
|
+
*
|
|
4
|
+
* 单图态(数据驱动尺寸):
|
|
5
|
+
* --odn-message-image-max-width 280:drawer 模式下 UserBubble inner 可用
|
|
6
|
+
* 宽 384px(chat area 560 - px-6×2),280 留 104px 余量;fullscreen
|
|
7
|
+
* 模式 UserBubble inner 576px 完全富余
|
|
8
|
+
* --odn-message-image-max-height 360:长边 × 1.286(≈ 黄金比 1.272),
|
|
9
|
+
* 竖图 9:16 → 203×360、3:4 → 270×360、2:3 → 240×360 都保留竖向张力;
|
|
10
|
+
* 与 iMessage(260×360) / Claude(300×400) 中段对齐
|
|
11
|
+
*
|
|
12
|
+
* 多图态(模板驱动尺寸):
|
|
13
|
+
* --odn-message-image-thumb-size 88:3 张时正好填满 280 包围盒(88×3 +
|
|
14
|
+
* gap 4×2 = 272,留 8 余量),4+ 张自然换行;与 iMessage / Telegram
|
|
15
|
+
* 多图缩略 80–100 区间一致
|
|
16
|
+
* --odn-message-image-thumb-gap 4:图与图之间最小可识别留白
|
|
17
|
+
*
|
|
18
|
+
* 以上都是 8 的整数倍,不破坏栅格。 */
|
|
19
|
+
html {
|
|
20
|
+
--odn-message-image-max-width: 280px;
|
|
21
|
+
--odn-message-image-max-height: 360px;
|
|
22
|
+
--odn-message-image-thumb-size: 88px;
|
|
23
|
+
--odn-message-image-thumb-gap: 4px;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* MessageImage = Image leaf 之上的「消息态」语义包装。
|
|
27
|
+
* - 单图:数据驱动尺寸(max 280×360 contain),保留原图比例
|
|
28
|
+
* - 多图:模板驱动尺寸(88×88 cover,flex wrap),整齐成组
|
|
29
|
+
* - 圆角 scoped 到 MessageImage 内的 Image leaf 容器,不影响其他场景下的
|
|
30
|
+
* Image leaf(Composer 缩略由 Composer 自己加圆角) */
|
|
31
|
+
[data-odn-message-image] {
|
|
32
|
+
display: inline-block;
|
|
33
|
+
max-width: min(100%, var(--odn-message-image-max-width));
|
|
34
|
+
}
|
|
35
|
+
[data-odn-message-image] [data-odn-image] {
|
|
36
|
+
display: block;
|
|
37
|
+
border-radius: 8px;
|
|
38
|
+
overflow: hidden;
|
|
39
|
+
}
|
|
40
|
+
[data-odn-message-image] img {
|
|
41
|
+
max-width: 100%;
|
|
42
|
+
max-height: var(--odn-message-image-max-height);
|
|
43
|
+
object-fit: contain;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
[data-odn-message-image][data-odn-message-image-multi] {
|
|
47
|
+
display: flex;
|
|
48
|
+
flex-wrap: wrap;
|
|
49
|
+
gap: var(--odn-message-image-thumb-gap);
|
|
50
|
+
}
|
|
51
|
+
[data-odn-message-image][data-odn-message-image-multi] [data-odn-image] {
|
|
52
|
+
width: var(--odn-message-image-thumb-size);
|
|
53
|
+
height: var(--odn-message-image-thumb-size);
|
|
54
|
+
}
|
|
55
|
+
[data-odn-message-image][data-odn-message-image-multi] img {
|
|
56
|
+
width: 100%;
|
|
57
|
+
height: 100%;
|
|
58
|
+
max-height: none;
|
|
59
|
+
object-fit: cover;
|
|
60
|
+
}
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
+
import { type MessageImageItem } from '../message-image';
|
|
2
3
|
import type { Attachment, ChatMessage } from '../_genui-types';
|
|
3
4
|
import './style';
|
|
4
5
|
export interface UserBubbleProps {
|
|
5
6
|
message: ChatMessage;
|
|
6
7
|
onFileClick?: (attachment: Attachment) => void;
|
|
8
|
+
/**
|
|
9
|
+
* 点击图片附件回调,业务方按此对接自己的 lightbox / 大图查看器。
|
|
10
|
+
* @param index 被点击的图片在「当前消息内已分流的图片子集」中的位置(0-based)
|
|
11
|
+
* @param images 当前消息内所有 image attachments(已转成 `MessageImageItem`
|
|
12
|
+
* 的形态,包含 `url` 与 `alt`),方便直接 push 到 lightbox
|
|
13
|
+
* 实现上下张切换
|
|
14
|
+
* 不传 → 图片不可点击预览。
|
|
15
|
+
*/
|
|
16
|
+
onImagePreview?: (index: number, images: MessageImageItem[]) => void;
|
|
7
17
|
}
|
|
8
|
-
export declare function UserBubble({ message, onFileClick }: UserBubbleProps): import("react").JSX.Element;
|
|
18
|
+
export declare function UserBubble({ message, onFileClick, onImagePreview }: UserBubbleProps): import("react").JSX.Element;
|
|
9
19
|
export declare namespace UserBubble {
|
|
10
20
|
var displayName: string;
|
|
11
21
|
}
|
|
@@ -1,20 +1,45 @@
|
|
|
1
1
|
import { Attachments } from "../attachments";
|
|
2
|
+
import MessageImage from "../message-image";
|
|
2
3
|
import "./style";
|
|
3
4
|
export function UserBubble(_ref) {
|
|
5
|
+
var _message$attachments;
|
|
4
6
|
var message = _ref.message,
|
|
5
|
-
onFileClick = _ref.onFileClick
|
|
7
|
+
onFileClick = _ref.onFileClick,
|
|
8
|
+
onImagePreview = _ref.onImagePreview;
|
|
6
9
|
var hasText = !!message.content;
|
|
7
|
-
var
|
|
10
|
+
var all = (_message$attachments = message.attachments) !== null && _message$attachments !== void 0 ? _message$attachments : [];
|
|
11
|
+
|
|
12
|
+
/* 图片附件分流到 MessageImage,保持其数据驱动尺寸的渲染语义;
|
|
13
|
+
* 其他附件(文件 / 报告 / chip)继续走 Attachments 的模板槽位渲染。
|
|
14
|
+
* 分流是 UserBubble 内部行为,业务方传入的 message.attachments 形状不变。 */
|
|
15
|
+
var images = all.filter(function (a) {
|
|
16
|
+
return a.type.startsWith('image/') && a.url;
|
|
17
|
+
}).map(function (a) {
|
|
18
|
+
return {
|
|
19
|
+
url: a.url,
|
|
20
|
+
alt: a.name
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
var files = all.filter(function (a) {
|
|
24
|
+
return !(a.type.startsWith('image/') && a.url);
|
|
25
|
+
});
|
|
8
26
|
return /*#__PURE__*/React.createElement("div", {
|
|
9
27
|
"data-odn-user-bubble": true
|
|
10
28
|
}, /*#__PURE__*/React.createElement("div", {
|
|
11
29
|
"data-odn-user-bubble-inner": true
|
|
12
|
-
},
|
|
30
|
+
}, images.length > 0 && /*#__PURE__*/React.createElement("div", {
|
|
31
|
+
"data-odn-user-bubble-images": true
|
|
32
|
+
}, /*#__PURE__*/React.createElement(MessageImage, {
|
|
33
|
+
images: images,
|
|
34
|
+
onPreview: onImagePreview ? function (i) {
|
|
35
|
+
return onImagePreview(i, images);
|
|
36
|
+
} : undefined
|
|
37
|
+
})), hasText && /*#__PURE__*/React.createElement("div", {
|
|
13
38
|
"data-odn-user-bubble-text": true
|
|
14
|
-
}, /*#__PURE__*/React.createElement("p", null, message.content)),
|
|
39
|
+
}, /*#__PURE__*/React.createElement("p", null, message.content)), files.length > 0 && /*#__PURE__*/React.createElement("div", {
|
|
15
40
|
"data-odn-user-bubble-files": true
|
|
16
41
|
}, /*#__PURE__*/React.createElement(Attachments, {
|
|
17
|
-
attachments:
|
|
42
|
+
attachments: files,
|
|
18
43
|
onFileClick: onFileClick,
|
|
19
44
|
compact: hasText
|
|
20
45
|
}))));
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
max-width: 75%;
|
|
8
8
|
display: flex;
|
|
9
9
|
flex-direction: column;
|
|
10
|
+
align-items: flex-end;
|
|
10
11
|
gap: 6px;
|
|
11
12
|
}
|
|
12
13
|
|
|
@@ -25,6 +26,11 @@
|
|
|
25
26
|
margin: 0;
|
|
26
27
|
}
|
|
27
28
|
|
|
29
|
+
[data-odn-user-bubble-images] {
|
|
30
|
+
display: flex;
|
|
31
|
+
justify-content: flex-end;
|
|
32
|
+
}
|
|
33
|
+
|
|
28
34
|
[data-odn-user-bubble-files] {
|
|
29
35
|
display: flex;
|
|
30
36
|
justify-content: flex-end;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "one-design-next",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"description": "One Design Next from TAD@tencent.com",
|
|
5
5
|
"module": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
"stylelint": "^16.23.1",
|
|
113
113
|
"stylelint-config-standard-scss": "^15.0.1",
|
|
114
114
|
"svgo": "latest",
|
|
115
|
-
"tailwind-merge": "^3.
|
|
115
|
+
"tailwind-merge": "^3.6.0",
|
|
116
116
|
"tailwindcss": "^4",
|
|
117
117
|
"tweakpane": "latest"
|
|
118
118
|
},
|