@customerhero/react 2.1.0 → 2.2.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/index.cjs CHANGED
@@ -27,7 +27,7 @@ __export(index_exports, {
27
27
  module.exports = __toCommonJS(index_exports);
28
28
 
29
29
  // src/components/chat-widget.tsx
30
- var import_react10 = require("react");
30
+ var import_react11 = require("react");
31
31
 
32
32
  // src/context.tsx
33
33
  var import_react = require("react");
@@ -118,6 +118,10 @@ function useChat() {
118
118
  consumePendingPrefill: (0, import_react2.useCallback)(
119
119
  () => client.consumePendingPrefill(),
120
120
  [client]
121
+ ),
122
+ dismissIncidentBanner: (0, import_react2.useCallback)(
123
+ () => client.dismissIncidentBanner(),
124
+ [client]
121
125
  )
122
126
  };
123
127
  }
@@ -207,7 +211,7 @@ function ChatBubble() {
207
211
  }
208
212
 
209
213
  // src/components/chat-window.tsx
210
- var import_react9 = require("react");
214
+ var import_react10 = require("react");
211
215
 
212
216
  // src/components/chat-header.tsx
213
217
  var import_react5 = require("react");
@@ -732,9 +736,11 @@ function renderMarkdown(source, opts = {}) {
732
736
  style: {
733
737
  margin: "0 0 8px",
734
738
  paddingLeft: 20,
735
- lineHeight: 1.5
739
+ lineHeight: 1.5,
740
+ listStyleType: "disc",
741
+ listStylePosition: "outside"
736
742
  },
737
- children: block.lines.map((l, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("li", { children: renderInline(l) }, i))
743
+ children: block.lines.map((l, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("li", { style: { display: "list-item" }, children: renderInline(l) }, i))
738
744
  },
739
745
  key
740
746
  );
@@ -745,9 +751,11 @@ function renderMarkdown(source, opts = {}) {
745
751
  style: {
746
752
  margin: "0 0 8px",
747
753
  paddingLeft: 22,
748
- lineHeight: 1.5
754
+ lineHeight: 1.5,
755
+ listStyleType: "decimal",
756
+ listStylePosition: "outside"
749
757
  },
750
- children: block.lines.map((l, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("li", { children: renderInline(l) }, i))
758
+ children: block.lines.map((l, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("li", { style: { display: "list-item" }, children: renderInline(l) }, i))
751
759
  },
752
760
  key
753
761
  );
@@ -950,11 +958,11 @@ function MessageStatusPill({
950
958
  const containerStyle = {
951
959
  display: "flex",
952
960
  alignItems: "center",
961
+ justifyContent: "flex-end",
953
962
  gap: 4,
954
963
  marginTop: 2,
955
964
  fontSize: 11,
956
- color: failed ? "#b91c1c" : "#888",
957
- alignSelf: "flex-end"
965
+ color: failed ? "#b91c1c" : "#888"
958
966
  };
959
967
  const labelKey = status === "sending" ? "status_sending" : status === "sent" ? "status_sent" : "status_failed";
960
968
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: containerStyle, "aria-live": "polite", children: [
@@ -1263,13 +1271,20 @@ function Message({
1263
1271
  };
1264
1272
  const linkColor = isUser ? "#ffffff" : config.primaryColor;
1265
1273
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(AnimatedMessage, { isUser, animate, reduced, children: [
1266
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: bubbleStyle, children: isUser ? message.content : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1267
- renderMarkdown(message.content, {
1268
- sources: message.sources,
1269
- linkColor
1270
- }),
1271
- message.streaming && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(StreamingCursor, { reduced })
1272
- ] }) }),
1274
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1275
+ "div",
1276
+ {
1277
+ style: bubbleStyle,
1278
+ "data-streaming-bubble": !isUser && message.streaming ? "true" : void 0,
1279
+ children: isUser ? message.content : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1280
+ renderMarkdown(message.content, {
1281
+ sources: message.sources,
1282
+ linkColor
1283
+ }),
1284
+ message.streaming && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(StreamingCursor, { reduced })
1285
+ ] })
1286
+ }
1287
+ ),
1273
1288
  isUser && message.status && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MessageStatusPill, { status: message.status, t }),
