@prodact.ai/sdk 0.0.9 → 0.0.11

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.js CHANGED
@@ -1247,7 +1247,7 @@ var UserFlowTracker = class {
1247
1247
  samplingRate: this.config.samplingRate,
1248
1248
  currentState: this.state,
1249
1249
  apiUrl: this.apiUrl,
1250
- hasSessionToken: !!this.sessionToken
1250
+ hasSessionToken: !!this.sdkSessionToken
1251
1251
  });
1252
1252
  if (!this.config.enabled) {
1253
1253
  console.warn("[UserFlow] Tracking disabled by config");
@@ -1373,6 +1373,57 @@ var UserFlowTracker = class {
1373
1373
  isTracking() {
1374
1374
  return this.state === "tracking";
1375
1375
  }
1376
+ /**
1377
+ * Get recent events for context (excludes SDK UI interactions like chat widget)
1378
+ * @param limit - Maximum number of events to return (default: 10)
1379
+ * @param excludeSelectors - CSS selectors to exclude (default: produck SDK elements)
1380
+ */
1381
+ getRecentEvents(limit = 10, excludeSelectors) {
1382
+ const defaultExcludeSelectors = [
1383
+ "[data-produck-chat]",
1384
+ ".produck-chat",
1385
+ ".produck-widget",
1386
+ "#produck-chat",
1387
+ "#produck-widget",
1388
+ '[class*="produck"]',
1389
+ '[id*="produck"]'
1390
+ ];
1391
+ const selectorsToExclude = excludeSelectors || defaultExcludeSelectors;
1392
+ const filteredEvents = this.events.filter((event) => {
1393
+ if (event.eventType === "navigation") return true;
1394
+ if (event.element?.selector) {
1395
+ const selectorLower = event.element.selector.toLowerCase();
1396
+ const matchesExclude = selectorsToExclude.some((excludeSel) => {
1397
+ const excludeLower = excludeSel.toLowerCase();
1398
+ if (excludeLower.includes("produck")) {
1399
+ return selectorLower.includes("produck");
1400
+ }
1401
+ return selectorLower.includes(excludeLower.replace(/[\[\].*#]/g, ""));
1402
+ });
1403
+ if (matchesExclude) return false;
1404
+ }
1405
+ return true;
1406
+ });
1407
+ return filteredEvents.slice(-limit);
1408
+ }
1409
+ /**
1410
+ * Get recent events as a summary string for chat context
1411
+ */
1412
+ getRecentEventsAsSummary(limit = 10) {
1413
+ const events = this.getRecentEvents(limit);
1414
+ if (events.length === 0) return "";
1415
+ return events.map((event) => {
1416
+ if (event.eventType === "navigation") {
1417
+ return `Navigated to: ${event.pageTitle || event.pagePath}`;
1418
+ } else if (event.eventType === "click" && event.element) {
1419
+ const elementDesc = event.element.text || event.element.tag || "element";
1420
+ return `Clicked: ${elementDesc}${event.pageTitle ? ` on ${event.pageTitle}` : ""}`;
1421
+ } else if (event.eventType === "form_submit") {
1422
+ return `Submitted form on: ${event.pageTitle || event.pagePath}`;
1423
+ }
1424
+ return `${event.eventType}: ${event.pageTitle || event.pagePath}`;
1425
+ }).join("\n");
1426
+ }
1376
1427
  /**
1377
1428
  * Add a custom event
1378
1429
  */
@@ -2015,12 +2066,16 @@ Check the Network tab in DevTools for more details.`
2015
2066
  });
2016
2067
  }
2017
2068
  }
2069
+ const userContext = this.getRecentUserFlowSummary(10);
2018
2070
  const sessionResponse = await fetch(
2019
2071
  `${this.config.apiUrl}/chat/sessions/${this.sessionToken}/message`,
2020
2072
  {
2021
2073
  method: "POST",
2022
2074
  headers: { "Content-Type": "application/json" },
2023
- body: JSON.stringify({ message })
2075
+ body: JSON.stringify({
2076
+ message,
2077
+ userContext: userContext || void 0
2078
+ })
2024
2079
  }
2025
2080
  );
2026
2081
  if (!sessionResponse.ok) {
@@ -2031,11 +2086,13 @@ Check the Network tab in DevTools for more details.`
2031
2086
  role: "assistant",
2032
2087
  content: result.message?.content || result.response || "",
2033
2088
  visualFlows: result.flows || [],
2034
- images: result.images || []
2089
+ images: result.images || [],
2090
+ userFlows: result.userFlows || []
2035
2091
  };
2036
2092
  await this.log("info", "Chat response received", {
2037
2093
  hasFlows: (result.flows || []).length > 0,
2038
- hasImages: (result.images || []).length > 0
2094
+ hasImages: (result.images || []).length > 0,
2095
+ hasUserFlows: (result.userFlows || []).length > 0
2039
2096
  });
2040
2097
  this.emit("message", chatMessage);
2041
2098
  return chatMessage;
@@ -2709,6 +2766,19 @@ Check the Network tab in DevTools for more details.`
2709
2766
  getUserFlowStats() {
2710
2767
  return this.userFlowTracker?.getStats() ?? null;
2711
2768
  }
2769
+ /**
2770
+ * Get recent user flow events (excluding SDK UI interactions)
2771
+ * Useful for providing context to chat
2772
+ */
2773
+ getRecentUserFlowEvents(limit = 10) {
2774
+ return this.userFlowTracker?.getRecentEvents(limit) ?? [];
2775
+ }
2776
+ /**
2777
+ * Get recent user flow events as a summary string for chat context
2778
+ */
2779
+ getRecentUserFlowSummary(limit = 10) {
2780
+ return this.userFlowTracker?.getRecentEventsAsSummary(limit) ?? "";
2781
+ }
2712
2782
  /**
2713
2783
  * Check if user flow tracking is active
2714
2784
  */
@@ -2879,7 +2949,7 @@ function ProduckProvider({
2879
2949
  }
2880
2950
 
2881
2951
  // src/react/ProduckChat.tsx
2882
- var import_react5 = require("react");
2952
+ var import_react6 = require("react");
2883
2953
 
2884
2954
  // src/react/hooks.ts
2885
2955
  var import_react3 = require("react");
@@ -3169,8 +3239,267 @@ function VisualFlowDisplay({
3169
3239
  ] });
3170
3240
  }
3171
3241
 
3172
- // src/react/ProduckChat.tsx
3242
+ // src/react/StepGuide.tsx
3243
+ var import_react5 = require("react");
3173
3244
  var import_jsx_runtime3 = require("react/jsx-runtime");
3245
+ function StepGuide({
3246
+ title,
3247
+ description,
3248
+ steps,
3249
+ theme = "light",
3250
+ primaryColor = "#f97316",
3251
+ onStepClick,
3252
+ hasReplay,
3253
+ onWatchReplay,
3254
+ compact = false
3255
+ }) {
3256
+ const [expandedStep, setExpandedStep] = (0, import_react5.useState)(null);
3257
+ const isDark = theme === "dark";
3258
+ const bgColor = isDark ? "#1f2937" : "#f9fafb";
3259
+ const borderColor = isDark ? "#374151" : "#e5e7eb";
3260
+ const textColor = isDark ? "#f3f4f6" : "#111827";
3261
+ const mutedColor = isDark ? "#9ca3af" : "#6b7280";
3262
+ const stepBgColor = isDark ? "#374151" : "#ffffff";
3263
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3264
+ "div",
3265
+ {
3266
+ style: {
3267
+ backgroundColor: compact ? "transparent" : bgColor,
3268
+ border: compact ? "none" : `1px solid ${borderColor}`,
3269
+ borderRadius: compact ? "0" : "12px",
3270
+ overflow: "hidden",
3271
+ marginTop: compact ? "0" : "12px"
3272
+ },
3273
+ children: [
3274
+ !compact && title && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3275
+ "div",
3276
+ {
3277
+ style: {
3278
+ padding: "12px 16px",
3279
+ borderBottom: `1px solid ${borderColor}`,
3280
+ backgroundColor: isDark ? "#111827" : "#ffffff"
3281
+ },
3282
+ children: [
3283
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
3284
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { fontSize: "18px" }, children: "\u{1F4CB}" }),
3285
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3286
+ "span",
3287
+ {
3288
+ style: {
3289
+ fontWeight: 600,
3290
+ fontSize: "14px",
3291
+ color: textColor
3292
+ },
3293
+ children: title
3294
+ }
3295
+ )
3296
+ ] }),
3297
+ description && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3298
+ "p",
3299
+ {
3300
+ style: {
3301
+ marginTop: "4px",
3302
+ fontSize: "12px",
3303
+ color: mutedColor,
3304
+ lineHeight: 1.4
3305
+ },
3306
+ children: description
3307
+ }
3308
+ )
3309
+ ]
3310
+ }
3311
+ ),
3312
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { padding: compact ? "0" : "12px" }, children: steps.map((step, index) => {
3313
+ const isLast = index === steps.length - 1;
3314
+ const isExpanded = expandedStep === index;
3315
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3316
+ "div",
3317
+ {
3318
+ style: {
3319
+ display: "flex",
3320
+ gap: "12px",
3321
+ cursor: onStepClick ? "pointer" : "default"
3322
+ },
3323
+ onClick: () => {
3324
+ if (onStepClick) {
3325
+ onStepClick(step, index);
3326
+ }
3327
+ setExpandedStep(isExpanded ? null : index);
3328
+ },
3329
+ children: [
3330
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3331
+ "div",
3332
+ {
3333
+ style: {
3334
+ display: "flex",
3335
+ flexDirection: "column",
3336
+ alignItems: "center",
3337
+ width: "24px"
3338
+ },
3339
+ children: [
3340
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3341
+ "div",
3342
+ {
3343
+ style: {
3344
+ width: "24px",
3345
+ height: "24px",
3346
+ borderRadius: "50%",
3347
+ backgroundColor: primaryColor,
3348
+ color: "#ffffff",
3349
+ display: "flex",
3350
+ alignItems: "center",
3351
+ justifyContent: "center",
3352
+ fontSize: "12px",
3353
+ fontWeight: 600,
3354
+ flexShrink: 0
3355
+ },
3356
+ children: step.stepNumber
3357
+ }
3358
+ ),
3359
+ !isLast && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3360
+ "div",
3361
+ {
3362
+ style: {
3363
+ width: "2px",
3364
+ flexGrow: 1,
3365
+ minHeight: "20px",
3366
+ backgroundColor: isDark ? "#4b5563" : "#d1d5db",
3367
+ marginTop: "4px"
3368
+ }
3369
+ }
3370
+ )
3371
+ ]
3372
+ }
3373
+ ),
3374
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3375
+ "div",
3376
+ {
3377
+ style: {
3378
+ flex: 1,
3379
+ paddingBottom: isLast ? 0 : "16px"
3380
+ },
3381
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3382
+ "div",
3383
+ {
3384
+ style: {
3385
+ backgroundColor: stepBgColor,
3386
+ border: `1px solid ${borderColor}`,
3387
+ borderRadius: "8px",
3388
+ padding: "10px 12px",
3389
+ transition: "all 0.2s ease"
3390
+ },
3391
+ children: [
3392
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3393
+ "div",
3394
+ {
3395
+ style: {
3396
+ fontSize: "13px",
3397
+ fontWeight: 500,
3398
+ color: textColor,
3399
+ lineHeight: 1.4
3400
+ },
3401
+ children: step.action
3402
+ }
3403
+ ),
3404
+ step.page && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3405
+ "div",
3406
+ {
3407
+ style: {
3408
+ marginTop: "4px",
3409
+ fontSize: "11px",
3410
+ color: mutedColor,
3411
+ display: "flex",
3412
+ alignItems: "center",
3413
+ gap: "4px"
3414
+ },
3415
+ children: [
3416
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "\u{1F4CD}" }),
3417
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: step.page })
3418
+ ]
3419
+ }
3420
+ ),
3421
+ isExpanded && step.details && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3422
+ "div",
3423
+ {
3424
+ style: {
3425
+ marginTop: "8px",
3426
+ paddingTop: "8px",
3427
+ borderTop: `1px solid ${borderColor}`,
3428
+ fontSize: "12px",
3429
+ color: mutedColor,
3430
+ lineHeight: 1.5
3431
+ },
3432
+ children: step.details
3433
+ }
3434
+ )
3435
+ ]
3436
+ }
3437
+ )
3438
+ }
3439
+ )
3440
+ ]
3441
+ },
3442
+ index
3443
+ );
3444
+ }) }),
3445
+ hasReplay && onWatchReplay && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3446
+ "div",
3447
+ {
3448
+ style: {
3449
+ padding: "12px 16px",
3450
+ borderTop: `1px solid ${borderColor}`,
3451
+ backgroundColor: isDark ? "#111827" : "#ffffff"
3452
+ },
3453
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3454
+ "button",
3455
+ {
3456
+ onClick: onWatchReplay,
3457
+ style: {
3458
+ display: "flex",
3459
+ alignItems: "center",
3460
+ justifyContent: "center",
3461
+ gap: "8px",
3462
+ width: "100%",
3463
+ padding: "10px 16px",
3464
+ backgroundColor: primaryColor,
3465
+ color: "#ffffff",
3466
+ border: "none",
3467
+ borderRadius: "8px",
3468
+ fontSize: "13px",
3469
+ fontWeight: 500,
3470
+ cursor: "pointer"
3471
+ },
3472
+ children: [
3473
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "\u25B6\uFE0F" }),
3474
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Watch Full Session Replay" })
3475
+ ]
3476
+ }
3477
+ )
3478
+ }
3479
+ )
3480
+ ]
3481
+ }
3482
+ );
3483
+ }
3484
+ function parseStepsFromStrings(steps) {
3485
+ return steps.map((stepStr, index) => {
3486
+ const stepMatch = stepStr.match(/^(?:Step\s+)?(\d+)[:.]\s*(.+?)(?:\s*\((?:on\s+)?(.+?)\))?$/i);
3487
+ if (stepMatch) {
3488
+ return {
3489
+ stepNumber: parseInt(stepMatch[1], 10),
3490
+ action: stepMatch[2].trim(),
3491
+ page: stepMatch[3]?.trim()
3492
+ };
3493
+ }
3494
+ return {
3495
+ stepNumber: index + 1,
3496
+ action: stepStr.replace(/^(?:Step\s+)?\d+[:.]\s*/i, "").trim()
3497
+ };
3498
+ });
3499
+ }
3500
+
3501
+ // src/react/ProduckChat.tsx
3502
+ var import_jsx_runtime4 = require("react/jsx-runtime");
3174
3503
  function ProduckChat({
3175
3504
  placeholder = "Ask a question...",
3176
3505
  title = "Chat Assistant",
@@ -3191,15 +3520,15 @@ function ProduckChat({
3191
3520
  }) {
3192
3521
  const { messages, isLoading, sendMessage } = useProduckMessages();
3193
3522
  const isReady = useProduckReady();
3194
- const [input, setInput] = (0, import_react5.useState)("");
3195
- const [isOpen, setIsOpen] = (0, import_react5.useState)(position === "inline" ? true : defaultOpen);
3196
- const [isHovering, setIsHovering] = (0, import_react5.useState)(false);
3197
- const messagesEndRef = (0, import_react5.useRef)(null);
3198
- const inputRef = (0, import_react5.useRef)(null);
3199
- const [streamedMessage, setStreamedMessage] = (0, import_react5.useState)("");
3200
- const [isStreamingInitial, setIsStreamingInitial] = (0, import_react5.useState)(false);
3201
- const [hasShownInitial, setHasShownInitial] = (0, import_react5.useState)(false);
3202
- (0, import_react5.useEffect)(() => {
3523
+ const [input, setInput] = (0, import_react6.useState)("");
3524
+ const [isOpen, setIsOpen] = (0, import_react6.useState)(position === "inline" ? true : defaultOpen);
3525
+ const [isHovering, setIsHovering] = (0, import_react6.useState)(false);
3526
+ const messagesEndRef = (0, import_react6.useRef)(null);
3527
+ const inputRef = (0, import_react6.useRef)(null);
3528
+ const [streamedMessage, setStreamedMessage] = (0, import_react6.useState)("");
3529
+ const [isStreamingInitial, setIsStreamingInitial] = (0, import_react6.useState)(false);
3530
+ const [hasShownInitial, setHasShownInitial] = (0, import_react6.useState)(false);
3531
+ (0, import_react6.useEffect)(() => {
3203
3532
  if (autoOpenDelay && autoOpenDelay > 0 && !isOpen && isReady) {
3204
3533
  const timer = setTimeout(() => {
3205
3534
  setIsOpen(true);
@@ -3207,7 +3536,7 @@ function ProduckChat({
3207
3536
  return () => clearTimeout(timer);
3208
3537
  }
3209
3538
  }, [autoOpenDelay, isReady]);
3210
- (0, import_react5.useEffect)(() => {
3539
+ (0, import_react6.useEffect)(() => {
3211
3540
  if (isOpen && initialMessage && isReady && !hasShownInitial) {
3212
3541
  const timer = setTimeout(() => {
3213
3542
  streamInitialMessage(initialMessage);
@@ -3228,12 +3557,12 @@ function ProduckChat({
3228
3557
  }
3229
3558
  setIsStreamingInitial(false);
3230
3559
  };
3231
- (0, import_react5.useEffect)(() => {
3560
+ (0, import_react6.useEffect)(() => {
3232
3561
  if (messagesEndRef.current) {
3233
3562
  messagesEndRef.current.scrollIntoView({ behavior: "smooth" });
3234
3563
  }
3235
3564
  }, [messages]);
3236
- (0, import_react5.useEffect)(() => {
3565
+ (0, import_react6.useEffect)(() => {
3237
3566
  if (isOpen && inputRef.current) {
3238
3567
  setTimeout(() => inputRef.current?.focus(), 100);
3239
3568
  }
@@ -3327,7 +3656,7 @@ function ProduckChat({
3327
3656
  backgroundColor: isDark ? "#111827" : "#f9fafb",
3328
3657
  flexShrink: 0
3329
3658
  };
3330
- const renderFloatingButton = () => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: containerStyles, className, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3659
+ const renderFloatingButton = () => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: containerStyles, className, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3331
3660
  "button",
3332
3661
  {
3333
3662
  onClick: () => setIsOpen(true),
@@ -3359,12 +3688,12 @@ function ProduckChat({
3359
3688
  return renderFloatingButton();
3360
3689
  }
3361
3690
  if (position === "inline" && !isReady) {
3362
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: containerStyles, className, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: chatWindowStyles, children: [
3363
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { ...headerStyles, justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
3364
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { animation: "spin 1s linear infinite" }, children: floatingButtonLoadingIcon }),
3691
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: containerStyles, className, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: chatWindowStyles, children: [
3692
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { ...headerStyles, justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
3693
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { animation: "spin 1s linear infinite" }, children: floatingButtonLoadingIcon }),
3365
3694
  "Loading..."
3366
3695
  ] }) }),
3367
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: {
3696
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: {
3368
3697
  flex: 1,
3369
3698
  display: "flex",
3370
3699
  alignItems: "center",
@@ -3373,14 +3702,14 @@ function ProduckChat({
3373
3702
  }, children: "Connecting to chat..." })
3374
3703
  ] }) });
3375
3704
  }
3376
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: containerStyles, className, children: [
3377
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: chatWindowStyles, children: [
3378
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: headerStyles, children: [
3379
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
3380
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: headerIcon }),
3381
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: title })
3705
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: containerStyles, className, children: [
3706
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: chatWindowStyles, children: [
3707
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: headerStyles, children: [
3708
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
3709
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: headerIcon }),
3710
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: title })
3382
3711
  ] }),
3383
- position !== "inline" && showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3712
+ position !== "inline" && showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3384
3713
  "button",
3385
3714
  {
3386
3715
  onClick: () => setIsOpen(false),
@@ -3402,15 +3731,15 @@ function ProduckChat({
3402
3731
  }
3403
3732
  )
3404
3733
  ] }),
3405
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: messagesContainerStyles, children: [
3406
- streamedMessage && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3734
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: messagesContainerStyles, children: [
3735
+ streamedMessage && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3407
3736
  "div",
3408
3737
  {
3409
3738
  style: {
3410
3739
  display: "flex",
3411
3740
  justifyContent: "flex-start"
3412
3741
  },
3413
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3742
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3414
3743
  "div",
3415
3744
  {
3416
3745
  style: {
@@ -3425,7 +3754,7 @@ function ProduckChat({
3425
3754
  },
3426
3755
  children: [
3427
3756
  streamedMessage,
3428
- isStreamingInitial && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3757
+ isStreamingInitial && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3429
3758
  "span",
3430
3759
  {
3431
3760
  style: {
@@ -3443,7 +3772,7 @@ function ProduckChat({
3443
3772
  )
3444
3773
  }
3445
3774
  ),
3446
- messages.length === 0 && !streamedMessage && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3775
+ messages.length === 0 && !streamedMessage && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3447
3776
  "div",
3448
3777
  {
3449
3778
  style: {
@@ -3452,20 +3781,20 @@ function ProduckChat({
3452
3781
  padding: "40px 20px"
3453
3782
  },
3454
3783
  children: [
3455
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { fontSize: "40px", marginBottom: "16px" }, children: emptyStateIcon }),
3456
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { fontSize: typeof fontSize === "number" ? `${fontSize + 2}px` : fontSize, fontWeight: 500 }, children: emptyStateTitle }),
3457
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { fontSize: typeof fontSize === "number" ? `${fontSize}px` : fontSize, marginTop: "8px", opacity: 0.8 }, children: emptyStateSubtitle })
3784
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { fontSize: "40px", marginBottom: "16px" }, children: emptyStateIcon }),
3785
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { fontSize: typeof fontSize === "number" ? `${fontSize + 2}px` : fontSize, fontWeight: 500 }, children: emptyStateTitle }),
3786
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { fontSize: typeof fontSize === "number" ? `${fontSize}px` : fontSize, marginTop: "8px", opacity: 0.8 }, children: emptyStateSubtitle })
3458
3787
  ]
3459
3788
  }
3460
3789
  ),
3461
- messages.map((msg, idx) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3790
+ messages.map((msg, idx) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3462
3791
  "div",
3463
3792
  {
3464
3793
  style: {
3465
3794
  display: "flex",
3466
3795
  justifyContent: msg.role === "user" ? "flex-end" : "flex-start"
3467
3796
  },
3468
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3797
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3469
3798
  "div",
3470
3799
  {
3471
3800
  style: {
@@ -3480,7 +3809,7 @@ function ProduckChat({
3480
3809
  },
3481
3810
  children: [
3482
3811
  msg.content,
3483
- msg.action && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3812
+ msg.action && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3484
3813
  "div",
3485
3814
  {
3486
3815
  style: {
@@ -3494,15 +3823,15 @@ function ProduckChat({
3494
3823
  gap: "6px"
3495
3824
  },
3496
3825
  children: [
3497
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "\u26A1" }),
3498
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
3826
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "\u26A1" }),
3827
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { children: [
3499
3828
  "Action triggered: ",
3500
3829
  msg.action.name
3501
3830
  ] })
3502
3831
  ]
3503
3832
  }
3504
3833
  ),
3505
- msg.visualFlows && msg.visualFlows.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { marginTop: "12px" }, children: msg.visualFlows.map((flowRef, flowIdx) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3834
+ msg.visualFlows && msg.visualFlows.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { marginTop: "12px" }, children: msg.visualFlows.map((flowRef, flowIdx) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3506
3835
  VisualFlowDisplay,
3507
3836
  {
3508
3837
  flowRef,
@@ -3511,7 +3840,7 @@ function ProduckChat({
3511
3840
  },
3512
3841
  flowRef.flowId || flowIdx
3513
3842
  )) }),
3514
- msg.images && msg.images.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { marginTop: "12px" }, children: msg.images.map((img, imgIdx) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3843
+ msg.images && msg.images.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { marginTop: "12px" }, children: msg.images.map((img, imgIdx) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3515
3844
  "div",
3516
3845
  {
3517
3846
  style: {
@@ -3521,7 +3850,7 @@ function ProduckChat({
3521
3850
  border: `1px solid ${isDark ? "#374151" : "#e5e7eb"}`
3522
3851
  },
3523
3852
  children: [
3524
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3853
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3525
3854
  "img",
3526
3855
  {
3527
3856
  src: img.url,
@@ -3533,7 +3862,7 @@ function ProduckChat({
3533
3862
  }
3534
3863
  }
3535
3864
  ),
3536
- img.name && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3865
+ img.name && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3537
3866
  "div",
3538
3867
  {
3539
3868
  style: {
@@ -3548,6 +3877,90 @@ function ProduckChat({
3548
3877
  ]
3549
3878
  },
3550
3879
  imgIdx
3880
+ )) }),
3881
+ msg.userFlows && msg.userFlows.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { marginTop: "12px" }, children: msg.userFlows.slice(0, 3).map((userFlow, ufIdx) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3882
+ "div",
3883
+ {
3884
+ style: {
3885
+ marginTop: ufIdx > 0 ? "12px" : 0,
3886
+ padding: "12px",
3887
+ borderRadius: "8px",
3888
+ border: `1px solid ${isDark ? "#374151" : "#e5e7eb"}`,
3889
+ backgroundColor: isDark ? "#1f2937" : "#f9fafb"
3890
+ },
3891
+ children: [
3892
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: {
3893
+ display: "flex",
3894
+ alignItems: "center",
3895
+ justifyContent: "space-between",
3896
+ marginBottom: "8px"
3897
+ }, children: [
3898
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
3899
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { fontSize: "16px" }, children: "\u{1F4CB}" }),
3900
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: {
3901
+ fontWeight: 600,
3902
+ fontSize: "14px",
3903
+ color: isDark ? "#f3f4f6" : "#111827"
3904
+ }, children: userFlow.title })
3905
+ ] }),
3906
+ userFlow.eventCount && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { style: {
3907
+ fontSize: "11px",
3908
+ padding: "2px 6px",
3909
+ backgroundColor: primaryColor + "20",
3910
+ color: primaryColor,
3911
+ borderRadius: "4px"
3912
+ }, children: [
3913
+ userFlow.eventCount,
3914
+ " steps"
3915
+ ] })
3916
+ ] }),
3917
+ userFlow.description && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { style: {
3918
+ fontSize: "12px",
3919
+ color: isDark ? "#9ca3af" : "#6b7280",
3920
+ marginBottom: "12px",
3921
+ lineHeight: 1.4
3922
+ }, children: userFlow.description }),
3923
+ userFlow.steps && userFlow.steps.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3924
+ StepGuide,
3925
+ {
3926
+ steps: parseStepsFromStrings(userFlow.steps),
3927
+ theme,
3928
+ primaryColor,
3929
+ compact: true
3930
+ }
3931
+ ),
3932
+ userFlow.hasReplay && userFlow.recordingId && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3933
+ "button",
3934
+ {
3935
+ onClick: () => {
3936
+ const replayUrl = `${window.location.origin}/recordings/${userFlow.recordingId}`;
3937
+ window.open(replayUrl, "_blank", "width=1200,height=800");
3938
+ },
3939
+ style: {
3940
+ display: "flex",
3941
+ alignItems: "center",
3942
+ gap: "6px",
3943
+ padding: "8px 12px",
3944
+ marginTop: userFlow.steps && userFlow.steps.length > 0 ? "12px" : "8px",
3945
+ backgroundColor: primaryColor,
3946
+ color: "#fff",
3947
+ border: "none",
3948
+ borderRadius: "6px",
3949
+ fontSize: "12px",
3950
+ fontWeight: 500,
3951
+ cursor: "pointer",
3952
+ width: "100%",
3953
+ justifyContent: "center"
3954
+ },
3955
+ children: [
3956
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "\u25B6\uFE0F" }),
3957
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Watch Session Replay" })
3958
+ ]
3959
+ }
3960
+ )
3961
+ ]
3962
+ },
3963
+ userFlow.id || ufIdx
3551
3964
  )) })
3552
3965
  ]
3553
3966
  }
@@ -3555,7 +3968,7 @@ function ProduckChat({
3555
3968
  },
3556
3969
  idx
3557
3970
  )),
3558
- isLoading && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { display: "flex", justifyContent: "flex-start" }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3971
+ isLoading && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { display: "flex", justifyContent: "flex-start" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3559
3972
  "div",
3560
3973
  {
3561
3974
  style: {
@@ -3565,16 +3978,16 @@ function ProduckChat({
3565
3978
  color: isDark ? "#9ca3af" : "#6b7280",
3566
3979
  fontSize: typeof fontSize === "number" ? `${fontSize}px` : fontSize
3567
3980
  },
3568
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: {
3981
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: {
3569
3982
  display: "inline-block",
3570
3983
  animation: "pulse 1.5s ease-in-out infinite"
3571
3984
  }, children: "Thinking..." })
3572
3985
  }
3573
3986
  ) }),
3574
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref: messagesEndRef })
3987
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { ref: messagesEndRef })
3575
3988
  ] }),
3576
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("form", { onSubmit: handleSubmit, style: inputContainerStyles, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "10px", alignItems: "center" }, children: [
3577
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3989
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("form", { onSubmit: handleSubmit, style: inputContainerStyles, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", gap: "10px", alignItems: "center" }, children: [
3990
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3578
3991
  "input",
3579
3992
  {
3580
3993
  ref: inputRef,
@@ -3605,7 +4018,7 @@ function ProduckChat({
3605
4018
  }
3606
4019
  }
3607
4020
  ),
3608
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
4021
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3609
4022
  "button",
3610
4023
  {
3611
4024
  type: "submit",
@@ -3637,13 +4050,13 @@ function ProduckChat({
3637
4050
  e.currentTarget.style.boxShadow = "none";
3638
4051
  },
3639
4052
  children: [
3640
- sendButtonIcon && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: sendButtonIcon }),
4053
+ sendButtonIcon && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: sendButtonIcon }),
3641
4054
  sendButtonText
3642
4055
  ]
3643
4056
  }
3644
4057
  )
3645
4058
  ] }) }),
3646
- showPoweredBy && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
4059
+ showPoweredBy && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3647
4060
  "div",
3648
4061
  {
3649
4062
  style: {
@@ -3651,7 +4064,7 @@ function ProduckChat({
3651
4064
  textAlign: "center",
3652
4065
  borderTop: `1px solid ${isDark ? "#374151" : "#e5e7eb"}`
3653
4066
  },
3654
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
4067
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3655
4068
  "a",
3656
4069
  {
3657
4070
  href: poweredByUrl,
@@ -3675,7 +4088,7 @@ function ProduckChat({
3675
4088
  }
3676
4089
  )
3677
4090
  ] }),
3678
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("style", { children: `
4091
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("style", { children: `
3679
4092
  @keyframes pulse {
3680
4093
  0%, 100% { opacity: 1; }
3681
4094
  50% { opacity: 0.5; }
@@ -3689,8 +4102,8 @@ function ProduckChat({
3689
4102
  }
3690
4103
 
3691
4104
  // src/react/ProduckTarget.tsx
3692
- var import_react6 = __toESM(require("react"));
3693
- var import_jsx_runtime4 = require("react/jsx-runtime");
4105
+ var import_react7 = __toESM(require("react"));
4106
+ var import_jsx_runtime5 = require("react/jsx-runtime");
3694
4107
  function ProduckTarget({
3695
4108
  actionKey,
3696
4109
  children,
@@ -3704,8 +4117,8 @@ function ProduckTarget({
3704
4117
  highlightDuration = 3e3,
3705
4118
  scrollIntoView = true
3706
4119
  }) {
3707
- const ref = (0, import_react6.useRef)(null);
3708
- const [isHighlighted, setIsHighlighted] = import_react6.default.useState(false);
4120
+ const ref = (0, import_react7.useRef)(null);
4121
+ const [isHighlighted, setIsHighlighted] = import_react7.default.useState(false);
3709
4122
  useProduckAction(
3710
4123
  actionKey,
3711
4124
  (payload) => {
@@ -3721,7 +4134,7 @@ function ProduckTarget({
3721
4134
  },
3722
4135
  [scrollIntoView, highlightDuration, onTrigger]
3723
4136
  );
3724
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4137
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3725
4138
  "div",
3726
4139
  {
3727
4140
  ref,