@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.
Files changed (118) hide show
  1. package/dist/brands/index.cjs +7 -7
  2. package/dist/brands/index.js +2 -2
  3. package/dist/{chunk-JYZW2PZS.cjs → chunk-254QK722.cjs} +7 -7
  4. package/dist/chunk-254QK722.cjs.map +1 -0
  5. package/dist/{chunk-FBLVPM2K.js → chunk-2JICT4A2.js} +26 -10
  6. package/dist/chunk-2JICT4A2.js.map +1 -0
  7. package/dist/{chunk-S45EERW3.cjs → chunk-35Y4ILCU.cjs} +4 -4
  8. package/dist/{chunk-S45EERW3.cjs.map → chunk-35Y4ILCU.cjs.map} +1 -1
  9. package/dist/{chunk-2BARVD4C.js → chunk-3RXZWHCU.js} +3 -3
  10. package/dist/{chunk-2BARVD4C.js.map → chunk-3RXZWHCU.js.map} +1 -1
  11. package/dist/{chunk-MWVW4APN.cjs → chunk-7UTBDFFL.cjs} +4 -4
  12. package/dist/{chunk-MWVW4APN.cjs.map → chunk-7UTBDFFL.cjs.map} +1 -1
  13. package/dist/{chunk-FJ7YPVKV.js → chunk-7X6R3JIA.js} +3 -3
  14. package/dist/{chunk-FJ7YPVKV.js.map → chunk-7X6R3JIA.js.map} +1 -1
  15. package/dist/{chunk-SYRLCTDV.js → chunk-7ZV67VZE.js} +3 -3
  16. package/dist/{chunk-SYRLCTDV.js.map → chunk-7ZV67VZE.js.map} +1 -1
  17. package/dist/chunk-BNH4SXJB.js +874 -0
  18. package/dist/chunk-BNH4SXJB.js.map +1 -0
  19. package/dist/{chunk-N2CJJHHB.cjs → chunk-BUT6MF5K.cjs} +27 -11
  20. package/dist/chunk-BUT6MF5K.cjs.map +1 -0
  21. package/dist/{chunk-6VFDHJSO.cjs → chunk-COM7RNZU.cjs} +2 -2
  22. package/dist/{chunk-6VFDHJSO.cjs.map → chunk-COM7RNZU.cjs.map} +1 -1
  23. package/dist/{chunk-SQHMGT4W.js → chunk-GW4RFJZ5.js} +7 -7
  24. package/dist/chunk-GW4RFJZ5.js.map +1 -0
  25. package/dist/{chunk-JID7AZTO.cjs → chunk-H3ROMJYI.cjs} +4 -4
  26. package/dist/{chunk-JID7AZTO.cjs.map → chunk-H3ROMJYI.cjs.map} +1 -1
  27. package/dist/{chunk-DZFGTWYF.js → chunk-JBIGSP2T.js} +3 -3
  28. package/dist/{chunk-DZFGTWYF.js.map → chunk-JBIGSP2T.js.map} +1 -1
  29. package/dist/{chunk-33DEVA3P.js → chunk-JHG3ELS2.js} +2 -2
  30. package/dist/{chunk-33DEVA3P.js.map → chunk-JHG3ELS2.js.map} +1 -1
  31. package/dist/{chunk-WWJIW2IH.cjs → chunk-JSXIB6EJ.cjs} +4 -4
  32. package/dist/{chunk-WWJIW2IH.cjs.map → chunk-JSXIB6EJ.cjs.map} +1 -1
  33. package/dist/{chunk-H5YXAMVH.js → chunk-MLAWXPRY.js} +44 -2
  34. package/dist/chunk-MLAWXPRY.js.map +1 -0
  35. package/dist/{chunk-AAYXCZMV.cjs → chunk-NKV76R65.cjs} +4 -4
  36. package/dist/{chunk-AAYXCZMV.cjs.map → chunk-NKV76R65.cjs.map} +1 -1
  37. package/dist/{chunk-PYJDVWXM.js → chunk-NUB5HRKS.js} +3 -3
  38. package/dist/{chunk-PYJDVWXM.js.map → chunk-NUB5HRKS.js.map} +1 -1
  39. package/dist/{chunk-LL6IWKI3.js → chunk-OW3SQJ7P.js} +3 -3
  40. package/dist/{chunk-LL6IWKI3.js.map → chunk-OW3SQJ7P.js.map} +1 -1
  41. package/dist/{chunk-OUZDYJ33.cjs → chunk-QURJVPRH.cjs} +44 -2
  42. package/dist/chunk-QURJVPRH.cjs.map +1 -0
  43. package/dist/{chunk-TZJQB4P2.js → chunk-RM2HPQIC.js} +72 -14
  44. package/dist/chunk-RM2HPQIC.js.map +1 -0
  45. package/dist/{chunk-P4VGVJVI.js → chunk-SD7ONW6S.js} +3 -3
  46. package/dist/{chunk-P4VGVJVI.js.map → chunk-SD7ONW6S.js.map} +1 -1
  47. package/dist/chunk-WXFGHDTV.cjs +896 -0
  48. package/dist/chunk-WXFGHDTV.cjs.map +1 -0
  49. package/dist/chunk-XDU65GLW.js +21 -0
  50. package/dist/chunk-XDU65GLW.js.map +1 -0
  51. package/dist/{chunk-MYHV2ND3.cjs → chunk-XRVMYT5G.cjs} +72 -13
  52. package/dist/chunk-XRVMYT5G.cjs.map +1 -0
  53. package/dist/{chunk-I4LXSHKO.cjs → chunk-YRHBSSQ3.cjs} +4 -4
  54. package/dist/{chunk-I4LXSHKO.cjs.map → chunk-YRHBSSQ3.cjs.map} +1 -1
  55. package/dist/chunk-YW2AKBLS.cjs +23 -0
  56. package/dist/chunk-YW2AKBLS.cjs.map +1 -0
  57. package/dist/{chunk-B2X732V3.cjs → chunk-ZTMYKAVU.cjs} +4 -4
  58. package/dist/{chunk-B2X732V3.cjs.map → chunk-ZTMYKAVU.cjs.map} +1 -1
  59. package/dist/components/Collapsible/index.cjs +5 -5
  60. package/dist/components/Collapsible/index.js +2 -2
  61. package/dist/components/MediaEditor/index.cjs +8 -8
  62. package/dist/components/MediaEditor/index.js +3 -3
  63. package/dist/components/MediaFeed/index.cjs +26 -0
  64. package/dist/components/MediaFeed/index.cjs.map +1 -0
  65. package/dist/components/MediaFeed/index.d.cts +104 -0
  66. package/dist/components/MediaFeed/index.d.ts +104 -0
  67. package/dist/components/MediaFeed/index.js +17 -0
  68. package/dist/components/MediaFeed/index.js.map +1 -0
  69. package/dist/components/MediaPlayer/index.cjs +5 -5
  70. package/dist/components/MediaPlayer/index.d.cts +18 -0
  71. package/dist/components/MediaPlayer/index.d.ts +18 -0
  72. package/dist/components/MediaPlayer/index.js +2 -2
  73. package/dist/components/RadialExplorer/index.cjs +3 -3
  74. package/dist/components/RadialExplorer/index.js +2 -2
  75. package/dist/components/SliderCalculator/index.cjs +4 -4
  76. package/dist/components/SliderCalculator/index.js +2 -2
  77. package/dist/components/SuperChat/index.cjs +654 -292
  78. package/dist/components/SuperChat/index.cjs.map +1 -1
  79. package/dist/components/SuperChat/index.d.cts +35 -6
  80. package/dist/components/SuperChat/index.d.ts +35 -6
  81. package/dist/components/SuperChat/index.js +648 -286
  82. package/dist/components/SuperChat/index.js.map +1 -1
  83. package/dist/components/SuperChat/plugins/index.d.cts +2 -2
  84. package/dist/components/SuperChat/plugins/index.d.ts +2 -2
  85. package/dist/components/ThemeProvider/index.cjs +9 -9
  86. package/dist/components/ThemeProvider/index.js +3 -3
  87. package/dist/components/Tooltip/index.cjs +3 -3
  88. package/dist/components/Tooltip/index.js +2 -2
  89. package/dist/esheet.cjs +6 -6
  90. package/dist/esheet.js +3 -3
  91. package/dist/globe.cjs +2 -2
  92. package/dist/globe.js +1 -1
  93. package/dist/hooks/index.cjs +4 -4
  94. package/dist/hooks/index.js +2 -2
  95. package/dist/index.cjs +164 -214
  96. package/dist/index.cjs.map +1 -1
  97. package/dist/index.d.cts +120 -1
  98. package/dist/index.d.ts +120 -1
  99. package/dist/index.js +25 -82
  100. package/dist/index.js.map +1 -1
  101. package/dist/styles.css +1 -1
  102. package/dist/tailwind-preset.cjs +4 -4
  103. package/dist/tailwind-preset.js +1 -1
  104. package/dist/{types-DOxdTwmq.d.cts → types-Cx1FHLq2.d.cts} +130 -1
  105. package/dist/{types-DOxdTwmq.d.ts → types-Cx1FHLq2.d.ts} +130 -1
  106. package/package.json +1 -1
  107. package/dist/chunk-6HFFWEM3.cjs +0 -22
  108. package/dist/chunk-6HFFWEM3.cjs.map +0 -1
  109. package/dist/chunk-FBLVPM2K.js.map +0 -1
  110. package/dist/chunk-H5YXAMVH.js.map +0 -1
  111. package/dist/chunk-HB7C7NB5.js +0 -20
  112. package/dist/chunk-HB7C7NB5.js.map +0 -1
  113. package/dist/chunk-JYZW2PZS.cjs.map +0 -1
  114. package/dist/chunk-MYHV2ND3.cjs.map +0 -1
  115. package/dist/chunk-N2CJJHHB.cjs.map +0 -1
  116. package/dist/chunk-OUZDYJ33.cjs.map +0 -1
  117. package/dist/chunk-SQHMGT4W.js.map +0 -1
  118. package/dist/chunk-TZJQB4P2.js.map +0 -1
