@smooai/chat-widget 0.10.0 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -228,6 +228,7 @@ Declarative attributes mirror the programmatic [`ChatWidgetConfig`](./src/config
228
228
  | `greeting` | `greeting` | Shown before the first message. |
229
229
  | `mode` | `mode` | `popover` (default) or `fullpage`. |
230
230
  | `start-open` | `startOpen` | Open the panel immediately (no launcher click). |
231
+ | `hide-branding` | `hideBranding` | Hide the "powered by smooth-operator" tag + footer link. Default shown. |
231
232
  | — | `theme` | Brand colors (see [Theming](#theming)). |
232
233
  | — | `userName` / `userEmail` | Optional participant identity. |
233
234
 
@@ -11772,6 +11772,7 @@ var SmoothAgentChat = (function(exports) {
11772
11772
  greeting: config.greeting ?? "Hi! How can I help you today?",
11773
11773
  connectionErrorMessage: config.connectionErrorMessage ?? "We couldn't reach the chat. Please try again in a moment.",
11774
11774
  startOpen: config.startOpen ?? false,
11775
+ hideBranding: config.hideBranding ?? false,
11775
11776
  examplePrompts: (config.examplePrompts ?? []).filter((p) => p.trim().length > 0).slice(0, 5),
11776
11777
  requireName: config.requireName ?? false,
11777
11778
  requireEmail: config.requireEmail ?? false,
@@ -13518,11 +13519,11 @@ var SmoothAgentChat = (function(exports) {
13518
13519
  --sac-ease: cubic-bezier(.16, 1, .3, 1);
13519
13520
 
13520
13521
  ${mode === "fullpage" ? `/* Full-page: fill the host's box (sized by its container, else the viewport). */
13521
- display: block;
13522
+ display: flex;
13523
+ flex-direction: column;
13522
13524
  position: relative;
13523
13525
  width: 100%;
13524
- height: 100%;
13525
- min-height: 100vh;` : `/* Popover: float in the bottom-right corner. */
13526
+ height: 100%;` : `/* Popover: float in the bottom-right corner. */
13526
13527
  position: fixed;
13527
13528
  bottom: 24px;
13528
13529
  right: 24px;
@@ -13530,7 +13531,20 @@ var SmoothAgentChat = (function(exports) {
13530
13531
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
13531
13532
  -webkit-font-smoothing: antialiased;
13532
13533
  }
13533
-
13534
+ ${mode === "fullpage" ? `
13535
+ /* Viewport fallback — the element sets this attribute only when the host's
13536
+ container gives it no resolved height (e.g. mounted straight into an
13537
+ auto-height <body>). A sized container always wins, so an embed inside a
13538
+ fixed-height box never overflows it (composer stays visible). */
13539
+ :host([data-viewport-fallback]) { min-height: 100dvh; }
13540
+ /* The render wrapper passes the host's box down to the panel via flex. */
13541
+ .wrap {
13542
+ flex: 1;
13543
+ display: flex;
13544
+ flex-direction: column;
13545
+ min-height: 0;
13546
+ }
13547
+ ` : ""}
13534
13548
  * { box-sizing: border-box; }
13535
13549
 
13536
13550
  /* ───────────────────────────── Launcher ───────────────────────────── */
@@ -13612,11 +13626,13 @@ var SmoothAgentChat = (function(exports) {
13612
13626
  pointer-events: none;
13613
13627
  background: radial-gradient(120% 100% at 50% 0%, color-mix(in srgb, var(--sac-primary) 22%, transparent), transparent 70%);
13614
13628
  }
13615
- /* Full-page: the panel becomes the whole surface. */
13629
+ /* Full-page: the panel becomes the whole surface — it follows the host's box
13630
+ (via the .wrap flex chain), never a hardcoded viewport unit. */
13616
13631
  .panel.fullpage {
13617
13632
  width: 100%;
13618
- height: 100%;
13619
- min-height: 100vh;
13633
+ flex: 1;
13634
+ height: auto;
13635
+ min-height: 0;
13620
13636
  max-width: none;
13621
13637
  max-height: none;
13622
13638
  border: none;
@@ -13692,7 +13708,8 @@ var SmoothAgentChat = (function(exports) {
13692
13708
  }
13693
13709
  .close:hover { background: color-mix(in srgb, var(--sac-text) 12%, transparent); transform: translateY(1px); }
13694
13710
  .close svg { width: 16px; height: 16px; opacity: .8; }
13695
- .powered { margin-left: auto; font-size: 10.5px; letter-spacing: .02em; opacity: .6; }
13711
+ .powered { margin-left: auto; font-size: 10.5px; letter-spacing: .02em; opacity: .6; color: inherit; text-decoration: none; }
13712
+ .powered:hover { opacity: .85; text-decoration: underline; }
13696
13713
  .header-sep { height: 1px; margin: 0 16px; background: linear-gradient(90deg, transparent, var(--sac-border), transparent); }
13697
13714
 
13698
13715
  /* Full-page header: taller, logo-led, no close. */
@@ -13964,6 +13981,8 @@ var SmoothAgentChat = (function(exports) {
13964
13981
  color: color-mix(in srgb, var(--sac-text) 38%, transparent);
13965
13982
  }
13966
13983
  .footer b { font-weight: 600; color: color-mix(in srgb, var(--sac-text) 55%, transparent); }
13984
+ .footer a { color: inherit; text-decoration: none; }
13985
+ .footer a:hover { text-decoration: underline; }
13967
13986
 
13968
13987
  /* ─────────────────── Pre-chat identity form ───────────────────────── */
13969
13988
  .prechat { flex: 1; display: flex; flex-direction: column; justify-content: center; gap: 18px; padding: 22px 20px; }
@@ -14217,6 +14236,8 @@ var SmoothAgentChat = (function(exports) {
14217
14236
  return null;
14218
14237
  }
14219
14238
  }
14239
+ /** Public smooth-operator repo — the "powered by" header tag + footer link here. */
14240
+ const SMOOTH_OPERATOR_URL = "https://github.com/SmooAI/smooth-operator";
14220
14241
  const OBSERVED = [
14221
14242
  "endpoint",
14222
14243
  "agent-id",
@@ -14225,7 +14246,8 @@ var SmoothAgentChat = (function(exports) {
14225
14246
  "placeholder",
14226
14247
  "greeting",
14227
14248
  "start-open",
14228
- "mode"
14249
+ "mode",
14250
+ "hide-branding"
14229
14251
  ];
14230
14252
  /**
14231
14253
  * Inline SVG icons (static, trusted strings — never interpolated with user data).
@@ -14342,6 +14364,7 @@ var SmoothAgentChat = (function(exports) {
14342
14364
  greeting: this.overrides.greeting ?? this.getAttribute("greeting") ?? void 0,
14343
14365
  connectionErrorMessage: this.overrides.connectionErrorMessage,
14344
14366
  startOpen: this.overrides.startOpen ?? this.hasAttribute("start-open"),
14367
+ hideBranding: this.overrides.hideBranding ?? this.hasAttribute("hide-branding"),
14345
14368
  examplePrompts: this.overrides.examplePrompts,
14346
14369
  requireName: this.overrides.requireName,
14347
14370
  requireEmail: this.overrides.requireEmail,
@@ -14395,7 +14418,7 @@ var SmoothAgentChat = (function(exports) {
14395
14418
  <span class="title">${escapeHtml(resolved.agentName)}</span>
14396
14419
  <span class="status"><span class="dot off"></span><span class="status-text"></span></span>
14397
14420
  </div>
14398
- <span class="powered">powered by smooth-operator</span>
14421
+ ${resolved.hideBranding ? "" : `<a class="powered" href="${SMOOTH_OPERATOR_URL}" target="_blank" rel="noopener noreferrer">powered by smooth-operator</a>`}
14399
14422
  </div>` : `<div class="header">
14400
14423
  <div class="avatar">${monogram}</div>
14401
14424
  <div class="meta">
@@ -14429,7 +14452,8 @@ var SmoothAgentChat = (function(exports) {
14429
14452
  <button type="submit" class="pc-submit">Start chat</button>
14430
14453
  </form>
14431
14454
  </div>`;
14432
- const restoreLink = this.allowChatRestore ? ` · <button type="button" class="restore-link">Restore my chats</button>` : "";
14455
+ const footerInner = [resolved.hideBranding ? "" : `<a href="${SMOOTH_OPERATOR_URL}" target="_blank" rel="noopener noreferrer">powered by <b>smooth&#8209;operator</b></a>`, this.allowChatRestore ? `<button type="button" class="restore-link">Restore my chats</button>` : ""].filter(Boolean).join(" · ");
14456
+ const footerHtml = footerInner ? `<div class="footer">${footerInner}</div>` : "";
14433
14457
  const chatHtml = `
14434
14458
  <div class="messages"></div>
14435
14459
  <div class="interrupt hidden"></div>
@@ -14438,9 +14462,10 @@ var SmoothAgentChat = (function(exports) {
14438
14462
  <textarea rows="1" placeholder="${escapeHtml(resolved.placeholder)}"></textarea>
14439
14463
  <button class="send" type="button" aria-label="Send message">${ICON.send}</button>
14440
14464
  </div>
14441
- <div class="footer">powered by <b>smooth&#8209;operator</b>${restoreLink}</div>
14465
+ ${footerHtml}
14442
14466
  </div>`;
14443
14467
  const container = document.createElement("div");
14468
+ container.className = "wrap";
14444
14469
  container.innerHTML = `
14445
14470
  ${fullpage ? "" : `<button class="launcher" part="launcher" aria-label="Open chat">${ICON.spark}</button>`}
14446
14471
  <div class="panel${fullpage ? " fullpage" : " hidden"}" part="panel" role="${fullpage ? "region" : "dialog"}" aria-label="${escapeHtml(resolved.agentName)} chat">
@@ -14484,6 +14509,7 @@ var SmoothAgentChat = (function(exports) {
14484
14509
  await this.controller?.connect().catch(() => {});
14485
14510
  })();
14486
14511
  });
14512
+ if (fullpage) this.syncViewportFallback();
14487
14513
  if (fullpage && !gating) this.controller?.connect().catch(() => {});
14488
14514
  this.syncOpenState();
14489
14515
  if (!gating) this.renderMessages();
@@ -14973,6 +14999,24 @@ var SmoothAgentChat = (function(exports) {
14973
14999
  this.streamBubbleEl.textContent = this.streamTarget;
14974
15000
  }
14975
15001
  }
15002
+ /**
15003
+ * Full-page sizing probe: decide whether the host's container gives it a
15004
+ * real box. With the `.wrap` flex chain hidden, `height: 100%` of a SIZED
15005
+ * container still resolves (clientHeight > 0), while an auto-height parent
15006
+ * (e.g. mounted straight into `<body>`) collapses to ~0. Only the latter
15007
+ * gets `data-viewport-fallback`, whose CSS applies `min-height: 100dvh` —
15008
+ * so an embed inside a fixed-height box never overflows it (the composer
15009
+ * stays visible), and a bare full-page route still fills the viewport.
15010
+ */
15011
+ syncViewportFallback() {
15012
+ const wrap = this.shadowRoot?.querySelector(".wrap");
15013
+ if (!wrap) return;
15014
+ const prev = wrap.style.display;
15015
+ wrap.style.display = "none";
15016
+ const heightless = this.clientHeight < 8;
15017
+ wrap.style.display = prev;
15018
+ this.toggleAttribute("data-viewport-fallback", heightless);
15019
+ }
14976
15020
  /** Cancel any in-flight reveal loop and clear its state (called on full rebuild). */
14977
15021
  resetReveal() {
14978
15022
  if (this.rafId && typeof cancelAnimationFrame === "function") cancelAnimationFrame(this.rafId);