vanilla-agent 1.14.0 → 1.16.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 +19 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.global.js +35 -34
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +18 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/composer-builder.ts +3 -2
- package/src/components/header-builder.ts +2 -1
- package/src/components/panel.ts +4 -4
- package/src/ui.ts +57 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vanilla-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.16.0",
|
|
4
4
|
"description": "Themeable, plugable streaming agent widget for websites, in plain JS with support for voice input and reasoning / tool output.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -46,7 +46,7 @@ export const buildComposer = (context: ComposerBuildContext): ComposerElements =
|
|
|
46
46
|
|
|
47
47
|
const footer = createElement(
|
|
48
48
|
"div",
|
|
49
|
-
"tvw-border-t-cw-divider tvw-bg-cw-surface tvw-px-6 tvw-py-4"
|
|
49
|
+
"tvw-widget-footer tvw-border-t-cw-divider tvw-bg-cw-surface tvw-px-6 tvw-py-4"
|
|
50
50
|
);
|
|
51
51
|
|
|
52
52
|
const suggestions = createElement(
|
|
@@ -67,7 +67,7 @@ export const buildComposer = (context: ComposerBuildContext): ComposerElements =
|
|
|
67
67
|
|
|
68
68
|
const composerForm = createElement(
|
|
69
69
|
"form",
|
|
70
|
-
`tvw-flex tvw-items-end ${gapClass} tvw-rounded-2xl tvw-border tvw-border-gray-200 tvw-bg-cw-input-background tvw-px-4 tvw-py-3`
|
|
70
|
+
`tvw-widget-composer tvw-flex tvw-items-end ${gapClass} tvw-rounded-2xl tvw-border tvw-border-gray-200 tvw-bg-cw-input-background tvw-px-4 tvw-py-3`
|
|
71
71
|
) as HTMLFormElement;
|
|
72
72
|
// Prevent form from getting focus styles
|
|
73
73
|
composerForm.style.outline = "none";
|
|
@@ -364,3 +364,4 @@ export const buildComposer = (context: ComposerBuildContext): ComposerElements =
|
|
|
364
364
|
};
|
|
365
365
|
};
|
|
366
366
|
|
|
367
|
+
|
|
@@ -29,7 +29,7 @@ export const buildHeader = (context: HeaderBuildContext): HeaderElements => {
|
|
|
29
29
|
|
|
30
30
|
const header = createElement(
|
|
31
31
|
"div",
|
|
32
|
-
"tvw-flex tvw-items-center tvw-gap-3 tvw-bg-cw-surface tvw-px-6 tvw-py-5 tvw-border-b-cw-divider"
|
|
32
|
+
"tvw-widget-header tvw-flex tvw-items-center tvw-gap-3 tvw-bg-cw-surface tvw-px-6 tvw-py-5 tvw-border-b-cw-divider"
|
|
33
33
|
);
|
|
34
34
|
|
|
35
35
|
const launcher = config?.launcher ?? {};
|
|
@@ -452,3 +452,4 @@ export const attachHeaderToContainer = (
|
|
|
452
452
|
}
|
|
453
453
|
};
|
|
454
454
|
|
|
455
|
+
|
package/src/components/panel.ts
CHANGED
|
@@ -36,12 +36,12 @@ export const createWrapper = (config?: AgentWidgetConfig): PanelWrapper => {
|
|
|
36
36
|
|
|
37
37
|
const wrapper = createElement(
|
|
38
38
|
"div",
|
|
39
|
-
`tvw-fixed ${position} tvw-z-50 tvw-transition`
|
|
39
|
+
`tvw-widget-wrapper tvw-fixed ${position} tvw-z-50 tvw-transition`
|
|
40
40
|
);
|
|
41
41
|
|
|
42
42
|
const panel = createElement(
|
|
43
43
|
"div",
|
|
44
|
-
"tvw-relative tvw-min-h-[320px]"
|
|
44
|
+
"tvw-widget-panel tvw-relative tvw-min-h-[320px]"
|
|
45
45
|
);
|
|
46
46
|
const launcherWidth = config?.launcher?.width ?? config?.launcherWidth;
|
|
47
47
|
const width = launcherWidth ?? "min(400px, calc(100vw - 24px))";
|
|
@@ -83,7 +83,7 @@ export const buildPanel = (config?: AgentWidgetConfig, showClose = true): PanelE
|
|
|
83
83
|
// the body (chat messages area) to scroll while header/footer stay fixed
|
|
84
84
|
const container = createElement(
|
|
85
85
|
"div",
|
|
86
|
-
"tvw-flex tvw-h-full tvw-w-full tvw-flex-1 tvw-min-h-0 tvw-flex-col tvw-bg-cw-surface tvw-text-cw-primary tvw-rounded-2xl tvw-overflow-hidden tvw-
|
|
86
|
+
"tvw-widget-container tvw-flex tvw-h-full tvw-w-full tvw-flex-1 tvw-min-h-0 tvw-flex-col tvw-bg-cw-surface tvw-text-cw-primary tvw-rounded-2xl tvw-overflow-hidden tvw-border tvw-border-cw-border"
|
|
87
87
|
);
|
|
88
88
|
|
|
89
89
|
// Build header using layout config if available, otherwise use standard builder
|
|
@@ -95,7 +95,7 @@ export const buildPanel = (config?: AgentWidgetConfig, showClose = true): PanelE
|
|
|
95
95
|
// Build body with intro card and messages wrapper
|
|
96
96
|
const body = createElement(
|
|
97
97
|
"div",
|
|
98
|
-
"tvw-flex tvw-flex-1 tvw-min-h-0 tvw-flex-col tvw-gap-6 tvw-overflow-y-auto tvw-bg-cw-container tvw-px-6 tvw-py-6"
|
|
98
|
+
"tvw-widget-body tvw-flex tvw-flex-1 tvw-min-h-0 tvw-flex-col tvw-gap-6 tvw-overflow-y-auto tvw-bg-cw-container tvw-px-6 tvw-py-6"
|
|
99
99
|
);
|
|
100
100
|
body.id = "vanilla-agent-scroll-container";
|
|
101
101
|
|
package/src/ui.ts
CHANGED
|
@@ -19,6 +19,7 @@ import { createElement } from "./utils/dom";
|
|
|
19
19
|
import { statusCopy } from "./utils/constants";
|
|
20
20
|
import { createLauncherButton } from "./components/launcher";
|
|
21
21
|
import { createWrapper, buildPanel, buildHeader, buildComposer, attachHeaderToContainer } from "./components/panel";
|
|
22
|
+
import { positionMap } from "./utils/positioning";
|
|
22
23
|
import type { HeaderElements, ComposerElements } from "./components/panel";
|
|
23
24
|
import { MessageTransform } from "./components/message-bubble";
|
|
24
25
|
import { createStandardBubble, createTypingIndicator } from "./components/message-bubble";
|
|
@@ -418,12 +419,36 @@ export const createAgentExperience = (
|
|
|
418
419
|
const panelShadow = theme.panelShadow ?? defaultPanelShadow;
|
|
419
420
|
const panelBorderRadius = theme.panelBorderRadius ?? defaultPanelBorderRadius;
|
|
420
421
|
|
|
421
|
-
//
|
|
422
|
+
// Reset all inline styles first to handle mode toggling
|
|
423
|
+
// This ensures styles don't persist when switching between modes
|
|
424
|
+
mount.style.cssText = '';
|
|
425
|
+
wrapper.style.cssText = '';
|
|
426
|
+
panel.style.cssText = '';
|
|
427
|
+
container.style.cssText = '';
|
|
428
|
+
body.style.cssText = '';
|
|
429
|
+
footer.style.cssText = '';
|
|
430
|
+
|
|
431
|
+
// Re-apply panel width/maxWidth from initial setup
|
|
432
|
+
const launcherWidth = config?.launcher?.width ?? config?.launcherWidth;
|
|
433
|
+
const width = launcherWidth ?? "min(400px, calc(100vw - 24px))";
|
|
434
|
+
if (!sidebarMode) {
|
|
435
|
+
panel.style.width = width;
|
|
436
|
+
panel.style.maxWidth = width;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// Apply panel styling
|
|
440
|
+
// Box-shadow is applied to panel (parent) instead of container to avoid
|
|
441
|
+
// rendering artifacts when container has overflow:hidden + border-radius
|
|
442
|
+
// Panel also gets border-radius to make the shadow follow the rounded corners
|
|
443
|
+
panel.style.boxShadow = panelShadow;
|
|
444
|
+
panel.style.borderRadius = panelBorderRadius;
|
|
422
445
|
container.style.border = panelBorder;
|
|
423
|
-
container.style.boxShadow = panelShadow;
|
|
424
446
|
container.style.borderRadius = panelBorderRadius;
|
|
425
447
|
|
|
426
448
|
if (fullHeight) {
|
|
449
|
+
// Check if this is inline embed mode (launcher disabled) vs launcher mode
|
|
450
|
+
const isInlineEmbed = config.launcher?.enabled === false;
|
|
451
|
+
|
|
427
452
|
// Mount container
|
|
428
453
|
mount.style.display = 'flex';
|
|
429
454
|
mount.style.flexDirection = 'column';
|
|
@@ -431,13 +456,17 @@ export const createAgentExperience = (
|
|
|
431
456
|
mount.style.minHeight = '0';
|
|
432
457
|
|
|
433
458
|
// Wrapper
|
|
459
|
+
// - Inline embed: needs overflow:hidden to contain the flex layout
|
|
460
|
+
// - Launcher mode: no overflow:hidden to allow panel's box-shadow to render fully
|
|
434
461
|
wrapper.style.display = 'flex';
|
|
435
462
|
wrapper.style.flexDirection = 'column';
|
|
436
463
|
wrapper.style.flex = '1 1 0%';
|
|
437
464
|
wrapper.style.minHeight = '0';
|
|
438
465
|
wrapper.style.maxHeight = '100%';
|
|
439
466
|
wrapper.style.height = '100%';
|
|
440
|
-
|
|
467
|
+
if (isInlineEmbed) {
|
|
468
|
+
wrapper.style.overflow = 'hidden';
|
|
469
|
+
}
|
|
441
470
|
|
|
442
471
|
// Panel
|
|
443
472
|
panel.style.display = 'flex';
|
|
@@ -465,16 +494,23 @@ export const createAgentExperience = (
|
|
|
465
494
|
footer.style.flexShrink = '0';
|
|
466
495
|
}
|
|
467
496
|
|
|
497
|
+
// Handle positioning classes based on mode
|
|
498
|
+
// First remove all position classes to reset state
|
|
499
|
+
wrapper.classList.remove(
|
|
500
|
+
'tvw-bottom-6', 'tvw-right-6', 'tvw-left-6', 'tvw-top-6',
|
|
501
|
+
'tvw-bottom-4', 'tvw-right-4', 'tvw-left-4', 'tvw-top-4'
|
|
502
|
+
);
|
|
503
|
+
|
|
504
|
+
if (!sidebarMode) {
|
|
505
|
+
// Restore positioning classes when not in sidebar mode
|
|
506
|
+
const positionClasses = positionMap[position as keyof typeof positionMap] ?? positionMap['bottom-right'];
|
|
507
|
+
positionClasses.split(' ').forEach(cls => wrapper.classList.add(cls));
|
|
508
|
+
}
|
|
509
|
+
|
|
468
510
|
// Apply sidebar-specific styles
|
|
469
511
|
if (sidebarMode) {
|
|
470
512
|
const sidebarWidth = config.launcher?.sidebarWidth ?? '420px';
|
|
471
513
|
|
|
472
|
-
// Remove Tailwind positioning classes that add spacing (tvw-bottom-6, tvw-right-6, etc.)
|
|
473
|
-
wrapper.classList.remove(
|
|
474
|
-
'tvw-bottom-6', 'tvw-right-6', 'tvw-left-6', 'tvw-top-6',
|
|
475
|
-
'tvw-bottom-4', 'tvw-right-4', 'tvw-left-4', 'tvw-top-4'
|
|
476
|
-
);
|
|
477
|
-
|
|
478
514
|
// Wrapper - fixed position, flush with edges
|
|
479
515
|
wrapper.style.cssText = `
|
|
480
516
|
position: fixed !important;
|
|
@@ -491,6 +527,8 @@ export const createAgentExperience = (
|
|
|
491
527
|
`;
|
|
492
528
|
|
|
493
529
|
// Panel - fill wrapper (override inline width/max-width from panel.ts)
|
|
530
|
+
// Box-shadow is on panel to avoid rendering artifacts with container's overflow:hidden
|
|
531
|
+
// Border-radius on panel ensures shadow follows rounded corners
|
|
494
532
|
panel.style.cssText = `
|
|
495
533
|
position: relative !important;
|
|
496
534
|
display: flex !important;
|
|
@@ -502,12 +540,15 @@ export const createAgentExperience = (
|
|
|
502
540
|
min-height: 0 !important;
|
|
503
541
|
margin: 0 !important;
|
|
504
542
|
padding: 0 !important;
|
|
543
|
+
box-shadow: ${panelShadow} !important;
|
|
544
|
+
border-radius: ${panelBorderRadius} !important;
|
|
505
545
|
`;
|
|
506
546
|
// Force override any inline width/maxWidth that may be set elsewhere
|
|
507
547
|
panel.style.setProperty('width', '100%', 'important');
|
|
508
548
|
panel.style.setProperty('max-width', '100%', 'important');
|
|
509
549
|
|
|
510
550
|
// Container - apply configurable styles with sidebar layout
|
|
551
|
+
// Note: box-shadow is on panel, not container
|
|
511
552
|
container.style.cssText = `
|
|
512
553
|
display: flex !important;
|
|
513
554
|
flex-direction: column !important;
|
|
@@ -519,7 +560,6 @@ export const createAgentExperience = (
|
|
|
519
560
|
overflow: hidden !important;
|
|
520
561
|
border-radius: ${panelBorderRadius} !important;
|
|
521
562
|
border: ${panelBorder} !important;
|
|
522
|
-
box-shadow: ${panelShadow} !important;
|
|
523
563
|
`;
|
|
524
564
|
|
|
525
565
|
// Remove footer border in sidebar mode
|
|
@@ -529,6 +569,13 @@ export const createAgentExperience = (
|
|
|
529
569
|
padding: 8px 16px 12px 16px !important;
|
|
530
570
|
`;
|
|
531
571
|
}
|
|
572
|
+
|
|
573
|
+
// Apply max-height constraints to wrapper to prevent expanding past viewport top
|
|
574
|
+
// Use both -moz-available (Firefox) and stretch (standard) for cross-browser support
|
|
575
|
+
// Append to cssText to allow multiple fallback values for the same property
|
|
576
|
+
const maxHeightStyles = 'max-height: -moz-available !important; max-height: stretch !important;';
|
|
577
|
+
const paddingStyles = sidebarMode ? '' : 'padding-top: 1.25em !important;';
|
|
578
|
+
wrapper.style.cssText += maxHeightStyles + paddingStyles;
|
|
532
579
|
};
|
|
533
580
|
applyFullHeightStyles();
|
|
534
581
|
|