@mieweb/ui 0.10.0-dev.29 → 0.10.0-dev.30
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/brands/index.cjs +7 -7
- package/dist/brands/index.js +2 -2
- package/dist/{chunk-JYZW2PZS.cjs → chunk-254QK722.cjs} +7 -7
- package/dist/chunk-254QK722.cjs.map +1 -0
- package/dist/{chunk-FBLVPM2K.js → chunk-2JICT4A2.js} +26 -10
- package/dist/chunk-2JICT4A2.js.map +1 -0
- package/dist/{chunk-S45EERW3.cjs → chunk-35Y4ILCU.cjs} +4 -4
- package/dist/{chunk-S45EERW3.cjs.map → chunk-35Y4ILCU.cjs.map} +1 -1
- package/dist/{chunk-2BARVD4C.js → chunk-3RXZWHCU.js} +3 -3
- package/dist/{chunk-2BARVD4C.js.map → chunk-3RXZWHCU.js.map} +1 -1
- package/dist/{chunk-MWVW4APN.cjs → chunk-7UTBDFFL.cjs} +4 -4
- package/dist/{chunk-MWVW4APN.cjs.map → chunk-7UTBDFFL.cjs.map} +1 -1
- package/dist/{chunk-FJ7YPVKV.js → chunk-7X6R3JIA.js} +3 -3
- package/dist/{chunk-FJ7YPVKV.js.map → chunk-7X6R3JIA.js.map} +1 -1
- package/dist/{chunk-SYRLCTDV.js → chunk-7ZV67VZE.js} +3 -3
- package/dist/{chunk-SYRLCTDV.js.map → chunk-7ZV67VZE.js.map} +1 -1
- package/dist/chunk-BNH4SXJB.js +874 -0
- package/dist/chunk-BNH4SXJB.js.map +1 -0
- package/dist/{chunk-N2CJJHHB.cjs → chunk-BUT6MF5K.cjs} +27 -11
- package/dist/chunk-BUT6MF5K.cjs.map +1 -0
- package/dist/{chunk-6VFDHJSO.cjs → chunk-COM7RNZU.cjs} +2 -2
- package/dist/{chunk-6VFDHJSO.cjs.map → chunk-COM7RNZU.cjs.map} +1 -1
- package/dist/{chunk-SQHMGT4W.js → chunk-GW4RFJZ5.js} +7 -7
- package/dist/chunk-GW4RFJZ5.js.map +1 -0
- package/dist/{chunk-JID7AZTO.cjs → chunk-H3ROMJYI.cjs} +4 -4
- package/dist/{chunk-JID7AZTO.cjs.map → chunk-H3ROMJYI.cjs.map} +1 -1
- package/dist/{chunk-DZFGTWYF.js → chunk-JBIGSP2T.js} +3 -3
- package/dist/{chunk-DZFGTWYF.js.map → chunk-JBIGSP2T.js.map} +1 -1
- package/dist/{chunk-33DEVA3P.js → chunk-JHG3ELS2.js} +2 -2
- package/dist/{chunk-33DEVA3P.js.map → chunk-JHG3ELS2.js.map} +1 -1
- package/dist/{chunk-WWJIW2IH.cjs → chunk-JSXIB6EJ.cjs} +4 -4
- package/dist/{chunk-WWJIW2IH.cjs.map → chunk-JSXIB6EJ.cjs.map} +1 -1
- package/dist/{chunk-H5YXAMVH.js → chunk-MLAWXPRY.js} +44 -2
- package/dist/chunk-MLAWXPRY.js.map +1 -0
- package/dist/{chunk-AAYXCZMV.cjs → chunk-NKV76R65.cjs} +4 -4
- package/dist/{chunk-AAYXCZMV.cjs.map → chunk-NKV76R65.cjs.map} +1 -1
- package/dist/{chunk-PYJDVWXM.js → chunk-NUB5HRKS.js} +3 -3
- package/dist/{chunk-PYJDVWXM.js.map → chunk-NUB5HRKS.js.map} +1 -1
- package/dist/{chunk-LL6IWKI3.js → chunk-OW3SQJ7P.js} +3 -3
- package/dist/{chunk-LL6IWKI3.js.map → chunk-OW3SQJ7P.js.map} +1 -1
- package/dist/{chunk-OUZDYJ33.cjs → chunk-QURJVPRH.cjs} +44 -2
- package/dist/chunk-QURJVPRH.cjs.map +1 -0
- package/dist/{chunk-TZJQB4P2.js → chunk-RM2HPQIC.js} +72 -14
- package/dist/chunk-RM2HPQIC.js.map +1 -0
- package/dist/{chunk-P4VGVJVI.js → chunk-SD7ONW6S.js} +3 -3
- package/dist/{chunk-P4VGVJVI.js.map → chunk-SD7ONW6S.js.map} +1 -1
- package/dist/chunk-WXFGHDTV.cjs +896 -0
- package/dist/chunk-WXFGHDTV.cjs.map +1 -0
- package/dist/chunk-XDU65GLW.js +21 -0
- package/dist/chunk-XDU65GLW.js.map +1 -0
- package/dist/{chunk-MYHV2ND3.cjs → chunk-XRVMYT5G.cjs} +72 -13
- package/dist/chunk-XRVMYT5G.cjs.map +1 -0
- package/dist/{chunk-I4LXSHKO.cjs → chunk-YRHBSSQ3.cjs} +4 -4
- package/dist/{chunk-I4LXSHKO.cjs.map → chunk-YRHBSSQ3.cjs.map} +1 -1
- package/dist/chunk-YW2AKBLS.cjs +23 -0
- package/dist/chunk-YW2AKBLS.cjs.map +1 -0
- package/dist/{chunk-B2X732V3.cjs → chunk-ZTMYKAVU.cjs} +4 -4
- package/dist/{chunk-B2X732V3.cjs.map → chunk-ZTMYKAVU.cjs.map} +1 -1
- package/dist/components/Collapsible/index.cjs +5 -5
- package/dist/components/Collapsible/index.js +2 -2
- package/dist/components/MediaEditor/index.cjs +8 -8
- package/dist/components/MediaEditor/index.js +3 -3
- package/dist/components/MediaFeed/index.cjs +26 -0
- package/dist/components/MediaFeed/index.cjs.map +1 -0
- package/dist/components/MediaFeed/index.d.cts +104 -0
- package/dist/components/MediaFeed/index.d.ts +104 -0
- package/dist/components/MediaFeed/index.js +17 -0
- package/dist/components/MediaFeed/index.js.map +1 -0
- package/dist/components/MediaPlayer/index.cjs +5 -5
- package/dist/components/MediaPlayer/index.d.cts +18 -0
- package/dist/components/MediaPlayer/index.d.ts +18 -0
- package/dist/components/MediaPlayer/index.js +2 -2
- package/dist/components/RadialExplorer/index.cjs +3 -3
- package/dist/components/RadialExplorer/index.js +2 -2
- package/dist/components/SliderCalculator/index.cjs +4 -4
- package/dist/components/SliderCalculator/index.js +2 -2
- package/dist/components/SuperChat/index.cjs +654 -292
- package/dist/components/SuperChat/index.cjs.map +1 -1
- package/dist/components/SuperChat/index.d.cts +35 -6
- package/dist/components/SuperChat/index.d.ts +35 -6
- package/dist/components/SuperChat/index.js +648 -286
- package/dist/components/SuperChat/index.js.map +1 -1
- package/dist/components/SuperChat/plugins/index.d.cts +2 -2
- package/dist/components/SuperChat/plugins/index.d.ts +2 -2
- package/dist/components/ThemeProvider/index.cjs +9 -9
- package/dist/components/ThemeProvider/index.js +3 -3
- package/dist/components/Tooltip/index.cjs +3 -3
- package/dist/components/Tooltip/index.js +2 -2
- package/dist/esheet.cjs +6 -6
- package/dist/esheet.js +3 -3
- package/dist/globe.cjs +2 -2
- package/dist/globe.js +1 -1
- package/dist/hooks/index.cjs +4 -4
- package/dist/hooks/index.js +2 -2
- package/dist/index.cjs +164 -214
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +120 -1
- package/dist/index.d.ts +120 -1
- package/dist/index.js +25 -82
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/tailwind-preset.cjs +4 -4
- package/dist/tailwind-preset.js +1 -1
- package/dist/{types-DOxdTwmq.d.cts → types-Cx1FHLq2.d.cts} +130 -1
- package/dist/{types-DOxdTwmq.d.ts → types-Cx1FHLq2.d.ts} +130 -1
- package/package.json +1 -1
- package/dist/chunk-6HFFWEM3.cjs +0 -22
- package/dist/chunk-6HFFWEM3.cjs.map +0 -1
- package/dist/chunk-FBLVPM2K.js.map +0 -1
- package/dist/chunk-H5YXAMVH.js.map +0 -1
- package/dist/chunk-HB7C7NB5.js +0 -20
- package/dist/chunk-HB7C7NB5.js.map +0 -1
- package/dist/chunk-JYZW2PZS.cjs.map +0 -1
- package/dist/chunk-MYHV2ND3.cjs.map +0 -1
- package/dist/chunk-N2CJJHHB.cjs.map +0 -1
- package/dist/chunk-OUZDYJ33.cjs.map +0 -1
- package/dist/chunk-SQHMGT4W.js.map +0 -1
- package/dist/chunk-TZJQB4P2.js.map +0 -1
|
@@ -1,295 +1,110 @@
|
|
|
1
1
|
import { TextRenderContext } from '../../chunk-I6CY5C6A.js';
|
|
2
2
|
export { TextRenderContext, useTextRenderContext } from '../../chunk-I6CY5C6A.js';
|
|
3
|
-
import { ChatBubble, MCPToolCallDisplay, AITypingIndicator, SparklesIcon, CloseIcon, JumpToBottomButton } from '../../chunk-
|
|
3
|
+
import { ChatBubble, MCPToolCallDisplay, AITypingIndicator, SparklesIcon, ButtonGroup, CloseIcon, JumpToBottomButton } from '../../chunk-RM2HPQIC.js';
|
|
4
4
|
import { notifyComposerMigrationOnce, ChatComposer } from '../../chunk-CRS2CQWM.js';
|
|
5
|
+
import { MediaFeed } from '../../chunk-BNH4SXJB.js';
|
|
6
|
+
import '../../chunk-RISZWWEQ.js';
|
|
7
|
+
import { MediaPlayer } from '../../chunk-2JICT4A2.js';
|
|
5
8
|
import { Dropdown, DropdownSubmenu, DropdownItem } from '../../chunk-E2PBPQGS.js';
|
|
6
9
|
import '../../chunk-VVDE4CHU.js';
|
|
7
10
|
import { Avatar } from '../../chunk-HZ4MBUC3.js';
|
|
8
11
|
import '../../chunk-IQ4KQJAO.js';
|
|
9
12
|
import { useStickToBottom, useStreamEndedBelowFold } from '../../chunk-BM35CACB.js';
|
|
13
|
+
import '../../chunk-GW4RFJZ5.js';
|
|
14
|
+
import '../../chunk-ENMXHZNE.js';
|
|
10
15
|
import '../../chunk-6NZXWKUE.js';
|
|
11
16
|
import '../../chunk-3IMM2PM4.js';
|
|
17
|
+
import '../../chunk-4SMSH4OY.js';
|
|
12
18
|
import '../../chunk-T4ME7QCT.js';
|
|
13
19
|
import '../../chunk-62ZOA6PX.js';
|
|
14
20
|
import '../../chunk-WSNMQQ4P.js';
|
|
21
|
+
import '../../chunk-VSQF22GL.js';
|
|
15
22
|
import '../../chunk-BKSPDTX4.js';
|
|
16
|
-
import { usePrefersReducedMotion } from '../../chunk-
|
|
23
|
+
import { usePrefersReducedMotion } from '../../chunk-XDU65GLW.js';
|
|
24
|
+
import { Button } from '../../chunk-7YO7DNUV.js';
|
|
17
25
|
import { Badge } from '../../chunk-BMSG4NBH.js';
|
|
26
|
+
import '../../chunk-GVM6DTR5.js';
|
|
18
27
|
import { AnimatedPresence, Animated } from '../../chunk-F4N67NAF.js';
|
|
19
28
|
import { cn } from '../../chunk-TQONQSJO.js';
|
|
20
29
|
import '../../chunk-PX6F3LHL.js';
|
|
21
30
|
import * as React3 from 'react';
|
|
31
|
+
import { createElement } from 'react';
|
|
32
|
+
import { Ellipsis, Check, Clipboard, Pencil, Play, ArrowLeft } from 'lucide-react';
|
|
33
|
+
import { cva } from 'class-variance-authority';
|
|
34
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
22
35
|
import Markdown, { defaultUrlTransform } from 'react-markdown';
|
|
23
36
|
import remarkGfm from 'remark-gfm';
|
|
24
37
|
import rehypeSanitize, { defaultSchema } from 'rehype-sanitize';
|
|
25
|
-
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
26
|
-
import { cva } from 'class-variance-authority';
|
|
27
|
-
import { Ellipsis, Check, Clipboard, Pencil } from 'lucide-react';
|
|
28
38
|
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
29
39
|
|
|
30
|
-
function
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
function baseSanitizeSchema() {
|
|
51
|
-
const schema = JSON.parse(JSON.stringify(defaultSchema));
|
|
52
|
-
const attributes = schema.attributes ?? {};
|
|
53
|
-
const allowClass = (tag) => {
|
|
54
|
-
const existing = attributes[tag] ?? [];
|
|
55
|
-
const withoutClass = existing.filter(
|
|
56
|
-
(a) => !(Array.isArray(a) && a[0] === "className")
|
|
57
|
-
);
|
|
58
|
-
attributes[tag] = [...withoutClass, "className"];
|
|
59
|
-
};
|
|
60
|
-
allowClass("code");
|
|
61
|
-
allowClass("pre");
|
|
62
|
-
allowClass("span");
|
|
63
|
-
allowClass("div");
|
|
64
|
-
schema.attributes = attributes;
|
|
65
|
-
return schema;
|
|
66
|
-
}
|
|
67
|
-
function mergeSanitizeSchema(base, extra) {
|
|
68
|
-
if (!extra) return base;
|
|
69
|
-
const out = { ...base };
|
|
70
|
-
if (Array.isArray(extra.tagNames)) {
|
|
71
|
-
const a = base.tagNames ?? [];
|
|
72
|
-
out.tagNames = Array.from(/* @__PURE__ */ new Set([...a, ...extra.tagNames]));
|
|
73
|
-
}
|
|
74
|
-
if (extra.attributes && typeof extra.attributes === "object") {
|
|
75
|
-
const baseAttrs = {
|
|
76
|
-
...base.attributes ?? {}
|
|
77
|
-
};
|
|
78
|
-
for (const [tag, attrs] of Object.entries(
|
|
79
|
-
extra.attributes
|
|
80
|
-
)) {
|
|
81
|
-
baseAttrs[tag] = [...baseAttrs[tag] ?? [], ...attrs];
|
|
82
|
-
}
|
|
83
|
-
out.attributes = baseAttrs;
|
|
84
|
-
}
|
|
85
|
-
if (extra.protocols && typeof extra.protocols === "object") {
|
|
86
|
-
const baseProtocols = {
|
|
87
|
-
...base.protocols ?? {}
|
|
88
|
-
};
|
|
89
|
-
for (const [attr, protocols] of Object.entries(
|
|
90
|
-
extra.protocols
|
|
91
|
-
)) {
|
|
92
|
-
baseProtocols[attr] = Array.from(
|
|
93
|
-
/* @__PURE__ */ new Set([...baseProtocols[attr] ?? [], ...protocols])
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
out.protocols = baseProtocols;
|
|
97
|
-
}
|
|
98
|
-
for (const [k, v] of Object.entries(extra)) {
|
|
99
|
-
if (k === "tagNames" || k === "attributes" || k === "protocols") continue;
|
|
100
|
-
out[k] = v;
|
|
101
|
-
}
|
|
102
|
-
return out;
|
|
103
|
-
}
|
|
104
|
-
function baseComponents() {
|
|
105
|
-
return {
|
|
106
|
-
a: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
|
|
107
|
-
"a",
|
|
108
|
-
{
|
|
109
|
-
...props,
|
|
110
|
-
className: cn(
|
|
111
|
-
"text-primary-800 hover:text-primary-900 dark:text-primary-300 underline underline-offset-2",
|
|
112
|
-
props.className
|
|
113
|
-
),
|
|
114
|
-
target: props.target ?? "_blank",
|
|
115
|
-
rel: props.rel ?? "noopener noreferrer",
|
|
116
|
-
children
|
|
117
|
-
}
|
|
118
|
-
),
|
|
119
|
-
pre: ({ node: _node, ...props }) => /* @__PURE__ */ jsx(
|
|
120
|
-
"pre",
|
|
121
|
-
{
|
|
122
|
-
...props,
|
|
123
|
-
tabIndex: 0,
|
|
124
|
-
className: cn(
|
|
125
|
-
"overflow-x-auto rounded-lg bg-neutral-900 p-3 text-sm text-neutral-100 dark:bg-neutral-950",
|
|
126
|
-
props.className
|
|
127
|
-
)
|
|
128
|
-
}
|
|
129
|
-
),
|
|
130
|
-
code: ({ node: _node, ...props }) => {
|
|
131
|
-
const isBlock = typeof props.className === "string" && props.className.includes("language-");
|
|
132
|
-
return /* @__PURE__ */ jsx(
|
|
133
|
-
"code",
|
|
134
|
-
{
|
|
135
|
-
...props,
|
|
136
|
-
className: cn(
|
|
137
|
-
!isBlock && "rounded bg-neutral-200 px-1 py-0.5 text-[0.85em] text-neutral-800 dark:bg-neutral-700 dark:text-neutral-100",
|
|
138
|
-
props.className
|
|
139
|
-
)
|
|
140
|
-
}
|
|
141
|
-
);
|
|
142
|
-
},
|
|
143
|
-
input: ({ node: _node, ...props }) => {
|
|
144
|
-
if (props.type === "checkbox") {
|
|
145
|
-
return /* @__PURE__ */ jsx(
|
|
146
|
-
"input",
|
|
40
|
+
function MessageMedia({
|
|
41
|
+
attachment,
|
|
42
|
+
onOpen,
|
|
43
|
+
openLabel,
|
|
44
|
+
playLabel,
|
|
45
|
+
errorLabel,
|
|
46
|
+
retryLabel,
|
|
47
|
+
launchId
|
|
48
|
+
}) {
|
|
49
|
+
const playable = attachment.kind !== "image";
|
|
50
|
+
const actionLabel = playable ? playLabel : openLabel;
|
|
51
|
+
return /* @__PURE__ */ jsxs(
|
|
52
|
+
"div",
|
|
53
|
+
{
|
|
54
|
+
"data-slot": "superchat-message-media",
|
|
55
|
+
className: "mt-3 flex w-72 max-w-full flex-col gap-2",
|
|
56
|
+
children: [
|
|
57
|
+
attachment.title && /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: attachment.title }),
|
|
58
|
+
attachment.kind === "image" && attachment.src ? /* @__PURE__ */ jsx(
|
|
59
|
+
"img",
|
|
147
60
|
{
|
|
148
|
-
|
|
149
|
-
|
|
61
|
+
src: attachment.src,
|
|
62
|
+
alt: attachment.alt ?? attachment.title ?? "",
|
|
63
|
+
loading: "lazy",
|
|
64
|
+
className: "max-h-72 w-full rounded-lg object-contain"
|
|
150
65
|
}
|
|
151
|
-
)
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
children
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
...props,
|
|
192
|
-
className: cn("mt-2 mb-1 text-base font-semibold", props.className),
|
|
193
|
-
children
|
|
194
|
-
}
|
|
195
|
-
),
|
|
196
|
-
h4: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
|
|
197
|
-
"h4",
|
|
198
|
-
{
|
|
199
|
-
...props,
|
|
200
|
-
className: cn("mt-2 mb-1 text-sm font-semibold", props.className),
|
|
201
|
-
children
|
|
202
|
-
}
|
|
203
|
-
),
|
|
204
|
-
h5: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
|
|
205
|
-
"h5",
|
|
206
|
-
{
|
|
207
|
-
...props,
|
|
208
|
-
className: cn("mt-2 mb-1 text-sm font-semibold", props.className),
|
|
209
|
-
children
|
|
210
|
-
}
|
|
211
|
-
),
|
|
212
|
-
h6: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
|
|
213
|
-
"h6",
|
|
214
|
-
{
|
|
215
|
-
...props,
|
|
216
|
-
className: cn(
|
|
217
|
-
"mt-2 mb-1 text-xs font-semibold tracking-wide uppercase",
|
|
218
|
-
props.className
|
|
219
|
-
),
|
|
220
|
-
children
|
|
221
|
-
}
|
|
222
|
-
),
|
|
223
|
-
hr: ({ node: _node, ...props }) => /* @__PURE__ */ jsx(
|
|
224
|
-
"hr",
|
|
225
|
-
{
|
|
226
|
-
...props,
|
|
227
|
-
className: cn(
|
|
228
|
-
"my-2 border-neutral-300 dark:border-neutral-600",
|
|
229
|
-
props.className
|
|
230
|
-
)
|
|
231
|
-
}
|
|
232
|
-
)
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
function createMarkdownRenderer(options = {}) {
|
|
236
|
-
const { plugins = [], trusted = false } = options;
|
|
237
|
-
const remarkPlugins = [
|
|
238
|
-
remarkGfm,
|
|
239
|
-
remarkPreserveLineBreaks,
|
|
240
|
-
...plugins.flatMap((p) => p.remarkPlugins ?? [])
|
|
241
|
-
];
|
|
242
|
-
const pluginRehype = plugins.flatMap(
|
|
243
|
-
(p) => p.rehypePlugins ?? []
|
|
244
|
-
);
|
|
245
|
-
const sanitizeSchema = plugins.reduce(
|
|
246
|
-
(acc, p) => mergeSanitizeSchema(acc, p.sanitizeSchema),
|
|
247
|
-
baseSanitizeSchema()
|
|
248
|
-
);
|
|
249
|
-
const rehypePlugins = trusted ? pluginRehype : [...pluginRehype, [rehypeSanitize, sanitizeSchema]];
|
|
250
|
-
const components = plugins.reduce(
|
|
251
|
-
(acc, p) => ({ ...acc, ...p.components }),
|
|
252
|
-
baseComponents()
|
|
253
|
-
);
|
|
254
|
-
const MarkdownRenderer = (text, ctx) => /* @__PURE__ */ jsx(
|
|
255
|
-
MarkdownContent,
|
|
256
|
-
{
|
|
257
|
-
text,
|
|
258
|
-
messageId: ctx.messageId,
|
|
259
|
-
streaming: ctx.streaming,
|
|
260
|
-
remarkPlugins,
|
|
261
|
-
rehypePlugins,
|
|
262
|
-
components
|
|
263
|
-
},
|
|
264
|
-
ctx.messageId
|
|
66
|
+
) : (attachment.kind === "video" || attachment.kind === "audio") && attachment.src ? (
|
|
67
|
+
// An opaque themed surface: the player's semi-transparent states
|
|
68
|
+
// (error, loading) must never compose onto a colored chat bubble.
|
|
69
|
+
/* @__PURE__ */ jsx("div", { className: "bg-background overflow-hidden rounded-lg", children: /* @__PURE__ */ jsx(
|
|
70
|
+
MediaPlayer,
|
|
71
|
+
{
|
|
72
|
+
src: attachment.src,
|
|
73
|
+
kind: attachment.kind,
|
|
74
|
+
poster: attachment.poster,
|
|
75
|
+
"aria-label": attachment.alt ?? attachment.title ?? openLabel,
|
|
76
|
+
controls: !onOpen,
|
|
77
|
+
preload: "metadata",
|
|
78
|
+
labels: { error: errorLabel, retry: retryLabel },
|
|
79
|
+
className: "max-h-72"
|
|
80
|
+
}
|
|
81
|
+
) })
|
|
82
|
+
) : attachment.poster ? /* @__PURE__ */ jsx(
|
|
83
|
+
"img",
|
|
84
|
+
{
|
|
85
|
+
src: attachment.poster,
|
|
86
|
+
alt: attachment.alt ?? attachment.title ?? "",
|
|
87
|
+
loading: "lazy",
|
|
88
|
+
className: "max-h-72 w-full rounded-lg object-contain"
|
|
89
|
+
}
|
|
90
|
+
) : null,
|
|
91
|
+
attachment.caption && /* @__PURE__ */ jsx("p", { className: "text-sm", children: attachment.caption }),
|
|
92
|
+
onOpen && /* @__PURE__ */ jsx(ButtonGroup, { children: /* @__PURE__ */ jsx(
|
|
93
|
+
Button,
|
|
94
|
+
{
|
|
95
|
+
"data-media-launch-id": launchId,
|
|
96
|
+
variant: "secondary",
|
|
97
|
+
size: "sm",
|
|
98
|
+
leftIcon: playable ? /* @__PURE__ */ jsx(Play, { className: "size-4", "aria-hidden": "true" }) : void 0,
|
|
99
|
+
"aria-label": playable && attachment.title ? `${playLabel} ${attachment.title}` : actionLabel,
|
|
100
|
+
onClick: () => onOpen(playable),
|
|
101
|
+
children: actionLabel
|
|
102
|
+
}
|
|
103
|
+
) })
|
|
104
|
+
]
|
|
105
|
+
}
|
|
265
106
|
);
|
|
266
|
-
return MarkdownRenderer;
|
|
267
107
|
}
|
|
268
|
-
var transformUrl = (url, key, node) => {
|
|
269
|
-
if (key === "src" && node.tagName === "img" && (/^data:image\//i.test(url) || /^blob:/i.test(url))) {
|
|
270
|
-
return url;
|
|
271
|
-
}
|
|
272
|
-
return defaultUrlTransform(url);
|
|
273
|
-
};
|
|
274
|
-
var MarkdownContent = React3.memo(function MarkdownContent2({
|
|
275
|
-
text,
|
|
276
|
-
messageId,
|
|
277
|
-
streaming,
|
|
278
|
-
remarkPlugins,
|
|
279
|
-
rehypePlugins,
|
|
280
|
-
components
|
|
281
|
-
}) {
|
|
282
|
-
return /* @__PURE__ */ jsx(TextRenderContext.Provider, { value: { messageId, streaming }, children: /* @__PURE__ */ jsx(
|
|
283
|
-
Markdown,
|
|
284
|
-
{
|
|
285
|
-
remarkPlugins,
|
|
286
|
-
rehypePlugins,
|
|
287
|
-
urlTransform: transformUrl,
|
|
288
|
-
components,
|
|
289
|
-
children: text
|
|
290
|
-
}
|
|
291
|
-
) });
|
|
292
|
-
});
|
|
293
108
|
function formatTime(time) {
|
|
294
109
|
return new Date(time).toLocaleTimeString(void 0, {
|
|
295
110
|
hour: "numeric",
|
|
@@ -652,10 +467,15 @@ var MessageRow = React3.memo(function MessageRow2({
|
|
|
652
467
|
onReferenceClick,
|
|
653
468
|
editable,
|
|
654
469
|
onMessageEdited,
|
|
655
|
-
defaultCopyFormat = "rich"
|
|
470
|
+
defaultCopyFormat = "rich",
|
|
471
|
+
onOpenMedia,
|
|
472
|
+
openMediaLabel = "Open in media feed",
|
|
473
|
+
playMediaLabel = "Play",
|
|
474
|
+
mediaErrorLabel,
|
|
475
|
+
mediaRetryLabel
|
|
656
476
|
}) {
|
|
657
477
|
const streaming = message.status === "streaming";
|
|
658
|
-
const hasBody = !!message.text || (message.content?.length ?? 0) > 0;
|
|
478
|
+
const hasBody = !!message.text || (message.content?.length ?? 0) > 0 || (message.media?.length ?? 0) > 0;
|
|
659
479
|
const [isEditing, setIsEditing] = React3.useState(false);
|
|
660
480
|
const [draft, setDraft] = React3.useState(message.text ?? "");
|
|
661
481
|
const [editMinWidth, setEditMinWidth] = React3.useState();
|
|
@@ -1016,6 +836,19 @@ ${block.text}
|
|
|
1016
836
|
streaming,
|
|
1017
837
|
role: participant?.kind === "human" ? "user" : "assistant"
|
|
1018
838
|
}) }),
|
|
839
|
+
message.media?.map((attachment) => /* @__PURE__ */ jsx(
|
|
840
|
+
MessageMedia,
|
|
841
|
+
{
|
|
842
|
+
attachment,
|
|
843
|
+
openLabel: openMediaLabel,
|
|
844
|
+
playLabel: playMediaLabel,
|
|
845
|
+
errorLabel: mediaErrorLabel,
|
|
846
|
+
retryLabel: mediaRetryLabel,
|
|
847
|
+
launchId: JSON.stringify([message.id, attachment.id]),
|
|
848
|
+
onOpen: onOpenMedia ? (play) => onOpenMedia(message.id, attachment.id, play) : void 0
|
|
849
|
+
},
|
|
850
|
+
attachment.id
|
|
851
|
+
)),
|
|
1019
852
|
streaming && !hasBody && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx(AITypingIndicator, {}) })
|
|
1020
853
|
] })
|
|
1021
854
|
}
|
|
@@ -1025,22 +858,306 @@ ${block.text}
|
|
|
1025
858
|
]
|
|
1026
859
|
}
|
|
1027
860
|
)
|
|
1028
|
-
]
|
|
1029
|
-
}
|
|
1030
|
-
);
|
|
1031
|
-
});
|
|
1032
|
-
var sidebarItem = cva(
|
|
1033
|
-
"flex w-full items-center gap-2 rounded-lg px-3 py-2 text-start text-sm transition-colors",
|
|
1034
|
-
{
|
|
1035
|
-
variants: {
|
|
1036
|
-
active: {
|
|
1037
|
-
true: "bg-primary-100 text-primary-900 dark:bg-primary-900/40 dark:text-primary-100",
|
|
1038
|
-
false: "text-neutral-700 hover:bg-neutral-100 dark:text-neutral-200 dark:hover:bg-neutral-800"
|
|
861
|
+
]
|
|
862
|
+
}
|
|
863
|
+
);
|
|
864
|
+
});
|
|
865
|
+
var sidebarItem = cva(
|
|
866
|
+
"flex w-full items-center gap-2 rounded-lg px-3 py-2 text-start text-sm transition-colors",
|
|
867
|
+
{
|
|
868
|
+
variants: {
|
|
869
|
+
active: {
|
|
870
|
+
true: "bg-primary-100 text-primary-900 dark:bg-primary-900/40 dark:text-primary-100",
|
|
871
|
+
false: "text-neutral-700 hover:bg-neutral-100 dark:text-neutral-200 dark:hover:bg-neutral-800"
|
|
872
|
+
}
|
|
873
|
+
},
|
|
874
|
+
defaultVariants: { active: false }
|
|
875
|
+
}
|
|
876
|
+
);
|
|
877
|
+
|
|
878
|
+
// src/components/SuperChat/media.ts
|
|
879
|
+
function getConversationMediaItems(conversation) {
|
|
880
|
+
const participants = new Map(
|
|
881
|
+
conversation.participants.map((participant) => [
|
|
882
|
+
participant.id,
|
|
883
|
+
participant
|
|
884
|
+
])
|
|
885
|
+
);
|
|
886
|
+
return [...conversation.thread].sort(byTime).flatMap(
|
|
887
|
+
(message) => (message.media ?? []).map((attachment) => ({
|
|
888
|
+
// Tuple encoding prevents collisions when ids themselves contain a
|
|
889
|
+
// delimiter. Including the conversation keeps selection scoped to it.
|
|
890
|
+
id: JSON.stringify([conversation.id, message.id, attachment.id]),
|
|
891
|
+
conversationId: conversation.id,
|
|
892
|
+
message,
|
|
893
|
+
attachment,
|
|
894
|
+
participant: participants.get(message.participantId)
|
|
895
|
+
}))
|
|
896
|
+
);
|
|
897
|
+
}
|
|
898
|
+
function remarkPreserveLineBreaks() {
|
|
899
|
+
const splitNode = (node) => {
|
|
900
|
+
if (!node.children) return;
|
|
901
|
+
const next = [];
|
|
902
|
+
for (const child of node.children) {
|
|
903
|
+
if (child.type === "text" && child.value && child.value.includes("\n")) {
|
|
904
|
+
const segments = child.value.split("\n");
|
|
905
|
+
segments.forEach((segment, i) => {
|
|
906
|
+
if (i > 0) next.push({ type: "break" });
|
|
907
|
+
if (segment) next.push({ type: "text", value: segment });
|
|
908
|
+
});
|
|
909
|
+
} else {
|
|
910
|
+
splitNode(child);
|
|
911
|
+
next.push(child);
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
node.children = next;
|
|
915
|
+
};
|
|
916
|
+
return (tree) => splitNode(tree);
|
|
917
|
+
}
|
|
918
|
+
function baseSanitizeSchema() {
|
|
919
|
+
const schema = JSON.parse(JSON.stringify(defaultSchema));
|
|
920
|
+
const attributes = schema.attributes ?? {};
|
|
921
|
+
const allowClass = (tag) => {
|
|
922
|
+
const existing = attributes[tag] ?? [];
|
|
923
|
+
const withoutClass = existing.filter(
|
|
924
|
+
(a) => !(Array.isArray(a) && a[0] === "className")
|
|
925
|
+
);
|
|
926
|
+
attributes[tag] = [...withoutClass, "className"];
|
|
927
|
+
};
|
|
928
|
+
allowClass("code");
|
|
929
|
+
allowClass("pre");
|
|
930
|
+
allowClass("span");
|
|
931
|
+
allowClass("div");
|
|
932
|
+
schema.attributes = attributes;
|
|
933
|
+
return schema;
|
|
934
|
+
}
|
|
935
|
+
function mergeSanitizeSchema(base, extra) {
|
|
936
|
+
if (!extra) return base;
|
|
937
|
+
const out = { ...base };
|
|
938
|
+
if (Array.isArray(extra.tagNames)) {
|
|
939
|
+
const a = base.tagNames ?? [];
|
|
940
|
+
out.tagNames = Array.from(/* @__PURE__ */ new Set([...a, ...extra.tagNames]));
|
|
941
|
+
}
|
|
942
|
+
if (extra.attributes && typeof extra.attributes === "object") {
|
|
943
|
+
const baseAttrs = {
|
|
944
|
+
...base.attributes ?? {}
|
|
945
|
+
};
|
|
946
|
+
for (const [tag, attrs] of Object.entries(
|
|
947
|
+
extra.attributes
|
|
948
|
+
)) {
|
|
949
|
+
baseAttrs[tag] = [...baseAttrs[tag] ?? [], ...attrs];
|
|
950
|
+
}
|
|
951
|
+
out.attributes = baseAttrs;
|
|
952
|
+
}
|
|
953
|
+
if (extra.protocols && typeof extra.protocols === "object") {
|
|
954
|
+
const baseProtocols = {
|
|
955
|
+
...base.protocols ?? {}
|
|
956
|
+
};
|
|
957
|
+
for (const [attr, protocols] of Object.entries(
|
|
958
|
+
extra.protocols
|
|
959
|
+
)) {
|
|
960
|
+
baseProtocols[attr] = Array.from(
|
|
961
|
+
/* @__PURE__ */ new Set([...baseProtocols[attr] ?? [], ...protocols])
|
|
962
|
+
);
|
|
963
|
+
}
|
|
964
|
+
out.protocols = baseProtocols;
|
|
965
|
+
}
|
|
966
|
+
for (const [k, v] of Object.entries(extra)) {
|
|
967
|
+
if (k === "tagNames" || k === "attributes" || k === "protocols") continue;
|
|
968
|
+
out[k] = v;
|
|
969
|
+
}
|
|
970
|
+
return out;
|
|
971
|
+
}
|
|
972
|
+
function baseComponents() {
|
|
973
|
+
return {
|
|
974
|
+
a: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
|
|
975
|
+
"a",
|
|
976
|
+
{
|
|
977
|
+
...props,
|
|
978
|
+
className: cn(
|
|
979
|
+
"text-primary-800 hover:text-primary-900 dark:text-primary-300 underline underline-offset-2",
|
|
980
|
+
props.className
|
|
981
|
+
),
|
|
982
|
+
target: props.target ?? "_blank",
|
|
983
|
+
rel: props.rel ?? "noopener noreferrer",
|
|
984
|
+
children
|
|
985
|
+
}
|
|
986
|
+
),
|
|
987
|
+
pre: ({ node: _node, ...props }) => /* @__PURE__ */ jsx(
|
|
988
|
+
"pre",
|
|
989
|
+
{
|
|
990
|
+
...props,
|
|
991
|
+
tabIndex: 0,
|
|
992
|
+
className: cn(
|
|
993
|
+
"overflow-x-auto rounded-lg bg-neutral-900 p-3 text-sm text-neutral-100 dark:bg-neutral-950",
|
|
994
|
+
props.className
|
|
995
|
+
)
|
|
996
|
+
}
|
|
997
|
+
),
|
|
998
|
+
code: ({ node: _node, ...props }) => {
|
|
999
|
+
const isBlock = typeof props.className === "string" && props.className.includes("language-");
|
|
1000
|
+
return /* @__PURE__ */ jsx(
|
|
1001
|
+
"code",
|
|
1002
|
+
{
|
|
1003
|
+
...props,
|
|
1004
|
+
className: cn(
|
|
1005
|
+
!isBlock && "rounded bg-neutral-200 px-1 py-0.5 text-[0.85em] text-neutral-800 dark:bg-neutral-700 dark:text-neutral-100",
|
|
1006
|
+
props.className
|
|
1007
|
+
)
|
|
1008
|
+
}
|
|
1009
|
+
);
|
|
1010
|
+
},
|
|
1011
|
+
input: ({ node: _node, ...props }) => {
|
|
1012
|
+
if (props.type === "checkbox") {
|
|
1013
|
+
return /* @__PURE__ */ jsx(
|
|
1014
|
+
"input",
|
|
1015
|
+
{
|
|
1016
|
+
...props,
|
|
1017
|
+
"aria-label": props["aria-label"] ?? (props["aria-labelledby"] ? void 0 : "Task list item")
|
|
1018
|
+
}
|
|
1019
|
+
);
|
|
1020
|
+
}
|
|
1021
|
+
return /* @__PURE__ */ jsx("input", { ...props });
|
|
1022
|
+
},
|
|
1023
|
+
table: ({ node: _node, ...props }) => /* @__PURE__ */ jsx("div", { className: "my-2 overflow-x-auto", children: /* @__PURE__ */ jsx(
|
|
1024
|
+
"table",
|
|
1025
|
+
{
|
|
1026
|
+
...props,
|
|
1027
|
+
className: cn(
|
|
1028
|
+
"w-full border-collapse text-sm [&_td]:border [&_td]:border-neutral-200 [&_td]:px-2 [&_td]:py-1 dark:[&_td]:border-neutral-700 [&_th]:border [&_th]:border-neutral-200 [&_th]:px-2 [&_th]:py-1 [&_th]:text-start dark:[&_th]:border-neutral-700",
|
|
1029
|
+
props.className
|
|
1030
|
+
)
|
|
1031
|
+
}
|
|
1032
|
+
) }),
|
|
1033
|
+
// Tailwind's preflight resets list markers/padding; restore them explicitly
|
|
1034
|
+
// so bullets/numbers show without depending on the typography plugin.
|
|
1035
|
+
ul: ({ node: _node, ...props }) => /* @__PURE__ */ jsx("ul", { ...props, className: cn("list-disc ps-5", props.className) }),
|
|
1036
|
+
ol: ({ node: _node, ...props }) => /* @__PURE__ */ jsx("ol", { ...props, className: cn("list-decimal ps-5", props.className) }),
|
|
1037
|
+
li: ({ node: _node, ...props }) => /* @__PURE__ */ jsx("li", { ...props, className: cn("ps-1", props.className) }),
|
|
1038
|
+
// Preflight also flattens headings to body size/weight; restore a sensible
|
|
1039
|
+
// hierarchy without depending on the typography plugin.
|
|
1040
|
+
h1: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
|
|
1041
|
+
"h1",
|
|
1042
|
+
{
|
|
1043
|
+
...props,
|
|
1044
|
+
className: cn("mt-3 mb-1 text-xl font-semibold", props.className),
|
|
1045
|
+
children
|
|
1046
|
+
}
|
|
1047
|
+
),
|
|
1048
|
+
h2: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
|
|
1049
|
+
"h2",
|
|
1050
|
+
{
|
|
1051
|
+
...props,
|
|
1052
|
+
className: cn("mt-3 mb-1 text-lg font-semibold", props.className),
|
|
1053
|
+
children
|
|
1054
|
+
}
|
|
1055
|
+
),
|
|
1056
|
+
h3: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
|
|
1057
|
+
"h3",
|
|
1058
|
+
{
|
|
1059
|
+
...props,
|
|
1060
|
+
className: cn("mt-2 mb-1 text-base font-semibold", props.className),
|
|
1061
|
+
children
|
|
1062
|
+
}
|
|
1063
|
+
),
|
|
1064
|
+
h4: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
|
|
1065
|
+
"h4",
|
|
1066
|
+
{
|
|
1067
|
+
...props,
|
|
1068
|
+
className: cn("mt-2 mb-1 text-sm font-semibold", props.className),
|
|
1069
|
+
children
|
|
1070
|
+
}
|
|
1071
|
+
),
|
|
1072
|
+
h5: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
|
|
1073
|
+
"h5",
|
|
1074
|
+
{
|
|
1075
|
+
...props,
|
|
1076
|
+
className: cn("mt-2 mb-1 text-sm font-semibold", props.className),
|
|
1077
|
+
children
|
|
1078
|
+
}
|
|
1079
|
+
),
|
|
1080
|
+
h6: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsx(
|
|
1081
|
+
"h6",
|
|
1082
|
+
{
|
|
1083
|
+
...props,
|
|
1084
|
+
className: cn(
|
|
1085
|
+
"mt-2 mb-1 text-xs font-semibold tracking-wide uppercase",
|
|
1086
|
+
props.className
|
|
1087
|
+
),
|
|
1088
|
+
children
|
|
1089
|
+
}
|
|
1090
|
+
),
|
|
1091
|
+
hr: ({ node: _node, ...props }) => /* @__PURE__ */ jsx(
|
|
1092
|
+
"hr",
|
|
1093
|
+
{
|
|
1094
|
+
...props,
|
|
1095
|
+
className: cn(
|
|
1096
|
+
"my-2 border-neutral-300 dark:border-neutral-600",
|
|
1097
|
+
props.className
|
|
1098
|
+
)
|
|
1039
1099
|
}
|
|
1100
|
+
)
|
|
1101
|
+
};
|
|
1102
|
+
}
|
|
1103
|
+
function createMarkdownRenderer(options = {}) {
|
|
1104
|
+
const { plugins = [], trusted = false } = options;
|
|
1105
|
+
const remarkPlugins = [
|
|
1106
|
+
remarkGfm,
|
|
1107
|
+
remarkPreserveLineBreaks,
|
|
1108
|
+
...plugins.flatMap((p) => p.remarkPlugins ?? [])
|
|
1109
|
+
];
|
|
1110
|
+
const pluginRehype = plugins.flatMap(
|
|
1111
|
+
(p) => p.rehypePlugins ?? []
|
|
1112
|
+
);
|
|
1113
|
+
const sanitizeSchema = plugins.reduce(
|
|
1114
|
+
(acc, p) => mergeSanitizeSchema(acc, p.sanitizeSchema),
|
|
1115
|
+
baseSanitizeSchema()
|
|
1116
|
+
);
|
|
1117
|
+
const rehypePlugins = trusted ? pluginRehype : [...pluginRehype, [rehypeSanitize, sanitizeSchema]];
|
|
1118
|
+
const components = plugins.reduce(
|
|
1119
|
+
(acc, p) => ({ ...acc, ...p.components }),
|
|
1120
|
+
baseComponents()
|
|
1121
|
+
);
|
|
1122
|
+
const MarkdownRenderer = (text, ctx) => /* @__PURE__ */ jsx(
|
|
1123
|
+
MarkdownContent,
|
|
1124
|
+
{
|
|
1125
|
+
text,
|
|
1126
|
+
messageId: ctx.messageId,
|
|
1127
|
+
streaming: ctx.streaming,
|
|
1128
|
+
remarkPlugins,
|
|
1129
|
+
rehypePlugins,
|
|
1130
|
+
components
|
|
1040
1131
|
},
|
|
1041
|
-
|
|
1132
|
+
ctx.messageId
|
|
1133
|
+
);
|
|
1134
|
+
return MarkdownRenderer;
|
|
1135
|
+
}
|
|
1136
|
+
var transformUrl = (url, key, node) => {
|
|
1137
|
+
if (key === "src" && node.tagName === "img" && (/^data:image\//i.test(url) || /^blob:/i.test(url))) {
|
|
1138
|
+
return url;
|
|
1042
1139
|
}
|
|
1043
|
-
);
|
|
1140
|
+
return defaultUrlTransform(url);
|
|
1141
|
+
};
|
|
1142
|
+
var MarkdownContent = React3.memo(function MarkdownContent2({
|
|
1143
|
+
text,
|
|
1144
|
+
messageId,
|
|
1145
|
+
streaming,
|
|
1146
|
+
remarkPlugins,
|
|
1147
|
+
rehypePlugins,
|
|
1148
|
+
components
|
|
1149
|
+
}) {
|
|
1150
|
+
return /* @__PURE__ */ jsx(TextRenderContext.Provider, { value: { messageId, streaming }, children: /* @__PURE__ */ jsx(
|
|
1151
|
+
Markdown,
|
|
1152
|
+
{
|
|
1153
|
+
remarkPlugins,
|
|
1154
|
+
rehypePlugins,
|
|
1155
|
+
urlTransform: transformUrl,
|
|
1156
|
+
components,
|
|
1157
|
+
children: text
|
|
1158
|
+
}
|
|
1159
|
+
) });
|
|
1160
|
+
});
|
|
1044
1161
|
function VirtualThread({
|
|
1045
1162
|
items,
|
|
1046
1163
|
participantById,
|
|
@@ -1051,6 +1168,11 @@ function VirtualThread({
|
|
|
1051
1168
|
editable,
|
|
1052
1169
|
onMessageEdited,
|
|
1053
1170
|
defaultCopyFormat,
|
|
1171
|
+
onOpenMedia,
|
|
1172
|
+
openMediaLabel,
|
|
1173
|
+
playMediaLabel,
|
|
1174
|
+
mediaErrorLabel,
|
|
1175
|
+
mediaRetryLabel,
|
|
1054
1176
|
scrollRef,
|
|
1055
1177
|
contentRef,
|
|
1056
1178
|
containerProps
|
|
@@ -1099,7 +1221,12 @@ function VirtualThread({
|
|
|
1099
1221
|
onReferenceClick,
|
|
1100
1222
|
editable,
|
|
1101
1223
|
onMessageEdited,
|
|
1102
|
-
defaultCopyFormat
|
|
1224
|
+
defaultCopyFormat,
|
|
1225
|
+
onOpenMedia,
|
|
1226
|
+
openMediaLabel,
|
|
1227
|
+
playMediaLabel,
|
|
1228
|
+
mediaErrorLabel,
|
|
1229
|
+
mediaRetryLabel
|
|
1103
1230
|
}
|
|
1104
1231
|
) })
|
|
1105
1232
|
},
|
|
@@ -1111,6 +1238,11 @@ function VirtualThread({
|
|
|
1111
1238
|
}
|
|
1112
1239
|
function SuperChat({
|
|
1113
1240
|
conversation,
|
|
1241
|
+
view,
|
|
1242
|
+
defaultView = "thread",
|
|
1243
|
+
onViewChange,
|
|
1244
|
+
mediaFeedProps,
|
|
1245
|
+
mediaLabels,
|
|
1114
1246
|
currentParticipantId,
|
|
1115
1247
|
renderPlugins,
|
|
1116
1248
|
renderTextContent,
|
|
@@ -1129,6 +1261,114 @@ function SuperChat({
|
|
|
1129
1261
|
onBack
|
|
1130
1262
|
}) {
|
|
1131
1263
|
const headingId = React3.useId();
|
|
1264
|
+
const [internalView, setInternalView] = React3.useState({
|
|
1265
|
+
conversationId: conversation.id,
|
|
1266
|
+
view: defaultView
|
|
1267
|
+
});
|
|
1268
|
+
const activeView = view ?? (internalView.conversationId === conversation.id ? internalView.view : "thread");
|
|
1269
|
+
const labels = {
|
|
1270
|
+
backToConversation: "Back to conversation",
|
|
1271
|
+
openMedia: "Open in media feed",
|
|
1272
|
+
playMedia: "Play",
|
|
1273
|
+
unknownAuthor: "Unknown",
|
|
1274
|
+
...mediaLabels
|
|
1275
|
+
};
|
|
1276
|
+
const mediaItems = React3.useMemo(() => {
|
|
1277
|
+
const items = getConversationMediaItems(conversation);
|
|
1278
|
+
return order === "desc" ? items.reverse() : items;
|
|
1279
|
+
}, [conversation, order]);
|
|
1280
|
+
const [mediaSelection, setMediaSelection] = React3.useState();
|
|
1281
|
+
const [manualPlaybackRequest, setManualPlaybackRequest] = React3.useState();
|
|
1282
|
+
const playbackRequestCounter = React3.useRef(0);
|
|
1283
|
+
const mediaFeedRef = React3.useRef(null);
|
|
1284
|
+
const backToConversationRef = React3.useRef(null);
|
|
1285
|
+
const focusMediaOnOpenRef = React3.useRef(false);
|
|
1286
|
+
const focusThreadOnBackRef = React3.useRef(false);
|
|
1287
|
+
const mediaReturnTargetRef = React3.useRef(void 0);
|
|
1288
|
+
const mediaContextRef = React3.useRef({
|
|
1289
|
+
conversation,
|
|
1290
|
+
view,
|
|
1291
|
+
onViewChange,
|
|
1292
|
+
mediaFeedProps,
|
|
1293
|
+
mediaItems
|
|
1294
|
+
});
|
|
1295
|
+
mediaContextRef.current = {
|
|
1296
|
+
conversation,
|
|
1297
|
+
view,
|
|
1298
|
+
onViewChange,
|
|
1299
|
+
mediaFeedProps,
|
|
1300
|
+
mediaItems
|
|
1301
|
+
};
|
|
1302
|
+
const setView = React3.useCallback((next) => {
|
|
1303
|
+
const context = mediaContextRef.current;
|
|
1304
|
+
if (context.view === void 0)
|
|
1305
|
+
setInternalView({ conversationId: context.conversation.id, view: next });
|
|
1306
|
+
context.onViewChange?.(next, { conversation: context.conversation });
|
|
1307
|
+
}, []);
|
|
1308
|
+
const handleMediaSelection = React3.useCallback((item) => {
|
|
1309
|
+
setMediaSelection({ conversationId: item.conversationId, itemId: item.id });
|
|
1310
|
+
mediaContextRef.current.mediaFeedProps?.onActiveItemChange?.(item);
|
|
1311
|
+
}, []);
|
|
1312
|
+
const handleOpenMedia = React3.useCallback(
|
|
1313
|
+
(messageId, attachmentId, play = false) => {
|
|
1314
|
+
const item = mediaContextRef.current.mediaItems.find(
|
|
1315
|
+
(candidate) => candidate.message.id === messageId && candidate.attachment.id === attachmentId
|
|
1316
|
+
);
|
|
1317
|
+
if (!item) return;
|
|
1318
|
+
handleMediaSelection(item);
|
|
1319
|
+
mediaReturnTargetRef.current = {
|
|
1320
|
+
conversationId: item.conversationId,
|
|
1321
|
+
messageId,
|
|
1322
|
+
attachmentId
|
|
1323
|
+
};
|
|
1324
|
+
focusMediaOnOpenRef.current = true;
|
|
1325
|
+
setManualPlaybackRequest(
|
|
1326
|
+
play ? {
|
|
1327
|
+
conversationId: item.conversationId,
|
|
1328
|
+
itemId: item.id,
|
|
1329
|
+
requestId: ++playbackRequestCounter.current
|
|
1330
|
+
} : void 0
|
|
1331
|
+
);
|
|
1332
|
+
setView("media");
|
|
1333
|
+
},
|
|
1334
|
+
[handleMediaSelection, setView]
|
|
1335
|
+
);
|
|
1336
|
+
const handleBackToConversation = React3.useCallback(() => {
|
|
1337
|
+
focusMediaOnOpenRef.current = false;
|
|
1338
|
+
focusThreadOnBackRef.current = true;
|
|
1339
|
+
setManualPlaybackRequest(void 0);
|
|
1340
|
+
setView("thread");
|
|
1341
|
+
}, [setView]);
|
|
1342
|
+
const hostPlaybackRequest = mediaFeedProps?.playbackRequest;
|
|
1343
|
+
const hostPlaybackKey = hostPlaybackRequest ? `${hostPlaybackRequest.itemId}\0${hostPlaybackRequest.requestId}` : void 0;
|
|
1344
|
+
React3.useEffect(() => {
|
|
1345
|
+
if (hostPlaybackKey === void 0) return;
|
|
1346
|
+
setManualPlaybackRequest(void 0);
|
|
1347
|
+
}, [hostPlaybackKey]);
|
|
1348
|
+
React3.useEffect(() => {
|
|
1349
|
+
if (internalView.conversationId !== conversation.id) {
|
|
1350
|
+
setInternalView({ conversationId: conversation.id, view: "thread" });
|
|
1351
|
+
}
|
|
1352
|
+
if (mediaReturnTargetRef.current?.conversationId !== conversation.id) {
|
|
1353
|
+
mediaReturnTargetRef.current = void 0;
|
|
1354
|
+
focusMediaOnOpenRef.current = false;
|
|
1355
|
+
focusThreadOnBackRef.current = false;
|
|
1356
|
+
setManualPlaybackRequest(void 0);
|
|
1357
|
+
}
|
|
1358
|
+
}, [conversation.id, internalView.conversationId]);
|
|
1359
|
+
React3.useEffect(() => {
|
|
1360
|
+
if (activeView !== "media" || !focusMediaOnOpenRef.current) return;
|
|
1361
|
+
const target = mediaFeedRef.current?.querySelector(
|
|
1362
|
+
'article[tabindex="0"]'
|
|
1363
|
+
) ?? mediaFeedRef.current?.querySelector('[role="feed"]');
|
|
1364
|
+
if (target) focusMediaOnOpenRef.current = false;
|
|
1365
|
+
(target ?? backToConversationRef.current)?.focus({ preventScroll: true });
|
|
1366
|
+
}, [
|
|
1367
|
+
activeView,
|
|
1368
|
+
mediaFeedProps?.loading,
|
|
1369
|
+
mediaFeedProps?.error,
|
|
1370
|
+
mediaItems.length
|
|
1371
|
+
]);
|
|
1132
1372
|
React3.useEffect(() => {
|
|
1133
1373
|
notifyComposerMigrationOnce("SuperChat");
|
|
1134
1374
|
}, []);
|
|
@@ -1148,12 +1388,36 @@ function SuperChat({
|
|
|
1148
1388
|
anchorToTurnStart,
|
|
1149
1389
|
followIfPinned,
|
|
1150
1390
|
stopFollowing
|
|
1151
|
-
} = useStickToBottom({
|
|
1391
|
+
} = useStickToBottom({
|
|
1392
|
+
disabled: order === "desc" || activeView === "media"
|
|
1393
|
+
});
|
|
1394
|
+
React3.useEffect(() => {
|
|
1395
|
+
if (activeView !== "thread") return;
|
|
1396
|
+
setManualPlaybackRequest(void 0);
|
|
1397
|
+
if (!focusThreadOnBackRef.current) return;
|
|
1398
|
+
focusThreadOnBackRef.current = false;
|
|
1399
|
+
const source = mediaReturnTargetRef.current;
|
|
1400
|
+
const launchId = source ? JSON.stringify([source.messageId, source.attachmentId]) : void 0;
|
|
1401
|
+
const launcher = source?.conversationId === conversation.id ? Array.from(
|
|
1402
|
+
threadRef.current?.querySelectorAll(
|
|
1403
|
+
"[data-media-launch-id]"
|
|
1404
|
+
) ?? []
|
|
1405
|
+
).find((button) => button.dataset.mediaLaunchId === launchId) : void 0;
|
|
1406
|
+
(launcher ?? threadRef.current)?.focus({ preventScroll: true });
|
|
1407
|
+
}, [activeView, conversation.id, threadRef]);
|
|
1152
1408
|
const [hasNewBelow, setHasNewBelow] = React3.useState(false);
|
|
1153
1409
|
const [turnStartId, setTurnStartId] = React3.useState(null);
|
|
1154
1410
|
const [turnMinHeight, setTurnMinHeight] = React3.useState();
|
|
1155
1411
|
const anchoredTurnRef = React3.useRef(null);
|
|
1412
|
+
const threadSnapshotRef = React3.useRef(void 0);
|
|
1413
|
+
const atBottomRef = React3.useRef(isAtBottom);
|
|
1414
|
+
atBottomRef.current = isAtBottom;
|
|
1415
|
+
const pendingMediaOwnSendRef = React3.useRef(false);
|
|
1416
|
+
const pendingMediaAppendRef = React3.useRef(false);
|
|
1156
1417
|
React3.useEffect(() => {
|
|
1418
|
+
threadSnapshotRef.current = void 0;
|
|
1419
|
+
pendingMediaOwnSendRef.current = false;
|
|
1420
|
+
pendingMediaAppendRef.current = false;
|
|
1157
1421
|
setTurnStartId(null);
|
|
1158
1422
|
anchoredTurnRef.current = null;
|
|
1159
1423
|
if (order === "desc") {
|
|
@@ -1187,6 +1451,7 @@ function SuperChat({
|
|
|
1187
1451
|
if (threadLength === prevThreadLengthRef.current) return;
|
|
1188
1452
|
const grew = threadLength > prevThreadLengthRef.current;
|
|
1189
1453
|
prevThreadLengthRef.current = threadLength;
|
|
1454
|
+
if (grew && activeView === "media") pendingMediaAppendRef.current = true;
|
|
1190
1455
|
if (order === "desc") {
|
|
1191
1456
|
const el = threadRef.current;
|
|
1192
1457
|
if (el) el.scrollTop = 0;
|
|
@@ -1202,6 +1467,7 @@ function SuperChat({
|
|
|
1202
1467
|
}
|
|
1203
1468
|
}
|
|
1204
1469
|
if (turnStart) {
|
|
1470
|
+
if (activeView === "media") pendingMediaOwnSendRef.current = true;
|
|
1205
1471
|
if (virtualized) {
|
|
1206
1472
|
scrollToBottom("auto");
|
|
1207
1473
|
} else {
|
|
@@ -1218,7 +1484,36 @@ function SuperChat({
|
|
|
1218
1484
|
} else {
|
|
1219
1485
|
followIfPinned("auto");
|
|
1220
1486
|
}
|
|
1221
|
-
}, [threadLength, order, isAtBottom, conversation.id]);
|
|
1487
|
+
}, [threadLength, order, isAtBottom, conversation.id, activeView]);
|
|
1488
|
+
React3.useLayoutEffect(() => {
|
|
1489
|
+
if (activeView !== "thread") return;
|
|
1490
|
+
const container = threadRef.current;
|
|
1491
|
+
if (!container) return;
|
|
1492
|
+
const snapshot = threadSnapshotRef.current;
|
|
1493
|
+
const sameThread = snapshot?.conversationId === conversation.id && snapshot.order === order;
|
|
1494
|
+
const ownSend = pendingMediaOwnSendRef.current;
|
|
1495
|
+
const appended = pendingMediaAppendRef.current;
|
|
1496
|
+
pendingMediaOwnSendRef.current = false;
|
|
1497
|
+
pendingMediaAppendRef.current = false;
|
|
1498
|
+
if (order === "desc") {
|
|
1499
|
+
container.scrollTop = sameThread && !appended ? snapshot.scrollTop : 0;
|
|
1500
|
+
} else if (ownSend && !virtualized) ; else if (sameThread && !ownSend && (!snapshot.atBottom || !appended)) {
|
|
1501
|
+
container.scrollTop = snapshot.scrollTop;
|
|
1502
|
+
if (!snapshot.atBottom) stopFollowing();
|
|
1503
|
+
} else {
|
|
1504
|
+
scrollToBottom("auto");
|
|
1505
|
+
if ([...conversation.thread].sort(byTime).at(-1)?.status === "streaming")
|
|
1506
|
+
stopFollowing();
|
|
1507
|
+
}
|
|
1508
|
+
return () => {
|
|
1509
|
+
threadSnapshotRef.current = {
|
|
1510
|
+
conversationId: conversation.id,
|
|
1511
|
+
order,
|
|
1512
|
+
scrollTop: container.scrollTop,
|
|
1513
|
+
atBottom: atBottomRef.current
|
|
1514
|
+
};
|
|
1515
|
+
};
|
|
1516
|
+
}, [conversation.id, order, activeView, virtualized]);
|
|
1222
1517
|
React3.useLayoutEffect(() => {
|
|
1223
1518
|
if (!turnStartId || anchoredTurnRef.current === turnStartId) return;
|
|
1224
1519
|
const container = threadRef.current;
|
|
@@ -1240,7 +1535,8 @@ function SuperChat({
|
|
|
1240
1535
|
turnMinHeight,
|
|
1241
1536
|
anchorToTurnStart,
|
|
1242
1537
|
prefersReducedMotion,
|
|
1243
|
-
threadRef
|
|
1538
|
+
threadRef,
|
|
1539
|
+
activeView
|
|
1244
1540
|
]);
|
|
1245
1541
|
React3.useEffect(() => {
|
|
1246
1542
|
prevMessageIdsRef.current = new Set(
|
|
@@ -1293,7 +1589,12 @@ function SuperChat({
|
|
|
1293
1589
|
onReferenceClick,
|
|
1294
1590
|
editable,
|
|
1295
1591
|
onMessageEdited: handleMessageEdited,
|
|
1296
|
-
defaultCopyFormat
|
|
1592
|
+
defaultCopyFormat,
|
|
1593
|
+
onOpenMedia: handleOpenMedia,
|
|
1594
|
+
openMediaLabel: labels.openMedia,
|
|
1595
|
+
playMediaLabel: labels.playMedia,
|
|
1596
|
+
mediaErrorLabel: mediaFeedProps?.labels?.mediaError,
|
|
1597
|
+
mediaRetryLabel: mediaFeedProps?.labels?.retry
|
|
1297
1598
|
},
|
|
1298
1599
|
m.id
|
|
1299
1600
|
);
|
|
@@ -1426,7 +1727,53 @@ function SuperChat({
|
|
|
1426
1727
|
]
|
|
1427
1728
|
}
|
|
1428
1729
|
),
|
|
1429
|
-
/* @__PURE__ */ jsxs(
|
|
1730
|
+
activeView === "media" ? /* @__PURE__ */ jsxs(
|
|
1731
|
+
"div",
|
|
1732
|
+
{
|
|
1733
|
+
"data-slot": "superchat-media-view",
|
|
1734
|
+
className: "flex min-h-0 flex-1 flex-col",
|
|
1735
|
+
children: [
|
|
1736
|
+
/* @__PURE__ */ jsx("div", { className: "px-4 pt-2", children: /* @__PURE__ */ jsx(ButtonGroup, { className: "justify-start", children: /* @__PURE__ */ jsx(
|
|
1737
|
+
Button,
|
|
1738
|
+
{
|
|
1739
|
+
ref: backToConversationRef,
|
|
1740
|
+
variant: "ghost",
|
|
1741
|
+
size: "sm",
|
|
1742
|
+
leftIcon: /* @__PURE__ */ jsx(
|
|
1743
|
+
ArrowLeft,
|
|
1744
|
+
{
|
|
1745
|
+
className: "size-4 rtl:rotate-180",
|
|
1746
|
+
"aria-hidden": "true"
|
|
1747
|
+
}
|
|
1748
|
+
),
|
|
1749
|
+
onClick: handleBackToConversation,
|
|
1750
|
+
children: labels.backToConversation
|
|
1751
|
+
}
|
|
1752
|
+
) }) }),
|
|
1753
|
+
/* @__PURE__ */ createElement(
|
|
1754
|
+
MediaFeed,
|
|
1755
|
+
{
|
|
1756
|
+
...mediaFeedProps,
|
|
1757
|
+
ref: mediaFeedRef,
|
|
1758
|
+
key: conversation.id,
|
|
1759
|
+
items: mediaItems,
|
|
1760
|
+
getId: (item) => item.id,
|
|
1761
|
+
getMedia: (item) => item.attachment,
|
|
1762
|
+
getTitle: (item) => item.attachment.title ?? "",
|
|
1763
|
+
getCaption: (item) => item.attachment.caption ?? item.message.text,
|
|
1764
|
+
getAuthor: (item) => ({
|
|
1765
|
+
name: item.participant?.name ?? labels.unknownAuthor,
|
|
1766
|
+
avatar: item.participant?.avatar
|
|
1767
|
+
}),
|
|
1768
|
+
activeItemId: mediaFeedProps?.activeItemId ?? (mediaSelection?.conversationId === conversation.id ? mediaSelection.itemId : void 0),
|
|
1769
|
+
onActiveItemChange: handleMediaSelection,
|
|
1770
|
+
playbackRequest: manualPlaybackRequest?.conversationId === conversation.id ? manualPlaybackRequest : mediaFeedProps?.playbackRequest,
|
|
1771
|
+
className: cn("min-h-0 flex-1", mediaFeedProps?.className)
|
|
1772
|
+
}
|
|
1773
|
+
)
|
|
1774
|
+
]
|
|
1775
|
+
}
|
|
1776
|
+
) : /* @__PURE__ */ jsxs(
|
|
1430
1777
|
"div",
|
|
1431
1778
|
{
|
|
1432
1779
|
"data-slot": "superchat-thread-viewport",
|
|
@@ -1444,6 +1791,11 @@ function SuperChat({
|
|
|
1444
1791
|
editable,
|
|
1445
1792
|
onMessageEdited: handleMessageEdited,
|
|
1446
1793
|
defaultCopyFormat,
|
|
1794
|
+
onOpenMedia: handleOpenMedia,
|
|
1795
|
+
openMediaLabel: labels.openMedia,
|
|
1796
|
+
playMediaLabel: labels.playMedia,
|
|
1797
|
+
mediaErrorLabel: mediaFeedProps?.labels?.mediaError,
|
|
1798
|
+
mediaRetryLabel: mediaFeedProps?.labels?.retry,
|
|
1447
1799
|
scrollRef: threadRef,
|
|
1448
1800
|
contentRef: threadContentRef,
|
|
1449
1801
|
containerProps: {
|
|
@@ -1615,6 +1967,11 @@ function SuperChatConversations({
|
|
|
1615
1967
|
}
|
|
1616
1968
|
function SuperChatInbox({
|
|
1617
1969
|
conversations,
|
|
1970
|
+
view,
|
|
1971
|
+
defaultView,
|
|
1972
|
+
onViewChange,
|
|
1973
|
+
mediaFeedProps,
|
|
1974
|
+
mediaLabels,
|
|
1618
1975
|
activeConversationId,
|
|
1619
1976
|
defaultActiveConversationId,
|
|
1620
1977
|
currentParticipantId,
|
|
@@ -1676,6 +2033,11 @@ function SuperChatInbox({
|
|
|
1676
2033
|
SuperChat,
|
|
1677
2034
|
{
|
|
1678
2035
|
conversation: active,
|
|
2036
|
+
view,
|
|
2037
|
+
defaultView,
|
|
2038
|
+
onViewChange,
|
|
2039
|
+
mediaFeedProps,
|
|
2040
|
+
mediaLabels,
|
|
1679
2041
|
currentParticipantId,
|
|
1680
2042
|
renderPlugins,
|
|
1681
2043
|
renderTextContent,
|
|
@@ -1711,6 +2073,6 @@ function SuperChatInbox({
|
|
|
1711
2073
|
);
|
|
1712
2074
|
}
|
|
1713
2075
|
|
|
1714
|
-
export { SuperChat, SuperChatConversations, SuperChatInbox, createMarkdownRenderer };
|
|
2076
|
+
export { SuperChat, SuperChatConversations, SuperChatInbox, createMarkdownRenderer, getConversationMediaItems };
|
|
1715
2077
|
//# sourceMappingURL=index.js.map
|
|
1716
2078
|
//# sourceMappingURL=index.js.map
|