@customerhero/react 2.3.0 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-BB2DI7WR.js → chunk-M7MROJ5Z.js} +209 -3
- package/dist/index.cjs +209 -3
- package/dist/index.js +1 -1
- package/dist/preview.cjs +209 -3
- package/dist/preview.js +1 -1
- package/package.json +2 -2
|
@@ -1307,6 +1307,201 @@ function StreamingCursor({ reduced }) {
|
|
|
1307
1307
|
)
|
|
1308
1308
|
] });
|
|
1309
1309
|
}
|
|
1310
|
+
function formatBytes(n) {
|
|
1311
|
+
if (n == null || n <= 0) return null;
|
|
1312
|
+
if (n < 1024) return `${n} B`;
|
|
1313
|
+
if (n < 1024 * 1024) return `${Math.round(n / 1024)} KB`;
|
|
1314
|
+
return `${(n / (1024 * 1024)).toFixed(1)} MB`;
|
|
1315
|
+
}
|
|
1316
|
+
function AttachmentList({
|
|
1317
|
+
attachments,
|
|
1318
|
+
isUser,
|
|
1319
|
+
primaryColor,
|
|
1320
|
+
t
|
|
1321
|
+
}) {
|
|
1322
|
+
const containerStyle = {
|
|
1323
|
+
display: "flex",
|
|
1324
|
+
flexDirection: "column",
|
|
1325
|
+
gap: 6,
|
|
1326
|
+
marginTop: 6,
|
|
1327
|
+
alignItems: isUser ? "flex-end" : "flex-start"
|
|
1328
|
+
};
|
|
1329
|
+
return /* @__PURE__ */ jsx6("div", { style: containerStyle, children: attachments.map((a) => /* @__PURE__ */ jsx6(
|
|
1330
|
+
AttachmentTile,
|
|
1331
|
+
{
|
|
1332
|
+
attachment: a,
|
|
1333
|
+
isUser,
|
|
1334
|
+
primaryColor,
|
|
1335
|
+
t
|
|
1336
|
+
},
|
|
1337
|
+
a.id
|
|
1338
|
+
)) });
|
|
1339
|
+
}
|
|
1340
|
+
function AttachmentTile({
|
|
1341
|
+
attachment,
|
|
1342
|
+
isUser,
|
|
1343
|
+
primaryColor,
|
|
1344
|
+
t
|
|
1345
|
+
}) {
|
|
1346
|
+
const tileBg = isUser ? `${primaryColor}11` : "#f3f4f6";
|
|
1347
|
+
const tileBorder = isUser ? `${primaryColor}33` : "#e5e7eb";
|
|
1348
|
+
if (attachment.kind === "image" && attachment.url) {
|
|
1349
|
+
return /* @__PURE__ */ jsx6(
|
|
1350
|
+
"a",
|
|
1351
|
+
{
|
|
1352
|
+
href: attachment.url,
|
|
1353
|
+
target: "_blank",
|
|
1354
|
+
rel: "noopener noreferrer",
|
|
1355
|
+
style: { display: "inline-block", maxWidth: 220, lineHeight: 0 },
|
|
1356
|
+
"aria-label": attachment.filename ?? t("attachment_image_alt"),
|
|
1357
|
+
children: /* @__PURE__ */ jsx6(
|
|
1358
|
+
"img",
|
|
1359
|
+
{
|
|
1360
|
+
src: attachment.url,
|
|
1361
|
+
alt: attachment.filename ?? t("attachment_image_alt"),
|
|
1362
|
+
style: {
|
|
1363
|
+
display: "block",
|
|
1364
|
+
maxWidth: 220,
|
|
1365
|
+
maxHeight: 220,
|
|
1366
|
+
width: "auto",
|
|
1367
|
+
height: "auto",
|
|
1368
|
+
borderRadius: 12,
|
|
1369
|
+
border: `1px solid ${tileBorder}`,
|
|
1370
|
+
objectFit: "cover"
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
)
|
|
1374
|
+
}
|
|
1375
|
+
);
|
|
1376
|
+
}
|
|
1377
|
+
if (attachment.kind === "location" && attachment.location) {
|
|
1378
|
+
const { latitude, longitude, label } = attachment.location;
|
|
1379
|
+
const href = `https://www.openstreetmap.org/?mlat=${latitude}&mlon=${longitude}#map=15/${latitude}/${longitude}`;
|
|
1380
|
+
return /* @__PURE__ */ jsxs5(
|
|
1381
|
+
"a",
|
|
1382
|
+
{
|
|
1383
|
+
href,
|
|
1384
|
+
target: "_blank",
|
|
1385
|
+
rel: "noopener noreferrer",
|
|
1386
|
+
style: tileLinkStyle(tileBg, tileBorder),
|
|
1387
|
+
children: [
|
|
1388
|
+
/* @__PURE__ */ jsx6(PinIcon, {}),
|
|
1389
|
+
/* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", minWidth: 0 }, children: [
|
|
1390
|
+
/* @__PURE__ */ jsx6("span", { style: tileTitleStyle(), children: label || t("attachment_location") }),
|
|
1391
|
+
/* @__PURE__ */ jsxs5("span", { style: tileSubStyle(), children: [
|
|
1392
|
+
latitude.toFixed(4),
|
|
1393
|
+
", ",
|
|
1394
|
+
longitude.toFixed(4)
|
|
1395
|
+
] })
|
|
1396
|
+
] })
|
|
1397
|
+
]
|
|
1398
|
+
}
|
|
1399
|
+
);
|
|
1400
|
+
}
|
|
1401
|
+
if (!attachment.url) return null;
|
|
1402
|
+
const sub = [attachment.mimeType, formatBytes(attachment.sizeBytes)].filter(Boolean).join(" \xB7 ");
|
|
1403
|
+
return /* @__PURE__ */ jsxs5(
|
|
1404
|
+
"a",
|
|
1405
|
+
{
|
|
1406
|
+
href: attachment.url,
|
|
1407
|
+
target: "_blank",
|
|
1408
|
+
rel: "noopener noreferrer",
|
|
1409
|
+
title: t("attachment_open"),
|
|
1410
|
+
style: tileLinkStyle(tileBg, tileBorder),
|
|
1411
|
+
children: [
|
|
1412
|
+
/* @__PURE__ */ jsx6(FileIcon, { kind: attachment.kind }),
|
|
1413
|
+
/* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", minWidth: 0 }, children: [
|
|
1414
|
+
/* @__PURE__ */ jsx6("span", { style: tileTitleStyle(), children: attachment.filename ?? t("attachment_open") }),
|
|
1415
|
+
sub && /* @__PURE__ */ jsx6("span", { style: tileSubStyle(), children: sub })
|
|
1416
|
+
] })
|
|
1417
|
+
]
|
|
1418
|
+
}
|
|
1419
|
+
);
|
|
1420
|
+
}
|
|
1421
|
+
function tileLinkStyle(bg, border) {
|
|
1422
|
+
return {
|
|
1423
|
+
display: "flex",
|
|
1424
|
+
alignItems: "center",
|
|
1425
|
+
gap: 10,
|
|
1426
|
+
padding: "8px 12px",
|
|
1427
|
+
background: bg,
|
|
1428
|
+
border: `1px solid ${border}`,
|
|
1429
|
+
borderRadius: 12,
|
|
1430
|
+
textDecoration: "none",
|
|
1431
|
+
color: "inherit",
|
|
1432
|
+
maxWidth: 260
|
|
1433
|
+
};
|
|
1434
|
+
}
|
|
1435
|
+
function tileTitleStyle() {
|
|
1436
|
+
return {
|
|
1437
|
+
fontSize: 13,
|
|
1438
|
+
fontWeight: 500,
|
|
1439
|
+
color: "#1f2937",
|
|
1440
|
+
overflow: "hidden",
|
|
1441
|
+
textOverflow: "ellipsis",
|
|
1442
|
+
whiteSpace: "nowrap",
|
|
1443
|
+
maxWidth: 200
|
|
1444
|
+
};
|
|
1445
|
+
}
|
|
1446
|
+
function tileSubStyle() {
|
|
1447
|
+
return {
|
|
1448
|
+
fontSize: 11,
|
|
1449
|
+
color: "#6b7280",
|
|
1450
|
+
overflow: "hidden",
|
|
1451
|
+
textOverflow: "ellipsis",
|
|
1452
|
+
whiteSpace: "nowrap",
|
|
1453
|
+
maxWidth: 200
|
|
1454
|
+
};
|
|
1455
|
+
}
|
|
1456
|
+
function FileIcon({ kind }) {
|
|
1457
|
+
return /* @__PURE__ */ jsx6(
|
|
1458
|
+
"svg",
|
|
1459
|
+
{
|
|
1460
|
+
width: "20",
|
|
1461
|
+
height: "20",
|
|
1462
|
+
viewBox: "0 0 24 24",
|
|
1463
|
+
fill: "none",
|
|
1464
|
+
stroke: "#4b5563",
|
|
1465
|
+
strokeWidth: "2",
|
|
1466
|
+
strokeLinecap: "round",
|
|
1467
|
+
strokeLinejoin: "round",
|
|
1468
|
+
"aria-hidden": "true",
|
|
1469
|
+
style: { flexShrink: 0 },
|
|
1470
|
+
children: kind === "audio" ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1471
|
+
/* @__PURE__ */ jsx6("path", { d: "M9 18V5l12-2v13" }),
|
|
1472
|
+
/* @__PURE__ */ jsx6("circle", { cx: "6", cy: "18", r: "3" }),
|
|
1473
|
+
/* @__PURE__ */ jsx6("circle", { cx: "18", cy: "16", r: "3" })
|
|
1474
|
+
] }) : kind === "video" ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1475
|
+
/* @__PURE__ */ jsx6("rect", { x: "2", y: "6", width: "14", height: "12", rx: "2" }),
|
|
1476
|
+
/* @__PURE__ */ jsx6("path", { d: "m22 8-6 4 6 4z" })
|
|
1477
|
+
] }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1478
|
+
/* @__PURE__ */ jsx6("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
|
|
1479
|
+
/* @__PURE__ */ jsx6("polyline", { points: "14 2 14 8 20 8" })
|
|
1480
|
+
] })
|
|
1481
|
+
}
|
|
1482
|
+
);
|
|
1483
|
+
}
|
|
1484
|
+
function PinIcon() {
|
|
1485
|
+
return /* @__PURE__ */ jsxs5(
|
|
1486
|
+
"svg",
|
|
1487
|
+
{
|
|
1488
|
+
width: "20",
|
|
1489
|
+
height: "20",
|
|
1490
|
+
viewBox: "0 0 24 24",
|
|
1491
|
+
fill: "none",
|
|
1492
|
+
stroke: "#4b5563",
|
|
1493
|
+
strokeWidth: "2",
|
|
1494
|
+
strokeLinecap: "round",
|
|
1495
|
+
strokeLinejoin: "round",
|
|
1496
|
+
"aria-hidden": "true",
|
|
1497
|
+
style: { flexShrink: 0 },
|
|
1498
|
+
children: [
|
|
1499
|
+
/* @__PURE__ */ jsx6("path", { d: "M20 10c0 7-8 13-8 13s-8-6-8-13a8 8 0 0 1 16 0Z" }),
|
|
1500
|
+
/* @__PURE__ */ jsx6("circle", { cx: "12", cy: "10", r: "3" })
|
|
1501
|
+
]
|
|
1502
|
+
}
|
|
1503
|
+
);
|
|
1504
|
+
}
|
|
1310
1505
|
function Message({
|
|
1311
1506
|
message,
|
|
1312
1507
|
config,
|
|
@@ -1338,8 +1533,10 @@ function Message({
|
|
|
1338
1533
|
}
|
|
1339
1534
|
};
|
|
1340
1535
|
const linkColor = isUser ? "#ffffff" : config.primaryColor;
|
|
1536
|
+
const hasContent = message.content.trim().length > 0;
|
|
1537
|
+
const hasAttachments = !!message.attachments?.length;
|
|
1341
1538
|
return /* @__PURE__ */ jsxs5(AnimatedMessage, { isUser, animate, reduced, children: [
|
|
1342
|
-
/* @__PURE__ */ jsx6(
|
|
1539
|
+
hasContent && /* @__PURE__ */ jsx6(
|
|
1343
1540
|
"div",
|
|
1344
1541
|
{
|
|
1345
1542
|
style: bubbleStyle,
|
|
@@ -1353,6 +1550,15 @@ function Message({
|
|
|
1353
1550
|
] })
|
|
1354
1551
|
}
|
|
1355
1552
|
),
|
|
1553
|
+
hasAttachments && /* @__PURE__ */ jsx6(
|
|
1554
|
+
AttachmentList,
|
|
1555
|
+
{
|
|
1556
|
+
attachments: message.attachments,
|
|
1557
|
+
isUser,
|
|
1558
|
+
primaryColor: config.primaryColor,
|
|
1559
|
+
t
|
|
1560
|
+
}
|
|
1561
|
+
),
|
|
1356
1562
|
isUser && message.status && /* @__PURE__ */ jsx6(MessageStatusPill, { status: message.status, t }),
|
|
1357
1563
|
!isUser && message.blocks?.map((block, i) => /* @__PURE__ */ jsx6(
|
|
1358
1564
|
BlockRenderer,
|
|
@@ -2167,7 +2373,7 @@ function Thumbnail({
|
|
|
2167
2373
|
fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"
|
|
2168
2374
|
};
|
|
2169
2375
|
const displayName = filename ?? (isImage ? "" : "Document");
|
|
2170
|
-
const sizeLabel =
|
|
2376
|
+
const sizeLabel = formatBytes2(blob.size);
|
|
2171
2377
|
return /* @__PURE__ */ jsxs6("div", { style: wrap, children: [
|
|
2172
2378
|
isImage ? /* @__PURE__ */ jsx8("img", { src: previewUrl, alt: "", style: img }) : /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
2173
2379
|
/* @__PURE__ */ jsx8(DocIcon, {}),
|
|
@@ -2271,7 +2477,7 @@ function DocIcon() {
|
|
|
2271
2477
|
}
|
|
2272
2478
|
);
|
|
2273
2479
|
}
|
|
2274
|
-
function
|
|
2480
|
+
function formatBytes2(bytes) {
|
|
2275
2481
|
if (!Number.isFinite(bytes) || bytes <= 0) return "";
|
|
2276
2482
|
if (bytes < 1024) return `${bytes} B`;
|
|
2277
2483
|
if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
|
package/dist/index.cjs
CHANGED
|
@@ -1326,6 +1326,201 @@ function StreamingCursor({ reduced }) {
|
|
|
1326
1326
|
)
|
|
1327
1327
|
] });
|
|
1328
1328
|
}
|
|
1329
|
+
function formatBytes(n) {
|
|
1330
|
+
if (n == null || n <= 0) return null;
|
|
1331
|
+
if (n < 1024) return `${n} B`;
|
|
1332
|
+
if (n < 1024 * 1024) return `${Math.round(n / 1024)} KB`;
|
|
1333
|
+
return `${(n / (1024 * 1024)).toFixed(1)} MB`;
|
|
1334
|
+
}
|
|
1335
|
+
function AttachmentList({
|
|
1336
|
+
attachments,
|
|
1337
|
+
isUser,
|
|
1338
|
+
primaryColor,
|
|
1339
|
+
t
|
|
1340
|
+
}) {
|
|
1341
|
+
const containerStyle = {
|
|
1342
|
+
display: "flex",
|
|
1343
|
+
flexDirection: "column",
|
|
1344
|
+
gap: 6,
|
|
1345
|
+
marginTop: 6,
|
|
1346
|
+
alignItems: isUser ? "flex-end" : "flex-start"
|
|
1347
|
+
};
|
|
1348
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: containerStyle, children: attachments.map((a) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1349
|
+
AttachmentTile,
|
|
1350
|
+
{
|
|
1351
|
+
attachment: a,
|
|
1352
|
+
isUser,
|
|
1353
|
+
primaryColor,
|
|
1354
|
+
t
|
|
1355
|
+
},
|
|
1356
|
+
a.id
|
|
1357
|
+
)) });
|
|
1358
|
+
}
|
|
1359
|
+
function AttachmentTile({
|
|
1360
|
+
attachment,
|
|
1361
|
+
isUser,
|
|
1362
|
+
primaryColor,
|
|
1363
|
+
t
|
|
1364
|
+
}) {
|
|
1365
|
+
const tileBg = isUser ? `${primaryColor}11` : "#f3f4f6";
|
|
1366
|
+
const tileBorder = isUser ? `${primaryColor}33` : "#e5e7eb";
|
|
1367
|
+
if (attachment.kind === "image" && attachment.url) {
|
|
1368
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1369
|
+
"a",
|
|
1370
|
+
{
|
|
1371
|
+
href: attachment.url,
|
|
1372
|
+
target: "_blank",
|
|
1373
|
+
rel: "noopener noreferrer",
|
|
1374
|
+
style: { display: "inline-block", maxWidth: 220, lineHeight: 0 },
|
|
1375
|
+
"aria-label": attachment.filename ?? t("attachment_image_alt"),
|
|
1376
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1377
|
+
"img",
|
|
1378
|
+
{
|
|
1379
|
+
src: attachment.url,
|
|
1380
|
+
alt: attachment.filename ?? t("attachment_image_alt"),
|
|
1381
|
+
style: {
|
|
1382
|
+
display: "block",
|
|
1383
|
+
maxWidth: 220,
|
|
1384
|
+
maxHeight: 220,
|
|
1385
|
+
width: "auto",
|
|
1386
|
+
height: "auto",
|
|
1387
|
+
borderRadius: 12,
|
|
1388
|
+
border: `1px solid ${tileBorder}`,
|
|
1389
|
+
objectFit: "cover"
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
)
|
|
1393
|
+
}
|
|
1394
|
+
);
|
|
1395
|
+
}
|
|
1396
|
+
if (attachment.kind === "location" && attachment.location) {
|
|
1397
|
+
const { latitude, longitude, label } = attachment.location;
|
|
1398
|
+
const href = `https://www.openstreetmap.org/?mlat=${latitude}&mlon=${longitude}#map=15/${latitude}/${longitude}`;
|
|
1399
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1400
|
+
"a",
|
|
1401
|
+
{
|
|
1402
|
+
href,
|
|
1403
|
+
target: "_blank",
|
|
1404
|
+
rel: "noopener noreferrer",
|
|
1405
|
+
style: tileLinkStyle(tileBg, tileBorder),
|
|
1406
|
+
children: [
|
|
1407
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PinIcon, {}),
|
|
1408
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", flexDirection: "column", minWidth: 0 }, children: [
|
|
1409
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: tileTitleStyle(), children: label || t("attachment_location") }),
|
|
1410
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { style: tileSubStyle(), children: [
|
|
1411
|
+
latitude.toFixed(4),
|
|
1412
|
+
", ",
|
|
1413
|
+
longitude.toFixed(4)
|
|
1414
|
+
] })
|
|
1415
|
+
] })
|
|
1416
|
+
]
|
|
1417
|
+
}
|
|
1418
|
+
);
|
|
1419
|
+
}
|
|
1420
|
+
if (!attachment.url) return null;
|
|
1421
|
+
const sub = [attachment.mimeType, formatBytes(attachment.sizeBytes)].filter(Boolean).join(" \xB7 ");
|
|
1422
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1423
|
+
"a",
|
|
1424
|
+
{
|
|
1425
|
+
href: attachment.url,
|
|
1426
|
+
target: "_blank",
|
|
1427
|
+
rel: "noopener noreferrer",
|
|
1428
|
+
title: t("attachment_open"),
|
|
1429
|
+
style: tileLinkStyle(tileBg, tileBorder),
|
|
1430
|
+
children: [
|
|
1431
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FileIcon, { kind: attachment.kind }),
|
|
1432
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", flexDirection: "column", minWidth: 0 }, children: [
|
|
1433
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: tileTitleStyle(), children: attachment.filename ?? t("attachment_open") }),
|
|
1434
|
+
sub && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: tileSubStyle(), children: sub })
|
|
1435
|
+
] })
|
|
1436
|
+
]
|
|
1437
|
+
}
|
|
1438
|
+
);
|
|
1439
|
+
}
|
|
1440
|
+
function tileLinkStyle(bg, border) {
|
|
1441
|
+
return {
|
|
1442
|
+
display: "flex",
|
|
1443
|
+
alignItems: "center",
|
|
1444
|
+
gap: 10,
|
|
1445
|
+
padding: "8px 12px",
|
|
1446
|
+
background: bg,
|
|
1447
|
+
border: `1px solid ${border}`,
|
|
1448
|
+
borderRadius: 12,
|
|
1449
|
+
textDecoration: "none",
|
|
1450
|
+
color: "inherit",
|
|
1451
|
+
maxWidth: 260
|
|
1452
|
+
};
|
|
1453
|
+
}
|
|
1454
|
+
function tileTitleStyle() {
|
|
1455
|
+
return {
|
|
1456
|
+
fontSize: 13,
|
|
1457
|
+
fontWeight: 500,
|
|
1458
|
+
color: "#1f2937",
|
|
1459
|
+
overflow: "hidden",
|
|
1460
|
+
textOverflow: "ellipsis",
|
|
1461
|
+
whiteSpace: "nowrap",
|
|
1462
|
+
maxWidth: 200
|
|
1463
|
+
};
|
|
1464
|
+
}
|
|
1465
|
+
function tileSubStyle() {
|
|
1466
|
+
return {
|
|
1467
|
+
fontSize: 11,
|
|
1468
|
+
color: "#6b7280",
|
|
1469
|
+
overflow: "hidden",
|
|
1470
|
+
textOverflow: "ellipsis",
|
|
1471
|
+
whiteSpace: "nowrap",
|
|
1472
|
+
maxWidth: 200
|
|
1473
|
+
};
|
|
1474
|
+
}
|
|
1475
|
+
function FileIcon({ kind }) {
|
|
1476
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1477
|
+
"svg",
|
|
1478
|
+
{
|
|
1479
|
+
width: "20",
|
|
1480
|
+
height: "20",
|
|
1481
|
+
viewBox: "0 0 24 24",
|
|
1482
|
+
fill: "none",
|
|
1483
|
+
stroke: "#4b5563",
|
|
1484
|
+
strokeWidth: "2",
|
|
1485
|
+
strokeLinecap: "round",
|
|
1486
|
+
strokeLinejoin: "round",
|
|
1487
|
+
"aria-hidden": "true",
|
|
1488
|
+
style: { flexShrink: 0 },
|
|
1489
|
+
children: kind === "audio" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1490
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M9 18V5l12-2v13" }),
|
|
1491
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "6", cy: "18", r: "3" }),
|
|
1492
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "18", cy: "16", r: "3" })
|
|
1493
|
+
] }) : kind === "video" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1494
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "2", y: "6", width: "14", height: "12", rx: "2" }),
|
|
1495
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "m22 8-6 4 6 4z" })
|
|
1496
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1497
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
|
|
1498
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("polyline", { points: "14 2 14 8 20 8" })
|
|
1499
|
+
] })
|
|
1500
|
+
}
|
|
1501
|
+
);
|
|
1502
|
+
}
|
|
1503
|
+
function PinIcon() {
|
|
1504
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1505
|
+
"svg",
|
|
1506
|
+
{
|
|
1507
|
+
width: "20",
|
|
1508
|
+
height: "20",
|
|
1509
|
+
viewBox: "0 0 24 24",
|
|
1510
|
+
fill: "none",
|
|
1511
|
+
stroke: "#4b5563",
|
|
1512
|
+
strokeWidth: "2",
|
|
1513
|
+
strokeLinecap: "round",
|
|
1514
|
+
strokeLinejoin: "round",
|
|
1515
|
+
"aria-hidden": "true",
|
|
1516
|
+
style: { flexShrink: 0 },
|
|
1517
|
+
children: [
|
|
1518
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M20 10c0 7-8 13-8 13s-8-6-8-13a8 8 0 0 1 16 0Z" }),
|
|
1519
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "12", cy: "10", r: "3" })
|
|
1520
|
+
]
|
|
1521
|
+
}
|
|
1522
|
+
);
|
|
1523
|
+
}
|
|
1329
1524
|
function Message({
|
|
1330
1525
|
message,
|
|
1331
1526
|
config,
|
|
@@ -1357,8 +1552,10 @@ function Message({
|
|
|
1357
1552
|
}
|
|
1358
1553
|
};
|
|
1359
1554
|
const linkColor = isUser ? "#ffffff" : config.primaryColor;
|
|
1555
|
+
const hasContent = message.content.trim().length > 0;
|
|
1556
|
+
const hasAttachments = !!message.attachments?.length;
|
|
1360
1557
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(AnimatedMessage, { isUser, animate, reduced, children: [
|
|
1361
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1558
|
+
hasContent && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1362
1559
|
"div",
|
|
1363
1560
|
{
|
|
1364
1561
|
style: bubbleStyle,
|
|
@@ -1372,6 +1569,15 @@ function Message({
|
|
|
1372
1569
|
] })
|
|
1373
1570
|
}
|
|
1374
1571
|
),
|
|
1572
|
+
hasAttachments && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1573
|
+
AttachmentList,
|
|
1574
|
+
{
|
|
1575
|
+
attachments: message.attachments,
|
|
1576
|
+
isUser,
|
|
1577
|
+
primaryColor: config.primaryColor,
|
|
1578
|
+
t
|
|
1579
|
+
}
|
|
1580
|
+
),
|
|
1375
1581
|
isUser && message.status && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MessageStatusPill, { status: message.status, t }),
|
|
1376
1582
|
!isUser && message.blocks?.map((block, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1377
1583
|
BlockRenderer,
|
|
@@ -2177,7 +2383,7 @@ function Thumbnail({
|
|
|
2177
2383
|
fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"
|
|
2178
2384
|
};
|
|
2179
2385
|
const displayName = filename ?? (isImage ? "" : "Document");
|
|
2180
|
-
const sizeLabel =
|
|
2386
|
+
const sizeLabel = formatBytes2(blob.size);
|
|
2181
2387
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: wrap, children: [
|
|
2182
2388
|
isImage ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("img", { src: previewUrl, alt: "", style: img }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
2183
2389
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(DocIcon, {}),
|
|
@@ -2281,7 +2487,7 @@ function DocIcon() {
|
|
|
2281
2487
|
}
|
|
2282
2488
|
);
|
|
2283
2489
|
}
|
|
2284
|
-
function
|
|
2490
|
+
function formatBytes2(bytes) {
|
|
2285
2491
|
if (!Number.isFinite(bytes) || bytes <= 0) return "";
|
|
2286
2492
|
if (bytes < 1024) return `${bytes} B`;
|
|
2287
2493
|
if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
|
package/dist/index.js
CHANGED
package/dist/preview.cjs
CHANGED
|
@@ -1322,6 +1322,201 @@ function StreamingCursor({ reduced }) {
|
|
|
1322
1322
|
)
|
|
1323
1323
|
] });
|
|
1324
1324
|
}
|
|
1325
|
+
function formatBytes(n) {
|
|
1326
|
+
if (n == null || n <= 0) return null;
|
|
1327
|
+
if (n < 1024) return `${n} B`;
|
|
1328
|
+
if (n < 1024 * 1024) return `${Math.round(n / 1024)} KB`;
|
|
1329
|
+
return `${(n / (1024 * 1024)).toFixed(1)} MB`;
|
|
1330
|
+
}
|
|
1331
|
+
function AttachmentList({
|
|
1332
|
+
attachments,
|
|
1333
|
+
isUser,
|
|
1334
|
+
primaryColor,
|
|
1335
|
+
t
|
|
1336
|
+
}) {
|
|
1337
|
+
const containerStyle = {
|
|
1338
|
+
display: "flex",
|
|
1339
|
+
flexDirection: "column",
|
|
1340
|
+
gap: 6,
|
|
1341
|
+
marginTop: 6,
|
|
1342
|
+
alignItems: isUser ? "flex-end" : "flex-start"
|
|
1343
|
+
};
|
|
1344
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: containerStyle, children: attachments.map((a) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1345
|
+
AttachmentTile,
|
|
1346
|
+
{
|
|
1347
|
+
attachment: a,
|
|
1348
|
+
isUser,
|
|
1349
|
+
primaryColor,
|
|
1350
|
+
t
|
|
1351
|
+
},
|
|
1352
|
+
a.id
|
|
1353
|
+
)) });
|
|
1354
|
+
}
|
|
1355
|
+
function AttachmentTile({
|
|
1356
|
+
attachment,
|
|
1357
|
+
isUser,
|
|
1358
|
+
primaryColor,
|
|
1359
|
+
t
|
|
1360
|
+
}) {
|
|
1361
|
+
const tileBg = isUser ? `${primaryColor}11` : "#f3f4f6";
|
|
1362
|
+
const tileBorder = isUser ? `${primaryColor}33` : "#e5e7eb";
|
|
1363
|
+
if (attachment.kind === "image" && attachment.url) {
|
|
1364
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1365
|
+
"a",
|
|
1366
|
+
{
|
|
1367
|
+
href: attachment.url,
|
|
1368
|
+
target: "_blank",
|
|
1369
|
+
rel: "noopener noreferrer",
|
|
1370
|
+
style: { display: "inline-block", maxWidth: 220, lineHeight: 0 },
|
|
1371
|
+
"aria-label": attachment.filename ?? t("attachment_image_alt"),
|
|
1372
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1373
|
+
"img",
|
|
1374
|
+
{
|
|
1375
|
+
src: attachment.url,
|
|
1376
|
+
alt: attachment.filename ?? t("attachment_image_alt"),
|
|
1377
|
+
style: {
|
|
1378
|
+
display: "block",
|
|
1379
|
+
maxWidth: 220,
|
|
1380
|
+
maxHeight: 220,
|
|
1381
|
+
width: "auto",
|
|
1382
|
+
height: "auto",
|
|
1383
|
+
borderRadius: 12,
|
|
1384
|
+
border: `1px solid ${tileBorder}`,
|
|
1385
|
+
objectFit: "cover"
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
)
|
|
1389
|
+
}
|
|
1390
|
+
);
|
|
1391
|
+
}
|
|
1392
|
+
if (attachment.kind === "location" && attachment.location) {
|
|
1393
|
+
const { latitude, longitude, label } = attachment.location;
|
|
1394
|
+
const href = `https://www.openstreetmap.org/?mlat=${latitude}&mlon=${longitude}#map=15/${latitude}/${longitude}`;
|
|
1395
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1396
|
+
"a",
|
|
1397
|
+
{
|
|
1398
|
+
href,
|
|
1399
|
+
target: "_blank",
|
|
1400
|
+
rel: "noopener noreferrer",
|
|
1401
|
+
style: tileLinkStyle(tileBg, tileBorder),
|
|
1402
|
+
children: [
|
|
1403
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PinIcon, {}),
|
|
1404
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", flexDirection: "column", minWidth: 0 }, children: [
|
|
1405
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: tileTitleStyle(), children: label || t("attachment_location") }),
|
|
1406
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { style: tileSubStyle(), children: [
|
|
1407
|
+
latitude.toFixed(4),
|
|
1408
|
+
", ",
|
|
1409
|
+
longitude.toFixed(4)
|
|
1410
|
+
] })
|
|
1411
|
+
] })
|
|
1412
|
+
]
|
|
1413
|
+
}
|
|
1414
|
+
);
|
|
1415
|
+
}
|
|
1416
|
+
if (!attachment.url) return null;
|
|
1417
|
+
const sub = [attachment.mimeType, formatBytes(attachment.sizeBytes)].filter(Boolean).join(" \xB7 ");
|
|
1418
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1419
|
+
"a",
|
|
1420
|
+
{
|
|
1421
|
+
href: attachment.url,
|
|
1422
|
+
target: "_blank",
|
|
1423
|
+
rel: "noopener noreferrer",
|
|
1424
|
+
title: t("attachment_open"),
|
|
1425
|
+
style: tileLinkStyle(tileBg, tileBorder),
|
|
1426
|
+
children: [
|
|
1427
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FileIcon, { kind: attachment.kind }),
|
|
1428
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", flexDirection: "column", minWidth: 0 }, children: [
|
|
1429
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: tileTitleStyle(), children: attachment.filename ?? t("attachment_open") }),
|
|
1430
|
+
sub && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: tileSubStyle(), children: sub })
|
|
1431
|
+
] })
|
|
1432
|
+
]
|
|
1433
|
+
}
|
|
1434
|
+
);
|
|
1435
|
+
}
|
|
1436
|
+
function tileLinkStyle(bg, border) {
|
|
1437
|
+
return {
|
|
1438
|
+
display: "flex",
|
|
1439
|
+
alignItems: "center",
|
|
1440
|
+
gap: 10,
|
|
1441
|
+
padding: "8px 12px",
|
|
1442
|
+
background: bg,
|
|
1443
|
+
border: `1px solid ${border}`,
|
|
1444
|
+
borderRadius: 12,
|
|
1445
|
+
textDecoration: "none",
|
|
1446
|
+
color: "inherit",
|
|
1447
|
+
maxWidth: 260
|
|
1448
|
+
};
|
|
1449
|
+
}
|
|
1450
|
+
function tileTitleStyle() {
|
|
1451
|
+
return {
|
|
1452
|
+
fontSize: 13,
|
|
1453
|
+
fontWeight: 500,
|
|
1454
|
+
color: "#1f2937",
|
|
1455
|
+
overflow: "hidden",
|
|
1456
|
+
textOverflow: "ellipsis",
|
|
1457
|
+
whiteSpace: "nowrap",
|
|
1458
|
+
maxWidth: 200
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1461
|
+
function tileSubStyle() {
|
|
1462
|
+
return {
|
|
1463
|
+
fontSize: 11,
|
|
1464
|
+
color: "#6b7280",
|
|
1465
|
+
overflow: "hidden",
|
|
1466
|
+
textOverflow: "ellipsis",
|
|
1467
|
+
whiteSpace: "nowrap",
|
|
1468
|
+
maxWidth: 200
|
|
1469
|
+
};
|
|
1470
|
+
}
|
|
1471
|
+
function FileIcon({ kind }) {
|
|
1472
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1473
|
+
"svg",
|
|
1474
|
+
{
|
|
1475
|
+
width: "20",
|
|
1476
|
+
height: "20",
|
|
1477
|
+
viewBox: "0 0 24 24",
|
|
1478
|
+
fill: "none",
|
|
1479
|
+
stroke: "#4b5563",
|
|
1480
|
+
strokeWidth: "2",
|
|
1481
|
+
strokeLinecap: "round",
|
|
1482
|
+
strokeLinejoin: "round",
|
|
1483
|
+
"aria-hidden": "true",
|
|
1484
|
+
style: { flexShrink: 0 },
|
|
1485
|
+
children: kind === "audio" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1486
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M9 18V5l12-2v13" }),
|
|
1487
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "6", cy: "18", r: "3" }),
|
|
1488
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "18", cy: "16", r: "3" })
|
|
1489
|
+
] }) : kind === "video" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1490
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "2", y: "6", width: "14", height: "12", rx: "2" }),
|
|
1491
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "m22 8-6 4 6 4z" })
|
|
1492
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1493
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
|
|
1494
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("polyline", { points: "14 2 14 8 20 8" })
|
|
1495
|
+
] })
|
|
1496
|
+
}
|
|
1497
|
+
);
|
|
1498
|
+
}
|
|
1499
|
+
function PinIcon() {
|
|
1500
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1501
|
+
"svg",
|
|
1502
|
+
{
|
|
1503
|
+
width: "20",
|
|
1504
|
+
height: "20",
|
|
1505
|
+
viewBox: "0 0 24 24",
|
|
1506
|
+
fill: "none",
|
|
1507
|
+
stroke: "#4b5563",
|
|
1508
|
+
strokeWidth: "2",
|
|
1509
|
+
strokeLinecap: "round",
|
|
1510
|
+
strokeLinejoin: "round",
|
|
1511
|
+
"aria-hidden": "true",
|
|
1512
|
+
style: { flexShrink: 0 },
|
|
1513
|
+
children: [
|
|
1514
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M20 10c0 7-8 13-8 13s-8-6-8-13a8 8 0 0 1 16 0Z" }),
|
|
1515
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "12", cy: "10", r: "3" })
|
|
1516
|
+
]
|
|
1517
|
+
}
|
|
1518
|
+
);
|
|
1519
|
+
}
|
|
1325
1520
|
function Message({
|
|
1326
1521
|
message,
|
|
1327
1522
|
config,
|
|
@@ -1353,8 +1548,10 @@ function Message({
|
|
|
1353
1548
|
}
|
|
1354
1549
|
};
|
|
1355
1550
|
const linkColor = isUser ? "#ffffff" : config.primaryColor;
|
|
1551
|
+
const hasContent = message.content.trim().length > 0;
|
|
1552
|
+
const hasAttachments = !!message.attachments?.length;
|
|
1356
1553
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(AnimatedMessage, { isUser, animate, reduced, children: [
|
|
1357
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1554
|
+
hasContent && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1358
1555
|
"div",
|
|
1359
1556
|
{
|
|
1360
1557
|
style: bubbleStyle,
|
|
@@ -1368,6 +1565,15 @@ function Message({
|
|
|
1368
1565
|
] })
|
|
1369
1566
|
}
|
|
1370
1567
|
),
|
|
1568
|
+
hasAttachments && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1569
|
+
AttachmentList,
|
|
1570
|
+
{
|
|
1571
|
+
attachments: message.attachments,
|
|
1572
|
+
isUser,
|
|
1573
|
+
primaryColor: config.primaryColor,
|
|
1574
|
+
t
|
|
1575
|
+
}
|
|
1576
|
+
),
|
|
1371
1577
|
isUser && message.status && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MessageStatusPill, { status: message.status, t }),
|
|
1372
1578
|
!isUser && message.blocks?.map((block, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1373
1579
|
BlockRenderer,
|
|
@@ -2173,7 +2379,7 @@ function Thumbnail({
|
|
|
2173
2379
|
fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"
|
|
2174
2380
|
};
|
|
2175
2381
|
const displayName = filename ?? (isImage ? "" : "Document");
|
|
2176
|
-
const sizeLabel =
|
|
2382
|
+
const sizeLabel = formatBytes2(blob.size);
|
|
2177
2383
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: wrap, children: [
|
|
2178
2384
|
isImage ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("img", { src: previewUrl, alt: "", style: img }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
2179
2385
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(DocIcon, {}),
|
|
@@ -2277,7 +2483,7 @@ function DocIcon() {
|
|
|
2277
2483
|
}
|
|
2278
2484
|
);
|
|
2279
2485
|
}
|
|
2280
|
-
function
|
|
2486
|
+
function formatBytes2(bytes) {
|
|
2281
2487
|
if (!Number.isFinite(bytes) || bytes <= 0) return "";
|
|
2282
2488
|
if (bytes < 1024) return `${bytes} B`;
|
|
2283
2489
|
if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
|
package/dist/preview.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@customerhero/react",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "React components for embedding the CustomerHero chat widget.",
|
|
6
6
|
"keywords": [
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"react": ">=18"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
|
-
"@customerhero/js": "^2.
|
|
71
|
+
"@customerhero/js": "^2.4.1",
|
|
72
72
|
"@testing-library/react": "^16.1.0",
|
|
73
73
|
"@types/react": "^19.0.0",
|
|
74
74
|
"@types/react-dom": "^19.0.0",
|