1274
1289
  !isUser && message.blocks?.map((block, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1275
1290
  BlockRenderer,
@@ -1354,16 +1369,51 @@ function ChatMessages() {
1354
1369
  t
1355
1370
  } = useChat();
1356
1371
  const reduced = useReducedMotion();
1372
+ const containerRef = (0, import_react7.useRef)(null);
1357
1373
  const messagesEndRef = (0, import_react7.useRef)(null);
1358
1374
  const isFirstRender = (0, import_react7.useRef)(true);
1359
1375
  const prevMessageCount = (0, import_react7.useRef)(0);
1376
+ const stickRef = (0, import_react7.useRef)(true);
1377
+ const suppressScrollRef = (0, import_react7.useRef)(false);
1378
+ const autoScrollTo = (top) => {
1379
+ const el = containerRef.current;
1380
+ if (!el) return;
1381
+ suppressScrollRef.current = true;
1382
+ el.scrollTop = top;
1383
+ requestAnimationFrame(() => {
1384
+ suppressScrollRef.current = false;
1385
+ });
1386
+ };
1387
+ const handleScroll = () => {
1388
+ if (suppressScrollRef.current) return;
1389
+ const el = containerRef.current;
1390
+ if (!el) return;
1391
+ const distFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight;
1392
+ stickRef.current = distFromBottom < 60;
1393
+ };
1360
1394
  (0, import_react7.useEffect)(() => {
1361
- if (messagesEndRef.current) {
1362
- messagesEndRef.current.scrollIntoView({
1363
- behavior: isFirstRender.current || reduced ? "auto" : "smooth"
1364
- });
1365
- isFirstRender.current = false;
1395
+ const el = containerRef.current;
1396
+ if (!el) return;
1397
+ const lastMsg2 = messages[messages.length - 1];
1398
+ if (messages.length > prevMessageCount.current && lastMsg2?.role === "user") {
1399
+ stickRef.current = true;
1366
1400
  }
1401
+ if (!stickRef.current && !isFirstRender.current) {
1402
+ return;
1403
+ }
1404
+ const streamingBubble = el.querySelector(
1405
+ "[data-streaming-bubble='true']"
1406
+ );
1407
+ let target = el.scrollHeight - el.clientHeight;
1408
+ if (streamingBubble && streamingBubble.offsetHeight > el.clientHeight - 24) {
1409
+ const containerTop = el.getBoundingClientRect().top;
1410
+ const bubbleTop = streamingBubble.getBoundingClientRect().top;
1411
+ const TOP_GAP = 16;
1412
+ target = el.scrollTop + (bubbleTop - containerTop) - TOP_GAP;
1413
+ stickRef.current = false;
1414
+ }
1415
+ autoScrollTo(target);
1416
+ isFirstRender.current = false;
1367
1417
  }, [messages, isLoading, reduced]);
1368
1418
  const newStartIndex = isFirstRender.current ? messages.length : prevMessageCount.current;
1369
1419
  (0, import_react7.useEffect)(() => {
@@ -1386,7 +1436,7 @@ function ChatMessages() {
1386
1436
  };
1387
1437
  const lastMsg = messages[messages.length - 1];
1388
1438
  const waitingForFirstToken = isLoading && (lastMsg?.role !== "bot" || lastMsg.streaming !== true);
1389
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: containerStyle, children: [
1439
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { ref: containerRef, style: containerStyle, onScroll: handleScroll, children: [
1390
1440
  messages.map((msg, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1391
1441
  Message,
1392
1442
  {
@@ -1505,12 +1555,23 @@ function ChatInput() {
1505
1555
  const [dragActive, setDragActive] = (0, import_react8.useState)(false);
1506
1556
  const [transientError, setTransientError] = (0, import_react8.useState)(null);
1507
1557
  const fileInputRef = (0, import_react8.useRef)(null);
1558
+ const textInputRef = (0, import_react8.useRef)(null);
1508
1559
  const menuRef = (0, import_react8.useRef)(null);
1509
1560
  const menuButtonRef = (0, import_react8.useRef)(null);
1510
1561
  const dragCounterRef = (0, import_react8.useRef)(0);
1511
1562
  (0, import_react8.useEffect)(() => {
1512
1563
  setCaptureSupported((0, import_js2.canCaptureScreenshot)());
1513
1564
  }, []);
1565
+ (0, import_react8.useEffect)(() => {
1566
+ const id = requestAnimationFrame(() => textInputRef.current?.focus());
1567
+ return () => cancelAnimationFrame(id);
1568
+ }, []);
1569
+ (0, import_react8.useLayoutEffect)(() => {
1570
+ const el = textInputRef.current;
1571
+ if (!el) return;
1572
+ el.style.height = "auto";
1573
+ el.style.height = `${el.scrollHeight}px`;
1574
+ }, [value]);
1514
1575
  (0, import_react8.useEffect)(() => {
1515
1576
  if (pendingPrefill === null) return;
1516
1577
  const text = consumePendingPrefill();
@@ -1688,19 +1749,27 @@ function ChatInput() {
1688
1749
  };
1689
1750
  const rowStyle = {
1690
1751
  display: "flex",
1691
- alignItems: "center",
1752
+ // Anchor the icon buttons to the bottom of the row so a multi-line
1753
+ // textarea grows upward without dragging them along.
1754
+ alignItems: "flex-end",
1692
1755
  gap: 8
1693
1756
  };
1757
+ const TEXTAREA_MAX_HEIGHT = 140;
1694
1758
  const inputStyle = {
1695
1759
  flex: 1,
1696
1760
  border: "1px solid #e0e0e0",
1697
- borderRadius: 24,
1761
+ borderRadius: 18,
1698
1762
  padding: "10px 16px",
1699
1763
  fontSize: 14,
1764
+ lineHeight: 1.4,
1700
1765
  outline: "none",
1701
1766
  background: "#fafafa",
1702
1767
  color: config.textColor,
1703
- fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"
1768
+ fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
1769
+ resize: "none",
1770
+ overflowY: "auto",
1771
+ maxHeight: TEXTAREA_MAX_HEIGHT,
1772
+ boxSizing: "border-box"
1704
1773
  };
1705
1774
  const sendButtonStyle = {
1706
1775
  width: 36,
@@ -1758,6 +1827,7 @@ function ChatInput() {
1758
1827
  fontSize: 14,
1759
1828
  color: "#333",
1760
1829
  textAlign: "left",
1830
+ whiteSpace: "nowrap",
1761
1831
  fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"
1762
1832
  };
1763
1833
  const dropOverlayStyle = {
@@ -1884,9 +1954,10 @@ function ChatInput() {
1884
1954
  }
1885
1955
  ),
1886
1956
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1887
- "input",
1957
+ "textarea",
1888
1958
  {
1889
- type: "text",
1959
+ ref: textInputRef,
1960
+ rows: 1,
1890
1961
  value,
1891
1962
  onChange: (e) => setValue(e.target.value),
1892
1963
  onKeyDown: handleKeyDown,
@@ -2159,8 +2230,231 @@ function Spinner2() {
2159
2230
  ] });
2160
2231
  }
2161
2232
 
2162
- // src/components/chat-window.tsx
2233
+ // src/components/incident-banner.tsx
2234
+ var import_react9 = require("react");
2163
2235
  var import_jsx_runtime9 = require("react/jsx-runtime");
2236
+ var PALETTE = {
2237
+ info: {
2238
+ bg: "#EFF6FF",
2239
+ fg: "#1E3A8A",
2240
+ fgMuted: "#3B5BA9",
2241
+ accent: "#2563EB",
2242
+ iconBg: "#DBEAFE",
2243
+ iconFg: "#2563EB"
2244
+ },
2245
+ warning: {
2246
+ bg: "#FFFBEB",
2247
+ fg: "#78350F",
2248
+ fgMuted: "#92541A",
2249
+ accent: "#B45309",
2250
+ iconBg: "#FEF3C7",
2251
+ iconFg: "#B45309"
2252
+ },
2253
+ outage: {
2254
+ bg: "#FEF2F2",
2255
+ fg: "#991B1B",
2256
+ fgMuted: "#B23A3A",
2257
+ accent: "#DC2626",
2258
+ iconBg: "#FEE2E2",
2259
+ iconFg: "#DC2626"
2260
+ }
2261
+ };
2262
+ function SeverityIcon({
2263
+ severity,
2264
+ color
2265
+ }) {
2266
+ const props = {
2267
+ width: 14,
2268
+ height: 14,
2269
+ viewBox: "0 0 24 24",
2270
+ fill: "none",
2271
+ stroke: color,
2272
+ strokeWidth: 2.25,
2273
+ strokeLinecap: "round",
2274
+ strokeLinejoin: "round",
2275
+ "aria-hidden": true
2276
+ };
2277
+ if (severity === "outage") {
2278
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("svg", { ...props, children: [
2279
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
2280
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
2281
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
2282
+ ] });
2283
+ }
2284
+ if (severity === "warning") {
2285
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("svg", { ...props, children: [
2286
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" }),
2287
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "12", y1: "9", x2: "12", y2: "13" }),
2288
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
2289
+ ] });
2290
+ }
2291
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("svg", { ...props, children: [
2292
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
2293
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "12", y1: "16", x2: "12", y2: "12" }),
2294
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "12", y1: "8", x2: "12.01", y2: "8" })
2295
+ ] });
2296
+ }
2297
+ function IncidentBanner() {
2298
+ const { incidentBanner, incidentBannerDismissed, dismissIncidentBanner, t } = useChat();
2299
+ const [linkHover, setLinkHover] = (0, import_react9.useState)(false);
2300
+ const [closeHover, setCloseHover] = (0, import_react9.useState)(false);
2301
+ if (!incidentBanner || incidentBannerDismissed) return null;
2302
+ const palette = PALETTE[incidentBanner.severity];
2303
+ const wrap = {
2304
+ background: palette.bg,
2305
+ color: palette.fg,
2306
+ padding: "12px 14px 12px 12px",
2307
+ display: "flex",
2308
+ gap: 10,
2309
+ alignItems: "flex-start",
2310
+ fontSize: 13,
2311
+ lineHeight: 1.45,
2312
+ boxShadow: "inset 0 -1px 0 rgba(0,0,0,0.04)"
2313
+ };
2314
+ const iconBadge = {
2315
+ width: 22,
2316
+ height: 22,
2317
+ borderRadius: "50%",
2318
+ background: palette.iconBg,
2319
+ display: "flex",
2320
+ alignItems: "center",
2321
+ justifyContent: "center",
2322
+ flexShrink: 0,
2323
+ marginTop: 1
2324
+ };
2325
+ const titleStyle = {
2326
+ margin: 0,
2327
+ fontSize: 13,
2328
+ fontWeight: 600,
2329
+ letterSpacing: "-0.005em"
2330
+ };
2331
+ const bodyStyle = {
2332
+ margin: "3px 0 0",
2333
+ fontSize: 12.5,
2334
+ color: palette.fgMuted
2335
+ };
2336
+ const footerRowStyle = {
2337
+ display: "flex",
2338
+ flexWrap: "wrap",
2339
+ alignItems: "center",
2340
+ gap: 10,
2341
+ marginTop: 8
2342
+ };
2343
+ const etaStyle = {
2344
+ display: "inline-block",
2345
+ padding: "2px 8px",
2346
+ borderRadius: 4,
2347
+ fontSize: 11,
2348
+ fontWeight: 500,
2349
+ color: palette.accent,
2350
+ background: palette.iconBg,
2351
+ lineHeight: 1.4
2352
+ };
2353
+ const linkStyle = {
2354
+ display: "inline-flex",
2355
+ alignItems: "center",
2356
+ gap: 4,
2357
+ color: palette.accent,
2358
+ textDecoration: linkHover ? "underline" : "none",
2359
+ textUnderlineOffset: 3,
2360
+ fontSize: 12.5,
2361
+ fontWeight: 600
2362
+ };
2363
+ const closeButtonStyle = {
2364
+ background: closeHover ? "rgba(0,0,0,0.06)" : "transparent",
2365
+ border: "none",
2366
+ color: palette.fgMuted,
2367
+ cursor: "pointer",
2368
+ padding: 4,
2369
+ borderRadius: 6,
2370
+ flexShrink: 0,
2371
+ lineHeight: 0,
2372
+ marginTop: -2,
2373
+ marginRight: -2,
2374
+ transition: "background-color 0.12s ease"
2375
+ };
2376
+ const role = incidentBanner.severity === "outage" ? "alert" : "status";
2377
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { role, style: wrap, children: [
2378
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: iconBadge, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2379
+ SeverityIcon,
2380
+ {
2381
+ severity: incidentBanner.severity,
2382
+ color: palette.iconFg
2383
+ }
2384
+ ) }),
2385
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
2386
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { style: titleStyle, children: incidentBanner.title }),
2387
+ incidentBanner.body ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { style: bodyStyle, children: incidentBanner.body }) : null,
2388
+ incidentBanner.eta || incidentBanner.link ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: footerRowStyle, children: [
2389
+ incidentBanner.eta ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: etaStyle, children: incidentBanner.eta }) : null,
2390
+ incidentBanner.link ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2391
+ "a",
2392
+ {
2393
+ href: incidentBanner.link.url,
2394
+ target: "_blank",
2395
+ rel: "noopener noreferrer",
2396
+ style: linkStyle,
2397
+ onMouseEnter: () => setLinkHover(true),
2398
+ onMouseLeave: () => setLinkHover(false),
2399
+ children: [
2400
+ incidentBanner.link.label ?? t("incident_default_link_label"),
2401
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2402
+ "svg",
2403
+ {
2404
+ width: "12",
2405
+ height: "12",
2406
+ viewBox: "0 0 24 24",
2407
+ fill: "none",
2408
+ stroke: "currentColor",
2409
+ strokeWidth: "2.5",
2410
+ strokeLinecap: "round",
2411
+ strokeLinejoin: "round",
2412
+ "aria-hidden": "true",
2413
+ children: [
2414
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "5", y1: "12", x2: "19", y2: "12" }),
2415
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("polyline", { points: "12 5 19 12 12 19" })
2416
+ ]
2417
+ }
2418
+ )
2419
+ ]
2420
+ }
2421
+ ) : null
2422
+ ] }) : null
2423
+ ] }),
2424
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2425
+ "button",
2426
+ {
2427
+ type: "button",
2428
+ onClick: dismissIncidentBanner,
2429
+ "aria-label": t("incident_dismiss"),
2430
+ style: closeButtonStyle,
2431
+ onMouseEnter: () => setCloseHover(true),
2432
+ onMouseLeave: () => setCloseHover(false),
2433
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2434
+ "svg",
2435
+ {
2436
+ width: "14",
2437
+ height: "14",
2438
+ viewBox: "0 0 24 24",
2439
+ fill: "none",
2440
+ stroke: "currentColor",
2441
+ strokeWidth: "2",
2442
+ strokeLinecap: "round",
2443
+ strokeLinejoin: "round",
2444
+ "aria-hidden": "true",
2445
+ children: [
2446
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
2447
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
2448
+ ]
2449
+ }
2450
+ )
2451
+ }
2452
+ )
2453
+ ] });
2454
+ }
2455
+
2456
+ // src/components/chat-window.tsx
2457
+ var import_jsx_runtime10 = require("react/jsx-runtime");
2164
2458
  function ConfigError({ message, title }) {
2165
2459
  const errorStyle = {
2166
2460
  flex: 1,
@@ -2172,8 +2466,8 @@ function ConfigError({ message, title }) {
2172
2466
  textAlign: "center",
2173
2467
  gap: 8
2174
2468
  };
2175
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: errorStyle, children: [
2176
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2469
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: errorStyle, children: [
2470
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2177
2471
  "svg",
2178
2472
  {
2179
2473
  width: "32",
@@ -2185,14 +2479,14 @@ function ConfigError({ message, title }) {
2185
2479
  strokeLinecap: "round",
2186
2480
  strokeLinejoin: "round",
2187
2481
  children: [
2188
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
2189
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
2190
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
2482
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
2483
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
2484
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
2191
2485
  ]
2192
2486
  }
2193
2487
  ),
2194
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { style: { fontSize: 14, fontWeight: 500, color: "#333", margin: 0 }, children: title }),
2195
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { style: { fontSize: 12, color: "#999", margin: 0 }, children: message })
2488
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: { fontSize: 14, fontWeight: 500, color: "#333", margin: 0 }, children: title }),
2489
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: { fontSize: 12, color: "#999", margin: 0 }, children: message })
2196
2490
  ] });