@@ -1,31 +1,40 @@
1
1
  'use strict';
2
2
 
3
3
  var chunkJFLC7SHM_cjs = require('../../chunk-JFLC7SHM.cjs');
4
- var chunkMYHV2ND3_cjs = require('../../chunk-MYHV2ND3.cjs');
4
+ var chunkXRVMYT5G_cjs = require('../../chunk-XRVMYT5G.cjs');
5
5
  var chunkR5Z7AOVU_cjs = require('../../chunk-R5Z7AOVU.cjs');
6
+ var chunkWXFGHDTV_cjs = require('../../chunk-WXFGHDTV.cjs');
7
+ require('../../chunk-GLXTVCHN.cjs');
8
+ var chunkBUT6MF5K_cjs = require('../../chunk-BUT6MF5K.cjs');
6
9
  var chunkTJCX4OML_cjs = require('../../chunk-TJCX4OML.cjs');
7
10
  require('../../chunk-PJ6CC53R.cjs');
8
11
  var chunkJEIW7BSV_cjs = require('../../chunk-JEIW7BSV.cjs');
9
12
  require('../../chunk-VBWRH4UW.cjs');
10
13
  var chunkVPTASZ2O_cjs = require('../../chunk-VPTASZ2O.cjs');
14
+ require('../../chunk-254QK722.cjs');
15
+ require('../../chunk-T4L7Q5FA.cjs');
11
16
  require('../../chunk-I44YNYI6.cjs');
12
17
  require('../../chunk-Z5S5JEJD.cjs');
18
+ require('../../chunk-NNEFAUHV.cjs');
13
19
  require('../../chunk-FHY3K6PL.cjs');
14
20
  require('../../chunk-FSGEDDF2.cjs');
15
21
  require('../../chunk-AOHJILLU.cjs');
22
+ require('../../chunk-SCV7C55E.cjs');
16
23
  require('../../chunk-L7L5S2HO.cjs');
17
- var chunk6HFFWEM3_cjs = require('../../chunk-6HFFWEM3.cjs');
24
+ var chunkYW2AKBLS_cjs = require('../../chunk-YW2AKBLS.cjs');
25
+ var chunkX6A27RGO_cjs = require('../../chunk-X6A27RGO.cjs');
18
26
  var chunkYVL3XATO_cjs = require('../../chunk-YVL3XATO.cjs');
27
+ require('../../chunk-DXEPYK3I.cjs');
19
28
  var chunkIEY3ZJIT_cjs = require('../../chunk-IEY3ZJIT.cjs');
20
29
  var chunkS5RVSXDV_cjs = require('../../chunk-S5RVSXDV.cjs');
21
30
  require('../../chunk-EUAMEVVI.cjs');
22
31
  var React3 = require('react');
32
+ var lucideReact = require('lucide-react');
33
+ var classVarianceAuthority = require('class-variance-authority');
34
+ var jsxRuntime = require('react/jsx-runtime');
23
35
  var Markdown = require('react-markdown');
24
36
  var remarkGfm = require('remark-gfm');
25
37
  var rehypeSanitize = require('rehype-sanitize');
26
- var jsxRuntime = require('react/jsx-runtime');
27
- var classVarianceAuthority = require('class-variance-authority');
28
- var lucideReact = require('lucide-react');
29
38
  var reactVirtual = require('@tanstack/react-virtual');
30
39
 
31
40
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -53,269 +62,74 @@ var Markdown__default = /*#__PURE__*/_interopDefault(Markdown);
53
62
  var remarkGfm__default = /*#__PURE__*/_interopDefault(remarkGfm);
54
63
  var rehypeSanitize__default = /*#__PURE__*/_interopDefault(rehypeSanitize);
55
64
 
