@runtypelabs/persona 3.18.0 → 3.20.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.
Files changed (42) hide show
  1. package/README.md +45 -2
  2. package/dist/index.cjs +47 -47
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +383 -6
  5. package/dist/index.d.ts +383 -6
  6. package/dist/index.global.js +102 -1636
  7. package/dist/index.global.js.map +1 -1
  8. package/dist/index.js +47 -47
  9. package/dist/index.js.map +1 -1
  10. package/dist/theme-editor.cjs +1514 -626
  11. package/dist/theme-editor.d.cts +192 -1
  12. package/dist/theme-editor.d.ts +192 -1
  13. package/dist/theme-editor.js +1628 -626
  14. package/dist/widget.css +348 -0
  15. package/package.json +1 -1
  16. package/src/components/composer-builder.test.ts +52 -0
  17. package/src/components/composer-builder.ts +67 -490
  18. package/src/components/composer-parts.test.ts +152 -0
  19. package/src/components/composer-parts.ts +452 -0
  20. package/src/components/header-builder.ts +22 -299
  21. package/src/components/header-parts.ts +360 -0
  22. package/src/components/panel.test.ts +61 -0
  23. package/src/components/panel.ts +262 -5
  24. package/src/components/pill-composer-builder.test.ts +85 -0
  25. package/src/components/pill-composer-builder.ts +183 -0
  26. package/src/index.ts +5 -0
  27. package/src/runtime/init.ts +4 -2
  28. package/src/runtime/persist-state.test.ts +152 -0
  29. package/src/session.test.ts +123 -0
  30. package/src/session.ts +58 -4
  31. package/src/styles/widget.css +348 -0
  32. package/src/types.ts +196 -1
  33. package/src/ui.component-directive.test.ts +183 -0
  34. package/src/ui.composer-bar.test.ts +1009 -0
  35. package/src/ui.ts +827 -72
  36. package/src/utils/attachment-manager.ts +1 -1
  37. package/src/utils/component-middleware.test.ts +134 -0
  38. package/src/utils/component-middleware.ts +44 -13
  39. package/src/utils/dock.test.ts +45 -0
  40. package/src/utils/dock.ts +3 -0
  41. package/src/utils/icons.ts +314 -58
  42. package/src/utils/stream-animation.ts +7 -2
@@ -7505,7 +7505,8 @@ var AgentWidgetSession = class _AgentWidgetSession {
7505
7505
  createdAt,
7506
7506
  sequence,
7507
7507
  streaming = false,
7508
- voiceProcessing
7508
+ voiceProcessing,
7509
+ rawContent
7509
7510
  } = options;
7510
7511
  const messageId = id != null ? id : role === "user" ? generateUserMessageId() : role === "assistant" ? generateAssistantMessageId() : `system-${Date.now()}-${Math.random().toString(16).slice(2)}`;