2197
2491
  }
2198
2492
  function fieldKey(field) {
@@ -2219,9 +2513,9 @@ function validateField(field, value) {
2219
2513
  }
2220
2514
  function PreChatFormView() {
2221
2515
  const { preChatForm, submitPreChatForm, cancelPreChatForm, config, t } = useChat();
2222
- const [values, setValues] = (0, import_react9.useState)({});
2223
- const [errors, setErrors] = (0, import_react9.useState)({});
2224
- const [submitting, setSubmitting] = (0, import_react9.useState)(false);
2516
+ const [values, setValues] = (0, import_react10.useState)({});
2517
+ const [errors, setErrors] = (0, import_react10.useState)({});
2518
+ const [submitting, setSubmitting] = (0, import_react10.useState)(false);
2225
2519
  if (!preChatForm) return null;
2226
2520
  function setValue(key, value) {
2227
2521
  setValues((prev) => ({ ...prev, [key]: value }));
@@ -2317,15 +2611,15 @@ function PreChatFormView() {
2317
2611
  fontSize: 14,
2318
2612
  cursor: "pointer"
2319
2613
  };
2320
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2614
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2321
2615
  "form",
2322
2616
  {
2323
2617
  style: containerStyle,
2324
2618
  onSubmit: handleSubmit,
2325
2619
  "data-customerhero-prechat-form": true,
2326
2620
  children: [
2327
- preChatForm.title && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h3", { style: { fontSize: 16, fontWeight: 600, margin: 0 }, children: preChatForm.title }),
2328
- preChatForm.description && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { style: { fontSize: 13, margin: 0, opacity: 0.8 }, children: preChatForm.description }),
2621
+ preChatForm.title && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h3", { style: { fontSize: 16, fontWeight: 600, margin: 0 }, children: preChatForm.title }),
2622
+ preChatForm.description && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: { fontSize: 13, margin: 0, opacity: 0.8 }, children: preChatForm.description }),
2329
2623
  preChatForm.fields.map((field) => {
2330
2624
  const k = fieldKey(field);
2331
2625
  const v = values[k];
@@ -2333,12 +2627,12 @@ function PreChatFormView() {
2333
2627
  const required = "required" in field ? !!field.required : false;
2334
2628
  const label = fieldLabel(field);
2335
2629
  if (field.kind === "textarea") {
2336
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { style: labelStyle, children: [
2337
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { children: [
2630
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { style: labelStyle, children: [
2631
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { children: [
2338
2632
  label,
2339
2633
  required && " *"
2340
2634
  ] }),
2341
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2635
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2342
2636
  "textarea",
2343
2637
  {
2344
2638
  style: { ...inputStyle, minHeight: 80, resize: "vertical" },
@@ -2347,32 +2641,32 @@ function PreChatFormView() {
2347
2641
  onChange: (e) => setValue(k, e.target.value)
2348
2642
  }
2349
2643
  ),
2350
- err && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: errorStyle, children: err })
2644
+ err && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: errorStyle, children: err })
2351
2645
  ] }, k);
2352
2646
  }
2353
2647
  if (field.kind === "select") {
2354
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { style: labelStyle, children: [
2355
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { children: [
2648
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { style: labelStyle, children: [
2649
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { children: [
2356
2650
  label,
2357
2651
  required && " *"
2358
2652
  ] }),
2359
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2653
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2360
2654
  "select",
2361
2655
  {
2362
2656
  style: inputStyle,
2363
2657
  value: v ?? "",
2364
2658
  onChange: (e) => setValue(k, e.target.value),
2365
2659
  children: [
2366
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("option", { value: "", children: "\u2014" }),
2367
- field.options.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("option", { value: opt.value, children: opt.label }, opt.value))
2660
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "", children: "\u2014" }),
2661
+ field.options.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: opt.value, children: opt.label }, opt.value))
2368
2662
  ]
2369
2663
  }
2370
2664
  ),
2371
- err && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: errorStyle, children: err })
2665
+ err && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: errorStyle, children: err })
2372
2666
  ] }, k);