56
- function remarkPreserveLineBreaks() {
57
- const splitNode = (node) => {
58
- if (!node.children) return;
59
- const next = [];
60
- for (const child of node.children) {
61
- if (child.type === "text" && child.value && child.value.includes("\n")) {
62
- const segments = child.value.split("\n");
63
- segments.forEach((segment, i) => {
64
- if (i > 0) next.push({ type: "break" });
65
- if (segment) next.push({ type: "text", value: segment });
66
- });
67
- } else {
68
- splitNode(child);
69
- next.push(child);
70
- }
71
- }
72
- node.children = next;
73
- };
74
- return (tree) => splitNode(tree);
75
- }
76
- function baseSanitizeSchema() {
77
- const schema = JSON.parse(JSON.stringify(rehypeSanitize.defaultSchema));
78
- const attributes = schema.attributes ?? {};
79
- const allowClass = (tag) => {
80
- const existing = attributes[tag] ?? [];
81
- const withoutClass = existing.filter(
82
- (a) => !(Array.isArray(a) && a[0] === "className")
83
- );
84
- attributes[tag] = [...withoutClass, "className"];
85
- };
86
- allowClass("code");
87
- allowClass("pre");
88
- allowClass("span");
89
- allowClass("div");
90
- schema.attributes = attributes;
91
- return schema;
92
- }
93
- function mergeSanitizeSchema(base, extra) {
94
- if (!extra) return base;
95
- const out = { ...base };
96
- if (Array.isArray(extra.tagNames)) {
97
- const a = base.tagNames ?? [];
98
- out.tagNames = Array.from(/* @__PURE__ */ new Set([...a, ...extra.tagNames]));
99
- }
100
- if (extra.attributes && typeof extra.attributes === "object") {
101
- const baseAttrs = {
102
- ...base.attributes ?? {}
103
- };
104
- for (const [tag, attrs] of Object.entries(
105
- extra.attributes
106
- )) {
107
- baseAttrs[tag] = [...baseAttrs[tag] ?? [], ...attrs];
108
- }
109
- out.attributes = baseAttrs;
110
- }
111
- if (extra.protocols && typeof extra.protocols === "object") {
112
- const baseProtocols = {
113
- ...base.protocols ?? {}
114
- };
115
- for (const [attr, protocols] of Object.entries(
116
- extra.protocols
117
- )) {
118
- baseProtocols[attr] = Array.from(
119
- /* @__PURE__ */ new Set([...baseProtocols[attr] ?? [], ...protocols])
120
- );
121
- }
122
- out.protocols = baseProtocols;
123
- }
124
- for (const [k, v] of Object.entries(extra)) {
125
- if (k === "tagNames" || k === "attributes" || k === "protocols") continue;
126
- out[k] = v;
127
- }
128
- return out;
129
- }
130
- function baseComponents() {
131
- return {
132
- a: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
133
- "a",
134
- {
135
- ...props,
136
- className: chunkS5RVSXDV_cjs.cn(
137
- "text-primary-800 hover:text-primary-900 dark:text-primary-300 underline underline-offset-2",
138
- props.className
139
- ),
140
- target: props.target ?? "_blank",
141
- rel: props.rel ?? "noopener noreferrer",
142
- children
143
- }
144
- ),
145
- pre: ({ node: _node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
146
- "pre",
147
- {
148
- ...props,
149
- tabIndex: 0,
150
- className: chunkS5RVSXDV_cjs.cn(
151
- "overflow-x-auto rounded-lg bg-neutral-900 p-3 text-sm text-neutral-100 dark:bg-neutral-950",
152
- props.className
153
- )
154
- }
155
- ),
156
- code: ({ node: _node, ...props }) => {
157
- const isBlock = typeof props.className === "string" && props.className.includes("language-");
158
- return /* @__PURE__ */ jsxRuntime.jsx(
159
- "code",
160
- {
161
- ...props,
162
- className: chunkS5RVSXDV_cjs.cn(
163
- !isBlock && "rounded bg-neutral-200 px-1 py-0.5 text-[0.85em] text-neutral-800 dark:bg-neutral-700 dark:text-neutral-100",
164
- props.className
165
- )
166
- }
167
- );
168
- },
169
- input: ({ node: _node, ...props }) => {
170
- if (props.type === "checkbox") {
171
- return /* @__PURE__ */ jsxRuntime.jsx(
172
- "input",
65
+ function MessageMedia({
66
+ attachment,
67
+ onOpen,
68
+ openLabel,
69
+ playLabel,
70
+ errorLabel,
71
+ retryLabel,
72
+ launchId
73
+ }) {
74
+ const playable = attachment.kind !== "image";
75
+ const actionLabel = playable ? playLabel : openLabel;
76
+ return /* @__PURE__ */ jsxRuntime.jsxs(
77
+ "div",
78
+ {
79
+ "data-slot": "superchat-message-media",
80
+ className: "mt-3 flex w-72 max-w-full flex-col gap-2",
81
+ children: [
82
+ attachment.title && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium", children: attachment.title }),
83
+ attachment.kind === "image" && attachment.src ? /* @__PURE__ */ jsxRuntime.jsx(
84
+ "img",
173
85
  {
174
- ...props,
175
- "aria-label": props["aria-label"] ?? (props["aria-labelledby"] ? void 0 : "Task list item")
86
+ src: attachment.src,
87
+ alt: attachment.alt ?? attachment.title ?? "",
88
+ loading: "lazy",
89
+ className: "max-h-72 w-full rounded-lg object-contain"
176
90
  }
177
- );
178
- }
179
- return /* @__PURE__ */ jsxRuntime.jsx("input", { ...props });
180
- },
181
- table: ({ node: _node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "my-2 overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsx(
182
- "table",
183
- {
184
- ...props,
185
- className: chunkS5RVSXDV_cjs.cn(
186
- "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",
187
- props.className
188
- )
189
- }
190
- ) }),
191
- // Tailwind's preflight resets list markers/padding; restore them explicitly
192
- // so bullets/numbers show without depending on the typography plugin.
193
- ul: ({ node: _node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("ul", { ...props, className: chunkS5RVSXDV_cjs.cn("list-disc ps-5", props.className) }),
194
- ol: ({ node: _node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("ol", { ...props, className: chunkS5RVSXDV_cjs.cn("list-decimal ps-5", props.className) }),
195
- li: ({ node: _node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("li", { ...props, className: chunkS5RVSXDV_cjs.cn("ps-1", props.className) }),
196
- // Preflight also flattens headings to body size/weight; restore a sensible
197
- // hierarchy without depending on the typography plugin.
198
- h1: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
199
- "h1",
200
- {
201
- ...props,
202
- className: chunkS5RVSXDV_cjs.cn("mt-3 mb-1 text-xl font-semibold", props.className),
203
- children
204
- }
205
- ),
206
- h2: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
207
- "h2",
208
- {
209
- ...props,
210
- className: chunkS5RVSXDV_cjs.cn("mt-3 mb-1 text-lg font-semibold", props.className),
211
- children
212
- }
213
- ),
214
- h3: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
215
- "h3",
216
- {
217
- ...props,
218
- className: chunkS5RVSXDV_cjs.cn("mt-2 mb-1 text-base font-semibold", props.className),
219
- children
220
- }
221
- ),
222
- h4: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
223
- "h4",
224
- {
225
- ...props,
226
- className: chunkS5RVSXDV_cjs.cn("mt-2 mb-1 text-sm font-semibold", props.className),
227
- children
228
- }
229
- ),
230
- h5: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
231
- "h5",
232
- {
233
- ...props,
234
- className: chunkS5RVSXDV_cjs.cn("mt-2 mb-1 text-sm font-semibold", props.className),
235
- children
236
- }
237
- ),
238
- h6: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
239
- "h6",
240
- {
241
- ...props,
242
- className: chunkS5RVSXDV_cjs.cn(
243
- "mt-2 mb-1 text-xs font-semibold tracking-wide uppercase",
244
- props.className
245
- ),
246
- children
247
- }
248
- ),
249
- hr: ({ node: _node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
250
- "hr",
251
- {
252
- ...props,
253
- className: chunkS5RVSXDV_cjs.cn(
254
- "my-2 border-neutral-300 dark:border-neutral-600",
255
- props.className
256
- )
257
- }
258
- )
259
- };
260
- }
261
- function createMarkdownRenderer(options = {}) {
262
- const { plugins = [], trusted = false } = options;
263
- const remarkPlugins = [
264
- remarkGfm__default.default,
265
- remarkPreserveLineBreaks,
266
- ...plugins.flatMap((p) => p.remarkPlugins ?? [])
267
- ];
268
- const pluginRehype = plugins.flatMap(
269
- (p) => p.rehypePlugins ?? []
270
- );
271
- const sanitizeSchema = plugins.reduce(
272
- (acc, p) => mergeSanitizeSchema(acc, p.sanitizeSchema),
273
- baseSanitizeSchema()
274
- );
275
- const rehypePlugins = trusted ? pluginRehype : [...pluginRehype, [rehypeSanitize__default.default, sanitizeSchema]];
276
- const components = plugins.reduce(
277
- (acc, p) => ({ ...acc, ...p.components }),
278
- baseComponents()
279
- );
280
- const MarkdownRenderer = (text, ctx) => /* @__PURE__ */ jsxRuntime.jsx(
281
- MarkdownContent,
282
- {
283
- text,
284
- messageId: ctx.messageId,
285
- streaming: ctx.streaming,
286
- remarkPlugins,
287
- rehypePlugins,
288
- components
289
- },
290
- ctx.messageId
91
+ ) : (attachment.kind === "video" || attachment.kind === "audio") && attachment.src ? (
92
+ // An opaque themed surface: the player's semi-transparent states
93
+ // (error, loading) must never compose onto a colored chat bubble.
94
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-background overflow-hidden rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsx(
95
+ chunkBUT6MF5K_cjs.MediaPlayer,
96
+ {
97
+ src: attachment.src,
98
+ kind: attachment.kind,
99
+ poster: attachment.poster,
100
+ "aria-label": attachment.alt ?? attachment.title ?? openLabel,
101
+ controls: !onOpen,
102
+ preload: "metadata",
103
+ labels: { error: errorLabel, retry: retryLabel },
104
+ className: "max-h-72"
105
+ }
106
+ ) })
107
+ ) : attachment.poster ? /* @__PURE__ */ jsxRuntime.jsx(
108
+ "img",
109
+ {
110
+ src: attachment.poster,
111
+ alt: attachment.alt ?? attachment.title ?? "",
112
+ loading: "lazy",
113
+ className: "max-h-72 w-full rounded-lg object-contain"
114
+ }
115
+ ) : null,
116
+ attachment.caption && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: attachment.caption }),
117
+ onOpen && /* @__PURE__ */ jsxRuntime.jsx(chunkXRVMYT5G_cjs.ButtonGroup, { children: /* @__PURE__ */ jsxRuntime.jsx(
118
+ chunkX6A27RGO_cjs.Button,
119
+ {
120
+ "data-media-launch-id": launchId,
121
+ variant: "secondary",
122
+ size: "sm",
123
+ leftIcon: playable ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Play, { className: "size-4", "aria-hidden": "true" }) : void 0,
124
+ "aria-label": playable && attachment.title ? `${playLabel} ${attachment.title}` : actionLabel,
125
+ onClick: () => onOpen(playable),
126
+ children: actionLabel
127
+ }
128
+ ) })
129
+ ]
130
+ }
291
131
  );
