@memberjunction/ng-ai-test-harness
Version:
MemberJunction AI Test Harness - A reusable component for testing AI agents and prompts with beautiful UX
125 lines • 10.7 kB
JavaScript
import { Injectable, Component, createComponent } from '@angular/core';
import * as i0 from "@angular/core";
const _forTrack0 = ($index, $item) => $item.windowId;
function WindowDockComponent_For_2_Template(rf, ctx) { if (rf & 1) {
const _r1 = i0.ɵɵgetCurrentView();
i0.ɵɵelementStart(0, "div", 2);
i0.ɵɵlistener("click", function WindowDockComponent_For_2_Template_div_click_0_listener() { const item_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.restoreWindow(item_r2)); });
i0.ɵɵelement(1, "i");
i0.ɵɵelementStart(2, "span", 3);
i0.ɵɵtext(3);
i0.ɵɵelementEnd()();
} if (rf & 2) {
const item_r2 = ctx.$implicit;
const ctx_r2 = i0.ɵɵnextContext();
i0.ɵɵproperty("title", item_r2.title);
i0.ɵɵadvance();
i0.ɵɵclassMap(item_r2.icon);
i0.ɵɵadvance(2);
i0.ɵɵtextInterpolate(ctx_r2.getTruncatedTitle(item_r2.title));
} }
export class WindowDockComponent {
constructor() {
this.dockItems = [];
}
addItem(item) {
this.dockItems.push(item);
}
removeItem(windowId) {
this.dockItems = this.dockItems.filter(item => item.windowId !== windowId);
}
restoreWindow(item) {
item.restoreCallback();
this.removeItem(item.windowId);
}
getTruncatedTitle(title) {
// Remove "Test: " prefix for the label to save space
const cleanTitle = title.startsWith('Test: ') ? title.substring(6) : title;
// Truncate to first 8 characters for the label
return cleanTitle.length > 8 ? cleanTitle.substring(0, 8) + '...' : cleanTitle;
}
static { this.ɵfac = function WindowDockComponent_Factory(t) { return new (t || WindowDockComponent)(); }; }
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: WindowDockComponent, selectors: [["mj-window-dock"]], standalone: true, features: [i0.ɵɵStandaloneFeature], decls: 3, vars: 0, consts: [[1, "window-dock"], [1, "dock-item", 3, "title"], [1, "dock-item", 3, "click", "title"], [1, "dock-item-label"]], template: function WindowDockComponent_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵelementStart(0, "div", 0);
i0.ɵɵrepeaterCreate(1, WindowDockComponent_For_2_Template, 4, 4, "div", 1, _forTrack0);
i0.ɵɵelementEnd();
} if (rf & 2) {
i0.ɵɵadvance();
i0.ɵɵrepeater(ctx.dockItems);
} }, styles: ["[_nghost-%COMP%] {\n position: fixed;\n bottom: 10px;\n right: 10px;\n z-index: 10001;\n }\n \n .window-dock[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n background: #f0f4f8;\n border: 1px solid #d0d8e0;\n border-radius: 8px;\n padding: 12px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n }\n \n .dock-item[_ngcontent-%COMP%] {\n width: 64px;\n height: 72px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 4px;\n cursor: pointer;\n border-radius: 6px;\n transition: all 0.2s;\n padding: 8px 4px;\n \n &:hover {\n background-color: rgba(255, 255, 255, 0.8);\n transform: translateY(-2px);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n }\n \n i {\n font-size: 28px;\n color: #2c5282;\n }\n \n .dock-item-label {\n font-size: 11px;\n color: #4a5568;\n text-align: center;\n line-height: 1.2;\n max-width: 60px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n \n .dock-item-progress {\n position: absolute;\n bottom: 2px;\n left: 2px;\n right: 2px;\n height: 3px;\n background: rgba(0, 0, 0, 0.1);\n border-radius: 2px;\n overflow: hidden;\n }\n \n .dock-item-progress-bar {\n height: 100%;\n background: #0076B6; \n\n transition: width 0.3s ease;\n }\n \n \n\n .dock-item-progress-bar[style*=\"width: 50%\"] {\n animation: _ngcontent-%COMP%_pulse-progress 1.5s ease-in-out infinite;\n }\n }\n \n @keyframes _ngcontent-%COMP%_pulse-progress {\n 0% { opacity: 0.6; width: 30%; }\n 50% { opacity: 1; width: 70%; }\n 100% { opacity: 0.6; width: 30%; }\n }"] }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(WindowDockComponent, [{
type: Component,
args: [{ selector: 'mj-window-dock', standalone: true, imports: [], template: `
<div class="window-dock">
(item of dockItems; track item.windowId) {
<div class="dock-item"
[title]="item.title"
(click)="restoreWindow(item)">
<i [class]="item.icon"></i>
<span class="dock-item-label">{{ getTruncatedTitle(item.title) }}</span>
</div>
}
</div>
`, styles: ["\n :host {\n position: fixed;\n bottom: 10px;\n right: 10px;\n z-index: 10001;\n }\n \n .window-dock {\n display: flex;\n gap: 12px;\n background: #f0f4f8;\n border: 1px solid #d0d8e0;\n border-radius: 8px;\n padding: 12px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n }\n \n .dock-item {\n width: 64px;\n height: 72px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 4px;\n cursor: pointer;\n border-radius: 6px;\n transition: all 0.2s;\n padding: 8px 4px;\n \n &:hover {\n background-color: rgba(255, 255, 255, 0.8);\n transform: translateY(-2px);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n }\n \n i {\n font-size: 28px;\n color: #2c5282;\n }\n \n .dock-item-label {\n font-size: 11px;\n color: #4a5568;\n text-align: center;\n line-height: 1.2;\n max-width: 60px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n \n .dock-item-progress {\n position: absolute;\n bottom: 2px;\n left: 2px;\n right: 2px;\n height: 3px;\n background: rgba(0, 0, 0, 0.1);\n border-radius: 2px;\n overflow: hidden;\n }\n \n .dock-item-progress-bar {\n height: 100%;\n background: #0076B6; /* MJ blue color */\n transition: width 0.3s ease;\n }\n \n /* Pulse animation for indeterminate progress (50%) */\n .dock-item-progress-bar[style*=\"width: 50%\"] {\n animation: pulse-progress 1.5s ease-in-out infinite;\n }\n }\n \n @keyframes pulse-progress {\n 0% { opacity: 0.6; width: 30%; }\n 50% { opacity: 1; width: 70%; }\n 100% { opacity: 0.6; width: 30%; }\n }\n "] }]
}], null, null); })();
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(WindowDockComponent, { className: "WindowDockComponent", filePath: "lib/window-dock.service.ts", lineNumber: 111 }); })();
export class WindowDockService {
constructor(appRef, injector) {
this.appRef = appRef;
this.injector = injector;
}
ensureDockExists() {
if (!this.dockComponent) {
// Create dock component
this.dockComponent = createComponent(WindowDockComponent, {
environmentInjector: this.appRef.injector,
elementInjector: this.injector
});
// Attach to DOM
document.body.appendChild(this.dockComponent.location.nativeElement);
this.appRef.attachView(this.dockComponent.hostView);
}
}
addWindow(windowId, title, icon, restoreCallback, iconUrl, progress) {
this.ensureDockExists();
if (this.dockComponent) {
this.dockComponent.instance.addItem({
windowId,
title,
icon,
iconUrl,
restoreCallback: restoreCallback || (() => { }),
progress
});
}
}
removeWindow(windowId) {
if (this.dockComponent) {
this.dockComponent.instance.removeItem(windowId);
// If no more items, remove the dock
if (this.dockComponent.instance.dockItems.length === 0) {
this.appRef.detachView(this.dockComponent.hostView);
this.dockComponent.destroy();
this.dockComponent = undefined;
}
}
}
updateWindowProgress(windowId, progress) {
if (this.dockComponent) {
const item = this.dockComponent.instance.dockItems.find(i => i.windowId === windowId);
if (item) {
item.progress = progress;
}
}
}
static { this.ɵfac = function WindowDockService_Factory(t) { return new (t || WindowDockService)(i0.ɵɵinject(i0.ApplicationRef), i0.ɵɵinject(i0.Injector)); }; }
static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: WindowDockService, factory: WindowDockService.ɵfac, providedIn: 'root' }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(WindowDockService, [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], () => [{ type: i0.ApplicationRef }, { type: i0.Injector }], null); })();
//# sourceMappingURL=window-dock.service.js.map