2373
2667
  }
2374
2668
  if (field.kind === "consent") {
2375
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2669
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2376
2670
  "label",
2377
2671
  {
2378
2672
  style: {
@@ -2382,7 +2676,7 @@ function PreChatFormView() {
2382
2676
  gap: 8
2383
2677
  },
2384
2678
  children: [
2385
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2679
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2386
2680
  "input",
2387
2681
  {
2388
2682
  type: "checkbox",
@@ -2391,11 +2685,11 @@ function PreChatFormView() {
2391
2685
  style: { marginTop: 3 }
2392
2686
  }
2393
2687
  ),
2394
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { style: { fontSize: 13, fontWeight: 400 }, children: [
2688
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { style: { fontSize: 13, fontWeight: 400 }, children: [
2395
2689
  field.label,
2396
- field.url && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
2690
+ field.url && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
2397
2691
  " ",
2398
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2692
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2399
2693
  "a",
2400
2694
  {
2401
2695
  href: field.url,
@@ -2407,7 +2701,7 @@ function PreChatFormView() {
2407
2701
  )
2408
2702
  ] })
2409
2703
  ] }),
2410
- err && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: errorStyle, children: err })
2704
+ err && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: errorStyle, children: err })
2411
2705
  ]
2412
2706
  },
