prime-ui-kit 0.21.4 → 0.21.5
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/chunks/{chunk-UNNQITFE.js → chunk-CM2KZEDV.js} +378 -288
- package/dist/chunks/{chunk-HMLQCKRL.js → chunk-FWL3NJYA.js} +578 -552
- package/dist/chunks/{chunk-WGXXPJDR.js → chunk-KQLHVPF5.js} +2 -2
- package/dist/chunks/{chunk-PFASPQSJ.js → chunk-XH64AMXF.js} +5 -1
- package/dist/chunks/chunk-ZGEHB27U.js +5643 -0
- package/dist/color-picker.js +3 -3
- package/dist/components/chat/Chat.d.ts +4 -2
- package/dist/components/chat/ChatRows.d.ts +57 -2
- package/dist/components/chat/messageFlow.d.ts +11 -0
- package/dist/components/index.d.ts +1 -1
- package/dist/icon-set.js +4 -4
- package/dist/icons/registry.d.ts +2 -0
- package/dist/index.css +1 -1
- package/dist/index.js +3 -3
- package/dist/internal/messageList.d.ts +3 -1
- package/dist/skill/api-contract.md +2 -2
- package/dist/skill/composition.md +1 -1
- package/dist/skill/reference/components/chat/COMPONENT.md +41 -5
- package/dist/skill/reference/components/chat/examples/events.tsx +129 -0
- package/dist/skill/reference/components/chat/examples/screen.tsx +56 -2
- package/package.json +1 -1
- package/src/components/chat/COMPONENT.md +41 -5
- package/src/components/chat/examples/events.tsx +129 -0
- package/src/components/chat/examples/screen.tsx +56 -2
- package/dist/chunks/chunk-SUGCIPD7.js +0 -5669
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/** What happened to the client, right in the dialog: who took it, a stage it moved to, a manager who joined; events in a row stand as one group, a new one rises in at the end — `isService`, `Chat.Service`, `Chat.ServiceIcon`, `Chat.ServiceChange`, `time`. */
|
|
2
|
+
import { Badge, Button, Card, Chat, Icon, Message } from "prime-ui-kit";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
import styles from "./examples.module.css";
|
|
6
|
+
|
|
7
|
+
const NOW = new Date(2026, 9, 15, 11, 0);
|
|
8
|
+
const at = (hour: number, minute: number) => new Date(2026, 9, 15, hour, minute);
|
|
9
|
+
|
|
10
|
+
type DialogItem =
|
|
11
|
+
| { id: string; kind: "message"; author: "client" | "agent"; sentAt: Date; text: string }
|
|
12
|
+
| { id: string; kind: "taken"; sentAt: Date }
|
|
13
|
+
| { id: string; kind: "stage"; sentAt: Date; from: string; to: string }
|
|
14
|
+
| { id: string; kind: "joined"; sentAt: Date; manager: string };
|
|
15
|
+
|
|
16
|
+
const DIALOG: DialogItem[] = [
|
|
17
|
+
{
|
|
18
|
+
id: "ev-1",
|
|
19
|
+
kind: "message",
|
|
20
|
+
author: "client",
|
|
21
|
+
sentAt: at(10, 12),
|
|
22
|
+
text: "Здравствуйте! Ищу склад под аренду, 100–150 м², с 1 ноября.",
|
|
23
|
+
},
|
|
24
|
+
{ id: "ev-2", kind: "taken", sentAt: at(10, 12) },
|
|
25
|
+
{ id: "ev-3", kind: "stage", sentAt: at(10, 12), from: "Лид", to: "Арендатор" },
|
|
26
|
+
{
|
|
27
|
+
id: "ev-4",
|
|
28
|
+
kind: "message",
|
|
29
|
+
author: "agent",
|
|
30
|
+
sentAt: at(10, 13),
|
|
31
|
+
text: "Добрый день! Есть склад 120 м² на Складской, 4, свободен с 25 октября. Прислать планировку?",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: "ev-5",
|
|
35
|
+
kind: "message",
|
|
36
|
+
author: "client",
|
|
37
|
+
sentAt: at(10, 15),
|
|
38
|
+
text: "Да, и хотелось бы обсудить скидку за год вперёд.",
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
const JOINED: DialogItem = {
|
|
43
|
+
id: "ev-6",
|
|
44
|
+
kind: "joined",
|
|
45
|
+
sentAt: at(10, 16),
|
|
46
|
+
manager: "Анна Котова",
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
function renderItem(item: DialogItem) {
|
|
50
|
+
if (item.kind === "taken") {
|
|
51
|
+
return (
|
|
52
|
+
<Chat.Service time={item.sentAt}>
|
|
53
|
+
<Chat.ServiceIcon>
|
|
54
|
+
<Icon name="object.bot" />
|
|
55
|
+
</Chat.ServiceIcon>
|
|
56
|
+
ИИ-агент взял клиента
|
|
57
|
+
</Chat.Service>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
if (item.kind === "stage") {
|
|
61
|
+
return (
|
|
62
|
+
<Chat.Service time={item.sentAt}>
|
|
63
|
+
<Chat.ServiceIcon>
|
|
64
|
+
<Icon name="object.funnel" />
|
|
65
|
+
</Chat.ServiceIcon>
|
|
66
|
+
ИИ-агент перевёл клиента
|
|
67
|
+
<Chat.ServiceChange
|
|
68
|
+
from={<Badge.Root color="gray">{item.from}</Badge.Root>}
|
|
69
|
+
to={<Badge.Root color="green">{item.to}</Badge.Root>}
|
|
70
|
+
/>
|
|
71
|
+
</Chat.Service>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
if (item.kind === "joined") {
|
|
75
|
+
return (
|
|
76
|
+
<Chat.Service time={item.sentAt}>
|
|
77
|
+
<Chat.ServiceIcon>
|
|
78
|
+
<Icon name="object.user" />
|
|
79
|
+
</Chat.ServiceIcon>
|
|
80
|
+
Менеджер {item.manager} подключилась к диалогу
|
|
81
|
+
</Chat.Service>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
return (
|
|
85
|
+
<Message.Root
|
|
86
|
+
direction={item.author === "agent" ? "outgoing" : "incoming"}
|
|
87
|
+
time={item.sentAt}
|
|
88
|
+
status={item.author === "agent" ? "read" : undefined}
|
|
89
|
+
>
|
|
90
|
+
<Message.Text>{item.text}</Message.Text>
|
|
91
|
+
</Message.Root>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export default function ChatEventsExample() {
|
|
96
|
+
const [items, setItems] = React.useState(DIALOG);
|
|
97
|
+
const joined = items.includes(JOINED);
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<div className={styles.live}>
|
|
101
|
+
<div className={styles.liveBar}>
|
|
102
|
+
<Button.Root
|
|
103
|
+
variant="soft"
|
|
104
|
+
disabled={joined}
|
|
105
|
+
onClick={() => setItems((current) => [...current, JOINED])}
|
|
106
|
+
>
|
|
107
|
+
<Button.Icon>
|
|
108
|
+
<Icon name="action.addContact" />
|
|
109
|
+
</Button.Icon>
|
|
110
|
+
Подключить менеджера
|
|
111
|
+
</Button.Root>
|
|
112
|
+
</div>
|
|
113
|
+
<Card.Root className={styles.short}>
|
|
114
|
+
<Chat.Root>
|
|
115
|
+
<Chat.Messages
|
|
116
|
+
aria-label="Диалог с клиентом «Склад на Складской»"
|
|
117
|
+
now={NOW}
|
|
118
|
+
items={items}
|
|
119
|
+
getKey={(item: DialogItem) => item.id}
|
|
120
|
+
getAuthor={(item: DialogItem) => (item.kind === "message" ? item.author : "system")}
|
|
121
|
+
getDate={(item: DialogItem) => item.sentAt}
|
|
122
|
+
isService={(item: DialogItem) => item.kind !== "message"}
|
|
123
|
+
renderMessage={renderItem}
|
|
124
|
+
/>
|
|
125
|
+
</Chat.Root>
|
|
126
|
+
</Card.Root>
|
|
127
|
+
</div>
|
|
128
|
+
);
|
|
129
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
/** A support messenger as a work screen: the title and the unread count in its top bar, the dialogs with a search over them beside the conversation (one pane at a time on a phone), history that loads above as you scroll up, the unread band, reply and edit from the menu, the typing signal both ways, unread counts from what was seen, and the Composer whose messages rise into the list while the client answers — `items`, `renderMessage`, `hasOlder`, `onLoadOlder`, `typing`. */
|
|
1
|
+
/** A support messenger as a work screen: the title and the unread count in its top bar, the dialogs with a search over them beside the conversation (one pane at a time on a phone), history that loads above as you scroll up, the unread band, reply and edit from the menu, the typing signal both ways, the request's events (an agent took it, its status moved, you joined) between the messages, unread counts from what was seen, and the Composer whose messages rise into the list while the client answers — `items`, `renderMessage`, `isService`, `hasOlder`, `onLoadOlder`, `typing`. */
|
|
2
2
|
import {
|
|
3
3
|
Avatar,
|
|
4
|
+
Badge,
|
|
4
5
|
Card,
|
|
5
6
|
Chat,
|
|
6
7
|
ChatList,
|
|
@@ -28,7 +29,13 @@ type Content =
|
|
|
28
29
|
| { kind: "text"; text: string }
|
|
29
30
|
| { kind: "media"; items: GalleryItem[]; caption?: string }
|
|
30
31
|
| { kind: "voice"; src: string; waveform: number[]; duration: number }
|
|
31
|
-
| { kind: "file"; name: string; size: number; href: string }
|
|
32
|
+
| { kind: "file"; name: string; size: number; href: string }
|
|
33
|
+
| {
|
|
34
|
+
kind: "event";
|
|
35
|
+
icon: "object.bot" | "object.funnel" | "object.user";
|
|
36
|
+
text: string;
|
|
37
|
+
change?: { from: string; to: string };
|
|
38
|
+
};
|
|
32
39
|
|
|
33
40
|
type ChatMessage = Content & {
|
|
34
41
|
id: string;
|
|
@@ -129,6 +136,31 @@ const HISTORY: ChatMessage[] = [
|
|
|
129
136
|
],
|
|
130
137
|
caption: "Вот так выглядит",
|
|
131
138
|
},
|
|
139
|
+
{
|
|
140
|
+
id: "e1",
|
|
141
|
+
from: "client",
|
|
142
|
+
sentAt: at(7, 10, 14),
|
|
143
|
+
kind: "event",
|
|
144
|
+
icon: "object.bot",
|
|
145
|
+
text: "ИИ-агент взял обращение",
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
id: "e2",
|
|
149
|
+
from: "client",
|
|
150
|
+
sentAt: at(7, 10, 14),
|
|
151
|
+
kind: "event",
|
|
152
|
+
icon: "object.funnel",
|
|
153
|
+
text: "ИИ-агент перевёл обращение",
|
|
154
|
+
change: { from: "Новое", to: "В работе" },
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
id: "e3",
|
|
158
|
+
from: "me",
|
|
159
|
+
sentAt: at(7, 10, 19),
|
|
160
|
+
kind: "event",
|
|
161
|
+
icon: "object.user",
|
|
162
|
+
text: "Вы подключились к диалогу",
|
|
163
|
+
},
|
|
132
164
|
{
|
|
133
165
|
id: "m3",
|
|
134
166
|
from: "me",
|
|
@@ -228,6 +260,8 @@ const excerpt = (message: ChatMessage) => {
|
|
|
228
260
|
);
|
|
229
261
|
case "file":
|
|
230
262
|
return message.name;
|
|
263
|
+
case "event":
|
|
264
|
+
return message.text;
|
|
231
265
|
}
|
|
232
266
|
};
|
|
233
267
|
|
|
@@ -260,6 +294,8 @@ const renderContent = (message: ChatMessage) => {
|
|
|
260
294
|
);
|
|
261
295
|
case "file":
|
|
262
296
|
return <Message.File name={message.name} fileSize={message.size} href={message.href} />;
|
|
297
|
+
case "event":
|
|
298
|
+
return null;
|
|
263
299
|
}
|
|
264
300
|
};
|
|
265
301
|
|
|
@@ -522,6 +558,23 @@ export default function ChatScreenExample() {
|
|
|
522
558
|
// re-renders the one message it touches. A dialog loads its own messages, so a row never
|
|
523
559
|
// outlives the contact it names; a reply's original comes from the list (`entry.find`).
|
|
524
560
|
const renderMessage = (message: ChatMessage, entry: ChatMessageEntry<ChatMessage>) => {
|
|
561
|
+
// What happened to the request (an agent took it, its status moved, you joined): a row.
|
|
562
|
+
if (message.kind === "event") {
|
|
563
|
+
return (
|
|
564
|
+
<Chat.Service time={message.sentAt}>
|
|
565
|
+
<Chat.ServiceIcon>
|
|
566
|
+
<Icon name={message.icon} />
|
|
567
|
+
</Chat.ServiceIcon>
|
|
568
|
+
{message.text}
|
|
569
|
+
{message.change ? (
|
|
570
|
+
<Chat.ServiceChange
|
|
571
|
+
from={<Badge.Root color="gray">{message.change.from}</Badge.Root>}
|
|
572
|
+
to={<Badge.Root color="blue">{message.change.to}</Badge.Root>}
|
|
573
|
+
/>
|
|
574
|
+
) : null}
|
|
575
|
+
</Chat.Service>
|
|
576
|
+
);
|
|
577
|
+
}
|
|
525
578
|
const own = message.from === "me";
|
|
526
579
|
const original = message.replyTo ? entry.find(message.replyTo) : undefined;
|
|
527
580
|
return (
|
|
@@ -645,6 +698,7 @@ export default function ChatScreenExample() {
|
|
|
645
698
|
getKey={(message) => message.id}
|
|
646
699
|
getAuthor={(message) => message.from}
|
|
647
700
|
getDate={(message) => message.sentAt}
|
|
701
|
+
isService={(message) => message.kind === "event"}
|
|
648
702
|
renderMessage={renderMessage}
|
|
649
703
|
unread={FIRST_UNREAD}
|
|
650
704
|
now={NOW}
|