@runtypelabs/persona 3.2.1 → 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/dist/index.cjs +284 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -1
- package/dist/index.d.ts +61 -1
- package/dist/index.global.js +324 -81
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +280 -37
- package/dist/index.js.map +1 -1
- package/dist/widget.css +62 -0
- package/package.json +1 -1
- package/src/components/composer-builder.ts +20 -4
- package/src/components/demo-carousel.ts +699 -0
- package/src/components/header-builder.ts +1 -1
- package/src/index.ts +8 -0
- package/src/runtime/host-layout.ts +1 -1
- package/src/styles/widget.css +62 -0
- package/src/types.ts +12 -0
- package/src/ui.overlay-z-index.test.ts +62 -0
- package/src/ui.ts +40 -16
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,
|
|
@@ -198,7 +198,7 @@ const applyDockStyles = (
|
|
|
198
198
|
dockSlot.style.minWidth = "0";
|
|
199
199
|
dockSlot.style.minHeight = "0";
|
|
200
200
|
dockSlot.style.overflow = "hidden";
|
|
201
|
-
dockSlot.style.zIndex =
|
|
201
|
+
dockSlot.style.zIndex = String(config?.launcher?.zIndex ?? 9999);
|
|
202
202
|
dockSlot.style.transform = "none";
|
|
203
203
|
dockSlot.style.transition = "none";
|
|
204
204
|
dockSlot.style.pointerEvents = "auto";
|
package/src/styles/widget.css
CHANGED
|
@@ -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
|
@@ -790,6 +790,14 @@ export type AgentWidgetLauncherConfig = {
|
|
|
790
790
|
* @default 640
|
|
791
791
|
*/
|
|
792
792
|
mobileBreakpoint?: number;
|
|
793
|
+
/**
|
|
794
|
+
* CSS z-index applied to the widget wrapper when it is in a positioned mode
|
|
795
|
+
* (floating panel, mobile fullscreen, or sidebar). Increase this value if
|
|
796
|
+
* other elements on the host page appear on top of the widget.
|
|
797
|
+
*
|
|
798
|
+
* @default 9999 in overlay modes (mobile fullscreen / sidebar); 50 for the regular floating panel
|
|
799
|
+
*/
|
|
800
|
+
zIndex?: number;
|
|
793
801
|
callToActionIconText?: string;
|
|
794
802
|
callToActionIconName?: string;
|
|
795
803
|
callToActionIconColor?: string;
|
|
@@ -876,7 +884,11 @@ export type AgentWidgetClearChatConfig = {
|
|
|
876
884
|
|
|
877
885
|
export type AgentWidgetStatusIndicatorConfig = {
|
|
878
886
|
visible?: boolean;
|
|
887
|
+
/** Text alignment. Default: 'right'. */
|
|
888
|
+
align?: 'left' | 'center' | 'right';
|
|
879
889
|
idleText?: string;
|
|
890
|
+
/** URL to open in a new tab when the idle text is clicked. */
|
|
891
|
+
idleLink?: string;
|
|
880
892
|
connectingText?: string;
|
|
881
893
|
connectedText?: string;
|
|
882
894
|
errorText?: string;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
|
|
3
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
4
|
+
|
|
5
|
+
import { createAgentExperience } from "./ui";
|
|
6
|
+
|
|
7
|
+
const originalInnerWidth = window.innerWidth;
|
|
8
|
+
|
|
9
|
+
const setInnerWidth = (value: number) => {
|
|
10
|
+
Object.defineProperty(window, "innerWidth", {
|
|
11
|
+
configurable: true,
|
|
12
|
+
writable: true,
|
|
13
|
+
value,
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const createMount = () => {
|
|
18
|
+
const mount = document.createElement("div");
|
|
19
|
+
document.body.appendChild(mount);
|
|
20
|
+
return mount;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
describe("createAgentExperience overlay z-index", () => {
|
|
24
|
+
afterEach(() => {
|
|
25
|
+
document.body.innerHTML = "";
|
|
26
|
+
setInnerWidth(originalInnerWidth);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("defaults sidebar mode to the overlay z-index", () => {
|
|
30
|
+
const mount = createMount();
|
|
31
|
+
const controller = createAgentExperience(mount, {
|
|
32
|
+
apiUrl: "https://api.example.com/chat",
|
|
33
|
+
launcher: {
|
|
34
|
+
sidebarMode: true,
|
|
35
|
+
position: "bottom-right",
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const wrapper = mount.firstElementChild as HTMLElement | null;
|
|
40
|
+
|
|
41
|
+
expect(wrapper).not.toBeNull();
|
|
42
|
+
expect(wrapper?.style.zIndex).toBe("9999");
|
|
43
|
+
|
|
44
|
+
controller.destroy();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("defaults mobile fullscreen to the overlay z-index", () => {
|
|
48
|
+
setInnerWidth(480);
|
|
49
|
+
|
|
50
|
+
const mount = createMount();
|
|
51
|
+
const controller = createAgentExperience(mount, {
|
|
52
|
+
apiUrl: "https://api.example.com/chat",
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const wrapper = mount.firstElementChild as HTMLElement | null;
|
|
56
|
+
|
|
57
|
+
expect(wrapper).not.toBeNull();
|
|
58
|
+
expect(wrapper?.style.zIndex).toBe("9999");
|
|
59
|
+
|
|
60
|
+
controller.destroy();
|
|
61
|
+
});
|
|
62
|
+
});
|
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 {
|
|
@@ -1474,6 +1491,7 @@ export const createAgentExperience = (
|
|
|
1474
1491
|
// Determine panel styling based on mode, with theme overrides
|
|
1475
1492
|
const position = config.launcher?.position ?? 'bottom-left';
|
|
1476
1493
|
const isLeftSidebar = position === 'bottom-left' || position === 'top-left';
|
|
1494
|
+
const overlayZIndex = config.launcher?.zIndex ?? 9999;
|
|
1477
1495
|
|
|
1478
1496
|
// Default values based on mode
|
|
1479
1497
|
let defaultPanelBorder = (sidebarMode || shouldGoFullscreen) ? 'none' : '1px solid var(--persona-border)';
|
|
@@ -1524,7 +1542,8 @@ export const createAgentExperience = (
|
|
|
1524
1542
|
padding: 0 !important;
|
|
1525
1543
|
display: flex !important;
|
|
1526
1544
|
flex-direction: column !important;
|
|
1527
|
-
z-index:
|
|
1545
|
+
z-index: ${overlayZIndex} !important;
|
|
1546
|
+
background-color: var(--persona-surface, #ffffff) !important;
|
|
1528
1547
|
`;
|
|
1529
1548
|
|
|
1530
1549
|
// Panel — fill wrapper, no radius/shadow
|
|
@@ -1690,6 +1709,7 @@ export const createAgentExperience = (
|
|
|
1690
1709
|
padding: 0 !important;
|
|
1691
1710
|
display: flex !important;
|
|
1692
1711
|
flex-direction: column !important;
|
|
1712
|
+
z-index: ${overlayZIndex} !important;
|
|
1693
1713
|
${isLeftSidebar ? 'left: 0 !important; right: auto !important;' : 'left: auto !important; right: 0 !important;'}
|
|
1694
1714
|
`;
|
|
1695
1715
|
|
|
@@ -1744,7 +1764,11 @@ export const createAgentExperience = (
|
|
|
1744
1764
|
if (!isInlineEmbed && !dockedMode) {
|
|
1745
1765
|
const maxHeightStyles = 'max-height: -moz-available !important; max-height: stretch !important;';
|
|
1746
1766
|
const paddingStyles = sidebarMode ? '' : 'padding-top: 1.25em !important;';
|
|
1747
|
-
|
|
1767
|
+
// Override z-index only when explicitly configured; otherwise the persona-z-50 class applies
|
|
1768
|
+
const zIndexStyles = !sidebarMode && config.launcher?.zIndex != null
|
|
1769
|
+
? `z-index: ${config.launcher.zIndex} !important;`
|
|
1770
|
+
: '';
|
|
1771
|
+
wrapper.style.cssText += maxHeightStyles + paddingStyles + zIndexStyles;
|
|
1748
1772
|
}
|
|
1749
1773
|
};
|
|
1750
1774
|
applyFullHeightStyles();
|
|
@@ -2663,14 +2687,14 @@ export const createAgentExperience = (
|
|
|
2663
2687
|
},
|
|
2664
2688
|
onStatusChanged(status) {
|
|
2665
2689
|
const currentStatusConfig = config.statusIndicator ?? {};
|
|
2666
|
-
const getCurrentStatusText = (
|
|
2667
|
-
if (
|
|
2668
|
-
if (
|
|
2669
|
-
if (
|
|
2670
|
-
if (
|
|
2671
|
-
return statusCopy[
|
|
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];
|
|
2672
2696
|
};
|
|
2673
|
-
statusText
|
|
2697
|
+
applyStatusToElement(statusText, getCurrentStatusText(status), currentStatusConfig, status);
|
|
2674
2698
|
},
|
|
2675
2699
|
onStreamingChanged(streaming) {
|
|
2676
2700
|
isStreaming = streaming;
|
|
@@ -4808,14 +4832,14 @@ export const createAgentExperience = (
|
|
|
4808
4832
|
// Update status text if status is currently set
|
|
4809
4833
|
if (session) {
|
|
4810
4834
|
const currentStatus = session.getStatus();
|
|
4811
|
-
const getCurrentStatusText = (
|
|
4812
|
-
if (
|
|
4813
|
-
if (
|
|
4814
|
-
if (
|
|
4815
|
-
if (
|
|
4816
|
-
return statusCopy[
|
|
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];
|
|
4817
4841
|
};
|
|
4818
|
-
statusText
|
|
4842
|
+
applyStatusToElement(statusText, getCurrentStatusText(currentStatus), statusIndicatorConfig, currentStatus);
|
|
4819
4843
|
}
|
|
4820
4844
|
},
|
|
4821
4845
|
open() {
|