292
- return MarkdownRenderer;
293
132
  }
294
- var transformUrl = (url, key, node) => {
295
- if (key === "src" && node.tagName === "img" && (/^data:image\//i.test(url) || /^blob:/i.test(url))) {
296
- return url;
297
- }
298
- return Markdown.defaultUrlTransform(url);
299
- };
300
- var MarkdownContent = React3__namespace.memo(function MarkdownContent2({
301
- text,
302
- messageId,
303
- streaming,
304
- remarkPlugins,
305
- rehypePlugins,
306
- components
307
- }) {
308
- return /* @__PURE__ */ jsxRuntime.jsx(chunkJFLC7SHM_cjs.TextRenderContext.Provider, { value: { messageId, streaming }, children: /* @__PURE__ */ jsxRuntime.jsx(
309
- Markdown__default.default,
310
- {
311
- remarkPlugins,
312
- rehypePlugins,
313
- urlTransform: transformUrl,
314
- components,
315
- children: text
316
- }
317
- ) });
318
- });
319
133
  function formatTime(time) {
320
134
  return new Date(time).toLocaleTimeString(void 0, {
321
135
  hour: "numeric",
@@ -407,7 +221,7 @@ function ParticipantAvatar({
407
221
  src: participant?.avatar,
408
222
  alt: "",
409
223
  name: participant?.name ?? "?",
410
- fallback: isAgent ? /* @__PURE__ */ jsxRuntime.jsx(chunkMYHV2ND3_cjs.SparklesIcon, { size: "sm" }) : void 0,
224
+ fallback: isAgent ? /* @__PURE__ */ jsxRuntime.jsx(chunkXRVMYT5G_cjs.SparklesIcon, { size: "sm" }) : void 0,
411
225
  style: { backgroundColor },
412
226
  "aria-hidden": "true",
413
227
  className: "shrink-0"
@@ -678,10 +492,15 @@ var MessageRow = React3__namespace.memo(function MessageRow2({
678
492
  onReferenceClick,
679
493
  editable,
680
494
  onMessageEdited,
681
- defaultCopyFormat = "rich"
495
+ defaultCopyFormat = "rich",
496
+ onOpenMedia,
497
+ openMediaLabel = "Open in media feed",
498
+ playMediaLabel = "Play",
499
+ mediaErrorLabel,
500
+ mediaRetryLabel
682
501
  }) {
683
502
  const streaming = message.status === "streaming";
684
- const hasBody = !!message.text || (message.content?.length ?? 0) > 0;
503
+ const hasBody = !!message.text || (message.content?.length ?? 0) > 0 || (message.media?.length ?? 0) > 0;
685
504
  const [isEditing, setIsEditing] = React3__namespace.useState(false);
686
505
  const [draft, setDraft] = React3__namespace.useState(message.text ?? "");
687
506
  const [editMinWidth, setEditMinWidth] = React3__namespace.useState();
@@ -938,7 +757,7 @@ ${block.text}
938
757
  isSelf ? "flex-row-reverse" : "flex-row"
939
758
  ),
940
759
  children: /* @__PURE__ */ jsxRuntime.jsx(
941
- chunkMYHV2ND3_cjs.ChatBubble,
760
+ chunkXRVMYT5G_cjs.ChatBubble,
942
761
  {
943
762
  ref: bubbleRef,
944
763
  "data-slot": "superchat-bubble",
@@ -1002,7 +821,7 @@ ${block.text}
1002
821
  ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1003
822
  message.content?.map((block, i) => {
1004
823
  if (block.type === "tool_use" && block.toolCall) {
1005
- return /* @__PURE__ */ jsxRuntime.jsx(chunkMYHV2ND3_cjs.MCPToolCallDisplay, { toolCall: block.toolCall }, i);
824
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkXRVMYT5G_cjs.MCPToolCallDisplay, { toolCall: block.toolCall }, i);
1006
825
  }
1007
826
  if ((block.type === "text" || block.type === "thinking") && block.text) {
1008
827
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -1042,7 +861,20 @@ ${block.text}
1042
861
  streaming,
1043
862
  role: participant?.kind === "human" ? "user" : "assistant"
1044
863
  }) }),
1045
- streaming && !hasBody && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(chunkMYHV2ND3_cjs.AITypingIndicator, {}) })
864
+ message.media?.map((attachment) => /* @__PURE__ */ jsxRuntime.jsx(
865
+ MessageMedia,
866
+ {
867
+ attachment,
868
+ openLabel: openMediaLabel,
869
+ playLabel: playMediaLabel,
870
+ errorLabel: mediaErrorLabel,
871
+ retryLabel: mediaRetryLabel,
872
+ launchId: JSON.stringify([message.id, attachment.id]),
873
+ onOpen: onOpenMedia ? (play) => onOpenMedia(message.id, attachment.id, play) : void 0
874
+ },
875
+ attachment.id
876
+ )),
877
+ streaming && !hasBody && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(chunkXRVMYT5G_cjs.AITypingIndicator, {}) })
1046
878
  ] })
1047
879
  }
1048
880
  )
@@ -1051,22 +883,306 @@ ${block.text}
1051
883
  ]
1052
884
  }
1053
885
  )