7511
7512
  const message = {
@@ -7518,7 +7519,8 @@ var AgentWidgetSession = class _AgentWidgetSession {
7518
7519
  // Only include optional fields if provided
7519
7520
  ...llmContent !== void 0 && { llmContent },
7520
7521
  ...contentParts !== void 0 && { contentParts },
7521
- ...voiceProcessing !== void 0 && { voiceProcessing }
7522
+ ...voiceProcessing !== void 0 && { voiceProcessing },
7523
+ ...rawContent !== void 0 && { rawContent }
7522
7524
  };
7523
7525
  this.upsertMessage(message);
7524
7526
  return message;
@@ -7583,7 +7585,9 @@ var AgentWidgetSession = class _AgentWidgetSession {
7583
7585
  id,
7584
7586
  createdAt,
7585
7587
  sequence,
7586
- streaming = false
7588
+ streaming = false,
7589
+ voiceProcessing,
7590
+ rawContent
7587
7591
  } = options;
7588
7592
  const messageId = id != null ? id : role === "user" ? generateUserMessageId() : role === "assistant" ? generateAssistantMessageId() : `system-${Date.now()}-${Math.random().toString(16).slice(2)}`;
7589
7593
  const message = {
@@ -7594,7 +7598,9 @@ var AgentWidgetSession = class _AgentWidgetSession {
7594
7598
  sequence: sequence != null ? sequence : this.nextSequence(),
7595
7599
  streaming,
7596
7600
  ...llmContent !== void 0 && { llmContent },
7597
- ...contentParts !== void 0 && { contentParts }
7601
+ ...contentParts !== void 0 && { contentParts },
7602
+ ...voiceProcessing !== void 0 && { voiceProcessing },
7603
+ ...rawContent !== void 0 && { rawContent }
7598
7604
  };
7599
7605
  results.push(message);
7600
7606
  }
@@ -7602,6 +7608,48 @@ var AgentWidgetSession = class _AgentWidgetSession {
7602
7608
  this.callbacks.onMessagesChanged([...this.messages]);
7603
7609
  return results;
7604
7610
  }
7611
+ /**
7612
+ * Convenience method for injecting a registered component directive as
7613
+ * an assistant message — the same shape Persona produces from a streamed
7614
+ * `{ "text": "...", "component": "...", "props": {...} }` payload.
7615
+ *
7616
+ * Sets `content` to `text`, `rawContent` to the JSON directive (so
7617
+ * `extractComponentDirectiveFromMessage` can find it), and forwards
7618
+ * `llmContent` / `id` / `createdAt` / `sequence`.
7619
+ *
7620
+ * @example
7621
+ * session.injectComponentDirective({
7622
+ * component: "DynamicForm",
7623
+ * props: { title: "Book a demo", fields: [...] },
7624
+ * text: "Share your details to book a demo.",
7625
+ * llmContent: "[Showed booking form]"
7626
+ * });
7627
+ */
7628
+ injectComponentDirective(options) {
7629
+ const {
7630
+ component,
7631
+ props = {},
7632
+ text = "",
7633
+ llmContent,
7634
+ id,
7635
+ createdAt,
7636
+ sequence
7637
+ } = options;
7638
+ const directive = {
7639
+ text,
7640
+ component,
7641
+ props
7642
+ };
7643
+ return this.injectMessage({
7644
+ role: "assistant",
7645
+ content: text,
7646
+ rawContent: JSON.stringify(directive),
7647
+ ...llmContent !== void 0 && { llmContent },
7648
+ ...id !== void 0 && { id },
7649
+ ...createdAt !== void 0 && { createdAt },
7650
+ ...sequence !== void 0 && { sequence }
7651
+ });
7652
+ }
7605
7653
  async sendMessage(rawInput, options) {
7606
7654
  var _a, _b, _c, _d, _e;
7607
7655
  const input = rawInput.trim();
@@ -8289,25 +8337,146 @@ var createElementInDocument = (documentRef, tag, className) => {
8289
8337
  };
8290
8338
 
8291
8339
  // src/utils/icons.ts
8292
- var icons = __toESM(require("lucide"), 1);
8340
+ var import_lucide = require("lucide");
8341
+ var LUCIDE_ICONS = {
8342
+ // Mandatory
8343
+ "activity": import_lucide.Activity,
8344
+ "arrow-down": import_lucide.ArrowDown,
8345
+ "arrow-up": import_lucide.ArrowUp,
8346
+ "arrow-up-right": import_lucide.ArrowUpRight,
8347
+ "bot": import_lucide.Bot,
8348
+ "chevron-down": import_lucide.ChevronDown,
8349
+ "chevron-up": import_lucide.ChevronUp,
8350
+ "chevron-right": import_lucide.ChevronRight,
8351
+ "chevron-left": import_lucide.ChevronLeft,
8352
+ "check": import_lucide.Check,
8353
+ "clipboard": import_lucide.Clipboard,
8354
+ "clipboard-copy": import_lucide.ClipboardCopy,
8355
+ "copy": import_lucide.Copy,
8356
+ "file": import_lucide.File,
8357
+ "file-code": import_lucide.FileCode,
8358
+ "file-spreadsheet": import_lucide.FileSpreadsheet,
8359
+ "file-text": import_lucide.FileText,
8360
+ "image-plus": import_lucide.ImagePlus,
8361
+ "loader": import_lucide.Loader,
8362
+ "loader-circle": import_lucide.LoaderCircle,
8363
+ "mic": import_lucide.Mic,
8364
+ "paperclip": import_lucide.Paperclip,
8365
+ "refresh-cw": import_lucide.RefreshCw,
8366
+ "search": import_lucide.Search,
8367
+ "send": import_lucide.Send,
8368
+ "shield-alert": import_lucide.ShieldAlert,
8369
+ "shield-check": import_lucide.ShieldCheck,
8370
+ "shield-x": import_lucide.ShieldX,
8371
+ "square": import_lucide.Square,
8372
+ "thumbs-down": import_lucide.ThumbsDown,
8373
+ "thumbs-up": import_lucide.ThumbsUp,
8374
+ "upload": import_lucide.Upload,
8375
+ "volume-2": import_lucide.Volume2,
8376
+ "x": import_lucide.X,
8377
+ // Forms / inputs
8378
+ "user": import_lucide.User,
8379
+ "mail": import_lucide.Mail,
8380
+ "phone": import_lucide.Phone,
8381
+ "calendar": import_lucide.Calendar,
8382
+ "clock": import_lucide.Clock,
8383
+ "building": import_lucide.Building,
8384
+ "map-pin": import_lucide.MapPin,
8385
+ "lock": import_lucide.Lock,
8386
+ "key": import_lucide.Key,
8387
+ "credit-card": import_lucide.CreditCard,
8388
+ "at-sign": import_lucide.AtSign,
8389
+ "hash": import_lucide.Hash,
8390
+ "globe": import_lucide.Globe,
8391
+ "link": import_lucide.Link,
8392
+ // Status / feedback
8393
+ "circle-check": import_lucide.CircleCheck,
8394
+ "circle-x": import_lucide.CircleX,
8395
+ "triangle-alert": import_lucide.TriangleAlert,
8396
+ "info": import_lucide.Info,
8397
+ "ban": import_lucide.Ban,
8398
+ "shield": import_lucide.Shield,
8399
+ // Navigation
8400
+ "arrow-left": import_lucide.ArrowLeft,
8401
+ "arrow-right": import_lucide.ArrowRight,
8402
+ "external-link": import_lucide.ExternalLink,
8403
+ "ellipsis": import_lucide.Ellipsis,
8404
+ "ellipsis-vertical": import_lucide.EllipsisVertical,
8405
+ "menu": import_lucide.Menu,
8406
+ "house": import_lucide.House,
8407
+ // Actions
8408
+ "plus": import_lucide.Plus,
8409
+ "minus": import_lucide.Minus,
8410
+ "pencil": import_lucide.Pencil,
8411
+ "trash": import_lucide.Trash,
8412
+ "trash-2": import_lucide.Trash2,
8413
+ "save": import_lucide.Save,
8414
+ "download": import_lucide.Download,
8415
+ "share": import_lucide.Share,
8416
+ "funnel": import_lucide.Funnel,
8417
+ "settings": import_lucide.Settings,
8418
+ "rotate-cw": import_lucide.RotateCw,
8419
+ "maximize": import_lucide.Maximize,
8420
+ "minimize": import_lucide.Minimize,
8421
+ // Commerce
8422
+ "shopping-cart": import_lucide.ShoppingCart,
8423
+ "shopping-bag": import_lucide.ShoppingBag,
8424
+ "package": import_lucide.Package,
8425
+ "truck": import_lucide.Truck,
8426
+ "tag": import_lucide.Tag,
8427
+ "gift": import_lucide.Gift,
8428
+ "receipt": import_lucide.Receipt,
8429
+ "wallet": import_lucide.Wallet,
8430
+ "store": import_lucide.Store,
8431
+ "dollar-sign": import_lucide.DollarSign,
8432
+ "percent": import_lucide.Percent,
8433
+ // Media
8434
+ "play": import_lucide.Play,
8435
+ "pause": import_lucide.Pause,
8436
+ "volume-x": import_lucide.VolumeX,
8437
+ "camera": import_lucide.Camera,
8438
+ "image": import_lucide.Image,
8439
+ "film": import_lucide.Film,
8440
+ "headphones": import_lucide.Headphones,
8441
+ // Social / Comms
8442
+ "message-circle": import_lucide.MessageCircle,
8443
+ "message-square": import_lucide.MessageSquare,
8444
+ "bell": import_lucide.Bell,
8445
+ "heart": import_lucide.Heart,
8446
+ "star": import_lucide.Star,
8447
+ "eye": import_lucide.Eye,
8448
+ "eye-off": import_lucide.EyeOff,
8449
+ "bookmark": import_lucide.Bookmark,
8450
+ // Time
8451
+ "calendar-days": import_lucide.CalendarDays,
8452
+ "history": import_lucide.History,
8453
+ "timer": import_lucide.Timer,
8454
+ // Files
8455
+ "folder": import_lucide.Folder,
8456
+ "folder-open": import_lucide.FolderOpen,
8457
+ "files": import_lucide.Files,
8458
+ // Decorative
8459
+ "sparkles": import_lucide.Sparkles,
8460
+ "zap": import_lucide.Zap,
8461
+ "sun": import_lucide.Sun,
8462
+ "moon": import_lucide.Moon,
8463
+ "flag": import_lucide.Flag,
8464
+ // Devices
8465
+ "monitor": import_lucide.Monitor,
8466
+ "smartphone": import_lucide.Smartphone
8467
+ };
8293
8468
  var renderLucideIcon = (iconName, size = 24, color = "currentColor", strokeWidth = 2) => {
8294
- try {
8295
- const pascalName = iconName.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
8296
- const iconData = icons[pascalName];
8297
- if (!iconData) {
8298
- console.warn(`Lucide icon "${iconName}" not found (tried "${pascalName}"). Available icons: https://lucide.dev/icons`);
8299
- return null;
8300
- }
8301
- return createSvgFromIconData(iconData, size, color, strokeWidth);
8302
- } catch (error) {
8303
- console.warn(`Failed to render Lucide icon "${iconName}":`, error);
8469
+ const iconData = LUCIDE_ICONS[iconName];
8470
+ if (!iconData) {
8471
+ console.warn(
8472
+ `Lucide icon "${iconName}" is not in the Persona registry. Add it to packages/widget/src/utils/icons.ts (see docs/icon-registry-shortlist.md).`
8473
+ );
8304
8474
  return null;
8305
8475
  }
8476
+ return createSvgFromIconData(iconData, size, color, strokeWidth);
8306
8477
  };
8307
8478
  function createSvgFromIconData(iconData, size, color, strokeWidth) {
8308
- if (!iconData || !Array.isArray(iconData)) {
8309
- return null;
8310
- }
8479
+ if (!Array.isArray(iconData)) return null;
8311
8480
  const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
8312
8481
  svg.setAttribute("width", String(size));
8313
8482
  svg.setAttribute("height", String(size));
@@ -8319,19 +8488,15 @@ function createSvgFromIconData(iconData, size, color, strokeWidth) {
8319
8488
  svg.setAttribute("stroke-linejoin", "round");
8320
8489
  svg.setAttribute("aria-hidden", "true");
8321
8490
  iconData.forEach((elementData) => {
8322
- if (Array.isArray(elementData) && elementData.length >= 2) {
8323
- const tagName = elementData[0];
8324
- const attrs = elementData[1];
8325
- if (attrs) {
8326
- const element = document.createElementNS("http://www.w3.org/2000/svg", tagName);
8327
- Object.entries(attrs).forEach(([key, value]) => {
8328
- if (key !== "stroke") {
8329
- element.setAttribute(key, String(value));
8330
- }
8331
- });
8332
- svg.appendChild(element);
8333
- }
8334
- }
8491
+ if (!Array.isArray(elementData) || elementData.length < 2) return;
8492
+ const tagName = elementData[0];
8493
+ const attrs = elementData[1];
8494
+ if (!attrs) return;
8495
+ const element = document.createElementNS("http://www.w3.org/2000/svg", tagName);
8496
+ Object.entries(attrs).forEach(([key, value]) => {
8497
+ if (key !== "stroke") element.setAttribute(key, String(value));
8498
+ });
8499
+ svg.appendChild(element);
8335
8500
  });
8336
8501
  return svg;
8337
8502
  }
@@ -8351,7 +8516,7 @@ function getFileIconName(mimeType) {
8351
8516
  if (mimeType.startsWith("text/")) return "file-text";
8352
8517
  if (mimeType.includes("word")) return "file-text";
8353
8518
  if (mimeType.includes("excel") || mimeType.includes("spreadsheet")) return "file-spreadsheet";
8354
- if (mimeType === "application/json") return "file-json";
8519
+ if (mimeType === "application/json") return "file-code";
8355
8520
  return "file";
8356
8521
  }
8357
8522
  var AttachmentManager = class _AttachmentManager {
@@ -8913,7 +9078,7 @@ var wrapTextNodeWords = (textNode, messageId, counterRef) => {
8913
9078
  parent.replaceChild(fragment, textNode);
8914
9079
  };
8915
9080
  var wrapStreamAnimation = (html, mode, messageId, options) => {
8916
- var _a;
9081
+ var _a, _b;
8917
9082
  if (!html) return html;
8918
9083
  if (typeof document === "undefined") return html;
8919
9084
  const scratch = document.createElement("div");
@@ -8928,7 +9093,7 @@ var wrapStreamAnimation = (html, mode, messageId, options) => {
8928
9093
  }
8929
9094
  node = walker.nextNode();
8930
9095
  }
8931
- const counterRef = { value: 0 };
9096
+ const counterRef = { value: (_b = options == null ? void 0 : options.startIndex) != null ? _b : 0 };
8932
9097
  const wrap = mode === "char" ? wrapTextNodeChars : wrapTextNodeWords;
8933
9098
  for (const textNode of textNodes) {
8934
9099
  wrap(textNode, messageId, counterRef);
@@ -9074,6 +9239,10 @@ var isDockedMountMode = (config) => {
9074
9239
  var _a, _b;
9075
9240
  return ((_b = (_a = config == null ? void 0 : config.launcher) == null ? void 0 : _a.mountMode) != null ? _b : "floating") === "docked";
9076
9241
  };
9242
+ var isComposerBarMountMode = (config) => {
9243
+ var _a, _b;
9244
+ return ((_b = (_a = config == null ? void 0 : config.launcher) == null ? void 0 : _a.mountMode) != null ? _b : "floating") === "composer-bar";
9245
+ };
9077
9246
  var resolveDockConfig = (config) => {
9078
9247
  var _a, _b, _c, _d, _e;
9079
9248
  const dock = (_a = config == null ? void 0 : config.launcher) == null ? void 0 : _a.dock;
@@ -9260,6 +9429,226 @@ var createLauncherButton = (config, onToggle) => {
9260
9429
  };
9261
9430
  };
9262
9431
 
9432
+ // src/components/header-parts.ts
9433
+ var DEFAULT_WRAPPER_CLASS = "persona-relative persona-ml-auto persona-inline-flex persona-items-center persona-justify-center";
9434
+ var createCloseButton = (config, options = {}) => {
9435
+ var _a, _b, _c, _d, _e, _f;
9436
+ const {
9437
+ showClose = true,
9438
+ wrapperClassName = DEFAULT_WRAPPER_CLASS,
9439
+ buttonSize,
9440
+ iconSize = "28px"
9441
+ } = options;
9442
+ const launcher = (_a = config == null ? void 0 : config.launcher) != null ? _a : {};
9443
+ const closeButtonSize = (_b = buttonSize != null ? buttonSize : launcher.closeButtonSize) != null ? _b : "32px";
9444
+ const wrapper = createElement("div", wrapperClassName);
9445
+ const button = createElement(
9446
+ "button",
9447
+ "persona-inline-flex persona-items-center persona-justify-center persona-rounded-full hover:persona-bg-gray-100 persona-cursor-pointer persona-border-none"
9448
+ );
9449
+ button.style.height = closeButtonSize;
9450
+ button.style.width = closeButtonSize;
9451
+ button.type = "button";
9452
+ const closeButtonTooltipText = (_c = launcher.closeButtonTooltipText) != null ? _c : "Close chat";
9453
+ const closeButtonShowTooltip = (_d = launcher.closeButtonShowTooltip) != null ? _d : true;
9454
+ button.setAttribute("aria-label", closeButtonTooltipText);
9455
+ button.style.display = showClose ? "" : "none";
9456
+ const closeButtonIconName = (_e = launcher.closeButtonIconName) != null ? _e : "x";
9457
+ const closeButtonIconText = (_f = launcher.closeButtonIconText) != null ? _f : "\xD7";
9458
+ button.style.color = launcher.closeButtonColor || HEADER_THEME_CSS.actionIconColor;
9459
+ const closeIconSvg = renderLucideIcon(closeButtonIconName, iconSize, "currentColor", 1);
9460
+ if (closeIconSvg) {
9461
+ closeIconSvg.style.display = "block";
9462
+ button.appendChild(closeIconSvg);
9463
+ } else {
9464
+ button.textContent = closeButtonIconText;
9465
+ }
9466
+ if (launcher.closeButtonBackgroundColor) {
9467
+ button.style.backgroundColor = launcher.closeButtonBackgroundColor;
9468
+ button.classList.remove("hover:persona-bg-gray-100");
9469
+ } else {
9470
+ button.style.backgroundColor = "";
9471
+ button.classList.add("hover:persona-bg-gray-100");
9472
+ }
9473
+ if (launcher.closeButtonBorderWidth || launcher.closeButtonBorderColor) {
9474
+ const borderWidth = launcher.closeButtonBorderWidth || "0px";
9475
+ const borderColor = launcher.closeButtonBorderColor || "transparent";
9476
+ button.style.border = `${borderWidth} solid ${borderColor}`;
9477
+ button.classList.remove("persona-border-none");
9478
+ } else {
9479
+ button.style.border = "";
9480
+ button.classList.add("persona-border-none");
9481
+ }
9482
+ if (launcher.closeButtonBorderRadius) {
9483
+ button.style.borderRadius = launcher.closeButtonBorderRadius;
9484
+ button.classList.remove("persona-rounded-full");
9485
+ } else {
9486
+ button.style.borderRadius = "";
9487
+ button.classList.add("persona-rounded-full");
9488
+ }
9489
+ if (launcher.closeButtonPaddingX) {
9490
+ button.style.paddingLeft = launcher.closeButtonPaddingX;
9491
+ button.style.paddingRight = launcher.closeButtonPaddingX;
9492
+ } else {
9493
+ button.style.paddingLeft = "";
9494
+ button.style.paddingRight = "";
9495
+ }
9496
+ if (launcher.closeButtonPaddingY) {
9497
+ button.style.paddingTop = launcher.closeButtonPaddingY;
9498
+ button.style.paddingBottom = launcher.closeButtonPaddingY;
9499
+ } else {
9500
+ button.style.paddingTop = "";
9501
+ button.style.paddingBottom = "";
9502
+ }
9503
+ wrapper.appendChild(button);
9504
+ if (closeButtonShowTooltip && closeButtonTooltipText) {
9505
+ let portaledTooltip = null;
9506
+ const showTooltip = () => {
9507
+ if (portaledTooltip) return;
9508
+ const tooltipDocument = button.ownerDocument;
9509
+ const tooltipContainer = tooltipDocument.body;
9510
+ if (!tooltipContainer) return;
9511
+ portaledTooltip = createElementInDocument(
9512
+ tooltipDocument,
9513
+ "div",
9514
+ "persona-clear-chat-tooltip"
9515
+ );
9516
+ portaledTooltip.textContent = closeButtonTooltipText;
9517
+ const arrow = createElementInDocument(tooltipDocument, "div");
9518
+ arrow.className = "persona-clear-chat-tooltip-arrow";
9519
+ portaledTooltip.appendChild(arrow);
9520
+ const buttonRect = button.getBoundingClientRect();
9521
+ portaledTooltip.style.position = "fixed";
9522
+ portaledTooltip.style.zIndex = String(PORTALED_OVERLAY_Z_INDEX);
9523
+ portaledTooltip.style.left = `${buttonRect.left + buttonRect.width / 2}px`;
9524
+ portaledTooltip.style.top = `${buttonRect.top - 8}px`;
9525
+ portaledTooltip.style.transform = "translate(-50%, -100%)";
9526
+ tooltipContainer.appendChild(portaledTooltip);
9527
+ };
9528
+ const hideTooltip = () => {
9529
+ if (portaledTooltip && portaledTooltip.parentNode) {
9530
+ portaledTooltip.parentNode.removeChild(portaledTooltip);
9531
+ portaledTooltip = null;
9532
+ }
9533
+ };
9534
+ wrapper.addEventListener("mouseenter", showTooltip);
9535
+ wrapper.addEventListener("mouseleave", hideTooltip);
9536
+ button.addEventListener("focus", showTooltip);
9537
+ button.addEventListener("blur", hideTooltip);
9538
+ wrapper._cleanupTooltip = () => {
9539
+ hideTooltip();
9540
+ wrapper.removeEventListener("mouseenter", showTooltip);
9541
+ wrapper.removeEventListener("mouseleave", hideTooltip);
9542
+ button.removeEventListener("focus", showTooltip);
9543
+ button.removeEventListener("blur", hideTooltip);
9544
+ };
9545
+ }
9546
+ return { button, wrapper };
9547
+ };
9548
+ var DEFAULT_CLEAR_CHAT_WRAPPER_CLASS = "persona-relative persona-ml-auto persona-clear-chat-button-wrapper";
9549
+ var createClearChatButton = (config, options = {}) => {
9550
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
9551
+ const {
9552
+ wrapperClassName = DEFAULT_CLEAR_CHAT_WRAPPER_CLASS,
9553
+ buttonSize,
9554
+ iconSize = "20px"
9555
+ } = options;
9556
+ const launcher = (_a = config == null ? void 0 : config.launcher) != null ? _a : {};
9557
+ const clearChatConfig = (_b = launcher.clearChat) != null ? _b : {};
9558
+ const clearChatSize = (_c = buttonSize != null ? buttonSize : clearChatConfig.size) != null ? _c : "32px";
9559
+ const clearChatIconName = (_d = clearChatConfig.iconName) != null ? _d : "refresh-cw";
9560
+ const clearChatIconColor = (_e = clearChatConfig.iconColor) != null ? _e : "";
9561
+ const clearChatBgColor = (_f = clearChatConfig.backgroundColor) != null ? _f : "";
9562
+ const clearChatBorderWidth = (_g = clearChatConfig.borderWidth) != null ? _g : "";
9563
+ const clearChatBorderColor = (_h = clearChatConfig.borderColor) != null ? _h : "";
9564
+ const clearChatBorderRadius = (_i = clearChatConfig.borderRadius) != null ? _i : "";
9565
+ const clearChatPaddingX = (_j = clearChatConfig.paddingX) != null ? _j : "";
9566
+ const clearChatPaddingY = (_k = clearChatConfig.paddingY) != null ? _k : "";
9567
+ const clearChatTooltipText = (_l = clearChatConfig.tooltipText) != null ? _l : "Clear chat";
9568
+ const clearChatShowTooltip = (_m = clearChatConfig.showTooltip) != null ? _m : true;
9569
+ const wrapper = createElement("div", wrapperClassName);
9570
+ const button = createElement(
9571
+ "button",
9572
+ "persona-inline-flex persona-items-center persona-justify-center persona-rounded-full hover:persona-bg-gray-100 persona-cursor-pointer persona-border-none"
9573
+ );
9574
+ button.style.height = clearChatSize;
9575
+ button.style.width = clearChatSize;
9576
+ button.type = "button";
9577
+ button.setAttribute("aria-label", clearChatTooltipText);
9578
+ button.style.color = clearChatIconColor || HEADER_THEME_CSS.actionIconColor;
9579
+ const iconSvg = renderLucideIcon(clearChatIconName, iconSize, "currentColor", 1);
9580
+ if (iconSvg) {
9581
+ iconSvg.style.display = "block";
9582
+ button.appendChild(iconSvg);
9583
+ }
9584
+ if (clearChatBgColor) {
9585
+ button.style.backgroundColor = clearChatBgColor;
9586
+ button.classList.remove("hover:persona-bg-gray-100");
9587
+ }
9588
+ if (clearChatBorderWidth || clearChatBorderColor) {
9589
+ const borderWidth = clearChatBorderWidth || "0px";
9590
+ const borderColor = clearChatBorderColor || "transparent";
9591
+ button.style.border = `${borderWidth} solid ${borderColor}`;
9592
+ button.classList.remove("persona-border-none");
9593
+ }
9594
+ if (clearChatBorderRadius) {
9595
+ button.style.borderRadius = clearChatBorderRadius;
9596
+ button.classList.remove("persona-rounded-full");
9597
+ }
9598
+ if (clearChatPaddingX) {
9599
+ button.style.paddingLeft = clearChatPaddingX;
9600
+ button.style.paddingRight = clearChatPaddingX;
9601
+ }
9602
+ if (clearChatPaddingY) {
9603
+ button.style.paddingTop = clearChatPaddingY;
9604
+ button.style.paddingBottom = clearChatPaddingY;
9605
+ }
9606
+ wrapper.appendChild(button);
9607
+ if (clearChatShowTooltip && clearChatTooltipText) {
9608
+ let portaledTooltip = null;
9609
+ const showTooltip = () => {
9610
+ if (portaledTooltip) return;
9611
+ const tooltipDocument = button.ownerDocument;
9612
+ const tooltipContainer = tooltipDocument.body;
9613
+ if (!tooltipContainer) return;
9614
+ portaledTooltip = createElementInDocument(
9615
+ tooltipDocument,
9616
+ "div",
9617
+ "persona-clear-chat-tooltip"
9618
+ );
9619
+ portaledTooltip.textContent = clearChatTooltipText;
9620
+ const arrow = createElementInDocument(tooltipDocument, "div");
9621
+ arrow.className = "persona-clear-chat-tooltip-arrow";
9622
+ portaledTooltip.appendChild(arrow);
9623
+ const buttonRect = button.getBoundingClientRect();
9624
+ portaledTooltip.style.position = "fixed";
9625
+ portaledTooltip.style.zIndex = String(PORTALED_OVERLAY_Z_INDEX);
9626
+ portaledTooltip.style.left = `${buttonRect.left + buttonRect.width / 2}px`;
9627
+ portaledTooltip.style.top = `${buttonRect.top - 8}px`;
9628
+ portaledTooltip.style.transform = "translate(-50%, -100%)";
9629
+ tooltipContainer.appendChild(portaledTooltip);
9630
+ };
9631
+ const hideTooltip = () => {
9632
+ if (portaledTooltip && portaledTooltip.parentNode) {
9633
+ portaledTooltip.parentNode.removeChild(portaledTooltip);
9634
+ portaledTooltip = null;
9635
+ }
9636
+ };
9637
+ wrapper.addEventListener("mouseenter", showTooltip);
9638
+ wrapper.addEventListener("mouseleave", hideTooltip);
9639
+ button.addEventListener("focus", showTooltip);
9640
+ button.addEventListener("blur", hideTooltip);
9641
+ wrapper._cleanupTooltip = () => {
9642
+ hideTooltip();
9643
+ wrapper.removeEventListener("mouseenter", showTooltip);
9644
+ wrapper.removeEventListener("mouseleave", hideTooltip);
9645
+ button.removeEventListener("focus", showTooltip);
9646
+ button.removeEventListener("blur", hideTooltip);
9647
+ };
9648
+ }
9649
+ return { button, wrapper };
9650
+ };
9651
+
9263
9652
  // src/components/header-builder.ts
9264
9653
  var HEADER_THEME_CSS = {
9265
9654
  titleColor: "var(--persona-header-title-fg, var(--persona-primary, #0f0f0f))",
@@ -9267,7 +9656,7 @@ var HEADER_THEME_CSS = {
9267
9656
  actionIconColor: "var(--persona-header-action-icon-fg, var(--persona-muted, #9ca3af))"
9268
9657
  };
9269
9658
  var buildHeader = (context) => {
9270
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F;
9659
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
9271
9660
  const { config, showClose = true } = context;
9272
9661
  const header = createElement(
9273
9662
  "div",
@@ -9280,9 +9669,8 @@ var buildHeader = (context) => {
9280
9669
  header.style.borderBottom = "var(--persona-header-border-bottom, 1px solid var(--persona-header-border, var(--persona-divider, #f1f5f9)))";
9281
9670
  const launcher = (_a = config == null ? void 0 : config.launcher) != null ? _a : {};
9282
9671
  const headerIconSize = (_b = launcher.headerIconSize) != null ? _b : "48px";
9283
- const closeButtonSize = (_c = launcher.closeButtonSize) != null ? _c : "32px";
9284
- const closeButtonPlacement = (_d = launcher.closeButtonPlacement) != null ? _d : "inline";
9285
- const headerIconHidden = (_e = launcher.headerIconHidden) != null ? _e : false;
9672
+ const closeButtonPlacement = (_c = launcher.closeButtonPlacement) != null ? _c : "inline";
9673
+ const headerIconHidden = (_d = launcher.headerIconHidden) != null ? _d : false;
9286
9674
  const headerIconName = launcher.headerIconName;
9287
9675
  const iconHolder = createElement(
9288
9676
  "div",
@@ -9299,9 +9687,9 @@ var buildHeader = (context) => {
9299
9687
  if (iconSvg) {
9300
9688
  iconHolder.replaceChildren(iconSvg);
9301
9689
  } else {
9302
- iconHolder.textContent = (_g = (_f = config == null ? void 0 : config.launcher) == null ? void 0 : _f.agentIconText) != null ? _g : "\u{1F4AC}";
9690
+ iconHolder.textContent = (_f = (_e = config == null ? void 0 : config.launcher) == null ? void 0 : _e.agentIconText) != null ? _f : "\u{1F4AC}";
9303
9691
  }
9304
- } else if ((_h = config == null ? void 0 : config.launcher) == null ? void 0 : _h.iconUrl) {
9692
+ } else if ((_g = config == null ? void 0 : config.launcher) == null ? void 0 : _g.iconUrl) {
9305
9693
  const img = createElement("img");
9306
9694
  img.src = config.launcher.iconUrl;
9307
9695
  img.alt = "";
@@ -9310,244 +9698,44 @@ var buildHeader = (context) => {
9310
9698
  img.style.width = headerIconSize;
9311
9699
  iconHolder.replaceChildren(img);
9312
9700
  } else {
9313
- iconHolder.textContent = (_j = (_i = config == null ? void 0 : config.launcher) == null ? void 0 : _i.agentIconText) != null ? _j : "\u{1F4AC}";
9701
+ iconHolder.textContent = (_i = (_h = config == null ? void 0 : config.launcher) == null ? void 0 : _h.agentIconText) != null ? _i : "\u{1F4AC}";
9314
9702
  }
9315
9703
  }
9316
9704
  const headerCopy = createElement("div", "persona-flex persona-flex-col persona-flex-1 persona-min-w-0");
9317
9705
  const title = createElement("span", "persona-text-base persona-font-semibold");
9318
9706
  title.style.color = HEADER_THEME_CSS.titleColor;
9319
- title.textContent = (_l = (_k = config == null ? void 0 : config.launcher) == null ? void 0 : _k.title) != null ? _l : "Chat Assistant";
9707
+ title.textContent = (_k = (_j = config == null ? void 0 : config.launcher) == null ? void 0 : _j.title) != null ? _k : "Chat Assistant";
9320
9708
  const subtitle = createElement("span", "persona-text-xs");
9321
9709
  subtitle.style.color = HEADER_THEME_CSS.subtitleColor;
9322
- subtitle.textContent = (_n = (_m = config == null ? void 0 : config.launcher) == null ? void 0 : _m.subtitle) != null ? _n : "Here to help you get answers fast";
9710
+ subtitle.textContent = (_m = (_l = config == null ? void 0 : config.launcher) == null ? void 0 : _l.subtitle) != null ? _m : "Here to help you get answers fast";
9323
9711
  headerCopy.append(title, subtitle);
9324
9712
  if (!headerIconHidden) {
9325
9713
  header.append(iconHolder, headerCopy);
9326
9714
  } else {
9327
9715
  header.append(headerCopy);
9328
9716
  }
9329
- const clearChatConfig = (_o = launcher.clearChat) != null ? _o : {};
9330
- const clearChatEnabled = (_p = clearChatConfig.enabled) != null ? _p : true;
9331
- const clearChatPlacement = (_q = clearChatConfig.placement) != null ? _q : "inline";
9717
+ const clearChatConfig = (_n = launcher.clearChat) != null ? _n : {};
9718
+ const clearChatEnabled = (_o = clearChatConfig.enabled) != null ? _o : true;
9719
+ const clearChatPlacement = (_p = clearChatConfig.placement) != null ? _p : "inline";
9332
9720
  let clearChatButton = null;
9333
9721
  let clearChatButtonWrapper = null;
9334
9722
  if (clearChatEnabled) {
9335
- const clearChatSize = (_r = clearChatConfig.size) != null ? _r : "32px";
9336
- const clearChatIconName = (_s = clearChatConfig.iconName) != null ? _s : "refresh-cw";
9337
- const clearChatIconColor = (_t = clearChatConfig.iconColor) != null ? _t : "";
9338
- const clearChatBgColor = (_u = clearChatConfig.backgroundColor) != null ? _u : "";
9339
- const clearChatBorderWidth = (_v = clearChatConfig.borderWidth) != null ? _v : "";
9340
- const clearChatBorderColor = (_w = clearChatConfig.borderColor) != null ? _w : "";
9341
- const clearChatBorderRadius = (_x = clearChatConfig.borderRadius) != null ? _x : "";
9342
- const clearChatPaddingX = (_y = clearChatConfig.paddingX) != null ? _y : "";
9343
- const clearChatPaddingY = (_z = clearChatConfig.paddingY) != null ? _z : "";
9344
- const clearChatTooltipText = (_A = clearChatConfig.tooltipText) != null ? _A : "Clear chat";
9345
- const clearChatShowTooltip = (_B = clearChatConfig.showTooltip) != null ? _B : true;
9346
- clearChatButtonWrapper = createElement(
9347
- "div",
9348
- clearChatPlacement === "top-right" ? "persona-absolute persona-top-4 persona-z-50" : "persona-relative persona-ml-auto persona-clear-chat-button-wrapper"
9349
- );
9723
+ const wrapperClassName = clearChatPlacement === "top-right" ? "persona-absolute persona-top-4 persona-z-50" : "persona-relative persona-ml-auto persona-clear-chat-button-wrapper";
9724
+ const parts = createClearChatButton(config, { wrapperClassName });
9725
+ clearChatButton = parts.button;
9726
+ clearChatButtonWrapper = parts.wrapper;
9350
9727
  if (clearChatPlacement === "top-right") {
9351
9728
  clearChatButtonWrapper.style.right = "48px";
9352
9729
  }
9353
- clearChatButton = createElement(
9354
- "button",
9355
- "persona-inline-flex persona-items-center persona-justify-center persona-rounded-full hover:persona-bg-gray-100 persona-cursor-pointer persona-border-none"
9356
- );
9357
- clearChatButton.style.height = clearChatSize;
9358
- clearChatButton.style.width = clearChatSize;
9359
- clearChatButton.type = "button";
9360
- clearChatButton.setAttribute("aria-label", clearChatTooltipText);
9361
- clearChatButton.style.color = clearChatIconColor || HEADER_THEME_CSS.actionIconColor;
9362
- const iconSvg = renderLucideIcon(clearChatIconName, "20px", "currentColor", 1);
9363
- if (iconSvg) {
9364
- iconSvg.style.display = "block";
9365
- clearChatButton.appendChild(iconSvg);
9366
- }
9367
- if (clearChatBgColor) {
9368
- clearChatButton.style.backgroundColor = clearChatBgColor;
9369
- clearChatButton.classList.remove("hover:persona-bg-gray-100");
9370
- }
9371
- if (clearChatBorderWidth || clearChatBorderColor) {
9372
- const borderWidth = clearChatBorderWidth || "0px";
9373
- const borderColor = clearChatBorderColor || "transparent";
9374
- clearChatButton.style.border = `${borderWidth} solid ${borderColor}`;
9375
- clearChatButton.classList.remove("persona-border-none");
9376
- }
9377
- if (clearChatBorderRadius) {
9378
- clearChatButton.style.borderRadius = clearChatBorderRadius;
9379
- clearChatButton.classList.remove("persona-rounded-full");
9380
- }
9381
- if (clearChatPaddingX) {
9382
- clearChatButton.style.paddingLeft = clearChatPaddingX;
9383
- clearChatButton.style.paddingRight = clearChatPaddingX;
9384
- } else {
9385
- clearChatButton.style.paddingLeft = "";
9386
- clearChatButton.style.paddingRight = "";
9387
- }
9388
- if (clearChatPaddingY) {
9389
- clearChatButton.style.paddingTop = clearChatPaddingY;
9390
- clearChatButton.style.paddingBottom = clearChatPaddingY;
9391
- } else {
9392
- clearChatButton.style.paddingTop = "";
9393
- clearChatButton.style.paddingBottom = "";
9394
- }
9395
- clearChatButtonWrapper.appendChild(clearChatButton);
9396
- if (clearChatShowTooltip && clearChatTooltipText && clearChatButton && clearChatButtonWrapper) {
9397
- let portaledTooltip = null;
9398
- const showTooltip = () => {
9399
- if (portaledTooltip || !clearChatButton) return;
9400
- const tooltipDocument = clearChatButton.ownerDocument;
9401
- const tooltipContainer = tooltipDocument.body;
9402
- if (!tooltipContainer) return;
9403
- portaledTooltip = createElementInDocument(
9404
- tooltipDocument,
9405
- "div",
9406
- "persona-clear-chat-tooltip"
9407
- );
9408
- portaledTooltip.textContent = clearChatTooltipText;
9409
- const arrow = createElementInDocument(tooltipDocument, "div");
9410
- arrow.className = "persona-clear-chat-tooltip-arrow";
9411
- portaledTooltip.appendChild(arrow);
9412
- const buttonRect = clearChatButton.getBoundingClientRect();
9413
- portaledTooltip.style.position = "fixed";
9414
- portaledTooltip.style.zIndex = String(PORTALED_OVERLAY_Z_INDEX);
9415
- portaledTooltip.style.left = `${buttonRect.left + buttonRect.width / 2}px`;
9416
- portaledTooltip.style.top = `${buttonRect.top - 8}px`;
9417
- portaledTooltip.style.transform = "translate(-50%, -100%)";
9418
- tooltipContainer.appendChild(portaledTooltip);
9419
- };
9420
- const hideTooltip = () => {
9421
- if (portaledTooltip && portaledTooltip.parentNode) {
9422
- portaledTooltip.parentNode.removeChild(portaledTooltip);
9423
- portaledTooltip = null;
9424
- }
9425
- };
9426
- clearChatButtonWrapper.addEventListener("mouseenter", showTooltip);
9427
- clearChatButtonWrapper.addEventListener("mouseleave", hideTooltip);
9428
- clearChatButton.addEventListener("focus", showTooltip);
9429
- clearChatButton.addEventListener("blur", hideTooltip);
9430
- clearChatButtonWrapper._cleanupTooltip = () => {
9431
- hideTooltip();
9432
- if (clearChatButtonWrapper) {
9433
- clearChatButtonWrapper.removeEventListener("mouseenter", showTooltip);
9434
- clearChatButtonWrapper.removeEventListener("mouseleave", hideTooltip);
9435
- }
9436
- if (clearChatButton) {
9437
- clearChatButton.removeEventListener("focus", showTooltip);
9438
- clearChatButton.removeEventListener("blur", hideTooltip);
9439
- }
9440
- };
9441
- }
9442
9730
  if (clearChatPlacement === "inline") {
9443
9731
  header.appendChild(clearChatButtonWrapper);
9444
9732
  }
9445
9733
  }
9446
- const closeButtonWrapper = createElement(
9447
- "div",
9448
- closeButtonPlacement === "top-right" ? "persona-absolute persona-top-4 persona-right-4 persona-z-50" : clearChatEnabled && clearChatPlacement === "inline" ? "persona-relative persona-inline-flex persona-items-center persona-justify-center" : "persona-relative persona-ml-auto persona-inline-flex persona-items-center persona-justify-center"
9449
- );
9450
- const closeButton = createElement(
9451
- "button",
9452
- "persona-inline-flex persona-items-center persona-justify-center persona-rounded-full hover:persona-bg-gray-100 persona-cursor-pointer persona-border-none"
9734
+ const closeButtonWrapperClass = closeButtonPlacement === "top-right" ? "persona-absolute persona-top-4 persona-right-4 persona-z-50" : clearChatEnabled && clearChatPlacement === "inline" ? "persona-relative persona-inline-flex persona-items-center persona-justify-center" : "persona-relative persona-ml-auto persona-inline-flex persona-items-center persona-justify-center";
9735
+ const { button: closeButton, wrapper: closeButtonWrapper } = createCloseButton(
9736
+ config,
9737
+ { showClose, wrapperClassName: closeButtonWrapperClass }
9453
9738
  );
9454
- closeButton.style.height = closeButtonSize;
9455
- closeButton.style.width = closeButtonSize;
9456
- closeButton.type = "button";
9457
- const closeButtonTooltipText = (_C = launcher.closeButtonTooltipText) != null ? _C : "Close chat";
9458
- const closeButtonShowTooltip = (_D = launcher.closeButtonShowTooltip) != null ? _D : true;
9459
- closeButton.setAttribute("aria-label", closeButtonTooltipText);
9460
- closeButton.style.display = showClose ? "" : "none";
9461
- const closeButtonIconName = (_E = launcher.closeButtonIconName) != null ? _E : "x";
9462
- const closeButtonIconText = (_F = launcher.closeButtonIconText) != null ? _F : "\xD7";
9463
- closeButton.style.color = launcher.closeButtonColor || HEADER_THEME_CSS.actionIconColor;
9464
- const closeIconSvg = renderLucideIcon(closeButtonIconName, "28px", "currentColor", 1);
9465
- if (closeIconSvg) {
9466
- closeIconSvg.style.display = "block";
9467
- closeButton.appendChild(closeIconSvg);
9468
- } else {
9469
- closeButton.textContent = closeButtonIconText;
9470
- }
9471
- if (launcher.closeButtonBackgroundColor) {
9472
- closeButton.style.backgroundColor = launcher.closeButtonBackgroundColor;
9473
- closeButton.classList.remove("hover:persona-bg-gray-100");
9474
- } else {
9475
- closeButton.style.backgroundColor = "";
9476
- closeButton.classList.add("hover:persona-bg-gray-100");
9477
- }
9478
- if (launcher.closeButtonBorderWidth || launcher.closeButtonBorderColor) {
9479
- const borderWidth = launcher.closeButtonBorderWidth || "0px";
9480
- const borderColor = launcher.closeButtonBorderColor || "transparent";
9481
- closeButton.style.border = `${borderWidth} solid ${borderColor}`;
9482
- closeButton.classList.remove("persona-border-none");
9483
- } else {
9484
- closeButton.style.border = "";
9485
- closeButton.classList.add("persona-border-none");
9486
- }
9487
- if (launcher.closeButtonBorderRadius) {
9488
- closeButton.style.borderRadius = launcher.closeButtonBorderRadius;
9489
- closeButton.classList.remove("persona-rounded-full");
9490
- } else {
9491
- closeButton.style.borderRadius = "";
9492
- closeButton.classList.add("persona-rounded-full");
9493
- }
9494
- if (launcher.closeButtonPaddingX) {
9495
- closeButton.style.paddingLeft = launcher.closeButtonPaddingX;
9496
- closeButton.style.paddingRight = launcher.closeButtonPaddingX;
9497
- } else {
9498
- closeButton.style.paddingLeft = "";
9499
- closeButton.style.paddingRight = "";
9500
- }
9501
- if (launcher.closeButtonPaddingY) {
9502
- closeButton.style.paddingTop = launcher.closeButtonPaddingY;
9503
- closeButton.style.paddingBottom = launcher.closeButtonPaddingY;
9504
- } else {
9505
- closeButton.style.paddingTop = "";
9506
- closeButton.style.paddingBottom = "";
9507
- }
9508
- closeButtonWrapper.appendChild(closeButton);
9509
- if (closeButtonShowTooltip && closeButtonTooltipText) {
9510
- let portaledTooltip = null;
9511
- const showTooltip = () => {
9512
- if (portaledTooltip) return;
9513
- const tooltipDocument = closeButton.ownerDocument;
9514
- const tooltipContainer = tooltipDocument.body;
9515
- if (!tooltipContainer) return;
9516
- portaledTooltip = createElementInDocument(
9517
- tooltipDocument,
9518
- "div",
9519
- "persona-clear-chat-tooltip"
9520
- );
9521
- portaledTooltip.textContent = closeButtonTooltipText;
9522
- const arrow = createElementInDocument(tooltipDocument, "div");
9523
- arrow.className = "persona-clear-chat-tooltip-arrow";
9524
- portaledTooltip.appendChild(arrow);
9525
- const buttonRect = closeButton.getBoundingClientRect();
9526
- portaledTooltip.style.position = "fixed";
9527
- portaledTooltip.style.zIndex = String(PORTALED_OVERLAY_Z_INDEX);
9528
- portaledTooltip.style.left = `${buttonRect.left + buttonRect.width / 2}px`;
9529
- portaledTooltip.style.top = `${buttonRect.top - 8}px`;
9530
- portaledTooltip.style.transform = "translate(-50%, -100%)";
9531
- tooltipContainer.appendChild(portaledTooltip);
9532
- };
9533
- const hideTooltip = () => {
9534
- if (portaledTooltip && portaledTooltip.parentNode) {
9535
- portaledTooltip.parentNode.removeChild(portaledTooltip);
9536
- portaledTooltip = null;
9537
- }
9538
- };
9539
- closeButtonWrapper.addEventListener("mouseenter", showTooltip);
9540
- closeButtonWrapper.addEventListener("mouseleave", hideTooltip);
9541
- closeButton.addEventListener("focus", showTooltip);
9542
- closeButton.addEventListener("blur", hideTooltip);
9543
- closeButtonWrapper._cleanupTooltip = () => {
9544
- hideTooltip();
9545
- closeButtonWrapper.removeEventListener("mouseenter", showTooltip);
9546
- closeButtonWrapper.removeEventListener("mouseleave", hideTooltip);
9547
- closeButton.removeEventListener("focus", showTooltip);
9548
- closeButton.removeEventListener("blur", hideTooltip);
9549
- };
9550
- }
9551
9739
  if (closeButtonPlacement !== "top-right") {
9552
9740
  header.appendChild(closeButtonWrapper);
9553
9741
  }
@@ -10084,25 +10272,9 @@ var buildHeaderWithLayout = (config, layoutConfig, context) => {
10084
10272
  return headerElements;
10085
10273
  };
10086
10274
 
10087
- // src/components/composer-builder.ts
10088
- var buildComposer = (context) => {
10089
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E;
10090
- const { config } = context;
10091
- const footer = createElement(
10092
- "div",
10093
- "persona-widget-footer persona-border-t-persona-divider persona-bg-persona-surface persona-px-6 persona-py-4"
10094
- );
10095
- footer.setAttribute("data-persona-theme-zone", "composer");
10096
- const suggestions = createElement(
10097
- "div",
10098
- "persona-mb-3 persona-flex persona-flex-wrap persona-gap-2"
10099
- );
10100
- const composerForm = createElement(
10101
- "form",
10102
- `persona-widget-composer persona-flex persona-flex-col persona-gap-2 persona-rounded-2xl persona-border persona-border-gray-200 persona-bg-persona-input-background persona-px-4 persona-py-3`
10103
- );
10104
- composerForm.setAttribute("data-persona-composer-form", "");
10105
- composerForm.style.outline = "none";
10275
+ // src/components/composer-parts.ts
10276
+ var createComposerTextarea = (config) => {
10277
+ var _a, _b;
10106
10278
  const textarea = createElement("textarea");
10107
10279
  textarea.setAttribute("data-persona-composer-input", "");
10108
10280
  textarea.placeholder = (_b = (_a = config == null ? void 0 : config.copy) == null ? void 0 : _a.inputPlaceholder) != null ? _b : "Type your message\u2026";
@@ -10110,17 +10282,21 @@ var buildComposer = (context) => {
10110
10282
  textarea.rows = 1;
10111
10283
  textarea.style.fontFamily = 'var(--persona-input-font-family, var(--persona-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial, sans-serif))';
10112
10284
  textarea.style.fontWeight = "var(--persona-input-font-weight, var(--persona-font-weight, 400))";
10113
- const maxLines = 3;
10285
+ const defaultMaxLines = 3;
10114
10286
  const lineHeight = 20;
10115
- const maxHeight = maxLines * lineHeight;
10116
- textarea.style.maxHeight = `${maxHeight}px`;
10287
+ textarea.style.maxHeight = `${defaultMaxLines * lineHeight}px`;
10117
10288
  textarea.style.overflowY = "auto";
10118
- const autoResize = () => {
10119
- textarea.style.height = "auto";
10120
- const newHeight = Math.min(textarea.scrollHeight, maxHeight);
10121
- textarea.style.height = `${newHeight}px`;
10289
+ const readMaxHeight = () => {
10290
+ const parsed = parseFloat(textarea.style.maxHeight);
10291
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : defaultMaxLines * lineHeight;
10292
+ };
10293
+ const attachAutoResize = () => {
10294
+ textarea.addEventListener("input", () => {
10295
+ textarea.style.height = "auto";
10296
+ const newHeight = Math.min(textarea.scrollHeight, readMaxHeight());
10297
+ textarea.style.height = `${newHeight}px`;
10298
+ });
10122
10299
  };
10123
- textarea.addEventListener("input", autoResize);
10124
10300
  textarea.style.border = "none";
10125
10301
  textarea.style.outline = "none";
10126
10302
  textarea.style.borderWidth = "0";
@@ -10138,333 +10314,474 @@ var buildComposer = (context) => {
10138
10314
  textarea.style.border = "none";
10139
10315
  textarea.style.outline = "none";
10140
10316
  });
10141
- const sendButtonConfig = (_c = config == null ? void 0 : config.sendButton) != null ? _c : {};
10142
- const useIcon = (_d = sendButtonConfig.useIcon) != null ? _d : false;
10143
- const iconText = (_e = sendButtonConfig.iconText) != null ? _e : "\u2191";
10317
+ return { textarea, attachAutoResize };
10318
+ };
10319
+ var createSendButton = (config) => {
10320
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
10321
+ const sendButtonConfig = (_a = config == null ? void 0 : config.sendButton) != null ? _a : {};
10322
+ const useIcon = (_b = sendButtonConfig.useIcon) != null ? _b : false;
10323
+ const iconText = (_c = sendButtonConfig.iconText) != null ? _c : "\u2191";
10144
10324
  const iconName = sendButtonConfig.iconName;
10145
- const stopIconName = (_f = sendButtonConfig.stopIconName) != null ? _f : "square";
10146
- const tooltipText = (_g = sendButtonConfig.tooltipText) != null ? _g : "Send message";
10147
- const stopTooltipText = (_h = sendButtonConfig.stopTooltipText) != null ? _h : "Stop generating";
10148
- const sendLabel = (_j = (_i = config == null ? void 0 : config.copy) == null ? void 0 : _i.sendButtonLabel) != null ? _j : "Send";
10149
- const stopLabel = (_l = (_k = config == null ? void 0 : config.copy) == null ? void 0 : _k.stopButtonLabel) != null ? _l : "Stop";
10150
- const showTooltip = (_m = sendButtonConfig.showTooltip) != null ? _m : false;
10151
- const buttonSize = (_n = sendButtonConfig.size) != null ? _n : "40px";
10325
+ const stopIconName = (_d = sendButtonConfig.stopIconName) != null ? _d : "square";
10326
+ const tooltipText = (_e = sendButtonConfig.tooltipText) != null ? _e : "Send message";
10327
+ const stopTooltipText = (_f = sendButtonConfig.stopTooltipText) != null ? _f : "Stop generating";
10328
+ const sendLabel = (_h = (_g = config == null ? void 0 : config.copy) == null ? void 0 : _g.sendButtonLabel) != null ? _h : "Send";
10329
+ const stopLabel = (_j = (_i = config == null ? void 0 : config.copy) == null ? void 0 : _i.stopButtonLabel) != null ? _j : "Stop";
10330
+ const showTooltip = (_k = sendButtonConfig.showTooltip) != null ? _k : false;
10331
+ const buttonSize = (_l = sendButtonConfig.size) != null ? _l : "40px";
10152
10332
  const backgroundColor = sendButtonConfig.backgroundColor;
10153
10333
  const textColor = sendButtonConfig.textColor;
10154
- const sendButtonWrapper = createElement("div", "persona-send-button-wrapper");
10155
- const sendButton = createElement(
10334
+ const wrapper = createElement("div", "persona-send-button-wrapper");
10335
+ const button = createElement(
10156
10336
  "button",
10157
10337
  useIcon ? "persona-rounded-button persona-flex persona-items-center persona-justify-center disabled:persona-opacity-50 persona-cursor-pointer" : "persona-rounded-button persona-bg-persona-accent persona-px-4 persona-py-2 persona-text-sm persona-font-semibold disabled:persona-opacity-50 persona-cursor-pointer"
10158
10338
  );
10159
- sendButton.type = "submit";
10160
- sendButton.setAttribute("data-persona-composer-submit", "");
10339
+ button.type = "submit";
10340
+ button.setAttribute("data-persona-composer-submit", "");
10161
10341
  let sendIcon = null;
10162
10342
  let stopIcon = null;
10163
10343
  if (useIcon) {
10164
- sendButton.style.width = buttonSize;
10165
- sendButton.style.height = buttonSize;
10166
- sendButton.style.minWidth = buttonSize;
10167
- sendButton.style.minHeight = buttonSize;
10168
- sendButton.style.fontSize = "18px";
10169
- sendButton.style.lineHeight = "1";
10170
- sendButton.innerHTML = "";
10344
+ button.style.width = buttonSize;
10345
+ button.style.height = buttonSize;
10346
+ button.style.minWidth = buttonSize;
10347
+ button.style.minHeight = buttonSize;
10348
+ button.style.fontSize = "18px";
10349
+ button.style.lineHeight = "1";
10350
+ button.innerHTML = "";
10171
10351
  if (textColor) {
10172
- sendButton.style.color = textColor;
10352
+ button.style.color = textColor;
10173
10353
  } else {
10174
- sendButton.style.color = "var(--persona-button-primary-fg, #ffffff)";
10354
+ button.style.color = "var(--persona-button-primary-fg, #ffffff)";
10175
10355
  }
10176
10356
  const iconSize = parseFloat(buttonSize) || 24;
10177
10357
  const iconColor = (textColor == null ? void 0 : textColor.trim()) || "currentColor";
10178
10358
  if (iconName) {
10179
10359
  sendIcon = renderLucideIcon(iconName, iconSize, iconColor, 2);
10180
10360
  if (sendIcon) {
10181
- sendButton.appendChild(sendIcon);
10361
+ button.appendChild(sendIcon);
10182
10362
  } else {
10183
- sendButton.textContent = iconText;
10363
+ button.textContent = iconText;
10184
10364
  }
10185
10365
  } else {
10186
- sendButton.textContent = iconText;
10366
+ button.textContent = iconText;
10187
10367
  }
10188
10368
  stopIcon = renderLucideIcon(stopIconName, iconSize, iconColor, 2);
10189
10369
  if (backgroundColor) {
10190
- sendButton.style.backgroundColor = backgroundColor;
10370
+ button.style.backgroundColor = backgroundColor;
10191
10371
  } else {
10192
- sendButton.classList.add("persona-bg-persona-primary");
10372
+ button.classList.add("persona-bg-persona-primary");
10193
10373
  }
10194
10374
  } else {
10195
- sendButton.textContent = sendLabel;
10375
+ button.textContent = sendLabel;
10196
10376
  if (textColor) {
10197
- sendButton.style.color = textColor;
10377
+ button.style.color = textColor;
10198
10378
  } else {
10199
- sendButton.classList.add("persona-text-white");
10379
+ button.classList.add("persona-text-white");
10200
10380
  }
10201
10381
  }
10202
10382
  if (sendButtonConfig.borderWidth) {
10203
- sendButton.style.borderWidth = sendButtonConfig.borderWidth;
10204
- sendButton.style.borderStyle = "solid";
10383
+ button.style.borderWidth = sendButtonConfig.borderWidth;
10384
+ button.style.borderStyle = "solid";
10205
10385
  }
10206
10386
  if (sendButtonConfig.borderColor) {
10207
- sendButton.style.borderColor = sendButtonConfig.borderColor;
10387
+ button.style.borderColor = sendButtonConfig.borderColor;
10208
10388
  }
10209
10389
  if (sendButtonConfig.paddingX) {
10210
- sendButton.style.paddingLeft = sendButtonConfig.paddingX;
10211
- sendButton.style.paddingRight = sendButtonConfig.paddingX;
10390
+ button.style.paddingLeft = sendButtonConfig.paddingX;
10391
+ button.style.paddingRight = sendButtonConfig.paddingX;
10212
10392
  } else {
10213
- sendButton.style.paddingLeft = "";
10214
- sendButton.style.paddingRight = "";
10393
+ button.style.paddingLeft = "";
10394
+ button.style.paddingRight = "";
10215
10395
  }
10216
10396
  if (sendButtonConfig.paddingY) {
10217
- sendButton.style.paddingTop = sendButtonConfig.paddingY;
10218
- sendButton.style.paddingBottom = sendButtonConfig.paddingY;
10397
+ button.style.paddingTop = sendButtonConfig.paddingY;
10398
+ button.style.paddingBottom = sendButtonConfig.paddingY;
10219
10399
  } else {
10220
- sendButton.style.paddingTop = "";
10221
- sendButton.style.paddingBottom = "";
10400
+ button.style.paddingTop = "";
10401
+ button.style.paddingBottom = "";
10222
10402
  }
10223
- let sendTooltip = null;
10403
+ let tooltip = null;
10224
10404
  if (showTooltip && tooltipText) {
10225
- sendTooltip = createElement("div", "persona-send-button-tooltip");
10226
- sendTooltip.textContent = tooltipText;
10227
- sendButtonWrapper.appendChild(sendTooltip);
10405
+ tooltip = createElement("div", "persona-send-button-tooltip");
10406
+ tooltip.textContent = tooltipText;
10407
+ wrapper.appendChild(tooltip);
10228
10408
  }
10229
- sendButton.setAttribute("aria-label", tooltipText);
10230
- sendButtonWrapper.appendChild(sendButton);
10409
+ button.setAttribute("aria-label", tooltipText);
10410
+ wrapper.appendChild(button);
10231
10411
  let currentMode = "send";
10232
- const setSendButtonMode = (mode) => {
10412
+ const setMode = (mode) => {
10233
10413
  if (mode === currentMode) return;
10234
10414
  currentMode = mode;
10235
10415
  const label = mode === "stop" ? stopTooltipText : tooltipText;
10236
- sendButton.setAttribute("aria-label", label);
10237
- if (sendTooltip) {
10238
- sendTooltip.textContent = label;
10416
+ button.setAttribute("aria-label", label);
10417
+ if (tooltip) {
10418
+ tooltip.textContent = label;
10239
10419
  }
10240
10420
  if (useIcon) {
10241
10421
  if (sendIcon && stopIcon) {
10242
10422
  const next = mode === "stop" ? stopIcon : sendIcon;
10243
10423
  const prev = mode === "stop" ? sendIcon : stopIcon;
10244
- if (prev.parentNode === sendButton) {
10245
- sendButton.replaceChild(next, prev);
10424
+ if (prev.parentNode === button) {
10425
+ button.replaceChild(next, prev);
10246
10426
  } else {
10247
- sendButton.appendChild(next);
10427
+ button.appendChild(next);
10248
10428
  }
10249
10429
  }
10250
10430
  } else {
10251
- sendButton.textContent = mode === "stop" ? stopLabel : sendLabel;
10431
+ button.textContent = mode === "stop" ? stopLabel : sendLabel;
10252
10432
  }
10253
10433
  };
10254
- const voiceRecognitionConfig = (_o = config == null ? void 0 : config.voiceRecognition) != null ? _o : {};
10434
+ return { button, wrapper, setMode };
10435
+ };
10436
+ var createMicButton = (config) => {
10437
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
10438
+ const voiceRecognitionConfig = (_a = config == null ? void 0 : config.voiceRecognition) != null ? _a : {};
10255
10439
  const voiceRecognitionEnabled = voiceRecognitionConfig.enabled === true;
10256
- let micButton = null;
10257
- let micButtonWrapper = null;
10440
+ if (!voiceRecognitionEnabled) return null;
10258
10441
  const hasSpeechRecognition = typeof window !== "undefined" && (typeof window.webkitSpeechRecognition !== "undefined" || typeof window.SpeechRecognition !== "undefined");
10259
- const hasRuntypeProvider = ((_p = voiceRecognitionConfig.provider) == null ? void 0 : _p.type) === "runtype";
10442
+ const hasRuntypeProvider = ((_b = voiceRecognitionConfig.provider) == null ? void 0 : _b.type) === "runtype";
10260
10443
  const hasVoiceInput = hasSpeechRecognition || hasRuntypeProvider;
10261
- if (voiceRecognitionEnabled && hasVoiceInput) {
10262
- micButtonWrapper = createElement("div", "persona-send-button-wrapper");
10263
- micButton = createElement(
10264
- "button",
10265
- "persona-rounded-button persona-flex persona-items-center persona-justify-center disabled:persona-opacity-50 persona-cursor-pointer"
10266
- );
10267
- micButton.type = "button";
10268
- micButton.setAttribute("data-persona-composer-mic", "");
10269
- micButton.setAttribute("aria-label", "Start voice recognition");
10270
- const micIconName = (_q = voiceRecognitionConfig.iconName) != null ? _q : "mic";
10271
- const micIconSize = (_r = voiceRecognitionConfig.iconSize) != null ? _r : buttonSize;
10272
- const micIconSizeNum = parseFloat(micIconSize) || 24;
10273
- const micBackgroundColor = (_s = voiceRecognitionConfig.backgroundColor) != null ? _s : backgroundColor;
10274
- const micIconColor = (_t = voiceRecognitionConfig.iconColor) != null ? _t : textColor;
10275
- micButton.style.width = micIconSize;
10276
- micButton.style.height = micIconSize;
10277
- micButton.style.minWidth = micIconSize;
10278
- micButton.style.minHeight = micIconSize;
10279
- micButton.style.fontSize = "18px";
10280
- micButton.style.lineHeight = "1";
10281
- if (micIconColor) {
10282
- micButton.style.color = micIconColor;
10283
- } else {
10284
- micButton.style.color = "var(--persona-text, #111827)";
10285
- }
10286
- const iconColorValue = micIconColor || "currentColor";
10287
- const micIconSvg = renderLucideIcon(
10288
- micIconName,
10289
- micIconSizeNum,
10290
- iconColorValue,
10291
- 1.5
10292
- );
10293
- if (micIconSvg) {
10294
- micButton.appendChild(micIconSvg);
10295
- } else {
10296
- micButton.textContent = "\u{1F3A4}";
10297
- }
10298
- if (micBackgroundColor) {
10299
- micButton.style.backgroundColor = micBackgroundColor;
10300
- }
10301
- if (voiceRecognitionConfig.borderWidth) {
10302
- micButton.style.borderWidth = voiceRecognitionConfig.borderWidth;
10303
- micButton.style.borderStyle = "solid";
10304
- }
10305
- if (voiceRecognitionConfig.borderColor) {
10306
- micButton.style.borderColor = voiceRecognitionConfig.borderColor;
10307
- }
10308
- if (voiceRecognitionConfig.paddingX) {
10309
- micButton.style.paddingLeft = voiceRecognitionConfig.paddingX;
10310
- micButton.style.paddingRight = voiceRecognitionConfig.paddingX;
10311
- }
10312
- if (voiceRecognitionConfig.paddingY) {
10313
- micButton.style.paddingTop = voiceRecognitionConfig.paddingY;
10314
- micButton.style.paddingBottom = voiceRecognitionConfig.paddingY;
10315
- }
10316
- micButtonWrapper.appendChild(micButton);
10317
- const micTooltipText = (_u = voiceRecognitionConfig.tooltipText) != null ? _u : "Start voice recognition";
10318
- const showMicTooltip = (_v = voiceRecognitionConfig.showTooltip) != null ? _v : false;
10319
- if (showMicTooltip && micTooltipText) {
10320
- const tooltip = createElement("div", "persona-send-button-tooltip");
10321
- tooltip.textContent = micTooltipText;
10322
- micButtonWrapper.appendChild(tooltip);
10323
- }
10324
- }
10325
- const attachmentsConfig = (_w = config == null ? void 0 : config.attachments) != null ? _w : {};
10326
- const attachmentsEnabled = attachmentsConfig.enabled === true;
10327
- let attachmentButton = null;
10328
- let attachmentButtonWrapper = null;
10329
- let attachmentInput = null;
10330
- let attachmentPreviewsContainer = null;
10331
- if (attachmentsEnabled) {
10332
- attachmentPreviewsContainer = createElement(
10333
- "div",
10334
- "persona-attachment-previews persona-flex persona-flex-wrap persona-gap-2 persona-mb-2"
10335
- );
10336
- attachmentPreviewsContainer.style.display = "none";
10337
- attachmentInput = createElement("input");
10338
- attachmentInput.type = "file";
10339
- attachmentInput.accept = ((_x = attachmentsConfig.allowedTypes) != null ? _x : ALL_SUPPORTED_MIME_TYPES).join(",");
10340
- attachmentInput.multiple = ((_y = attachmentsConfig.maxFiles) != null ? _y : 4) > 1;
10341
- attachmentInput.style.display = "none";
10342
- attachmentInput.setAttribute("aria-label", "Attach files");
10343
- attachmentButtonWrapper = createElement("div", "persona-send-button-wrapper");
10344
- attachmentButton = createElement(
10345
- "button",
10346
- "persona-rounded-button persona-flex persona-items-center persona-justify-center disabled:persona-opacity-50 persona-cursor-pointer persona-attachment-button"
10347
- );
10348
- attachmentButton.type = "button";
10349
- attachmentButton.setAttribute("aria-label", (_z = attachmentsConfig.buttonTooltipText) != null ? _z : "Attach file");
10350
- const attachIconName = (_A = attachmentsConfig.buttonIconName) != null ? _A : "paperclip";
10351
- const attachIconSize = buttonSize;
10352
- const buttonSizeNum = parseFloat(attachIconSize) || 40;
10353
- const attachIconSizeNum = Math.round(buttonSizeNum * 0.6);
10354
- attachmentButton.style.width = attachIconSize;
10355
- attachmentButton.style.height = attachIconSize;
10356
- attachmentButton.style.minWidth = attachIconSize;
10357
- attachmentButton.style.minHeight = attachIconSize;
10358
- attachmentButton.style.fontSize = "18px";
10359
- attachmentButton.style.lineHeight = "1";
10360
- attachmentButton.style.backgroundColor = "transparent";
10361
- attachmentButton.style.color = "var(--persona-primary, #111827)";
10362
- attachmentButton.style.border = "none";
10363
- attachmentButton.style.borderRadius = "6px";
10364
- attachmentButton.style.transition = "background-color 0.15s ease";
10365
- attachmentButton.addEventListener("mouseenter", () => {
10366
- attachmentButton.style.backgroundColor = "var(--persona-palette-colors-black-alpha-50, rgba(0, 0, 0, 0.05))";
10367
- });
10368
- attachmentButton.addEventListener("mouseleave", () => {
10369
- attachmentButton.style.backgroundColor = "transparent";
10370
- });
10371
- const attachIconSvg = renderLucideIcon(
10372
- attachIconName,
10373
- attachIconSizeNum,
10374
- "currentColor",
10375
- 1.5
10376
- );
10377
- if (attachIconSvg) {
10378
- attachmentButton.appendChild(attachIconSvg);
10379
- } else {
10380
- attachmentButton.textContent = "\u{1F4CE}";
10381
- }
10382
- attachmentButton.addEventListener("click", (e) => {
10383
- e.preventDefault();
10384
- attachmentInput == null ? void 0 : attachmentInput.click();
10385
- });
10386
- attachmentButtonWrapper.appendChild(attachmentButton);
10387
- const attachTooltipText = (_B = attachmentsConfig.buttonTooltipText) != null ? _B : "Attach file";
10444
+ if (!hasVoiceInput) return null;
10445
+ const buttonSize = (_d = (_c = config == null ? void 0 : config.sendButton) == null ? void 0 : _c.size) != null ? _d : "40px";
10446
+ const wrapper = createElement("div", "persona-send-button-wrapper");
10447
+ const button = createElement(
10448
+ "button",
10449
+ "persona-rounded-button persona-flex persona-items-center persona-justify-center disabled:persona-opacity-50 persona-cursor-pointer"
10450
+ );
10451
+ button.type = "button";
10452
+ button.setAttribute("data-persona-composer-mic", "");
10453
+ button.setAttribute("aria-label", "Start voice recognition");
10454
+ const micIconName = (_e = voiceRecognitionConfig.iconName) != null ? _e : "mic";
10455
+ const micIconSize = (_f = voiceRecognitionConfig.iconSize) != null ? _f : buttonSize;
10456
+ const micIconSizeNum = parseFloat(micIconSize) || 24;
10457
+ const micBackgroundColor = (_h = voiceRecognitionConfig.backgroundColor) != null ? _h : (_g = config == null ? void 0 : config.sendButton) == null ? void 0 : _g.backgroundColor;
10458
+ const micIconColor = (_j = voiceRecognitionConfig.iconColor) != null ? _j : (_i = config == null ? void 0 : config.sendButton) == null ? void 0 : _i.textColor;
10459
+ button.style.width = micIconSize;
10460
+ button.style.height = micIconSize;
10461
+ button.style.minWidth = micIconSize;
10462
+ button.style.minHeight = micIconSize;
10463
+ button.style.fontSize = "18px";
10464
+ button.style.lineHeight = "1";
10465
+ if (micIconColor) {
10466
+ button.style.color = micIconColor;
10467
+ } else {
10468
+ button.style.color = "var(--persona-text, #111827)";
10469
+ }
10470
+ const iconColorValue = micIconColor || "currentColor";
10471
+ const micIconSvg = renderLucideIcon(micIconName, micIconSizeNum, iconColorValue, 1.5);
10472
+ if (micIconSvg) {
10473
+ button.appendChild(micIconSvg);
10474
+ } else {
10475
+ button.textContent = "\u{1F3A4}";
10476
+ }
10477
+ if (micBackgroundColor) {
10478
+ button.style.backgroundColor = micBackgroundColor;
10479
+ }
10480
+ if (voiceRecognitionConfig.borderWidth) {
10481
+ button.style.borderWidth = voiceRecognitionConfig.borderWidth;
10482
+ button.style.borderStyle = "solid";
10483
+ }
10484
+ if (voiceRecognitionConfig.borderColor) {
10485
+ button.style.borderColor = voiceRecognitionConfig.borderColor;
10486
+ }
10487
+ if (voiceRecognitionConfig.paddingX) {
10488
+ button.style.paddingLeft = voiceRecognitionConfig.paddingX;
10489
+ button.style.paddingRight = voiceRecognitionConfig.paddingX;
10490
+ }
10491
+ if (voiceRecognitionConfig.paddingY) {
10492
+ button.style.paddingTop = voiceRecognitionConfig.paddingY;
10493
+ button.style.paddingBottom = voiceRecognitionConfig.paddingY;
10494
+ }
10495
+ wrapper.appendChild(button);
10496
+ const micTooltipText = (_k = voiceRecognitionConfig.tooltipText) != null ? _k : "Start voice recognition";
10497
+ const showMicTooltip = (_l = voiceRecognitionConfig.showTooltip) != null ? _l : false;
10498
+ if (showMicTooltip && micTooltipText) {
10388
10499
  const tooltip = createElement("div", "persona-send-button-tooltip");
10389
- tooltip.textContent = attachTooltipText;
10390
- attachmentButtonWrapper.appendChild(tooltip);
10500
+ tooltip.textContent = micTooltipText;
10501
+ wrapper.appendChild(tooltip);
10391
10502
  }
10392
- composerForm.addEventListener("click", (e) => {
10393
- if (e.target !== sendButton && e.target !== sendButtonWrapper && e.target !== micButton && e.target !== micButtonWrapper && e.target !== attachmentButton && e.target !== attachmentButtonWrapper) {
10394
- textarea.focus();
10395
- }
10503
+ return { button, wrapper };
10504
+ };
10505
+ var createAttachmentControls = (config) => {
10506
+ var _a, _b, _c, _d, _e, _f, _g, _h;
10507
+ const attachmentsConfig = (_a = config == null ? void 0 : config.attachments) != null ? _a : {};
10508
+ if (attachmentsConfig.enabled !== true) return null;
10509
+ const buttonSize = (_c = (_b = config == null ? void 0 : config.sendButton) == null ? void 0 : _b.size) != null ? _c : "40px";
10510
+ const previewsContainer = createElement(
10511
+ "div",
10512
+ "persona-attachment-previews persona-flex persona-flex-wrap persona-gap-2 persona-mb-2"
10513
+ );
10514
+ previewsContainer.style.display = "none";
10515
+ const input = createElement("input");
10516
+ input.type = "file";
10517
+ input.accept = ((_d = attachmentsConfig.allowedTypes) != null ? _d : ALL_SUPPORTED_MIME_TYPES).join(",");
10518
+ input.multiple = ((_e = attachmentsConfig.maxFiles) != null ? _e : 4) > 1;
10519
+ input.style.display = "none";
10520
+ input.setAttribute("aria-label", "Attach files");
10521
+ const wrapper = createElement("div", "persona-send-button-wrapper");
10522
+ const button = createElement(
10523
+ "button",
10524
+ "persona-rounded-button persona-flex persona-items-center persona-justify-center disabled:persona-opacity-50 persona-cursor-pointer persona-attachment-button"
10525
+ );
10526
+ button.type = "button";
10527
+ button.setAttribute("aria-label", (_f = attachmentsConfig.buttonTooltipText) != null ? _f : "Attach file");
10528
+ const attachIconName = (_g = attachmentsConfig.buttonIconName) != null ? _g : "paperclip";
10529
+ const attachIconSize = buttonSize;
10530
+ const buttonSizeNum = parseFloat(attachIconSize) || 40;
10531
+ const attachIconSizeNum = Math.round(buttonSizeNum * 0.6);
10532
+ button.style.width = attachIconSize;
10533
+ button.style.height = attachIconSize;
10534
+ button.style.minWidth = attachIconSize;
10535
+ button.style.minHeight = attachIconSize;
10536
+ button.style.fontSize = "18px";
10537
+ button.style.lineHeight = "1";
10538
+ button.style.backgroundColor = "transparent";
10539
+ button.style.color = "var(--persona-primary, #111827)";
10540
+ button.style.border = "none";
10541
+ button.style.borderRadius = "6px";
10542
+ button.style.transition = "background-color 0.15s ease";
10543
+ button.addEventListener("mouseenter", () => {
10544
+ button.style.backgroundColor = "var(--persona-palette-colors-black-alpha-50, rgba(0, 0, 0, 0.05))";
10396
10545
  });
10397
- if (attachmentPreviewsContainer) {
10398
- attachmentPreviewsContainer.style.gap = "8px";
10399
- composerForm.append(attachmentPreviewsContainer);
10400
- }
10401
- if (attachmentInput) {
10402
- composerForm.append(attachmentInput);
10546
+ button.addEventListener("mouseleave", () => {
10547
+ button.style.backgroundColor = "transparent";
10548
+ });
10549
+ const attachIconSvg = renderLucideIcon(attachIconName, attachIconSizeNum, "currentColor", 1.5);
10550
+ if (attachIconSvg) {
10551
+ button.appendChild(attachIconSvg);
10552
+ } else {
10553
+ button.textContent = "\u{1F4CE}";
10403
10554
  }
10404
- composerForm.append(textarea);
10405
- const actionsRow = createElement("div", "persona-flex persona-items-center persona-justify-between persona-w-full");
10406
- const leftActions = createElement("div", "persona-flex persona-items-center persona-gap-2");
10407
- if (attachmentButtonWrapper) {
10408
- leftActions.append(attachmentButtonWrapper);
10555
+ button.addEventListener("click", (e) => {
10556
+ e.preventDefault();
10557
+ input.click();
10558
+ });
10559
+ wrapper.appendChild(button);
10560
+ const attachTooltipText = (_h = attachmentsConfig.buttonTooltipText) != null ? _h : "Attach file";
10561
+ const tooltip = createElement("div", "persona-send-button-tooltip");
10562
+ tooltip.textContent = attachTooltipText;
10563
+ wrapper.appendChild(tooltip);
10564
+ return { button, wrapper, input, previewsContainer };
10565
+ };
10566
+ var createStatusText = (config) => {
10567
+ var _a, _b, _c;
10568
+ const statusConfig = (_a = config == null ? void 0 : config.statusIndicator) != null ? _a : {};
10569
+ const alignClass = statusConfig.align === "left" ? "persona-text-left" : statusConfig.align === "center" ? "persona-text-center" : "persona-text-right";
10570
+ const statusText = createElement(
10571
+ "div",
10572
+ `persona-mt-2 ${alignClass} persona-text-xs persona-text-persona-muted`
10573
+ );
10574
+ statusText.setAttribute("data-persona-composer-status", "");
10575
+ const isVisible = (_b = statusConfig.visible) != null ? _b : true;
10576
+ statusText.style.display = isVisible ? "" : "none";
10577
+ const idleLabel = (_c = statusConfig.idleText) != null ? _c : "Online";
10578
+ if (statusConfig.idleLink) {
10579
+ const link = createElement("a");
10580
+ link.href = statusConfig.idleLink;
10581
+ link.target = "_blank";
10582
+ link.rel = "noopener noreferrer";
10583
+ link.textContent = idleLabel;
10584
+ link.style.color = "inherit";
10585
+ link.style.textDecoration = "none";
10586
+ statusText.appendChild(link);
10587
+ } else {
10588
+ statusText.textContent = idleLabel;
10409
10589
  }
10410
- const rightActions = createElement("div", "persona-flex persona-items-center persona-gap-1");
10411
- if (micButtonWrapper) {
10412
- rightActions.append(micButtonWrapper);
10590
+ return statusText;
10591
+ };
10592
+ var createSuggestionsRow = () => createElement("div", "persona-mb-3 persona-flex persona-flex-wrap persona-gap-2");
10593
+
10594
+ // src/components/composer-builder.ts
10595
+ var buildComposer = (context) => {
10596
+ var _a, _b, _c, _d, _e, _f;
10597
+ const { config } = context;
10598
+ const footer = createElement(
10599
+ "div",
10600
+ "persona-widget-footer persona-border-t-persona-divider persona-bg-persona-surface persona-px-6 persona-py-4"
10601
+ );
10602
+ footer.setAttribute("data-persona-theme-zone", "composer");
10603
+ const suggestions = createSuggestionsRow();
10604
+ const composerForm = createElement(
10605
+ "form",
10606
+ "persona-widget-composer persona-flex persona-flex-col persona-gap-2 persona-rounded-2xl persona-border persona-border-gray-200 persona-bg-persona-input-background persona-px-4 persona-py-3"
10607
+ );
10608
+ composerForm.setAttribute("data-persona-composer-form", "");
10609
+ composerForm.style.outline = "none";
10610
+ const { textarea, attachAutoResize } = createComposerTextarea(config);
10611
+ attachAutoResize();
10612
+ const send = createSendButton(config);
10613
+ const mic = createMicButton(config);
10614
+ const attachment = createAttachmentControls(config);
10615
+ const statusText = createStatusText(config);
10616
+ if (attachment) {
10617
+ attachment.previewsContainer.style.gap = "8px";
10618
+ composerForm.append(attachment.previewsContainer, attachment.input);
10413
10619
  }
10414
- rightActions.append(sendButtonWrapper);
10620
+ composerForm.append(textarea);
10621
+ const actionsRow = createElement(
10622
+ "div",
10623
+ "persona-widget-composer__actions persona-flex persona-items-center persona-justify-between persona-w-full"
10624
+ );
10625
+ const leftActions = createElement(
10626
+ "div",
10627
+ "persona-widget-composer__left-actions persona-flex persona-items-center persona-gap-2"
10628
+ );
10629
+ const rightActions = createElement(
10630
+ "div",
10631
+ "persona-widget-composer__right-actions persona-flex persona-items-center persona-gap-1"
10632
+ );
10633
+ if (attachment) leftActions.append(attachment.wrapper);
10634
+ if (mic) rightActions.append(mic.wrapper);
10635
+ rightActions.append(send.wrapper);
10415
10636
  actionsRow.append(leftActions, rightActions);
10416
10637
  composerForm.append(actionsRow);
10417
- const statusConfig = (_C = config == null ? void 0 : config.statusIndicator) != null ? _C : {};
10418
- const alignClass = statusConfig.align === "left" ? "persona-text-left" : statusConfig.align === "center" ? "persona-text-center" : "persona-text-right";
10419
- const statusText = createElement(
10638
+ composerForm.addEventListener("click", (e) => {
10639
+ if (e.target !== send.button && e.target !== send.wrapper && e.target !== (mic == null ? void 0 : mic.button) && e.target !== (mic == null ? void 0 : mic.wrapper) && e.target !== (attachment == null ? void 0 : attachment.button) && e.target !== (attachment == null ? void 0 : attachment.wrapper)) {
10640
+ textarea.focus();
10641
+ }
10642
+ });
10643
+ footer.append(suggestions, composerForm, statusText);
10644
+ return {
10645
+ footer,
10646
+ suggestions,
10647
+ composerForm,
10648
+ textarea,
10649
+ sendButton: send.button,
10650
+ sendButtonWrapper: send.wrapper,
10651
+ micButton: (_a = mic == null ? void 0 : mic.button) != null ? _a : null,
10652
+ micButtonWrapper: (_b = mic == null ? void 0 : mic.wrapper) != null ? _b : null,
10653
+ statusText,
10654
+ attachmentButton: (_c = attachment == null ? void 0 : attachment.button) != null ? _c : null,
10655
+ attachmentButtonWrapper: (_d = attachment == null ? void 0 : attachment.wrapper) != null ? _d : null,
10656
+ attachmentInput: (_e = attachment == null ? void 0 : attachment.input) != null ? _e : null,
10657
+ attachmentPreviewsContainer: (_f = attachment == null ? void 0 : attachment.previewsContainer) != null ? _f : null,
10658
+ actionsRow,
10659
+ leftActions,
10660
+ rightActions,
10661
+ setSendButtonMode: send.setMode
10662
+ };
10663
+ };
10664
+
10665
+ // src/components/pill-composer-builder.ts
10666
+ var buildPillPeekBanner = () => {
10667
+ const root = createElement("button", "persona-pill-peek");
10668
+ root.type = "button";
10669
+ root.setAttribute("data-persona-pill-peek", "");
10670
+ root.setAttribute("aria-label", "Show conversation");
10671
+ root.setAttribute("tabindex", "-1");
10672
+ const iconHolder = createElement("span", "persona-pill-peek__icon");
10673
+ const messageIcon = renderLucideIcon("message-square", 16, "currentColor", 1.5);
10674
+ if (messageIcon) {
10675
+ iconHolder.appendChild(messageIcon);
10676
+ }
10677
+ const textNode = createElement("span", "persona-pill-peek__text");
10678
+ const caret = createElement("span", "persona-pill-peek__caret");
10679
+ const caretIcon = renderLucideIcon("chevron-up", 16, "currentColor", 1.5);
10680
+ if (caretIcon) {
10681
+ caret.appendChild(caretIcon);
10682
+ }
10683
+ root.append(iconHolder, textNode, caret);
10684
+ return { root, textNode };
10685
+ };
10686
+ var buildPillComposer = (context) => {
10687
+ var _a, _b, _c, _d, _e, _f;
10688
+ const { config } = context;
10689
+ const footer = createElement("div", "persona-widget-footer persona-widget-footer--pill");
10690
+ footer.setAttribute("data-persona-theme-zone", "composer");
10691
+ const suggestions = createSuggestionsRow();
10692
+ suggestions.style.display = "none";
10693
+ const statusText = createStatusText(config);
10694
+ statusText.style.display = "none";
10695
+ const { textarea, attachAutoResize } = createComposerTextarea(config);
10696
+ textarea.style.maxHeight = "100px";
10697
+ attachAutoResize();
10698
+ const send = createSendButton(config);
10699
+ const mic = createMicButton(config);
10700
+ const attachment = createAttachmentControls(config);
10701
+ if (attachment) {
10702
+ attachment.previewsContainer.classList.add("persona-pill-composer__previews");
10703
+ }
10704
+ const composerForm = createElement(
10705
+ "form",
10706
+ "persona-widget-composer persona-pill-composer"
10707
+ );
10708
+ composerForm.setAttribute("data-persona-composer-form", "");
10709
+ composerForm.style.outline = "none";
10710
+ const leftActions = createElement(
10420
10711
  "div",
10421
- `persona-mt-2 ${alignClass} persona-text-xs persona-text-persona-muted`
10712
+ "persona-widget-composer__left-actions persona-pill-composer__left"
10422
10713
  );
10423
- statusText.setAttribute("data-persona-composer-status", "");
10424
- const isVisible = (_D = statusConfig.visible) != null ? _D : true;
10425
- statusText.style.display = isVisible ? "" : "none";
10426
- const idleLabel = (_E = statusConfig.idleText) != null ? _E : "Online";
10427
- if (statusConfig.idleLink) {
10428
- const link = createElement("a");
10429
- link.href = statusConfig.idleLink;
10430
- link.target = "_blank";
10431
- link.rel = "noopener noreferrer";
10432
- link.textContent = idleLabel;
10433
- link.style.color = "inherit";
10434
- link.style.textDecoration = "none";
10435
- statusText.appendChild(link);
10436
- } else {
10437
- statusText.textContent = idleLabel;
10438
- }
10439
- footer.append(suggestions, composerForm, statusText);
10714
+ if (attachment) leftActions.append(attachment.wrapper);
10715
+ const rightActions = createElement(
10716
+ "div",
10717
+ "persona-widget-composer__right-actions persona-pill-composer__right"
10718
+ );
10719
+ if (mic) rightActions.append(mic.wrapper);
10720
+ rightActions.append(send.wrapper);
10721
+ composerForm.addEventListener("click", (e) => {
10722
+ if (e.target !== send.button && e.target !== send.wrapper && e.target !== (mic == null ? void 0 : mic.button) && e.target !== (mic == null ? void 0 : mic.wrapper) && e.target !== (attachment == null ? void 0 : attachment.button) && e.target !== (attachment == null ? void 0 : attachment.wrapper)) {
10723
+ textarea.focus();
10724
+ }
10725
+ });
10726
+ if (attachment) composerForm.append(attachment.input);
10727
+ composerForm.append(leftActions, textarea, rightActions);
10728
+ if (attachment) footer.append(attachment.previewsContainer);
10729
+ footer.append(composerForm, suggestions, statusText);
10730
+ const actionsRow = composerForm;
10440
10731
  return {
10441
10732
  footer,
10442
10733
  suggestions,
10443
10734
  composerForm,
10444
10735
  textarea,
10445
- sendButton,
10446
- sendButtonWrapper,
10447
- micButton,
10448
- micButtonWrapper,
10736
+ sendButton: send.button,
10737
+ sendButtonWrapper: send.wrapper,
10738
+ micButton: (_a = mic == null ? void 0 : mic.button) != null ? _a : null,
10739
+ micButtonWrapper: (_b = mic == null ? void 0 : mic.wrapper) != null ? _b : null,
10449
10740
  statusText,
10450
- // Attachment elements
10451
- attachmentButton,
10452
- attachmentButtonWrapper,
10453
- attachmentInput,
10454
- attachmentPreviewsContainer,
10455
- // Actions row layout elements
10741
+ attachmentButton: (_c = attachment == null ? void 0 : attachment.button) != null ? _c : null,
10742
+ attachmentButtonWrapper: (_d = attachment == null ? void 0 : attachment.wrapper) != null ? _d : null,
10743
+ attachmentInput: (_e = attachment == null ? void 0 : attachment.input) != null ? _e : null,
10744
+ attachmentPreviewsContainer: (_f = attachment == null ? void 0 : attachment.previewsContainer) != null ? _f : null,
10456
10745
  actionsRow,
10457
10746
  leftActions,
10458
10747
  rightActions,
10459
- setSendButtonMode
10748
+ setSendButtonMode: send.setMode
10460
10749
  };
10461
10750
  };
10462
10751
 
10463
10752
  // src/components/panel.ts
10464
10753
  var createWrapper = (config) => {
10465
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
10754
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
10466
10755
  const launcherEnabled = (_b = (_a = config == null ? void 0 : config.launcher) == null ? void 0 : _a.enabled) != null ? _b : true;
10467
10756
  const dockedMode = isDockedMountMode(config);
10757
+ const composerBarMode = isComposerBarMountMode(config);
10758
+ if (composerBarMode) {
10759
+ const cb = (_d = (_c = config == null ? void 0 : config.launcher) == null ? void 0 : _c.composerBar) != null ? _d : {};
10760
+ const wrapper2 = createElement(
10761
+ "div",
10762
+ "persona-widget-wrapper persona-fixed persona-transition"
10763
+ );
10764
+ wrapper2.setAttribute("data-persona-composer-bar", "");
10765
+ wrapper2.dataset.state = "collapsed";
10766
+ wrapper2.dataset.expandedSize = (_e = cb.expandedSize) != null ? _e : "anchored";
10767
+ wrapper2.style.zIndex = String(
10768
+ (_g = (_f = config == null ? void 0 : config.launcher) == null ? void 0 : _f.zIndex) != null ? _g : DEFAULT_OVERLAY_Z_INDEX
10769
+ );
10770
+ const panel2 = createElement(
10771
+ "div",
10772
+ "persona-widget-panel persona-relative persona-flex persona-flex-1 persona-min-h-0 persona-flex-col"
10773
+ );
10774
+ panel2.style.width = "100%";
10775
+ wrapper2.appendChild(panel2);
10776
+ const pillRoot = createElement("div", "persona-widget-pill-root");
10777
+ pillRoot.setAttribute("data-persona-composer-bar", "");
10778
+ pillRoot.dataset.state = "collapsed";
10779
+ pillRoot.dataset.expandedSize = (_h = cb.expandedSize) != null ? _h : "anchored";
10780
+ pillRoot.style.zIndex = String(
10781
+ (_j = (_i = config == null ? void 0 : config.launcher) == null ? void 0 : _i.zIndex) != null ? _j : DEFAULT_OVERLAY_Z_INDEX
10782
+ );
10783
+ return { wrapper: wrapper2, panel: panel2, pillRoot };
10784
+ }
10468
10785
  if (dockedMode) {
10469
10786
  const wrapper2 = createElement(
10470
10787
  "div",
@@ -10486,35 +10803,171 @@ var createWrapper = (config) => {
10486
10803
  "div",
10487
10804
  "persona-relative persona-flex-1 persona-flex persona-flex-col persona-min-h-0"
10488
10805
  );
10489
- const inlineWidth = (_d = (_c = config == null ? void 0 : config.launcher) == null ? void 0 : _c.width) != null ? _d : "100%";
10806
+ const inlineWidth = (_l = (_k = config == null ? void 0 : config.launcher) == null ? void 0 : _k.width) != null ? _l : "100%";
10490
10807
  wrapper2.style.width = inlineWidth;
10491
10808
  panel2.style.width = "100%";
10492
10809
  wrapper2.appendChild(panel2);
10493
10810
  return { wrapper: wrapper2, panel: panel2 };
10494
10811
  }
10495
- const launcher = (_e = config == null ? void 0 : config.launcher) != null ? _e : {};
10812
+ const launcher = (_m = config == null ? void 0 : config.launcher) != null ? _m : {};
10496
10813
  const position = launcher.position && positionMap[launcher.position] ? positionMap[launcher.position] : positionMap["bottom-right"];
10497
10814
  const wrapper = createElement(
10498
10815
  "div",
10499
10816
  `persona-widget-wrapper persona-fixed ${position} persona-transition`
10500
10817
  );
10501
- wrapper.style.zIndex = String((_g = (_f = config == null ? void 0 : config.launcher) == null ? void 0 : _f.zIndex) != null ? _g : DEFAULT_OVERLAY_Z_INDEX);
10818
+ wrapper.style.zIndex = String((_o = (_n = config == null ? void 0 : config.launcher) == null ? void 0 : _n.zIndex) != null ? _o : DEFAULT_OVERLAY_Z_INDEX);
10502
10819
  const panel = createElement(
10503
10820
  "div",
10504
10821
  "persona-widget-panel persona-relative persona-min-h-[320px]"
10505
10822
  );
10506
- const launcherWidth = (_i = (_h = config == null ? void 0 : config.launcher) == null ? void 0 : _h.width) != null ? _i : config == null ? void 0 : config.launcherWidth;
10823
+ const launcherWidth = (_q = (_p = config == null ? void 0 : config.launcher) == null ? void 0 : _p.width) != null ? _q : config == null ? void 0 : config.launcherWidth;
10507
10824
  const width = launcherWidth != null ? launcherWidth : DEFAULT_FLOATING_LAUNCHER_WIDTH;
10508
10825
  panel.style.width = width;
10509
10826
  panel.style.maxWidth = width;
10510
10827
  wrapper.appendChild(panel);
10511
10828
  return { wrapper, panel };
10512
10829
  };
10830
+ var buildComposerBarPanel = (config, showClose) => {
10831
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
10832
+ const container = createElement(
10833
+ "div",
10834
+ "persona-widget-container persona-relative persona-flex persona-flex-1 persona-min-h-0 persona-flex-col persona-text-persona-primary"
10835
+ );
10836
+ container.setAttribute("data-persona-theme-zone", "container");
10837
+ const { button: closeButton, wrapper: closeButtonWrapper } = createCloseButton(
10838
+ config,
10839
+ {
10840
+ showClose,
10841
+ wrapperClassName: "persona-composer-bar-close",
10842
+ buttonSize: "16px",
10843
+ iconSize: "14px"
10844
+ }
10845
+ );
10846
+ closeButtonWrapper.style.position = "absolute";
10847
+ closeButtonWrapper.style.top = "8px";
10848
+ closeButtonWrapper.style.right = "8px";
10849
+ closeButtonWrapper.style.zIndex = "10";
10850
+ const clearChatEnabled = (_c = (_b = (_a = config == null ? void 0 : config.launcher) == null ? void 0 : _a.clearChat) == null ? void 0 : _b.enabled) != null ? _c : true;
10851
+ let clearChatButton = null;
10852
+ let clearChatButtonWrapper = null;
10853
+ if (clearChatEnabled) {
10854
+ const parts = createClearChatButton(config, {
10855
+ wrapperClassName: "persona-composer-bar-clear-chat",
10856
+ buttonSize: "16px",
10857
+ iconSize: "14px"
10858
+ });
10859
+ clearChatButton = parts.button;
10860
+ clearChatButtonWrapper = parts.wrapper;
10861
+ clearChatButtonWrapper.style.position = "absolute";
10862
+ clearChatButtonWrapper.style.top = "8px";
10863
+ clearChatButtonWrapper.style.right = "32px";
10864
+ clearChatButtonWrapper.style.zIndex = "10";
10865
+ }
10866
+ const headerPlaceholder = createElement("span", "persona-widget-header");
10867
+ headerPlaceholder.setAttribute("data-persona-theme-zone", "header");
10868
+ headerPlaceholder.style.display = "none";
10869
+ const body = createElement(
10870
+ "div",
10871
+ "persona-widget-body persona-flex persona-flex-1 persona-min-h-0 persona-flex-col persona-gap-6 persona-overflow-y-auto persona-bg-persona-container persona-px-6 persona-py-6"
10872
+ );
10873
+ body.style.paddingTop = "48px";
10874
+ body.id = "persona-scroll-container";
10875
+ body.setAttribute("data-persona-theme-zone", "messages");
10876
+ const introCard = createElement(
10877
+ "div",
10878
+ "persona-rounded-2xl persona-bg-persona-surface persona-p-6"
10879
+ );
10880
+ introCard.style.boxShadow = "var(--persona-intro-card-shadow, 0 5px 15px rgba(15, 23, 42, 0.08))";
10881
+ introCard.setAttribute("data-persona-intro-card", "");
10882
+ const introTitle = createElement(
10883
+ "h2",
10884
+ "persona-text-lg persona-font-semibold persona-text-persona-primary"
10885
+ );
10886
+ introTitle.textContent = (_e = (_d = config == null ? void 0 : config.copy) == null ? void 0 : _d.welcomeTitle) != null ? _e : "Hello \u{1F44B}";
10887
+ const introSubtitle = createElement(
10888
+ "p",
10889
+ "persona-mt-2 persona-text-sm persona-text-persona-muted"
10890
+ );
10891
+ introSubtitle.textContent = (_g = (_f = config == null ? void 0 : config.copy) == null ? void 0 : _f.welcomeSubtitle) != null ? _g : "Ask anything about your account or products.";
10892
+ introCard.append(introTitle, introSubtitle);
10893
+ const messagesWrapper = createElement(
10894
+ "div",
10895
+ "persona-flex persona-flex-col persona-gap-3"
10896
+ );
10897
+ const contentMaxWidth = (_h = config == null ? void 0 : config.layout) == null ? void 0 : _h.contentMaxWidth;
10898
+ if (contentMaxWidth) {
10899
+ messagesWrapper.style.maxWidth = contentMaxWidth;
10900
+ messagesWrapper.style.marginLeft = "auto";
10901
+ messagesWrapper.style.marginRight = "auto";
10902
+ messagesWrapper.style.width = "100%";
10903
+ }
10904
+ const showWelcomeCard = ((_i = config == null ? void 0 : config.copy) == null ? void 0 : _i.showWelcomeCard) !== false;
10905
+ if (!showWelcomeCard) {
10906
+ introCard.style.display = "none";
10907
+ body.classList.remove("persona-gap-6");
10908
+ body.classList.add("persona-gap-3");
10909
+ }
10910
+ body.append(introCard, messagesWrapper);
10911
+ const composerOverlay = createElement(
10912
+ "div",
10913
+ "persona-composer-overlay persona-pointer-events-none"
10914
+ );
10915
+ composerOverlay.setAttribute("data-persona-composer-overlay", "");
10916
+ composerOverlay.style.position = "absolute";
10917
+ composerOverlay.style.left = "0";
10918
+ composerOverlay.style.right = "0";
10919
+ composerOverlay.style.bottom = "0";
10920
+ composerOverlay.style.zIndex = "20";
10921
+ const composerElements = buildPillComposer({ config });
10922
+ const { root: peekBanner, textNode: peekTextNode } = buildPillPeekBanner();
10923
+ container.append(headerPlaceholder, closeButtonWrapper, body, composerOverlay);
10924
+ if (clearChatButtonWrapper) {
10925
+ container.appendChild(clearChatButtonWrapper);
10926
+ }
10927
+ return {
10928
+ container,
10929
+ body,
10930
+ messagesWrapper,
10931
+ composerOverlay,
10932
+ suggestions: composerElements.suggestions,
10933
+ textarea: composerElements.textarea,
10934
+ sendButton: composerElements.sendButton,
10935
+ sendButtonWrapper: composerElements.sendButtonWrapper,
10936
+ micButton: composerElements.micButton,
10937
+ micButtonWrapper: composerElements.micButtonWrapper,
10938
+ composerForm: composerElements.composerForm,
10939
+ statusText: composerElements.statusText,
10940
+ introTitle,
10941
+ introSubtitle,
10942
+ closeButton,
10943
+ closeButtonWrapper,
10944
+ clearChatButton,
10945
+ clearChatButtonWrapper,
10946
+ iconHolder: createElement("span"),
10947
+ headerTitle: createElement("span"),
10948
+ headerSubtitle: createElement("span"),
10949
+ header: headerPlaceholder,
10950
+ footer: composerElements.footer,
10951
+ attachmentButton: composerElements.attachmentButton,
10952
+ attachmentButtonWrapper: composerElements.attachmentButtonWrapper,
10953
+ attachmentInput: composerElements.attachmentInput,
10954
+ attachmentPreviewsContainer: composerElements.attachmentPreviewsContainer,
10955
+ actionsRow: composerElements.actionsRow,
10956
+ leftActions: composerElements.leftActions,
10957
+ rightActions: composerElements.rightActions,
10958
+ setSendButtonMode: composerElements.setSendButtonMode,
10959
+ peekBanner,
10960
+ peekTextNode
10961
+ };
10962
+ };
10513
10963
  var buildPanel = (config, showClose = true) => {
10514
10964
  var _a, _b, _c, _d, _e, _f, _g, _h, _i;
10965
+ if (isComposerBarMountMode(config)) {
10966
+ return buildComposerBarPanel(config, showClose);
10967
+ }
10515
10968
  const container = createElement(
10516
10969
  "div",
10517
- "persona-widget-container persona-flex persona-h-full persona-w-full persona-flex-1 persona-min-h-0 persona-flex-col persona-bg-persona-surface persona-text-persona-primary persona-rounded-2xl persona-overflow-hidden persona-border persona-border-persona-border"
10970
+ "persona-widget-container persona-flex persona-h-full persona-w-full persona-flex-1 persona-min-h-0 persona-flex-col persona-text-persona-primary persona-bg-persona-surface persona-rounded-2xl persona-overflow-hidden persona-border persona-border-persona-border"
10518
10971
  );
10519
10972
  container.setAttribute("data-persona-theme-zone", "container");
10520
10973
  const headerLayoutConfig = (_a = config == null ? void 0 : config.layout) == null ? void 0 : _a.header;
@@ -14921,24 +15374,39 @@ function renderComponentDirective(directive, options) {
14921
15374
  return null;
14922
15375
  }
14923
15376
  }
15377
+ function selectDirectiveSource(message) {
15378
+ if (typeof message.rawContent === "string" && message.rawContent.length > 0) {
15379
+ return message.rawContent;
15380
+ }
15381
+ if (typeof message.content === "string") {
15382
+ const trimmed = message.content.trim();
15383
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
15384
+ return message.content;
15385
+ }
15386
+ }
15387
+ return null;
15388
+ }
14924
15389
  function hasComponentDirective(message) {
14925
- if (!message.rawContent) return false;
15390
+ const source = selectDirectiveSource(message);
15391
+ if (!source) return false;
14926
15392
  try {
14927
- const parsed = JSON.parse(message.rawContent);
15393
+ const parsed = JSON.parse(source);
14928
15394
  return typeof parsed === "object" && parsed !== null && "component" in parsed && typeof parsed.component === "string";
14929
15395
  } catch {
14930
15396
  return false;
14931
15397
  }
14932
15398
  }
14933
15399
  function extractComponentDirectiveFromMessage(message) {
14934
- if (!message.rawContent) return null;
15400
+ const source = selectDirectiveSource(message);
15401
+ if (!source) return null;
14935
15402
  try {
14936
- const parsed = JSON.parse(message.rawContent);
15403
+ const parsed = JSON.parse(source);
14937
15404
  if (typeof parsed === "object" && parsed !== null && "component" in parsed && typeof parsed.component === "string") {
15405
+ const directive = parsed;
14938
15406
  return {
14939
- component: parsed.component,
14940
- props: parsed.props && typeof parsed.props === "object" && parsed.props !== null ? parsed.props : {},
14941
- raw: message.rawContent
15407
+ component: directive.component,
15408
+ props: directive.props && typeof directive.props === "object" && directive.props !== null ? directive.props : {},
15409
+ raw: source
14942
15410
  };
14943
15411
  }
14944
15412
  } catch {
@@ -15365,7 +15833,7 @@ function buildDropOverlay(dropCfg) {
15365
15833
  return overlay;
15366
15834
  }
15367
15835
  var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
15368
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q;
15836
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U;
15369
15837
  if (mount == null) {
15370
15838
  throw new Error(
15371
15839
  'createAgentExperience: mount must be a non-null HTMLElement (e.g. pass document.getElementById("my-root") after the node exists).'
@@ -15383,7 +15851,8 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
15383
15851
  componentRegistry.registerAll(config.components);
15384
15852
  }
15385
15853
  const eventBus = createEventBus();
15386
- const storageAdapter = (_a = config.storageAdapter) != null ? _a : createLocalStorageAdapter();
15854
+ const messagePersistenceDisabled = config.persistState === false;
15855
+ const storageAdapter = messagePersistenceDisabled ? null : (_a = config.storageAdapter) != null ? _a : createLocalStorageAdapter();
15387
15856
  let persistentMetadata = {};
15388
15857
  let pendingStoredState = null;
15389
15858
  let shouldOpenAfterStateLoaded = false;
@@ -15474,7 +15943,9 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
15474
15943
  let prevLauncherEnabled = launcherEnabled;
15475
15944
  let prevHeaderLayout = (_l = (_k = config.layout) == null ? void 0 : _k.header) == null ? void 0 : _l.layout;
15476
15945
  let wasMobileFullscreen = false;
15477
- let open = launcherEnabled ? autoExpand : true;
15946
+ const isComposerBar = () => isComposerBarMountMode(config);
15947
+ const isPanelToggleable = () => launcherEnabled || isComposerBar();
15948
+ let open = isComposerBar() ? false : launcherEnabled ? autoExpand : true;
15478
15949
  let pendingResubmit = false;
15479
15950
  let pendingResubmitTimeout = null;
15480
15951
  const handleResubmitRequested = () => {
@@ -15560,8 +16031,8 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
15560
16031
  el.textContent = text;
15561
16032
  }
15562
16033
  }
15563
- const { wrapper, panel } = createWrapper(config);
15564
- const panelElements = buildPanel(config, launcherEnabled);
16034
+ const { wrapper, panel, pillRoot } = createWrapper(config);
16035
+ const panelElements = buildPanel(config, isPanelToggleable());
15565
16036
  let {
15566
16037
  container,
15567
16038
  body,
@@ -15644,7 +16115,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
15644
16115
  const customHeader = headerPlugin.renderHeader({
15645
16116
  config,
15646
16117
  defaultRenderer: () => {
15647
- const headerElements = buildHeader({ config, showClose: launcherEnabled });
16118
+ const headerElements = buildHeader({ config, showClose: isPanelToggleable() });
15648
16119
  attachHeaderToContainer(container, headerElements, config);
15649
16120
  return headerElements.header;
15650
16121
  },
@@ -15787,6 +16258,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
15787
16258
  const value = text.trim();
15788
16259
  const hasAttachments = (_a2 = attachmentManager == null ? void 0 : attachmentManager.hasAttachments()) != null ? _a2 : false;
15789
16260
  if (!value && !hasAttachments) return;
16261
+ maybeExpandComposerBar();
15790
16262
  let contentParts;
15791
16263
  if (hasAttachments) {
15792
16264
  contentParts = [];
@@ -15852,23 +16324,29 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
15852
16324
  };
15853
16325
  ensureComposerAttachmentSurface(footer);
15854
16326
  bindComposerRefsFromFooter(footer);
15855
- const contentMaxWidth = (_D = config.layout) == null ? void 0 : _D.contentMaxWidth;
15856
- if (contentMaxWidth && composerForm) {
16327
+ const contentMaxWidth = (_H = (_D = config.layout) == null ? void 0 : _D.contentMaxWidth) != null ? _H : isComposerBar() ? (_G = (_F = (_E = config.launcher) == null ? void 0 : _E.composerBar) == null ? void 0 : _F.contentMaxWidth) != null ? _G : "720px" : void 0;
16328
+ if (contentMaxWidth) {
16329
+ messagesWrapper.style.maxWidth = contentMaxWidth;
16330
+ messagesWrapper.style.marginLeft = "auto";
16331
+ messagesWrapper.style.marginRight = "auto";
16332
+ messagesWrapper.style.width = "100%";
16333
+ }
16334
+ if (contentMaxWidth && composerForm && !isComposerBar()) {
15857
16335
  composerForm.style.maxWidth = contentMaxWidth;
15858
16336
  composerForm.style.marginLeft = "auto";
15859
16337
  composerForm.style.marginRight = "auto";
15860
16338
  }
15861
- if (contentMaxWidth && suggestions) {
16339
+ if (contentMaxWidth && suggestions && !isComposerBar()) {
15862
16340
  suggestions.style.maxWidth = contentMaxWidth;
15863
16341
  suggestions.style.marginLeft = "auto";
15864
16342
  suggestions.style.marginRight = "auto";
15865
16343
  }
15866
- if (contentMaxWidth && attachmentPreviewsContainer) {
16344
+ if (contentMaxWidth && attachmentPreviewsContainer && !isComposerBar()) {
15867
16345
  attachmentPreviewsContainer.style.maxWidth = contentMaxWidth;
15868
16346
  attachmentPreviewsContainer.style.marginLeft = "auto";
15869
16347
  attachmentPreviewsContainer.style.marginRight = "auto";
15870
16348
  }
15871
- if (((_E = config.attachments) == null ? void 0 : _E.enabled) && attachmentInput && attachmentPreviewsContainer) {
16349
+ if (((_I = config.attachments) == null ? void 0 : _I.enabled) && attachmentInput && attachmentPreviewsContainer) {
15872
16350
  attachmentManager = AttachmentManager.fromConfig(config.attachments);
15873
16351
  attachmentManager.setPreviewsContainer(attachmentPreviewsContainer);
15874
16352
  attachmentInput.addEventListener("change", (e) => {
@@ -16678,29 +17156,70 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
16678
17156
  }
16679
17157
  } else {
16680
17158
  panel.appendChild(container);
17159
+ if (isComposerBar() && pillRoot) {
17160
+ if (panelElements.peekBanner) {
17161
+ pillRoot.appendChild(panelElements.peekBanner);
17162
+ }
17163
+ pillRoot.appendChild(footer);
17164
+ }
16681
17165
  }
16682
17166
  mount.appendChild(wrapper);
17167
+ if (pillRoot) {
17168
+ mount.appendChild(pillRoot);
17169
+ }
16683
17170
  const applyFullHeightStyles = () => {
16684
- var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2, _k2, _l2, _m2, _n2, _o2, _p2, _q2, _r2, _s2, _t2, _u2, _v2, _w2;
17171
+ var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2, _k2, _l2, _m2, _n2, _o2, _p2, _q2, _r2, _s2, _t2, _u2, _v2, _w2, _x2, _y2, _z2, _A2, _B2;
17172
+ if (isComposerBar()) {
17173
+ panel.style.width = "100%";
17174
+ panel.style.maxWidth = "100%";
17175
+ const cb = (_b2 = (_a2 = config.launcher) == null ? void 0 : _a2.composerBar) != null ? _b2 : {};
17176
+ const isExpanded = wrapper.dataset.state === "expanded";
17177
+ const expandedSize = (_c2 = cb.expandedSize) != null ? _c2 : "anchored";
17178
+ const wantsChrome = isExpanded && expandedSize !== "fullscreen";
17179
+ if (!wantsChrome) {
17180
+ container.style.background = "";
17181
+ container.style.border = "";
17182
+ container.style.borderRadius = "";
17183
+ container.style.overflow = "";
17184
+ container.style.boxShadow = "";
17185
+ return;
17186
+ }
17187
+ const panelPartial2 = (_e2 = (_d2 = config.theme) == null ? void 0 : _d2.components) == null ? void 0 : _e2.panel;
17188
+ const activeTheme2 = getActiveTheme(config);
17189
+ const resolveCb = (raw, fallback) => {
17190
+ var _a3;
17191
+ if (raw == null || raw === "") return fallback;
17192
+ return (_a3 = resolveTokenValue(activeTheme2, raw)) != null ? _a3 : raw;
17193
+ };
17194
+ const defaultBorder = "1px solid var(--persona-border)";
17195
+ const defaultShadow = "var(--persona-palette-shadows-xl, 0 25px 50px -12px rgba(0, 0, 0, 0.25))";
17196
+ const defaultRadius = "var(--persona-panel-radius, var(--persona-radius-xl, 0.75rem))";
17197
+ container.style.background = "var(--persona-surface, #ffffff)";
17198
+ container.style.border = resolveCb(panelPartial2 == null ? void 0 : panelPartial2.border, defaultBorder);
17199
+ container.style.borderRadius = resolveCb(panelPartial2 == null ? void 0 : panelPartial2.borderRadius, defaultRadius);
17200
+ container.style.boxShadow = resolveCb(panelPartial2 == null ? void 0 : panelPartial2.shadow, defaultShadow);
17201
+ container.style.overflow = "hidden";
17202
+ return;
17203
+ }
16685
17204
  const dockedMode = isDockedMountMode(config);
16686
- const sidebarMode = (_b2 = (_a2 = config.launcher) == null ? void 0 : _a2.sidebarMode) != null ? _b2 : false;
16687
- const fullHeight = dockedMode || sidebarMode || ((_d2 = (_c2 = config.launcher) == null ? void 0 : _c2.fullHeight) != null ? _d2 : false);
16688
- const isInlineEmbed = ((_e2 = config.launcher) == null ? void 0 : _e2.enabled) === false;
16689
- const panelPartial = (_g2 = (_f2 = config.theme) == null ? void 0 : _f2.components) == null ? void 0 : _g2.panel;
17205
+ const sidebarMode = (_g2 = (_f2 = config.launcher) == null ? void 0 : _f2.sidebarMode) != null ? _g2 : false;
17206
+ const fullHeight = dockedMode || sidebarMode || ((_i2 = (_h2 = config.launcher) == null ? void 0 : _h2.fullHeight) != null ? _i2 : false);
17207
+ const isInlineEmbed = ((_j2 = config.launcher) == null ? void 0 : _j2.enabled) === false;
17208
+ const panelPartial = (_l2 = (_k2 = config.theme) == null ? void 0 : _k2.components) == null ? void 0 : _l2.panel;
16690
17209
  const activeTheme = getActiveTheme(config);
16691
17210
  const resolvePanelChrome = (raw, fallback) => {
16692
17211
  var _a3;
16693
17212
  if (raw == null || raw === "") return fallback;
16694
17213
  return (_a3 = resolveTokenValue(activeTheme, raw)) != null ? _a3 : raw;
16695
17214
  };
16696
- const ownerWindow2 = (_h2 = mount.ownerDocument.defaultView) != null ? _h2 : window;
16697
- const mobileFullscreen = (_j2 = (_i2 = config.launcher) == null ? void 0 : _i2.mobileFullscreen) != null ? _j2 : true;
16698
- const mobileBreakpoint = (_l2 = (_k2 = config.launcher) == null ? void 0 : _k2.mobileBreakpoint) != null ? _l2 : 640;
17215
+ const ownerWindow2 = (_m2 = mount.ownerDocument.defaultView) != null ? _m2 : window;
17216
+ const mobileFullscreen = (_o2 = (_n2 = config.launcher) == null ? void 0 : _n2.mobileFullscreen) != null ? _o2 : true;
17217
+ const mobileBreakpoint = (_q2 = (_p2 = config.launcher) == null ? void 0 : _p2.mobileBreakpoint) != null ? _q2 : 640;
16699
17218
  const isMobileViewport = ownerWindow2.innerWidth <= mobileBreakpoint;
16700
17219
  const shouldGoFullscreen = mobileFullscreen && isMobileViewport && launcherEnabled;
16701
- const position = (_n2 = (_m2 = config.launcher) == null ? void 0 : _m2.position) != null ? _n2 : "bottom-left";
17220
+ const position = (_s2 = (_r2 = config.launcher) == null ? void 0 : _r2.position) != null ? _s2 : "bottom-left";
16702
17221
  const isLeftSidebar = position === "bottom-left" || position === "top-left";
16703
- const overlayZIndex = (_p2 = (_o2 = config.launcher) == null ? void 0 : _o2.zIndex) != null ? _p2 : DEFAULT_OVERLAY_Z_INDEX;
17222
+ const overlayZIndex = (_u2 = (_t2 = config.launcher) == null ? void 0 : _t2.zIndex) != null ? _u2 : DEFAULT_OVERLAY_Z_INDEX;
16704
17223
  let defaultPanelBorder = sidebarMode || shouldGoFullscreen ? "none" : "1px solid var(--persona-border)";
16705
17224
  let defaultPanelShadow = shouldGoFullscreen ? "none" : sidebarMode ? isLeftSidebar ? "var(--persona-palette-shadows-sidebar-left, 2px 0 12px rgba(0, 0, 0, 0.08))" : "var(--persona-palette-shadows-sidebar-right, -2px 0 12px rgba(0, 0, 0, 0.08))" : "var(--persona-palette-shadows-xl, 0 25px 50px -12px rgba(0, 0, 0, 0.25))";
16706
17225
  if (dockedMode && !shouldGoFullscreen) {
@@ -16787,7 +17306,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
16787
17306
  restoreBodyScrollTop();
16788
17307
  return;
16789
17308
  }
16790
- const launcherWidth = (_r2 = (_q2 = config == null ? void 0 : config.launcher) == null ? void 0 : _q2.width) != null ? _r2 : config == null ? void 0 : config.launcherWidth;
17309
+ const launcherWidth = (_w2 = (_v2 = config == null ? void 0 : config.launcher) == null ? void 0 : _v2.width) != null ? _w2 : config == null ? void 0 : config.launcherWidth;
16791
17310
  const width = launcherWidth != null ? launcherWidth : DEFAULT_FLOATING_LAUNCHER_WIDTH;
16792
17311
  if (!sidebarMode && !dockedMode) {
16793
17312
  if (isInlineEmbed && fullHeight) {
@@ -16868,11 +17387,11 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
16868
17387
  "persona-top-4"
16869
17388
  );
16870
17389
  if (!sidebarMode && !isInlineEmbed && !dockedMode) {
16871
- const positionClasses = (_s2 = positionMap[position]) != null ? _s2 : positionMap["bottom-right"];
17390
+ const positionClasses = (_x2 = positionMap[position]) != null ? _x2 : positionMap["bottom-right"];
16872
17391
  positionClasses.split(" ").forEach((cls) => wrapper.classList.add(cls));
16873
17392
  }
16874
17393
  if (sidebarMode) {
16875
- const sidebarWidth = (_u2 = (_t2 = config.launcher) == null ? void 0 : _t2.sidebarWidth) != null ? _u2 : "420px";
17394
+ const sidebarWidth = (_z2 = (_y2 = config.launcher) == null ? void 0 : _y2.sidebarWidth) != null ? _z2 : "420px";
16876
17395
  wrapper.style.cssText = `
16877
17396
  position: fixed !important;
16878
17397
  top: 0 !important;
@@ -16924,7 +17443,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
16924
17443
  if (!isInlineEmbed && !dockedMode) {
16925
17444
  const maxHeightStyles = "max-height: -moz-available !important; max-height: stretch !important;";
16926
17445
  const paddingStyles = sidebarMode ? "" : "padding-top: 1.25em !important;";
16927
- const zIndexStyles = !sidebarMode ? `z-index: ${(_w2 = (_v2 = config.launcher) == null ? void 0 : _v2.zIndex) != null ? _w2 : DEFAULT_OVERLAY_Z_INDEX} !important;` : "";
17446
+ const zIndexStyles = !sidebarMode ? `z-index: ${(_B2 = (_A2 = config.launcher) == null ? void 0 : _A2.zIndex) != null ? _B2 : DEFAULT_OVERLAY_Z_INDEX} !important;` : "";
16928
17447
  wrapper.style.cssText += maxHeightStyles + paddingStyles + zIndexStyles;
16929
17448
  }
16930
17449
  restoreBodyScrollTop();
@@ -16994,7 +17513,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
16994
17513
  cleanupThemeObserver = null;
16995
17514
  }
16996
17515
  });
16997
- const streamAnimationConfig = (_F = config.features) == null ? void 0 : _F.streamAnimation;
17516
+ const streamAnimationConfig = (_J = config.features) == null ? void 0 : _J.streamAnimation;
16998
17517
  if ((streamAnimationConfig == null ? void 0 : streamAnimationConfig.type) && streamAnimationConfig.type !== "none") {
16999
17518
  const plugin = resolveStreamAnimationPlugin(
17000
17519
  streamAnimationConfig.type,
@@ -17011,6 +17530,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
17011
17530
  let isStreaming = false;
17012
17531
  const messageCache = createMessageCache();
17013
17532
  const lastAskBubbleFingerprint = /* @__PURE__ */ new Map();
17533
+ const lastComponentDirectiveFingerprint = /* @__PURE__ */ new Map();
17014
17534
  let configVersion = 0;
17015
17535
  const autoFollow = createFollowStateController();
17016
17536
  let lastScrollTop = 0;
@@ -17027,7 +17547,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
17027
17547
  lastUserMessageWasVoice: false,
17028
17548
  lastUserMessageId: null
17029
17549
  };
17030
- const voiceAutoResumeMode = (_H = (_G = config.voiceRecognition) == null ? void 0 : _G.autoResume) != null ? _H : false;
17550
+ const voiceAutoResumeMode = (_L = (_K = config.voiceRecognition) == null ? void 0 : _K.autoResume) != null ? _L : false;
17031
17551
  const emitVoiceState = (source) => {
17032
17552
  eventBus.emit("voice:state", {
17033
17553
  active: voiceState.active,
@@ -17258,13 +17778,21 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
17258
17778
  const liveAskToolIds = /* @__PURE__ */ new Set();
17259
17779
  const hasAskPlugin = plugins.some((p) => p.renderAskUserQuestion);
17260
17780
  const askPluginHydrate = [];
17781
+ const componentDirectiveHydrate = [];
17782
+ const componentStreamingEnabled = config.enableComponentStreaming !== false;
17261
17783
  messages.forEach((message) => {
17262
17784
  var _a3, _b3, _c3, _d3, _e3, _f3, _g2, _h2, _i2, _j2, _k2, _l2, _m2, _n2;
17263
17785
  activeMessageIds.add(message.id);
17264
17786
  const askWithPlugin = hasAskPlugin && isAskUserQuestionMessage(message);
17787
+ const hasDirectiveBubble = !askWithPlugin && message.role === "assistant" && !message.variant && componentStreamingEnabled && hasComponentDirective(message);
17788
+ if (!hasDirectiveBubble && lastComponentDirectiveFingerprint.has(message.id)) {
17789
+ const existing = container2.querySelector(`#wrapper-${message.id}`);
17790
+ existing == null ? void 0 : existing.removeAttribute("data-preserve-runtime");
17791
+ lastComponentDirectiveFingerprint.delete(message.id);
17792
+ }
17265
17793
  const askMeta = isAskUserQuestionMessage(message) ? `:${((_a3 = message.agentMetadata) == null ? void 0 : _a3.askUserQuestionAnswered) ? "a" : "u"}:${((_b3 = message.agentMetadata) == null ? void 0 : _b3.askUserQuestionAnswers) ? Object.keys(message.agentMetadata.askUserQuestionAnswers).length : 0}` : "";
17266
17794
  const fingerprint = computeMessageFingerprint(message, configVersion) + askMeta;
17267
- const cachedWrapper = askWithPlugin ? null : getCachedWrapper(messageCache, message.id, fingerprint);
17795
+ const cachedWrapper = askWithPlugin || hasDirectiveBubble ? null : getCachedWrapper(messageCache, message.id, fingerprint);
17268
17796
  if (cachedWrapper) {
17269
17797
  tempContainer.appendChild(cachedWrapper.cloneNode(true));
17270
17798
  if (isAskUserQuestionMessage(message) && ((_c3 = message.toolCall) == null ? void 0 : _c3.id) && ((_d3 = message.agentMetadata) == null ? void 0 : _d3.awaitingLocalTool) === true && !((_e3 = message.agentMetadata) == null ? void 0 : _e3.askUserQuestionAnswered)) {
@@ -17403,18 +17931,20 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
17403
17931
  });
17404
17932
  }
17405
17933
  }
17406
- if (!bubble && message.role === "assistant" && !message.variant) {
17407
- const enableComponentStreaming = config.enableComponentStreaming !== false;
17408
- if (enableComponentStreaming && hasComponentDirective(message)) {
17409
- const directive = extractComponentDirectiveFromMessage(message);
17410
- if (directive) {
17934
+ if (!bubble && hasDirectiveBubble) {
17935
+ const directive = extractComponentDirectiveFromMessage(message);
17936
+ if (directive) {
17937
+ const lastFp = lastComponentDirectiveFingerprint.get(message.id);
17938
+ const needsRebuild = lastFp !== fingerprint;
17939
+ const wrapChrome = config.wrapComponentDirectiveInBubble !== false;
17940
+ let liveBubble = null;
17941
+ if (needsRebuild) {
17411
17942
  const componentBubble = renderComponentDirective(directive, {
17412
17943
  config,
17413
17944
  message,
17414
17945
  transform
17415
17946
  });
17416
17947
  if (componentBubble) {
17417
- const wrapChrome = config.wrapComponentDirectiveInBubble !== false;
17418
17948
  if (wrapChrome) {
17419
17949
  const componentWrapper = document.createElement("div");
17420
17950
  componentWrapper.className = [
@@ -17440,7 +17970,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
17440
17970
  componentWrapper.appendChild(textDiv);
17441
17971
  }
17442
17972
  componentWrapper.appendChild(componentBubble);
17443
- bubble = componentWrapper;
17973
+ liveBubble = componentWrapper;
17444
17974
  } else {
17445
17975
  const stack = document.createElement("div");
17446
17976
  stack.className = "persona-flex persona-flex-col persona-w-full persona-max-w-full persona-gap-3 persona-items-stretch";
@@ -17459,10 +17989,28 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
17459
17989
  stack.appendChild(textDiv);
17460
17990
  }
17461
17991
  stack.appendChild(componentBubble);
17462
- bubble = stack;
17992
+ liveBubble = stack;
17463
17993
  }
17464
17994
  }
17465
17995
  }
17996
+ if (liveBubble || lastFp != null) {
17997
+ const stub = document.createElement("div");
17998
+ stub.className = "persona-flex";
17999
+ stub.id = `wrapper-${message.id}`;
18000
+ stub.setAttribute("data-wrapper-id", message.id);
18001
+ stub.setAttribute("data-component-directive-stub", "true");
18002
+ stub.setAttribute("data-preserve-runtime", "true");
18003
+ if (!wrapChrome) {
18004
+ stub.classList.add("persona-w-full");
18005
+ }
18006
+ tempContainer.appendChild(stub);
18007
+ componentDirectiveHydrate.push({
18008
+ messageId: message.id,
18009
+ fingerprint,
18010
+ bubble: liveBubble
18011
+ });
18012
+ return;
18013
+ }
17466
18014
  }
17467
18015
  }
17468
18016
  if (!bubble) {
@@ -17713,15 +18261,327 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
17713
18261
  if (!activeMessageIds.has(id)) lastAskBubbleFingerprint.delete(id);
17714
18262
  }
17715
18263
  }
18264
+ if (componentDirectiveHydrate.length > 0) {
18265
+ for (const { messageId, fingerprint, bubble } of componentDirectiveHydrate) {
18266
+ const wrapper2 = container2.querySelector(`#wrapper-${messageId}`);
18267
+ if (!wrapper2) continue;
18268
+ if (bubble === null) {
18269
+ continue;
18270
+ }
18271
+ wrapper2.replaceChildren(bubble);
18272
+ wrapper2.setAttribute("data-bubble-fp", fingerprint);
18273
+ lastComponentDirectiveFingerprint.set(messageId, fingerprint);
18274
+ }
18275
+ }
18276
+ if (lastComponentDirectiveFingerprint.size > 0) {
18277
+ for (const id of lastComponentDirectiveFingerprint.keys()) {
18278
+ if (!activeMessageIds.has(id)) lastComponentDirectiveFingerprint.delete(id);
18279
+ }
18280
+ }
17716
18281
  };
17717
18282
  const renderMessagesWithPlugins = renderMessagesWithPluginsImpl;
18283
+ let composerBarOutsideClickListener = null;
18284
+ const attachComposerBarOutsideClickDismiss = () => {
18285
+ var _a2;
18286
+ if (composerBarOutsideClickListener) return;
18287
+ const listener = (event) => {
18288
+ const path = event.composedPath();
18289
+ if (path.includes(wrapper)) return;
18290
+ if (pillRoot && path.includes(pillRoot)) return;
18291
+ setOpenState(false, "user");
18292
+ };
18293
+ composerBarOutsideClickListener = listener;
18294
+ const targetDoc = (_a2 = mount.ownerDocument) != null ? _a2 : document;
18295
+ targetDoc.addEventListener("pointerdown", listener, true);
18296
+ };
18297
+ const detachComposerBarOutsideClickDismiss = () => {
18298
+ var _a2;
18299
+ if (!composerBarOutsideClickListener) return;
18300
+ const targetDoc = (_a2 = mount.ownerDocument) != null ? _a2 : document;
18301
+ targetDoc.removeEventListener(
18302
+ "pointerdown",
18303
+ composerBarOutsideClickListener,
18304
+ true
18305
+ );
18306
+ composerBarOutsideClickListener = null;
18307
+ };
18308
+ destroyCallbacks.push(() => detachComposerBarOutsideClickDismiss());
18309
+ let composerBarEscapeListener = null;
18310
+ const attachComposerBarEscapeDismiss = () => {
18311
+ var _a2;
18312
+ if (composerBarEscapeListener) return;
18313
+ const listener = (event) => {
18314
+ if (event.key !== "Escape") return;
18315
+ if (event.isComposing) return;
18316
+ setOpenState(false, "user");
18317
+ };
18318
+ composerBarEscapeListener = listener;
18319
+ const targetDoc = (_a2 = mount.ownerDocument) != null ? _a2 : document;
18320
+ targetDoc.addEventListener("keydown", listener, true);
18321
+ };
18322
+ const detachComposerBarEscapeDismiss = () => {
18323
+ var _a2;
18324
+ if (!composerBarEscapeListener) return;
18325
+ const targetDoc = (_a2 = mount.ownerDocument) != null ? _a2 : document;
18326
+ targetDoc.removeEventListener(
18327
+ "keydown",
18328
+ composerBarEscapeListener,
18329
+ true
18330
+ );
18331
+ composerBarEscapeListener = null;
18332
+ };
18333
+ destroyCallbacks.push(() => detachComposerBarEscapeDismiss());
18334
+ let composerHovered = false;
18335
+ const peekActivatedPlugins = /* @__PURE__ */ new Set();
18336
+ const resolvePeekStreamAnimationFeature = () => {
18337
+ var _a2, _b2, _c2, _d2;
18338
+ const peekFeature = (_c2 = (_b2 = (_a2 = config.launcher) == null ? void 0 : _a2.composerBar) == null ? void 0 : _b2.peek) == null ? void 0 : _c2.streamAnimation;
18339
+ if (peekFeature) return peekFeature;
18340
+ return (_d2 = config.features) == null ? void 0 : _d2.streamAnimation;
18341
+ };
18342
+ const syncComposerBarPeek = () => {
18343
+ var _a2, _b2, _c2, _d2;
18344
+ if (!isComposerBar()) return;
18345
+ const peekBanner = panelElements.peekBanner;
18346
+ const peekTextNode = panelElements.peekTextNode;
18347
+ if (!peekBanner || !peekTextNode) return;
18348
+ if (open) {
18349
+ peekBanner.classList.remove("persona-pill-peek--visible");
18350
+ return;
18351
+ }
18352
+ const messages = (_a2 = session == null ? void 0 : session.getMessages()) != null ? _a2 : [];
18353
+ let lastAssistant;
18354
+ for (let i = messages.length - 1; i >= 0; i--) {
18355
+ const m = messages[i];
18356
+ if (m.role === "assistant" && m.content) {
18357
+ lastAssistant = m;
18358
+ break;
18359
+ }
18360
+ }
18361
+ if (!lastAssistant) {
18362
+ peekBanner.classList.remove("persona-pill-peek--visible");
18363
+ return;
18364
+ }
18365
+ const text = lastAssistant.content;
18366
+ const streaming = Boolean(lastAssistant.streaming);
18367
+ const feature = resolvePeekStreamAnimationFeature();
18368
+ const streamAnimation = resolveStreamAnimation(feature);
18369
+ const plugin = streamAnimation.type !== "none" ? resolveStreamAnimationPlugin(streamAnimation.type, feature == null ? void 0 : feature.plugins) : null;
18370
+ const pluginStillAnimating = ((_b2 = plugin == null ? void 0 : plugin.isAnimating) == null ? void 0 : _b2.call(plugin, lastAssistant)) === true;
18371
+ const animationActive = plugin !== null && (streaming || pluginStillAnimating);
18372
+ if (animationActive && plugin && !peekActivatedPlugins.has(plugin.name)) {
18373
+ ensurePluginActive(plugin, mount);
18374
+ peekActivatedPlugins.add(plugin.name);
18375
+ }
18376
+ const desiredContainerClass = animationActive && (plugin == null ? void 0 : plugin.containerClass) ? plugin.containerClass : null;
18377
+ const currentContainerClass = (_c2 = peekTextNode.dataset.personaPeekStreamClass) != null ? _c2 : null;
18378
+ if (currentContainerClass && currentContainerClass !== desiredContainerClass) {
18379
+ peekTextNode.classList.remove(currentContainerClass);
18380
+ delete peekTextNode.dataset.personaPeekStreamClass;
18381
+ }
18382
+ if (desiredContainerClass && currentContainerClass !== desiredContainerClass) {
18383
+ peekTextNode.classList.add(desiredContainerClass);
18384
+ peekTextNode.dataset.personaPeekStreamClass = desiredContainerClass;
18385
+ }
18386
+ if (animationActive) {
18387
+ peekTextNode.style.setProperty(
18388
+ "--persona-stream-step",
18389
+ `${streamAnimation.speed}ms`
18390
+ );
18391
+ peekTextNode.style.setProperty(
18392
+ "--persona-stream-duration",
18393
+ `${streamAnimation.duration}ms`
18394
+ );
18395
+ } else {
18396
+ peekTextNode.style.removeProperty("--persona-stream-step");
18397
+ peekTextNode.style.removeProperty("--persona-stream-duration");
18398
+ }
18399
+ const buffered = animationActive ? applyStreamBuffer(text, streamAnimation.buffer, plugin, lastAssistant, streaming) : text;
18400
+ const skeletonEnabled = animationActive && streamAnimation.placeholder === "skeleton";
18401
+ const showSkeletonOnly = skeletonEnabled && streaming && (!buffered || !buffered.trim());
18402
+ if (showSkeletonOnly) {
18403
+ const tempContainer = document.createElement("div");
18404
+ const skeleton = createSkeletonPlaceholder();
18405
+ skeleton.classList.add("persona-pill-peek__skeleton");
18406
+ tempContainer.appendChild(skeleton);
18407
+ morphMessages(peekTextNode, tempContainer);
18408
+ } else {
18409
+ const sliceStart = Math.max(0, buffered.length - 100);
18410
+ const slice = buffered.length > 100 ? buffered.slice(-100) : buffered;
18411
+ const escaped = escapeHtml(slice);
18412
+ if (!animationActive || !plugin) {
18413
+ const preview = buffered.length > 100 ? `\u2026${slice}` : slice;
18414
+ if (peekTextNode.textContent !== preview) {
18415
+ peekTextNode.textContent = preview;
18416
+ }
18417
+ } else {
18418
+ let html = escaped;
18419
+ if (plugin.wrap === "char" || plugin.wrap === "word") {
18420
+ html = wrapStreamAnimation(
18421
+ escaped,
18422
+ plugin.wrap,
18423
+ // Namespace span IDs to the peek surface so they don't collide
18424
+ // with the main bubble's spans for the same message id.
18425
+ `peek-${lastAssistant.id}`,
18426
+ { skipTags: plugin.skipTags, startIndex: sliceStart }
18427
+ );
18428
+ }
18429
+ const tempContainer = document.createElement("div");
18430
+ tempContainer.innerHTML = html;
18431
+ if (plugin.useCaret && slice.length > 0) {
18432
+ const caret = createStreamCaret();
18433
+ const spans = tempContainer.querySelectorAll(
18434
+ ".persona-stream-char, .persona-stream-word"
18435
+ );
18436
+ const lastSpan = spans[spans.length - 1];
18437
+ if (lastSpan == null ? void 0 : lastSpan.parentNode) {
18438
+ lastSpan.parentNode.insertBefore(caret, lastSpan.nextSibling);
18439
+ } else {
18440
+ tempContainer.appendChild(caret);
18441
+ }
18442
+ }
18443
+ morphMessages(peekTextNode, tempContainer);
18444
+ (_d2 = plugin.onAfterRender) == null ? void 0 : _d2.call(plugin, {
18445
+ container: peekTextNode,
18446
+ bubble: peekBanner,
18447
+ messageId: lastAssistant.id,
18448
+ message: lastAssistant,
18449
+ speed: streamAnimation.speed,
18450
+ duration: streamAnimation.duration
18451
+ });
18452
+ }
18453
+ }
18454
+ const shouldShow = isStreaming || composerHovered;
18455
+ peekBanner.classList.toggle("persona-pill-peek--visible", shouldShow);
18456
+ };
18457
+ if (isComposerBar()) {
18458
+ const peekBanner = panelElements.peekBanner;
18459
+ if (peekBanner) {
18460
+ const onPeekPointerDown = (e) => {
18461
+ e.preventDefault();
18462
+ e.stopPropagation();
18463
+ setOpenState(true, "user");
18464
+ };
18465
+ peekBanner.addEventListener("pointerdown", onPeekPointerDown);
18466
+ destroyCallbacks.push(() => {
18467
+ peekBanner.removeEventListener("pointerdown", onPeekPointerDown);
18468
+ });
18469
+ }
18470
+ const onPanelPointerEnter = () => {
18471
+ if (composerHovered) return;
18472
+ composerHovered = true;
18473
+ syncComposerBarPeek();
18474
+ };
18475
+ const onPanelPointerLeave = () => {
18476
+ if (!composerHovered) return;
18477
+ composerHovered = false;
18478
+ syncComposerBarPeek();
18479
+ };
18480
+ panel.addEventListener("pointerenter", onPanelPointerEnter);
18481
+ panel.addEventListener("pointerleave", onPanelPointerLeave);
18482
+ destroyCallbacks.push(() => {
18483
+ panel.removeEventListener("pointerenter", onPanelPointerEnter);
18484
+ panel.removeEventListener("pointerleave", onPanelPointerLeave);
18485
+ });
18486
+ if (pillRoot) {
18487
+ pillRoot.addEventListener("pointerenter", onPanelPointerEnter);
18488
+ pillRoot.addEventListener("pointerleave", onPanelPointerLeave);
18489
+ destroyCallbacks.push(() => {
18490
+ pillRoot.removeEventListener("pointerenter", onPanelPointerEnter);
18491
+ pillRoot.removeEventListener("pointerleave", onPanelPointerLeave);
18492
+ });
18493
+ }
18494
+ }
18495
+ const applyComposerBarGeometry = (isOpen) => {
18496
+ var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2;
18497
+ const cb = (_b2 = (_a2 = config.launcher) == null ? void 0 : _a2.composerBar) != null ? _b2 : {};
18498
+ const expandedSize = (_c2 = cb.expandedSize) != null ? _c2 : "anchored";
18499
+ const bottomOffset = (_d2 = cb.bottomOffset) != null ? _d2 : "16px";
18500
+ const collapsedMaxWidth = cb.collapsedMaxWidth;
18501
+ const expandedMaxWidth = (_e2 = cb.expandedMaxWidth) != null ? _e2 : "880px";
18502
+ const expandedTopOffset = (_f2 = cb.expandedTopOffset) != null ? _f2 : "5vh";
18503
+ const modalMaxWidth = (_g2 = cb.modalMaxWidth) != null ? _g2 : "880px";
18504
+ const modalMaxHeight = (_h2 = cb.modalMaxHeight) != null ? _h2 : "min(90vh, 800px)";
18505
+ const viewportClamp = "calc(100vw - 32px)";
18506
+ const pillAreaClearance = "var(--persona-pill-area-height, 80px)";
18507
+ const s = wrapper.style;
18508
+ s.left = "";
18509
+ s.right = "";
18510
+ s.top = "";
18511
+ s.bottom = "";
18512
+ s.transform = "";
18513
+ s.width = "";
18514
+ s.maxWidth = "";
18515
+ s.height = "";
18516
+ s.maxHeight = "";
18517
+ if (pillRoot) {
18518
+ const ps = pillRoot.style;
18519
+ ps.bottom = bottomOffset;
18520
+ ps.width = collapsedMaxWidth != null ? collapsedMaxWidth : "";
18521
+ }
18522
+ if (!isOpen) {
18523
+ return;
18524
+ }
18525
+ if (expandedSize === "fullscreen") {
18526
+ return;
18527
+ }
18528
+ if (expandedSize === "modal") {
18529
+ s.top = "50%";
18530
+ s.left = "50%";
18531
+ s.transform = "translate(-50%, -50%)";
18532
+ s.bottom = "auto";
18533
+ s.right = "auto";
18534
+ s.width = modalMaxWidth;
18535
+ s.maxWidth = viewportClamp;
18536
+ s.maxHeight = modalMaxHeight;
18537
+ s.height = modalMaxHeight;
18538
+ return;
18539
+ }
18540
+ s.left = "50%";
18541
+ s.transform = "translateX(-50%)";
18542
+ s.bottom = `calc(${bottomOffset} + ${pillAreaClearance})`;
18543
+ s.top = expandedTopOffset;
18544
+ s.width = expandedMaxWidth;
18545
+ s.maxWidth = viewportClamp;
18546
+ };
17718
18547
  const updateOpenState = () => {
17719
- var _a2, _b2, _c2, _d2, _e2;
17720
- if (!launcherEnabled) return;
18548
+ var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2;
18549
+ if (!isPanelToggleable()) return;
18550
+ if (isComposerBar()) {
18551
+ const cb = (_b2 = (_a2 = config.launcher) == null ? void 0 : _a2.composerBar) != null ? _b2 : {};
18552
+ const expandedSize = (_c2 = cb.expandedSize) != null ? _c2 : "anchored";
18553
+ const nextState = open ? "expanded" : "collapsed";
18554
+ wrapper.dataset.state = nextState;
18555
+ wrapper.dataset.expandedSize = expandedSize;
18556
+ if (pillRoot) {
18557
+ pillRoot.dataset.state = nextState;
18558
+ pillRoot.dataset.expandedSize = expandedSize;
18559
+ }
18560
+ wrapper.style.removeProperty("display");
18561
+ wrapper.classList.remove("persona-pointer-events-none", "persona-opacity-0");
18562
+ panel.classList.remove(
18563
+ "persona-scale-95",
18564
+ "persona-opacity-0",
18565
+ "persona-scale-100",
18566
+ "persona-opacity-100"
18567
+ );
18568
+ applyComposerBarGeometry(open);
18569
+ container.style.display = open ? "flex" : "none";
18570
+ applyFullHeightStyles();
18571
+ if (open) {
18572
+ attachComposerBarOutsideClickDismiss();
18573
+ attachComposerBarEscapeDismiss();
18574
+ } else {
18575
+ detachComposerBarOutsideClickDismiss();
18576
+ detachComposerBarEscapeDismiss();
18577
+ }
18578
+ syncComposerBarPeek();
18579
+ return;
18580
+ }
17721
18581
  const dockedMode = isDockedMountMode(config);
17722
- const ownerWindow2 = (_a2 = mount.ownerDocument.defaultView) != null ? _a2 : window;
17723
- const mobileBreakpoint = (_c2 = (_b2 = config.launcher) == null ? void 0 : _b2.mobileBreakpoint) != null ? _c2 : 640;
17724
- const mobileFullscreen = (_e2 = (_d2 = config.launcher) == null ? void 0 : _d2.mobileFullscreen) != null ? _e2 : true;
18582
+ const ownerWindow2 = (_d2 = mount.ownerDocument.defaultView) != null ? _d2 : window;
18583
+ const mobileBreakpoint = (_f2 = (_e2 = config.launcher) == null ? void 0 : _e2.mobileBreakpoint) != null ? _f2 : 640;
18584
+ const mobileFullscreen = (_h2 = (_g2 = config.launcher) == null ? void 0 : _g2.mobileFullscreen) != null ? _h2 : true;
17725
18585
  const isMobileViewport = ownerWindow2.innerWidth <= mobileBreakpoint;
17726
18586
  const shouldGoFullscreen = mobileFullscreen && isMobileViewport && launcherEnabled;
17727
18587
  const dockReveal = resolveDockConfig(config).reveal;
@@ -17764,20 +18624,21 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
17764
18624
  };
17765
18625
  const setOpenState = (nextOpen, source = "user") => {
17766
18626
  var _a2, _b2;
17767
- if (!launcherEnabled) return;
18627
+ if (!isPanelToggleable()) return;
17768
18628
  if (open === nextOpen) return;
17769
18629
  const prevOpen = open;
17770
18630
  open = nextOpen;
17771
18631
  updateOpenState();
17772
18632
  const isViewportCovering = (() => {
17773
- var _a3, _b3, _c2, _d2, _e2, _f2, _g2;
18633
+ var _a3, _b3, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2;
17774
18634
  const sm = (_b3 = (_a3 = config.launcher) == null ? void 0 : _a3.sidebarMode) != null ? _b3 : false;
17775
18635
  const ow = (_c2 = mount.ownerDocument.defaultView) != null ? _c2 : window;
17776
18636
  const mf = (_e2 = (_d2 = config.launcher) == null ? void 0 : _d2.mobileFullscreen) != null ? _e2 : true;
17777
18637
  const mb = (_g2 = (_f2 = config.launcher) == null ? void 0 : _f2.mobileBreakpoint) != null ? _g2 : 640;
17778
18638
  const isMobile = ow.innerWidth <= mb;
17779
18639
  const dockedMF = isDockedMountMode(config) && mf && isMobile;
17780
- return sm || mf && isMobile && launcherEnabled || dockedMF;
18640
+ const composerBarFS = isComposerBar() && ((_j2 = (_i2 = (_h2 = config.launcher) == null ? void 0 : _h2.composerBar) == null ? void 0 : _i2.expandedSize) != null ? _j2 : "fullscreen") === "fullscreen";
18641
+ return sm || mf && isMobile && launcherEnabled || dockedMF || composerBarFS;
17781
18642
  })();
17782
18643
  if (open && isViewportCovering) {
17783
18644
  if (!teardownHostStacking) {
@@ -17922,6 +18783,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
17922
18783
  }
17923
18784
  voiceState.lastUserMessageWasVoice = Boolean(lastUserMessage == null ? void 0 : lastUserMessage.viaVoice);
17924
18785
  persistState(messages);
18786
+ syncComposerBarPeek();
17925
18787
  },
17926
18788
  onStatusChanged(status) {
17927
18789
  var _a2;
@@ -17945,6 +18807,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
17945
18807
  if (!streaming) {
17946
18808
  scheduleAutoScroll(true);
17947
18809
  }
18810
+ syncComposerBarPeek();
17948
18811
  },
17949
18812
  onVoiceStatusChanged(status) {
17950
18813
  var _a2, _b2;
@@ -17981,7 +18844,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
17981
18844
  }
17982
18845
  });
17983
18846
  sessionRef.current = session;
17984
- if (((_J = (_I = config.voiceRecognition) == null ? void 0 : _I.provider) == null ? void 0 : _J.type) === "runtype") {
18847
+ if (((_N = (_M = config.voiceRecognition) == null ? void 0 : _M.provider) == null ? void 0 : _N.type) === "runtype") {
17985
18848
  try {
17986
18849
  session.setupVoice();
17987
18850
  } catch (err) {
@@ -18032,6 +18895,14 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
18032
18895
  }
18033
18896
  });
18034
18897
  }
18898
+ const maybeExpandComposerBar = () => {
18899
+ var _a2, _b2, _c2;
18900
+ if (!isComposerBar()) return;
18901
+ if (open) return;
18902
+ const expandOnSubmit = (_c2 = (_b2 = (_a2 = config.launcher) == null ? void 0 : _a2.composerBar) == null ? void 0 : _b2.expandOnSubmit) != null ? _c2 : true;
18903
+ if (!expandOnSubmit) return;
18904
+ setOpenState(true, "auto");
18905
+ };
18035
18906
  const handleSubmit = (event) => {
18036
18907
  var _a2;
18037
18908
  event.preventDefault();
@@ -18042,6 +18913,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
18042
18913
  const value = textarea.value.trim();
18043
18914
  const hasAttachments = (_a2 = attachmentManager == null ? void 0 : attachmentManager.hasAttachments()) != null ? _a2 : false;
18044
18915
  if (!value && !hasAttachments) return;
18916
+ maybeExpandComposerBar();
18045
18917
  let contentParts;
18046
18918
  if (hasAttachments) {
18047
18919
  contentParts = [];
@@ -18207,7 +19079,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
18207
19079
  micButton.setAttribute("aria-label", "Start voice recognition");
18208
19080
  }
18209
19081
  };
18210
- const createMicButton = (voiceConfig, sendButtonConfig) => {
19082
+ const createMicButton2 = (voiceConfig, sendButtonConfig) => {
18211
19083
  var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2;
18212
19084
  const hasSpeechRecognition = typeof window !== "undefined" && (typeof window.webkitSpeechRecognition !== "undefined" || typeof window.SpeechRecognition !== "undefined");
18213
19085
  const hasRuntypeProvider = ((_a2 = voiceConfig == null ? void 0 : voiceConfig.provider) == null ? void 0 : _a2.type) === "runtype";
@@ -18484,7 +19356,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
18484
19356
  };
18485
19357
  let launcherButtonInstance = null;
18486
19358
  let customLauncherElement = null;
18487
- if (launcherEnabled) {
19359
+ if (launcherEnabled && !isComposerBar()) {
18488
19360
  const launcherPlugin = plugins.find((p) => p.renderLauncher);
18489
19361
  if (launcherPlugin == null ? void 0 : launcherPlugin.renderLauncher) {
18490
19362
  const customLauncher = launcherPlugin.renderLauncher({
@@ -18515,7 +19387,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
18515
19387
  scheduleAutoScroll(true);
18516
19388
  maybeRestoreVoiceFromMetadata();
18517
19389
  if (autoFocusInput) {
18518
- if (!launcherEnabled) {
19390
+ if (!launcherEnabled || isComposerBar()) {
18519
19391
  setTimeout(() => maybeFocusInput(), 0);
18520
19392
  } else if (open) {
18521
19393
  setTimeout(() => maybeFocusInput(), 200);
@@ -18523,6 +19395,11 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
18523
19395
  }
18524
19396
  const recalcPanelHeight = () => {
18525
19397
  var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2, _k2, _l2, _m2, _n2, _o2, _p2, _q2, _r2, _s2, _t2, _u2, _v2;
19398
+ if (isComposerBar()) {
19399
+ updateScrollToBottomButtonOffset();
19400
+ updateOpenState();
19401
+ return;
19402
+ }
18526
19403
  const dockedMode = isDockedMountMode(config);
18527
19404
  const sidebarMode = (_b2 = (_a2 = config.launcher) == null ? void 0 : _a2.sidebarMode) != null ? _b2 : false;
18528
19405
  const fullHeight = dockedMode || sidebarMode || ((_d2 = (_c2 = config.launcher) == null ? void 0 : _c2.fullHeight) != null ? _d2 : false);
@@ -18593,7 +19470,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
18593
19470
  }
18594
19471
  };
18595
19472
  recalcPanelHeight();
18596
- const ownerWindow = (_K = mount.ownerDocument.defaultView) != null ? _K : window;
19473
+ const ownerWindow = (_O = mount.ownerDocument.defaultView) != null ? _O : window;
18597
19474
  ownerWindow.addEventListener("resize", recalcPanelHeight);
18598
19475
  destroyCallbacks.push(() => ownerWindow.removeEventListener("resize", recalcPanelHeight));
18599
19476
  if (typeof ResizeObserver !== "undefined") {
@@ -18663,7 +19540,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
18663
19540
  closeButton.removeEventListener("click", closeHandler);
18664
19541
  closeHandler = null;
18665
19542
  }
18666
- if (launcherEnabled) {
19543
+ if (isPanelToggleable()) {
18667
19544
  closeButton.style.display = "";
18668
19545
  closeHandler = () => {
18669
19546
  setOpenState(false, "user");
@@ -18817,7 +19694,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
18817
19694
  }
18818
19695
  const controller = {
18819
19696
  update(nextConfig) {
18820
- var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2, _k2, _l2, _m2, _n2, _o2, _p2, _q2, _r2, _s2, _t2, _u2, _v2, _w2, _x2, _y2, _z2, _A2, _B2, _C2, _D2, _E2, _F2, _G2, _H2, _I2, _J2, _K2, _L2, _M2, _N2, _O2, _P2, _Q2, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, __, _$, _aa, _ba, _ca, _da, _ea, _fa, _ga, _ha, _ia, _ja, _ka, _la, _ma, _na, _oa, _pa, _qa, _ra, _sa, _ta, _ua, _va, _wa, _xa, _ya, _za, _Aa, _Ba, _Ca, _Da, _Ea, _Fa, _Ga, _Ha, _Ia, _Ja, _Ka, _La, _Ma, _Na, _Oa, _Pa, _Qa, _Ra, _Sa, _Ta, _Ua, _Va, _Wa, _Xa, _Ya, _Za, __a, _$a, _ab;
19697
+ var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2, _k2, _l2, _m2, _n2, _o2, _p2, _q2, _r2, _s2, _t2, _u2, _v2, _w2, _x2, _y2, _z2, _A2, _B2, _C2, _D2, _E2, _F2, _G2, _H2, _I2, _J2, _K2, _L2, _M2, _N2, _O2, _P2, _Q2, _R2, _S2, _T2, _U2, _V, _W, _X, _Y, _Z, __, _$, _aa, _ba, _ca, _da, _ea, _fa, _ga, _ha, _ia, _ja, _ka, _la, _ma, _na, _oa, _pa, _qa, _ra, _sa, _ta, _ua, _va, _wa, _xa, _ya, _za, _Aa, _Ba, _Ca, _Da, _Ea, _Fa, _Ga, _Ha, _Ia, _Ja, _Ka, _La, _Ma, _Na, _Oa, _Pa, _Qa, _Ra, _Sa, _Ta, _Ua, _Va, _Wa, _Xa, _Ya, _Za, __a, _$a, _ab, _bb, _cb, _db, _eb;
18821
19698
  const previousToolCallConfig = config.toolCall;
18822
19699
  const previousMessageActions = config.messageActions;
18823
19700
  const previousLayoutMessages = (_a2 = config.layout) == null ? void 0 : _a2.messages;
@@ -18947,11 +19824,11 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
18947
19824
  const headerLayoutChanged = (headerLayoutConfig == null ? void 0 : headerLayoutConfig.layout) !== prevHeaderLayout;
18948
19825
  if (headerLayoutChanged && header) {
18949
19826
  const newHeaderElements = headerLayoutConfig ? buildHeaderWithLayout(config, headerLayoutConfig, {
18950
- showClose: launcherEnabled,
19827
+ showClose: isPanelToggleable(),
18951
19828
  onClose: () => setOpenState(false, "user")
18952
19829
  }) : buildHeader({
18953
19830
  config,
18954
- showClose: launcherEnabled,
19831
+ showClose: isPanelToggleable(),
18955
19832
  onClose: () => setOpenState(false, "user")
18956
19833
  });
18957
19834
  header.replaceWith(newHeaderElements.header);
@@ -19081,7 +19958,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
19081
19958
  if (existingSvg || existingImg) {
19082
19959
  iconHolder.replaceChildren();
19083
19960
  }
19084
- iconHolder.textContent = (_R = launcher.agentIconText) != null ? _R : "\u{1F4AC}";
19961
+ iconHolder.textContent = (_R2 = launcher.agentIconText) != null ? _R2 : "\u{1F4AC}";
19085
19962
  }
19086
19963
  const img = iconHolder.querySelector("img");
19087
19964
  if (img) {
@@ -19090,8 +19967,8 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
19090
19967
  }
19091
19968
  }
19092
19969
  }
19093
- const layoutShowTitle = (_T = (_S = config.layout) == null ? void 0 : _S.header) == null ? void 0 : _T.showTitle;
19094
- const layoutShowSubtitle = (_V = (_U = config.layout) == null ? void 0 : _U.header) == null ? void 0 : _V.showSubtitle;
19970
+ const layoutShowTitle = (_T2 = (_S2 = config.layout) == null ? void 0 : _S2.header) == null ? void 0 : _T2.showTitle;
19971
+ const layoutShowSubtitle = (_V = (_U2 = config.layout) == null ? void 0 : _U2.header) == null ? void 0 : _V.showSubtitle;
19095
19972
  if (headerTitle) {
19096
19973
  headerTitle.style.display = layoutShowTitle === false ? "none" : "";
19097
19974
  }
@@ -19241,7 +20118,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
19241
20118
  if (clearChatButtonWrapper) {
19242
20119
  clearChatButtonWrapper.style.display = shouldShowClearChat ? "" : "none";
19243
20120
  const { closeButtonWrapper } = panelElements;
19244
- if (closeButtonWrapper && !closeButtonWrapper.classList.contains("persona-absolute")) {
20121
+ if (!isComposerBar() && closeButtonWrapper && !closeButtonWrapper.classList.contains("persona-absolute")) {
19245
20122
  if (shouldShowClearChat) {
19246
20123
  closeButtonWrapper.classList.remove("persona-ml-auto");
19247
20124
  } else {
@@ -19250,7 +20127,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
19250
20127
  }
19251
20128
  const isTopRight = clearChatPlacement === "top-right";
19252
20129
  const currentlyTopRight = clearChatButtonWrapper.classList.contains("persona-absolute");
19253
- if (isTopRight !== currentlyTopRight && shouldShowClearChat) {
20130
+ if (!isComposerBar() && isTopRight !== currentlyTopRight && shouldShowClearChat) {
19254
20131
  clearChatButtonWrapper.remove();
19255
20132
  if (isTopRight) {
19256
20133
  clearChatButtonWrapper.className = "persona-absolute persona-top-4 persona-z-50";
@@ -19279,14 +20156,17 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
19279
20156
  }
19280
20157
  }
19281
20158
  if (shouldShowClearChat) {
19282
- const clearChatSize = (_la = clearChatConfig.size) != null ? _la : "32px";
19283
- clearChatButton.style.height = clearChatSize;
19284
- clearChatButton.style.width = clearChatSize;
20159
+ if (!isComposerBar()) {
20160
+ const clearChatSize = (_la = clearChatConfig.size) != null ? _la : "32px";
20161
+ clearChatButton.style.height = clearChatSize;
20162
+ clearChatButton.style.width = clearChatSize;
20163
+ }
19285
20164
  const clearChatIconName = (_ma = clearChatConfig.iconName) != null ? _ma : "refresh-cw";
19286
20165
  const clearChatIconColor = (_na = clearChatConfig.iconColor) != null ? _na : "";
19287
20166
  clearChatButton.style.color = clearChatIconColor || HEADER_THEME_CSS.actionIconColor;
19288
20167
  clearChatButton.innerHTML = "";
19289
- const iconSvg = renderLucideIcon(clearChatIconName, "20px", "currentColor", 2);
20168
+ const clearChatIconSize = isComposerBar() ? "14px" : "20px";
20169
+ const iconSvg = renderLucideIcon(clearChatIconName, clearChatIconSize, "currentColor", 2);
19290
20170
  if (iconSvg) {
19291
20171
  clearChatButton.appendChild(iconSvg);
19292
20172
  }
@@ -19410,7 +20290,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
19410
20290
  const hasVoiceInput = hasSpeechRecognition || hasRuntypeProvider;
19411
20291
  if (voiceRecognitionEnabled && hasVoiceInput) {
19412
20292
  if (!micButton || !micButtonWrapper) {
19413
- const micButtonResult = createMicButton(config.voiceRecognition, config.sendButton);
20293
+ const micButtonResult = createMicButton2(config.voiceRecognition, config.sendButton);
19414
20294
  if (micButtonResult) {
19415
20295
  micButton = micButtonResult.micButton;
19416
20296
  micButtonWrapper = micButtonResult.micButtonWrapper;
@@ -19707,7 +20587,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
19707
20587
  } else if (tooltip) {
19708
20588
  tooltip.style.display = "none";
19709
20589
  }
19710
- const updatedContentMaxWidth = (__a = config.layout) == null ? void 0 : __a.contentMaxWidth;
20590
+ const updatedContentMaxWidth = (_cb = (__a = config.layout) == null ? void 0 : __a.contentMaxWidth) != null ? _cb : isComposerBar() ? (_bb = (_ab = (_$a = config.launcher) == null ? void 0 : _$a.composerBar) == null ? void 0 : _ab.contentMaxWidth) != null ? _bb : "720px" : void 0;
19711
20591
  if (updatedContentMaxWidth) {
19712
20592
  messagesWrapper.style.maxWidth = updatedContentMaxWidth;
19713
20593
  messagesWrapper.style.marginLeft = "auto";
@@ -19739,8 +20619,8 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
19739
20619
  suggestions.style.marginRight = "";
19740
20620
  }
19741
20621
  }
19742
- const statusIndicatorConfig = (_$a = config.statusIndicator) != null ? _$a : {};
19743
- const isVisible = (_ab = statusIndicatorConfig.visible) != null ? _ab : true;
20622
+ const statusIndicatorConfig = (_db = config.statusIndicator) != null ? _db : {};
20623
+ const isVisible = (_eb = statusIndicatorConfig.visible) != null ? _eb : true;
19744
20624
  statusText.style.display = isVisible ? "" : "none";
19745
20625
  if (session) {
19746
20626
  const currentStatus = session.getStatus();
@@ -19759,15 +20639,15 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
19759
20639
  statusText.classList.add(alignClass);
19760
20640
  },
19761
20641
  open() {
19762
- if (!launcherEnabled) return;
20642
+ if (!isPanelToggleable()) return;
19763
20643
  setOpenState(true, "api");
19764
20644
  },
19765
20645
  close() {
19766
- if (!launcherEnabled) return;
20646
+ if (!isPanelToggleable()) return;
19767
20647
  setOpenState(false, "api");
19768
20648
  },
19769
20649
  toggle() {
19770
- if (!launcherEnabled) return;
20650
+ if (!isPanelToggleable()) return;
19771
20651
  setOpenState(!open, "api");
19772
20652
  },
19773
20653
  clearChat() {
@@ -19821,7 +20701,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
19821
20701
  setMessage(message) {
19822
20702
  if (!textarea) return false;
19823
20703
  if (session.isStreaming()) return false;
19824
- if (!open && launcherEnabled) {
20704
+ if (!open && isPanelToggleable()) {
19825
20705
  setOpenState(true, "system");
19826
20706
  }
19827
20707
  textarea.value = message;
@@ -19832,7 +20712,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
19832
20712
  if (session.isStreaming()) return false;
19833
20713
  const valueToSubmit = (message == null ? void 0 : message.trim()) || textarea.value.trim();
19834
20714
  if (!valueToSubmit) return false;
19835
- if (!open && launcherEnabled) {
20715
+ if (!open && isPanelToggleable()) {
19836
20716
  setOpenState(true, "system");
19837
20717
  }
19838
20718
  textarea.value = "";
@@ -19845,7 +20725,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
19845
20725
  if (session.isStreaming()) return false;
19846
20726
  if (((_b2 = (_a2 = config.voiceRecognition) == null ? void 0 : _a2.provider) == null ? void 0 : _b2.type) === "runtype") {
19847
20727
  if (session.isVoiceActive()) return true;
19848
- if (!open && launcherEnabled) setOpenState(true, "system");
20728
+ if (!open && isPanelToggleable()) setOpenState(true, "system");
19849
20729
  voiceState.manuallyDeactivated = false;
19850
20730
  persistVoiceMetadata();
19851
20731
  session.toggleVoice().then(() => {
@@ -19858,7 +20738,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
19858
20738
  if (isRecording) return true;
19859
20739
  const SpeechRecognitionClass = getSpeechRecognitionClass();
19860
20740
  if (!SpeechRecognitionClass) return false;
19861
- if (!open && launcherEnabled) setOpenState(true, "system");
20741
+ if (!open && isPanelToggleable()) setOpenState(true, "system");
19862
20742
  voiceState.manuallyDeactivated = false;
19863
20743
  persistVoiceMetadata();
19864
20744
  startVoiceRecognition("user");
@@ -19884,13 +20764,13 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
19884
20764
  return true;
19885
20765
  },
19886
20766
  injectMessage(options) {
19887
- if (!open && launcherEnabled) {
20767
+ if (!open && isPanelToggleable()) {
19888
20768
  setOpenState(true, "system");
19889
20769
  }
19890
20770
  return session.injectMessage(options);
19891
20771
  },
19892
20772
  injectAssistantMessage(options) {
19893
- if (!open && launcherEnabled) {
20773
+ if (!open && isPanelToggleable()) {
19894
20774
  setOpenState(true, "system");
19895
20775
  }
19896
20776
  const result = session.injectAssistantMessage(options);
@@ -19909,26 +20789,32 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
19909
20789
  return result;
19910
20790
  },
19911
20791
  injectUserMessage(options) {
19912
- if (!open && launcherEnabled) {
20792
+ if (!open && isPanelToggleable()) {
19913
20793
  setOpenState(true, "system");
19914
20794
  }
19915
20795
  return session.injectUserMessage(options);
19916
20796
  },
19917
20797
  injectSystemMessage(options) {
19918
- if (!open && launcherEnabled) {
20798
+ if (!open && isPanelToggleable()) {
19919
20799
  setOpenState(true, "system");
19920
20800
  }
19921
20801
  return session.injectSystemMessage(options);
19922
20802
  },
19923
20803
  injectMessageBatch(optionsList) {
19924
- if (!open && launcherEnabled) {
20804
+ if (!open && isPanelToggleable()) {
19925
20805
  setOpenState(true, "system");
19926
20806
  }
19927
20807
  return session.injectMessageBatch(optionsList);
19928
20808
  },
20809
+ injectComponentDirective(options) {
20810
+ if (!open && isPanelToggleable()) {
20811
+ setOpenState(true, "system");
20812
+ }
20813
+ return session.injectComponentDirective(options);
20814
+ },
19929
20815
  /** @deprecated Use injectMessage() instead */
19930
20816
  injectTestMessage(event) {
19931
- if (!open && launcherEnabled) {
20817
+ if (!open && isPanelToggleable()) {
19932
20818
  setOpenState(true, "system");
19933
20819
  }
19934
20820
  session.injectTestEvent(event);
@@ -19991,7 +20877,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
19991
20877
  return (_a2 = session == null ? void 0 : session.getSelectedArtifactId()) != null ? _a2 : null;
19992
20878
  },
19993
20879
  focusInput() {
19994
- if (launcherEnabled && !open) return false;
20880
+ if (launcherEnabled && !open && !isComposerBar()) return false;
19995
20881
  if (!textarea) return false;
19996
20882
  textarea.focus();
19997
20883
  return true;
@@ -20029,14 +20915,14 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
20029
20915
  },
20030
20916
  // State query methods
20031
20917
  isOpen() {
20032
- return launcherEnabled && open;
20918
+ return isPanelToggleable() && open;
20033
20919
  },
20034
20920
  isVoiceActive() {
20035
20921
  return voiceState.active;
20036
20922
  },
20037
20923
  getState() {
20038
20924
  return {
20039
- open: launcherEnabled && open,
20925
+ open: isPanelToggleable() && open,
20040
20926
  launcherEnabled,
20041
20927
  voiceActive: voiceState.active,
20042
20928
  streaming: session.isStreaming()
@@ -20044,7 +20930,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
20044
20930
  },
20045
20931
  // Feedback methods (CSAT/NPS)
20046
20932
  showCSATFeedback(options) {
20047
- if (!open && launcherEnabled) {
20933
+ if (!open && isPanelToggleable()) {
20048
20934
  setOpenState(true, "system");
20049
20935
  }
20050
20936
  const existingFeedback = messagesWrapper.querySelector(".persona-feedback-container");
@@ -20066,7 +20952,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
20066
20952
  feedbackEl.scrollIntoView({ behavior: "smooth", block: "end" });
20067
20953
  },
20068
20954
  showNPSFeedback(options) {
20069
- if (!open && launcherEnabled) {
20955
+ if (!open && isPanelToggleable()) {
20070
20956
  setOpenState(true, "system");
20071
20957
  }
20072
20958
  const existingFeedback = messagesWrapper.querySelector(".persona-feedback-container");
@@ -20100,6 +20986,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
20100
20986
  }
20101
20987
  destroyCallbacks.forEach((cb) => cb());
20102
20988
  wrapper.remove();
20989
+ pillRoot == null ? void 0 : pillRoot.remove();
20103
20990
  launcherButtonInstance == null ? void 0 : launcherButtonInstance.destroy();
20104
20991
  customLauncherElement == null ? void 0 : customLauncherElement.remove();
20105
20992
  if (closeHandler) {
@@ -20107,7 +20994,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
20107
20994
  }
20108
20995
  }
20109
20996
  };
20110
- const shouldExposeDebugApi = ((_L = runtimeOptions == null ? void 0 : runtimeOptions.debugTools) != null ? _L : false) || Boolean(config.debug);
20997
+ const shouldExposeDebugApi = ((_P = runtimeOptions == null ? void 0 : runtimeOptions.debugTools) != null ? _P : false) || Boolean(config.debug);
20111
20998
  if (shouldExposeDebugApi && typeof window !== "undefined") {
20112
20999
  const previousDebug = window.AgentWidgetBrowser;
20113
21000
  const debugApi = {
@@ -20204,15 +21091,15 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
20204
21091
  });
20205
21092
  }
20206
21093
  const persistConfig = normalizePersistStateConfig(config.persistState);
20207
- if (persistConfig && launcherEnabled) {
21094
+ if (persistConfig && isPanelToggleable()) {
20208
21095
  const storage = getPersistStorage(persistConfig.storage);
20209
21096
  const openKey = `${persistConfig.keyPrefix}widget-open`;
20210
21097
  const voiceKey = `${persistConfig.keyPrefix}widget-voice`;
20211
21098
  const voiceModeKey = `${persistConfig.keyPrefix}widget-voice-mode`;
20212
21099
  if (storage) {
20213
- const wasOpen = ((_M = persistConfig.persist) == null ? void 0 : _M.openState) && storage.getItem(openKey) === "true";
20214
- const wasVoiceActive = ((_N = persistConfig.persist) == null ? void 0 : _N.voiceState) && storage.getItem(voiceKey) === "true";
20215
- const wasInVoiceMode = ((_O = persistConfig.persist) == null ? void 0 : _O.voiceState) && storage.getItem(voiceModeKey) === "true";
21100
+ const wasOpen = ((_Q = persistConfig.persist) == null ? void 0 : _Q.openState) && storage.getItem(openKey) === "true";
21101
+ const wasVoiceActive = ((_R = persistConfig.persist) == null ? void 0 : _R.voiceState) && storage.getItem(voiceKey) === "true";
21102
+ const wasInVoiceMode = ((_S = persistConfig.persist) == null ? void 0 : _S.voiceState) && storage.getItem(voiceModeKey) === "true";
20216
21103
  if (wasOpen) {
20217
21104
  setTimeout(() => {
20218
21105
  controller.open();
@@ -20229,7 +21116,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
20229
21116
  }, 100);
20230
21117
  }, 0);
20231
21118
  }
20232
- if ((_P = persistConfig.persist) == null ? void 0 : _P.openState) {
21119
+ if ((_T = persistConfig.persist) == null ? void 0 : _T.openState) {
20233
21120
  eventBus.on("widget:opened", () => {
20234
21121
  storage.setItem(openKey, "true");
20235
21122
  });
@@ -20237,7 +21124,7 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
20237
21124
  storage.setItem(openKey, "false");
20238
21125
  });
20239
21126
  }
20240
- if ((_Q = persistConfig.persist) == null ? void 0 : _Q.voiceState) {
21127
+ if ((_U = persistConfig.persist) == null ? void 0 : _U.voiceState) {
20241
21128
  eventBus.on("voice:state", (event) => {
20242
21129
  storage.setItem(voiceKey, event.active ? "true" : "false");
20243
21130
  });
@@ -20259,11 +21146,12 @@ var createAgentExperience = (mount, initialConfig, runtimeOptions) => {
20259
21146
  }
20260
21147
  }
20261
21148
  }
20262
- if (shouldOpenAfterStateLoaded && launcherEnabled) {
21149
+ if (shouldOpenAfterStateLoaded && isPanelToggleable()) {
20263
21150
  setTimeout(() => {
20264
21151
  controller.open();
20265
21152
  }, 0);
20266
21153
  }
21154
+ syncComposerBarPeek();
20267
21155
  return controller;
20268
21156
  };
20269
21157