2413
2707
  k
@@ -2415,12 +2709,12 @@ function PreChatFormView() {
2415
2709
  }
2416
2710
  const inputType = field.kind === "email" ? "email" : field.kind === "phone" ? "tel" : "text";
2417
2711
  const maxLength = field.kind === "text" ? field.maxLength : void 0;
2418
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { style: labelStyle, children: [
2419
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { children: [
2712
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { style: labelStyle, children: [
2713
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { children: [
2420
2714
  label,
2421
2715
  required && " *"
2422
2716
  ] }),
2423
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2717
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2424
2718
  "input",
2425
2719
  {
2426
2720
  type: inputType,
@@ -2430,11 +2724,11 @@ function PreChatFormView() {
2430
2724
  onChange: (e) => setValue(k, e.target.value)
2431
2725
  }
2432
2726
  ),
2433
- err && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: errorStyle, children: err })
2727
+ err && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: errorStyle, children: err })
2434
2728
  ] }, k);
2435
2729
  }),
2436
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: buttonRowStyle, children: [
2437
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2730
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: buttonRowStyle, children: [
2731
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2438
2732
  "button",
2439
2733
  {
2440
2734
  type: "button",
@@ -2444,7 +2738,7 @@ function PreChatFormView() {
2444
2738
  children: t("action_cancel")
2445
2739
  }
2446
2740
  ),
2447
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "submit", style: submitStyle, disabled: submitting, children: preChatForm.submitLabel })
2741
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "submit", style: submitStyle, disabled: submitting, children: preChatForm.submitLabel })
2448
2742
  ] })