1054
- ]
1055
- }
1056
- );
1057
- });
1058
- var sidebarItem = classVarianceAuthority.cva(
1059
- "flex w-full items-center gap-2 rounded-lg px-3 py-2 text-start text-sm transition-colors",
1060
- {
1061
- variants: {
1062
- active: {
1063
- true: "bg-primary-100 text-primary-900 dark:bg-primary-900/40 dark:text-primary-100",
1064
- false: "text-neutral-700 hover:bg-neutral-100 dark:text-neutral-200 dark:hover:bg-neutral-800"
886
+ ]
887
+ }
888
+ );
889
+ });
890
+ var sidebarItem = classVarianceAuthority.cva(
891
+ "flex w-full items-center gap-2 rounded-lg px-3 py-2 text-start text-sm transition-colors",
892
+ {
893
+ variants: {
894
+ active: {
895
+ true: "bg-primary-100 text-primary-900 dark:bg-primary-900/40 dark:text-primary-100",
896
+ false: "text-neutral-700 hover:bg-neutral-100 dark:text-neutral-200 dark:hover:bg-neutral-800"
897
+ }
898
+ },
899
+ defaultVariants: { active: false }
900
+ }
901
+ );
902
+
903
+ // src/components/SuperChat/media.ts
904
+ function getConversationMediaItems(conversation) {
905
+ const participants = new Map(
906
+ conversation.participants.map((participant) => [
907
+ participant.id,
908
+ participant
909
+ ])
910
+ );
911
+ return [...conversation.thread].sort(byTime).flatMap(
912
+ (message) => (message.media ?? []).map((attachment) => ({
913
+ // Tuple encoding prevents collisions when ids themselves contain a
914
+ // delimiter. Including the conversation keeps selection scoped to it.
915
+ id: JSON.stringify([conversation.id, message.id, attachment.id]),
916
+ conversationId: conversation.id,
917
+ message,
918
+ attachment,
919
+ participant: participants.get(message.participantId)
920
+ }))
921
+ );
922
+ }
923
+ function remarkPreserveLineBreaks() {
924
+ const splitNode = (node) => {
925
+ if (!node.children) return;
926
+ const next = [];
927
+ for (const child of node.children) {
928
+ if (child.type === "text" && child.value && child.value.includes("\n")) {
929
+ const segments = child.value.split("\n");
930
+ segments.forEach((segment, i) => {
931
+ if (i > 0) next.push({ type: "break" });
932
+ if (segment) next.push({ type: "text", value: segment });
933
+ });
934
+ } else {
935
+ splitNode(child);
936
+ next.push(child);
937
+ }
938
+ }
939
+ node.children = next;
940
+ };
941
+ return (tree) => splitNode(tree);
942
+ }
943
+ function baseSanitizeSchema() {
944
+ const schema = JSON.parse(JSON.stringify(rehypeSanitize.defaultSchema));
945
+ const attributes = schema.attributes ?? {};
946
+ const allowClass = (tag) => {
947
+ const existing = attributes[tag] ?? [];
948
+ const withoutClass = existing.filter(
949
+ (a) => !(Array.isArray(a) && a[0] === "className")
950
+ );
951
+ attributes[tag] = [...withoutClass, "className"];
952
+ };
953
+ allowClass("code");
954
+ allowClass("pre");
955
+ allowClass("span");
956
+ allowClass("div");
957
+ schema.attributes = attributes;
958
+ return schema;
959
+ }
960
+ function mergeSanitizeSchema(base, extra) {
961
+ if (!extra) return base;
962
+ const out = { ...base };
963
+ if (Array.isArray(extra.tagNames)) {
964
+ const a = base.tagNames ?? [];
965
+ out.tagNames = Array.from(/* @__PURE__ */ new Set([...a, ...extra.tagNames]));
966
+ }
967
+ if (extra.attributes && typeof extra.attributes === "object") {
968
+ const baseAttrs = {
969
+ ...base.attributes ?? {}
970
+ };
971
+ for (const [tag, attrs] of Object.entries(
972
+ extra.attributes
973
+ )) {
974
+ baseAttrs[tag] = [...baseAttrs[tag] ?? [], ...attrs];
975
+ }
976
+ out.attributes = baseAttrs;
977
+ }
978
+ if (extra.protocols && typeof extra.protocols === "object") {
979
+ const baseProtocols = {
980
+ ...base.protocols ?? {}
981
+ };
982
+ for (const [attr, protocols] of Object.entries(
983
+ extra.protocols
984
+ )) {
985
+ baseProtocols[attr] = Array.from(
986
+ /* @__PURE__ */ new Set([...baseProtocols[attr] ?? [], ...protocols])
987
+ );
988
+ }
989
+ out.protocols = baseProtocols;
990
+ }
991
+ for (const [k, v] of Object.entries(extra)) {
992
+ if (k === "tagNames" || k === "attributes" || k === "protocols") continue;
993
+ out[k] = v;
994
+ }
995
+ return out;
996
+ }
997
+ function baseComponents() {
998
+ return {
999
+ a: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
1000
+ "a",
1001
+ {
1002
+ ...props,
1003
+ className: chunkS5RVSXDV_cjs.cn(
1004
+ "text-primary-800 hover:text-primary-900 dark:text-primary-300 underline underline-offset-2",
1005
+ props.className
1006
+ ),
1007
+ target: props.target ?? "_blank",
1008
+ rel: props.rel ?? "noopener noreferrer",
1009
+ children
1010
+ }
1011
+ ),
1012
+ pre: ({ node: _node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
1013
+ "pre",
1014
+ {
1015
+ ...props,
1016
+ tabIndex: 0,
1017
+ className: chunkS5RVSXDV_cjs.cn(
1018
+ "overflow-x-auto rounded-lg bg-neutral-900 p-3 text-sm text-neutral-100 dark:bg-neutral-950",
1019
+ props.className
1020
+ )
1021
+ }
1022
+ ),
1023
+ code: ({ node: _node, ...props }) => {
1024
+ const isBlock = typeof props.className === "string" && props.className.includes("language-");
1025
+ return /* @__PURE__ */ jsxRuntime.jsx(
1026
+ "code",
1027
+ {
1028
+ ...props,
1029
+ className: chunkS5RVSXDV_cjs.cn(
1030
+ !isBlock && "rounded bg-neutral-200 px-1 py-0.5 text-[0.85em] text-neutral-800 dark:bg-neutral-700 dark:text-neutral-100",
1031
+ props.className
1032
+ )
1033
+ }
1034
+ );
1035
+ },
1036
+ input: ({ node: _node, ...props }) => {
1037
+ if (props.type === "checkbox") {
1038
+ return /* @__PURE__ */ jsxRuntime.jsx(
1039
+ "input",
1040
+ {
1041
+ ...props,
1042
+ "aria-label": props["aria-label"] ?? (props["aria-labelledby"] ? void 0 : "Task list item")
1043
+ }
1044
+ );
1045
+ }
1046
+ return /* @__PURE__ */ jsxRuntime.jsx("input", { ...props });
1047
+ },
1048
+ table: ({ node: _node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "my-2 overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsx(
1049
+ "table",
1050
+ {
1051
+ ...props,
1052
+ className: chunkS5RVSXDV_cjs.cn(
1053
+ "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",
1054
+ props.className
1055
+ )
1056
+ }
1057
+ ) }),
1058
+ // Tailwind's preflight resets list markers/padding; restore them explicitly
1059
+ // so bullets/numbers show without depending on the typography plugin.
1060
+ ul: ({ node: _node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("ul", { ...props, className: chunkS5RVSXDV_cjs.cn("list-disc ps-5", props.className) }),
1061
+ ol: ({ node: _node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("ol", { ...props, className: chunkS5RVSXDV_cjs.cn("list-decimal ps-5", props.className) }),
1062
+ li: ({ node: _node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("li", { ...props, className: chunkS5RVSXDV_cjs.cn("ps-1", props.className) }),
1063
+ // Preflight also flattens headings to body size/weight; restore a sensible
1064
+ // hierarchy without depending on the typography plugin.
1065
+ h1: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
1066
+ "h1",
1067
+ {
1068
+ ...props,
1069
+ className: chunkS5RVSXDV_cjs.cn("mt-3 mb-1 text-xl font-semibold", props.className),
1070
+ children
1071
+ }
1072
+ ),
1073
+ h2: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
1074
+ "h2",
1075
+ {
1076
+ ...props,
1077
+ className: chunkS5RVSXDV_cjs.cn("mt-3 mb-1 text-lg font-semibold", props.className),
1078
+ children
1079
+ }
1080
+ ),
1081
+ h3: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
1082
+ "h3",
1083
+ {
1084
+ ...props,
1085
+ className: chunkS5RVSXDV_cjs.cn("mt-2 mb-1 text-base font-semibold", props.className),
1086
+ children
1087
+ }
1088
+ ),
1089
+ h4: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
1090
+ "h4",
1091
+ {
1092
+ ...props,
1093
+ className: chunkS5RVSXDV_cjs.cn("mt-2 mb-1 text-sm font-semibold", props.className),
1094
+ children
1095
+ }
1096
+ ),
1097
+ h5: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
1098
+ "h5",
1099
+ {
1100
+ ...props,
1101
+ className: chunkS5RVSXDV_cjs.cn("mt-2 mb-1 text-sm font-semibold", props.className),
1102
+ children
1103
+ }
1104
+ ),
1105
+ h6: ({ node: _node, children, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
1106
+ "h6",
1107
+ {
1108
+ ...props,
1109
+ className: chunkS5RVSXDV_cjs.cn(
1110
+ "mt-2 mb-1 text-xs font-semibold tracking-wide uppercase",
1111
+ props.className
1112
+ ),
1113
+ children
1114
+ }
1115
+ ),
1116
+ hr: ({ node: _node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
1117
+ "hr",
1118
+ {
1119
+ ...props,
1120
+ className: chunkS5RVSXDV_cjs.cn(
1121
+ "my-2 border-neutral-300 dark:border-neutral-600",
1122
+ props.className
1123
+ )
1065
1124
  }
1125
+ )
1126
+ };
1127
+ }
1128
+ function createMarkdownRenderer(options = {}) {
1129
+ const { plugins = [], trusted = false } = options;
1130
+ const remarkPlugins = [
1131
+ remarkGfm__default.default,
1132
+ remarkPreserveLineBreaks,
1133
+ ...plugins.flatMap((p) => p.remarkPlugins ?? [])
1134
+ ];
1135
+ const pluginRehype = plugins.flatMap(
1136
+ (p) => p.rehypePlugins ?? []
1137
+ );
1138
+ const sanitizeSchema = plugins.reduce(
1139
+ (acc, p) => mergeSanitizeSchema(acc, p.sanitizeSchema),
1140
+ baseSanitizeSchema()
1141
+ );
1142
+ const rehypePlugins = trusted ? pluginRehype : [...pluginRehype, [rehypeSanitize__default.default, sanitizeSchema]];
1143
+ const components = plugins.reduce(
1144
+ (acc, p) => ({ ...acc, ...p.components }),
1145
+ baseComponents()
1146
+ );
1147
+ const MarkdownRenderer = (text, ctx) => /* @__PURE__ */ jsxRuntime.jsx(
1148
+ MarkdownContent,
1149
+ {
1150
+ text,
1151
+ messageId: ctx.messageId,
1152
+ streaming: ctx.streaming,
1153
+ remarkPlugins,
1154
+ rehypePlugins,
1155
+ components
1066
1156
  },
1067
- defaultVariants: { active: false }
1157
+ ctx.messageId
1158
+ );
1159
+ return MarkdownRenderer;
1160
+ }
1161
+ var transformUrl = (url, key, node) => {
1162
+ if (key === "src" && node.tagName === "img" && (/^data:image\//i.test(url) || /^blob:/i.test(url))) {
1163
+ return url;
1068
1164
  }
1069
- );
1165
+ return Markdown.defaultUrlTransform(url);
1166
+ };
1167
+ var MarkdownContent = React3__namespace.memo(function MarkdownContent2({
1168
+ text,
1169
+ messageId,
1170
+ streaming,
1171
+ remarkPlugins,
1172
+ rehypePlugins,
1173
+ components
1174
+ }) {
1175
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkJFLC7SHM_cjs.TextRenderContext.Provider, { value: { messageId, streaming }, children: /* @__PURE__ */ jsxRuntime.jsx(
1176
+ Markdown__default.default,
1177
+ {
1178
+ remarkPlugins,
1179
+ rehypePlugins,
1180
+ urlTransform: transformUrl,
1181
+ components,
1182
+ children: text
1183
+ }
1184
+ ) });
1185
+ });
1070
1186
  function VirtualThread({
1071
1187
  items,
1072
1188
  participantById,
@@ -1077,6 +1193,11 @@ function VirtualThread({
1077
1193
  editable,
1078
1194
  onMessageEdited,
1079
1195
  defaultCopyFormat,
1196
+ onOpenMedia,
1197
+ openMediaLabel,
1198
+ playMediaLabel,
1199
+ mediaErrorLabel,
1200
+ mediaRetryLabel,
1080
1201
  scrollRef,
1081
1202
  contentRef,
1082
1203
  containerProps
@@ -1125,7 +1246,12 @@ function VirtualThread({
1125
1246
  onReferenceClick,
1126
1247
  editable,
1127
1248
  onMessageEdited,
1128
- defaultCopyFormat
1249
+ defaultCopyFormat,
1250
+ onOpenMedia,
1251
+ openMediaLabel,
1252
+ playMediaLabel,
1253
+ mediaErrorLabel,
1254
+ mediaRetryLabel
1129
1255
  }
1130
1256
  ) })
1131
1257
  },
@@ -1137,6 +1263,11 @@ function VirtualThread({
1137
1263
  }
1138
1264
  function SuperChat({
1139
1265
  conversation,
1266
+ view,
1267
+ defaultView = "thread",
1268
+ onViewChange,
1269
+ mediaFeedProps,
1270
+ mediaLabels,
1140
1271
  currentParticipantId,
1141
1272
  renderPlugins,
1142
1273
  renderTextContent,
@@ -1155,6 +1286,114 @@ function SuperChat({
1155
1286
  onBack
1156
1287
  }) {
1157
1288
  const headingId = React3__namespace.useId();
1289
+ const [internalView, setInternalView] = React3__namespace.useState({
1290
+ conversationId: conversation.id,
1291
+ view: defaultView
1292
+ });
1293
+ const activeView = view ?? (internalView.conversationId === conversation.id ? internalView.view : "thread");
1294
+ const labels = {
1295
+ backToConversation: "Back to conversation",
1296
+ openMedia: "Open in media feed",
1297
+ playMedia: "Play",
1298
+ unknownAuthor: "Unknown",
1299
+ ...mediaLabels
1300
+ };
1301
+ const mediaItems = React3__namespace.useMemo(() => {
1302
+ const items = getConversationMediaItems(conversation);
1303
+ return order === "desc" ? items.reverse() : items;
1304
+ }, [conversation, order]);
1305
+ const [mediaSelection, setMediaSelection] = React3__namespace.useState();
1306
+ const [manualPlaybackRequest, setManualPlaybackRequest] = React3__namespace.useState();
1307
+ const playbackRequestCounter = React3__namespace.useRef(0);
1308
+ const mediaFeedRef = React3__namespace.useRef(null);
1309
+ const backToConversationRef = React3__namespace.useRef(null);
1310
+ const focusMediaOnOpenRef = React3__namespace.useRef(false);
1311
+ const focusThreadOnBackRef = React3__namespace.useRef(false);
1312
+ const mediaReturnTargetRef = React3__namespace.useRef(void 0);
1313
+ const mediaContextRef = React3__namespace.useRef({
1314
+ conversation,
1315
+ view,
1316
+ onViewChange,
1317
+ mediaFeedProps,
1318
+ mediaItems
1319
+ });
1320
+ mediaContextRef.current = {
1321
+ conversation,
1322
+ view,
1323
+ onViewChange,
1324
+ mediaFeedProps,
1325
+ mediaItems
1326
+ };
1327
+ const setView = React3__namespace.useCallback((next) => {
1328
+ const context = mediaContextRef.current;
1329
+ if (context.view === void 0)
1330
+ setInternalView({ conversationId: context.conversation.id, view: next });
1331
+ context.onViewChange?.(next, { conversation: context.conversation });
1332
+ }, []);
1333
+ const handleMediaSelection = React3__namespace.useCallback((item) => {
1334
+ setMediaSelection({ conversationId: item.conversationId, itemId: item.id });
1335
+ mediaContextRef.current.mediaFeedProps?.onActiveItemChange?.(item);
1336
+ }, []);
1337
+ const handleOpenMedia = React3__namespace.useCallback(
1338
+ (messageId, attachmentId, play = false) => {
1339
+ const item = mediaContextRef.current.mediaItems.find(
1340
+ (candidate) => candidate.message.id === messageId && candidate.attachment.id === attachmentId
1341
+ );
1342
+ if (!item) return;
1343
+ handleMediaSelection(item);
1344
+ mediaReturnTargetRef.current = {
1345
+ conversationId: item.conversationId,
1346
+ messageId,
1347
+ attachmentId
1348
+ };
1349
+ focusMediaOnOpenRef.current = true;
1350
+ setManualPlaybackRequest(
1351
+ play ? {
1352
+ conversationId: item.conversationId,
1353
+ itemId: item.id,
1354
+ requestId: ++playbackRequestCounter.current
1355
+ } : void 0
1356
+ );
1357
+ setView("media");
1358
+ },
1359
+ [handleMediaSelection, setView]
1360
+ );
1361
+ const handleBackToConversation = React3__namespace.useCallback(() => {
1362
+ focusMediaOnOpenRef.current = false;
1363
+ focusThreadOnBackRef.current = true;
1364
+ setManualPlaybackRequest(void 0);
1365
+ setView("thread");
1366
+ }, [setView]);
1367
+ const hostPlaybackRequest = mediaFeedProps?.playbackRequest;
1368
+ const hostPlaybackKey = hostPlaybackRequest ? `${hostPlaybackRequest.itemId}\0${hostPlaybackRequest.requestId}` : void 0;
1369
+ React3__namespace.useEffect(() => {
1370
+ if (hostPlaybackKey === void 0) return;
1371
+ setManualPlaybackRequest(void 0);
1372
+ }, [hostPlaybackKey]);
1373
+ React3__namespace.useEffect(() => {
1374
+ if (internalView.conversationId !== conversation.id) {
1375
+ setInternalView({ conversationId: conversation.id, view: "thread" });
1376
+ }
1377
+ if (mediaReturnTargetRef.current?.conversationId !== conversation.id) {
1378
+ mediaReturnTargetRef.current = void 0;
1379
+ focusMediaOnOpenRef.current = false;
1380
+ focusThreadOnBackRef.current = false;
1381
+ setManualPlaybackRequest(void 0);
1382
+ }
1383
+ }, [conversation.id, internalView.conversationId]);
1384
+ React3__namespace.useEffect(() => {
1385
+ if (activeView !== "media" || !focusMediaOnOpenRef.current) return;
1386
+ const target = mediaFeedRef.current?.querySelector(
1387
+ 'article[tabindex="0"]'
1388
+ ) ?? mediaFeedRef.current?.querySelector('[role="feed"]');
1389
+ if (target) focusMediaOnOpenRef.current = false;
1390
+ (target ?? backToConversationRef.current)?.focus({ preventScroll: true });
1391
+ }, [
1392
+ activeView,
1393
+ mediaFeedProps?.loading,
1394
+ mediaFeedProps?.error,
1395
+ mediaItems.length
1396
+ ]);
1158
1397
  React3__namespace.useEffect(() => {
1159
1398
  chunkR5Z7AOVU_cjs.notifyComposerMigrationOnce("SuperChat");
1160
1399
  }, []);
@@ -1165,7 +1404,7 @@ function SuperChat({
1165
1404
  }),
1166
1405
  [renderTextContent, renderPlugins, trustedContent]
1167
1406
  );
1168
- const prefersReducedMotion = chunk6HFFWEM3_cjs.usePrefersReducedMotion();
1407
+ const prefersReducedMotion = chunkYW2AKBLS_cjs.usePrefersReducedMotion();
1169
1408
  const {
1170
1409
  containerRef: threadRef,
1171
1410
  contentRef: threadContentRef,
@@ -1174,12 +1413,36 @@ function SuperChat({
1174
1413
  anchorToTurnStart,
1175
1414
  followIfPinned,
1176
1415
  stopFollowing
1177
- } = chunkVPTASZ2O_cjs.useStickToBottom({ disabled: order === "desc" });
1416
+ } = chunkVPTASZ2O_cjs.useStickToBottom({
1417
+ disabled: order === "desc" || activeView === "media"
1418
+ });
1419
+ React3__namespace.useEffect(() => {
1420
+ if (activeView !== "thread") return;
1421
+ setManualPlaybackRequest(void 0);
1422
+ if (!focusThreadOnBackRef.current) return;
1423
+ focusThreadOnBackRef.current = false;
1424
+ const source = mediaReturnTargetRef.current;
1425
+ const launchId = source ? JSON.stringify([source.messageId, source.attachmentId]) : void 0;
1426
+ const launcher = source?.conversationId === conversation.id ? Array.from(
1427
+ threadRef.current?.querySelectorAll(
1428
+ "[data-media-launch-id]"
1429
+ ) ?? []
1430
+ ).find((button) => button.dataset.mediaLaunchId === launchId) : void 0;
1431
+ (launcher ?? threadRef.current)?.focus({ preventScroll: true });
1432
+ }, [activeView, conversation.id, threadRef]);
1178
1433
  const [hasNewBelow, setHasNewBelow] = React3__namespace.useState(false);
1179
1434
  const [turnStartId, setTurnStartId] = React3__namespace.useState(null);
1180
1435
  const [turnMinHeight, setTurnMinHeight] = React3__namespace.useState();
1181
1436
  const anchoredTurnRef = React3__namespace.useRef(null);
1437
+ const threadSnapshotRef = React3__namespace.useRef(void 0);
1438
+ const atBottomRef = React3__namespace.useRef(isAtBottom);
1439
+ atBottomRef.current = isAtBottom;
1440
+ const pendingMediaOwnSendRef = React3__namespace.useRef(false);
1441
+ const pendingMediaAppendRef = React3__namespace.useRef(false);
1182
1442
  React3__namespace.useEffect(() => {
1443
+ threadSnapshotRef.current = void 0;
1444
+ pendingMediaOwnSendRef.current = false;
1445
+ pendingMediaAppendRef.current = false;
1183
1446
  setTurnStartId(null);
1184
1447
  anchoredTurnRef.current = null;
1185
1448
  if (order === "desc") {
@@ -1213,6 +1476,7 @@ function SuperChat({
1213
1476
  if (threadLength === prevThreadLengthRef.current) return;
1214
1477
  const grew = threadLength > prevThreadLengthRef.current;
1215
1478
  prevThreadLengthRef.current = threadLength;
1479
+ if (grew && activeView === "media") pendingMediaAppendRef.current = true;
1216
1480
  if (order === "desc") {
1217
1481
  const el = threadRef.current;
1218
1482
  if (el) el.scrollTop = 0;
@@ -1228,6 +1492,7 @@ function SuperChat({
1228
1492
  }
1229
1493
  }
1230
1494
  if (turnStart) {
1495
+ if (activeView === "media") pendingMediaOwnSendRef.current = true;
1231
1496
  if (virtualized) {
1232
1497
  scrollToBottom("auto");
1233
1498
  } else {
@@ -1244,7 +1509,36 @@ function SuperChat({
1244
1509
  } else {
1245
1510
  followIfPinned("auto");
1246
1511
  }
1247
- }, [threadLength, order, isAtBottom, conversation.id]);
1512
+ }, [threadLength, order, isAtBottom, conversation.id, activeView]);
1513
+ React3__namespace.useLayoutEffect(() => {
1514
+ if (activeView !== "thread") return;
1515
+ const container = threadRef.current;
1516
+ if (!container) return;
1517
+ const snapshot = threadSnapshotRef.current;
1518
+ const sameThread = snapshot?.conversationId === conversation.id && snapshot.order === order;
1519
+ const ownSend = pendingMediaOwnSendRef.current;
1520
+ const appended = pendingMediaAppendRef.current;
1521
+ pendingMediaOwnSendRef.current = false;
1522
+ pendingMediaAppendRef.current = false;
1523
+ if (order === "desc") {
1524
+ container.scrollTop = sameThread && !appended ? snapshot.scrollTop : 0;
1525
+ } else if (ownSend && !virtualized) ; else if (sameThread && !ownSend && (!snapshot.atBottom || !appended)) {
1526
+ container.scrollTop = snapshot.scrollTop;
1527
+ if (!snapshot.atBottom) stopFollowing();
1528
+ } else {
1529
+ scrollToBottom("auto");
1530
+ if ([...conversation.thread].sort(byTime).at(-1)?.status === "streaming")
1531
+ stopFollowing();
1532
+ }
1533
+ return () => {
1534
+ threadSnapshotRef.current = {
1535
+ conversationId: conversation.id,
1536
+ order,
1537
+ scrollTop: container.scrollTop,
1538
+ atBottom: atBottomRef.current
1539
+ };
1540
+ };
1541
+ }, [conversation.id, order, activeView, virtualized]);
1248
1542
  React3__namespace.useLayoutEffect(() => {
1249
1543
  if (!turnStartId || anchoredTurnRef.current === turnStartId) return;
1250
1544
  const container = threadRef.current;
@@ -1266,7 +1560,8 @@ function SuperChat({
1266
1560
  turnMinHeight,
1267
1561
  anchorToTurnStart,
1268
1562
  prefersReducedMotion,
1269
- threadRef
1563
+ threadRef,
1564
+ activeView
1270
1565
  ]);
1271
1566
  React3__namespace.useEffect(() => {
1272
1567
  prevMessageIdsRef.current = new Set(
@@ -1319,7 +1614,12 @@ function SuperChat({
1319
1614
  onReferenceClick,
1320
1615
  editable,
1321
1616
  onMessageEdited: handleMessageEdited,
1322
- defaultCopyFormat
1617
+ defaultCopyFormat,
1618
+ onOpenMedia: handleOpenMedia,
1619
+ openMediaLabel: labels.openMedia,
1620
+ playMediaLabel: labels.playMedia,
1621
+ mediaErrorLabel: mediaFeedProps?.labels?.mediaError,
1622
+ mediaRetryLabel: mediaFeedProps?.labels?.retry
1323
1623
  },
1324
1624
  m.id
1325
1625
  );
@@ -1446,13 +1746,59 @@ function SuperChat({
1446
1746
  onClick: () => onConversationClosed(conversation),
1447
1747
  "aria-label": "Close conversation",
1448
1748
  className: "rounded-md p-1 text-neutral-400 hover:bg-neutral-100 dark:hover:bg-neutral-800",
1449
- children: /* @__PURE__ */ jsxRuntime.jsx(chunkMYHV2ND3_cjs.CloseIcon, {})
1749
+ children: /* @__PURE__ */ jsxRuntime.jsx(chunkXRVMYT5G_cjs.CloseIcon, {})
1450
1750
  }
1451
1751
  )
1452
1752
  ]
1453
1753
  }
1454
1754
  ),
1455
- /* @__PURE__ */ jsxRuntime.jsxs(
1755
+ activeView === "media" ? /* @__PURE__ */ jsxRuntime.jsxs(
1756
+ "div",
1757
+ {
1758
+ "data-slot": "superchat-media-view",
1759
+ className: "flex min-h-0 flex-1 flex-col",
1760
+ children: [
1761
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 pt-2", children: /* @__PURE__ */ jsxRuntime.jsx(chunkXRVMYT5G_cjs.ButtonGroup, { className: "justify-start", children: /* @__PURE__ */ jsxRuntime.jsx(
1762
+ chunkX6A27RGO_cjs.Button,
1763
+ {
1764
+ ref: backToConversationRef,
1765
+ variant: "ghost",
1766
+ size: "sm",
1767
+ leftIcon: /* @__PURE__ */ jsxRuntime.jsx(
1768
+ lucideReact.ArrowLeft,
1769
+ {
1770
+ className: "size-4 rtl:rotate-180",
1771
+ "aria-hidden": "true"
1772
+ }
1773
+ ),
1774
+ onClick: handleBackToConversation,
1775
+ children: labels.backToConversation
1776
+ }
1777
+ ) }) }),
1778
+ /* @__PURE__ */ React3.createElement(
1779
+ chunkWXFGHDTV_cjs.MediaFeed,
1780
+ {
1781
+ ...mediaFeedProps,
1782
+ ref: mediaFeedRef,
1783
+ key: conversation.id,
1784
+ items: mediaItems,
1785
+ getId: (item) => item.id,
1786
+ getMedia: (item) => item.attachment,
1787
+ getTitle: (item) => item.attachment.title ?? "",
1788
+ getCaption: (item) => item.attachment.caption ?? item.message.text,
1789
+ getAuthor: (item) => ({
1790
+ name: item.participant?.name ?? labels.unknownAuthor,
1791
+ avatar: item.participant?.avatar
1792
+ }),
1793
+ activeItemId: mediaFeedProps?.activeItemId ?? (mediaSelection?.conversationId === conversation.id ? mediaSelection.itemId : void 0),
1794
+ onActiveItemChange: handleMediaSelection,
1795
+ playbackRequest: manualPlaybackRequest?.conversationId === conversation.id ? manualPlaybackRequest : mediaFeedProps?.playbackRequest,
1796
+ className: chunkS5RVSXDV_cjs.cn("min-h-0 flex-1", mediaFeedProps?.className)
1797
+ }
1798
+ )
1799
+ ]
1800
+ }
1801
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(
1456
1802
  "div",
1457
1803
  {
1458
1804
  "data-slot": "superchat-thread-viewport",
@@ -1470,6 +1816,11 @@ function SuperChat({
1470
1816
  editable,
1471
1817
  onMessageEdited: handleMessageEdited,
1472
1818
  defaultCopyFormat,
1819
+ onOpenMedia: handleOpenMedia,
1820
+ openMediaLabel: labels.openMedia,
1821
+ playMediaLabel: labels.playMedia,
1822
+ mediaErrorLabel: mediaFeedProps?.labels?.mediaError,
1823
+ mediaRetryLabel: mediaFeedProps?.labels?.retry,
1473
1824
  scrollRef: threadRef,
1474
1825
  contentRef: threadContentRef,
1475
1826
  containerProps: {
@@ -1513,7 +1864,7 @@ function SuperChat({
1513
1864
  mode: "presence",
1514
1865
  className: "absolute inset-x-0 bottom-0 z-20",
1515
1866
  children: /* @__PURE__ */ jsxRuntime.jsx(
1516
- chunkMYHV2ND3_cjs.JumpToBottomButton,
1867
+ chunkXRVMYT5G_cjs.JumpToBottomButton,
1517
1868
  {
1518
1869
  dataSlot: "superchat-jump-to-bottom",
1519
1870
  hasNewMessages: hasNewBelow,
@@ -1641,6 +1992,11 @@ function SuperChatConversations({
1641
1992
  }
1642
1993
  function SuperChatInbox({
1643
1994
  conversations,
1995
+ view,
1996
+ defaultView,
1997
+ onViewChange,
1998
+ mediaFeedProps,
1999
+ mediaLabels,
1644
2000
  activeConversationId,
1645
2001
  defaultActiveConversationId,
1646
2002
  currentParticipantId,
@@ -1702,6 +2058,11 @@ function SuperChatInbox({
1702
2058
  SuperChat,
1703
2059
  {
1704
2060
  conversation: active,
2061
+ view,
2062
+ defaultView,
2063
+ onViewChange,
2064
+ mediaFeedProps,
2065
+ mediaLabels,
1705
2066
  currentParticipantId,
1706
2067
  renderPlugins,
1707
2068
  renderTextContent,
@@ -1749,5 +2110,6 @@ exports.SuperChat = SuperChat;
1749
2110
  exports.SuperChatConversations = SuperChatConversations;
1750
2111
  exports.SuperChatInbox = SuperChatInbox;
1751
2112
  exports.createMarkdownRenderer = createMarkdownRenderer;
2113
+ exports.getConversationMediaItems = getConversationMediaItems;
1752
2114
  //# sourceMappingURL=index.cjs.map
1753
2115
  //# sourceMappingURL=index.cjs.map