@epam/ai-dial-attachment-input 1.2.0-dev.75 → 1.2.0-dev.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +197 -200
- package/package.json +2 -2
- package/utils/attachment.d.ts +5 -2
- package/utils/attachment.d.ts.map +1 -1
package/index.js
CHANGED
|
@@ -1,102 +1,99 @@
|
|
|
1
|
-
import { AttachmentErrorReason as e, AttachmentType as t, MIME_TYPE_EXT_MAP as n, RequestStatus as r, buildCssVars as i,
|
|
2
|
-
import { useCallback as
|
|
3
|
-
import { IconClipboard as
|
|
4
|
-
import { DIAL_ICON_SIZE as
|
|
5
|
-
import { Fragment as
|
|
1
|
+
import { AttachmentErrorReason as e, AttachmentType as t, MIME_TYPE_EXT_MAP as n, RequestStatus as r, buildCssVars as i, getBaseMimeType as a, mergeClasses as o, normalizeMimeType as s } from "@epam/ai-dial-chat-shared";
|
|
2
|
+
import { useCallback as c, useEffect as l, useId as u, useMemo as d, useRef as f, useState as p } from "react";
|
|
3
|
+
import { IconClipboard as m, IconDownload as h, IconExternalLink as g, IconFile as _, IconFileDescription as v, IconFileTypeBmp as y, IconFileTypeCss as b, IconFileTypeCsv as x, IconFileTypeDoc as S, IconFileTypeDocx as C, IconFileTypeHtml as w, IconFileTypeJpg as T, IconFileTypeJs as E, IconFileTypeJsx as D, IconFileTypePdf as O, IconFileTypePhp as k, IconFileTypePng as A, IconFileTypePpt as j, IconFileTypeRs as M, IconFileTypeSql as N, IconFileTypeSvg as P, IconFileTypeTs as F, IconFileTypeTsx as I, IconFileTypeTxt as L, IconFileTypeVue as ee, IconFileTypeXls as R, IconFileTypeXml as z, IconFileTypeZip as B, IconFileX as V, IconMusic as H, IconPaperclip as te, IconPhoto as U, IconReload as ne, IconTerminal2 as re, IconVideo as ie, IconX as ae } from "@tabler/icons-react";
|
|
4
|
+
import { DIAL_ICON_SIZE as W, DIAL_KIT_ICON_STROKE as G, ElementSize as oe, GhostIconButton as se, Highlight as ce, Skeleton as le, SkeletonVariant as ue, Spinner as de, StaticIconButton as fe } from "@epam/ai-dial-ui-kit";
|
|
5
|
+
import { Fragment as pe, jsx as K, jsxs as q } from "react/jsx-runtime";
|
|
6
6
|
//#region src/utils/attachment.ts
|
|
7
|
-
var
|
|
7
|
+
var me = () => `${Date.now()}-${Math.random().toString(36).slice(2)}`, he = (e) => {
|
|
8
8
|
if (e == null) return "";
|
|
9
9
|
let t = e.lastIndexOf(".");
|
|
10
10
|
return t > 0 ? e.slice(0, t) : e;
|
|
11
|
-
},
|
|
11
|
+
}, ge = {
|
|
12
12
|
image: "Image files",
|
|
13
13
|
audio: "Audio files",
|
|
14
14
|
video: "Video files",
|
|
15
15
|
text: "Text files",
|
|
16
16
|
"*": "All files"
|
|
17
|
-
},
|
|
18
|
-
let r = e
|
|
17
|
+
}, _e = { "image/jpeg": "JPEG" }, ve = (e, t = ge) => e.map((e) => {
|
|
18
|
+
let r = a(e);
|
|
19
19
|
if (r.endsWith("/*")) {
|
|
20
20
|
let e = r.slice(0, -2);
|
|
21
21
|
return t[e] ?? `${e} files`;
|
|
22
22
|
}
|
|
23
|
-
let i =
|
|
24
|
-
if (
|
|
25
|
-
let
|
|
26
|
-
if (
|
|
27
|
-
let
|
|
28
|
-
return
|
|
29
|
-
}).join(", "),
|
|
30
|
-
if (t ===
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
23
|
+
let i = s(r), o = _e[i];
|
|
24
|
+
if (o) return o;
|
|
25
|
+
let c = n[i];
|
|
26
|
+
if (c) return c.toUpperCase();
|
|
27
|
+
let l = i.split("/")[1];
|
|
28
|
+
return l == null ? e.toUpperCase() : l.toUpperCase();
|
|
29
|
+
}).join(", "), ye = (e, t) => {
|
|
30
|
+
if (t.length === 0) return !1;
|
|
31
|
+
let n = a(e), r = s(n);
|
|
32
|
+
return t.some((e) => {
|
|
33
|
+
let t = a(e);
|
|
34
|
+
if (t === "*" || t === "*/*") return !0;
|
|
35
|
+
if (t.endsWith("/*")) {
|
|
36
|
+
let e = t.slice(0, -2);
|
|
37
|
+
return n.startsWith(`${e}/`) || r.startsWith(`${e}/`);
|
|
38
|
+
}
|
|
39
|
+
return r === s(t);
|
|
40
|
+
});
|
|
41
|
+
}, be = (e) => {
|
|
42
|
+
if (!e) return _;
|
|
43
|
+
let t = s(e);
|
|
44
|
+
if (t.startsWith("image/")) switch (t) {
|
|
45
|
+
case "image/jpeg": return T;
|
|
46
|
+
case "image/png": return A;
|
|
47
|
+
case "image/svg+xml": return P;
|
|
48
|
+
case "image/bmp": return y;
|
|
49
|
+
default: return U;
|
|
45
50
|
}
|
|
46
|
-
if (
|
|
47
|
-
if (
|
|
48
|
-
switch (
|
|
49
|
-
case "application/pdf": return
|
|
50
|
-
case "application/msword":
|
|
51
|
-
case "application/vnd.
|
|
52
|
-
case "application/vnd.
|
|
53
|
-
case "application/vnd.
|
|
54
|
-
case "application/vnd.
|
|
55
|
-
case "application/vnd.
|
|
56
|
-
case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": return L;
|
|
51
|
+
if (t.startsWith("video/")) return ie;
|
|
52
|
+
if (t.startsWith("audio/")) return H;
|
|
53
|
+
switch (t) {
|
|
54
|
+
case "application/pdf": return O;
|
|
55
|
+
case "application/msword": return S;
|
|
56
|
+
case "application/vnd.openxmlformats-officedocument.wordprocessingml.document": return C;
|
|
57
|
+
case "application/vnd.ms-powerpoint": return j;
|
|
58
|
+
case "application/vnd.openxmlformats-officedocument.presentationml.presentation": return j;
|
|
59
|
+
case "application/vnd.ms-excel": return R;
|
|
60
|
+
case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": return R;
|
|
57
61
|
case "application/zip":
|
|
58
|
-
case "application/
|
|
59
|
-
case "application/x-rar-compressed":
|
|
62
|
+
case "application/vnd.rar":
|
|
60
63
|
case "application/x-7z-compressed":
|
|
61
64
|
case "application/gzip":
|
|
62
|
-
case "application/x-tar": return
|
|
63
|
-
case "text/csv": return
|
|
64
|
-
case "text/plain": return
|
|
65
|
+
case "application/x-tar": return B;
|
|
66
|
+
case "text/csv": return x;
|
|
67
|
+
case "text/plain": return L;
|
|
65
68
|
case "text/html":
|
|
66
|
-
case "application/xhtml+xml": return
|
|
67
|
-
case "
|
|
68
|
-
case "application/
|
|
69
|
-
case "
|
|
70
|
-
case "text/
|
|
71
|
-
case "text/
|
|
72
|
-
case "
|
|
73
|
-
case "text/
|
|
74
|
-
case "
|
|
75
|
-
case "text/
|
|
76
|
-
case "text/
|
|
77
|
-
|
|
78
|
-
case "text/x-php":
|
|
79
|
-
case "application/x-php": return D;
|
|
80
|
-
case "text/x-rustsrc":
|
|
81
|
-
case "application/x-rust": return A;
|
|
82
|
-
case "text/x-vue": return I;
|
|
83
|
-
default: return h;
|
|
69
|
+
case "application/xhtml+xml": return w;
|
|
70
|
+
case "application/xml": return z;
|
|
71
|
+
case "application/sql": return N;
|
|
72
|
+
case "text/javascript": return E;
|
|
73
|
+
case "text/jsx": return D;
|
|
74
|
+
case "text/typescript": return F;
|
|
75
|
+
case "text/tsx": return I;
|
|
76
|
+
case "text/css": return b;
|
|
77
|
+
case "text/x-php": return k;
|
|
78
|
+
case "text/x-rustsrc": return M;
|
|
79
|
+
case "text/x-vue": return ee;
|
|
80
|
+
default: return _;
|
|
84
81
|
}
|
|
85
|
-
},
|
|
82
|
+
}, xe = (e) => {
|
|
86
83
|
let { type: n, contentType: r } = e;
|
|
87
|
-
return n === t.Prompt ?
|
|
88
|
-
},
|
|
89
|
-
let t = e
|
|
84
|
+
return n === t.Prompt ? re : n === t.Pasted ? m : n === t.Image ? U : be(r ?? "");
|
|
85
|
+
}, Se = (e) => {
|
|
86
|
+
let t = s(e), r = n[t];
|
|
90
87
|
if (r) return r;
|
|
91
88
|
let i = t.split("/")[1];
|
|
92
89
|
if (i && !i.startsWith("vnd.") && !i.includes("+")) return i;
|
|
93
|
-
},
|
|
90
|
+
}, Ce = (e, n) => {
|
|
94
91
|
let { type: r, name: i, contentType: a } = e;
|
|
95
92
|
if (r === t.Prompt) return n.promptLabel ?? "Prompt";
|
|
96
93
|
if (r === t.Pasted) return n.pastedLabel ?? "Pasted";
|
|
97
94
|
if (r === t.Image) return n.imageLabel ?? "Image";
|
|
98
95
|
if (a) {
|
|
99
|
-
let e =
|
|
96
|
+
let e = Se(a);
|
|
100
97
|
if (e) return `.${e}`;
|
|
101
98
|
}
|
|
102
99
|
if (i == null) return "";
|
|
@@ -109,10 +106,10 @@ var fe = () => `${Date.now()}-${Math.random().toString(36).slice(2)}`, pe = (e)
|
|
|
109
106
|
isError: l,
|
|
110
107
|
isImage: u,
|
|
111
108
|
isLink: d,
|
|
112
|
-
BottomIcon: d ? null :
|
|
113
|
-
typeLabel: d ? null :
|
|
109
|
+
BottomIcon: d ? null : xe(e),
|
|
110
|
+
typeLabel: d ? null : Ce(e, n)
|
|
114
111
|
};
|
|
115
|
-
},
|
|
112
|
+
}, we = 5, Te = "flex size-[84px] items-center justify-center rounded-xl border", Y = {
|
|
116
113
|
tray: "dial-ai-attachment-tray",
|
|
117
114
|
trayItem: "dial-ai-attachment-tray-item",
|
|
118
115
|
tile: "dial-ai-attachment-tile",
|
|
@@ -131,106 +128,106 @@ var fe = () => `${Date.now()}-${Math.random().toString(36).slice(2)}`, pe = (e)
|
|
|
131
128
|
track: "_track_s2es2_50",
|
|
132
129
|
actionButton: "_actionButton_s2es2_56",
|
|
133
130
|
imageActionButton: "_imageActionButton_s2es2_60"
|
|
134
|
-
}, Z = ({ ariaLabel: e, errorTitle: t, errorDescId: n, onClick: r, id: i, icon:
|
|
135
|
-
icon:
|
|
136
|
-
size:
|
|
137
|
-
className:
|
|
131
|
+
}, Z = ({ ariaLabel: e, errorTitle: t, errorDescId: n, onClick: r, id: i, icon: a, className: s }) => /* @__PURE__ */ K(fe, {
|
|
132
|
+
icon: a,
|
|
133
|
+
size: oe.Small,
|
|
134
|
+
className: o("opacity-0 focus-visible:opacity-100 group-focus-within/attachment-tile:opacity-100 group-hover/attachment-tile:opacity-100", X.actionButton, s, Y.tileAction),
|
|
138
135
|
"aria-label": e,
|
|
139
136
|
"aria-describedby": t ? n : void 0,
|
|
140
137
|
onClick: (e) => {
|
|
141
138
|
e.stopPropagation(), r(i);
|
|
142
139
|
}
|
|
143
|
-
}),
|
|
140
|
+
}), Ee = ({ ...e }) => /* @__PURE__ */ K(Z, {
|
|
144
141
|
icon: /* @__PURE__ */ K(ne, {
|
|
145
|
-
size:
|
|
142
|
+
size: W.SM,
|
|
146
143
|
"aria-hidden": !0,
|
|
147
|
-
stroke:
|
|
144
|
+
stroke: G
|
|
148
145
|
}),
|
|
149
146
|
className: X.retryIcon,
|
|
150
147
|
...e
|
|
151
|
-
}),
|
|
152
|
-
icon: /* @__PURE__ */ K(
|
|
153
|
-
size:
|
|
148
|
+
}), De = ({ ...e }) => /* @__PURE__ */ K(Z, {
|
|
149
|
+
icon: /* @__PURE__ */ K(h, {
|
|
150
|
+
size: W.SM,
|
|
154
151
|
"aria-hidden": !0,
|
|
155
|
-
stroke:
|
|
152
|
+
stroke: G
|
|
156
153
|
}),
|
|
157
154
|
...e
|
|
158
|
-
}),
|
|
159
|
-
icon: /* @__PURE__ */ K(
|
|
160
|
-
size:
|
|
155
|
+
}), Oe = ({ ...e }) => /* @__PURE__ */ K(Z, {
|
|
156
|
+
icon: /* @__PURE__ */ K(g, {
|
|
157
|
+
size: W.SM,
|
|
161
158
|
"aria-hidden": !0,
|
|
162
|
-
stroke:
|
|
159
|
+
stroke: G
|
|
163
160
|
}),
|
|
164
161
|
...e
|
|
165
|
-
}),
|
|
166
|
-
icon: /* @__PURE__ */ K(
|
|
167
|
-
size:
|
|
162
|
+
}), ke = ({ ...e }) => /* @__PURE__ */ K(Z, {
|
|
163
|
+
icon: /* @__PURE__ */ K(ae, {
|
|
164
|
+
size: W.SM,
|
|
168
165
|
"aria-hidden": !0,
|
|
169
|
-
stroke:
|
|
166
|
+
stroke: G
|
|
170
167
|
}),
|
|
171
168
|
...e
|
|
172
|
-
}),
|
|
169
|
+
}), Ae = {
|
|
173
170
|
[e.Network]: "Upload failed · network error",
|
|
174
171
|
[e.UnsupportedType]: "Upload failed · unsupported file type",
|
|
175
172
|
[e.FileTooLarge]: "Upload failed · file too large"
|
|
176
|
-
},
|
|
177
|
-
let { clickLabel: b = "Download attachment", retryLabel: x = "Retry upload", removeLabel: S = "Remove attachment", openInNewTabLabel: C = "Open in new tab", sizeLabel: w, uploadingLabel: T = "Uploading", errorReasonLabels: E, genericErrorLabel: D = "Upload failed" } =
|
|
173
|
+
}, je = ({ attachment: t, searchQuery: n = "", onClick: i, onRetry: a, labels: s, styles: l, onDownload: f, isPasted: p, isLink: m, cssVars: h, onExpand: g, isExpandable: _, onRemove: v, isSelected: y }) => {
|
|
174
|
+
let { clickLabel: b = "Download attachment", retryLabel: x = "Retry upload", removeLabel: S = "Remove attachment", openInNewTabLabel: C = "Open in new tab", sizeLabel: w, uploadingLabel: T = "Uploading", errorReasonLabels: E, genericErrorLabel: D = "Upload failed" } = s ?? {}, { typography: O, className: k } = l ?? {}, { id: A, name: j, status: M, errorReason: N } = t, P = M === r.Loading, F = M === r.Error, I = u(), L = F ? N && (E?.[N] ?? Ae[N]) || D : "", { BottomIcon: ee, typeLabel: R } = J(t), z = !F && !P && f && !m, B = F && !!a && N !== e.UnsupportedType && N !== e.FileTooLarge, V = Number(!!z) + Number(!!B) + Number(!!m) + Number(!!v), H = V > 1 ? "pe-11" : V === 1 ? "pe-5" : void 0, te = (e) => {
|
|
178
175
|
e.target === e.currentTarget && (e.key === "Enter" || e.key === " ") && (e.preventDefault(), i?.(t.id));
|
|
179
|
-
},
|
|
176
|
+
}, U = d(() => p ? j : he(j), [p, j]), ne = c(() => {
|
|
180
177
|
window.open(t.referenceUrl, "_blank", "noopener,noreferrer");
|
|
181
|
-
}, [t]),
|
|
182
|
-
title:
|
|
183
|
-
className:
|
|
184
|
-
children: n ? /* @__PURE__ */ K(
|
|
185
|
-
text:
|
|
178
|
+
}, [t]), re = o(Te, "group/attachment-tile relative flex-col justify-between items-start gap-1 overflow-hidden p-1.5", X.tile, !F && X.hovered, y && X.selected, F && X.tileError, Y.tile, y && Y.tileSelected), ie = /* @__PURE__ */ K("div", {
|
|
179
|
+
title: U,
|
|
180
|
+
className: o(O?.nameClassName ?? "dial-caption-text", "line-clamp-2 w-full min-w-0 break-words", X.nameText, !F && H, Y.tileName),
|
|
181
|
+
children: n ? /* @__PURE__ */ K(ce, {
|
|
182
|
+
text: U,
|
|
186
183
|
query: n,
|
|
187
184
|
maxLines: 2
|
|
188
|
-
}) :
|
|
189
|
-
}),
|
|
190
|
-
className:
|
|
191
|
-
children: [/* @__PURE__ */ K(
|
|
185
|
+
}) : U
|
|
186
|
+
}), ae = ee && /* @__PURE__ */ q("div", {
|
|
187
|
+
className: o("flex w-full items-center gap-1", F && H, Y.tileType),
|
|
188
|
+
children: [/* @__PURE__ */ K(ee, {
|
|
192
189
|
size: 16,
|
|
193
190
|
className: X.typeText,
|
|
194
191
|
"aria-hidden": !0
|
|
195
192
|
}), /* @__PURE__ */ K("span", {
|
|
196
|
-
className:
|
|
197
|
-
children: w ? `${
|
|
193
|
+
className: o(O?.metaClassName ?? "dial-caption-text", "min-w-0 flex-1 truncate", X.typeText),
|
|
194
|
+
children: w ? `${R} · ${w}` : R
|
|
198
195
|
})]
|
|
199
|
-
}),
|
|
196
|
+
}), W = () => {
|
|
200
197
|
_ && g ? g(A) : i && i(A);
|
|
201
|
-
},
|
|
202
|
-
|
|
203
|
-
|
|
198
|
+
}, G = /* @__PURE__ */ q(pe, { children: [
|
|
199
|
+
ie,
|
|
200
|
+
ae,
|
|
204
201
|
P && /* @__PURE__ */ K("div", {
|
|
205
202
|
role: "progressbar",
|
|
206
203
|
"aria-label": T,
|
|
207
|
-
className:
|
|
208
|
-
children: /* @__PURE__ */ K(
|
|
204
|
+
className: o("absolute start-[-1px] top-[-1px] flex size-full items-center justify-center rounded", X.track),
|
|
205
|
+
children: /* @__PURE__ */ K(de, { size: 32 })
|
|
209
206
|
}),
|
|
210
207
|
/* @__PURE__ */ q("div", {
|
|
211
208
|
className: "absolute end-1 top-1 flex gap-1",
|
|
212
209
|
children: [
|
|
213
|
-
|
|
210
|
+
z && /* @__PURE__ */ K(De, {
|
|
214
211
|
ariaLabel: b,
|
|
215
212
|
errorTitle: L,
|
|
216
213
|
errorDescId: I,
|
|
217
214
|
onClick: f,
|
|
218
215
|
id: A
|
|
219
216
|
}),
|
|
220
|
-
|
|
217
|
+
B && /* @__PURE__ */ K(Ee, {
|
|
221
218
|
ariaLabel: x,
|
|
222
219
|
errorTitle: L,
|
|
223
220
|
errorDescId: I,
|
|
224
|
-
onClick:
|
|
221
|
+
onClick: a,
|
|
225
222
|
id: A
|
|
226
223
|
}),
|
|
227
|
-
m && /* @__PURE__ */ K(
|
|
224
|
+
m && /* @__PURE__ */ K(Oe, {
|
|
228
225
|
ariaLabel: C,
|
|
229
226
|
errorTitle: L,
|
|
230
227
|
errorDescId: I,
|
|
231
|
-
onClick:
|
|
228
|
+
onClick: ne
|
|
232
229
|
}),
|
|
233
|
-
v && /* @__PURE__ */ K(
|
|
230
|
+
v && /* @__PURE__ */ K(ke, {
|
|
234
231
|
ariaLabel: S,
|
|
235
232
|
errorTitle: L,
|
|
236
233
|
errorDescId: I,
|
|
@@ -249,26 +246,26 @@ var fe = () => `${Date.now()}-${Math.random().toString(36).slice(2)}`, pe = (e)
|
|
|
249
246
|
] });
|
|
250
247
|
return /* @__PURE__ */ K("div", {
|
|
251
248
|
style: h,
|
|
252
|
-
className:
|
|
249
|
+
className: o("inline-flex", k),
|
|
253
250
|
children: /* @__PURE__ */ K("div", {
|
|
254
251
|
role: "button",
|
|
255
252
|
tabIndex: 0,
|
|
256
253
|
"aria-label": b,
|
|
257
254
|
"aria-busy": P,
|
|
258
|
-
onClick:
|
|
259
|
-
onKeyDown:
|
|
255
|
+
onClick: W,
|
|
256
|
+
onKeyDown: te,
|
|
260
257
|
style: h,
|
|
261
|
-
className:
|
|
262
|
-
children:
|
|
258
|
+
className: o(re, "cursor-pointer focus-within:outline focus-within:outline-1 focus-within:outline-offset-1"),
|
|
259
|
+
children: G
|
|
263
260
|
})
|
|
264
261
|
});
|
|
265
262
|
}, Q = /* @__PURE__ */ function(e) {
|
|
266
263
|
return e.Idle = "idle", e.Loading = "loading", e.Loaded = "loaded", e.Error = "error", e;
|
|
267
|
-
}({}),
|
|
268
|
-
let n =
|
|
269
|
-
return
|
|
264
|
+
}({}), Me = ({ enabled: e, src: t }) => {
|
|
265
|
+
let n = f(null), [r, i] = p("idle");
|
|
266
|
+
return l(() => {
|
|
270
267
|
i(e && t ? "loading" : "idle");
|
|
271
|
-
}, [e, t]),
|
|
268
|
+
}, [e, t]), l(() => {
|
|
272
269
|
let r = n.current;
|
|
273
270
|
if (!r || !e || !t) return;
|
|
274
271
|
let a = () => i("loaded"), o = () => i("error");
|
|
@@ -279,15 +276,15 @@ var fe = () => `${Date.now()}-${Math.random().toString(36).slice(2)}`, pe = (e)
|
|
|
279
276
|
imageRef: n,
|
|
280
277
|
imageLoadStatus: r
|
|
281
278
|
};
|
|
282
|
-
},
|
|
283
|
-
let { clickLabel: f = "Open attachment", expandLabel: p = "Expand pasted text", removeLabel: m = "Remove attachment", downloadLabel: h = "Download attachment" } = i ?? {}, { className: g } =
|
|
279
|
+
}, Ne = ({ attachment: e, onExpand: n, onClick: r, labels: i, onRemove: a, cssVars: s, onDownload: c, styles: l, isSelected: u }) => {
|
|
280
|
+
let { clickLabel: f = "Open attachment", expandLabel: p = "Expand pasted text", removeLabel: m = "Remove attachment", downloadLabel: h = "Download attachment" } = i ?? {}, { className: g } = l ?? {}, { id: _, name: v } = e, y = e.previewUrl ?? e.url, b = e.type === t.Pasted && n !== void 0, { isLoading: x, isError: S, isImage: C } = d(() => J(e), [e]), w = r !== void 0 && !b && !x && !S, { imageRef: T, imageLoadStatus: E } = Me({
|
|
284
281
|
enabled: C,
|
|
285
282
|
src: y
|
|
286
283
|
}), D = () => {
|
|
287
284
|
b && n ? n(_) : w && r && r(_);
|
|
288
285
|
};
|
|
289
286
|
return /* @__PURE__ */ K("div", {
|
|
290
|
-
className:
|
|
287
|
+
className: o(Te, "group/attachment-tile", w && "cursor-pointer", X.tile, u && X.selected, g, Y.tile, u && Y.tileSelected),
|
|
291
288
|
onClick: D,
|
|
292
289
|
onKeyDown: (e) => {
|
|
293
290
|
e.target === e.currentTarget && (e.key === "Enter" || e.key === " ") && (e.preventDefault(), D());
|
|
@@ -301,28 +298,28 @@ var fe = () => `${Date.now()}-${Math.random().toString(36).slice(2)}`, pe = (e)
|
|
|
301
298
|
children: [
|
|
302
299
|
/* @__PURE__ */ q("div", {
|
|
303
300
|
className: "absolute end-1 top-1 z-10 flex gap-1",
|
|
304
|
-
children: [
|
|
301
|
+
children: [a && /* @__PURE__ */ K(ke, {
|
|
305
302
|
ariaLabel: m,
|
|
306
|
-
onClick:
|
|
303
|
+
onClick: a,
|
|
307
304
|
id: _,
|
|
308
305
|
className: X.imageActionButton
|
|
309
|
-
}), c && /* @__PURE__ */ K(
|
|
306
|
+
}), c && /* @__PURE__ */ K(De, {
|
|
310
307
|
ariaLabel: h,
|
|
311
308
|
onClick: c,
|
|
312
309
|
id: _,
|
|
313
310
|
className: X.imageActionButton
|
|
314
311
|
})]
|
|
315
312
|
}),
|
|
316
|
-
E !== Q.Loaded && /* @__PURE__ */ K(
|
|
317
|
-
variant:
|
|
313
|
+
E !== Q.Loaded && /* @__PURE__ */ K(le, {
|
|
314
|
+
variant: ue.Rectangular,
|
|
318
315
|
width: "100%",
|
|
319
316
|
height: "100%",
|
|
320
317
|
active: E === Q.Loading,
|
|
321
|
-
overlay: /* @__PURE__ */ K(
|
|
322
|
-
size:
|
|
318
|
+
overlay: /* @__PURE__ */ K(U, {
|
|
319
|
+
size: W.LG,
|
|
323
320
|
className: X.typeText,
|
|
324
321
|
"aria-hidden": !0,
|
|
325
|
-
stroke:
|
|
322
|
+
stroke: G
|
|
326
323
|
}),
|
|
327
324
|
className: "absolute inset-0 rounded-xl"
|
|
328
325
|
}),
|
|
@@ -332,13 +329,13 @@ var fe = () => `${Date.now()}-${Math.random().toString(36).slice(2)}`, pe = (e)
|
|
|
332
329
|
alt: v,
|
|
333
330
|
loading: "lazy",
|
|
334
331
|
decoding: "async",
|
|
335
|
-
className:
|
|
332
|
+
className: o("h-full w-full rounded-xl object-cover transition-opacity duration-200", E === Q.Loaded ? "opacity-100" : "opacity-0")
|
|
336
333
|
})
|
|
337
334
|
]
|
|
338
335
|
})
|
|
339
336
|
});
|
|
340
|
-
},
|
|
341
|
-
let { colors: p } =
|
|
337
|
+
}, Pe = ({ attachment: e, searchQuery: n = "", onRemove: r, onRetry: a, onExpand: o, onClick: s, onDownload: c, labels: l, styles: u, isSelected: f }) => {
|
|
338
|
+
let { colors: p } = u ?? {}, m = e.type === t.Pasted, h = m && o !== void 0, g = i({
|
|
342
339
|
"--ai-tile-bg": p?.background,
|
|
343
340
|
"--ai-tile-border": p?.border,
|
|
344
341
|
"--ai-tile-bg-hover": p?.backgroundHover,
|
|
@@ -354,18 +351,18 @@ var fe = () => `${Date.now()}-${Math.random().toString(36).slice(2)}`, pe = (e)
|
|
|
354
351
|
"--ai-tile-hover-icon-bg": p?.hoverIconBackground,
|
|
355
352
|
"--ai-tile-hover-icon-color": p?.hoverIconColor,
|
|
356
353
|
"--ai-tile-progress-track": p?.trackBackground
|
|
357
|
-
}), { isImage: _, isLink: v } =
|
|
358
|
-
return _ ? /* @__PURE__ */ K(
|
|
354
|
+
}), { isImage: _, isLink: v } = d(() => J(e), [e]);
|
|
355
|
+
return _ ? /* @__PURE__ */ K(Ne, {
|
|
359
356
|
attachment: e,
|
|
360
|
-
labels:
|
|
357
|
+
labels: l,
|
|
361
358
|
onClick: s,
|
|
362
359
|
onExpand: o,
|
|
363
|
-
styles:
|
|
360
|
+
styles: u,
|
|
364
361
|
onRemove: r,
|
|
365
362
|
cssVars: g,
|
|
366
363
|
onDownload: c,
|
|
367
364
|
isSelected: f
|
|
368
|
-
}) : /* @__PURE__ */ K(
|
|
365
|
+
}) : /* @__PURE__ */ K(je, {
|
|
369
366
|
attachment: e,
|
|
370
367
|
searchQuery: n,
|
|
371
368
|
onClick: s,
|
|
@@ -374,23 +371,23 @@ var fe = () => `${Date.now()}-${Math.random().toString(36).slice(2)}`, pe = (e)
|
|
|
374
371
|
onDownload: c,
|
|
375
372
|
isLink: v,
|
|
376
373
|
isPasted: m,
|
|
377
|
-
styles:
|
|
378
|
-
labels:
|
|
374
|
+
styles: u,
|
|
375
|
+
labels: l,
|
|
379
376
|
onExpand: o,
|
|
380
377
|
cssVars: g,
|
|
381
378
|
isExpandable: h,
|
|
382
379
|
isSelected: f
|
|
383
380
|
});
|
|
384
|
-
},
|
|
385
|
-
let { ariaLabel: c = "Attached files", removeLabel: l, retryLabel: u, clickLabel: d, uploadingLabel: f } =
|
|
381
|
+
}, Fe = ({ attachments: e, onRemove: t, onRetry: n, onExpand: r, onAttachmentClick: i, labels: a, styles: s }) => {
|
|
382
|
+
let { ariaLabel: c = "Attached files", removeLabel: l, retryLabel: u, clickLabel: d, uploadingLabel: f } = a ?? {}, { className: p } = s ?? {};
|
|
386
383
|
return e.length === 0 ? null : /* @__PURE__ */ K("div", {
|
|
387
384
|
role: "list",
|
|
388
385
|
"aria-label": c,
|
|
389
|
-
className:
|
|
386
|
+
className: o("flex w-full min-w-0 gap-2 overflow-x-auto", p, Y.tray),
|
|
390
387
|
children: e.map((e) => /* @__PURE__ */ K("div", {
|
|
391
388
|
role: "listitem",
|
|
392
389
|
className: Y.trayItem,
|
|
393
|
-
children: /* @__PURE__ */ K(
|
|
390
|
+
children: /* @__PURE__ */ K(Pe, {
|
|
394
391
|
attachment: e,
|
|
395
392
|
onRemove: t,
|
|
396
393
|
onRetry: n,
|
|
@@ -405,88 +402,88 @@ var fe = () => `${Date.now()}-${Math.random().toString(36).slice(2)}`, pe = (e)
|
|
|
405
402
|
})
|
|
406
403
|
}, e.id))
|
|
407
404
|
});
|
|
408
|
-
},
|
|
405
|
+
}, Ie = {
|
|
409
406
|
headerIcon: "_headerIcon_1dmgi_1",
|
|
410
407
|
headerLabel: "_headerLabel_1dmgi_2"
|
|
411
|
-
},
|
|
412
|
-
let { ariaLabel: d = "Attachments", clickLabel: f = "Download attachment", retryLabel:
|
|
408
|
+
}, Le = (e, t) => `${e} ${t}${e === 1 ? "" : "s"}`, Re = ({ attachments: e, onAttachmentClick: n, onDownloadAll: a, onRetry: s, labels: c, styles: l, selectedAttachmentId: u }) => {
|
|
409
|
+
let { ariaLabel: d = "Attachments", clickLabel: f = "Download attachment", retryLabel: p = "Retry upload", downloadAllLabel: m = "Download all", openInNewTabLabel: g, getHeaderLabel: v = (e) => Le(e, "attachment"), promptLabel: y, pastedLabel: b, imageLabel: x } = c ?? {}, { typography: S, colors: C, className: w } = l ?? {}, T = i({ "--ai-group-text": C?.text });
|
|
413
410
|
if (e.length === 0) return null;
|
|
414
|
-
let E = e.some((e) => e.type === t.Image), D = e.some((e) => e.type !== t.Image), O = E && D, k = e.length >= 5, A = O ?
|
|
411
|
+
let E = e.some((e) => e.type === t.Image), D = e.some((e) => e.type !== t.Image), O = E && D, k = e.length >= 5, A = O ? te : E ? U : _, j = v(e.length), M = () => {
|
|
415
412
|
let t = e.filter((e) => e.status === r.Idle);
|
|
416
|
-
|
|
413
|
+
a ? a(t) : t.forEach((e) => n?.(e.id));
|
|
417
414
|
}, N = (t) => {
|
|
418
415
|
let n = e.find((e) => e.id === t);
|
|
419
|
-
n &&
|
|
416
|
+
n && a?.([n]);
|
|
420
417
|
};
|
|
421
418
|
return /* @__PURE__ */ q("div", {
|
|
422
419
|
role: "group",
|
|
423
420
|
"aria-label": d,
|
|
424
421
|
style: T,
|
|
425
|
-
className:
|
|
422
|
+
className: o("flex flex-col gap-1", k ? "w-full min-w-0 max-w-[492px]" : "max-w-[420px]", Ie.container, w),
|
|
426
423
|
children: [/* @__PURE__ */ q("div", {
|
|
427
424
|
className: "flex items-center justify-between",
|
|
428
425
|
children: [/* @__PURE__ */ q("div", {
|
|
429
426
|
className: "flex items-center gap-1",
|
|
430
427
|
children: [/* @__PURE__ */ K(A, {
|
|
431
|
-
size:
|
|
432
|
-
className:
|
|
428
|
+
size: W.SM,
|
|
429
|
+
className: o("shrink-0", Ie.headerIcon),
|
|
433
430
|
"aria-hidden": !0
|
|
434
431
|
}), /* @__PURE__ */ K("span", {
|
|
435
|
-
className:
|
|
432
|
+
className: o(S?.headerLabelClassName ?? "dial-tiny-semi-text", Ie.headerLabel),
|
|
436
433
|
children: j
|
|
437
434
|
})]
|
|
438
|
-
}), e.length >= 2 && (
|
|
439
|
-
icon: /* @__PURE__ */ K(
|
|
440
|
-
size:
|
|
435
|
+
}), e.length >= 2 && (a || n) && /* @__PURE__ */ K(se, {
|
|
436
|
+
icon: /* @__PURE__ */ K(h, {
|
|
437
|
+
size: W.SM,
|
|
441
438
|
"aria-hidden": !0,
|
|
442
|
-
stroke:
|
|
439
|
+
stroke: G
|
|
443
440
|
}),
|
|
444
|
-
size:
|
|
445
|
-
"aria-label":
|
|
441
|
+
size: oe.Small,
|
|
442
|
+
"aria-label": m,
|
|
446
443
|
onClick: M
|
|
447
444
|
})]
|
|
448
445
|
}), /* @__PURE__ */ K("div", {
|
|
449
446
|
role: "list",
|
|
450
447
|
"aria-label": j,
|
|
451
|
-
className:
|
|
448
|
+
className: o("gap-3", k ? "grid grid-cols-[repeat(5,83px)]" : "flex flex-wrap"),
|
|
452
449
|
children: e.map((e, t) => /* @__PURE__ */ K("div", {
|
|
453
450
|
role: "listitem",
|
|
454
|
-
children: /* @__PURE__ */ K(
|
|
451
|
+
children: /* @__PURE__ */ K(Pe, {
|
|
455
452
|
attachment: e,
|
|
456
453
|
onClick: n,
|
|
457
454
|
onDownload: N,
|
|
458
455
|
onRetry: s,
|
|
459
456
|
labels: {
|
|
460
457
|
clickLabel: f,
|
|
461
|
-
retryLabel:
|
|
458
|
+
retryLabel: p,
|
|
462
459
|
promptLabel: y,
|
|
463
460
|
pastedLabel: b,
|
|
464
461
|
imageLabel: x,
|
|
465
|
-
openInNewTabLabel:
|
|
462
|
+
openInNewTabLabel: g
|
|
466
463
|
},
|
|
467
464
|
isSelected: e.id === u
|
|
468
465
|
})
|
|
469
466
|
}, `${e.id}-${t}`))
|
|
470
467
|
})]
|
|
471
468
|
});
|
|
472
|
-
},
|
|
469
|
+
}, ze = {
|
|
473
470
|
overlay: "_overlay_mzpdp_1",
|
|
474
471
|
icon: "_icon_mzpdp_5",
|
|
475
472
|
deniedIcon: "_deniedIcon_mzpdp_9"
|
|
476
|
-
},
|
|
477
|
-
let { title:
|
|
473
|
+
}, Be = ({ isVisible: e, isAttachmentsAllowed: t = !0, labels: n, styles: r }) => {
|
|
474
|
+
let { title: a, subtitle: s } = n ?? {}, { colors: c, typography: l } = r ?? {};
|
|
478
475
|
if (!e) return null;
|
|
479
476
|
let u = i({
|
|
480
477
|
"--ai-fd-bg": c?.background,
|
|
481
478
|
"--ai-fd-icon": c?.icon,
|
|
482
479
|
"--ai-fd-denied-icon": c?.deniedIcon
|
|
483
|
-
}), d =
|
|
480
|
+
}), d = a ?? (t ? "Attach files" : "No attachments allowed"), f = s ?? (t ? "Drop files here to attach them to message" : "Attachments can't be added to message"), p = t ? ze.icon : ze.deniedIcon, m = (e) => {
|
|
484
481
|
e.preventDefault();
|
|
485
|
-
}, h = t ?
|
|
482
|
+
}, h = t ? v : V;
|
|
486
483
|
return /* @__PURE__ */ K("div", {
|
|
487
484
|
role: "status",
|
|
488
485
|
"aria-live": "polite",
|
|
489
|
-
className:
|
|
486
|
+
className: o("fixed inset-0 z-[9999] flex items-center justify-center backdrop-blur-sm", ze.overlay, t ? "pointer-events-none" : "pointer-events-auto cursor-not-allowed"),
|
|
490
487
|
onDragOver: t ? void 0 : m,
|
|
491
488
|
onDrop: t ? void 0 : m,
|
|
492
489
|
style: u,
|
|
@@ -499,32 +496,32 @@ var fe = () => `${Date.now()}-${Math.random().toString(36).slice(2)}`, pe = (e)
|
|
|
499
496
|
"aria-hidden": !0
|
|
500
497
|
}),
|
|
501
498
|
/* @__PURE__ */ K("span", {
|
|
502
|
-
className:
|
|
499
|
+
className: o("mt-5", l?.titleClassName ?? "dial-h3-text"),
|
|
503
500
|
children: d
|
|
504
501
|
}),
|
|
505
502
|
/* @__PURE__ */ K("span", {
|
|
506
|
-
className:
|
|
503
|
+
className: o("mt-4", l?.subtitleClassName ?? "dial-small-text"),
|
|
507
504
|
children: f
|
|
508
505
|
})
|
|
509
506
|
]
|
|
510
507
|
})
|
|
511
508
|
});
|
|
512
|
-
}, $ = (e) => String(e).padStart(2, "0"),
|
|
509
|
+
}, $ = (e) => String(e).padStart(2, "0"), Ve = (e) => `${e.getFullYear()}-${$(e.getMonth() + 1)}-${$(e.getDate())} ${$(e.getHours())}-${$(e.getMinutes())}-${$(e.getSeconds())}`, He = (e, t, n) => {
|
|
513
510
|
let r = e.lastIndexOf("."), i = r > 0, a = i ? e.slice(0, r) : e, o = i ? e.slice(r) : "", s = n === 0 ? "" : ` (${n + 1})`;
|
|
514
|
-
return `${a} ${
|
|
515
|
-
},
|
|
516
|
-
let { screenshotName: a = "Screenshot.png", pastedTextName:
|
|
517
|
-
return { handlePaste:
|
|
511
|
+
return `${a} ${Ve(t)}${s}${o}`;
|
|
512
|
+
}, Ue = (e, n, i = {}) => {
|
|
513
|
+
let { screenshotName: a = "Screenshot.png", pastedTextName: o = "Pasted text" } = i;
|
|
514
|
+
return { handlePaste: c((i) => {
|
|
518
515
|
if (!i.clipboardData) return;
|
|
519
|
-
let
|
|
520
|
-
if (
|
|
521
|
-
let n = [],
|
|
522
|
-
for (let e of
|
|
516
|
+
let s = Array.from(i.clipboardData.items).filter((e) => e.kind === "file" && e.type.startsWith("image/")), c = i.clipboardData.getData("text/plain").length > 0;
|
|
517
|
+
if (s.length > 0 && !c) {
|
|
518
|
+
let n = [], o = /* @__PURE__ */ new Date();
|
|
519
|
+
for (let e of s) {
|
|
523
520
|
let i = e.getAsFile();
|
|
524
521
|
if (!i) continue;
|
|
525
|
-
let
|
|
526
|
-
id:
|
|
527
|
-
name:
|
|
522
|
+
let s = He(a, o, n.length), c = new File([i], s, { type: i.type }), l = {
|
|
523
|
+
id: me(),
|
|
524
|
+
name: s,
|
|
528
525
|
contentType: i.type,
|
|
529
526
|
file: c,
|
|
530
527
|
type: t.Image,
|
|
@@ -538,11 +535,11 @@ var fe = () => `${Date.now()}-${Math.random().toString(36).slice(2)}`, pe = (e)
|
|
|
538
535
|
}
|
|
539
536
|
let l = i.clipboardData.getData("text/plain");
|
|
540
537
|
if (l.length > n) {
|
|
541
|
-
let n = l.trim(), a = (n.length > 80 ? `${n.slice(0, 80).trimEnd()}…` : n) ||
|
|
542
|
-
id:
|
|
538
|
+
let n = l.trim(), a = (n.length > 80 ? `${n.slice(0, 80).trimEnd()}…` : n) || o, s = new File([l], a, { type: "text/plain" }), c = {
|
|
539
|
+
id: me(),
|
|
543
540
|
name: a,
|
|
544
541
|
contentType: "text/plain",
|
|
545
|
-
file:
|
|
542
|
+
file: s,
|
|
546
543
|
type: t.Pasted,
|
|
547
544
|
status: r.Idle
|
|
548
545
|
};
|
|
@@ -552,8 +549,8 @@ var fe = () => `${Date.now()}-${Math.random().toString(36).slice(2)}`, pe = (e)
|
|
|
552
549
|
e,
|
|
553
550
|
n,
|
|
554
551
|
a,
|
|
555
|
-
|
|
552
|
+
o
|
|
556
553
|
]) };
|
|
557
|
-
},
|
|
554
|
+
}, We = 100;
|
|
558
555
|
//#endregion
|
|
559
|
-
export {
|
|
556
|
+
export { we as ATTACHMENT_COLLAPSE_THRESHOLD, Y as ATTACHMENT_INPUT_CLASS, Pe as AttachmentCard, Re as AttachmentGroup, Fe as AttachmentTray, Be as FileDndOverlay, Q as LazyImageLoadStatus, We as MAX_UPLOADS_PER_MINUTE, me as generateAttachmentId, J as getAttachmentCardState, be as getAttachmentIcon, Se as getExtFromContentType, he as getNameWithoutExtension, ye as isMimeTypeAllowed, ve as mimeTypesToExtensionLabels, Ue as useClipboardPaste, Me as useLazyImageLoad };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@epam/ai-dial-attachment-input",
|
|
3
3
|
"description": "File attachment input components with upload validation, drag-and-drop, and progress tracking",
|
|
4
|
-
"version": "1.2.0-dev.
|
|
4
|
+
"version": "1.2.0-dev.80",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./index.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"@tabler/icons-react": "^3.44.0"
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
|
23
|
-
"@epam/ai-dial-chat-shared": "1.2.0-dev.
|
|
23
|
+
"@epam/ai-dial-chat-shared": "1.2.0-dev.80",
|
|
24
24
|
"react": "^19.2.8",
|
|
25
25
|
"@epam/ai-dial-ui-kit": "^0.15.0-dev.9"
|
|
26
26
|
},
|
package/utils/attachment.d.ts
CHANGED
|
@@ -13,12 +13,15 @@ export declare const mimeTypesToExtensionLabels: (types: string[], wildcardLabel
|
|
|
13
13
|
* Matching rules:
|
|
14
14
|
* - Exact match: `'application/pdf'` allows `'application/pdf'`.
|
|
15
15
|
* - Wildcard prefix: `'image/*'` allows any `'image/...'` MIME type.
|
|
16
|
+
* - Alias match: both sides are canonicalized, so `'text/json'` allows
|
|
17
|
+
* `'application/json'` and vice versa.
|
|
18
|
+
* - Parameters and letter case are ignored on both sides.
|
|
16
19
|
*
|
|
17
20
|
* Returns `false` when `allowedTypes` is empty (no attachment types allowed).
|
|
18
21
|
*/
|
|
19
22
|
export declare const isMimeTypeAllowed: (mimeType: string, allowedTypes: string[]) => boolean;
|
|
20
|
-
/** Returns the Tabler icon component for a given MIME content type, or `IconFile` for unknown types. */
|
|
21
|
-
export declare const getAttachmentIcon: (
|
|
23
|
+
/** Returns the Tabler icon component for a given MIME content type, or `IconFile` for unknown types. Aliases resolve to their canonical type first. */
|
|
24
|
+
export declare const getAttachmentIcon: (rawContentType: string) => Icon;
|
|
22
25
|
/** Derives a bare file extension (no leading dot) from a MIME type, e.g. `'application/pdf'` -> `'pdf'`. */
|
|
23
26
|
export declare const getExtFromContentType: (contentType: string) => string | undefined;
|
|
24
27
|
/** Derives the display state (icons, labels, color classes) an AttachmentCard needs to render a given attachment. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachment.d.ts","sourceRoot":"","sources":["../../src/utils/attachment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"attachment.d.ts","sourceRoot":"","sources":["../../src/utils/attachment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAQnE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAgChD,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,2BAA2B,CAAC;AAEnC,uDAAuD;AACvD,eAAO,MAAM,oBAAoB,QAAO,MACgB,CAAC;AAEzD,4GAA4G;AAC5G,eAAO,MAAM,uBAAuB,GAAI,MAAM,MAAM,KAAG,MAItD,CAAC;AAcF,uHAAuH;AACvH,eAAO,MAAM,0BAA0B,GACrC,OAAO,MAAM,EAAE,EACf,iBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAwB,KAC5D,MAoBF,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iBAAiB,GAC5B,UAAU,MAAM,EAChB,cAAc,MAAM,EAAE,KACrB,OAsBF,CAAC;AAEF,uJAAuJ;AACvJ,eAAO,MAAM,iBAAiB,GAAI,gBAAgB,MAAM,KAAG,IAkF1D,CAAC;AAUF,4GAA4G;AAC5G,eAAO,MAAM,qBAAqB,GAChC,aAAa,MAAM,KAClB,MAAM,GAAG,SAUX,CAAC;AA6BF,qHAAqH;AACrH,eAAO,MAAM,sBAAsB,GACjC,YAAY,iBAAiB,EAC7B,aAAY,oBAAyB,KACpC,mBAiBF,CAAC"}
|