@cqa-lib/cqa-ui 1.1.264 → 1.1.266

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.
@@ -25345,10 +25345,10 @@ class AdvancedVariablesFormComponent {
25345
25345
  }
25346
25346
  }
25347
25347
  AdvancedVariablesFormComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: AdvancedVariablesFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
25348
- AdvancedVariablesFormComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: AdvancedVariablesFormComponent, selector: "cqa-advanced-variables-form", inputs: { advancedVariables: "advancedVariables", advancedVariableForm: "advancedVariableForm" }, outputs: { variableBooleanChange: "variableBooleanChange", variableValueChange: "variableValueChange" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-flex cqa-gap-x-6 cqa-gap-y-4 cqa-flex-wrap advanced-variables-form cqa-mb-4\">\n <ng-container *ngFor=\"let variable of advancedVariables; let i = index; trackBy: trackByVariable\">\n <!-- Boolean variables with mat-slide-toggle -->\n <ng-container *ngIf=\"isBooleanType(variable)\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" style=\"width: 100%\">\n <mat-slide-toggle \n [checked]=\"getBooleanValue(variable, i)\"\n (change)=\"onVariableBooleanChange(variable.name, $event.checked)\" \n color=\"primary\">\n </mat-slide-toggle>\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 capitalize-first\">\n {{ variable.label }}\n </label>\n </div>\n </ng-container>\n\n <!-- str_list variables with dynamic list -->\n <ng-container *ngIf=\"isStrListType(variable)\">\n <div class=\"cqa-flex cqa-flex-col cqa-w-full\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <ng-container *ngIf=\"getStrListFormArray(variable, i) as formArray\">\n <div *ngFor=\"let control of formArray.controls; let itemIndex = index; trackBy: trackByControl\" class=\"cqa-flex cqa-gap-2 cqa-items-center\">\n <cqa-custom-input \n [placeholder]=\"'Enter locator'\" \n [value]=\"control.value\" \n [fullWidth]=\"true\"\n (valueChange)=\"onStrListItemChange(variable, i, itemIndex, $event)\">\n </cqa-custom-input>\n <div class=\"cqa-cursor-pointer cqa-text-red-600 cqa-flex cqa-items-center cqa-justify-center\" (click)=\"removeStrListItem(variable, i, itemIndex)\">\n <mat-icon style=\"font-size: 24px;\">delete</mat-icon>\n </div>\n <div *ngIf=\"itemIndex === formArray.length - 1\" class=\"cqa-cursor-pointer cqa-text-blue-600 cqa-flex cqa-items-center cqa-justify-center\" (click)=\"addStrListItem(variable, i)\">\n <mat-icon style=\"font-size: 24px;\">add</mat-icon>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n </ng-container>\n </ng-container>\n</div>\n\n", components: [{ type: i4$2.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["disabled", "disableRipple", "color", "tabIndex", "name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "checked"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
25348
+ AdvancedVariablesFormComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: AdvancedVariablesFormComponent, selector: "cqa-advanced-variables-form", inputs: { advancedVariables: "advancedVariables", advancedVariableForm: "advancedVariableForm" }, outputs: { variableBooleanChange: "variableBooleanChange", variableValueChange: "variableValueChange" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-flex cqa-gap-x-6 cqa-gap-y-4 cqa-flex-wrap advanced-variables-form cqa-mb-4\">\n <ng-container *ngFor=\"let variable of advancedVariables; let i = index; trackBy: trackByVariable\">\n <!-- Boolean variables with mat-slide-toggle -->\n <ng-container *ngIf=\"isBooleanType(variable)\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" style=\"width: 100%\">\n <mat-slide-toggle \n [checked]=\"getBooleanValue(variable, i)\"\n (change)=\"onVariableBooleanChange(variable.name, $event.checked)\" \n color=\"primary\">\n </mat-slide-toggle>\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 capitalize-first\">\n {{ variable.label }}\n </label>\n </div>\n </ng-container>\n\n <!-- str_list variables with dynamic list -->\n <ng-container *ngIf=\"isStrListType(variable)\">\n <div class=\"cqa-flex cqa-flex-col cqa-w-full\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <ng-container *ngIf=\"getStrListFormArray(variable, i) as formArray\">\n <div *ngFor=\"let control of formArray.controls; let itemIndex = index; trackBy: trackByControl\" class=\"cqa-flex cqa-gap-2 cqa-items-center\">\n <cqa-custom-input \n [placeholder]=\"'Enter locator'\" \n [value]=\"control.value\" \n [fullWidth]=\"true\"\n (valueChange)=\"onStrListItemChange(variable, i, itemIndex, $event)\">\n </cqa-custom-input>\n <div *ngIf=\"formArray.length > 1\" class=\"cqa-cursor-pointer cqa-text-red-600 cqa-flex cqa-items-center cqa-justify-center\" (click)=\"removeStrListItem(variable, i, itemIndex)\">\n <mat-icon style=\"font-size: 24px;\">delete</mat-icon>\n </div>\n <div *ngIf=\"itemIndex === formArray.length - 1\" class=\"cqa-cursor-pointer cqa-text-blue-600 cqa-flex cqa-items-center cqa-justify-center\" (click)=\"addStrListItem(variable, i)\">\n <mat-icon style=\"font-size: 24px;\">add</mat-icon>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n </ng-container>\n </ng-container>\n</div>\n\n", components: [{ type: i4$2.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["disabled", "disableRipple", "color", "tabIndex", "name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "checked"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
25349
25349
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: AdvancedVariablesFormComponent, decorators: [{
25350
25350
  type: Component,
25351
- args: [{ selector: 'cqa-advanced-variables-form', host: { class: 'cqa-ui-root' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"cqa-flex cqa-gap-x-6 cqa-gap-y-4 cqa-flex-wrap advanced-variables-form cqa-mb-4\">\n <ng-container *ngFor=\"let variable of advancedVariables; let i = index; trackBy: trackByVariable\">\n <!-- Boolean variables with mat-slide-toggle -->\n <ng-container *ngIf=\"isBooleanType(variable)\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" style=\"width: 100%\">\n <mat-slide-toggle \n [checked]=\"getBooleanValue(variable, i)\"\n (change)=\"onVariableBooleanChange(variable.name, $event.checked)\" \n color=\"primary\">\n </mat-slide-toggle>\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 capitalize-first\">\n {{ variable.label }}\n </label>\n </div>\n </ng-container>\n\n <!-- str_list variables with dynamic list -->\n <ng-container *ngIf=\"isStrListType(variable)\">\n <div class=\"cqa-flex cqa-flex-col cqa-w-full\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <ng-container *ngIf=\"getStrListFormArray(variable, i) as formArray\">\n <div *ngFor=\"let control of formArray.controls; let itemIndex = index; trackBy: trackByControl\" class=\"cqa-flex cqa-gap-2 cqa-items-center\">\n <cqa-custom-input \n [placeholder]=\"'Enter locator'\" \n [value]=\"control.value\" \n [fullWidth]=\"true\"\n (valueChange)=\"onStrListItemChange(variable, i, itemIndex, $event)\">\n </cqa-custom-input>\n <div class=\"cqa-cursor-pointer cqa-text-red-600 cqa-flex cqa-items-center cqa-justify-center\" (click)=\"removeStrListItem(variable, i, itemIndex)\">\n <mat-icon style=\"font-size: 24px;\">delete</mat-icon>\n </div>\n <div *ngIf=\"itemIndex === formArray.length - 1\" class=\"cqa-cursor-pointer cqa-text-blue-600 cqa-flex cqa-items-center cqa-justify-center\" (click)=\"addStrListItem(variable, i)\">\n <mat-icon style=\"font-size: 24px;\">add</mat-icon>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n </ng-container>\n </ng-container>\n</div>\n\n", styles: [] }]
25351
+ args: [{ selector: 'cqa-advanced-variables-form', host: { class: 'cqa-ui-root' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"cqa-flex cqa-gap-x-6 cqa-gap-y-4 cqa-flex-wrap advanced-variables-form cqa-mb-4\">\n <ng-container *ngFor=\"let variable of advancedVariables; let i = index; trackBy: trackByVariable\">\n <!-- Boolean variables with mat-slide-toggle -->\n <ng-container *ngIf=\"isBooleanType(variable)\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" style=\"width: 100%\">\n <mat-slide-toggle \n [checked]=\"getBooleanValue(variable, i)\"\n (change)=\"onVariableBooleanChange(variable.name, $event.checked)\" \n color=\"primary\">\n </mat-slide-toggle>\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 capitalize-first\">\n {{ variable.label }}\n </label>\n </div>\n </ng-container>\n\n <!-- str_list variables with dynamic list -->\n <ng-container *ngIf=\"isStrListType(variable)\">\n <div class=\"cqa-flex cqa-flex-col cqa-w-full\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <ng-container *ngIf=\"getStrListFormArray(variable, i) as formArray\">\n <div *ngFor=\"let control of formArray.controls; let itemIndex = index; trackBy: trackByControl\" class=\"cqa-flex cqa-gap-2 cqa-items-center\">\n <cqa-custom-input \n [placeholder]=\"'Enter locator'\" \n [value]=\"control.value\" \n [fullWidth]=\"true\"\n (valueChange)=\"onStrListItemChange(variable, i, itemIndex, $event)\">\n </cqa-custom-input>\n <div *ngIf=\"formArray.length > 1\" class=\"cqa-cursor-pointer cqa-text-red-600 cqa-flex cqa-items-center cqa-justify-center\" (click)=\"removeStrListItem(variable, i, itemIndex)\">\n <mat-icon style=\"font-size: 24px;\">delete</mat-icon>\n </div>\n <div *ngIf=\"itemIndex === formArray.length - 1\" class=\"cqa-cursor-pointer cqa-text-blue-600 cqa-flex cqa-items-center cqa-justify-center\" (click)=\"addStrListItem(variable, i)\">\n <mat-icon style=\"font-size: 24px;\">add</mat-icon>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n </ng-container>\n </ng-container>\n</div>\n\n", styles: [] }]
25352
25352
  }], propDecorators: { advancedVariables: [{
25353
25353
  type: Input
25354
25354
  }], advancedVariableForm: [{
@@ -27442,15 +27442,18 @@ class TemplateVariablesFormComponent {
27442
27442
  if (this.isElementType(variable) && variable.screenNameId) {
27443
27443
  const variableGroup = this.getVariableFormGroup(variable.name);
27444
27444
  if (variableGroup) {
27445
- // Initialize screen name form control with screenNameId (since valueBy is 'screenNameId')
27445
+ // Initialize screen name form control with screenNameId as string (to match option id format), or 'none' by default
27446
27446
  if (!variableGroup.get('selectedScreenName')) {
27447
- variableGroup.addControl('selectedScreenName', new FormControl(variable.screenNameId));
27447
+ const initialValue = variable.screenNameId ? String(variable.screenNameId) : 'none';
27448
+ variableGroup.addControl('selectedScreenName', new FormControl(initialValue));
27448
27449
  }
27449
27450
  else {
27450
27451
  // Update form control value if it doesn't match
27451
27452
  const currentValue = variableGroup.get('selectedScreenName')?.value;
27452
- if (currentValue !== variable.screenNameId) {
27453
- variableGroup.get('selectedScreenName')?.setValue(variable.screenNameId, { emitEvent: false });
27453
+ const expectedValue = variable.screenNameId ? String(variable.screenNameId) : 'none';
27454
+ const currentValueStr = currentValue != null ? String(currentValue) : null;
27455
+ if (currentValueStr !== expectedValue && currentValue !== variable.screenNameId) {
27456
+ variableGroup.get('selectedScreenName')?.setValue(expectedValue, { emitEvent: false });
27454
27457
  }
27455
27458
  }
27456
27459
  // If we have screenNameId but not selectedScreenName, find it from screenNameOptions
@@ -27484,67 +27487,105 @@ class TemplateVariablesFormComponent {
27484
27487
  if (this.isElementType(variable)) {
27485
27488
  const variableGroup = this.getVariableFormGroup(variable.name);
27486
27489
  if (variableGroup) {
27487
- let element = null;
27488
- // Priority 1: Find by elementId if available (from setTemplateVariables)
27490
+ // Only try to find and set element if elementId exists in template data
27491
+ // If no elementId, don't select anything - use default values
27489
27492
  if (variable.elementId) {
27493
+ let element = null;
27494
+ // Priority 1: Find by elementId (from setTemplateVariables)
27490
27495
  element = this.elementOptions.find(el => el.id === variable.elementId);
27491
- }
27492
- // Priority 2: Find by elementName if available (from setTemplateVariables)
27493
- if (!element && variable.elementName) {
27494
- element = this.elementOptions.find(el => el.name === variable.elementName);
27495
- }
27496
- // Priority 3: Find by locatorValue (for backward compatibility)
27497
- if (!element && variable.value) {
27498
- const elementValue = variable.value;
27499
- element = this.elementOptions.find(el => el.locatorValue === elementValue);
27500
- }
27501
- if (element) {
27502
- // Set screen name info from the found element
27503
- if (element.screenNameId && element.screenNameObj) {
27504
- variable.selectedScreenName = element.screenNameObj.name;
27505
- variable.screenNameId = element.screenNameId;
27506
- // Set form controls
27507
- // Since valueBy is 'screenNameId', we need to store the screenNameId (number) in the form control
27508
- if (!variableGroup.get('selectedScreenName')) {
27509
- variableGroup.addControl('selectedScreenName', new FormControl(element.screenNameId));
27496
+ // Priority 2: Find by elementName if elementId search didn't find it (fallback)
27497
+ if (!element && variable.elementName) {
27498
+ element = this.elementOptions.find(el => el.name === variable.elementName);
27499
+ }
27500
+ // Priority 3: Find by locatorValue (for backward compatibility)
27501
+ if (!element && variable.value) {
27502
+ const elementValue = variable.value;
27503
+ element = this.elementOptions.find(el => el.locatorValue === elementValue);
27504
+ }
27505
+ if (element) {
27506
+ // Set screen name info from the found element
27507
+ if (element.screenNameId && element.screenNameObj) {
27508
+ variable.selectedScreenName = element.screenNameObj.name;
27509
+ variable.screenNameId = element.screenNameId;
27510
+ // Set form controls
27511
+ // Store screenNameId as string to match option id format (for consistency with getScreenNameSelectConfig)
27512
+ const screenNameIdString = String(element.screenNameId);
27513
+ if (!variableGroup.get('selectedScreenName')) {
27514
+ variableGroup.addControl('selectedScreenName', new FormControl(screenNameIdString));
27515
+ }
27516
+ else {
27517
+ // Only update if form control doesn't already have a valid screen name selected
27518
+ // This prevents resetting user's selection when elementOptions changes
27519
+ const currentValue = variableGroup.get('selectedScreenName')?.value;
27520
+ const currentValueStr = currentValue != null ? String(currentValue) : null;
27521
+ if (currentValueStr !== screenNameIdString && currentValueStr !== 'none') {
27522
+ variableGroup.get('selectedScreenName')?.setValue(screenNameIdString, { emitEvent: false });
27523
+ }
27524
+ }
27525
+ }
27526
+ // Set/update element details from the found element
27527
+ variable.elementId = element.id;
27528
+ variable.elementLocator = element.locatorValue || '';
27529
+ // Only update elementName if it wasn't already set (preserve from setTemplateVariables)
27530
+ if (!variable.elementName) {
27531
+ variable.elementName = element.name || '';
27532
+ }
27533
+ // For selector, use elementLocator as value; for others, use elementName
27534
+ if (variable.name === 'selector') {
27535
+ variable.value = element.locatorValue || element.name || '';
27536
+ }
27537
+ else if (!variable.value || variable.value === '') {
27538
+ variable.value = element.name || element.locatorValue || '';
27539
+ }
27540
+ // Set element ID form control for the dropdown (key is 'id' in config)
27541
+ if (!variableGroup.get('id')) {
27542
+ variableGroup.addControl('id', new FormControl(element.id));
27510
27543
  }
27511
27544
  else {
27512
- variableGroup.get('selectedScreenName')?.setValue(element.screenNameId, { emitEvent: false });
27545
+ variableGroup.get('id')?.setValue(element.id, { emitEvent: false });
27546
+ }
27547
+ // Update value form control
27548
+ if (variableGroup.get('value')) {
27549
+ variableGroup.get('value')?.setValue(variable.value, { emitEvent: false });
27513
27550
  }
27514
27551
  }
27515
- // Set/update element details from the found element
27516
- variable.elementId = element.id;
27517
- variable.elementLocator = element.locatorValue || '';
27518
- // Only update elementName if it wasn't already set (preserve from setTemplateVariables)
27519
- if (!variable.elementName) {
27520
- variable.elementName = element.name || '';
27521
- }
27522
- // For selector, use elementLocator as value; for others, use elementName
27523
- if (variable.name === 'selector') {
27524
- variable.value = element.locatorValue || element.name || '';
27552
+ else {
27553
+ // Element not found in elementOptions yet - might need to fetch
27554
+ // Keep elementId and elementName if they exist (from setTemplateVariables)
27555
+ // If we have elementId but element isn't found, we might need to fetch elements
27556
+ // However, we don't know the screen name yet, so we'll wait for elementOptions to be loaded
27557
+ // The initialization will run again when elementOptions changes via ngOnChanges
27525
27558
  }
27526
- else if (!variable.value || variable.value === '') {
27527
- variable.value = element.name || element.locatorValue || '';
27559
+ }
27560
+ else {
27561
+ // No elementId in template data - clear all element-related fields and set defaults
27562
+ // But don't override user's screen name selection if they've already selected one
27563
+ variable.elementId = undefined;
27564
+ variable.elementLocator = undefined;
27565
+ variable.elementName = undefined;
27566
+ // Only clear screenNameId if it wasn't set by user selection
27567
+ // Check if form control has a valid screen name (not 'none')
27568
+ const currentScreenNameValue = variableGroup.get('selectedScreenName')?.value;
27569
+ if (!currentScreenNameValue || currentScreenNameValue === 'none' || currentScreenNameValue === null) {
27570
+ variable.screenNameId = undefined;
27571
+ variable.selectedScreenName = undefined;
27572
+ // Set form controls to default values
27573
+ // Screen name should be 'none' (Select option)
27574
+ if (!variableGroup.get('selectedScreenName')) {
27575
+ variableGroup.addControl('selectedScreenName', new FormControl('none'));
27576
+ }
27577
+ else {
27578
+ variableGroup.get('selectedScreenName')?.setValue('none', { emitEvent: false });
27579
+ }
27528
27580
  }
27529
- // Set element ID form control for the dropdown (key is 'id' in config)
27581
+ // Element ID should be null
27530
27582
  if (!variableGroup.get('id')) {
27531
- variableGroup.addControl('id', new FormControl(element.id));
27583
+ variableGroup.addControl('id', new FormControl(null));
27532
27584
  }
27533
27585
  else {
27534
- variableGroup.get('id')?.setValue(element.id, { emitEvent: false });
27535
- }
27536
- // Update value form control
27537
- if (variableGroup.get('value')) {
27538
- variableGroup.get('value')?.setValue(variable.value, { emitEvent: false });
27586
+ variableGroup.get('id')?.setValue(null, { emitEvent: false });
27539
27587
  }
27540
27588
  }
27541
- else {
27542
- // Element not found in elementOptions yet - might need to fetch
27543
- // Keep elementId and elementName if they exist (from setTemplateVariables)
27544
- // If we have elementId but element isn't found, we might need to fetch elements
27545
- // However, we don't know the screen name yet, so we'll wait for elementOptions to be loaded
27546
- // The initialization will run again when elementOptions changes via ngOnChanges
27547
- }
27548
27589
  }
27549
27590
  }
27550
27591
  });
@@ -27761,66 +27802,104 @@ class TemplateVariablesFormComponent {
27761
27802
  }
27762
27803
  // For element type, parse the value to extract screen name and element
27763
27804
  if (this.isElementType(variable)) {
27764
- let element = null;
27765
- // Priority 1: Find by elementId if available (from setTemplateVariables)
27805
+ // Only try to find and set element if elementId exists in template data
27806
+ // If no elementId, don't select anything - use default values
27766
27807
  if (variable.elementId) {
27808
+ let element = null;
27809
+ // Priority 1: Find by elementId (from setTemplateVariables)
27767
27810
  element = this.elementOptions.find(el => el.id === variable.elementId);
27768
- }
27769
- // Priority 2: Find by elementName if available (from setTemplateVariables)
27770
- if (!element && variable.elementName) {
27771
- element = this.elementOptions.find(el => el.name === variable.elementName);
27772
- }
27773
- // Priority 3: Find by locatorValue (for backward compatibility)
27774
- if (!element && variable.value) {
27775
- const elementValue = variable.value;
27776
- element = this.elementOptions.find(el => el.locatorValue === elementValue);
27777
- }
27778
- if (element) {
27779
- // Set screen name info from the found element
27780
- if (element.screenNameId && element.screenNameObj) {
27781
- variable.selectedScreenName = element.screenNameObj.name;
27782
- variable.screenNameId = element.screenNameId;
27783
- // Set form controls
27784
- // Since valueBy is 'screenNameId', we need to store the screenNameId (number) in the form control
27785
- if (!variableGroup.get('selectedScreenName')) {
27786
- variableGroup.addControl('selectedScreenName', new FormControl(element.screenNameId));
27811
+ // Priority 2: Find by elementName if elementId search didn't find it (fallback)
27812
+ if (!element && variable.elementName) {
27813
+ element = this.elementOptions.find(el => el.name === variable.elementName);
27814
+ }
27815
+ // Priority 3: Find by locatorValue (for backward compatibility)
27816
+ if (!element && variable.value) {
27817
+ const elementValue = variable.value;
27818
+ element = this.elementOptions.find(el => el.locatorValue === elementValue);
27819
+ }
27820
+ if (element) {
27821
+ // Set screen name info from the found element
27822
+ if (element.screenNameId && element.screenNameObj) {
27823
+ variable.selectedScreenName = element.screenNameObj.name;
27824
+ variable.screenNameId = element.screenNameId;
27825
+ // Set form controls
27826
+ // Store screenNameId as string to match option id format (for consistency with getScreenNameSelectConfig)
27827
+ const screenNameIdString = String(element.screenNameId);
27828
+ if (!variableGroup.get('selectedScreenName')) {
27829
+ variableGroup.addControl('selectedScreenName', new FormControl(screenNameIdString));
27830
+ }
27831
+ else {
27832
+ // Only update if form control doesn't already have a valid screen name selected
27833
+ // This prevents resetting user's selection when elementOptions changes
27834
+ const currentValue = variableGroup.get('selectedScreenName')?.value;
27835
+ const currentValueStr = currentValue != null ? String(currentValue) : null;
27836
+ if (currentValueStr !== screenNameIdString && currentValueStr !== 'none') {
27837
+ variableGroup.get('selectedScreenName')?.setValue(screenNameIdString, { emitEvent: false });
27838
+ }
27839
+ }
27840
+ }
27841
+ // Set/update element details from the found element
27842
+ variable.elementId = element.id;
27843
+ variable.elementLocator = element.locatorValue || '';
27844
+ // Only update elementName if it wasn't already set (preserve from setTemplateVariables)
27845
+ if (!variable.elementName) {
27846
+ variable.elementName = element.name || '';
27847
+ }
27848
+ // For selector, use elementLocator as value; for others, use elementName
27849
+ if (variable.name === 'selector') {
27850
+ variable.value = element.locatorValue || element.name || '';
27851
+ }
27852
+ else if (!variable.value || variable.value === '') {
27853
+ variable.value = element.name || element.locatorValue || '';
27854
+ }
27855
+ // Set element ID form control for the dropdown (key is 'id' in config)
27856
+ if (!variableGroup.get('id')) {
27857
+ variableGroup.addControl('id', new FormControl(element.id));
27787
27858
  }
27788
27859
  else {
27789
- variableGroup.get('selectedScreenName')?.setValue(element.screenNameId, { emitEvent: false });
27860
+ variableGroup.get('id')?.setValue(element.id, { emitEvent: false });
27861
+ }
27862
+ // Update value form control
27863
+ if (variableGroup.get('value')) {
27864
+ variableGroup.get('value')?.setValue(variable.value, { emitEvent: false });
27790
27865
  }
27791
27866
  }
27792
- // Set/update element details from the found element
27793
- variable.elementId = element.id;
27794
- variable.elementLocator = element.locatorValue || '';
27795
- // Only update elementName if it wasn't already set (preserve from setTemplateVariables)
27796
- if (!variable.elementName) {
27797
- variable.elementName = element.name || '';
27798
- }
27799
- // For selector, use elementLocator as value; for others, use elementName
27800
- if (variable.name === 'selector') {
27801
- variable.value = element.locatorValue || element.name || '';
27867
+ else {
27868
+ // Element not found in elementOptions yet - might need to fetch
27869
+ // Keep elementId and elementName if they exist (from setTemplateVariables)
27870
+ // If we have elementId but element isn't found, we might need to fetch elements
27871
+ // However, we don't know the screen name yet, so we'll wait for elementOptions to be loaded
27872
+ // The initialization will run again when elementOptions changes via ngOnChanges
27802
27873
  }
27803
- else if (!variable.value || variable.value === '') {
27804
- variable.value = element.name || element.locatorValue || '';
27874
+ }
27875
+ else {
27876
+ // No elementId in template data - clear all element-related fields and set defaults
27877
+ // But don't override user's screen name selection if they've already selected one
27878
+ variable.elementId = undefined;
27879
+ variable.elementLocator = undefined;
27880
+ variable.elementName = undefined;
27881
+ // Only clear screenNameId if it wasn't set by user selection
27882
+ // Check if form control has a valid screen name (not 'none')
27883
+ const currentScreenNameValue = variableGroup.get('selectedScreenName')?.value;
27884
+ if (!currentScreenNameValue || currentScreenNameValue === 'none' || currentScreenNameValue === null) {
27885
+ variable.screenNameId = undefined;
27886
+ variable.selectedScreenName = undefined;
27887
+ // Set form controls to default values
27888
+ // Screen name should be 'none' (Select option)
27889
+ if (!variableGroup.get('selectedScreenName')) {
27890
+ variableGroup.addControl('selectedScreenName', new FormControl('none'));
27891
+ }
27892
+ else {
27893
+ variableGroup.get('selectedScreenName')?.setValue('none', { emitEvent: false });
27894
+ }
27805
27895
  }
27806
- // Set element ID form control for the dropdown (key is 'id' in config)
27896
+ // Element ID should be null
27807
27897
  if (!variableGroup.get('id')) {
27808
- variableGroup.addControl('id', new FormControl(element.id));
27898
+ variableGroup.addControl('id', new FormControl(null));
27809
27899
  }
27810
27900
  else {
27811
- variableGroup.get('id')?.setValue(element.id, { emitEvent: false });
27901
+ variableGroup.get('id')?.setValue(null, { emitEvent: false });
27812
27902
  }
27813
- // Update value form control
27814
- if (variableGroup.get('value')) {
27815
- variableGroup.get('value')?.setValue(variable.value, { emitEvent: false });
27816
- }
27817
- }
27818
- else {
27819
- // Element not found in elementOptions yet - might need to fetch
27820
- // Keep elementId and elementName if they exist (from setTemplateVariables)
27821
- // If we have elementId but element isn't found, we might need to fetch elements
27822
- // However, we don't know the screen name yet, so we'll wait for elementOptions to be loaded
27823
- // The initialization will run again when elementOptions changes via ngOnChanges
27824
27903
  }
27825
27904
  }
27826
27905
  }
@@ -28888,8 +28967,14 @@ class TemplateVariablesFormComponent {
28888
28967
  }
28889
28968
  /**
28890
28969
  * Check if screen name is selected for an element variable
28970
+ * Returns true if either selectedScreenName or screenNameId is set (and not "None")
28891
28971
  */
28892
28972
  hasSelectedScreenName(variable) {
28973
+ // Check if screenNameId exists and is a valid number (not null/undefined)
28974
+ if (variable.screenNameId != null && typeof variable.screenNameId === 'number' && !isNaN(variable.screenNameId)) {
28975
+ return true;
28976
+ }
28977
+ // Fallback: check selectedScreenName
28893
28978
  return !!variable.selectedScreenName;
28894
28979
  }
28895
28980
  /**
@@ -28901,29 +28986,46 @@ class TemplateVariablesFormComponent {
28901
28986
  if (this.screenNameSelectConfigCache.has(cacheKey)) {
28902
28987
  return this.screenNameSelectConfigCache.get(cacheKey);
28903
28988
  }
28904
- // Use screenNameOptions from API (not extracted from elementOptions)
28905
- const optionsArray = this.screenNameOptions.map(screenName => ({
28906
- id: screenName.id?.toString() || '',
28907
- value: screenName.name,
28908
- name: screenName.name,
28909
- label: screenName.name,
28910
- screenNameId: screenName.id
28911
- }));
28989
+ // Build options: include a "None" option (displayed as "Select") plus screenNameOptions from API
28990
+ const optionsArray = [
28991
+ {
28992
+ id: 'none',
28993
+ value: 'Select',
28994
+ name: 'None',
28995
+ label: 'None'
28996
+ },
28997
+ ...this.screenNameOptions.map(screenName => ({
28998
+ id: screenName.id?.toString() || '',
28999
+ value: screenName.name,
29000
+ name: screenName.name,
29001
+ label: screenName.name
29002
+ }))
29003
+ ];
28912
29004
  // Ensure form control exists for screen name selection
28913
- // Since valueBy is 'screenNameId', we need to store the screenNameId (number) in the form control
29005
+ // The form control value should match the option id (string for "none", string representation of number for real screen names)
28914
29006
  const variableGroup = this.getVariableFormGroup(variable.name);
28915
29007
  if (variableGroup) {
28916
29008
  if (!variableGroup.get('selectedScreenName')) {
28917
- // Initialize with screenNameId if available, otherwise null
28918
- const initialValue = variable.screenNameId || null;
29009
+ // Initialize with screenNameId as string (to match option id format), or 'none' by default
29010
+ const initialValue = variable.screenNameId ? String(variable.screenNameId) : 'none';
28919
29011
  variableGroup.addControl('selectedScreenName', new FormControl(initialValue));
28920
29012
  }
28921
29013
  else {
28922
29014
  // Update form control value if variable has screenNameId but form control doesn't match
28923
29015
  if (variable.screenNameId) {
28924
29016
  const currentValue = variableGroup.get('selectedScreenName')?.value;
28925
- if (currentValue !== variable.screenNameId) {
28926
- variableGroup.get('selectedScreenName')?.setValue(variable.screenNameId, { emitEvent: false });
29017
+ const expectedValue = String(variable.screenNameId);
29018
+ // Compare as strings to handle both number and string values
29019
+ const currentValueStr = currentValue != null ? String(currentValue) : null;
29020
+ if (currentValueStr !== expectedValue) {
29021
+ variableGroup.get('selectedScreenName')?.setValue(expectedValue, { emitEvent: false });
29022
+ }
29023
+ }
29024
+ else {
29025
+ // If no screenNameId, ensure form control is 'none' (for "None" selection by default)
29026
+ const currentValue = variableGroup.get('selectedScreenName')?.value;
29027
+ if (currentValue !== 'none' && currentValue !== null && currentValue !== '') {
29028
+ variableGroup.get('selectedScreenName')?.setValue('none', { emitEvent: false });
28927
29029
  }
28928
29030
  }
28929
29031
  }
@@ -28937,42 +29039,92 @@ class TemplateVariablesFormComponent {
28937
29039
  options: optionsArray,
28938
29040
  hasMore: this.hasMoreScreenNames,
28939
29041
  isLoading: this.isLoadingScreenNames,
28940
- valueBy: 'screenNameId',
28941
29042
  onChange: (value) => {
28942
- // Store selected screen name on the variable object
28943
- // value is the screenNameId (number) since valueBy is 'screenNameId'
28944
- variable.screenNameId = value;
28945
- // Find and store screen name name from screenNameOptions
28946
- const screenNameOption = this.screenNameOptions.find(sn => sn.id === value);
28947
- if (screenNameOption && screenNameOption.id) {
28948
- variable.selectedScreenName = screenNameOption.name;
28949
- }
28950
- // Clear the element selection when screen name changes
28951
- variable.value = '';
28952
- // Clear element config cache to force refresh
28953
- // Clear all element configs for this variable since screen name changed
28954
- const keysToDelete = [];
28955
- this.elementSelectConfigCache.forEach((_, key) => {
28956
- if (key.startsWith(`${variable.name}_element`)) {
28957
- keysToDelete.push(key);
28958
- }
28959
- });
28960
- keysToDelete.forEach(key => this.elementSelectConfigCache.delete(key));
28961
- // Update form control
28962
- if (variableGroup) {
28963
- if (variableGroup.get('value')) {
28964
- variableGroup.get('value')?.setValue('', { emitEvent: false });
29043
+ // If "None" is selected (value is 'none' string or null), clear screen name and element info
29044
+ if (value == null || value === 'none' || value === '') {
29045
+ variable.screenNameId = undefined;
29046
+ variable.selectedScreenName = undefined;
29047
+ variable.elementId = undefined;
29048
+ variable.elementLocator = undefined;
29049
+ variable.elementName = undefined;
29050
+ variable.value = '';
29051
+ // Clear element config cache for this variable
29052
+ const keysToDelete = [];
29053
+ this.elementSelectConfigCache.forEach((_, key) => {
29054
+ if (key.startsWith(`${variable.name}_element`)) {
29055
+ keysToDelete.push(key);
29056
+ }
29057
+ });
29058
+ keysToDelete.forEach(key => this.elementSelectConfigCache.delete(key));
29059
+ // Update form controls - clear all element-related form controls
29060
+ // Set selectedScreenName to 'none' to show "None" is selected
29061
+ if (variableGroup) {
29062
+ if (variableGroup.get('value')) {
29063
+ variableGroup.get('value')?.setValue('', { emitEvent: false });
29064
+ }
29065
+ if (variableGroup.get('selectedScreenName')) {
29066
+ variableGroup.get('selectedScreenName')?.setValue('none', { emitEvent: false });
29067
+ }
29068
+ // Clear element ID form control to ensure elementId is cleared
29069
+ if (variableGroup.get('id')) {
29070
+ variableGroup.get('id')?.setValue(null, { emitEvent: false });
29071
+ }
28965
29072
  }
28966
- // The form control already has the correct value (screenNameId) from the dropdown
28967
- // No need to update it here as it's already set by mat-select
29073
+ // Mark for check and stop (no element fetch when None)
29074
+ this.cdr.markForCheck();
29075
+ return;
28968
29076
  }
28969
- // Emit event to fetch elements filtered by selected screen name
28970
- if (variable.screenNameId) {
29077
+ // value is the option id (string for "none", string representation of number for real screen names)
29078
+ // Convert to number for screenNameId if it's a valid number
29079
+ const screenNameIdNum = typeof value === 'string' && value !== 'none' ? parseInt(value, 10) : (typeof value === 'number' ? value : null);
29080
+ if (screenNameIdNum && !isNaN(screenNameIdNum)) {
29081
+ // Store selected screen name on the variable object
29082
+ variable.screenNameId = screenNameIdNum;
29083
+ // Find and store screen name name from screenNameOptions
29084
+ const screenNameOption = this.screenNameOptions.find(sn => sn.id === screenNameIdNum);
29085
+ if (screenNameOption) {
29086
+ variable.selectedScreenName = screenNameOption.name;
29087
+ }
29088
+ else {
29089
+ // Fallback: if not found, still set the ID but clear the name
29090
+ variable.selectedScreenName = undefined;
29091
+ }
29092
+ // Clear the element selection when screen name changes
29093
+ variable.elementId = undefined;
29094
+ variable.elementLocator = undefined;
29095
+ variable.elementName = undefined;
29096
+ variable.value = '';
29097
+ // Clear element config cache to force refresh
29098
+ // Clear all element configs for this variable since screen name changed
29099
+ const keysToDelete = [];
29100
+ this.elementSelectConfigCache.forEach((_, key) => {
29101
+ if (key.startsWith(`${variable.name}_element`)) {
29102
+ keysToDelete.push(key);
29103
+ }
29104
+ });
29105
+ keysToDelete.forEach(key => this.elementSelectConfigCache.delete(key));
29106
+ // Update form control
29107
+ if (variableGroup) {
29108
+ if (variableGroup.get('value')) {
29109
+ variableGroup.get('value')?.setValue('', { emitEvent: false });
29110
+ }
29111
+ // Ensure form control has the correct value (as string to match option id)
29112
+ if (variableGroup.get('selectedScreenName')) {
29113
+ variableGroup.get('selectedScreenName')?.setValue(String(screenNameIdNum), { emitEvent: false });
29114
+ }
29115
+ }
29116
+ // Emit event to fetch elements filtered by selected screen name
28971
29117
  this.searchElementsByScreenName.emit({
28972
29118
  screenNameId: variable.screenNameId,
28973
29119
  searchTerm: ''
28974
29120
  });
28975
29121
  }
29122
+ else {
29123
+ // Invalid value - clear everything
29124
+ variable.screenNameId = undefined;
29125
+ variable.selectedScreenName = undefined;
29126
+ variable.value = '';
29127
+ }
28976
29128
  // Mark for check to update UI first
28977
29129
  this.cdr.markForCheck();
28978
29130
  // The element config will be recomputed automatically when elementOptions input changes
@@ -28994,7 +29146,6 @@ class TemplateVariablesFormComponent {
28994
29146
  */
28995
29147
  getElementSelectConfig(variable, index) {
28996
29148
  // Get selected screen name ID
28997
- console.log('variable', variable);
28998
29149
  const selectedScreenNameId = variable.screenNameId;
28999
29150
  // Include elementOptions length and loading state in cache key to invalidate when elements change
29000
29151
  const cacheKey = `${variable.name}_element_${selectedScreenNameId || ''}_${this.elementOptions.length}_${this.isLoadingElements}`;
@@ -29085,6 +29236,16 @@ class TemplateVariablesFormComponent {
29085
29236
  variable.elementId = selectedElement.id;
29086
29237
  variable.elementLocator = selectedElement.locatorValue || '';
29087
29238
  variable.elementName = selectedElement.name || '';
29239
+ // Update screen name from the selected element
29240
+ // This ensures the screen name dropdown shows the correct selection
29241
+ if (selectedElement.screenNameId) {
29242
+ variable.screenNameId = selectedElement.screenNameId;
29243
+ // Find and store screen name name from screenNameOptions
29244
+ const screenNameOption = this.screenNameOptions.find(sn => sn.id === selectedElement.screenNameId);
29245
+ if (screenNameOption) {
29246
+ variable.selectedScreenName = screenNameOption.name;
29247
+ }
29248
+ }
29088
29249
  // Find and patch the selector variable with dataKey 'not_found'
29089
29250
  const selectorVariable = this.templateVariables.find(v => v.name === 'selector' && v.dataKey === 'not_found');
29090
29251
  if (selectorVariable && selectedElement.locatorValue) {
@@ -29104,8 +29265,6 @@ class TemplateVariablesFormComponent {
29104
29265
  // Fallback: if element not found, just set the value
29105
29266
  variable.value = value;
29106
29267
  }
29107
- // Screen name ID is already stored on variable.selectedScreenNameId
29108
- // (it was set when screen name was selected)
29109
29268
  // Update form control in FormArray
29110
29269
  const variableGroup = this.getVariableFormGroup(variable.name);
29111
29270
  if (variableGroup) {
@@ -29116,6 +29275,11 @@ class TemplateVariablesFormComponent {
29116
29275
  if (selectedElement && variableGroup.get('id')) {
29117
29276
  variableGroup.get('id')?.setValue(selectedElement.id, { emitEvent: false });
29118
29277
  }
29278
+ // Update screen name form control if element has a screen name
29279
+ if (selectedElement && selectedElement.screenNameId && variableGroup.get('selectedScreenName')) {
29280
+ // Set the screen name ID as string to match option id format
29281
+ variableGroup.get('selectedScreenName')?.setValue(String(selectedElement.screenNameId), { emitEvent: false });
29282
+ }
29119
29283
  }
29120
29284
  // Mark for check and emit
29121
29285
  this.cdr.markForCheck();
@@ -29141,10 +29305,10 @@ class TemplateVariablesFormComponent {
29141
29305
  }
29142
29306
  }
29143
29307
  TemplateVariablesFormComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TemplateVariablesFormComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
29144
- TemplateVariablesFormComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TemplateVariablesFormComponent, selector: "cqa-template-variables-form", inputs: { templateVariables: "templateVariables", variablesForm: "variablesForm", metadata: "metadata", description: "description", elementOptions: "elementOptions", hasMoreElements: "hasMoreElements", isLoadingElements: "isLoadingElements", screenNameOptions: "screenNameOptions", hasMoreScreenNames: "hasMoreScreenNames", isLoadingScreenNames: "isLoadingScreenNames", parameterOptions: "parameterOptions", hasMoreParameters: "hasMoreParameters", isLoadingParameters: "isLoadingParameters", environmentOptions: "environmentOptions", hasMoreEnvironments: "hasMoreEnvironments", isLoadingEnvironments: "isLoadingEnvironments", defaultTestDataProfileId: "defaultTestDataProfileId", defaultTestDataStartIndex: "defaultTestDataStartIndex", isEditInDepth: "isEditInDepth", createElementVisible: "createElementVisible" }, outputs: { variableValueChange: "variableValueChange", variableBooleanChange: "variableBooleanChange", metadataChange: "metadataChange", descriptionChange: "descriptionChange", loadMoreElements: "loadMoreElements", searchElements: "searchElements", searchElementsByScreenName: "searchElementsByScreenName", createElement: "createElement", searchScreenName: "searchScreenName", loadMoreScreenNames: "loadMoreScreenNames", createScreenNameRequest: "createScreenNameRequest", searchParameters: "searchParameters", loadMoreParameters: "loadMoreParameters", searchEnvironments: "searchEnvironments", loadMoreEnvironments: "loadMoreEnvironments", cancelElementForm: "cancelElementForm", elementFormVisibilityChange: "elementFormVisibilityChange" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<style>\n .capitalize-first::first-letter {\n text-transform: uppercase;\n }\n</style>\n<div class=\"cqa-flex cqa-gap-x-6 cqa-gap-y-4 cqa-flex-wrap template-variables-form\" [ngClass]=\"{'cqa-flex-col': isEditInDepth}\" *ngIf=\"!createElementVisible\">\n \n <!-- Metadata - Only show if element is available in form -->\n <div *ngIf=\"selectorVariableAvailable\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Metadata\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"metadata\" [fullWidth]=\"true\"\n (valueChange)=\"metadataChange.emit($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- Description -->\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Description\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"description\" [fullWidth]=\"true\"\n (valueChange)=\"descriptionChange.emit($event)\">\n </cqa-custom-input>\n </div>\n \n <ng-container *ngFor=\"let variable of templateVariables; let i = index; trackBy: trackByVariable\">\n <!-- Boolean variables with mat-slide-toggle -->\n <ng-container *ngIf=\"variable.type === 'boolean'\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 capitalize-first\">\n {{ variable.label }}\n </label>\n <mat-slide-toggle [checked]=\"variablesForm.at(i)?.get('value')?.value || variable.value || false\"\n (change)=\"onVariableBooleanChange(variable.name, $event.checked)\" color=\"primary\">\n </mat-slide-toggle>\n </div>\n </ng-container>\n\n <!-- Non-boolean, non-custom_code variables -->\n <ng-container *ngIf=\"variable.name !== 'custom_code' && variable.type !== 'boolean'\">\n <!-- Element variables with cascading dropdowns (screen name + element) -->\n <ng-container *ngIf=\"isElementType(variable)\">\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }} Screen Name\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getScreenNameSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <div *ngIf=\"hasSelectedScreenName(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getElementSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n </ng-container>\n <ng-container *ngIf=\"!isElementType(variable)\">\n <!-- Other dropdown variables (type, scrollTo, label) -->\n <ng-container *ngIf=\"shouldShowDropdown(variable); else defaultInput\">\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n </ng-container>\n </ng-container>\n <ng-template #defaultInput>\n <!-- Test-data, source-value, or target-value with data type dropdown -->\n <ng-container *ngIf=\"needsDataTypeDropdown(variable); else regularInput\">\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }} Type\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getDataTypeSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <ng-container *ngIf=\"isEnvironmentType(variable)\">\n <div *ngIf=\"isEnvironmentType(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Environment Name\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getEnvironmentSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <div *ngIf=\"hasSelectedEnvironment(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Environment Value\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getEnvironmentParameterSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n </ng-container>\n <ng-container *ngIf=\"isParameterType(variable)\">\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Test Data Profile\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getTestDataProfileSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <div *ngIf=\"hasSelectedTestDataProfile(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Data Set\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getDataSetSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <div *ngIf=\"hasSelectedDataSet(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getParameterSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div> \n </ng-container>\n <div *ngIf=\"isPlainTextType(variable) || isRuntimeType(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }} \n </label>\n <!-- Show custom input for plain-text type -->\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"getRawValue(variable)\" [fullWidth]=\"true\"\n (valueChange)=\"onTestDataValueChange(variable.name, $event)\">\n </cqa-custom-input>\n </div>\n </ng-container>\n <ng-template #regularInput>\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"variable.value\" [fullWidth]=\"true\"\n (valueChange)=\"onVariableValueChange(variable.name, $event)\">\n </cqa-custom-input>\n </div>\n </ng-template>\n </ng-template>\n </ng-container>\n </ng-container>\n</div>\n\n<div *ngIf=\"createElementVisible\">\n <cqa-element-form\n [isCreateMode]=\"true\"\n [screenNameOptions]=\"screenNameOptions\"\n [hasMoreScreenNames]=\"hasMoreScreenNames\"\n [isLoadingScreenNames]=\"isLoadingScreenNames\"\n [isEditInDepthAvailable]=\"false\"\n (createElement)=\"onCreateElement($event)\"\n (cancel)=\"onCancelElementForm()\"\n (searchScreenName)=\"searchScreenName.emit($event)\"\n (loadMoreScreenNames)=\"loadMoreScreenNames.emit($event)\"\n (createScreenNameRequest)=\"createScreenNameRequest.emit($event)\">\n </cqa-element-form>\n</div>", styles: ["\n .capitalize-first::first-letter {\n text-transform: uppercase;\n }\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: i4$2.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["disabled", "disableRipple", "color", "tabIndex", "name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "checked"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore", "addCustomValue"] }, { type: ElementFormComponent, selector: "cqa-element-form", inputs: ["elementId", "element", "screenNameOptions", "hasMoreScreenNames", "isLoadingScreenNames", "isElementLoading", "isEditMode", "isCreateMode", "isEditInDepthAvailable"], outputs: ["createElement", "updateElement", "createScreenNameRequest", "searchScreenName", "loadMoreScreenNames", "cancel", "editInDepth"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
29308
+ TemplateVariablesFormComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TemplateVariablesFormComponent, selector: "cqa-template-variables-form", inputs: { templateVariables: "templateVariables", variablesForm: "variablesForm", metadata: "metadata", description: "description", elementOptions: "elementOptions", hasMoreElements: "hasMoreElements", isLoadingElements: "isLoadingElements", screenNameOptions: "screenNameOptions", hasMoreScreenNames: "hasMoreScreenNames", isLoadingScreenNames: "isLoadingScreenNames", parameterOptions: "parameterOptions", hasMoreParameters: "hasMoreParameters", isLoadingParameters: "isLoadingParameters", environmentOptions: "environmentOptions", hasMoreEnvironments: "hasMoreEnvironments", isLoadingEnvironments: "isLoadingEnvironments", defaultTestDataProfileId: "defaultTestDataProfileId", defaultTestDataStartIndex: "defaultTestDataStartIndex", isEditInDepth: "isEditInDepth", createElementVisible: "createElementVisible" }, outputs: { variableValueChange: "variableValueChange", variableBooleanChange: "variableBooleanChange", metadataChange: "metadataChange", descriptionChange: "descriptionChange", loadMoreElements: "loadMoreElements", searchElements: "searchElements", searchElementsByScreenName: "searchElementsByScreenName", createElement: "createElement", searchScreenName: "searchScreenName", loadMoreScreenNames: "loadMoreScreenNames", createScreenNameRequest: "createScreenNameRequest", searchParameters: "searchParameters", loadMoreParameters: "loadMoreParameters", searchEnvironments: "searchEnvironments", loadMoreEnvironments: "loadMoreEnvironments", cancelElementForm: "cancelElementForm", elementFormVisibilityChange: "elementFormVisibilityChange" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<style>\n .capitalize-first::first-letter {\n text-transform: uppercase;\n }\n</style>\n<div class=\"cqa-flex cqa-gap-x-6 cqa-gap-y-4 cqa-flex-wrap template-variables-form\" [ngClass]=\"{'cqa-flex-col': isEditInDepth}\" *ngIf=\"!createElementVisible\">\n \n <!-- Metadata - Only show if element is available in form -->\n <div *ngIf=\"selectorVariableAvailable\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Metadata\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"metadata\" [fullWidth]=\"true\"\n (valueChange)=\"metadataChange.emit($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- Description -->\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Description\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"description\" [fullWidth]=\"true\"\n (valueChange)=\"descriptionChange.emit($event)\">\n </cqa-custom-input>\n </div>\n \n <ng-container *ngFor=\"let variable of templateVariables; let i = index; trackBy: trackByVariable\">\n <!-- Boolean variables with mat-slide-toggle -->\n <ng-container *ngIf=\"variable.type === 'boolean'\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 capitalize-first\">\n {{ variable.label }}\n </label>\n <mat-slide-toggle [checked]=\"variablesForm.at(i)?.get('value')?.value || variable.value || false\"\n (change)=\"onVariableBooleanChange(variable.name, $event.checked)\" color=\"primary\">\n </mat-slide-toggle>\n </div>\n </ng-container>\n\n <!-- Non-boolean, non-custom_code variables -->\n <ng-container *ngIf=\"variable.name !== 'custom_code' && variable.type !== 'boolean'\">\n <!-- Element variables with cascading dropdowns (screen name + element) -->\n <ng-container *ngIf=\"isElementType(variable)\">\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }} Screen Name\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getScreenNameSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <div *ngIf=\"hasSelectedScreenName(variable); else elementManualInput\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getElementSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <ng-template #elementManualInput>\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"variable.value\" [fullWidth]=\"true\"\n (valueChange)=\"onVariableValueChange(variable.name, $event)\">\n </cqa-custom-input>\n </div>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"!isElementType(variable)\">\n <!-- Other dropdown variables (type, scrollTo, label) -->\n <ng-container *ngIf=\"shouldShowDropdown(variable); else defaultInput\">\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n </ng-container>\n </ng-container>\n <ng-template #defaultInput>\n <!-- Test-data, source-value, or target-value with data type dropdown -->\n <ng-container *ngIf=\"needsDataTypeDropdown(variable); else regularInput\">\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }} Type\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getDataTypeSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <ng-container *ngIf=\"isEnvironmentType(variable)\">\n <div *ngIf=\"isEnvironmentType(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Environment Name\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getEnvironmentSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <div *ngIf=\"hasSelectedEnvironment(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Environment Value\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getEnvironmentParameterSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n </ng-container>\n <ng-container *ngIf=\"isParameterType(variable)\">\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Test Data Profile\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getTestDataProfileSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <div *ngIf=\"hasSelectedTestDataProfile(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Data Set\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getDataSetSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <div *ngIf=\"hasSelectedDataSet(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getParameterSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div> \n </ng-container>\n <div *ngIf=\"isPlainTextType(variable) || isRuntimeType(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }} \n </label>\n <!-- Show custom input for plain-text type -->\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"getRawValue(variable)\" [fullWidth]=\"true\"\n (valueChange)=\"onTestDataValueChange(variable.name, $event)\">\n </cqa-custom-input>\n </div>\n </ng-container>\n <ng-template #regularInput>\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"variable.value\" [fullWidth]=\"true\"\n (valueChange)=\"onVariableValueChange(variable.name, $event)\">\n </cqa-custom-input>\n </div>\n </ng-template>\n </ng-template>\n </ng-container>\n </ng-container>\n</div>\n\n<div *ngIf=\"createElementVisible\">\n <cqa-element-form\n [isCreateMode]=\"true\"\n [screenNameOptions]=\"screenNameOptions\"\n [hasMoreScreenNames]=\"hasMoreScreenNames\"\n [isLoadingScreenNames]=\"isLoadingScreenNames\"\n [isEditInDepthAvailable]=\"false\"\n (createElement)=\"onCreateElement($event)\"\n (cancel)=\"onCancelElementForm()\"\n (searchScreenName)=\"searchScreenName.emit($event)\"\n (loadMoreScreenNames)=\"loadMoreScreenNames.emit($event)\"\n (createScreenNameRequest)=\"createScreenNameRequest.emit($event)\">\n </cqa-element-form>\n</div>", styles: ["\n .capitalize-first::first-letter {\n text-transform: uppercase;\n }\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: i4$2.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["disabled", "disableRipple", "color", "tabIndex", "name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "checked"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore", "addCustomValue"] }, { type: ElementFormComponent, selector: "cqa-element-form", inputs: ["elementId", "element", "screenNameOptions", "hasMoreScreenNames", "isLoadingScreenNames", "isElementLoading", "isEditMode", "isCreateMode", "isEditInDepthAvailable"], outputs: ["createElement", "updateElement", "createScreenNameRequest", "searchScreenName", "loadMoreScreenNames", "cancel", "editInDepth"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
29145
29309
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TemplateVariablesFormComponent, decorators: [{
29146
29310
  type: Component,
29147
- args: [{ selector: 'cqa-template-variables-form', host: { class: 'cqa-ui-root' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<style>\n .capitalize-first::first-letter {\n text-transform: uppercase;\n }\n</style>\n<div class=\"cqa-flex cqa-gap-x-6 cqa-gap-y-4 cqa-flex-wrap template-variables-form\" [ngClass]=\"{'cqa-flex-col': isEditInDepth}\" *ngIf=\"!createElementVisible\">\n \n <!-- Metadata - Only show if element is available in form -->\n <div *ngIf=\"selectorVariableAvailable\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Metadata\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"metadata\" [fullWidth]=\"true\"\n (valueChange)=\"metadataChange.emit($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- Description -->\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Description\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"description\" [fullWidth]=\"true\"\n (valueChange)=\"descriptionChange.emit($event)\">\n </cqa-custom-input>\n </div>\n \n <ng-container *ngFor=\"let variable of templateVariables; let i = index; trackBy: trackByVariable\">\n <!-- Boolean variables with mat-slide-toggle -->\n <ng-container *ngIf=\"variable.type === 'boolean'\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 capitalize-first\">\n {{ variable.label }}\n </label>\n <mat-slide-toggle [checked]=\"variablesForm.at(i)?.get('value')?.value || variable.value || false\"\n (change)=\"onVariableBooleanChange(variable.name, $event.checked)\" color=\"primary\">\n </mat-slide-toggle>\n </div>\n </ng-container>\n\n <!-- Non-boolean, non-custom_code variables -->\n <ng-container *ngIf=\"variable.name !== 'custom_code' && variable.type !== 'boolean'\">\n <!-- Element variables with cascading dropdowns (screen name + element) -->\n <ng-container *ngIf=\"isElementType(variable)\">\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }} Screen Name\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getScreenNameSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <div *ngIf=\"hasSelectedScreenName(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getElementSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n </ng-container>\n <ng-container *ngIf=\"!isElementType(variable)\">\n <!-- Other dropdown variables (type, scrollTo, label) -->\n <ng-container *ngIf=\"shouldShowDropdown(variable); else defaultInput\">\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n </ng-container>\n </ng-container>\n <ng-template #defaultInput>\n <!-- Test-data, source-value, or target-value with data type dropdown -->\n <ng-container *ngIf=\"needsDataTypeDropdown(variable); else regularInput\">\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }} Type\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getDataTypeSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <ng-container *ngIf=\"isEnvironmentType(variable)\">\n <div *ngIf=\"isEnvironmentType(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Environment Name\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getEnvironmentSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <div *ngIf=\"hasSelectedEnvironment(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Environment Value\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getEnvironmentParameterSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n </ng-container>\n <ng-container *ngIf=\"isParameterType(variable)\">\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Test Data Profile\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getTestDataProfileSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <div *ngIf=\"hasSelectedTestDataProfile(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Data Set\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getDataSetSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <div *ngIf=\"hasSelectedDataSet(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getParameterSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div> \n </ng-container>\n <div *ngIf=\"isPlainTextType(variable) || isRuntimeType(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }} \n </label>\n <!-- Show custom input for plain-text type -->\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"getRawValue(variable)\" [fullWidth]=\"true\"\n (valueChange)=\"onTestDataValueChange(variable.name, $event)\">\n </cqa-custom-input>\n </div>\n </ng-container>\n <ng-template #regularInput>\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"variable.value\" [fullWidth]=\"true\"\n (valueChange)=\"onVariableValueChange(variable.name, $event)\">\n </cqa-custom-input>\n </div>\n </ng-template>\n </ng-template>\n </ng-container>\n </ng-container>\n</div>\n\n<div *ngIf=\"createElementVisible\">\n <cqa-element-form\n [isCreateMode]=\"true\"\n [screenNameOptions]=\"screenNameOptions\"\n [hasMoreScreenNames]=\"hasMoreScreenNames\"\n [isLoadingScreenNames]=\"isLoadingScreenNames\"\n [isEditInDepthAvailable]=\"false\"\n (createElement)=\"onCreateElement($event)\"\n (cancel)=\"onCancelElementForm()\"\n (searchScreenName)=\"searchScreenName.emit($event)\"\n (loadMoreScreenNames)=\"loadMoreScreenNames.emit($event)\"\n (createScreenNameRequest)=\"createScreenNameRequest.emit($event)\">\n </cqa-element-form>\n</div>", styles: ["\n .capitalize-first::first-letter {\n text-transform: uppercase;\n }\n"] }]
29311
+ args: [{ selector: 'cqa-template-variables-form', host: { class: 'cqa-ui-root' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<style>\n .capitalize-first::first-letter {\n text-transform: uppercase;\n }\n</style>\n<div class=\"cqa-flex cqa-gap-x-6 cqa-gap-y-4 cqa-flex-wrap template-variables-form\" [ngClass]=\"{'cqa-flex-col': isEditInDepth}\" *ngIf=\"!createElementVisible\">\n \n <!-- Metadata - Only show if element is available in form -->\n <div *ngIf=\"selectorVariableAvailable\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Metadata\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"metadata\" [fullWidth]=\"true\"\n (valueChange)=\"metadataChange.emit($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- Description -->\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Description\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"description\" [fullWidth]=\"true\"\n (valueChange)=\"descriptionChange.emit($event)\">\n </cqa-custom-input>\n </div>\n \n <ng-container *ngFor=\"let variable of templateVariables; let i = index; trackBy: trackByVariable\">\n <!-- Boolean variables with mat-slide-toggle -->\n <ng-container *ngIf=\"variable.type === 'boolean'\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 capitalize-first\">\n {{ variable.label }}\n </label>\n <mat-slide-toggle [checked]=\"variablesForm.at(i)?.get('value')?.value || variable.value || false\"\n (change)=\"onVariableBooleanChange(variable.name, $event.checked)\" color=\"primary\">\n </mat-slide-toggle>\n </div>\n </ng-container>\n\n <!-- Non-boolean, non-custom_code variables -->\n <ng-container *ngIf=\"variable.name !== 'custom_code' && variable.type !== 'boolean'\">\n <!-- Element variables with cascading dropdowns (screen name + element) -->\n <ng-container *ngIf=\"isElementType(variable)\">\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }} Screen Name\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getScreenNameSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <div *ngIf=\"hasSelectedScreenName(variable); else elementManualInput\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getElementSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <ng-template #elementManualInput>\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"variable.value\" [fullWidth]=\"true\"\n (valueChange)=\"onVariableValueChange(variable.name, $event)\">\n </cqa-custom-input>\n </div>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"!isElementType(variable)\">\n <!-- Other dropdown variables (type, scrollTo, label) -->\n <ng-container *ngIf=\"shouldShowDropdown(variable); else defaultInput\">\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n </ng-container>\n </ng-container>\n <ng-template #defaultInput>\n <!-- Test-data, source-value, or target-value with data type dropdown -->\n <ng-container *ngIf=\"needsDataTypeDropdown(variable); else regularInput\">\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }} Type\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getDataTypeSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <ng-container *ngIf=\"isEnvironmentType(variable)\">\n <div *ngIf=\"isEnvironmentType(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Environment Name\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getEnvironmentSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <div *ngIf=\"hasSelectedEnvironment(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Environment Value\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getEnvironmentParameterSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n </ng-container>\n <ng-container *ngIf=\"isParameterType(variable)\">\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Test Data Profile\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getTestDataProfileSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <div *ngIf=\"hasSelectedTestDataProfile(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1\">\n Data Set\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getDataSetSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div>\n <div *ngIf=\"hasSelectedDataSet(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <cqa-dynamic-select [form]=\"getFormGroupAt(i)!\" [config]=\"getParameterSelectConfig(variable, i)\">\n </cqa-dynamic-select>\n </div> \n </ng-container>\n <div *ngIf=\"isPlainTextType(variable) || isRuntimeType(variable)\" class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }} \n </label>\n <!-- Show custom input for plain-text type -->\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"getRawValue(variable)\" [fullWidth]=\"true\"\n (valueChange)=\"onTestDataValueChange(variable.name, $event)\">\n </cqa-custom-input>\n </div>\n </ng-container>\n <ng-template #regularInput>\n <div class=\"cqa-flex cqa-flex-col\" [style.width]=\"isEditInDepth ? null : 'calc(50% - 12px)'\" [ngClass]=\"{'cqa-w-full': isEditInDepth}\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1 capitalize-first\">\n {{ variable.label }}\n </label>\n <cqa-custom-input [placeholder]=\"'Text Input'\" [value]=\"variable.value\" [fullWidth]=\"true\"\n (valueChange)=\"onVariableValueChange(variable.name, $event)\">\n </cqa-custom-input>\n </div>\n </ng-template>\n </ng-template>\n </ng-container>\n </ng-container>\n</div>\n\n<div *ngIf=\"createElementVisible\">\n <cqa-element-form\n [isCreateMode]=\"true\"\n [screenNameOptions]=\"screenNameOptions\"\n [hasMoreScreenNames]=\"hasMoreScreenNames\"\n [isLoadingScreenNames]=\"isLoadingScreenNames\"\n [isEditInDepthAvailable]=\"false\"\n (createElement)=\"onCreateElement($event)\"\n (cancel)=\"onCancelElementForm()\"\n (searchScreenName)=\"searchScreenName.emit($event)\"\n (loadMoreScreenNames)=\"loadMoreScreenNames.emit($event)\"\n (createScreenNameRequest)=\"createScreenNameRequest.emit($event)\">\n </cqa-element-form>\n</div>", styles: ["\n .capitalize-first::first-letter {\n text-transform: uppercase;\n }\n"] }]
29148
29312
  }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { templateVariables: [{
29149
29313
  type: Input
29150
29314
  }], variablesForm: [{
@@ -33504,96 +33668,368 @@ const DETAIL_SIDE_PANEL_SCROLL_STYLES = `
33504
33668
  }
33505
33669
  `;
33506
33670
 
33507
- /** Keys for each dynamic select in test-case-details-edit. Use these with selectConfigOverrides. */
33508
- const TEST_CASE_DETAILS_SELECT_KEYS = {
33509
- status: 'status',
33510
- priority: 'priority',
33511
- type: 'type',
33512
- labels: 'labels',
33513
- prerequisiteCases: 'prerequisiteCases',
33514
- testDataProfile: 'testDataProfile',
33515
- testDataSet: 'testDataSet',
33516
- videoRecording: 'videoRecording',
33517
- enableAiSmartness: 'enableAiSmartness',
33518
- defaultAiAction: 'defaultAiAction',
33519
- knowledgeBaseDefaultTestCase: 'knowledgeBaseDefaultTestCase',
33520
- useAiMetadata: 'useAiMetadata',
33521
- defaultBrowser: 'defaultBrowser',
33522
- defaultViewport: 'defaultViewport',
33523
- deviceType: 'deviceType',
33524
- deviceOS: 'deviceOS',
33525
- };
33526
- const FREQUENTLY_USED_LABELS = [
33527
- 'Case',
33528
- 'Critical',
33529
- 'PO',
33530
- 'Upload',
33531
- 'Validation',
33532
- 'Review',
33533
- 'Edge-cases',
33534
- 'Security',
33535
- 'Integration',
33536
- 'Smoke',
33537
- ];
33538
- class TestCaseDetailsEditComponent {
33539
- constructor(cdr) {
33540
- this.cdr = cdr;
33541
- this.descriptionTitle = 'Description';
33542
- this.descriptionContent = '';
33543
- /** When true, description uses Trix rich text editor (Bold, Italic, etc.). Host app must load Trix. */
33544
- this.enableMarkdown = false;
33545
- this.metadataItems = [];
33546
- this.labels = [];
33547
- this.configTitle = 'Configuration';
33548
- this.configSections = [];
33549
- this.configSectionsRow2 = [];
33550
- /** Optional list of prerequisite test case options for the multi-select. If not provided, uses default sample options. */
33551
- this.prerequisiteCaseOptions = [];
33552
- /** Platform: 'web' shows Default Browser + Viewport; 'mobile' shows Device Type + OS. Defaults to 'web'. */
33553
- this.platform = 'web';
33554
- /** When true, hides Priority, Type, and Test Data Set fields (step groups don't have these). Defaults to false. */
33555
- this.isStepGroup = false;
33556
- /**
33557
- * Override config per select key. Use for:
33558
- * - API-driven options: pass options array (update when API returns)
33559
- * - Server-side search: serverSearch: true, onSearch in override or listen to selectSearch
33560
- * - Infinite scroll: hasMore: true, onLoadMore in override or listen to selectLoadMore
33561
- * - Initial fetch on open: initialFetchOnOpen: true
33562
- */
33563
- this.selectConfigOverrides = {};
33564
- this.save = new EventEmitter();
33565
- this.cancel = new EventEmitter();
33566
- /** Emitted when user searches in a select (serverSearch mode). Call API and update options via selectConfigOverrides. */
33567
- this.selectSearch = new EventEmitter();
33568
- /** Emitted when user scrolls to load more. Call API, append to options via selectConfigOverrides. */
33569
- this.selectLoadMore = new EventEmitter();
33570
- /** Emitted when a select panel is opened. Use to call API for initial load (e.g. when initialFetchOnOpen). */
33571
- this.selectOpened = new EventEmitter();
33572
- /** Emitted when selection changes in any select. */
33573
- this.selectionChange = new EventEmitter();
33574
- /** Emitted when user adds a new custom label via the "New" option. */
33575
- this.labelAdded = new EventEmitter();
33576
- /** Form state */
33577
- this.editDescription = '';
33578
- this.editStatus = '';
33579
- this.editPriority = '';
33580
- this.editLabels = [];
33581
- this.testCaseTimeout = '';
33582
- this.waitTimeoutLocators = '';
33583
- this.autoWaitEnabled = false;
33584
- this.retryFailedSteps = '';
33585
- this.configExpanded = true;
33586
- this.executionExpanded = true;
33587
- this.aiConfigExpanded = true;
33588
- this.waitsRetriesExpanded = true;
33589
- this.deviceExpanded = true;
33590
- this.keyFlagsExpanded = true;
33591
- this.mobileTestingEnabled = false;
33592
- this.extensionUseEnabled = false;
33593
- this.dataDrivenEnabled = false;
33594
- this.frequentlyUsedLabels = FREQUENTLY_USED_LABELS;
33595
- /** FormGroup for cqa-dynamic-select bindings */
33596
- this.editForm = new FormGroup({
33671
+ class DetailSidePanelComponent {
33672
+ constructor() {
33673
+ /** Tabs - each tab has a side panel icon button; tabs and buttons are 1:1. Host defines tabs and content. */
33674
+ this.tabs = [
33675
+ { label: 'Test Case', value: 'test-case', icon: 'description' },
33676
+ { label: 'Data Library', value: 'data-library', icon: 'folder' },
33677
+ { label: 'Variables', value: 'variables', icon: 'code' },
33678
+ ];
33679
+ /** Currently active tab value */
33680
+ this.activeTab = 'test-case';
33681
+ /** Whether to show the close button in the side menu */
33682
+ this.showCloseButton = false;
33683
+ /** Whether the panel is expanded (affects expand button icon and panel width) */
33684
+ this.expanded = true;
33685
+ /** Panel width when expanded (e.g. '480px', '25%') */
33686
+ this.expandedWidth = '380px';
33687
+ /** Panel width when collapsed (e.g. '56px' - fits icon bar + back button) */
33688
+ this.collapsedWidth = '56px';
33689
+ this.hostOverflow = 'hidden';
33690
+ /** Tooltip for expand button when panel is collapsed */
33691
+ this.expandTooltip = 'Expand';
33692
+ /** Tooltip for expand button when panel is expanded (collapse) */
33693
+ this.collapseTooltip = 'Collapse';
33694
+ /** Tooltip for close button */
33695
+ this.closeTooltip = 'Close';
33696
+ this.back = new EventEmitter();
33697
+ this.tabChange = new EventEmitter();
33698
+ this.expandToggle = new EventEmitter();
33699
+ this.close = new EventEmitter();
33700
+ }
33701
+ get hostWidth() {
33702
+ return this.expanded ? this.expandedWidth : this.collapsedWidth;
33703
+ }
33704
+ get hostMinWidth() {
33705
+ return this.expanded ? this.expandedWidth : this.collapsedWidth;
33706
+ }
33707
+ get hostMaxWidth() {
33708
+ return this.expanded ? this.expandedWidth : this.collapsedWidth;
33709
+ }
33710
+ trackByTabValue(_i, tab) {
33711
+ return tab.value;
33712
+ }
33713
+ onBack() {
33714
+ this.back.emit();
33715
+ }
33716
+ onTabClick(tab) {
33717
+ if (!this.expanded) {
33718
+ this.expandToggle.emit();
33719
+ }
33720
+ if (tab.value !== this.activeTab) {
33721
+ this.tabChange.emit(tab.value);
33722
+ }
33723
+ }
33724
+ onExpandToggle() {
33725
+ this.expandToggle.emit();
33726
+ }
33727
+ onClose() {
33728
+ this.close.emit();
33729
+ }
33730
+ }
33731
+ DetailSidePanelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailSidePanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
33732
+ DetailSidePanelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DetailSidePanelComponent, selector: "cqa-detail-side-panel", inputs: { tabs: "tabs", activeTab: "activeTab", showCloseButton: "showCloseButton", expanded: "expanded", expandedWidth: "expandedWidth", collapsedWidth: "collapsedWidth", expandTooltip: "expandTooltip", collapseTooltip: "collapseTooltip", closeTooltip: "closeTooltip" }, outputs: { back: "back", tabChange: "tabChange", expandToggle: "expandToggle", close: "close" }, host: { properties: { "style.width": "this.hostWidth", "style.min-width": "this.hostMinWidth", "style.max-width": "this.hostMaxWidth", "style.overflow": "this.hostOverflow" }, styleAttribute: "transition: width 0.3s ease-in-out", classAttribute: "cqa-ui-root cqa-flex cqa-flex-col cqa-h-full cqa-flex-shrink-0 cqa-flex-grow-0 cqa-bg-white cqa-shadow-[-4px_0_6px_-1px_rgba(0,0,0,0.05)]" }, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-min-w-0 cqa-bg-white\">\n <!-- Main content: Side menu + Scrollable content -->\n <div\n class=\"cqa-grid cqa-flex-1 cqa-min-h-0 cqa-min-w-0 cqa-overflow-hidden\"\n [style.grid-template-columns]=\"expanded ? 'auto 1fr' : 'auto 0fr'\"\n style=\"transition: grid-template-columns 0.3s ease-in-out\">\n <!-- Left vertical icon menu -->\n <div\n class=\"cqa-flex cqa-flex-col cqa-items-center cqa-gap-2 cqa-py-4 cqa-px-2 cqa-border-r cqa-border-[#F5F5F5] cqa-flex-shrink-0 cqa-text-[#0A0A0A]\"\n style=\"box-shadow: 1px 4px 12px 1px rgba(0, 0, 0, 0.05);\">\n <!-- Expand / Collapse button (always visible) -->\n <button\n type=\"button\"\n [matTooltip]=\"expanded ? collapseTooltip : expandTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onExpandToggle()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ expanded ? 'chevron_left' : 'chevron_right' }}</mat-icon>\n </button>\n <!-- Close button -->\n <button\n *ngIf=\"showCloseButton\"\n type=\"button\"\n [matTooltip]=\"closeTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onClose()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">close</mat-icon>\n </button>\n <!-- Tab buttons (1:1 with tabs) -->\n <button\n *ngFor=\"let tab of tabs; trackBy: trackByTabValue\"\n type=\"button\"\n [matTooltip]=\"tab.label\"\n [class.cqa-bg-[#3F43EE]]=\"activeTab === tab.value\"\n [class.cqa-text-white]=\"activeTab === tab.value\"\n [class.cqa-text-[#64748B]]=\"activeTab !== tab.value\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onTabClick(tab)\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ tab.icon || 'circle' }}</mat-icon>\n </button>\n </div>\n\n <!-- Scrollable content area (collapses with animation when expanded is false) -->\n <div class=\"cqa-flex cqa-flex-col cqa-min-h-0 cqa-min-w-0 cqa-overflow-hidden cqa-w-full cqa-h-full\">\n <div class=\"detail-side-panel-scroll cqa-flex-1 cqa-min-h-0 cqa-min-w-0 cqa-overflow-y-auto cqa-overflow-x-hidden cqa-p-4 cqa-space-y-4\" style=\"overflow-y: auto; overflow-x: hidden; min-height: 0; -webkit-overflow-scrolling: touch;\">\n <!-- Tabs: equally distributed (Figma: purple active, gray inactive) -->\n <div class=\"cqa-flex cqa-gap-[3.5px] cqa-p-[3.5px] cqa-bg-[#F1F5F9] cqa-rounded-lg cqa-w-full\" role=\"tablist\">\n <button\n *ngFor=\"let tab of tabs; trackBy: trackByTabValue\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === tab.value\"\n [class.cqa-bg-[#3F43EE]]=\"activeTab === tab.value\"\n [class.cqa-text-white]=\"activeTab === tab.value\"\n [class.cqa-text-[#64748B]]=\"activeTab !== tab.value\"\n class=\"cqa-flex-1 cqa-flex cqa-justify-center cqa-items-center cqa-py-2 cqa-rounded-lg cqa-text-xs cqa-font-medium cqa-transition-colors hover:cqa-opacity-90 focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onTabClick(tab)\">\n {{ tab.label }}\n </button>\n </div>\n\n <!-- Tab content: fully provided by host via content projection. Host uses *ngIf per tab so only active content is projected. Add/remove tabs in the host without changing cqa-ui-lib. -->\n <ng-content></ng-content>\n </div>\n </div>\n </div>\n</div>\n", styles: [".detail-side-panel-scroll{overflow-y:auto!important;overflow-x:hidden!important;min-height:0!important;-webkit-overflow-scrolling:touch}\n"], components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i5.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
33733
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailSidePanelComponent, decorators: [{
33734
+ type: Component,
33735
+ args: [{ selector: 'cqa-detail-side-panel', styles: [DETAIL_SIDE_PANEL_SCROLL_STYLES], changeDetection: ChangeDetectionStrategy.OnPush, host: {
33736
+ class: 'cqa-ui-root cqa-flex cqa-flex-col cqa-h-full cqa-flex-shrink-0 cqa-flex-grow-0 cqa-bg-white cqa-shadow-[-4px_0_6px_-1px_rgba(0,0,0,0.05)]',
33737
+ style: 'transition: width 0.3s ease-in-out',
33738
+ }, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-min-w-0 cqa-bg-white\">\n <!-- Main content: Side menu + Scrollable content -->\n <div\n class=\"cqa-grid cqa-flex-1 cqa-min-h-0 cqa-min-w-0 cqa-overflow-hidden\"\n [style.grid-template-columns]=\"expanded ? 'auto 1fr' : 'auto 0fr'\"\n style=\"transition: grid-template-columns 0.3s ease-in-out\">\n <!-- Left vertical icon menu -->\n <div\n class=\"cqa-flex cqa-flex-col cqa-items-center cqa-gap-2 cqa-py-4 cqa-px-2 cqa-border-r cqa-border-[#F5F5F5] cqa-flex-shrink-0 cqa-text-[#0A0A0A]\"\n style=\"box-shadow: 1px 4px 12px 1px rgba(0, 0, 0, 0.05);\">\n <!-- Expand / Collapse button (always visible) -->\n <button\n type=\"button\"\n [matTooltip]=\"expanded ? collapseTooltip : expandTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onExpandToggle()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ expanded ? 'chevron_left' : 'chevron_right' }}</mat-icon>\n </button>\n <!-- Close button -->\n <button\n *ngIf=\"showCloseButton\"\n type=\"button\"\n [matTooltip]=\"closeTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onClose()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">close</mat-icon>\n </button>\n <!-- Tab buttons (1:1 with tabs) -->\n <button\n *ngFor=\"let tab of tabs; trackBy: trackByTabValue\"\n type=\"button\"\n [matTooltip]=\"tab.label\"\n [class.cqa-bg-[#3F43EE]]=\"activeTab === tab.value\"\n [class.cqa-text-white]=\"activeTab === tab.value\"\n [class.cqa-text-[#64748B]]=\"activeTab !== tab.value\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onTabClick(tab)\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ tab.icon || 'circle' }}</mat-icon>\n </button>\n </div>\n\n <!-- Scrollable content area (collapses with animation when expanded is false) -->\n <div class=\"cqa-flex cqa-flex-col cqa-min-h-0 cqa-min-w-0 cqa-overflow-hidden cqa-w-full cqa-h-full\">\n <div class=\"detail-side-panel-scroll cqa-flex-1 cqa-min-h-0 cqa-min-w-0 cqa-overflow-y-auto cqa-overflow-x-hidden cqa-p-4 cqa-space-y-4\" style=\"overflow-y: auto; overflow-x: hidden; min-height: 0; -webkit-overflow-scrolling: touch;\">\n <!-- Tabs: equally distributed (Figma: purple active, gray inactive) -->\n <div class=\"cqa-flex cqa-gap-[3.5px] cqa-p-[3.5px] cqa-bg-[#F1F5F9] cqa-rounded-lg cqa-w-full\" role=\"tablist\">\n <button\n *ngFor=\"let tab of tabs; trackBy: trackByTabValue\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === tab.value\"\n [class.cqa-bg-[#3F43EE]]=\"activeTab === tab.value\"\n [class.cqa-text-white]=\"activeTab === tab.value\"\n [class.cqa-text-[#64748B]]=\"activeTab !== tab.value\"\n class=\"cqa-flex-1 cqa-flex cqa-justify-center cqa-items-center cqa-py-2 cqa-rounded-lg cqa-text-xs cqa-font-medium cqa-transition-colors hover:cqa-opacity-90 focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onTabClick(tab)\">\n {{ tab.label }}\n </button>\n </div>\n\n <!-- Tab content: fully provided by host via content projection. Host uses *ngIf per tab so only active content is projected. Add/remove tabs in the host without changing cqa-ui-lib. -->\n <ng-content></ng-content>\n </div>\n </div>\n </div>\n</div>\n" }]
33739
+ }], propDecorators: { tabs: [{
33740
+ type: Input
33741
+ }], activeTab: [{
33742
+ type: Input
33743
+ }], showCloseButton: [{
33744
+ type: Input
33745
+ }], expanded: [{
33746
+ type: Input
33747
+ }], expandedWidth: [{
33748
+ type: Input
33749
+ }], collapsedWidth: [{
33750
+ type: Input
33751
+ }], hostWidth: [{
33752
+ type: HostBinding,
33753
+ args: ['style.width']
33754
+ }], hostMinWidth: [{
33755
+ type: HostBinding,
33756
+ args: ['style.min-width']
33757
+ }], hostMaxWidth: [{
33758
+ type: HostBinding,
33759
+ args: ['style.max-width']
33760
+ }], hostOverflow: [{
33761
+ type: HostBinding,
33762
+ args: ['style.overflow']
33763
+ }], expandTooltip: [{
33764
+ type: Input
33765
+ }], collapseTooltip: [{
33766
+ type: Input
33767
+ }], closeTooltip: [{
33768
+ type: Input
33769
+ }], back: [{
33770
+ type: Output
33771
+ }], tabChange: [{
33772
+ type: Output
33773
+ }], expandToggle: [{
33774
+ type: Output
33775
+ }], close: [{
33776
+ type: Output
33777
+ }] } });
33778
+
33779
+ class DetailDrawerTabContentDirective {
33780
+ constructor(templateRef) {
33781
+ this.templateRef = templateRef;
33782
+ }
33783
+ }
33784
+ DetailDrawerTabContentDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerTabContentDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
33785
+ DetailDrawerTabContentDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.4.0", type: DetailDrawerTabContentDirective, selector: "[cqaTabContent]", ngImport: i0 });
33786
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerTabContentDirective, decorators: [{
33787
+ type: Directive,
33788
+ args: [{
33789
+ selector: '[cqaTabContent]',
33790
+ }]
33791
+ }], ctorParameters: function () { return [{ type: i0.TemplateRef }]; } });
33792
+
33793
+ class DetailDrawerTabComponent {
33794
+ constructor() {
33795
+ /** Tab label (shown in tooltip on icon button) */
33796
+ this.label = '';
33797
+ /** Tab value (unique identifier) */
33798
+ this.value = '';
33799
+ /** Material icon name for the tab button */
33800
+ this.icon = 'folder';
33801
+ }
33802
+ get contentTemplate() {
33803
+ return this.contentDirective?.templateRef ?? null;
33804
+ }
33805
+ }
33806
+ DetailDrawerTabComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerTabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
33807
+ DetailDrawerTabComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DetailDrawerTabComponent, selector: "cqa-detail-drawer-tab", inputs: { label: "label", value: "value", icon: "icon" }, host: { styleAttribute: "display: contents" }, queries: [{ propertyName: "contentDirective", first: true, predicate: DetailDrawerTabContentDirective, descendants: true }], ngImport: i0, template: '', isInline: true });
33808
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerTabComponent, decorators: [{
33809
+ type: Component,
33810
+ args: [{
33811
+ selector: 'cqa-detail-drawer-tab',
33812
+ template: '',
33813
+ host: {
33814
+ style: 'display: contents',
33815
+ },
33816
+ }]
33817
+ }], propDecorators: { label: [{
33818
+ type: Input
33819
+ }], value: [{
33820
+ type: Input
33821
+ }], icon: [{
33822
+ type: Input
33823
+ }], contentDirective: [{
33824
+ type: ContentChild,
33825
+ args: [DetailDrawerTabContentDirective]
33826
+ }] } });
33827
+
33828
+ class DetailDrawerComponent {
33829
+ constructor() {
33830
+ /** Currently active tab value */
33831
+ this.activeTab = '';
33832
+ /** Whether to show the close button */
33833
+ this.showCloseButton = true;
33834
+ /** Whether the drawer is expanded */
33835
+ this.expanded = true;
33836
+ /** Panel width when expanded */
33837
+ this.expandedWidth = '280px';
33838
+ /** Maximum width when expanded (e.g. '600px', '30vw'). Default: 30% of viewport */
33839
+ this.maxExpandedWidth = '30vw';
33840
+ /** Panel width when collapsed */
33841
+ this.collapsedWidth = '56px';
33842
+ this.expandTooltip = 'Expand';
33843
+ this.collapseTooltip = 'Collapse';
33844
+ this.closeTooltip = 'Close';
33845
+ this.activeTabChange = new EventEmitter();
33846
+ this.expandToggle = new EventEmitter();
33847
+ this.close = new EventEmitter();
33848
+ }
33849
+ get hostWidth() {
33850
+ return this.expanded ? this.expandedWidth : this.collapsedWidth;
33851
+ }
33852
+ get hostMinWidth() {
33853
+ return this.expanded && this.minExpandedWidth ? this.minExpandedWidth : null;
33854
+ }
33855
+ get hostMaxWidth() {
33856
+ return this.expanded ? this.maxExpandedWidth : null;
33857
+ }
33858
+ ngAfterContentInit() {
33859
+ this.ensureActiveTab();
33860
+ }
33861
+ ngAfterContentChecked() {
33862
+ this.ensureActiveTab();
33863
+ }
33864
+ ensureActiveTab() {
33865
+ const tabs = this.tabComponents?.toArray() ?? [];
33866
+ if (tabs.length > 0 && !this.activeTab) {
33867
+ this.activeTab = tabs[0].value;
33868
+ this.activeTabChange.emit(this.activeTab);
33869
+ }
33870
+ }
33871
+ onTabClick(tab) {
33872
+ // If drawer is collapsed, open it (but never close on tab click)
33873
+ if (!this.expanded) {
33874
+ this.expandToggle.emit();
33875
+ }
33876
+ // Select the tab
33877
+ if (tab.value !== this.activeTab) {
33878
+ this.activeTab = tab.value;
33879
+ this.activeTabChange.emit(this.activeTab);
33880
+ }
33881
+ }
33882
+ onExpandToggle() {
33883
+ this.expandToggle.emit();
33884
+ }
33885
+ onClose() {
33886
+ this.close.emit();
33887
+ }
33888
+ trackByValue(_i, tab) {
33889
+ return tab.value;
33890
+ }
33891
+ isTabActive(tab) {
33892
+ return tab.value === this.activeTab;
33893
+ }
33894
+ }
33895
+ DetailDrawerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
33896
+ DetailDrawerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DetailDrawerComponent, selector: "cqa-detail-drawer", inputs: { activeTab: "activeTab", showCloseButton: "showCloseButton", expanded: "expanded", expandedWidth: "expandedWidth", minExpandedWidth: "minExpandedWidth", maxExpandedWidth: "maxExpandedWidth", collapsedWidth: "collapsedWidth", expandTooltip: "expandTooltip", collapseTooltip: "collapseTooltip", closeTooltip: "closeTooltip" }, outputs: { activeTabChange: "activeTabChange", expandToggle: "expandToggle", close: "close" }, host: { properties: { "style.width": "this.hostWidth", "style.min-width": "this.hostMinWidth", "style.max-width": "this.hostMaxWidth" }, styleAttribute: "transition: width 0.3s ease-in-out", classAttribute: "cqa-ui-root cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-shadow-[-4px_0_6px_-1px_rgba(0,0,0,0.05)]" }, queries: [{ propertyName: "tabComponents", predicate: DetailDrawerTabComponent }], ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white\">\n <div\n class=\"cqa-grid cqa-flex-1 cqa-min-h-0 cqa-overflow-hidden\"\n [style.grid-template-columns]=\"expanded ? 'auto 1fr' : 'auto 0fr'\"\n style=\"transition: grid-template-columns 0.3s ease-in-out\">\n <!-- Left vertical icon bar: one button per tab -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-min-h-0 cqa-items-center cqa-py-4 cqa-px-2 cqa-border-r cqa-border-[#E2E8F0] cqa-bg-[#FAFAFA] cqa-flex-shrink-0\">\n <!-- Expand / Collapse button (always visible) -->\n <button\n type=\"button\"\n [matTooltip]=\"expanded ? collapseTooltip : expandTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n (click)=\"onExpandToggle()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ expanded ? 'unfold_less' : 'unfold_more' }}</mat-icon>\n </button>\n <!-- Close button -->\n <button\n *ngIf=\"showCloseButton\"\n type=\"button\"\n [matTooltip]=\"closeTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n (click)=\"onClose()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">close</mat-icon>\n </button>\n <!-- Tab buttons: equally distributed in remaining space -->\n <div class=\"cqa-flex cqa-flex-1 cqa-flex-col cqa-justify-evenly cqa-items-center cqa-w-full\">\n <button\n *ngFor=\"let tab of tabComponents; trackBy: trackByValue\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"isTabActive(tab)\"\n [matTooltip]=\"tab.label\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n [ngClass]=\"{\n 'cqa-bg-[#3F43EE] cqa-text-white': isTabActive(tab),\n 'cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155]': !isTabActive(tab)\n }\"\n (click)=\"onTabClick(tab)\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ tab.icon }}</mat-icon>\n </button>\n </div>\n </div>\n\n <!-- Content area: show only the active tab's content -->\n <div class=\"cqa-min-w-0 cqa-overflow-hidden\">\n <div class=\"cqa-h-full cqa-overflow-y-auto cqa-p-4\">\n <ng-container *ngFor=\"let tab of tabComponents\">\n <ng-container *ngIf=\"tab.value === activeTab && tab.contentTemplate\" [ngTemplateOutlet]=\"tab.contentTemplate\"></ng-container>\n </ng-container>\n </div>\n </div>\n </div>\n</div>\n", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i5.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
33897
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerComponent, decorators: [{
33898
+ type: Component,
33899
+ args: [{ selector: 'cqa-detail-drawer', changeDetection: ChangeDetectionStrategy.OnPush, host: {
33900
+ class: 'cqa-ui-root cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-shadow-[-4px_0_6px_-1px_rgba(0,0,0,0.05)]',
33901
+ style: 'transition: width 0.3s ease-in-out',
33902
+ }, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white\">\n <div\n class=\"cqa-grid cqa-flex-1 cqa-min-h-0 cqa-overflow-hidden\"\n [style.grid-template-columns]=\"expanded ? 'auto 1fr' : 'auto 0fr'\"\n style=\"transition: grid-template-columns 0.3s ease-in-out\">\n <!-- Left vertical icon bar: one button per tab -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-min-h-0 cqa-items-center cqa-py-4 cqa-px-2 cqa-border-r cqa-border-[#E2E8F0] cqa-bg-[#FAFAFA] cqa-flex-shrink-0\">\n <!-- Expand / Collapse button (always visible) -->\n <button\n type=\"button\"\n [matTooltip]=\"expanded ? collapseTooltip : expandTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n (click)=\"onExpandToggle()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ expanded ? 'unfold_less' : 'unfold_more' }}</mat-icon>\n </button>\n <!-- Close button -->\n <button\n *ngIf=\"showCloseButton\"\n type=\"button\"\n [matTooltip]=\"closeTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n (click)=\"onClose()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">close</mat-icon>\n </button>\n <!-- Tab buttons: equally distributed in remaining space -->\n <div class=\"cqa-flex cqa-flex-1 cqa-flex-col cqa-justify-evenly cqa-items-center cqa-w-full\">\n <button\n *ngFor=\"let tab of tabComponents; trackBy: trackByValue\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"isTabActive(tab)\"\n [matTooltip]=\"tab.label\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n [ngClass]=\"{\n 'cqa-bg-[#3F43EE] cqa-text-white': isTabActive(tab),\n 'cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155]': !isTabActive(tab)\n }\"\n (click)=\"onTabClick(tab)\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ tab.icon }}</mat-icon>\n </button>\n </div>\n </div>\n\n <!-- Content area: show only the active tab's content -->\n <div class=\"cqa-min-w-0 cqa-overflow-hidden\">\n <div class=\"cqa-h-full cqa-overflow-y-auto cqa-p-4\">\n <ng-container *ngFor=\"let tab of tabComponents\">\n <ng-container *ngIf=\"tab.value === activeTab && tab.contentTemplate\" [ngTemplateOutlet]=\"tab.contentTemplate\"></ng-container>\n </ng-container>\n </div>\n </div>\n </div>\n</div>\n", styles: [] }]
33903
+ }], propDecorators: { tabComponents: [{
33904
+ type: ContentChildren,
33905
+ args: [DetailDrawerTabComponent]
33906
+ }], activeTab: [{
33907
+ type: Input
33908
+ }], showCloseButton: [{
33909
+ type: Input
33910
+ }], expanded: [{
33911
+ type: Input
33912
+ }], expandedWidth: [{
33913
+ type: Input
33914
+ }], minExpandedWidth: [{
33915
+ type: Input
33916
+ }], maxExpandedWidth: [{
33917
+ type: Input
33918
+ }], collapsedWidth: [{
33919
+ type: Input
33920
+ }], hostWidth: [{
33921
+ type: HostBinding,
33922
+ args: ['style.width']
33923
+ }], hostMinWidth: [{
33924
+ type: HostBinding,
33925
+ args: ['style.min-width']
33926
+ }], hostMaxWidth: [{
33927
+ type: HostBinding,
33928
+ args: ['style.max-width']
33929
+ }], expandTooltip: [{
33930
+ type: Input
33931
+ }], collapseTooltip: [{
33932
+ type: Input
33933
+ }], closeTooltip: [{
33934
+ type: Input
33935
+ }], activeTabChange: [{
33936
+ type: Output
33937
+ }], expandToggle: [{
33938
+ type: Output
33939
+ }], close: [{
33940
+ type: Output
33941
+ }] } });
33942
+
33943
+ /** Keys for each dynamic select in test-case-details-edit. Use these with selectConfigOverrides. */
33944
+ const TEST_CASE_DETAILS_SELECT_KEYS = {
33945
+ status: 'status',
33946
+ priority: 'priority',
33947
+ type: 'type',
33948
+ labels: 'labels',
33949
+ prerequisiteCases: 'prerequisiteCases',
33950
+ testDataProfile: 'testDataProfile',
33951
+ testDataSet: 'testDataSet',
33952
+ videoRecording: 'videoRecording',
33953
+ enableAiSmartness: 'enableAiSmartness',
33954
+ defaultAiAction: 'defaultAiAction',
33955
+ knowledgeBaseDefaultTestCase: 'knowledgeBaseDefaultTestCase',
33956
+ useAiMetadata: 'useAiMetadata',
33957
+ defaultBrowser: 'defaultBrowser',
33958
+ defaultViewport: 'defaultViewport',
33959
+ deviceType: 'deviceType',
33960
+ deviceOS: 'deviceOS',
33961
+ };
33962
+ const FREQUENTLY_USED_LABELS = [
33963
+ 'Case',
33964
+ 'Critical',
33965
+ 'PO',
33966
+ 'Upload',
33967
+ 'Validation',
33968
+ 'Review',
33969
+ 'Edge-cases',
33970
+ 'Security',
33971
+ 'Integration',
33972
+ 'Smoke',
33973
+ ];
33974
+ class TestCaseDetailsEditComponent {
33975
+ constructor(cdr) {
33976
+ this.cdr = cdr;
33977
+ this.descriptionTitle = 'Description';
33978
+ this.descriptionContent = '';
33979
+ /** When true, description uses Trix rich text editor (Bold, Italic, etc.). Host app must load Trix. */
33980
+ this.enableMarkdown = false;
33981
+ this.metadataItems = [];
33982
+ this.labels = [];
33983
+ this.configTitle = 'Configuration';
33984
+ this.configSections = [];
33985
+ this.configSectionsRow2 = [];
33986
+ /** Optional list of prerequisite test case options for the multi-select. If not provided, uses default sample options. */
33987
+ this.prerequisiteCaseOptions = [];
33988
+ /** Platform: 'web' shows Default Browser + Viewport; 'mobile' shows Device Type + OS. Defaults to 'web'. */
33989
+ this.platform = 'web';
33990
+ /** When true, hides Priority, Type, and Test Data Set fields (step groups don't have these). Defaults to false. */
33991
+ this.isStepGroup = false;
33992
+ /**
33993
+ * Override config per select key. Use for:
33994
+ * - API-driven options: pass options array (update when API returns)
33995
+ * - Server-side search: serverSearch: true, onSearch in override or listen to selectSearch
33996
+ * - Infinite scroll: hasMore: true, onLoadMore in override or listen to selectLoadMore
33997
+ * - Initial fetch on open: initialFetchOnOpen: true
33998
+ */
33999
+ this.selectConfigOverrides = {};
34000
+ this.save = new EventEmitter();
34001
+ this.cancel = new EventEmitter();
34002
+ /** Emitted when user searches in a select (serverSearch mode). Call API and update options via selectConfigOverrides. */
34003
+ this.selectSearch = new EventEmitter();
34004
+ /** Emitted when user scrolls to load more. Call API, append to options via selectConfigOverrides. */
34005
+ this.selectLoadMore = new EventEmitter();
34006
+ /** Emitted when a select panel is opened. Use to call API for initial load (e.g. when initialFetchOnOpen). */
34007
+ this.selectOpened = new EventEmitter();
34008
+ /** Emitted when selection changes in any select. */
34009
+ this.selectionChange = new EventEmitter();
34010
+ /** Emitted when user adds a new custom label via the "New" option. */
34011
+ this.labelAdded = new EventEmitter();
34012
+ /** Form state */
34013
+ this.editDescription = '';
34014
+ this.editStatus = '';
34015
+ this.editPriority = '';
34016
+ this.editLabels = [];
34017
+ this.testCaseTimeout = '';
34018
+ this.waitTimeoutLocators = '';
34019
+ this.autoWaitEnabled = false;
34020
+ this.retryFailedSteps = '';
34021
+ this.configExpanded = true;
34022
+ this.executionExpanded = true;
34023
+ this.aiConfigExpanded = true;
34024
+ this.waitsRetriesExpanded = true;
34025
+ this.deviceExpanded = true;
34026
+ this.keyFlagsExpanded = true;
34027
+ this.mobileTestingEnabled = false;
34028
+ this.extensionUseEnabled = false;
34029
+ this.dataDrivenEnabled = false;
34030
+ this.frequentlyUsedLabels = FREQUENTLY_USED_LABELS;
34031
+ /** FormGroup for cqa-dynamic-select bindings */
34032
+ this.editForm = new FormGroup({
33597
34033
  status: new FormControl(''),
33598
34034
  priority: new FormControl(''),
33599
34035
  type: new FormControl(''),
@@ -34424,234 +34860,43 @@ class TestCaseDetailsComponent {
34424
34860
  return this.editing !== undefined ? this.editing : this._editing;
34425
34861
  }
34426
34862
  ngOnInit() {
34427
- if (this.startInEditMode) {
34428
- this._editing = true;
34429
- }
34430
- }
34431
- /** Filtered metadata items - excludes Priority and Type for step groups */
34432
- get filteredMetadataItems() {
34433
- if (!this.isStepGroup) {
34434
- return this.metadataItems;
34435
- }
34436
- return this.metadataItems.filter((item) => !this.stepGroupExcludedMetadataLabels.includes(item.label?.toLowerCase() ?? ''));
34437
- }
34438
- onEditClick() {
34439
- if (this.editing === undefined) {
34440
- this._editing = true;
34441
- this.cdr.detectChanges();
34442
- }
34443
- this.editDescription.emit();
34444
- }
34445
- onSaveChanges(data) {
34446
- if (this.editing === undefined) {
34447
- this._editing = false;
34448
- }
34449
- this.cdr.detectChanges();
34450
- this.saveChanges.emit(data);
34451
- }
34452
- onCancelEdit() {
34453
- this.cancel.emit();
34454
- if (this.editing === undefined) {
34455
- this._editing = false;
34456
- }
34457
- this.cdr.detectChanges();
34458
- }
34459
- trackByConfigTitle(_i, section) {
34460
- return section.title;
34461
- }
34462
- trackByMetadataLabel(_i, item) {
34463
- return item.label;
34464
- }
34465
- onMetadataLinkClick(item) {
34466
- if (item.link) {
34467
- this.metadataLinkClick.emit(item);
34468
- }
34469
- }
34470
- getStatusDotClass(item) {
34471
- if (!item.statusColor)
34472
- return '';
34473
- switch (item.statusColor) {
34474
- case 'yellow':
34475
- return 'cqa-bg-[#EAB308]';
34476
- case 'red':
34477
- return 'cqa-bg-[#DC2626]';
34478
- case 'green':
34479
- return 'cqa-bg-[#16A34A]';
34480
- case 'gray':
34481
- default:
34482
- return 'cqa-bg-[#94A3B8]';
34483
- }
34484
- }
34485
- /** Text color for metadata value (e.g. red for critical priority) */
34486
- getValueTextClass(item) {
34487
- if (item.statusColor === 'red') {
34488
- return 'cqa-text-[#DC2626]';
34489
- }
34490
- return 'cqa-text-[#111827]';
34491
- }
34492
- }
34493
- TestCaseDetailsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestCaseDetailsComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
34494
- TestCaseDetailsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TestCaseDetailsComponent, selector: "cqa-test-case-details", inputs: { editing: "editing", startInEditMode: "startInEditMode", descriptionTitle: "descriptionTitle", descriptionContent: "descriptionContent", enableMarkdown: "enableMarkdown", showEditButton: "showEditButton", metadataItems: "metadataItems", labels: "labels", configTitle: "configTitle", configSections: "configSections", configSectionsRow2: "configSectionsRow2", platform: "platform", isStepGroup: "isStepGroup", selectConfigOverrides: "selectConfigOverrides" }, outputs: { editDescription: "editDescription", cancel: "cancel", saveChanges: "saveChanges", metadataLinkClick: "metadataLinkClick", selectSearch: "selectSearch", selectLoadMore: "selectLoadMore", selectOpened: "selectOpened", selectionChange: "selectionChange", labelAdded: "labelAdded" }, ngImport: i0, template: "<!-- Edit mode: show edit form (Figma design) -->\n<cqa-test-case-details-edit\n *ngIf=\"isEditing\"\n [descriptionTitle]=\"descriptionTitle\"\n [descriptionContent]=\"descriptionContent\"\n [enableMarkdown]=\"enableMarkdown\"\n [metadataItems]=\"metadataItems\"\n [labels]=\"labels\"\n [configTitle]=\"configTitle\"\n [configSections]=\"configSections\"\n [configSectionsRow2]=\"configSectionsRow2\"\n [platform]=\"platform\"\n [isStepGroup]=\"isStepGroup\"\n [selectConfigOverrides]=\"selectConfigOverrides\"\n (save)=\"onSaveChanges($event)\"\n (cancel)=\"onCancelEdit()\"\n (selectSearch)=\"selectSearch.emit($event)\"\n (selectLoadMore)=\"selectLoadMore.emit($event)\"\n (selectOpened)=\"selectOpened.emit($event)\"\n (selectionChange)=\"selectionChange.emit($event)\"\n (labelAdded)=\"labelAdded.emit($event)\">\n</cqa-test-case-details-edit>\n\n<!-- View mode: read-only details -->\n<div *ngIf=\"!isEditing\" class=\"cqa-self-stretch cqa-py-4 cqa-px-0 cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <!-- Description Section -->\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-inline-flex cqa-justify-between cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-w-5 cqa-h-5 cqa-p-1 cqa-flex-shrink-0 cqa-bg-[#3F43EE1A] cqa-rounded-md cqa-inline-flex cqa-justify-center cqa-items-center\">\n <mat-icon class=\"cqa-text-[#1B1FEB] cqa-text-[12px] cqa-w-3 cqa-h-3 cqa-leading-none cqa-block\">description</mat-icon>\n </div>\n <span class=\"cqa-text-[#374151] cqa-text-sm cqa-font-semibold cqa-leading-[19.6px]\">{{ descriptionTitle }}</span>\n </div>\n <button\n *ngIf=\"showEditButton\"\n type=\"button\"\n class=\"cqa-flex cqa-justify-end cqa-items-center cqa-gap-2 cqa-text-[#A3A3A3] cqa-text-xs cqa-font-semibold hover:cqa-text-[#737373] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onEditClick()\">\n <mat-icon class=\"cqa-text-[14px] cqa-w-4 cqa-h-4\">edit</mat-icon>\n Edit\n </button>\n </div>\n <div *ngIf=\"descriptionContent\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start\">\n <div *ngIf=\"enableMarkdown\" class=\"cqa-self-stretch cqa-text-[#111827] cqa-text-sm cqa-leading-[19.6px] cqa-font-normal cqa-prose cqa-prose-sm cqa-max-w-none\" [innerHTML]=\"descriptionContent\"></div>\n <div *ngIf=\"!enableMarkdown\" class=\"cqa-self-stretch cqa-text-[#111827] cqa-text-sm cqa-leading-[19.6px] cqa-font-normal\">{{ descriptionContent }}</div>\n </div>\n </div>\n\n <!-- Metadata Section -->\n <div *ngIf=\"filteredMetadataItems.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-grid cqa-grid-cols-2 cqa-gap-x-0 cqa-gap-y-4\">\n <ng-container *ngFor=\"let item of filteredMetadataItems; trackBy: trackByMetadataLabel\">\n <div class=\"cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-0.5\">\n <div class=\"cqa-text-[#6B7280] cqa-text-xs cqa-leading-[15px] cqa-font-medium\">{{ item.label }}</div>\n <div\n class=\"cqa-flex cqa-justify-start cqa-items-center cqa-gap-[5px] cqa-min-w-0 cqa-w-full cqa-text-left cqa-text-[#0A0A0A] cqa-border cqa-border-[#F5F5F5]\">\n <mat-icon *ngIf=\"item.icon && (!item.iconLibrary || item.iconLibrary === 'mat')\" class=\"cqa-text-[#6B7280] cqa-text-sm cqa-w-4 cqa-h-4\">\n {{ item.icon }}\n </mat-icon>\n <span *ngIf=\"item.statusColor\" class=\"cqa-w-3.5 cqa-h-3.5 cqa-rounded-full cqa-flex-shrink-0\" [ngClass]=\"getStatusDotClass(item)\"></span>\n <a\n *ngIf=\"item.link\"\n href=\"javascript:void(0)\"\n class=\"cqa-text-[#2563EB] cqa-text-xs cqa-leading-[12px] cqa-font-normal hover:cqa-underline cqa-cursor-pointer cqa-block cqa-truncate cqa-min-w-0\"\n (click)=\"onMetadataLinkClick(item); $event.preventDefault()\">\n {{ item.value }}\n </a>\n <span *ngIf=\"!item.link\" class=\"cqa-text-xs cqa-leading-[12px] cqa-font-normal cqa-align-middle\" [ngClass]=\"getValueTextClass(item)\">\n {{ item.value }}\n </span>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n\n <!-- Labels (Figma: Labels title, cqa-badge chips with tag icon) -->\n <div *ngIf=\"labels.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2 cqa-text-sm cqa-leading-[19.6px]\">\n <span class=\"cqa-text-[#111827] cqa-text-sm cqa-font-medium cqa-leading-5\">Labels</span>\n <div class=\"cqa-flex cqa-flex-wrap cqa-gap-2\">\n <cqa-badge\n *ngFor=\"let label of labels\"\n [label]=\"label\"\n icon=\"label\"\n variant=\"outline\"\n size=\"small\"\n backgroundColor=\"#ffffff\"\n textColor=\"#475569\"\n borderColor=\"#E2E8F0\"\n iconColor=\"#94A3B8\">\n </cqa-badge>\n </div>\n </div>\n\n <!-- Configuration Section -->\n <div *ngIf=\"configSections.length || configSectionsRow2.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-inline-flex cqa-justify-start cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-w-5 cqa-h-5 cqa-p-1 cqa-flex-shrink-0 cqa-bg-[#3F43EE1A] cqa-rounded-md cqa-inline-flex cqa-justify-center cqa-items-center\">\n <mat-icon class=\"cqa-text-[#1B1FEB] cqa-text-[12px] cqa-w-3 cqa-h-3 cqa-leading-none cqa-block\">settings</mat-icon>\n </div>\n <span class=\"cqa-text-[#374151] cqa-text-sm cqa-font-semibold cqa-leading-[19.6px]\">{{ configTitle }}</span>\n </div>\n </div>\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-grid cqa-grid-cols-1 cqa-gap-2.5\">\n <ng-container *ngFor=\"let section of configSections; trackBy: trackByConfigTitle\">\n <cqa-configuration-card\n [icon]=\"section.icon || 'tune'\"\n [title]=\"section.title\"\n [data]=\"section.items\">\n </cqa-configuration-card>\n </ng-container>\n </div>\n <div *ngIf=\"configSectionsRow2.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <cqa-configuration-card\n *ngFor=\"let section of configSectionsRow2; trackBy: trackByConfigTitle\"\n [icon]=\"section.icon || 'tune'\"\n [title]=\"section.title\"\n [data]=\"section.items\">\n </cqa-configuration-card>\n </div>\n </div>\n </div>\n </div>\n</div>\n", components: [{ type: TestCaseDetailsEditComponent, selector: "cqa-test-case-details-edit", inputs: ["descriptionTitle", "descriptionContent", "enableMarkdown", "metadataItems", "labels", "configTitle", "configSections", "configSectionsRow2", "prerequisiteCaseOptions", "platform", "isStepGroup", "selectConfigOverrides"], outputs: ["save", "cancel", "selectSearch", "selectLoadMore", "selectOpened", "selectionChange", "labelAdded"] }, { type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: ConfigurationCardComponent, selector: "cqa-configuration-card", inputs: ["icon", "title", "data"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
34495
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestCaseDetailsComponent, decorators: [{
34496
- type: Component,
34497
- args: [{ selector: 'cqa-test-case-details', changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Edit mode: show edit form (Figma design) -->\n<cqa-test-case-details-edit\n *ngIf=\"isEditing\"\n [descriptionTitle]=\"descriptionTitle\"\n [descriptionContent]=\"descriptionContent\"\n [enableMarkdown]=\"enableMarkdown\"\n [metadataItems]=\"metadataItems\"\n [labels]=\"labels\"\n [configTitle]=\"configTitle\"\n [configSections]=\"configSections\"\n [configSectionsRow2]=\"configSectionsRow2\"\n [platform]=\"platform\"\n [isStepGroup]=\"isStepGroup\"\n [selectConfigOverrides]=\"selectConfigOverrides\"\n (save)=\"onSaveChanges($event)\"\n (cancel)=\"onCancelEdit()\"\n (selectSearch)=\"selectSearch.emit($event)\"\n (selectLoadMore)=\"selectLoadMore.emit($event)\"\n (selectOpened)=\"selectOpened.emit($event)\"\n (selectionChange)=\"selectionChange.emit($event)\"\n (labelAdded)=\"labelAdded.emit($event)\">\n</cqa-test-case-details-edit>\n\n<!-- View mode: read-only details -->\n<div *ngIf=\"!isEditing\" class=\"cqa-self-stretch cqa-py-4 cqa-px-0 cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <!-- Description Section -->\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-inline-flex cqa-justify-between cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-w-5 cqa-h-5 cqa-p-1 cqa-flex-shrink-0 cqa-bg-[#3F43EE1A] cqa-rounded-md cqa-inline-flex cqa-justify-center cqa-items-center\">\n <mat-icon class=\"cqa-text-[#1B1FEB] cqa-text-[12px] cqa-w-3 cqa-h-3 cqa-leading-none cqa-block\">description</mat-icon>\n </div>\n <span class=\"cqa-text-[#374151] cqa-text-sm cqa-font-semibold cqa-leading-[19.6px]\">{{ descriptionTitle }}</span>\n </div>\n <button\n *ngIf=\"showEditButton\"\n type=\"button\"\n class=\"cqa-flex cqa-justify-end cqa-items-center cqa-gap-2 cqa-text-[#A3A3A3] cqa-text-xs cqa-font-semibold hover:cqa-text-[#737373] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onEditClick()\">\n <mat-icon class=\"cqa-text-[14px] cqa-w-4 cqa-h-4\">edit</mat-icon>\n Edit\n </button>\n </div>\n <div *ngIf=\"descriptionContent\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start\">\n <div *ngIf=\"enableMarkdown\" class=\"cqa-self-stretch cqa-text-[#111827] cqa-text-sm cqa-leading-[19.6px] cqa-font-normal cqa-prose cqa-prose-sm cqa-max-w-none\" [innerHTML]=\"descriptionContent\"></div>\n <div *ngIf=\"!enableMarkdown\" class=\"cqa-self-stretch cqa-text-[#111827] cqa-text-sm cqa-leading-[19.6px] cqa-font-normal\">{{ descriptionContent }}</div>\n </div>\n </div>\n\n <!-- Metadata Section -->\n <div *ngIf=\"filteredMetadataItems.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-grid cqa-grid-cols-2 cqa-gap-x-0 cqa-gap-y-4\">\n <ng-container *ngFor=\"let item of filteredMetadataItems; trackBy: trackByMetadataLabel\">\n <div class=\"cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-0.5\">\n <div class=\"cqa-text-[#6B7280] cqa-text-xs cqa-leading-[15px] cqa-font-medium\">{{ item.label }}</div>\n <div\n class=\"cqa-flex cqa-justify-start cqa-items-center cqa-gap-[5px] cqa-min-w-0 cqa-w-full cqa-text-left cqa-text-[#0A0A0A] cqa-border cqa-border-[#F5F5F5]\">\n <mat-icon *ngIf=\"item.icon && (!item.iconLibrary || item.iconLibrary === 'mat')\" class=\"cqa-text-[#6B7280] cqa-text-sm cqa-w-4 cqa-h-4\">\n {{ item.icon }}\n </mat-icon>\n <span *ngIf=\"item.statusColor\" class=\"cqa-w-3.5 cqa-h-3.5 cqa-rounded-full cqa-flex-shrink-0\" [ngClass]=\"getStatusDotClass(item)\"></span>\n <a\n *ngIf=\"item.link\"\n href=\"javascript:void(0)\"\n class=\"cqa-text-[#2563EB] cqa-text-xs cqa-leading-[12px] cqa-font-normal hover:cqa-underline cqa-cursor-pointer cqa-block cqa-truncate cqa-min-w-0\"\n (click)=\"onMetadataLinkClick(item); $event.preventDefault()\">\n {{ item.value }}\n </a>\n <span *ngIf=\"!item.link\" class=\"cqa-text-xs cqa-leading-[12px] cqa-font-normal cqa-align-middle\" [ngClass]=\"getValueTextClass(item)\">\n {{ item.value }}\n </span>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n\n <!-- Labels (Figma: Labels title, cqa-badge chips with tag icon) -->\n <div *ngIf=\"labels.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2 cqa-text-sm cqa-leading-[19.6px]\">\n <span class=\"cqa-text-[#111827] cqa-text-sm cqa-font-medium cqa-leading-5\">Labels</span>\n <div class=\"cqa-flex cqa-flex-wrap cqa-gap-2\">\n <cqa-badge\n *ngFor=\"let label of labels\"\n [label]=\"label\"\n icon=\"label\"\n variant=\"outline\"\n size=\"small\"\n backgroundColor=\"#ffffff\"\n textColor=\"#475569\"\n borderColor=\"#E2E8F0\"\n iconColor=\"#94A3B8\">\n </cqa-badge>\n </div>\n </div>\n\n <!-- Configuration Section -->\n <div *ngIf=\"configSections.length || configSectionsRow2.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-inline-flex cqa-justify-start cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-w-5 cqa-h-5 cqa-p-1 cqa-flex-shrink-0 cqa-bg-[#3F43EE1A] cqa-rounded-md cqa-inline-flex cqa-justify-center cqa-items-center\">\n <mat-icon class=\"cqa-text-[#1B1FEB] cqa-text-[12px] cqa-w-3 cqa-h-3 cqa-leading-none cqa-block\">settings</mat-icon>\n </div>\n <span class=\"cqa-text-[#374151] cqa-text-sm cqa-font-semibold cqa-leading-[19.6px]\">{{ configTitle }}</span>\n </div>\n </div>\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-grid cqa-grid-cols-1 cqa-gap-2.5\">\n <ng-container *ngFor=\"let section of configSections; trackBy: trackByConfigTitle\">\n <cqa-configuration-card\n [icon]=\"section.icon || 'tune'\"\n [title]=\"section.title\"\n [data]=\"section.items\">\n </cqa-configuration-card>\n </ng-container>\n </div>\n <div *ngIf=\"configSectionsRow2.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <cqa-configuration-card\n *ngFor=\"let section of configSectionsRow2; trackBy: trackByConfigTitle\"\n [icon]=\"section.icon || 'tune'\"\n [title]=\"section.title\"\n [data]=\"section.items\">\n </cqa-configuration-card>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [] }]
34498
- }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { editing: [{
34499
- type: Input
34500
- }], startInEditMode: [{
34501
- type: Input
34502
- }], descriptionTitle: [{
34503
- type: Input
34504
- }], descriptionContent: [{
34505
- type: Input
34506
- }], enableMarkdown: [{
34507
- type: Input
34508
- }], showEditButton: [{
34509
- type: Input
34510
- }], metadataItems: [{
34511
- type: Input
34512
- }], labels: [{
34513
- type: Input
34514
- }], configTitle: [{
34515
- type: Input
34516
- }], configSections: [{
34517
- type: Input
34518
- }], configSectionsRow2: [{
34519
- type: Input
34520
- }], platform: [{
34521
- type: Input
34522
- }], isStepGroup: [{
34523
- type: Input
34524
- }], selectConfigOverrides: [{
34525
- type: Input
34526
- }], editDescription: [{
34527
- type: Output
34528
- }], cancel: [{
34529
- type: Output
34530
- }], saveChanges: [{
34531
- type: Output
34532
- }], metadataLinkClick: [{
34533
- type: Output
34534
- }], selectSearch: [{
34535
- type: Output
34536
- }], selectLoadMore: [{
34537
- type: Output
34538
- }], selectOpened: [{
34539
- type: Output
34540
- }], selectionChange: [{
34541
- type: Output
34542
- }], labelAdded: [{
34543
- type: Output
34544
- }] } });
34545
-
34546
- class DetailSidePanelComponent {
34547
- constructor(cdr) {
34548
- this.cdr = cdr;
34549
- /** Tabs - each tab has a side panel icon button; tabs and buttons are 1:1 */
34550
- this.tabs = [
34551
- { label: 'Test Case', value: 'test-case', icon: 'description' },
34552
- { label: 'Data Library', value: 'data-library', icon: 'folder' },
34553
- { label: 'Variables', value: 'variables', icon: 'code' },
34554
- ];
34555
- /** Currently active tab value */
34556
- this.activeTab = 'test-case';
34557
- /** Description section title */
34558
- this.descriptionTitle = 'Description';
34559
- /** Description text content */
34560
- this.descriptionContent = '';
34561
- /** When true, description uses rich text editor and renders as HTML. Host app must load Trix. */
34562
- this.enableMarkdown = false;
34563
- /** Whether to show the Edit button in the Description header */
34564
- this.showEditButton = true;
34565
- /** Metadata items (Created on, Status, Priority, etc.) */
34566
- this.metadataItems = [];
34567
- /** Labels/tags (e.g. Automation, API, SDK, UI/UX) */
34568
- this.labels = [];
34569
- /** Configuration sections - full width (e.g. Execution, AI Configuration) */
34570
- this.configSections = [];
34571
- /** Optional config sections displayed in a 2-column row (e.g. Waits & Retries, Device) */
34572
- this.configSectionsRow2 = [];
34573
- /** Platform: 'web' or 'mobile'. Defaults to 'web'. Used for Device Settings. */
34574
- this.platform = 'web';
34575
- /** When true, hides Priority, Type, Test Data Set, and Prerequisite Case (step groups don't have these). Defaults to false. */
34576
- this.isStepGroup = false;
34577
- /** Configuration section title */
34578
- this.configTitle = 'Configuration';
34579
- /** Whether to show the close button in the side menu */
34580
- this.showCloseButton = false;
34581
- /** When true, test case details start in edit mode (useful for Storybook). */
34582
- this.startInEditMode = false;
34583
- /** Override config per select for API-driven options, server search, load more. */
34584
- this.selectConfigOverrides = {};
34585
- /** Whether the panel is expanded (affects expand button icon and panel width) */
34586
- this.expanded = true;
34587
- /** Panel width when expanded (e.g. '480px', '25%') */
34588
- this.expandedWidth = '380px';
34589
- /** Panel width when collapsed (e.g. '56px' - fits icon bar + back button) */
34590
- this.collapsedWidth = '56px';
34591
- this.hostOverflow = 'hidden';
34592
- /** Tooltip for expand button when panel is collapsed */
34593
- this.expandTooltip = 'Expand';
34594
- /** Tooltip for expand button when panel is expanded (collapse) */
34595
- this.collapseTooltip = 'Collapse';
34596
- /** Tooltip for close button */
34597
- this.closeTooltip = 'Close';
34598
- this.back = new EventEmitter();
34599
- this.tabChange = new EventEmitter();
34600
- this.editDescription = new EventEmitter();
34601
- this.cancel = new EventEmitter();
34602
- this.saveChanges = new EventEmitter();
34603
- this.metadataLinkClick = new EventEmitter();
34604
- this.selectSearch = new EventEmitter();
34605
- this.selectLoadMore = new EventEmitter();
34606
- this.selectOpened = new EventEmitter();
34607
- this.selectionChange = new EventEmitter();
34608
- this.labelAdded = new EventEmitter();
34609
- this.expandToggle = new EventEmitter();
34610
- this.close = new EventEmitter();
34611
- }
34612
- get hostWidth() {
34613
- return this.expanded ? this.expandedWidth : this.collapsedWidth;
34614
- }
34615
- get hostMinWidth() {
34616
- return this.expanded ? this.expandedWidth : this.collapsedWidth;
34617
- }
34618
- get hostMaxWidth() {
34619
- return this.expanded ? this.expandedWidth : this.collapsedWidth;
34620
- }
34621
- trackByTabValue(_i, tab) {
34622
- return tab.value;
34623
- }
34624
- trackByMetadataLabel(_i, item) {
34625
- return item.label;
34626
- }
34627
- trackByConfigTitle(_i, section) {
34628
- return section.title;
34629
- }
34630
- onBack() {
34631
- this.back.emit();
34632
- }
34633
- onTabClick(tab) {
34634
- if (!this.expanded) {
34635
- this.expandToggle.emit();
34863
+ if (this.startInEditMode) {
34864
+ this._editing = true;
34636
34865
  }
34637
- if (tab.value !== this.activeTab) {
34638
- this.tabChange.emit(tab.value);
34866
+ }
34867
+ /** Filtered metadata items - excludes Priority and Type for step groups */
34868
+ get filteredMetadataItems() {
34869
+ if (!this.isStepGroup) {
34870
+ return this.metadataItems;
34639
34871
  }
34872
+ return this.metadataItems.filter((item) => !this.stepGroupExcludedMetadataLabels.includes(item.label?.toLowerCase() ?? ''));
34640
34873
  }
34641
- onEditDescription() {
34874
+ onEditClick() {
34875
+ if (this.editing === undefined) {
34876
+ this._editing = true;
34877
+ this.cdr.detectChanges();
34878
+ }
34642
34879
  this.editDescription.emit();
34643
34880
  }
34644
34881
  onSaveChanges(data) {
34882
+ if (this.editing === undefined) {
34883
+ this._editing = false;
34884
+ }
34885
+ this.cdr.detectChanges();
34645
34886
  this.saveChanges.emit(data);
34646
34887
  }
34647
- onCancel() {
34888
+ onCancelEdit() {
34648
34889
  this.cancel.emit();
34890
+ if (this.editing === undefined) {
34891
+ this._editing = false;
34892
+ }
34893
+ this.cdr.detectChanges();
34649
34894
  }
34650
- onExpandToggle() {
34651
- this.expandToggle.emit();
34895
+ trackByConfigTitle(_i, section) {
34896
+ return section.title;
34652
34897
  }
34653
- onClose() {
34654
- this.close.emit();
34898
+ trackByMetadataLabel(_i, item) {
34899
+ return item.label;
34655
34900
  }
34656
34901
  onMetadataLinkClick(item) {
34657
34902
  if (item.link) {
@@ -34673,18 +34918,22 @@ class DetailSidePanelComponent {
34673
34918
  return 'cqa-bg-[#94A3B8]';
34674
34919
  }
34675
34920
  }
34921
+ /** Text color for metadata value (e.g. red for critical priority) */
34922
+ getValueTextClass(item) {
34923
+ if (item.statusColor === 'red') {
34924
+ return 'cqa-text-[#DC2626]';
34925
+ }
34926
+ return 'cqa-text-[#111827]';
34927
+ }
34676
34928
  }
34677
- DetailSidePanelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailSidePanelComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
34678
- DetailSidePanelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DetailSidePanelComponent, selector: "cqa-detail-side-panel", inputs: { tabs: "tabs", activeTab: "activeTab", descriptionTitle: "descriptionTitle", descriptionContent: "descriptionContent", enableMarkdown: "enableMarkdown", showEditButton: "showEditButton", metadataItems: "metadataItems", labels: "labels", configSections: "configSections", configSectionsRow2: "configSectionsRow2", platform: "platform", isStepGroup: "isStepGroup", configTitle: "configTitle", showCloseButton: "showCloseButton", startInEditMode: "startInEditMode", editing: "editing", selectConfigOverrides: "selectConfigOverrides", expanded: "expanded", expandedWidth: "expandedWidth", collapsedWidth: "collapsedWidth", expandTooltip: "expandTooltip", collapseTooltip: "collapseTooltip", closeTooltip: "closeTooltip" }, outputs: { back: "back", tabChange: "tabChange", editDescription: "editDescription", cancel: "cancel", saveChanges: "saveChanges", metadataLinkClick: "metadataLinkClick", selectSearch: "selectSearch", selectLoadMore: "selectLoadMore", selectOpened: "selectOpened", selectionChange: "selectionChange", labelAdded: "labelAdded", expandToggle: "expandToggle", close: "close" }, host: { properties: { "style.width": "this.hostWidth", "style.min-width": "this.hostMinWidth", "style.max-width": "this.hostMaxWidth", "style.overflow": "this.hostOverflow" }, styleAttribute: "transition: width 0.3s ease-in-out", classAttribute: "cqa-ui-root cqa-flex cqa-flex-col cqa-h-full cqa-flex-shrink-0 cqa-flex-grow-0 cqa-bg-white cqa-shadow-[-4px_0_6px_-1px_rgba(0,0,0,0.05)]" }, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-min-w-0 cqa-bg-white\">\n <!-- Main content: Side menu + Scrollable content -->\n <div\n class=\"cqa-grid cqa-flex-1 cqa-min-h-0 cqa-min-w-0 cqa-overflow-hidden\"\n [style.grid-template-columns]=\"expanded ? 'auto 1fr' : 'auto 0fr'\"\n style=\"transition: grid-template-columns 0.3s ease-in-out\">\n <!-- Left vertical icon menu -->\n <div\n class=\"cqa-flex cqa-flex-col cqa-items-center cqa-gap-2 cqa-py-4 cqa-px-2 cqa-border-r cqa-border-[#F5F5F5] cqa-flex-shrink-0 cqa-text-[#0A0A0A]\"\n style=\"box-shadow: 1px 4px 12px 1px rgba(0, 0, 0, 0.05);\">\n <!-- Expand / Collapse button (always visible) -->\n <button\n type=\"button\"\n [matTooltip]=\"expanded ? collapseTooltip : expandTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onExpandToggle()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ expanded ? 'chevron_left' : 'chevron_right' }}</mat-icon>\n </button>\n <!-- Close button -->\n <button\n *ngIf=\"showCloseButton\"\n type=\"button\"\n [matTooltip]=\"closeTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onClose()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">close</mat-icon>\n </button>\n <!-- Tab buttons (1:1 with tabs) -->\n <button\n *ngFor=\"let tab of tabs; trackBy: trackByTabValue\"\n type=\"button\"\n [matTooltip]=\"tab.label\"\n [class.cqa-bg-[#3F43EE]]=\"activeTab === tab.value\"\n [class.cqa-text-white]=\"activeTab === tab.value\"\n [class.cqa-text-[#64748B]]=\"activeTab !== tab.value\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onTabClick(tab)\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ tab.icon || 'circle' }}</mat-icon>\n </button>\n </div>\n\n <!-- Scrollable content area (collapses with animation when expanded is false) -->\n <div class=\"cqa-flex cqa-flex-col cqa-min-h-0 cqa-min-w-0 cqa-overflow-hidden cqa-w-full cqa-h-full\">\n <div class=\"detail-side-panel-scroll cqa-flex-1 cqa-min-h-0 cqa-min-w-0 cqa-overflow-y-auto cqa-overflow-x-hidden cqa-p-4 cqa-space-y-4\" style=\"overflow-y: auto; overflow-x: hidden; min-height: 0; -webkit-overflow-scrolling: touch;\">\n <!-- Tabs: equally distributed (Figma: purple active, gray inactive) -->\n <div class=\"cqa-flex cqa-gap-[3.5px] cqa-p-[3.5px] cqa-bg-[#F1F5F9] cqa-rounded-lg cqa-w-full\" role=\"tablist\">\n <button\n *ngFor=\"let tab of tabs; trackBy: trackByTabValue\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === tab.value\"\n [class.cqa-bg-[#3F43EE]]=\"activeTab === tab.value\"\n [class.cqa-text-white]=\"activeTab === tab.value\"\n [class.cqa-text-[#64748B]]=\"activeTab !== tab.value\"\n class=\"cqa-flex-1 cqa-flex cqa-justify-center cqa-items-center cqa-py-2 cqa-rounded-lg cqa-text-xs cqa-font-medium cqa-transition-colors hover:cqa-opacity-90 focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onTabClick(tab)\">\n {{ tab.label }}\n </button>\n </div>\n\n <!-- Test Case tab: use cqa-test-case-details (Figma design) -->\n <cqa-test-case-details\n *ngIf=\"activeTab === 'test-case'\"\n [descriptionTitle]=\"descriptionTitle\"\n [descriptionContent]=\"descriptionContent\"\n [enableMarkdown]=\"enableMarkdown\"\n [showEditButton]=\"showEditButton\"\n [startInEditMode]=\"startInEditMode\"\n [editing]=\"editing\"\n [selectConfigOverrides]=\"selectConfigOverrides\"\n [metadataItems]=\"metadataItems\"\n [labels]=\"labels\"\n [configTitle]=\"configTitle\"\n [configSections]=\"configSections\"\n [configSectionsRow2]=\"configSectionsRow2\"\n [platform]=\"platform\"\n [isStepGroup]=\"isStepGroup\"\n (editDescription)=\"onEditDescription()\"\n (cancel)=\"onCancel()\"\n (saveChanges)=\"onSaveChanges($event)\"\n (metadataLinkClick)=\"onMetadataLinkClick($event)\"\n (selectSearch)=\"selectSearch.emit($event)\"\n (selectLoadMore)=\"selectLoadMore.emit($event)\"\n (selectOpened)=\"selectOpened.emit($event)\"\n (selectionChange)=\"selectionChange.emit($event)\"\n (labelAdded)=\"labelAdded.emit($event)\">\n </cqa-test-case-details>\n\n <!-- Placeholder for other tabs (Data Library, Variables) -->\n <div *ngIf=\"activeTab !== 'test-case'\" class=\"cqa-p-4 cqa-text-[#64748B] cqa-text-sm\">\n {{ activeTab === 'data-library' ? 'Data Library content' : 'Variables content' }} \u2013 coming soon\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".detail-side-panel-scroll{overflow-y:auto!important;overflow-x:hidden!important;min-height:0!important;-webkit-overflow-scrolling:touch}\n"], components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: TestCaseDetailsComponent, selector: "cqa-test-case-details", inputs: ["editing", "startInEditMode", "descriptionTitle", "descriptionContent", "enableMarkdown", "showEditButton", "metadataItems", "labels", "configTitle", "configSections", "configSectionsRow2", "platform", "isStepGroup", "selectConfigOverrides"], outputs: ["editDescription", "cancel", "saveChanges", "metadataLinkClick", "selectSearch", "selectLoadMore", "selectOpened", "selectionChange", "labelAdded"] }], directives: [{ type: i5.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
34679
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailSidePanelComponent, decorators: [{
34929
+ TestCaseDetailsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestCaseDetailsComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
34930
+ TestCaseDetailsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TestCaseDetailsComponent, selector: "cqa-test-case-details", inputs: { editing: "editing", startInEditMode: "startInEditMode", descriptionTitle: "descriptionTitle", descriptionContent: "descriptionContent", enableMarkdown: "enableMarkdown", showEditButton: "showEditButton", metadataItems: "metadataItems", labels: "labels", configTitle: "configTitle", configSections: "configSections", configSectionsRow2: "configSectionsRow2", platform: "platform", isStepGroup: "isStepGroup", selectConfigOverrides: "selectConfigOverrides" }, outputs: { editDescription: "editDescription", cancel: "cancel", saveChanges: "saveChanges", metadataLinkClick: "metadataLinkClick", selectSearch: "selectSearch", selectLoadMore: "selectLoadMore", selectOpened: "selectOpened", selectionChange: "selectionChange", labelAdded: "labelAdded" }, ngImport: i0, template: "<!-- Edit mode: show edit form (Figma design) -->\n<cqa-test-case-details-edit\n *ngIf=\"isEditing\"\n [descriptionTitle]=\"descriptionTitle\"\n [descriptionContent]=\"descriptionContent\"\n [enableMarkdown]=\"enableMarkdown\"\n [metadataItems]=\"metadataItems\"\n [labels]=\"labels\"\n [configTitle]=\"configTitle\"\n [configSections]=\"configSections\"\n [configSectionsRow2]=\"configSectionsRow2\"\n [platform]=\"platform\"\n [isStepGroup]=\"isStepGroup\"\n [selectConfigOverrides]=\"selectConfigOverrides\"\n (save)=\"onSaveChanges($event)\"\n (cancel)=\"onCancelEdit()\"\n (selectSearch)=\"selectSearch.emit($event)\"\n (selectLoadMore)=\"selectLoadMore.emit($event)\"\n (selectOpened)=\"selectOpened.emit($event)\"\n (selectionChange)=\"selectionChange.emit($event)\"\n (labelAdded)=\"labelAdded.emit($event)\">\n</cqa-test-case-details-edit>\n\n<!-- View mode: read-only details -->\n<div *ngIf=\"!isEditing\" class=\"cqa-self-stretch cqa-py-4 cqa-px-0 cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <!-- Description Section -->\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-inline-flex cqa-justify-between cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-w-5 cqa-h-5 cqa-p-1 cqa-flex-shrink-0 cqa-bg-[#3F43EE1A] cqa-rounded-md cqa-inline-flex cqa-justify-center cqa-items-center\">\n <mat-icon class=\"cqa-text-[#1B1FEB] cqa-text-[12px] cqa-w-3 cqa-h-3 cqa-leading-none cqa-block\">description</mat-icon>\n </div>\n <span class=\"cqa-text-[#374151] cqa-text-sm cqa-font-semibold cqa-leading-[19.6px]\">{{ descriptionTitle }}</span>\n </div>\n <button\n *ngIf=\"showEditButton\"\n type=\"button\"\n class=\"cqa-flex cqa-justify-end cqa-items-center cqa-gap-2 cqa-text-[#A3A3A3] cqa-text-xs cqa-font-semibold hover:cqa-text-[#737373] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onEditClick()\">\n <mat-icon class=\"cqa-text-[14px] cqa-w-4 cqa-h-4\">edit</mat-icon>\n Edit\n </button>\n </div>\n <div *ngIf=\"descriptionContent\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start\">\n <div *ngIf=\"enableMarkdown\" class=\"cqa-self-stretch cqa-text-[#111827] cqa-text-sm cqa-leading-[19.6px] cqa-font-normal cqa-prose cqa-prose-sm cqa-max-w-none\" [innerHTML]=\"descriptionContent\"></div>\n <div *ngIf=\"!enableMarkdown\" class=\"cqa-self-stretch cqa-text-[#111827] cqa-text-sm cqa-leading-[19.6px] cqa-font-normal\">{{ descriptionContent }}</div>\n </div>\n </div>\n\n <!-- Metadata Section -->\n <div *ngIf=\"filteredMetadataItems.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-grid cqa-grid-cols-2 cqa-gap-x-0 cqa-gap-y-4\">\n <ng-container *ngFor=\"let item of filteredMetadataItems; trackBy: trackByMetadataLabel\">\n <div class=\"cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-0.5\">\n <div class=\"cqa-text-[#6B7280] cqa-text-xs cqa-leading-[15px] cqa-font-medium\">{{ item.label }}</div>\n <div\n class=\"cqa-flex cqa-justify-start cqa-items-center cqa-gap-[5px] cqa-min-w-0 cqa-w-full cqa-text-left cqa-text-[#0A0A0A] cqa-border cqa-border-[#F5F5F5]\">\n <mat-icon *ngIf=\"item.icon && (!item.iconLibrary || item.iconLibrary === 'mat')\" class=\"cqa-text-[#6B7280] cqa-text-sm cqa-w-4 cqa-h-4\">\n {{ item.icon }}\n </mat-icon>\n <span *ngIf=\"item.statusColor\" class=\"cqa-w-3.5 cqa-h-3.5 cqa-rounded-full cqa-flex-shrink-0\" [ngClass]=\"getStatusDotClass(item)\"></span>\n <a\n *ngIf=\"item.link\"\n href=\"javascript:void(0)\"\n class=\"cqa-text-[#2563EB] cqa-text-xs cqa-leading-[12px] cqa-font-normal hover:cqa-underline cqa-cursor-pointer cqa-block cqa-truncate cqa-min-w-0\"\n (click)=\"onMetadataLinkClick(item); $event.preventDefault()\">\n {{ item.value }}\n </a>\n <span *ngIf=\"!item.link\" class=\"cqa-text-xs cqa-leading-[12px] cqa-font-normal cqa-align-middle\" [ngClass]=\"getValueTextClass(item)\">\n {{ item.value }}\n </span>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n\n <!-- Labels (Figma: Labels title, cqa-badge chips with tag icon) -->\n <div *ngIf=\"labels.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2 cqa-text-sm cqa-leading-[19.6px]\">\n <span class=\"cqa-text-[#111827] cqa-text-sm cqa-font-medium cqa-leading-5\">Labels</span>\n <div class=\"cqa-flex cqa-flex-wrap cqa-gap-2\">\n <cqa-badge\n *ngFor=\"let label of labels\"\n [label]=\"label\"\n icon=\"label\"\n variant=\"outline\"\n size=\"small\"\n backgroundColor=\"#ffffff\"\n textColor=\"#475569\"\n borderColor=\"#E2E8F0\"\n iconColor=\"#94A3B8\">\n </cqa-badge>\n </div>\n </div>\n\n <!-- Configuration Section -->\n <div *ngIf=\"configSections.length || configSectionsRow2.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-inline-flex cqa-justify-start cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-w-5 cqa-h-5 cqa-p-1 cqa-flex-shrink-0 cqa-bg-[#3F43EE1A] cqa-rounded-md cqa-inline-flex cqa-justify-center cqa-items-center\">\n <mat-icon class=\"cqa-text-[#1B1FEB] cqa-text-[12px] cqa-w-3 cqa-h-3 cqa-leading-none cqa-block\">settings</mat-icon>\n </div>\n <span class=\"cqa-text-[#374151] cqa-text-sm cqa-font-semibold cqa-leading-[19.6px]\">{{ configTitle }}</span>\n </div>\n </div>\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-grid cqa-grid-cols-1 cqa-gap-2.5\">\n <ng-container *ngFor=\"let section of configSections; trackBy: trackByConfigTitle\">\n <cqa-configuration-card\n [icon]=\"section.icon || 'tune'\"\n [title]=\"section.title\"\n [data]=\"section.items\">\n </cqa-configuration-card>\n </ng-container>\n </div>\n <div *ngIf=\"configSectionsRow2.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <cqa-configuration-card\n *ngFor=\"let section of configSectionsRow2; trackBy: trackByConfigTitle\"\n [icon]=\"section.icon || 'tune'\"\n [title]=\"section.title\"\n [data]=\"section.items\">\n </cqa-configuration-card>\n </div>\n </div>\n </div>\n </div>\n</div>\n", components: [{ type: TestCaseDetailsEditComponent, selector: "cqa-test-case-details-edit", inputs: ["descriptionTitle", "descriptionContent", "enableMarkdown", "metadataItems", "labels", "configTitle", "configSections", "configSectionsRow2", "prerequisiteCaseOptions", "platform", "isStepGroup", "selectConfigOverrides"], outputs: ["save", "cancel", "selectSearch", "selectLoadMore", "selectOpened", "selectionChange", "labelAdded"] }, { type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: ConfigurationCardComponent, selector: "cqa-configuration-card", inputs: ["icon", "title", "data"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
34931
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestCaseDetailsComponent, decorators: [{
34680
34932
  type: Component,
34681
- args: [{ selector: 'cqa-detail-side-panel', styles: [DETAIL_SIDE_PANEL_SCROLL_STYLES], changeDetection: ChangeDetectionStrategy.OnPush, host: {
34682
- class: 'cqa-ui-root cqa-flex cqa-flex-col cqa-h-full cqa-flex-shrink-0 cqa-flex-grow-0 cqa-bg-white cqa-shadow-[-4px_0_6px_-1px_rgba(0,0,0,0.05)]',
34683
- style: 'transition: width 0.3s ease-in-out',
34684
- }, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-min-w-0 cqa-bg-white\">\n <!-- Main content: Side menu + Scrollable content -->\n <div\n class=\"cqa-grid cqa-flex-1 cqa-min-h-0 cqa-min-w-0 cqa-overflow-hidden\"\n [style.grid-template-columns]=\"expanded ? 'auto 1fr' : 'auto 0fr'\"\n style=\"transition: grid-template-columns 0.3s ease-in-out\">\n <!-- Left vertical icon menu -->\n <div\n class=\"cqa-flex cqa-flex-col cqa-items-center cqa-gap-2 cqa-py-4 cqa-px-2 cqa-border-r cqa-border-[#F5F5F5] cqa-flex-shrink-0 cqa-text-[#0A0A0A]\"\n style=\"box-shadow: 1px 4px 12px 1px rgba(0, 0, 0, 0.05);\">\n <!-- Expand / Collapse button (always visible) -->\n <button\n type=\"button\"\n [matTooltip]=\"expanded ? collapseTooltip : expandTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onExpandToggle()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ expanded ? 'chevron_left' : 'chevron_right' }}</mat-icon>\n </button>\n <!-- Close button -->\n <button\n *ngIf=\"showCloseButton\"\n type=\"button\"\n [matTooltip]=\"closeTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onClose()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">close</mat-icon>\n </button>\n <!-- Tab buttons (1:1 with tabs) -->\n <button\n *ngFor=\"let tab of tabs; trackBy: trackByTabValue\"\n type=\"button\"\n [matTooltip]=\"tab.label\"\n [class.cqa-bg-[#3F43EE]]=\"activeTab === tab.value\"\n [class.cqa-text-white]=\"activeTab === tab.value\"\n [class.cqa-text-[#64748B]]=\"activeTab !== tab.value\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onTabClick(tab)\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ tab.icon || 'circle' }}</mat-icon>\n </button>\n </div>\n\n <!-- Scrollable content area (collapses with animation when expanded is false) -->\n <div class=\"cqa-flex cqa-flex-col cqa-min-h-0 cqa-min-w-0 cqa-overflow-hidden cqa-w-full cqa-h-full\">\n <div class=\"detail-side-panel-scroll cqa-flex-1 cqa-min-h-0 cqa-min-w-0 cqa-overflow-y-auto cqa-overflow-x-hidden cqa-p-4 cqa-space-y-4\" style=\"overflow-y: auto; overflow-x: hidden; min-height: 0; -webkit-overflow-scrolling: touch;\">\n <!-- Tabs: equally distributed (Figma: purple active, gray inactive) -->\n <div class=\"cqa-flex cqa-gap-[3.5px] cqa-p-[3.5px] cqa-bg-[#F1F5F9] cqa-rounded-lg cqa-w-full\" role=\"tablist\">\n <button\n *ngFor=\"let tab of tabs; trackBy: trackByTabValue\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === tab.value\"\n [class.cqa-bg-[#3F43EE]]=\"activeTab === tab.value\"\n [class.cqa-text-white]=\"activeTab === tab.value\"\n [class.cqa-text-[#64748B]]=\"activeTab !== tab.value\"\n class=\"cqa-flex-1 cqa-flex cqa-justify-center cqa-items-center cqa-py-2 cqa-rounded-lg cqa-text-xs cqa-font-medium cqa-transition-colors hover:cqa-opacity-90 focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onTabClick(tab)\">\n {{ tab.label }}\n </button>\n </div>\n\n <!-- Test Case tab: use cqa-test-case-details (Figma design) -->\n <cqa-test-case-details\n *ngIf=\"activeTab === 'test-case'\"\n [descriptionTitle]=\"descriptionTitle\"\n [descriptionContent]=\"descriptionContent\"\n [enableMarkdown]=\"enableMarkdown\"\n [showEditButton]=\"showEditButton\"\n [startInEditMode]=\"startInEditMode\"\n [editing]=\"editing\"\n [selectConfigOverrides]=\"selectConfigOverrides\"\n [metadataItems]=\"metadataItems\"\n [labels]=\"labels\"\n [configTitle]=\"configTitle\"\n [configSections]=\"configSections\"\n [configSectionsRow2]=\"configSectionsRow2\"\n [platform]=\"platform\"\n [isStepGroup]=\"isStepGroup\"\n (editDescription)=\"onEditDescription()\"\n (cancel)=\"onCancel()\"\n (saveChanges)=\"onSaveChanges($event)\"\n (metadataLinkClick)=\"onMetadataLinkClick($event)\"\n (selectSearch)=\"selectSearch.emit($event)\"\n (selectLoadMore)=\"selectLoadMore.emit($event)\"\n (selectOpened)=\"selectOpened.emit($event)\"\n (selectionChange)=\"selectionChange.emit($event)\"\n (labelAdded)=\"labelAdded.emit($event)\">\n </cqa-test-case-details>\n\n <!-- Placeholder for other tabs (Data Library, Variables) -->\n <div *ngIf=\"activeTab !== 'test-case'\" class=\"cqa-p-4 cqa-text-[#64748B] cqa-text-sm\">\n {{ activeTab === 'data-library' ? 'Data Library content' : 'Variables content' }} \u2013 coming soon\n </div>\n </div>\n </div>\n </div>\n</div>\n" }]
34685
- }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { tabs: [{
34933
+ args: [{ selector: 'cqa-test-case-details', changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Edit mode: show edit form (Figma design) -->\n<cqa-test-case-details-edit\n *ngIf=\"isEditing\"\n [descriptionTitle]=\"descriptionTitle\"\n [descriptionContent]=\"descriptionContent\"\n [enableMarkdown]=\"enableMarkdown\"\n [metadataItems]=\"metadataItems\"\n [labels]=\"labels\"\n [configTitle]=\"configTitle\"\n [configSections]=\"configSections\"\n [configSectionsRow2]=\"configSectionsRow2\"\n [platform]=\"platform\"\n [isStepGroup]=\"isStepGroup\"\n [selectConfigOverrides]=\"selectConfigOverrides\"\n (save)=\"onSaveChanges($event)\"\n (cancel)=\"onCancelEdit()\"\n (selectSearch)=\"selectSearch.emit($event)\"\n (selectLoadMore)=\"selectLoadMore.emit($event)\"\n (selectOpened)=\"selectOpened.emit($event)\"\n (selectionChange)=\"selectionChange.emit($event)\"\n (labelAdded)=\"labelAdded.emit($event)\">\n</cqa-test-case-details-edit>\n\n<!-- View mode: read-only details -->\n<div *ngIf=\"!isEditing\" class=\"cqa-self-stretch cqa-py-4 cqa-px-0 cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <!-- Description Section -->\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-inline-flex cqa-justify-between cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-w-5 cqa-h-5 cqa-p-1 cqa-flex-shrink-0 cqa-bg-[#3F43EE1A] cqa-rounded-md cqa-inline-flex cqa-justify-center cqa-items-center\">\n <mat-icon class=\"cqa-text-[#1B1FEB] cqa-text-[12px] cqa-w-3 cqa-h-3 cqa-leading-none cqa-block\">description</mat-icon>\n </div>\n <span class=\"cqa-text-[#374151] cqa-text-sm cqa-font-semibold cqa-leading-[19.6px]\">{{ descriptionTitle }}</span>\n </div>\n <button\n *ngIf=\"showEditButton\"\n type=\"button\"\n class=\"cqa-flex cqa-justify-end cqa-items-center cqa-gap-2 cqa-text-[#A3A3A3] cqa-text-xs cqa-font-semibold hover:cqa-text-[#737373] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2\"\n (click)=\"onEditClick()\">\n <mat-icon class=\"cqa-text-[14px] cqa-w-4 cqa-h-4\">edit</mat-icon>\n Edit\n </button>\n </div>\n <div *ngIf=\"descriptionContent\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start\">\n <div *ngIf=\"enableMarkdown\" class=\"cqa-self-stretch cqa-text-[#111827] cqa-text-sm cqa-leading-[19.6px] cqa-font-normal cqa-prose cqa-prose-sm cqa-max-w-none\" [innerHTML]=\"descriptionContent\"></div>\n <div *ngIf=\"!enableMarkdown\" class=\"cqa-self-stretch cqa-text-[#111827] cqa-text-sm cqa-leading-[19.6px] cqa-font-normal\">{{ descriptionContent }}</div>\n </div>\n </div>\n\n <!-- Metadata Section -->\n <div *ngIf=\"filteredMetadataItems.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-grid cqa-grid-cols-2 cqa-gap-x-0 cqa-gap-y-4\">\n <ng-container *ngFor=\"let item of filteredMetadataItems; trackBy: trackByMetadataLabel\">\n <div class=\"cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-0.5\">\n <div class=\"cqa-text-[#6B7280] cqa-text-xs cqa-leading-[15px] cqa-font-medium\">{{ item.label }}</div>\n <div\n class=\"cqa-flex cqa-justify-start cqa-items-center cqa-gap-[5px] cqa-min-w-0 cqa-w-full cqa-text-left cqa-text-[#0A0A0A] cqa-border cqa-border-[#F5F5F5]\">\n <mat-icon *ngIf=\"item.icon && (!item.iconLibrary || item.iconLibrary === 'mat')\" class=\"cqa-text-[#6B7280] cqa-text-sm cqa-w-4 cqa-h-4\">\n {{ item.icon }}\n </mat-icon>\n <span *ngIf=\"item.statusColor\" class=\"cqa-w-3.5 cqa-h-3.5 cqa-rounded-full cqa-flex-shrink-0\" [ngClass]=\"getStatusDotClass(item)\"></span>\n <a\n *ngIf=\"item.link\"\n href=\"javascript:void(0)\"\n class=\"cqa-text-[#2563EB] cqa-text-xs cqa-leading-[12px] cqa-font-normal hover:cqa-underline cqa-cursor-pointer cqa-block cqa-truncate cqa-min-w-0\"\n (click)=\"onMetadataLinkClick(item); $event.preventDefault()\">\n {{ item.value }}\n </a>\n <span *ngIf=\"!item.link\" class=\"cqa-text-xs cqa-leading-[12px] cqa-font-normal cqa-align-middle\" [ngClass]=\"getValueTextClass(item)\">\n {{ item.value }}\n </span>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n\n <!-- Labels (Figma: Labels title, cqa-badge chips with tag icon) -->\n <div *ngIf=\"labels.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2 cqa-text-sm cqa-leading-[19.6px]\">\n <span class=\"cqa-text-[#111827] cqa-text-sm cqa-font-medium cqa-leading-5\">Labels</span>\n <div class=\"cqa-flex cqa-flex-wrap cqa-gap-2\">\n <cqa-badge\n *ngFor=\"let label of labels\"\n [label]=\"label\"\n icon=\"label\"\n variant=\"outline\"\n size=\"small\"\n backgroundColor=\"#ffffff\"\n textColor=\"#475569\"\n borderColor=\"#E2E8F0\"\n iconColor=\"#94A3B8\">\n </cqa-badge>\n </div>\n </div>\n\n <!-- Configuration Section -->\n <div *ngIf=\"configSections.length || configSectionsRow2.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-inline-flex cqa-justify-start cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-w-5 cqa-h-5 cqa-p-1 cqa-flex-shrink-0 cqa-bg-[#3F43EE1A] cqa-rounded-md cqa-inline-flex cqa-justify-center cqa-items-center\">\n <mat-icon class=\"cqa-text-[#1B1FEB] cqa-text-[12px] cqa-w-3 cqa-h-3 cqa-leading-none cqa-block\">settings</mat-icon>\n </div>\n <span class=\"cqa-text-[#374151] cqa-text-sm cqa-font-semibold cqa-leading-[19.6px]\">{{ configTitle }}</span>\n </div>\n </div>\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-2.5\">\n <div class=\"cqa-self-stretch cqa-grid cqa-grid-cols-1 cqa-gap-2.5\">\n <ng-container *ngFor=\"let section of configSections; trackBy: trackByConfigTitle\">\n <cqa-configuration-card\n [icon]=\"section.icon || 'tune'\"\n [title]=\"section.title\"\n [data]=\"section.items\">\n </cqa-configuration-card>\n </ng-container>\n </div>\n <div *ngIf=\"configSectionsRow2.length\" class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-gap-4 cqa-text-sm cqa-leading-[19.6px]\">\n <cqa-configuration-card\n *ngFor=\"let section of configSectionsRow2; trackBy: trackByConfigTitle\"\n [icon]=\"section.icon || 'tune'\"\n [title]=\"section.title\"\n [data]=\"section.items\">\n </cqa-configuration-card>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [] }]
34934
+ }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { editing: [{
34686
34935
  type: Input
34687
- }], activeTab: [{
34936
+ }], startInEditMode: [{
34688
34937
  type: Input
34689
34938
  }], descriptionTitle: [{
34690
34939
  type: Input
@@ -34698,6 +34947,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
34698
34947
  type: Input
34699
34948
  }], labels: [{
34700
34949
  type: Input
34950
+ }], configTitle: [{
34951
+ type: Input
34701
34952
  }], configSections: [{
34702
34953
  type: Input
34703
34954
  }], configSectionsRow2: [{
@@ -34706,44 +34957,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
34706
34957
  type: Input
34707
34958
  }], isStepGroup: [{
34708
34959
  type: Input
34709
- }], configTitle: [{
34710
- type: Input
34711
- }], showCloseButton: [{
34712
- type: Input
34713
- }], startInEditMode: [{
34714
- type: Input
34715
- }], editing: [{
34716
- type: Input
34717
34960
  }], selectConfigOverrides: [{
34718
34961
  type: Input
34719
- }], expanded: [{
34720
- type: Input
34721
- }], expandedWidth: [{
34722
- type: Input
34723
- }], collapsedWidth: [{
34724
- type: Input
34725
- }], hostWidth: [{
34726
- type: HostBinding,
34727
- args: ['style.width']
34728
- }], hostMinWidth: [{
34729
- type: HostBinding,
34730
- args: ['style.min-width']
34731
- }], hostMaxWidth: [{
34732
- type: HostBinding,
34733
- args: ['style.max-width']
34734
- }], hostOverflow: [{
34735
- type: HostBinding,
34736
- args: ['style.overflow']
34737
- }], expandTooltip: [{
34738
- type: Input
34739
- }], collapseTooltip: [{
34740
- type: Input
34741
- }], closeTooltip: [{
34742
- type: Input
34743
- }], back: [{
34744
- type: Output
34745
- }], tabChange: [{
34746
- type: Output
34747
34962
  }], editDescription: [{
34748
34963
  type: Output
34749
34964
  }], cancel: [{
@@ -34762,174 +34977,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
34762
34977
  type: Output
34763
34978
  }], labelAdded: [{
34764
34979
  type: Output
34765
- }], expandToggle: [{
34766
- type: Output
34767
- }], close: [{
34768
- type: Output
34769
- }] } });
34770
-
34771
- class DetailDrawerTabContentDirective {
34772
- constructor(templateRef) {
34773
- this.templateRef = templateRef;
34774
- }
34775
- }
34776
- DetailDrawerTabContentDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerTabContentDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
34777
- DetailDrawerTabContentDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.4.0", type: DetailDrawerTabContentDirective, selector: "[cqaTabContent]", ngImport: i0 });
34778
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerTabContentDirective, decorators: [{
34779
- type: Directive,
34780
- args: [{
34781
- selector: '[cqaTabContent]',
34782
- }]
34783
- }], ctorParameters: function () { return [{ type: i0.TemplateRef }]; } });
34784
-
34785
- class DetailDrawerTabComponent {
34786
- constructor() {
34787
- /** Tab label (shown in tooltip on icon button) */
34788
- this.label = '';
34789
- /** Tab value (unique identifier) */
34790
- this.value = '';
34791
- /** Material icon name for the tab button */
34792
- this.icon = 'folder';
34793
- }
34794
- get contentTemplate() {
34795
- return this.contentDirective?.templateRef ?? null;
34796
- }
34797
- }
34798
- DetailDrawerTabComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerTabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
34799
- DetailDrawerTabComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DetailDrawerTabComponent, selector: "cqa-detail-drawer-tab", inputs: { label: "label", value: "value", icon: "icon" }, host: { styleAttribute: "display: contents" }, queries: [{ propertyName: "contentDirective", first: true, predicate: DetailDrawerTabContentDirective, descendants: true }], ngImport: i0, template: '', isInline: true });
34800
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerTabComponent, decorators: [{
34801
- type: Component,
34802
- args: [{
34803
- selector: 'cqa-detail-drawer-tab',
34804
- template: '',
34805
- host: {
34806
- style: 'display: contents',
34807
- },
34808
- }]
34809
- }], propDecorators: { label: [{
34810
- type: Input
34811
- }], value: [{
34812
- type: Input
34813
- }], icon: [{
34814
- type: Input
34815
- }], contentDirective: [{
34816
- type: ContentChild,
34817
- args: [DetailDrawerTabContentDirective]
34818
- }] } });
34819
-
34820
- class DetailDrawerComponent {
34821
- constructor() {
34822
- /** Currently active tab value */
34823
- this.activeTab = '';
34824
- /** Whether to show the close button */
34825
- this.showCloseButton = true;
34826
- /** Whether the drawer is expanded */
34827
- this.expanded = true;
34828
- /** Panel width when expanded */
34829
- this.expandedWidth = '280px';
34830
- /** Maximum width when expanded (e.g. '600px', '30vw'). Default: 30% of viewport */
34831
- this.maxExpandedWidth = '30vw';
34832
- /** Panel width when collapsed */
34833
- this.collapsedWidth = '56px';
34834
- this.expandTooltip = 'Expand';
34835
- this.collapseTooltip = 'Collapse';
34836
- this.closeTooltip = 'Close';
34837
- this.activeTabChange = new EventEmitter();
34838
- this.expandToggle = new EventEmitter();
34839
- this.close = new EventEmitter();
34840
- }
34841
- get hostWidth() {
34842
- return this.expanded ? this.expandedWidth : this.collapsedWidth;
34843
- }
34844
- get hostMinWidth() {
34845
- return this.expanded && this.minExpandedWidth ? this.minExpandedWidth : null;
34846
- }
34847
- get hostMaxWidth() {
34848
- return this.expanded ? this.maxExpandedWidth : null;
34849
- }
34850
- ngAfterContentInit() {
34851
- this.ensureActiveTab();
34852
- }
34853
- ngAfterContentChecked() {
34854
- this.ensureActiveTab();
34855
- }
34856
- ensureActiveTab() {
34857
- const tabs = this.tabComponents?.toArray() ?? [];
34858
- if (tabs.length > 0 && !this.activeTab) {
34859
- this.activeTab = tabs[0].value;
34860
- this.activeTabChange.emit(this.activeTab);
34861
- }
34862
- }
34863
- onTabClick(tab) {
34864
- // If drawer is collapsed, open it (but never close on tab click)
34865
- if (!this.expanded) {
34866
- this.expandToggle.emit();
34867
- }
34868
- // Select the tab
34869
- if (tab.value !== this.activeTab) {
34870
- this.activeTab = tab.value;
34871
- this.activeTabChange.emit(this.activeTab);
34872
- }
34873
- }
34874
- onExpandToggle() {
34875
- this.expandToggle.emit();
34876
- }
34877
- onClose() {
34878
- this.close.emit();
34879
- }
34880
- trackByValue(_i, tab) {
34881
- return tab.value;
34882
- }
34883
- isTabActive(tab) {
34884
- return tab.value === this.activeTab;
34885
- }
34886
- }
34887
- DetailDrawerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
34888
- DetailDrawerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DetailDrawerComponent, selector: "cqa-detail-drawer", inputs: { activeTab: "activeTab", showCloseButton: "showCloseButton", expanded: "expanded", expandedWidth: "expandedWidth", minExpandedWidth: "minExpandedWidth", maxExpandedWidth: "maxExpandedWidth", collapsedWidth: "collapsedWidth", expandTooltip: "expandTooltip", collapseTooltip: "collapseTooltip", closeTooltip: "closeTooltip" }, outputs: { activeTabChange: "activeTabChange", expandToggle: "expandToggle", close: "close" }, host: { properties: { "style.width": "this.hostWidth", "style.min-width": "this.hostMinWidth", "style.max-width": "this.hostMaxWidth" }, styleAttribute: "transition: width 0.3s ease-in-out", classAttribute: "cqa-ui-root cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-shadow-[-4px_0_6px_-1px_rgba(0,0,0,0.05)]" }, queries: [{ propertyName: "tabComponents", predicate: DetailDrawerTabComponent }], ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white\">\n <div\n class=\"cqa-grid cqa-flex-1 cqa-min-h-0 cqa-overflow-hidden\"\n [style.grid-template-columns]=\"expanded ? 'auto 1fr' : 'auto 0fr'\"\n style=\"transition: grid-template-columns 0.3s ease-in-out\">\n <!-- Left vertical icon bar: one button per tab -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-min-h-0 cqa-items-center cqa-py-4 cqa-px-2 cqa-border-r cqa-border-[#E2E8F0] cqa-bg-[#FAFAFA] cqa-flex-shrink-0\">\n <!-- Expand / Collapse button (always visible) -->\n <button\n type=\"button\"\n [matTooltip]=\"expanded ? collapseTooltip : expandTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n (click)=\"onExpandToggle()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ expanded ? 'unfold_less' : 'unfold_more' }}</mat-icon>\n </button>\n <!-- Close button -->\n <button\n *ngIf=\"showCloseButton\"\n type=\"button\"\n [matTooltip]=\"closeTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n (click)=\"onClose()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">close</mat-icon>\n </button>\n <!-- Tab buttons: equally distributed in remaining space -->\n <div class=\"cqa-flex cqa-flex-1 cqa-flex-col cqa-justify-evenly cqa-items-center cqa-w-full\">\n <button\n *ngFor=\"let tab of tabComponents; trackBy: trackByValue\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"isTabActive(tab)\"\n [matTooltip]=\"tab.label\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n [ngClass]=\"{\n 'cqa-bg-[#3F43EE] cqa-text-white': isTabActive(tab),\n 'cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155]': !isTabActive(tab)\n }\"\n (click)=\"onTabClick(tab)\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ tab.icon }}</mat-icon>\n </button>\n </div>\n </div>\n\n <!-- Content area: show only the active tab's content -->\n <div class=\"cqa-min-w-0 cqa-overflow-hidden\">\n <div class=\"cqa-h-full cqa-overflow-y-auto cqa-p-4\">\n <ng-container *ngFor=\"let tab of tabComponents\">\n <ng-container *ngIf=\"tab.value === activeTab && tab.contentTemplate\" [ngTemplateOutlet]=\"tab.contentTemplate\"></ng-container>\n </ng-container>\n </div>\n </div>\n </div>\n</div>\n", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i5.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
34889
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DetailDrawerComponent, decorators: [{
34890
- type: Component,
34891
- args: [{ selector: 'cqa-detail-drawer', changeDetection: ChangeDetectionStrategy.OnPush, host: {
34892
- class: 'cqa-ui-root cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-shadow-[-4px_0_6px_-1px_rgba(0,0,0,0.05)]',
34893
- style: 'transition: width 0.3s ease-in-out',
34894
- }, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white\">\n <div\n class=\"cqa-grid cqa-flex-1 cqa-min-h-0 cqa-overflow-hidden\"\n [style.grid-template-columns]=\"expanded ? 'auto 1fr' : 'auto 0fr'\"\n style=\"transition: grid-template-columns 0.3s ease-in-out\">\n <!-- Left vertical icon bar: one button per tab -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-min-h-0 cqa-items-center cqa-py-4 cqa-px-2 cqa-border-r cqa-border-[#E2E8F0] cqa-bg-[#FAFAFA] cqa-flex-shrink-0\">\n <!-- Expand / Collapse button (always visible) -->\n <button\n type=\"button\"\n [matTooltip]=\"expanded ? collapseTooltip : expandTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n (click)=\"onExpandToggle()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ expanded ? 'unfold_less' : 'unfold_more' }}</mat-icon>\n </button>\n <!-- Close button -->\n <button\n *ngIf=\"showCloseButton\"\n type=\"button\"\n [matTooltip]=\"closeTooltip\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155] cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n (click)=\"onClose()\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">close</mat-icon>\n </button>\n <!-- Tab buttons: equally distributed in remaining space -->\n <div class=\"cqa-flex cqa-flex-1 cqa-flex-col cqa-justify-evenly cqa-items-center cqa-w-full\">\n <button\n *ngFor=\"let tab of tabComponents; trackBy: trackByValue\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"isTabActive(tab)\"\n [matTooltip]=\"tab.label\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-9 cqa-h-9 cqa-rounded-lg cqa-transition-colors focus:cqa-outline-none focus-visible:cqa-ring-2 focus-visible:cqa-ring-[#3F43EE] focus-visible:cqa-ring-offset-2 cqa-flex-shrink-0\"\n [ngClass]=\"{\n 'cqa-bg-[#3F43EE] cqa-text-white': isTabActive(tab),\n 'cqa-text-[#64748B] hover:cqa-bg-[#E2E8F0] hover:cqa-text-[#334155]': !isTabActive(tab)\n }\"\n (click)=\"onTabClick(tab)\">\n <mat-icon class=\"cqa-text-[20px] cqa-w-5 cqa-h-5\">{{ tab.icon }}</mat-icon>\n </button>\n </div>\n </div>\n\n <!-- Content area: show only the active tab's content -->\n <div class=\"cqa-min-w-0 cqa-overflow-hidden\">\n <div class=\"cqa-h-full cqa-overflow-y-auto cqa-p-4\">\n <ng-container *ngFor=\"let tab of tabComponents\">\n <ng-container *ngIf=\"tab.value === activeTab && tab.contentTemplate\" [ngTemplateOutlet]=\"tab.contentTemplate\"></ng-container>\n </ng-container>\n </div>\n </div>\n </div>\n</div>\n", styles: [] }]
34895
- }], propDecorators: { tabComponents: [{
34896
- type: ContentChildren,
34897
- args: [DetailDrawerTabComponent]
34898
- }], activeTab: [{
34899
- type: Input
34900
- }], showCloseButton: [{
34901
- type: Input
34902
- }], expanded: [{
34903
- type: Input
34904
- }], expandedWidth: [{
34905
- type: Input
34906
- }], minExpandedWidth: [{
34907
- type: Input
34908
- }], maxExpandedWidth: [{
34909
- type: Input
34910
- }], collapsedWidth: [{
34911
- type: Input
34912
- }], hostWidth: [{
34913
- type: HostBinding,
34914
- args: ['style.width']
34915
- }], hostMinWidth: [{
34916
- type: HostBinding,
34917
- args: ['style.min-width']
34918
- }], hostMaxWidth: [{
34919
- type: HostBinding,
34920
- args: ['style.max-width']
34921
- }], expandTooltip: [{
34922
- type: Input
34923
- }], collapseTooltip: [{
34924
- type: Input
34925
- }], closeTooltip: [{
34926
- type: Input
34927
- }], activeTabChange: [{
34928
- type: Output
34929
- }], expandToggle: [{
34930
- type: Output
34931
- }], close: [{
34932
- type: Output
34933
34980
  }] } });
34934
34981
 
34935
34982
  class StepBuilderGroupComponent {