2449
2743
  ]
2450
2744
  }
@@ -2453,9 +2747,9 @@ function PreChatFormView() {
2453
2747
  function ChatWindow() {
2454
2748
  const { isOpen, config, configError, t, isRtl, preChatFormVisible } = useChat();
2455
2749
  const reduced = useReducedMotion();
2456
- const [visible, setVisible] = (0, import_react9.useState)(false);
2457
- const [shouldRender, setShouldRender] = (0, import_react9.useState)(false);
2458
- (0, import_react9.useEffect)(() => {
2750
+ const [visible, setVisible] = (0, import_react10.useState)(false);
2751
+ const [shouldRender, setShouldRender] = (0, import_react10.useState)(false);
2752
+ (0, import_react10.useEffect)(() => {
2459
2753
  if (isOpen) {
2460
2754
  setShouldRender(true);
2461
2755
  requestAnimationFrame(() => {
@@ -2504,17 +2798,18 @@ function ChatWindow() {
2504
2798
  textDecoration: "underline",
2505
2799
  textUnderlineOffset: 2
2506
2800
  };
2507
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style, dir: isRtl ? "rtl" : "ltr", children: [
2508
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ChatHeader, {}),
2509
- configError ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ConfigError, { title: t("unable_to_load"), message: configError }) : preChatFormVisible ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PreChatFormView, {}) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
2510
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ChatMessages, {}),
2511
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ChatSuggestions, {}),
2512
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ChatInput, {})
2801
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style, dir: isRtl ? "rtl" : "ltr", children: [
2802
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ChatHeader, {}),
2803
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IncidentBanner, {}),
2804
+ configError ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ConfigError, { title: t("unable_to_load"), message: configError }) : preChatFormVisible ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(PreChatFormView, {}) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
2805
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ChatMessages, {}),
2806
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ChatSuggestions, {}),
2807
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ChatInput, {})
2513
2808
  ] }),
