@mieweb/ui 0.9.0 → 0.10.0-dev.0

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 (121) hide show
  1. package/MIGRATION.md +112 -0
  2. package/dist/{Animated-Cs-naa2g.d.cts → Animated-XmH6k8pZ.d.cts} +16 -3
  3. package/dist/{Animated-Cs-naa2g.d.ts → Animated-XmH6k8pZ.d.ts} +16 -3
  4. package/dist/{chunk-XUVEF2RQ.js → chunk-24SEAAOH.js} +2 -2
  5. package/dist/{chunk-XUVEF2RQ.js.map → chunk-24SEAAOH.js.map} +1 -1
  6. package/dist/{chunk-FUFBRKOG.cjs → chunk-2WBPNXO2.cjs} +21 -21
  7. package/dist/{chunk-FUFBRKOG.cjs.map → chunk-2WBPNXO2.cjs.map} +1 -1
  8. package/dist/{chunk-IUDY6S7I.cjs → chunk-37UZHCLM.cjs} +35 -14
  9. package/dist/chunk-37UZHCLM.cjs.map +1 -0
  10. package/dist/{chunk-L52N6BEN.cjs → chunk-AUOTJQGO.cjs} +7 -7
  11. package/dist/{chunk-L52N6BEN.cjs.map → chunk-AUOTJQGO.cjs.map} +1 -1
  12. package/dist/{chunk-6XDPJWSC.cjs → chunk-E7G22IQM.cjs} +32 -28
  13. package/dist/chunk-E7G22IQM.cjs.map +1 -0
  14. package/dist/chunk-IIFQ6BSJ.js +1888 -0
  15. package/dist/chunk-IIFQ6BSJ.js.map +1 -0
  16. package/dist/{chunk-ONNY7UO4.js → chunk-JDJQTKTX.js} +3 -3
  17. package/dist/{chunk-ONNY7UO4.js.map → chunk-JDJQTKTX.js.map} +1 -1
  18. package/dist/{chunk-BJKAVWED.js → chunk-MBWF36DJ.js} +35 -14
  19. package/dist/chunk-MBWF36DJ.js.map +1 -0
  20. package/dist/chunk-NV2CWBI2.cjs +290 -0
  21. package/dist/chunk-NV2CWBI2.cjs.map +1 -0
  22. package/dist/{chunk-FQBTGS3E.cjs → chunk-OFUKTVBN.cjs} +363 -285
  23. package/dist/chunk-OFUKTVBN.cjs.map +1 -0
  24. package/dist/{chunk-7KN6J7XV.cjs → chunk-OMAACCFW.cjs} +7 -7
  25. package/dist/{chunk-7KN6J7XV.cjs.map → chunk-OMAACCFW.cjs.map} +1 -1
  26. package/dist/chunk-OYQ7GYAA.cjs +1921 -0
  27. package/dist/chunk-OYQ7GYAA.cjs.map +1 -0
  28. package/dist/{chunk-YJP6DUFO.cjs → chunk-PKD3JLS2.cjs} +6 -6
  29. package/dist/{chunk-YJP6DUFO.cjs.map → chunk-PKD3JLS2.cjs.map} +1 -1
  30. package/dist/{chunk-CXDMZT45.cjs → chunk-PY7XAG4D.cjs} +27 -4
  31. package/dist/chunk-PY7XAG4D.cjs.map +1 -0
  32. package/dist/{chunk-5H7SAEQO.js → chunk-QKFJDQEK.js} +3 -3
  33. package/dist/{chunk-5H7SAEQO.js.map → chunk-QKFJDQEK.js.map} +1 -1
  34. package/dist/{chunk-XJTFZLWH.cjs → chunk-QO6PRHDX.cjs} +2 -2
  35. package/dist/{chunk-XJTFZLWH.cjs.map → chunk-QO6PRHDX.cjs.map} +1 -1
  36. package/dist/{chunk-OHDIJOGG.js → chunk-RD3JDFYJ.js} +3 -3
  37. package/dist/{chunk-OHDIJOGG.js.map → chunk-RD3JDFYJ.js.map} +1 -1
  38. package/dist/{chunk-4SM3I7WE.cjs → chunk-RXPEZXAB.cjs} +67 -38
  39. package/dist/chunk-RXPEZXAB.cjs.map +1 -0
  40. package/dist/{chunk-VTR2KGLY.cjs → chunk-S3BCHPXT.cjs} +9 -9
  41. package/dist/{chunk-VTR2KGLY.cjs.map → chunk-S3BCHPXT.cjs.map} +1 -1
  42. package/dist/{chunk-KU3XRHWA.js → chunk-TZX76ZNZ.js} +67 -38
  43. package/dist/chunk-TZX76ZNZ.js.map +1 -0
  44. package/dist/{chunk-MXQ7J4BB.js → chunk-VSVGMMNO.js} +361 -284
  45. package/dist/chunk-VSVGMMNO.js.map +1 -0
  46. package/dist/{chunk-Q7G56ZIO.js → chunk-WUBMDOTG.js} +3 -3
  47. package/dist/{chunk-Q7G56ZIO.js.map → chunk-WUBMDOTG.js.map} +1 -1
  48. package/dist/{chunk-DGRXAIWK.js → chunk-X5YM3KXY.js} +27 -4
  49. package/dist/chunk-X5YM3KXY.js.map +1 -0
  50. package/dist/chunk-XCP454Q6.js +263 -0
  51. package/dist/chunk-XCP454Q6.js.map +1 -0
  52. package/dist/{chunk-I3DQXUSC.js → chunk-Y6DFMDMH.js} +3 -3
  53. package/dist/{chunk-I3DQXUSC.js.map → chunk-Y6DFMDMH.js.map} +1 -1
  54. package/dist/{chunk-ODYQYLO2.js → chunk-YSEMAI4I.js} +8 -4
  55. package/dist/chunk-YSEMAI4I.js.map +1 -0
  56. package/dist/components/AlertDialog/index.cjs +4 -4
  57. package/dist/components/AlertDialog/index.js +3 -3
  58. package/dist/components/Collapsible/index.cjs +6 -4
  59. package/dist/components/Collapsible/index.js +3 -1
  60. package/dist/components/Dropdown/index.cjs +9 -8
  61. package/dist/components/Dropdown/index.js +2 -1
  62. package/dist/components/KeyboardShortcutsOverlay/index.cjs +5 -5
  63. package/dist/components/KeyboardShortcutsOverlay/index.js +3 -3
  64. package/dist/components/MediaEditor/index.cjs +8 -8
  65. package/dist/components/MediaEditor/index.js +3 -3
  66. package/dist/components/Modal/index.cjs +10 -10
  67. package/dist/components/Modal/index.js +2 -2
  68. package/dist/components/RichTextEditor/index.cjs +6 -5
  69. package/dist/components/RichTextEditor/index.js +3 -2
  70. package/dist/components/SuperChat/index.cjs +40 -17
  71. package/dist/components/SuperChat/index.cjs.map +1 -1
  72. package/dist/components/SuperChat/index.d.cts +20 -7
  73. package/dist/components/SuperChat/index.d.ts +20 -7
  74. package/dist/components/SuperChat/index.js +35 -12
  75. package/dist/components/SuperChat/index.js.map +1 -1
  76. package/dist/components/SuperChat/plugins/index.cjs +10 -3
  77. package/dist/components/SuperChat/plugins/index.cjs.map +1 -1
  78. package/dist/components/SuperChat/plugins/index.d.cts +3 -3
  79. package/dist/components/SuperChat/plugins/index.d.ts +3 -3
  80. package/dist/components/SuperChat/plugins/index.js +9 -2
  81. package/dist/components/SuperChat/plugins/index.js.map +1 -1
  82. package/dist/esheet.cjs +6 -6
  83. package/dist/esheet.js +3 -3
  84. package/dist/hooks/index.cjs +13 -13
  85. package/dist/hooks/index.js +1 -1
  86. package/dist/index.cjs +720 -1671
  87. package/dist/index.cjs.map +1 -1
  88. package/dist/index.d.cts +347 -347
  89. package/dist/index.d.ts +347 -347
  90. package/dist/index.js +459 -1405
  91. package/dist/index.js.map +1 -1
  92. package/dist/motion.cjs +7 -7
  93. package/dist/motion.d.cts +1 -1
  94. package/dist/motion.d.ts +1 -1
  95. package/dist/motion.js +2 -2
  96. package/dist/styles.css +1 -1
  97. package/dist/tailwind-preset.cjs +4 -4
  98. package/dist/tailwind-preset.js +1 -1
  99. package/dist/{types-DZDroUW8.d.cts → types-B97JNRNQ.d.cts} +1 -1
  100. package/dist/{types-B2RLmdVd.d.ts → types-CnPEwzlp.d.cts} +6 -2
  101. package/dist/{types-B2RLmdVd.d.cts → types-CnPEwzlp.d.ts} +6 -2
  102. package/dist/{types-9vK_YdEb.d.ts → types-gZXrfLj6.d.ts} +1 -1
  103. package/package.json +2 -1
  104. package/dist/chunk-4SM3I7WE.cjs.map +0 -1
  105. package/dist/chunk-5BVFVXHN.cjs +0 -1244
  106. package/dist/chunk-5BVFVXHN.cjs.map +0 -1
  107. package/dist/chunk-6XDPJWSC.cjs.map +0 -1
  108. package/dist/chunk-BJKAVWED.js.map +0 -1
  109. package/dist/chunk-BN75TLUN.cjs +0 -163
  110. package/dist/chunk-BN75TLUN.cjs.map +0 -1
  111. package/dist/chunk-CXDMZT45.cjs.map +0 -1
  112. package/dist/chunk-DGRXAIWK.js.map +0 -1
  113. package/dist/chunk-FQBTGS3E.cjs.map +0 -1
  114. package/dist/chunk-IUDY6S7I.cjs.map +0 -1
  115. package/dist/chunk-KU3XRHWA.js.map +0 -1
  116. package/dist/chunk-MXQ7J4BB.js.map +0 -1
  117. package/dist/chunk-O6GJ4IYS.js +0 -1210
  118. package/dist/chunk-O6GJ4IYS.js.map +0 -1
  119. package/dist/chunk-ODYQYLO2.js.map +0 -1
  120. package/dist/chunk-WYMO3IIK.js +0 -136
  121. package/dist/chunk-WYMO3IIK.js.map +0 -1
