vanilla-agent 1.14.0 → 1.15.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 +50 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vanilla-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.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,9 +419,30 @@ 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) {
|
|
@@ -430,14 +452,13 @@ export const createAgentExperience = (
|
|
|
430
452
|
mount.style.height = '100%';
|
|
431
453
|
mount.style.minHeight = '0';
|
|
432
454
|
|
|
433
|
-
// Wrapper
|
|
455
|
+
// Wrapper - no overflow:hidden to allow panel's box-shadow to render fully
|
|
434
456
|
wrapper.style.display = 'flex';
|
|
435
457
|
wrapper.style.flexDirection = 'column';
|
|
436
458
|
wrapper.style.flex = '1 1 0%';
|
|
437
459
|
wrapper.style.minHeight = '0';
|
|
438
460
|
wrapper.style.maxHeight = '100%';
|
|
439
461
|
wrapper.style.height = '100%';
|
|
440
|
-
wrapper.style.overflow = 'hidden';
|
|
441
462
|
|
|
442
463
|
// Panel
|
|
443
464
|
panel.style.display = 'flex';
|
|
@@ -465,16 +486,23 @@ export const createAgentExperience = (
|
|
|
465
486
|
footer.style.flexShrink = '0';
|
|
466
487
|
}
|
|
467
488
|
|
|
489
|
+
// Handle positioning classes based on mode
|
|
490
|
+
// First remove all position classes to reset state
|
|
491
|
+
wrapper.classList.remove(
|
|
492
|
+
'tvw-bottom-6', 'tvw-right-6', 'tvw-left-6', 'tvw-top-6',
|
|
493
|
+
'tvw-bottom-4', 'tvw-right-4', 'tvw-left-4', 'tvw-top-4'
|
|
494
|
+
);
|
|
495
|
+
|
|
496
|
+
if (!sidebarMode) {
|
|
497
|
+
// Restore positioning classes when not in sidebar mode
|
|
498
|
+
const positionClasses = positionMap[position as keyof typeof positionMap] ?? positionMap['bottom-right'];
|
|
499
|
+
positionClasses.split(' ').forEach(cls => wrapper.classList.add(cls));
|
|
500
|
+
}
|
|
501
|
+
|
|
468
502
|
// Apply sidebar-specific styles
|
|
469
503
|
if (sidebarMode) {
|
|
470
504
|
const sidebarWidth = config.launcher?.sidebarWidth ?? '420px';
|
|
471
505
|
|
|
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
506
|
// Wrapper - fixed position, flush with edges
|
|
479
507
|
wrapper.style.cssText = `
|
|
480
508
|
position: fixed !important;
|
|
@@ -491,6 +519,8 @@ export const createAgentExperience = (
|
|
|
491
519
|
`;
|
|
492
520
|
|
|
493
521
|
// Panel - fill wrapper (override inline width/max-width from panel.ts)
|
|
522
|
+
// Box-shadow is on panel to avoid rendering artifacts with container's overflow:hidden
|
|
523
|
+
// Border-radius on panel ensures shadow follows rounded corners
|
|
494
524
|
panel.style.cssText = `
|
|
495
525
|
position: relative !important;
|
|
496
526
|
display: flex !important;
|
|
@@ -502,12 +532,15 @@ export const createAgentExperience = (
|
|
|
502
532
|
min-height: 0 !important;
|
|
503
533
|
margin: 0 !important;
|
|
504
534
|
padding: 0 !important;
|
|
535
|
+
box-shadow: ${panelShadow} !important;
|
|
536
|
+
border-radius: ${panelBorderRadius} !important;
|
|
505
537
|
`;
|
|
506
538
|
// Force override any inline width/maxWidth that may be set elsewhere
|
|
507
539
|
panel.style.setProperty('width', '100%', 'important');
|
|
508
540
|
panel.style.setProperty('max-width', '100%', 'important');
|
|
509
541
|
|
|
510
542
|
// Container - apply configurable styles with sidebar layout
|
|
543
|
+
// Note: box-shadow is on panel, not container
|
|
511
544
|
container.style.cssText = `
|
|
512
545
|
display: flex !important;
|
|
513
546
|
flex-direction: column !important;
|
|
@@ -519,7 +552,6 @@ export const createAgentExperience = (
|
|
|
519
552
|
overflow: hidden !important;
|
|
520
553
|
border-radius: ${panelBorderRadius} !important;
|
|
521
554
|
border: ${panelBorder} !important;
|
|
522
|
-
box-shadow: ${panelShadow} !important;
|
|
523
555
|
`;
|
|
524
556
|
|
|
525
557
|
// Remove footer border in sidebar mode
|
|
@@ -529,6 +561,13 @@ export const createAgentExperience = (
|
|
|
529
561
|
padding: 8px 16px 12px 16px !important;
|
|
530
562
|
`;
|
|
531
563
|
}
|
|
564
|
+
|
|
565
|
+
// Apply max-height constraints to wrapper to prevent expanding past viewport top
|
|
566
|
+
// Use both -moz-available (Firefox) and stretch (standard) for cross-browser support
|
|
567
|
+
// Append to cssText to allow multiple fallback values for the same property
|
|
568
|
+
const maxHeightStyles = 'max-height: -moz-available !important; max-height: stretch !important;';
|
|
569
|
+
const paddingStyles = sidebarMode ? '' : 'padding-top: 1.25em !important;';
|
|
570
|
+
wrapper.style.cssText += maxHeightStyles + paddingStyles;
|
|
532
571
|
};
|
|
533
572
|
applyFullHeightStyles();
|
|
534
573
|
|