@runtypelabs/persona 3.2.2 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts CHANGED
@@ -194,6 +194,14 @@ export type {
194
194
  ComboButtonHandle
195
195
  } from "./utils/buttons";
196
196
 
197
+ // Demo carousel exports
198
+ export { createDemoCarousel } from "./components/demo-carousel";
199
+ export type {
200
+ DemoCarouselItem,
201
+ DemoCarouselOptions,
202
+ DemoCarouselHandle
203
+ } from "./components/demo-carousel";
204
+
197
205
  // Theme system exports
198
206
  export {
199
207
  createTheme,
@@ -1222,6 +1222,68 @@
1222
1222
  font-size: 0.8125rem;
1223
1223
  }
1224
1224
 
1225
+ /* Code block copy button */
1226
+ .persona-code-block-wrapper {
1227
+ position: relative;
1228
+ margin: 0.5rem 0;
1229
+ }
1230
+
1231
+ .persona-code-block-wrapper pre {
1232
+ margin: 0 !important;
1233
+ border-top-left-radius: 0 !important;
1234
+ border-top-right-radius: 0 !important;
1235
+ }
1236
+
1237
+ .persona-code-block-header {
1238
+ display: flex;
1239
+ align-items: center;
1240
+ justify-content: space-between;
1241
+ background-color: var(--persona-md-code-block-bg, #f3f4f6);
1242
+ border: 1px solid var(--persona-md-code-block-border-color, #e5e7eb);
1243
+ border-bottom: none;
1244
+ border-top-left-radius: var(--persona-md-code-block-border-radius, 0.375rem);
1245
+ border-top-right-radius: var(--persona-md-code-block-border-radius, 0.375rem);
1246
+ padding: 0.25rem 0.5rem 0.25rem 0.75rem;
1247
+ font-size: 0.75rem;
1248
+ color: var(--persona-text-muted, #6b7280);
1249
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono", Menlo, monospace;
1250
+ }
1251
+
1252
+ .persona-code-copy-btn {
1253
+ display: inline-flex;
1254
+ align-items: center;
1255
+ gap: 0.25rem;
1256
+ background: none;
1257
+ border: 1px solid transparent;
1258
+ border-radius: 0.25rem;
1259
+ padding: 0.25rem 0.5rem;
1260
+ cursor: pointer;
1261
+ color: var(--persona-text-muted, #6b7280);
1262
+ font-size: 0.75rem;
1263
+ font-family: inherit;
1264
+ line-height: 1;
1265
+ transition: color 0.15s ease, border-color 0.15s ease;
1266
+ }
1267
+
1268
+ .persona-code-copy-btn:hover {
1269
+ color: var(--persona-text, #111827);
1270
+ border-color: var(--persona-md-code-block-border-color, #e5e7eb);
1271
+ }
1272
+
1273
+ .persona-code-copy-btn.persona-code-copied {
1274
+ color: #16a34a;
1275
+ }
1276
+
1277
+ .persona-code-copy-btn.persona-code-copy-generating {
1278
+ cursor: default;
1279
+ opacity: 0.5;
1280
+ }
1281
+
1282
+ .persona-code-copy-btn.persona-code-copy-generating:hover {
1283
+ color: var(--persona-text-muted, #6b7280);
1284
+ border-color: transparent;
1285
+ }
1286
+
1225
1287
  /* Ensure all links in chat bubbles have underlines */
1226
1288
  .vanilla-message-bubble a {
1227
1289
  text-decoration: underline;
package/src/types.ts CHANGED
@@ -884,7 +884,11 @@ export type AgentWidgetClearChatConfig = {
884
884
 
885
885
  export type AgentWidgetStatusIndicatorConfig = {
886
886
  visible?: boolean;
887
+ /** Text alignment. Default: 'right'. */
888
+ align?: 'left' | 'center' | 'right';
887
889
  idleText?: string;
890
+ /** URL to open in a new tab when the idle text is clicked. */
891
+ idleLink?: string;
888
892
  connectingText?: string;
889
893
  connectedText?: string;
890
894
  errorText?: string;
package/src/ui.ts CHANGED
@@ -604,6 +604,23 @@ export const createAgentExperience = (
604
604
  return statusCopy[status];
605
605
  };
606
606
 
607
+ /** Update statusText element, rendering a link for idle status when idleLink is configured. */
608
+ function applyStatusToElement(el: HTMLElement, text: string, statusCfg: typeof statusConfig, status: string): void {
609
+ if (status === "idle" && statusCfg.idleLink) {
610
+ el.textContent = "";
611
+ const link = document.createElement("a");
612
+ link.href = statusCfg.idleLink;
613
+ link.target = "_blank";
614
+ link.rel = "noopener noreferrer";
615
+ link.textContent = text;
616
+ link.style.color = "inherit";
617
+ link.style.textDecoration = "none";
618
+ el.appendChild(link);
619
+ } else {
620
+ el.textContent = text;
621
+ }
622
+ }
623
+
607
624
  const { wrapper, panel } = createWrapper(config);
608
625
  const panelElements = buildPanel(config, launcherEnabled);
609
626
  let {
@@ -2670,14 +2687,14 @@ export const createAgentExperience = (
2670
2687
  },
2671
2688
  onStatusChanged(status) {
2672
2689
  const currentStatusConfig = config.statusIndicator ?? {};
2673
- const getCurrentStatusText = (status: AgentWidgetSessionStatus): string => {
2674
- if (status === "idle") return currentStatusConfig.idleText ?? statusCopy.idle;
2675
- if (status === "connecting") return currentStatusConfig.connectingText ?? statusCopy.connecting;
2676
- if (status === "connected") return currentStatusConfig.connectedText ?? statusCopy.connected;
2677
- if (status === "error") return currentStatusConfig.errorText ?? statusCopy.error;
2678
- return statusCopy[status];
2690
+ const getCurrentStatusText = (s: AgentWidgetSessionStatus): string => {
2691
+ if (s === "idle") return currentStatusConfig.idleText ?? statusCopy.idle;
2692
+ if (s === "connecting") return currentStatusConfig.connectingText ?? statusCopy.connecting;
2693
+ if (s === "connected") return currentStatusConfig.connectedText ?? statusCopy.connected;
2694
+ if (s === "error") return currentStatusConfig.errorText ?? statusCopy.error;
2695
+ return statusCopy[s];
2679
2696
  };
2680
- statusText.textContent = getCurrentStatusText(status);
2697
+ applyStatusToElement(statusText, getCurrentStatusText(status), currentStatusConfig, status);
2681
2698
  },
2682
2699
  onStreamingChanged(streaming) {
2683
2700
  isStreaming = streaming;
@@ -4815,14 +4832,14 @@ export const createAgentExperience = (
4815
4832
  // Update status text if status is currently set
4816
4833
  if (session) {
4817
4834
  const currentStatus = session.getStatus();
4818
- const getCurrentStatusText = (status: AgentWidgetSessionStatus): string => {
4819
- if (status === "idle") return statusIndicatorConfig.idleText ?? statusCopy.idle;
4820
- if (status === "connecting") return statusIndicatorConfig.connectingText ?? statusCopy.connecting;
4821
- if (status === "connected") return statusIndicatorConfig.connectedText ?? statusCopy.connected;
4822
- if (status === "error") return statusIndicatorConfig.errorText ?? statusCopy.error;
4823
- return statusCopy[status];
4835
+ const getCurrentStatusText = (s: AgentWidgetSessionStatus): string => {
4836
+ if (s === "idle") return statusIndicatorConfig.idleText ?? statusCopy.idle;
4837
+ if (s === "connecting") return statusIndicatorConfig.connectingText ?? statusCopy.connecting;
4838
+ if (s === "connected") return statusIndicatorConfig.connectedText ?? statusCopy.connected;
4839
+ if (s === "error") return statusIndicatorConfig.errorText ?? statusCopy.error;
4840
+ return statusCopy[s];
4824
4841
  };
4825
- statusText.textContent = getCurrentStatusText(currentStatus);
4842
+ applyStatusToElement(statusText, getCurrentStatusText(currentStatus), statusIndicatorConfig, currentStatus);
4826
4843
  }
4827
4844
  },
4828
4845
  open() {