@cqa-lib/cqa-ui 1.1.185 → 1.1.187

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.
Files changed (26) hide show
  1. package/esm2020/lib/execution-screen/main-step-collapse/main-step-collapse.component.mjs +20 -3
  2. package/esm2020/lib/simulator/simulator.component.mjs +188 -346
  3. package/esm2020/lib/step-builder/step-builder-api/step-builder-api.component.mjs +132 -7
  4. package/esm2020/lib/step-builder/step-builder-database/step-builder-database.component.mjs +4 -5
  5. package/esm2020/lib/test-case-details/condition-step/condition-step.component.mjs +1 -1
  6. package/esm2020/lib/test-case-details/loop-step/loop-step.component.mjs +1 -1
  7. package/esm2020/lib/test-case-details/normal-step/normal-step.component.mjs +24 -32
  8. package/esm2020/lib/test-case-details/step-group/step-group.component.mjs +1 -1
  9. package/esm2020/lib/test-case-details/test-case-details-renderer/test-case-details-renderer.component.mjs +15 -3
  10. package/esm2020/lib/test-case-details/test-case-step.models.mjs +1 -1
  11. package/esm2020/lib/test-case-details/test-data-modal/test-data-modal-data.mjs +1 -1
  12. package/esm2020/lib/test-case-details/test-data-modal/test-data-modal.component.mjs +51 -17
  13. package/fesm2015/cqa-lib-cqa-ui.mjs +436 -416
  14. package/fesm2015/cqa-lib-cqa-ui.mjs.map +1 -1
  15. package/fesm2020/cqa-lib-cqa-ui.mjs +424 -404
  16. package/fesm2020/cqa-lib-cqa-ui.mjs.map +1 -1
  17. package/lib/execution-screen/main-step-collapse/main-step-collapse.component.d.ts +6 -3
  18. package/lib/simulator/simulator.component.d.ts +10 -22
  19. package/lib/step-builder/step-builder-api/step-builder-api.component.d.ts +6 -0
  20. package/lib/test-case-details/normal-step/normal-step.component.d.ts +7 -2
  21. package/lib/test-case-details/test-case-details-renderer/test-case-details-renderer.component.d.ts +7 -1
  22. package/lib/test-case-details/test-case-step.models.d.ts +1 -0
  23. package/lib/test-case-details/test-data-modal/test-data-modal-data.d.ts +6 -1
  24. package/lib/test-case-details/test-data-modal/test-data-modal.component.d.ts +11 -7
  25. package/package.json +1 -1
  26. package/styles.css +1 -1
@@ -3,7 +3,7 @@ import { EventEmitter, Component, Input, Output, HostListener, ViewChildren, Vie
3
3
  import * as i2 from '@angular/common';
4
4
  import { CommonModule } from '@angular/common';
5
5
  import * as i2$1 from '@angular/forms';
6
- import { NG_VALUE_ACCESSOR, FormControl, FormGroup, FormBuilder, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
6
+ import { NG_VALUE_ACCESSOR, FormControl, FormGroup, FormBuilder, Validators, FormArray, FormsModule, ReactiveFormsModule } from '@angular/forms';
7
7
  import * as i1 from '@angular/material/icon';
8
8
  import { MatIconModule } from '@angular/material/icon';
9
9
  import * as i3$1 from '@angular/material/menu';
@@ -11271,6 +11271,8 @@ class MainStepCollapseComponent {
11271
11271
  this.viewStepsAsRedirect = false;
11272
11272
  /** When redirecting, open link in new tab. Default true */
11273
11273
  this.viewStepsOpenInNewTab = true;
11274
+ /** Optional initial item id to expand (e.g. first failed prerequisite). When set and present in items, that item is expanded on load. */
11275
+ this.initialExpandedItemId = null;
11274
11276
  this.viewSteps = new EventEmitter();
11275
11277
  this.headerButtonClick = new EventEmitter();
11276
11278
  this.expandedChange = new EventEmitter();
@@ -11279,11 +11281,25 @@ class MainStepCollapseComponent {
11279
11281
  }
11280
11282
  ngOnInit() {
11281
11283
  this.isExpanded = this.expanded;
11284
+ this.applyInitialExpandedItemId();
11282
11285
  }
11283
11286
  ngOnChanges(changes) {
11284
11287
  if (changes['expanded']) {
11285
11288
  this.isExpanded = this.expanded;
11286
11289
  }
11290
+ if (changes['initialExpandedItemId'] || changes['items']) {
11291
+ this.applyInitialExpandedItemId();
11292
+ }
11293
+ }
11294
+ applyInitialExpandedItemId() {
11295
+ var _a;
11296
+ if (this.initialExpandedItemId == null || !((_a = this.items) === null || _a === void 0 ? void 0 : _a.length)) {
11297
+ return;
11298
+ }
11299
+ const match = this.items.find((item) => item.id == this.initialExpandedItemId);
11300
+ if (match) {
11301
+ this.expandedItemId = match.id;
11302
+ }
11287
11303
  }
11288
11304
  toggle() {
11289
11305
  this.isExpanded = !this.isExpanded;
@@ -11335,7 +11351,7 @@ class MainStepCollapseComponent {
11335
11351
  this.viewSteps.emit(item);
11336
11352
  }
11337
11353
  isItemExpanded(itemId) {
11338
- return this.expandedItemId === itemId;
11354
+ return this.expandedItemId == itemId;
11339
11355
  }
11340
11356
  getDisplayCount() {
11341
11357
  var _a;
@@ -11365,7 +11381,7 @@ class MainStepCollapseComponent {
11365
11381
  }
11366
11382
  }
11367
11383
  MainStepCollapseComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: MainStepCollapseComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11368
- MainStepCollapseComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: MainStepCollapseComponent, selector: "cqa-main-step-collapse", inputs: { title: "title", items: "items", expanded: "expanded", icon: "icon", count: "count", itemContentTemplate: "itemContentTemplate", headerButtons: "headerButtons", viewStepsAsRedirect: "viewStepsAsRedirect", getViewStepsUrl: "getViewStepsUrl", viewStepsOpenInNewTab: "viewStepsOpenInNewTab" }, outputs: { viewSteps: "viewSteps", headerButtonClick: "headerButtonClick", expandedChange: "expandedChange" }, host: { classAttribute: "cqa-ui-root" }, queries: [{ propertyName: "itemContentTpl", first: true, predicate: ["itemContent"], descendants: true, read: TemplateRef }], usesOnChanges: true, ngImport: i0, template: "<!-- Header -->\n<div\n class=\"cqa-mt-2 cqa-flex cqa-items-center cqa-justify-between cqa-gap-3 cqa-px-3 cqa-py-2 cqa-cursor-pointer cqa-bg-[#EEF2FF] cqa-rounded-[4px] cqa-border cqa-border-[#C6D2FF] cqa-border-solid\"\n (click)=\"toggle()\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-w-full\">\n <!-- Chevron Icon (Left) -->\n <!-- <svg [class.cqa-rotate-180]=\"isExpanded\" class=\"cqa-transition-transform\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 6L8 10L12 6\" stroke=\"#3F51B5\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg> -->\n <div><svg [class.cqa-rotate-180]=\"isExpanded\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 6L8 10L12 6\" stroke=\"#4F39F6\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg></div>\n\n <!-- Chain-Link Icon (if configured, otherwise default) -->\n <!-- <div *ngIf=\"icon && icon.type === 'folder'\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M11.6666 11.6667C11.976 11.6667 12.2728 11.5437 12.4916 11.325C12.7104 11.1062 12.8333 10.8094 12.8333 10.5V4.66667C12.8333 4.35725 12.7104 4.0605 12.4916 3.84171C12.2728 3.62292 11.976 3.5 11.6666 3.5H7.05829C6.86318 3.50191 6.67069 3.45486 6.49847 3.36314C6.32624 3.27142 6.17977 3.13797 6.07246 2.975L5.59996 2.275C5.49373 2.11369 5.34911 1.98128 5.17908 1.88965C5.00906 1.79802 4.81894 1.75003 4.62579 1.75H2.33329C2.02387 1.75 1.72713 1.87292 1.50833 2.09171C1.28954 2.3105 1.16663 2.60725 1.16663 2.91667V10.5C1.16663 10.8094 1.28954 11.1062 1.50833 11.325C1.72713 11.5437 2.02387 11.6667 2.33329 11.6667H11.6666Z\" fill=\"#EFF6FF\" stroke=\"#3F51B5\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n <div *ngIf=\"icon && icon.type === 'loop'\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect width=\"16\" height=\"16\" rx=\"4\" fill=\"#EBECFD\"/>\n <path d=\"M9.66663 4.66666L11 5.99999L9.66663 7.33332\" stroke=\"#3F51B5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M5 7.66667V7.33333C5 6.97971 5.14048 6.64057 5.39052 6.39052C5.64057 6.14048 5.97971 6 6.33333 6H11\" stroke=\"#3F51B5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.33333 11.3333L5 9.99999L6.33333 8.66666\" stroke=\"#3F51B5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M11 8.33334V8.66668C11 9.0203 10.8595 9.35944 10.6095 9.60949C10.3594 9.85953 10.0203 10 9.66667 10H5\" stroke=\"#3F51B5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div> -->\n <!-- Bar Icon (Bulleted List) -->\n <div *ngIf=\"icon && icon.type === 'bar'\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <!-- First bullet and line -->\n <circle cx=\"3\" cy=\"5\" r=\"2\" fill=\"#4F39F6\"/>\n <line x1=\"7\" y1=\"5\" x2=\"17\" y2=\"5\" stroke=\"#4F39F6\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n <!-- Second bullet and line -->\n <circle cx=\"3\" cy=\"10\" r=\"2\" fill=\"#4F39F6\"/>\n <line x1=\"7\" y1=\"10\" x2=\"17\" y2=\"10\" stroke=\"#4F39F6\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n <!-- Third bullet and line -->\n <circle cx=\"3\" cy=\"15\" r=\"2\" fill=\"#4F39F6\"/>\n <line x1=\"7\" y1=\"15\" x2=\"17\" y2=\"15\" stroke=\"#4F39F6\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n </svg>\n </div>\n\n <!-- Default Chain-Link Icon (when no icon or icon type is not specified) -->\n <div *ngIf=\"!icon || (icon.type !== 'bar' && icon.type !== 'folder' && icon.type !== 'loop' && icon.type !== 'custom')\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M7.50033 14.1663H5.83366C4.72859 14.1663 3.66878 13.7274 2.88738 12.946C2.10598 12.1646 1.66699 11.1047 1.66699 9.99967C1.66699 8.89461 2.10598 7.8348 2.88738 7.0534C3.66878 6.27199 4.72859 5.83301 5.83366 5.83301H7.50033\"\n stroke=\"#4F39F6\" stroke-width=\"1.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M12.5 5.83301H14.1667C15.2717 5.83301 16.3315 6.27199 17.1129 7.0534C17.8943 7.8348 18.3333 8.89461 18.3333 9.99967C18.3333 11.1047 17.8943 12.1646 17.1129 12.946C16.3315 13.7274 15.2717 14.1663 14.1667 14.1663H12.5\"\n stroke=\"#4F39F6\" stroke-width=\"1.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M6.66699 10H13.3337\" stroke=\"#4F39F6\" stroke-width=\"1.66667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </div>\n\n <!-- Custom Icon -->\n <div *ngIf=\"icon && icon.type === 'custom' && icon.svg\" [innerHTML]=\"icon.svg\"></div>\n\n <!-- Title -->\n <span class=\"cqa-font-semibold cqa-text-[14px] cqa-leading-[17px] cqa-text-[#312C85] cqa-flex-1\">\n {{ title }}\n </span>\n\n <!-- Badge and dynamic header buttons -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" (click)=\"$event.stopPropagation()\">\n <ng-container *ngFor=\"let btn of headerButtons; let i = index\">\n <cqa-button\n [text]=\"btn.text\"\n [icon]=\"btn.icon\"\n [variant]=\"btn.variant || 'outlined'\"\n [disabled]=\"btn.disabled\"\n [tooltip]=\"btn.tooltip\"\n [customClass]=\"btn.customClass\"\n [btnSize]=\"btn.btnSize || 'sm'\"\n (clicked)=\"onHeaderButtonClick(btn, i, $event)\">\n </cqa-button>\n </ng-container>\n <span\n class=\"cqa-px-2 cqa-py-[2px] cqa-rounded-[4px] cqa-bg-[#C6D2FF] cqa-text-[12px] cqa-leading-[16px] cqa-text-[#432DD7]\">\n {{ getDisplayCount() }}\n </span>\n </div>\n </div>\n</div>\n\n<!-- Expanded Content -->\n<div *ngIf=\"isExpanded\" class=\"cqa-mt-2 cqa-flex cqa-flex-col cqa-gap-2 cqa-px-2.5\">\n <!-- When there are no items, display ng-content directly -->\n <ng-container *ngIf=\"!items || items.length === 0\">\n <ng-content></ng-content>\n </ng-container>\n\n <!-- When items exist, display them -->\n <div *ngFor=\"let item of items\">\n\n <!-- Item Header -->\n <div class=\"cqa-bg-white cqa-border cqa-border-solid cqa-border-[#E5E5E5] cqa-rounded-md cqa-overflow-hidden\">\n <div class=\"cqa-py-2 cqa-px-3 cqa-flex cqa-items-center cqa-justify-between cqa-gap-3\">\n <!-- Left side: Status and Title -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-flex-1\">\n <!-- Status Icon (Filled Green Circle with Checkmark) -->\n <div>\n <!-- Success -->\n <svg *ngIf=\"item.status === 'success'\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <g clip-path=\"url(#clip0_48_121)\">\n <path\n d=\"M10.0003 18.3337C14.6027 18.3337 18.3337 14.6027 18.3337 10.0003C18.3337 5.39795 14.6027 1.66699 10.0003 1.66699C5.39795 1.66699 1.66699 5.39795 1.66699 10.0003C1.66699 14.6027 5.39795 18.3337 10.0003 18.3337Z\"\n stroke=\"#00A63E\" stroke-width=\"1.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M7.5 9.99967L9.16667 11.6663L12.5 8.33301\" stroke=\"#00A63E\" stroke-width=\"1.66667\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </g>\n <defs>\n <clipPath id=\"clip0_48_121\">\n <rect width=\"20\" height=\"20\" fill=\"white\" />\n </clipPath>\n </defs>\n </svg>\n <!-- Failed -->\n <svg *ngIf=\"item.status === 'failed'\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"10\" cy=\"10\" r=\"8\" fill=\"#EF4444\" />\n <path d=\"M7 7L13 13M13 7L7 13\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n <!-- Pending -->\n <svg *ngIf=\"item.status === 'pending'\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"10\" cy=\"10\" r=\"8\" fill=\"#9CA3AF\" />\n <path d=\"M10 6V10L13 12\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n <!-- Running -->\n <svg *ngIf=\"item.status === 'running'\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"10\" cy=\"10\" r=\"8\" fill=\"#3B82F6\" />\n <path d=\"M10 6V10L13 12\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </div>\n \n <!-- Title -->\n <span class=\"cqa-text-[14px] cqa-leading-[18px]\" style=\"word-break: break-word;\">\n {{ item.title }}\n </span>\n </div>\n \n <!-- Right side: Duration and View Steps Link -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-3\">\n <!-- Duration with Clock Icon -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M6 11C8.76142 11 11 8.76142 11 6C11 3.23858 8.76142 1 6 1C3.23858 1 1 3.23858 1 6C1 8.76142 3.23858 11 6 11Z\"\n stroke=\"#6A7282\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M6 3V6L8 7\" stroke=\"#6A7282\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n <span class=\"cqa-text-[14px] cqa-leading-[20px] cqa-text-[#6A7282]\">\n {{ formatDuration(item.duration) }}\n </span>\n </div>\n \n <!-- View Steps Link: redirect mode (navigates to URL) or inline mode (toggle expand) -->\n <a *ngIf=\"hasViewStepsRedirectUrl(item)\"\n [href]=\"getItemViewStepsUrl(item)\"\n [attr.target]=\"viewStepsOpenInNewTab ? '_blank' : null\"\n [attr.rel]=\"viewStepsOpenInNewTab ? 'noopener noreferrer' : null\"\n class=\"cqa-text-[12px] cqa-leading-[15px] cqa-font-semibold cqa-text-[#3F43EE] cqa-no-underline cqa-flex cqa-items-center cqa-gap-1 hover:cqa-underline\">\n <span>View steps</span>\n <svg class=\"cqa-transition-transform\" width=\"16\" height=\"15\"\n viewBox=\"0 0 16 15\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M8.6552 12.8184L7.55413 11.7668L10.852 8.5864H2.83984V7.05032H10.852L7.55413 3.87506L8.6552 2.81836L13.8398 7.81836L8.6552 12.8184Z\"\n fill=\"#3F43EE\" />\n </svg>\n </a>\n <a *ngIf=\"!hasViewStepsRedirectUrl(item)\" href=\"#\" (click)=\"onViewSteps(item, $event)\"\n class=\"cqa-text-[12px] cqa-leading-[15px] cqa-font-semibold cqa-text-[#3F43EE] cqa-no-underline cqa-flex cqa-items-center cqa-gap-1 hover:cqa-underline\">\n <span>{{ isItemExpanded(item.id) ? 'Hide steps' : 'View steps' }}</span>\n <svg [class.cqa-rotate-90]=\"isItemExpanded(item.id)\" class=\"cqa-transition-transform\" width=\"16\" height=\"15\"\n viewBox=\"0 0 16 15\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M8.6552 12.8184L7.55413 11.7668L10.852 8.5864H2.83984V7.05032H10.852L7.55413 3.87506L8.6552 2.81836L13.8398 7.81836L8.6552 12.8184Z\"\n fill=\"#3F43EE\" />\n </svg>\n </a>\n </div>\n </div>\n </div>\n\n <!-- Steps Content (shown when item is expanded) -->\n <div *ngIf=\"isItemExpanded(item.id)\">\n <!-- Custom template via TemplateRef (from @ContentChild or @Input) - passes item as context -->\n <ng-container *ngIf=\"itemContentTpl || itemContentTemplate\">\n <div class=\"cqa-p-3\">\n <ng-container\n *ngTemplateOutlet=\"(itemContentTpl || itemContentTemplate)!; context: { $implicit: item, item: item }\"></ng-container>\n </div>\n </ng-container>\n\n <!-- Custom content projection via ng-content - displayed for all expanded items -->\n <ng-content select=\"[itemContent]\"></ng-content>\n </div>\n </div>\n</div>\n\n<!-- Custom content projection after all items - for steps loaded after API call -->\n<ng-content select=\"[afterItems]\"></ng-content>", components: [{ type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }] });
11384
+ MainStepCollapseComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: MainStepCollapseComponent, selector: "cqa-main-step-collapse", inputs: { title: "title", items: "items", expanded: "expanded", icon: "icon", count: "count", itemContentTemplate: "itemContentTemplate", headerButtons: "headerButtons", viewStepsAsRedirect: "viewStepsAsRedirect", getViewStepsUrl: "getViewStepsUrl", viewStepsOpenInNewTab: "viewStepsOpenInNewTab", initialExpandedItemId: "initialExpandedItemId" }, outputs: { viewSteps: "viewSteps", headerButtonClick: "headerButtonClick", expandedChange: "expandedChange" }, host: { classAttribute: "cqa-ui-root" }, queries: [{ propertyName: "itemContentTpl", first: true, predicate: ["itemContent"], descendants: true, read: TemplateRef }], usesOnChanges: true, ngImport: i0, template: "<!-- Header -->\n<div\n class=\"cqa-mt-2 cqa-flex cqa-items-center cqa-justify-between cqa-gap-3 cqa-px-3 cqa-py-2 cqa-cursor-pointer cqa-bg-[#EEF2FF] cqa-rounded-[4px] cqa-border cqa-border-[#C6D2FF] cqa-border-solid\"\n (click)=\"toggle()\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-w-full\">\n <!-- Chevron Icon (Left) -->\n <!-- <svg [class.cqa-rotate-180]=\"isExpanded\" class=\"cqa-transition-transform\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 6L8 10L12 6\" stroke=\"#3F51B5\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg> -->\n <div><svg [class.cqa-rotate-180]=\"isExpanded\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 6L8 10L12 6\" stroke=\"#4F39F6\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg></div>\n\n <!-- Chain-Link Icon (if configured, otherwise default) -->\n <!-- <div *ngIf=\"icon && icon.type === 'folder'\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M11.6666 11.6667C11.976 11.6667 12.2728 11.5437 12.4916 11.325C12.7104 11.1062 12.8333 10.8094 12.8333 10.5V4.66667C12.8333 4.35725 12.7104 4.0605 12.4916 3.84171C12.2728 3.62292 11.976 3.5 11.6666 3.5H7.05829C6.86318 3.50191 6.67069 3.45486 6.49847 3.36314C6.32624 3.27142 6.17977 3.13797 6.07246 2.975L5.59996 2.275C5.49373 2.11369 5.34911 1.98128 5.17908 1.88965C5.00906 1.79802 4.81894 1.75003 4.62579 1.75H2.33329C2.02387 1.75 1.72713 1.87292 1.50833 2.09171C1.28954 2.3105 1.16663 2.60725 1.16663 2.91667V10.5C1.16663 10.8094 1.28954 11.1062 1.50833 11.325C1.72713 11.5437 2.02387 11.6667 2.33329 11.6667H11.6666Z\" fill=\"#EFF6FF\" stroke=\"#3F51B5\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n <div *ngIf=\"icon && icon.type === 'loop'\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect width=\"16\" height=\"16\" rx=\"4\" fill=\"#EBECFD\"/>\n <path d=\"M9.66663 4.66666L11 5.99999L9.66663 7.33332\" stroke=\"#3F51B5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M5 7.66667V7.33333C5 6.97971 5.14048 6.64057 5.39052 6.39052C5.64057 6.14048 5.97971 6 6.33333 6H11\" stroke=\"#3F51B5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.33333 11.3333L5 9.99999L6.33333 8.66666\" stroke=\"#3F51B5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M11 8.33334V8.66668C11 9.0203 10.8595 9.35944 10.6095 9.60949C10.3594 9.85953 10.0203 10 9.66667 10H5\" stroke=\"#3F51B5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div> -->\n <!-- Bar Icon (Bulleted List) -->\n <div *ngIf=\"icon && icon.type === 'bar'\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <!-- First bullet and line -->\n <circle cx=\"3\" cy=\"5\" r=\"2\" fill=\"#4F39F6\"/>\n <line x1=\"7\" y1=\"5\" x2=\"17\" y2=\"5\" stroke=\"#4F39F6\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n <!-- Second bullet and line -->\n <circle cx=\"3\" cy=\"10\" r=\"2\" fill=\"#4F39F6\"/>\n <line x1=\"7\" y1=\"10\" x2=\"17\" y2=\"10\" stroke=\"#4F39F6\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n <!-- Third bullet and line -->\n <circle cx=\"3\" cy=\"15\" r=\"2\" fill=\"#4F39F6\"/>\n <line x1=\"7\" y1=\"15\" x2=\"17\" y2=\"15\" stroke=\"#4F39F6\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n </svg>\n </div>\n\n <!-- Default Chain-Link Icon (when no icon or icon type is not specified) -->\n <div *ngIf=\"!icon || (icon.type !== 'bar' && icon.type !== 'folder' && icon.type !== 'loop' && icon.type !== 'custom')\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M7.50033 14.1663H5.83366C4.72859 14.1663 3.66878 13.7274 2.88738 12.946C2.10598 12.1646 1.66699 11.1047 1.66699 9.99967C1.66699 8.89461 2.10598 7.8348 2.88738 7.0534C3.66878 6.27199 4.72859 5.83301 5.83366 5.83301H7.50033\"\n stroke=\"#4F39F6\" stroke-width=\"1.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M12.5 5.83301H14.1667C15.2717 5.83301 16.3315 6.27199 17.1129 7.0534C17.8943 7.8348 18.3333 8.89461 18.3333 9.99967C18.3333 11.1047 17.8943 12.1646 17.1129 12.946C16.3315 13.7274 15.2717 14.1663 14.1667 14.1663H12.5\"\n stroke=\"#4F39F6\" stroke-width=\"1.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M6.66699 10H13.3337\" stroke=\"#4F39F6\" stroke-width=\"1.66667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </div>\n\n <!-- Custom Icon -->\n <div *ngIf=\"icon && icon.type === 'custom' && icon.svg\" [innerHTML]=\"icon.svg\"></div>\n\n <!-- Title -->\n <span class=\"cqa-font-semibold cqa-text-[14px] cqa-leading-[17px] cqa-text-[#312C85] cqa-flex-1\">\n {{ title }}\n </span>\n\n <!-- Badge and dynamic header buttons -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" (click)=\"$event.stopPropagation()\">\n <ng-container *ngFor=\"let btn of headerButtons; let i = index\">\n <cqa-button\n [text]=\"btn.text\"\n [icon]=\"btn.icon\"\n [variant]=\"btn.variant || 'outlined'\"\n [disabled]=\"btn.disabled\"\n [tooltip]=\"btn.tooltip\"\n [customClass]=\"btn.customClass\"\n [btnSize]=\"btn.btnSize || 'sm'\"\n (clicked)=\"onHeaderButtonClick(btn, i, $event)\">\n </cqa-button>\n </ng-container>\n <span\n class=\"cqa-px-2 cqa-py-[2px] cqa-rounded-[4px] cqa-bg-[#C6D2FF] cqa-text-[12px] cqa-leading-[16px] cqa-text-[#432DD7]\">\n {{ getDisplayCount() }}\n </span>\n </div>\n </div>\n</div>\n\n<!-- Expanded Content -->\n<div *ngIf=\"isExpanded\" class=\"cqa-mt-2 cqa-flex cqa-flex-col cqa-gap-2 cqa-px-2.5\">\n <!-- When there are no items, display ng-content directly -->\n <ng-container *ngIf=\"!items || items.length === 0\">\n <ng-content></ng-content>\n </ng-container>\n\n <!-- When items exist, display them -->\n <div *ngFor=\"let item of items\">\n\n <!-- Item Header -->\n <div class=\"cqa-bg-white cqa-border cqa-border-solid cqa-border-[#E5E5E5] cqa-rounded-md cqa-overflow-hidden\">\n <div class=\"cqa-py-2 cqa-px-3 cqa-flex cqa-items-center cqa-justify-between cqa-gap-3\">\n <!-- Left side: Status and Title -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-flex-1\">\n <!-- Status Icon (Filled Green Circle with Checkmark) -->\n <div>\n <!-- Success -->\n <svg *ngIf=\"item.status === 'success'\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <g clip-path=\"url(#clip0_48_121)\">\n <path\n d=\"M10.0003 18.3337C14.6027 18.3337 18.3337 14.6027 18.3337 10.0003C18.3337 5.39795 14.6027 1.66699 10.0003 1.66699C5.39795 1.66699 1.66699 5.39795 1.66699 10.0003C1.66699 14.6027 5.39795 18.3337 10.0003 18.3337Z\"\n stroke=\"#00A63E\" stroke-width=\"1.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M7.5 9.99967L9.16667 11.6663L12.5 8.33301\" stroke=\"#00A63E\" stroke-width=\"1.66667\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </g>\n <defs>\n <clipPath id=\"clip0_48_121\">\n <rect width=\"20\" height=\"20\" fill=\"white\" />\n </clipPath>\n </defs>\n </svg>\n <!-- Failed -->\n <svg *ngIf=\"item.status === 'failed'\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"10\" cy=\"10\" r=\"8\" fill=\"#EF4444\" />\n <path d=\"M7 7L13 13M13 7L7 13\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n <!-- Pending -->\n <svg *ngIf=\"item.status === 'pending'\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"10\" cy=\"10\" r=\"8\" fill=\"#9CA3AF\" />\n <path d=\"M10 6V10L13 12\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n <!-- Running -->\n <svg *ngIf=\"item.status === 'running'\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"10\" cy=\"10\" r=\"8\" fill=\"#3B82F6\" />\n <path d=\"M10 6V10L13 12\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </div>\n \n <!-- Title -->\n <span class=\"cqa-text-[14px] cqa-leading-[18px]\" style=\"word-break: break-word;\">\n {{ item.title }}\n </span>\n </div>\n \n <!-- Right side: Duration and View Steps Link -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-3\">\n <!-- Duration with Clock Icon -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M6 11C8.76142 11 11 8.76142 11 6C11 3.23858 8.76142 1 6 1C3.23858 1 1 3.23858 1 6C1 8.76142 3.23858 11 6 11Z\"\n stroke=\"#6A7282\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M6 3V6L8 7\" stroke=\"#6A7282\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n <span class=\"cqa-text-[14px] cqa-leading-[20px] cqa-text-[#6A7282]\">\n {{ formatDuration(item.duration) }}\n </span>\n </div>\n \n <!-- View Steps Link: redirect mode (navigates to URL) or inline mode (toggle expand) -->\n <a *ngIf=\"hasViewStepsRedirectUrl(item)\"\n [href]=\"getItemViewStepsUrl(item)\"\n [attr.target]=\"viewStepsOpenInNewTab ? '_blank' : null\"\n [attr.rel]=\"viewStepsOpenInNewTab ? 'noopener noreferrer' : null\"\n class=\"cqa-text-[12px] cqa-leading-[15px] cqa-font-semibold cqa-text-[#3F43EE] cqa-no-underline cqa-flex cqa-items-center cqa-gap-1 hover:cqa-underline\">\n <span>View steps</span>\n <svg class=\"cqa-transition-transform\" width=\"16\" height=\"15\"\n viewBox=\"0 0 16 15\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M8.6552 12.8184L7.55413 11.7668L10.852 8.5864H2.83984V7.05032H10.852L7.55413 3.87506L8.6552 2.81836L13.8398 7.81836L8.6552 12.8184Z\"\n fill=\"#3F43EE\" />\n </svg>\n </a>\n <a *ngIf=\"!hasViewStepsRedirectUrl(item)\" href=\"#\" (click)=\"onViewSteps(item, $event)\"\n class=\"cqa-text-[12px] cqa-leading-[15px] cqa-font-semibold cqa-text-[#3F43EE] cqa-no-underline cqa-flex cqa-items-center cqa-gap-1 hover:cqa-underline\">\n <span>{{ isItemExpanded(item.id) ? 'Hide steps' : 'View steps' }}</span>\n <svg [class.cqa-rotate-90]=\"isItemExpanded(item.id)\" class=\"cqa-transition-transform\" width=\"16\" height=\"15\"\n viewBox=\"0 0 16 15\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M8.6552 12.8184L7.55413 11.7668L10.852 8.5864H2.83984V7.05032H10.852L7.55413 3.87506L8.6552 2.81836L13.8398 7.81836L8.6552 12.8184Z\"\n fill=\"#3F43EE\" />\n </svg>\n </a>\n </div>\n </div>\n </div>\n\n <!-- Steps Content (shown when item is expanded) -->\n <div *ngIf=\"isItemExpanded(item.id)\">\n <!-- Custom template via TemplateRef (from @ContentChild or @Input) - passes item as context -->\n <ng-container *ngIf=\"itemContentTpl || itemContentTemplate\">\n <div class=\"cqa-p-3\">\n <ng-container\n *ngTemplateOutlet=\"(itemContentTpl || itemContentTemplate)!; context: { $implicit: item, item: item }\"></ng-container>\n </div>\n </ng-container>\n\n <!-- Custom content projection via ng-content - displayed for all expanded items -->\n <ng-content select=\"[itemContent]\"></ng-content>\n </div>\n </div>\n</div>\n\n<!-- Custom content projection after all items - for steps loaded after API call -->\n<ng-content select=\"[afterItems]\"></ng-content>", components: [{ type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }] });
11369
11385
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: MainStepCollapseComponent, decorators: [{
11370
11386
  type: Component,
11371
11387
  args: [{ selector: 'cqa-main-step-collapse', host: { class: 'cqa-ui-root' }, template: "<!-- Header -->\n<div\n class=\"cqa-mt-2 cqa-flex cqa-items-center cqa-justify-between cqa-gap-3 cqa-px-3 cqa-py-2 cqa-cursor-pointer cqa-bg-[#EEF2FF] cqa-rounded-[4px] cqa-border cqa-border-[#C6D2FF] cqa-border-solid\"\n (click)=\"toggle()\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-w-full\">\n <!-- Chevron Icon (Left) -->\n <!-- <svg [class.cqa-rotate-180]=\"isExpanded\" class=\"cqa-transition-transform\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 6L8 10L12 6\" stroke=\"#3F51B5\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg> -->\n <div><svg [class.cqa-rotate-180]=\"isExpanded\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 6L8 10L12 6\" stroke=\"#4F39F6\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg></div>\n\n <!-- Chain-Link Icon (if configured, otherwise default) -->\n <!-- <div *ngIf=\"icon && icon.type === 'folder'\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M11.6666 11.6667C11.976 11.6667 12.2728 11.5437 12.4916 11.325C12.7104 11.1062 12.8333 10.8094 12.8333 10.5V4.66667C12.8333 4.35725 12.7104 4.0605 12.4916 3.84171C12.2728 3.62292 11.976 3.5 11.6666 3.5H7.05829C6.86318 3.50191 6.67069 3.45486 6.49847 3.36314C6.32624 3.27142 6.17977 3.13797 6.07246 2.975L5.59996 2.275C5.49373 2.11369 5.34911 1.98128 5.17908 1.88965C5.00906 1.79802 4.81894 1.75003 4.62579 1.75H2.33329C2.02387 1.75 1.72713 1.87292 1.50833 2.09171C1.28954 2.3105 1.16663 2.60725 1.16663 2.91667V10.5C1.16663 10.8094 1.28954 11.1062 1.50833 11.325C1.72713 11.5437 2.02387 11.6667 2.33329 11.6667H11.6666Z\" fill=\"#EFF6FF\" stroke=\"#3F51B5\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n <div *ngIf=\"icon && icon.type === 'loop'\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect width=\"16\" height=\"16\" rx=\"4\" fill=\"#EBECFD\"/>\n <path d=\"M9.66663 4.66666L11 5.99999L9.66663 7.33332\" stroke=\"#3F51B5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M5 7.66667V7.33333C5 6.97971 5.14048 6.64057 5.39052 6.39052C5.64057 6.14048 5.97971 6 6.33333 6H11\" stroke=\"#3F51B5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.33333 11.3333L5 9.99999L6.33333 8.66666\" stroke=\"#3F51B5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M11 8.33334V8.66668C11 9.0203 10.8595 9.35944 10.6095 9.60949C10.3594 9.85953 10.0203 10 9.66667 10H5\" stroke=\"#3F51B5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div> -->\n <!-- Bar Icon (Bulleted List) -->\n <div *ngIf=\"icon && icon.type === 'bar'\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <!-- First bullet and line -->\n <circle cx=\"3\" cy=\"5\" r=\"2\" fill=\"#4F39F6\"/>\n <line x1=\"7\" y1=\"5\" x2=\"17\" y2=\"5\" stroke=\"#4F39F6\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n <!-- Second bullet and line -->\n <circle cx=\"3\" cy=\"10\" r=\"2\" fill=\"#4F39F6\"/>\n <line x1=\"7\" y1=\"10\" x2=\"17\" y2=\"10\" stroke=\"#4F39F6\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n <!-- Third bullet and line -->\n <circle cx=\"3\" cy=\"15\" r=\"2\" fill=\"#4F39F6\"/>\n <line x1=\"7\" y1=\"15\" x2=\"17\" y2=\"15\" stroke=\"#4F39F6\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n </svg>\n </div>\n\n <!-- Default Chain-Link Icon (when no icon or icon type is not specified) -->\n <div *ngIf=\"!icon || (icon.type !== 'bar' && icon.type !== 'folder' && icon.type !== 'loop' && icon.type !== 'custom')\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M7.50033 14.1663H5.83366C4.72859 14.1663 3.66878 13.7274 2.88738 12.946C2.10598 12.1646 1.66699 11.1047 1.66699 9.99967C1.66699 8.89461 2.10598 7.8348 2.88738 7.0534C3.66878 6.27199 4.72859 5.83301 5.83366 5.83301H7.50033\"\n stroke=\"#4F39F6\" stroke-width=\"1.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M12.5 5.83301H14.1667C15.2717 5.83301 16.3315 6.27199 17.1129 7.0534C17.8943 7.8348 18.3333 8.89461 18.3333 9.99967C18.3333 11.1047 17.8943 12.1646 17.1129 12.946C16.3315 13.7274 15.2717 14.1663 14.1667 14.1663H12.5\"\n stroke=\"#4F39F6\" stroke-width=\"1.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M6.66699 10H13.3337\" stroke=\"#4F39F6\" stroke-width=\"1.66667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </div>\n\n <!-- Custom Icon -->\n <div *ngIf=\"icon && icon.type === 'custom' && icon.svg\" [innerHTML]=\"icon.svg\"></div>\n\n <!-- Title -->\n <span class=\"cqa-font-semibold cqa-text-[14px] cqa-leading-[17px] cqa-text-[#312C85] cqa-flex-1\">\n {{ title }}\n </span>\n\n <!-- Badge and dynamic header buttons -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" (click)=\"$event.stopPropagation()\">\n <ng-container *ngFor=\"let btn of headerButtons; let i = index\">\n <cqa-button\n [text]=\"btn.text\"\n [icon]=\"btn.icon\"\n [variant]=\"btn.variant || 'outlined'\"\n [disabled]=\"btn.disabled\"\n [tooltip]=\"btn.tooltip\"\n [customClass]=\"btn.customClass\"\n [btnSize]=\"btn.btnSize || 'sm'\"\n (clicked)=\"onHeaderButtonClick(btn, i, $event)\">\n </cqa-button>\n </ng-container>\n <span\n class=\"cqa-px-2 cqa-py-[2px] cqa-rounded-[4px] cqa-bg-[#C6D2FF] cqa-text-[12px] cqa-leading-[16px] cqa-text-[#432DD7]\">\n {{ getDisplayCount() }}\n </span>\n </div>\n </div>\n</div>\n\n<!-- Expanded Content -->\n<div *ngIf=\"isExpanded\" class=\"cqa-mt-2 cqa-flex cqa-flex-col cqa-gap-2 cqa-px-2.5\">\n <!-- When there are no items, display ng-content directly -->\n <ng-container *ngIf=\"!items || items.length === 0\">\n <ng-content></ng-content>\n </ng-container>\n\n <!-- When items exist, display them -->\n <div *ngFor=\"let item of items\">\n\n <!-- Item Header -->\n <div class=\"cqa-bg-white cqa-border cqa-border-solid cqa-border-[#E5E5E5] cqa-rounded-md cqa-overflow-hidden\">\n <div class=\"cqa-py-2 cqa-px-3 cqa-flex cqa-items-center cqa-justify-between cqa-gap-3\">\n <!-- Left side: Status and Title -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-flex-1\">\n <!-- Status Icon (Filled Green Circle with Checkmark) -->\n <div>\n <!-- Success -->\n <svg *ngIf=\"item.status === 'success'\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <g clip-path=\"url(#clip0_48_121)\">\n <path\n d=\"M10.0003 18.3337C14.6027 18.3337 18.3337 14.6027 18.3337 10.0003C18.3337 5.39795 14.6027 1.66699 10.0003 1.66699C5.39795 1.66699 1.66699 5.39795 1.66699 10.0003C1.66699 14.6027 5.39795 18.3337 10.0003 18.3337Z\"\n stroke=\"#00A63E\" stroke-width=\"1.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M7.5 9.99967L9.16667 11.6663L12.5 8.33301\" stroke=\"#00A63E\" stroke-width=\"1.66667\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </g>\n <defs>\n <clipPath id=\"clip0_48_121\">\n <rect width=\"20\" height=\"20\" fill=\"white\" />\n </clipPath>\n </defs>\n </svg>\n <!-- Failed -->\n <svg *ngIf=\"item.status === 'failed'\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"10\" cy=\"10\" r=\"8\" fill=\"#EF4444\" />\n <path d=\"M7 7L13 13M13 7L7 13\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n <!-- Pending -->\n <svg *ngIf=\"item.status === 'pending'\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"10\" cy=\"10\" r=\"8\" fill=\"#9CA3AF\" />\n <path d=\"M10 6V10L13 12\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n <!-- Running -->\n <svg *ngIf=\"item.status === 'running'\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"10\" cy=\"10\" r=\"8\" fill=\"#3B82F6\" />\n <path d=\"M10 6V10L13 12\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </div>\n \n <!-- Title -->\n <span class=\"cqa-text-[14px] cqa-leading-[18px]\" style=\"word-break: break-word;\">\n {{ item.title }}\n </span>\n </div>\n \n <!-- Right side: Duration and View Steps Link -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-3\">\n <!-- Duration with Clock Icon -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M6 11C8.76142 11 11 8.76142 11 6C11 3.23858 8.76142 1 6 1C3.23858 1 1 3.23858 1 6C1 8.76142 3.23858 11 6 11Z\"\n stroke=\"#6A7282\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M6 3V6L8 7\" stroke=\"#6A7282\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n <span class=\"cqa-text-[14px] cqa-leading-[20px] cqa-text-[#6A7282]\">\n {{ formatDuration(item.duration) }}\n </span>\n </div>\n \n <!-- View Steps Link: redirect mode (navigates to URL) or inline mode (toggle expand) -->\n <a *ngIf=\"hasViewStepsRedirectUrl(item)\"\n [href]=\"getItemViewStepsUrl(item)\"\n [attr.target]=\"viewStepsOpenInNewTab ? '_blank' : null\"\n [attr.rel]=\"viewStepsOpenInNewTab ? 'noopener noreferrer' : null\"\n class=\"cqa-text-[12px] cqa-leading-[15px] cqa-font-semibold cqa-text-[#3F43EE] cqa-no-underline cqa-flex cqa-items-center cqa-gap-1 hover:cqa-underline\">\n <span>View steps</span>\n <svg class=\"cqa-transition-transform\" width=\"16\" height=\"15\"\n viewBox=\"0 0 16 15\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M8.6552 12.8184L7.55413 11.7668L10.852 8.5864H2.83984V7.05032H10.852L7.55413 3.87506L8.6552 2.81836L13.8398 7.81836L8.6552 12.8184Z\"\n fill=\"#3F43EE\" />\n </svg>\n </a>\n <a *ngIf=\"!hasViewStepsRedirectUrl(item)\" href=\"#\" (click)=\"onViewSteps(item, $event)\"\n class=\"cqa-text-[12px] cqa-leading-[15px] cqa-font-semibold cqa-text-[#3F43EE] cqa-no-underline cqa-flex cqa-items-center cqa-gap-1 hover:cqa-underline\">\n <span>{{ isItemExpanded(item.id) ? 'Hide steps' : 'View steps' }}</span>\n <svg [class.cqa-rotate-90]=\"isItemExpanded(item.id)\" class=\"cqa-transition-transform\" width=\"16\" height=\"15\"\n viewBox=\"0 0 16 15\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M8.6552 12.8184L7.55413 11.7668L10.852 8.5864H2.83984V7.05032H10.852L7.55413 3.87506L8.6552 2.81836L13.8398 7.81836L8.6552 12.8184Z\"\n fill=\"#3F43EE\" />\n </svg>\n </a>\n </div>\n </div>\n </div>\n\n <!-- Steps Content (shown when item is expanded) -->\n <div *ngIf=\"isItemExpanded(item.id)\">\n <!-- Custom template via TemplateRef (from @ContentChild or @Input) - passes item as context -->\n <ng-container *ngIf=\"itemContentTpl || itemContentTemplate\">\n <div class=\"cqa-p-3\">\n <ng-container\n *ngTemplateOutlet=\"(itemContentTpl || itemContentTemplate)!; context: { $implicit: item, item: item }\"></ng-container>\n </div>\n </ng-container>\n\n <!-- Custom content projection via ng-content - displayed for all expanded items -->\n <ng-content select=\"[itemContent]\"></ng-content>\n </div>\n </div>\n</div>\n\n<!-- Custom content projection after all items - for steps loaded after API call -->\n<ng-content select=\"[afterItems]\"></ng-content>", styles: [] }]
@@ -11389,6 +11405,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
11389
11405
  type: Input
11390
11406
  }], viewStepsOpenInNewTab: [{
11391
11407
  type: Input
11408
+ }], initialExpandedItemId: [{
11409
+ type: Input
11392
11410
  }], itemContentTpl: [{
11393
11411
  type: ContentChild,
11394
11412
  args: ['itemContent', { read: TemplateRef }]
@@ -11459,7 +11477,6 @@ class SimulatorComponent {
11459
11477
  this.speedControlClickOutsideHandler = null;
11460
11478
  this.preloadVideoElement = null;
11461
11479
  this.preloadAllVideoElement = null;
11462
- this.targetGlobalTimeDuringSwitch = null;
11463
11480
  this.traceViewerLoading = false;
11464
11481
  this.traceViewerError = false;
11465
11482
  this.isCorrectDeviceFrameAvailable = false;
@@ -11593,6 +11610,9 @@ class SimulatorComponent {
11593
11610
  get isPlayerSwitching() {
11594
11611
  return this.playerState === 'switching';
11595
11612
  }
11613
+ get shouldApplySmallHeightClasses() {
11614
+ return typeof window !== 'undefined' && window.innerHeight < 600 && this.platformType === 'browser' && this.isLive;
11615
+ }
11596
11616
  get effectiveBrowserViewPort() {
11597
11617
  const defaultViewport = { width: 1280, height: 720 };
11598
11618
  if (!this.browserViewPort) {
@@ -11740,52 +11760,12 @@ class SimulatorComponent {
11740
11760
  return;
11741
11761
  this.enqueueOperation(() => this.seekToTimeInternal(milliseconds));
11742
11762
  }
11743
- /**
11744
- * Seek to a global time on the combined timeline (converts to segment + local time)
11745
- */
11746
- seekToGlobalTime(globalTimeMs) {
11747
- return __awaiter(this, void 0, void 0, function* () {
11748
- const total = this.totalDuration;
11749
- if (total <= 0)
11750
- return;
11751
- const clampedGlobal = Math.max(0, Math.min(globalTimeMs, total));
11752
- const boundaries = this.segmentBoundaries;
11753
- let segmentIndex = 0;
11754
- let segmentStart = 0;
11755
- for (let i = 0; i < boundaries.length; i++) {
11756
- if (clampedGlobal < boundaries[i]) {
11757
- segmentIndex = i;
11758
- segmentStart = i === 0 ? 0 : boundaries[i - 1];
11759
- break;
11760
- }
11761
- segmentIndex = i;
11762
- segmentStart = i === 0 ? 0 : boundaries[i - 1];
11763
- }
11764
- if (boundaries.length > 0 && clampedGlobal >= boundaries[boundaries.length - 1]) {
11765
- segmentIndex = boundaries.length - 1;
11766
- segmentStart = segmentIndex === 0 ? 0 : boundaries[segmentIndex - 1];
11767
- }
11768
- const localTimeMs = clampedGlobal - segmentStart;
11769
- if (this.currentVideoIndex === segmentIndex) {
11770
- yield this.seekToTimeInternal(localTimeMs);
11771
- // Update progress after seek in same segment
11772
- if (this.totalDuration > 0) {
11773
- this.progress = Math.min(100, Math.max(0, (this.globalCurrentTime / this.totalDuration) * 100));
11774
- }
11775
- }
11776
- else {
11777
- const cumulativeTimestamp = segmentStart + localTimeMs;
11778
- yield this.switchToVideoAndSeekInternal(cumulativeTimestamp);
11779
- // Progress is already updated inside switchToVideoAndSeekInternal
11780
- }
11781
- });
11782
- }
11783
11763
  /**
11784
11764
  * Seek video internal implementation (no enqueue - called from queue)
11785
11765
  * This prevents pipeline read errors during rapid seek operations
11786
11766
  */
11787
11767
  seekToTimeInternal(milliseconds) {
11788
- var _a;
11768
+ var _a, _b;
11789
11769
  return __awaiter(this, void 0, void 0, function* () {
11790
11770
  const video = (_a = this.vplayer) === null || _a === void 0 ? void 0 : _a.nativeElement;
11791
11771
  if (!video || !video.duration)
@@ -11812,11 +11792,13 @@ class SimulatorComponent {
11812
11792
  this.lastSetDuration = milliseconds;
11813
11793
  // Wait briefly for seek to complete (prevents rapid seek issues)
11814
11794
  yield new Promise(resolve => setTimeout(resolve, 50));
11815
- const total = this.totalDuration;
11816
- if (total > 0) {
11817
- this.progress = Math.min(100, Math.max(0, (this.globalCurrentTime / total) * 100));
11795
+ // Per-video progress (0-100% of current video)
11796
+ const durationMs = video.duration * 1000;
11797
+ if (durationMs > 0) {
11798
+ this.progress = Math.min(100, Math.max(0, (video.currentTime * 1000 / durationMs) * 100));
11818
11799
  }
11819
- this.videoTimeUpdate.emit(this.globalCurrentTime);
11800
+ const segmentStart = this.currentVideoIndex === 0 ? 0 : ((_b = this.segmentBoundaries[this.currentVideoIndex - 1]) !== null && _b !== void 0 ? _b : 0);
11801
+ this.videoTimeUpdate.emit(segmentStart + video.currentTime * 1000);
11820
11802
  // Set to paused state (user must explicitly play)
11821
11803
  this.playerState = 'paused';
11822
11804
  console.log('[Simulator] seekToTimeInternal: seek complete', {
@@ -11902,7 +11884,7 @@ class SimulatorComponent {
11902
11884
  * This eliminates FFmpegDemuxer errors and play promise interruptions
11903
11885
  */
11904
11886
  playVideoInternal() {
11905
- var _a, _b, _c, _d, _e;
11887
+ var _a, _b, _c, _d;
11906
11888
  return __awaiter(this, void 0, void 0, function* () {
11907
11889
  const video = (_a = this.vplayer) === null || _a === void 0 ? void 0 : _a.nativeElement;
11908
11890
  if (!video) {
@@ -11914,91 +11896,6 @@ class SimulatorComponent {
11914
11896
  console.log('[Simulator] playVideoInternal: already playing, skipping');
11915
11897
  return;
11916
11898
  }
11917
- if (this.hasMultipleVideos && this.videoUrls) {
11918
- const total = this.totalDuration;
11919
- const currentGlobalTime = this.globalCurrentTime;
11920
- const isAtEnd = total > 0 && (this.progress >= 100 || currentGlobalTime >= total);
11921
- const isLastVideo = this.currentVideoIndex >= this.videoUrls.length - 1;
11922
- const isLastVideoAtEnd = isLastVideo && video.duration && video.currentTime >= video.duration - 0.1;
11923
- if (isAtEnd || isLastVideoAtEnd) {
11924
- console.log('[Simulator] playVideoInternal: all videos completed, resetting to first video', {
11925
- progress: this.progress,
11926
- currentGlobalTime,
11927
- total,
11928
- currentVideoIndex: this.currentVideoIndex,
11929
- isAtEnd,
11930
- isLastVideoAtEnd
11931
- });
11932
- // Reset to first video at 0 progress
11933
- this.currentVideoIndex = 0;
11934
- this.progress = 0;
11935
- this.targetGlobalTimeDuringSwitch = 0;
11936
- this.hitMarkers.clear();
11937
- // Switch to first video and seek to 0
11938
- yield this.switchToVideoAndSeekInternal(0);
11939
- // Update video reference after switch
11940
- const videoAfterSwitch = (_b = this.vplayer) === null || _b === void 0 ? void 0 : _b.nativeElement;
11941
- if (!videoAfterSwitch) {
11942
- console.error('[Simulator] playVideoInternal: video element not found after switch');
11943
- return;
11944
- }
11945
- // Continue with normal play logic below
11946
- // The video element reference has changed, so we'll use videoAfterSwitch
11947
- // But we need to wait for metadata again
11948
- if (videoAfterSwitch.readyState < HTMLMediaElement.HAVE_METADATA) {
11949
- yield new Promise((resolve, reject) => {
11950
- const onLoadedMetadata = () => {
11951
- videoAfterSwitch.removeEventListener('loadedmetadata', onLoadedMetadata);
11952
- videoAfterSwitch.removeEventListener('error', onError);
11953
- resolve();
11954
- };
11955
- const onError = () => {
11956
- videoAfterSwitch.removeEventListener('loadedmetadata', onLoadedMetadata);
11957
- videoAfterSwitch.removeEventListener('error', onError);
11958
- reject(new Error('Failed to load video metadata'));
11959
- };
11960
- videoAfterSwitch.addEventListener('loadedmetadata', onLoadedMetadata, { once: true });
11961
- videoAfterSwitch.addEventListener('error', onError, { once: true });
11962
- setTimeout(() => {
11963
- videoAfterSwitch.removeEventListener('loadedmetadata', onLoadedMetadata);
11964
- videoAfterSwitch.removeEventListener('error', onError);
11965
- if (videoAfterSwitch.readyState >= HTMLMediaElement.HAVE_METADATA) {
11966
- resolve();
11967
- }
11968
- else {
11969
- reject(new Error('Timeout waiting for metadata'));
11970
- }
11971
- }, 500);
11972
- });
11973
- }
11974
- // Set state to loading
11975
- this.playerState = 'loading';
11976
- try {
11977
- yield videoAfterSwitch.play();
11978
- this.playerState = 'playing';
11979
- this.isPlaying = true;
11980
- this.playPromise = null;
11981
- this.videoPlay.emit();
11982
- this.isVideoPlayingChange.emit(true);
11983
- this.targetGlobalTimeDuringSwitch = null;
11984
- console.log('[Simulator] playVideoInternal: restarted from first video');
11985
- return;
11986
- }
11987
- catch (err) {
11988
- this.playerState = 'error';
11989
- this.isPlaying = false;
11990
- this.playPromise = null;
11991
- this.isVideoPlayingChange.emit(false);
11992
- if (err.name === 'AbortError') {
11993
- this.playerState = 'paused';
11994
- }
11995
- else {
11996
- console.error('[Simulator] playVideoInternal: failed after reset', err);
11997
- }
11998
- return;
11999
- }
12000
- }
12001
- }
12002
11899
  console.log('[Simulator] playVideoInternal: starting', {
12003
11900
  playerState: this.playerState,
12004
11901
  currentTime: video.currentTime,
@@ -12020,17 +11917,6 @@ class SimulatorComponent {
12020
11917
  };
12021
11918
  video.addEventListener('loadedmetadata', onLoadedMetadata, { once: true });
12022
11919
  video.addEventListener('error', onError, { once: true });
12023
- // Timeout fallback
12024
- setTimeout(() => {
12025
- video.removeEventListener('loadedmetadata', onLoadedMetadata);
12026
- video.removeEventListener('error', onError);
12027
- if (video.readyState >= HTMLMediaElement.HAVE_METADATA) {
12028
- resolve();
12029
- }
12030
- else {
12031
- reject(new Error('Timeout waiting for metadata'));
12032
- }
12033
- }, 500);
12034
11920
  });
12035
11921
  }
12036
11922
  // Clear hit markers if starting from beginning
@@ -12042,7 +11928,7 @@ class SimulatorComponent {
12042
11928
  this.playerState = 'loading';
12043
11929
  try {
12044
11930
  // Verify video element is still available before playing
12045
- const currentVideo = (_c = this.vplayer) === null || _c === void 0 ? void 0 : _c.nativeElement;
11931
+ const currentVideo = (_b = this.vplayer) === null || _b === void 0 ? void 0 : _b.nativeElement;
12046
11932
  if (!currentVideo || currentVideo !== video) {
12047
11933
  console.warn('[Simulator] playVideoInternal: video element changed or unavailable');
12048
11934
  this.playerState = 'paused';
@@ -12053,7 +11939,7 @@ class SimulatorComponent {
12053
11939
  // Await play promise - this is critical
12054
11940
  yield video.play();
12055
11941
  // Verify video element is still available after play promise resolves
12056
- const videoAfterPlay = (_d = this.vplayer) === null || _d === void 0 ? void 0 : _d.nativeElement;
11942
+ const videoAfterPlay = (_c = this.vplayer) === null || _c === void 0 ? void 0 : _c.nativeElement;
12057
11943
  if (!videoAfterPlay || videoAfterPlay !== video) {
12058
11944
  console.warn('[Simulator] playVideoInternal: video element changed during play');
12059
11945
  this.playerState = 'paused';
@@ -12071,17 +11957,19 @@ class SimulatorComponent {
12071
11957
  currentTime: video.currentTime,
12072
11958
  playerState: this.playerState
12073
11959
  });
12074
- // Check early markers (non-blocking, doesn't need to be queued)
12075
11960
  setTimeout(() => {
12076
- if (this.isPlaying) {
12077
- this.checkMarkerHit(this.globalCurrentTime);
11961
+ var _a, _b;
11962
+ if (this.isPlaying && ((_a = this.vplayer) === null || _a === void 0 ? void 0 : _a.nativeElement)) {
11963
+ const v = this.vplayer.nativeElement;
11964
+ const segmentStart = this.currentVideoIndex === 0 ? 0 : ((_b = this.segmentBoundaries[this.currentVideoIndex - 1]) !== null && _b !== void 0 ? _b : 0);
11965
+ this.checkMarkerHit(segmentStart + v.currentTime * 1000);
12078
11966
  }
12079
11967
  }, 50);
12080
11968
  }
12081
11969
  catch (err) {
12082
11970
  // Play failed
12083
11971
  // Check if video element is still available
12084
- const videoAfterError = (_e = this.vplayer) === null || _e === void 0 ? void 0 : _e.nativeElement;
11972
+ const videoAfterError = (_d = this.vplayer) === null || _d === void 0 ? void 0 : _d.nativeElement;
12085
11973
  if (!videoAfterError || videoAfterError !== video) {
12086
11974
  console.warn('[Simulator] playVideoInternal: video element changed during error');
12087
11975
  this.playerState = 'paused';
@@ -12186,39 +12074,90 @@ class SimulatorComponent {
12186
12074
  }
12187
12075
  return [];
12188
12076
  }
12189
- get globalCurrentTime() {
12190
- var _a, _b;
12191
- if (this.targetGlobalTimeDuringSwitch !== null && !this.isPlaying && this.playerState !== 'playing') {
12192
- return this.targetGlobalTimeDuringSwitch;
12077
+ get currentVideoMarkers() {
12078
+ let markersToProcess;
12079
+ if (!this.hasMultipleVideos) {
12080
+ markersToProcess = this.stepMarkers;
12193
12081
  }
12194
- const video = (_a = this.vplayer) === null || _a === void 0 ? void 0 : _a.nativeElement;
12195
- if (!(video === null || video === void 0 ? void 0 : video.duration) || !isFinite(video.duration)) {
12196
- // Fallback to override if video not ready yet
12197
- if (this.targetGlobalTimeDuringSwitch !== null) {
12198
- return this.targetGlobalTimeDuringSwitch;
12082
+ else {
12083
+ const boundaries = this.getVideoDurationBoundaries();
12084
+ if (boundaries.length === 0 || this.currentVideoIndex >= boundaries.length) {
12085
+ markersToProcess = this.stepMarkers;
12199
12086
  }
12200
- return 0;
12087
+ else {
12088
+ const currentBoundary = boundaries[this.currentVideoIndex];
12089
+ markersToProcess = this.stepMarkers
12090
+ .filter(marker => {
12091
+ return marker.cumulativeDuration >= currentBoundary.start &&
12092
+ marker.cumulativeDuration < currentBoundary.end;
12093
+ })
12094
+ .map(marker => this.adjustChildStepsDuration(marker, currentBoundary.start, currentBoundary.start, currentBoundary.end));
12095
+ }
12096
+ }
12097
+ return this.flattenMarkers(markersToProcess);
12098
+ }
12099
+ adjustChildStepsDuration(marker, adjustment, videoStart, videoEnd) {
12100
+ const adjustedMarker = Object.assign(Object.assign({}, marker), { cumulativeDuration: marker.cumulativeDuration - adjustment });
12101
+ if (marker.childSteps && marker.childSteps.length > 0) {
12102
+ adjustedMarker.childSteps = marker.childSteps
12103
+ .filter(child => child.cumulativeDuration >= videoStart && child.cumulativeDuration < videoEnd)
12104
+ .map(child => {
12105
+ const adjustedChild = Object.assign(Object.assign({}, child), { cumulativeDuration: child.cumulativeDuration - adjustment });
12106
+ if (child.childSteps && child.childSteps.length > 0) {
12107
+ adjustedChild.childSteps = child.childSteps
12108
+ .filter(nestedChild => nestedChild.cumulativeDuration >= videoStart && nestedChild.cumulativeDuration < videoEnd)
12109
+ .map(nestedChild => this.adjustChildStepsDuration(nestedChild, adjustment, videoStart, videoEnd));
12110
+ }
12111
+ return adjustedChild;
12112
+ });
12201
12113
  }
12202
- const segmentStart = this.currentVideoIndex === 0 ? 0 : ((_b = this.segmentBoundaries[this.currentVideoIndex - 1]) !== null && _b !== void 0 ? _b : 0);
12203
- return segmentStart + video.currentTime * 1000;
12114
+ return adjustedMarker;
12204
12115
  }
12205
- getActualGlobalTime() {
12206
- var _a, _b;
12116
+ getStepLeftPosition(step) {
12117
+ var _a;
12207
12118
  const video = (_a = this.vplayer) === null || _a === void 0 ? void 0 : _a.nativeElement;
12208
- if (!(video === null || video === void 0 ? void 0 : video.duration) || !isFinite(video.duration))
12119
+ if (!(video === null || video === void 0 ? void 0 : video.duration))
12209
12120
  return 0;
12210
- const segmentStart = this.currentVideoIndex === 0 ? 0 : ((_b = this.segmentBoundaries[this.currentVideoIndex - 1]) !== null && _b !== void 0 ? _b : 0);
12211
- return segmentStart + video.currentTime * 1000;
12121
+ const durationMs = video.duration * 1000;
12122
+ return (step.cumulativeDuration / durationMs) * 100;
12212
12123
  }
12213
- /** Global step markers for rendering on the combined timeline */
12214
- get globalStepMarkers() {
12215
- const allMarkers = this.flattenMarkers(this.stepMarkers);
12216
- return allMarkers.map(m => ({
12217
- globalTime: m.cumulativeDuration,
12218
- result: m.result,
12219
- testStepId: m.testStepId,
12220
- title: m.title,
12221
- level: m.level
12124
+ getStepColor(step) {
12125
+ return step.level === 1 ? '#000000' : '#6366F1';
12126
+ }
12127
+ getStepResultColor(step) {
12128
+ return this.getGlobalMarkerResultColor(step.result);
12129
+ }
12130
+ getGlobalMarkerColor(level) {
12131
+ return level === 1 ? '#000000' : '#FFA500';
12132
+ }
12133
+ getGlobalMarkerResultColor(result) {
12134
+ switch (result) {
12135
+ case 'SUCCESS':
12136
+ return '#12B76A';
12137
+ case 'FAILURE':
12138
+ return '#B91C1C';
12139
+ case 'ABORTED':
12140
+ return '#F79009';
12141
+ case 'SKIPPED':
12142
+ return '#667085';
12143
+ default:
12144
+ return '#6366F1';
12145
+ }
12146
+ }
12147
+ onMarkerClick(event, marker) {
12148
+ var _a;
12149
+ event.stopPropagation();
12150
+ event.preventDefault();
12151
+ const video = (_a = this.vplayer) === null || _a === void 0 ? void 0 : _a.nativeElement;
12152
+ if (!(video === null || video === void 0 ? void 0 : video.duration))
12153
+ return;
12154
+ const targetTimeMs = marker.cumulativeDuration;
12155
+ this.enqueueOperation(() => __awaiter(this, void 0, void 0, function* () {
12156
+ yield this.seekToTimeInternal(targetTimeMs);
12157
+ if (marker.testStepId != null) {
12158
+ this.hitMarkers.add(marker.testStepId);
12159
+ this.markerHit.emit(marker);
12160
+ }
12222
12161
  }));
12223
12162
  }
12224
12163
  get currentVideoUrl() {
@@ -12260,37 +12199,35 @@ class SimulatorComponent {
12260
12199
  if (!this.hasMultipleVideos)
12261
12200
  return;
12262
12201
  if (this.currentVideoIndex > 0) {
12263
- this.currentVideoIndex -= 1;
12264
- this.resetVideoState();
12202
+ this.enqueueOperation(() => this.switchToVideoAndResetInternal(this.currentVideoIndex - 1));
12265
12203
  }
12266
12204
  }
12267
12205
  nextVideo() {
12268
12206
  if (!this.hasMultipleVideos)
12269
12207
  return;
12270
12208
  if (this.videoUrls && this.currentVideoIndex < this.videoUrls.length - 1) {
12271
- this.currentVideoIndex += 1;
12272
- this.resetVideoState();
12209
+ this.enqueueOperation(() => this.switchToVideoAndResetInternal(this.currentVideoIndex + 1));
12273
12210
  }
12274
12211
  }
12275
12212
  onTimelineClick(event) {
12276
- var _a;
12277
- if (!((_a = this.timelineBar) === null || _a === void 0 ? void 0 : _a.nativeElement))
12213
+ var _a, _b;
12214
+ if (!((_a = this.timelineBar) === null || _a === void 0 ? void 0 : _a.nativeElement) || !((_b = this.vplayer) === null || _b === void 0 ? void 0 : _b.nativeElement))
12215
+ return;
12216
+ const video = this.vplayer.nativeElement;
12217
+ if (!video.duration || !isFinite(video.duration))
12278
12218
  return;
12279
12219
  const rect = this.timelineBar.nativeElement.getBoundingClientRect();
12280
12220
  const clickX = event.clientX - rect.left;
12281
12221
  const percent = Math.max(0, Math.min(1, clickX / rect.width));
12282
- const total = this.totalDuration;
12283
- if (total <= 0)
12284
- return;
12285
- const globalTimeMs = percent * total;
12222
+ const targetTimeMs = percent * video.duration * 1000;
12286
12223
  const shouldResumePlaying = this.isPlaying;
12287
12224
  console.log('[Simulator] onTimelineClick', {
12288
12225
  percent,
12289
- globalTimeMs,
12226
+ targetTimeMs,
12290
12227
  shouldResumePlaying
12291
12228
  });
12292
12229
  this.enqueueOperation(() => __awaiter(this, void 0, void 0, function* () {
12293
- yield this.seekToGlobalTime(globalTimeMs);
12230
+ yield this.seekToTimeInternal(targetTimeMs);
12294
12231
  if (shouldResumePlaying) {
12295
12232
  yield new Promise(resolve => setTimeout(resolve, 100));
12296
12233
  yield this.playVideoInternal();
@@ -12325,11 +12262,11 @@ class SimulatorComponent {
12325
12262
  this.progress = percent * 100; // Global timeline position
12326
12263
  }
12327
12264
  stopDrag() {
12265
+ var _a;
12328
12266
  if (!this.dragging)
12329
12267
  return;
12330
12268
  this.dragging = false;
12331
12269
  this.removeDragListeners();
12332
- // CRITICAL: Capture the playing state BEFORE any async operations
12333
12270
  const shouldResumePlaying = this.wasPlayingBeforeDrag;
12334
12271
  console.log('[Simulator] stopDrag: drag ended', {
12335
12272
  progress: this.progress,
@@ -12337,19 +12274,15 @@ class SimulatorComponent {
12337
12274
  shouldResumePlaying: shouldResumePlaying,
12338
12275
  currentPlayerState: this.playerState
12339
12276
  });
12340
- const total = this.totalDuration;
12341
- if (total <= 0)
12277
+ const video = (_a = this.vplayer) === null || _a === void 0 ? void 0 : _a.nativeElement;
12278
+ if (!video || !video.duration || !isFinite(video.duration))
12342
12279
  return;
12343
- const globalTimeMs = (this.progress / 100) * total;
12344
- // CRITICAL FIX: Queue both seek and resume play together
12345
- // This ensures seek completes before attempting to play
12280
+ const targetTimeMs = (this.progress / 100) * video.duration * 1000;
12346
12281
  this.enqueueOperation(() => __awaiter(this, void 0, void 0, function* () {
12347
- // Perform seek (this will pause the video)
12348
- yield this.seekToGlobalTime(globalTimeMs);
12349
- // If video was playing before drag, resume it
12282
+ yield this.seekToTimeInternal(targetTimeMs);
12350
12283
  if (shouldResumePlaying) {
12351
12284
  console.log('[Simulator] stopDrag: resuming playback after seek', {
12352
- globalTimeMs,
12285
+ targetTimeMs,
12353
12286
  playerState: this.playerState
12354
12287
  });
12355
12288
  // Wait a bit longer to ensure seek is fully complete
@@ -12415,19 +12348,18 @@ class SimulatorComponent {
12415
12348
  this.attachVideoListeners();
12416
12349
  }
12417
12350
  onVideoEnded() {
12418
- var _a;
12419
12351
  this.isPlaying = false;
12420
12352
  this.playerState = 'paused';
12421
12353
  this.videoPause.emit();
12422
12354
  this.isVideoPlayingChange.emit(false);
12423
- // Seamlessly load and play next segment
12355
+ // Switch to next video and reset to 0
12424
12356
  if (this.hasMultipleVideos && this.videoUrls && this.currentVideoIndex < this.videoUrls.length - 1) {
12425
- const nextIndex = this.currentVideoIndex + 1;
12426
- const segmentStart = nextIndex === 0 ? 0 : ((_a = this.segmentBoundaries[nextIndex - 1]) !== null && _a !== void 0 ? _a : 0);
12357
+ this.currentVideoIndex += 1;
12427
12358
  this.enqueueOperation(() => __awaiter(this, void 0, void 0, function* () {
12428
- var _b;
12429
- yield this.switchToVideoAndSeekInternal(segmentStart);
12430
- if (((_b = this.vplayer) === null || _b === void 0 ? void 0 : _b.nativeElement) && this.currentVideoUrl) {
12359
+ var _a;
12360
+ yield this.resetVideoStateInternal();
12361
+ yield new Promise(resolve => setTimeout(resolve, 100));
12362
+ if (((_a = this.vplayer) === null || _a === void 0 ? void 0 : _a.nativeElement) && this.currentVideoUrl) {
12431
12363
  yield this.playVideoInternal();
12432
12364
  }
12433
12365
  }));
@@ -12445,30 +12377,22 @@ class SimulatorComponent {
12445
12377
  return;
12446
12378
  let lastUpdate = 0;
12447
12379
  const handler = () => {
12380
+ var _a;
12448
12381
  const now = Date.now();
12449
12382
  if (now - lastUpdate < 100)
12450
12383
  return;
12451
12384
  lastUpdate = now;
12452
12385
  const currentMs = video.currentTime * 1000;
12453
12386
  if (!this.dragging && this.playerState !== 'switching') {
12454
- const total = this.totalDuration;
12455
- // Clear targetGlobalTimeDuringSwitch if we've reached the target position
12456
- // When playing, be more aggressive about clearing to allow live updates
12457
- if (this.targetGlobalTimeDuringSwitch !== null) {
12458
- const currentGlobal = this.getActualGlobalTime();
12459
- const tolerance = this.isPlaying ? 1000 : 500; // More tolerance when playing
12460
- if (Math.abs(currentGlobal - this.targetGlobalTimeDuringSwitch) < tolerance) {
12461
- this.targetGlobalTimeDuringSwitch = null;
12462
- }
12463
- }
12464
- // globalCurrentTime now handles override logic - use it directly
12465
- if (total > 0) {
12466
- this.progress = Math.min(100, Math.max(0, (this.globalCurrentTime / total) * 100));
12387
+ // Per-video progress (0-100% of current video)
12388
+ const durationMs = video.duration * 1000;
12389
+ if (durationMs > 0) {
12390
+ this.progress = Math.min(100, Math.max(0, (currentMs / durationMs) * 100));
12467
12391
  }
12468
- this.videoTimeUpdate.emit(this.globalCurrentTime);
12469
- // Check if current time hits any marker
12470
- this.checkMarkerHit(this.globalCurrentTime);
12471
- // Preload next segment when ~5-10 seconds from ending
12392
+ // Emit cumulative time for parent (step highlighting)
12393
+ const segmentStart = this.currentVideoIndex === 0 ? 0 : ((_a = this.segmentBoundaries[this.currentVideoIndex - 1]) !== null && _a !== void 0 ? _a : 0);
12394
+ this.videoTimeUpdate.emit(segmentStart + currentMs);
12395
+ this.checkMarkerHit(segmentStart + currentMs);
12472
12396
  this.maybePreloadNextSegment();
12473
12397
  }
12474
12398
  };
@@ -12672,48 +12596,10 @@ class SimulatorComponent {
12672
12596
  // Mark as hit and emit event
12673
12597
  this.hitMarkers.add(marker.testStepId);
12674
12598
  this.markerHit.emit(marker);
12675
- console.log('[Simulator] Marker hit detected', {
12676
- testStepId: marker.testStepId,
12677
- cumulativeDuration: marker.cumulativeDuration,
12678
- currentTime: globalTimeMs,
12679
- timeDifference,
12680
- title: marker.title,
12681
- level: marker.level
12682
- });
12683
12599
  break; // Only emit one marker per check
12684
12600
  }
12685
12601
  }
12686
12602
  }
12687
- getGlobalMarkerResultColor(result) {
12688
- switch (result) {
12689
- case 'SUCCESS':
12690
- return '#12B76A';
12691
- case 'FAILURE':
12692
- return '#B91C1C';
12693
- case 'ABORTED':
12694
- return '#F79009';
12695
- case 'SKIPPED':
12696
- return '#667085';
12697
- default:
12698
- return '#6366F1';
12699
- }
12700
- }
12701
- getGlobalMarkerColor(level) {
12702
- return level === 1 ? '#000000' : '#FFA500';
12703
- }
12704
- onMarkerClick(event, marker) {
12705
- event.stopPropagation();
12706
- event.preventDefault();
12707
- this.enqueueOperation(() => __awaiter(this, void 0, void 0, function* () {
12708
- yield this.seekToGlobalTime(marker.globalTime);
12709
- if (marker.testStepId != null) {
12710
- this.hitMarkers.add(marker.testStepId);
12711
- const fullMarker = this.flattenMarkers(this.stepMarkers).find(m => m.testStepId === marker.testStepId);
12712
- if (fullMarker)
12713
- this.markerHit.emit(fullMarker);
12714
- }
12715
- }));
12716
- }
12717
12603
  toggleFullScreen() {
12718
12604
  var _a, _b;
12719
12605
  const wasPlaying = this.isPlaying;
@@ -12769,20 +12655,15 @@ class SimulatorComponent {
12769
12655
  }
12770
12656
  onSegmentChange(value) {
12771
12657
  this.currentView = value;
12772
- // Pause video when switching away from video view
12773
12658
  if (this.currentView !== 'video') {
12774
12659
  this.pauseVideo();
12775
12660
  this.progress = 0;
12776
12661
  }
12777
12662
  else {
12778
- // Reset everything when switching back to video view
12779
12663
  this.enqueueOperation(() => __awaiter(this, void 0, void 0, function* () {
12780
12664
  yield this.resetVideoStateInternal();
12781
- // If multiple videos, reset to first video
12782
12665
  if (this.hasMultipleVideos && this.videoUrls) {
12783
12666
  this.currentVideoIndex = 0;
12784
- this.targetGlobalTimeDuringSwitch = 0;
12785
- // Switch to first video and seek to 0
12786
12667
  yield this.switchToVideoAndSeekInternal(0);
12787
12668
  }
12788
12669
  }));
@@ -12980,6 +12861,66 @@ class SimulatorComponent {
12980
12861
  }
12981
12862
  return null;
12982
12863
  }
12864
+ switchToVideoAndResetInternal(targetVideoIndex) {
12865
+ var _a, _b;
12866
+ return __awaiter(this, void 0, void 0, function* () {
12867
+ const video = (_a = this.vplayer) === null || _a === void 0 ? void 0 : _a.nativeElement;
12868
+ if (!video || !this.videoUrls || targetVideoIndex < 0 || targetVideoIndex >= this.videoUrls.length) {
12869
+ return;
12870
+ }
12871
+ if (this.currentVideoIndex === targetVideoIndex) {
12872
+ yield this.resetVideoStateInternal();
12873
+ return;
12874
+ }
12875
+ this.playerState = 'switching';
12876
+ try {
12877
+ video.pause();
12878
+ this.isPlaying = false;
12879
+ this.playPromise = null;
12880
+ this.videoPause.emit();
12881
+ this.isVideoPlayingChange.emit(false);
12882
+ this.currentVideoIndex = targetVideoIndex;
12883
+ yield new Promise((resolve, reject) => {
12884
+ let resolved = false;
12885
+ const cleanup = () => {
12886
+ if (resolved)
12887
+ return;
12888
+ resolved = true;
12889
+ video.removeEventListener('loadedmetadata', onLoadedMetadata);
12890
+ video.removeEventListener('error', onError);
12891
+ };
12892
+ const onLoadedMetadata = () => {
12893
+ cleanup();
12894
+ resolve();
12895
+ };
12896
+ const onError = () => {
12897
+ cleanup();
12898
+ reject(new Error('Failed to load video'));
12899
+ };
12900
+ setTimeout(() => {
12901
+ if (resolved)
12902
+ return;
12903
+ video.addEventListener('loadedmetadata', onLoadedMetadata, { once: true });
12904
+ video.addEventListener('error', onError, { once: true });
12905
+ }, 100);
12906
+ });
12907
+ video.currentTime = 0;
12908
+ this.progress = 0;
12909
+ this.playPromise = null;
12910
+ this.hitMarkers.clear();
12911
+ this.lastSetDuration = -1;
12912
+ const segmentStart = targetVideoIndex === 0 ? 0 : ((_b = this.segmentBoundaries[targetVideoIndex - 1]) !== null && _b !== void 0 ? _b : 0);
12913
+ this.videoTimeUpdate.emit(segmentStart);
12914
+ }
12915
+ catch (err) {
12916
+ console.error('[Simulator] switchToVideoAndReset failed:', err);
12917
+ this.progress = 0;
12918
+ }
12919
+ finally {
12920
+ this.playerState = 'paused';
12921
+ }
12922
+ });
12923
+ }
12983
12924
  switchToVideoAndSeek(cumulativeTimestamp) {
12984
12925
  this.enqueueOperation(() => this.switchToVideoAndSeekInternal(cumulativeTimestamp));
12985
12926
  }
@@ -13006,20 +12947,13 @@ class SimulatorComponent {
13006
12947
  const video = (_a = this.vplayer) === null || _a === void 0 ? void 0 : _a.nativeElement;
13007
12948
  if (!video)
13008
12949
  return;
13009
- const total = this.totalDuration;
13010
- this.targetGlobalTimeDuringSwitch = cumulativeTimestamp;
13011
- if (total > 0) {
13012
- this.progress = Math.min(100, Math.max(0, (cumulativeTimestamp / total) * 100));
13013
- }
13014
12950
  this.playerState = 'switching';
13015
12951
  try {
13016
- // CRITICAL: Pause before switching source
13017
12952
  video.pause();
13018
12953
  this.isPlaying = false;
13019
12954
  this.playPromise = null;
13020
12955
  this.videoPause.emit();
13021
12956
  this.isVideoPlayingChange.emit(false);
13022
- // Switch video source
13023
12957
  this.currentVideoIndex = targetVideoIndex;
13024
12958
  yield new Promise((resolve, reject) => {
13025
12959
  let resolved = false;
@@ -13029,20 +12963,13 @@ class SimulatorComponent {
13029
12963
  resolved = true;
13030
12964
  video.removeEventListener('loadedmetadata', onLoadedMetadata);
13031
12965
  video.removeEventListener('error', onError);
13032
- clearTimeout(timeoutId);
13033
12966
  };
13034
12967
  const onLoadedMetadata = () => {
13035
12968
  cleanup();
13036
- console.log('[Simulator] switchToVideoAndSeek: loadedmetadata', {
13037
- readyState: video.readyState,
13038
- duration: video.duration,
13039
- currentTime: video.currentTime
13040
- });
13041
12969
  resolve();
13042
12970
  };
13043
12971
  const onError = () => {
13044
12972
  cleanup();
13045
- console.error('[Simulator] switchToVideoAndSeek: video error');
13046
12973
  reject(new Error('Failed to load video'));
13047
12974
  };
13048
12975
  setTimeout(() => {
@@ -13051,121 +12978,51 @@ class SimulatorComponent {
13051
12978
  video.addEventListener('loadedmetadata', onLoadedMetadata, { once: true });
13052
12979
  video.addEventListener('error', onError, { once: true });
13053
12980
  }, 100);
13054
- const timeoutId = setTimeout(() => {
13055
- cleanup();
13056
- if (video.readyState >= HTMLMediaElement.HAVE_METADATA) {
13057
- console.log('[Simulator] switchToVideoAndSeek: metadata timeout but video ready', {
13058
- readyState: video.readyState,
13059
- duration: video.duration
13060
- });
13061
- resolve();
13062
- }
13063
- else {
13064
- console.error('[Simulator] switchToVideoAndSeek: metadata timeout and video not ready');
13065
- reject(new Error('Timeout waiting for video to load'));
13066
- }
13067
- }, 2000);
13068
12981
  });
13069
- // Seek to the target position using 'seeked' event for reliability
13070
12982
  const seekSeconds = relativeTimestamp / 1000;
13071
12983
  const targetTime = Math.max(0, Math.min(seekSeconds, video.duration || seekSeconds));
13072
- console.log('[Simulator] switchToVideoAndSeek: setting currentTime', {
13073
- targetTime,
13074
- seekSeconds,
13075
- relativeTimestamp,
13076
- videoDuration: video.duration
13077
- });
13078
12984
  yield new Promise((resolve) => {
13079
- let resolved = false;
13080
12985
  const onSeeked = () => {
13081
- if (resolved)
13082
- return;
13083
- resolved = true;
13084
12986
  video.removeEventListener('seeked', onSeeked);
13085
12987
  clearTimeout(timeoutId);
13086
- console.log('[Simulator] switchToVideoAndSeek: seeked event fired', {
13087
- currentTime: video.currentTime,
13088
- targetTime,
13089
- diff: Math.abs(video.currentTime - targetTime)
13090
- });
13091
- // Small delay to ensure browser has processed the seek
13092
12988
  setTimeout(() => resolve(), 100);
13093
12989
  };
13094
12990
  video.addEventListener('seeked', onSeeked, { once: true });
13095
12991
  video.currentTime = targetTime;
13096
- // Fallback timeout
13097
12992
  const timeoutId = setTimeout(() => {
13098
- if (resolved)
13099
- return;
13100
- resolved = true;
13101
12993
  video.removeEventListener('seeked', onSeeked);
13102
- console.log('[Simulator] switchToVideoAndSeek: seeked timeout, current time is', video.currentTime);
13103
12994
  resolve();
13104
12995
  }, 1000);
13105
12996
  });
13106
12997
  this.lastSetDuration = cumulativeTimestamp;
13107
- // Double-check: if video is not at target, force it again
13108
12998
  if (Math.abs(video.currentTime - targetTime) > 0.5) {
13109
- console.warn('[Simulator] switchToVideoAndSeek: video not at target after seeked, forcing again', {
13110
- currentTime: video.currentTime,
13111
- targetTime
13112
- });
13113
12999
  video.currentTime = targetTime;
13114
13000
  yield new Promise(resolve => setTimeout(resolve, 200));
13115
13001
  }
13116
- // Verify seek completed
13117
- const actualGlobal = this.getActualGlobalTime();
13118
- const actualVideoTime = video.currentTime;
13119
- console.log('[Simulator] switchToVideoAndSeek: seek verification', {
13120
- actualGlobal,
13121
- targetGlobal: cumulativeTimestamp,
13122
- diff: Math.abs(actualGlobal - cumulativeTimestamp),
13123
- actualVideoTime,
13124
- targetVideoTime: targetTime,
13125
- videoDiff: Math.abs(actualVideoTime - targetTime)
13126
- });
13127
- // Clear override only if video is actually at the target
13128
- const tolerance = 500;
13129
- if (Math.abs(actualGlobal - cumulativeTimestamp) < tolerance) {
13130
- this.targetGlobalTimeDuringSwitch = null;
13131
- console.log('[Simulator] switchToVideoAndSeek: cleared override - video at target');
13132
- }
13133
- // Update UI with actual current position
13134
- if (total > 0) {
13135
- this.progress = Math.min(100, Math.max(0, (this.globalCurrentTime / total) * 100));
13002
+ // Per-video progress
13003
+ const durationMs = video.duration * 1000;
13004
+ if (durationMs > 0) {
13005
+ this.progress = Math.min(100, Math.max(0, (video.currentTime * 1000 / durationMs) * 100));
13136
13006
  }
13137
- this.videoTimeUpdate.emit(this.globalCurrentTime);
13007
+ this.videoTimeUpdate.emit(cumulativeTimestamp);
13138
13008
  }
13139
13009
  catch (err) {
13140
13010
  console.error('[Simulator] switchToVideoAndSeek failed:', err);
13141
- // Even on error, try to update to target position
13142
- if (total > 0) {
13143
- this.progress = Math.min(100, Math.max(0, (cumulativeTimestamp / total) * 100));
13144
- }
13011
+ this.progress = 0;
13145
13012
  this.videoTimeUpdate.emit(cumulativeTimestamp);
13146
13013
  }
13147
13014
  finally {
13148
13015
  this.playerState = 'paused';
13149
13016
  this.hitMarkers.clear();
13150
- // Don't clear targetGlobalTimeDuringSwitch here - it's either already cleared
13151
- // or will be cleared by timeupdate handler when video reaches target
13152
- }
13153
- console.log('[Simulator] switchToVideoAndSeek: complete', {
13154
- currentVideoIndex: this.currentVideoIndex,
13155
- videoCurrentTime: video.currentTime,
13156
- globalCurrentTime: this.globalCurrentTime,
13157
- targetGlobalTimeDuringSwitch: this.targetGlobalTimeDuringSwitch,
13158
- playerState: this.playerState,
13159
- progress: this.progress
13160
- });
13017
+ }
13161
13018
  });
13162
13019
  }
13163
13020
  }
13164
13021
  SimulatorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: SimulatorComponent, deps: [{ token: i1$1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
13165
- SimulatorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: SimulatorComponent, selector: "cqa-simulator", inputs: { videoUrl: "videoUrl", videoUrls: "videoUrls", videoCurrentDuration: "videoCurrentDuration", stepMarkers: "stepMarkers", screenShotUrl: "screenShotUrl", traceViewUrl: "traceViewUrl", platformName: "platformName", platformType: "platformType", platform: "platform", deviceName: "deviceName", isLive: "isLive", liveStatus: "liveStatus", liveLoadingLabel: "liveLoadingLabel", isContentVideoLoading: "isContentVideoLoading", failedStatusMessage: "failedStatusMessage", isVNCSessionIntruppted: "isVNCSessionIntruppted", vncSessionIntupptedMessage: "vncSessionIntupptedMessage", selectedView: "selectedView", hideVideoTab: "hideVideoTab", browserViewPort: "browserViewPort" }, outputs: { videoTimeUpdate: "videoTimeUpdate", videoPlay: "videoPlay", videoPause: "videoPause", markerHit: "markerHit", isVideoPlayingChange: "isVideoPlayingChange" }, viewQueries: [{ propertyName: "vplayerRef", first: true, predicate: ["vplayer"], descendants: true }, { propertyName: "timelineBarRef", first: true, predicate: ["timelineBar"], descendants: true }, { propertyName: "speedControlContainerRef", first: true, predicate: ["speedControlContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-ui-root\" style=\"background-color: #F3F4F6; height: 100%; display: flex; flex-direction: column;\" [ngStyle]=\"{\n position: isFullScreen ? 'fixed' : null,\n inset: isFullScreen ? '1rem' : null,\n zIndex: isFullScreen ? '50' : null,\n boxShadow: isFullScreen ? '0px 13px 25px -12px rgba(0, 0, 0, 0.25)' : null,\n borderRadius: isFullScreen ? '.5rem' : null,\n border: isFullScreen ? '1px solid #E5E7EB' : null,\n width: isFullScreen ? 'calc(100% - 32px)' : null,\n height: isFullScreen ? 'calc(100% - 32px)' : '100%',\n overflow: isFullScreen ? 'hidden' : null\n}\">\n <div class=\"cqa-w-full cqa-py-1 cqa-px-2 cqa-bg-[#FFFFFF]\" style=\"border-bottom: 1px solid #E5E7EB;box-shadow: 0px 1px 2px 0px #0000000D;\">\n <div class=\"cqa-w-full cqa-flex cqa-items-center cqa-justify-between cqa-flex-wrap\">\n <div class=\"cqa-flex cqa-items-center\">\n <div *ngIf=\"isLive\" class=\"cqa-h-[21px] cqa-inline-flex cqa-items-center cqa-gap-1.5 cqa-mr-2 cqa-px-[9px] cqa-py-[3px] cqa-bg-[#FCD9D9] cqa-rounded-[6px]\" style=\"border: 1px solid #F9BFBF;\">\n <span class=\"cqa-relative cqa-w-2 cqa-h-2 cqa-rounded-full cqa-bg-[#F47F7F]\" style=\"flex-shrink: 0;\">\n <span class=\"cqa-absolute cqa-inset-0 cqa-rounded-full cqa-bg-[#F47F7F] cqa-opacity-75 cqa-animate-ping\"></span>\n </span>\n <span class=\"cqa-text-[10px] cqa-font-medium cqa-text-[#C63535] cqa-leading-[15px]\">Live</span>\n </div>\n <mat-icon *ngIf=\"platformType === 'browser'\" style=\"width: 10px; height: 10px;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <g clip-path=\"url(#clip0_935_15847)\">\n <path\n d=\"M0.625 5C0.625 6.16032 1.08594 7.27312 1.90641 8.09359C2.72688 8.91406 3.83968 9.375 5 9.375C6.16032 9.375 7.27312 8.91406 8.09359 8.09359C8.91406 7.27312 9.375 6.16032 9.375 5C9.375 3.83968 8.91406 2.72688 8.09359 1.90641C7.27312 1.08594 6.16032 0.625 5 0.625C3.83968 0.625 2.72688 1.08594 1.90641 1.90641C1.08594 2.72688 0.625 3.83968 0.625 5Z\"\n stroke=\"#9CA3AF\" stroke-width=\"0.6\" stroke-linejoin=\"round\" />\n <path\n d=\"M3.125 5C3.125 3.83968 3.32254 2.72688 3.67417 1.90641C4.02581 1.08594 4.50272 0.625 5 0.625C5.49728 0.625 5.97419 1.08594 6.32582 1.90641C6.67746 2.72688 6.875 3.83968 6.875 5C6.875 6.16032 6.67746 7.27312 6.32582 8.09359C5.97419 8.91406 5.49728 9.375 5 9.375C4.50272 9.375 4.02581 8.91406 3.67417 8.09359C3.32254 7.27312 3.125 6.16032 3.125 5Z\"\n stroke=\"#9CA3AF\" stroke-width=\"0.6\" stroke-linejoin=\"round\" />\n <path d=\"M0.9375 6.45866H9.0625M0.9375 3.54199H9.0625\" stroke=\"#9CA3AF\" stroke-width=\"0.6\"\n stroke-linecap=\"round\" />\n </g>\n <defs>\n <clipPath id=\"clip0_935_15847\">\n <rect width=\"10\" height=\"10\" fill=\"white\" />\n </clipPath>\n </defs>\n </svg>\n </mat-icon>\n <mat-icon *ngIf=\"platformType === 'device'\" style=\"width: 10px; height: 10px;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M7.08325 0.833008H2.91659C2.45635 0.833008 2.08325 1.2061 2.08325 1.66634V8.33301C2.08325 8.79324 2.45635 9.16634 2.91659 9.16634H7.08325C7.54349 9.16634 7.91658 8.79324 7.91658 8.33301V1.66634C7.91658 1.2061 7.54349 0.833008 7.08325 0.833008Z\" stroke=\"#6B7280\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M5 7.5H5.00417\" stroke=\"#6B7280\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </mat-icon>\n <p class=\"cqa-text-sm !cqa-text-[10px] cqa-text-[#6B7280] cqa-ml-2\">\n {{ platformName }}\n <span\n *ngIf=\"platformType === 'browser'\"\n class=\"cqa-ml-1\"\n [matTooltip]=\"'Screen size: ' + effectiveBrowserViewPort.width + 'x' + effectiveBrowserViewPort.height\"\n matTooltipPosition=\"below\"\n >\n \u00B7\n <span class=\"cqa-ml-1\">\n {{ effectiveBrowserViewPort.width }}x{{ effectiveBrowserViewPort.height }}\n </span>\n </span>\n </p>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div *ngIf=\"isLive\" [ngClass]=\"getStatusBadgeClass()\">\n <span [ngClass]=\"getStatusTextClass()\">{{ liveStatus }}</span>\n </div>\n\n <ng-container *ngIf=\"!isLive\">\n <cqa-segment-control \n [segments]=\"segments\" \n [value]=\"currentView\"\n (valueChange)=\"onSegmentChange($event)\">\n </cqa-segment-control>\n \n <div *ngIf=\"!isFullScreen\" \n class=\"cqa-p-1 cqa-cursor-pointer hover:cqa-bg-gray-100 cqa-rounded-sm cqa-transition-colors\"\n (click)=\"toggleFullScreen()\"\n title=\"Expand\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M6.25 1.25H8.75V3.75\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.74992 1.25L5.83325 4.16667\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M1.25 8.74967L4.16667 5.83301\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M3.75 8.75H1.25V6.25\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n\n <div *ngIf=\"isFullScreen\" \n class=\"cqa-p-1 cqa-cursor-pointer hover:cqa-bg-gray-100 cqa-rounded-sm cqa-transition-colors\"\n (click)=\"toggleFullScreen()\"\n title=\"Exit full screen\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M8.75 6.25H6.25V8.75\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.25008 6.25L9.16675 9.16667\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M0.833252 0.833008L3.74992 3.74967\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M1.25 3.75H3.75V1.25\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n </ng-container>\n </div>\n </div>\n </div>\n <div class=\"cqa-w-full cqa-bg-[#F3F4F6] cqa-h-[calc(100%-41px)]\">\n <!-- Live Content View -->\n <div *ngIf=\"isLive\" class=\"cqa-h-full cqa-flex cqa-flex-col cqa-justify-center cqa-relative\">\n <ng-container *ngIf=\"hasDeviceFrame;\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center cqa-p-4\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser', 'cqa-max-h-full cqa-h-full': platformType !== 'browser' || !isLive, 'cqa-min-w-max': platformType === 'device'}\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-max-h-full cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-z-20': platformType === 'browser', 'cqa-bg-white': platformType !== 'browser'}\">\n <!-- Loading State -->\n <div *ngIf=\"isContentVideoLoading\" class=\"cqa-p-10 cqa-text-center cqa-h-full cqa-flex cqa-flex-col cqa-items-center cqa-justify-center\">\n <div class=\"cqa-mb-4\">\n <mat-progress-spinner mode=\"indeterminate\" diameter=\"40\"></mat-progress-spinner>\n </div>\n <p class=\"cqa-text-gray-400 cqa-text-sm\">{{ liveLoadingLabel }}</p>\n </div>\n\n <!-- Live Content (when not loading) -->\n <div *ngIf=\"!isContentVideoLoading\" class=\"cqa-w-full cqa-h-full cqa-flex cqa-flex-col cqa-items-center cqa-justify-center cqa-relative\">\n <div *ngIf=\"liveStatus === 'Failed' && failedStatusMessage\" class=\"cqa-p-6 cqa-text-center cqa-w-full\">\n <div class=\"cqa-inline-flex cqa-items-center cqa-gap-2 cqa-px-4 cqa-py-3 cqa-bg-[#FCD9D9] cqa-border cqa-border-[#F9BFBF] cqa-rounded-lg\">\n <mat-icon style=\"width: 18px; height: 18px; color: #C63535; font-size: 18px;\">error</mat-icon>\n <p class=\"cqa-text-[#C63535] cqa-text-sm cqa-font-medium cqa-m-0\">{{ failedStatusMessage }}</p>\n </div>\n </div>\n <ng-content *ngIf=\"liveStatus !== 'Failed' || !failedStatusMessage\"></ng-content>\n </div>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n\n <!-- Normal Video View (when not live) -->\n <div *ngIf=\"!isLive && currentView === 'video'\"\n class=\"cqa-h-full cqa-flex cqa-flex-col\"\n tabindex=\"0\"\n role=\"region\"\n aria-label=\"Video playback\"\n (keydown)=\"onVideoKeydown($event)\">\n <div class=\"cqa-w-full cqa-py-4 cqa-flex cqa-items-center cqa-max-h-[calc(100%-83px)]\" *ngIf=\"currentVideoUrl\" [ngClass]=\"{'!cqa-h-full': platformType === 'device', 'cqa-mt-auto': hasDeviceFrame}\">\n <ng-container *ngIf=\"hasDeviceFrame\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-p-4': platformType === 'browser'}\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center cqa-max-h-full\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser', 'cqa-min-w-max': platformType === 'device'}\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-max-h-full cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-bg-white': platformType !== 'browser'}\">\n <video\n #vplayer\n class=\"cqa-object-cover cqa-w-full cqa-h-full cqa-block cqa-bg-[##F2F2F2]\"\n [src]=\"currentVideoUrl\"\n type=\"video/webm\"\n [ngClass]=\"{'cqa-z-20': platformType === 'browser'}\"\n (loadedmetadata)=\"onVideoMetadataLoaded()\"\n (canplay)=\"onVideoCanPlay()\"\n (ended)=\"onVideoEnded()\"\n ></video>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!currentVideoUrl\">\n <ng-container *ngIf=\"isVNCSessionIntruppted && vncSessionIntupptedMessage; else noVideoDefault\">\n <p class=\"cqa-text-sm cqa-text-gray-600\">\n {{ vncSessionIntupptedMessage }}\n </p>\n </ng-container>\n <ng-template #noVideoDefault>\n <span>No video recording found</span>\n </ng-template>\n </div>\n \n <div class=\"cqa-px-2 cqa-py-2 cqa-bg-white\" style=\"border-top: 1px solid #E5E7EB;\" [ngClass]=\"{'cqa-mt-auto': hasDeviceFrame}\" *ngIf=\"currentVideoUrl && !isLive\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-flex cqa-items-center cqa-justify-center\" style=\"width: 16px; height: 16px;\">\n <mat-progress-spinner\n *ngIf=\"isPlayerSwitching\"\n mode=\"indeterminate\"\n diameter=\"16\"\n class=\"cqa-inline-block\">\n </mat-progress-spinner>\n <button \n *ngIf=\"!isPlayerSwitching\"\n type=\"button\"\n class=\"cqa-bg-transparent cqa-border-none cqa-cursor-pointer !cqa-px-0 cqa-flex cqa-items-center cqa-justify-center hover:cqa-opacity-70 cqa-transition-opacity cqa-outline-none\"\n style=\"pointer-events: auto;\"\n (click)=\"togglePlay()\"\n matTooltip=\"{{ isPlaying ? 'Pause' : 'Play' }}\"\n matTooltipPosition=\"above\">\n <span *ngIf=\"!isPlaying\" class=\"cqa-flex cqa-items-center cqa-justify-center\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M3 2L13 8L3 14V2Z\" fill=\"#374151\"/>\n </svg>\n </span>\n <span *ngIf=\"isPlaying\" class=\"cqa-flex cqa-items-center cqa-justify-center\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"3\" y=\"2\" width=\"3\" height=\"12\" fill=\"#374151\"/>\n <rect x=\"10\" y=\"2\" width=\"3\" height=\"12\" fill=\"#374151\"/>\n </svg>\n </span>\n </button>\n </div>\n\n <span class=\"cqa-text-[#9CA3AF] cqa-text-[9px] cqa-font-normal cqa-whitespace-nowrap cqa-select-none\">\n {{ formatTime(globalCurrentTime / 1000) }}\n </span>\n\n <div #speedControlContainer class=\"cqa-relative cqa-mr-[8px] cqa-flex cqa-items-center cqa-justify-center\">\n <button\n type=\"button\"\n class=\"cqa-bg-transparent cqa-border-none cqa-cursor-pointer cqa-text-[#9CA3AF] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-whitespace-nowrap cqa-select-none hover:cqa-opacity-70 cqa-transition-opacity cqa-outline-none cqa-px-1\"\n (click)=\"toggleSpeedControl()\"\n [matTooltip]=\"'Playback Speed'\"\n [matTooltipPosition]=\"'below'\">\n {{ currentSpeed }}\n </button>\n \n <div \n *ngIf=\"isSpeedControlOpen\"\n class=\"cqa-absolute cqa-bottom-full cqa-mb-2 cqa-right-0 cqa-bg-[#F0F0F1] cqa-rounded-lg cqa-overflow-hidden cqa-shadow-lg cqa-z-50\"\n style=\"min-width: max-content; left: 50%; bottom: 0%; transform: translate(-50%, -50%);\">\n <cqa-segment-control\n [segments]=\"speedSegments\"\n [value]=\"currentSpeed\"\n [containerBgColor]=\"'#F0F0F1'\"\n (valueChange)=\"onSpeedChange($event)\">\n </cqa-segment-control>\n </div>\n </div>\n \n <div \n #timelineBar\n class=\"cqa-relative cqa-h-1 cqa-bg-gray-200 cqa-rounded-full cqa-cursor-pointer cqa-flex-1\"\n (click)=\"onTimelineClick($event)\">\n \n <div \n *ngFor=\"let marker of globalStepMarkers\" \n class=\"cqa-absolute cqa-rounded-full\"\n [style.left.%]=\"totalDuration > 0 ? (marker.globalTime / totalDuration) * 100 : 0\"\n [style.width]=\"'8px'\"\n [style.height]=\"'8px'\"\n [style.background]=\"getGlobalMarkerColor(marker.level)\"\n [style.border]=\"'2px solid ' + getGlobalMarkerResultColor(marker.result)\"\n [style.box-sizing]=\"'border-box'\"\n [attr.title]=\"marker.title || ''\"\n style=\"pointer-events: auto; z-index: 50; cursor: pointer; transform: translate(-50%, -50%); top: 50%;\"\n (click)=\"onMarkerClick($event, marker)\">\n </div>\n \n <div \n class=\"cqa-absolute cqa-left-0 cqa-top-0 cqa-h-full cqa-bg-blue-500 cqa-rounded-full\"\n [style.width.%]=\"progress\"\n [style.transition]=\"dragging ? 'none' : 'width 100ms'\"\n style=\"pointer-events: none; z-index: 2;\">\n </div>\n \n <div \n class=\"cqa-absolute cqa-top-1/2 cqa-w-3 cqa-h-3 cqa-bg-blue-600 cqa-rounded-full cqa-cursor-grab active:cqa-cursor-grabbing cqa-shadow-md\"\n [style.left.%]=\"progress\"\n style=\"transform: translate(-50%, -50%); z-index: 60;\"\n (mousedown)=\"startDrag($event)\">\n </div>\n </div>\n\n <span class=\"cqa-text-[#9CA3AF] cqa-text-[9px] cqa-font-normal cqa-whitespace-nowrap cqa-select-none\">\n {{ formatTime(totalDuration / 1000) }}\n </span>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"!isLive && currentView === 'screenshots'\" class=\"cqa-h-full\">\n <div class=\"cqa-w-full cqa-py-4 cqa-h-full cqa-flex cqa-items-center\" *ngIf=\"screenShotUrl\">\n <ng-container *ngIf=\"hasDeviceFrame\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-p-4': platformType === 'browser'}\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center cqa-max-h-full\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser', 'cqa-min-w-max': platformType === 'device'}\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n [ngClass]=\"{'cqa-max-h-[inherit]': platformType === 'browser', 'cqa-max-h-full': platformType !== 'browser'}\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-bg-white': platformType !== 'browser'}\">\n <img\n [src]=\"screenShotUrl\"\n alt=\"Screenshot\"\n [ngClass]=\"{'cqa-z-20': platformType === 'browser'}\"\n class=\"cqa-object-contain cqa-w-full cqa-h-full cqa-block cqa-bg-[##F2F2F2]\"\n />\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!screenShotUrl\">\n No screenshot available\n </div>\n </div>\n\n <div *ngIf=\"!isLive && currentView === 'trace'\" class=\"cqa-h-full cqa-flex cqa-flex-col cqa-justify-center\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-relative\" *ngIf=\"traceViewUrl\" [ngClass]=\"{'!cqa-h-full': platformType === 'device'}\" style=\"padding-top: 48px; padding-bottom: 0px;\">\n <div class=\"cqa-w-full cqa-h-full cqa-overflow-hidden cqa-relative\">\n <iframe \n [src]=\"safeTraceUrl\" \n title=\"Trace Viewer\"\n class=\"cqa-object-contain cqa-w-full cqa-min-h-[250px] cqa-max-h-full cqa-block cqa-bg-[##F2F2F2]\"\n style=\"margin-top: -48px; height: calc(100% + 48px);\"\n frameborder=\"0\"\n allowfullscreen\n width=\"100%\"\n loading=\"lazy\"\n (load)=\"onTraceViewerLoad()\"\n (error)=\"onTraceViewerError()\">\n </iframe>\n </div>\n \n <div *ngIf=\"traceViewerLoading\" class=\"cqa-absolute cqa-inset-0 cqa-bg-[#F3F4F6] cqa-flex cqa-items-center cqa-justify-center cqa-z-10\">\n <div class=\"cqa-text-center cqa-text-gray-400 cqa-text-sm\">\n Loading trace viewer...\n </div>\n </div>\n \n <div *ngIf=\"traceViewerError\" class=\"cqa-absolute cqa-inset-0 cqa-bg-[#F3F4F6] cqa-flex cqa-items-center cqa-justify-center cqa-z-10\">\n <div class=\"cqa-text-center cqa-text-gray-400 cqa-text-sm\">\n Failed to load trace viewer\n </div>\n </div>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!traceViewUrl\">\n No trace available\n </div>\n </div> \n </div>\n</div>", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: SegmentControlComponent, selector: "cqa-segment-control", inputs: ["segments", "value", "disabled", "containerBgColor"], outputs: ["valueChange"] }, { type: i2$3.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "diameter", "strokeWidth", "mode", "value"], exportAs: ["matProgressSpinner"] }], directives: [{ type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
13022
+ SimulatorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: SimulatorComponent, selector: "cqa-simulator", inputs: { videoUrl: "videoUrl", videoUrls: "videoUrls", videoCurrentDuration: "videoCurrentDuration", stepMarkers: "stepMarkers", screenShotUrl: "screenShotUrl", traceViewUrl: "traceViewUrl", platformName: "platformName", platformType: "platformType", platform: "platform", deviceName: "deviceName", isLive: "isLive", liveStatus: "liveStatus", liveLoadingLabel: "liveLoadingLabel", isContentVideoLoading: "isContentVideoLoading", failedStatusMessage: "failedStatusMessage", isVNCSessionIntruppted: "isVNCSessionIntruppted", vncSessionIntupptedMessage: "vncSessionIntupptedMessage", selectedView: "selectedView", hideVideoTab: "hideVideoTab", browserViewPort: "browserViewPort" }, outputs: { videoTimeUpdate: "videoTimeUpdate", videoPlay: "videoPlay", videoPause: "videoPause", markerHit: "markerHit", isVideoPlayingChange: "isVideoPlayingChange" }, viewQueries: [{ propertyName: "vplayerRef", first: true, predicate: ["vplayer"], descendants: true }, { propertyName: "timelineBarRef", first: true, predicate: ["timelineBar"], descendants: true }, { propertyName: "speedControlContainerRef", first: true, predicate: ["speedControlContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-ui-root\" style=\"background-color: #F3F4F6; height: 100%; display: flex; flex-direction: column;\" [ngStyle]=\"{\n position: isFullScreen ? 'fixed' : null,\n inset: isFullScreen ? '1rem' : null,\n zIndex: isFullScreen ? '50' : null,\n boxShadow: isFullScreen ? '0px 13px 25px -12px rgba(0, 0, 0, 0.25)' : null,\n borderRadius: isFullScreen ? '.5rem' : null,\n border: isFullScreen ? '1px solid #E5E7EB' : null,\n width: isFullScreen ? 'calc(100% - 32px)' : null,\n height: isFullScreen ? 'calc(100% - 32px)' : '100%',\n overflow: isFullScreen ? 'hidden' : null\n}\">\n <div class=\"cqa-w-full cqa-py-1 cqa-px-2 cqa-bg-[#FFFFFF]\" style=\"border-bottom: 1px solid #E5E7EB;box-shadow: 0px 1px 2px 0px #0000000D;\">\n <div class=\"cqa-w-full cqa-flex cqa-items-center cqa-justify-between cqa-flex-wrap\">\n <div class=\"cqa-flex cqa-items-center\">\n <div *ngIf=\"isLive\" class=\"cqa-h-[21px] cqa-inline-flex cqa-items-center cqa-gap-1.5 cqa-mr-2 cqa-px-[9px] cqa-py-[3px] cqa-bg-[#FCD9D9] cqa-rounded-[6px]\" style=\"border: 1px solid #F9BFBF;\">\n <span class=\"cqa-relative cqa-w-2 cqa-h-2 cqa-rounded-full cqa-bg-[#F47F7F]\" style=\"flex-shrink: 0;\">\n <span class=\"cqa-absolute cqa-inset-0 cqa-rounded-full cqa-bg-[#F47F7F] cqa-opacity-75 cqa-animate-ping\"></span>\n </span>\n <span class=\"cqa-text-[10px] cqa-font-medium cqa-text-[#C63535] cqa-leading-[15px]\">Live</span>\n </div>\n <mat-icon *ngIf=\"platformType === 'browser'\" style=\"width: 10px; height: 10px;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <g clip-path=\"url(#clip0_935_15847)\">\n <path\n d=\"M0.625 5C0.625 6.16032 1.08594 7.27312 1.90641 8.09359C2.72688 8.91406 3.83968 9.375 5 9.375C6.16032 9.375 7.27312 8.91406 8.09359 8.09359C8.91406 7.27312 9.375 6.16032 9.375 5C9.375 3.83968 8.91406 2.72688 8.09359 1.90641C7.27312 1.08594 6.16032 0.625 5 0.625C3.83968 0.625 2.72688 1.08594 1.90641 1.90641C1.08594 2.72688 0.625 3.83968 0.625 5Z\"\n stroke=\"#9CA3AF\" stroke-width=\"0.6\" stroke-linejoin=\"round\" />\n <path\n d=\"M3.125 5C3.125 3.83968 3.32254 2.72688 3.67417 1.90641C4.02581 1.08594 4.50272 0.625 5 0.625C5.49728 0.625 5.97419 1.08594 6.32582 1.90641C6.67746 2.72688 6.875 3.83968 6.875 5C6.875 6.16032 6.67746 7.27312 6.32582 8.09359C5.97419 8.91406 5.49728 9.375 5 9.375C4.50272 9.375 4.02581 8.91406 3.67417 8.09359C3.32254 7.27312 3.125 6.16032 3.125 5Z\"\n stroke=\"#9CA3AF\" stroke-width=\"0.6\" stroke-linejoin=\"round\" />\n <path d=\"M0.9375 6.45866H9.0625M0.9375 3.54199H9.0625\" stroke=\"#9CA3AF\" stroke-width=\"0.6\"\n stroke-linecap=\"round\" />\n </g>\n <defs>\n <clipPath id=\"clip0_935_15847\">\n <rect width=\"10\" height=\"10\" fill=\"white\" />\n </clipPath>\n </defs>\n </svg>\n </mat-icon>\n <mat-icon *ngIf=\"platformType === 'device'\" style=\"width: 10px; height: 10px;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M7.08325 0.833008H2.91659C2.45635 0.833008 2.08325 1.2061 2.08325 1.66634V8.33301C2.08325 8.79324 2.45635 9.16634 2.91659 9.16634H7.08325C7.54349 9.16634 7.91658 8.79324 7.91658 8.33301V1.66634C7.91658 1.2061 7.54349 0.833008 7.08325 0.833008Z\" stroke=\"#6B7280\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M5 7.5H5.00417\" stroke=\"#6B7280\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </mat-icon>\n <p class=\"cqa-text-sm !cqa-text-[10px] cqa-text-[#6B7280] cqa-ml-2\">\n {{ platformName }}\n <span\n *ngIf=\"platformType === 'browser'\"\n class=\"cqa-ml-1\"\n [matTooltip]=\"'Screen size: ' + effectiveBrowserViewPort.width + 'x' + effectiveBrowserViewPort.height\"\n matTooltipPosition=\"below\"\n >\n \u00B7\n <span class=\"cqa-ml-1\">\n {{ effectiveBrowserViewPort.width }}x{{ effectiveBrowserViewPort.height }}\n </span>\n </span>\n </p>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div *ngIf=\"isLive\" [ngClass]=\"getStatusBadgeClass()\">\n <span [ngClass]=\"getStatusTextClass()\">{{ liveStatus }}</span>\n </div>\n\n <ng-container *ngIf=\"!isLive\">\n <cqa-segment-control \n [segments]=\"segments\" \n [value]=\"currentView\"\n (valueChange)=\"onSegmentChange($event)\">\n </cqa-segment-control>\n \n <div *ngIf=\"!isFullScreen\" \n class=\"cqa-p-1 cqa-cursor-pointer hover:cqa-bg-gray-100 cqa-rounded-sm cqa-transition-colors\"\n (click)=\"toggleFullScreen()\"\n title=\"Expand\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M6.25 1.25H8.75V3.75\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.74992 1.25L5.83325 4.16667\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M1.25 8.74967L4.16667 5.83301\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M3.75 8.75H1.25V6.25\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n\n <div *ngIf=\"isFullScreen\" \n class=\"cqa-p-1 cqa-cursor-pointer hover:cqa-bg-gray-100 cqa-rounded-sm cqa-transition-colors\"\n (click)=\"toggleFullScreen()\"\n title=\"Exit full screen\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M8.75 6.25H6.25V8.75\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.25008 6.25L9.16675 9.16667\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M0.833252 0.833008L3.74992 3.74967\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M1.25 3.75H3.75V1.25\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n </ng-container>\n </div>\n </div>\n </div>\n <div class=\"cqa-w-full cqa-bg-[#F3F4F6] cqa-h-[calc(100%-41px)]\">\n <!-- Live Content View -->\n <div *ngIf=\"isLive\" class=\"cqa-h-full cqa-flex cqa-flex-col cqa-justify-center cqa-relative\">\n <ng-container *ngIf=\"hasDeviceFrame;\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center cqa-p-4\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser', 'cqa-max-h-full cqa-h-full': platformType !== 'browser' || !isLive, 'cqa-min-w-max': platformType === 'device', '!cqa-h-full !cqa-max-h-[500px]': shouldApplySmallHeightClasses}\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-max-h-full cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-z-20': platformType === 'browser', 'cqa-bg-white': platformType !== 'browser'}\">\n <!-- Loading State -->\n <div *ngIf=\"isContentVideoLoading\" class=\"cqa-p-10 cqa-text-center cqa-h-full cqa-flex cqa-flex-col cqa-items-center cqa-justify-center\">\n <div class=\"cqa-mb-4\">\n <mat-progress-spinner mode=\"indeterminate\" diameter=\"40\"></mat-progress-spinner>\n </div>\n <p class=\"cqa-text-gray-400 cqa-text-sm\">{{ liveLoadingLabel }}</p>\n </div>\n\n <!-- Live Content (when not loading) -->\n <div *ngIf=\"!isContentVideoLoading\" class=\"cqa-w-full cqa-h-full cqa-flex cqa-flex-col cqa-items-center cqa-justify-center cqa-relative\">\n <div *ngIf=\"liveStatus === 'Failed' && failedStatusMessage\" class=\"cqa-p-6 cqa-text-center cqa-w-full\">\n <div class=\"cqa-inline-flex cqa-items-center cqa-gap-2 cqa-px-4 cqa-py-3 cqa-bg-[#FCD9D9] cqa-border cqa-border-[#F9BFBF] cqa-rounded-lg\">\n <mat-icon style=\"width: 18px; height: 18px; color: #C63535; font-size: 18px;\">error</mat-icon>\n <p class=\"cqa-text-[#C63535] cqa-text-sm cqa-font-medium cqa-m-0\">{{ failedStatusMessage }}</p>\n </div>\n </div>\n <ng-content *ngIf=\"liveStatus !== 'Failed' || !failedStatusMessage\"></ng-content>\n </div>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n\n <!-- Normal Video View (when not live) -->\n <div *ngIf=\"!isLive && currentView === 'video'\"\n class=\"cqa-h-full cqa-flex cqa-flex-col\"\n tabindex=\"0\"\n role=\"region\"\n aria-label=\"Video playback\"\n (keydown)=\"onVideoKeydown($event)\">\n <div class=\"cqa-w-full cqa-py-4 cqa-flex cqa-items-center cqa-max-h-[calc(100%-97px)]\" *ngIf=\"currentVideoUrl\" [ngClass]=\"{'!cqa-h-full': platformType === 'device', 'cqa-mt-auto': hasDeviceFrame}\">\n <ng-container *ngIf=\"hasDeviceFrame\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-p-4': platformType === 'browser'}\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center cqa-max-h-full\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser', 'cqa-min-w-max': platformType === 'device'}\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-max-h-full cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-bg-white': platformType !== 'browser'}\">\n <video\n #vplayer\n class=\"cqa-object-cover cqa-w-full cqa-h-full cqa-block cqa-bg-[##F2F2F2]\"\n [src]=\"currentVideoUrl\"\n type=\"video/webm\"\n [ngClass]=\"{'cqa-z-20': platformType === 'browser'}\"\n (loadedmetadata)=\"onVideoMetadataLoaded()\"\n (canplay)=\"onVideoCanPlay()\"\n (ended)=\"onVideoEnded()\"\n ></video>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!currentVideoUrl\">\n <ng-container *ngIf=\"isVNCSessionIntruppted && vncSessionIntupptedMessage; else noVideoDefault\">\n <p class=\"cqa-text-sm cqa-text-gray-600\">\n {{ vncSessionIntupptedMessage }}\n </p>\n </ng-container>\n <ng-template #noVideoDefault>\n <span>No video recording found</span>\n </ng-template>\n </div>\n \n <div class=\"cqa-px-2 cqa-py-2 cqa-bg-white\" style=\"border-top: 1px solid #E5E7EB;\" [ngClass]=\"{'cqa-mt-auto': hasDeviceFrame}\" *ngIf=\"currentVideoUrl && !isLive\">\n <span class=\"cqa-text-[#6B7280] cqa-text-[12px] cqa-font-medium cqa-mb-2 cqa-whitespace-nowrap cqa-block\">\n Video {{ currentVideoIndex + 1 }} playing out of {{ videoUrls?.length || 0 }}\n </span>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <button \n *ngIf=\"hasMultipleVideos\"\n type=\"button\"\n class=\"cqa-bg-transparent cqa-border-none cqa-cursor-pointer !cqa-px-0 cqa-flex cqa-items-center cqa-justify-center hover:cqa-opacity-70 cqa-transition-opacity cqa-outline-none\"\n style=\"pointer-events: auto;\"\n [disabled]=\"currentVideoIndex === 0\"\n [ngClass]=\"{'cqa-opacity-50 cqa-cursor-not-allowed': currentVideoIndex === 0}\"\n (click)=\"prevVideo()\"\n matTooltip=\"Previous video\"\n matTooltipPosition=\"above\">\n <mat-icon class=\"cqa-w-4 cqa-h-4 !cqa-text-[16px] cqa-text-[#374151]\" [ngClass]=\"{'cqa-opacity-50 cqa-cursor-not-allowed': currentVideoIndex === 0}\">skip_previous</mat-icon>\n </button>\n\n <div class=\"cqa-flex cqa-items-center cqa-justify-center\" style=\"width: 16px; height: 16px;\">\n <mat-progress-spinner\n *ngIf=\"isPlayerSwitching\"\n mode=\"indeterminate\"\n diameter=\"16\"\n class=\"cqa-inline-block\">\n </mat-progress-spinner>\n <button \n *ngIf=\"!isPlayerSwitching\"\n type=\"button\"\n class=\"cqa-bg-transparent cqa-border-none cqa-cursor-pointer !cqa-px-0 cqa-flex cqa-items-center cqa-justify-center hover:cqa-opacity-70 cqa-transition-opacity cqa-outline-none\"\n style=\"pointer-events: auto;\"\n (click)=\"togglePlay()\"\n matTooltip=\"{{ isPlaying ? 'Pause' : 'Play' }}\"\n matTooltipPosition=\"above\">\n <span *ngIf=\"!isPlaying\" class=\"cqa-flex cqa-items-center cqa-justify-center\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M3 2L13 8L3 14V2Z\" fill=\"#374151\"/>\n </svg>\n </span>\n <span *ngIf=\"isPlaying\" class=\"cqa-flex cqa-items-center cqa-justify-center\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"3\" y=\"2\" width=\"3\" height=\"12\" fill=\"#374151\"/>\n <rect x=\"10\" y=\"2\" width=\"3\" height=\"12\" fill=\"#374151\"/>\n </svg>\n </span>\n </button>\n </div>\n\n <button \n *ngIf=\"hasMultipleVideos\"\n type=\"button\"\n class=\"cqa-bg-transparent cqa-border-none cqa-cursor-pointer !cqa-px-0 cqa-flex cqa-items-center cqa-justify-center hover:cqa-opacity-70 cqa-transition-opacity cqa-outline-none\"\n style=\"pointer-events: auto;\"\n [disabled]=\"videoUrls && (currentVideoIndex >= videoUrls.length - 1)\"\n [ngClass]=\"{'cqa-opacity-50 cqa-cursor-not-allowed': videoUrls && (currentVideoIndex >= videoUrls.length - 1)}\"\n (click)=\"nextVideo()\"\n matTooltip=\"Next video\"\n matTooltipPosition=\"above\">\n <mat-icon class=\"cqa-w-4 cqa-h-4 !cqa-text-[16px] cqa-text-[#374151]\" [ngClass]=\"{'cqa-opacity-50 cqa-cursor-not-allowed': videoUrls && (currentVideoIndex >= videoUrls.length - 1)}\">skip_next</mat-icon>\n </button>\n\n <span class=\"cqa-text-[#9CA3AF] cqa-text-[9px] cqa-font-normal cqa-whitespace-nowrap cqa-select-none\">\n {{ formatTime(vplayer?.nativeElement?.currentTime || 0) }}\n </span>\n\n <div #speedControlContainer class=\"cqa-relative cqa-mr-[8px] cqa-flex cqa-items-center cqa-justify-center\">\n <button\n type=\"button\"\n class=\"cqa-bg-transparent cqa-border-none cqa-cursor-pointer cqa-text-[#9CA3AF] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-whitespace-nowrap cqa-select-none hover:cqa-opacity-70 cqa-transition-opacity cqa-outline-none cqa-px-1\"\n (click)=\"toggleSpeedControl()\"\n [matTooltip]=\"'Playback Speed'\"\n [matTooltipPosition]=\"'below'\">\n {{ currentSpeed }}\n </button>\n \n <div \n *ngIf=\"isSpeedControlOpen\"\n class=\"cqa-absolute cqa-bottom-full cqa-mb-2 cqa-right-0 cqa-bg-[#F0F0F1] cqa-rounded-lg cqa-overflow-hidden cqa-shadow-lg cqa-z-50\"\n style=\"min-width: max-content; left: 50%; bottom: 0%; transform: translate(-50%, -50%);\">\n <cqa-segment-control\n [segments]=\"speedSegments\"\n [value]=\"currentSpeed\"\n [containerBgColor]=\"'#F0F0F1'\"\n (valueChange)=\"onSpeedChange($event)\">\n </cqa-segment-control>\n </div>\n </div>\n \n <div class=\"cqa-flex-1 cqa-min-w-0\">\n <div \n #timelineBar\n class=\"cqa-relative cqa-h-1 cqa-bg-gray-200 cqa-rounded-full cqa-cursor-pointer cqa-w-full\"\n (click)=\"onTimelineClick($event)\">\n \n <div \n *ngFor=\"let marker of currentVideoMarkers\" \n class=\"cqa-absolute cqa-rounded-full\"\n [style.left.%]=\"getStepLeftPosition(marker)\"\n [style.width]=\"'8px'\"\n [style.height]=\"'8px'\"\n [style.background]=\"getGlobalMarkerColor(marker.level)\"\n [style.border]=\"'2px solid ' + getGlobalMarkerResultColor(marker.result)\"\n [style.box-sizing]=\"'border-box'\"\n [attr.title]=\"marker.title || ''\"\n style=\"pointer-events: auto; z-index: 50; cursor: pointer; transform: translate(-50%, -50%); top: 50%;\"\n (click)=\"onMarkerClick($event, marker)\">\n </div>\n \n <div \n class=\"cqa-absolute cqa-left-0 cqa-top-0 cqa-h-full cqa-bg-blue-500 cqa-rounded-full\"\n [style.width.%]=\"progress\"\n [style.transition]=\"dragging ? 'none' : 'width 100ms'\"\n style=\"pointer-events: none; z-index: 2;\">\n </div>\n \n <div \n class=\"cqa-absolute cqa-top-1/2 cqa-w-3 cqa-h-3 cqa-bg-blue-600 cqa-rounded-full cqa-cursor-grab active:cqa-cursor-grabbing cqa-shadow-md\"\n [style.left.%]=\"progress\"\n style=\"transform: translate(-50%, -50%); z-index: 60;\"\n (mousedown)=\"startDrag($event)\">\n </div>\n </div>\n </div>\n\n <span class=\"cqa-text-[#9CA3AF] cqa-text-[9px] cqa-font-normal cqa-whitespace-nowrap cqa-select-none\">\n {{ formatTime(vplayer?.nativeElement?.duration || 0) }}\n </span>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"!isLive && currentView === 'screenshots'\" class=\"cqa-h-full\">\n <div class=\"cqa-w-full cqa-py-4 cqa-h-full cqa-flex cqa-items-center\" *ngIf=\"screenShotUrl\">\n <ng-container *ngIf=\"hasDeviceFrame\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-p-4': platformType === 'browser'}\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center cqa-max-h-full\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser', 'cqa-min-w-max': platformType === 'device'}\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n [ngClass]=\"{'cqa-max-h-[inherit]': platformType === 'browser', 'cqa-max-h-full': platformType !== 'browser'}\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-bg-white': platformType !== 'browser'}\">\n <img\n [src]=\"screenShotUrl\"\n alt=\"Screenshot\"\n [ngClass]=\"{'cqa-z-20': platformType === 'browser'}\"\n class=\"cqa-object-contain cqa-w-full cqa-h-full cqa-block cqa-bg-[##F2F2F2]\"\n />\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!screenShotUrl\">\n No screenshot available\n </div>\n </div>\n\n <div *ngIf=\"!isLive && currentView === 'trace'\" class=\"cqa-h-full cqa-flex cqa-flex-col cqa-justify-center\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-relative\" *ngIf=\"traceViewUrl\" [ngClass]=\"{'!cqa-h-full': platformType === 'device'}\" style=\"padding-top: 48px; padding-bottom: 0px;\">\n <div class=\"cqa-w-full cqa-h-full cqa-overflow-hidden cqa-relative\">\n <iframe \n [src]=\"safeTraceUrl\" \n title=\"Trace Viewer\"\n class=\"cqa-object-contain cqa-w-full cqa-min-h-[250px] cqa-max-h-full cqa-block cqa-bg-[##F2F2F2]\"\n style=\"margin-top: -48px; height: calc(100% + 48px);\"\n frameborder=\"0\"\n allowfullscreen\n width=\"100%\"\n loading=\"lazy\"\n (load)=\"onTraceViewerLoad()\"\n (error)=\"onTraceViewerError()\">\n </iframe>\n </div>\n \n <div *ngIf=\"traceViewerLoading\" class=\"cqa-absolute cqa-inset-0 cqa-bg-[#F3F4F6] cqa-flex cqa-items-center cqa-justify-center cqa-z-10\">\n <div class=\"cqa-text-center cqa-text-gray-400 cqa-text-sm\">\n Loading trace viewer...\n </div>\n </div>\n \n <div *ngIf=\"traceViewerError\" class=\"cqa-absolute cqa-inset-0 cqa-bg-[#F3F4F6] cqa-flex cqa-items-center cqa-justify-center cqa-z-10\">\n <div class=\"cqa-text-center cqa-text-gray-400 cqa-text-sm\">\n Failed to load trace viewer\n </div>\n </div>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!traceViewUrl\">\n No trace available\n </div>\n </div> \n </div>\n</div>", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: SegmentControlComponent, selector: "cqa-segment-control", inputs: ["segments", "value", "disabled", "containerBgColor"], outputs: ["valueChange"] }, { type: i2$3.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "diameter", "strokeWidth", "mode", "value"], exportAs: ["matProgressSpinner"] }], directives: [{ type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
13166
13023
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: SimulatorComponent, decorators: [{
13167
13024
  type: Component,
13168
- args: [{ selector: 'cqa-simulator', template: "<div class=\"cqa-ui-root\" style=\"background-color: #F3F4F6; height: 100%; display: flex; flex-direction: column;\" [ngStyle]=\"{\n position: isFullScreen ? 'fixed' : null,\n inset: isFullScreen ? '1rem' : null,\n zIndex: isFullScreen ? '50' : null,\n boxShadow: isFullScreen ? '0px 13px 25px -12px rgba(0, 0, 0, 0.25)' : null,\n borderRadius: isFullScreen ? '.5rem' : null,\n border: isFullScreen ? '1px solid #E5E7EB' : null,\n width: isFullScreen ? 'calc(100% - 32px)' : null,\n height: isFullScreen ? 'calc(100% - 32px)' : '100%',\n overflow: isFullScreen ? 'hidden' : null\n}\">\n <div class=\"cqa-w-full cqa-py-1 cqa-px-2 cqa-bg-[#FFFFFF]\" style=\"border-bottom: 1px solid #E5E7EB;box-shadow: 0px 1px 2px 0px #0000000D;\">\n <div class=\"cqa-w-full cqa-flex cqa-items-center cqa-justify-between cqa-flex-wrap\">\n <div class=\"cqa-flex cqa-items-center\">\n <div *ngIf=\"isLive\" class=\"cqa-h-[21px] cqa-inline-flex cqa-items-center cqa-gap-1.5 cqa-mr-2 cqa-px-[9px] cqa-py-[3px] cqa-bg-[#FCD9D9] cqa-rounded-[6px]\" style=\"border: 1px solid #F9BFBF;\">\n <span class=\"cqa-relative cqa-w-2 cqa-h-2 cqa-rounded-full cqa-bg-[#F47F7F]\" style=\"flex-shrink: 0;\">\n <span class=\"cqa-absolute cqa-inset-0 cqa-rounded-full cqa-bg-[#F47F7F] cqa-opacity-75 cqa-animate-ping\"></span>\n </span>\n <span class=\"cqa-text-[10px] cqa-font-medium cqa-text-[#C63535] cqa-leading-[15px]\">Live</span>\n </div>\n <mat-icon *ngIf=\"platformType === 'browser'\" style=\"width: 10px; height: 10px;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <g clip-path=\"url(#clip0_935_15847)\">\n <path\n d=\"M0.625 5C0.625 6.16032 1.08594 7.27312 1.90641 8.09359C2.72688 8.91406 3.83968 9.375 5 9.375C6.16032 9.375 7.27312 8.91406 8.09359 8.09359C8.91406 7.27312 9.375 6.16032 9.375 5C9.375 3.83968 8.91406 2.72688 8.09359 1.90641C7.27312 1.08594 6.16032 0.625 5 0.625C3.83968 0.625 2.72688 1.08594 1.90641 1.90641C1.08594 2.72688 0.625 3.83968 0.625 5Z\"\n stroke=\"#9CA3AF\" stroke-width=\"0.6\" stroke-linejoin=\"round\" />\n <path\n d=\"M3.125 5C3.125 3.83968 3.32254 2.72688 3.67417 1.90641C4.02581 1.08594 4.50272 0.625 5 0.625C5.49728 0.625 5.97419 1.08594 6.32582 1.90641C6.67746 2.72688 6.875 3.83968 6.875 5C6.875 6.16032 6.67746 7.27312 6.32582 8.09359C5.97419 8.91406 5.49728 9.375 5 9.375C4.50272 9.375 4.02581 8.91406 3.67417 8.09359C3.32254 7.27312 3.125 6.16032 3.125 5Z\"\n stroke=\"#9CA3AF\" stroke-width=\"0.6\" stroke-linejoin=\"round\" />\n <path d=\"M0.9375 6.45866H9.0625M0.9375 3.54199H9.0625\" stroke=\"#9CA3AF\" stroke-width=\"0.6\"\n stroke-linecap=\"round\" />\n </g>\n <defs>\n <clipPath id=\"clip0_935_15847\">\n <rect width=\"10\" height=\"10\" fill=\"white\" />\n </clipPath>\n </defs>\n </svg>\n </mat-icon>\n <mat-icon *ngIf=\"platformType === 'device'\" style=\"width: 10px; height: 10px;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M7.08325 0.833008H2.91659C2.45635 0.833008 2.08325 1.2061 2.08325 1.66634V8.33301C2.08325 8.79324 2.45635 9.16634 2.91659 9.16634H7.08325C7.54349 9.16634 7.91658 8.79324 7.91658 8.33301V1.66634C7.91658 1.2061 7.54349 0.833008 7.08325 0.833008Z\" stroke=\"#6B7280\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M5 7.5H5.00417\" stroke=\"#6B7280\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </mat-icon>\n <p class=\"cqa-text-sm !cqa-text-[10px] cqa-text-[#6B7280] cqa-ml-2\">\n {{ platformName }}\n <span\n *ngIf=\"platformType === 'browser'\"\n class=\"cqa-ml-1\"\n [matTooltip]=\"'Screen size: ' + effectiveBrowserViewPort.width + 'x' + effectiveBrowserViewPort.height\"\n matTooltipPosition=\"below\"\n >\n \u00B7\n <span class=\"cqa-ml-1\">\n {{ effectiveBrowserViewPort.width }}x{{ effectiveBrowserViewPort.height }}\n </span>\n </span>\n </p>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div *ngIf=\"isLive\" [ngClass]=\"getStatusBadgeClass()\">\n <span [ngClass]=\"getStatusTextClass()\">{{ liveStatus }}</span>\n </div>\n\n <ng-container *ngIf=\"!isLive\">\n <cqa-segment-control \n [segments]=\"segments\" \n [value]=\"currentView\"\n (valueChange)=\"onSegmentChange($event)\">\n </cqa-segment-control>\n \n <div *ngIf=\"!isFullScreen\" \n class=\"cqa-p-1 cqa-cursor-pointer hover:cqa-bg-gray-100 cqa-rounded-sm cqa-transition-colors\"\n (click)=\"toggleFullScreen()\"\n title=\"Expand\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M6.25 1.25H8.75V3.75\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.74992 1.25L5.83325 4.16667\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M1.25 8.74967L4.16667 5.83301\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M3.75 8.75H1.25V6.25\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n\n <div *ngIf=\"isFullScreen\" \n class=\"cqa-p-1 cqa-cursor-pointer hover:cqa-bg-gray-100 cqa-rounded-sm cqa-transition-colors\"\n (click)=\"toggleFullScreen()\"\n title=\"Exit full screen\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M8.75 6.25H6.25V8.75\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.25008 6.25L9.16675 9.16667\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M0.833252 0.833008L3.74992 3.74967\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M1.25 3.75H3.75V1.25\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n </ng-container>\n </div>\n </div>\n </div>\n <div class=\"cqa-w-full cqa-bg-[#F3F4F6] cqa-h-[calc(100%-41px)]\">\n <!-- Live Content View -->\n <div *ngIf=\"isLive\" class=\"cqa-h-full cqa-flex cqa-flex-col cqa-justify-center cqa-relative\">\n <ng-container *ngIf=\"hasDeviceFrame;\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center cqa-p-4\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser', 'cqa-max-h-full cqa-h-full': platformType !== 'browser' || !isLive, 'cqa-min-w-max': platformType === 'device'}\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-max-h-full cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-z-20': platformType === 'browser', 'cqa-bg-white': platformType !== 'browser'}\">\n <!-- Loading State -->\n <div *ngIf=\"isContentVideoLoading\" class=\"cqa-p-10 cqa-text-center cqa-h-full cqa-flex cqa-flex-col cqa-items-center cqa-justify-center\">\n <div class=\"cqa-mb-4\">\n <mat-progress-spinner mode=\"indeterminate\" diameter=\"40\"></mat-progress-spinner>\n </div>\n <p class=\"cqa-text-gray-400 cqa-text-sm\">{{ liveLoadingLabel }}</p>\n </div>\n\n <!-- Live Content (when not loading) -->\n <div *ngIf=\"!isContentVideoLoading\" class=\"cqa-w-full cqa-h-full cqa-flex cqa-flex-col cqa-items-center cqa-justify-center cqa-relative\">\n <div *ngIf=\"liveStatus === 'Failed' && failedStatusMessage\" class=\"cqa-p-6 cqa-text-center cqa-w-full\">\n <div class=\"cqa-inline-flex cqa-items-center cqa-gap-2 cqa-px-4 cqa-py-3 cqa-bg-[#FCD9D9] cqa-border cqa-border-[#F9BFBF] cqa-rounded-lg\">\n <mat-icon style=\"width: 18px; height: 18px; color: #C63535; font-size: 18px;\">error</mat-icon>\n <p class=\"cqa-text-[#C63535] cqa-text-sm cqa-font-medium cqa-m-0\">{{ failedStatusMessage }}</p>\n </div>\n </div>\n <ng-content *ngIf=\"liveStatus !== 'Failed' || !failedStatusMessage\"></ng-content>\n </div>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n\n <!-- Normal Video View (when not live) -->\n <div *ngIf=\"!isLive && currentView === 'video'\"\n class=\"cqa-h-full cqa-flex cqa-flex-col\"\n tabindex=\"0\"\n role=\"region\"\n aria-label=\"Video playback\"\n (keydown)=\"onVideoKeydown($event)\">\n <div class=\"cqa-w-full cqa-py-4 cqa-flex cqa-items-center cqa-max-h-[calc(100%-83px)]\" *ngIf=\"currentVideoUrl\" [ngClass]=\"{'!cqa-h-full': platformType === 'device', 'cqa-mt-auto': hasDeviceFrame}\">\n <ng-container *ngIf=\"hasDeviceFrame\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-p-4': platformType === 'browser'}\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center cqa-max-h-full\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser', 'cqa-min-w-max': platformType === 'device'}\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-max-h-full cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-bg-white': platformType !== 'browser'}\">\n <video\n #vplayer\n class=\"cqa-object-cover cqa-w-full cqa-h-full cqa-block cqa-bg-[##F2F2F2]\"\n [src]=\"currentVideoUrl\"\n type=\"video/webm\"\n [ngClass]=\"{'cqa-z-20': platformType === 'browser'}\"\n (loadedmetadata)=\"onVideoMetadataLoaded()\"\n (canplay)=\"onVideoCanPlay()\"\n (ended)=\"onVideoEnded()\"\n ></video>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!currentVideoUrl\">\n <ng-container *ngIf=\"isVNCSessionIntruppted && vncSessionIntupptedMessage; else noVideoDefault\">\n <p class=\"cqa-text-sm cqa-text-gray-600\">\n {{ vncSessionIntupptedMessage }}\n </p>\n </ng-container>\n <ng-template #noVideoDefault>\n <span>No video recording found</span>\n </ng-template>\n </div>\n \n <div class=\"cqa-px-2 cqa-py-2 cqa-bg-white\" style=\"border-top: 1px solid #E5E7EB;\" [ngClass]=\"{'cqa-mt-auto': hasDeviceFrame}\" *ngIf=\"currentVideoUrl && !isLive\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-flex cqa-items-center cqa-justify-center\" style=\"width: 16px; height: 16px;\">\n <mat-progress-spinner\n *ngIf=\"isPlayerSwitching\"\n mode=\"indeterminate\"\n diameter=\"16\"\n class=\"cqa-inline-block\">\n </mat-progress-spinner>\n <button \n *ngIf=\"!isPlayerSwitching\"\n type=\"button\"\n class=\"cqa-bg-transparent cqa-border-none cqa-cursor-pointer !cqa-px-0 cqa-flex cqa-items-center cqa-justify-center hover:cqa-opacity-70 cqa-transition-opacity cqa-outline-none\"\n style=\"pointer-events: auto;\"\n (click)=\"togglePlay()\"\n matTooltip=\"{{ isPlaying ? 'Pause' : 'Play' }}\"\n matTooltipPosition=\"above\">\n <span *ngIf=\"!isPlaying\" class=\"cqa-flex cqa-items-center cqa-justify-center\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M3 2L13 8L3 14V2Z\" fill=\"#374151\"/>\n </svg>\n </span>\n <span *ngIf=\"isPlaying\" class=\"cqa-flex cqa-items-center cqa-justify-center\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"3\" y=\"2\" width=\"3\" height=\"12\" fill=\"#374151\"/>\n <rect x=\"10\" y=\"2\" width=\"3\" height=\"12\" fill=\"#374151\"/>\n </svg>\n </span>\n </button>\n </div>\n\n <span class=\"cqa-text-[#9CA3AF] cqa-text-[9px] cqa-font-normal cqa-whitespace-nowrap cqa-select-none\">\n {{ formatTime(globalCurrentTime / 1000) }}\n </span>\n\n <div #speedControlContainer class=\"cqa-relative cqa-mr-[8px] cqa-flex cqa-items-center cqa-justify-center\">\n <button\n type=\"button\"\n class=\"cqa-bg-transparent cqa-border-none cqa-cursor-pointer cqa-text-[#9CA3AF] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-whitespace-nowrap cqa-select-none hover:cqa-opacity-70 cqa-transition-opacity cqa-outline-none cqa-px-1\"\n (click)=\"toggleSpeedControl()\"\n [matTooltip]=\"'Playback Speed'\"\n [matTooltipPosition]=\"'below'\">\n {{ currentSpeed }}\n </button>\n \n <div \n *ngIf=\"isSpeedControlOpen\"\n class=\"cqa-absolute cqa-bottom-full cqa-mb-2 cqa-right-0 cqa-bg-[#F0F0F1] cqa-rounded-lg cqa-overflow-hidden cqa-shadow-lg cqa-z-50\"\n style=\"min-width: max-content; left: 50%; bottom: 0%; transform: translate(-50%, -50%);\">\n <cqa-segment-control\n [segments]=\"speedSegments\"\n [value]=\"currentSpeed\"\n [containerBgColor]=\"'#F0F0F1'\"\n (valueChange)=\"onSpeedChange($event)\">\n </cqa-segment-control>\n </div>\n </div>\n \n <div \n #timelineBar\n class=\"cqa-relative cqa-h-1 cqa-bg-gray-200 cqa-rounded-full cqa-cursor-pointer cqa-flex-1\"\n (click)=\"onTimelineClick($event)\">\n \n <div \n *ngFor=\"let marker of globalStepMarkers\" \n class=\"cqa-absolute cqa-rounded-full\"\n [style.left.%]=\"totalDuration > 0 ? (marker.globalTime / totalDuration) * 100 : 0\"\n [style.width]=\"'8px'\"\n [style.height]=\"'8px'\"\n [style.background]=\"getGlobalMarkerColor(marker.level)\"\n [style.border]=\"'2px solid ' + getGlobalMarkerResultColor(marker.result)\"\n [style.box-sizing]=\"'border-box'\"\n [attr.title]=\"marker.title || ''\"\n style=\"pointer-events: auto; z-index: 50; cursor: pointer; transform: translate(-50%, -50%); top: 50%;\"\n (click)=\"onMarkerClick($event, marker)\">\n </div>\n \n <div \n class=\"cqa-absolute cqa-left-0 cqa-top-0 cqa-h-full cqa-bg-blue-500 cqa-rounded-full\"\n [style.width.%]=\"progress\"\n [style.transition]=\"dragging ? 'none' : 'width 100ms'\"\n style=\"pointer-events: none; z-index: 2;\">\n </div>\n \n <div \n class=\"cqa-absolute cqa-top-1/2 cqa-w-3 cqa-h-3 cqa-bg-blue-600 cqa-rounded-full cqa-cursor-grab active:cqa-cursor-grabbing cqa-shadow-md\"\n [style.left.%]=\"progress\"\n style=\"transform: translate(-50%, -50%); z-index: 60;\"\n (mousedown)=\"startDrag($event)\">\n </div>\n </div>\n\n <span class=\"cqa-text-[#9CA3AF] cqa-text-[9px] cqa-font-normal cqa-whitespace-nowrap cqa-select-none\">\n {{ formatTime(totalDuration / 1000) }}\n </span>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"!isLive && currentView === 'screenshots'\" class=\"cqa-h-full\">\n <div class=\"cqa-w-full cqa-py-4 cqa-h-full cqa-flex cqa-items-center\" *ngIf=\"screenShotUrl\">\n <ng-container *ngIf=\"hasDeviceFrame\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-p-4': platformType === 'browser'}\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center cqa-max-h-full\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser', 'cqa-min-w-max': platformType === 'device'}\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n [ngClass]=\"{'cqa-max-h-[inherit]': platformType === 'browser', 'cqa-max-h-full': platformType !== 'browser'}\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-bg-white': platformType !== 'browser'}\">\n <img\n [src]=\"screenShotUrl\"\n alt=\"Screenshot\"\n [ngClass]=\"{'cqa-z-20': platformType === 'browser'}\"\n class=\"cqa-object-contain cqa-w-full cqa-h-full cqa-block cqa-bg-[##F2F2F2]\"\n />\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!screenShotUrl\">\n No screenshot available\n </div>\n </div>\n\n <div *ngIf=\"!isLive && currentView === 'trace'\" class=\"cqa-h-full cqa-flex cqa-flex-col cqa-justify-center\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-relative\" *ngIf=\"traceViewUrl\" [ngClass]=\"{'!cqa-h-full': platformType === 'device'}\" style=\"padding-top: 48px; padding-bottom: 0px;\">\n <div class=\"cqa-w-full cqa-h-full cqa-overflow-hidden cqa-relative\">\n <iframe \n [src]=\"safeTraceUrl\" \n title=\"Trace Viewer\"\n class=\"cqa-object-contain cqa-w-full cqa-min-h-[250px] cqa-max-h-full cqa-block cqa-bg-[##F2F2F2]\"\n style=\"margin-top: -48px; height: calc(100% + 48px);\"\n frameborder=\"0\"\n allowfullscreen\n width=\"100%\"\n loading=\"lazy\"\n (load)=\"onTraceViewerLoad()\"\n (error)=\"onTraceViewerError()\">\n </iframe>\n </div>\n \n <div *ngIf=\"traceViewerLoading\" class=\"cqa-absolute cqa-inset-0 cqa-bg-[#F3F4F6] cqa-flex cqa-items-center cqa-justify-center cqa-z-10\">\n <div class=\"cqa-text-center cqa-text-gray-400 cqa-text-sm\">\n Loading trace viewer...\n </div>\n </div>\n \n <div *ngIf=\"traceViewerError\" class=\"cqa-absolute cqa-inset-0 cqa-bg-[#F3F4F6] cqa-flex cqa-items-center cqa-justify-center cqa-z-10\">\n <div class=\"cqa-text-center cqa-text-gray-400 cqa-text-sm\">\n Failed to load trace viewer\n </div>\n </div>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!traceViewUrl\">\n No trace available\n </div>\n </div> \n </div>\n</div>", styles: [] }]
13025
+ args: [{ selector: 'cqa-simulator', template: "<div class=\"cqa-ui-root\" style=\"background-color: #F3F4F6; height: 100%; display: flex; flex-direction: column;\" [ngStyle]=\"{\n position: isFullScreen ? 'fixed' : null,\n inset: isFullScreen ? '1rem' : null,\n zIndex: isFullScreen ? '50' : null,\n boxShadow: isFullScreen ? '0px 13px 25px -12px rgba(0, 0, 0, 0.25)' : null,\n borderRadius: isFullScreen ? '.5rem' : null,\n border: isFullScreen ? '1px solid #E5E7EB' : null,\n width: isFullScreen ? 'calc(100% - 32px)' : null,\n height: isFullScreen ? 'calc(100% - 32px)' : '100%',\n overflow: isFullScreen ? 'hidden' : null\n}\">\n <div class=\"cqa-w-full cqa-py-1 cqa-px-2 cqa-bg-[#FFFFFF]\" style=\"border-bottom: 1px solid #E5E7EB;box-shadow: 0px 1px 2px 0px #0000000D;\">\n <div class=\"cqa-w-full cqa-flex cqa-items-center cqa-justify-between cqa-flex-wrap\">\n <div class=\"cqa-flex cqa-items-center\">\n <div *ngIf=\"isLive\" class=\"cqa-h-[21px] cqa-inline-flex cqa-items-center cqa-gap-1.5 cqa-mr-2 cqa-px-[9px] cqa-py-[3px] cqa-bg-[#FCD9D9] cqa-rounded-[6px]\" style=\"border: 1px solid #F9BFBF;\">\n <span class=\"cqa-relative cqa-w-2 cqa-h-2 cqa-rounded-full cqa-bg-[#F47F7F]\" style=\"flex-shrink: 0;\">\n <span class=\"cqa-absolute cqa-inset-0 cqa-rounded-full cqa-bg-[#F47F7F] cqa-opacity-75 cqa-animate-ping\"></span>\n </span>\n <span class=\"cqa-text-[10px] cqa-font-medium cqa-text-[#C63535] cqa-leading-[15px]\">Live</span>\n </div>\n <mat-icon *ngIf=\"platformType === 'browser'\" style=\"width: 10px; height: 10px;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <g clip-path=\"url(#clip0_935_15847)\">\n <path\n d=\"M0.625 5C0.625 6.16032 1.08594 7.27312 1.90641 8.09359C2.72688 8.91406 3.83968 9.375 5 9.375C6.16032 9.375 7.27312 8.91406 8.09359 8.09359C8.91406 7.27312 9.375 6.16032 9.375 5C9.375 3.83968 8.91406 2.72688 8.09359 1.90641C7.27312 1.08594 6.16032 0.625 5 0.625C3.83968 0.625 2.72688 1.08594 1.90641 1.90641C1.08594 2.72688 0.625 3.83968 0.625 5Z\"\n stroke=\"#9CA3AF\" stroke-width=\"0.6\" stroke-linejoin=\"round\" />\n <path\n d=\"M3.125 5C3.125 3.83968 3.32254 2.72688 3.67417 1.90641C4.02581 1.08594 4.50272 0.625 5 0.625C5.49728 0.625 5.97419 1.08594 6.32582 1.90641C6.67746 2.72688 6.875 3.83968 6.875 5C6.875 6.16032 6.67746 7.27312 6.32582 8.09359C5.97419 8.91406 5.49728 9.375 5 9.375C4.50272 9.375 4.02581 8.91406 3.67417 8.09359C3.32254 7.27312 3.125 6.16032 3.125 5Z\"\n stroke=\"#9CA3AF\" stroke-width=\"0.6\" stroke-linejoin=\"round\" />\n <path d=\"M0.9375 6.45866H9.0625M0.9375 3.54199H9.0625\" stroke=\"#9CA3AF\" stroke-width=\"0.6\"\n stroke-linecap=\"round\" />\n </g>\n <defs>\n <clipPath id=\"clip0_935_15847\">\n <rect width=\"10\" height=\"10\" fill=\"white\" />\n </clipPath>\n </defs>\n </svg>\n </mat-icon>\n <mat-icon *ngIf=\"platformType === 'device'\" style=\"width: 10px; height: 10px;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M7.08325 0.833008H2.91659C2.45635 0.833008 2.08325 1.2061 2.08325 1.66634V8.33301C2.08325 8.79324 2.45635 9.16634 2.91659 9.16634H7.08325C7.54349 9.16634 7.91658 8.79324 7.91658 8.33301V1.66634C7.91658 1.2061 7.54349 0.833008 7.08325 0.833008Z\" stroke=\"#6B7280\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M5 7.5H5.00417\" stroke=\"#6B7280\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </mat-icon>\n <p class=\"cqa-text-sm !cqa-text-[10px] cqa-text-[#6B7280] cqa-ml-2\">\n {{ platformName }}\n <span\n *ngIf=\"platformType === 'browser'\"\n class=\"cqa-ml-1\"\n [matTooltip]=\"'Screen size: ' + effectiveBrowserViewPort.width + 'x' + effectiveBrowserViewPort.height\"\n matTooltipPosition=\"below\"\n >\n \u00B7\n <span class=\"cqa-ml-1\">\n {{ effectiveBrowserViewPort.width }}x{{ effectiveBrowserViewPort.height }}\n </span>\n </span>\n </p>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div *ngIf=\"isLive\" [ngClass]=\"getStatusBadgeClass()\">\n <span [ngClass]=\"getStatusTextClass()\">{{ liveStatus }}</span>\n </div>\n\n <ng-container *ngIf=\"!isLive\">\n <cqa-segment-control \n [segments]=\"segments\" \n [value]=\"currentView\"\n (valueChange)=\"onSegmentChange($event)\">\n </cqa-segment-control>\n \n <div *ngIf=\"!isFullScreen\" \n class=\"cqa-p-1 cqa-cursor-pointer hover:cqa-bg-gray-100 cqa-rounded-sm cqa-transition-colors\"\n (click)=\"toggleFullScreen()\"\n title=\"Expand\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M6.25 1.25H8.75V3.75\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.74992 1.25L5.83325 4.16667\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M1.25 8.74967L4.16667 5.83301\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M3.75 8.75H1.25V6.25\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n\n <div *ngIf=\"isFullScreen\" \n class=\"cqa-p-1 cqa-cursor-pointer hover:cqa-bg-gray-100 cqa-rounded-sm cqa-transition-colors\"\n (click)=\"toggleFullScreen()\"\n title=\"Exit full screen\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M8.75 6.25H6.25V8.75\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.25008 6.25L9.16675 9.16667\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M0.833252 0.833008L3.74992 3.74967\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M1.25 3.75H3.75V1.25\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n </ng-container>\n </div>\n </div>\n </div>\n <div class=\"cqa-w-full cqa-bg-[#F3F4F6] cqa-h-[calc(100%-41px)]\">\n <!-- Live Content View -->\n <div *ngIf=\"isLive\" class=\"cqa-h-full cqa-flex cqa-flex-col cqa-justify-center cqa-relative\">\n <ng-container *ngIf=\"hasDeviceFrame;\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center cqa-p-4\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser', 'cqa-max-h-full cqa-h-full': platformType !== 'browser' || !isLive, 'cqa-min-w-max': platformType === 'device', '!cqa-h-full !cqa-max-h-[500px]': shouldApplySmallHeightClasses}\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-max-h-full cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-z-20': platformType === 'browser', 'cqa-bg-white': platformType !== 'browser'}\">\n <!-- Loading State -->\n <div *ngIf=\"isContentVideoLoading\" class=\"cqa-p-10 cqa-text-center cqa-h-full cqa-flex cqa-flex-col cqa-items-center cqa-justify-center\">\n <div class=\"cqa-mb-4\">\n <mat-progress-spinner mode=\"indeterminate\" diameter=\"40\"></mat-progress-spinner>\n </div>\n <p class=\"cqa-text-gray-400 cqa-text-sm\">{{ liveLoadingLabel }}</p>\n </div>\n\n <!-- Live Content (when not loading) -->\n <div *ngIf=\"!isContentVideoLoading\" class=\"cqa-w-full cqa-h-full cqa-flex cqa-flex-col cqa-items-center cqa-justify-center cqa-relative\">\n <div *ngIf=\"liveStatus === 'Failed' && failedStatusMessage\" class=\"cqa-p-6 cqa-text-center cqa-w-full\">\n <div class=\"cqa-inline-flex cqa-items-center cqa-gap-2 cqa-px-4 cqa-py-3 cqa-bg-[#FCD9D9] cqa-border cqa-border-[#F9BFBF] cqa-rounded-lg\">\n <mat-icon style=\"width: 18px; height: 18px; color: #C63535; font-size: 18px;\">error</mat-icon>\n <p class=\"cqa-text-[#C63535] cqa-text-sm cqa-font-medium cqa-m-0\">{{ failedStatusMessage }}</p>\n </div>\n </div>\n <ng-content *ngIf=\"liveStatus !== 'Failed' || !failedStatusMessage\"></ng-content>\n </div>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n\n <!-- Normal Video View (when not live) -->\n <div *ngIf=\"!isLive && currentView === 'video'\"\n class=\"cqa-h-full cqa-flex cqa-flex-col\"\n tabindex=\"0\"\n role=\"region\"\n aria-label=\"Video playback\"\n (keydown)=\"onVideoKeydown($event)\">\n <div class=\"cqa-w-full cqa-py-4 cqa-flex cqa-items-center cqa-max-h-[calc(100%-97px)]\" *ngIf=\"currentVideoUrl\" [ngClass]=\"{'!cqa-h-full': platformType === 'device', 'cqa-mt-auto': hasDeviceFrame}\">\n <ng-container *ngIf=\"hasDeviceFrame\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-p-4': platformType === 'browser'}\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center cqa-max-h-full\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser', 'cqa-min-w-max': platformType === 'device'}\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-max-h-full cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-bg-white': platformType !== 'browser'}\">\n <video\n #vplayer\n class=\"cqa-object-cover cqa-w-full cqa-h-full cqa-block cqa-bg-[##F2F2F2]\"\n [src]=\"currentVideoUrl\"\n type=\"video/webm\"\n [ngClass]=\"{'cqa-z-20': platformType === 'browser'}\"\n (loadedmetadata)=\"onVideoMetadataLoaded()\"\n (canplay)=\"onVideoCanPlay()\"\n (ended)=\"onVideoEnded()\"\n ></video>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!currentVideoUrl\">\n <ng-container *ngIf=\"isVNCSessionIntruppted && vncSessionIntupptedMessage; else noVideoDefault\">\n <p class=\"cqa-text-sm cqa-text-gray-600\">\n {{ vncSessionIntupptedMessage }}\n </p>\n </ng-container>\n <ng-template #noVideoDefault>\n <span>No video recording found</span>\n </ng-template>\n </div>\n \n <div class=\"cqa-px-2 cqa-py-2 cqa-bg-white\" style=\"border-top: 1px solid #E5E7EB;\" [ngClass]=\"{'cqa-mt-auto': hasDeviceFrame}\" *ngIf=\"currentVideoUrl && !isLive\">\n <span class=\"cqa-text-[#6B7280] cqa-text-[12px] cqa-font-medium cqa-mb-2 cqa-whitespace-nowrap cqa-block\">\n Video {{ currentVideoIndex + 1 }} playing out of {{ videoUrls?.length || 0 }}\n </span>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <button \n *ngIf=\"hasMultipleVideos\"\n type=\"button\"\n class=\"cqa-bg-transparent cqa-border-none cqa-cursor-pointer !cqa-px-0 cqa-flex cqa-items-center cqa-justify-center hover:cqa-opacity-70 cqa-transition-opacity cqa-outline-none\"\n style=\"pointer-events: auto;\"\n [disabled]=\"currentVideoIndex === 0\"\n [ngClass]=\"{'cqa-opacity-50 cqa-cursor-not-allowed': currentVideoIndex === 0}\"\n (click)=\"prevVideo()\"\n matTooltip=\"Previous video\"\n matTooltipPosition=\"above\">\n <mat-icon class=\"cqa-w-4 cqa-h-4 !cqa-text-[16px] cqa-text-[#374151]\" [ngClass]=\"{'cqa-opacity-50 cqa-cursor-not-allowed': currentVideoIndex === 0}\">skip_previous</mat-icon>\n </button>\n\n <div class=\"cqa-flex cqa-items-center cqa-justify-center\" style=\"width: 16px; height: 16px;\">\n <mat-progress-spinner\n *ngIf=\"isPlayerSwitching\"\n mode=\"indeterminate\"\n diameter=\"16\"\n class=\"cqa-inline-block\">\n </mat-progress-spinner>\n <button \n *ngIf=\"!isPlayerSwitching\"\n type=\"button\"\n class=\"cqa-bg-transparent cqa-border-none cqa-cursor-pointer !cqa-px-0 cqa-flex cqa-items-center cqa-justify-center hover:cqa-opacity-70 cqa-transition-opacity cqa-outline-none\"\n style=\"pointer-events: auto;\"\n (click)=\"togglePlay()\"\n matTooltip=\"{{ isPlaying ? 'Pause' : 'Play' }}\"\n matTooltipPosition=\"above\">\n <span *ngIf=\"!isPlaying\" class=\"cqa-flex cqa-items-center cqa-justify-center\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M3 2L13 8L3 14V2Z\" fill=\"#374151\"/>\n </svg>\n </span>\n <span *ngIf=\"isPlaying\" class=\"cqa-flex cqa-items-center cqa-justify-center\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"3\" y=\"2\" width=\"3\" height=\"12\" fill=\"#374151\"/>\n <rect x=\"10\" y=\"2\" width=\"3\" height=\"12\" fill=\"#374151\"/>\n </svg>\n </span>\n </button>\n </div>\n\n <button \n *ngIf=\"hasMultipleVideos\"\n type=\"button\"\n class=\"cqa-bg-transparent cqa-border-none cqa-cursor-pointer !cqa-px-0 cqa-flex cqa-items-center cqa-justify-center hover:cqa-opacity-70 cqa-transition-opacity cqa-outline-none\"\n style=\"pointer-events: auto;\"\n [disabled]=\"videoUrls && (currentVideoIndex >= videoUrls.length - 1)\"\n [ngClass]=\"{'cqa-opacity-50 cqa-cursor-not-allowed': videoUrls && (currentVideoIndex >= videoUrls.length - 1)}\"\n (click)=\"nextVideo()\"\n matTooltip=\"Next video\"\n matTooltipPosition=\"above\">\n <mat-icon class=\"cqa-w-4 cqa-h-4 !cqa-text-[16px] cqa-text-[#374151]\" [ngClass]=\"{'cqa-opacity-50 cqa-cursor-not-allowed': videoUrls && (currentVideoIndex >= videoUrls.length - 1)}\">skip_next</mat-icon>\n </button>\n\n <span class=\"cqa-text-[#9CA3AF] cqa-text-[9px] cqa-font-normal cqa-whitespace-nowrap cqa-select-none\">\n {{ formatTime(vplayer?.nativeElement?.currentTime || 0) }}\n </span>\n\n <div #speedControlContainer class=\"cqa-relative cqa-mr-[8px] cqa-flex cqa-items-center cqa-justify-center\">\n <button\n type=\"button\"\n class=\"cqa-bg-transparent cqa-border-none cqa-cursor-pointer cqa-text-[#9CA3AF] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-whitespace-nowrap cqa-select-none hover:cqa-opacity-70 cqa-transition-opacity cqa-outline-none cqa-px-1\"\n (click)=\"toggleSpeedControl()\"\n [matTooltip]=\"'Playback Speed'\"\n [matTooltipPosition]=\"'below'\">\n {{ currentSpeed }}\n </button>\n \n <div \n *ngIf=\"isSpeedControlOpen\"\n class=\"cqa-absolute cqa-bottom-full cqa-mb-2 cqa-right-0 cqa-bg-[#F0F0F1] cqa-rounded-lg cqa-overflow-hidden cqa-shadow-lg cqa-z-50\"\n style=\"min-width: max-content; left: 50%; bottom: 0%; transform: translate(-50%, -50%);\">\n <cqa-segment-control\n [segments]=\"speedSegments\"\n [value]=\"currentSpeed\"\n [containerBgColor]=\"'#F0F0F1'\"\n (valueChange)=\"onSpeedChange($event)\">\n </cqa-segment-control>\n </div>\n </div>\n \n <div class=\"cqa-flex-1 cqa-min-w-0\">\n <div \n #timelineBar\n class=\"cqa-relative cqa-h-1 cqa-bg-gray-200 cqa-rounded-full cqa-cursor-pointer cqa-w-full\"\n (click)=\"onTimelineClick($event)\">\n \n <div \n *ngFor=\"let marker of currentVideoMarkers\" \n class=\"cqa-absolute cqa-rounded-full\"\n [style.left.%]=\"getStepLeftPosition(marker)\"\n [style.width]=\"'8px'\"\n [style.height]=\"'8px'\"\n [style.background]=\"getGlobalMarkerColor(marker.level)\"\n [style.border]=\"'2px solid ' + getGlobalMarkerResultColor(marker.result)\"\n [style.box-sizing]=\"'border-box'\"\n [attr.title]=\"marker.title || ''\"\n style=\"pointer-events: auto; z-index: 50; cursor: pointer; transform: translate(-50%, -50%); top: 50%;\"\n (click)=\"onMarkerClick($event, marker)\">\n </div>\n \n <div \n class=\"cqa-absolute cqa-left-0 cqa-top-0 cqa-h-full cqa-bg-blue-500 cqa-rounded-full\"\n [style.width.%]=\"progress\"\n [style.transition]=\"dragging ? 'none' : 'width 100ms'\"\n style=\"pointer-events: none; z-index: 2;\">\n </div>\n \n <div \n class=\"cqa-absolute cqa-top-1/2 cqa-w-3 cqa-h-3 cqa-bg-blue-600 cqa-rounded-full cqa-cursor-grab active:cqa-cursor-grabbing cqa-shadow-md\"\n [style.left.%]=\"progress\"\n style=\"transform: translate(-50%, -50%); z-index: 60;\"\n (mousedown)=\"startDrag($event)\">\n </div>\n </div>\n </div>\n\n <span class=\"cqa-text-[#9CA3AF] cqa-text-[9px] cqa-font-normal cqa-whitespace-nowrap cqa-select-none\">\n {{ formatTime(vplayer?.nativeElement?.duration || 0) }}\n </span>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"!isLive && currentView === 'screenshots'\" class=\"cqa-h-full\">\n <div class=\"cqa-w-full cqa-py-4 cqa-h-full cqa-flex cqa-items-center\" *ngIf=\"screenShotUrl\">\n <ng-container *ngIf=\"hasDeviceFrame\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-p-4': platformType === 'browser'}\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center cqa-max-h-full\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser', 'cqa-min-w-max': platformType === 'device'}\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n [ngClass]=\"{'cqa-max-h-[inherit]': platformType === 'browser', 'cqa-max-h-full': platformType !== 'browser'}\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-bg-white': platformType !== 'browser'}\">\n <img\n [src]=\"screenShotUrl\"\n alt=\"Screenshot\"\n [ngClass]=\"{'cqa-z-20': platformType === 'browser'}\"\n class=\"cqa-object-contain cqa-w-full cqa-h-full cqa-block cqa-bg-[##F2F2F2]\"\n />\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!screenShotUrl\">\n No screenshot available\n </div>\n </div>\n\n <div *ngIf=\"!isLive && currentView === 'trace'\" class=\"cqa-h-full cqa-flex cqa-flex-col cqa-justify-center\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-relative\" *ngIf=\"traceViewUrl\" [ngClass]=\"{'!cqa-h-full': platformType === 'device'}\" style=\"padding-top: 48px; padding-bottom: 0px;\">\n <div class=\"cqa-w-full cqa-h-full cqa-overflow-hidden cqa-relative\">\n <iframe \n [src]=\"safeTraceUrl\" \n title=\"Trace Viewer\"\n class=\"cqa-object-contain cqa-w-full cqa-min-h-[250px] cqa-max-h-full cqa-block cqa-bg-[##F2F2F2]\"\n style=\"margin-top: -48px; height: calc(100% + 48px);\"\n frameborder=\"0\"\n allowfullscreen\n width=\"100%\"\n loading=\"lazy\"\n (load)=\"onTraceViewerLoad()\"\n (error)=\"onTraceViewerError()\">\n </iframe>\n </div>\n \n <div *ngIf=\"traceViewerLoading\" class=\"cqa-absolute cqa-inset-0 cqa-bg-[#F3F4F6] cqa-flex cqa-items-center cqa-justify-center cqa-z-10\">\n <div class=\"cqa-text-center cqa-text-gray-400 cqa-text-sm\">\n Loading trace viewer...\n </div>\n </div>\n \n <div *ngIf=\"traceViewerError\" class=\"cqa-absolute cqa-inset-0 cqa-bg-[#F3F4F6] cqa-flex cqa-items-center cqa-justify-center cqa-z-10\">\n <div class=\"cqa-text-center cqa-text-gray-400 cqa-text-sm\">\n Failed to load trace viewer\n </div>\n </div>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!traceViewUrl\">\n No trace available\n </div>\n </div> \n </div>\n</div>", styles: [] }]
13169
13026
  }], ctorParameters: function () { return [{ type: i1$1.DomSanitizer }]; }, propDecorators: { videoUrl: [{
13170
13027
  type: Input
13171
13028
  }], videoUrls: [{
@@ -16490,12 +16347,12 @@ const PARAMETER_FILTER_TABS = [
16490
16347
  ];
16491
16348
  /** Mock runtime variable suggestions (replace with API when integrating). */
16492
16349
  const RUNTIME_SUGGESTED_VALUES = [
16493
- '{{runtime.MaxWaitTime}}',
16494
- '{{runtime.session_id}}',
16495
- '{{runtime.auth_token}}',
16496
- '{{runtime.step_index}}',
16497
- '{{runtime.timestamp}}',
16498
- '{{runtime.test_name}}',
16350
+ 'runtime.MaxWaitTime',
16351
+ 'runtime.session_id',
16352
+ 'runtime.auth_token',
16353
+ 'runtime.step_index',
16354
+ 'runtime.timestamp',
16355
+ 'runtime.test_name',
16499
16356
  ];
16500
16357
  class TestDataModalComponent {
16501
16358
  constructor(fb, cdr, ref, data) {
@@ -16506,11 +16363,15 @@ class TestDataModalComponent {
16506
16363
  this.apply = new EventEmitter();
16507
16364
  this.cancel = new EventEmitter();
16508
16365
  this.editInDepth = new EventEmitter();
16366
+ this.parameterCreate = new EventEmitter();
16367
+ this.parameterEdit = new EventEmitter();
16368
+ this.environmentCreate = new EventEmitter();
16369
+ this.environmentEdit = new EventEmitter();
16509
16370
  this.tabSegments = TAB_SEGMENTS;
16510
16371
  this.parameterFilterTabs = PARAMETER_FILTER_TABS;
16511
- /** Mock parameter list (replace with API when integrating). */
16372
+ /** Parameter list from input, falls back to mock data if not provided. */
16512
16373
  this.parameters = MOCK_PARAMETERS;
16513
- /** Mock environment list (replace with API when integrating). */
16374
+ /** Environment list from input, falls back to mock data if not provided. */
16514
16375
  this.environmentItems = MOCK_ENVIRONMENT_ITEMS;
16515
16376
  /** Runtime tab: suggested variable chips. */
16516
16377
  this.runtimeSuggestedValues = RUNTIME_SUGGESTED_VALUES;
@@ -16538,6 +16399,13 @@ class TestDataModalComponent {
16538
16399
  this.environmentSearchQuery = (_g = data.environmentSearchQuery) !== null && _g !== void 0 ? _g : '';
16539
16400
  this.selectedEnvironmentId = (_h = data.selectedEnvironmentId) !== null && _h !== void 0 ? _h : null;
16540
16401
  this.runtimeValue = (_j = data.runtimeValue) !== null && _j !== void 0 ? _j : '';
16402
+ // Set parameters and environmentItems from data if provided
16403
+ if (data.parameters !== undefined) {
16404
+ this.parameters = data.parameters;
16405
+ }
16406
+ if (data.environmentItems !== undefined) {
16407
+ this.environmentItems = data.environmentItems;
16408
+ }
16541
16409
  }
16542
16410
  }
16543
16411
  ngOnInit() {
@@ -16670,12 +16538,12 @@ class TestDataModalComponent {
16670
16538
  this.onEditFormFieldChange('value', param.name);
16671
16539
  }
16672
16540
  }
16673
- onParameterEdit(_paramId) {
16674
- // Placeholder for future edit action (e.g. open edit drawer).
16541
+ onParameterEdit(paramId) {
16542
+ this.parameterEdit.emit(paramId);
16675
16543
  }
16676
16544
  onCreateNewVariable(event) {
16677
16545
  event.preventDefault();
16678
- // Placeholder for future "Create New" action (no API yet).
16546
+ this.parameterCreate.emit();
16679
16547
  }
16680
16548
  onEnvironmentSearchInput(value) {
16681
16549
  this.onEditFormFieldChange('environmentSearchQuery', value);
@@ -16689,12 +16557,12 @@ class TestDataModalComponent {
16689
16557
  this.onEditFormFieldChange('value', item.name);
16690
16558
  }
16691
16559
  }
16692
- onEnvironmentEdit(_itemId) {
16693
- // Placeholder for future edit action (e.g. open edit drawer).
16560
+ onEnvironmentEdit(itemId) {
16561
+ this.environmentEdit.emit(itemId);
16694
16562
  }
16695
16563
  onCreateNewEnvironment(event) {
16696
16564
  event.preventDefault();
16697
- // Placeholder for future "Create New" action (no API yet).
16565
+ this.environmentCreate.emit();
16698
16566
  }
16699
16567
  /** Runtime tab: insert suggested value into the runtime input field. */
16700
16568
  onRuntimeChipInsert(snippet) {
@@ -16714,6 +16582,17 @@ class TestDataModalComponent {
16714
16582
  else if (this.activeTab === 'environment') {
16715
16583
  valueToApply = this.selectedEnvironmentId ? (_d = (_c = this.environmentItems.find((e) => e.id === this.selectedEnvironmentId)) === null || _c === void 0 ? void 0 : _c.name) !== null && _d !== void 0 ? _d : '' : '';
16716
16584
  }
16585
+ // Wrap valueToApply based on active tab
16586
+ if (this.activeTab === 'parameter' && valueToApply) {
16587
+ valueToApply = `@|${valueToApply}|`;
16588
+ }
16589
+ else if (this.activeTab === 'runtime' && valueToApply) {
16590
+ valueToApply = `$|${valueToApply}|`;
16591
+ }
16592
+ else if (this.activeTab === 'environment' && valueToApply) {
16593
+ valueToApply = `*|${valueToApply}|`;
16594
+ }
16595
+ // plain-text tab: no wrapping, use value as is
16717
16596
  // Build result with only the active tab's data, clear other tabs' data
16718
16597
  const result = {
16719
16598
  value: valueToApply,
@@ -16753,7 +16632,7 @@ class TestDataModalComponent {
16753
16632
  }
16754
16633
  }
16755
16634
  TestDataModalComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestDataModalComponent, deps: [{ token: i2$1.FormBuilder }, { token: i0.ChangeDetectorRef }, { token: TEST_DATA_MODAL_REF }, { token: TEST_DATA_MODAL_DATA, optional: true }], target: i0.ɵɵFactoryTarget.Component });
16756
- TestDataModalComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TestDataModalComponent, selector: "cqa-test-data-modal", outputs: { apply: "apply", cancel: "cancel", editInDepth: "editInDepth" }, host: { classAttribute: "cqa-ui-root" }, ngImport: i0, template: "<div\n class=\"cqa-bg-white cqa-rounded-[12px] cqa-shadow-lg cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-w-[500px] cqa-flex cqa-flex-col cqa-gap-[12px] cqa-p-2 cqa-box-border cqa-min-h-0\">\n <!-- Header: title left; Need help? + close icon right -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-gap-2 cqa-px-4\">\n <h2 class=\"cqa-text-[16px] cqa-leading-[24px] cqa-font-bold cqa-text-[#111827] cqa-m-0 cqa-font-[600]\">\n Test Data\n </h2>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-min-h-[28px]\">\n <!-- Need help? with custom tooltip (works inside overlay) -->\n <div class=\"cqa-relative cqa-inline-flex cqa-items-center\"\n (mouseenter)=\"showHelpTooltip = true\" (mouseleave)=\"showHelpTooltip = false\">\n <a *ngIf=\"helpUrl\" href=\"#\" (click)=\"onHelp($event)\"\n class=\"cqa-flex cqa-items-center cqa-gap-1 cqa-text-[#3F43EE] cqa-text-[12px] cqa-leading-[21px] cqa-no-underline hover:cqa-underline cqa-cursor-pointer\">\n <svg width=\"17\" height=\"16\" viewBox=\"0 0 17 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" class=\"cqa-flex-shrink-0\" aria-hidden=\"true\">\n <g clip-path=\"url(#test-data-help-clip)\">\n <path d=\"M8.50033 14.6663C12.4123 14.6663 15.5837 11.6816 15.5837 7.99967C15.5837 4.31778 12.4123 1.33301 8.50033 1.33301C4.58831 1.33301 1.41699 4.31778 1.41699 7.99967C1.41699 11.6816 4.58831 14.6663 8.50033 14.6663Z\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.43848 6.00038C6.60501 5.55483 6.93371 5.17912 7.36636 4.9398C7.79901 4.70049 8.30769 4.61301 8.80231 4.69285C9.29693 4.7727 9.74556 5.01473 10.0687 5.37607C10.3919 5.7374 10.5688 6.19473 10.5681 6.66705C10.5681 8.00038 8.44306 8.66705 8.44306 8.66705\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.5 11.333H8.50966\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </g>\n <defs>\n <clipPath id=\"test-data-help-clip\">\n <rect width=\"17\" height=\"16\" fill=\"white\"/>\n </clipPath>\n </defs>\n </svg>\n Need help ?\n </a>\n <span *ngIf=\"!helpUrl\" class=\"cqa-flex cqa-items-center cqa-gap-1.5 cqa-font-[500] cqa-text-[10px] cqa-cursor-default\">\n <svg width=\"17\" height=\"16\" viewBox=\"0 0 17 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" class=\"cqa-flex-shrink-0 cqa-text-[#3F43EE]\" aria-hidden=\"true\">\n <g clip-path=\"url(#test-data-help-clip-nolink)\">\n <path d=\"M8.50033 14.6663C12.4123 14.6663 15.5837 11.6816 15.5837 7.99967C15.5837 4.31778 12.4123 1.33301 8.50033 1.33301C4.58831 1.33301 1.41699 4.31778 1.41699 7.99967C1.41699 11.6816 4.58831 14.6663 8.50033 14.6663Z\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.43848 6.00038C6.60501 5.55483 6.93371 5.17912 7.36636 4.9398C7.79901 4.70049 8.30769 4.61301 8.80231 4.69285C9.29693 4.7727 9.74556 5.01473 10.0687 5.37607C10.3919 5.7374 10.5688 6.19473 10.5681 6.66705C10.5681 8.00038 8.44306 8.66705 8.44306 8.66705\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.5 11.333H8.50966\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </g>\n <defs>\n <clipPath id=\"test-data-help-clip-nolink\">\n <rect width=\"17\" height=\"16\" fill=\"white\"/>\n </clipPath>\n </defs>\n </svg>\n Need help ?\n </span>\n <!-- Custom tooltip (exact spec: 306\u00D720 content, 6px radius, #0A0A0A, no arrow) -->\n <div *ngIf=\"showHelpTooltip\"\n class=\"cqa-absolute cqa-pointer-events-none cqa-z-[100] cqa-top-[-24px] cqa-left-[-125px]\"\n role=\"tooltip\">\n <div\n class=\"cqa-text-white cqa-text-center cqa-whitespace-nowrap cqa-w-[306px] cqa-min-h-[20px] cqa-rounded-[6px] cqa-py-1 cqa-px-2 cqa-bg-[#0A0A0A] cqa-leading-[20px] cqa-text-[8px]\">\n {{ helpTooltipText }}\n </div>\n </div>\n </div>\n <button type=\"button\" (click)=\"onClose()\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-min-h-[28px] cqa-min-w-[28px] cqa-rounded cqa-text-[#6B7280] hover:cqa-bg-[#F3F4F6] cqa-p-0\"\n title=\"Close\" aria-label=\"Close\">\n <mat-icon class=\"!cqa-w-5 !cqa-h-5 !cqa-text-[20px] !cqa-block !cqa-leading-none\">close</mat-icon>\n </button>\n </div>\n </div>\n\n <!-- Line below header (full width of modal, no side margin) -->\n <div class=\"cqa--mx-2 cqa-w-[calc(100%+1rem)] cqa-flex-shrink-0\">\n <div class=\"cqa-h-px cqa-w-full cqa-bg-[#E5E7EB]\" role=\"presentation\"></div>\n </div>\n\n <!-- Tabs: Plain Text, Parameter, Environment, Runtime (bound to editForm like Loop Step) -->\n <div class=\"cqa-w-full cqa-test-data-modal-tabs\">\n <cqa-segment-control\n [segments]=\"tabSegments\"\n [value]=\"editForm.get('activeTab')?.value ?? activeTab\"\n (valueChange)=\"onTabChange($event)\">\n </cqa-segment-control>\n </div>\n\n <!-- Content per tab: flex-1 min-h-0 so Parameter/Environment/Runtime content can scroll -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1.5 cqa-min-h-0\"\n [class.cqa-flex-1]=\"activeTab === 'parameter' || activeTab === 'environment' || activeTab === 'runtime'\">\n <!-- Plain Text tab (form-bound like Loop Step editForm + onEditFormFieldChange) -->\n <ng-container *ngIf=\"activeTab === 'plain-text'\">\n <cqa-custom-input\n label=\"Value\"\n [value]=\"editForm.get('value')?.value ?? ''\"\n (valueChange)=\"onEditFormFieldChange('value', $event)\"\n placeholder=\"https://example.com/dashboard\"\n [fullWidth]=\"true\"\n size=\"md\">\n </cqa-custom-input>\n <p class=\"cqa-text-[12px] cqa-leading-[18px] cqa-text-[#0A0A0A] cqa-m-0\">\n Enter a static text value that won't change during execution.\n </p>\n </ng-container>\n\n <!-- Parameter tab: Variable Library -->\n <ng-container *ngIf=\"activeTab === 'parameter'\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2 cqa-min-h-0 cqa-flex-1 cqa-min-h-[18rem]\">\n <!-- Variable Library header -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-flex-shrink-0\">\n <h3 class=\"cqa-text-[12px] cqa-leading-[20px] cqa-font-semibold cqa-text-[#111827] cqa-m-0\">\n Variable Library\n </h3>\n <a href=\"#\" (click)=\"onCreateNewVariable($event)\"\n class=\"cqa-text-[#3F43EE] cqa-text-[12px] cqa-leading-[18px] cqa-font-medium cqa-no-underline hover:cqa-opacity-90 cqa-cursor-pointer\">\n Create New +\n </a>\n </div>\n <!-- Filter tabs: All, Global, Local (blue underline under active label only) -->\n <div class=\"cqa-flex cqa-w-full cqa-flex-shrink-0\">\n <button *ngFor=\"let tab of parameterFilterTabs\" type=\"button\"\n (click)=\"onParameterScopeFilterChange(tab.value)\"\n class=\"cqa-flex-1 cqa-py-0 cqa-px-3 cqa-text-[12px] cqa-leading-[18px] cqa-font-medium cqa-bg-transparent cqa-cursor-pointer cqa-transition-colors cqa-flex cqa-justify-center cqa-items-center\"\n [class.cqa-text-[#6B7280]]=\"parameterScopeFilter !== tab.value\">\n <span class=\"cqa-test-data-param-filter-label cqa-inline-block cqa-pb-0.5\"\n [class.cqa-test-data-param-filter-active]=\"parameterScopeFilter === tab.value\">\n {{ tab.label }}\n </span>\n </button>\n </div>\n <!-- Search: bound to editForm (same pattern as Loop Step control binding) -->\n <div class=\"cqa-flex-shrink-0 cqa-relative cqa-flex cqa-items-center\">\n <span class=\"cqa-absolute cqa-left-4 cqa-top-0 cqa-bottom-0 cqa-flex cqa-items-center cqa-justify-center cqa-pointer-events-none cqa-text-[#6B7280] cqa-leading-none\" aria-hidden=\"true\">\n <mat-icon class=\"!cqa-w-4 !cqa-h-4 !cqa-text-[16px]\">search</mat-icon>\n </span>\n <input\n type=\"text\"\n [value]=\"editForm.get('parameterSearchQuery')?.value ?? ''\"\n (input)=\"onParameterSearchInput($any($event.target).value)\"\n placeholder=\"Search library\"\n class=\"cqa-test-data-search-input cqa-w-full cqa-pl-10 cqa-pr-4 cqa-py-2.5 cqa-text-sm cqa-leading-5 cqa-text-[#0A0A0A] placeholder:cqa-text-[#9CA3AF] focus:cqa-outline-none focus:cqa-border-[#3B82F6] focus:cqa-ring-1 focus:cqa-ring-[#3B82F6]\"\n aria-label=\"Search library\"\n />\n </div>\n <!-- Parameter list (scrollable, search-integrated via filtered list binding) -->\n <div class=\"cqa-min-h-[200px] cqa-flex-1 cqa-flex cqa-flex-col\">\n <cqa-item-list\n [items]=\"parameterListConfig\"\n [selectedId]=\"selectedParameterId\"\n emptyMessage=\"No parameters match your search.\"\n [scrollable]=\"true\"\n (itemSelect)=\"onParameterSelect($event)\"\n (itemEdit)=\"onParameterEdit($event)\">\n </cqa-item-list>\n </div>\n </div>\n </ng-container>\n\n <!-- Environment tab: Variable library by environment -->\n <ng-container *ngIf=\"activeTab === 'environment'\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2 cqa-min-h-0 cqa-flex-1 cqa-min-h-[18rem]\">\n <!-- Section header -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-flex-shrink-0\">\n <h3 class=\"cqa-text-[12px] cqa-leading-[20px] cqa-font-semibold cqa-text-[#111827] cqa-m-0\">\n Environment\n </h3>\n <a href=\"#\" (click)=\"onCreateNewEnvironment($event)\"\n class=\"cqa-text-[#3F43EE] cqa-text-[12px] cqa-leading-[18px] cqa-font-medium cqa-no-underline hover:cqa-opacity-90 cqa-cursor-pointer\">\n Create New +\n </a>\n </div>\n <!-- Search: bound to editForm (same pattern as Loop Step control binding) -->\n <div class=\"cqa-flex-shrink-0 cqa-relative cqa-flex cqa-items-center\">\n <span class=\"cqa-absolute cqa-left-4 cqa-top-0 cqa-bottom-0 cqa-flex cqa-items-center cqa-justify-center cqa-pointer-events-none cqa-text-[#6B7280] cqa-leading-none\" aria-hidden=\"true\">\n <mat-icon class=\"!cqa-w-4 !cqa-h-4 !cqa-text-[16px]\">search</mat-icon>\n </span>\n <input\n type=\"text\"\n [value]=\"editForm.get('environmentSearchQuery')?.value ?? ''\"\n (input)=\"onEnvironmentSearchInput($any($event.target).value)\"\n placeholder=\"Search Environment\"\n class=\"cqa-test-data-search-input cqa-w-full cqa-pl-10 cqa-pr-4 cqa-py-2.5 cqa-text-sm cqa-leading-5 cqa-text-[#0A0A0A] placeholder:cqa-text-[#9CA3AF] focus:cqa-outline-none focus:cqa-border-[#3B82F6] focus:cqa-ring-1 focus:cqa-ring-[#3B82F6]\"\n aria-label=\"Search Environment\"\n />\n </div>\n <!-- Environment list (scrollable, search-integrated via filtered list binding) -->\n <div class=\"cqa-min-h-[220px] cqa-flex-1 cqa-flex cqa-flex-col\">\n <cqa-item-list\n [items]=\"environmentListConfig\"\n [selectedId]=\"selectedEnvironmentId\"\n emptyMessage=\"No environment variables match your search.\"\n [scrollable]=\"true\"\n (itemSelect)=\"onEnvironmentSelect($event)\"\n (itemEdit)=\"onEnvironmentEdit($event)\">\n </cqa-item-list>\n </div>\n </div>\n </ng-container>\n\n <!-- Runtime tab: dynamic value injector -->\n <ng-container *ngIf=\"activeTab === 'runtime'\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3 cqa-min-h-0 cqa-h-full cqa-overflow-y-auto\">\n <h3 class=\"cqa-text-[12px] cqa-leading-[20px] cqa-font-semibold cqa-text-[#111827] cqa-m-0 cqa-flex-shrink-0\">\n Runtime\n </h3>\n <div class=\"cqa-flex-shrink-0\">\n <cqa-custom-input\n [value]=\"editForm.get('runtimeValue')?.value ?? ''\"\n (valueChange)=\"onEditFormFieldChange('runtimeValue', $event)\"\n placeholder=\"input text\"\n [fullWidth]=\"true\"\n size=\"md\">\n </cqa-custom-input>\n <p class=\"cqa-text-[12px] cqa-leading-[18px] cqa-text-[#6B7280] cqa-mt-1.5 cqa-mb-0\">\n Values resolved during test execution based on session and step state.\n </p>\n </div>\n <!-- Recommended: suggestion chips -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2 cqa-flex-shrink-0\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <mat-icon class=\"!cqa-w-4 !cqa-h-4 !cqa-text-[16px] cqa-text-[#9CA3AF]\" aria-hidden=\"true\">schedule</mat-icon>\n <span class=\"cqa-text-[12px] cqa-leading-[18px] cqa-font-medium cqa-text-[#374151]\">Recommended</span>\n </div>\n <div class=\"cqa-test-data-runtime-chips-scroll cqa-flex cqa-gap-2 cqa-overflow-x-auto cqa-min-w-0 cqa-pb-1\">\n <button\n *ngFor=\"let snippet of runtimeSuggestedValues\"\n type=\"button\"\n (click)=\"onRuntimeChipInsert(snippet)\"\n class=\"cqa-flex-shrink-0 cqa-px-3 cqa-py-1.5 cqa-text-[12px] cqa-leading-[18px] cqa-font-medium cqa-text-[#374151] cqa-bg-[#F3F4F6] cqa-rounded-full hover:cqa-bg-[#E5E7EB] focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] cqa-transition-colors cqa-whitespace-nowrap\">\n {{ snippet }}\n </button>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n\n <!-- Line below content (full width of modal, no side margin) -->\n <div class=\"cqa--mx-2 cqa-w-[calc(100%+1rem)] cqa-flex-shrink-0\">\n <div class=\"cqa-h-px cqa-w-full cqa-bg-[#E5E7EB]\" role=\"presentation\"></div>\n </div>\n\n <!-- Footer: Cancel, Apply (full width in one row) -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <div class=\"cqa-flex cqa-items-stretch cqa-gap-2 cqa-w-full\">\n <div class=\"cqa-flex-1 cqa-min-w-0\">\n <cqa-button variant=\"outlined\" btnSize=\"lg\" [text]=\"'Cancel'\" [fullWidth]=\"true\" (clicked)=\"onCancel()\"\n [customClass]=\"'cqa-text-[12px] cqa-py-[9px] cqa-border-[#414146]'\"></cqa-button>\n </div>\n <div class=\"cqa-flex-1 cqa-min-w-0\">\n <cqa-button variant=\"filled\" btnSize=\"lg\" [text]=\"'Apply'\" [fullWidth]=\"true\" (clicked)=\"onApply()\"\n [customClass]=\"'cqa-text-[12px] cqa-py-[9px] cqa-border-[#3F43EE]'\"></cqa-button>\n </div>\n </div>\n <a href=\"#\" (click)=\"onEditInDepth($event)\"\n class=\"cqa-text-[#3F43EE] cqa-text-[12px] cqa-leading-[18px] cqa-font-medium cqa-flex cqa-items-center cqa-gap-1.5 cqa-no-underline hover:cqa-no-underline cqa-self-center\">\n <mat-icon class=\"!cqa-w-4 !cqa-h-4 !cqa-text-[16px]\">open_in_new</mat-icon>\n Edit in depth (open detailed right panel)\n </a>\n </div>\n</div>\n", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: SegmentControlComponent, selector: "cqa-segment-control", inputs: ["segments", "value", "disabled", "containerBgColor"], outputs: ["valueChange"] }, { type: CustomInputComponent, selector: "cqa-custom-input", inputs: ["label", "type", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "inputInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused", "enterPressed"] }, { type: ItemListComponent, selector: "cqa-item-list", inputs: ["items", "selectedId", "emptyMessage", "scrollable"], outputs: ["itemSelect", "itemEdit"] }, { type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
16635
+ TestDataModalComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TestDataModalComponent, selector: "cqa-test-data-modal", inputs: { parameters: "parameters", environmentItems: "environmentItems" }, outputs: { apply: "apply", cancel: "cancel", editInDepth: "editInDepth", parameterCreate: "parameterCreate", parameterEdit: "parameterEdit", environmentCreate: "environmentCreate", environmentEdit: "environmentEdit" }, host: { classAttribute: "cqa-ui-root" }, ngImport: i0, template: "<div\n class=\"cqa-bg-white cqa-rounded-[12px] cqa-shadow-lg cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-w-[500px] cqa-flex cqa-flex-col cqa-gap-[12px] cqa-p-2 cqa-box-border cqa-min-h-0\">\n <!-- Header: title left; Need help? + close icon right -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-gap-2 cqa-px-4\">\n <h2 class=\"cqa-text-[16px] cqa-leading-[24px] cqa-font-bold cqa-text-[#111827] cqa-m-0 cqa-font-[600]\">\n Test Data\n </h2>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-min-h-[28px]\">\n <!-- Need help? with custom tooltip (works inside overlay) -->\n <div class=\"cqa-relative cqa-inline-flex cqa-items-center\"\n (mouseenter)=\"showHelpTooltip = true\" (mouseleave)=\"showHelpTooltip = false\">\n <a *ngIf=\"helpUrl\" href=\"#\" (click)=\"onHelp($event)\"\n class=\"cqa-flex cqa-items-center cqa-gap-1 cqa-text-[#3F43EE] cqa-text-[12px] cqa-leading-[21px] cqa-no-underline hover:cqa-underline cqa-cursor-pointer\">\n <svg width=\"17\" height=\"16\" viewBox=\"0 0 17 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" class=\"cqa-flex-shrink-0\" aria-hidden=\"true\">\n <g clip-path=\"url(#test-data-help-clip)\">\n <path d=\"M8.50033 14.6663C12.4123 14.6663 15.5837 11.6816 15.5837 7.99967C15.5837 4.31778 12.4123 1.33301 8.50033 1.33301C4.58831 1.33301 1.41699 4.31778 1.41699 7.99967C1.41699 11.6816 4.58831 14.6663 8.50033 14.6663Z\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.43848 6.00038C6.60501 5.55483 6.93371 5.17912 7.36636 4.9398C7.79901 4.70049 8.30769 4.61301 8.80231 4.69285C9.29693 4.7727 9.74556 5.01473 10.0687 5.37607C10.3919 5.7374 10.5688 6.19473 10.5681 6.66705C10.5681 8.00038 8.44306 8.66705 8.44306 8.66705\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.5 11.333H8.50966\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </g>\n <defs>\n <clipPath id=\"test-data-help-clip\">\n <rect width=\"17\" height=\"16\" fill=\"white\"/>\n </clipPath>\n </defs>\n </svg>\n Need help ?\n </a>\n <span *ngIf=\"!helpUrl\" class=\"cqa-flex cqa-items-center cqa-gap-1.5 cqa-font-[500] cqa-text-[10px] cqa-cursor-default\">\n <svg width=\"17\" height=\"16\" viewBox=\"0 0 17 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" class=\"cqa-flex-shrink-0 cqa-text-[#3F43EE]\" aria-hidden=\"true\">\n <g clip-path=\"url(#test-data-help-clip-nolink)\">\n <path d=\"M8.50033 14.6663C12.4123 14.6663 15.5837 11.6816 15.5837 7.99967C15.5837 4.31778 12.4123 1.33301 8.50033 1.33301C4.58831 1.33301 1.41699 4.31778 1.41699 7.99967C1.41699 11.6816 4.58831 14.6663 8.50033 14.6663Z\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.43848 6.00038C6.60501 5.55483 6.93371 5.17912 7.36636 4.9398C7.79901 4.70049 8.30769 4.61301 8.80231 4.69285C9.29693 4.7727 9.74556 5.01473 10.0687 5.37607C10.3919 5.7374 10.5688 6.19473 10.5681 6.66705C10.5681 8.00038 8.44306 8.66705 8.44306 8.66705\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.5 11.333H8.50966\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </g>\n <defs>\n <clipPath id=\"test-data-help-clip-nolink\">\n <rect width=\"17\" height=\"16\" fill=\"white\"/>\n </clipPath>\n </defs>\n </svg>\n Need help ?\n </span>\n <!-- Custom tooltip (exact spec: 306\u00D720 content, 6px radius, #0A0A0A, no arrow) -->\n <div *ngIf=\"showHelpTooltip\"\n class=\"cqa-absolute cqa-pointer-events-none cqa-z-[100] cqa-top-[-24px] cqa-left-[-125px]\"\n role=\"tooltip\">\n <div\n class=\"cqa-text-white cqa-text-center cqa-whitespace-nowrap cqa-w-[306px] cqa-min-h-[20px] cqa-rounded-[6px] cqa-py-1 cqa-px-2 cqa-bg-[#0A0A0A] cqa-leading-[20px] cqa-text-[8px]\">\n {{ helpTooltipText }}\n </div>\n </div>\n </div>\n <button type=\"button\" (click)=\"onClose()\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-min-h-[28px] cqa-min-w-[28px] cqa-rounded cqa-text-[#6B7280] hover:cqa-bg-[#F3F4F6] cqa-p-0\"\n title=\"Close\" aria-label=\"Close\">\n <mat-icon class=\"!cqa-w-5 !cqa-h-5 !cqa-text-[20px] !cqa-block !cqa-leading-none\">close</mat-icon>\n </button>\n </div>\n </div>\n\n <!-- Line below header (full width of modal, no side margin) -->\n <div class=\"cqa--mx-2 cqa-w-[calc(100%+1rem)] cqa-flex-shrink-0\">\n <div class=\"cqa-h-px cqa-w-full cqa-bg-[#E5E7EB]\" role=\"presentation\"></div>\n </div>\n\n <!-- Tabs: Plain Text, Parameter, Environment, Runtime (bound to editForm like Loop Step) -->\n <div class=\"cqa-w-full cqa-test-data-modal-tabs\">\n <cqa-segment-control\n [segments]=\"tabSegments\"\n [value]=\"editForm.get('activeTab')?.value ?? activeTab\"\n (valueChange)=\"onTabChange($event)\">\n </cqa-segment-control>\n </div>\n\n <!-- Content per tab: flex-1 min-h-0 so Parameter/Environment/Runtime content can scroll -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1.5 cqa-min-h-0\"\n [class.cqa-flex-1]=\"activeTab === 'parameter' || activeTab === 'environment' || activeTab === 'runtime'\">\n <!-- Plain Text tab (form-bound like Loop Step editForm + onEditFormFieldChange) -->\n <ng-container *ngIf=\"activeTab === 'plain-text'\">\n <cqa-custom-input\n label=\"Value\"\n [value]=\"editForm.get('value')?.value ?? ''\"\n (valueChange)=\"onEditFormFieldChange('value', $event)\"\n placeholder=\"https://example.com/dashboard\"\n [fullWidth]=\"true\"\n size=\"md\">\n </cqa-custom-input>\n <p class=\"cqa-text-[12px] cqa-leading-[18px] cqa-text-[#0A0A0A] cqa-m-0\">\n Enter a static text value that won't change during execution.\n </p>\n </ng-container>\n\n <!-- Parameter tab: Variable Library -->\n <ng-container *ngIf=\"activeTab === 'parameter'\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2 cqa-min-h-0 cqa-flex-1 cqa-min-h-[18rem]\">\n <!-- Variable Library header -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-flex-shrink-0\">\n <h3 class=\"cqa-text-[12px] cqa-leading-[20px] cqa-font-semibold cqa-text-[#111827] cqa-m-0\">\n Variable Library\n </h3>\n <a href=\"#\" (click)=\"onCreateNewVariable($event)\"\n class=\"cqa-text-[#3F43EE] cqa-text-[12px] cqa-leading-[18px] cqa-font-medium cqa-no-underline hover:cqa-opacity-90 cqa-cursor-pointer\">\n Create New +\n </a>\n </div>\n <!-- Filter tabs: All, Global, Local (blue underline under active label only) -->\n <div class=\"cqa-flex cqa-w-full cqa-flex-shrink-0\">\n <button *ngFor=\"let tab of parameterFilterTabs\" type=\"button\"\n (click)=\"onParameterScopeFilterChange(tab.value)\"\n class=\"cqa-flex-1 cqa-py-0 cqa-px-3 cqa-text-[12px] cqa-leading-[18px] cqa-font-medium cqa-bg-transparent cqa-cursor-pointer cqa-transition-colors cqa-flex cqa-justify-center cqa-items-center\"\n [class.cqa-text-[#6B7280]]=\"parameterScopeFilter !== tab.value\">\n <span class=\"cqa-test-data-param-filter-label cqa-inline-block cqa-pb-0.5\"\n [class.cqa-test-data-param-filter-active]=\"parameterScopeFilter === tab.value\">\n {{ tab.label }}\n </span>\n </button>\n </div>\n <!-- Search: bound to editForm (same pattern as Loop Step control binding) -->\n <div class=\"cqa-flex-shrink-0 cqa-relative cqa-flex cqa-items-center\">\n <span class=\"cqa-absolute cqa-left-4 cqa-top-0 cqa-bottom-0 cqa-flex cqa-items-center cqa-justify-center cqa-pointer-events-none cqa-text-[#6B7280] cqa-leading-none\" aria-hidden=\"true\">\n <mat-icon class=\"!cqa-w-4 !cqa-h-4 !cqa-text-[16px]\">search</mat-icon>\n </span>\n <input\n type=\"text\"\n [value]=\"editForm.get('parameterSearchQuery')?.value ?? ''\"\n (input)=\"onParameterSearchInput($any($event.target).value)\"\n placeholder=\"Search library\"\n class=\"cqa-test-data-search-input cqa-w-full cqa-pl-10 cqa-pr-4 cqa-py-2.5 cqa-text-sm cqa-leading-5 cqa-text-[#0A0A0A] placeholder:cqa-text-[#9CA3AF] focus:cqa-outline-none focus:cqa-border-[#3B82F6] focus:cqa-ring-1 focus:cqa-ring-[#3B82F6]\"\n aria-label=\"Search library\"\n />\n </div>\n <!-- Parameter list (scrollable, search-integrated via filtered list binding) -->\n <div class=\"cqa-min-h-[200px] cqa-flex-1 cqa-flex cqa-flex-col\">\n <cqa-item-list\n [items]=\"parameterListConfig\"\n [selectedId]=\"selectedParameterId\"\n emptyMessage=\"No parameters match your search.\"\n [scrollable]=\"true\"\n (itemSelect)=\"onParameterSelect($event)\"\n (itemEdit)=\"onParameterEdit($event)\">\n </cqa-item-list>\n </div>\n </div>\n </ng-container>\n\n <!-- Environment tab: Variable library by environment -->\n <ng-container *ngIf=\"activeTab === 'environment'\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2 cqa-min-h-0 cqa-flex-1 cqa-min-h-[18rem]\">\n <!-- Section header -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-flex-shrink-0\">\n <h3 class=\"cqa-text-[12px] cqa-leading-[20px] cqa-font-semibold cqa-text-[#111827] cqa-m-0\">\n Environment\n </h3>\n <a href=\"#\" (click)=\"onCreateNewEnvironment($event)\"\n class=\"cqa-text-[#3F43EE] cqa-text-[12px] cqa-leading-[18px] cqa-font-medium cqa-no-underline hover:cqa-opacity-90 cqa-cursor-pointer\">\n Create New +\n </a>\n </div>\n <!-- Search: bound to editForm (same pattern as Loop Step control binding) -->\n <div class=\"cqa-flex-shrink-0 cqa-relative cqa-flex cqa-items-center\">\n <span class=\"cqa-absolute cqa-left-4 cqa-top-0 cqa-bottom-0 cqa-flex cqa-items-center cqa-justify-center cqa-pointer-events-none cqa-text-[#6B7280] cqa-leading-none\" aria-hidden=\"true\">\n <mat-icon class=\"!cqa-w-4 !cqa-h-4 !cqa-text-[16px]\">search</mat-icon>\n </span>\n <input\n type=\"text\"\n [value]=\"editForm.get('environmentSearchQuery')?.value ?? ''\"\n (input)=\"onEnvironmentSearchInput($any($event.target).value)\"\n placeholder=\"Search Environment\"\n class=\"cqa-test-data-search-input cqa-w-full cqa-pl-10 cqa-pr-4 cqa-py-2.5 cqa-text-sm cqa-leading-5 cqa-text-[#0A0A0A] placeholder:cqa-text-[#9CA3AF] focus:cqa-outline-none focus:cqa-border-[#3B82F6] focus:cqa-ring-1 focus:cqa-ring-[#3B82F6]\"\n aria-label=\"Search Environment\"\n />\n </div>\n <!-- Environment list (scrollable, search-integrated via filtered list binding) -->\n <div class=\"cqa-min-h-[220px] cqa-flex-1 cqa-flex cqa-flex-col\">\n <cqa-item-list\n [items]=\"environmentListConfig\"\n [selectedId]=\"selectedEnvironmentId\"\n emptyMessage=\"No environment variables match your search.\"\n [scrollable]=\"true\"\n (itemSelect)=\"onEnvironmentSelect($event)\"\n (itemEdit)=\"onEnvironmentEdit($event)\">\n </cqa-item-list>\n </div>\n </div>\n </ng-container>\n\n <!-- Runtime tab: dynamic value injector -->\n <ng-container *ngIf=\"activeTab === 'runtime'\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3 cqa-min-h-0 cqa-h-full cqa-overflow-y-auto\">\n <h3 class=\"cqa-text-[12px] cqa-leading-[20px] cqa-font-semibold cqa-text-[#111827] cqa-m-0 cqa-flex-shrink-0\">\n Runtime\n </h3>\n <div class=\"cqa-flex-shrink-0\">\n <cqa-custom-input\n [value]=\"editForm.get('runtimeValue')?.value ?? ''\"\n (valueChange)=\"onEditFormFieldChange('runtimeValue', $event)\"\n placeholder=\"input text\"\n [fullWidth]=\"true\"\n size=\"md\">\n </cqa-custom-input>\n <p class=\"cqa-text-[12px] cqa-leading-[18px] cqa-text-[#6B7280] cqa-mt-1.5 cqa-mb-0\">\n Values resolved during test execution based on session and step state.\n </p>\n </div>\n <!-- Recommended: suggestion chips -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2 cqa-flex-shrink-0\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <mat-icon class=\"!cqa-w-4 !cqa-h-4 !cqa-text-[16px] cqa-text-[#9CA3AF]\" aria-hidden=\"true\">schedule</mat-icon>\n <span class=\"cqa-text-[12px] cqa-leading-[18px] cqa-font-medium cqa-text-[#374151]\">Recommended</span>\n </div>\n <div class=\"cqa-test-data-runtime-chips-scroll cqa-flex cqa-gap-2 cqa-overflow-x-auto cqa-min-w-0 cqa-pb-1\">\n <button\n *ngFor=\"let snippet of runtimeSuggestedValues\"\n type=\"button\"\n (click)=\"onRuntimeChipInsert(snippet)\"\n class=\"cqa-flex-shrink-0 cqa-px-3 cqa-py-1.5 cqa-text-[12px] cqa-leading-[18px] cqa-font-medium cqa-text-[#374151] cqa-bg-[#F3F4F6] cqa-rounded-full hover:cqa-bg-[#E5E7EB] focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] cqa-transition-colors cqa-whitespace-nowrap\">\n {{ snippet }}\n </button>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n\n <!-- Line below content (full width of modal, no side margin) -->\n <div class=\"cqa--mx-2 cqa-w-[calc(100%+1rem)] cqa-flex-shrink-0\">\n <div class=\"cqa-h-px cqa-w-full cqa-bg-[#E5E7EB]\" role=\"presentation\"></div>\n </div>\n\n <!-- Footer: Cancel, Apply (full width in one row) -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <div class=\"cqa-flex cqa-items-stretch cqa-gap-2 cqa-w-full\">\n <div class=\"cqa-flex-1 cqa-min-w-0\">\n <cqa-button variant=\"outlined\" btnSize=\"lg\" [text]=\"'Cancel'\" [fullWidth]=\"true\" (clicked)=\"onCancel()\"\n [customClass]=\"'cqa-text-[12px] cqa-py-[9px] cqa-border-[#414146]'\"></cqa-button>\n </div>\n <div class=\"cqa-flex-1 cqa-min-w-0\">\n <cqa-button variant=\"filled\" btnSize=\"lg\" [text]=\"'Apply'\" [fullWidth]=\"true\" (clicked)=\"onApply()\"\n [customClass]=\"'cqa-text-[12px] cqa-py-[9px] cqa-border-[#3F43EE]'\"></cqa-button>\n </div>\n </div>\n <a href=\"#\" (click)=\"onEditInDepth($event)\"\n class=\"cqa-text-[#3F43EE] cqa-text-[12px] cqa-leading-[18px] cqa-font-medium cqa-flex cqa-items-center cqa-gap-1.5 cqa-no-underline hover:cqa-no-underline cqa-self-center\">\n <mat-icon class=\"!cqa-w-4 !cqa-h-4 !cqa-text-[16px]\">open_in_new</mat-icon>\n Edit in depth (open detailed right panel)\n </a>\n </div>\n</div>\n", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: SegmentControlComponent, selector: "cqa-segment-control", inputs: ["segments", "value", "disabled", "containerBgColor"], outputs: ["valueChange"] }, { type: CustomInputComponent, selector: "cqa-custom-input", inputs: ["label", "type", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "inputInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused", "enterPressed"] }, { type: ItemListComponent, selector: "cqa-item-list", inputs: ["items", "selectedId", "emptyMessage", "scrollable"], outputs: ["itemSelect", "itemEdit"] }, { type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
16757
16636
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestDataModalComponent, decorators: [{
16758
16637
  type: Component,
16759
16638
  args: [{ selector: 'cqa-test-data-modal', host: { class: 'cqa-ui-root' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"cqa-bg-white cqa-rounded-[12px] cqa-shadow-lg cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-w-[500px] cqa-flex cqa-flex-col cqa-gap-[12px] cqa-p-2 cqa-box-border cqa-min-h-0\">\n <!-- Header: title left; Need help? + close icon right -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-gap-2 cqa-px-4\">\n <h2 class=\"cqa-text-[16px] cqa-leading-[24px] cqa-font-bold cqa-text-[#111827] cqa-m-0 cqa-font-[600]\">\n Test Data\n </h2>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-min-h-[28px]\">\n <!-- Need help? with custom tooltip (works inside overlay) -->\n <div class=\"cqa-relative cqa-inline-flex cqa-items-center\"\n (mouseenter)=\"showHelpTooltip = true\" (mouseleave)=\"showHelpTooltip = false\">\n <a *ngIf=\"helpUrl\" href=\"#\" (click)=\"onHelp($event)\"\n class=\"cqa-flex cqa-items-center cqa-gap-1 cqa-text-[#3F43EE] cqa-text-[12px] cqa-leading-[21px] cqa-no-underline hover:cqa-underline cqa-cursor-pointer\">\n <svg width=\"17\" height=\"16\" viewBox=\"0 0 17 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" class=\"cqa-flex-shrink-0\" aria-hidden=\"true\">\n <g clip-path=\"url(#test-data-help-clip)\">\n <path d=\"M8.50033 14.6663C12.4123 14.6663 15.5837 11.6816 15.5837 7.99967C15.5837 4.31778 12.4123 1.33301 8.50033 1.33301C4.58831 1.33301 1.41699 4.31778 1.41699 7.99967C1.41699 11.6816 4.58831 14.6663 8.50033 14.6663Z\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.43848 6.00038C6.60501 5.55483 6.93371 5.17912 7.36636 4.9398C7.79901 4.70049 8.30769 4.61301 8.80231 4.69285C9.29693 4.7727 9.74556 5.01473 10.0687 5.37607C10.3919 5.7374 10.5688 6.19473 10.5681 6.66705C10.5681 8.00038 8.44306 8.66705 8.44306 8.66705\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.5 11.333H8.50966\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </g>\n <defs>\n <clipPath id=\"test-data-help-clip\">\n <rect width=\"17\" height=\"16\" fill=\"white\"/>\n </clipPath>\n </defs>\n </svg>\n Need help ?\n </a>\n <span *ngIf=\"!helpUrl\" class=\"cqa-flex cqa-items-center cqa-gap-1.5 cqa-font-[500] cqa-text-[10px] cqa-cursor-default\">\n <svg width=\"17\" height=\"16\" viewBox=\"0 0 17 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" class=\"cqa-flex-shrink-0 cqa-text-[#3F43EE]\" aria-hidden=\"true\">\n <g clip-path=\"url(#test-data-help-clip-nolink)\">\n <path d=\"M8.50033 14.6663C12.4123 14.6663 15.5837 11.6816 15.5837 7.99967C15.5837 4.31778 12.4123 1.33301 8.50033 1.33301C4.58831 1.33301 1.41699 4.31778 1.41699 7.99967C1.41699 11.6816 4.58831 14.6663 8.50033 14.6663Z\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.43848 6.00038C6.60501 5.55483 6.93371 5.17912 7.36636 4.9398C7.79901 4.70049 8.30769 4.61301 8.80231 4.69285C9.29693 4.7727 9.74556 5.01473 10.0687 5.37607C10.3919 5.7374 10.5688 6.19473 10.5681 6.66705C10.5681 8.00038 8.44306 8.66705 8.44306 8.66705\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.5 11.333H8.50966\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </g>\n <defs>\n <clipPath id=\"test-data-help-clip-nolink\">\n <rect width=\"17\" height=\"16\" fill=\"white\"/>\n </clipPath>\n </defs>\n </svg>\n Need help ?\n </span>\n <!-- Custom tooltip (exact spec: 306\u00D720 content, 6px radius, #0A0A0A, no arrow) -->\n <div *ngIf=\"showHelpTooltip\"\n class=\"cqa-absolute cqa-pointer-events-none cqa-z-[100] cqa-top-[-24px] cqa-left-[-125px]\"\n role=\"tooltip\">\n <div\n class=\"cqa-text-white cqa-text-center cqa-whitespace-nowrap cqa-w-[306px] cqa-min-h-[20px] cqa-rounded-[6px] cqa-py-1 cqa-px-2 cqa-bg-[#0A0A0A] cqa-leading-[20px] cqa-text-[8px]\">\n {{ helpTooltipText }}\n </div>\n </div>\n </div>\n <button type=\"button\" (click)=\"onClose()\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-min-h-[28px] cqa-min-w-[28px] cqa-rounded cqa-text-[#6B7280] hover:cqa-bg-[#F3F4F6] cqa-p-0\"\n title=\"Close\" aria-label=\"Close\">\n <mat-icon class=\"!cqa-w-5 !cqa-h-5 !cqa-text-[20px] !cqa-block !cqa-leading-none\">close</mat-icon>\n </button>\n </div>\n </div>\n\n <!-- Line below header (full width of modal, no side margin) -->\n <div class=\"cqa--mx-2 cqa-w-[calc(100%+1rem)] cqa-flex-shrink-0\">\n <div class=\"cqa-h-px cqa-w-full cqa-bg-[#E5E7EB]\" role=\"presentation\"></div>\n </div>\n\n <!-- Tabs: Plain Text, Parameter, Environment, Runtime (bound to editForm like Loop Step) -->\n <div class=\"cqa-w-full cqa-test-data-modal-tabs\">\n <cqa-segment-control\n [segments]=\"tabSegments\"\n [value]=\"editForm.get('activeTab')?.value ?? activeTab\"\n (valueChange)=\"onTabChange($event)\">\n </cqa-segment-control>\n </div>\n\n <!-- Content per tab: flex-1 min-h-0 so Parameter/Environment/Runtime content can scroll -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1.5 cqa-min-h-0\"\n [class.cqa-flex-1]=\"activeTab === 'parameter' || activeTab === 'environment' || activeTab === 'runtime'\">\n <!-- Plain Text tab (form-bound like Loop Step editForm + onEditFormFieldChange) -->\n <ng-container *ngIf=\"activeTab === 'plain-text'\">\n <cqa-custom-input\n label=\"Value\"\n [value]=\"editForm.get('value')?.value ?? ''\"\n (valueChange)=\"onEditFormFieldChange('value', $event)\"\n placeholder=\"https://example.com/dashboard\"\n [fullWidth]=\"true\"\n size=\"md\">\n </cqa-custom-input>\n <p class=\"cqa-text-[12px] cqa-leading-[18px] cqa-text-[#0A0A0A] cqa-m-0\">\n Enter a static text value that won't change during execution.\n </p>\n </ng-container>\n\n <!-- Parameter tab: Variable Library -->\n <ng-container *ngIf=\"activeTab === 'parameter'\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2 cqa-min-h-0 cqa-flex-1 cqa-min-h-[18rem]\">\n <!-- Variable Library header -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-flex-shrink-0\">\n <h3 class=\"cqa-text-[12px] cqa-leading-[20px] cqa-font-semibold cqa-text-[#111827] cqa-m-0\">\n Variable Library\n </h3>\n <a href=\"#\" (click)=\"onCreateNewVariable($event)\"\n class=\"cqa-text-[#3F43EE] cqa-text-[12px] cqa-leading-[18px] cqa-font-medium cqa-no-underline hover:cqa-opacity-90 cqa-cursor-pointer\">\n Create New +\n </a>\n </div>\n <!-- Filter tabs: All, Global, Local (blue underline under active label only) -->\n <div class=\"cqa-flex cqa-w-full cqa-flex-shrink-0\">\n <button *ngFor=\"let tab of parameterFilterTabs\" type=\"button\"\n (click)=\"onParameterScopeFilterChange(tab.value)\"\n class=\"cqa-flex-1 cqa-py-0 cqa-px-3 cqa-text-[12px] cqa-leading-[18px] cqa-font-medium cqa-bg-transparent cqa-cursor-pointer cqa-transition-colors cqa-flex cqa-justify-center cqa-items-center\"\n [class.cqa-text-[#6B7280]]=\"parameterScopeFilter !== tab.value\">\n <span class=\"cqa-test-data-param-filter-label cqa-inline-block cqa-pb-0.5\"\n [class.cqa-test-data-param-filter-active]=\"parameterScopeFilter === tab.value\">\n {{ tab.label }}\n </span>\n </button>\n </div>\n <!-- Search: bound to editForm (same pattern as Loop Step control binding) -->\n <div class=\"cqa-flex-shrink-0 cqa-relative cqa-flex cqa-items-center\">\n <span class=\"cqa-absolute cqa-left-4 cqa-top-0 cqa-bottom-0 cqa-flex cqa-items-center cqa-justify-center cqa-pointer-events-none cqa-text-[#6B7280] cqa-leading-none\" aria-hidden=\"true\">\n <mat-icon class=\"!cqa-w-4 !cqa-h-4 !cqa-text-[16px]\">search</mat-icon>\n </span>\n <input\n type=\"text\"\n [value]=\"editForm.get('parameterSearchQuery')?.value ?? ''\"\n (input)=\"onParameterSearchInput($any($event.target).value)\"\n placeholder=\"Search library\"\n class=\"cqa-test-data-search-input cqa-w-full cqa-pl-10 cqa-pr-4 cqa-py-2.5 cqa-text-sm cqa-leading-5 cqa-text-[#0A0A0A] placeholder:cqa-text-[#9CA3AF] focus:cqa-outline-none focus:cqa-border-[#3B82F6] focus:cqa-ring-1 focus:cqa-ring-[#3B82F6]\"\n aria-label=\"Search library\"\n />\n </div>\n <!-- Parameter list (scrollable, search-integrated via filtered list binding) -->\n <div class=\"cqa-min-h-[200px] cqa-flex-1 cqa-flex cqa-flex-col\">\n <cqa-item-list\n [items]=\"parameterListConfig\"\n [selectedId]=\"selectedParameterId\"\n emptyMessage=\"No parameters match your search.\"\n [scrollable]=\"true\"\n (itemSelect)=\"onParameterSelect($event)\"\n (itemEdit)=\"onParameterEdit($event)\">\n </cqa-item-list>\n </div>\n </div>\n </ng-container>\n\n <!-- Environment tab: Variable library by environment -->\n <ng-container *ngIf=\"activeTab === 'environment'\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2 cqa-min-h-0 cqa-flex-1 cqa-min-h-[18rem]\">\n <!-- Section header -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-flex-shrink-0\">\n <h3 class=\"cqa-text-[12px] cqa-leading-[20px] cqa-font-semibold cqa-text-[#111827] cqa-m-0\">\n Environment\n </h3>\n <a href=\"#\" (click)=\"onCreateNewEnvironment($event)\"\n class=\"cqa-text-[#3F43EE] cqa-text-[12px] cqa-leading-[18px] cqa-font-medium cqa-no-underline hover:cqa-opacity-90 cqa-cursor-pointer\">\n Create New +\n </a>\n </div>\n <!-- Search: bound to editForm (same pattern as Loop Step control binding) -->\n <div class=\"cqa-flex-shrink-0 cqa-relative cqa-flex cqa-items-center\">\n <span class=\"cqa-absolute cqa-left-4 cqa-top-0 cqa-bottom-0 cqa-flex cqa-items-center cqa-justify-center cqa-pointer-events-none cqa-text-[#6B7280] cqa-leading-none\" aria-hidden=\"true\">\n <mat-icon class=\"!cqa-w-4 !cqa-h-4 !cqa-text-[16px]\">search</mat-icon>\n </span>\n <input\n type=\"text\"\n [value]=\"editForm.get('environmentSearchQuery')?.value ?? ''\"\n (input)=\"onEnvironmentSearchInput($any($event.target).value)\"\n placeholder=\"Search Environment\"\n class=\"cqa-test-data-search-input cqa-w-full cqa-pl-10 cqa-pr-4 cqa-py-2.5 cqa-text-sm cqa-leading-5 cqa-text-[#0A0A0A] placeholder:cqa-text-[#9CA3AF] focus:cqa-outline-none focus:cqa-border-[#3B82F6] focus:cqa-ring-1 focus:cqa-ring-[#3B82F6]\"\n aria-label=\"Search Environment\"\n />\n </div>\n <!-- Environment list (scrollable, search-integrated via filtered list binding) -->\n <div class=\"cqa-min-h-[220px] cqa-flex-1 cqa-flex cqa-flex-col\">\n <cqa-item-list\n [items]=\"environmentListConfig\"\n [selectedId]=\"selectedEnvironmentId\"\n emptyMessage=\"No environment variables match your search.\"\n [scrollable]=\"true\"\n (itemSelect)=\"onEnvironmentSelect($event)\"\n (itemEdit)=\"onEnvironmentEdit($event)\">\n </cqa-item-list>\n </div>\n </div>\n </ng-container>\n\n <!-- Runtime tab: dynamic value injector -->\n <ng-container *ngIf=\"activeTab === 'runtime'\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3 cqa-min-h-0 cqa-h-full cqa-overflow-y-auto\">\n <h3 class=\"cqa-text-[12px] cqa-leading-[20px] cqa-font-semibold cqa-text-[#111827] cqa-m-0 cqa-flex-shrink-0\">\n Runtime\n </h3>\n <div class=\"cqa-flex-shrink-0\">\n <cqa-custom-input\n [value]=\"editForm.get('runtimeValue')?.value ?? ''\"\n (valueChange)=\"onEditFormFieldChange('runtimeValue', $event)\"\n placeholder=\"input text\"\n [fullWidth]=\"true\"\n size=\"md\">\n </cqa-custom-input>\n <p class=\"cqa-text-[12px] cqa-leading-[18px] cqa-text-[#6B7280] cqa-mt-1.5 cqa-mb-0\">\n Values resolved during test execution based on session and step state.\n </p>\n </div>\n <!-- Recommended: suggestion chips -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2 cqa-flex-shrink-0\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <mat-icon class=\"!cqa-w-4 !cqa-h-4 !cqa-text-[16px] cqa-text-[#9CA3AF]\" aria-hidden=\"true\">schedule</mat-icon>\n <span class=\"cqa-text-[12px] cqa-leading-[18px] cqa-font-medium cqa-text-[#374151]\">Recommended</span>\n </div>\n <div class=\"cqa-test-data-runtime-chips-scroll cqa-flex cqa-gap-2 cqa-overflow-x-auto cqa-min-w-0 cqa-pb-1\">\n <button\n *ngFor=\"let snippet of runtimeSuggestedValues\"\n type=\"button\"\n (click)=\"onRuntimeChipInsert(snippet)\"\n class=\"cqa-flex-shrink-0 cqa-px-3 cqa-py-1.5 cqa-text-[12px] cqa-leading-[18px] cqa-font-medium cqa-text-[#374151] cqa-bg-[#F3F4F6] cqa-rounded-full hover:cqa-bg-[#E5E7EB] focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] cqa-transition-colors cqa-whitespace-nowrap\">\n {{ snippet }}\n </button>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n\n <!-- Line below content (full width of modal, no side margin) -->\n <div class=\"cqa--mx-2 cqa-w-[calc(100%+1rem)] cqa-flex-shrink-0\">\n <div class=\"cqa-h-px cqa-w-full cqa-bg-[#E5E7EB]\" role=\"presentation\"></div>\n </div>\n\n <!-- Footer: Cancel, Apply (full width in one row) -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <div class=\"cqa-flex cqa-items-stretch cqa-gap-2 cqa-w-full\">\n <div class=\"cqa-flex-1 cqa-min-w-0\">\n <cqa-button variant=\"outlined\" btnSize=\"lg\" [text]=\"'Cancel'\" [fullWidth]=\"true\" (clicked)=\"onCancel()\"\n [customClass]=\"'cqa-text-[12px] cqa-py-[9px] cqa-border-[#414146]'\"></cqa-button>\n </div>\n <div class=\"cqa-flex-1 cqa-min-w-0\">\n <cqa-button variant=\"filled\" btnSize=\"lg\" [text]=\"'Apply'\" [fullWidth]=\"true\" (clicked)=\"onApply()\"\n [customClass]=\"'cqa-text-[12px] cqa-py-[9px] cqa-border-[#3F43EE]'\"></cqa-button>\n </div>\n </div>\n <a href=\"#\" (click)=\"onEditInDepth($event)\"\n class=\"cqa-text-[#3F43EE] cqa-text-[12px] cqa-leading-[18px] cqa-font-medium cqa-flex cqa-items-center cqa-gap-1.5 cqa-no-underline hover:cqa-no-underline cqa-self-center\">\n <mat-icon class=\"!cqa-w-4 !cqa-h-4 !cqa-text-[16px]\">open_in_new</mat-icon>\n Edit in depth (open detailed right panel)\n </a>\n </div>\n</div>\n" }]
@@ -16773,6 +16652,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
16773
16652
  type: Output
16774
16653
  }], editInDepth: [{
16775
16654
  type: Output
16655
+ }], parameterCreate: [{
16656
+ type: Output
16657
+ }], parameterEdit: [{
16658
+ type: Output
16659
+ }], environmentCreate: [{
16660
+ type: Output
16661
+ }], environmentEdit: [{
16662
+ type: Output
16663
+ }], parameters: [{
16664
+ type: Input
16665
+ }], environmentItems: [{
16666
+ type: Input
16776
16667
  }] } });
16777
16668
 
16778
16669
  class TestDataModalService {
@@ -16863,12 +16754,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
16863
16754
  }], ctorParameters: function () { return [{ type: i1$6.Overlay }, { type: i0.Injector }]; } });
16864
16755
 
16865
16756
  class TestCaseNormalStepComponent {
16866
- constructor(customEditStep, elementPopup, testDataModal, cdr, ngZone) {
16757
+ constructor(customEditStep, elementPopup, testDataModal, cdr, ngZone, sanitizer) {
16867
16758
  this.customEditStep = customEditStep;
16868
16759
  this.elementPopup = elementPopup;
16869
16760
  this.testDataModal = testDataModal;
16870
16761
  this.cdr = cdr;
16871
16762
  this.ngZone = ngZone;
16763
+ this.sanitizer = sanitizer;
16872
16764
  this.parameters = [];
16873
16765
  this.selected = false;
16874
16766
  this.disabled = false;
@@ -16883,6 +16775,7 @@ class TestCaseNormalStepComponent {
16883
16775
  this.delete = new EventEmitter();
16884
16776
  this.moreOptions = new EventEmitter();
16885
16777
  this.selectionChange = new EventEmitter();
16778
+ this.clickAction = new EventEmitter();
16886
16779
  this.eventTypeDropdownOpen = false;
16887
16780
  /** Stored test data modal state for reopening with same selections. */
16888
16781
  this.testDataModalState = null;
@@ -16959,6 +16852,7 @@ class TestCaseNormalStepComponent {
16959
16852
  }
16960
16853
  ngOnInit() {
16961
16854
  if (this.config) {
16855
+ this.action = this.config.action || '';
16962
16856
  this.stepNumber = this.config.stepNumber;
16963
16857
  this.eventType = this.config.eventType;
16964
16858
  this.parameters = this.config.parameters || [];
@@ -16970,31 +16864,10 @@ class TestCaseNormalStepComponent {
16970
16864
  return this.eventTypeConfigs.find(etc => etc.type === this.eventType) || this.eventTypeConfigs[0];
16971
16865
  }
16972
16866
  getActionDescription() {
16973
- const config = this.getCurrentEventTypeConfig();
16974
- switch (this.eventType) {
16975
- case 'navigate':
16976
- return 'Navigate to';
16977
- case 'type':
16978
- return 'Type';
16979
- case 'click':
16980
- return 'Click on';
16981
- case 'doubleClick':
16982
- return 'Double click on';
16983
- case 'pressEnter':
16984
- return 'Press Enter on';
16985
- case 'enter':
16986
- return 'Enter';
16987
- case 'wait':
16988
- return 'Wait';
16989
- case 'verify':
16990
- return 'Verify';
16991
- case 'custom':
16992
- return 'Custom step';
16993
- case 'ai-agent':
16994
- return 'AI Agent';
16995
- default:
16996
- return '';
16867
+ if (this.action) {
16868
+ return this.action ? this.sanitizer.bypassSecurityTrustHtml(this.action) : '';
16997
16869
  }
16870
+ return '';
16998
16871
  }
16999
16872
  getActionSuffix() {
17000
16873
  switch (this.eventType) {
@@ -17225,13 +17098,18 @@ class TestCaseNormalStepComponent {
17225
17098
  this.closeEventTypeDropdown();
17226
17099
  }
17227
17100
  }
17101
+ clickOnAction(event) {
17102
+ event.preventDefault();
17103
+ event.stopPropagation();
17104
+ this.clickAction.emit(event);
17105
+ }
17228
17106
  }
17229
- TestCaseNormalStepComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestCaseNormalStepComponent, deps: [{ token: CustomEditStepService }, { token: ElementPopupService }, { token: TestDataModalService }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
17230
- TestCaseNormalStepComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TestCaseNormalStepComponent, selector: "cqa-test-case-normal-step", inputs: { config: "config", stepNumber: "stepNumber", eventType: "eventType", parameters: "parameters", selected: "selected", disabled: "disabled", isNested: "isNested", isInsideLoop: "isInsideLoop", isReorder: "isReorder" }, outputs: { eventTypeChange: "eventTypeChange", parameterChange: "parameterChange", edit: "edit", link: "link", duplicate: "duplicate", delete: "delete", moreOptions: "moreOptions", selectionChange: "selectionChange" }, host: { listeners: { "document:click": "onDocumentClick($event)" }, classAttribute: "cqa-ui-root" }, viewQueries: [{ propertyName: "dropdownContainer", first: true, predicate: ["dropdownContainer"], descendants: true }, { propertyName: "descriptionTrigger", first: true, predicate: ["descriptionTrigger"], descendants: true }, { propertyName: "testDataTrigger", first: true, predicate: ["testDataTrigger"], descendants: true }, { propertyName: "editTrigger", first: true, predicate: ["editTrigger"], descendants: true }, { propertyName: "elementTrigger", first: true, predicate: ["elementTrigger"], descendants: true }], ngImport: i0, template: "<div [class]=\"'step-row cqa-flex cqa-items-center cqa-gap-3 cqa-py-[12.5px] ' + (isInsideLoop ? 'cqa-pl-10 cqa-pr-4' : 'cqa-px-4')\" style=\"border-bottom: 1px solid #E5E7EB;\">\n\n <div class=\"cqa-inline-flex cqa-items-center\">\n <!-- Drag Handle Icon (when isReorder is true) - 9-dot grid (3x3) -->\n <div *ngIf=\"isReorder\" class=\"cqa-mr-2 cqa-cursor-move cqa-text-[#6B7280] hover:cqa-text-[#111827]\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"3\" cy=\"3\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"8\" cy=\"3\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"13\" cy=\"3\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"3\" cy=\"8\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"8\" cy=\"8\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"13\" cy=\"8\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"3\" cy=\"13\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"8\" cy=\"13\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"13\" cy=\"13\" r=\"1.5\" fill=\"currentColor\"/>\n </svg>\n </div>\n <!-- Checkbox (when isReorder is false) -->\n <label *ngIf=\"!isReorder\" class=\"cqa-flex cqa-items-center cqa-cursor-pointer cqa-relative cqa-mr-2\">\n <input type=\"checkbox\"\n [ngModel]=\"selected\"\n [disabled]=\"disabled\"\n (ngModelChange)=\"onSelectionChange($event)\"\n class=\"cqa-h-4 cqa-w-4 cqa-cursor-pointer cqa-transition-all cqa-appearance-none cqa-rounded shadow hover:cqa-shadow-md cqa-border cqa-border-solid cqa-border-slate-300 cqa-flex-shrink-0\"\n [class.cqa-bg-[#3F43EE]]=\"selected\"\n [class.cqa-border-[#3F43EE]]=\"selected\"\n id=\"check\" />\n <span class=\"cqa-absolute cqa-text-white cqa-top-1/2 cqa-left-1/2 cqa--translate-x-1/2 cqa--translate-y-1/2 cqa-pointer-events-none cqa-flex cqa-items-center cqa-justify-center\"\n [class.cqa-opacity-0]=\"!selected\"\n [class.cqa-opacity-100]=\"selected\">\n <svg width=\"12\" height=\"13\" viewBox=\"0 0 12 13\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M10 3.125L4.5 8.625L2 6.125\" stroke=\"white\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </span>\n </label>\n </div>\n\n <!-- Step Number -->\n <span class=\"cqa-text-[#6B7280] cqa-text-[14px] cqa-leading-[18px] cqa-min-w-[32px]\">\n {{ stepNumber }}\n </span>\n\n <!-- Event Type Selector (Pill Button) #### (click)=\"toggleEventTypeDropdown(); $event.stopPropagation()\" -->\n <div class=\"cqa-relative\" #dropdownContainer>\n <button type=\"button\" \n [style.background-color]=\"getCurrentEventTypeConfig().backgroundColor\"\n [style.color]=\"getCurrentEventTypeConfig().color\" [style.border-color]=\"getCurrentEventTypeConfig().color\"\n class=\"cqa-px-2.5 cqa-py-1 cqa-rounded-lg cqa-flex cqa-items-center cqa-gap-2 cqa-cursor-pointer\">\n <!-- Icon -->\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'paper_plane'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1.75 6.41663L12.8333 1.16663L7.58333 12.25L6.41667 7.58329L1.75 6.41663Z\" stroke=\"#432DD7\"\n stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'star'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M5.797 9.04165C5.74492 8.83977 5.63969 8.65554 5.49227 8.50812C5.34485 8.3607 5.16062 8.25548 4.95875 8.2034L1.38 7.28057C1.31894 7.26324 1.2652 7.22646 1.22694 7.17583C1.18867 7.12519 1.16797 7.06345 1.16797 6.99998C1.16797 6.93651 1.18867 6.87478 1.22694 6.82414C1.2652 6.7735 1.31894 6.73673 1.38 6.7194L4.95875 5.79598C5.16055 5.74395 5.34473 5.63882 5.49215 5.49151C5.63956 5.34419 5.74483 5.16008 5.797 4.95832L6.71983 1.37957C6.73698 1.31827 6.77372 1.26427 6.82443 1.2258C6.87515 1.18733 6.93705 1.1665 7.0007 1.1665C7.06436 1.1665 7.12626 1.18733 7.17698 1.2258C7.22769 1.26427 7.26442 1.31827 7.28158 1.37957L8.20383 4.95832C8.25591 5.16019 8.36113 5.34442 8.50855 5.49184C8.65597 5.63926 8.8402 5.74449 9.04208 5.79657L12.6208 6.71882C12.6824 6.73579 12.7366 6.77249 12.7753 6.82328C12.814 6.87407 12.8349 6.93614 12.8349 6.99998C12.8349 7.06382 12.814 7.1259 12.7753 7.17669C12.7366 7.22748 12.6824 7.26417 12.6208 7.28115L9.04208 8.2034C8.8402 8.25548 8.65597 8.3607 8.50855 8.50812C8.36113 8.65554 8.25591 8.83977 8.20383 9.04165L7.281 12.6204C7.26384 12.6817 7.22711 12.7357 7.17639 12.7742C7.12568 12.8126 7.06377 12.8335 7.00012 12.8335C6.93647 12.8335 6.87456 12.8126 6.82385 12.7742C6.77314 12.7357 6.7364 12.6817 6.71925 12.6204L5.797 9.04165Z\"\n stroke=\"#7008E7\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M11.666 1.75V4.08333\" stroke=\"#7008E7\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M12.8333 2.91663H10.5\" stroke=\"#7008E7\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M2.33398 9.91663V11.0833\" stroke=\"#7008E7\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M2.91667 10.5H1.75\" stroke=\"#7008E7\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'T'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M2.33398 4.08325V2.33325H11.6673V4.08325\" stroke=\"#8200DB\" stroke-width=\"1.16667\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M5.25 11.6667H8.75\" stroke=\"#8200DB\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M7 2.33325V11.6666\" stroke=\"#8200DB\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'cursor'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1.75 1.75L5.87417 11.6492L7.33833 7.33833L11.6492 5.87417L1.75 1.75Z\" stroke=\"#1447E6\"\n stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M7.58398 7.58325L11.084 11.0833\" stroke=\"#1447E6\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'cursor-double'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8.16667 2.3916L7 3.49993\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M2.97487 4.66662L1.2832 4.19995\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M3.50091 7L2.39258 8.16667\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M4.19922 1.28345L4.66589 2.97511\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M5.27114 5.65255C5.24852 5.59926 5.24234 5.54043 5.25338 5.48361C5.26443 5.42678 5.2922 5.37455 5.33313 5.33362C5.37407 5.29269 5.4263 5.26492 5.48312 5.25387C5.53994 5.24283 5.59877 5.24901 5.65206 5.27163L12.0687 7.89663C12.1258 7.92006 12.174 7.961 12.2064 8.01357C12.2388 8.06613 12.2536 8.12761 12.2488 8.18915C12.244 8.25069 12.2198 8.30912 12.1797 8.35603C12.1396 8.40295 12.0856 8.43592 12.0256 8.45021L9.48864 9.05746C9.38391 9.08248 9.28815 9.13599 9.21196 9.21208C9.13578 9.28816 9.08213 9.38385 9.05698 9.48855L8.45031 12.026C8.43617 12.0863 8.40323 12.1405 8.35626 12.1808C8.30928 12.2211 8.25071 12.2454 8.189 12.2502C8.1273 12.255 8.06567 12.2401 8.01302 12.2075C7.96037 12.175 7.91944 12.1266 7.89614 12.0692L5.27114 5.65255Z\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'enter'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M11.0833 1.75L11.0833 5.83333L2.91667 5.83333\" stroke=\"#1447E6\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M7.58333 1.75L11.0833 5.25L7.58333 8.75\" stroke=\"#1447E6\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M2.91667 8.75L2.91667 12.25\" stroke=\"#1447E6\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'clock'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M6.99935 12.8334C10.221 12.8334 12.8327 10.2217 12.8327 7.00008C12.8327 3.77842 10.221 1.16675 6.99935 1.16675C3.77769 1.16675 1.16602 3.77842 1.16602 7.00008C1.16602 10.2217 3.77769 12.8334 6.99935 12.8334Z\"\n stroke=\"#364153\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M7 3.5V7L9.33333 8.16667\" stroke=\"#364153\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </span>\n\n <!-- Label -->\n <span class=\"cqa-text-[#432DD7] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium\">{{\n getCurrentEventTypeConfig().label }}</span>\n </button>\n\n <!-- Dropdown Menu -->\n <div *ngIf=\"eventTypeDropdownOpen\" (click)=\"$event.stopPropagation()\"\n class=\"cqa-absolute cqa-top-full cqa-left-0 cqa-mt-1 cqa-bg-white cqa-rounded-lg cqa-shadow-lg cqa-border cqa-border-gray-200 cqa-z-50 cqa-min-w-[150px] cqa-py-1\">\n <button *ngFor=\"let etc of eventTypeConfigs\" type=\"button\" (click)=\"onEventTypeSelect(etc.type)\"\n [class.cqa-bg-primary-50]=\"eventType === etc.type\"\n class=\"cqa-w-full cqa-px-3 cqa-py-2 cqa-text-left cqa-flex cqa-items-center cqa-gap-2 hover:cqa-bg-gray-50 cqa-transition-colors\">\n <span *ngIf=\"etc.icon === 'paper_plane'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1 5.5L11 1M11 1L7.5 11L6 6.5L1 5.5M11 1L1 5.5\" stroke=\"currentColor\" stroke-width=\"1.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"etc.icon === 'star'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 1L7.5 4.5L11 5L7.5 5.5L6 9L4.5 5.5L1 5L4.5 4.5L6 1Z\" fill=\"currentColor\" />\n </svg>\n </span>\n <span *ngIf=\"etc.icon === 'T'\">\n T\n </span>\n <span *ngIf=\"etc.icon === 'cursor'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M2 2L9 1L10 8L7 7L5 9L4 7L2 2Z\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"etc.icon === 'cursor-double'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8.16667 2.3916L7 3.49993\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M2.97487 4.66662L1.2832 4.19995\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M3.50091 7L2.39258 8.16667\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M4.19922 1.28345L4.66589 2.97511\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M5.27114 5.65255C5.24852 5.59926 5.24234 5.54043 5.25338 5.48361C5.26443 5.42678 5.2922 5.37455 5.33313 5.33362C5.37407 5.29269 5.4263 5.26492 5.48312 5.25387C5.53994 5.24283 5.59877 5.24901 5.65206 5.27163L12.0687 7.89663C12.1258 7.92006 12.174 7.961 12.2064 8.01357C12.2388 8.06613 12.2536 8.12761 12.2488 8.18915C12.244 8.25069 12.2198 8.30912 12.1797 8.35603C12.1396 8.40295 12.0856 8.43592 12.0256 8.45021L9.48864 9.05746C9.38391 9.08248 9.28815 9.13599 9.21196 9.21208C9.13578 9.28816 9.08213 9.38385 9.05698 9.48855L8.45031 12.026C8.43617 12.0863 8.40323 12.1405 8.35626 12.1808C8.30928 12.2211 8.25071 12.2454 8.189 12.2502C8.1273 12.255 8.06567 12.2401 8.01302 12.2075C7.96037 12.175 7.91944 12.1266 7.89614 12.0692L5.27114 5.65255Z\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg> \n </span>\n <span *ngIf=\"etc.icon === 'enter'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M9.5 1.5L9.5 5L2 5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.5 1.5L9.5 4.5L6.5 7.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M2 7.5L2 10.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span *ngIf=\"etc.icon === 'clock'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"6\" cy=\"6\" r=\"5\" stroke=\"currentColor\" stroke-width=\"1.5\" />\n <path d=\"M6 3V6L8 7\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n </span>\n <span>{{ etc.label }}</span>\n </button>\n </div>\n </div>\n\n <!-- Action Description -->\n <span class=\"cqa-text-[#111827] cqa-text-[14px] cqa-leading-[18px]\" *ngIf=\"getActionDescription()\">\n {{ getActionDescription() }}\n </span>\n\n <!-- Parameters -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-3\">\n <!-- Navigate: URL as clickable trigger for Test Data modal -->\n <span *ngIf=\"eventType === 'navigate' && getNavigateUrlParameter()\" #testDataTrigger\n (click)=\"openTestDataModal($event)\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC] cqa-cursor-pointer hover:cqa-opacity-90\">\n {{ getNavigateUrlParameter()?.value || getNavigateUrlParameter()?.displayValue }}\n </span>\n \n <!-- Other event types: loop through parameters (navigate excluded) -->\n <ng-container *ngFor=\"let param of parameters; let i = index\">\n <!-- Skip navigate parameters in the loop (already shown above) -->\n <ng-container *ngIf=\"eventType !== 'navigate'\">\n\n <!-- Type: First param (text value like {{username}}) -->\n <span *ngIf=\"eventType === 'type' && i === 0\" class=\"cqa-text-gray-900 cqa-text-sm\">\n {{ param.value }}\n </span>\n\n <!-- Type: \"into\" text -->\n <span *ngIf=\"eventType === 'type' && i === 0\" class=\"cqa-text-gray-900 cqa-text-sm\">\n into\n </span>\n\n <!-- Type: Second param (selector) -->\n <span *ngIf=\"eventType === 'type' && i === 1\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- Click: Selector input/display -->\n <span *ngIf=\"eventType === 'click' && param.name === 'element'\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- Click: Suffix text (like \"if Present\") -->\n <span *ngIf=\"eventType === 'click' && param.name === 'suffix'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n {{ param.value }}\n </span>\n\n <!-- Double Click: Selector input/display -->\n <span *ngIf=\"eventType === 'doubleClick' && i === 0\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- Press Enter: Selector input/display with HTML support -->\n <span *ngIf=\"eventType === 'pressEnter' && i === 0\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\"\n [innerHTML]=\"param.displayValue || param.value\">\n </span>\n\n <!-- Enter: Value display with quotes (like click action) -->\n <span *ngIf=\"eventType === 'enter' && param.name === 'value'\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- Enter: \"in the\" text -->\n <span *ngIf=\"eventType === 'enter' && param.name === 'value'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n in the\n </span>\n\n <!-- Enter: Label display with quotes (like click action) -->\n <span *ngIf=\"eventType === 'enter' && param.name === 'label'\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- Enter: \"field\" text -->\n <span *ngIf=\"eventType === 'enter' && param.name === 'label'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n field\n </span>\n\n <!-- Wait: Duration input -->\n <input *ngIf=\"eventType === 'wait' && param.name === 'duration'\" type=\"number\" [value]=\"param.value\"\n (input)=\"onParameterChange(param, $any($event.target).value)\" placeholder=\"2\"\n class=\"cqa-w-16 cqa-px-2 cqa-py-1.5 cqa-rounded-lg cqa-border cqa-border-solid cqa-border-[#9E9EE3] cqa-bg-[#D1C4E9] cqa-text-[#3F43EE] cqa-text-sm cqa-font-medium cqa-outline-none focus:cqa-ring-2 focus:cqa-ring-[#3F43EE] focus:cqa-ring-opacity-50\" />\n <span *ngIf=\"eventType === 'wait' && param.name === 'duration'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n seconds\n </span>\n\n <!-- Wait: Element selector -->\n <span *ngIf=\"eventType === 'wait' && param.name === 'element'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n for element\n </span>\n <span *ngIf=\"eventType === 'wait' && param.name === 'element'\" \n #elementTrigger\n (click)=\"openElementPopup($event)\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-cursor-pointer cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n <span *ngIf=\"eventType === 'wait' && param.name === 'element'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n to be visible\n </span>\n\n <!-- Custom: Description (clickable to open Step Description modal; pass $event so modal opens below this trigger) -->\n <span *ngIf=\"eventType === 'custom'\" #descriptionTrigger\n (click)=\"openStepDescriptionModal($event)\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC] cqa-cursor-pointer hover:cqa-opacity-90\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- AI Agent: Instructions -->\n <span *ngIf=\"eventType === 'ai-agent'\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n </ng-container>\n </ng-container>\n </div>\n\n <!-- AI Agent View Details Link -->\n <a *ngIf=\"eventType === 'ai-agent'\" href=\"#\" (click)=\"onMoreOptions(); $event.preventDefault()\" class=\"cqa-ml-auto cqa-text-[#3F43EE] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-flex cqa-items-center cqa-gap-2 cqa-no-underline\">View Details<svg width=\"8\" height=\"8\" viewBox=\"0 0 8 8\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2.03809 6.74329L2.62809 7.33329L5.96142 3.99996L2.62809 0.666626L2.03809 1.25663L4.78142 3.99996L2.03809 6.74329Z\" fill=\"#3F43EE\"/></svg></a>\n\n <!-- Action Icons: Edit, Link, Duplicate, Delete (show on hover, same as API step) -->\n <div class=\"step-actions cqa-flex cqa-items-center cqa-gap-3 cqa-ml-auto cqa-px-[7px]\">\n <button type=\"button\" #editTrigger (click)=\"onEdit(); $event.stopPropagation()\" title=\"Edit\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7 11.6666H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M9.55208 2.1128C9.7843 1.88058 10.0993 1.75012 10.4277 1.75012C10.7561 1.75012 11.071 1.88058 11.3033 2.1128C11.5355 2.34502 11.6659 2.65998 11.6659 2.98838C11.6659 3.31679 11.5355 3.63175 11.3033 3.86397L4.29742 10.8704C4.15864 11.0092 3.9871 11.1107 3.79867 11.1656L2.12333 11.6544C2.07314 11.669 2.01993 11.6699 1.96928 11.6569C1.91863 11.6439 1.8724 11.6176 1.83543 11.5806C1.79846 11.5437 1.7721 11.4974 1.75913 11.4468C1.74615 11.3961 1.74703 11.3429 1.76167 11.2927L2.2505 9.61738C2.30546 9.42916 2.40698 9.25783 2.54567 9.11922L9.55208 2.1128Z\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n <button type=\"button\" (click)=\"onLink(); $event.stopPropagation()\" title=\"Link\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M5.00065 9.91671H3.66732C2.78326 9.91671 1.93542 9.60942 1.3103 9.06244C0.685174 8.51545 0.333984 7.77359 0.333984 7.00004C0.333984 6.22649 0.685174 5.48463 1.3103 4.93765C1.93542 4.39066 2.78326 4.08337 3.66732 4.08337H5.00065\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M9 4.08337H10.3333C11.2174 4.08337 12.0652 4.39066 12.6904 4.93765C13.3155 5.48463 13.6667 6.22649 13.6667 7.00004C13.6667 7.77359 13.3155 8.51545 12.6904 9.06244C12.0652 9.60942 11.2174 9.91671 10.3333 9.91671H9\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M4.33398 7H9.66732\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n <button type=\"button\" (click)=\"onDuplicate(); $event.stopPropagation()\" title=\"Duplicate\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M11.666 4.66663H5.83268C5.18835 4.66663 4.66602 5.18896 4.66602 5.83329V11.6666C4.66602 12.311 5.18835 12.8333 5.83268 12.8333H11.666C12.3103 12.8333 12.8327 12.311 12.8327 11.6666V5.83329C12.8327 5.18896 12.3103 4.66663 11.666 4.66663Z\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M2.33268 9.33329C1.69102 9.33329 1.16602 8.80829 1.16602 8.16663V2.33329C1.16602 1.69163 1.69102 1.16663 2.33268 1.16663H8.16602C8.80768 1.16663 9.33268 1.69163 9.33268 2.33329\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n <button type=\"button\" (click)=\"onDelete(); $event.stopPropagation()\" title=\"Delete\" class=\"cqa-p-0 cqa-text-[#ff6467] hover:cqa-text-[#C63535]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1.75 3.5H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M11.0827 3.5V11.6667C11.0827 12.25 10.4993 12.8333 9.91602 12.8333H4.08268C3.49935 12.8333 2.91602 12.25 2.91602 11.6667V3.5\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M4.66602 3.49996V2.33329C4.66602 1.74996 5.24935 1.16663 5.83268 1.16663H8.16602C8.74935 1.16663 9.33268 1.74996 9.33268 2.33329V3.49996\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M5.83398 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.16602 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n </div>\n</div>", styles: [".step-actions{opacity:0;transition:opacity .15s ease}.step-row:hover .step-actions{opacity:1}\n"], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
17107
+ TestCaseNormalStepComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestCaseNormalStepComponent, deps: [{ token: CustomEditStepService }, { token: ElementPopupService }, { token: TestDataModalService }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: i1$1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
17108
+ TestCaseNormalStepComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TestCaseNormalStepComponent, selector: "cqa-test-case-normal-step", inputs: { config: "config", stepNumber: "stepNumber", action: "action", eventType: "eventType", parameters: "parameters", selected: "selected", disabled: "disabled", isNested: "isNested", isInsideLoop: "isInsideLoop", isReorder: "isReorder" }, outputs: { eventTypeChange: "eventTypeChange", parameterChange: "parameterChange", edit: "edit", link: "link", duplicate: "duplicate", delete: "delete", moreOptions: "moreOptions", selectionChange: "selectionChange", clickAction: "clickAction" }, host: { listeners: { "document:click": "onDocumentClick($event)" }, classAttribute: "cqa-ui-root" }, viewQueries: [{ propertyName: "dropdownContainer", first: true, predicate: ["dropdownContainer"], descendants: true }, { propertyName: "descriptionTrigger", first: true, predicate: ["descriptionTrigger"], descendants: true }, { propertyName: "testDataTrigger", first: true, predicate: ["testDataTrigger"], descendants: true }, { propertyName: "editTrigger", first: true, predicate: ["editTrigger"], descendants: true }, { propertyName: "elementTrigger", first: true, predicate: ["elementTrigger"], descendants: true }], ngImport: i0, template: "<div [class]=\"'step-row cqa-flex cqa-items-center cqa-gap-3 cqa-py-[12.5px] ' + (isInsideLoop ? 'cqa-pl-10 cqa-pr-4' : 'cqa-px-4')\" style=\"border-bottom: 1px solid #E5E7EB;\">\n\n <div class=\"cqa-inline-flex cqa-items-center\">\n <!-- Drag Handle Icon (when isReorder is true) - 9-dot grid (3x3) -->\n <div *ngIf=\"isReorder\" class=\"cqa-mr-2 cqa-cursor-move cqa-text-[#6B7280] hover:cqa-text-[#111827]\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"3\" cy=\"3\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"8\" cy=\"3\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"13\" cy=\"3\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"3\" cy=\"8\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"8\" cy=\"8\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"13\" cy=\"8\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"3\" cy=\"13\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"8\" cy=\"13\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"13\" cy=\"13\" r=\"1.5\" fill=\"currentColor\"/>\n </svg>\n </div>\n <!-- Checkbox (when isReorder is false) -->\n <label *ngIf=\"!isReorder\" class=\"cqa-flex cqa-items-center cqa-cursor-pointer cqa-relative cqa-mr-2\">\n <input type=\"checkbox\"\n [ngModel]=\"selected\"\n [disabled]=\"disabled\"\n (ngModelChange)=\"onSelectionChange($event)\"\n class=\"cqa-h-4 cqa-w-4 cqa-cursor-pointer cqa-transition-all cqa-appearance-none cqa-rounded shadow hover:cqa-shadow-md cqa-border cqa-border-solid cqa-border-slate-300 cqa-flex-shrink-0\"\n [class.cqa-bg-[#3F43EE]]=\"selected\"\n [class.cqa-border-[#3F43EE]]=\"selected\"\n id=\"check\" />\n <span class=\"cqa-absolute cqa-text-white cqa-top-1/2 cqa-left-1/2 cqa--translate-x-1/2 cqa--translate-y-1/2 cqa-pointer-events-none cqa-flex cqa-items-center cqa-justify-center\"\n [class.cqa-opacity-0]=\"!selected\"\n [class.cqa-opacity-100]=\"selected\">\n <svg width=\"12\" height=\"13\" viewBox=\"0 0 12 13\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M10 3.125L4.5 8.625L2 6.125\" stroke=\"white\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </span>\n </label>\n </div>\n\n <!-- Step Number -->\n <span class=\"cqa-text-[#6B7280] cqa-text-[14px] cqa-leading-[18px] cqa-min-w-[32px]\">\n {{ stepNumber }}\n </span>\n\n <!-- Event Type Selector (Pill Button) #### (click)=\"toggleEventTypeDropdown(); $event.stopPropagation()\" -->\n <div class=\"cqa-relative\" #dropdownContainer>\n <button type=\"button\" \n [style.background-color]=\"getCurrentEventTypeConfig().backgroundColor\"\n [style.color]=\"getCurrentEventTypeConfig().color\" [style.border-color]=\"getCurrentEventTypeConfig().color\"\n class=\"cqa-px-2.5 cqa-py-1 cqa-rounded-lg cqa-flex cqa-items-center cqa-gap-2 cqa-cursor-pointer\">\n <!-- Icon -->\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'paper_plane'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1.75 6.41663L12.8333 1.16663L7.58333 12.25L6.41667 7.58329L1.75 6.41663Z\" stroke=\"#432DD7\"\n stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'star'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M5.797 9.04165C5.74492 8.83977 5.63969 8.65554 5.49227 8.50812C5.34485 8.3607 5.16062 8.25548 4.95875 8.2034L1.38 7.28057C1.31894 7.26324 1.2652 7.22646 1.22694 7.17583C1.18867 7.12519 1.16797 7.06345 1.16797 6.99998C1.16797 6.93651 1.18867 6.87478 1.22694 6.82414C1.2652 6.7735 1.31894 6.73673 1.38 6.7194L4.95875 5.79598C5.16055 5.74395 5.34473 5.63882 5.49215 5.49151C5.63956 5.34419 5.74483 5.16008 5.797 4.95832L6.71983 1.37957C6.73698 1.31827 6.77372 1.26427 6.82443 1.2258C6.87515 1.18733 6.93705 1.1665 7.0007 1.1665C7.06436 1.1665 7.12626 1.18733 7.17698 1.2258C7.22769 1.26427 7.26442 1.31827 7.28158 1.37957L8.20383 4.95832C8.25591 5.16019 8.36113 5.34442 8.50855 5.49184C8.65597 5.63926 8.8402 5.74449 9.04208 5.79657L12.6208 6.71882C12.6824 6.73579 12.7366 6.77249 12.7753 6.82328C12.814 6.87407 12.8349 6.93614 12.8349 6.99998C12.8349 7.06382 12.814 7.1259 12.7753 7.17669C12.7366 7.22748 12.6824 7.26417 12.6208 7.28115L9.04208 8.2034C8.8402 8.25548 8.65597 8.3607 8.50855 8.50812C8.36113 8.65554 8.25591 8.83977 8.20383 9.04165L7.281 12.6204C7.26384 12.6817 7.22711 12.7357 7.17639 12.7742C7.12568 12.8126 7.06377 12.8335 7.00012 12.8335C6.93647 12.8335 6.87456 12.8126 6.82385 12.7742C6.77314 12.7357 6.7364 12.6817 6.71925 12.6204L5.797 9.04165Z\"\n stroke=\"#7008E7\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M11.666 1.75V4.08333\" stroke=\"#7008E7\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M12.8333 2.91663H10.5\" stroke=\"#7008E7\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M2.33398 9.91663V11.0833\" stroke=\"#7008E7\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M2.91667 10.5H1.75\" stroke=\"#7008E7\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'T'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M2.33398 4.08325V2.33325H11.6673V4.08325\" stroke=\"#8200DB\" stroke-width=\"1.16667\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M5.25 11.6667H8.75\" stroke=\"#8200DB\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M7 2.33325V11.6666\" stroke=\"#8200DB\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'cursor'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1.75 1.75L5.87417 11.6492L7.33833 7.33833L11.6492 5.87417L1.75 1.75Z\" stroke=\"#1447E6\"\n stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M7.58398 7.58325L11.084 11.0833\" stroke=\"#1447E6\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'cursor-double'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8.16667 2.3916L7 3.49993\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M2.97487 4.66662L1.2832 4.19995\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M3.50091 7L2.39258 8.16667\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M4.19922 1.28345L4.66589 2.97511\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M5.27114 5.65255C5.24852 5.59926 5.24234 5.54043 5.25338 5.48361C5.26443 5.42678 5.2922 5.37455 5.33313 5.33362C5.37407 5.29269 5.4263 5.26492 5.48312 5.25387C5.53994 5.24283 5.59877 5.24901 5.65206 5.27163L12.0687 7.89663C12.1258 7.92006 12.174 7.961 12.2064 8.01357C12.2388 8.06613 12.2536 8.12761 12.2488 8.18915C12.244 8.25069 12.2198 8.30912 12.1797 8.35603C12.1396 8.40295 12.0856 8.43592 12.0256 8.45021L9.48864 9.05746C9.38391 9.08248 9.28815 9.13599 9.21196 9.21208C9.13578 9.28816 9.08213 9.38385 9.05698 9.48855L8.45031 12.026C8.43617 12.0863 8.40323 12.1405 8.35626 12.1808C8.30928 12.2211 8.25071 12.2454 8.189 12.2502C8.1273 12.255 8.06567 12.2401 8.01302 12.2075C7.96037 12.175 7.91944 12.1266 7.89614 12.0692L5.27114 5.65255Z\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'enter'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M11.0833 1.75L11.0833 5.83333L2.91667 5.83333\" stroke=\"#1447E6\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M7.58333 1.75L11.0833 5.25L7.58333 8.75\" stroke=\"#1447E6\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M2.91667 8.75L2.91667 12.25\" stroke=\"#1447E6\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'clock'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M6.99935 12.8334C10.221 12.8334 12.8327 10.2217 12.8327 7.00008C12.8327 3.77842 10.221 1.16675 6.99935 1.16675C3.77769 1.16675 1.16602 3.77842 1.16602 7.00008C1.16602 10.2217 3.77769 12.8334 6.99935 12.8334Z\"\n stroke=\"#364153\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M7 3.5V7L9.33333 8.16667\" stroke=\"#364153\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </span>\n\n <!-- Label -->\n <span class=\"cqa-text-[#432DD7] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium\">{{\n getCurrentEventTypeConfig().label }}</span>\n </button>\n\n <!-- Dropdown Menu -->\n <div *ngIf=\"eventTypeDropdownOpen\" (click)=\"$event.stopPropagation()\"\n class=\"cqa-absolute cqa-top-full cqa-left-0 cqa-mt-1 cqa-bg-white cqa-rounded-lg cqa-shadow-lg cqa-border cqa-border-gray-200 cqa-z-50 cqa-min-w-[150px] cqa-py-1\">\n <button *ngFor=\"let etc of eventTypeConfigs\" type=\"button\" (click)=\"onEventTypeSelect(etc.type)\"\n [class.cqa-bg-primary-50]=\"eventType === etc.type\"\n class=\"cqa-w-full cqa-px-3 cqa-py-2 cqa-text-left cqa-flex cqa-items-center cqa-gap-2 hover:cqa-bg-gray-50 cqa-transition-colors\">\n <span *ngIf=\"etc.icon === 'paper_plane'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1 5.5L11 1M11 1L7.5 11L6 6.5L1 5.5M11 1L1 5.5\" stroke=\"currentColor\" stroke-width=\"1.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"etc.icon === 'star'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 1L7.5 4.5L11 5L7.5 5.5L6 9L4.5 5.5L1 5L4.5 4.5L6 1Z\" fill=\"currentColor\" />\n </svg>\n </span>\n <span *ngIf=\"etc.icon === 'T'\">\n T\n </span>\n <span *ngIf=\"etc.icon === 'cursor'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M2 2L9 1L10 8L7 7L5 9L4 7L2 2Z\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"etc.icon === 'cursor-double'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8.16667 2.3916L7 3.49993\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M2.97487 4.66662L1.2832 4.19995\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M3.50091 7L2.39258 8.16667\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M4.19922 1.28345L4.66589 2.97511\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M5.27114 5.65255C5.24852 5.59926 5.24234 5.54043 5.25338 5.48361C5.26443 5.42678 5.2922 5.37455 5.33313 5.33362C5.37407 5.29269 5.4263 5.26492 5.48312 5.25387C5.53994 5.24283 5.59877 5.24901 5.65206 5.27163L12.0687 7.89663C12.1258 7.92006 12.174 7.961 12.2064 8.01357C12.2388 8.06613 12.2536 8.12761 12.2488 8.18915C12.244 8.25069 12.2198 8.30912 12.1797 8.35603C12.1396 8.40295 12.0856 8.43592 12.0256 8.45021L9.48864 9.05746C9.38391 9.08248 9.28815 9.13599 9.21196 9.21208C9.13578 9.28816 9.08213 9.38385 9.05698 9.48855L8.45031 12.026C8.43617 12.0863 8.40323 12.1405 8.35626 12.1808C8.30928 12.2211 8.25071 12.2454 8.189 12.2502C8.1273 12.255 8.06567 12.2401 8.01302 12.2075C7.96037 12.175 7.91944 12.1266 7.89614 12.0692L5.27114 5.65255Z\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg> \n </span>\n <span *ngIf=\"etc.icon === 'enter'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M9.5 1.5L9.5 5L2 5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.5 1.5L9.5 4.5L6.5 7.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M2 7.5L2 10.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span *ngIf=\"etc.icon === 'clock'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"6\" cy=\"6\" r=\"5\" stroke=\"currentColor\" stroke-width=\"1.5\" />\n <path d=\"M6 3V6L8 7\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n </span>\n <span>{{ etc.label }}</span>\n </button>\n </div>\n </div>\n\n <!-- Action Description -->\n <span class=\"cqa-text-[#111827] cqa-text-[14px] cqa-leading-[18px]\" *ngIf=\"getActionDescription()\"\n [innerHTML]=\"getActionDescription()\" (click)=\"clickOnAction($event)\">\n </span>\n\n <!-- Parameters -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-3\" *ngIf=\"false\">\n <!-- Navigate: URL as clickable trigger for Test Data modal -->\n <span *ngIf=\"eventType === 'navigate' && getNavigateUrlParameter()\" #testDataTrigger\n (click)=\"openTestDataModal($event)\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC] cqa-cursor-pointer hover:cqa-opacity-90\">\n {{ getNavigateUrlParameter()?.value || getNavigateUrlParameter()?.displayValue }}\n </span>\n \n <!-- Other event types: loop through parameters (navigate excluded) -->\n <ng-container *ngFor=\"let param of parameters; let i = index\">\n <!-- Skip navigate parameters in the loop (already shown above) -->\n <ng-container *ngIf=\"eventType !== 'navigate'\">\n\n <!-- Type: First param (text value like {{username}}) -->\n <span *ngIf=\"eventType === 'type' && i === 0\" class=\"cqa-text-gray-900 cqa-text-sm\">\n {{ param.value }}\n </span>\n\n <!-- Type: \"into\" text -->\n <span *ngIf=\"eventType === 'type' && i === 0\" class=\"cqa-text-gray-900 cqa-text-sm\">\n into\n </span>\n\n <!-- Type: Second param (selector) -->\n <span *ngIf=\"eventType === 'type' && i === 1\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- Click: Selector input/display -->\n <span *ngIf=\"eventType === 'click' && param.name === 'element'\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- Click: Suffix text (like \"if Present\") -->\n <span *ngIf=\"eventType === 'click' && param.name === 'suffix'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n {{ param.value }}\n </span>\n\n <!-- Double Click: Selector input/display -->\n <span *ngIf=\"eventType === 'doubleClick' && i === 0\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- Press Enter: Selector input/display with HTML support -->\n <span *ngIf=\"eventType === 'pressEnter' && i === 0\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\"\n [innerHTML]=\"param.displayValue || param.value\">\n </span>\n\n <!-- Enter: Value display with quotes (like click action) -->\n <span *ngIf=\"eventType === 'enter' && param.name === 'value'\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- Enter: \"in the\" text -->\n <span *ngIf=\"eventType === 'enter' && param.name === 'value'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n in the\n </span>\n\n <!-- Enter: Label display with quotes (like click action) -->\n <span *ngIf=\"eventType === 'enter' && param.name === 'label'\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- Enter: \"field\" text -->\n <span *ngIf=\"eventType === 'enter' && param.name === 'label'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n field\n </span>\n\n <!-- Wait: Duration input -->\n <input *ngIf=\"eventType === 'wait' && param.name === 'duration'\" type=\"number\" [value]=\"param.value\"\n (input)=\"onParameterChange(param, $any($event.target).value)\" placeholder=\"2\"\n class=\"cqa-w-16 cqa-px-2 cqa-py-1.5 cqa-rounded-lg cqa-border cqa-border-solid cqa-border-[#9E9EE3] cqa-bg-[#D1C4E9] cqa-text-[#3F43EE] cqa-text-sm cqa-font-medium cqa-outline-none focus:cqa-ring-2 focus:cqa-ring-[#3F43EE] focus:cqa-ring-opacity-50\" />\n <span *ngIf=\"eventType === 'wait' && param.name === 'duration'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n seconds\n </span>\n\n <!-- Wait: Element selector -->\n <span *ngIf=\"eventType === 'wait' && param.name === 'element'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n for element\n </span>\n <span *ngIf=\"eventType === 'wait' && param.name === 'element'\" \n #elementTrigger\n (click)=\"openElementPopup($event)\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-cursor-pointer cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n <span *ngIf=\"eventType === 'wait' && param.name === 'element'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n to be visible\n </span>\n\n <!-- Custom: Description (clickable to open Step Description modal; pass $event so modal opens below this trigger) -->\n <span *ngIf=\"eventType === 'custom'\" #descriptionTrigger\n (click)=\"openStepDescriptionModal($event)\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC] cqa-cursor-pointer hover:cqa-opacity-90\"\n [innerHTML]=\"param.displayValue || param.value\">\n </span>\n\n <!-- AI Agent: Instructions -->\n <span *ngIf=\"eventType === 'ai-agent'\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n </ng-container>\n </ng-container>\n </div>\n\n <!-- AI Agent View Details Link -->\n <a *ngIf=\"eventType === 'ai-agent'\" href=\"#\" (click)=\"onMoreOptions(); $event.preventDefault()\" class=\"cqa-ml-auto cqa-text-[#3F43EE] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-flex cqa-items-center cqa-gap-2 cqa-no-underline\">View Details<svg width=\"8\" height=\"8\" viewBox=\"0 0 8 8\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2.03809 6.74329L2.62809 7.33329L5.96142 3.99996L2.62809 0.666626L2.03809 1.25663L4.78142 3.99996L2.03809 6.74329Z\" fill=\"#3F43EE\"/></svg></a>\n\n <!-- Action Icons: Edit, Link, Duplicate, Delete (show on hover, same as API step) -->\n <div class=\"step-actions cqa-flex cqa-items-center cqa-gap-3 cqa-ml-auto cqa-px-[7px]\">\n <button type=\"button\" #editTrigger (click)=\"onEdit(); $event.stopPropagation()\" title=\"Edit\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7 11.6666H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M9.55208 2.1128C9.7843 1.88058 10.0993 1.75012 10.4277 1.75012C10.7561 1.75012 11.071 1.88058 11.3033 2.1128C11.5355 2.34502 11.6659 2.65998 11.6659 2.98838C11.6659 3.31679 11.5355 3.63175 11.3033 3.86397L4.29742 10.8704C4.15864 11.0092 3.9871 11.1107 3.79867 11.1656L2.12333 11.6544C2.07314 11.669 2.01993 11.6699 1.96928 11.6569C1.91863 11.6439 1.8724 11.6176 1.83543 11.5806C1.79846 11.5437 1.7721 11.4974 1.75913 11.4468C1.74615 11.3961 1.74703 11.3429 1.76167 11.2927L2.2505 9.61738C2.30546 9.42916 2.40698 9.25783 2.54567 9.11922L9.55208 2.1128Z\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n <button type=\"button\" (click)=\"onLink(); $event.stopPropagation()\" title=\"Link\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M5.00065 9.91671H3.66732C2.78326 9.91671 1.93542 9.60942 1.3103 9.06244C0.685174 8.51545 0.333984 7.77359 0.333984 7.00004C0.333984 6.22649 0.685174 5.48463 1.3103 4.93765C1.93542 4.39066 2.78326 4.08337 3.66732 4.08337H5.00065\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M9 4.08337H10.3333C11.2174 4.08337 12.0652 4.39066 12.6904 4.93765C13.3155 5.48463 13.6667 6.22649 13.6667 7.00004C13.6667 7.77359 13.3155 8.51545 12.6904 9.06244C12.0652 9.60942 11.2174 9.91671 10.3333 9.91671H9\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M4.33398 7H9.66732\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n <button type=\"button\" (click)=\"onDuplicate(); $event.stopPropagation()\" title=\"Duplicate\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M11.666 4.66663H5.83268C5.18835 4.66663 4.66602 5.18896 4.66602 5.83329V11.6666C4.66602 12.311 5.18835 12.8333 5.83268 12.8333H11.666C12.3103 12.8333 12.8327 12.311 12.8327 11.6666V5.83329C12.8327 5.18896 12.3103 4.66663 11.666 4.66663Z\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M2.33268 9.33329C1.69102 9.33329 1.16602 8.80829 1.16602 8.16663V2.33329C1.16602 1.69163 1.69102 1.16663 2.33268 1.16663H8.16602C8.80768 1.16663 9.33268 1.69163 9.33268 2.33329\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n <button type=\"button\" (click)=\"onDelete(); $event.stopPropagation()\" title=\"Delete\" class=\"cqa-p-0 cqa-text-[#ff6467] hover:cqa-text-[#C63535]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1.75 3.5H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M11.0827 3.5V11.6667C11.0827 12.25 10.4993 12.8333 9.91602 12.8333H4.08268C3.49935 12.8333 2.91602 12.25 2.91602 11.6667V3.5\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M4.66602 3.49996V2.33329C4.66602 1.74996 5.24935 1.16663 5.83268 1.16663H8.16602C8.74935 1.16663 9.33268 1.74996 9.33268 2.33329V3.49996\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M5.83398 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.16602 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n </div>\n</div>", styles: [".step-actions{opacity:0;transition:opacity .15s ease}.step-row:hover .step-actions{opacity:1}\n"], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
17231
17109
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestCaseNormalStepComponent, decorators: [{
17232
17110
  type: Component,
17233
- args: [{ selector: 'cqa-test-case-normal-step', host: { class: 'cqa-ui-root' }, styles: [STEP_ROW_ACTIONS_STYLES], template: "<div [class]=\"'step-row cqa-flex cqa-items-center cqa-gap-3 cqa-py-[12.5px] ' + (isInsideLoop ? 'cqa-pl-10 cqa-pr-4' : 'cqa-px-4')\" style=\"border-bottom: 1px solid #E5E7EB;\">\n\n <div class=\"cqa-inline-flex cqa-items-center\">\n <!-- Drag Handle Icon (when isReorder is true) - 9-dot grid (3x3) -->\n <div *ngIf=\"isReorder\" class=\"cqa-mr-2 cqa-cursor-move cqa-text-[#6B7280] hover:cqa-text-[#111827]\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"3\" cy=\"3\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"8\" cy=\"3\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"13\" cy=\"3\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"3\" cy=\"8\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"8\" cy=\"8\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"13\" cy=\"8\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"3\" cy=\"13\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"8\" cy=\"13\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"13\" cy=\"13\" r=\"1.5\" fill=\"currentColor\"/>\n </svg>\n </div>\n <!-- Checkbox (when isReorder is false) -->\n <label *ngIf=\"!isReorder\" class=\"cqa-flex cqa-items-center cqa-cursor-pointer cqa-relative cqa-mr-2\">\n <input type=\"checkbox\"\n [ngModel]=\"selected\"\n [disabled]=\"disabled\"\n (ngModelChange)=\"onSelectionChange($event)\"\n class=\"cqa-h-4 cqa-w-4 cqa-cursor-pointer cqa-transition-all cqa-appearance-none cqa-rounded shadow hover:cqa-shadow-md cqa-border cqa-border-solid cqa-border-slate-300 cqa-flex-shrink-0\"\n [class.cqa-bg-[#3F43EE]]=\"selected\"\n [class.cqa-border-[#3F43EE]]=\"selected\"\n id=\"check\" />\n <span class=\"cqa-absolute cqa-text-white cqa-top-1/2 cqa-left-1/2 cqa--translate-x-1/2 cqa--translate-y-1/2 cqa-pointer-events-none cqa-flex cqa-items-center cqa-justify-center\"\n [class.cqa-opacity-0]=\"!selected\"\n [class.cqa-opacity-100]=\"selected\">\n <svg width=\"12\" height=\"13\" viewBox=\"0 0 12 13\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M10 3.125L4.5 8.625L2 6.125\" stroke=\"white\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </span>\n </label>\n </div>\n\n <!-- Step Number -->\n <span class=\"cqa-text-[#6B7280] cqa-text-[14px] cqa-leading-[18px] cqa-min-w-[32px]\">\n {{ stepNumber }}\n </span>\n\n <!-- Event Type Selector (Pill Button) #### (click)=\"toggleEventTypeDropdown(); $event.stopPropagation()\" -->\n <div class=\"cqa-relative\" #dropdownContainer>\n <button type=\"button\" \n [style.background-color]=\"getCurrentEventTypeConfig().backgroundColor\"\n [style.color]=\"getCurrentEventTypeConfig().color\" [style.border-color]=\"getCurrentEventTypeConfig().color\"\n class=\"cqa-px-2.5 cqa-py-1 cqa-rounded-lg cqa-flex cqa-items-center cqa-gap-2 cqa-cursor-pointer\">\n <!-- Icon -->\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'paper_plane'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1.75 6.41663L12.8333 1.16663L7.58333 12.25L6.41667 7.58329L1.75 6.41663Z\" stroke=\"#432DD7\"\n stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'star'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M5.797 9.04165C5.74492 8.83977 5.63969 8.65554 5.49227 8.50812C5.34485 8.3607 5.16062 8.25548 4.95875 8.2034L1.38 7.28057C1.31894 7.26324 1.2652 7.22646 1.22694 7.17583C1.18867 7.12519 1.16797 7.06345 1.16797 6.99998C1.16797 6.93651 1.18867 6.87478 1.22694 6.82414C1.2652 6.7735 1.31894 6.73673 1.38 6.7194L4.95875 5.79598C5.16055 5.74395 5.34473 5.63882 5.49215 5.49151C5.63956 5.34419 5.74483 5.16008 5.797 4.95832L6.71983 1.37957C6.73698 1.31827 6.77372 1.26427 6.82443 1.2258C6.87515 1.18733 6.93705 1.1665 7.0007 1.1665C7.06436 1.1665 7.12626 1.18733 7.17698 1.2258C7.22769 1.26427 7.26442 1.31827 7.28158 1.37957L8.20383 4.95832C8.25591 5.16019 8.36113 5.34442 8.50855 5.49184C8.65597 5.63926 8.8402 5.74449 9.04208 5.79657L12.6208 6.71882C12.6824 6.73579 12.7366 6.77249 12.7753 6.82328C12.814 6.87407 12.8349 6.93614 12.8349 6.99998C12.8349 7.06382 12.814 7.1259 12.7753 7.17669C12.7366 7.22748 12.6824 7.26417 12.6208 7.28115L9.04208 8.2034C8.8402 8.25548 8.65597 8.3607 8.50855 8.50812C8.36113 8.65554 8.25591 8.83977 8.20383 9.04165L7.281 12.6204C7.26384 12.6817 7.22711 12.7357 7.17639 12.7742C7.12568 12.8126 7.06377 12.8335 7.00012 12.8335C6.93647 12.8335 6.87456 12.8126 6.82385 12.7742C6.77314 12.7357 6.7364 12.6817 6.71925 12.6204L5.797 9.04165Z\"\n stroke=\"#7008E7\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M11.666 1.75V4.08333\" stroke=\"#7008E7\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M12.8333 2.91663H10.5\" stroke=\"#7008E7\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M2.33398 9.91663V11.0833\" stroke=\"#7008E7\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M2.91667 10.5H1.75\" stroke=\"#7008E7\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'T'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M2.33398 4.08325V2.33325H11.6673V4.08325\" stroke=\"#8200DB\" stroke-width=\"1.16667\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M5.25 11.6667H8.75\" stroke=\"#8200DB\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M7 2.33325V11.6666\" stroke=\"#8200DB\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'cursor'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1.75 1.75L5.87417 11.6492L7.33833 7.33833L11.6492 5.87417L1.75 1.75Z\" stroke=\"#1447E6\"\n stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M7.58398 7.58325L11.084 11.0833\" stroke=\"#1447E6\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'cursor-double'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8.16667 2.3916L7 3.49993\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M2.97487 4.66662L1.2832 4.19995\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M3.50091 7L2.39258 8.16667\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M4.19922 1.28345L4.66589 2.97511\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M5.27114 5.65255C5.24852 5.59926 5.24234 5.54043 5.25338 5.48361C5.26443 5.42678 5.2922 5.37455 5.33313 5.33362C5.37407 5.29269 5.4263 5.26492 5.48312 5.25387C5.53994 5.24283 5.59877 5.24901 5.65206 5.27163L12.0687 7.89663C12.1258 7.92006 12.174 7.961 12.2064 8.01357C12.2388 8.06613 12.2536 8.12761 12.2488 8.18915C12.244 8.25069 12.2198 8.30912 12.1797 8.35603C12.1396 8.40295 12.0856 8.43592 12.0256 8.45021L9.48864 9.05746C9.38391 9.08248 9.28815 9.13599 9.21196 9.21208C9.13578 9.28816 9.08213 9.38385 9.05698 9.48855L8.45031 12.026C8.43617 12.0863 8.40323 12.1405 8.35626 12.1808C8.30928 12.2211 8.25071 12.2454 8.189 12.2502C8.1273 12.255 8.06567 12.2401 8.01302 12.2075C7.96037 12.175 7.91944 12.1266 7.89614 12.0692L5.27114 5.65255Z\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'enter'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M11.0833 1.75L11.0833 5.83333L2.91667 5.83333\" stroke=\"#1447E6\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M7.58333 1.75L11.0833 5.25L7.58333 8.75\" stroke=\"#1447E6\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M2.91667 8.75L2.91667 12.25\" stroke=\"#1447E6\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'clock'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M6.99935 12.8334C10.221 12.8334 12.8327 10.2217 12.8327 7.00008C12.8327 3.77842 10.221 1.16675 6.99935 1.16675C3.77769 1.16675 1.16602 3.77842 1.16602 7.00008C1.16602 10.2217 3.77769 12.8334 6.99935 12.8334Z\"\n stroke=\"#364153\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M7 3.5V7L9.33333 8.16667\" stroke=\"#364153\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </span>\n\n <!-- Label -->\n <span class=\"cqa-text-[#432DD7] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium\">{{\n getCurrentEventTypeConfig().label }}</span>\n </button>\n\n <!-- Dropdown Menu -->\n <div *ngIf=\"eventTypeDropdownOpen\" (click)=\"$event.stopPropagation()\"\n class=\"cqa-absolute cqa-top-full cqa-left-0 cqa-mt-1 cqa-bg-white cqa-rounded-lg cqa-shadow-lg cqa-border cqa-border-gray-200 cqa-z-50 cqa-min-w-[150px] cqa-py-1\">\n <button *ngFor=\"let etc of eventTypeConfigs\" type=\"button\" (click)=\"onEventTypeSelect(etc.type)\"\n [class.cqa-bg-primary-50]=\"eventType === etc.type\"\n class=\"cqa-w-full cqa-px-3 cqa-py-2 cqa-text-left cqa-flex cqa-items-center cqa-gap-2 hover:cqa-bg-gray-50 cqa-transition-colors\">\n <span *ngIf=\"etc.icon === 'paper_plane'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1 5.5L11 1M11 1L7.5 11L6 6.5L1 5.5M11 1L1 5.5\" stroke=\"currentColor\" stroke-width=\"1.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"etc.icon === 'star'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 1L7.5 4.5L11 5L7.5 5.5L6 9L4.5 5.5L1 5L4.5 4.5L6 1Z\" fill=\"currentColor\" />\n </svg>\n </span>\n <span *ngIf=\"etc.icon === 'T'\">\n T\n </span>\n <span *ngIf=\"etc.icon === 'cursor'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M2 2L9 1L10 8L7 7L5 9L4 7L2 2Z\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"etc.icon === 'cursor-double'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8.16667 2.3916L7 3.49993\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M2.97487 4.66662L1.2832 4.19995\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M3.50091 7L2.39258 8.16667\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M4.19922 1.28345L4.66589 2.97511\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M5.27114 5.65255C5.24852 5.59926 5.24234 5.54043 5.25338 5.48361C5.26443 5.42678 5.2922 5.37455 5.33313 5.33362C5.37407 5.29269 5.4263 5.26492 5.48312 5.25387C5.53994 5.24283 5.59877 5.24901 5.65206 5.27163L12.0687 7.89663C12.1258 7.92006 12.174 7.961 12.2064 8.01357C12.2388 8.06613 12.2536 8.12761 12.2488 8.18915C12.244 8.25069 12.2198 8.30912 12.1797 8.35603C12.1396 8.40295 12.0856 8.43592 12.0256 8.45021L9.48864 9.05746C9.38391 9.08248 9.28815 9.13599 9.21196 9.21208C9.13578 9.28816 9.08213 9.38385 9.05698 9.48855L8.45031 12.026C8.43617 12.0863 8.40323 12.1405 8.35626 12.1808C8.30928 12.2211 8.25071 12.2454 8.189 12.2502C8.1273 12.255 8.06567 12.2401 8.01302 12.2075C7.96037 12.175 7.91944 12.1266 7.89614 12.0692L5.27114 5.65255Z\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg> \n </span>\n <span *ngIf=\"etc.icon === 'enter'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M9.5 1.5L9.5 5L2 5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.5 1.5L9.5 4.5L6.5 7.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M2 7.5L2 10.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span *ngIf=\"etc.icon === 'clock'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"6\" cy=\"6\" r=\"5\" stroke=\"currentColor\" stroke-width=\"1.5\" />\n <path d=\"M6 3V6L8 7\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n </span>\n <span>{{ etc.label }}</span>\n </button>\n </div>\n </div>\n\n <!-- Action Description -->\n <span class=\"cqa-text-[#111827] cqa-text-[14px] cqa-leading-[18px]\" *ngIf=\"getActionDescription()\">\n {{ getActionDescription() }}\n </span>\n\n <!-- Parameters -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-3\">\n <!-- Navigate: URL as clickable trigger for Test Data modal -->\n <span *ngIf=\"eventType === 'navigate' && getNavigateUrlParameter()\" #testDataTrigger\n (click)=\"openTestDataModal($event)\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC] cqa-cursor-pointer hover:cqa-opacity-90\">\n {{ getNavigateUrlParameter()?.value || getNavigateUrlParameter()?.displayValue }}\n </span>\n \n <!-- Other event types: loop through parameters (navigate excluded) -->\n <ng-container *ngFor=\"let param of parameters; let i = index\">\n <!-- Skip navigate parameters in the loop (already shown above) -->\n <ng-container *ngIf=\"eventType !== 'navigate'\">\n\n <!-- Type: First param (text value like {{username}}) -->\n <span *ngIf=\"eventType === 'type' && i === 0\" class=\"cqa-text-gray-900 cqa-text-sm\">\n {{ param.value }}\n </span>\n\n <!-- Type: \"into\" text -->\n <span *ngIf=\"eventType === 'type' && i === 0\" class=\"cqa-text-gray-900 cqa-text-sm\">\n into\n </span>\n\n <!-- Type: Second param (selector) -->\n <span *ngIf=\"eventType === 'type' && i === 1\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- Click: Selector input/display -->\n <span *ngIf=\"eventType === 'click' && param.name === 'element'\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- Click: Suffix text (like \"if Present\") -->\n <span *ngIf=\"eventType === 'click' && param.name === 'suffix'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n {{ param.value }}\n </span>\n\n <!-- Double Click: Selector input/display -->\n <span *ngIf=\"eventType === 'doubleClick' && i === 0\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- Press Enter: Selector input/display with HTML support -->\n <span *ngIf=\"eventType === 'pressEnter' && i === 0\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\"\n [innerHTML]=\"param.displayValue || param.value\">\n </span>\n\n <!-- Enter: Value display with quotes (like click action) -->\n <span *ngIf=\"eventType === 'enter' && param.name === 'value'\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- Enter: \"in the\" text -->\n <span *ngIf=\"eventType === 'enter' && param.name === 'value'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n in the\n </span>\n\n <!-- Enter: Label display with quotes (like click action) -->\n <span *ngIf=\"eventType === 'enter' && param.name === 'label'\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- Enter: \"field\" text -->\n <span *ngIf=\"eventType === 'enter' && param.name === 'label'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n field\n </span>\n\n <!-- Wait: Duration input -->\n <input *ngIf=\"eventType === 'wait' && param.name === 'duration'\" type=\"number\" [value]=\"param.value\"\n (input)=\"onParameterChange(param, $any($event.target).value)\" placeholder=\"2\"\n class=\"cqa-w-16 cqa-px-2 cqa-py-1.5 cqa-rounded-lg cqa-border cqa-border-solid cqa-border-[#9E9EE3] cqa-bg-[#D1C4E9] cqa-text-[#3F43EE] cqa-text-sm cqa-font-medium cqa-outline-none focus:cqa-ring-2 focus:cqa-ring-[#3F43EE] focus:cqa-ring-opacity-50\" />\n <span *ngIf=\"eventType === 'wait' && param.name === 'duration'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n seconds\n </span>\n\n <!-- Wait: Element selector -->\n <span *ngIf=\"eventType === 'wait' && param.name === 'element'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n for element\n </span>\n <span *ngIf=\"eventType === 'wait' && param.name === 'element'\" \n #elementTrigger\n (click)=\"openElementPopup($event)\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-cursor-pointer cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n <span *ngIf=\"eventType === 'wait' && param.name === 'element'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n to be visible\n </span>\n\n <!-- Custom: Description (clickable to open Step Description modal; pass $event so modal opens below this trigger) -->\n <span *ngIf=\"eventType === 'custom'\" #descriptionTrigger\n (click)=\"openStepDescriptionModal($event)\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC] cqa-cursor-pointer hover:cqa-opacity-90\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- AI Agent: Instructions -->\n <span *ngIf=\"eventType === 'ai-agent'\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n </ng-container>\n </ng-container>\n </div>\n\n <!-- AI Agent View Details Link -->\n <a *ngIf=\"eventType === 'ai-agent'\" href=\"#\" (click)=\"onMoreOptions(); $event.preventDefault()\" class=\"cqa-ml-auto cqa-text-[#3F43EE] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-flex cqa-items-center cqa-gap-2 cqa-no-underline\">View Details<svg width=\"8\" height=\"8\" viewBox=\"0 0 8 8\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2.03809 6.74329L2.62809 7.33329L5.96142 3.99996L2.62809 0.666626L2.03809 1.25663L4.78142 3.99996L2.03809 6.74329Z\" fill=\"#3F43EE\"/></svg></a>\n\n <!-- Action Icons: Edit, Link, Duplicate, Delete (show on hover, same as API step) -->\n <div class=\"step-actions cqa-flex cqa-items-center cqa-gap-3 cqa-ml-auto cqa-px-[7px]\">\n <button type=\"button\" #editTrigger (click)=\"onEdit(); $event.stopPropagation()\" title=\"Edit\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7 11.6666H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M9.55208 2.1128C9.7843 1.88058 10.0993 1.75012 10.4277 1.75012C10.7561 1.75012 11.071 1.88058 11.3033 2.1128C11.5355 2.34502 11.6659 2.65998 11.6659 2.98838C11.6659 3.31679 11.5355 3.63175 11.3033 3.86397L4.29742 10.8704C4.15864 11.0092 3.9871 11.1107 3.79867 11.1656L2.12333 11.6544C2.07314 11.669 2.01993 11.6699 1.96928 11.6569C1.91863 11.6439 1.8724 11.6176 1.83543 11.5806C1.79846 11.5437 1.7721 11.4974 1.75913 11.4468C1.74615 11.3961 1.74703 11.3429 1.76167 11.2927L2.2505 9.61738C2.30546 9.42916 2.40698 9.25783 2.54567 9.11922L9.55208 2.1128Z\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n <button type=\"button\" (click)=\"onLink(); $event.stopPropagation()\" title=\"Link\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M5.00065 9.91671H3.66732C2.78326 9.91671 1.93542 9.60942 1.3103 9.06244C0.685174 8.51545 0.333984 7.77359 0.333984 7.00004C0.333984 6.22649 0.685174 5.48463 1.3103 4.93765C1.93542 4.39066 2.78326 4.08337 3.66732 4.08337H5.00065\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M9 4.08337H10.3333C11.2174 4.08337 12.0652 4.39066 12.6904 4.93765C13.3155 5.48463 13.6667 6.22649 13.6667 7.00004C13.6667 7.77359 13.3155 8.51545 12.6904 9.06244C12.0652 9.60942 11.2174 9.91671 10.3333 9.91671H9\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M4.33398 7H9.66732\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n <button type=\"button\" (click)=\"onDuplicate(); $event.stopPropagation()\" title=\"Duplicate\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M11.666 4.66663H5.83268C5.18835 4.66663 4.66602 5.18896 4.66602 5.83329V11.6666C4.66602 12.311 5.18835 12.8333 5.83268 12.8333H11.666C12.3103 12.8333 12.8327 12.311 12.8327 11.6666V5.83329C12.8327 5.18896 12.3103 4.66663 11.666 4.66663Z\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M2.33268 9.33329C1.69102 9.33329 1.16602 8.80829 1.16602 8.16663V2.33329C1.16602 1.69163 1.69102 1.16663 2.33268 1.16663H8.16602C8.80768 1.16663 9.33268 1.69163 9.33268 2.33329\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n <button type=\"button\" (click)=\"onDelete(); $event.stopPropagation()\" title=\"Delete\" class=\"cqa-p-0 cqa-text-[#ff6467] hover:cqa-text-[#C63535]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1.75 3.5H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M11.0827 3.5V11.6667C11.0827 12.25 10.4993 12.8333 9.91602 12.8333H4.08268C3.49935 12.8333 2.91602 12.25 2.91602 11.6667V3.5\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M4.66602 3.49996V2.33329C4.66602 1.74996 5.24935 1.16663 5.83268 1.16663H8.16602C8.74935 1.16663 9.33268 1.74996 9.33268 2.33329V3.49996\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M5.83398 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.16602 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n </div>\n</div>" }]
17234
- }], ctorParameters: function () { return [{ type: CustomEditStepService }, { type: ElementPopupService }, { type: TestDataModalService }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }]; }, propDecorators: { dropdownContainer: [{
17111
+ args: [{ selector: 'cqa-test-case-normal-step', host: { class: 'cqa-ui-root' }, styles: [STEP_ROW_ACTIONS_STYLES], template: "<div [class]=\"'step-row cqa-flex cqa-items-center cqa-gap-3 cqa-py-[12.5px] ' + (isInsideLoop ? 'cqa-pl-10 cqa-pr-4' : 'cqa-px-4')\" style=\"border-bottom: 1px solid #E5E7EB;\">\n\n <div class=\"cqa-inline-flex cqa-items-center\">\n <!-- Drag Handle Icon (when isReorder is true) - 9-dot grid (3x3) -->\n <div *ngIf=\"isReorder\" class=\"cqa-mr-2 cqa-cursor-move cqa-text-[#6B7280] hover:cqa-text-[#111827]\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"3\" cy=\"3\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"8\" cy=\"3\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"13\" cy=\"3\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"3\" cy=\"8\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"8\" cy=\"8\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"13\" cy=\"8\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"3\" cy=\"13\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"8\" cy=\"13\" r=\"1.5\" fill=\"currentColor\"/>\n <circle cx=\"13\" cy=\"13\" r=\"1.5\" fill=\"currentColor\"/>\n </svg>\n </div>\n <!-- Checkbox (when isReorder is false) -->\n <label *ngIf=\"!isReorder\" class=\"cqa-flex cqa-items-center cqa-cursor-pointer cqa-relative cqa-mr-2\">\n <input type=\"checkbox\"\n [ngModel]=\"selected\"\n [disabled]=\"disabled\"\n (ngModelChange)=\"onSelectionChange($event)\"\n class=\"cqa-h-4 cqa-w-4 cqa-cursor-pointer cqa-transition-all cqa-appearance-none cqa-rounded shadow hover:cqa-shadow-md cqa-border cqa-border-solid cqa-border-slate-300 cqa-flex-shrink-0\"\n [class.cqa-bg-[#3F43EE]]=\"selected\"\n [class.cqa-border-[#3F43EE]]=\"selected\"\n id=\"check\" />\n <span class=\"cqa-absolute cqa-text-white cqa-top-1/2 cqa-left-1/2 cqa--translate-x-1/2 cqa--translate-y-1/2 cqa-pointer-events-none cqa-flex cqa-items-center cqa-justify-center\"\n [class.cqa-opacity-0]=\"!selected\"\n [class.cqa-opacity-100]=\"selected\">\n <svg width=\"12\" height=\"13\" viewBox=\"0 0 12 13\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M10 3.125L4.5 8.625L2 6.125\" stroke=\"white\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </span>\n </label>\n </div>\n\n <!-- Step Number -->\n <span class=\"cqa-text-[#6B7280] cqa-text-[14px] cqa-leading-[18px] cqa-min-w-[32px]\">\n {{ stepNumber }}\n </span>\n\n <!-- Event Type Selector (Pill Button) #### (click)=\"toggleEventTypeDropdown(); $event.stopPropagation()\" -->\n <div class=\"cqa-relative\" #dropdownContainer>\n <button type=\"button\" \n [style.background-color]=\"getCurrentEventTypeConfig().backgroundColor\"\n [style.color]=\"getCurrentEventTypeConfig().color\" [style.border-color]=\"getCurrentEventTypeConfig().color\"\n class=\"cqa-px-2.5 cqa-py-1 cqa-rounded-lg cqa-flex cqa-items-center cqa-gap-2 cqa-cursor-pointer\">\n <!-- Icon -->\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'paper_plane'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1.75 6.41663L12.8333 1.16663L7.58333 12.25L6.41667 7.58329L1.75 6.41663Z\" stroke=\"#432DD7\"\n stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'star'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M5.797 9.04165C5.74492 8.83977 5.63969 8.65554 5.49227 8.50812C5.34485 8.3607 5.16062 8.25548 4.95875 8.2034L1.38 7.28057C1.31894 7.26324 1.2652 7.22646 1.22694 7.17583C1.18867 7.12519 1.16797 7.06345 1.16797 6.99998C1.16797 6.93651 1.18867 6.87478 1.22694 6.82414C1.2652 6.7735 1.31894 6.73673 1.38 6.7194L4.95875 5.79598C5.16055 5.74395 5.34473 5.63882 5.49215 5.49151C5.63956 5.34419 5.74483 5.16008 5.797 4.95832L6.71983 1.37957C6.73698 1.31827 6.77372 1.26427 6.82443 1.2258C6.87515 1.18733 6.93705 1.1665 7.0007 1.1665C7.06436 1.1665 7.12626 1.18733 7.17698 1.2258C7.22769 1.26427 7.26442 1.31827 7.28158 1.37957L8.20383 4.95832C8.25591 5.16019 8.36113 5.34442 8.50855 5.49184C8.65597 5.63926 8.8402 5.74449 9.04208 5.79657L12.6208 6.71882C12.6824 6.73579 12.7366 6.77249 12.7753 6.82328C12.814 6.87407 12.8349 6.93614 12.8349 6.99998C12.8349 7.06382 12.814 7.1259 12.7753 7.17669C12.7366 7.22748 12.6824 7.26417 12.6208 7.28115L9.04208 8.2034C8.8402 8.25548 8.65597 8.3607 8.50855 8.50812C8.36113 8.65554 8.25591 8.83977 8.20383 9.04165L7.281 12.6204C7.26384 12.6817 7.22711 12.7357 7.17639 12.7742C7.12568 12.8126 7.06377 12.8335 7.00012 12.8335C6.93647 12.8335 6.87456 12.8126 6.82385 12.7742C6.77314 12.7357 6.7364 12.6817 6.71925 12.6204L5.797 9.04165Z\"\n stroke=\"#7008E7\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M11.666 1.75V4.08333\" stroke=\"#7008E7\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M12.8333 2.91663H10.5\" stroke=\"#7008E7\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M2.33398 9.91663V11.0833\" stroke=\"#7008E7\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M2.91667 10.5H1.75\" stroke=\"#7008E7\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'T'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M2.33398 4.08325V2.33325H11.6673V4.08325\" stroke=\"#8200DB\" stroke-width=\"1.16667\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M5.25 11.6667H8.75\" stroke=\"#8200DB\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M7 2.33325V11.6666\" stroke=\"#8200DB\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'cursor'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1.75 1.75L5.87417 11.6492L7.33833 7.33833L11.6492 5.87417L1.75 1.75Z\" stroke=\"#1447E6\"\n stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M7.58398 7.58325L11.084 11.0833\" stroke=\"#1447E6\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'cursor-double'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8.16667 2.3916L7 3.49993\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M2.97487 4.66662L1.2832 4.19995\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M3.50091 7L2.39258 8.16667\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M4.19922 1.28345L4.66589 2.97511\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M5.27114 5.65255C5.24852 5.59926 5.24234 5.54043 5.25338 5.48361C5.26443 5.42678 5.2922 5.37455 5.33313 5.33362C5.37407 5.29269 5.4263 5.26492 5.48312 5.25387C5.53994 5.24283 5.59877 5.24901 5.65206 5.27163L12.0687 7.89663C12.1258 7.92006 12.174 7.961 12.2064 8.01357C12.2388 8.06613 12.2536 8.12761 12.2488 8.18915C12.244 8.25069 12.2198 8.30912 12.1797 8.35603C12.1396 8.40295 12.0856 8.43592 12.0256 8.45021L9.48864 9.05746C9.38391 9.08248 9.28815 9.13599 9.21196 9.21208C9.13578 9.28816 9.08213 9.38385 9.05698 9.48855L8.45031 12.026C8.43617 12.0863 8.40323 12.1405 8.35626 12.1808C8.30928 12.2211 8.25071 12.2454 8.189 12.2502C8.1273 12.255 8.06567 12.2401 8.01302 12.2075C7.96037 12.175 7.91944 12.1266 7.89614 12.0692L5.27114 5.65255Z\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'enter'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M11.0833 1.75L11.0833 5.83333L2.91667 5.83333\" stroke=\"#1447E6\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M7.58333 1.75L11.0833 5.25L7.58333 8.75\" stroke=\"#1447E6\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M2.91667 8.75L2.91667 12.25\" stroke=\"#1447E6\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span *ngIf=\"getCurrentEventTypeConfig().icon === 'clock'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M6.99935 12.8334C10.221 12.8334 12.8327 10.2217 12.8327 7.00008C12.8327 3.77842 10.221 1.16675 6.99935 1.16675C3.77769 1.16675 1.16602 3.77842 1.16602 7.00008C1.16602 10.2217 3.77769 12.8334 6.99935 12.8334Z\"\n stroke=\"#364153\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M7 3.5V7L9.33333 8.16667\" stroke=\"#364153\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </span>\n\n <!-- Label -->\n <span class=\"cqa-text-[#432DD7] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium\">{{\n getCurrentEventTypeConfig().label }}</span>\n </button>\n\n <!-- Dropdown Menu -->\n <div *ngIf=\"eventTypeDropdownOpen\" (click)=\"$event.stopPropagation()\"\n class=\"cqa-absolute cqa-top-full cqa-left-0 cqa-mt-1 cqa-bg-white cqa-rounded-lg cqa-shadow-lg cqa-border cqa-border-gray-200 cqa-z-50 cqa-min-w-[150px] cqa-py-1\">\n <button *ngFor=\"let etc of eventTypeConfigs\" type=\"button\" (click)=\"onEventTypeSelect(etc.type)\"\n [class.cqa-bg-primary-50]=\"eventType === etc.type\"\n class=\"cqa-w-full cqa-px-3 cqa-py-2 cqa-text-left cqa-flex cqa-items-center cqa-gap-2 hover:cqa-bg-gray-50 cqa-transition-colors\">\n <span *ngIf=\"etc.icon === 'paper_plane'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1 5.5L11 1M11 1L7.5 11L6 6.5L1 5.5M11 1L1 5.5\" stroke=\"currentColor\" stroke-width=\"1.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"etc.icon === 'star'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 1L7.5 4.5L11 5L7.5 5.5L6 9L4.5 5.5L1 5L4.5 4.5L6 1Z\" fill=\"currentColor\" />\n </svg>\n </span>\n <span *ngIf=\"etc.icon === 'T'\">\n T\n </span>\n <span *ngIf=\"etc.icon === 'cursor'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M2 2L9 1L10 8L7 7L5 9L4 7L2 2Z\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </span>\n <span *ngIf=\"etc.icon === 'cursor-double'\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8.16667 2.3916L7 3.49993\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M2.97487 4.66662L1.2832 4.19995\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M3.50091 7L2.39258 8.16667\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M4.19922 1.28345L4.66589 2.97511\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M5.27114 5.65255C5.24852 5.59926 5.24234 5.54043 5.25338 5.48361C5.26443 5.42678 5.2922 5.37455 5.33313 5.33362C5.37407 5.29269 5.4263 5.26492 5.48312 5.25387C5.53994 5.24283 5.59877 5.24901 5.65206 5.27163L12.0687 7.89663C12.1258 7.92006 12.174 7.961 12.2064 8.01357C12.2388 8.06613 12.2536 8.12761 12.2488 8.18915C12.244 8.25069 12.2198 8.30912 12.1797 8.35603C12.1396 8.40295 12.0856 8.43592 12.0256 8.45021L9.48864 9.05746C9.38391 9.08248 9.28815 9.13599 9.21196 9.21208C9.13578 9.28816 9.08213 9.38385 9.05698 9.48855L8.45031 12.026C8.43617 12.0863 8.40323 12.1405 8.35626 12.1808C8.30928 12.2211 8.25071 12.2454 8.189 12.2502C8.1273 12.255 8.06567 12.2401 8.01302 12.2075C7.96037 12.175 7.91944 12.1266 7.89614 12.0692L5.27114 5.65255Z\" stroke=\"#1447E6\" stroke-width=\"1.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg> \n </span>\n <span *ngIf=\"etc.icon === 'enter'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M9.5 1.5L9.5 5L2 5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.5 1.5L9.5 4.5L6.5 7.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M2 7.5L2 10.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span *ngIf=\"etc.icon === 'clock'\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"6\" cy=\"6\" r=\"5\" stroke=\"currentColor\" stroke-width=\"1.5\" />\n <path d=\"M6 3V6L8 7\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n </span>\n <span>{{ etc.label }}</span>\n </button>\n </div>\n </div>\n\n <!-- Action Description -->\n <span class=\"cqa-text-[#111827] cqa-text-[14px] cqa-leading-[18px]\" *ngIf=\"getActionDescription()\"\n [innerHTML]=\"getActionDescription()\" (click)=\"clickOnAction($event)\">\n </span>\n\n <!-- Parameters -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-3\" *ngIf=\"false\">\n <!-- Navigate: URL as clickable trigger for Test Data modal -->\n <span *ngIf=\"eventType === 'navigate' && getNavigateUrlParameter()\" #testDataTrigger\n (click)=\"openTestDataModal($event)\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC] cqa-cursor-pointer hover:cqa-opacity-90\">\n {{ getNavigateUrlParameter()?.value || getNavigateUrlParameter()?.displayValue }}\n </span>\n \n <!-- Other event types: loop through parameters (navigate excluded) -->\n <ng-container *ngFor=\"let param of parameters; let i = index\">\n <!-- Skip navigate parameters in the loop (already shown above) -->\n <ng-container *ngIf=\"eventType !== 'navigate'\">\n\n <!-- Type: First param (text value like {{username}}) -->\n <span *ngIf=\"eventType === 'type' && i === 0\" class=\"cqa-text-gray-900 cqa-text-sm\">\n {{ param.value }}\n </span>\n\n <!-- Type: \"into\" text -->\n <span *ngIf=\"eventType === 'type' && i === 0\" class=\"cqa-text-gray-900 cqa-text-sm\">\n into\n </span>\n\n <!-- Type: Second param (selector) -->\n <span *ngIf=\"eventType === 'type' && i === 1\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- Click: Selector input/display -->\n <span *ngIf=\"eventType === 'click' && param.name === 'element'\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- Click: Suffix text (like \"if Present\") -->\n <span *ngIf=\"eventType === 'click' && param.name === 'suffix'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n {{ param.value }}\n </span>\n\n <!-- Double Click: Selector input/display -->\n <span *ngIf=\"eventType === 'doubleClick' && i === 0\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- Press Enter: Selector input/display with HTML support -->\n <span *ngIf=\"eventType === 'pressEnter' && i === 0\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\"\n [innerHTML]=\"param.displayValue || param.value\">\n </span>\n\n <!-- Enter: Value display with quotes (like click action) -->\n <span *ngIf=\"eventType === 'enter' && param.name === 'value'\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- Enter: \"in the\" text -->\n <span *ngIf=\"eventType === 'enter' && param.name === 'value'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n in the\n </span>\n\n <!-- Enter: Label display with quotes (like click action) -->\n <span *ngIf=\"eventType === 'enter' && param.name === 'label'\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n\n <!-- Enter: \"field\" text -->\n <span *ngIf=\"eventType === 'enter' && param.name === 'label'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n field\n </span>\n\n <!-- Wait: Duration input -->\n <input *ngIf=\"eventType === 'wait' && param.name === 'duration'\" type=\"number\" [value]=\"param.value\"\n (input)=\"onParameterChange(param, $any($event.target).value)\" placeholder=\"2\"\n class=\"cqa-w-16 cqa-px-2 cqa-py-1.5 cqa-rounded-lg cqa-border cqa-border-solid cqa-border-[#9E9EE3] cqa-bg-[#D1C4E9] cqa-text-[#3F43EE] cqa-text-sm cqa-font-medium cqa-outline-none focus:cqa-ring-2 focus:cqa-ring-[#3F43EE] focus:cqa-ring-opacity-50\" />\n <span *ngIf=\"eventType === 'wait' && param.name === 'duration'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n seconds\n </span>\n\n <!-- Wait: Element selector -->\n <span *ngIf=\"eventType === 'wait' && param.name === 'element'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n for element\n </span>\n <span *ngIf=\"eventType === 'wait' && param.name === 'element'\" \n #elementTrigger\n (click)=\"openElementPopup($event)\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-cursor-pointer cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n <span *ngIf=\"eventType === 'wait' && param.name === 'element'\" class=\"cqa-text-gray-900 cqa-text-sm\">\n to be visible\n </span>\n\n <!-- Custom: Description (clickable to open Step Description modal; pass $event so modal opens below this trigger) -->\n <span *ngIf=\"eventType === 'custom'\" #descriptionTrigger\n (click)=\"openStepDescriptionModal($event)\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC] cqa-cursor-pointer hover:cqa-opacity-90\"\n [innerHTML]=\"param.displayValue || param.value\">\n </span>\n\n <!-- AI Agent: Instructions -->\n <span *ngIf=\"eventType === 'ai-agent'\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ param.displayValue || param.value }}\n </span>\n </ng-container>\n </ng-container>\n </div>\n\n <!-- AI Agent View Details Link -->\n <a *ngIf=\"eventType === 'ai-agent'\" href=\"#\" (click)=\"onMoreOptions(); $event.preventDefault()\" class=\"cqa-ml-auto cqa-text-[#3F43EE] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-flex cqa-items-center cqa-gap-2 cqa-no-underline\">View Details<svg width=\"8\" height=\"8\" viewBox=\"0 0 8 8\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2.03809 6.74329L2.62809 7.33329L5.96142 3.99996L2.62809 0.666626L2.03809 1.25663L4.78142 3.99996L2.03809 6.74329Z\" fill=\"#3F43EE\"/></svg></a>\n\n <!-- Action Icons: Edit, Link, Duplicate, Delete (show on hover, same as API step) -->\n <div class=\"step-actions cqa-flex cqa-items-center cqa-gap-3 cqa-ml-auto cqa-px-[7px]\">\n <button type=\"button\" #editTrigger (click)=\"onEdit(); $event.stopPropagation()\" title=\"Edit\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7 11.6666H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M9.55208 2.1128C9.7843 1.88058 10.0993 1.75012 10.4277 1.75012C10.7561 1.75012 11.071 1.88058 11.3033 2.1128C11.5355 2.34502 11.6659 2.65998 11.6659 2.98838C11.6659 3.31679 11.5355 3.63175 11.3033 3.86397L4.29742 10.8704C4.15864 11.0092 3.9871 11.1107 3.79867 11.1656L2.12333 11.6544C2.07314 11.669 2.01993 11.6699 1.96928 11.6569C1.91863 11.6439 1.8724 11.6176 1.83543 11.5806C1.79846 11.5437 1.7721 11.4974 1.75913 11.4468C1.74615 11.3961 1.74703 11.3429 1.76167 11.2927L2.2505 9.61738C2.30546 9.42916 2.40698 9.25783 2.54567 9.11922L9.55208 2.1128Z\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n <button type=\"button\" (click)=\"onLink(); $event.stopPropagation()\" title=\"Link\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M5.00065 9.91671H3.66732C2.78326 9.91671 1.93542 9.60942 1.3103 9.06244C0.685174 8.51545 0.333984 7.77359 0.333984 7.00004C0.333984 6.22649 0.685174 5.48463 1.3103 4.93765C1.93542 4.39066 2.78326 4.08337 3.66732 4.08337H5.00065\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M9 4.08337H10.3333C11.2174 4.08337 12.0652 4.39066 12.6904 4.93765C13.3155 5.48463 13.6667 6.22649 13.6667 7.00004C13.6667 7.77359 13.3155 8.51545 12.6904 9.06244C12.0652 9.60942 11.2174 9.91671 10.3333 9.91671H9\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M4.33398 7H9.66732\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n <button type=\"button\" (click)=\"onDuplicate(); $event.stopPropagation()\" title=\"Duplicate\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M11.666 4.66663H5.83268C5.18835 4.66663 4.66602 5.18896 4.66602 5.83329V11.6666C4.66602 12.311 5.18835 12.8333 5.83268 12.8333H11.666C12.3103 12.8333 12.8327 12.311 12.8327 11.6666V5.83329C12.8327 5.18896 12.3103 4.66663 11.666 4.66663Z\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M2.33268 9.33329C1.69102 9.33329 1.16602 8.80829 1.16602 8.16663V2.33329C1.16602 1.69163 1.69102 1.16663 2.33268 1.16663H8.16602C8.80768 1.16663 9.33268 1.69163 9.33268 2.33329\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n <button type=\"button\" (click)=\"onDelete(); $event.stopPropagation()\" title=\"Delete\" class=\"cqa-p-0 cqa-text-[#ff6467] hover:cqa-text-[#C63535]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1.75 3.5H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M11.0827 3.5V11.6667C11.0827 12.25 10.4993 12.8333 9.91602 12.8333H4.08268C3.49935 12.8333 2.91602 12.25 2.91602 11.6667V3.5\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M4.66602 3.49996V2.33329C4.66602 1.74996 5.24935 1.16663 5.83268 1.16663H8.16602C8.74935 1.16663 9.33268 1.74996 9.33268 2.33329V3.49996\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M5.83398 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.16602 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </button>\n </div>\n</div>" }]
17112
+ }], ctorParameters: function () { return [{ type: CustomEditStepService }, { type: ElementPopupService }, { type: TestDataModalService }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: i1$1.DomSanitizer }]; }, propDecorators: { dropdownContainer: [{
17235
17113
  type: ViewChild,
17236
17114
  args: ['dropdownContainer', { static: false }]
17237
17115
  }], descriptionTrigger: [{
@@ -17250,6 +17128,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
17250
17128
  type: Input
17251
17129
  }], stepNumber: [{
17252
17130
  type: Input
17131
+ }], action: [{
17132
+ type: Input
17253
17133
  }], eventType: [{
17254
17134
  type: Input
17255
17135
  }], parameters: [{
@@ -17280,6 +17160,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
17280
17160
  type: Output
17281
17161
  }], selectionChange: [{
17282
17162
  type: Output
17163
+ }], clickAction: [{
17164
+ type: Output
17283
17165
  }], onDocumentClick: [{
17284
17166
  type: HostListener,
17285
17167
  args: ['document:click', ['$event']]
@@ -17362,6 +17244,7 @@ class TestCaseDetailsRendererComponent {
17362
17244
  this.isInsideLoop = false;
17363
17245
  /** When true, enables drag-and-drop reordering and shows drag handle icon instead of checkbox */
17364
17246
  this.isReorder = false;
17247
+ this.addStepBetween = false;
17365
17248
  this.nestedStepChange = new EventEmitter();
17366
17249
  this.addStep = new EventEmitter();
17367
17250
  this.deleteStep = new EventEmitter();
@@ -17388,8 +17271,10 @@ class TestCaseDetailsRendererComponent {
17388
17271
  this.maxIterationsChange = new EventEmitter();
17389
17272
  this.eventTypeChange = new EventEmitter();
17390
17273
  this.parameterChange = new EventEmitter();
17274
+ this.clickAction = new EventEmitter();
17391
17275
  /** Emitted when a step is dropped in a nested dropzone (step-group, loop, condition). Payload: { event, targetList }. */
17392
17276
  this.dndDropInZone = new EventEmitter();
17277
+ this.addStepBetweenClick = new EventEmitter();
17393
17278
  this.componentRef = null;
17394
17279
  }
17395
17280
  ngAfterViewInit() {
@@ -17510,14 +17395,16 @@ class TestCaseDetailsRendererComponent {
17510
17395
  wire('maxIterationsChange', this.maxIterationsChange);
17511
17396
  wire('eventTypeChange', this.eventTypeChange);
17512
17397
  wire('parameterChange', this.parameterChange);
17398
+ wire('clickAction', this.clickAction);
17513
17399
  wire('dndDropInZone', this.dndDropInZone);
17400
+ wire('addStepBetweenClick', this.addStepBetweenClick);
17514
17401
  }
17515
17402
  }
17516
17403
  TestCaseDetailsRendererComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestCaseDetailsRendererComponent, deps: [{ token: TEST_CASE_STEP_COMPONENT_MAP }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
17517
- TestCaseDetailsRendererComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TestCaseDetailsRendererComponent, selector: "cqa-test-case-details-renderer", inputs: { step: "step", index: "index", isNested: "isNested", isInsideLoop: "isInsideLoop", branch: "branch", isReorder: "isReorder" }, outputs: { nestedStepChange: "nestedStepChange", addStep: "addStep", deleteStep: "deleteStep", toggleExpanded: "toggleExpanded", groupNameChange: "groupNameChange", descriptionChange: "descriptionChange", reusableChange: "reusableChange", openExternal: "openExternal", edit: "edit", link: "link", duplicate: "duplicate", delete: "delete", viewDetails: "viewDetails", selectionChange: "selectionChange", conditionChange: "conditionChange", branchStepChange: "branchStepChange", addStepForBranch: "addStepForBranch", deleteStepWithBranch: "deleteStepWithBranch", addBranch: "addBranch", deleteBranch: "deleteBranch", testDataProfileChange: "testDataProfileChange", startStepChange: "startStepChange", endStepChange: "endStepChange", maxIterationsChange: "maxIterationsChange", eventTypeChange: "eventTypeChange", parameterChange: "parameterChange", dndDropInZone: "dndDropInZone" }, host: { classAttribute: "cqa-ui-root" }, viewQueries: [{ propertyName: "stepHost", first: true, predicate: ["stepHost"], descendants: true, read: ViewContainerRef }], usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-relative\">\n <ng-container #stepHost></ng-container>\n <button class=\"cqa-absolute cqa-top-[calc(100%-12px)] cqa-left-[50%] cqa-translate-x-[-50%] cqa-p-0 cqa-z-[1] cqa-hidden\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"1\" y=\"1\" width=\"21.1822\" height=\"22\" rx=\"10.5911\" fill=\"white\"/><rect x=\"1\" y=\"1\" width=\"21.1822\" height=\"22\" rx=\"10.5911\" stroke=\"#3F43EE\" stroke-width=\"2\"/><path d=\"M8.5 12H15.5\" stroke=\"#3F43EE\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M12 8.5V15.5\" stroke=\"#3F43EE\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n</div>" });
17404
+ TestCaseDetailsRendererComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TestCaseDetailsRendererComponent, selector: "cqa-test-case-details-renderer", inputs: { step: "step", index: "index", isNested: "isNested", isInsideLoop: "isInsideLoop", branch: "branch", isReorder: "isReorder", addStepBetween: "addStepBetween" }, outputs: { nestedStepChange: "nestedStepChange", addStep: "addStep", deleteStep: "deleteStep", toggleExpanded: "toggleExpanded", groupNameChange: "groupNameChange", descriptionChange: "descriptionChange", reusableChange: "reusableChange", openExternal: "openExternal", edit: "edit", link: "link", duplicate: "duplicate", delete: "delete", viewDetails: "viewDetails", selectionChange: "selectionChange", conditionChange: "conditionChange", branchStepChange: "branchStepChange", addStepForBranch: "addStepForBranch", deleteStepWithBranch: "deleteStepWithBranch", addBranch: "addBranch", deleteBranch: "deleteBranch", testDataProfileChange: "testDataProfileChange", startStepChange: "startStepChange", endStepChange: "endStepChange", maxIterationsChange: "maxIterationsChange", eventTypeChange: "eventTypeChange", parameterChange: "parameterChange", clickAction: "clickAction", dndDropInZone: "dndDropInZone", addStepBetweenClick: "addStepBetweenClick" }, host: { classAttribute: "cqa-ui-root" }, viewQueries: [{ propertyName: "stepHost", first: true, predicate: ["stepHost"], descendants: true, read: ViewContainerRef }], usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-relative\">\n <button *ngIf=\"addStepBetween\" class=\"cqa-absolute cqa-top-[calc(100%-12px)] cqa-left-[50%] cqa-translate-x-[-50%] cqa-p-0 cqa-z-[1]\" (click)=\"addStepBetweenClick.emit({step: step, index: index})\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"1\" y=\"1\" width=\"21.1822\" height=\"22\" rx=\"10.5911\" fill=\"white\"/><rect x=\"1\" y=\"1\" width=\"21.1822\" height=\"22\" rx=\"10.5911\" stroke=\"#3F43EE\" stroke-width=\"2\"/><path d=\"M8.5 12H15.5\" stroke=\"#3F43EE\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M12 8.5V15.5\" stroke=\"#3F43EE\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n <ng-container #stepHost></ng-container>\n <button *ngIf=\"addStepBetween\" class=\"cqa-absolute cqa-top-[calc(100%-12px)] cqa-left-[50%] cqa-translate-x-[-50%] cqa-p-0 cqa-z-[1]\" (click)=\"addStepBetweenClick.emit({step: step, index: index})\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"1\" y=\"1\" width=\"21.1822\" height=\"22\" rx=\"10.5911\" fill=\"white\"/><rect x=\"1\" y=\"1\" width=\"21.1822\" height=\"22\" rx=\"10.5911\" stroke=\"#3F43EE\" stroke-width=\"2\"/><path d=\"M8.5 12H15.5\" stroke=\"#3F43EE\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M12 8.5V15.5\" stroke=\"#3F43EE\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n</div>", directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
17518
17405
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestCaseDetailsRendererComponent, decorators: [{
17519
17406
  type: Component,
17520
- args: [{ selector: 'cqa-test-case-details-renderer', host: { class: 'cqa-ui-root' }, template: "<div class=\"cqa-relative\">\n <ng-container #stepHost></ng-container>\n <button class=\"cqa-absolute cqa-top-[calc(100%-12px)] cqa-left-[50%] cqa-translate-x-[-50%] cqa-p-0 cqa-z-[1] cqa-hidden\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"1\" y=\"1\" width=\"21.1822\" height=\"22\" rx=\"10.5911\" fill=\"white\"/><rect x=\"1\" y=\"1\" width=\"21.1822\" height=\"22\" rx=\"10.5911\" stroke=\"#3F43EE\" stroke-width=\"2\"/><path d=\"M8.5 12H15.5\" stroke=\"#3F43EE\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M12 8.5V15.5\" stroke=\"#3F43EE\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n</div>" }]
17407
+ args: [{ selector: 'cqa-test-case-details-renderer', host: { class: 'cqa-ui-root' }, template: "<div class=\"cqa-relative\">\n <button *ngIf=\"addStepBetween\" class=\"cqa-absolute cqa-top-[calc(100%-12px)] cqa-left-[50%] cqa-translate-x-[-50%] cqa-p-0 cqa-z-[1]\" (click)=\"addStepBetweenClick.emit({step: step, index: index})\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"1\" y=\"1\" width=\"21.1822\" height=\"22\" rx=\"10.5911\" fill=\"white\"/><rect x=\"1\" y=\"1\" width=\"21.1822\" height=\"22\" rx=\"10.5911\" stroke=\"#3F43EE\" stroke-width=\"2\"/><path d=\"M8.5 12H15.5\" stroke=\"#3F43EE\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M12 8.5V15.5\" stroke=\"#3F43EE\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n <ng-container #stepHost></ng-container>\n <button *ngIf=\"addStepBetween\" class=\"cqa-absolute cqa-top-[calc(100%-12px)] cqa-left-[50%] cqa-translate-x-[-50%] cqa-p-0 cqa-z-[1]\" (click)=\"addStepBetweenClick.emit({step: step, index: index})\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"1\" y=\"1\" width=\"21.1822\" height=\"22\" rx=\"10.5911\" fill=\"white\"/><rect x=\"1\" y=\"1\" width=\"21.1822\" height=\"22\" rx=\"10.5911\" stroke=\"#3F43EE\" stroke-width=\"2\"/><path d=\"M8.5 12H15.5\" stroke=\"#3F43EE\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M12 8.5V15.5\" stroke=\"#3F43EE\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n</div>" }]
17521
17408
  }], ctorParameters: function () {
17522
17409
  return [{ type: undefined, decorators: [{
17523
17410
  type: Inject,
@@ -17538,6 +17425,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
17538
17425
  type: Input
17539
17426
  }], isReorder: [{
17540
17427
  type: Input
17428
+ }], addStepBetween: [{
17429
+ type: Input
17541
17430
  }], nestedStepChange: [{
17542
17431
  type: Output
17543
17432
  }], addStep: [{
@@ -17590,8 +17479,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
17590
17479
  type: Output
17591
17480
  }], parameterChange: [{
17592
17481
  type: Output
17482
+ }], clickAction: [{
17483
+ type: Output
17593
17484
  }], dndDropInZone: [{
17594
17485
  type: Output
17486
+ }], addStepBetweenClick: [{
17487
+ type: Output
17595
17488
  }] } });
17596
17489
 
17597
17490
  class TestCaseLoopStepComponent {
@@ -17896,7 +17789,7 @@ class TestCaseLoopStepComponent {
17896
17789
  }
17897
17790
  }
17898
17791
  TestCaseLoopStepComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestCaseLoopStepComponent, deps: [{ token: i2$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
17899
- TestCaseLoopStepComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TestCaseLoopStepComponent, selector: "cqa-test-case-loop-step", inputs: { config: "config", id: "id", loopType: "loopType", stepNumber: "stepNumber", condition: "condition", maxIterations: "maxIterations", testDataProfile: "testDataProfile", startStep: "startStep", endStep: "endStep", nestedSteps: "nestedSteps", expanded: "expanded", isNested: "isNested", isInsideLoop: "isInsideLoop", isReorder: "isReorder" }, outputs: { toggleExpanded: "toggleExpanded", testDataProfileChange: "testDataProfileChange", startStepChange: "startStepChange", endStepChange: "endStepChange", conditionChange: "conditionChange", maxIterationsChange: "maxIterationsChange", nestedStepChange: "nestedStepChange", addStep: "addStep", deleteStep: "deleteStep", duplicate: "duplicate", delete: "delete", moreOptions: "moreOptions", edit: "edit", dndDropInZone: "dndDropInZone" }, host: { classAttribute: "cqa-ui-root" }, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col\">\n <!-- Inline Edit Mode: Frame 2147224910 - flex row, 1056\u00D736, gap 12px, flex-none -->\n <div *ngIf=\"isEditing\" class=\"cqa-py-2.5 cqa-px-4 cqa-flex cqa-items-center cqa-gap-3 cqa-justify-between\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-flex-grow\">\n <!-- Loop Type Label -->\n <div class=\"cqa-font-semibold cqa-text-[#1C398E] cqa-text-[12px] cqa-leading-[15px]\">\n {{ getLoopTypeLabel() }}\n </div>\n\n <!-- FOR LOOP inline edit: cqa-dynamic-select (same usage as default stories) -->\n <ng-container *ngIf=\"loopType === 'for'\">\n <!-- First select: width 216.25px, height 36px, gap 4px, opacity 1 -->\n <cqa-dynamic-select [form]=\"editForm\" [config]=\"forOptionTypeSelectConfig\"\n class=\"cqa-w-full cqa-max-w-[216px]\"></cqa-dynamic-select>\n <cqa-custom-input [value]=\"editForm.get('testDataProfile')?.value ?? ''\"\n (valueChange)=\"onEditFormFieldChange('testDataProfile', $event)\" placeholder=\"Testdataprofile\"\n class=\"cqa-w-full cqa-max-w-[216px]\" size=\"sm\">\n </cqa-custom-input>\n <cqa-dynamic-select [form]=\"editForm\" [config]=\"startStepSelectConfig\"\n class=\"cqa-w-full cqa-max-w-[216px]\"></cqa-dynamic-select>\n <cqa-dynamic-select [form]=\"editForm\" [config]=\"endStepSelectConfig\"\n class=\"cqa-w-full cqa-max-w-[216px]\"></cqa-dynamic-select>\n </ng-container>\n\n <!-- WHILE LOOP inline edit -->\n <ng-container *ngIf=\"isWhileLoop()\">\n <cqa-custom-input [value]=\"editForm.get('condition')?.value ?? ''\" class=\"cqa-w-full cqa-max-w-[216px]\"\n (valueChange)=\"onEditFormFieldChange('condition', $event)\" placeholder='element \".selector\" exists' size=\"sm\">\n </cqa-custom-input>\n </ng-container>\n\n <!-- Edit In depth link -->\n <a href=\"#\" (click)=\"onEditInDepth(); $event.preventDefault()\"\n class=\"cqa-text-[#3F43EE] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-flex cqa-items-center cqa-gap-[2px] cqa-no-underline\">\n Edit In depth\n <svg width=\"8\" height=\"8\" viewBox=\"0 0 8 8\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M2.03809 6.74329L2.62809 7.33329L5.96142 3.99996L2.62809 0.666626L2.03809 1.25663L4.78142 3.99996L2.03809 6.74329Z\"\n fill=\"#3F43EE\" />\n </svg>\n </a>\n </div>\n\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <!-- Cancel / Apply -->\n <cqa-button variant=\"outlined\" btnSize=\"lg\" [customClass]=\"'cqa-text-[14px] cqa-py-[9px]'\" [text]=\"'Cancel'\"\n (clicked)=\"onEditCancel()\"></cqa-button>\n <cqa-button variant=\"filled\" btnSize=\"lg\" [customClass]=\"'cqa-text-[14px] cqa-py-[9px]'\" [text]=\"'Apply'\"\n (clicked)=\"onEditApply()\"></cqa-button>\n </div>\n </div>\n\n <!-- Loop Header (normal view when not editing) -->\n <div *ngIf=\"!isEditing\"\n [class]=\"'step-row cqa-flex cqa-items-center cqa-gap-3 cqa-py-2 ' + (isInsideLoop ? 'cqa-pl-10 cqa-pr-4' : 'cqa-px-4')\">\n <!-- Expand/Collapse Icon -->\n <button type=\"button\" (click)=\"onToggleExpanded()\" class=\"cqa-p-0\">\n <svg [class.cqa-rotate-180]=\"!expanded\" class=\"cqa-transition-transform\" width=\"16\" height=\"16\"\n viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M12 10L8 6L4 10\" stroke=\"#6B7280\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n\n <!-- Loop Icon -->\n <div *ngIf=\"loopType === 'for'\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M11.334 1.33325L14.0007 3.99992L11.334 6.66659\" stroke=\"#1C398E\" stroke-width=\"1.33333\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M2 7.33333V6.66667C2 5.95942 2.28095 5.28115 2.78105 4.78105C3.28115 4.28095 3.95942 4 4.66667 4H14\"\n stroke=\"#1C398E\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M4.66667 14.6666L2 11.9999L4.66667 9.33325\" stroke=\"#1C398E\" stroke-width=\"1.33333\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M14 8.66675V9.33341C14 10.0407 13.719 10.7189 13.219 11.219C12.7189 11.7191 12.0406 12.0001 11.3333 12.0001H2\"\n stroke=\"#1C398E\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </div>\n <div *ngIf=\"loopType === 'while'\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M11.334 1.33325L14.0007 3.99992L11.334 6.66659\" stroke=\"#59168B\" stroke-width=\"1.33333\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M2 7.33333V6.66667C2 5.95942 2.28095 5.28115 2.78105 4.78105C3.28115 4.28095 3.95942 4 4.66667 4H14\"\n stroke=\"#59168B\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M4.66667 14.6666L2 11.9999L4.66667 9.33325\" stroke=\"#59168B\" stroke-width=\"1.33333\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M14 8.66675V9.33341C14 10.0407 13.719 10.7189 13.219 11.219C12.7189 11.7191 12.0406 12.0001 11.3333 12.0001H2\"\n stroke=\"#59168B\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </div>\n\n <!-- Loop Type Label -->\n <span class=\"cqa-font-semibold cqa-text-[#1C398E] cqa-text-[12px] cqa-leading-none\">\n {{ getLoopTypeLabel() }}\n </span>\n\n <!-- For Loop Controls -->\n <div *ngIf=\"loopType === 'for'\" class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-ml-2\">\n <!-- Test Data Profile Button -->\n <button type=\"button\" [class.cqa-bg-primary-100]=\"testDataProfile\" [class.cqa-text-primary]=\"testDataProfile\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ getTestDataProfileLabel() }}\n </button>\n\n <!-- Start Button -->\n <button type=\"button\" [class.cqa-bg-primary-100]=\"startStep\" [class.cqa-text-primary]=\"startStep\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ getStartStepLabel() }}\n </button>\n\n <!-- End Button -->\n <button type=\"button\" [class.cqa-bg-primary-100]=\"endStep\" [class.cqa-text-primary]=\"endStep\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ getEndStepLabel() }}\n </button>\n </div>\n\n <!-- While Loop Condition (only show if condition exists) -->\n <div *ngIf=\"isWhileLoop() && condition\" class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-ml-2 cqa-flex-1\">\n <span class=\"cqa-text-gray-700 cqa-text-sm\">\n While\n </span>\n <span class=\"cqa-text-gray-900 cqa-text-sm\" [innerHTML]=\"getConditionDisplay()\"></span>\n </div>\n\n <!-- Steps Summary -->\n <div\n class=\"cqa-ml-auto cqa-border cqa-border-solid cqa-border-[#E5E5E5] cqa-rounded-lg cqa-py-0.5 cqa-px-2 cqa-text-[#0A0A0A] cqa-text-[12px] cqa-leading-[15px]\">\n {{ getStepsSummary() }}\n </div>\n\n <!-- Action Icons: Edit, Link, Duplicate, Delete (show on hover) -->\n <div class=\"step-actions cqa-flex cqa-items-center cqa-gap-3 cqa-px-[7px]\">\n <button type=\"button\" (click)=\"onEdit(); $event.stopPropagation()\" title=\"Edit\"\n class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7 11.6666H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path\n d=\"M9.55208 2.1128C9.7843 1.88058 10.0993 1.75012 10.4277 1.75012C10.7561 1.75012 11.071 1.88058 11.3033 2.1128C11.5355 2.34502 11.6659 2.65998 11.6659 2.98838C11.6659 3.31679 11.5355 3.63175 11.3033 3.86397L4.29742 10.8704C4.15864 11.0092 3.9871 11.1107 3.79867 11.1656L2.12333 11.6544C2.07314 11.669 2.01993 11.6699 1.96928 11.6569C1.91863 11.6439 1.8724 11.6176 1.83543 11.5806C1.79846 11.5437 1.7721 11.4974 1.75913 11.4468C1.74615 11.3961 1.74703 11.3429 1.76167 11.2927L2.2505 9.61738C2.30546 9.42916 2.40698 9.25783 2.54567 9.11922L9.55208 2.1128Z\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </button>\n <button type=\"button\" (click)=\"onLink(); $event.stopPropagation()\" title=\"Link\"\n class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M5.00065 9.91671H3.66732C2.78326 9.91671 1.93542 9.60942 1.3103 9.06244C0.685174 8.51545 0.333984 7.77359 0.333984 7.00004C0.333984 6.22649 0.685174 5.48463 1.3103 4.93765C1.93542 4.39066 2.78326 4.08337 3.66732 4.08337H5.00065\"\n stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M9 4.08337H10.3333C11.2174 4.08337 12.0652 4.39066 12.6904 4.93765C13.3155 5.48463 13.6667 6.22649 13.6667 7.00004C13.6667 7.77359 13.3155 8.51545 12.6904 9.06244C12.0652 9.60942 11.2174 9.91671 10.3333 9.91671H9\"\n stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M4.33398 7H9.66732\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n <button type=\"button\" (click)=\"onDuplicate(); $event.stopPropagation()\" title=\"Duplicate\"\n class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M11.666 4.66663H5.83268C5.18835 4.66663 4.66602 5.18896 4.66602 5.83329V11.6666C4.66602 12.311 5.18835 12.8333 5.83268 12.8333H11.666C12.3103 12.8333 12.8327 12.311 12.8327 11.6666V5.83329C12.8327 5.18896 12.3103 4.66663 11.666 4.66663Z\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M2.33268 9.33329C1.69102 9.33329 1.16602 8.80829 1.16602 8.16663V2.33329C1.16602 1.69163 1.69102 1.16663 2.33268 1.16663H8.16602C8.80768 1.16663 9.33268 1.69163 9.33268 2.33329\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </button>\n <button type=\"button\" (click)=\"onDelete(); $event.stopPropagation()\" title=\"Delete\"\n class=\"cqa-p-0 cqa-text-[#ff6467] hover:cqa-text-[#C63535]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1.75 3.5H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path\n d=\"M11.0827 3.5V11.6667C11.0827 12.25 10.4993 12.8333 9.91602 12.8333H4.08268C3.49935 12.8333 2.91602 12.25 2.91602 11.6667V3.5\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M4.66602 3.49996V2.33329C4.66602 1.74996 5.24935 1.16663 5.83268 1.16663H8.16602C8.74935 1.16663 9.33268 1.74996 9.33268 2.33329V3.49996\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M5.83398 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M8.16602 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n </div>\n </div>\n\n <!-- Expanded Content with Nested Steps (renderer dispatches by step type, n-level nesting) -->\n <div *ngIf=\"expanded\" class=\"cqa-flex cqa-flex-col\">\n <div *ngIf=\"!isReorder\" class=\"cqa-flex cqa-flex-col\">\n <cqa-test-case-details-renderer *ngFor=\"let step of nestedSteps; let i = index\" [step]=\"step\" [index]=\"i\"\n [isNested]=\"true\" [isInsideLoop]=\"true\" [isReorder]=\"isReorder\" (nestedStepChange)=\"onNestedStepChange($event.step, $event.index)\"\n (addStep)=\"onAddStep()\" (deleteStep)=\"onDeleteStep($event)\"\n (toggleExpanded)=\"onNestedToggleExpanded($event, step, i)\"\n (groupNameChange)=\"$any(step).groupName = $event; onNestedStepChange(step, i)\"\n (descriptionChange)=\"$any(step).description = $event; onNestedStepChange(step, i)\"\n (reusableChange)=\"$any(step).reusable = $event; onNestedStepChange(step, i)\"\n (openExternal)=\"onNestedStepChange(step, i)\" (edit)=\"onNestedStepChange(step, i)\"\n (link)=\"onNestedStepChange(step, i)\" (duplicate)=\"onNestedStepChange(step, i)\" (delete)=\"onDeleteStep(i)\"\n (conditionChange)=\"$any(step).condition = $event; onNestedStepChange(step, i)\"\n (branchStepChange)=\"onNestedStepChange(step, i)\" (addBranch)=\"onNestedConditionAddBranch($any(step), i)\"\n (deleteBranch)=\"onNestedConditionDeleteBranch($any(step), $event, i)\"\n (testDataProfileChange)=\"$any(step).testDataProfile = $event; onNestedStepChange(step, i)\"\n (startStepChange)=\"$any(step).startStep = $event; onNestedStepChange(step, i)\"\n (endStepChange)=\"$any(step).endStep = $event; onNestedStepChange(step, i)\"\n (maxIterationsChange)=\"$any(step).maxIterations = $event; onNestedStepChange(step, i)\"\n (eventTypeChange)=\"$any(step).eventType = $event; onNestedStepChange(step, i)\"\n (parameterChange)=\"onNestedStepChange(step, i)\"\n (selectionChange)=\"$any(step).selected = $event; onNestedStepChange(step, i)\"\n (dndDropInZone)=\"dndDropInZone.emit($event)\">\n </cqa-test-case-details-renderer>\n </div>\n <div *ngIf=\"isReorder\" class=\"cqa-flex cqa-flex-col nested-step-drop-list\"\n [dndDropzone]=\"['step']\"\n dndEffectAllowed=\"move\"\n dndDragoverClass=\"dndDragover\"\n (dndDrop)=\"onDndDrop($event)\">\n <div dndPlaceholderRef class=\"step-drag-placeholder-nested cqa-my-1 cqa-min-h-[50px] cqa-border-2 cqa-border-dashed cqa-border-[#3F43EE] cqa-rounded cqa-bg-[rgba(63,67,238,0.08)] cqa-flex cqa-items-center cqa-justify-center cqa-text-[#3F43EE] cqa-text-xs\">Drop here</div>\n <div *ngFor=\"let step of nestedSteps; let i = index\" class=\"nested-step-drag-item\"\n [dndDraggable]=\"step\"\n dndEffectAllowed=\"move\"\n dndType=\"step\">\n <cqa-test-case-details-renderer [step]=\"step\" [index]=\"i\"\n [isNested]=\"true\" [isInsideLoop]=\"true\" [isReorder]=\"isReorder\"\n (nestedStepChange)=\"onNestedStepChange($event.step, $event.index)\"\n (addStep)=\"onAddStep()\" (deleteStep)=\"onDeleteStep($event)\"\n (toggleExpanded)=\"onNestedToggleExpanded($event, step, i)\"\n (groupNameChange)=\"$any(step).groupName = $event; onNestedStepChange(step, i)\"\n (descriptionChange)=\"$any(step).description = $event; onNestedStepChange(step, i)\"\n (reusableChange)=\"$any(step).reusable = $event; onNestedStepChange(step, i)\"\n (openExternal)=\"onNestedStepChange(step, i)\" (edit)=\"onNestedStepChange(step, i)\"\n (link)=\"onNestedStepChange(step, i)\" (duplicate)=\"onNestedStepChange(step, i)\" (delete)=\"onDeleteStep(i)\"\n (conditionChange)=\"$any(step).condition = $event; onNestedStepChange(step, i)\"\n (branchStepChange)=\"onNestedStepChange(step, i)\" (addBranch)=\"onNestedConditionAddBranch($any(step), i)\"\n (deleteBranch)=\"onNestedConditionDeleteBranch($any(step), $event, i)\"\n (testDataProfileChange)=\"$any(step).testDataProfile = $event; onNestedStepChange(step, i)\"\n (startStepChange)=\"$any(step).startStep = $event; onNestedStepChange(step, i)\"\n (endStepChange)=\"$any(step).endStep = $event; onNestedStepChange(step, i)\"\n (maxIterationsChange)=\"$any(step).maxIterations = $event; onNestedStepChange(step, i)\"\n (eventTypeChange)=\"$any(step).eventType = $event; onNestedStepChange(step, i)\"\n (parameterChange)=\"onNestedStepChange(step, i)\"\n (selectionChange)=\"$any(step).selected = $event; onNestedStepChange(step, i)\"\n (dndDropInZone)=\"dndDropInZone.emit($event)\">\n </cqa-test-case-details-renderer>\n </div>\n </div>\n\n <!-- END Marker -->\n <div\n [class]=\"'cqa-pl-4 cqa-py-1 cqa-bg-[#DBEAFE80] cqa-text-[#1C398E] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium'\"\n style=\"border-top: 1px solid #BEDBFF;\">\n {{ getEndLabel() }}\n </div>\n </div>\n</div>", styles: [".step-actions{opacity:0;transition:opacity .15s ease}.step-row:hover .step-actions{opacity:1}\n"], components: [{ type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore"] }, { type: CustomInputComponent, selector: "cqa-custom-input", inputs: ["label", "type", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "inputInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused", "enterPressed"] }, { type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }, { type: TestCaseDetailsRendererComponent, selector: "cqa-test-case-details-renderer", inputs: ["step", "index", "isNested", "isInsideLoop", "branch", "isReorder"], outputs: ["nestedStepChange", "addStep", "deleteStep", "toggleExpanded", "groupNameChange", "descriptionChange", "reusableChange", "openExternal", "edit", "link", "duplicate", "delete", "viewDetails", "selectionChange", "conditionChange", "branchStepChange", "addStepForBranch", "deleteStepWithBranch", "addBranch", "deleteBranch", "testDataProfileChange", "startStepChange", "endStepChange", "maxIterationsChange", "eventTypeChange", "parameterChange", "dndDropInZone"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i7.DndDropzoneDirective, selector: "[dndDropzone]", inputs: ["dndDropzone", "dndEffectAllowed", "dndAllowExternal", "dndHorizontal", "dndDragoverClass", "dndDropzoneDisabledClass", "dndDisableIf", "dndDisableDropIf"], outputs: ["dndDragover", "dndDrop"] }, { type: i7.DndPlaceholderRefDirective, selector: "[dndPlaceholderRef]" }, { type: i7.DndDraggableDirective, selector: "[dndDraggable]", inputs: ["dndDraggable", "dndEffectAllowed", "dndType", "dndDraggingClass", "dndDraggingSourceClass", "dndDraggableDisabledClass", "dndDragImageOffsetFunction", "dndDisableIf", "dndDisableDragIf"], outputs: ["dndStart", "dndDrag", "dndEnd", "dndMoved", "dndCopied", "dndLinked", "dndCanceled"] }] });
17792
+ TestCaseLoopStepComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TestCaseLoopStepComponent, selector: "cqa-test-case-loop-step", inputs: { config: "config", id: "id", loopType: "loopType", stepNumber: "stepNumber", condition: "condition", maxIterations: "maxIterations", testDataProfile: "testDataProfile", startStep: "startStep", endStep: "endStep", nestedSteps: "nestedSteps", expanded: "expanded", isNested: "isNested", isInsideLoop: "isInsideLoop", isReorder: "isReorder" }, outputs: { toggleExpanded: "toggleExpanded", testDataProfileChange: "testDataProfileChange", startStepChange: "startStepChange", endStepChange: "endStepChange", conditionChange: "conditionChange", maxIterationsChange: "maxIterationsChange", nestedStepChange: "nestedStepChange", addStep: "addStep", deleteStep: "deleteStep", duplicate: "duplicate", delete: "delete", moreOptions: "moreOptions", edit: "edit", dndDropInZone: "dndDropInZone" }, host: { classAttribute: "cqa-ui-root" }, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col\">\n <!-- Inline Edit Mode: Frame 2147224910 - flex row, 1056\u00D736, gap 12px, flex-none -->\n <div *ngIf=\"isEditing\" class=\"cqa-py-2.5 cqa-px-4 cqa-flex cqa-items-center cqa-gap-3 cqa-justify-between\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-flex-grow\">\n <!-- Loop Type Label -->\n <div class=\"cqa-font-semibold cqa-text-[#1C398E] cqa-text-[12px] cqa-leading-[15px]\">\n {{ getLoopTypeLabel() }}\n </div>\n\n <!-- FOR LOOP inline edit: cqa-dynamic-select (same usage as default stories) -->\n <ng-container *ngIf=\"loopType === 'for'\">\n <!-- First select: width 216.25px, height 36px, gap 4px, opacity 1 -->\n <cqa-dynamic-select [form]=\"editForm\" [config]=\"forOptionTypeSelectConfig\"\n class=\"cqa-w-full cqa-max-w-[216px]\"></cqa-dynamic-select>\n <cqa-custom-input [value]=\"editForm.get('testDataProfile')?.value ?? ''\"\n (valueChange)=\"onEditFormFieldChange('testDataProfile', $event)\" placeholder=\"Testdataprofile\"\n class=\"cqa-w-full cqa-max-w-[216px]\" size=\"sm\">\n </cqa-custom-input>\n <cqa-dynamic-select [form]=\"editForm\" [config]=\"startStepSelectConfig\"\n class=\"cqa-w-full cqa-max-w-[216px]\"></cqa-dynamic-select>\n <cqa-dynamic-select [form]=\"editForm\" [config]=\"endStepSelectConfig\"\n class=\"cqa-w-full cqa-max-w-[216px]\"></cqa-dynamic-select>\n </ng-container>\n\n <!-- WHILE LOOP inline edit -->\n <ng-container *ngIf=\"isWhileLoop()\">\n <cqa-custom-input [value]=\"editForm.get('condition')?.value ?? ''\" class=\"cqa-w-full cqa-max-w-[216px]\"\n (valueChange)=\"onEditFormFieldChange('condition', $event)\" placeholder='element \".selector\" exists' size=\"sm\">\n </cqa-custom-input>\n </ng-container>\n\n <!-- Edit In depth link -->\n <a href=\"#\" (click)=\"onEditInDepth(); $event.preventDefault()\"\n class=\"cqa-text-[#3F43EE] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-flex cqa-items-center cqa-gap-[2px] cqa-no-underline\">\n Edit In depth\n <svg width=\"8\" height=\"8\" viewBox=\"0 0 8 8\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M2.03809 6.74329L2.62809 7.33329L5.96142 3.99996L2.62809 0.666626L2.03809 1.25663L4.78142 3.99996L2.03809 6.74329Z\"\n fill=\"#3F43EE\" />\n </svg>\n </a>\n </div>\n\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <!-- Cancel / Apply -->\n <cqa-button variant=\"outlined\" btnSize=\"lg\" [customClass]=\"'cqa-text-[14px] cqa-py-[9px]'\" [text]=\"'Cancel'\"\n (clicked)=\"onEditCancel()\"></cqa-button>\n <cqa-button variant=\"filled\" btnSize=\"lg\" [customClass]=\"'cqa-text-[14px] cqa-py-[9px]'\" [text]=\"'Apply'\"\n (clicked)=\"onEditApply()\"></cqa-button>\n </div>\n </div>\n\n <!-- Loop Header (normal view when not editing) -->\n <div *ngIf=\"!isEditing\"\n [class]=\"'step-row cqa-flex cqa-items-center cqa-gap-3 cqa-py-2 ' + (isInsideLoop ? 'cqa-pl-10 cqa-pr-4' : 'cqa-px-4')\">\n <!-- Expand/Collapse Icon -->\n <button type=\"button\" (click)=\"onToggleExpanded()\" class=\"cqa-p-0\">\n <svg [class.cqa-rotate-180]=\"!expanded\" class=\"cqa-transition-transform\" width=\"16\" height=\"16\"\n viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M12 10L8 6L4 10\" stroke=\"#6B7280\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n\n <!-- Loop Icon -->\n <div *ngIf=\"loopType === 'for'\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M11.334 1.33325L14.0007 3.99992L11.334 6.66659\" stroke=\"#1C398E\" stroke-width=\"1.33333\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M2 7.33333V6.66667C2 5.95942 2.28095 5.28115 2.78105 4.78105C3.28115 4.28095 3.95942 4 4.66667 4H14\"\n stroke=\"#1C398E\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M4.66667 14.6666L2 11.9999L4.66667 9.33325\" stroke=\"#1C398E\" stroke-width=\"1.33333\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M14 8.66675V9.33341C14 10.0407 13.719 10.7189 13.219 11.219C12.7189 11.7191 12.0406 12.0001 11.3333 12.0001H2\"\n stroke=\"#1C398E\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </div>\n <div *ngIf=\"loopType === 'while'\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M11.334 1.33325L14.0007 3.99992L11.334 6.66659\" stroke=\"#59168B\" stroke-width=\"1.33333\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M2 7.33333V6.66667C2 5.95942 2.28095 5.28115 2.78105 4.78105C3.28115 4.28095 3.95942 4 4.66667 4H14\"\n stroke=\"#59168B\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M4.66667 14.6666L2 11.9999L4.66667 9.33325\" stroke=\"#59168B\" stroke-width=\"1.33333\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M14 8.66675V9.33341C14 10.0407 13.719 10.7189 13.219 11.219C12.7189 11.7191 12.0406 12.0001 11.3333 12.0001H2\"\n stroke=\"#59168B\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </div>\n\n <!-- Loop Type Label -->\n <span class=\"cqa-font-semibold cqa-text-[#1C398E] cqa-text-[12px] cqa-leading-none\">\n {{ getLoopTypeLabel() }}\n </span>\n\n <!-- For Loop Controls -->\n <div *ngIf=\"loopType === 'for'\" class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-ml-2\">\n <!-- Test Data Profile Button -->\n <button type=\"button\" [class.cqa-bg-primary-100]=\"testDataProfile\" [class.cqa-text-primary]=\"testDataProfile\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ getTestDataProfileLabel() }}\n </button>\n\n <!-- Start Button -->\n <button type=\"button\" [class.cqa-bg-primary-100]=\"startStep\" [class.cqa-text-primary]=\"startStep\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ getStartStepLabel() }}\n </button>\n\n <!-- End Button -->\n <button type=\"button\" [class.cqa-bg-primary-100]=\"endStep\" [class.cqa-text-primary]=\"endStep\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ getEndStepLabel() }}\n </button>\n </div>\n\n <!-- While Loop Condition (only show if condition exists) -->\n <div *ngIf=\"isWhileLoop() && condition\" class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-ml-2 cqa-flex-1\">\n <span class=\"cqa-text-gray-700 cqa-text-sm\">\n While\n </span>\n <span class=\"cqa-text-gray-900 cqa-text-sm\" [innerHTML]=\"getConditionDisplay()\"></span>\n </div>\n\n <!-- Steps Summary -->\n <div\n class=\"cqa-ml-auto cqa-border cqa-border-solid cqa-border-[#E5E5E5] cqa-rounded-lg cqa-py-0.5 cqa-px-2 cqa-text-[#0A0A0A] cqa-text-[12px] cqa-leading-[15px]\">\n {{ getStepsSummary() }}\n </div>\n\n <!-- Action Icons: Edit, Link, Duplicate, Delete (show on hover) -->\n <div class=\"step-actions cqa-flex cqa-items-center cqa-gap-3 cqa-px-[7px]\">\n <button type=\"button\" (click)=\"onEdit(); $event.stopPropagation()\" title=\"Edit\"\n class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7 11.6666H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path\n d=\"M9.55208 2.1128C9.7843 1.88058 10.0993 1.75012 10.4277 1.75012C10.7561 1.75012 11.071 1.88058 11.3033 2.1128C11.5355 2.34502 11.6659 2.65998 11.6659 2.98838C11.6659 3.31679 11.5355 3.63175 11.3033 3.86397L4.29742 10.8704C4.15864 11.0092 3.9871 11.1107 3.79867 11.1656L2.12333 11.6544C2.07314 11.669 2.01993 11.6699 1.96928 11.6569C1.91863 11.6439 1.8724 11.6176 1.83543 11.5806C1.79846 11.5437 1.7721 11.4974 1.75913 11.4468C1.74615 11.3961 1.74703 11.3429 1.76167 11.2927L2.2505 9.61738C2.30546 9.42916 2.40698 9.25783 2.54567 9.11922L9.55208 2.1128Z\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </button>\n <button type=\"button\" (click)=\"onLink(); $event.stopPropagation()\" title=\"Link\"\n class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M5.00065 9.91671H3.66732C2.78326 9.91671 1.93542 9.60942 1.3103 9.06244C0.685174 8.51545 0.333984 7.77359 0.333984 7.00004C0.333984 6.22649 0.685174 5.48463 1.3103 4.93765C1.93542 4.39066 2.78326 4.08337 3.66732 4.08337H5.00065\"\n stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M9 4.08337H10.3333C11.2174 4.08337 12.0652 4.39066 12.6904 4.93765C13.3155 5.48463 13.6667 6.22649 13.6667 7.00004C13.6667 7.77359 13.3155 8.51545 12.6904 9.06244C12.0652 9.60942 11.2174 9.91671 10.3333 9.91671H9\"\n stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M4.33398 7H9.66732\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n <button type=\"button\" (click)=\"onDuplicate(); $event.stopPropagation()\" title=\"Duplicate\"\n class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M11.666 4.66663H5.83268C5.18835 4.66663 4.66602 5.18896 4.66602 5.83329V11.6666C4.66602 12.311 5.18835 12.8333 5.83268 12.8333H11.666C12.3103 12.8333 12.8327 12.311 12.8327 11.6666V5.83329C12.8327 5.18896 12.3103 4.66663 11.666 4.66663Z\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M2.33268 9.33329C1.69102 9.33329 1.16602 8.80829 1.16602 8.16663V2.33329C1.16602 1.69163 1.69102 1.16663 2.33268 1.16663H8.16602C8.80768 1.16663 9.33268 1.69163 9.33268 2.33329\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </button>\n <button type=\"button\" (click)=\"onDelete(); $event.stopPropagation()\" title=\"Delete\"\n class=\"cqa-p-0 cqa-text-[#ff6467] hover:cqa-text-[#C63535]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1.75 3.5H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path\n d=\"M11.0827 3.5V11.6667C11.0827 12.25 10.4993 12.8333 9.91602 12.8333H4.08268C3.49935 12.8333 2.91602 12.25 2.91602 11.6667V3.5\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M4.66602 3.49996V2.33329C4.66602 1.74996 5.24935 1.16663 5.83268 1.16663H8.16602C8.74935 1.16663 9.33268 1.74996 9.33268 2.33329V3.49996\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M5.83398 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M8.16602 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n </div>\n </div>\n\n <!-- Expanded Content with Nested Steps (renderer dispatches by step type, n-level nesting) -->\n <div *ngIf=\"expanded\" class=\"cqa-flex cqa-flex-col\">\n <div *ngIf=\"!isReorder\" class=\"cqa-flex cqa-flex-col\">\n <cqa-test-case-details-renderer *ngFor=\"let step of nestedSteps; let i = index\" [step]=\"step\" [index]=\"i\"\n [isNested]=\"true\" [isInsideLoop]=\"true\" [isReorder]=\"isReorder\" (nestedStepChange)=\"onNestedStepChange($event.step, $event.index)\"\n (addStep)=\"onAddStep()\" (deleteStep)=\"onDeleteStep($event)\"\n (toggleExpanded)=\"onNestedToggleExpanded($event, step, i)\"\n (groupNameChange)=\"$any(step).groupName = $event; onNestedStepChange(step, i)\"\n (descriptionChange)=\"$any(step).description = $event; onNestedStepChange(step, i)\"\n (reusableChange)=\"$any(step).reusable = $event; onNestedStepChange(step, i)\"\n (openExternal)=\"onNestedStepChange(step, i)\" (edit)=\"onNestedStepChange(step, i)\"\n (link)=\"onNestedStepChange(step, i)\" (duplicate)=\"onNestedStepChange(step, i)\" (delete)=\"onDeleteStep(i)\"\n (conditionChange)=\"$any(step).condition = $event; onNestedStepChange(step, i)\"\n (branchStepChange)=\"onNestedStepChange(step, i)\" (addBranch)=\"onNestedConditionAddBranch($any(step), i)\"\n (deleteBranch)=\"onNestedConditionDeleteBranch($any(step), $event, i)\"\n (testDataProfileChange)=\"$any(step).testDataProfile = $event; onNestedStepChange(step, i)\"\n (startStepChange)=\"$any(step).startStep = $event; onNestedStepChange(step, i)\"\n (endStepChange)=\"$any(step).endStep = $event; onNestedStepChange(step, i)\"\n (maxIterationsChange)=\"$any(step).maxIterations = $event; onNestedStepChange(step, i)\"\n (eventTypeChange)=\"$any(step).eventType = $event; onNestedStepChange(step, i)\"\n (parameterChange)=\"onNestedStepChange(step, i)\"\n (selectionChange)=\"$any(step).selected = $event; onNestedStepChange(step, i)\"\n (dndDropInZone)=\"dndDropInZone.emit($event)\">\n </cqa-test-case-details-renderer>\n </div>\n <div *ngIf=\"isReorder\" class=\"cqa-flex cqa-flex-col nested-step-drop-list\"\n [dndDropzone]=\"['step']\"\n dndEffectAllowed=\"move\"\n dndDragoverClass=\"dndDragover\"\n (dndDrop)=\"onDndDrop($event)\">\n <div dndPlaceholderRef class=\"step-drag-placeholder-nested cqa-my-1 cqa-min-h-[50px] cqa-border-2 cqa-border-dashed cqa-border-[#3F43EE] cqa-rounded cqa-bg-[rgba(63,67,238,0.08)] cqa-flex cqa-items-center cqa-justify-center cqa-text-[#3F43EE] cqa-text-xs\">Drop here</div>\n <div *ngFor=\"let step of nestedSteps; let i = index\" class=\"nested-step-drag-item\"\n [dndDraggable]=\"step\"\n dndEffectAllowed=\"move\"\n dndType=\"step\">\n <cqa-test-case-details-renderer [step]=\"step\" [index]=\"i\"\n [isNested]=\"true\" [isInsideLoop]=\"true\" [isReorder]=\"isReorder\"\n (nestedStepChange)=\"onNestedStepChange($event.step, $event.index)\"\n (addStep)=\"onAddStep()\" (deleteStep)=\"onDeleteStep($event)\"\n (toggleExpanded)=\"onNestedToggleExpanded($event, step, i)\"\n (groupNameChange)=\"$any(step).groupName = $event; onNestedStepChange(step, i)\"\n (descriptionChange)=\"$any(step).description = $event; onNestedStepChange(step, i)\"\n (reusableChange)=\"$any(step).reusable = $event; onNestedStepChange(step, i)\"\n (openExternal)=\"onNestedStepChange(step, i)\" (edit)=\"onNestedStepChange(step, i)\"\n (link)=\"onNestedStepChange(step, i)\" (duplicate)=\"onNestedStepChange(step, i)\" (delete)=\"onDeleteStep(i)\"\n (conditionChange)=\"$any(step).condition = $event; onNestedStepChange(step, i)\"\n (branchStepChange)=\"onNestedStepChange(step, i)\" (addBranch)=\"onNestedConditionAddBranch($any(step), i)\"\n (deleteBranch)=\"onNestedConditionDeleteBranch($any(step), $event, i)\"\n (testDataProfileChange)=\"$any(step).testDataProfile = $event; onNestedStepChange(step, i)\"\n (startStepChange)=\"$any(step).startStep = $event; onNestedStepChange(step, i)\"\n (endStepChange)=\"$any(step).endStep = $event; onNestedStepChange(step, i)\"\n (maxIterationsChange)=\"$any(step).maxIterations = $event; onNestedStepChange(step, i)\"\n (eventTypeChange)=\"$any(step).eventType = $event; onNestedStepChange(step, i)\"\n (parameterChange)=\"onNestedStepChange(step, i)\"\n (selectionChange)=\"$any(step).selected = $event; onNestedStepChange(step, i)\"\n (dndDropInZone)=\"dndDropInZone.emit($event)\">\n </cqa-test-case-details-renderer>\n </div>\n </div>\n\n <!-- END Marker -->\n <div\n [class]=\"'cqa-pl-4 cqa-py-1 cqa-bg-[#DBEAFE80] cqa-text-[#1C398E] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium'\"\n style=\"border-top: 1px solid #BEDBFF;\">\n {{ getEndLabel() }}\n </div>\n </div>\n</div>", styles: [".step-actions{opacity:0;transition:opacity .15s ease}.step-row:hover .step-actions{opacity:1}\n"], components: [{ type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore"] }, { type: CustomInputComponent, selector: "cqa-custom-input", inputs: ["label", "type", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "inputInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused", "enterPressed"] }, { type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }, { type: TestCaseDetailsRendererComponent, selector: "cqa-test-case-details-renderer", inputs: ["step", "index", "isNested", "isInsideLoop", "branch", "isReorder", "addStepBetween"], outputs: ["nestedStepChange", "addStep", "deleteStep", "toggleExpanded", "groupNameChange", "descriptionChange", "reusableChange", "openExternal", "edit", "link", "duplicate", "delete", "viewDetails", "selectionChange", "conditionChange", "branchStepChange", "addStepForBranch", "deleteStepWithBranch", "addBranch", "deleteBranch", "testDataProfileChange", "startStepChange", "endStepChange", "maxIterationsChange", "eventTypeChange", "parameterChange", "clickAction", "dndDropInZone", "addStepBetweenClick"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i7.DndDropzoneDirective, selector: "[dndDropzone]", inputs: ["dndDropzone", "dndEffectAllowed", "dndAllowExternal", "dndHorizontal", "dndDragoverClass", "dndDropzoneDisabledClass", "dndDisableIf", "dndDisableDropIf"], outputs: ["dndDragover", "dndDrop"] }, { type: i7.DndPlaceholderRefDirective, selector: "[dndPlaceholderRef]" }, { type: i7.DndDraggableDirective, selector: "[dndDraggable]", inputs: ["dndDraggable", "dndEffectAllowed", "dndType", "dndDraggingClass", "dndDraggingSourceClass", "dndDraggableDisabledClass", "dndDragImageOffsetFunction", "dndDisableIf", "dndDisableDragIf"], outputs: ["dndStart", "dndDrag", "dndEnd", "dndMoved", "dndCopied", "dndLinked", "dndCanceled"] }] });
17900
17793
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestCaseLoopStepComponent, decorators: [{
17901
17794
  type: Component,
17902
17795
  args: [{ selector: 'cqa-test-case-loop-step', host: { class: 'cqa-ui-root' }, styles: [STEP_ROW_ACTIONS_STYLES], template: "<div class=\"cqa-flex cqa-flex-col\">\n <!-- Inline Edit Mode: Frame 2147224910 - flex row, 1056\u00D736, gap 12px, flex-none -->\n <div *ngIf=\"isEditing\" class=\"cqa-py-2.5 cqa-px-4 cqa-flex cqa-items-center cqa-gap-3 cqa-justify-between\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-flex-grow\">\n <!-- Loop Type Label -->\n <div class=\"cqa-font-semibold cqa-text-[#1C398E] cqa-text-[12px] cqa-leading-[15px]\">\n {{ getLoopTypeLabel() }}\n </div>\n\n <!-- FOR LOOP inline edit: cqa-dynamic-select (same usage as default stories) -->\n <ng-container *ngIf=\"loopType === 'for'\">\n <!-- First select: width 216.25px, height 36px, gap 4px, opacity 1 -->\n <cqa-dynamic-select [form]=\"editForm\" [config]=\"forOptionTypeSelectConfig\"\n class=\"cqa-w-full cqa-max-w-[216px]\"></cqa-dynamic-select>\n <cqa-custom-input [value]=\"editForm.get('testDataProfile')?.value ?? ''\"\n (valueChange)=\"onEditFormFieldChange('testDataProfile', $event)\" placeholder=\"Testdataprofile\"\n class=\"cqa-w-full cqa-max-w-[216px]\" size=\"sm\">\n </cqa-custom-input>\n <cqa-dynamic-select [form]=\"editForm\" [config]=\"startStepSelectConfig\"\n class=\"cqa-w-full cqa-max-w-[216px]\"></cqa-dynamic-select>\n <cqa-dynamic-select [form]=\"editForm\" [config]=\"endStepSelectConfig\"\n class=\"cqa-w-full cqa-max-w-[216px]\"></cqa-dynamic-select>\n </ng-container>\n\n <!-- WHILE LOOP inline edit -->\n <ng-container *ngIf=\"isWhileLoop()\">\n <cqa-custom-input [value]=\"editForm.get('condition')?.value ?? ''\" class=\"cqa-w-full cqa-max-w-[216px]\"\n (valueChange)=\"onEditFormFieldChange('condition', $event)\" placeholder='element \".selector\" exists' size=\"sm\">\n </cqa-custom-input>\n </ng-container>\n\n <!-- Edit In depth link -->\n <a href=\"#\" (click)=\"onEditInDepth(); $event.preventDefault()\"\n class=\"cqa-text-[#3F43EE] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-flex cqa-items-center cqa-gap-[2px] cqa-no-underline\">\n Edit In depth\n <svg width=\"8\" height=\"8\" viewBox=\"0 0 8 8\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M2.03809 6.74329L2.62809 7.33329L5.96142 3.99996L2.62809 0.666626L2.03809 1.25663L4.78142 3.99996L2.03809 6.74329Z\"\n fill=\"#3F43EE\" />\n </svg>\n </a>\n </div>\n\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <!-- Cancel / Apply -->\n <cqa-button variant=\"outlined\" btnSize=\"lg\" [customClass]=\"'cqa-text-[14px] cqa-py-[9px]'\" [text]=\"'Cancel'\"\n (clicked)=\"onEditCancel()\"></cqa-button>\n <cqa-button variant=\"filled\" btnSize=\"lg\" [customClass]=\"'cqa-text-[14px] cqa-py-[9px]'\" [text]=\"'Apply'\"\n (clicked)=\"onEditApply()\"></cqa-button>\n </div>\n </div>\n\n <!-- Loop Header (normal view when not editing) -->\n <div *ngIf=\"!isEditing\"\n [class]=\"'step-row cqa-flex cqa-items-center cqa-gap-3 cqa-py-2 ' + (isInsideLoop ? 'cqa-pl-10 cqa-pr-4' : 'cqa-px-4')\">\n <!-- Expand/Collapse Icon -->\n <button type=\"button\" (click)=\"onToggleExpanded()\" class=\"cqa-p-0\">\n <svg [class.cqa-rotate-180]=\"!expanded\" class=\"cqa-transition-transform\" width=\"16\" height=\"16\"\n viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M12 10L8 6L4 10\" stroke=\"#6B7280\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n\n <!-- Loop Icon -->\n <div *ngIf=\"loopType === 'for'\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M11.334 1.33325L14.0007 3.99992L11.334 6.66659\" stroke=\"#1C398E\" stroke-width=\"1.33333\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M2 7.33333V6.66667C2 5.95942 2.28095 5.28115 2.78105 4.78105C3.28115 4.28095 3.95942 4 4.66667 4H14\"\n stroke=\"#1C398E\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M4.66667 14.6666L2 11.9999L4.66667 9.33325\" stroke=\"#1C398E\" stroke-width=\"1.33333\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M14 8.66675V9.33341C14 10.0407 13.719 10.7189 13.219 11.219C12.7189 11.7191 12.0406 12.0001 11.3333 12.0001H2\"\n stroke=\"#1C398E\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </div>\n <div *ngIf=\"loopType === 'while'\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M11.334 1.33325L14.0007 3.99992L11.334 6.66659\" stroke=\"#59168B\" stroke-width=\"1.33333\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M2 7.33333V6.66667C2 5.95942 2.28095 5.28115 2.78105 4.78105C3.28115 4.28095 3.95942 4 4.66667 4H14\"\n stroke=\"#59168B\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M4.66667 14.6666L2 11.9999L4.66667 9.33325\" stroke=\"#59168B\" stroke-width=\"1.33333\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M14 8.66675V9.33341C14 10.0407 13.719 10.7189 13.219 11.219C12.7189 11.7191 12.0406 12.0001 11.3333 12.0001H2\"\n stroke=\"#59168B\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </div>\n\n <!-- Loop Type Label -->\n <span class=\"cqa-font-semibold cqa-text-[#1C398E] cqa-text-[12px] cqa-leading-none\">\n {{ getLoopTypeLabel() }}\n </span>\n\n <!-- For Loop Controls -->\n <div *ngIf=\"loopType === 'for'\" class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-ml-2\">\n <!-- Test Data Profile Button -->\n <button type=\"button\" [class.cqa-bg-primary-100]=\"testDataProfile\" [class.cqa-text-primary]=\"testDataProfile\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ getTestDataProfileLabel() }}\n </button>\n\n <!-- Start Button -->\n <button type=\"button\" [class.cqa-bg-primary-100]=\"startStep\" [class.cqa-text-primary]=\"startStep\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ getStartStepLabel() }}\n </button>\n\n <!-- End Button -->\n <button type=\"button\" [class.cqa-bg-primary-100]=\"endStep\" [class.cqa-text-primary]=\"endStep\"\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">\n {{ getEndStepLabel() }}\n </button>\n </div>\n\n <!-- While Loop Condition (only show if condition exists) -->\n <div *ngIf=\"isWhileLoop() && condition\" class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-ml-2 cqa-flex-1\">\n <span class=\"cqa-text-gray-700 cqa-text-sm\">\n While\n </span>\n <span class=\"cqa-text-gray-900 cqa-text-sm\" [innerHTML]=\"getConditionDisplay()\"></span>\n </div>\n\n <!-- Steps Summary -->\n <div\n class=\"cqa-ml-auto cqa-border cqa-border-solid cqa-border-[#E5E5E5] cqa-rounded-lg cqa-py-0.5 cqa-px-2 cqa-text-[#0A0A0A] cqa-text-[12px] cqa-leading-[15px]\">\n {{ getStepsSummary() }}\n </div>\n\n <!-- Action Icons: Edit, Link, Duplicate, Delete (show on hover) -->\n <div class=\"step-actions cqa-flex cqa-items-center cqa-gap-3 cqa-px-[7px]\">\n <button type=\"button\" (click)=\"onEdit(); $event.stopPropagation()\" title=\"Edit\"\n class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7 11.6666H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path\n d=\"M9.55208 2.1128C9.7843 1.88058 10.0993 1.75012 10.4277 1.75012C10.7561 1.75012 11.071 1.88058 11.3033 2.1128C11.5355 2.34502 11.6659 2.65998 11.6659 2.98838C11.6659 3.31679 11.5355 3.63175 11.3033 3.86397L4.29742 10.8704C4.15864 11.0092 3.9871 11.1107 3.79867 11.1656L2.12333 11.6544C2.07314 11.669 2.01993 11.6699 1.96928 11.6569C1.91863 11.6439 1.8724 11.6176 1.83543 11.5806C1.79846 11.5437 1.7721 11.4974 1.75913 11.4468C1.74615 11.3961 1.74703 11.3429 1.76167 11.2927L2.2505 9.61738C2.30546 9.42916 2.40698 9.25783 2.54567 9.11922L9.55208 2.1128Z\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </button>\n <button type=\"button\" (click)=\"onLink(); $event.stopPropagation()\" title=\"Link\"\n class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M5.00065 9.91671H3.66732C2.78326 9.91671 1.93542 9.60942 1.3103 9.06244C0.685174 8.51545 0.333984 7.77359 0.333984 7.00004C0.333984 6.22649 0.685174 5.48463 1.3103 4.93765C1.93542 4.39066 2.78326 4.08337 3.66732 4.08337H5.00065\"\n stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M9 4.08337H10.3333C11.2174 4.08337 12.0652 4.39066 12.6904 4.93765C13.3155 5.48463 13.6667 6.22649 13.6667 7.00004C13.6667 7.77359 13.3155 8.51545 12.6904 9.06244C12.0652 9.60942 11.2174 9.91671 10.3333 9.91671H9\"\n stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M4.33398 7H9.66732\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n <button type=\"button\" (click)=\"onDuplicate(); $event.stopPropagation()\" title=\"Duplicate\"\n class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M11.666 4.66663H5.83268C5.18835 4.66663 4.66602 5.18896 4.66602 5.83329V11.6666C4.66602 12.311 5.18835 12.8333 5.83268 12.8333H11.666C12.3103 12.8333 12.8327 12.311 12.8327 11.6666V5.83329C12.8327 5.18896 12.3103 4.66663 11.666 4.66663Z\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M2.33268 9.33329C1.69102 9.33329 1.16602 8.80829 1.16602 8.16663V2.33329C1.16602 1.69163 1.69102 1.16663 2.33268 1.16663H8.16602C8.80768 1.16663 9.33268 1.69163 9.33268 2.33329\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </button>\n <button type=\"button\" (click)=\"onDelete(); $event.stopPropagation()\" title=\"Delete\"\n class=\"cqa-p-0 cqa-text-[#ff6467] hover:cqa-text-[#C63535]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1.75 3.5H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path\n d=\"M11.0827 3.5V11.6667C11.0827 12.25 10.4993 12.8333 9.91602 12.8333H4.08268C3.49935 12.8333 2.91602 12.25 2.91602 11.6667V3.5\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M4.66602 3.49996V2.33329C4.66602 1.74996 5.24935 1.16663 5.83268 1.16663H8.16602C8.74935 1.16663 9.33268 1.74996 9.33268 2.33329V3.49996\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M5.83398 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M8.16602 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n </div>\n </div>\n\n <!-- Expanded Content with Nested Steps (renderer dispatches by step type, n-level nesting) -->\n <div *ngIf=\"expanded\" class=\"cqa-flex cqa-flex-col\">\n <div *ngIf=\"!isReorder\" class=\"cqa-flex cqa-flex-col\">\n <cqa-test-case-details-renderer *ngFor=\"let step of nestedSteps; let i = index\" [step]=\"step\" [index]=\"i\"\n [isNested]=\"true\" [isInsideLoop]=\"true\" [isReorder]=\"isReorder\" (nestedStepChange)=\"onNestedStepChange($event.step, $event.index)\"\n (addStep)=\"onAddStep()\" (deleteStep)=\"onDeleteStep($event)\"\n (toggleExpanded)=\"onNestedToggleExpanded($event, step, i)\"\n (groupNameChange)=\"$any(step).groupName = $event; onNestedStepChange(step, i)\"\n (descriptionChange)=\"$any(step).description = $event; onNestedStepChange(step, i)\"\n (reusableChange)=\"$any(step).reusable = $event; onNestedStepChange(step, i)\"\n (openExternal)=\"onNestedStepChange(step, i)\" (edit)=\"onNestedStepChange(step, i)\"\n (link)=\"onNestedStepChange(step, i)\" (duplicate)=\"onNestedStepChange(step, i)\" (delete)=\"onDeleteStep(i)\"\n (conditionChange)=\"$any(step).condition = $event; onNestedStepChange(step, i)\"\n (branchStepChange)=\"onNestedStepChange(step, i)\" (addBranch)=\"onNestedConditionAddBranch($any(step), i)\"\n (deleteBranch)=\"onNestedConditionDeleteBranch($any(step), $event, i)\"\n (testDataProfileChange)=\"$any(step).testDataProfile = $event; onNestedStepChange(step, i)\"\n (startStepChange)=\"$any(step).startStep = $event; onNestedStepChange(step, i)\"\n (endStepChange)=\"$any(step).endStep = $event; onNestedStepChange(step, i)\"\n (maxIterationsChange)=\"$any(step).maxIterations = $event; onNestedStepChange(step, i)\"\n (eventTypeChange)=\"$any(step).eventType = $event; onNestedStepChange(step, i)\"\n (parameterChange)=\"onNestedStepChange(step, i)\"\n (selectionChange)=\"$any(step).selected = $event; onNestedStepChange(step, i)\"\n (dndDropInZone)=\"dndDropInZone.emit($event)\">\n </cqa-test-case-details-renderer>\n </div>\n <div *ngIf=\"isReorder\" class=\"cqa-flex cqa-flex-col nested-step-drop-list\"\n [dndDropzone]=\"['step']\"\n dndEffectAllowed=\"move\"\n dndDragoverClass=\"dndDragover\"\n (dndDrop)=\"onDndDrop($event)\">\n <div dndPlaceholderRef class=\"step-drag-placeholder-nested cqa-my-1 cqa-min-h-[50px] cqa-border-2 cqa-border-dashed cqa-border-[#3F43EE] cqa-rounded cqa-bg-[rgba(63,67,238,0.08)] cqa-flex cqa-items-center cqa-justify-center cqa-text-[#3F43EE] cqa-text-xs\">Drop here</div>\n <div *ngFor=\"let step of nestedSteps; let i = index\" class=\"nested-step-drag-item\"\n [dndDraggable]=\"step\"\n dndEffectAllowed=\"move\"\n dndType=\"step\">\n <cqa-test-case-details-renderer [step]=\"step\" [index]=\"i\"\n [isNested]=\"true\" [isInsideLoop]=\"true\" [isReorder]=\"isReorder\"\n (nestedStepChange)=\"onNestedStepChange($event.step, $event.index)\"\n (addStep)=\"onAddStep()\" (deleteStep)=\"onDeleteStep($event)\"\n (toggleExpanded)=\"onNestedToggleExpanded($event, step, i)\"\n (groupNameChange)=\"$any(step).groupName = $event; onNestedStepChange(step, i)\"\n (descriptionChange)=\"$any(step).description = $event; onNestedStepChange(step, i)\"\n (reusableChange)=\"$any(step).reusable = $event; onNestedStepChange(step, i)\"\n (openExternal)=\"onNestedStepChange(step, i)\" (edit)=\"onNestedStepChange(step, i)\"\n (link)=\"onNestedStepChange(step, i)\" (duplicate)=\"onNestedStepChange(step, i)\" (delete)=\"onDeleteStep(i)\"\n (conditionChange)=\"$any(step).condition = $event; onNestedStepChange(step, i)\"\n (branchStepChange)=\"onNestedStepChange(step, i)\" (addBranch)=\"onNestedConditionAddBranch($any(step), i)\"\n (deleteBranch)=\"onNestedConditionDeleteBranch($any(step), $event, i)\"\n (testDataProfileChange)=\"$any(step).testDataProfile = $event; onNestedStepChange(step, i)\"\n (startStepChange)=\"$any(step).startStep = $event; onNestedStepChange(step, i)\"\n (endStepChange)=\"$any(step).endStep = $event; onNestedStepChange(step, i)\"\n (maxIterationsChange)=\"$any(step).maxIterations = $event; onNestedStepChange(step, i)\"\n (eventTypeChange)=\"$any(step).eventType = $event; onNestedStepChange(step, i)\"\n (parameterChange)=\"onNestedStepChange(step, i)\"\n (selectionChange)=\"$any(step).selected = $event; onNestedStepChange(step, i)\"\n (dndDropInZone)=\"dndDropInZone.emit($event)\">\n </cqa-test-case-details-renderer>\n </div>\n </div>\n\n <!-- END Marker -->\n <div\n [class]=\"'cqa-pl-4 cqa-py-1 cqa-bg-[#DBEAFE80] cqa-text-[#1C398E] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium'\"\n style=\"border-top: 1px solid #BEDBFF;\">\n {{ getEndLabel() }}\n </div>\n </div>\n</div>" }]
@@ -18207,7 +18100,7 @@ class TestCaseConditionStepComponent {
18207
18100
  }
18208
18101
  }
18209
18102
  TestCaseConditionStepComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestCaseConditionStepComponent, deps: [{ token: i2$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
18210
- TestCaseConditionStepComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TestCaseConditionStepComponent, selector: "cqa-test-case-condition-step", inputs: { config: "config", id: "id", stepNumber: "stepNumber", condition: "condition", branches: "branches", expanded: "expanded", isNested: "isNested", isInsideLoop: "isInsideLoop", isReorder: "isReorder" }, outputs: { toggleExpanded: "toggleExpanded", conditionChange: "conditionChange", branchStepChange: "branchStepChange", addStep: "addStep", deleteStep: "deleteStep", addBranch: "addBranch", deleteBranch: "deleteBranch", duplicate: "duplicate", delete: "delete", moreOptions: "moreOptions", dndDropInZone: "dndDropInZone" }, host: { classAttribute: "cqa-ui-root" }, ngImport: i0, template: "<div [class]=\"'cqa-flex cqa-flex-col cqa-border cqa-border-solid cqa-border-[#E5E7EB] ' + (isNested ? ' cqa-pl-[24px]' : '')\">\n <!-- Inline Edit Mode: CONDITION tag, three fields, IF/ELSE chips, Edit In depth, Cancel/Apply -->\n <div *ngIf=\"isEditing\" class=\"cqa-py-2.5 cqa-px-4 cqa-flex cqa-items-center cqa-gap-3 cqa-justify-between\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-flex-grow\">\n <!-- CONDITION Tag (orange) -->\n <span class=\"cqa-px-1.5 cqa-rounded-md cqa-text-[#EA580C] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-bg-[#FFEDD5]\">\n CONDITION\n </span>\n\n <!-- First field: left operand (e.g. Usertype) -->\n <cqa-custom-input\n [value]=\"editForm.get('conditionLeft')?.value ?? ''\"\n (valueChange)=\"onEditFormFieldChange('conditionLeft', $event)\"\n placeholder=\"Usertype\"\n class=\"cqa-w-full cqa-max-w-[216px]\"\n size=\"sm\">\n </cqa-custom-input>\n\n <!-- Operator: dynamic-select (IS, IS NOT, etc.) -->\n <cqa-dynamic-select [form]=\"editForm\" [config]=\"operatorSelectConfig\" class=\"cqa-w-full cqa-max-w-[216px]\"></cqa-dynamic-select>\n\n <!-- Third field: right operand (e.g. Premium) -->\n <cqa-custom-input\n [value]=\"editForm.get('conditionRight')?.value ?? ''\"\n (valueChange)=\"onEditFormFieldChange('conditionRight', $event)\"\n placeholder=\"Premium\"\n class=\"cqa-w-full cqa-max-w-[216px]\"\n size=\"sm\">\n </cqa-custom-input>\n\n <!-- IF / ELSE indicators -->\n <span class=\"cqa-px-2 cqa-py-[2px] cqa-rounded-[4px] cqa-text-[8px] cqa-leading-[12px] cqa-bg-[#DCFCE7] cqa-text-[#008236] cqa-border cqa-border-solid cqa-border-[#B9F8CF] cqa-flex cqa-items-center cqa-gap-1.5\">\n <svg width=\"8\" height=\"8\" viewBox=\"0 0 8 8\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M6.66634 2L2.99967 5.66667L1.33301 4\" stroke=\"#008236\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n IF\n </span>\n <span class=\"cqa-px-2 cqa-py-[2px] cqa-rounded-[4px] cqa-text-[8px] cqa-leading-[12px] cqa-bg-[#F3F4F6] cqa-text-[#99A1AF] cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-flex cqa-items-center cqa-gap-1.5\">\n Add ELSE\n </span>\n\n <!-- Edit In depth link -->\n <a href=\"#\" (click)=\"onEditInDepth(); $event.preventDefault()\"\n class=\"cqa-text-[#3F43EE] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-flex cqa-items-center cqa-gap-[2px] cqa-no-underline\">\n Edit In depth\n <svg width=\"8\" height=\"8\" viewBox=\"0 0 8 8\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2.03809 6.74329L2.62809 7.33329L5.96142 3.99996L2.62809 0.666626L2.03809 1.25663L4.78142 3.99996L2.03809 6.74329Z\" fill=\"#3F43EE\"/></svg>\n </a> \n </div>\n <!-- Cancel / Apply -->\n <cqa-button variant=\"outlined\" btnSize=\"lg\" [customClass]=\"'cqa-text-[14px] cqa-py-[9px]'\" [text]=\"'Cancel'\" (clicked)=\"onEditCancel()\"></cqa-button>\n <cqa-button variant=\"filled\" btnSize=\"lg\" [customClass]=\"'cqa-text-[14px] cqa-py-[9px]'\" [text]=\"'Apply'\" (clicked)=\"onEditApply()\"></cqa-button>\n </div>\n\n <!-- Condition Header (normal view when not editing) -->\n <div *ngIf=\"!isEditing\" [class]=\"'step-row cqa-flex cqa-items-center cqa-gap-3 cqa-py-2 ' + (isInsideLoop ? 'cqa-pl-10 cqa-pr-4' : 'cqa-px-4')\">\n <!-- Expand/Collapse Icon -->\n <button type=\"button\" (click)=\"onToggleExpanded()\" class=\"cqa-p-0\">\n <svg [class.cqa-rotate-180]=\"!expanded\" class=\"cqa-transition-transform\" width=\"16\" height=\"16\"\n viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M12 10L8 6L4 10\" stroke=\"#6B7280\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n\n <!-- IF/ELSE Icon -->\n <div><svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 2V10\" stroke=\"#7B3306\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M12 6C13.1046 6 14 5.10457 14 4C14 2.89543 13.1046 2 12 2C10.8954 2 10 2.89543 10 4C10 5.10457 10.8954 6 12 6Z\"\n stroke=\"#7B3306\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M4 14C5.10457 14 6 13.1046 6 12C6 10.8954 5.10457 10 4 10C2.89543 10 2 10.8954 2 12C2 13.1046 2.89543 14 4 14Z\"\n stroke=\"#7B3306\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M12 6C12 7.5913 11.3679 9.11742 10.2426 10.2426C9.11742 11.3679 7.5913 12 6 12\" stroke=\"#7B3306\"\n stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg></div>\n\n <!-- IF/ELSE Label -->\n <span class=\"cqa-font-semibold cqa-text-[#7B3306] cqa-text-[12px] cqa-leading-none\">\n IF / ELSE\n </span>\n\n <!-- Condition Input -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-ml-2 cqa-flex-1\">\n <span [innerHTML]=\"condition\"></span>\n <!-- <span class=\"cqa-text-[#6B7280] cqa-text-[14px] cqa-leading-[18px]\">\n If\n </span>\n <span\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">.success-message</span>\n <span class=\"cqa-text-[#6B7280] cqa-text-[14px] cqa-leading-[18px]\">\n is visible\n </span> -->\n <!-- <input\n type=\"text\"\n [value]=\"condition\"\n (input)=\"onConditionChange($any($event.target).value)\"\n placeholder=\"element `.success-message` is visible\"\n class=\"cqa-px-3 cqa-py-1.5 cqa-rounded-lg cqa-border cqa-border-gray-300 cqa-bg-white cqa-text-gray-900 cqa-text-sm cqa-flex-1 cqa-max-w-md cqa-outline-none focus:cqa-ring-2 focus:cqa-ring-primary focus:cqa-ring-opacity-50\"\n /> -->\n </div>\n\n <!-- Steps Summary -->\n <div\n class=\"cqa-ml-auto cqa-border cqa-border-solid cqa-border-[#E5E5E5] cqa-rounded-lg cqa-py-0.5 cqa-px-2 cqa-text-[#0A0A0A] cqa-text-[12px] cqa-leading-[15px]\">\n {{ getStepsSummary() }}\n </div>\n\n <!-- Action Icons: Edit, Link, Duplicate, Delete (show on hover) -->\n <div class=\"step-actions cqa-flex cqa-items-center cqa-gap-3 cqa-px-[7px]\">\n <button type=\"button\" (click)=\"onEdit(); $event.stopPropagation()\" title=\"Edit\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M7 11.6666H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M9.55208 2.1128C9.7843 1.88058 10.0993 1.75012 10.4277 1.75012C10.7561 1.75012 11.071 1.88058 11.3033 2.1128C11.5355 2.34502 11.6659 2.65998 11.6659 2.98838C11.6659 3.31679 11.5355 3.63175 11.3033 3.86397L4.29742 10.8704C4.15864 11.0092 3.9871 11.1107 3.79867 11.1656L2.12333 11.6544C2.07314 11.669 2.01993 11.6699 1.96928 11.6569C1.91863 11.6439 1.8724 11.6176 1.83543 11.5806C1.79846 11.5437 1.7721 11.4974 1.75913 11.4468C1.74615 11.3961 1.74703 11.3429 1.76167 11.2927L2.2505 9.61738C2.30546 9.42916 2.40698 9.25783 2.54567 9.11922L9.55208 2.1128Z\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n <button type=\"button\" (click)=\"onLink(); $event.stopPropagation()\" title=\"Link\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M5.00065 9.91671H3.66732C2.78326 9.91671 1.93542 9.60942 1.3103 9.06244C0.685174 8.51545 0.333984 7.77359 0.333984 7.00004C0.333984 6.22649 0.685174 5.48463 1.3103 4.93765C1.93542 4.39066 2.78326 4.08337 3.66732 4.08337H5.00065\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M9 4.08337H10.3333C11.2174 4.08337 12.0652 4.39066 12.6904 4.93765C13.3155 5.48463 13.6667 6.22649 13.6667 7.00004C13.6667 7.77359 13.3155 8.51545 12.6904 9.06244C12.0652 9.60942 11.2174 9.91671 10.3333 9.91671H9\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M4.33398 7H9.66732\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n <button type=\"button\" (click)=\"onDuplicate(); $event.stopPropagation()\" title=\"Duplicate\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M11.666 4.66663H5.83268C5.18835 4.66663 4.66602 5.18896 4.66602 5.83329V11.6666C4.66602 12.311 5.18835 12.8333 5.83268 12.8333H11.666C12.3103 12.8333 12.8327 12.311 12.8327 11.6666V5.83329C12.8327 5.18896 12.3103 4.66663 11.666 4.66663Z\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M2.33268 9.33329C1.69102 9.33329 1.16602 8.80829 1.16602 8.16663V2.33329C1.16602 1.69163 1.69102 1.16663 2.33268 1.16663H8.16602C8.80768 1.16663 9.33268 1.69163 9.33268 2.33329\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n <button type=\"button\" (click)=\"onDelete(); $event.stopPropagation()\" title=\"Delete\" class=\"cqa-p-0 cqa-text-[#ff6467] hover:cqa-text-[#C63535]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M1.75 3.5H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M11.0827 3.5V11.6667C11.0827 12.25 10.4993 12.8333 9.91602 12.8333H4.08268C3.49935 12.8333 2.91602 12.25 2.91602 11.6667V3.5\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M4.66602 3.49996V2.33329C4.66602 1.74996 5.24935 1.16663 5.83268 1.16663H8.16602C8.74935 1.16663 9.33268 1.74996 9.33268 2.33329V3.49996\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M5.83398 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M8.16602 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n </div>\n </div>\n\n <!-- Expanded Content with Branches -->\n <div *ngIf=\"expanded\" class=\"cqa-flex cqa-flex-col\">\n <!-- Branches (IF TRUE, ELSE IF, ELSE) -->\n <div *ngFor=\"let branch of branches\" class=\"cqa-flex cqa-flex-col\">\n <!-- Branch Header -->\n <div\n [class]=\"'cqa-px-4 cqa-py-2 cqa-text-[12px] cqa-leading-[15px] cqa-flex cqa-items-center cqa-gap-2 ' + getBranchTextColor(branch) + ' ' + getBranchColorClass(branch)\">\n <span>{{ getBranchLabel(branch) }}</span>\n <span *ngIf=\"branch.action\" [innerHTML]=\"branch.action\" class=\"cqa-text-[#111827]\"></span>\n </div>\n\n <!-- Branch Content (Nested Steps \u2013 renderer dispatches by step type, n-level nesting) -->\n <div *ngIf=\"!isReorder\" class=\"cqa-flex cqa-flex-col\">\n <cqa-test-case-details-renderer\n *ngFor=\"let step of branch.nestedSteps; let i = index\"\n [step]=\"step\"\n [index]=\"i\"\n [branch]=\"branch\"\n [isNested]=\"true\"\n [isReorder]=\"isReorder\"\n (branchStepChange)=\"onBranchStepChange($event.branch, $event.step, $event.stepIndex)\"\n (addStepForBranch)=\"onAddStep($event.branch)\"\n (deleteStepWithBranch)=\"onDeleteStep($event.branch, $event.stepIndex)\"\n (toggleExpanded)=\"onNestedToggleExpanded($event, branch, step, i)\"\n (groupNameChange)=\"$any(step).groupName = $event; onBranchStepChange(branch, step, i)\"\n (descriptionChange)=\"$any(step).description = $event; onBranchStepChange(branch, step, i)\"\n (reusableChange)=\"$any(step).reusable = $event; onBranchStepChange(branch, step, i)\"\n (openExternal)=\"onBranchStepChange(branch, step, i)\"\n (edit)=\"onBranchStepChange(branch, step, i)\"\n (link)=\"onBranchStepChange(branch, step, i)\"\n (duplicate)=\"onBranchStepChange(branch, step, i)\"\n (conditionChange)=\"$any(step).condition = $event; onBranchStepChange(branch, step, i)\"\n (addBranch)=\"onNestedConditionAddBranch($any(step)); onBranchStepChange(branch, step, i)\"\n (deleteBranch)=\"onNestedConditionDeleteBranch($any(step), $event); onBranchStepChange(branch, step, i)\"\n (testDataProfileChange)=\"$any(step).testDataProfile = $event; onBranchStepChange(branch, step, i)\"\n (startStepChange)=\"$any(step).startStep = $event; onBranchStepChange(branch, step, i)\"\n (endStepChange)=\"$any(step).endStep = $event; onBranchStepChange(branch, step, i)\"\n (maxIterationsChange)=\"$any(step).maxIterations = $event; onBranchStepChange(branch, step, i)\"\n (eventTypeChange)=\"$any(step).eventType = $event; onBranchStepChange(branch, step, i)\"\n (parameterChange)=\"onBranchStepChange(branch, step, i)\"\n (selectionChange)=\"$any(step).selected = $event; onBranchStepChange(branch, step, i)\"\n (dndDropInZone)=\"dndDropInZone.emit($event)\"\n >\n </cqa-test-case-details-renderer>\n </div>\n <div *ngIf=\"isReorder\" class=\"cqa-flex cqa-flex-col nested-step-drop-list\"\n [dndDropzone]=\"['step']\"\n dndEffectAllowed=\"move\"\n dndDragoverClass=\"dndDragover\"\n (dndDrop)=\"onDndDrop($event, branch)\">\n <div dndPlaceholderRef class=\"step-drag-placeholder-nested cqa-my-1 cqa-min-h-[50px] cqa-border-2 cqa-border-dashed cqa-border-[#3F43EE] cqa-rounded cqa-bg-[rgba(63,67,238,0.08)] cqa-flex cqa-items-center cqa-justify-center cqa-text-[#3F43EE] cqa-text-xs\">Drop here</div>\n <div *ngFor=\"let step of branch.nestedSteps; let i = index\" class=\"nested-step-drag-item\"\n [dndDraggable]=\"step\"\n dndEffectAllowed=\"move\"\n dndType=\"step\">\n <cqa-test-case-details-renderer\n [step]=\"step\"\n [index]=\"i\"\n [branch]=\"branch\"\n [isNested]=\"true\"\n [isReorder]=\"isReorder\"\n (branchStepChange)=\"onBranchStepChange($event.branch, $event.step, $event.stepIndex)\"\n (addStepForBranch)=\"onAddStep($event.branch)\"\n (deleteStepWithBranch)=\"onDeleteStep($event.branch, $event.stepIndex)\"\n (toggleExpanded)=\"onNestedToggleExpanded($event, branch, step, i)\"\n (groupNameChange)=\"$any(step).groupName = $event; onBranchStepChange(branch, step, i)\"\n (descriptionChange)=\"$any(step).description = $event; onBranchStepChange(branch, step, i)\"\n (reusableChange)=\"$any(step).reusable = $event; onBranchStepChange(branch, step, i)\"\n (openExternal)=\"onBranchStepChange(branch, step, i)\"\n (edit)=\"onBranchStepChange(branch, step, i)\"\n (link)=\"onBranchStepChange(branch, step, i)\"\n (duplicate)=\"onBranchStepChange(branch, step, i)\"\n (conditionChange)=\"$any(step).condition = $event; onBranchStepChange(branch, step, i)\"\n (addBranch)=\"onNestedConditionAddBranch($any(step)); onBranchStepChange(branch, step, i)\"\n (deleteBranch)=\"onNestedConditionDeleteBranch($any(step), $event); onBranchStepChange(branch, step, i)\"\n (testDataProfileChange)=\"$any(step).testDataProfile = $event; onBranchStepChange(branch, step, i)\"\n (startStepChange)=\"$any(step).startStep = $event; onBranchStepChange(branch, step, i)\"\n (endStepChange)=\"$any(step).endStep = $event; onBranchStepChange(branch, step, i)\"\n (maxIterationsChange)=\"$any(step).maxIterations = $event; onBranchStepChange(branch, step, i)\"\n (eventTypeChange)=\"$any(step).eventType = $event; onBranchStepChange(branch, step, i)\"\n (parameterChange)=\"onBranchStepChange(branch, step, i)\"\n (selectionChange)=\"$any(step).selected = $event; onBranchStepChange(branch, step, i)\"\n (dndDropInZone)=\"dndDropInZone.emit($event)\"\n >\n </cqa-test-case-details-renderer>\n </div>\n </div>\n </div>\n\n <!-- END IF Marker -->\n <div [class]=\"'cqa-pl-4 cqa-py-1 cqa-text-[#7B3306] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium'\" style=\"border-top: 1px solid #E5E7EB;\">\n END IF\n </div>\n </div>\n</div>", styles: [".step-actions{opacity:0;transition:opacity .15s ease}.step-row:hover .step-actions{opacity:1}\n"], components: [{ type: CustomInputComponent, selector: "cqa-custom-input", inputs: ["label", "type", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "inputInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused", "enterPressed"] }, { type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore"] }, { type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }, { type: TestCaseDetailsRendererComponent, selector: "cqa-test-case-details-renderer", inputs: ["step", "index", "isNested", "isInsideLoop", "branch", "isReorder"], outputs: ["nestedStepChange", "addStep", "deleteStep", "toggleExpanded", "groupNameChange", "descriptionChange", "reusableChange", "openExternal", "edit", "link", "duplicate", "delete", "viewDetails", "selectionChange", "conditionChange", "branchStepChange", "addStepForBranch", "deleteStepWithBranch", "addBranch", "deleteBranch", "testDataProfileChange", "startStepChange", "endStepChange", "maxIterationsChange", "eventTypeChange", "parameterChange", "dndDropInZone"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i7.DndDropzoneDirective, selector: "[dndDropzone]", inputs: ["dndDropzone", "dndEffectAllowed", "dndAllowExternal", "dndHorizontal", "dndDragoverClass", "dndDropzoneDisabledClass", "dndDisableIf", "dndDisableDropIf"], outputs: ["dndDragover", "dndDrop"] }, { type: i7.DndPlaceholderRefDirective, selector: "[dndPlaceholderRef]" }, { type: i7.DndDraggableDirective, selector: "[dndDraggable]", inputs: ["dndDraggable", "dndEffectAllowed", "dndType", "dndDraggingClass", "dndDraggingSourceClass", "dndDraggableDisabledClass", "dndDragImageOffsetFunction", "dndDisableIf", "dndDisableDragIf"], outputs: ["dndStart", "dndDrag", "dndEnd", "dndMoved", "dndCopied", "dndLinked", "dndCanceled"] }] });
18103
+ TestCaseConditionStepComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TestCaseConditionStepComponent, selector: "cqa-test-case-condition-step", inputs: { config: "config", id: "id", stepNumber: "stepNumber", condition: "condition", branches: "branches", expanded: "expanded", isNested: "isNested", isInsideLoop: "isInsideLoop", isReorder: "isReorder" }, outputs: { toggleExpanded: "toggleExpanded", conditionChange: "conditionChange", branchStepChange: "branchStepChange", addStep: "addStep", deleteStep: "deleteStep", addBranch: "addBranch", deleteBranch: "deleteBranch", duplicate: "duplicate", delete: "delete", moreOptions: "moreOptions", dndDropInZone: "dndDropInZone" }, host: { classAttribute: "cqa-ui-root" }, ngImport: i0, template: "<div [class]=\"'cqa-flex cqa-flex-col cqa-border cqa-border-solid cqa-border-[#E5E7EB] ' + (isNested ? ' cqa-pl-[24px]' : '')\">\n <!-- Inline Edit Mode: CONDITION tag, three fields, IF/ELSE chips, Edit In depth, Cancel/Apply -->\n <div *ngIf=\"isEditing\" class=\"cqa-py-2.5 cqa-px-4 cqa-flex cqa-items-center cqa-gap-3 cqa-justify-between\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-flex-grow\">\n <!-- CONDITION Tag (orange) -->\n <span class=\"cqa-px-1.5 cqa-rounded-md cqa-text-[#EA580C] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-bg-[#FFEDD5]\">\n CONDITION\n </span>\n\n <!-- First field: left operand (e.g. Usertype) -->\n <cqa-custom-input\n [value]=\"editForm.get('conditionLeft')?.value ?? ''\"\n (valueChange)=\"onEditFormFieldChange('conditionLeft', $event)\"\n placeholder=\"Usertype\"\n class=\"cqa-w-full cqa-max-w-[216px]\"\n size=\"sm\">\n </cqa-custom-input>\n\n <!-- Operator: dynamic-select (IS, IS NOT, etc.) -->\n <cqa-dynamic-select [form]=\"editForm\" [config]=\"operatorSelectConfig\" class=\"cqa-w-full cqa-max-w-[216px]\"></cqa-dynamic-select>\n\n <!-- Third field: right operand (e.g. Premium) -->\n <cqa-custom-input\n [value]=\"editForm.get('conditionRight')?.value ?? ''\"\n (valueChange)=\"onEditFormFieldChange('conditionRight', $event)\"\n placeholder=\"Premium\"\n class=\"cqa-w-full cqa-max-w-[216px]\"\n size=\"sm\">\n </cqa-custom-input>\n\n <!-- IF / ELSE indicators -->\n <span class=\"cqa-px-2 cqa-py-[2px] cqa-rounded-[4px] cqa-text-[8px] cqa-leading-[12px] cqa-bg-[#DCFCE7] cqa-text-[#008236] cqa-border cqa-border-solid cqa-border-[#B9F8CF] cqa-flex cqa-items-center cqa-gap-1.5\">\n <svg width=\"8\" height=\"8\" viewBox=\"0 0 8 8\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M6.66634 2L2.99967 5.66667L1.33301 4\" stroke=\"#008236\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n IF\n </span>\n <span class=\"cqa-px-2 cqa-py-[2px] cqa-rounded-[4px] cqa-text-[8px] cqa-leading-[12px] cqa-bg-[#F3F4F6] cqa-text-[#99A1AF] cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-flex cqa-items-center cqa-gap-1.5\">\n Add ELSE\n </span>\n\n <!-- Edit In depth link -->\n <a href=\"#\" (click)=\"onEditInDepth(); $event.preventDefault()\"\n class=\"cqa-text-[#3F43EE] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-flex cqa-items-center cqa-gap-[2px] cqa-no-underline\">\n Edit In depth\n <svg width=\"8\" height=\"8\" viewBox=\"0 0 8 8\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2.03809 6.74329L2.62809 7.33329L5.96142 3.99996L2.62809 0.666626L2.03809 1.25663L4.78142 3.99996L2.03809 6.74329Z\" fill=\"#3F43EE\"/></svg>\n </a> \n </div>\n <!-- Cancel / Apply -->\n <cqa-button variant=\"outlined\" btnSize=\"lg\" [customClass]=\"'cqa-text-[14px] cqa-py-[9px]'\" [text]=\"'Cancel'\" (clicked)=\"onEditCancel()\"></cqa-button>\n <cqa-button variant=\"filled\" btnSize=\"lg\" [customClass]=\"'cqa-text-[14px] cqa-py-[9px]'\" [text]=\"'Apply'\" (clicked)=\"onEditApply()\"></cqa-button>\n </div>\n\n <!-- Condition Header (normal view when not editing) -->\n <div *ngIf=\"!isEditing\" [class]=\"'step-row cqa-flex cqa-items-center cqa-gap-3 cqa-py-2 ' + (isInsideLoop ? 'cqa-pl-10 cqa-pr-4' : 'cqa-px-4')\">\n <!-- Expand/Collapse Icon -->\n <button type=\"button\" (click)=\"onToggleExpanded()\" class=\"cqa-p-0\">\n <svg [class.cqa-rotate-180]=\"!expanded\" class=\"cqa-transition-transform\" width=\"16\" height=\"16\"\n viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M12 10L8 6L4 10\" stroke=\"#6B7280\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n\n <!-- IF/ELSE Icon -->\n <div><svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 2V10\" stroke=\"#7B3306\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M12 6C13.1046 6 14 5.10457 14 4C14 2.89543 13.1046 2 12 2C10.8954 2 10 2.89543 10 4C10 5.10457 10.8954 6 12 6Z\"\n stroke=\"#7B3306\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M4 14C5.10457 14 6 13.1046 6 12C6 10.8954 5.10457 10 4 10C2.89543 10 2 10.8954 2 12C2 13.1046 2.89543 14 4 14Z\"\n stroke=\"#7B3306\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M12 6C12 7.5913 11.3679 9.11742 10.2426 10.2426C9.11742 11.3679 7.5913 12 6 12\" stroke=\"#7B3306\"\n stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg></div>\n\n <!-- IF/ELSE Label -->\n <span class=\"cqa-font-semibold cqa-text-[#7B3306] cqa-text-[12px] cqa-leading-none\">\n IF / ELSE\n </span>\n\n <!-- Condition Input -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-ml-2 cqa-flex-1\">\n <span [innerHTML]=\"condition\"></span>\n <!-- <span class=\"cqa-text-[#6B7280] cqa-text-[14px] cqa-leading-[18px]\">\n If\n </span>\n <span\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">.success-message</span>\n <span class=\"cqa-text-[#6B7280] cqa-text-[14px] cqa-leading-[18px]\">\n is visible\n </span> -->\n <!-- <input\n type=\"text\"\n [value]=\"condition\"\n (input)=\"onConditionChange($any($event.target).value)\"\n placeholder=\"element `.success-message` is visible\"\n class=\"cqa-px-3 cqa-py-1.5 cqa-rounded-lg cqa-border cqa-border-gray-300 cqa-bg-white cqa-text-gray-900 cqa-text-sm cqa-flex-1 cqa-max-w-md cqa-outline-none focus:cqa-ring-2 focus:cqa-ring-primary focus:cqa-ring-opacity-50\"\n /> -->\n </div>\n\n <!-- Steps Summary -->\n <div\n class=\"cqa-ml-auto cqa-border cqa-border-solid cqa-border-[#E5E5E5] cqa-rounded-lg cqa-py-0.5 cqa-px-2 cqa-text-[#0A0A0A] cqa-text-[12px] cqa-leading-[15px]\">\n {{ getStepsSummary() }}\n </div>\n\n <!-- Action Icons: Edit, Link, Duplicate, Delete (show on hover) -->\n <div class=\"step-actions cqa-flex cqa-items-center cqa-gap-3 cqa-px-[7px]\">\n <button type=\"button\" (click)=\"onEdit(); $event.stopPropagation()\" title=\"Edit\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M7 11.6666H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M9.55208 2.1128C9.7843 1.88058 10.0993 1.75012 10.4277 1.75012C10.7561 1.75012 11.071 1.88058 11.3033 2.1128C11.5355 2.34502 11.6659 2.65998 11.6659 2.98838C11.6659 3.31679 11.5355 3.63175 11.3033 3.86397L4.29742 10.8704C4.15864 11.0092 3.9871 11.1107 3.79867 11.1656L2.12333 11.6544C2.07314 11.669 2.01993 11.6699 1.96928 11.6569C1.91863 11.6439 1.8724 11.6176 1.83543 11.5806C1.79846 11.5437 1.7721 11.4974 1.75913 11.4468C1.74615 11.3961 1.74703 11.3429 1.76167 11.2927L2.2505 9.61738C2.30546 9.42916 2.40698 9.25783 2.54567 9.11922L9.55208 2.1128Z\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n <button type=\"button\" (click)=\"onLink(); $event.stopPropagation()\" title=\"Link\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M5.00065 9.91671H3.66732C2.78326 9.91671 1.93542 9.60942 1.3103 9.06244C0.685174 8.51545 0.333984 7.77359 0.333984 7.00004C0.333984 6.22649 0.685174 5.48463 1.3103 4.93765C1.93542 4.39066 2.78326 4.08337 3.66732 4.08337H5.00065\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M9 4.08337H10.3333C11.2174 4.08337 12.0652 4.39066 12.6904 4.93765C13.3155 5.48463 13.6667 6.22649 13.6667 7.00004C13.6667 7.77359 13.3155 8.51545 12.6904 9.06244C12.0652 9.60942 11.2174 9.91671 10.3333 9.91671H9\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M4.33398 7H9.66732\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n <button type=\"button\" (click)=\"onDuplicate(); $event.stopPropagation()\" title=\"Duplicate\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M11.666 4.66663H5.83268C5.18835 4.66663 4.66602 5.18896 4.66602 5.83329V11.6666C4.66602 12.311 5.18835 12.8333 5.83268 12.8333H11.666C12.3103 12.8333 12.8327 12.311 12.8327 11.6666V5.83329C12.8327 5.18896 12.3103 4.66663 11.666 4.66663Z\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M2.33268 9.33329C1.69102 9.33329 1.16602 8.80829 1.16602 8.16663V2.33329C1.16602 1.69163 1.69102 1.16663 2.33268 1.16663H8.16602C8.80768 1.16663 9.33268 1.69163 9.33268 2.33329\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n <button type=\"button\" (click)=\"onDelete(); $event.stopPropagation()\" title=\"Delete\" class=\"cqa-p-0 cqa-text-[#ff6467] hover:cqa-text-[#C63535]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M1.75 3.5H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M11.0827 3.5V11.6667C11.0827 12.25 10.4993 12.8333 9.91602 12.8333H4.08268C3.49935 12.8333 2.91602 12.25 2.91602 11.6667V3.5\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M4.66602 3.49996V2.33329C4.66602 1.74996 5.24935 1.16663 5.83268 1.16663H8.16602C8.74935 1.16663 9.33268 1.74996 9.33268 2.33329V3.49996\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M5.83398 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M8.16602 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n </div>\n </div>\n\n <!-- Expanded Content with Branches -->\n <div *ngIf=\"expanded\" class=\"cqa-flex cqa-flex-col\">\n <!-- Branches (IF TRUE, ELSE IF, ELSE) -->\n <div *ngFor=\"let branch of branches\" class=\"cqa-flex cqa-flex-col\">\n <!-- Branch Header -->\n <div\n [class]=\"'cqa-px-4 cqa-py-2 cqa-text-[12px] cqa-leading-[15px] cqa-flex cqa-items-center cqa-gap-2 ' + getBranchTextColor(branch) + ' ' + getBranchColorClass(branch)\">\n <span>{{ getBranchLabel(branch) }}</span>\n <span *ngIf=\"branch.action\" [innerHTML]=\"branch.action\" class=\"cqa-text-[#111827]\"></span>\n </div>\n\n <!-- Branch Content (Nested Steps \u2013 renderer dispatches by step type, n-level nesting) -->\n <div *ngIf=\"!isReorder\" class=\"cqa-flex cqa-flex-col\">\n <cqa-test-case-details-renderer\n *ngFor=\"let step of branch.nestedSteps; let i = index\"\n [step]=\"step\"\n [index]=\"i\"\n [branch]=\"branch\"\n [isNested]=\"true\"\n [isReorder]=\"isReorder\"\n (branchStepChange)=\"onBranchStepChange($event.branch, $event.step, $event.stepIndex)\"\n (addStepForBranch)=\"onAddStep($event.branch)\"\n (deleteStepWithBranch)=\"onDeleteStep($event.branch, $event.stepIndex)\"\n (toggleExpanded)=\"onNestedToggleExpanded($event, branch, step, i)\"\n (groupNameChange)=\"$any(step).groupName = $event; onBranchStepChange(branch, step, i)\"\n (descriptionChange)=\"$any(step).description = $event; onBranchStepChange(branch, step, i)\"\n (reusableChange)=\"$any(step).reusable = $event; onBranchStepChange(branch, step, i)\"\n (openExternal)=\"onBranchStepChange(branch, step, i)\"\n (edit)=\"onBranchStepChange(branch, step, i)\"\n (link)=\"onBranchStepChange(branch, step, i)\"\n (duplicate)=\"onBranchStepChange(branch, step, i)\"\n (conditionChange)=\"$any(step).condition = $event; onBranchStepChange(branch, step, i)\"\n (addBranch)=\"onNestedConditionAddBranch($any(step)); onBranchStepChange(branch, step, i)\"\n (deleteBranch)=\"onNestedConditionDeleteBranch($any(step), $event); onBranchStepChange(branch, step, i)\"\n (testDataProfileChange)=\"$any(step).testDataProfile = $event; onBranchStepChange(branch, step, i)\"\n (startStepChange)=\"$any(step).startStep = $event; onBranchStepChange(branch, step, i)\"\n (endStepChange)=\"$any(step).endStep = $event; onBranchStepChange(branch, step, i)\"\n (maxIterationsChange)=\"$any(step).maxIterations = $event; onBranchStepChange(branch, step, i)\"\n (eventTypeChange)=\"$any(step).eventType = $event; onBranchStepChange(branch, step, i)\"\n (parameterChange)=\"onBranchStepChange(branch, step, i)\"\n (selectionChange)=\"$any(step).selected = $event; onBranchStepChange(branch, step, i)\"\n (dndDropInZone)=\"dndDropInZone.emit($event)\"\n >\n </cqa-test-case-details-renderer>\n </div>\n <div *ngIf=\"isReorder\" class=\"cqa-flex cqa-flex-col nested-step-drop-list\"\n [dndDropzone]=\"['step']\"\n dndEffectAllowed=\"move\"\n dndDragoverClass=\"dndDragover\"\n (dndDrop)=\"onDndDrop($event, branch)\">\n <div dndPlaceholderRef class=\"step-drag-placeholder-nested cqa-my-1 cqa-min-h-[50px] cqa-border-2 cqa-border-dashed cqa-border-[#3F43EE] cqa-rounded cqa-bg-[rgba(63,67,238,0.08)] cqa-flex cqa-items-center cqa-justify-center cqa-text-[#3F43EE] cqa-text-xs\">Drop here</div>\n <div *ngFor=\"let step of branch.nestedSteps; let i = index\" class=\"nested-step-drag-item\"\n [dndDraggable]=\"step\"\n dndEffectAllowed=\"move\"\n dndType=\"step\">\n <cqa-test-case-details-renderer\n [step]=\"step\"\n [index]=\"i\"\n [branch]=\"branch\"\n [isNested]=\"true\"\n [isReorder]=\"isReorder\"\n (branchStepChange)=\"onBranchStepChange($event.branch, $event.step, $event.stepIndex)\"\n (addStepForBranch)=\"onAddStep($event.branch)\"\n (deleteStepWithBranch)=\"onDeleteStep($event.branch, $event.stepIndex)\"\n (toggleExpanded)=\"onNestedToggleExpanded($event, branch, step, i)\"\n (groupNameChange)=\"$any(step).groupName = $event; onBranchStepChange(branch, step, i)\"\n (descriptionChange)=\"$any(step).description = $event; onBranchStepChange(branch, step, i)\"\n (reusableChange)=\"$any(step).reusable = $event; onBranchStepChange(branch, step, i)\"\n (openExternal)=\"onBranchStepChange(branch, step, i)\"\n (edit)=\"onBranchStepChange(branch, step, i)\"\n (link)=\"onBranchStepChange(branch, step, i)\"\n (duplicate)=\"onBranchStepChange(branch, step, i)\"\n (conditionChange)=\"$any(step).condition = $event; onBranchStepChange(branch, step, i)\"\n (addBranch)=\"onNestedConditionAddBranch($any(step)); onBranchStepChange(branch, step, i)\"\n (deleteBranch)=\"onNestedConditionDeleteBranch($any(step), $event); onBranchStepChange(branch, step, i)\"\n (testDataProfileChange)=\"$any(step).testDataProfile = $event; onBranchStepChange(branch, step, i)\"\n (startStepChange)=\"$any(step).startStep = $event; onBranchStepChange(branch, step, i)\"\n (endStepChange)=\"$any(step).endStep = $event; onBranchStepChange(branch, step, i)\"\n (maxIterationsChange)=\"$any(step).maxIterations = $event; onBranchStepChange(branch, step, i)\"\n (eventTypeChange)=\"$any(step).eventType = $event; onBranchStepChange(branch, step, i)\"\n (parameterChange)=\"onBranchStepChange(branch, step, i)\"\n (selectionChange)=\"$any(step).selected = $event; onBranchStepChange(branch, step, i)\"\n (dndDropInZone)=\"dndDropInZone.emit($event)\"\n >\n </cqa-test-case-details-renderer>\n </div>\n </div>\n </div>\n\n <!-- END IF Marker -->\n <div [class]=\"'cqa-pl-4 cqa-py-1 cqa-text-[#7B3306] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium'\" style=\"border-top: 1px solid #E5E7EB;\">\n END IF\n </div>\n </div>\n</div>", styles: [".step-actions{opacity:0;transition:opacity .15s ease}.step-row:hover .step-actions{opacity:1}\n"], components: [{ type: CustomInputComponent, selector: "cqa-custom-input", inputs: ["label", "type", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "inputInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused", "enterPressed"] }, { type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore"] }, { type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }, { type: TestCaseDetailsRendererComponent, selector: "cqa-test-case-details-renderer", inputs: ["step", "index", "isNested", "isInsideLoop", "branch", "isReorder", "addStepBetween"], outputs: ["nestedStepChange", "addStep", "deleteStep", "toggleExpanded", "groupNameChange", "descriptionChange", "reusableChange", "openExternal", "edit", "link", "duplicate", "delete", "viewDetails", "selectionChange", "conditionChange", "branchStepChange", "addStepForBranch", "deleteStepWithBranch", "addBranch", "deleteBranch", "testDataProfileChange", "startStepChange", "endStepChange", "maxIterationsChange", "eventTypeChange", "parameterChange", "clickAction", "dndDropInZone", "addStepBetweenClick"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i7.DndDropzoneDirective, selector: "[dndDropzone]", inputs: ["dndDropzone", "dndEffectAllowed", "dndAllowExternal", "dndHorizontal", "dndDragoverClass", "dndDropzoneDisabledClass", "dndDisableIf", "dndDisableDropIf"], outputs: ["dndDragover", "dndDrop"] }, { type: i7.DndPlaceholderRefDirective, selector: "[dndPlaceholderRef]" }, { type: i7.DndDraggableDirective, selector: "[dndDraggable]", inputs: ["dndDraggable", "dndEffectAllowed", "dndType", "dndDraggingClass", "dndDraggingSourceClass", "dndDraggableDisabledClass", "dndDragImageOffsetFunction", "dndDisableIf", "dndDisableDragIf"], outputs: ["dndStart", "dndDrag", "dndEnd", "dndMoved", "dndCopied", "dndLinked", "dndCanceled"] }] });
18211
18104
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestCaseConditionStepComponent, decorators: [{
18212
18105
  type: Component,
18213
18106
  args: [{ selector: 'cqa-test-case-condition-step', host: { class: 'cqa-ui-root' }, styles: [STEP_ROW_ACTIONS_STYLES], template: "<div [class]=\"'cqa-flex cqa-flex-col cqa-border cqa-border-solid cqa-border-[#E5E7EB] ' + (isNested ? ' cqa-pl-[24px]' : '')\">\n <!-- Inline Edit Mode: CONDITION tag, three fields, IF/ELSE chips, Edit In depth, Cancel/Apply -->\n <div *ngIf=\"isEditing\" class=\"cqa-py-2.5 cqa-px-4 cqa-flex cqa-items-center cqa-gap-3 cqa-justify-between\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-flex-grow\">\n <!-- CONDITION Tag (orange) -->\n <span class=\"cqa-px-1.5 cqa-rounded-md cqa-text-[#EA580C] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-bg-[#FFEDD5]\">\n CONDITION\n </span>\n\n <!-- First field: left operand (e.g. Usertype) -->\n <cqa-custom-input\n [value]=\"editForm.get('conditionLeft')?.value ?? ''\"\n (valueChange)=\"onEditFormFieldChange('conditionLeft', $event)\"\n placeholder=\"Usertype\"\n class=\"cqa-w-full cqa-max-w-[216px]\"\n size=\"sm\">\n </cqa-custom-input>\n\n <!-- Operator: dynamic-select (IS, IS NOT, etc.) -->\n <cqa-dynamic-select [form]=\"editForm\" [config]=\"operatorSelectConfig\" class=\"cqa-w-full cqa-max-w-[216px]\"></cqa-dynamic-select>\n\n <!-- Third field: right operand (e.g. Premium) -->\n <cqa-custom-input\n [value]=\"editForm.get('conditionRight')?.value ?? ''\"\n (valueChange)=\"onEditFormFieldChange('conditionRight', $event)\"\n placeholder=\"Premium\"\n class=\"cqa-w-full cqa-max-w-[216px]\"\n size=\"sm\">\n </cqa-custom-input>\n\n <!-- IF / ELSE indicators -->\n <span class=\"cqa-px-2 cqa-py-[2px] cqa-rounded-[4px] cqa-text-[8px] cqa-leading-[12px] cqa-bg-[#DCFCE7] cqa-text-[#008236] cqa-border cqa-border-solid cqa-border-[#B9F8CF] cqa-flex cqa-items-center cqa-gap-1.5\">\n <svg width=\"8\" height=\"8\" viewBox=\"0 0 8 8\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M6.66634 2L2.99967 5.66667L1.33301 4\" stroke=\"#008236\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n IF\n </span>\n <span class=\"cqa-px-2 cqa-py-[2px] cqa-rounded-[4px] cqa-text-[8px] cqa-leading-[12px] cqa-bg-[#F3F4F6] cqa-text-[#99A1AF] cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-flex cqa-items-center cqa-gap-1.5\">\n Add ELSE\n </span>\n\n <!-- Edit In depth link -->\n <a href=\"#\" (click)=\"onEditInDepth(); $event.preventDefault()\"\n class=\"cqa-text-[#3F43EE] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-flex cqa-items-center cqa-gap-[2px] cqa-no-underline\">\n Edit In depth\n <svg width=\"8\" height=\"8\" viewBox=\"0 0 8 8\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M2.03809 6.74329L2.62809 7.33329L5.96142 3.99996L2.62809 0.666626L2.03809 1.25663L4.78142 3.99996L2.03809 6.74329Z\" fill=\"#3F43EE\"/></svg>\n </a> \n </div>\n <!-- Cancel / Apply -->\n <cqa-button variant=\"outlined\" btnSize=\"lg\" [customClass]=\"'cqa-text-[14px] cqa-py-[9px]'\" [text]=\"'Cancel'\" (clicked)=\"onEditCancel()\"></cqa-button>\n <cqa-button variant=\"filled\" btnSize=\"lg\" [customClass]=\"'cqa-text-[14px] cqa-py-[9px]'\" [text]=\"'Apply'\" (clicked)=\"onEditApply()\"></cqa-button>\n </div>\n\n <!-- Condition Header (normal view when not editing) -->\n <div *ngIf=\"!isEditing\" [class]=\"'step-row cqa-flex cqa-items-center cqa-gap-3 cqa-py-2 ' + (isInsideLoop ? 'cqa-pl-10 cqa-pr-4' : 'cqa-px-4')\">\n <!-- Expand/Collapse Icon -->\n <button type=\"button\" (click)=\"onToggleExpanded()\" class=\"cqa-p-0\">\n <svg [class.cqa-rotate-180]=\"!expanded\" class=\"cqa-transition-transform\" width=\"16\" height=\"16\"\n viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M12 10L8 6L4 10\" stroke=\"#6B7280\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n\n <!-- IF/ELSE Icon -->\n <div><svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 2V10\" stroke=\"#7B3306\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M12 6C13.1046 6 14 5.10457 14 4C14 2.89543 13.1046 2 12 2C10.8954 2 10 2.89543 10 4C10 5.10457 10.8954 6 12 6Z\"\n stroke=\"#7B3306\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M4 14C5.10457 14 6 13.1046 6 12C6 10.8954 5.10457 10 4 10C2.89543 10 2 10.8954 2 12C2 13.1046 2.89543 14 4 14Z\"\n stroke=\"#7B3306\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M12 6C12 7.5913 11.3679 9.11742 10.2426 10.2426C9.11742 11.3679 7.5913 12 6 12\" stroke=\"#7B3306\"\n stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg></div>\n\n <!-- IF/ELSE Label -->\n <span class=\"cqa-font-semibold cqa-text-[#7B3306] cqa-text-[12px] cqa-leading-none\">\n IF / ELSE\n </span>\n\n <!-- Condition Input -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-ml-2 cqa-flex-1\">\n <span [innerHTML]=\"condition\"></span>\n <!-- <span class=\"cqa-text-[#6B7280] cqa-text-[14px] cqa-leading-[18px]\">\n If\n </span>\n <span\n class=\"cqa-py-0.5 cqa-px-2 cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[17px] cqa-font-semibold cqa-border cqa-border-solid cqa-border-[#8A8CF4] cqa-rounded cqa-bg-[#D8D9FC]\">.success-message</span>\n <span class=\"cqa-text-[#6B7280] cqa-text-[14px] cqa-leading-[18px]\">\n is visible\n </span> -->\n <!-- <input\n type=\"text\"\n [value]=\"condition\"\n (input)=\"onConditionChange($any($event.target).value)\"\n placeholder=\"element `.success-message` is visible\"\n class=\"cqa-px-3 cqa-py-1.5 cqa-rounded-lg cqa-border cqa-border-gray-300 cqa-bg-white cqa-text-gray-900 cqa-text-sm cqa-flex-1 cqa-max-w-md cqa-outline-none focus:cqa-ring-2 focus:cqa-ring-primary focus:cqa-ring-opacity-50\"\n /> -->\n </div>\n\n <!-- Steps Summary -->\n <div\n class=\"cqa-ml-auto cqa-border cqa-border-solid cqa-border-[#E5E5E5] cqa-rounded-lg cqa-py-0.5 cqa-px-2 cqa-text-[#0A0A0A] cqa-text-[12px] cqa-leading-[15px]\">\n {{ getStepsSummary() }}\n </div>\n\n <!-- Action Icons: Edit, Link, Duplicate, Delete (show on hover) -->\n <div class=\"step-actions cqa-flex cqa-items-center cqa-gap-3 cqa-px-[7px]\">\n <button type=\"button\" (click)=\"onEdit(); $event.stopPropagation()\" title=\"Edit\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M7 11.6666H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M9.55208 2.1128C9.7843 1.88058 10.0993 1.75012 10.4277 1.75012C10.7561 1.75012 11.071 1.88058 11.3033 2.1128C11.5355 2.34502 11.6659 2.65998 11.6659 2.98838C11.6659 3.31679 11.5355 3.63175 11.3033 3.86397L4.29742 10.8704C4.15864 11.0092 3.9871 11.1107 3.79867 11.1656L2.12333 11.6544C2.07314 11.669 2.01993 11.6699 1.96928 11.6569C1.91863 11.6439 1.8724 11.6176 1.83543 11.5806C1.79846 11.5437 1.7721 11.4974 1.75913 11.4468C1.74615 11.3961 1.74703 11.3429 1.76167 11.2927L2.2505 9.61738C2.30546 9.42916 2.40698 9.25783 2.54567 9.11922L9.55208 2.1128Z\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n <button type=\"button\" (click)=\"onLink(); $event.stopPropagation()\" title=\"Link\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M5.00065 9.91671H3.66732C2.78326 9.91671 1.93542 9.60942 1.3103 9.06244C0.685174 8.51545 0.333984 7.77359 0.333984 7.00004C0.333984 6.22649 0.685174 5.48463 1.3103 4.93765C1.93542 4.39066 2.78326 4.08337 3.66732 4.08337H5.00065\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M9 4.08337H10.3333C11.2174 4.08337 12.0652 4.39066 12.6904 4.93765C13.3155 5.48463 13.6667 6.22649 13.6667 7.00004C13.6667 7.77359 13.3155 8.51545 12.6904 9.06244C12.0652 9.60942 11.2174 9.91671 10.3333 9.91671H9\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M4.33398 7H9.66732\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n <button type=\"button\" (click)=\"onDuplicate(); $event.stopPropagation()\" title=\"Duplicate\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M11.666 4.66663H5.83268C5.18835 4.66663 4.66602 5.18896 4.66602 5.83329V11.6666C4.66602 12.311 5.18835 12.8333 5.83268 12.8333H11.666C12.3103 12.8333 12.8327 12.311 12.8327 11.6666V5.83329C12.8327 5.18896 12.3103 4.66663 11.666 4.66663Z\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M2.33268 9.33329C1.69102 9.33329 1.16602 8.80829 1.16602 8.16663V2.33329C1.16602 1.69163 1.69102 1.16663 2.33268 1.16663H8.16602C8.80768 1.16663 9.33268 1.69163 9.33268 2.33329\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n <button type=\"button\" (click)=\"onDelete(); $event.stopPropagation()\" title=\"Delete\" class=\"cqa-p-0 cqa-text-[#ff6467] hover:cqa-text-[#C63535]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M1.75 3.5H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M11.0827 3.5V11.6667C11.0827 12.25 10.4993 12.8333 9.91602 12.8333H4.08268C3.49935 12.8333 2.91602 12.25 2.91602 11.6667V3.5\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M4.66602 3.49996V2.33329C4.66602 1.74996 5.24935 1.16663 5.83268 1.16663H8.16602C8.74935 1.16663 9.33268 1.74996 9.33268 2.33329V3.49996\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M5.83398 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M8.16602 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n </div>\n </div>\n\n <!-- Expanded Content with Branches -->\n <div *ngIf=\"expanded\" class=\"cqa-flex cqa-flex-col\">\n <!-- Branches (IF TRUE, ELSE IF, ELSE) -->\n <div *ngFor=\"let branch of branches\" class=\"cqa-flex cqa-flex-col\">\n <!-- Branch Header -->\n <div\n [class]=\"'cqa-px-4 cqa-py-2 cqa-text-[12px] cqa-leading-[15px] cqa-flex cqa-items-center cqa-gap-2 ' + getBranchTextColor(branch) + ' ' + getBranchColorClass(branch)\">\n <span>{{ getBranchLabel(branch) }}</span>\n <span *ngIf=\"branch.action\" [innerHTML]=\"branch.action\" class=\"cqa-text-[#111827]\"></span>\n </div>\n\n <!-- Branch Content (Nested Steps \u2013 renderer dispatches by step type, n-level nesting) -->\n <div *ngIf=\"!isReorder\" class=\"cqa-flex cqa-flex-col\">\n <cqa-test-case-details-renderer\n *ngFor=\"let step of branch.nestedSteps; let i = index\"\n [step]=\"step\"\n [index]=\"i\"\n [branch]=\"branch\"\n [isNested]=\"true\"\n [isReorder]=\"isReorder\"\n (branchStepChange)=\"onBranchStepChange($event.branch, $event.step, $event.stepIndex)\"\n (addStepForBranch)=\"onAddStep($event.branch)\"\n (deleteStepWithBranch)=\"onDeleteStep($event.branch, $event.stepIndex)\"\n (toggleExpanded)=\"onNestedToggleExpanded($event, branch, step, i)\"\n (groupNameChange)=\"$any(step).groupName = $event; onBranchStepChange(branch, step, i)\"\n (descriptionChange)=\"$any(step).description = $event; onBranchStepChange(branch, step, i)\"\n (reusableChange)=\"$any(step).reusable = $event; onBranchStepChange(branch, step, i)\"\n (openExternal)=\"onBranchStepChange(branch, step, i)\"\n (edit)=\"onBranchStepChange(branch, step, i)\"\n (link)=\"onBranchStepChange(branch, step, i)\"\n (duplicate)=\"onBranchStepChange(branch, step, i)\"\n (conditionChange)=\"$any(step).condition = $event; onBranchStepChange(branch, step, i)\"\n (addBranch)=\"onNestedConditionAddBranch($any(step)); onBranchStepChange(branch, step, i)\"\n (deleteBranch)=\"onNestedConditionDeleteBranch($any(step), $event); onBranchStepChange(branch, step, i)\"\n (testDataProfileChange)=\"$any(step).testDataProfile = $event; onBranchStepChange(branch, step, i)\"\n (startStepChange)=\"$any(step).startStep = $event; onBranchStepChange(branch, step, i)\"\n (endStepChange)=\"$any(step).endStep = $event; onBranchStepChange(branch, step, i)\"\n (maxIterationsChange)=\"$any(step).maxIterations = $event; onBranchStepChange(branch, step, i)\"\n (eventTypeChange)=\"$any(step).eventType = $event; onBranchStepChange(branch, step, i)\"\n (parameterChange)=\"onBranchStepChange(branch, step, i)\"\n (selectionChange)=\"$any(step).selected = $event; onBranchStepChange(branch, step, i)\"\n (dndDropInZone)=\"dndDropInZone.emit($event)\"\n >\n </cqa-test-case-details-renderer>\n </div>\n <div *ngIf=\"isReorder\" class=\"cqa-flex cqa-flex-col nested-step-drop-list\"\n [dndDropzone]=\"['step']\"\n dndEffectAllowed=\"move\"\n dndDragoverClass=\"dndDragover\"\n (dndDrop)=\"onDndDrop($event, branch)\">\n <div dndPlaceholderRef class=\"step-drag-placeholder-nested cqa-my-1 cqa-min-h-[50px] cqa-border-2 cqa-border-dashed cqa-border-[#3F43EE] cqa-rounded cqa-bg-[rgba(63,67,238,0.08)] cqa-flex cqa-items-center cqa-justify-center cqa-text-[#3F43EE] cqa-text-xs\">Drop here</div>\n <div *ngFor=\"let step of branch.nestedSteps; let i = index\" class=\"nested-step-drag-item\"\n [dndDraggable]=\"step\"\n dndEffectAllowed=\"move\"\n dndType=\"step\">\n <cqa-test-case-details-renderer\n [step]=\"step\"\n [index]=\"i\"\n [branch]=\"branch\"\n [isNested]=\"true\"\n [isReorder]=\"isReorder\"\n (branchStepChange)=\"onBranchStepChange($event.branch, $event.step, $event.stepIndex)\"\n (addStepForBranch)=\"onAddStep($event.branch)\"\n (deleteStepWithBranch)=\"onDeleteStep($event.branch, $event.stepIndex)\"\n (toggleExpanded)=\"onNestedToggleExpanded($event, branch, step, i)\"\n (groupNameChange)=\"$any(step).groupName = $event; onBranchStepChange(branch, step, i)\"\n (descriptionChange)=\"$any(step).description = $event; onBranchStepChange(branch, step, i)\"\n (reusableChange)=\"$any(step).reusable = $event; onBranchStepChange(branch, step, i)\"\n (openExternal)=\"onBranchStepChange(branch, step, i)\"\n (edit)=\"onBranchStepChange(branch, step, i)\"\n (link)=\"onBranchStepChange(branch, step, i)\"\n (duplicate)=\"onBranchStepChange(branch, step, i)\"\n (conditionChange)=\"$any(step).condition = $event; onBranchStepChange(branch, step, i)\"\n (addBranch)=\"onNestedConditionAddBranch($any(step)); onBranchStepChange(branch, step, i)\"\n (deleteBranch)=\"onNestedConditionDeleteBranch($any(step), $event); onBranchStepChange(branch, step, i)\"\n (testDataProfileChange)=\"$any(step).testDataProfile = $event; onBranchStepChange(branch, step, i)\"\n (startStepChange)=\"$any(step).startStep = $event; onBranchStepChange(branch, step, i)\"\n (endStepChange)=\"$any(step).endStep = $event; onBranchStepChange(branch, step, i)\"\n (maxIterationsChange)=\"$any(step).maxIterations = $event; onBranchStepChange(branch, step, i)\"\n (eventTypeChange)=\"$any(step).eventType = $event; onBranchStepChange(branch, step, i)\"\n (parameterChange)=\"onBranchStepChange(branch, step, i)\"\n (selectionChange)=\"$any(step).selected = $event; onBranchStepChange(branch, step, i)\"\n (dndDropInZone)=\"dndDropInZone.emit($event)\"\n >\n </cqa-test-case-details-renderer>\n </div>\n </div>\n </div>\n\n <!-- END IF Marker -->\n <div [class]=\"'cqa-pl-4 cqa-py-1 cqa-text-[#7B3306] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium'\" style=\"border-top: 1px solid #E5E7EB;\">\n END IF\n </div>\n </div>\n</div>" }]
@@ -18456,7 +18349,7 @@ class TestCaseStepGroupComponent {
18456
18349
  }
18457
18350
  }
18458
18351
  TestCaseStepGroupComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestCaseStepGroupComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
18459
- TestCaseStepGroupComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TestCaseStepGroupComponent, selector: "cqa-test-case-step-group", inputs: { config: "config", id: "id", stepNumber: "stepNumber", groupName: "groupName", description: "description", reusable: "reusable", nestedSteps: "nestedSteps", expanded: "expanded", isNested: "isNested", isInsideLoop: "isInsideLoop", isReorder: "isReorder", loading: "loading" }, outputs: { toggleExpanded: "toggleExpanded", groupNameChange: "groupNameChange", descriptionChange: "descriptionChange", reusableChange: "reusableChange", nestedStepChange: "nestedStepChange", addStep: "addStep", deleteStep: "deleteStep", openExternal: "openExternal", edit: "edit", link: "link", duplicate: "duplicate", delete: "delete", dndDropInZone: "dndDropInZone" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<div [class]=\"'cqa-flex cqa-flex-col'\">\n <!-- Step Group Header -->\n <div [class]=\"'step-row cqa-flex cqa-gap-3 cqa-items-center cqa-py-2 ' + (isInsideLoop ? 'cqa-pl-10 cqa-pr-4' : 'cqa-px-4')\">\n <!-- Expand/Collapse Icon -->\n <button type=\"button\" (click)=\"onToggleExpanded()\" class=\"cqa-p-0\">\n <svg [class.cqa-rotate-180]=\"expanded\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 6L8 10L12 6\" stroke=\"#6B7280\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n\n <!-- Folder Icon -->\n <div>\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M15 15C15.3978 15 15.7794 14.842 16.0607 14.5607C16.342 14.2794 16.5 13.8978 16.5 13.5V6C16.5 5.60217 16.342 5.22064 16.0607 4.93934C15.7794 4.65804 15.3978 4.5 15 4.5H9.075C8.82413 4.50246 8.57666 4.44196 8.35523 4.32403C8.13379 4.20611 7.94547 4.03453 7.8075 3.825L7.2 2.925C7.06342 2.7176 6.87748 2.54736 6.65887 2.42955C6.44027 2.31174 6.19583 2.25004 5.9475 2.25H3C2.60218 2.25 2.22064 2.40804 1.93934 2.68934C1.65804 2.97064 1.5 3.35218 1.5 3.75V13.5C1.5 13.8978 1.65804 14.2794 1.93934 14.5607C2.22064 14.842 2.60218 15 3 15H15Z\"\n fill=\"#EFF6FF\" stroke=\"#60A5FA\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </div>\n\n <!-- Group Name and Description -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-gap-[2px]\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <!-- Group Name Input -->\n <p class=\"cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[18px] cqa-font-bold\">{{groupName}}</p>\n <!-- Reusable Tag -->\n <span *ngIf=\"reusable\"\n class=\"cqa-px-2 cqa-py-[1.5px] cqa-rounded-lg cqa-text-[#3F43EE] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-bg-[#D8D9FC] cqa-border cqa-border-solid cqa-border-[#8A8CF4]\">\n Reusable\n </span>\n </div>\n\n <!-- Description -->\n <p class=\"cqa-text-[#6B7280] cqa-text-[12px] cqa-leading-[15px]\">{{description}}</p>\n </div>\n\n <!-- Steps Summary and Action Icons -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n\n <!-- External Link Icon -->\n <button type=\"button\" (click)=\"onOpenExternal(); $event.stopPropagation()\" title=\"Open in new tab\"\n class=\"cqa-p-0 cqa-text-[#99999E] hover:cqa-text-[#1447E6]\">\n <svg width=\"16\" height=\"17\" viewBox=\"0 0 16 17\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M12 8.66667V12.6667C12 13.0203 11.8595 13.3594 11.6095 13.6095C11.3594 13.8595 11.0203 14 10.6667 14H3.33333C2.97971 14 2.64057 13.8595 2.39052 13.6095C2.14048 13.3594 2 13.0203 2 12.6667V5.33333C2 4.97971 2.14048 4.64057 2.39052 4.39052C2.64057 4.14048 2.97971 4 3.33333 4H7.33333M10 2H14M14 2V6M14 2L6.66667 9.33333\"\n stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </button>\n\n <!-- Steps Summary -->\n <span class=\"cqa-border cqa-border-solid cqa-border-[#E5E5E5] cqa-rounded-lg cqa-py-0.5 cqa-px-2 cqa-text-[#0A0A0A] cqa-text-[12px] cqa-leading-[15px]\">\n {{ getStepsSummary() }}\n </span>\n\n <!-- Action Icons (show on hover, same as API step) -->\n <div class=\"step-actions cqa-flex cqa-items-center cqa-gap-[14px] cqa-ml-auto cqa-px-[7px]\">\n\n <!-- Edit Icon -->\n <button type=\"button\" (click)=\"onEdit(); $event.stopPropagation()\" title=\"Edit\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7 11.6666H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path\n d=\"M9.55208 2.1128C9.7843 1.88058 10.0993 1.75012 10.4277 1.75012C10.7561 1.75012 11.071 1.88058 11.3033 2.1128C11.5355 2.34502 11.6659 2.65998 11.6659 2.98838C11.6659 3.31679 11.5355 3.63175 11.3033 3.86397L4.29742 10.8704C4.15864 11.0092 3.9871 11.1107 3.79867 11.1656L2.12333 11.6544C2.07314 11.669 2.01993 11.6699 1.96928 11.6569C1.91863 11.6439 1.8724 11.6176 1.83543 11.5806C1.79846 11.5437 1.7721 11.4974 1.75913 11.4468C1.74615 11.3961 1.74703 11.3429 1.76167 11.2927L2.2505 9.61738C2.30546 9.42916 2.40698 9.25783 2.54567 9.11922L9.55208 2.1128Z\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </button>\n\n <!-- Link Icon -->\n <button type=\"button\" (click)=\"onLink(); $event.stopPropagation()\" title=\"Link\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g clip-path=\"url(#clip0_609_26588)\">\n <path\n d=\"M5.00065 9.91671H3.66732C2.78326 9.91671 1.93542 9.60942 1.3103 9.06244C0.685174 8.51545 0.333984 7.77359 0.333984 7.00004C0.333984 6.22649 0.685174 5.48463 1.3103 4.93765C1.93542 4.39066 2.78326 4.08337 3.66732 4.08337H5.00065\"\n stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M9 4.08337H10.3333C11.2174 4.08337 12.0652 4.39066 12.6904 4.93765C13.3155 5.48463 13.6667 6.22649 13.6667 7.00004C13.6667 7.77359 13.3155 8.51545 12.6904 9.06244C12.0652 9.60942 11.2174 9.91671 10.3333 9.91671H9\"\n stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M4.33398 7H9.66732\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </g>\n <defs>\n <clipPath id=\"clip0_609_26588\">\n <rect width=\"14\" height=\"14\" fill=\"white\" />\n </clipPath>\n </defs>\n </svg>\n </button>\n\n <!-- Duplicate Icon -->\n <button type=\"button\" (click)=\"onDuplicate(); $event.stopPropagation()\" title=\"Duplicate\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M11.666 4.66663H5.83268C5.18835 4.66663 4.66602 5.18896 4.66602 5.83329V11.6666C4.66602 12.311 5.18835 12.8333 5.83268 12.8333H11.666C12.3103 12.8333 12.8327 12.311 12.8327 11.6666V5.83329C12.8327 5.18896 12.3103 4.66663 11.666 4.66663Z\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M2.33268 9.33329C1.69102 9.33329 1.16602 8.80829 1.16602 8.16663V2.33329C1.16602 1.69163 1.69102 1.16663 2.33268 1.16663H8.16602C8.80768 1.16663 9.33268 1.69163 9.33268 2.33329\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </button>\n\n <!-- Delete Icon -->\n <button type=\"button\" (click)=\"onDelete(); $event.stopPropagation()\" title=\"Delete\" class=\"cqa-p-0 cqa-text-[#ff6467] hover:cqa-text-[#C63535]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1.75 3.5H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path\n d=\"M11.0827 3.5V11.6667C11.0827 12.25 10.4993 12.8333 9.91602 12.8333H4.08268C3.49935 12.8333 2.91602 12.25 2.91602 11.6667V3.5\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M4.66602 3.49996V2.33329C4.66602 1.74996 5.24935 1.16663 5.83268 1.16663H8.16602C8.74935 1.16663 9.33268 1.74996 9.33268 2.33329V3.49996\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M5.83398 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M8.16602 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n </div>\n </div>\n </div>\n\n <!-- Expanded Content with Nested Steps (renderer dispatches by step type, n-level nesting) -->\n <div *ngIf=\"expanded\" class=\"cqa-flex cqa-flex-col\">\n <!-- Loading Indicator -->\n <div *ngIf=\"loading\" class=\"cqa-flex cqa-items-center cqa-justify-center cqa-py-8 cqa-px-4\">\n <div class=\"cqa-flex cqa-flex-col cqa-items-center cqa-gap-3\">\n <!-- Spinner -->\n <svg class=\"cqa-animate-spin cqa-h-6 cqa-w-6 cqa-text-[#3F43EE]\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"cqa-opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"cqa-opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n <span class=\"cqa-text-[#6B7280] cqa-text-sm\">Loading steps...</span>\n </div>\n </div>\n \n <!-- Nested Steps Content (only show when not loading) -->\n <div *ngIf=\"!loading\" class=\"cqa-flex cqa-flex-col\">\n <div class=\"cqa-flex cqa-flex-col\" *ngIf=\"!isReorder\">\n <cqa-test-case-details-renderer\n *ngFor=\"let step of nestedSteps; let i = index\"\n [step]=\"step\"\n [index]=\"i\"\n [isNested]=\"true\"\n [isReorder]=\"isReorder\"\n (nestedStepChange)=\"onNestedStepChange($event.step, $event.index)\"\n (addStep)=\"onAddStep()\"\n (deleteStep)=\"onDeleteStep($event)\"\n (toggleExpanded)=\"onNestedToggleExpanded($event, step, i)\"\n (groupNameChange)=\"$any(step).groupName = $event; onNestedStepChange(step, i)\"\n (descriptionChange)=\"$any(step).description = $event; onNestedStepChange(step, i)\"\n (reusableChange)=\"$any(step).reusable = $event; onNestedStepChange(step, i)\"\n (openExternal)=\"onNestedStepChange(step, i)\"\n (edit)=\"onNestedStepChange(step, i)\"\n (link)=\"onNestedStepChange(step, i)\"\n (duplicate)=\"onNestedStepChange(step, i)\"\n (delete)=\"onDeleteStep(i)\"\n (conditionChange)=\"$any(step).condition = $event; onNestedStepChange(step, i)\"\n (branchStepChange)=\"onNestedStepChange(step, i)\"\n (addBranch)=\"onNestedConditionAddBranch($any(step), i)\"\n (deleteBranch)=\"onNestedConditionDeleteBranch($any(step), $event, i)\"\n (testDataProfileChange)=\"$any(step).testDataProfile = $event; onNestedStepChange(step, i)\"\n (startStepChange)=\"$any(step).startStep = $event; onNestedStepChange(step, i)\"\n (endStepChange)=\"$any(step).endStep = $event; onNestedStepChange(step, i)\"\n (maxIterationsChange)=\"$any(step).maxIterations = $event; onNestedStepChange(step, i)\"\n (eventTypeChange)=\"$any(step).eventType = $event; onNestedStepChange(step, i)\"\n (parameterChange)=\"onNestedStepChange(step, i)\"\n (selectionChange)=\"$any(step).selected = $event; onNestedStepChange(step, i)\"\n (dndDropInZone)=\"dndDropInZone.emit($event)\"\n >\n </cqa-test-case-details-renderer>\n </div>\n <div *ngIf=\"isReorder\" class=\"cqa-flex cqa-flex-col nested-step-drop-list\"\n [dndDropzone]=\"['step']\"\n dndEffectAllowed=\"move\"\n dndDragoverClass=\"dndDragover\"\n (dndDrop)=\"onDndDrop($event)\">\n <div dndPlaceholderRef class=\"step-drag-placeholder-nested cqa-my-1 cqa-min-h-[50px] cqa-border-2 cqa-border-dashed cqa-border-[#3F43EE] cqa-rounded cqa-bg-[rgba(63,67,238,0.08)] cqa-flex cqa-items-center cqa-justify-center cqa-text-[#3F43EE] cqa-text-xs\">Drop here</div>\n <div *ngFor=\"let step of nestedSteps; let i = index\" class=\"nested-step-drag-item\"\n [dndDraggable]=\"step\"\n dndEffectAllowed=\"move\"\n dndType=\"step\">\n <cqa-test-case-details-renderer\n [step]=\"step\"\n [index]=\"i\"\n [isNested]=\"true\"\n [isReorder]=\"isReorder\"\n (nestedStepChange)=\"onNestedStepChange($event.step, $event.index)\"\n (addStep)=\"onAddStep()\"\n (deleteStep)=\"onDeleteStep($event)\"\n (toggleExpanded)=\"onNestedToggleExpanded($event, step, i)\"\n (groupNameChange)=\"$any(step).groupName = $event; onNestedStepChange(step, i)\"\n (descriptionChange)=\"$any(step).description = $event; onNestedStepChange(step, i)\"\n (reusableChange)=\"$any(step).reusable = $event; onNestedStepChange(step, i)\"\n (openExternal)=\"onNestedStepChange(step, i)\"\n (edit)=\"onNestedStepChange(step, i)\"\n (link)=\"onNestedStepChange(step, i)\"\n (duplicate)=\"onNestedStepChange(step, i)\"\n (delete)=\"onDeleteStep(i)\"\n (conditionChange)=\"$any(step).condition = $event; onNestedStepChange(step, i)\"\n (branchStepChange)=\"onNestedStepChange(step, i)\"\n (addBranch)=\"onNestedConditionAddBranch($any(step), i)\"\n (deleteBranch)=\"onNestedConditionDeleteBranch($any(step), $event, i)\"\n (testDataProfileChange)=\"$any(step).testDataProfile = $event; onNestedStepChange(step, i)\"\n (startStepChange)=\"$any(step).startStep = $event; onNestedStepChange(step, i)\"\n (endStepChange)=\"$any(step).endStep = $event; onNestedStepChange(step, i)\"\n (maxIterationsChange)=\"$any(step).maxIterations = $event; onNestedStepChange(step, i)\"\n (eventTypeChange)=\"$any(step).eventType = $event; onNestedStepChange(step, i)\"\n (parameterChange)=\"onNestedStepChange(step, i)\"\n (selectionChange)=\"$any(step).selected = $event; onNestedStepChange(step, i)\"\n (dndDropInZone)=\"dndDropInZone.emit($event)\"\n >\n </cqa-test-case-details-renderer>\n </div>\n </div>\n\n <!-- END GROUP Marker -->\n <div [class]=\"'cqa-pl-8 cqa-py-2 cqa-border-t cqa-border-[#D1C4E9] cqa-bg-[#D1C4E9]'\">\n <span class=\"cqa-font-bold cqa-text-white cqa-text-sm cqa-uppercase\">\n END GROUP\n </span>\n </div>\n </div>\n </div>\n</div>", styles: [".step-actions{opacity:0;transition:opacity .15s ease}.step-row:hover .step-actions{opacity:1}\n"], components: [{ type: TestCaseDetailsRendererComponent, selector: "cqa-test-case-details-renderer", inputs: ["step", "index", "isNested", "isInsideLoop", "branch", "isReorder"], outputs: ["nestedStepChange", "addStep", "deleteStep", "toggleExpanded", "groupNameChange", "descriptionChange", "reusableChange", "openExternal", "edit", "link", "duplicate", "delete", "viewDetails", "selectionChange", "conditionChange", "branchStepChange", "addStepForBranch", "deleteStepWithBranch", "addBranch", "deleteBranch", "testDataProfileChange", "startStepChange", "endStepChange", "maxIterationsChange", "eventTypeChange", "parameterChange", "dndDropInZone"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i7.DndDropzoneDirective, selector: "[dndDropzone]", inputs: ["dndDropzone", "dndEffectAllowed", "dndAllowExternal", "dndHorizontal", "dndDragoverClass", "dndDropzoneDisabledClass", "dndDisableIf", "dndDisableDropIf"], outputs: ["dndDragover", "dndDrop"] }, { type: i7.DndPlaceholderRefDirective, selector: "[dndPlaceholderRef]" }, { type: i7.DndDraggableDirective, selector: "[dndDraggable]", inputs: ["dndDraggable", "dndEffectAllowed", "dndType", "dndDraggingClass", "dndDraggingSourceClass", "dndDraggableDisabledClass", "dndDragImageOffsetFunction", "dndDisableIf", "dndDisableDragIf"], outputs: ["dndStart", "dndDrag", "dndEnd", "dndMoved", "dndCopied", "dndLinked", "dndCanceled"] }] });
18352
+ TestCaseStepGroupComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TestCaseStepGroupComponent, selector: "cqa-test-case-step-group", inputs: { config: "config", id: "id", stepNumber: "stepNumber", groupName: "groupName", description: "description", reusable: "reusable", nestedSteps: "nestedSteps", expanded: "expanded", isNested: "isNested", isInsideLoop: "isInsideLoop", isReorder: "isReorder", loading: "loading" }, outputs: { toggleExpanded: "toggleExpanded", groupNameChange: "groupNameChange", descriptionChange: "descriptionChange", reusableChange: "reusableChange", nestedStepChange: "nestedStepChange", addStep: "addStep", deleteStep: "deleteStep", openExternal: "openExternal", edit: "edit", link: "link", duplicate: "duplicate", delete: "delete", dndDropInZone: "dndDropInZone" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<div [class]=\"'cqa-flex cqa-flex-col'\">\n <!-- Step Group Header -->\n <div [class]=\"'step-row cqa-flex cqa-gap-3 cqa-items-center cqa-py-2 ' + (isInsideLoop ? 'cqa-pl-10 cqa-pr-4' : 'cqa-px-4')\">\n <!-- Expand/Collapse Icon -->\n <button type=\"button\" (click)=\"onToggleExpanded()\" class=\"cqa-p-0\">\n <svg [class.cqa-rotate-180]=\"expanded\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 6L8 10L12 6\" stroke=\"#6B7280\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n\n <!-- Folder Icon -->\n <div>\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M15 15C15.3978 15 15.7794 14.842 16.0607 14.5607C16.342 14.2794 16.5 13.8978 16.5 13.5V6C16.5 5.60217 16.342 5.22064 16.0607 4.93934C15.7794 4.65804 15.3978 4.5 15 4.5H9.075C8.82413 4.50246 8.57666 4.44196 8.35523 4.32403C8.13379 4.20611 7.94547 4.03453 7.8075 3.825L7.2 2.925C7.06342 2.7176 6.87748 2.54736 6.65887 2.42955C6.44027 2.31174 6.19583 2.25004 5.9475 2.25H3C2.60218 2.25 2.22064 2.40804 1.93934 2.68934C1.65804 2.97064 1.5 3.35218 1.5 3.75V13.5C1.5 13.8978 1.65804 14.2794 1.93934 14.5607C2.22064 14.842 2.60218 15 3 15H15Z\"\n fill=\"#EFF6FF\" stroke=\"#60A5FA\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </div>\n\n <!-- Group Name and Description -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-gap-[2px]\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <!-- Group Name Input -->\n <p class=\"cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[18px] cqa-font-bold\">{{groupName}}</p>\n <!-- Reusable Tag -->\n <span *ngIf=\"reusable\"\n class=\"cqa-px-2 cqa-py-[1.5px] cqa-rounded-lg cqa-text-[#3F43EE] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-bg-[#D8D9FC] cqa-border cqa-border-solid cqa-border-[#8A8CF4]\">\n Reusable\n </span>\n </div>\n\n <!-- Description -->\n <p class=\"cqa-text-[#6B7280] cqa-text-[12px] cqa-leading-[15px]\">{{description}}</p>\n </div>\n\n <!-- Steps Summary and Action Icons -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n\n <!-- External Link Icon -->\n <button type=\"button\" (click)=\"onOpenExternal(); $event.stopPropagation()\" title=\"Open in new tab\"\n class=\"cqa-p-0 cqa-text-[#99999E] hover:cqa-text-[#1447E6]\">\n <svg width=\"16\" height=\"17\" viewBox=\"0 0 16 17\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M12 8.66667V12.6667C12 13.0203 11.8595 13.3594 11.6095 13.6095C11.3594 13.8595 11.0203 14 10.6667 14H3.33333C2.97971 14 2.64057 13.8595 2.39052 13.6095C2.14048 13.3594 2 13.0203 2 12.6667V5.33333C2 4.97971 2.14048 4.64057 2.39052 4.39052C2.64057 4.14048 2.97971 4 3.33333 4H7.33333M10 2H14M14 2V6M14 2L6.66667 9.33333\"\n stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </button>\n\n <!-- Steps Summary -->\n <span class=\"cqa-border cqa-border-solid cqa-border-[#E5E5E5] cqa-rounded-lg cqa-py-0.5 cqa-px-2 cqa-text-[#0A0A0A] cqa-text-[12px] cqa-leading-[15px]\">\n {{ getStepsSummary() }}\n </span>\n\n <!-- Action Icons (show on hover, same as API step) -->\n <div class=\"step-actions cqa-flex cqa-items-center cqa-gap-[14px] cqa-ml-auto cqa-px-[7px]\">\n\n <!-- Edit Icon -->\n <button type=\"button\" (click)=\"onEdit(); $event.stopPropagation()\" title=\"Edit\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7 11.6666H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path\n d=\"M9.55208 2.1128C9.7843 1.88058 10.0993 1.75012 10.4277 1.75012C10.7561 1.75012 11.071 1.88058 11.3033 2.1128C11.5355 2.34502 11.6659 2.65998 11.6659 2.98838C11.6659 3.31679 11.5355 3.63175 11.3033 3.86397L4.29742 10.8704C4.15864 11.0092 3.9871 11.1107 3.79867 11.1656L2.12333 11.6544C2.07314 11.669 2.01993 11.6699 1.96928 11.6569C1.91863 11.6439 1.8724 11.6176 1.83543 11.5806C1.79846 11.5437 1.7721 11.4974 1.75913 11.4468C1.74615 11.3961 1.74703 11.3429 1.76167 11.2927L2.2505 9.61738C2.30546 9.42916 2.40698 9.25783 2.54567 9.11922L9.55208 2.1128Z\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </button>\n\n <!-- Link Icon -->\n <button type=\"button\" (click)=\"onLink(); $event.stopPropagation()\" title=\"Link\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g clip-path=\"url(#clip0_609_26588)\">\n <path\n d=\"M5.00065 9.91671H3.66732C2.78326 9.91671 1.93542 9.60942 1.3103 9.06244C0.685174 8.51545 0.333984 7.77359 0.333984 7.00004C0.333984 6.22649 0.685174 5.48463 1.3103 4.93765C1.93542 4.39066 2.78326 4.08337 3.66732 4.08337H5.00065\"\n stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M9 4.08337H10.3333C11.2174 4.08337 12.0652 4.39066 12.6904 4.93765C13.3155 5.48463 13.6667 6.22649 13.6667 7.00004C13.6667 7.77359 13.3155 8.51545 12.6904 9.06244C12.0652 9.60942 11.2174 9.91671 10.3333 9.91671H9\"\n stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M4.33398 7H9.66732\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </g>\n <defs>\n <clipPath id=\"clip0_609_26588\">\n <rect width=\"14\" height=\"14\" fill=\"white\" />\n </clipPath>\n </defs>\n </svg>\n </button>\n\n <!-- Duplicate Icon -->\n <button type=\"button\" (click)=\"onDuplicate(); $event.stopPropagation()\" title=\"Duplicate\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M11.666 4.66663H5.83268C5.18835 4.66663 4.66602 5.18896 4.66602 5.83329V11.6666C4.66602 12.311 5.18835 12.8333 5.83268 12.8333H11.666C12.3103 12.8333 12.8327 12.311 12.8327 11.6666V5.83329C12.8327 5.18896 12.3103 4.66663 11.666 4.66663Z\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M2.33268 9.33329C1.69102 9.33329 1.16602 8.80829 1.16602 8.16663V2.33329C1.16602 1.69163 1.69102 1.16663 2.33268 1.16663H8.16602C8.80768 1.16663 9.33268 1.69163 9.33268 2.33329\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </button>\n\n <!-- Delete Icon -->\n <button type=\"button\" (click)=\"onDelete(); $event.stopPropagation()\" title=\"Delete\" class=\"cqa-p-0 cqa-text-[#ff6467] hover:cqa-text-[#C63535]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1.75 3.5H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path\n d=\"M11.0827 3.5V11.6667C11.0827 12.25 10.4993 12.8333 9.91602 12.8333H4.08268C3.49935 12.8333 2.91602 12.25 2.91602 11.6667V3.5\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M4.66602 3.49996V2.33329C4.66602 1.74996 5.24935 1.16663 5.83268 1.16663H8.16602C8.74935 1.16663 9.33268 1.74996 9.33268 2.33329V3.49996\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M5.83398 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M8.16602 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n </div>\n </div>\n </div>\n\n <!-- Expanded Content with Nested Steps (renderer dispatches by step type, n-level nesting) -->\n <div *ngIf=\"expanded\" class=\"cqa-flex cqa-flex-col\">\n <!-- Loading Indicator -->\n <div *ngIf=\"loading\" class=\"cqa-flex cqa-items-center cqa-justify-center cqa-py-8 cqa-px-4\">\n <div class=\"cqa-flex cqa-flex-col cqa-items-center cqa-gap-3\">\n <!-- Spinner -->\n <svg class=\"cqa-animate-spin cqa-h-6 cqa-w-6 cqa-text-[#3F43EE]\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"cqa-opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"cqa-opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n <span class=\"cqa-text-[#6B7280] cqa-text-sm\">Loading steps...</span>\n </div>\n </div>\n \n <!-- Nested Steps Content (only show when not loading) -->\n <div *ngIf=\"!loading\" class=\"cqa-flex cqa-flex-col\">\n <div class=\"cqa-flex cqa-flex-col\" *ngIf=\"!isReorder\">\n <cqa-test-case-details-renderer\n *ngFor=\"let step of nestedSteps; let i = index\"\n [step]=\"step\"\n [index]=\"i\"\n [isNested]=\"true\"\n [isReorder]=\"isReorder\"\n (nestedStepChange)=\"onNestedStepChange($event.step, $event.index)\"\n (addStep)=\"onAddStep()\"\n (deleteStep)=\"onDeleteStep($event)\"\n (toggleExpanded)=\"onNestedToggleExpanded($event, step, i)\"\n (groupNameChange)=\"$any(step).groupName = $event; onNestedStepChange(step, i)\"\n (descriptionChange)=\"$any(step).description = $event; onNestedStepChange(step, i)\"\n (reusableChange)=\"$any(step).reusable = $event; onNestedStepChange(step, i)\"\n (openExternal)=\"onNestedStepChange(step, i)\"\n (edit)=\"onNestedStepChange(step, i)\"\n (link)=\"onNestedStepChange(step, i)\"\n (duplicate)=\"onNestedStepChange(step, i)\"\n (delete)=\"onDeleteStep(i)\"\n (conditionChange)=\"$any(step).condition = $event; onNestedStepChange(step, i)\"\n (branchStepChange)=\"onNestedStepChange(step, i)\"\n (addBranch)=\"onNestedConditionAddBranch($any(step), i)\"\n (deleteBranch)=\"onNestedConditionDeleteBranch($any(step), $event, i)\"\n (testDataProfileChange)=\"$any(step).testDataProfile = $event; onNestedStepChange(step, i)\"\n (startStepChange)=\"$any(step).startStep = $event; onNestedStepChange(step, i)\"\n (endStepChange)=\"$any(step).endStep = $event; onNestedStepChange(step, i)\"\n (maxIterationsChange)=\"$any(step).maxIterations = $event; onNestedStepChange(step, i)\"\n (eventTypeChange)=\"$any(step).eventType = $event; onNestedStepChange(step, i)\"\n (parameterChange)=\"onNestedStepChange(step, i)\"\n (selectionChange)=\"$any(step).selected = $event; onNestedStepChange(step, i)\"\n (dndDropInZone)=\"dndDropInZone.emit($event)\"\n >\n </cqa-test-case-details-renderer>\n </div>\n <div *ngIf=\"isReorder\" class=\"cqa-flex cqa-flex-col nested-step-drop-list\"\n [dndDropzone]=\"['step']\"\n dndEffectAllowed=\"move\"\n dndDragoverClass=\"dndDragover\"\n (dndDrop)=\"onDndDrop($event)\">\n <div dndPlaceholderRef class=\"step-drag-placeholder-nested cqa-my-1 cqa-min-h-[50px] cqa-border-2 cqa-border-dashed cqa-border-[#3F43EE] cqa-rounded cqa-bg-[rgba(63,67,238,0.08)] cqa-flex cqa-items-center cqa-justify-center cqa-text-[#3F43EE] cqa-text-xs\">Drop here</div>\n <div *ngFor=\"let step of nestedSteps; let i = index\" class=\"nested-step-drag-item\"\n [dndDraggable]=\"step\"\n dndEffectAllowed=\"move\"\n dndType=\"step\">\n <cqa-test-case-details-renderer\n [step]=\"step\"\n [index]=\"i\"\n [isNested]=\"true\"\n [isReorder]=\"isReorder\"\n (nestedStepChange)=\"onNestedStepChange($event.step, $event.index)\"\n (addStep)=\"onAddStep()\"\n (deleteStep)=\"onDeleteStep($event)\"\n (toggleExpanded)=\"onNestedToggleExpanded($event, step, i)\"\n (groupNameChange)=\"$any(step).groupName = $event; onNestedStepChange(step, i)\"\n (descriptionChange)=\"$any(step).description = $event; onNestedStepChange(step, i)\"\n (reusableChange)=\"$any(step).reusable = $event; onNestedStepChange(step, i)\"\n (openExternal)=\"onNestedStepChange(step, i)\"\n (edit)=\"onNestedStepChange(step, i)\"\n (link)=\"onNestedStepChange(step, i)\"\n (duplicate)=\"onNestedStepChange(step, i)\"\n (delete)=\"onDeleteStep(i)\"\n (conditionChange)=\"$any(step).condition = $event; onNestedStepChange(step, i)\"\n (branchStepChange)=\"onNestedStepChange(step, i)\"\n (addBranch)=\"onNestedConditionAddBranch($any(step), i)\"\n (deleteBranch)=\"onNestedConditionDeleteBranch($any(step), $event, i)\"\n (testDataProfileChange)=\"$any(step).testDataProfile = $event; onNestedStepChange(step, i)\"\n (startStepChange)=\"$any(step).startStep = $event; onNestedStepChange(step, i)\"\n (endStepChange)=\"$any(step).endStep = $event; onNestedStepChange(step, i)\"\n (maxIterationsChange)=\"$any(step).maxIterations = $event; onNestedStepChange(step, i)\"\n (eventTypeChange)=\"$any(step).eventType = $event; onNestedStepChange(step, i)\"\n (parameterChange)=\"onNestedStepChange(step, i)\"\n (selectionChange)=\"$any(step).selected = $event; onNestedStepChange(step, i)\"\n (dndDropInZone)=\"dndDropInZone.emit($event)\"\n >\n </cqa-test-case-details-renderer>\n </div>\n </div>\n\n <!-- END GROUP Marker -->\n <div [class]=\"'cqa-pl-8 cqa-py-2 cqa-border-t cqa-border-[#D1C4E9] cqa-bg-[#D1C4E9]'\">\n <span class=\"cqa-font-bold cqa-text-white cqa-text-sm cqa-uppercase\">\n END GROUP\n </span>\n </div>\n </div>\n </div>\n</div>", styles: [".step-actions{opacity:0;transition:opacity .15s ease}.step-row:hover .step-actions{opacity:1}\n"], components: [{ type: TestCaseDetailsRendererComponent, selector: "cqa-test-case-details-renderer", inputs: ["step", "index", "isNested", "isInsideLoop", "branch", "isReorder", "addStepBetween"], outputs: ["nestedStepChange", "addStep", "deleteStep", "toggleExpanded", "groupNameChange", "descriptionChange", "reusableChange", "openExternal", "edit", "link", "duplicate", "delete", "viewDetails", "selectionChange", "conditionChange", "branchStepChange", "addStepForBranch", "deleteStepWithBranch", "addBranch", "deleteBranch", "testDataProfileChange", "startStepChange", "endStepChange", "maxIterationsChange", "eventTypeChange", "parameterChange", "clickAction", "dndDropInZone", "addStepBetweenClick"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i7.DndDropzoneDirective, selector: "[dndDropzone]", inputs: ["dndDropzone", "dndEffectAllowed", "dndAllowExternal", "dndHorizontal", "dndDragoverClass", "dndDropzoneDisabledClass", "dndDisableIf", "dndDisableDropIf"], outputs: ["dndDragover", "dndDrop"] }, { type: i7.DndPlaceholderRefDirective, selector: "[dndPlaceholderRef]" }, { type: i7.DndDraggableDirective, selector: "[dndDraggable]", inputs: ["dndDraggable", "dndEffectAllowed", "dndType", "dndDraggingClass", "dndDraggingSourceClass", "dndDraggableDisabledClass", "dndDragImageOffsetFunction", "dndDisableIf", "dndDisableDragIf"], outputs: ["dndStart", "dndDrag", "dndEnd", "dndMoved", "dndCopied", "dndLinked", "dndCanceled"] }] });
18460
18353
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestCaseStepGroupComponent, decorators: [{
18461
18354
  type: Component,
18462
18355
  args: [{ selector: 'cqa-test-case-step-group', host: { class: 'cqa-ui-root' }, styles: [STEP_ROW_ACTIONS_STYLES], template: "<div [class]=\"'cqa-flex cqa-flex-col'\">\n <!-- Step Group Header -->\n <div [class]=\"'step-row cqa-flex cqa-gap-3 cqa-items-center cqa-py-2 ' + (isInsideLoop ? 'cqa-pl-10 cqa-pr-4' : 'cqa-px-4')\">\n <!-- Expand/Collapse Icon -->\n <button type=\"button\" (click)=\"onToggleExpanded()\" class=\"cqa-p-0\">\n <svg [class.cqa-rotate-180]=\"expanded\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 6L8 10L12 6\" stroke=\"#6B7280\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n\n <!-- Folder Icon -->\n <div>\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M15 15C15.3978 15 15.7794 14.842 16.0607 14.5607C16.342 14.2794 16.5 13.8978 16.5 13.5V6C16.5 5.60217 16.342 5.22064 16.0607 4.93934C15.7794 4.65804 15.3978 4.5 15 4.5H9.075C8.82413 4.50246 8.57666 4.44196 8.35523 4.32403C8.13379 4.20611 7.94547 4.03453 7.8075 3.825L7.2 2.925C7.06342 2.7176 6.87748 2.54736 6.65887 2.42955C6.44027 2.31174 6.19583 2.25004 5.9475 2.25H3C2.60218 2.25 2.22064 2.40804 1.93934 2.68934C1.65804 2.97064 1.5 3.35218 1.5 3.75V13.5C1.5 13.8978 1.65804 14.2794 1.93934 14.5607C2.22064 14.842 2.60218 15 3 15H15Z\"\n fill=\"#EFF6FF\" stroke=\"#60A5FA\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </div>\n\n <!-- Group Name and Description -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-gap-[2px]\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <!-- Group Name Input -->\n <p class=\"cqa-text-[#3F43EE] cqa-text-[14px] cqa-leading-[18px] cqa-font-bold\">{{groupName}}</p>\n <!-- Reusable Tag -->\n <span *ngIf=\"reusable\"\n class=\"cqa-px-2 cqa-py-[1.5px] cqa-rounded-lg cqa-text-[#3F43EE] cqa-text-[10px] cqa-leading-[15px] cqa-font-medium cqa-bg-[#D8D9FC] cqa-border cqa-border-solid cqa-border-[#8A8CF4]\">\n Reusable\n </span>\n </div>\n\n <!-- Description -->\n <p class=\"cqa-text-[#6B7280] cqa-text-[12px] cqa-leading-[15px]\">{{description}}</p>\n </div>\n\n <!-- Steps Summary and Action Icons -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n\n <!-- External Link Icon -->\n <button type=\"button\" (click)=\"onOpenExternal(); $event.stopPropagation()\" title=\"Open in new tab\"\n class=\"cqa-p-0 cqa-text-[#99999E] hover:cqa-text-[#1447E6]\">\n <svg width=\"16\" height=\"17\" viewBox=\"0 0 16 17\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M12 8.66667V12.6667C12 13.0203 11.8595 13.3594 11.6095 13.6095C11.3594 13.8595 11.0203 14 10.6667 14H3.33333C2.97971 14 2.64057 13.8595 2.39052 13.6095C2.14048 13.3594 2 13.0203 2 12.6667V5.33333C2 4.97971 2.14048 4.64057 2.39052 4.39052C2.64057 4.14048 2.97971 4 3.33333 4H7.33333M10 2H14M14 2V6M14 2L6.66667 9.33333\"\n stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </button>\n\n <!-- Steps Summary -->\n <span class=\"cqa-border cqa-border-solid cqa-border-[#E5E5E5] cqa-rounded-lg cqa-py-0.5 cqa-px-2 cqa-text-[#0A0A0A] cqa-text-[12px] cqa-leading-[15px]\">\n {{ getStepsSummary() }}\n </span>\n\n <!-- Action Icons (show on hover, same as API step) -->\n <div class=\"step-actions cqa-flex cqa-items-center cqa-gap-[14px] cqa-ml-auto cqa-px-[7px]\">\n\n <!-- Edit Icon -->\n <button type=\"button\" (click)=\"onEdit(); $event.stopPropagation()\" title=\"Edit\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7 11.6666H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path\n d=\"M9.55208 2.1128C9.7843 1.88058 10.0993 1.75012 10.4277 1.75012C10.7561 1.75012 11.071 1.88058 11.3033 2.1128C11.5355 2.34502 11.6659 2.65998 11.6659 2.98838C11.6659 3.31679 11.5355 3.63175 11.3033 3.86397L4.29742 10.8704C4.15864 11.0092 3.9871 11.1107 3.79867 11.1656L2.12333 11.6544C2.07314 11.669 2.01993 11.6699 1.96928 11.6569C1.91863 11.6439 1.8724 11.6176 1.83543 11.5806C1.79846 11.5437 1.7721 11.4974 1.75913 11.4468C1.74615 11.3961 1.74703 11.3429 1.76167 11.2927L2.2505 9.61738C2.30546 9.42916 2.40698 9.25783 2.54567 9.11922L9.55208 2.1128Z\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </button>\n\n <!-- Link Icon -->\n <button type=\"button\" (click)=\"onLink(); $event.stopPropagation()\" title=\"Link\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g clip-path=\"url(#clip0_609_26588)\">\n <path\n d=\"M5.00065 9.91671H3.66732C2.78326 9.91671 1.93542 9.60942 1.3103 9.06244C0.685174 8.51545 0.333984 7.77359 0.333984 7.00004C0.333984 6.22649 0.685174 5.48463 1.3103 4.93765C1.93542 4.39066 2.78326 4.08337 3.66732 4.08337H5.00065\"\n stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M9 4.08337H10.3333C11.2174 4.08337 12.0652 4.39066 12.6904 4.93765C13.3155 5.48463 13.6667 6.22649 13.6667 7.00004C13.6667 7.77359 13.3155 8.51545 12.6904 9.06244C12.0652 9.60942 11.2174 9.91671 10.3333 9.91671H9\"\n stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M4.33398 7H9.66732\" stroke=\"currentColor\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </g>\n <defs>\n <clipPath id=\"clip0_609_26588\">\n <rect width=\"14\" height=\"14\" fill=\"white\" />\n </clipPath>\n </defs>\n </svg>\n </button>\n\n <!-- Duplicate Icon -->\n <button type=\"button\" (click)=\"onDuplicate(); $event.stopPropagation()\" title=\"Duplicate\" class=\"cqa-p-0 cqa-text-[#99A1Af] hover:cqa-text-[#1447E6]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M11.666 4.66663H5.83268C5.18835 4.66663 4.66602 5.18896 4.66602 5.83329V11.6666C4.66602 12.311 5.18835 12.8333 5.83268 12.8333H11.666C12.3103 12.8333 12.8327 12.311 12.8327 11.6666V5.83329C12.8327 5.18896 12.3103 4.66663 11.666 4.66663Z\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M2.33268 9.33329C1.69102 9.33329 1.16602 8.80829 1.16602 8.16663V2.33329C1.16602 1.69163 1.69102 1.16663 2.33268 1.16663H8.16602C8.80768 1.16663 9.33268 1.69163 9.33268 2.33329\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </button>\n\n <!-- Delete Icon -->\n <button type=\"button\" (click)=\"onDelete(); $event.stopPropagation()\" title=\"Delete\" class=\"cqa-p-0 cqa-text-[#ff6467] hover:cqa-text-[#C63535]\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1.75 3.5H12.25\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path\n d=\"M11.0827 3.5V11.6667C11.0827 12.25 10.4993 12.8333 9.91602 12.8333H4.08268C3.49935 12.8333 2.91602 12.25 2.91602 11.6667V3.5\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path\n d=\"M4.66602 3.49996V2.33329C4.66602 1.74996 5.24935 1.16663 5.83268 1.16663H8.16602C8.74935 1.16663 9.33268 1.74996 9.33268 2.33329V3.49996\"\n stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M5.83398 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M8.16602 6.41663V9.91663\" stroke=\"currentColor\" stroke-width=\"1.16667\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n </div>\n </div>\n </div>\n\n <!-- Expanded Content with Nested Steps (renderer dispatches by step type, n-level nesting) -->\n <div *ngIf=\"expanded\" class=\"cqa-flex cqa-flex-col\">\n <!-- Loading Indicator -->\n <div *ngIf=\"loading\" class=\"cqa-flex cqa-items-center cqa-justify-center cqa-py-8 cqa-px-4\">\n <div class=\"cqa-flex cqa-flex-col cqa-items-center cqa-gap-3\">\n <!-- Spinner -->\n <svg class=\"cqa-animate-spin cqa-h-6 cqa-w-6 cqa-text-[#3F43EE]\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"cqa-opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"cqa-opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n <span class=\"cqa-text-[#6B7280] cqa-text-sm\">Loading steps...</span>\n </div>\n </div>\n \n <!-- Nested Steps Content (only show when not loading) -->\n <div *ngIf=\"!loading\" class=\"cqa-flex cqa-flex-col\">\n <div class=\"cqa-flex cqa-flex-col\" *ngIf=\"!isReorder\">\n <cqa-test-case-details-renderer\n *ngFor=\"let step of nestedSteps; let i = index\"\n [step]=\"step\"\n [index]=\"i\"\n [isNested]=\"true\"\n [isReorder]=\"isReorder\"\n (nestedStepChange)=\"onNestedStepChange($event.step, $event.index)\"\n (addStep)=\"onAddStep()\"\n (deleteStep)=\"onDeleteStep($event)\"\n (toggleExpanded)=\"onNestedToggleExpanded($event, step, i)\"\n (groupNameChange)=\"$any(step).groupName = $event; onNestedStepChange(step, i)\"\n (descriptionChange)=\"$any(step).description = $event; onNestedStepChange(step, i)\"\n (reusableChange)=\"$any(step).reusable = $event; onNestedStepChange(step, i)\"\n (openExternal)=\"onNestedStepChange(step, i)\"\n (edit)=\"onNestedStepChange(step, i)\"\n (link)=\"onNestedStepChange(step, i)\"\n (duplicate)=\"onNestedStepChange(step, i)\"\n (delete)=\"onDeleteStep(i)\"\n (conditionChange)=\"$any(step).condition = $event; onNestedStepChange(step, i)\"\n (branchStepChange)=\"onNestedStepChange(step, i)\"\n (addBranch)=\"onNestedConditionAddBranch($any(step), i)\"\n (deleteBranch)=\"onNestedConditionDeleteBranch($any(step), $event, i)\"\n (testDataProfileChange)=\"$any(step).testDataProfile = $event; onNestedStepChange(step, i)\"\n (startStepChange)=\"$any(step).startStep = $event; onNestedStepChange(step, i)\"\n (endStepChange)=\"$any(step).endStep = $event; onNestedStepChange(step, i)\"\n (maxIterationsChange)=\"$any(step).maxIterations = $event; onNestedStepChange(step, i)\"\n (eventTypeChange)=\"$any(step).eventType = $event; onNestedStepChange(step, i)\"\n (parameterChange)=\"onNestedStepChange(step, i)\"\n (selectionChange)=\"$any(step).selected = $event; onNestedStepChange(step, i)\"\n (dndDropInZone)=\"dndDropInZone.emit($event)\"\n >\n </cqa-test-case-details-renderer>\n </div>\n <div *ngIf=\"isReorder\" class=\"cqa-flex cqa-flex-col nested-step-drop-list\"\n [dndDropzone]=\"['step']\"\n dndEffectAllowed=\"move\"\n dndDragoverClass=\"dndDragover\"\n (dndDrop)=\"onDndDrop($event)\">\n <div dndPlaceholderRef class=\"step-drag-placeholder-nested cqa-my-1 cqa-min-h-[50px] cqa-border-2 cqa-border-dashed cqa-border-[#3F43EE] cqa-rounded cqa-bg-[rgba(63,67,238,0.08)] cqa-flex cqa-items-center cqa-justify-center cqa-text-[#3F43EE] cqa-text-xs\">Drop here</div>\n <div *ngFor=\"let step of nestedSteps; let i = index\" class=\"nested-step-drag-item\"\n [dndDraggable]=\"step\"\n dndEffectAllowed=\"move\"\n dndType=\"step\">\n <cqa-test-case-details-renderer\n [step]=\"step\"\n [index]=\"i\"\n [isNested]=\"true\"\n [isReorder]=\"isReorder\"\n (nestedStepChange)=\"onNestedStepChange($event.step, $event.index)\"\n (addStep)=\"onAddStep()\"\n (deleteStep)=\"onDeleteStep($event)\"\n (toggleExpanded)=\"onNestedToggleExpanded($event, step, i)\"\n (groupNameChange)=\"$any(step).groupName = $event; onNestedStepChange(step, i)\"\n (descriptionChange)=\"$any(step).description = $event; onNestedStepChange(step, i)\"\n (reusableChange)=\"$any(step).reusable = $event; onNestedStepChange(step, i)\"\n (openExternal)=\"onNestedStepChange(step, i)\"\n (edit)=\"onNestedStepChange(step, i)\"\n (link)=\"onNestedStepChange(step, i)\"\n (duplicate)=\"onNestedStepChange(step, i)\"\n (delete)=\"onDeleteStep(i)\"\n (conditionChange)=\"$any(step).condition = $event; onNestedStepChange(step, i)\"\n (branchStepChange)=\"onNestedStepChange(step, i)\"\n (addBranch)=\"onNestedConditionAddBranch($any(step), i)\"\n (deleteBranch)=\"onNestedConditionDeleteBranch($any(step), $event, i)\"\n (testDataProfileChange)=\"$any(step).testDataProfile = $event; onNestedStepChange(step, i)\"\n (startStepChange)=\"$any(step).startStep = $event; onNestedStepChange(step, i)\"\n (endStepChange)=\"$any(step).endStep = $event; onNestedStepChange(step, i)\"\n (maxIterationsChange)=\"$any(step).maxIterations = $event; onNestedStepChange(step, i)\"\n (eventTypeChange)=\"$any(step).eventType = $event; onNestedStepChange(step, i)\"\n (parameterChange)=\"onNestedStepChange(step, i)\"\n (selectionChange)=\"$any(step).selected = $event; onNestedStepChange(step, i)\"\n (dndDropInZone)=\"dndDropInZone.emit($event)\"\n >\n </cqa-test-case-details-renderer>\n </div>\n </div>\n\n <!-- END GROUP Marker -->\n <div [class]=\"'cqa-pl-8 cqa-py-2 cqa-border-t cqa-border-[#D1C4E9] cqa-bg-[#D1C4E9]'\">\n <span class=\"cqa-font-bold cqa-text-white cqa-text-sm cqa-uppercase\">\n END GROUP\n </span>\n </div>\n </div>\n </div>\n</div>" }]
@@ -20807,10 +20700,10 @@ class StepBuilderDatabaseComponent {
20807
20700
  }
20808
20701
  }
20809
20702
  StepBuilderDatabaseComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepBuilderDatabaseComponent, deps: [{ token: i2$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
20810
- StepBuilderDatabaseComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StepBuilderDatabaseComponent, selector: "cqa-step-builder-database", inputs: { dbEnvironmentOptions: "dbEnvironmentOptions", queries: "queries", queryResults: "queryResults", isLoading: "isLoading" }, outputs: { createStep: "createStep", cancelled: "cancelled", runQuery: "runQuery", addQuery: "addQuery", deleteQuery: "deleteQuery" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Create Database Test Step\n </h2>\n\n <!-- DB Environment Section -->\n <div class=\"cqa-flex cqa-items-start cqa-gap-4 cqa-mb-6\">\n <div class=\"cqa-flex-1\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5 cqa-block\">\n DB Environment <span class=\"cqa-text-red-500\">*</span>\n </label>\n <cqa-dynamic-select\n [form]=\"databaseForm\"\n [config]=\"getDbEnvironmentConfig()\">\n </cqa-dynamic-select>\n <p class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">\n Uses Database environments from Environments.\n </p>\n </div>\n <div class=\"cqa-flex cqa-items-end cqa-mb-1\">\n <cqa-button\n variant=\"filled\"\n text=\"Run Query\"\n [customClass]=\"'cqa-whitespace-nowrap'\"\n (clicked)=\"onRunQuery()\"\n [disabled]=\"!databaseForm.get('dbEnvironment')?.value || isLoading\">\n </cqa-button>\n </div>\n </div>\n\n <!-- Main Content: Two Column Layout -->\n <div class=\"cqa-flex cqa-gap-4 cqa-flex-1 cqa-overflow-hidden cqa-mb-6\">\n <!-- Left Panel: Query List -->\n <div class=\"cqa-w-64 cqa-flex-shrink-0 cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden\">\n <div class=\"cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Queries</h3>\n </div>\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-p-2\">\n <div *ngFor=\"let query of queries; let i = index\"\n class=\"cqa-flex cqa-items-center cqa-justify-between cqa-p-2 cqa-rounded cqa-cursor-pointer cqa-mb-1\"\n [class.cqa-bg-blue-50]=\"selectedQueryIndex === i\"\n [class.cqa-border]=\"selectedQueryIndex === i\"\n [class.cqa-border-blue-500]=\"selectedQueryIndex === i\"\n (click)=\"onSelectQuery(i)\">\n <span class=\"cqa-text-sm cqa-font-medium cqa-text-gray-900\">Query {{ i + 1 }}</span>\n <cqa-badge\n *ngIf=\"query.status\"\n [label]=\"query.status === 'passed' ? 'Passed' : query.status === 'failed' ? 'Failed' : 'Pending'\"\n [variant]=\"query.status === 'passed' ? 'success' : query.status === 'failed' ? 'error' : 'default'\"\n size=\"small\">\n </cqa-badge>\n </div>\n </div>\n </div>\n\n <!-- Right Panel: Query Editor -->\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden\">\n <div class=\"cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Query & Store Response</h3>\n </div>\n \n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-p-4 cqa-flex cqa-flex-col cqa-gap-4\">\n <!-- SQL Query Textarea -->\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col\">\n <cqa-custom-textarea\n [placeholder]=\"'Enter your SQL query here...'\"\n [value]=\"getCurrentQueryFormGroup()?.get('query')?.value || ''\"\n [fullWidth]=\"true\"\n [rows]=\"8\"\n (valueChange)=\"getCurrentQueryFormGroup()?.get('query')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n\n <!-- Variable Input -->\n <div class=\"cqa-flex cqa-gap-4\">\n <div class=\"cqa-flex-1\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5 cqa-block\">\n Variable\n </label>\n <cqa-custom-input\n [placeholder]=\"'Variable name'\"\n [value]=\"getCurrentQueryFormGroup()?.get('variable')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getCurrentQueryFormGroup()?.get('variable')?.setValue($event)\">\n </cqa-custom-input>\n <p class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">\n Use letters, numbers, underscore. No spaces. Unique per step. Case sensitive.\n </p>\n </div>\n </div>\n\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <cqa-button\n variant=\"outlined\"\n text=\"Add Query\"\n icon=\"add\"\n (clicked)=\"addNewQuery()\">\n </cqa-button>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-10 cqa-h-10 cqa-rounded cqa-text-gray-500 hover:cqa-text-gray-700 hover:cqa-bg-gray-100 cqa-transition-colors cqa-border cqa-border-gray-300\"\n (click)=\"deleteQueryById(getCurrentQuery()?.id || '')\"\n [disabled]=\"queries.length <= 1\"\n [attr.aria-label]=\"'Delete query'\">\n <mat-icon class=\"cqa-text-lg\">delete</mat-icon>\n </button>\n <cqa-button\n variant=\"filled\"\n text=\"Run\"\n icon=\"play_arrow\"\n (clicked)=\"onRunQuery()\"\n [disabled]=\"!databaseForm.get('dbEnvironment')?.value || isLoading\">\n </cqa-button>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Results Section -->\n <div class=\"cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden cqa-mb-6\">\n <!-- Tabs -->\n <div class=\"cqa-flex cqa-items-center cqa-border-b cqa-border-gray-200 cqa-bg-gray-50\">\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'output'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'output'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'output'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'output'\"\n (click)=\"onTabChange('output')\">\n Output\n </button>\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'verification'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'verification'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'verification'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'verification'\"\n (click)=\"onTabChange('verification')\">\n Verification\n </button>\n </div>\n\n <!-- Tab Content -->\n <div class=\"cqa-p-4\">\n <!-- Output Tab -->\n <div *ngIf=\"selectedTab === 'output'\">\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-mb-3\">\n <h4 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Query Results</h4>\n <cqa-button\n variant=\"text\"\n text=\"Copy\"\n icon=\"content_copy\"\n [customClass]=\"'cqa-text-blue-600'\"\n (clicked)=\"onCopyResults()\">\n </cqa-button>\n </div>\n \n <!-- Results Table -->\n <div *ngIf=\"queryResults && queryResults.length > 0\" class=\"cqa-overflow-x-auto\">\n <table class=\"cqa-w-full cqa-border-collapse\">\n <thead>\n <tr class=\"cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <th *ngFor=\"let key of getTableColumns()\" \n class=\"cqa-px-4 cqa-py-2 cqa-text-left cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">\n {{ key }}\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of queryResults\" \n class=\"cqa-border-b cqa-border-gray-200 hover:cqa-bg-gray-50\">\n <td *ngFor=\"let key of getTableColumns()\" \n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-text-gray-900\">\n {{ row[key] }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n \n <div *ngIf=\"!queryResults || queryResults.length === 0\" \n class=\"cqa-text-center cqa-py-8 cqa-text-gray-400 cqa-text-sm\">\n No results yet. Run a query to see results.\n </div>\n </div>\n\n <!-- Verification Tab -->\n <div *ngIf=\"selectedTab === 'verification'\">\n <p class=\"cqa-text-sm cqa-text-gray-600\">Verification settings will be available here.</p>\n </div>\n </div>\n </div>\n\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-w-full cqa-gap-2 cqa-mt-auto cqa-pt-4 cqa-border-t cqa-border-gray-200\">\n <cqa-button\n class=\"cqa-w-1/2\"\n variant=\"outlined\"\n text=\"Cancel\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <cqa-button\n class=\"cqa-w-1/2\"\n variant=\"filled\"\n text=\"Create Step\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCreateStep()\">\n </cqa-button>\n </div>\n</div>\n\n", components: [{ type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore"] }, { type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }, { type: BadgeComponent, selector: "cqa-badge", inputs: ["type", "label", "icon", "iconLibrary", "variant", "size", "backgroundColor", "textColor", "borderColor", "iconBackgroundColor", "iconColor", "iconSize", "inlineStyles", "key", "value", "keyTextColor", "valueTextColor", "isLoading"] }, { type: CustomTextareaComponent, selector: "cqa-custom-textarea", inputs: ["label", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "rows", "cols", "resize", "textareaInlineStyle", "labelInlineStyle", "customClass"], outputs: ["valueChange", "blurred", "focused"] }, { type: CustomInputComponent, selector: "cqa-custom-input", inputs: ["label", "type", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "inputInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused", "enterPressed"] }, { type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
20703
+ StepBuilderDatabaseComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StepBuilderDatabaseComponent, selector: "cqa-step-builder-database", inputs: { dbEnvironmentOptions: "dbEnvironmentOptions", queries: "queries", queryResults: "queryResults", isLoading: "isLoading" }, outputs: { createStep: "createStep", cancelled: "cancelled", runQuery: "runQuery", addQuery: "addQuery", deleteQuery: "deleteQuery" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Create Database Test Step\n </h2>\n\n <!-- DB Environment Section -->\n <div class=\"cqa-flex cqa-items-end cqa-justify-between cqa-mb-6\">\n <div class=\"cqa-flex-1\" style=\"max-width: 280px;\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5 cqa-block\">\n DB Environment <span class=\"cqa-text-red-500\">*</span>\n </label>\n <cqa-dynamic-select [form]=\"databaseForm\" [config]=\"getDbEnvironmentConfig()\">\n </cqa-dynamic-select>\n <p class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">\n Uses Database environments from Environments.\n </p>\n </div>\n <div class=\"cqa-flex cqa-items-end cqa-mb-1\">\n <cqa-button variant=\"filled\" text=\"Run Query\" [customClass]=\"'cqa-whitespace-nowrap'\" (clicked)=\"onRunQuery()\"\n [disabled]=\"!databaseForm.get('dbEnvironment')?.value || isLoading\">\n </cqa-button>\n </div>\n </div>\n\n <!-- Main Content: Two Column Layout -->\n <div class=\"cqa-flex cqa-gap-4 cqa-flex-1 cqa-overflow-hidden cqa-mb-6\">\n <!-- Left Panel: Query List -->\n <div\n class=\"cqa-w-64 cqa-flex-shrink-0 cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden\"\n style=\"max-width: 174px;\">\n <!-- <div class=\"cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Queries</h3>\n </div> -->\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-p-2\">\n <div *ngFor=\"let query of queries; let i = index\"\n class=\"cqa-flex cqa-items-center cqa-justify-between cqa-p-2 cqa-rounded cqa-cursor-pointer cqa-mb-1\"\n [class.cqa-bg-blue-50]=\"selectedQueryIndex === i\" [class.cqa-border]=\"selectedQueryIndex === i\"\n [class.cqa-border-blue-500]=\"selectedQueryIndex === i\" (click)=\"onSelectQuery(i)\" style=\"height: 49px;\">\n <span class=\"cqa-text-sm cqa-font-medium cqa-text-gray-900\">Query {{ i + 1 }}</span>\n <cqa-badge *ngIf=\"query.status\"\n [label]=\"query.status === 'passed' ? 'Passed' : query.status === 'failed' ? 'Failed' : 'Pending'\"\n [variant]=\"query.status === 'passed' ? 'success' : query.status === 'failed' ? 'error' : 'default'\"\n size=\"small\">\n </cqa-badge>\n </div>\n </div>\n </div>\n\n <!-- Right Panel: Query Editor -->\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col cqa-overflow-auto\">\n <div class=\"cqa-flex-1 cqa-flex cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-gap-4\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-4\" style=\"width: 50%;\">\n <div class=\"\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900 cqa-text-[14px]\">Query & Store Response</h3>\n </div>\n\n <div class=\"cqa-flex cqa-justify-between\">\n <!-- SQL Query Textarea -->\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col\">\n <cqa-custom-textarea [placeholder]=\"'Enter your SQL query here...'\"\n [value]=\"getCurrentQueryFormGroup()?.get('query')?.value || ''\" [fullWidth]=\"true\" [rows]=\"8\"\n (valueChange)=\"getCurrentQueryFormGroup()?.get('query')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n </div>\n </div>\n\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-flex cqa-flex-col cqa-gap-4\">\n\n\n <!-- Variable Input -->\n <div class=\"cqa-flex cqa-gap-4\">\n <div class=\"cqa-flex-1\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5 cqa-block cqa-text-[14px] cqa-font-semibold\">\n Variable\n </label>\n <cqa-custom-input [placeholder]=\"'Variable name'\"\n [value]=\"getCurrentQueryFormGroup()?.get('variable')?.value || ''\" [fullWidth]=\"true\"\n (valueChange)=\"getCurrentQueryFormGroup()?.get('variable')?.setValue($event)\">\n </cqa-custom-input>\n <p class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">\n Use letters, numbers, underscore. No spaces. Unique per step. Case sensitive.\n </p>\n </div>\n </div>\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <cqa-button variant=\"outlined\" text=\"Add Query\" icon=\"add\" (clicked)=\"addNewQuery()\">\n </cqa-button>\n <!-- <button type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-10 cqa-h-10 cqa-rounded cqa-text-gray-500 hover:cqa-text-gray-700 hover:cqa-bg-gray-100 cqa-transition-colors cqa-border cqa-border-gray-300\"\n (click)=\"deleteQueryById(getCurrentQuery()?.id || '')\" [disabled]=\"queries.length <= 1\"\n [attr.aria-label]=\"'Delete query'\">\n <mat-icon class=\"cqa-text-lg\">delete</mat-icon>\n </button> -->\n <cqa-button variant=\"text\" icon=\"delete\" (clicked)=\"deleteQueryById(getCurrentQuery()?.id || '')\"\n [disabled]=\"queries.length <= 1\" [customClass]=\"'cqa-text-red-500'\" [attr.aria-label]=\"'Delete query'\">\n </cqa-button>\n <cqa-button variant=\"filled\" text=\"Run\" icon=\"play_arrow\" (clicked)=\"onRunQuery()\"\n [disabled]=\"!getCurrentQueryFormGroup()?.get('query')?.value || !databaseForm.get('dbEnvironment')?.value || isLoading\">\n </cqa-button>\n </div>\n </div>\n </div>\n <!-- Results Section -->\n <div class=\"cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-mb-6\">\n <!-- Tabs -->\n <div class=\"cqa-flex cqa-items-center cqa-border-b cqa-border-gray-200 cqa-bg-gray-50\">\n <button type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'output'\" [class.cqa-border-blue-600]=\"selectedTab === 'output'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'output'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'output'\" (click)=\"onTabChange('output')\">\n Output\n </button>\n <button type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'verification'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'verification'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'verification'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'verification'\" (click)=\"onTabChange('verification')\">\n Verification\n </button>\n </div>\n\n <!-- Tab Content -->\n <div class=\"cqa-p-4\">\n <!-- Output Tab -->\n <div *ngIf=\"selectedTab === 'output'\">\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-mb-3\">\n <h4 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Query Results</h4>\n <cqa-button variant=\"text\" text=\"Copy\" icon=\"content_copy\" [customClass]=\"'cqa-text-blue-600'\"\n (clicked)=\"onCopyResults()\">\n </cqa-button>\n </div>\n\n <!-- Results Table -->\n <div *ngIf=\"queryResults && queryResults.length > 0\" class=\"cqa-overflow-x-auto\">\n <table class=\"cqa-w-full cqa-border-collapse\">\n <thead>\n <tr class=\"cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <th *ngFor=\"let key of getTableColumns()\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-left cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">\n {{ key }}\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of queryResults\" class=\"cqa-border-b cqa-border-gray-200 hover:cqa-bg-gray-50\">\n <td *ngFor=\"let key of getTableColumns()\" class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-text-gray-900\">\n {{ row[key] }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <div *ngIf=\"!queryResults || queryResults.length === 0\"\n class=\"cqa-text-center cqa-py-8 cqa-text-gray-400 cqa-text-sm\">\n No results yet. Run a query to see results.\n </div>\n </div>\n\n <!-- Verification Tab -->\n <div *ngIf=\"selectedTab === 'verification'\">\n <p class=\"cqa-text-sm cqa-text-gray-600\">Verification settings will be available here.</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n\n\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-w-full cqa-gap-2 cqa-mt-auto cqa-pt-4 cqa-border-t cqa-border-gray-200\">\n <cqa-button class=\"cqa-w-1/2\" variant=\"outlined\" text=\"Cancel\" [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <cqa-button class=\"cqa-w-1/2\" variant=\"filled\" text=\"Create Step\" [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCreateStep()\">\n </cqa-button>\n </div>\n</div>", components: [{ type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore"] }, { type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }, { type: BadgeComponent, selector: "cqa-badge", inputs: ["type", "label", "icon", "iconLibrary", "variant", "size", "backgroundColor", "textColor", "borderColor", "iconBackgroundColor", "iconColor", "iconSize", "inlineStyles", "key", "value", "keyTextColor", "valueTextColor", "isLoading"] }, { type: CustomTextareaComponent, selector: "cqa-custom-textarea", inputs: ["label", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "rows", "cols", "resize", "textareaInlineStyle", "labelInlineStyle", "customClass"], outputs: ["valueChange", "blurred", "focused"] }, { type: CustomInputComponent, selector: "cqa-custom-input", inputs: ["label", "type", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "inputInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused", "enterPressed"] }], directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
20811
20704
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepBuilderDatabaseComponent, decorators: [{
20812
20705
  type: Component,
20813
- args: [{ selector: 'cqa-step-builder-database', host: { class: 'cqa-ui-root' }, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Create Database Test Step\n </h2>\n\n <!-- DB Environment Section -->\n <div class=\"cqa-flex cqa-items-start cqa-gap-4 cqa-mb-6\">\n <div class=\"cqa-flex-1\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5 cqa-block\">\n DB Environment <span class=\"cqa-text-red-500\">*</span>\n </label>\n <cqa-dynamic-select\n [form]=\"databaseForm\"\n [config]=\"getDbEnvironmentConfig()\">\n </cqa-dynamic-select>\n <p class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">\n Uses Database environments from Environments.\n </p>\n </div>\n <div class=\"cqa-flex cqa-items-end cqa-mb-1\">\n <cqa-button\n variant=\"filled\"\n text=\"Run Query\"\n [customClass]=\"'cqa-whitespace-nowrap'\"\n (clicked)=\"onRunQuery()\"\n [disabled]=\"!databaseForm.get('dbEnvironment')?.value || isLoading\">\n </cqa-button>\n </div>\n </div>\n\n <!-- Main Content: Two Column Layout -->\n <div class=\"cqa-flex cqa-gap-4 cqa-flex-1 cqa-overflow-hidden cqa-mb-6\">\n <!-- Left Panel: Query List -->\n <div class=\"cqa-w-64 cqa-flex-shrink-0 cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden\">\n <div class=\"cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Queries</h3>\n </div>\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-p-2\">\n <div *ngFor=\"let query of queries; let i = index\"\n class=\"cqa-flex cqa-items-center cqa-justify-between cqa-p-2 cqa-rounded cqa-cursor-pointer cqa-mb-1\"\n [class.cqa-bg-blue-50]=\"selectedQueryIndex === i\"\n [class.cqa-border]=\"selectedQueryIndex === i\"\n [class.cqa-border-blue-500]=\"selectedQueryIndex === i\"\n (click)=\"onSelectQuery(i)\">\n <span class=\"cqa-text-sm cqa-font-medium cqa-text-gray-900\">Query {{ i + 1 }}</span>\n <cqa-badge\n *ngIf=\"query.status\"\n [label]=\"query.status === 'passed' ? 'Passed' : query.status === 'failed' ? 'Failed' : 'Pending'\"\n [variant]=\"query.status === 'passed' ? 'success' : query.status === 'failed' ? 'error' : 'default'\"\n size=\"small\">\n </cqa-badge>\n </div>\n </div>\n </div>\n\n <!-- Right Panel: Query Editor -->\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden\">\n <div class=\"cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Query & Store Response</h3>\n </div>\n \n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-p-4 cqa-flex cqa-flex-col cqa-gap-4\">\n <!-- SQL Query Textarea -->\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col\">\n <cqa-custom-textarea\n [placeholder]=\"'Enter your SQL query here...'\"\n [value]=\"getCurrentQueryFormGroup()?.get('query')?.value || ''\"\n [fullWidth]=\"true\"\n [rows]=\"8\"\n (valueChange)=\"getCurrentQueryFormGroup()?.get('query')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n\n <!-- Variable Input -->\n <div class=\"cqa-flex cqa-gap-4\">\n <div class=\"cqa-flex-1\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5 cqa-block\">\n Variable\n </label>\n <cqa-custom-input\n [placeholder]=\"'Variable name'\"\n [value]=\"getCurrentQueryFormGroup()?.get('variable')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getCurrentQueryFormGroup()?.get('variable')?.setValue($event)\">\n </cqa-custom-input>\n <p class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">\n Use letters, numbers, underscore. No spaces. Unique per step. Case sensitive.\n </p>\n </div>\n </div>\n\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <cqa-button\n variant=\"outlined\"\n text=\"Add Query\"\n icon=\"add\"\n (clicked)=\"addNewQuery()\">\n </cqa-button>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-10 cqa-h-10 cqa-rounded cqa-text-gray-500 hover:cqa-text-gray-700 hover:cqa-bg-gray-100 cqa-transition-colors cqa-border cqa-border-gray-300\"\n (click)=\"deleteQueryById(getCurrentQuery()?.id || '')\"\n [disabled]=\"queries.length <= 1\"\n [attr.aria-label]=\"'Delete query'\">\n <mat-icon class=\"cqa-text-lg\">delete</mat-icon>\n </button>\n <cqa-button\n variant=\"filled\"\n text=\"Run\"\n icon=\"play_arrow\"\n (clicked)=\"onRunQuery()\"\n [disabled]=\"!databaseForm.get('dbEnvironment')?.value || isLoading\">\n </cqa-button>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Results Section -->\n <div class=\"cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden cqa-mb-6\">\n <!-- Tabs -->\n <div class=\"cqa-flex cqa-items-center cqa-border-b cqa-border-gray-200 cqa-bg-gray-50\">\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'output'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'output'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'output'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'output'\"\n (click)=\"onTabChange('output')\">\n Output\n </button>\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'verification'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'verification'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'verification'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'verification'\"\n (click)=\"onTabChange('verification')\">\n Verification\n </button>\n </div>\n\n <!-- Tab Content -->\n <div class=\"cqa-p-4\">\n <!-- Output Tab -->\n <div *ngIf=\"selectedTab === 'output'\">\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-mb-3\">\n <h4 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Query Results</h4>\n <cqa-button\n variant=\"text\"\n text=\"Copy\"\n icon=\"content_copy\"\n [customClass]=\"'cqa-text-blue-600'\"\n (clicked)=\"onCopyResults()\">\n </cqa-button>\n </div>\n \n <!-- Results Table -->\n <div *ngIf=\"queryResults && queryResults.length > 0\" class=\"cqa-overflow-x-auto\">\n <table class=\"cqa-w-full cqa-border-collapse\">\n <thead>\n <tr class=\"cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <th *ngFor=\"let key of getTableColumns()\" \n class=\"cqa-px-4 cqa-py-2 cqa-text-left cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">\n {{ key }}\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of queryResults\" \n class=\"cqa-border-b cqa-border-gray-200 hover:cqa-bg-gray-50\">\n <td *ngFor=\"let key of getTableColumns()\" \n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-text-gray-900\">\n {{ row[key] }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n \n <div *ngIf=\"!queryResults || queryResults.length === 0\" \n class=\"cqa-text-center cqa-py-8 cqa-text-gray-400 cqa-text-sm\">\n No results yet. Run a query to see results.\n </div>\n </div>\n\n <!-- Verification Tab -->\n <div *ngIf=\"selectedTab === 'verification'\">\n <p class=\"cqa-text-sm cqa-text-gray-600\">Verification settings will be available here.</p>\n </div>\n </div>\n </div>\n\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-w-full cqa-gap-2 cqa-mt-auto cqa-pt-4 cqa-border-t cqa-border-gray-200\">\n <cqa-button\n class=\"cqa-w-1/2\"\n variant=\"outlined\"\n text=\"Cancel\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <cqa-button\n class=\"cqa-w-1/2\"\n variant=\"filled\"\n text=\"Create Step\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCreateStep()\">\n </cqa-button>\n </div>\n</div>\n\n", styles: [] }]
20706
+ args: [{ selector: 'cqa-step-builder-database', host: { class: 'cqa-ui-root' }, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Create Database Test Step\n </h2>\n\n <!-- DB Environment Section -->\n <div class=\"cqa-flex cqa-items-end cqa-justify-between cqa-mb-6\">\n <div class=\"cqa-flex-1\" style=\"max-width: 280px;\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5 cqa-block\">\n DB Environment <span class=\"cqa-text-red-500\">*</span>\n </label>\n <cqa-dynamic-select [form]=\"databaseForm\" [config]=\"getDbEnvironmentConfig()\">\n </cqa-dynamic-select>\n <p class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">\n Uses Database environments from Environments.\n </p>\n </div>\n <div class=\"cqa-flex cqa-items-end cqa-mb-1\">\n <cqa-button variant=\"filled\" text=\"Run Query\" [customClass]=\"'cqa-whitespace-nowrap'\" (clicked)=\"onRunQuery()\"\n [disabled]=\"!databaseForm.get('dbEnvironment')?.value || isLoading\">\n </cqa-button>\n </div>\n </div>\n\n <!-- Main Content: Two Column Layout -->\n <div class=\"cqa-flex cqa-gap-4 cqa-flex-1 cqa-overflow-hidden cqa-mb-6\">\n <!-- Left Panel: Query List -->\n <div\n class=\"cqa-w-64 cqa-flex-shrink-0 cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden\"\n style=\"max-width: 174px;\">\n <!-- <div class=\"cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Queries</h3>\n </div> -->\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-p-2\">\n <div *ngFor=\"let query of queries; let i = index\"\n class=\"cqa-flex cqa-items-center cqa-justify-between cqa-p-2 cqa-rounded cqa-cursor-pointer cqa-mb-1\"\n [class.cqa-bg-blue-50]=\"selectedQueryIndex === i\" [class.cqa-border]=\"selectedQueryIndex === i\"\n [class.cqa-border-blue-500]=\"selectedQueryIndex === i\" (click)=\"onSelectQuery(i)\" style=\"height: 49px;\">\n <span class=\"cqa-text-sm cqa-font-medium cqa-text-gray-900\">Query {{ i + 1 }}</span>\n <cqa-badge *ngIf=\"query.status\"\n [label]=\"query.status === 'passed' ? 'Passed' : query.status === 'failed' ? 'Failed' : 'Pending'\"\n [variant]=\"query.status === 'passed' ? 'success' : query.status === 'failed' ? 'error' : 'default'\"\n size=\"small\">\n </cqa-badge>\n </div>\n </div>\n </div>\n\n <!-- Right Panel: Query Editor -->\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col cqa-overflow-auto\">\n <div class=\"cqa-flex-1 cqa-flex cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-gap-4\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-4\" style=\"width: 50%;\">\n <div class=\"\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900 cqa-text-[14px]\">Query & Store Response</h3>\n </div>\n\n <div class=\"cqa-flex cqa-justify-between\">\n <!-- SQL Query Textarea -->\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col\">\n <cqa-custom-textarea [placeholder]=\"'Enter your SQL query here...'\"\n [value]=\"getCurrentQueryFormGroup()?.get('query')?.value || ''\" [fullWidth]=\"true\" [rows]=\"8\"\n (valueChange)=\"getCurrentQueryFormGroup()?.get('query')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n </div>\n </div>\n\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-flex cqa-flex-col cqa-gap-4\">\n\n\n <!-- Variable Input -->\n <div class=\"cqa-flex cqa-gap-4\">\n <div class=\"cqa-flex-1\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5 cqa-block cqa-text-[14px] cqa-font-semibold\">\n Variable\n </label>\n <cqa-custom-input [placeholder]=\"'Variable name'\"\n [value]=\"getCurrentQueryFormGroup()?.get('variable')?.value || ''\" [fullWidth]=\"true\"\n (valueChange)=\"getCurrentQueryFormGroup()?.get('variable')?.setValue($event)\">\n </cqa-custom-input>\n <p class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">\n Use letters, numbers, underscore. No spaces. Unique per step. Case sensitive.\n </p>\n </div>\n </div>\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <cqa-button variant=\"outlined\" text=\"Add Query\" icon=\"add\" (clicked)=\"addNewQuery()\">\n </cqa-button>\n <!-- <button type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-10 cqa-h-10 cqa-rounded cqa-text-gray-500 hover:cqa-text-gray-700 hover:cqa-bg-gray-100 cqa-transition-colors cqa-border cqa-border-gray-300\"\n (click)=\"deleteQueryById(getCurrentQuery()?.id || '')\" [disabled]=\"queries.length <= 1\"\n [attr.aria-label]=\"'Delete query'\">\n <mat-icon class=\"cqa-text-lg\">delete</mat-icon>\n </button> -->\n <cqa-button variant=\"text\" icon=\"delete\" (clicked)=\"deleteQueryById(getCurrentQuery()?.id || '')\"\n [disabled]=\"queries.length <= 1\" [customClass]=\"'cqa-text-red-500'\" [attr.aria-label]=\"'Delete query'\">\n </cqa-button>\n <cqa-button variant=\"filled\" text=\"Run\" icon=\"play_arrow\" (clicked)=\"onRunQuery()\"\n [disabled]=\"!getCurrentQueryFormGroup()?.get('query')?.value || !databaseForm.get('dbEnvironment')?.value || isLoading\">\n </cqa-button>\n </div>\n </div>\n </div>\n <!-- Results Section -->\n <div class=\"cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-mb-6\">\n <!-- Tabs -->\n <div class=\"cqa-flex cqa-items-center cqa-border-b cqa-border-gray-200 cqa-bg-gray-50\">\n <button type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'output'\" [class.cqa-border-blue-600]=\"selectedTab === 'output'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'output'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'output'\" (click)=\"onTabChange('output')\">\n Output\n </button>\n <button type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'verification'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'verification'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'verification'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'verification'\" (click)=\"onTabChange('verification')\">\n Verification\n </button>\n </div>\n\n <!-- Tab Content -->\n <div class=\"cqa-p-4\">\n <!-- Output Tab -->\n <div *ngIf=\"selectedTab === 'output'\">\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-mb-3\">\n <h4 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Query Results</h4>\n <cqa-button variant=\"text\" text=\"Copy\" icon=\"content_copy\" [customClass]=\"'cqa-text-blue-600'\"\n (clicked)=\"onCopyResults()\">\n </cqa-button>\n </div>\n\n <!-- Results Table -->\n <div *ngIf=\"queryResults && queryResults.length > 0\" class=\"cqa-overflow-x-auto\">\n <table class=\"cqa-w-full cqa-border-collapse\">\n <thead>\n <tr class=\"cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <th *ngFor=\"let key of getTableColumns()\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-left cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">\n {{ key }}\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of queryResults\" class=\"cqa-border-b cqa-border-gray-200 hover:cqa-bg-gray-50\">\n <td *ngFor=\"let key of getTableColumns()\" class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-text-gray-900\">\n {{ row[key] }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <div *ngIf=\"!queryResults || queryResults.length === 0\"\n class=\"cqa-text-center cqa-py-8 cqa-text-gray-400 cqa-text-sm\">\n No results yet. Run a query to see results.\n </div>\n </div>\n\n <!-- Verification Tab -->\n <div *ngIf=\"selectedTab === 'verification'\">\n <p class=\"cqa-text-sm cqa-text-gray-600\">Verification settings will be available here.</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n\n\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-w-full cqa-gap-2 cqa-mt-auto cqa-pt-4 cqa-border-t cqa-border-gray-200\">\n <cqa-button class=\"cqa-w-1/2\" variant=\"outlined\" text=\"Cancel\" [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <cqa-button class=\"cqa-w-1/2\" variant=\"filled\" text=\"Create Step\" [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCreateStep()\">\n </cqa-button>\n </div>\n</div>", styles: [] }]
20814
20707
  }], ctorParameters: function () { return [{ type: i2$1.FormBuilder }]; }, propDecorators: { dbEnvironmentOptions: [{
20815
20708
  type: Input
20816
20709
  }], queries: [{
@@ -21552,6 +21445,7 @@ class StepBuilderApiComponent {
21552
21445
  this.importCurl = new EventEmitter();
21553
21446
  this.selectedTab = 'headers';
21554
21447
  this.selectedProgressStep = 'request-details';
21448
+ this.formSubmitted = false;
21555
21449
  // progressSteps: ProgressStep[] = ['request-details', 'store-response', 'validation'];
21556
21450
  // Cache config objects to prevent infinite change detection loops
21557
21451
  this.verificationTypeConfigCache = null;
@@ -21560,9 +21454,13 @@ class StepBuilderApiComponent {
21560
21454
  this.headerNameConfigCache = null;
21561
21455
  this.paramNameConfigCache = null;
21562
21456
  this.hasLoadedInitialData = false;
21457
+ // Get first HTTP method option (default to 'GET' if options not available yet)
21458
+ const firstMethod = this.httpMethodOptions.length > 0
21459
+ ? this.httpMethodOptions[0].value
21460
+ : 'GET';
21563
21461
  this.apiForm = this.fb.group({
21564
- method: ['GET', Validators.required],
21565
- url: ['', Validators.required],
21462
+ method: [firstMethod, Validators.required],
21463
+ url: ['', [Validators.required, this.urlValidator()]],
21566
21464
  headers: this.fb.array([]),
21567
21465
  body: [''],
21568
21466
  params: this.fb.array([]),
@@ -21571,11 +21469,49 @@ class StepBuilderApiComponent {
21571
21469
  validation: this.fb.array([])
21572
21470
  });
21573
21471
  }
21472
+ urlValidator() {
21473
+ return (control) => {
21474
+ const url = control.value;
21475
+ if (!url) {
21476
+ return null; // Let required validator handle empty case
21477
+ }
21478
+ // Pattern for plain URLs only (no parameters)
21479
+ const urlPattern = /^(https?:\/\/)?([\w-]+(\.[\w-]+)+)([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?$/;
21480
+ // Pattern to detect any parameter patterns: *|param|, $|param|, @|param|, or ${param}
21481
+ const parameterPattern = /(\*\|[\w-]+\|(\*)?|\$\|[\w-]+\|(\*)?|@\|[\w-]+\|(\*)?|\$\{[^}]+\})/;
21482
+ // Pattern for parameter-only values: *|param|, $|param|, @|param|, or ${param}
21483
+ const envPattern = /^\*\|[\w-]+\|(\*)?$|^\$\|[\w-]+\|(\*)?$|^@\|[\w-]+\|(\*)?$|^\$\{[^}]+\}$/;
21484
+ // Pattern to allow URLs with embedded parameters: *|param|, $|param|, @|param|, or ${param}
21485
+ const flexibleUrlPattern = /^[@]?(https?:\/\/)?([\w-]+(\.[\w-]+)+)([\w.,@?^=%&:/~+#-]*(\*\|[\w-]+\|(\*)?|\$\|[\w-]+\|(\*)?|@\|[\w-]+\|(\*)?|\$\{[^}]+\})[\w.,@?^=%&:/~+#-]*)*$/;
21486
+ // Pattern that allows parameters anywhere after http:// or https://
21487
+ const protocolWithParamsPattern = /^https?:\/\/(\*\|[\w-]+\|(\*)?|\$\|[\w-]+\|(\*)?|@\|[\w-]+\|(\*)?|\$\{[^}]+\})[^\s]*$|^https?:\/\/[^\s]*(\*\|[\w-]+\|(\*)?|\$\|[\w-]+\|(\*)?|@\|[\w-]+\|(\*)?|\$\{[^}]+\})[^\s]*$/;
21488
+ // Check if URL contains parameters
21489
+ if (parameterPattern.test(url)) {
21490
+ // If it contains parameters, check if it matches allowed patterns
21491
+ const envCombined = new RegExp(`${urlPattern.source}|${flexibleUrlPattern.source}|${envPattern.source}|${protocolWithParamsPattern.source}`);
21492
+ if (!envCombined.test(url)) {
21493
+ return { hasParameter: true };
21494
+ }
21495
+ }
21496
+ else {
21497
+ // If no parameters, check if it's a valid plain URL
21498
+ if (!urlPattern.test(url)) {
21499
+ return { pattern: true };
21500
+ }
21501
+ }
21502
+ return null;
21503
+ };
21504
+ }
21574
21505
  ngOnInit() {
21506
+ var _a, _b;
21575
21507
  // Sync currentStep input with selectedProgressStep
21576
21508
  if (this.currentStep) {
21577
21509
  this.selectedProgressStep = this.currentStep;
21578
21510
  }
21511
+ // Set method to first option if not already set
21512
+ if (!((_a = this.apiForm.get('method')) === null || _a === void 0 ? void 0 : _a.value) && this.httpMethodOptions.length > 0) {
21513
+ (_b = this.apiForm.get('method')) === null || _b === void 0 ? void 0 : _b.setValue(this.httpMethodOptions[0].value);
21514
+ }
21579
21515
  // Load initial data if provided (edit mode)
21580
21516
  if (this.initialData) {
21581
21517
  this.loadInitialData(this.initialData);
@@ -21671,8 +21607,18 @@ class StepBuilderApiComponent {
21671
21607
  return this.apiForm.get('validation');
21672
21608
  }
21673
21609
  addHeader() {
21610
+ // Get first header name option
21611
+ const headerOptions = this.headerNameOptions.length > 0
21612
+ ? this.headerNameOptions
21613
+ : [
21614
+ { id: 'string', value: 'string', name: 'string', label: 'string' },
21615
+ { id: 'Content-Type', value: 'Content-Type', name: 'Content-Type', label: 'Content-Type' },
21616
+ { id: 'Authorization', value: 'Authorization', name: 'Authorization', label: 'Authorization' },
21617
+ { id: 'Accept', value: 'Accept', name: 'Accept', label: 'Accept' }
21618
+ ];
21619
+ const firstHeaderName = headerOptions.length > 0 ? headerOptions[0].value : '';
21674
21620
  const headerGroup = this.fb.group({
21675
- name: ['', Validators.required],
21621
+ name: [firstHeaderName, Validators.required],
21676
21622
  value: ['', Validators.required]
21677
21623
  });
21678
21624
  this.headersFormArray.push(headerGroup);
@@ -21694,9 +21640,25 @@ class StepBuilderApiComponent {
21694
21640
  // Reset config caches when inputs change
21695
21641
  if (changes['httpMethodOptions']) {
21696
21642
  this.httpMethodConfigCache = null;
21643
+ // Set method to first option if not already set or if we're not in edit mode
21644
+ if (!this.hasLoadedInitialData && this.httpMethodOptions.length > 0) {
21645
+ const methodControl = this.apiForm.get('method');
21646
+ if (methodControl && !methodControl.value) {
21647
+ methodControl.setValue(this.httpMethodOptions[0].value);
21648
+ }
21649
+ }
21697
21650
  }
21698
21651
  if (changes['headerNameOptions']) {
21699
21652
  this.headerNameConfigCache = null;
21653
+ // Update header names to first option for empty headers (only if not in edit mode)
21654
+ if (!this.hasLoadedInitialData && this.headerNameOptions.length > 0) {
21655
+ this.headersFormArray.controls.forEach((headerGroup) => {
21656
+ const nameControl = headerGroup.get('name');
21657
+ if (nameControl && !nameControl.value) {
21658
+ nameControl.setValue(this.headerNameOptions[0].value);
21659
+ }
21660
+ });
21661
+ }
21700
21662
  }
21701
21663
  // Load initial data if it's set after component initialization
21702
21664
  if (changes['initialData'] && !changes['initialData'].firstChange && this.initialData && !this.hasLoadedInitialData) {
@@ -21756,6 +21718,10 @@ class StepBuilderApiComponent {
21756
21718
  this.selectedTab = tab;
21757
21719
  }
21758
21720
  onSendRequest() {
21721
+ this.formSubmitted = true;
21722
+ this.markFormGroupTouched(this.apiForm);
21723
+ console.log('onSendRequest: apiForm', this.apiForm.value);
21724
+ console.log('onSendRequest: apiForm valid', this.apiForm);
21759
21725
  if (this.apiForm.valid) {
21760
21726
  const formValue = this.apiForm.value;
21761
21727
  const headers = formValue.headers.map((h) => ({
@@ -21782,6 +21748,8 @@ class StepBuilderApiComponent {
21782
21748
  this.cancelled.emit();
21783
21749
  }
21784
21750
  onCreateStep() {
21751
+ this.formSubmitted = true;
21752
+ this.markFormGroupTouched(this.apiForm);
21785
21753
  if (this.apiForm.valid) {
21786
21754
  const formValue = this.apiForm.value;
21787
21755
  const stepData = {
@@ -21995,12 +21963,64 @@ class StepBuilderApiComponent {
21995
21963
  this.removeValidationRule(index);
21996
21964
  });
21997
21965
  }
21966
+ markFormGroupTouched(formGroup) {
21967
+ Object.keys(formGroup.controls).forEach(key => {
21968
+ const control = formGroup.get(key);
21969
+ if (control) {
21970
+ control.markAsTouched();
21971
+ if (control instanceof FormGroup) {
21972
+ this.markFormGroupTouched(control);
21973
+ }
21974
+ else if (control instanceof FormArray) {
21975
+ control.controls.forEach((ctrl) => {
21976
+ if (ctrl instanceof FormGroup) {
21977
+ this.markFormGroupTouched(ctrl);
21978
+ }
21979
+ else {
21980
+ ctrl.markAsTouched();
21981
+ }
21982
+ });
21983
+ }
21984
+ }
21985
+ });
21986
+ }
21987
+ onUrlChange(value) {
21988
+ const urlControl = this.apiForm.get('url');
21989
+ if (urlControl) {
21990
+ urlControl.setValue(value);
21991
+ urlControl.updateValueAndValidity();
21992
+ }
21993
+ }
21994
+ onUrlBlur() {
21995
+ const urlControl = this.apiForm.get('url');
21996
+ if (urlControl) {
21997
+ urlControl.markAsTouched();
21998
+ }
21999
+ }
22000
+ getUrlErrors() {
22001
+ var _a, _b, _c;
22002
+ const urlControl = this.apiForm.get('url');
22003
+ if (!urlControl || (!this.formSubmitted && !urlControl.touched)) {
22004
+ return [];
22005
+ }
22006
+ const errors = [];
22007
+ if ((_a = urlControl.errors) === null || _a === void 0 ? void 0 : _a['required']) {
22008
+ errors.push('URL is required');
22009
+ }
22010
+ else if ((_b = urlControl.errors) === null || _b === void 0 ? void 0 : _b['pattern']) {
22011
+ errors.push('URL is not valid');
22012
+ }
22013
+ else if ((_c = urlControl.errors) === null || _c === void 0 ? void 0 : _c['hasParameter']) {
22014
+ errors.push('URL format is invalid. Please check the parameter format.');
22015
+ }
22016
+ return errors;
22017
+ }
21998
22018
  }
21999
22019
  StepBuilderApiComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepBuilderApiComponent, deps: [{ token: i2$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
22000
- StepBuilderApiComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StepBuilderApiComponent, selector: "cqa-step-builder-api", inputs: { httpMethodOptions: "httpMethodOptions", headerNameOptions: "headerNameOptions", currentStep: "currentStep", responsePreview: "responsePreview", isLoading: "isLoading", initialData: "initialData" }, outputs: { createStep: "createStep", cancelled: "cancelled", sendRequest: "sendRequest", importCurl: "importCurl" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Create API Test Step\n </h2>\n\n <!-- Progress Tracker -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-4 cqa-mb-6 cqa-pb-4 cqa-border-b cqa-border-gray-200\">\n <!-- <div *ngFor=\"let step of progressSteps\"\n class=\"cqa-flex cqa-items-center cqa-gap-2\"\n [ngClass]=\"getProgressStepClass(step)\">\n <span class=\"cqa-text-sm cqa-font-medium\">{{ getProgressStepNumber(step) }} {{ getProgressStepLabel(step) }}</span>\n <span *ngIf=\"step !== 'validation'\" class=\"cqa-text-gray-300\">\u2022</span>\n </div> -->\n <div\n class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [ngClass]=\"{'cqa-text-purple-600 cqa-font-semibold': selectedProgressStep === 'request-details'}\" (click)=\"onProgressStepChange('request-details')\">\n <div>1</div>\n <div>Request Details</div>\n <div></div>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [ngClass]=\"{'cqa-text-purple-600 cqa-font-semibold': selectedProgressStep === 'store-response'}\" (click)=\"onProgressStepChange('store-response')\">\n <div>2</div>\n <div>Store Response</div>\n <div></div>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [ngClass]=\"{'cqa-text-purple-600 cqa-font-semibold': selectedProgressStep === 'validation'}\" (click)=\"onProgressStepChange('validation')\">\n <div>3</div>\n <div>Validation</div>\n <div></div>\n </div>\n </div>\n </div>\n <ng-container *ngIf=\"selectedProgressStep === 'request-details'\">\n <!-- API Request Configuration -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-mb-6\">\n <div class=\"cqa-w-32 cqa-flex-shrink-0\">\n <cqa-dynamic-select\n [form]=\"apiForm\"\n [config]=\"getHttpMethodConfig()\">\n </cqa-dynamic-select>\n </div>\n <div class=\"cqa-flex-1\">\n <cqa-custom-input\n [placeholder]=\"'Enter API endpoint URL'\"\n [value]=\"apiForm.get('url')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"apiForm.get('url')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <cqa-button\n variant=\"outlined\"\n text=\"Import API cURL\"\n (clicked)=\"onImportCurl()\">\n </cqa-button>\n <cqa-button\n variant=\"filled\"\n text=\"Send Request\"\n (clicked)=\"onSendRequest()\"\n [disabled]=\"!apiForm.get('url')?.value || isLoading\">\n </cqa-button>\n </div>\n\n <!-- Request Details Tabs -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-overflow-hidden cqa-mb-6\">\n <!-- Tab Navigation -->\n <div class=\"cqa-flex cqa-items-center cqa-border-b cqa-border-gray-200 cqa-bg-gray-50\">\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'headers'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'headers'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'headers'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'headers'\"\n (click)=\"onTabChange('headers')\">\n Headers\n </button>\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'body'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'body'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'body'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'body'\"\n (click)=\"onTabChange('body')\">\n Body\n </button>\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'params'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'params'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'params'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'params'\"\n (click)=\"onTabChange('params')\">\n Params\n </button>\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'scripts'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'scripts'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'scripts'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'scripts'\"\n (click)=\"onTabChange('scripts')\">\n Scripts\n </button>\n </div>\n\n <!-- Tab Content -->\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-p-4 cqa-border cqa-border-gray-200 cqa-border-t-0 cqa-rounded-b-lg\">\n <!-- Headers Tab -->\n <div *ngIf=\"selectedTab === 'headers'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-start\">\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Header Name</div>\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Header Value</div>\n </div>\n <div *ngFor=\"let header of headersFormArray.controls; let i = index; trackBy: trackByHeaderIndex\" \n class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-center\">\n <div>\n <cqa-dynamic-select\n [form]=\"getHeaderFormGroup(i)\"\n [config]=\"getHeaderNameConfig(i)\">\n </cqa-dynamic-select>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-flex-1\">\n <cqa-custom-input\n [placeholder]=\"'Header value'\"\n [value]=\"getHeaderFormGroup(i).get('value')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getHeaderFormGroup(i).get('value')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-8 cqa-h-8 cqa-rounded cqa-text-red-500 hover:cqa-text-red-700 hover:cqa-bg-red-50 cqa-transition-colors\"\n (click)=\"removeHeader(i)\"\n [attr.aria-label]=\"'Remove header'\">\n <mat-icon class=\"cqa-text-lg\">delete</mat-icon>\n </button>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"cqa-text-blue-600 cqa-text-sm cqa-font-medium cqa-self-start cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-blue-700 cqa-transition-colors\"\n (click)=\"addHeader()\">\n <mat-icon class=\"cqa-text-base\">add</mat-icon>\n <span>Add Header</span>\n </button>\n </div>\n\n <!-- Body Tab -->\n <div *ngIf=\"selectedTab === 'body'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <cqa-custom-textarea\n [placeholder]=\"'Enter request body (JSON, XML, etc.)'\"\n [value]=\"apiForm.get('body')?.value || ''\"\n [fullWidth]=\"true\"\n [rows]=\"10\"\n (valueChange)=\"apiForm.get('body')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n\n <!-- Params Tab -->\n <div *ngIf=\"selectedTab === 'params'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-start\">\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Parameter Name</div>\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Parameter Value</div>\n </div>\n <div *ngFor=\"let param of paramsFormArray.controls; let i = index; trackBy: trackByParamIndex\" \n class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-center\">\n <div>\n <cqa-custom-input\n [placeholder]=\"'Parameter name'\"\n [value]=\"getParamFormGroup(i).get('name')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getParamFormGroup(i).get('name')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-flex-1\">\n <cqa-custom-input\n [placeholder]=\"'Parameter value'\"\n [value]=\"getParamFormGroup(i).get('value')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getParamFormGroup(i).get('value')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-8 cqa-h-8 cqa-rounded cqa-text-red-500 hover:cqa-text-red-700 hover:cqa-bg-red-50 cqa-transition-colors\"\n (click)=\"removeParam(i)\"\n [attr.aria-label]=\"'Remove parameter'\">\n <mat-icon class=\"cqa-text-lg\">delete</mat-icon>\n </button>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"cqa-text-blue-600 cqa-text-sm cqa-font-medium cqa-self-start cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-blue-700 cqa-transition-colors\"\n (click)=\"addParam()\">\n <mat-icon class=\"cqa-text-base\">add</mat-icon>\n <span>Add Parameter</span>\n </button>\n </div>\n\n <!-- Scripts Tab -->\n <div *ngIf=\"selectedTab === 'scripts'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <cqa-custom-textarea\n [placeholder]=\"'Enter scripts (JavaScript, etc.)'\"\n [value]=\"apiForm.get('scripts')?.value || ''\"\n [fullWidth]=\"true\"\n [rows]=\"10\"\n (valueChange)=\"apiForm.get('scripts')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n </div>\n </div>\n\n\n</ng-container>\n<ng-container *ngIf=\"selectedProgressStep === 'store-response'\">\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-max-h-[500px] cqa-overflow-y-auto\">\n <!-- Store Response Title -->\n <h3 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Store Response\n </h3>\n\n <!-- Variable Name Input -->\n <div class=\"cqa-mb-6\">\n <label class=\"cqa-text-[12px] cqa-font-medium cqa-text-gray-700 cqa-mb-1 cqa-block\">\n Variable Name\n </label>\n <cqa-custom-input\n [placeholder]=\"'Variable Name'\"\n [value]=\"apiForm.get('variableName')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"apiForm.get('variableName')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n </div>\n</ng-container>\n<ng-container *ngIf=\"selectedProgressStep === 'validation'\">\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-max-h-[500px] cqa-overflow-y-auto\">\n <!-- Validation Rules Title -->\n <h3 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Validation Rules\n </h3>\n\n <!-- Validation Rules Table -->\n <div class=\"cqa-bg-white cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden cqa-mb-4\">\n <!-- Table Header -->\n <div class=\"cqa-grid cqa-grid-cols-6 cqa-gap-2 cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200 cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center\">\n <mat-checkbox\n [checked]=\"allValidationRulesSelected\"\n [indeterminate]=\"someValidationRulesSelected\"\n (change)=\"onSelectAllValidationRules($event.checked)\">\n </mat-checkbox>\n </div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">jsonPath</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">verificationType</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">expectedType</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">expectedValue</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Result</div>\n </div>\n\n <!-- Table Body -->\n <div class=\"cqa-flex cqa-flex-col\">\n <div *ngFor=\"let validationRule of validationFormArray.controls; let i = index; trackBy: trackByValidationRuleIndex\" \n [formGroup]=\"getValidationFormGroup(i)\"\n class=\"cqa-grid cqa-grid-cols-6 cqa-gap-2 cqa-p-3 cqa-border-b cqa-border-gray-200 cqa-items-center cqa-last:border-b-0\">\n <!-- Checkbox -->\n <div class=\"cqa-flex cqa-items-center\">\n <mat-checkbox formControlName=\"checked\">\n </mat-checkbox>\n </div>\n\n <!-- jsonPath -->\n <div>\n <cqa-custom-input\n [placeholder]=\"'jsonPath'\"\n [value]=\"getValidationFormGroup(i).get('jsonPath')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getValidationFormGroup(i).get('jsonPath')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- verificationType -->\n <div>\n <cqa-dynamic-select\n [form]=\"getValidationFormGroup(i)\"\n [config]=\"getVerificationTypeConfig(i)\">\n </cqa-dynamic-select>\n </div>\n\n <!-- expectedType -->\n <div>\n <cqa-dynamic-select\n [form]=\"getValidationFormGroup(i)\"\n [config]=\"getExpectedTypeConfig(i)\">\n </cqa-dynamic-select>\n </div>\n\n <!-- expectedValue -->\n <div>\n <cqa-custom-input\n [placeholder]=\"'expectedValue'\"\n [value]=\"getValidationFormGroup(i).get('expectedValue')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getValidationFormGroup(i).get('expectedValue')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- Result and Delete -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <button\n type=\"button\"\n class=\"cqa-px-3 cqa-py-1 cqa-rounded cqa-text-[10px] cqa-font-medium\"\n [ngClass]=\"getResultClass(getValidationFormGroup(i).get('result')?.value || 'Not run')\">\n {{ getValidationFormGroup(i).get('result')?.value || 'Not run' }}\n </button>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-6 cqa-h-6 cqa-rounded cqa-text-red-500 hover:cqa-text-red-700 hover:cqa-bg-red-50 cqa-transition-colors\"\n (click)=\"removeValidationRule(i)\"\n [attr.aria-label]=\"'Delete validation rule'\">\n <mat-icon class=\"cqa-text-base\">delete</mat-icon>\n </button>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Add Another Rule and Delete Selected -->\n <div class=\"cqa-flex cqa-justify-between cqa-items-center cqa-mb-4\">\n <button\n *ngIf=\"someValidationRulesSelected || allValidationRulesSelected\"\n type=\"button\"\n class=\"cqa-text-red-600 cqa-text-sm cqa-font-medium cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-red-700 cqa-transition-colors\"\n (click)=\"onDeleteSelectedValidationRules()\">\n <mat-icon class=\"cqa-text-base\">delete</mat-icon>\n <span>Delete Selected</span>\n </button>\n <button\n type=\"button\"\n class=\"cqa-text-blue-600 cqa-text-sm cqa-font-medium cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-blue-700 cqa-transition-colors\"\n (click)=\"addValidationRule()\">\n <mat-icon class=\"cqa-text-base\">add</mat-icon>\n <span>Add Another</span>\n </button>\n </div>\n </div>\n</ng-container>\n\n\n <!-- Response Preview Section -->\n <div class=\"cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden cqa-mb-6\">\n <div class=\"cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Response Preview</h3>\n </div>\n <div class=\"cqa-p-4 cqa-bg-gray-50 cqa-overflow-auto\" style=\"max-height: 300px;\">\n <pre *ngIf=\"responsePreview\" class=\"cqa-text-xs cqa-font-mono cqa-text-gray-800 cqa-whitespace-pre-wrap\">{{ formatJsonResponse(responsePreview) }}</pre>\n <p *ngIf=\"!responsePreview\" class=\"cqa-text-sm cqa-text-gray-400 cqa-text-center cqa-py-8\">\n No response yet. Send a request to see the response preview.\n </p>\n </div>\n </div>\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-w-full cqa-gap-2 cqa-mt-auto cqa-pt-4 cqa-border-t cqa-border-gray-200\">\n <!-- Cancel button (only on first step) -->\n <cqa-button\n *ngIf=\"selectedProgressStep === 'request-details'\"\n class=\"cqa-w-1/2\"\n variant=\"outlined\"\n text=\"Cancel\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <!-- Back button (on all steps except first) -->\n <cqa-button\n *ngIf=\"selectedProgressStep !== 'request-details'\"\n class=\"cqa-w-1/2\"\n variant=\"outlined\"\n text=\"Back\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onBack()\">\n </cqa-button>\n <!-- Next/Create Step button -->\n <cqa-button\n class=\"cqa-w-1/2\"\n variant=\"filled\"\n [text]=\"isLastStep() ? 'Create Step' : 'Next'\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"isLastStep() ? onCreateStep() : onNext()\">\n </cqa-button>\n </div>\n</div>\n\n", components: [{ type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore"] }, { type: CustomInputComponent, selector: "cqa-custom-input", inputs: ["label", "type", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "inputInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused", "enterPressed"] }, { type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }, { type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: CustomTextareaComponent, selector: "cqa-custom-textarea", inputs: ["label", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "rows", "cols", "resize", "textareaInlineStyle", "labelInlineStyle", "customClass"], outputs: ["valueChange", "blurred", "focused"] }, { type: i3$3.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }], directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] });
22020
+ StepBuilderApiComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StepBuilderApiComponent, selector: "cqa-step-builder-api", inputs: { httpMethodOptions: "httpMethodOptions", headerNameOptions: "headerNameOptions", currentStep: "currentStep", responsePreview: "responsePreview", isLoading: "isLoading", initialData: "initialData" }, outputs: { createStep: "createStep", cancelled: "cancelled", sendRequest: "sendRequest", importCurl: "importCurl" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Create API Test Step\n </h2>\n\n <!-- Progress Tracker -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-4 cqa-mb-6 cqa-pb-4 cqa-border-b cqa-border-gray-200\">\n <!-- <div *ngFor=\"let step of progressSteps\"\n class=\"cqa-flex cqa-items-center cqa-gap-2\"\n [ngClass]=\"getProgressStepClass(step)\">\n <span class=\"cqa-text-sm cqa-font-medium\">{{ getProgressStepNumber(step) }} {{ getProgressStepLabel(step) }}</span>\n <span *ngIf=\"step !== 'validation'\" class=\"cqa-text-gray-300\">\u2022</span>\n </div> -->\n <div class=\"cqa-flex cqa-items-center cqa-w-full cqa-justify-between\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [ngClass]=\"{'cqa-text-purple-600 cqa-font-semibold': selectedProgressStep === 'request-details'}\" (click)=\"onProgressStepChange('request-details')\">\n <div class=\"cqa-w-8 cqa-h-8 cqa-flex cqa-items-center cqa-justify-center cqa-rounded-full cqa-bg-purple-600 cqa-text-white cqa-text-xs cqa-font-semibold\">1</div>\n <div>Request Details</div>\n <div></div>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [ngClass]=\"{'cqa-text-purple-600 cqa-font-semibold': selectedProgressStep === 'store-response'}\" (click)=\"onProgressStepChange('store-response')\">\n <div class=\"cqa-w-8 cqa-h-8 cqa-flex cqa-items-center cqa-justify-center cqa-rounded-full cqa-bg-purple-600 cqa-text-white cqa-text-xs cqa-font-semibold\">2</div>\n <div>Store Response</div>\n <div></div>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [ngClass]=\"{'cqa-text-purple-600 cqa-font-semibold': selectedProgressStep === 'validation'}\" (click)=\"onProgressStepChange('validation')\">\n <div class=\"cqa-w-8 cqa-h-8 cqa-flex cqa-items-center cqa-justify-center cqa-rounded-full cqa-bg-purple-600 cqa-text-white cqa-text-xs cqa-font-semibold\">3</div>\n <div>Validation</div>\n <div></div>\n </div>\n </div>\n </div>\n <ng-container *ngIf=\"selectedProgressStep === 'request-details'\">\n <!-- API Request Configuration -->\n <div class=\"cqa-flex cqa-items-start cqa-gap-2 cqa-mb-3\">\n <div class=\"cqa-w-32 cqa-flex-shrink-0\">\n <cqa-dynamic-select\n [form]=\"apiForm\"\n [config]=\"getHttpMethodConfig()\">\n </cqa-dynamic-select>\n </div>\n <div class=\"cqa-flex-1\">\n <cqa-custom-input\n [placeholder]=\"'Enter API endpoint URL'\"\n [value]=\"apiForm.get('url')?.value || ''\"\n [fullWidth]=\"true\"\n [errors]=\"getUrlErrors()\"\n (valueChange)=\"onUrlChange($event)\"\n (blurred)=\"onUrlBlur()\">\n </cqa-custom-input>\n </div>\n <cqa-button\n variant=\"outlined\"\n text=\"Import API cURL\"\n (clicked)=\"onImportCurl()\">\n </cqa-button>\n <cqa-button\n variant=\"filled\"\n text=\"Send Request\"\n (clicked)=\"onSendRequest()\"\n [disabled]=\"!apiForm.get('url')?.value || isLoading\">\n </cqa-button>\n </div>\n\n <!-- Request Details Tabs -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-overflow-hidden cqa-mb-6\">\n <!-- Tab Navigation -->\n <div class=\"cqa-flex cqa-items-center cqa-border-b cqa-border-gray-200 cqa-bg-gray-50\">\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'headers'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'headers'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'headers'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'headers'\"\n (click)=\"onTabChange('headers')\">\n Headers\n </button>\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'body'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'body'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'body'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'body'\"\n (click)=\"onTabChange('body')\">\n Body\n </button>\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'params'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'params'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'params'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'params'\"\n (click)=\"onTabChange('params')\">\n Params\n </button>\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'scripts'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'scripts'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'scripts'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'scripts'\"\n (click)=\"onTabChange('scripts')\">\n Scripts\n </button>\n </div>\n\n <!-- Tab Content -->\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-p-4 cqa-border cqa-border-gray-200 cqa-border-t-0 cqa-rounded-b-lg\">\n <!-- Headers Tab -->\n <div *ngIf=\"selectedTab === 'headers'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-start\">\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Header Name*</div>\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Header Value*</div>\n </div>\n <div *ngFor=\"let header of headersFormArray.controls; let i = index; trackBy: trackByHeaderIndex\" \n class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-center\">\n <div>\n <cqa-dynamic-select\n [form]=\"getHeaderFormGroup(i)\"\n [config]=\"getHeaderNameConfig(i)\">\n </cqa-dynamic-select>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-flex-1\">\n <cqa-custom-input\n [placeholder]=\"'Header value'\"\n [value]=\"getHeaderFormGroup(i).get('value')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getHeaderFormGroup(i).get('value')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-8 cqa-h-8 cqa-rounded cqa-text-red-500 hover:cqa-text-red-700 hover:cqa-bg-red-50 cqa-transition-colors\"\n (click)=\"removeHeader(i)\"\n [attr.aria-label]=\"'Remove header'\">\n <mat-icon class=\"cqa-text-lg\">delete</mat-icon>\n </button>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"cqa-text-blue-600 cqa-text-sm cqa-font-medium cqa-self-start cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-blue-700 cqa-transition-colors\"\n (click)=\"addHeader()\">\n <mat-icon class=\"cqa-text-base\">add</mat-icon>\n <span>Add Header</span>\n </button>\n </div>\n\n <!-- Body Tab -->\n <div *ngIf=\"selectedTab === 'body'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <cqa-custom-textarea\n [placeholder]=\"'Enter request body (JSON, XML, etc.)'\"\n [value]=\"apiForm.get('body')?.value || ''\"\n [fullWidth]=\"true\"\n [rows]=\"10\"\n (valueChange)=\"apiForm.get('body')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n\n <!-- Params Tab -->\n <div *ngIf=\"selectedTab === 'params'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-start\">\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Parameter Name</div>\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Parameter Value</div>\n </div>\n <div *ngFor=\"let param of paramsFormArray.controls; let i = index; trackBy: trackByParamIndex\" \n class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-center\">\n <div>\n <cqa-custom-input\n [placeholder]=\"'Parameter name'\"\n [value]=\"getParamFormGroup(i).get('name')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getParamFormGroup(i).get('name')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-flex-1\">\n <cqa-custom-input\n [placeholder]=\"'Parameter value'\"\n [value]=\"getParamFormGroup(i).get('value')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getParamFormGroup(i).get('value')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-8 cqa-h-8 cqa-rounded cqa-text-red-500 hover:cqa-text-red-700 hover:cqa-bg-red-50 cqa-transition-colors\"\n (click)=\"removeParam(i)\"\n [attr.aria-label]=\"'Remove parameter'\">\n <mat-icon class=\"cqa-text-lg\">delete</mat-icon>\n </button>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"cqa-text-blue-600 cqa-text-sm cqa-font-medium cqa-self-start cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-blue-700 cqa-transition-colors\"\n (click)=\"addParam()\">\n <mat-icon class=\"cqa-text-base\">add</mat-icon>\n <span>Add Parameter</span>\n </button>\n </div>\n\n <!-- Scripts Tab -->\n <div *ngIf=\"selectedTab === 'scripts'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <cqa-custom-textarea\n [placeholder]=\"'Enter scripts (JavaScript, etc.)'\"\n [value]=\"apiForm.get('scripts')?.value || ''\"\n [fullWidth]=\"true\"\n [rows]=\"10\"\n (valueChange)=\"apiForm.get('scripts')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n </div>\n </div>\n\n\n</ng-container>\n<ng-container *ngIf=\"selectedProgressStep === 'store-response'\">\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-max-h-[500px] cqa-overflow-y-auto\">\n <!-- Store Response Title -->\n <h3 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Store Response\n </h3>\n\n <!-- Variable Name Input -->\n <div class=\"cqa-mb-6\">\n <label class=\"cqa-text-[12px] cqa-font-medium cqa-text-gray-700 cqa-mb-1 cqa-block\">\n Variable Name\n </label>\n <cqa-custom-input\n [placeholder]=\"'Variable Name'\"\n [value]=\"apiForm.get('variableName')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"apiForm.get('variableName')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n </div>\n</ng-container>\n<ng-container *ngIf=\"selectedProgressStep === 'validation'\">\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-max-h-[500px] cqa-overflow-y-auto\">\n <!-- Validation Rules Title -->\n <h3 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Validation Rules\n </h3>\n\n <!-- Validation Rules Table -->\n <div class=\"cqa-bg-white cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden cqa-mb-4\">\n <!-- Table Header -->\n <div class=\"cqa-grid cqa-grid-cols-6 cqa-gap-2 cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200 cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center\">\n <mat-checkbox\n [checked]=\"allValidationRulesSelected\"\n [indeterminate]=\"someValidationRulesSelected\"\n (change)=\"onSelectAllValidationRules($event.checked)\">\n </mat-checkbox>\n </div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">jsonPath</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">verificationType</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">expectedType</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">expectedValue</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Result</div>\n </div>\n\n <!-- Table Body -->\n <div class=\"cqa-flex cqa-flex-col\">\n <div *ngFor=\"let validationRule of validationFormArray.controls; let i = index; trackBy: trackByValidationRuleIndex\" \n [formGroup]=\"getValidationFormGroup(i)\"\n class=\"cqa-grid cqa-grid-cols-6 cqa-gap-2 cqa-p-3 cqa-border-b cqa-border-gray-200 cqa-items-center cqa-last:border-b-0\">\n <!-- Checkbox -->\n <div class=\"cqa-flex cqa-items-center\">\n <mat-checkbox formControlName=\"checked\">\n </mat-checkbox>\n </div>\n\n <!-- jsonPath -->\n <div>\n <cqa-custom-input\n [placeholder]=\"'jsonPath'\"\n [value]=\"getValidationFormGroup(i).get('jsonPath')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getValidationFormGroup(i).get('jsonPath')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- verificationType -->\n <div>\n <cqa-dynamic-select\n [form]=\"getValidationFormGroup(i)\"\n [config]=\"getVerificationTypeConfig(i)\">\n </cqa-dynamic-select>\n </div>\n\n <!-- expectedType -->\n <div>\n <cqa-dynamic-select\n [form]=\"getValidationFormGroup(i)\"\n [config]=\"getExpectedTypeConfig(i)\">\n </cqa-dynamic-select>\n </div>\n\n <!-- expectedValue -->\n <div>\n <cqa-custom-input\n [placeholder]=\"'expectedValue'\"\n [value]=\"getValidationFormGroup(i).get('expectedValue')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getValidationFormGroup(i).get('expectedValue')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- Result and Delete -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <button\n type=\"button\"\n class=\"cqa-px-3 cqa-py-1 cqa-rounded cqa-text-[10px] cqa-font-medium\"\n [ngClass]=\"getResultClass(getValidationFormGroup(i).get('result')?.value || 'Not run')\">\n {{ getValidationFormGroup(i).get('result')?.value || 'Not run' }}\n </button>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-6 cqa-h-6 cqa-rounded cqa-text-red-500 hover:cqa-text-red-700 hover:cqa-bg-red-50 cqa-transition-colors\"\n (click)=\"removeValidationRule(i)\"\n [attr.aria-label]=\"'Delete validation rule'\">\n <mat-icon class=\"cqa-text-base\">delete</mat-icon>\n </button>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Add Another Rule and Delete Selected -->\n <div class=\"cqa-flex cqa-justify-between cqa-items-center cqa-mb-4\">\n <button\n *ngIf=\"someValidationRulesSelected || allValidationRulesSelected\"\n type=\"button\"\n class=\"cqa-text-red-600 cqa-text-sm cqa-font-medium cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-red-700 cqa-transition-colors\"\n (click)=\"onDeleteSelectedValidationRules()\">\n <mat-icon class=\"cqa-text-base\">delete</mat-icon>\n <span>Delete Selected</span>\n </button>\n <button\n type=\"button\"\n class=\"cqa-text-blue-600 cqa-text-sm cqa-font-medium cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-blue-700 cqa-transition-colors\"\n (click)=\"addValidationRule()\">\n <mat-icon class=\"cqa-text-base\">add</mat-icon>\n <span>Add Another</span>\n </button>\n </div>\n </div>\n</ng-container>\n\n\n <!-- Response Preview Section -->\n <div class=\"cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden cqa-mb-6\">\n <div class=\"cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Response Preview</h3>\n </div>\n <div class=\"cqa-p-4 cqa-bg-gray-50 cqa-overflow-auto\" style=\"max-height: 300px;\">\n <pre *ngIf=\"responsePreview\" class=\"cqa-text-xs cqa-font-mono cqa-text-gray-800 cqa-whitespace-pre-wrap\">{{ formatJsonResponse(responsePreview) }}</pre>\n <p *ngIf=\"!responsePreview\" class=\"cqa-text-sm cqa-text-gray-400 cqa-text-center cqa-py-8\">\n No response yet. Send a request to see the response preview.\n </p>\n </div>\n </div>\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-w-full cqa-gap-2 cqa-mt-auto cqa-pt-4 cqa-border-t cqa-border-gray-200\">\n <!-- Cancel button (only on first step) -->\n <cqa-button\n *ngIf=\"selectedProgressStep === 'request-details'\"\n class=\"cqa-w-1/2\"\n variant=\"outlined\"\n text=\"Cancel\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <!-- Back button (on all steps except first) -->\n <cqa-button\n *ngIf=\"selectedProgressStep !== 'request-details'\"\n class=\"cqa-w-1/2\"\n variant=\"outlined\"\n text=\"Back\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onBack()\">\n </cqa-button>\n <!-- Next/Create Step button -->\n <cqa-button\n class=\"cqa-w-1/2\"\n variant=\"filled\"\n [text]=\"isLastStep() ? 'Create Step' : 'Next'\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"isLastStep() ? onCreateStep() : onNext()\">\n </cqa-button>\n </div>\n</div>\n\n", components: [{ type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore"] }, { type: CustomInputComponent, selector: "cqa-custom-input", inputs: ["label", "type", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "inputInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused", "enterPressed"] }, { type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }, { type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: CustomTextareaComponent, selector: "cqa-custom-textarea", inputs: ["label", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "rows", "cols", "resize", "textareaInlineStyle", "labelInlineStyle", "customClass"], outputs: ["valueChange", "blurred", "focused"] }, { type: i3$3.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }], directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] });
22001
22021
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepBuilderApiComponent, decorators: [{
22002
22022
  type: Component,
22003
- args: [{ selector: 'cqa-step-builder-api', host: { class: 'cqa-ui-root' }, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Create API Test Step\n </h2>\n\n <!-- Progress Tracker -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-4 cqa-mb-6 cqa-pb-4 cqa-border-b cqa-border-gray-200\">\n <!-- <div *ngFor=\"let step of progressSteps\"\n class=\"cqa-flex cqa-items-center cqa-gap-2\"\n [ngClass]=\"getProgressStepClass(step)\">\n <span class=\"cqa-text-sm cqa-font-medium\">{{ getProgressStepNumber(step) }} {{ getProgressStepLabel(step) }}</span>\n <span *ngIf=\"step !== 'validation'\" class=\"cqa-text-gray-300\">\u2022</span>\n </div> -->\n <div\n class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [ngClass]=\"{'cqa-text-purple-600 cqa-font-semibold': selectedProgressStep === 'request-details'}\" (click)=\"onProgressStepChange('request-details')\">\n <div>1</div>\n <div>Request Details</div>\n <div></div>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [ngClass]=\"{'cqa-text-purple-600 cqa-font-semibold': selectedProgressStep === 'store-response'}\" (click)=\"onProgressStepChange('store-response')\">\n <div>2</div>\n <div>Store Response</div>\n <div></div>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [ngClass]=\"{'cqa-text-purple-600 cqa-font-semibold': selectedProgressStep === 'validation'}\" (click)=\"onProgressStepChange('validation')\">\n <div>3</div>\n <div>Validation</div>\n <div></div>\n </div>\n </div>\n </div>\n <ng-container *ngIf=\"selectedProgressStep === 'request-details'\">\n <!-- API Request Configuration -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-mb-6\">\n <div class=\"cqa-w-32 cqa-flex-shrink-0\">\n <cqa-dynamic-select\n [form]=\"apiForm\"\n [config]=\"getHttpMethodConfig()\">\n </cqa-dynamic-select>\n </div>\n <div class=\"cqa-flex-1\">\n <cqa-custom-input\n [placeholder]=\"'Enter API endpoint URL'\"\n [value]=\"apiForm.get('url')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"apiForm.get('url')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <cqa-button\n variant=\"outlined\"\n text=\"Import API cURL\"\n (clicked)=\"onImportCurl()\">\n </cqa-button>\n <cqa-button\n variant=\"filled\"\n text=\"Send Request\"\n (clicked)=\"onSendRequest()\"\n [disabled]=\"!apiForm.get('url')?.value || isLoading\">\n </cqa-button>\n </div>\n\n <!-- Request Details Tabs -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-overflow-hidden cqa-mb-6\">\n <!-- Tab Navigation -->\n <div class=\"cqa-flex cqa-items-center cqa-border-b cqa-border-gray-200 cqa-bg-gray-50\">\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'headers'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'headers'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'headers'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'headers'\"\n (click)=\"onTabChange('headers')\">\n Headers\n </button>\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'body'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'body'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'body'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'body'\"\n (click)=\"onTabChange('body')\">\n Body\n </button>\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'params'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'params'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'params'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'params'\"\n (click)=\"onTabChange('params')\">\n Params\n </button>\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'scripts'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'scripts'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'scripts'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'scripts'\"\n (click)=\"onTabChange('scripts')\">\n Scripts\n </button>\n </div>\n\n <!-- Tab Content -->\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-p-4 cqa-border cqa-border-gray-200 cqa-border-t-0 cqa-rounded-b-lg\">\n <!-- Headers Tab -->\n <div *ngIf=\"selectedTab === 'headers'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-start\">\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Header Name</div>\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Header Value</div>\n </div>\n <div *ngFor=\"let header of headersFormArray.controls; let i = index; trackBy: trackByHeaderIndex\" \n class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-center\">\n <div>\n <cqa-dynamic-select\n [form]=\"getHeaderFormGroup(i)\"\n [config]=\"getHeaderNameConfig(i)\">\n </cqa-dynamic-select>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-flex-1\">\n <cqa-custom-input\n [placeholder]=\"'Header value'\"\n [value]=\"getHeaderFormGroup(i).get('value')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getHeaderFormGroup(i).get('value')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-8 cqa-h-8 cqa-rounded cqa-text-red-500 hover:cqa-text-red-700 hover:cqa-bg-red-50 cqa-transition-colors\"\n (click)=\"removeHeader(i)\"\n [attr.aria-label]=\"'Remove header'\">\n <mat-icon class=\"cqa-text-lg\">delete</mat-icon>\n </button>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"cqa-text-blue-600 cqa-text-sm cqa-font-medium cqa-self-start cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-blue-700 cqa-transition-colors\"\n (click)=\"addHeader()\">\n <mat-icon class=\"cqa-text-base\">add</mat-icon>\n <span>Add Header</span>\n </button>\n </div>\n\n <!-- Body Tab -->\n <div *ngIf=\"selectedTab === 'body'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <cqa-custom-textarea\n [placeholder]=\"'Enter request body (JSON, XML, etc.)'\"\n [value]=\"apiForm.get('body')?.value || ''\"\n [fullWidth]=\"true\"\n [rows]=\"10\"\n (valueChange)=\"apiForm.get('body')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n\n <!-- Params Tab -->\n <div *ngIf=\"selectedTab === 'params'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-start\">\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Parameter Name</div>\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Parameter Value</div>\n </div>\n <div *ngFor=\"let param of paramsFormArray.controls; let i = index; trackBy: trackByParamIndex\" \n class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-center\">\n <div>\n <cqa-custom-input\n [placeholder]=\"'Parameter name'\"\n [value]=\"getParamFormGroup(i).get('name')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getParamFormGroup(i).get('name')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-flex-1\">\n <cqa-custom-input\n [placeholder]=\"'Parameter value'\"\n [value]=\"getParamFormGroup(i).get('value')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getParamFormGroup(i).get('value')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-8 cqa-h-8 cqa-rounded cqa-text-red-500 hover:cqa-text-red-700 hover:cqa-bg-red-50 cqa-transition-colors\"\n (click)=\"removeParam(i)\"\n [attr.aria-label]=\"'Remove parameter'\">\n <mat-icon class=\"cqa-text-lg\">delete</mat-icon>\n </button>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"cqa-text-blue-600 cqa-text-sm cqa-font-medium cqa-self-start cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-blue-700 cqa-transition-colors\"\n (click)=\"addParam()\">\n <mat-icon class=\"cqa-text-base\">add</mat-icon>\n <span>Add Parameter</span>\n </button>\n </div>\n\n <!-- Scripts Tab -->\n <div *ngIf=\"selectedTab === 'scripts'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <cqa-custom-textarea\n [placeholder]=\"'Enter scripts (JavaScript, etc.)'\"\n [value]=\"apiForm.get('scripts')?.value || ''\"\n [fullWidth]=\"true\"\n [rows]=\"10\"\n (valueChange)=\"apiForm.get('scripts')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n </div>\n </div>\n\n\n</ng-container>\n<ng-container *ngIf=\"selectedProgressStep === 'store-response'\">\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-max-h-[500px] cqa-overflow-y-auto\">\n <!-- Store Response Title -->\n <h3 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Store Response\n </h3>\n\n <!-- Variable Name Input -->\n <div class=\"cqa-mb-6\">\n <label class=\"cqa-text-[12px] cqa-font-medium cqa-text-gray-700 cqa-mb-1 cqa-block\">\n Variable Name\n </label>\n <cqa-custom-input\n [placeholder]=\"'Variable Name'\"\n [value]=\"apiForm.get('variableName')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"apiForm.get('variableName')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n </div>\n</ng-container>\n<ng-container *ngIf=\"selectedProgressStep === 'validation'\">\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-max-h-[500px] cqa-overflow-y-auto\">\n <!-- Validation Rules Title -->\n <h3 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Validation Rules\n </h3>\n\n <!-- Validation Rules Table -->\n <div class=\"cqa-bg-white cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden cqa-mb-4\">\n <!-- Table Header -->\n <div class=\"cqa-grid cqa-grid-cols-6 cqa-gap-2 cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200 cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center\">\n <mat-checkbox\n [checked]=\"allValidationRulesSelected\"\n [indeterminate]=\"someValidationRulesSelected\"\n (change)=\"onSelectAllValidationRules($event.checked)\">\n </mat-checkbox>\n </div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">jsonPath</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">verificationType</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">expectedType</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">expectedValue</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Result</div>\n </div>\n\n <!-- Table Body -->\n <div class=\"cqa-flex cqa-flex-col\">\n <div *ngFor=\"let validationRule of validationFormArray.controls; let i = index; trackBy: trackByValidationRuleIndex\" \n [formGroup]=\"getValidationFormGroup(i)\"\n class=\"cqa-grid cqa-grid-cols-6 cqa-gap-2 cqa-p-3 cqa-border-b cqa-border-gray-200 cqa-items-center cqa-last:border-b-0\">\n <!-- Checkbox -->\n <div class=\"cqa-flex cqa-items-center\">\n <mat-checkbox formControlName=\"checked\">\n </mat-checkbox>\n </div>\n\n <!-- jsonPath -->\n <div>\n <cqa-custom-input\n [placeholder]=\"'jsonPath'\"\n [value]=\"getValidationFormGroup(i).get('jsonPath')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getValidationFormGroup(i).get('jsonPath')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- verificationType -->\n <div>\n <cqa-dynamic-select\n [form]=\"getValidationFormGroup(i)\"\n [config]=\"getVerificationTypeConfig(i)\">\n </cqa-dynamic-select>\n </div>\n\n <!-- expectedType -->\n <div>\n <cqa-dynamic-select\n [form]=\"getValidationFormGroup(i)\"\n [config]=\"getExpectedTypeConfig(i)\">\n </cqa-dynamic-select>\n </div>\n\n <!-- expectedValue -->\n <div>\n <cqa-custom-input\n [placeholder]=\"'expectedValue'\"\n [value]=\"getValidationFormGroup(i).get('expectedValue')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getValidationFormGroup(i).get('expectedValue')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- Result and Delete -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <button\n type=\"button\"\n class=\"cqa-px-3 cqa-py-1 cqa-rounded cqa-text-[10px] cqa-font-medium\"\n [ngClass]=\"getResultClass(getValidationFormGroup(i).get('result')?.value || 'Not run')\">\n {{ getValidationFormGroup(i).get('result')?.value || 'Not run' }}\n </button>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-6 cqa-h-6 cqa-rounded cqa-text-red-500 hover:cqa-text-red-700 hover:cqa-bg-red-50 cqa-transition-colors\"\n (click)=\"removeValidationRule(i)\"\n [attr.aria-label]=\"'Delete validation rule'\">\n <mat-icon class=\"cqa-text-base\">delete</mat-icon>\n </button>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Add Another Rule and Delete Selected -->\n <div class=\"cqa-flex cqa-justify-between cqa-items-center cqa-mb-4\">\n <button\n *ngIf=\"someValidationRulesSelected || allValidationRulesSelected\"\n type=\"button\"\n class=\"cqa-text-red-600 cqa-text-sm cqa-font-medium cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-red-700 cqa-transition-colors\"\n (click)=\"onDeleteSelectedValidationRules()\">\n <mat-icon class=\"cqa-text-base\">delete</mat-icon>\n <span>Delete Selected</span>\n </button>\n <button\n type=\"button\"\n class=\"cqa-text-blue-600 cqa-text-sm cqa-font-medium cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-blue-700 cqa-transition-colors\"\n (click)=\"addValidationRule()\">\n <mat-icon class=\"cqa-text-base\">add</mat-icon>\n <span>Add Another</span>\n </button>\n </div>\n </div>\n</ng-container>\n\n\n <!-- Response Preview Section -->\n <div class=\"cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden cqa-mb-6\">\n <div class=\"cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Response Preview</h3>\n </div>\n <div class=\"cqa-p-4 cqa-bg-gray-50 cqa-overflow-auto\" style=\"max-height: 300px;\">\n <pre *ngIf=\"responsePreview\" class=\"cqa-text-xs cqa-font-mono cqa-text-gray-800 cqa-whitespace-pre-wrap\">{{ formatJsonResponse(responsePreview) }}</pre>\n <p *ngIf=\"!responsePreview\" class=\"cqa-text-sm cqa-text-gray-400 cqa-text-center cqa-py-8\">\n No response yet. Send a request to see the response preview.\n </p>\n </div>\n </div>\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-w-full cqa-gap-2 cqa-mt-auto cqa-pt-4 cqa-border-t cqa-border-gray-200\">\n <!-- Cancel button (only on first step) -->\n <cqa-button\n *ngIf=\"selectedProgressStep === 'request-details'\"\n class=\"cqa-w-1/2\"\n variant=\"outlined\"\n text=\"Cancel\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <!-- Back button (on all steps except first) -->\n <cqa-button\n *ngIf=\"selectedProgressStep !== 'request-details'\"\n class=\"cqa-w-1/2\"\n variant=\"outlined\"\n text=\"Back\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onBack()\">\n </cqa-button>\n <!-- Next/Create Step button -->\n <cqa-button\n class=\"cqa-w-1/2\"\n variant=\"filled\"\n [text]=\"isLastStep() ? 'Create Step' : 'Next'\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"isLastStep() ? onCreateStep() : onNext()\">\n </cqa-button>\n </div>\n</div>\n\n", styles: [] }]
22023
+ args: [{ selector: 'cqa-step-builder-api', host: { class: 'cqa-ui-root' }, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Create API Test Step\n </h2>\n\n <!-- Progress Tracker -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-4 cqa-mb-6 cqa-pb-4 cqa-border-b cqa-border-gray-200\">\n <!-- <div *ngFor=\"let step of progressSteps\"\n class=\"cqa-flex cqa-items-center cqa-gap-2\"\n [ngClass]=\"getProgressStepClass(step)\">\n <span class=\"cqa-text-sm cqa-font-medium\">{{ getProgressStepNumber(step) }} {{ getProgressStepLabel(step) }}</span>\n <span *ngIf=\"step !== 'validation'\" class=\"cqa-text-gray-300\">\u2022</span>\n </div> -->\n <div class=\"cqa-flex cqa-items-center cqa-w-full cqa-justify-between\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [ngClass]=\"{'cqa-text-purple-600 cqa-font-semibold': selectedProgressStep === 'request-details'}\" (click)=\"onProgressStepChange('request-details')\">\n <div class=\"cqa-w-8 cqa-h-8 cqa-flex cqa-items-center cqa-justify-center cqa-rounded-full cqa-bg-purple-600 cqa-text-white cqa-text-xs cqa-font-semibold\">1</div>\n <div>Request Details</div>\n <div></div>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [ngClass]=\"{'cqa-text-purple-600 cqa-font-semibold': selectedProgressStep === 'store-response'}\" (click)=\"onProgressStepChange('store-response')\">\n <div class=\"cqa-w-8 cqa-h-8 cqa-flex cqa-items-center cqa-justify-center cqa-rounded-full cqa-bg-purple-600 cqa-text-white cqa-text-xs cqa-font-semibold\">2</div>\n <div>Store Response</div>\n <div></div>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [ngClass]=\"{'cqa-text-purple-600 cqa-font-semibold': selectedProgressStep === 'validation'}\" (click)=\"onProgressStepChange('validation')\">\n <div class=\"cqa-w-8 cqa-h-8 cqa-flex cqa-items-center cqa-justify-center cqa-rounded-full cqa-bg-purple-600 cqa-text-white cqa-text-xs cqa-font-semibold\">3</div>\n <div>Validation</div>\n <div></div>\n </div>\n </div>\n </div>\n <ng-container *ngIf=\"selectedProgressStep === 'request-details'\">\n <!-- API Request Configuration -->\n <div class=\"cqa-flex cqa-items-start cqa-gap-2 cqa-mb-3\">\n <div class=\"cqa-w-32 cqa-flex-shrink-0\">\n <cqa-dynamic-select\n [form]=\"apiForm\"\n [config]=\"getHttpMethodConfig()\">\n </cqa-dynamic-select>\n </div>\n <div class=\"cqa-flex-1\">\n <cqa-custom-input\n [placeholder]=\"'Enter API endpoint URL'\"\n [value]=\"apiForm.get('url')?.value || ''\"\n [fullWidth]=\"true\"\n [errors]=\"getUrlErrors()\"\n (valueChange)=\"onUrlChange($event)\"\n (blurred)=\"onUrlBlur()\">\n </cqa-custom-input>\n </div>\n <cqa-button\n variant=\"outlined\"\n text=\"Import API cURL\"\n (clicked)=\"onImportCurl()\">\n </cqa-button>\n <cqa-button\n variant=\"filled\"\n text=\"Send Request\"\n (clicked)=\"onSendRequest()\"\n [disabled]=\"!apiForm.get('url')?.value || isLoading\">\n </cqa-button>\n </div>\n\n <!-- Request Details Tabs -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-overflow-hidden cqa-mb-6\">\n <!-- Tab Navigation -->\n <div class=\"cqa-flex cqa-items-center cqa-border-b cqa-border-gray-200 cqa-bg-gray-50\">\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'headers'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'headers'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'headers'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'headers'\"\n (click)=\"onTabChange('headers')\">\n Headers\n </button>\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'body'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'body'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'body'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'body'\"\n (click)=\"onTabChange('body')\">\n Body\n </button>\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'params'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'params'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'params'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'params'\"\n (click)=\"onTabChange('params')\">\n Params\n </button>\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'scripts'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'scripts'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'scripts'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'scripts'\"\n (click)=\"onTabChange('scripts')\">\n Scripts\n </button>\n </div>\n\n <!-- Tab Content -->\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-p-4 cqa-border cqa-border-gray-200 cqa-border-t-0 cqa-rounded-b-lg\">\n <!-- Headers Tab -->\n <div *ngIf=\"selectedTab === 'headers'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-start\">\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Header Name*</div>\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Header Value*</div>\n </div>\n <div *ngFor=\"let header of headersFormArray.controls; let i = index; trackBy: trackByHeaderIndex\" \n class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-center\">\n <div>\n <cqa-dynamic-select\n [form]=\"getHeaderFormGroup(i)\"\n [config]=\"getHeaderNameConfig(i)\">\n </cqa-dynamic-select>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-flex-1\">\n <cqa-custom-input\n [placeholder]=\"'Header value'\"\n [value]=\"getHeaderFormGroup(i).get('value')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getHeaderFormGroup(i).get('value')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-8 cqa-h-8 cqa-rounded cqa-text-red-500 hover:cqa-text-red-700 hover:cqa-bg-red-50 cqa-transition-colors\"\n (click)=\"removeHeader(i)\"\n [attr.aria-label]=\"'Remove header'\">\n <mat-icon class=\"cqa-text-lg\">delete</mat-icon>\n </button>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"cqa-text-blue-600 cqa-text-sm cqa-font-medium cqa-self-start cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-blue-700 cqa-transition-colors\"\n (click)=\"addHeader()\">\n <mat-icon class=\"cqa-text-base\">add</mat-icon>\n <span>Add Header</span>\n </button>\n </div>\n\n <!-- Body Tab -->\n <div *ngIf=\"selectedTab === 'body'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <cqa-custom-textarea\n [placeholder]=\"'Enter request body (JSON, XML, etc.)'\"\n [value]=\"apiForm.get('body')?.value || ''\"\n [fullWidth]=\"true\"\n [rows]=\"10\"\n (valueChange)=\"apiForm.get('body')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n\n <!-- Params Tab -->\n <div *ngIf=\"selectedTab === 'params'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-start\">\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Parameter Name</div>\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Parameter Value</div>\n </div>\n <div *ngFor=\"let param of paramsFormArray.controls; let i = index; trackBy: trackByParamIndex\" \n class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-center\">\n <div>\n <cqa-custom-input\n [placeholder]=\"'Parameter name'\"\n [value]=\"getParamFormGroup(i).get('name')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getParamFormGroup(i).get('name')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-flex-1\">\n <cqa-custom-input\n [placeholder]=\"'Parameter value'\"\n [value]=\"getParamFormGroup(i).get('value')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getParamFormGroup(i).get('value')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-8 cqa-h-8 cqa-rounded cqa-text-red-500 hover:cqa-text-red-700 hover:cqa-bg-red-50 cqa-transition-colors\"\n (click)=\"removeParam(i)\"\n [attr.aria-label]=\"'Remove parameter'\">\n <mat-icon class=\"cqa-text-lg\">delete</mat-icon>\n </button>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"cqa-text-blue-600 cqa-text-sm cqa-font-medium cqa-self-start cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-blue-700 cqa-transition-colors\"\n (click)=\"addParam()\">\n <mat-icon class=\"cqa-text-base\">add</mat-icon>\n <span>Add Parameter</span>\n </button>\n </div>\n\n <!-- Scripts Tab -->\n <div *ngIf=\"selectedTab === 'scripts'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <cqa-custom-textarea\n [placeholder]=\"'Enter scripts (JavaScript, etc.)'\"\n [value]=\"apiForm.get('scripts')?.value || ''\"\n [fullWidth]=\"true\"\n [rows]=\"10\"\n (valueChange)=\"apiForm.get('scripts')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n </div>\n </div>\n\n\n</ng-container>\n<ng-container *ngIf=\"selectedProgressStep === 'store-response'\">\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-max-h-[500px] cqa-overflow-y-auto\">\n <!-- Store Response Title -->\n <h3 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Store Response\n </h3>\n\n <!-- Variable Name Input -->\n <div class=\"cqa-mb-6\">\n <label class=\"cqa-text-[12px] cqa-font-medium cqa-text-gray-700 cqa-mb-1 cqa-block\">\n Variable Name\n </label>\n <cqa-custom-input\n [placeholder]=\"'Variable Name'\"\n [value]=\"apiForm.get('variableName')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"apiForm.get('variableName')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n </div>\n</ng-container>\n<ng-container *ngIf=\"selectedProgressStep === 'validation'\">\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-max-h-[500px] cqa-overflow-y-auto\">\n <!-- Validation Rules Title -->\n <h3 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Validation Rules\n </h3>\n\n <!-- Validation Rules Table -->\n <div class=\"cqa-bg-white cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden cqa-mb-4\">\n <!-- Table Header -->\n <div class=\"cqa-grid cqa-grid-cols-6 cqa-gap-2 cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200 cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center\">\n <mat-checkbox\n [checked]=\"allValidationRulesSelected\"\n [indeterminate]=\"someValidationRulesSelected\"\n (change)=\"onSelectAllValidationRules($event.checked)\">\n </mat-checkbox>\n </div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">jsonPath</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">verificationType</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">expectedType</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">expectedValue</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Result</div>\n </div>\n\n <!-- Table Body -->\n <div class=\"cqa-flex cqa-flex-col\">\n <div *ngFor=\"let validationRule of validationFormArray.controls; let i = index; trackBy: trackByValidationRuleIndex\" \n [formGroup]=\"getValidationFormGroup(i)\"\n class=\"cqa-grid cqa-grid-cols-6 cqa-gap-2 cqa-p-3 cqa-border-b cqa-border-gray-200 cqa-items-center cqa-last:border-b-0\">\n <!-- Checkbox -->\n <div class=\"cqa-flex cqa-items-center\">\n <mat-checkbox formControlName=\"checked\">\n </mat-checkbox>\n </div>\n\n <!-- jsonPath -->\n <div>\n <cqa-custom-input\n [placeholder]=\"'jsonPath'\"\n [value]=\"getValidationFormGroup(i).get('jsonPath')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getValidationFormGroup(i).get('jsonPath')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- verificationType -->\n <div>\n <cqa-dynamic-select\n [form]=\"getValidationFormGroup(i)\"\n [config]=\"getVerificationTypeConfig(i)\">\n </cqa-dynamic-select>\n </div>\n\n <!-- expectedType -->\n <div>\n <cqa-dynamic-select\n [form]=\"getValidationFormGroup(i)\"\n [config]=\"getExpectedTypeConfig(i)\">\n </cqa-dynamic-select>\n </div>\n\n <!-- expectedValue -->\n <div>\n <cqa-custom-input\n [placeholder]=\"'expectedValue'\"\n [value]=\"getValidationFormGroup(i).get('expectedValue')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getValidationFormGroup(i).get('expectedValue')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- Result and Delete -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <button\n type=\"button\"\n class=\"cqa-px-3 cqa-py-1 cqa-rounded cqa-text-[10px] cqa-font-medium\"\n [ngClass]=\"getResultClass(getValidationFormGroup(i).get('result')?.value || 'Not run')\">\n {{ getValidationFormGroup(i).get('result')?.value || 'Not run' }}\n </button>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-6 cqa-h-6 cqa-rounded cqa-text-red-500 hover:cqa-text-red-700 hover:cqa-bg-red-50 cqa-transition-colors\"\n (click)=\"removeValidationRule(i)\"\n [attr.aria-label]=\"'Delete validation rule'\">\n <mat-icon class=\"cqa-text-base\">delete</mat-icon>\n </button>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Add Another Rule and Delete Selected -->\n <div class=\"cqa-flex cqa-justify-between cqa-items-center cqa-mb-4\">\n <button\n *ngIf=\"someValidationRulesSelected || allValidationRulesSelected\"\n type=\"button\"\n class=\"cqa-text-red-600 cqa-text-sm cqa-font-medium cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-red-700 cqa-transition-colors\"\n (click)=\"onDeleteSelectedValidationRules()\">\n <mat-icon class=\"cqa-text-base\">delete</mat-icon>\n <span>Delete Selected</span>\n </button>\n <button\n type=\"button\"\n class=\"cqa-text-blue-600 cqa-text-sm cqa-font-medium cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-blue-700 cqa-transition-colors\"\n (click)=\"addValidationRule()\">\n <mat-icon class=\"cqa-text-base\">add</mat-icon>\n <span>Add Another</span>\n </button>\n </div>\n </div>\n</ng-container>\n\n\n <!-- Response Preview Section -->\n <div class=\"cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden cqa-mb-6\">\n <div class=\"cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Response Preview</h3>\n </div>\n <div class=\"cqa-p-4 cqa-bg-gray-50 cqa-overflow-auto\" style=\"max-height: 300px;\">\n <pre *ngIf=\"responsePreview\" class=\"cqa-text-xs cqa-font-mono cqa-text-gray-800 cqa-whitespace-pre-wrap\">{{ formatJsonResponse(responsePreview) }}</pre>\n <p *ngIf=\"!responsePreview\" class=\"cqa-text-sm cqa-text-gray-400 cqa-text-center cqa-py-8\">\n No response yet. Send a request to see the response preview.\n </p>\n </div>\n </div>\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-w-full cqa-gap-2 cqa-mt-auto cqa-pt-4 cqa-border-t cqa-border-gray-200\">\n <!-- Cancel button (only on first step) -->\n <cqa-button\n *ngIf=\"selectedProgressStep === 'request-details'\"\n class=\"cqa-w-1/2\"\n variant=\"outlined\"\n text=\"Cancel\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <!-- Back button (on all steps except first) -->\n <cqa-button\n *ngIf=\"selectedProgressStep !== 'request-details'\"\n class=\"cqa-w-1/2\"\n variant=\"outlined\"\n text=\"Back\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onBack()\">\n </cqa-button>\n <!-- Next/Create Step button -->\n <cqa-button\n class=\"cqa-w-1/2\"\n variant=\"filled\"\n [text]=\"isLastStep() ? 'Create Step' : 'Next'\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"isLastStep() ? onCreateStep() : onNext()\">\n </cqa-button>\n </div>\n</div>\n\n", styles: [] }]
22004
22024
  }], ctorParameters: function () { return [{ type: i2$1.FormBuilder }]; }, propDecorators: { httpMethodOptions: [{
22005
22025
  type: Input
22006
22026
  }], headerNameOptions: [{