@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/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-RRBY35TJ.mjs';
3
- export { getVariantDisplayName } from './chunk-RRBY35TJ.mjs';
4
- import { messagePreview, splitGenUIContent } from './chunk-U4MW6PYU.mjs';
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, useContext, useMemo, useRef, useState, useCallback, useEffect, useId, useSyncExternalStore } from 'react';
12
- import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
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
- var MAX_ATTACHMENT_BYTES = 5 * 1024 * 1024;
17150
- var KEEP_DISMISSED_KEY = "cimplify_keep_chat_dismissed";
17151
- var AT_BOTTOM_SLACK_PX = 48;
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 lastSeenCustomerMessageId(bubbles, seenAt) {
17569
- if (!seenAt || !bubbles.some((m) => m.sender_type === "agent")) return null;
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 partitioned = partitionMessages(messages);
17601
- const bubbles = partitioned.bubbles.filter(
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
- className: cn(
17617
- "flex flex-1 flex-col gap-1 overflow-y-auto bg-muted/50 px-5 py-5",
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-2", children: /* @__PURE__ */ jsx(
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-border bg-background px-3 py-1 text-[11px] font-semibold text-muted-foreground hover:text-foreground",
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
- if (msg.sender_type === "system") {
17639
- return /* @__PURE__ */ jsx("div", { className: "my-2 text-center text-[11px] font-medium text-muted-foreground", children: msg.content }, msg.id);
17640
- }
17641
- return /* @__PURE__ */ jsxs("div", { children: [
17642
- newDay && /* @__PURE__ */ jsx("div", { className: "my-2 text-center text-[10px] font-semibold tracking-wide text-muted-foreground", children: dayLabel(msg.created_at) }),
17643
- !sameSenderAsPrev && i > 0 && /* @__PURE__ */ jsx("div", { className: "h-3" }),
17644
- /* @__PURE__ */ jsxs(
17645
- "div",
17646
- {
17647
- className: cn(
17648
- "group relative flex max-w-[85%]",
17649
- isCustomer ? "ml-auto" : "mr-auto"
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
- children: [
17652
- !isCustomer && !optimistic && /* @__PURE__ */ jsx(HoverRail, { message: msg, onReact, onReply }),
17653
- /* @__PURE__ */ jsxs(
17654
- "div",
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
- className: cn(
17657
- "rounded-2xl px-3.5 py-2.5 text-sm leading-relaxed",
17658
- isCustomer ? "bg-foreground text-background" : "border border-border bg-background text-foreground",
17659
- isCustomer ? sameSenderAsPrev ? "rounded-tr" : "rounded-br" : sameSenderAsPrev ? "rounded-tl" : "rounded-bl",
17660
- optimistic && "opacity-70"
17661
- ),
17662
- children: [
17663
- !sameSenderAsPrev && /* @__PURE__ */ jsx(SenderChip, { sender: msg.sender_type, businessName }),
17664
- msg.reply_to && /* @__PURE__ */ jsxs(
17665
- "div",
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
- reactions && reactions.length > 0 && /* @__PURE__ */ jsx("div", { className: cn("mt-0.5 flex gap-1", isCustomer ? "justify-end" : "justify-start"), children: reactions.map((reaction) => /* @__PURE__ */ jsx(
17722
- "span",
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 };