@@ -1,1244 +0,0 @@
1
- 'use strict';
2
-
3
- var chunkS5RVSXDV_cjs = require('./chunk-S5RVSXDV.cjs');
4
- var chunkAOHJILLU_cjs = require('./chunk-AOHJILLU.cjs');
5
- var React3 = require('react');
6
- var jsxRuntime = require('react/jsx-runtime');
7
- var classVarianceAuthority = require('class-variance-authority');
8
- var reactDom = require('react-dom');
9
-
10
- function _interopNamespace(e) {
11
- if (e && e.__esModule) return e;
12
- var n = Object.create(null);
13
- if (e) {
14
- Object.keys(e).forEach(function (k) {
15
- if (k !== 'default') {
16
- var d = Object.getOwnPropertyDescriptor(e, k);
17
- Object.defineProperty(n, k, d.get ? d : {
18
- enumerable: true,
19
- get: function () { return e[k]; }
20
- });
21
- }
22
- });
23
- }
24
- n.default = e;
25
- return Object.freeze(n);
26
- }
27
-
28
- var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
29
-
30
- function getFileType(mimeType) {
31
- if (mimeType.startsWith("image/")) return "image";
32
- if (mimeType.startsWith("video/")) return "video";
33
- if (mimeType.startsWith("audio/")) return "audio";
34
- if (mimeType.includes("pdf") || mimeType.includes("document") || mimeType.includes("text")) {
35
- return "document";
36
- }
37
- return "file";
38
- }
39
- function formatFileSize(bytes) {
40
- if (bytes < 1024) return `${bytes} B`;
41
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
42
- return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
43
- }
44
- function validateFile(file, acceptedTypes, maxSize) {
45
- if (acceptedTypes && acceptedTypes.length > 0) {
46
- const isAccepted = acceptedTypes.some((type) => {
47
- if (type.startsWith(".")) {
48
- return file.name.toLowerCase().endsWith(type.toLowerCase());
49
- }
50
- if (type.endsWith("/*")) {
51
- return file.type.startsWith(type.replace("/*", "/"));
52
- }
53
- return file.type === type;
54
- });
55
- if (!isAccepted) {
56
- return { valid: false, error: "File type not supported" };
57
- }
58
- }
59
- if (maxSize && file.size > maxSize) {
60
- return {
61
- valid: false,
62
- error: `File too large (max ${formatFileSize(maxSize)})`
63
- };
64
- }
65
- return { valid: true };
66
- }
67
- function generateAttachmentId() {
68
- return `attachment-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
69
- }
70
- function AttachmentPreviewItem({
71
- attachment,
72
- onRemove,
73
- onRetry,
74
- disabled = false,
75
- className
76
- }) {
77
- const { file, previewUrl, type, state, progress } = attachment;
78
- const isImage = type === "image";
79
- const isVideo = type === "video";
80
- const isUploading = state === "uploading";
81
- const isFailed = state === "failed";
82
- return /* @__PURE__ */ jsxRuntime.jsxs(
83
- "div",
84
- {
85
- className: chunkS5RVSXDV_cjs.cn(
86
- "group relative overflow-hidden rounded-lg",
87
- "bg-neutral-100 dark:bg-neutral-800",
88
- "border border-neutral-200 dark:border-neutral-700",
89
- isFailed && "border-red-500",
90
- className
91
- ),
92
- children: [
93
- (isImage || isVideo) && previewUrl ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative h-20 w-20", children: [
94
- isVideo ? /* @__PURE__ */ jsxRuntime.jsx(
95
- "video",
96
- {
97
- src: previewUrl,
98
- "aria-label": file.name,
99
- muted: true,
100
- playsInline: true,
101
- preload: "metadata",
102
- className: chunkS5RVSXDV_cjs.cn(
103
- "h-full w-full object-cover",
104
- (isUploading || isFailed) && "opacity-50"
105
- )
106
- }
107
- ) : /* @__PURE__ */ jsxRuntime.jsx(
108
- "img",
109
- {
110
- src: previewUrl,
111
- alt: file.name,
112
- className: chunkS5RVSXDV_cjs.cn(
113
- "h-full w-full object-cover",
114
- (isUploading || isFailed) && "opacity-50"
115
- )
116
- }
117
- ),
118
- isVideo && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
119
- "svg",
120
- {
121
- "aria-hidden": "true",
122
- className: "h-6 w-6 text-white drop-shadow",
123
- fill: "currentColor",
124
- viewBox: "0 0 24 24",
125
- children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 5v14l11-7z" })
126
- }
127
- ) })
128
- ] }) : (
129
- /* File preview */
130
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-20 w-20 flex-col items-center justify-center p-2", children: [
131
- /* @__PURE__ */ jsxRuntime.jsx(
132
- "svg",
133
- {
134
- "aria-hidden": "true",
135
- className: "h-8 w-8 text-neutral-500",
136
- fill: "none",
137
- viewBox: "0 0 24 24",
138
- stroke: "currentColor",
139
- children: /* @__PURE__ */ jsxRuntime.jsx(
140
- "path",
141
- {
142
- strokeLinecap: "round",
143
- strokeLinejoin: "round",
144
- strokeWidth: 2,
145
- d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
146
- }
147
- )
148
- }
149
- ),
150
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-1 max-w-full truncate px-1 text-xs text-neutral-600 dark:text-neutral-400", children: file.name.split(".").pop()?.toUpperCase() })
151
- ] })
152
- ),
153
- isUploading && progress !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-black/50", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center text-white", children: [
154
- /* @__PURE__ */ jsxRuntime.jsxs(
155
- "svg",
156
- {
157
- "aria-hidden": "true",
158
- className: "mx-auto h-6 w-6 animate-spin",
159
- fill: "none",
160
- viewBox: "0 0 24 24",
161
- children: [
162
- /* @__PURE__ */ jsxRuntime.jsx(
163
- "circle",
164
- {
165
- className: "opacity-25",
166
- cx: "12",
167
- cy: "12",
168
- r: "10",
169
- stroke: "currentColor",
170
- strokeWidth: "4"
171
- }
172
- ),
173
- /* @__PURE__ */ jsxRuntime.jsx(
174
- "path",
175
- {
176
- className: "opacity-75",
177
- fill: "currentColor",
178
- d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
179
- }
180
- )
181
- ]
182
- }
183
- ),
184
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "mt-1 text-xs", children: [
185
- progress,
186
- "%"
187
- ] })
188
- ] }) }),
189
- isFailed && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-black/50", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
190
- /* @__PURE__ */ jsxRuntime.jsx(
191
- "svg",
192
- {
193
- "aria-hidden": "true",
194
- className: "mx-auto h-6 w-6 text-red-400",
195
- fill: "none",
196
- viewBox: "0 0 24 24",
197
- stroke: "currentColor",
198
- children: /* @__PURE__ */ jsxRuntime.jsx(
199
- "path",
200
- {
201
- strokeLinecap: "round",
202
- strokeLinejoin: "round",
203
- strokeWidth: 2,
204
- d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
205
- }
206
- )
207
- }
208
- ),
209
- onRetry && /* @__PURE__ */ jsxRuntime.jsx(
210
- "button",
211
- {
212
- type: "button",
213
- onClick: onRetry,
214
- disabled,
215
- className: "mt-1 text-xs text-white underline hover:no-underline disabled:no-underline disabled:opacity-50",
216
- children: "Retry"
217
- }
218
- )
219
- ] }) }),
220
- /* @__PURE__ */ jsxRuntime.jsx(
221
- "button",
222
- {
223
- type: "button",
224
- onClick: onRemove,
225
- disabled,
226
- className: chunkS5RVSXDV_cjs.cn(
227
- "absolute -end-1 -top-1 z-10",
228
- "rounded-full p-1",
229
- "bg-neutral-900 text-white",
230
- "opacity-0 group-hover:opacity-100",
231
- "focus:ring-primary-500 focus:opacity-100 focus:ring-2 focus:outline-none",
232
- "transition-opacity",
233
- "disabled:cursor-not-allowed disabled:group-hover:opacity-0"
234
- ),
235
- "aria-label": `Remove ${file.name}`,
236
- children: /* @__PURE__ */ jsxRuntime.jsx(
237
- "svg",
238
- {
239
- "aria-hidden": "true",
240
- className: "h-3 w-3",
241
- fill: "none",
242
- viewBox: "0 0 24 24",
243
- stroke: "currentColor",
244
- children: /* @__PURE__ */ jsxRuntime.jsx(
245
- "path",
246
- {
247
- strokeLinecap: "round",
248
- strokeLinejoin: "round",
249
- strokeWidth: 2,
250
- d: "M6 18L18 6M6 6l12 12"
251
- }
252
- )
253
- }
254
- )
255
- }
256
- ),
257
- /* @__PURE__ */ jsxRuntime.jsx(
258
- "div",
259
- {
260
- className: chunkS5RVSXDV_cjs.cn(
261
- "absolute start-0 end-0 bottom-0",
262
- "bg-black/70 px-1 py-0.5",
263
- "opacity-0 group-hover:opacity-100",
264
- "transition-opacity"
265
- ),
266
- children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-xs text-white", children: file.name })
267
- }
268
- )
269
- ]
270
- }
271
- );
272
- }
273
- AttachmentPreviewItem.displayName = "AttachmentPreviewItem";
274
- var AttachmentPicker = React3__namespace.forwardRef(
275
- ({
276
- onFilesSelected,
277
- acceptedTypes = ["image/*", "video/*", ".pdf", ".doc", ".docx"],
278
- maxFileSize = 25 * 1024 * 1024,
279
- // 25MB
280
- maxFiles = 10,
281
- multiple = true,
282
- disabled = false,
283
- onError,
284
- className,
285
- children
286
- }, ref) => {
287
- const inputRef = React3__namespace.useRef(null);
288
- React3__namespace.useImperativeHandle(ref, () => inputRef.current);
289
- const handleClick = () => {
290
- inputRef.current?.click();
291
- };
292
- const handleChange = (event) => {
293
- const files = Array.from(event.target.files || []);
294
- if (files.length === 0) return;
295
- const validFiles = [];
296
- for (const file of files.slice(0, maxFiles)) {
297
- const validation = validateFile(file, acceptedTypes, maxFileSize);
298
- if (validation.valid) {
299
- validFiles.push(file);
300
- } else if (onError) {
301
- onError(`${file.name}: ${validation.error}`);
302
- }
303
- }
304
- if (files.length > maxFiles && onError) {
305
- onError(`Maximum ${maxFiles} files allowed`);
306
- }
307
- if (validFiles.length > 0) {
308
- onFilesSelected(validFiles);
309
- }
310
- event.target.value = "";
311
- };
312
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
313
- /* @__PURE__ */ jsxRuntime.jsx(
314
- "input",
315
- {
316
- ref: inputRef,
317
- type: "file",
318
- accept: acceptedTypes.join(","),
319
- multiple,
320
- onChange: handleChange,
321
- disabled,
322
- className: "sr-only",
323
- "aria-label": "Select files to attach"
324
- }
325
- ),
326
- /* @__PURE__ */ jsxRuntime.jsx(
327
- "button",
328
- {
329
- type: "button",
330
- onClick: handleClick,
331
- disabled,
332
- "data-slot": "attachment-picker-button",
333
- className: chunkS5RVSXDV_cjs.cn(
334
- "inline-flex items-center justify-center",
335
- "rounded-full p-2",
336
- "text-neutral-500 hover:text-neutral-700",
337
- "dark:text-neutral-400 dark:hover:text-neutral-200",
338
- "hover:bg-neutral-100 dark:hover:bg-neutral-800",
339
- "focus:ring-primary-500 focus:ring-2 focus:outline-none",
340
- "disabled:cursor-not-allowed disabled:opacity-50",
341
- "transition-colors",
342
- className
343
- ),
344
- "aria-label": "Attach files",
345
- children: children || /* @__PURE__ */ jsxRuntime.jsx(
346
- "svg",
347
- {
348
- "aria-hidden": "true",
349
- className: "h-5 w-5",
350
- fill: "none",
351
- viewBox: "0 0 24 24",
352
- stroke: "currentColor",
353
- children: /* @__PURE__ */ jsxRuntime.jsx(
354
- "path",
355
- {
356
- strokeLinecap: "round",
357
- strokeLinejoin: "round",
358
- strokeWidth: 2,
359
- d: "M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13"
360
- }
361
- )
362
- }
363
- )
364
- }
365
- )
366
- ] });
367
- }
368
- );
369
- AttachmentPicker.displayName = "AttachmentPicker";
370
- function DragDropZone({
371
- onFilesDropped,
372
- acceptedTypes,
373
- maxFileSize,
374
- maxFiles = 10,
375
- disabled = false,
376
- onError,
377
- overlayLabel = "Drop files here",
378
- children,
379
- className
380
- }) {
381
- const [isDragging, setIsDragging] = React3__namespace.useState(false);
382
- const dragCounterRef = React3__namespace.useRef(0);
383
- const handleDragEnter = (event) => {
384
- event.preventDefault();
385
- event.stopPropagation();
386
- if (disabled) return;
387
- dragCounterRef.current++;
388
- if (event.dataTransfer.items && event.dataTransfer.items.length > 0) {
389
- setIsDragging(true);
390
- }
391
- };
392
- const handleDragLeave = (event) => {
393
- event.preventDefault();
394
- event.stopPropagation();
395
- if (disabled) return;
396
- dragCounterRef.current--;
397
- if (dragCounterRef.current === 0) {
398
- setIsDragging(false);
399
- }
400
- };
401
- const handleDragOver = (event) => {
402
- event.preventDefault();
403
- event.stopPropagation();
404
- };
405
- const handleDrop = (event) => {
406
- event.preventDefault();
407
- event.stopPropagation();
408
- if (disabled) return;
409
- setIsDragging(false);
410
- dragCounterRef.current = 0;
411
- const files = Array.from(event.dataTransfer.files);
412
- if (files.length === 0) return;
413
- const validFiles = [];
414
- for (const file of files.slice(0, maxFiles)) {
415
- const validation = validateFile(file, acceptedTypes, maxFileSize);
416
- if (validation.valid) {
417
- validFiles.push(file);
418
- } else if (onError) {
419
- onError(`${file.name}: ${validation.error}`);
420
- }
421
- }
422
- if (files.length > maxFiles && onError) {
423
- onError(`Maximum ${maxFiles} files allowed`);
424
- }
425
- if (validFiles.length > 0) {
426
- onFilesDropped(validFiles);
427
- }
428
- };
429
- return /* @__PURE__ */ jsxRuntime.jsxs(
430
- "div",
431
- {
432
- onDragEnter: handleDragEnter,
433
- onDragLeave: handleDragLeave,
434
- onDragOver: handleDragOver,
435
- onDrop: handleDrop,
436
- className: chunkS5RVSXDV_cjs.cn("relative", className),
437
- children: [
438
- children,
439
- isDragging && /* @__PURE__ */ jsxRuntime.jsx(
440
- "div",
441
- {
442
- className: chunkS5RVSXDV_cjs.cn(
443
- "absolute inset-0 z-50",
444
- "flex items-center justify-center",
445
- "bg-primary-50/90 dark:bg-primary-900/90",
446
- "border-primary-500 border-2 border-dashed",
447
- "rounded-lg"
448
- ),
449
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
450
- /* @__PURE__ */ jsxRuntime.jsx(
451
- "svg",
452
- {
453
- "aria-hidden": "true",
454
- className: "text-primary-800 mx-auto h-12 w-12",
455
- fill: "none",
456
- viewBox: "0 0 24 24",
457
- stroke: "currentColor",
458
- children: /* @__PURE__ */ jsxRuntime.jsx(
459
- "path",
460
- {
461
- strokeLinecap: "round",
462
- strokeLinejoin: "round",
463
- strokeWidth: 2,
464
- d: "M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"
465
- }
466
- )
467
- }
468
- ),
469
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-primary-700 dark:text-primary-300 mt-2 text-sm font-medium", children: overlayLabel })
470
- ] })
471
- }
472
- )
473
- ]
474
- }
475
- );
476
- }
477
- DragDropZone.displayName = "DragDropZone";
478
- function CameraButton({
479
- onCapture,
480
- useFrontCamera = false,
481
- disabled = false,
482
- className
483
- }) {
484
- const inputRef = React3__namespace.useRef(null);
485
- const handleClick = () => {
486
- inputRef.current?.click();
487
- };
488
- const handleChange = (event) => {
489
- const file = event.target.files?.[0];
490
- if (file) {
491
- onCapture(file);
492
- }
493
- event.target.value = "";
494
- };
495
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
496
- /* @__PURE__ */ jsxRuntime.jsx(
497
- "input",
498
- {
499
- ref: inputRef,
500
- type: "file",
501
- accept: "image/*",
502
- capture: useFrontCamera ? "user" : "environment",
503
- onChange: handleChange,
504
- disabled,
505
- className: "sr-only",
506
- "aria-label": "Take a photo"
507
- }
508
- ),
509
- /* @__PURE__ */ jsxRuntime.jsx(
510
- "button",
511
- {
512
- type: "button",
513
- onClick: handleClick,
514
- disabled,
515
- className: chunkS5RVSXDV_cjs.cn(
516
- "inline-flex items-center justify-center",
517
- "rounded-full p-2",
518
- "text-neutral-500 hover:text-neutral-700",
519
- "dark:text-neutral-400 dark:hover:text-neutral-200",
520
- "hover:bg-neutral-100 dark:hover:bg-neutral-800",
521
- "focus:ring-primary-500 focus:ring-2 focus:outline-none",
522
- "disabled:cursor-not-allowed disabled:opacity-50",
523
- "transition-colors",
524
- className
525
- ),
526
- "aria-label": "Take a photo",
527
- children: /* @__PURE__ */ jsxRuntime.jsxs(
528
- "svg",
529
- {
530
- "aria-hidden": "true",
531
- className: "h-5 w-5",
532
- fill: "none",
533
- viewBox: "0 0 24 24",
534
- stroke: "currentColor",
535
- children: [
536
- /* @__PURE__ */ jsxRuntime.jsx(
537
- "path",
538
- {
539
- strokeLinecap: "round",
540
- strokeLinejoin: "round",
541
- strokeWidth: 2,
542
- d: "M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z"
543
- }
544
- ),
545
- /* @__PURE__ */ jsxRuntime.jsx(
546
- "path",
547
- {
548
- strokeLinecap: "round",
549
- strokeLinejoin: "round",
550
- strokeWidth: 2,
551
- d: "M15 13a3 3 0 11-6 0 3 3 0 016 0z"
552
- }
553
- )
554
- ]
555
- }
556
- )
557
- }
558
- )
559
- ] });
560
- }
561
- CameraButton.displayName = "CameraButton";
562
- function activeMentionQuery(value, caret) {
563
- const upToCaret = value.slice(0, caret);
564
- const match = /(^|\s)@([^\s@]*)$/.exec(upToCaret);
565
- if (!match) return null;
566
- const query = match[2];
567
- return { query, start: caret - query.length - 1 };
568
- }
569
- function useMentionAutocomplete({
570
- options,
571
- value,
572
- setValue,
573
- textareaRef
574
- }) {
575
- const enabled = !!options && options.length > 0;
576
- const [mention, setMention] = React3__namespace.useState(null);
577
- const [highlight, setHighlight] = React3__namespace.useState(0);
578
- const listId = React3__namespace.useId();
579
- const optionId = React3__namespace.useCallback(
580
- (index) => `${listId}-option-${index}`,
581
- [listId]
582
- );
583
- const suggestions = React3__namespace.useMemo(() => {
584
- if (!mention || !options) return [];
585
- const q = mention.query.toLowerCase();
586
- return options.filter((o) => o.label.toLowerCase().includes(q));
587
- }, [mention, options]);
588
- const menuOpen = enabled && mention !== null && suggestions.length > 0;
589
- const {
590
- anchorRef,
591
- floatingRef,
592
- style: menuStyle
593
- } = chunkAOHJILLU_cjs.useAnchoredPosition({
594
- open: menuOpen,
595
- placement: "top-start",
596
- maxHeight: 224
597
- });
598
- const clampedHighlight = menuOpen ? Math.min(highlight, suggestions.length - 1) : -1;
599
- const activeOptionId = menuOpen ? optionId(clampedHighlight) : void 0;
600
- const sync = React3__namespace.useCallback(
601
- (nextValue, caret) => {
602
- if (!enabled) return;
603
- setMention(activeMentionQuery(nextValue, caret));
604
- setHighlight(0);
605
- },
606
- [enabled]
607
- );
608
- const insert = (option) => {
609
- if (!mention) return;
610
- const insertValue = option.value ?? option.label.split(" ")[0];
611
- const before = value.slice(0, mention.start);
612
- const after = value.slice(mention.start + 1 + mention.query.length);
613
- const insertText = `@${insertValue} `;
614
- setValue(before + insertText + after);
615
- setMention(null);
616
- const caret = before.length + insertText.length;
617
- requestAnimationFrame(() => {
618
- const el = textareaRef.current;
619
- if (el) {
620
- el.focus();
621
- el.setSelectionRange(caret, caret);
622
- }
623
- });
624
- };
625
- const handleKeyDown = (event) => {
626
- if (!menuOpen) return false;
627
- if (event.key === "ArrowDown") {
628
- event.preventDefault();
629
- setHighlight(
630
- (h) => (Math.min(h, suggestions.length - 1) + 1) % suggestions.length
631
- );
632
- return true;
633
- }
634
- if (event.key === "ArrowUp") {
635
- event.preventDefault();
636
- setHighlight(
637
- (h) => (Math.min(h, suggestions.length - 1) - 1 + suggestions.length) % suggestions.length
638
- );
639
- return true;
640
- }
641
- if (event.key === "Enter" || event.key === "Tab") {
642
- event.preventDefault();
643
- const chosen = suggestions[clampedHighlight];
644
- if (chosen) insert(chosen);
645
- return true;
646
- }
647
- if (event.key === "Escape") {
648
- event.preventDefault();
649
- setMention(null);
650
- return true;
651
- }
652
- return false;
653
- };
654
- const inputProps = enabled ? {
655
- "aria-controls": menuOpen ? listId : void 0,
656
- "aria-activedescendant": activeOptionId,
657
- "aria-autocomplete": "list"
658
- } : {};
659
- return {
660
- enabled,
661
- menuOpen,
662
- suggestions,
663
- highlight: clampedHighlight,
664
- listId,
665
- optionId,
666
- anchorRef,
667
- floatingRef,
668
- menuStyle,
669
- sync,
670
- insert,
671
- setHighlight,
672
- handleKeyDown,
673
- inputProps
674
- };
675
- }
676
- function MentionMenu({
677
- mention,
678
- label = "Mention",
679
- dataSlot = "composer-mention-list"
680
- }) {
681
- if (!mention.menuOpen) return null;
682
- return reactDom.createPortal(
683
- /* @__PURE__ */ jsxRuntime.jsx(
684
- "ul",
685
- {
686
- ref: mention.floatingRef,
687
- style: mention.menuStyle,
688
- id: mention.listId,
689
- role: "listbox",
690
- "aria-label": label,
691
- "data-slot": dataSlot,
692
- className: "w-64 overflow-y-auto rounded-lg border border-neutral-200 bg-white py-1 shadow-lg dark:border-neutral-700 dark:bg-neutral-800",
693
- children: mention.suggestions.map((option, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
694
- "button",
695
- {
696
- type: "button",
697
- id: mention.optionId(i),
698
- role: "option",
699
- "aria-selected": i === mention.highlight,
700
- onMouseDown: (e) => {
701
- e.preventDefault();
702
- mention.insert(option);
703
- },
704
- onMouseEnter: () => mention.setHighlight(i),
705
- className: chunkS5RVSXDV_cjs.cn(
706
- "flex w-full items-center gap-2 px-3 py-1.5 text-start text-sm",
707
- i === mention.highlight ? "bg-primary-100 text-primary-900 dark:bg-primary-900/40 dark:text-primary-100" : "text-neutral-700 dark:text-neutral-200"
708
- ),
709
- children: [
710
- option.icon,
711
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 flex-1 truncate", children: [
712
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: option.label }),
713
- option.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ms-1 text-xs text-neutral-400", children: option.description })
714
- ] }),
715
- option.meta && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-neutral-400", children: option.meta })
716
- ]
717
- }
718
- ) }, option.id))
719
- }
720
- ),
721
- document.body
722
- );
723
- }
724
- MentionMenu.displayName = "MentionMenu";
725
- function isFileAccepted(file, accepted) {
726
- if (!accepted || accepted.length === 0) return true;
727
- const mime = file.type;
728
- const name = file.name.toLowerCase();
729
- return accepted.some((token) => {
730
- if (token.startsWith(".")) return name.endsWith(token.toLowerCase());
731
- if (token.endsWith("/*")) return mime.startsWith(token.slice(0, -1));
732
- if (token.includes("/")) return mime === token;
733
- return false;
734
- });
735
- }
736
- function CharacterCounter({
737
- current,
738
- max,
739
- showWarningAt = 0.9,
740
- className
741
- }) {
742
- const percentage = current / max;
743
- const isWarning = percentage >= showWarningAt && percentage < 1;
744
- const isOver = current > max;
745
- return /* @__PURE__ */ jsxRuntime.jsxs(
746
- "span",
747
- {
748
- className: chunkS5RVSXDV_cjs.cn(
749
- "text-xs tabular-nums",
750
- isOver ? "font-medium text-red-700 dark:text-red-400" : isWarning ? "text-amber-700 dark:text-amber-400" : "text-neutral-600 dark:text-neutral-400",
751
- className
752
- ),
753
- "aria-live": "polite",
754
- "aria-label": `${current} of ${max} characters`,
755
- children: [
756
- current,
757
- "/",
758
- max
759
- ]
760
- }
761
- );
762
- }
763
- CharacterCounter.displayName = "CharacterCounter";
764
- var sendButtonVariants = classVarianceAuthority.cva(
765
- [
766
- "inline-flex items-center justify-center",
767
- "rounded-full p-3 self-start",
768
- "transition-all duration-200",
769
- "focus:outline-none focus:ring-2 focus:ring-primary-500",
770
- "disabled:opacity-50 disabled:cursor-not-allowed"
771
- ],
772
- {
773
- variants: {
774
- variant: {
775
- primary: [
776
- "bg-primary-800 text-white",
777
- "hover:bg-primary-900",
778
- "active:scale-95"
779
- ],
780
- subtle: [
781
- "bg-transparent text-primary-800",
782
- "hover:bg-primary-50 dark:hover:bg-primary-900/20"
783
- ]
784
- },
785
- canSend: {
786
- true: "",
787
- false: "opacity-50 cursor-not-allowed"
788
- }
789
- },
790
- defaultVariants: {
791
- variant: "primary",
792
- canSend: false
793
- }
794
- }
795
- );
796
- var SendButton = React3__namespace.forwardRef(
797
- ({ className, variant, canSend, isLoading, disabled, ...props }, ref) => {
798
- return /* @__PURE__ */ jsxRuntime.jsx(
799
- "button",
800
- {
801
- ref,
802
- type: "submit",
803
- disabled: disabled || !canSend || isLoading,
804
- "data-slot": "composer-send-button",
805
- className: chunkS5RVSXDV_cjs.cn(sendButtonVariants({ variant, canSend }), className),
806
- "aria-label": isLoading ? "Sending message" : "Send message",
807
- ...props,
808
- children: isLoading ? /* @__PURE__ */ jsxRuntime.jsxs(
809
- "svg",
810
- {
811
- "aria-hidden": "true",
812
- className: "h-5 w-5 animate-spin",
813
- fill: "none",
814
- viewBox: "0 0 24 24",
815
- children: [
816
- /* @__PURE__ */ jsxRuntime.jsx(
817
- "circle",
818
- {
819
- className: "opacity-25",
820
- cx: "12",
821
- cy: "12",
822
- r: "10",
823
- stroke: "currentColor",
824
- strokeWidth: "4"
825
- }
826
- ),
827
- /* @__PURE__ */ jsxRuntime.jsx(
828
- "path",
829
- {
830
- className: "opacity-75",
831
- fill: "currentColor",
832
- d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
833
- }
834
- )
835
- ]
836
- }
837
- ) : /* @__PURE__ */ jsxRuntime.jsx(
838
- "svg",
839
- {
840
- "aria-hidden": "true",
841
- className: "h-5 w-5",
842
- fill: "none",
843
- viewBox: "0 0 24 24",
844
- stroke: "currentColor",
845
- children: /* @__PURE__ */ jsxRuntime.jsx(
846
- "path",
847
- {
848
- strokeLinecap: "round",
849
- strokeLinejoin: "round",
850
- strokeWidth: 2,
851
- d: "M12 19l9 2-9-18-9 18 9-2zm0 0v-8"
852
- }
853
- )
854
- }
855
- )
856
- }
857
- );
858
- }
859
- );
860
- SendButton.displayName = "SendButton";
861
- var MessageComposer = React3__namespace.forwardRef(
862
- ({
863
- onSend,
864
- onTypingStart,
865
- onTypingStop,
866
- value: controlledValue,
867
- onValueChange,
868
- placeholder = "Type a message...",
869
- maxLength = 1600,
870
- showCharacterCount = false,
871
- disabled = false,
872
- isSending = false,
873
- showAttachmentPicker = true,
874
- showCameraButton = false,
875
- acceptedFileTypes = ["image/*", "video/*", ".pdf", ".doc", ".docx"],
876
- maxFileSize = 25 * 1024 * 1024,
877
- maxAttachments = 10,
878
- onError,
879
- autoFocus = false,
880
- replyTo = null,
881
- onCancelReply,
882
- variant = "default",
883
- inputTrailing,
884
- mentionOptions,
885
- className
886
- }, ref) => {
887
- const textareaRef = React3__namespace.useRef(null);
888
- const [internalContent, setInternalContent] = React3__namespace.useState("");
889
- const isControlled = controlledValue !== void 0;
890
- const content = isControlled ? controlledValue : internalContent;
891
- const setContent = React3__namespace.useCallback(
892
- (val) => {
893
- if (isControlled) {
894
- const newVal = typeof val === "function" ? val(controlledValue) : val;
895
- onValueChange?.(newVal);
896
- } else {
897
- setInternalContent(val);
898
- }
899
- },
900
- [isControlled, controlledValue, onValueChange]
901
- );
902
- const [attachments, setAttachments] = React3__namespace.useState(
903
- []
904
- );
905
- const [isTyping, setIsTyping] = React3__namespace.useState(false);
906
- const typingTimeoutRef = React3__namespace.useRef(null);
907
- React3__namespace.useImperativeHandle(ref, () => textareaRef.current);
908
- React3__namespace.useEffect(() => {
909
- const textarea = textareaRef.current;
910
- if (textarea) {
911
- textarea.style.height = "auto";
912
- textarea.style.height = `${Math.min(textarea.scrollHeight, 150)}px`;
913
- }
914
- }, [content]);
915
- React3__namespace.useEffect(() => {
916
- if (content.length > 0 && !isTyping) {
917
- setIsTyping(true);
918
- onTypingStart?.();
919
- }
920
- if (typingTimeoutRef.current) {
921
- clearTimeout(typingTimeoutRef.current);
922
- }
923
- typingTimeoutRef.current = setTimeout(() => {
924
- if (isTyping) {
925
- setIsTyping(false);
926
- onTypingStop?.();
927
- }
928
- }, 2e3);
929
- return () => {
930
- if (typingTimeoutRef.current) {
931
- clearTimeout(typingTimeoutRef.current);
932
- }
933
- };
934
- }, [content, isTyping, onTypingStart, onTypingStop]);
935
- React3__namespace.useEffect(() => {
936
- if (autoFocus) {
937
- textareaRef.current?.focus();
938
- }
939
- }, [autoFocus]);
940
- React3__namespace.useEffect(() => {
941
- if (replyTo) {
942
- textareaRef.current?.focus();
943
- }
944
- }, [replyTo]);
945
- const mention = useMentionAutocomplete({
946
- options: mentionOptions,
947
- value: content,
948
- setValue: setContent,
949
- textareaRef
950
- });
951
- const canSend = (content.trim().length > 0 || attachments.length > 0) && content.length <= maxLength && !disabled && !isSending;
952
- const handleSubmit = async (event) => {
953
- event.preventDefault();
954
- if (!canSend) return;
955
- const message = {
956
- content: content.trim(),
957
- attachments: attachments.map((a) => a.file),
958
- replyToId: replyTo?.id
959
- };
960
- setContent("");
961
- setAttachments([]);
962
- setIsTyping(false);
963
- onTypingStop?.();
964
- try {
965
- await onSend(message);
966
- } catch {
967
- setContent(message.content);
968
- onError?.("Failed to send message");
969
- }
970
- };
971
- const handleKeyDown = (event) => {
972
- if (mention.handleKeyDown(event)) return;
973
- if (event.key === "Enter" && !event.shiftKey) {
974
- event.preventDefault();
975
- if (canSend) {
976
- handleSubmit(event);
977
- }
978
- }
979
- };
980
- const handleFilesSelected = (files) => {
981
- const remainingSlots = maxAttachments - attachments.length;
982
- const filesToAdd = files.slice(0, remainingSlots);
983
- if (files.length > remainingSlots) {
984
- onError?.(`Maximum ${maxAttachments} attachments allowed`);
985
- }
986
- const newAttachments = filesToAdd.map((file) => {
987
- const type = getFileType(file.type);
988
- let previewUrl;
989
- if (type === "image" || type === "video") {
990
- previewUrl = URL.createObjectURL(file);
991
- }
992
- return {
993
- id: generateAttachmentId(),
994
- file,
995
- previewUrl,
996
- type,
997
- state: "pending"
998
- };
999
- });
1000
- setAttachments((prev) => [...prev, ...newAttachments]);
1001
- };
1002
- const handlePaste = (event) => {
1003
- if (!showAttachmentPicker || disabled) return;
1004
- const pasted = Array.from(event.clipboardData.items).filter((item) => item.kind === "file").map((item) => item.getAsFile()).filter((f) => f !== null).filter((f) => isFileAccepted(f, acceptedFileTypes));
1005
- if (pasted.length === 0) return;
1006
- event.preventDefault();
1007
- handleFilesSelected(pasted);
1008
- };
1009
- const handleRemoveAttachment = (attachmentId) => {
1010
- setAttachments((prev) => {
1011
- const attachment = prev.find((a) => a.id === attachmentId);
1012
- if (attachment?.previewUrl) {
1013
- URL.revokeObjectURL(attachment.previewUrl);
1014
- }
1015
- return prev.filter((a) => a.id !== attachmentId);
1016
- });
1017
- };
1018
- React3__namespace.useEffect(() => {
1019
- const currentAttachments = attachments;
1020
- return () => {
1021
- currentAttachments.forEach((a) => {
1022
- if (a.previewUrl) {
1023
- URL.revokeObjectURL(a.previewUrl);
1024
- }
1025
- });
1026
- };
1027
- }, [attachments]);
1028
- return /* @__PURE__ */ jsxRuntime.jsx(
1029
- DragDropZone,
1030
- {
1031
- onFilesDropped: handleFilesSelected,
1032
- acceptedTypes: acceptedFileTypes,
1033
- maxFileSize,
1034
- maxFiles: maxAttachments - attachments.length,
1035
- disabled: disabled || attachments.length >= maxAttachments,
1036
- onError,
1037
- className: chunkS5RVSXDV_cjs.cn("w-full", className),
1038
- children: /* @__PURE__ */ jsxRuntime.jsxs(
1039
- "form",
1040
- {
1041
- onSubmit: handleSubmit,
1042
- "data-slot": "message-composer",
1043
- className: "w-full",
1044
- children: [
1045
- replyTo && /* @__PURE__ */ jsxRuntime.jsxs(
1046
- "div",
1047
- {
1048
- "data-slot": "composer-reply-preview",
1049
- className: chunkS5RVSXDV_cjs.cn(
1050
- "flex items-center gap-2 px-4 py-2",
1051
- "bg-neutral-50 dark:bg-neutral-800/50",
1052
- "border-primary-500 border-s-4"
1053
- ),
1054
- children: [
1055
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
1056
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-primary-800 dark:text-primary-400 text-xs font-medium", children: [
1057
- "Replying to ",
1058
- replyTo.senderName
1059
- ] }),
1060
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-sm text-neutral-600 dark:text-neutral-300", children: replyTo.content })
1061
- ] }),
1062
- /* @__PURE__ */ jsxRuntime.jsx(
1063
- "button",
1064
- {
1065
- type: "button",
1066
- onClick: onCancelReply,
1067
- className: chunkS5RVSXDV_cjs.cn(
1068
- "shrink-0 rounded p-1",
1069
- "text-neutral-500 hover:text-neutral-700",
1070
- "dark:text-neutral-400 dark:hover:text-neutral-200",
1071
- "focus:ring-primary-500 focus:ring-2 focus:outline-none"
1072
- ),
1073
- "aria-label": "Cancel reply",
1074
- children: /* @__PURE__ */ jsxRuntime.jsx(
1075
- "svg",
1076
- {
1077
- "aria-hidden": "true",
1078
- className: "h-4 w-4",
1079
- fill: "none",
1080
- viewBox: "0 0 24 24",
1081
- stroke: "currentColor",
1082
- children: /* @__PURE__ */ jsxRuntime.jsx(
1083
- "path",
1084
- {
1085
- strokeLinecap: "round",
1086
- strokeLinejoin: "round",
1087
- strokeWidth: 2,
1088
- d: "M6 18L18 6M6 6l12 12"
1089
- }
1090
- )
1091
- }
1092
- )
1093
- }
1094
- )
1095
- ]
1096
- }
1097
- ),
1098
- attachments.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
1099
- "div",
1100
- {
1101
- "data-slot": "composer-attachments",
1102
- className: chunkS5RVSXDV_cjs.cn(
1103
- "flex flex-wrap gap-2 p-3",
1104
- "border-t border-neutral-200 dark:border-neutral-700"
1105
- ),
1106
- children: attachments.map((attachment) => /* @__PURE__ */ jsxRuntime.jsx(
1107
- AttachmentPreviewItem,
1108
- {
1109
- attachment,
1110
- onRemove: () => handleRemoveAttachment(attachment.id)
1111
- },
1112
- attachment.id
1113
- ))
1114
- }
1115
- ),
1116
- /* @__PURE__ */ jsxRuntime.jsxs(
1117
- "div",
1118
- {
1119
- "data-slot": "composer-input-area",
1120
- className: chunkS5RVSXDV_cjs.cn(
1121
- "flex items-center gap-2 p-3",
1122
- "bg-white dark:bg-neutral-900",
1123
- variant === "default" && "border-t border-neutral-200 dark:border-neutral-700"
1124
- ),
1125
- children: [
1126
- showAttachmentPicker && /* @__PURE__ */ jsxRuntime.jsx(
1127
- AttachmentPicker,
1128
- {
1129
- onFilesSelected: handleFilesSelected,
1130
- acceptedTypes: acceptedFileTypes,
1131
- maxFileSize,
1132
- maxFiles: maxAttachments - attachments.length,
1133
- disabled: disabled || attachments.length >= maxAttachments,
1134
- onError
1135
- }
1136
- ),
1137
- showCameraButton && /* @__PURE__ */ jsxRuntime.jsx(
1138
- CameraButton,
1139
- {
1140
- onCapture: (file) => handleFilesSelected([file]),
1141
- disabled: disabled || attachments.length >= maxAttachments
1142
- }
1143
- ),
1144
- /* @__PURE__ */ jsxRuntime.jsxs(
1145
- "div",
1146
- {
1147
- "data-slot": "composer-input-wrapper",
1148
- className: "relative flex-1",
1149
- ref: mention.anchorRef,
1150
- children: [
1151
- /* @__PURE__ */ jsxRuntime.jsx(MentionMenu, { mention }),
1152
- /* @__PURE__ */ jsxRuntime.jsx(
1153
- "textarea",
1154
- {
1155
- ref: textareaRef,
1156
- "data-slot": "composer-input",
1157
- value: content,
1158
- onChange: (e) => {
1159
- setContent(e.target.value);
1160
- mention.sync(
1161
- e.target.value,
1162
- e.target.selectionStart ?? e.target.value.length
1163
- );
1164
- },
1165
- onClick: (e) => {
1166
- const el = e.currentTarget;
1167
- mention.sync(el.value, el.selectionStart ?? el.value.length);
1168
- },
1169
- onKeyDown: handleKeyDown,
1170
- onPaste: handlePaste,
1171
- placeholder,
1172
- disabled: disabled || isSending,
1173
- rows: 1,
1174
- className: chunkS5RVSXDV_cjs.cn(
1175
- "w-full resize-none rounded-2xl py-2.5",
1176
- inputTrailing ? "ps-4 pe-10" : "px-4",
1177
- "bg-neutral-100 dark:bg-neutral-800",
1178
- "text-neutral-900 dark:text-neutral-100",
1179
- "placeholder:text-neutral-400 dark:placeholder:text-neutral-500",
1180
- "focus:ring-primary-500 focus:ring-2 focus:outline-none",
1181
- "disabled:cursor-not-allowed disabled:opacity-50",
1182
- "transition-colors",
1183
- "max-h-[150px]"
1184
- ),
1185
- "aria-label": "Message",
1186
- "aria-describedby": showCharacterCount ? "char-count" : void 0,
1187
- ...mention.inputProps
1188
- }
1189
- ),
1190
- inputTrailing && /* @__PURE__ */ jsxRuntime.jsx(
1191
- "div",
1192
- {
1193
- "data-slot": "composer-input-trailing",
1194
- className: "pointer-events-none absolute end-1 top-0 flex h-[44px] items-center [&>*]:pointer-events-auto",
1195
- children: inputTrailing
1196
- }
1197
- ),
1198
- showCharacterCount && /* @__PURE__ */ jsxRuntime.jsx(
1199
- "div",
1200
- {
1201
- "data-slot": "composer-char-count",
1202
- id: "char-count",
1203
- className: "absolute end-3 bottom-1.5",
1204
- children: /* @__PURE__ */ jsxRuntime.jsx(CharacterCounter, { current: content.length, max: maxLength })
1205
- }
1206
- )
1207
- ]
1208
- }
1209
- ),
1210
- /* @__PURE__ */ jsxRuntime.jsx(
1211
- SendButton,
1212
- {
1213
- canSend,
1214
- isLoading: isSending,
1215
- disabled
1216
- }
1217
- )
1218
- ]
1219
- }
1220
- )
1221
- ]
1222
- }
1223
- )
1224
- }
1225
- );
1226
- }
1227
- );
1228
- MessageComposer.displayName = "MessageComposer";
1229
-
1230
- exports.AttachmentPicker = AttachmentPicker;
1231
- exports.AttachmentPreviewItem = AttachmentPreviewItem;
1232
- exports.CameraButton = CameraButton;
1233
- exports.CharacterCounter = CharacterCounter;
1234
- exports.DragDropZone = DragDropZone;
1235
- exports.MentionMenu = MentionMenu;
1236
- exports.MessageComposer = MessageComposer;
1237
- exports.SendButton = SendButton;
1238
- exports.generateAttachmentId = generateAttachmentId;
1239
- exports.getFileType = getFileType;
1240
- exports.sendButtonVariants = sendButtonVariants;
1241
- exports.useMentionAutocomplete = useMentionAutocomplete;
1242
- exports.validateFile = validateFile;
1243
- //# sourceMappingURL=chunk-5BVFVXHN.cjs.map
1244
- //# sourceMappingURL=chunk-5BVFVXHN.cjs.map