2514
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: poweredStyle, children: [
2809
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: poweredStyle, children: [
2515
2810
  t("powered_by"),
2516
2811
  " ",
2517
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2812
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2518
2813
  "a",
2519
2814
  {
2520
2815
  href: "https://customerhero.app",
@@ -2529,12 +2824,12 @@ function ChatWindow() {
2529
2824
  }
2530
2825
 
2531
2826
  // src/components/chat-widget.tsx
2532
- var import_jsx_runtime10 = require("react/jsx-runtime");
2827
+ var import_jsx_runtime11 = require("react/jsx-runtime");
2533
2828
  function ChatWidgetInner({ identity }) {
2534
2829
  const client = useCustomerHeroClient();
2535
2830
  const { configLoaded, configError } = useChat();
2536
- const prevIdentityRef = (0, import_react10.useRef)(void 0);
2537
- (0, import_react10.useEffect)(() => {
2831
+ const prevIdentityRef = (0, import_react11.useRef)(void 0);
2832
+ (0, import_react11.useEffect)(() => {
2538
2833
  const key = identity ? JSON.stringify(identity) : void 0;
2539
2834
  if (key !== prevIdentityRef.current) {
2540
2835
  prevIdentityRef.current = key;
@@ -2544,13 +2839,13 @@ function ChatWidgetInner({ identity }) {
2544
2839
  }
2545
2840
  }, [identity, client]);
2546
2841
  if (!configLoaded || configError) return null;
2547
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
2548
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ChatBubble, {}),
2549
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ChatWindow, {})
2842
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
2843
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ChatBubble, {}),
2844
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ChatWindow, {})
2550
2845
  ] });
2551
2846
  }
2552
2847
  function ChatWidget({ identity, ...config }) {
2553
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CustomerHeroProvider, { ...config, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ChatWidgetInner, { identity }) });
2848
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(CustomerHeroProvider, { ...config, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ChatWidgetInner, { identity }) });
2554
2849
  }
2555
2850
  // Annotate the CommonJS export names for ESM import in node:
2556
2851
  0 && (module.exports = {