@cimplify/sdk 0.97.0 → 0.98.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.
- package/dist/{chunk-RRBY35TJ.mjs → chunk-4G5UWFC3.mjs} +7 -1
- package/dist/{chunk-HKN3YG76.js → chunk-QPRI2NII.js} +7 -0
- package/dist/index.js +22 -25
- package/dist/index.mjs +2 -8
- package/dist/react.d.mts +382 -261
- package/dist/react.d.ts +382 -261
- package/dist/react.js +696 -211
- package/dist/react.mjs +627 -161
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/registry/chat-widget.json +1 -1
package/dist/react.mjs
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { DURATION_UNIT, getVariantDisplayName, INPUT_FIELD_TYPE, isMultiDayService, serviceBillingMultiplier, PRODUCT_TYPE, BOUNDARY_KIND, resolveGallery, RENDER_HINT, DEFAULT_CDN_BASE_URL } from './chunk-
|
|
3
|
-
export { getVariantDisplayName } from './chunk-
|
|
4
|
-
import {
|
|
2
|
+
import { DURATION_UNIT, getVariantDisplayName, INPUT_FIELD_TYPE, isMultiDayService, serviceBillingMultiplier, PRODUCT_TYPE, BOUNDARY_KIND, resolveGallery, chatMessageCards, RENDER_HINT, DEFAULT_CDN_BASE_URL } from './chunk-4G5UWFC3.mjs';
|
|
3
|
+
export { getVariantDisplayName } from './chunk-4G5UWFC3.mjs';
|
|
4
|
+
import { splitGenUIContent, messagePreview } from './chunk-U4MW6PYU.mjs';
|
|
5
5
|
export { messagePreview, splitGenUIContent } from './chunk-U4MW6PYU.mjs';
|
|
6
6
|
import { SESSION_CLAIMED, SESSION_CLEARED, createCimplifyClient, MUTATION_ERROR } from './chunk-XMDLF5Y6.mjs';
|
|
7
7
|
import { generateIdempotencyKey, ELEMENT_TYPES, EVENT_TYPES, startSignIn } from './chunk-VUSHG3HA.mjs';
|
|
8
8
|
import { parsePrice, formatMoney, formatPrice, getProductCurrency, getUnitPriceAtQuantity, isOnSale, getDiscountPercentage, getBasePrice, getPriceRange, formatPriceRange } from './chunk-KFLGQGMC.mjs';
|
|
9
9
|
import { isSupportedCurrency, CimplifyError } from './chunk-K5EN2W2Q.mjs';
|
|
10
10
|
import './chunk-3G6RQLXK.mjs';
|
|
11
|
-
import React14, { createContext, lazy, memo, Suspense,
|
|
12
|
-
import { jsx,
|
|
11
|
+
import React14, { createContext, lazy, memo, Suspense, useMemo, useContext, useRef, useCallback, useState, useEffect, useId, useSyncExternalStore } from 'react';
|
|
12
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
13
13
|
import * as ReactDOM from 'react-dom';
|
|
14
14
|
import { clsx } from 'clsx';
|
|
15
15
|
import { twMerge } from 'tailwind-merge';
|
|
@@ -17146,12 +17146,582 @@ var ChatMarkdown = memo(function ChatMarkdown2({
|
|
|
17146
17146
|
}
|
|
17147
17147
|
return /* @__PURE__ */ jsx(SettledMarkdown, { text, className });
|
|
17148
17148
|
});
|
|
17149
|
-
|
|
17150
|
-
|
|
17151
|
-
|
|
17149
|
+
|
|
17150
|
+
// src/react/chat-kit/motion.ts
|
|
17151
|
+
function prefersReducedMotion() {
|
|
17152
|
+
return typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
17153
|
+
}
|
|
17154
|
+
function scrollBehavior() {
|
|
17155
|
+
return prefersReducedMotion() ? "auto" : "smooth";
|
|
17156
|
+
}
|
|
17157
|
+
function QuoteBlock({
|
|
17158
|
+
quote,
|
|
17159
|
+
inCustomerBubble,
|
|
17160
|
+
businessName,
|
|
17161
|
+
onMissing
|
|
17162
|
+
}) {
|
|
17163
|
+
const quotedIsCustomer = quote.sender_type === "customer";
|
|
17164
|
+
const jumpToOriginal = async () => {
|
|
17165
|
+
let original = document.getElementById(`chat-msg-${quote.id}`);
|
|
17166
|
+
if (!original && onMissing && await onMissing()) {
|
|
17167
|
+
original = document.getElementById(`chat-msg-${quote.id}`);
|
|
17168
|
+
}
|
|
17169
|
+
if (!original) return;
|
|
17170
|
+
original.scrollIntoView({ behavior: scrollBehavior(), block: "center" });
|
|
17171
|
+
original.classList.remove("animate-quote-flash");
|
|
17172
|
+
void original.offsetWidth;
|
|
17173
|
+
original.classList.add("animate-quote-flash");
|
|
17174
|
+
};
|
|
17175
|
+
return /* @__PURE__ */ jsxs(
|
|
17176
|
+
"button",
|
|
17177
|
+
{
|
|
17178
|
+
type: "button",
|
|
17179
|
+
onClick: () => void jumpToOriginal(),
|
|
17180
|
+
className: cn(
|
|
17181
|
+
"flex w-full gap-2 rounded-[10px] px-2.5 py-1.5 text-left",
|
|
17182
|
+
inCustomerBubble ? "bg-primary-foreground/15" : "bg-background/70"
|
|
17183
|
+
),
|
|
17184
|
+
children: [
|
|
17185
|
+
/* @__PURE__ */ jsx(
|
|
17186
|
+
"span",
|
|
17187
|
+
{
|
|
17188
|
+
className: cn(
|
|
17189
|
+
"w-[3px] shrink-0 self-stretch rounded-full",
|
|
17190
|
+
inCustomerBubble ? "bg-primary-foreground/50" : quotedIsCustomer ? "bg-primary" : "bg-muted-foreground/50"
|
|
17191
|
+
)
|
|
17192
|
+
}
|
|
17193
|
+
),
|
|
17194
|
+
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col", children: [
|
|
17195
|
+
/* @__PURE__ */ jsx(
|
|
17196
|
+
"span",
|
|
17197
|
+
{
|
|
17198
|
+
className: cn(
|
|
17199
|
+
"text-[11px] leading-4 font-semibold",
|
|
17200
|
+
inCustomerBubble ? "text-primary-foreground" : "text-foreground"
|
|
17201
|
+
),
|
|
17202
|
+
children: quotedIsCustomer ? "You" : businessName
|
|
17203
|
+
}
|
|
17204
|
+
),
|
|
17205
|
+
/* @__PURE__ */ jsx(
|
|
17206
|
+
"span",
|
|
17207
|
+
{
|
|
17208
|
+
className: cn(
|
|
17209
|
+
"truncate text-xs leading-4",
|
|
17210
|
+
inCustomerBubble ? "text-primary-foreground/75" : "text-muted-foreground"
|
|
17211
|
+
),
|
|
17212
|
+
children: quote.preview
|
|
17213
|
+
}
|
|
17214
|
+
)
|
|
17215
|
+
] })
|
|
17216
|
+
]
|
|
17217
|
+
}
|
|
17218
|
+
);
|
|
17219
|
+
}
|
|
17220
|
+
var SWIPE_COMMIT_PX = 48;
|
|
17221
|
+
var SWIPE_ARM_PX = 10;
|
|
17222
|
+
var OVERDRAG_RATE = 0.25;
|
|
17223
|
+
var LONG_PRESS_MS = 450;
|
|
17224
|
+
var RETURN_TRANSITION = "transform 0.25s cubic-bezier(0.2, 0, 0, 1)";
|
|
17225
|
+
function swipeTravel(distance) {
|
|
17226
|
+
if (distance <= 0) return 0;
|
|
17227
|
+
if (distance <= SWIPE_COMMIT_PX) return distance;
|
|
17228
|
+
return SWIPE_COMMIT_PX + (distance - SWIPE_COMMIT_PX) * OVERDRAG_RATE;
|
|
17229
|
+
}
|
|
17230
|
+
function swipeCommitted(distance) {
|
|
17231
|
+
return distance >= SWIPE_COMMIT_PX;
|
|
17232
|
+
}
|
|
17233
|
+
function swipeProgress(distance) {
|
|
17234
|
+
return Math.min(Math.max(distance / SWIPE_COMMIT_PX, 0), 1);
|
|
17235
|
+
}
|
|
17236
|
+
function useSwipeReply({ onReply, onLongPress }) {
|
|
17237
|
+
const rowRef = useRef(null);
|
|
17238
|
+
const glyphRef = useRef(null);
|
|
17239
|
+
const gestureRef = useRef(null);
|
|
17240
|
+
const suppressClickRef = useRef(false);
|
|
17241
|
+
const optionsRef = useRef({ onReply, onLongPress });
|
|
17242
|
+
optionsRef.current = { onReply, onLongPress };
|
|
17243
|
+
const settle = useCallback((glyphVisible) => {
|
|
17244
|
+
const row = rowRef.current;
|
|
17245
|
+
const glyph = glyphRef.current;
|
|
17246
|
+
if (row) {
|
|
17247
|
+
row.style.transition = RETURN_TRANSITION;
|
|
17248
|
+
row.style.transform = "translateX(0px)";
|
|
17249
|
+
}
|
|
17250
|
+
if (glyph && !glyphVisible) {
|
|
17251
|
+
glyph.style.transition = "opacity 0.2s ease-out";
|
|
17252
|
+
glyph.style.opacity = "0";
|
|
17253
|
+
}
|
|
17254
|
+
}, []);
|
|
17255
|
+
const clearGesture = useCallback(() => {
|
|
17256
|
+
const gesture = gestureRef.current;
|
|
17257
|
+
if (gesture?.longPressTimer) clearTimeout(gesture.longPressTimer);
|
|
17258
|
+
gestureRef.current = null;
|
|
17259
|
+
}, []);
|
|
17260
|
+
const onPointerDown = useCallback((event) => {
|
|
17261
|
+
if (!event.isPrimary) return;
|
|
17262
|
+
suppressClickRef.current = false;
|
|
17263
|
+
gestureRef.current = {
|
|
17264
|
+
pointerId: event.pointerId,
|
|
17265
|
+
startX: event.clientX,
|
|
17266
|
+
startY: event.clientY,
|
|
17267
|
+
armed: false,
|
|
17268
|
+
distance: 0,
|
|
17269
|
+
longPressTimer: setTimeout(() => {
|
|
17270
|
+
gestureRef.current = null;
|
|
17271
|
+
suppressClickRef.current = true;
|
|
17272
|
+
optionsRef.current.onLongPress();
|
|
17273
|
+
}, LONG_PRESS_MS)
|
|
17274
|
+
};
|
|
17275
|
+
}, []);
|
|
17276
|
+
const onPointerMove = useCallback((event) => {
|
|
17277
|
+
const gesture = gestureRef.current;
|
|
17278
|
+
if (!gesture || gesture.pointerId !== event.pointerId) return;
|
|
17279
|
+
const leftward = gesture.startX - event.clientX;
|
|
17280
|
+
const vertical = Math.abs(event.clientY - gesture.startY);
|
|
17281
|
+
if (!gesture.armed) {
|
|
17282
|
+
const scrolling = vertical > SWIPE_ARM_PX && vertical >= leftward;
|
|
17283
|
+
const rightward = leftward < -SWIPE_ARM_PX;
|
|
17284
|
+
if (scrolling || rightward) {
|
|
17285
|
+
clearGesture();
|
|
17286
|
+
return;
|
|
17287
|
+
}
|
|
17288
|
+
if (leftward <= SWIPE_ARM_PX || leftward <= vertical) return;
|
|
17289
|
+
if (prefersReducedMotion()) {
|
|
17290
|
+
clearGesture();
|
|
17291
|
+
return;
|
|
17292
|
+
}
|
|
17293
|
+
gesture.armed = true;
|
|
17294
|
+
if (gesture.longPressTimer) clearTimeout(gesture.longPressTimer);
|
|
17295
|
+
gesture.longPressTimer = null;
|
|
17296
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
17297
|
+
if (rowRef.current) rowRef.current.style.transition = "none";
|
|
17298
|
+
if (glyphRef.current) glyphRef.current.style.transition = "none";
|
|
17299
|
+
}
|
|
17300
|
+
gesture.distance = leftward;
|
|
17301
|
+
if (rowRef.current) {
|
|
17302
|
+
rowRef.current.style.transform = `translateX(-${swipeTravel(leftward)}px)`;
|
|
17303
|
+
}
|
|
17304
|
+
if (glyphRef.current) {
|
|
17305
|
+
glyphRef.current.style.opacity = String(swipeProgress(leftward));
|
|
17306
|
+
}
|
|
17307
|
+
}, [clearGesture]);
|
|
17308
|
+
const onPointerUp = useCallback(
|
|
17309
|
+
(event) => {
|
|
17310
|
+
const gesture = gestureRef.current;
|
|
17311
|
+
if (!gesture || gesture.pointerId !== event.pointerId) return;
|
|
17312
|
+
const commit = gesture.armed && swipeCommitted(gesture.distance);
|
|
17313
|
+
const wasArmed = gesture.armed;
|
|
17314
|
+
clearGesture();
|
|
17315
|
+
if (wasArmed) {
|
|
17316
|
+
suppressClickRef.current = true;
|
|
17317
|
+
settle(false);
|
|
17318
|
+
}
|
|
17319
|
+
if (commit) optionsRef.current.onReply();
|
|
17320
|
+
},
|
|
17321
|
+
[clearGesture, settle]
|
|
17322
|
+
);
|
|
17323
|
+
const onPointerCancel = useCallback(
|
|
17324
|
+
(event) => {
|
|
17325
|
+
const gesture = gestureRef.current;
|
|
17326
|
+
if (!gesture || gesture.pointerId !== event.pointerId) return;
|
|
17327
|
+
const wasArmed = gesture.armed;
|
|
17328
|
+
clearGesture();
|
|
17329
|
+
if (wasArmed) settle(false);
|
|
17330
|
+
},
|
|
17331
|
+
[clearGesture, settle]
|
|
17332
|
+
);
|
|
17333
|
+
const onClickCapture = useCallback((event) => {
|
|
17334
|
+
if (!suppressClickRef.current) return;
|
|
17335
|
+
suppressClickRef.current = false;
|
|
17336
|
+
event.preventDefault();
|
|
17337
|
+
event.stopPropagation();
|
|
17338
|
+
}, []);
|
|
17339
|
+
return {
|
|
17340
|
+
rowRef,
|
|
17341
|
+
glyphRef,
|
|
17342
|
+
handlers: { onPointerDown, onPointerMove, onPointerUp, onPointerCancel, onClickCapture }
|
|
17343
|
+
};
|
|
17344
|
+
}
|
|
17345
|
+
var PROSE_CLASS = "[&_p]:my-0 [&_p+p]:mt-1.5 [&_ul]:my-1 [&_ul]:list-disc [&_ul]:pl-4 [&_ol]:my-1 [&_ol]:list-decimal [&_ol]:pl-4 [&_li]:my-0.5 [&_h1]:text-[15px] [&_h1]:font-bold [&_h2]:text-[15px] [&_h2]:font-bold [&_h3]:text-sm [&_h3]:font-semibold [&_hr]:my-2 [&_hr]:border-border [&_table]:my-1 [&_table]:w-full [&_th]:pb-1 [&_th]:text-left [&_th]:text-[11px] [&_th]:font-semibold [&_th]:uppercase [&_th]:text-muted-foreground [&_td]:border-b [&_td]:border-border/50 [&_td]:py-1 [&_td:last-child]:text-right [&_td:last-child]:font-semibold [&_td:last-child]:tabular-nums [&_tr:last-child_td]:border-b-0 [&_a]:underline [&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:text-[13px]";
|
|
17346
|
+
function bubbleShape(isCustomer, group) {
|
|
17347
|
+
if (!hasTail(group)) return "rounded-[18px]";
|
|
17348
|
+
return isCustomer ? "rounded-[18px] rounded-br-none" : "rounded-[18px] rounded-bl-none";
|
|
17349
|
+
}
|
|
17350
|
+
function hasTail(group) {
|
|
17351
|
+
return group === "single" || group === "last";
|
|
17352
|
+
}
|
|
17353
|
+
var TAIL_SWEEP = "M21 0 L21 5 C21 15 25 16 25 16 C20.93 16.43 16.84 14.94 13.96 11.96 C9 16 5 16 0 16";
|
|
17354
|
+
var TAIL_FILL = `${TAIL_SWEEP} Z`;
|
|
17355
|
+
var TAIL_NOTCH = "M25 16 C20.93 16.43 16.84 14.94 13.96 11.96 C9 16 5 16 0 16 Z";
|
|
17356
|
+
function BubbleTail({ isCustomer }) {
|
|
17357
|
+
return /* @__PURE__ */ jsxs(
|
|
17358
|
+
"svg",
|
|
17359
|
+
{
|
|
17360
|
+
width: "25",
|
|
17361
|
+
height: "16",
|
|
17362
|
+
viewBox: "0 0 25 16",
|
|
17363
|
+
"aria-hidden": "true",
|
|
17364
|
+
className: cn(
|
|
17365
|
+
"absolute bottom-0",
|
|
17366
|
+
isCustomer ? "-right-[4px] fill-primary" : "-left-[4px] -scale-x-100 fill-background"
|
|
17367
|
+
),
|
|
17368
|
+
children: [
|
|
17369
|
+
/* @__PURE__ */ jsx("path", { d: TAIL_FILL }),
|
|
17370
|
+
/* @__PURE__ */ jsx("path", { d: TAIL_NOTCH, style: { fill: "var(--color-chat-canvas, var(--color-muted, #f3f5f3))" } }),
|
|
17371
|
+
!isCustomer && /* @__PURE__ */ jsx("path", { d: TAIL_SWEEP, fill: "none", strokeWidth: "1", className: "stroke-foreground/[0.07]" })
|
|
17372
|
+
]
|
|
17373
|
+
}
|
|
17374
|
+
);
|
|
17375
|
+
}
|
|
17376
|
+
function clockLabel(at) {
|
|
17377
|
+
const date = new Date(at);
|
|
17378
|
+
if (Number.isNaN(date.getTime())) return "";
|
|
17379
|
+
const hour = date.getHours() % 12 || 12;
|
|
17380
|
+
return `${hour}:${String(date.getMinutes()).padStart(2, "0")}`;
|
|
17381
|
+
}
|
|
17382
|
+
function DoubleTick() {
|
|
17383
|
+
return /* @__PURE__ */ jsxs("svg", { width: "15", height: "9", viewBox: "0 0 15 9", fill: "none", "aria-hidden": "true", children: [
|
|
17384
|
+
/* @__PURE__ */ jsx("path", { d: "M1 4.5L4 7.5L9.5 1.5", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
17385
|
+
/* @__PURE__ */ jsx("path", { d: "M6.5 4.5L9.5 7.5L14 2.5", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
17386
|
+
] });
|
|
17387
|
+
}
|
|
17388
|
+
function SendingClock() {
|
|
17389
|
+
return /* @__PURE__ */ jsxs("svg", { width: "11", height: "11", viewBox: "0 0 11 11", fill: "none", "aria-hidden": "true", children: [
|
|
17390
|
+
/* @__PURE__ */ jsx("circle", { cx: "5.5", cy: "5.5", r: "4.5", stroke: "currentColor", strokeWidth: "1.2" }),
|
|
17391
|
+
/* @__PURE__ */ jsx("path", { d: "M5.5 3v2.7l1.8 1", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" })
|
|
17392
|
+
] });
|
|
17393
|
+
}
|
|
17394
|
+
function PaperclipIcon() {
|
|
17395
|
+
return /* @__PURE__ */ jsx(
|
|
17396
|
+
"svg",
|
|
17397
|
+
{
|
|
17398
|
+
width: "14",
|
|
17399
|
+
height: "14",
|
|
17400
|
+
viewBox: "0 0 24 24",
|
|
17401
|
+
fill: "none",
|
|
17402
|
+
stroke: "currentColor",
|
|
17403
|
+
strokeWidth: "2",
|
|
17404
|
+
strokeLinecap: "round",
|
|
17405
|
+
strokeLinejoin: "round",
|
|
17406
|
+
"aria-hidden": "true",
|
|
17407
|
+
children: /* @__PURE__ */ jsx("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" })
|
|
17408
|
+
}
|
|
17409
|
+
);
|
|
17410
|
+
}
|
|
17411
|
+
function ReplyGlyph() {
|
|
17412
|
+
return /* @__PURE__ */ jsxs(
|
|
17413
|
+
"svg",
|
|
17414
|
+
{
|
|
17415
|
+
width: "18",
|
|
17416
|
+
height: "18",
|
|
17417
|
+
viewBox: "0 0 24 24",
|
|
17418
|
+
fill: "none",
|
|
17419
|
+
stroke: "currentColor",
|
|
17420
|
+
strokeWidth: "2.2",
|
|
17421
|
+
strokeLinecap: "round",
|
|
17422
|
+
strokeLinejoin: "round",
|
|
17423
|
+
"aria-hidden": "true",
|
|
17424
|
+
children: [
|
|
17425
|
+
/* @__PURE__ */ jsx("polyline", { points: "9 17 4 12 9 7" }),
|
|
17426
|
+
/* @__PURE__ */ jsx("path", { d: "M20 18v-2a4 4 0 0 0-4-4H4" })
|
|
17427
|
+
]
|
|
17428
|
+
}
|
|
17429
|
+
);
|
|
17430
|
+
}
|
|
17431
|
+
var DELIVERY_LABELS = {
|
|
17432
|
+
sending: "Sending",
|
|
17433
|
+
delivered: "Delivered",
|
|
17434
|
+
seen: "Seen"
|
|
17435
|
+
};
|
|
17436
|
+
function BubbleMeta({
|
|
17437
|
+
at,
|
|
17438
|
+
isCustomer,
|
|
17439
|
+
delivery
|
|
17440
|
+
}) {
|
|
17441
|
+
return /* @__PURE__ */ jsxs(
|
|
17442
|
+
"span",
|
|
17443
|
+
{
|
|
17444
|
+
className: cn(
|
|
17445
|
+
"ml-auto flex shrink-0 items-center gap-[3px] self-end pb-px whitespace-nowrap",
|
|
17446
|
+
isCustomer ? "text-primary-foreground/70" : "text-muted-foreground"
|
|
17447
|
+
),
|
|
17448
|
+
children: [
|
|
17449
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10.5px] leading-[13px] font-medium", children: clockLabel(at) }),
|
|
17450
|
+
isCustomer && delivery && /* @__PURE__ */ jsx(
|
|
17451
|
+
"span",
|
|
17452
|
+
{
|
|
17453
|
+
role: "img",
|
|
17454
|
+
"aria-label": DELIVERY_LABELS[delivery],
|
|
17455
|
+
className: cn(
|
|
17456
|
+
"flex items-center text-primary-foreground",
|
|
17457
|
+
delivery !== "seen" && "opacity-55"
|
|
17458
|
+
),
|
|
17459
|
+
children: delivery === "sending" ? /* @__PURE__ */ jsx(SendingClock, {}) : /* @__PURE__ */ jsx(DoubleTick, {})
|
|
17460
|
+
}
|
|
17461
|
+
)
|
|
17462
|
+
]
|
|
17463
|
+
}
|
|
17464
|
+
);
|
|
17465
|
+
}
|
|
17466
|
+
function reactionPills(reactions) {
|
|
17467
|
+
const counts = /* @__PURE__ */ new Map();
|
|
17468
|
+
for (const reaction of reactions) {
|
|
17469
|
+
const emoji = reaction.content.trim();
|
|
17470
|
+
if (emoji) counts.set(emoji, (counts.get(emoji) ?? 0) + 1);
|
|
17471
|
+
}
|
|
17472
|
+
return [...counts.entries()].map(([emoji, count]) => ({ emoji, count }));
|
|
17473
|
+
}
|
|
17474
|
+
var MessageBubble = memo(function MessageBubble2({
|
|
17475
|
+
message,
|
|
17476
|
+
reactions,
|
|
17477
|
+
businessName,
|
|
17478
|
+
group = "single",
|
|
17479
|
+
delivery,
|
|
17480
|
+
onReply,
|
|
17481
|
+
onLongPress,
|
|
17482
|
+
avatar,
|
|
17483
|
+
overlay,
|
|
17484
|
+
renderCards,
|
|
17485
|
+
renderProgram,
|
|
17486
|
+
onQuoteMiss
|
|
17487
|
+
}) {
|
|
17488
|
+
const showAvatar = group === "single" || group === "last";
|
|
17489
|
+
const isCustomer = message.sender_type === "customer";
|
|
17490
|
+
const isBusiness = !isCustomer;
|
|
17491
|
+
const segments = useMemo(
|
|
17492
|
+
() => isCustomer ? [{ kind: "prose", text: message.content }] : splitGenUIContent(message.content),
|
|
17493
|
+
[isCustomer, message.content]
|
|
17494
|
+
);
|
|
17495
|
+
const drawable = useMemo(
|
|
17496
|
+
() => segments.filter(
|
|
17497
|
+
(segment) => segment.kind === "prose" && segment.text.trim() !== "" || segment.kind === "program" && renderProgram != null
|
|
17498
|
+
),
|
|
17499
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
17500
|
+
[segments, renderProgram != null]
|
|
17501
|
+
);
|
|
17502
|
+
const swipe = useSwipeReply({
|
|
17503
|
+
onReply: () => onReply(message),
|
|
17504
|
+
onLongPress: () => onLongPress?.(message)
|
|
17505
|
+
});
|
|
17506
|
+
const quote = message.reply_to ?? null;
|
|
17507
|
+
const pills = reactions ? reactionPills(reactions) : [];
|
|
17508
|
+
const cards = renderCards?.(message);
|
|
17509
|
+
const proseSegments = drawable.filter((segment) => segment.kind === "prose");
|
|
17510
|
+
const lastProseIndex = drawable.lastIndexOf(proseSegments[proseSegments.length - 1]);
|
|
17511
|
+
return /* @__PURE__ */ jsxs("div", { id: `chat-msg-${message.id}`, className: "relative rounded-xl", children: [
|
|
17512
|
+
/* @__PURE__ */ jsx(
|
|
17513
|
+
"span",
|
|
17514
|
+
{
|
|
17515
|
+
ref: swipe.glyphRef,
|
|
17516
|
+
"aria-hidden": "true",
|
|
17517
|
+
className: "absolute top-1/2 right-1 -translate-y-1/2 text-muted-foreground opacity-0",
|
|
17518
|
+
children: /* @__PURE__ */ jsx(ReplyGlyph, {})
|
|
17519
|
+
}
|
|
17520
|
+
),
|
|
17521
|
+
overlay,
|
|
17522
|
+
/* @__PURE__ */ jsxs(
|
|
17523
|
+
"div",
|
|
17524
|
+
{
|
|
17525
|
+
ref: swipe.rowRef,
|
|
17526
|
+
...swipe.handlers,
|
|
17527
|
+
onContextMenu: onLongPress ? (event) => {
|
|
17528
|
+
event.preventDefault();
|
|
17529
|
+
onLongPress(message);
|
|
17530
|
+
} : void 0,
|
|
17531
|
+
className: cn(
|
|
17532
|
+
"flex touch-pan-y flex-col gap-[3px] select-none [-webkit-touch-callout:none]",
|
|
17533
|
+
isCustomer ? "items-end" : "items-start"
|
|
17534
|
+
),
|
|
17535
|
+
children: [
|
|
17536
|
+
quote && drawable[0]?.kind !== "prose" && /* @__PURE__ */ jsx("div", { className: "max-w-[280px] rounded-[14px] border border-foreground/[0.07] bg-background p-1.5 shadow-[0_1px_1px_rgba(15,23,42,0.03)]", children: /* @__PURE__ */ jsx(QuoteBlock, { quote, inCustomerBubble: false, businessName, onMissing: onQuoteMiss }) }),
|
|
17537
|
+
message.attachments.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex max-w-[280px] flex-wrap gap-1.5", children: message.attachments.map((attachment, index) => {
|
|
17538
|
+
const url = safeAttachmentUrl(attachment.url);
|
|
17539
|
+
if (!url) return null;
|
|
17540
|
+
return isImageAttachment(attachment) ? /* @__PURE__ */ jsx("a", { href: url, target: "_blank", rel: "noreferrer", children: /* @__PURE__ */ jsx(
|
|
17541
|
+
"img",
|
|
17542
|
+
{
|
|
17543
|
+
src: url,
|
|
17544
|
+
alt: attachment.filename ?? "Photo",
|
|
17545
|
+
loading: "lazy",
|
|
17546
|
+
className: "max-h-[240px] max-w-[240px] rounded-[16px] object-cover"
|
|
17547
|
+
}
|
|
17548
|
+
) }, index) : /* @__PURE__ */ jsxs(
|
|
17549
|
+
"a",
|
|
17550
|
+
{
|
|
17551
|
+
href: url,
|
|
17552
|
+
target: "_blank",
|
|
17553
|
+
rel: "noreferrer",
|
|
17554
|
+
className: "flex items-center gap-2 rounded-[14px] border border-foreground/[0.07] bg-background px-3 py-2 text-[13px] font-medium text-foreground shadow-[0_1px_1px_rgba(15,23,42,0.03)]",
|
|
17555
|
+
children: [
|
|
17556
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", children: /* @__PURE__ */ jsx(PaperclipIcon, {}) }),
|
|
17557
|
+
/* @__PURE__ */ jsx("span", { className: "max-w-[200px] truncate", children: attachment.filename ?? "Attachment" })
|
|
17558
|
+
]
|
|
17559
|
+
},
|
|
17560
|
+
index
|
|
17561
|
+
);
|
|
17562
|
+
}) }),
|
|
17563
|
+
drawable.map(
|
|
17564
|
+
(segment, index) => segment.kind === "program" ? /* @__PURE__ */ jsx(React14.Fragment, { children: renderProgram?.(segment.source) }, index) : /* @__PURE__ */ jsxs("div", { className: "flex max-w-full items-end gap-1.5", children: [
|
|
17565
|
+
isBusiness && avatar && /* @__PURE__ */ jsx(
|
|
17566
|
+
"span",
|
|
17567
|
+
{
|
|
17568
|
+
"aria-label": businessName,
|
|
17569
|
+
className: cn(
|
|
17570
|
+
"shrink-0",
|
|
17571
|
+
// One avatar per run, anchored to its last bubble.
|
|
17572
|
+
showAvatar && index === lastProseIndex ? "visible" : "invisible"
|
|
17573
|
+
),
|
|
17574
|
+
children: avatar
|
|
17575
|
+
}
|
|
17576
|
+
),
|
|
17577
|
+
/* @__PURE__ */ jsxs(
|
|
17578
|
+
"div",
|
|
17579
|
+
{
|
|
17580
|
+
className: cn(
|
|
17581
|
+
"relative flex max-w-[280px] min-w-0 flex-col gap-1.5 py-2 pr-[11px] pl-3.5 text-[15px] leading-[21px] font-[450] break-words",
|
|
17582
|
+
bubbleShape(isCustomer, index === lastProseIndex ? group : "middle"),
|
|
17583
|
+
isCustomer ? "bg-primary text-primary-foreground" : "border border-foreground/[0.07] bg-background text-foreground shadow-[0_1px_1px_rgba(15,23,42,0.03)]"
|
|
17584
|
+
),
|
|
17585
|
+
children: [
|
|
17586
|
+
index === 0 && quote && /* @__PURE__ */ jsx(QuoteBlock, { quote, inCustomerBubble: isCustomer, businessName, onMissing: onQuoteMiss }),
|
|
17587
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-wrap items-end gap-x-2 gap-y-0.5", children: [
|
|
17588
|
+
isCustomer ? /* @__PURE__ */ jsx("span", { className: "whitespace-pre-wrap", children: segment.text }) : /* @__PURE__ */ jsx(ChatMarkdown, { text: segment.text, className: cn("min-w-0", PROSE_CLASS) }),
|
|
17589
|
+
index === lastProseIndex && /* @__PURE__ */ jsx(BubbleMeta, { at: message.created_at, isCustomer, delivery })
|
|
17590
|
+
] }),
|
|
17591
|
+
index === lastProseIndex && hasTail(group) && /* @__PURE__ */ jsx(BubbleTail, { isCustomer })
|
|
17592
|
+
]
|
|
17593
|
+
}
|
|
17594
|
+
)
|
|
17595
|
+
] }, index)
|
|
17596
|
+
),
|
|
17597
|
+
cards,
|
|
17598
|
+
pills.length > 0 && /* @__PURE__ */ jsx(
|
|
17599
|
+
"div",
|
|
17600
|
+
{
|
|
17601
|
+
className: cn(
|
|
17602
|
+
"z-[1] -mt-3 flex gap-1",
|
|
17603
|
+
// Overlap the bubble corner by ~9px, tucked inside the tail side.
|
|
17604
|
+
isCustomer ? "mr-2.5" : "ml-10"
|
|
17605
|
+
),
|
|
17606
|
+
children: pills.map((pill) => /* @__PURE__ */ jsxs(
|
|
17607
|
+
"span",
|
|
17608
|
+
{
|
|
17609
|
+
className: "flex items-center gap-[3px] rounded-full border border-foreground/[0.08] bg-background px-[7px] py-[2px] shadow-[0_1px_3px_rgba(15,23,42,0.08)]",
|
|
17610
|
+
children: [
|
|
17611
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs leading-4", children: pill.emoji }),
|
|
17612
|
+
/* @__PURE__ */ jsx("span", { className: "text-[11px] leading-[13px] font-semibold text-muted-foreground", children: pill.count })
|
|
17613
|
+
]
|
|
17614
|
+
},
|
|
17615
|
+
pill.emoji
|
|
17616
|
+
))
|
|
17617
|
+
}
|
|
17618
|
+
)
|
|
17619
|
+
]
|
|
17620
|
+
}
|
|
17621
|
+
)
|
|
17622
|
+
] });
|
|
17623
|
+
});
|
|
17624
|
+
function Seam({
|
|
17625
|
+
label,
|
|
17626
|
+
variant = "line"
|
|
17627
|
+
}) {
|
|
17628
|
+
if (variant === "chip") {
|
|
17629
|
+
return /* @__PURE__ */ jsx("div", { className: "flex justify-center py-1.5", children: /* @__PURE__ */ jsx("span", { className: "rounded-full border border-foreground/[0.06] bg-background px-3 py-1 text-[11px] leading-[14px] font-semibold tracking-[0.04em] text-muted-foreground uppercase shadow-[0_1px_2px_rgba(15,23,42,0.04)]", children: label }) });
|
|
17630
|
+
}
|
|
17631
|
+
const unread = variant === "unread";
|
|
17632
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 py-1.5", children: [
|
|
17633
|
+
/* @__PURE__ */ jsx(
|
|
17634
|
+
"span",
|
|
17635
|
+
{
|
|
17636
|
+
className: cn("h-px flex-1", unread ? "bg-primary/35" : "bg-foreground/[0.08]"),
|
|
17637
|
+
"aria-hidden": "true"
|
|
17638
|
+
}
|
|
17639
|
+
),
|
|
17640
|
+
/* @__PURE__ */ jsx(
|
|
17641
|
+
"span",
|
|
17642
|
+
{
|
|
17643
|
+
className: cn(
|
|
17644
|
+
"whitespace-nowrap",
|
|
17645
|
+
unread ? "text-[11px] leading-[14px] font-semibold tracking-[0.04em] text-primary uppercase" : "text-[11.5px] leading-[15px] font-medium text-muted-foreground"
|
|
17646
|
+
),
|
|
17647
|
+
children: label
|
|
17648
|
+
}
|
|
17649
|
+
),
|
|
17650
|
+
/* @__PURE__ */ jsx(
|
|
17651
|
+
"span",
|
|
17652
|
+
{
|
|
17653
|
+
className: cn("h-px flex-1", unread ? "bg-primary/35" : "bg-foreground/[0.08]"),
|
|
17654
|
+
"aria-hidden": "true"
|
|
17655
|
+
}
|
|
17656
|
+
)
|
|
17657
|
+
] });
|
|
17658
|
+
}
|
|
17659
|
+
|
|
17660
|
+
// src/react/chat-kit/timeline.ts
|
|
17661
|
+
function sameDay(a, b) {
|
|
17662
|
+
return new Date(a).toDateString() === new Date(b).toDateString();
|
|
17663
|
+
}
|
|
17664
|
+
function dayLabel(at) {
|
|
17665
|
+
const date = new Date(at);
|
|
17666
|
+
const today = /* @__PURE__ */ new Date();
|
|
17667
|
+
if (date.toDateString() === today.toDateString()) return "Today";
|
|
17668
|
+
const yesterday = new Date(today);
|
|
17669
|
+
yesterday.setDate(today.getDate() - 1);
|
|
17670
|
+
if (date.toDateString() === yesterday.toDateString()) return "Yesterday";
|
|
17671
|
+
return date.toLocaleDateString([], { weekday: "short", day: "numeric", month: "short" });
|
|
17672
|
+
}
|
|
17152
17673
|
function proseOf(content) {
|
|
17153
17674
|
return splitGenUIContent(content).filter((segment) => segment.kind === "prose").map((segment) => segment.text).join("\n\n").trim();
|
|
17154
17675
|
}
|
|
17676
|
+
function hasProgram(content) {
|
|
17677
|
+
return splitGenUIContent(content).some((segment) => segment.kind === "program");
|
|
17678
|
+
}
|
|
17679
|
+
function chatTimeline(messages, options = {}) {
|
|
17680
|
+
const { readAt = null, rendersPrograms = false } = options;
|
|
17681
|
+
const partitioned = partitionMessages(messages);
|
|
17682
|
+
const bubbles = partitioned.bubbles.filter(
|
|
17683
|
+
(message) => message.sender_type === "system" || message.attachments.length > 0 || chatMessageCards(message).length > 0 || rendersPrograms && hasProgram(message.content) || (message.sender_type === "customer" ? message.content.trim() !== "" : proseOf(message.content) !== "")
|
|
17684
|
+
);
|
|
17685
|
+
let firstUnreadId;
|
|
17686
|
+
let unreadOnOpen = 0;
|
|
17687
|
+
if (readAt) {
|
|
17688
|
+
const readAtMs = new Date(readAt).getTime();
|
|
17689
|
+
for (const message of bubbles) {
|
|
17690
|
+
if (message.sender_type === "customer" || new Date(message.created_at).getTime() <= readAtMs)
|
|
17691
|
+
continue;
|
|
17692
|
+
firstUnreadId ?? (firstUnreadId = message.id);
|
|
17693
|
+
unreadOnOpen += 1;
|
|
17694
|
+
}
|
|
17695
|
+
}
|
|
17696
|
+
return {
|
|
17697
|
+
bubbles,
|
|
17698
|
+
reactionsByTarget: partitioned.reactionsByTarget,
|
|
17699
|
+
firstUnreadId,
|
|
17700
|
+
unreadOnOpen,
|
|
17701
|
+
firstAgentMessageId: bubbles.find((m) => m.sender_type === "agent")?.id
|
|
17702
|
+
};
|
|
17703
|
+
}
|
|
17704
|
+
function groupPosition(timeline, index) {
|
|
17705
|
+
const { bubbles, firstAgentMessageId, firstUnreadId } = timeline;
|
|
17706
|
+
const message = bubbles[index];
|
|
17707
|
+
const previous = bubbles[index - 1];
|
|
17708
|
+
const next = bubbles[index + 1];
|
|
17709
|
+
const startsRun = !previous || !sameDay(previous.created_at, message.created_at) || previous.sender_type !== message.sender_type || message.id === firstAgentMessageId || message.id === firstUnreadId || previous.sender_type === "system";
|
|
17710
|
+
const endsRun = !next || next.sender_type !== message.sender_type || next.sender_type === "system" || !sameDay(message.created_at, next.created_at);
|
|
17711
|
+
if (startsRun && endsRun) return "single";
|
|
17712
|
+
if (startsRun) return "first";
|
|
17713
|
+
if (endsRun) return "last";
|
|
17714
|
+
return "middle";
|
|
17715
|
+
}
|
|
17716
|
+
function deliveryState(message, timeline, seenAt, isOptimistic2) {
|
|
17717
|
+
if (message.sender_type !== "customer") return void 0;
|
|
17718
|
+
if (isOptimistic2(message)) return "sending";
|
|
17719
|
+
const seenCutoff = timeline.firstAgentMessageId ? seenAt : null;
|
|
17720
|
+
return seenCutoff && message.created_at <= seenCutoff ? "seen" : "delivered";
|
|
17721
|
+
}
|
|
17722
|
+
var MAX_ATTACHMENT_BYTES = 5 * 1024 * 1024;
|
|
17723
|
+
var KEEP_DISMISSED_KEY = "cimplify_keep_chat_dismissed";
|
|
17724
|
+
var AT_BOTTOM_SLACK_PX = 48;
|
|
17155
17725
|
function ChatWidget({
|
|
17156
17726
|
client: clientProp,
|
|
17157
17727
|
businessName = "Support",
|
|
@@ -17276,6 +17846,7 @@ function ChatWidget({
|
|
|
17276
17846
|
isSending,
|
|
17277
17847
|
isTyping: showTyping,
|
|
17278
17848
|
seenAt,
|
|
17849
|
+
readAt,
|
|
17279
17850
|
error: error ?? attachError,
|
|
17280
17851
|
isActive,
|
|
17281
17852
|
isLeft,
|
|
@@ -17347,6 +17918,7 @@ function Panel({
|
|
|
17347
17918
|
isSending,
|
|
17348
17919
|
isTyping,
|
|
17349
17920
|
seenAt,
|
|
17921
|
+
readAt,
|
|
17350
17922
|
error,
|
|
17351
17923
|
isActive,
|
|
17352
17924
|
isLeft,
|
|
@@ -17405,6 +17977,7 @@ function Panel({
|
|
|
17405
17977
|
isLoading,
|
|
17406
17978
|
isSending: isTyping,
|
|
17407
17979
|
seenAt,
|
|
17980
|
+
readAt,
|
|
17408
17981
|
humanRequested,
|
|
17409
17982
|
mayHaveOlder,
|
|
17410
17983
|
onReact,
|
|
@@ -17565,22 +18138,8 @@ function Welcome({
|
|
|
17565
18138
|
);
|
|
17566
18139
|
}
|
|
17567
18140
|
var QUICK_REACTIONS = ["\u{1F44D}", "\u2764\uFE0F"];
|
|
17568
|
-
function
|
|
17569
|
-
|
|
17570
|
-
for (let i = bubbles.length - 1; i >= 0; i--) {
|
|
17571
|
-
if (bubbles[i].sender_type !== "customer") continue;
|
|
17572
|
-
return bubbles[i].created_at <= seenAt ? bubbles[i].id : null;
|
|
17573
|
-
}
|
|
17574
|
-
return null;
|
|
17575
|
-
}
|
|
17576
|
-
function dayLabel(at) {
|
|
17577
|
-
const date = new Date(at);
|
|
17578
|
-
const today = /* @__PURE__ */ new Date();
|
|
17579
|
-
if (date.toDateString() === today.toDateString()) return "Today";
|
|
17580
|
-
const yesterday = new Date(today);
|
|
17581
|
-
yesterday.setDate(today.getDate() - 1);
|
|
17582
|
-
if (date.toDateString() === yesterday.toDateString()) return "Yesterday";
|
|
17583
|
-
return date.toLocaleDateString([], { weekday: "short", day: "numeric", month: "short" });
|
|
18141
|
+
function LetterAvatar({ name }) {
|
|
18142
|
+
return /* @__PURE__ */ jsx("span", { className: "flex size-6 items-center justify-center rounded-full bg-foreground text-[10px] font-bold text-background", children: name.charAt(0).toUpperCase() });
|
|
17584
18143
|
}
|
|
17585
18144
|
function MessageList({
|
|
17586
18145
|
messages,
|
|
@@ -17588,6 +18147,7 @@ function MessageList({
|
|
|
17588
18147
|
isLoading,
|
|
17589
18148
|
isSending,
|
|
17590
18149
|
seenAt,
|
|
18150
|
+
readAt,
|
|
17591
18151
|
humanRequested,
|
|
17592
18152
|
mayHaveOlder,
|
|
17593
18153
|
onReact,
|
|
@@ -17597,12 +18157,8 @@ function MessageList({
|
|
|
17597
18157
|
className
|
|
17598
18158
|
}) {
|
|
17599
18159
|
const scrolledUpRef = useRef(false);
|
|
17600
|
-
const
|
|
17601
|
-
const bubbles =
|
|
17602
|
-
(m) => m.sender_type === "system" || m.attachments.length > 0 || (m.sender_type === "customer" ? m.content.trim() !== "" : proseOf(m.content) !== "")
|
|
17603
|
-
);
|
|
17604
|
-
const reactionsByTarget = partitioned.reactionsByTarget;
|
|
17605
|
-
const seenMessageId = lastSeenCustomerMessageId(bubbles, seenAt);
|
|
18160
|
+
const timeline = chatTimeline(messages, { readAt });
|
|
18161
|
+
const { bubbles, reactionsByTarget, firstUnreadId, unreadOnOpen, firstAgentMessageId } = timeline;
|
|
17606
18162
|
const lastBubble = bubbles[bubbles.length - 1];
|
|
17607
18163
|
const offerHuman = !humanRequested && lastBubble?.sender_type === "bot" && !isSending;
|
|
17608
18164
|
const handleScroll = (event) => {
|
|
@@ -17613,121 +18169,62 @@ function MessageList({
|
|
|
17613
18169
|
"div",
|
|
17614
18170
|
{
|
|
17615
18171
|
onScroll: handleScroll,
|
|
17616
|
-
|
|
17617
|
-
|
|
17618
|
-
className
|
|
17619
|
-
),
|
|
18172
|
+
style: { background: "var(--color-chat-canvas, var(--color-muted, #f3f5f3))" },
|
|
18173
|
+
className: cn("flex flex-1 flex-col gap-0.5 overflow-y-auto px-3.5 py-3.5", className),
|
|
17620
18174
|
children: [
|
|
17621
18175
|
isLoading && messages.length === 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-center", children: /* @__PURE__ */ jsx(TypingDots, {}) }),
|
|
17622
|
-
mayHaveOlder && /* @__PURE__ */ jsx("div", { className: "flex justify-center pb-
|
|
18176
|
+
mayHaveOlder && /* @__PURE__ */ jsx("div", { className: "flex justify-center pb-1", children: /* @__PURE__ */ jsx(
|
|
17623
18177
|
"button",
|
|
17624
18178
|
{
|
|
17625
18179
|
type: "button",
|
|
17626
18180
|
onClick: onLoadOlder,
|
|
17627
|
-
className: "rounded-full border border-
|
|
18181
|
+
className: "rounded-full border border-foreground/[0.06] bg-background px-3.5 py-[7px] text-xs font-semibold text-muted-foreground shadow-[0_1px_2px_rgba(15,23,42,0.04)]",
|
|
17628
18182
|
children: "Show earlier messages"
|
|
17629
18183
|
}
|
|
17630
18184
|
) }),
|
|
17631
18185
|
bubbles.map((msg, i) => {
|
|
17632
|
-
const isCustomer = msg.sender_type === "customer";
|
|
17633
18186
|
const prev = bubbles[i - 1];
|
|
17634
|
-
const sameSenderAsPrev = prev?.sender_type === msg.sender_type;
|
|
17635
|
-
const optimistic = isOptimistic(msg);
|
|
17636
|
-
const reactions = reactionsByTarget.get(msg.id);
|
|
17637
18187
|
const newDay = !prev || !sameDay(prev.created_at, msg.created_at);
|
|
17638
|
-
|
|
17639
|
-
|
|
17640
|
-
|
|
17641
|
-
return /* @__PURE__ */ jsxs(
|
|
17642
|
-
|
|
17643
|
-
|
|
17644
|
-
|
|
17645
|
-
|
|
17646
|
-
|
|
17647
|
-
|
|
17648
|
-
|
|
17649
|
-
|
|
18188
|
+
const group = groupPosition(timeline, i);
|
|
18189
|
+
const startsRun = group === "single" || group === "first";
|
|
18190
|
+
const delivery = deliveryState(msg, timeline, seenAt, isOptimistic);
|
|
18191
|
+
return /* @__PURE__ */ jsxs(
|
|
18192
|
+
"div",
|
|
18193
|
+
{
|
|
18194
|
+
className: cn("flex flex-col gap-1.5", startsRun && i > 0 && "mt-2.5"),
|
|
18195
|
+
children: [
|
|
18196
|
+
newDay && /* @__PURE__ */ jsx(Seam, { variant: "chip", label: dayLabel(msg.created_at) }),
|
|
18197
|
+
msg.id === firstUnreadId && /* @__PURE__ */ jsx(
|
|
18198
|
+
Seam,
|
|
18199
|
+
{
|
|
18200
|
+
variant: "unread",
|
|
18201
|
+
label: `${unreadOnOpen} new message${unreadOnOpen === 1 ? "" : "s"}`
|
|
18202
|
+
}
|
|
17650
18203
|
),
|
|
17651
|
-
|
|
17652
|
-
|
|
17653
|
-
/* @__PURE__ */
|
|
17654
|
-
|
|
18204
|
+
msg.id === firstAgentMessageId && /* @__PURE__ */ jsx(Seam, { label: "A person joined" }),
|
|
18205
|
+
msg.sender_type === "system" ? /* @__PURE__ */ jsx(Seam, { label: "Passing you to the team" }) : /* @__PURE__ */ jsxs("div", { className: "group relative", children: [
|
|
18206
|
+
msg.sender_type !== "customer" && !isOptimistic(msg) && /* @__PURE__ */ jsx(HoverRail, { message: msg, onReact, onReply }),
|
|
18207
|
+
/* @__PURE__ */ jsx(
|
|
18208
|
+
MessageBubble,
|
|
17655
18209
|
{
|
|
17656
|
-
|
|
17657
|
-
|
|
17658
|
-
|
|
17659
|
-
|
|
17660
|
-
|
|
17661
|
-
|
|
17662
|
-
|
|
17663
|
-
|
|
17664
|
-
|
|
17665
|
-
|
|
17666
|
-
|
|
17667
|
-
className: cn(
|
|
17668
|
-
"mb-1.5 flex gap-1.5 rounded-lg px-2 py-1 text-xs",
|
|
17669
|
-
isCustomer ? "bg-background/15" : "bg-muted"
|
|
17670
|
-
),
|
|
17671
|
-
children: [
|
|
17672
|
-
/* @__PURE__ */ jsx(
|
|
17673
|
-
"span",
|
|
17674
|
-
{
|
|
17675
|
-
className: cn(
|
|
17676
|
-
"w-[3px] shrink-0 self-stretch rounded-full",
|
|
17677
|
-
isCustomer ? "bg-background/40" : "bg-muted-foreground/40"
|
|
17678
|
-
)
|
|
17679
|
-
}
|
|
17680
|
-
),
|
|
17681
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate opacity-80", children: msg.reply_to.preview })
|
|
17682
|
-
]
|
|
17683
|
-
}
|
|
17684
|
-
),
|
|
17685
|
-
msg.attachments.length > 0 && /* @__PURE__ */ jsx("div", { className: cn("flex flex-wrap gap-1.5", msg.content && "mb-1.5"), children: msg.attachments.map((attachment, index) => {
|
|
17686
|
-
const url = safeAttachmentUrl(attachment.url);
|
|
17687
|
-
if (!url) return null;
|
|
17688
|
-
return attachment.mime_type?.startsWith("image/") ? /* @__PURE__ */ jsx("a", { href: url, target: "_blank", rel: "noreferrer", children: /* @__PURE__ */ jsx(
|
|
17689
|
-
"img",
|
|
17690
|
-
{
|
|
17691
|
-
src: url,
|
|
17692
|
-
alt: attachment.filename ?? "Photo",
|
|
17693
|
-
loading: "lazy",
|
|
17694
|
-
className: "max-h-48 max-w-full rounded-lg object-cover"
|
|
17695
|
-
}
|
|
17696
|
-
) }, index) : /* @__PURE__ */ jsx(
|
|
17697
|
-
"a",
|
|
17698
|
-
{
|
|
17699
|
-
href: url,
|
|
17700
|
-
target: "_blank",
|
|
17701
|
-
rel: "noreferrer",
|
|
17702
|
-
className: "truncate text-xs underline",
|
|
17703
|
-
children: attachment.filename ?? "Attachment"
|
|
17704
|
-
},
|
|
17705
|
-
index
|
|
17706
|
-
);
|
|
17707
|
-
}) }),
|
|
17708
|
-
isCustomer ? msg.content && /* @__PURE__ */ jsx("div", { className: "whitespace-pre-wrap", children: msg.content }) : /* @__PURE__ */ jsx(
|
|
17709
|
-
ChatMarkdown,
|
|
17710
|
-
{
|
|
17711
|
-
text: proseOf(msg.content),
|
|
17712
|
-
className: "[&_p]:my-0 [&_p+p]:mt-1.5 [&_ul]:my-1 [&_ul]:list-disc [&_ul]:pl-4 [&_ol]:my-1 [&_ol]:list-decimal [&_ol]:pl-4 [&_li]:my-0.5 [&_h1]:text-sm [&_h1]:font-bold [&_h2]:text-sm [&_h2]:font-bold [&_h3]:text-sm [&_h3]:font-semibold [&_hr]:my-2 [&_table]:my-1 [&_table]:w-full [&_th]:pb-1 [&_th]:text-left [&_th]:text-[10px] [&_th]:font-semibold [&_th]:uppercase [&_td]:py-1 [&_td:last-child]:text-right [&_td:last-child]:font-semibold [&_td:last-child]:tabular-nums [&_a]:underline"
|
|
17713
|
-
}
|
|
17714
|
-
)
|
|
17715
|
-
]
|
|
18210
|
+
message: msg,
|
|
18211
|
+
reactions: reactionsByTarget.get(msg.id),
|
|
18212
|
+
businessName,
|
|
18213
|
+
group,
|
|
18214
|
+
delivery,
|
|
18215
|
+
onReply,
|
|
18216
|
+
avatar: /* @__PURE__ */ jsx(LetterAvatar, { name: businessName }),
|
|
18217
|
+
onQuoteMiss: async () => {
|
|
18218
|
+
onLoadOlder();
|
|
18219
|
+
return true;
|
|
18220
|
+
}
|
|
17716
18221
|
}
|
|
17717
18222
|
)
|
|
17718
|
-
]
|
|
17719
|
-
|
|
17720
|
-
|
|
17721
|
-
|
|
17722
|
-
|
|
17723
|
-
{
|
|
17724
|
-
className: "rounded-full border border-border bg-background px-1.5 py-0.5 text-xs shadow-sm",
|
|
17725
|
-
children: reaction.content
|
|
17726
|
-
},
|
|
17727
|
-
reaction.id
|
|
17728
|
-
)) }),
|
|
17729
|
-
msg.id === seenMessageId && /* @__PURE__ */ jsx("div", { className: "mt-0.5 text-right text-[10px] font-medium text-muted-foreground", children: "Seen" })
|
|
17730
|
-
] }, msg.id);
|
|
18223
|
+
] })
|
|
18224
|
+
]
|
|
18225
|
+
},
|
|
18226
|
+
msg.id
|
|
18227
|
+
);
|
|
17731
18228
|
}),
|
|
17732
18229
|
isSending && /* @__PURE__ */ jsx("div", { className: "mr-auto mt-1", children: /* @__PURE__ */ jsx(TypingDots, {}) }),
|
|
17733
18230
|
offerHuman && /* @__PURE__ */ jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsx(
|
|
@@ -17752,24 +18249,6 @@ function MessageList({
|
|
|
17752
18249
|
}
|
|
17753
18250
|
);
|
|
17754
18251
|
}
|
|
17755
|
-
function sameDay(a, b) {
|
|
17756
|
-
return new Date(a).toDateString() === new Date(b).toDateString();
|
|
17757
|
-
}
|
|
17758
|
-
function SenderChip({
|
|
17759
|
-
sender,
|
|
17760
|
-
businessName
|
|
17761
|
-
}) {
|
|
17762
|
-
if (sender === "bot") {
|
|
17763
|
-
return /* @__PURE__ */ jsxs("span", { className: "mb-1 inline-flex items-center gap-1 rounded bg-primary/10 px-1.5 py-0.5 text-[10px] font-semibold text-primary", children: [
|
|
17764
|
-
/* @__PURE__ */ jsx(SparkleIcon, { className: "h-[11px] w-[11px]" }),
|
|
17765
|
-
"AI"
|
|
17766
|
-
] });
|
|
17767
|
-
}
|
|
17768
|
-
if (sender === "agent") {
|
|
17769
|
-
return /* @__PURE__ */ jsx("span", { className: "mb-1 inline-flex items-center rounded bg-muted px-1.5 py-0.5 text-[10px] font-semibold text-muted-foreground", children: businessName });
|
|
17770
|
-
}
|
|
17771
|
-
return null;
|
|
17772
|
-
}
|
|
17773
18252
|
function HoverRail({
|
|
17774
18253
|
message,
|
|
17775
18254
|
onReact,
|
|
@@ -18162,19 +18641,6 @@ function ReplyIcon({ className }) {
|
|
|
18162
18641
|
}
|
|
18163
18642
|
);
|
|
18164
18643
|
}
|
|
18165
|
-
function SparkleIcon({ className }) {
|
|
18166
|
-
return /* @__PURE__ */ jsx(
|
|
18167
|
-
"svg",
|
|
18168
|
-
{
|
|
18169
|
-
className,
|
|
18170
|
-
viewBox: "0 0 24 24",
|
|
18171
|
-
fill: "none",
|
|
18172
|
-
stroke: "currentColor",
|
|
18173
|
-
strokeWidth: 2.5,
|
|
18174
|
-
children: /* @__PURE__ */ jsx("path", { d: "M12 2v4m0 12v4M4.93 4.93l2.83 2.83m8.48 8.48l2.83 2.83M2 12h4m12 0h4M4.93 19.07l2.83-2.83m8.48-8.48l2.83-2.83" })
|
|
18175
|
-
}
|
|
18176
|
-
);
|
|
18177
|
-
}
|
|
18178
18644
|
|
|
18179
18645
|
// src/react/genui/catalog.ts
|
|
18180
18646
|
function genUICatalog(registry) {
|
|
@@ -19997,4 +20463,4 @@ async function genUIFingerprint(manifest) {
|
|
|
19997
20463
|
return Array.from(new Uint8Array(digest)).map((byte) => byte.toString(16).padStart(2, "0")).join("").slice(0, 16);
|
|
19998
20464
|
}
|
|
19999
20465
|
|
|
20000
|
-
export { AccommodationCard, AccountContent, AccountDashboardPage, AccountHero, AccountIdentityStrip, AccountLineItem, AccountLineItems, AccountNav, AccountOrderDetailPage, AccountOrderView, AccountOrdersPage, AccountShell, AccountSidebar, AccountSignedOutPrompt, AccountSubscriptionDetailPage, AccountSubscriptionsPage, Ad, AdProvider, AddOnSelector, AddressAutocomplete, AddressElement, AuthElement, AvailabilityBadge, BackLink, BillingPlanSelector, BookingCard, BookingList, BookingPage, BookingSummary, BookingsPage, BoxIcon24, BundleProductCard, BundleProductLayout, BundleSelector, Button, CIMPLIFY_GENUI_REGISTRY, CardImage, CardShell, CardVariant, CartDrawer, CartDrawerProvider, CartPage, CartSummary, CartTemplate, CatalogueCollectionLayout, CataloguePage, CatalogueTemplate, CategoryFilter, CategoryGrid, ChatMarkdown, ChatWidget, CheckIcon, CheckoutPage, CimplifyCheckout, CimplifyProvider, CimplifySignInButton, CimplifyUserButton, CollectionPage, CollectionTemplate, CompactCartLayout, CompactCatalogueLayout, CompactSearchLayout, CompactServiceCard, CompositeProductCard, CompositeProductLayout, CompositeSelector, ContextCard, ContinuityCard, CurrencySelector, CustomAttributesTable, CustomerInputFields, DashboardIcon, DashboardIcon20, DatePicker, DateSlotPicker, DealBanner, DealsPage, DefaultCartLayout, DefaultCatalogueLayout, DefaultCollectionLayout, DefaultProductLayout, DefaultSearchLayout, DeliveryEstimate, DeliveryTracker, DeliveryTruckIcon, DigitalProductCard, DigitalProductLayout, DiscountInput, ElementsProvider, EmptyState, ErrorState, FeaturedCollectionLayout, FilterTabs, FoodProductCard, FoodProductLayout, GenUIView, HappeningCard, IdentityIcon, IdentityOfframp, InventoryBadge, ItemsCard, LeaseServiceCard, LineItemDetails, LocationPicker, MediaGallery, MetadataStringList, MobileAccountShell, MobileBackButton, MobileMoreButton, MobileTabBar, NextDeliveryCard, OrderDetailHeader, OrderDetailMetaPipe, OrderDetailPage, OrderHistory, OrderHistoryPage, OrderList, OrderRow, OrderSummary, OrderTimeline, OrderTotals, OrdersIcon, OrdersIcon20, OvenIcon, PackageIcon, PaymentElement, Price, PriceRange, ProductCard, ProductCustomizer, ProductGrid, ProductImageGallery, ProductModel3D, ProductPage, ProductSheet, ProductTemplate, PropertiesTable, QuantitySelector, QuickAddButton, RecentlyViewed, RecommendationCarousel, RelatedProductsSection, RentalServiceCard, ResourcePicker, RetailProductCard, RichText, SaleBadge, SalePrice, SaleTeaser, ScheduleServiceCard, SearchInput, SearchPage, SearchTemplate, Section, SectionMore, ServiceProductLayout, SessionMessageBanner, SignOutIcon, Skeleton, SlotPicker, SoldOutOverlay, StaffPicker, StandardServiceCard, Status, StoreNav, StoreVideo, SubscriptionCard, SubscriptionList, SubscriptionRow, SubscriptionsIcon, SubscriptionsIcon20, TagPills, TimePicker, Toast, TwoColumnGrid, VariantSelector, VolumePricing, WelcomeCard, WholesaleProductCard, WholesaleProductLayout, WishlistButton, clearOrdersCache, cn, createPlacesSessionToken, defaultBoundaryKind, genUICatalog, genUIFingerprint, genUIManifest, genUIManifestJson, getBoundaryLabels, isImageAttachment, isTerminalOrderStatus, parse as parseGenUIProgram, partitionMessages, prefetchProduct, prefetchProducts, resolveBoundaryKind, roomToResource, safeAttachmentUrl, sanitizeRichTextHtml, stripHtmlToText, toAccountLineItem, toAccountLineItems, toAccountOrderView, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCartDrawer, useCategories, useChat, useCheckout, useCimplify, useCimplifyClient, useCimplifySession, useCollection, useCollections, useDeals, useDeliveryFee, useDeliveryOptions, useElements, useElementsReady, useFxRate, useGenUIProgram, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useStoreCredit, useSubscription, useSubscriptions, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };
|
|
20466
|
+
export { AccommodationCard, AccountContent, AccountDashboardPage, AccountHero, AccountIdentityStrip, AccountLineItem, AccountLineItems, AccountNav, AccountOrderDetailPage, AccountOrderView, AccountOrdersPage, AccountShell, AccountSidebar, AccountSignedOutPrompt, AccountSubscriptionDetailPage, AccountSubscriptionsPage, Ad, AdProvider, AddOnSelector, AddressAutocomplete, AddressElement, AuthElement, AvailabilityBadge, BackLink, BillingPlanSelector, BookingCard, BookingList, BookingPage, BookingSummary, BookingsPage, BoxIcon24, BubbleTail, BundleProductCard, BundleProductLayout, BundleSelector, Button, CIMPLIFY_GENUI_REGISTRY, CardImage, CardShell, CardVariant, CartDrawer, CartDrawerProvider, CartPage, CartSummary, CartTemplate, CatalogueCollectionLayout, CataloguePage, CatalogueTemplate, CategoryFilter, CategoryGrid, ChatMarkdown, ChatWidget, CheckIcon, CheckoutPage, CimplifyCheckout, CimplifyProvider, CimplifySignInButton, CimplifyUserButton, CollectionPage, CollectionTemplate, CompactCartLayout, CompactCatalogueLayout, CompactSearchLayout, CompactServiceCard, CompositeProductCard, CompositeProductLayout, CompositeSelector, ContextCard, ContinuityCard, CurrencySelector, CustomAttributesTable, CustomerInputFields, DashboardIcon, DashboardIcon20, DatePicker, DateSlotPicker, DealBanner, DealsPage, DefaultCartLayout, DefaultCatalogueLayout, DefaultCollectionLayout, DefaultProductLayout, DefaultSearchLayout, DeliveryEstimate, DeliveryTracker, DeliveryTruckIcon, DigitalProductCard, DigitalProductLayout, DiscountInput, ElementsProvider, EmptyState, ErrorState, FeaturedCollectionLayout, FilterTabs, FoodProductCard, FoodProductLayout, GenUIView, HappeningCard, IdentityIcon, IdentityOfframp, InventoryBadge, ItemsCard, LeaseServiceCard, LineItemDetails, LocationPicker, MediaGallery, MessageBubble, MetadataStringList, MobileAccountShell, MobileBackButton, MobileMoreButton, MobileTabBar, NextDeliveryCard, OrderDetailHeader, OrderDetailMetaPipe, OrderDetailPage, OrderHistory, OrderHistoryPage, OrderList, OrderRow, OrderSummary, OrderTimeline, OrderTotals, OrdersIcon, OrdersIcon20, OvenIcon, PackageIcon, PaymentElement, Price, PriceRange, ProductCard, ProductCustomizer, ProductGrid, ProductImageGallery, ProductModel3D, ProductPage, ProductSheet, ProductTemplate, PropertiesTable, QuantitySelector, QuickAddButton, QuoteBlock, RecentlyViewed, RecommendationCarousel, RelatedProductsSection, RentalServiceCard, ResourcePicker, RetailProductCard, RichText, SWIPE_COMMIT_PX, SaleBadge, SalePrice, SaleTeaser, ScheduleServiceCard, Seam, SearchInput, SearchPage, SearchTemplate, Section, SectionMore, ServiceProductLayout, SessionMessageBanner, SignOutIcon, Skeleton, SlotPicker, SoldOutOverlay, StaffPicker, StandardServiceCard, Status, StoreNav, StoreVideo, SubscriptionCard, SubscriptionList, SubscriptionRow, SubscriptionsIcon, SubscriptionsIcon20, TagPills, TimePicker, Toast, TwoColumnGrid, VariantSelector, VolumePricing, WelcomeCard, WholesaleProductCard, WholesaleProductLayout, WishlistButton, chatTimeline, clearOrdersCache, cn, createPlacesSessionToken, dayLabel, defaultBoundaryKind, deliveryState, genUICatalog, genUIFingerprint, genUIManifest, genUIManifestJson, getBoundaryLabels, groupPosition, isImageAttachment, isOptimistic, isTerminalOrderStatus, optimisticId, parse as parseGenUIProgram, partitionMessages, prefersReducedMotion, prefetchProduct, prefetchProducts, proseOf, resolveBoundaryKind, roomToResource, safeAttachmentUrl, sameDay, sanitizeRichTextHtml, scrollBehavior, stripHtmlToText, swipeCommitted, swipeProgress, swipeTravel, toAccountLineItem, toAccountLineItems, toAccountOrderView, useActivityState, useAds, useAttributeDefinitions, useAvailableSlots, useBillingPlans, useBookings, useBootstrap, useBundles, useCart, useCartDrawer, useCategories, useChat, useCheckout, useCimplify, useCimplifyClient, useCimplifySession, useCollection, useCollections, useDeals, useDeliveryFee, useDeliveryOptions, useElements, useElementsReady, useFxRate, useGenUIProgram, useLocations, useOptionalCimplify, useOrder, useOrders, useProduct, useProductAvailability, useProductDeals, useProductPrice, useProductSchedules, useProducts, useProductsOnSale, usePropertyFacets, useQuote, useRecommendations, useSearch, useServiceAvailability, useServices, useStoreCredit, useSubscription, useSubscriptions, useSwipeReply, useTaxonomies, useTaxonomy, useTaxonomyPath, useValidateDiscount, useVariantSelector };
|