@cqa-lib/cqa-ui 1.1.101 → 1.1.102

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.
@@ -21,7 +21,7 @@ import { MatCheckboxModule } from '@angular/material/checkbox';
21
21
  import * as i4 from '@angular/material/radio';
22
22
  import { MatRadioModule } from '@angular/material/radio';
23
23
  import { MatDatepickerModule } from '@angular/material/datepicker';
24
- import * as i5 from '@angular/material/progress-spinner';
24
+ import * as i4$1 from '@angular/material/progress-spinner';
25
25
  import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
26
26
  import * as i2 from '@angular/material/tooltip';
27
27
  import { MatTooltipModule } from '@angular/material/tooltip';
@@ -9662,6 +9662,7 @@ class SimulatorComponent {
9662
9662
  constructor(sanitizer) {
9663
9663
  this.sanitizer = sanitizer;
9664
9664
  this.videoUrl = '';
9665
+ this.videoUrls = [];
9665
9666
  this.videoCurrentDuration = 0;
9666
9667
  this.stepMarkers = [];
9667
9668
  this.screenShotUrl = '';
@@ -9684,6 +9685,7 @@ class SimulatorComponent {
9684
9685
  this.isPlaying = false;
9685
9686
  this.isFullScreen = false;
9686
9687
  this.currentView = 'video';
9688
+ this.currentVideoIndex = 0;
9687
9689
  this.segments = [
9688
9690
  { label: 'Screenshots', value: 'screenshots', icon: 'photo' },
9689
9691
  { label: 'Video', value: 'video', icon: 'videocam' },
@@ -9699,7 +9701,7 @@ class SimulatorComponent {
9699
9701
  this.deviceErrorEmptyStateConfig = Object.assign(Object.assign({}, this.emptyStateConfig), { title: 'Device Not Supported', description: 'The device you are trying to use is not supported.', actions: [] });
9700
9702
  this.deviceFrameConfigs = {
9701
9703
  // Pixels
9702
- pixel_5: {
9704
+ 'Pixel 5': {
9703
9705
  mockupImage: 'assets/images/mockups/pixel-5.png',
9704
9706
  screenInset: {
9705
9707
  top: '2%',
@@ -9709,7 +9711,7 @@ class SimulatorComponent {
9709
9711
  },
9710
9712
  borderRadius: '4%'
9711
9713
  },
9712
- pixel_8: {
9714
+ 'Pixel 8': {
9713
9715
  mockupImage: 'assets/images/mockups/pixel-8.png',
9714
9716
  screenInset: {
9715
9717
  top: '2%',
@@ -9719,8 +9721,18 @@ class SimulatorComponent {
9719
9721
  },
9720
9722
  borderRadius: '4%'
9721
9723
  },
9724
+ 'Pixel 9': {
9725
+ mockupImage: 'assets/images/mockups/pixel-9-pro.webp',
9726
+ screenInset: {
9727
+ top: '4%',
9728
+ right: '6%',
9729
+ bottom: '4%',
9730
+ left: '6%'
9731
+ },
9732
+ borderRadius: '5%'
9733
+ },
9722
9734
  // iPhones
9723
- iphone_11: {
9735
+ 'iPhone 11': {
9724
9736
  mockupImage: 'assets/images/mockups/apple-iphone-11.png',
9725
9737
  screenInset: {
9726
9738
  top: '3%',
@@ -9730,7 +9742,7 @@ class SimulatorComponent {
9730
9742
  },
9731
9743
  borderRadius: '4%'
9732
9744
  },
9733
- iphone_13: {
9745
+ 'iPhone 13': {
9734
9746
  mockupImage: 'assets/images/mockups/apple-iphone-13.png',
9735
9747
  screenInset: {
9736
9748
  top: '2%',
@@ -9740,7 +9752,7 @@ class SimulatorComponent {
9740
9752
  },
9741
9753
  borderRadius: '4%'
9742
9754
  },
9743
- iphone_15: {
9755
+ 'iPhone 15': {
9744
9756
  mockupImage: 'assets/images/mockups/apple-iphone-15.png',
9745
9757
  screenInset: {
9746
9758
  top: '1.5%',
@@ -9750,7 +9762,7 @@ class SimulatorComponent {
9750
9762
  },
9751
9763
  borderRadius: '4%'
9752
9764
  },
9753
- iphone_xr: {
9765
+ 'iPhone XR': {
9754
9766
  mockupImage: 'assets/images/mockups/apple-iphone-xr.png',
9755
9767
  screenInset: {
9756
9768
  top: '3.5%',
@@ -9760,13 +9772,13 @@ class SimulatorComponent {
9760
9772
  },
9761
9773
  borderRadius: '4%'
9762
9774
  },
9763
- galaxy_s20_fe: {
9775
+ 'Galaxy S20 FE': {
9764
9776
  mockupImage: 'assets/images/mockups/samsung-galaxy-s20.png',
9765
9777
  screenInset: {
9766
9778
  top: '1.5%',
9767
- right: '4.5%',
9768
- bottom: '2.5%',
9769
- left: '3.5%'
9779
+ right: '3%',
9780
+ bottom: '1.5%',
9781
+ left: '3%'
9770
9782
  },
9771
9783
  borderRadius: '4%'
9772
9784
  },
@@ -9784,21 +9796,26 @@ class SimulatorComponent {
9784
9796
  this.safeTraceUrl = this.sanitizer.bypassSecurityTrustResourceUrl('');
9785
9797
  this.updateSegments();
9786
9798
  }
9799
+ set vplayerRef(ref) {
9800
+ if (!ref)
9801
+ return;
9802
+ this._vplayer = ref;
9803
+ this.onVideoElementReady();
9804
+ }
9805
+ get vplayer() {
9806
+ return this._vplayer;
9807
+ }
9787
9808
  get hasDeviceFrame() {
9788
9809
  return !!this.deviceFrameConfig;
9789
9810
  }
9790
9811
  get deviceFrameConfig() {
9791
9812
  if (this.platformType === 'browser') {
9792
- this.isCorrectDeviceFrameAvailable = true;
9793
9813
  return this.deviceFrameConfigs['browser'] || null;
9794
9814
  }
9795
9815
  if (!this.deviceName) {
9796
- this.isCorrectDeviceFrameAvailable = false;
9797
9816
  return null;
9798
9817
  }
9799
- const normalizedName = this.deviceName.toLowerCase().replace(/[\s-]/g, '_');
9800
- this.isCorrectDeviceFrameAvailable = !!this.deviceFrameConfigs[normalizedName];
9801
- return this.deviceFrameConfigs[normalizedName] || null;
9818
+ return this.deviceFrameConfigs[this.deviceName] || null;
9802
9819
  }
9803
9820
  get deviceMockupImage() {
9804
9821
  var _a;
@@ -9826,6 +9843,12 @@ class SimulatorComponent {
9826
9843
  }
9827
9844
  ngOnChanges(changes) {
9828
9845
  var _a;
9846
+ if (changes['videoUrls']) {
9847
+ const arr = changes['videoUrls'].currentValue;
9848
+ if (arr && arr.length > 0) {
9849
+ this.currentVideoIndex = 0;
9850
+ }
9851
+ }
9829
9852
  if (changes['videoCurrentDuration'] && !changes['videoCurrentDuration'].firstChange) {
9830
9853
  const newDuration = changes['videoCurrentDuration'].currentValue;
9831
9854
  if (newDuration !== this.lastSetDuration && ((_a = this.vplayer) === null || _a === void 0 ? void 0 : _a.nativeElement)) {
@@ -9871,7 +9894,7 @@ class SimulatorComponent {
9871
9894
  if (!video)
9872
9895
  return;
9873
9896
  // Do not attempt to play if there is no valid source yet
9874
- if (!this.videoUrl || video.networkState === HTMLMediaElement.NETWORK_NO_SOURCE || video.error) {
9897
+ if (!this.currentVideoUrl || video.networkState === HTMLMediaElement.NETWORK_NO_SOURCE || video.error) {
9875
9898
  return;
9876
9899
  }
9877
9900
  if (this.isPlaying) {
@@ -9888,6 +9911,42 @@ class SimulatorComponent {
9888
9911
  });
9889
9912
  }
9890
9913
  }
9914
+ get hasMultipleVideos() {
9915
+ return Array.isArray(this.videoUrls) && this.videoUrls.length > 1;
9916
+ }
9917
+ get currentVideoUrl() {
9918
+ if (Array.isArray(this.videoUrls) && this.videoUrls.length > 0) {
9919
+ const idx = Math.min(Math.max(this.currentVideoIndex, 0), this.videoUrls.length - 1);
9920
+ return this.videoUrls[idx];
9921
+ }
9922
+ return this.videoUrl;
9923
+ }
9924
+ resetVideoState() {
9925
+ var _a;
9926
+ this.isPlaying = false;
9927
+ this.progress = 0;
9928
+ if ((_a = this.vplayer) === null || _a === void 0 ? void 0 : _a.nativeElement) {
9929
+ this.vplayer.nativeElement.pause();
9930
+ this.vplayer.nativeElement.currentTime = 0;
9931
+ }
9932
+ this.lastSetDuration = -1;
9933
+ }
9934
+ prevVideo() {
9935
+ if (!this.hasMultipleVideos)
9936
+ return;
9937
+ if (this.currentVideoIndex > 0) {
9938
+ this.currentVideoIndex -= 1;
9939
+ this.resetVideoState();
9940
+ }
9941
+ }
9942
+ nextVideo() {
9943
+ if (!this.hasMultipleVideos)
9944
+ return;
9945
+ if (this.videoUrls && this.currentVideoIndex < this.videoUrls.length - 1) {
9946
+ this.currentVideoIndex += 1;
9947
+ this.resetVideoState();
9948
+ }
9949
+ }
9891
9950
  onTimelineClick(event) {
9892
9951
  var _a, _b;
9893
9952
  if (!((_a = this.timelineBar) === null || _a === void 0 ? void 0 : _a.nativeElement) || !((_b = this.vplayer) === null || _b === void 0 ? void 0 : _b.nativeElement))
@@ -10108,14 +10167,23 @@ class SimulatorComponent {
10108
10167
  this.currentView = 'screenshots';
10109
10168
  }
10110
10169
  }
10170
+ onVideoElementReady() {
10171
+ var _a;
10172
+ const video = (_a = this._vplayer) === null || _a === void 0 ? void 0 : _a.nativeElement;
10173
+ if (!video)
10174
+ return;
10175
+ this.attachVideoListeners();
10176
+ }
10111
10177
  }
10112
10178
  SimulatorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: SimulatorComponent, deps: [{ token: i1$1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
10113
- SimulatorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: SimulatorComponent, selector: "cqa-simulator", inputs: { videoUrl: "videoUrl", videoCurrentDuration: "videoCurrentDuration", stepMarkers: "stepMarkers", screenShotUrl: "screenShotUrl", traceViewUrl: "traceViewUrl", platformName: "platformName", platformType: "platformType", deviceName: "deviceName", isLive: "isLive", liveStatus: "liveStatus", liveLoadingLabel: "liveLoadingLabel", isContentVideoLoading: "isContentVideoLoading", failedStatusMessage: "failedStatusMessage", selectedView: "selectedView", hideVideoTab: "hideVideoTab" }, outputs: { videoTimeUpdate: "videoTimeUpdate", videoPlay: "videoPlay", videoPause: "videoPause" }, viewQueries: [{ propertyName: "vplayer", first: true, predicate: ["vplayer"], descendants: true }, { propertyName: "timelineBar", first: true, predicate: ["timelineBar"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-ui-root\" style=\"background-color: #F3F4F6; height: 100%; display: flex; flex-direction: column;\" [ngStyle]=\"{\n position: isFullScreen ? 'fixed' : null,\n inset: isFullScreen ? '1rem' : null,\n zIndex: isFullScreen ? '50' : null,\n boxShadow: isFullScreen ? '0px 13px 25px -12px rgba(0, 0, 0, 0.25)' : null,\n borderRadius: isFullScreen ? '.5rem' : null,\n border: isFullScreen ? '1px solid #E5E7EB' : null,\n width: isFullScreen ? 'calc(100% - 32px)' : null,\n height: isFullScreen ? 'calc(100% - 32px)' : '100%',\n overflow: isFullScreen ? 'hidden' : null\n}\">\n <div class=\"cqa-w-full cqa-py-1 cqa-px-2 cqa-bg-[#FFFFFF]\" style=\"border-bottom: 1px solid #E5E7EB;box-shadow: 0px 1px 2px 0px #0000000D;\">\n <div class=\"cqa-w-full cqa-flex cqa-items-center cqa-justify-between\">\n <div class=\"cqa-flex cqa-items-center\">\n <div *ngIf=\"isLive\" class=\"cqa-h-[21px] cqa-inline-flex cqa-items-center cqa-gap-1.5 cqa-mr-2 cqa-px-[9px] cqa-py-[3px] cqa-bg-[#FCD9D9] cqa-rounded-[6px]\" style=\"border: 1px solid #F9BFBF;\">\n <span class=\"cqa-relative cqa-w-2 cqa-h-2 cqa-rounded-full cqa-bg-[#F47F7F]\" style=\"flex-shrink: 0;\">\n <span class=\"cqa-absolute cqa-inset-0 cqa-rounded-full cqa-bg-[#F47F7F] cqa-opacity-75 cqa-animate-ping\"></span>\n </span>\n <span class=\"cqa-text-[10px] cqa-font-medium cqa-text-[#C63535] cqa-leading-[15px]\">Live</span>\n </div>\n <mat-icon *ngIf=\"platformType === 'browser'\" style=\"width: 10px; height: 10px;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <g clip-path=\"url(#clip0_935_15847)\">\n <path\n d=\"M0.625 5C0.625 6.16032 1.08594 7.27312 1.90641 8.09359C2.72688 8.91406 3.83968 9.375 5 9.375C6.16032 9.375 7.27312 8.91406 8.09359 8.09359C8.91406 7.27312 9.375 6.16032 9.375 5C9.375 3.83968 8.91406 2.72688 8.09359 1.90641C7.27312 1.08594 6.16032 0.625 5 0.625C3.83968 0.625 2.72688 1.08594 1.90641 1.90641C1.08594 2.72688 0.625 3.83968 0.625 5Z\"\n stroke=\"#9CA3AF\" stroke-width=\"0.6\" stroke-linejoin=\"round\" />\n <path\n d=\"M3.125 5C3.125 3.83968 3.32254 2.72688 3.67417 1.90641C4.02581 1.08594 4.50272 0.625 5 0.625C5.49728 0.625 5.97419 1.08594 6.32582 1.90641C6.67746 2.72688 6.875 3.83968 6.875 5C6.875 6.16032 6.67746 7.27312 6.32582 8.09359C5.97419 8.91406 5.49728 9.375 5 9.375C4.50272 9.375 4.02581 8.91406 3.67417 8.09359C3.32254 7.27312 3.125 6.16032 3.125 5Z\"\n stroke=\"#9CA3AF\" stroke-width=\"0.6\" stroke-linejoin=\"round\" />\n <path d=\"M0.9375 6.45866H9.0625M0.9375 3.54199H9.0625\" stroke=\"#9CA3AF\" stroke-width=\"0.6\"\n stroke-linecap=\"round\" />\n </g>\n <defs>\n <clipPath id=\"clip0_935_15847\">\n <rect width=\"10\" height=\"10\" fill=\"white\" />\n </clipPath>\n </defs>\n </svg>\n </mat-icon>\n <mat-icon *ngIf=\"platformType === 'device'\" style=\"width: 10px; height: 10px;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M7.08325 0.833008H2.91659C2.45635 0.833008 2.08325 1.2061 2.08325 1.66634V8.33301C2.08325 8.79324 2.45635 9.16634 2.91659 9.16634H7.08325C7.54349 9.16634 7.91658 8.79324 7.91658 8.33301V1.66634C7.91658 1.2061 7.54349 0.833008 7.08325 0.833008Z\" stroke=\"#6B7280\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M5 7.5H5.00417\" stroke=\"#6B7280\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </mat-icon>\n <p class=\"cqa-text-sm !cqa-text-[10px] cqa-text-[#6B7280] cqa-ml-2\">{{ platformName }}</p>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div *ngIf=\"isLive\" [ngClass]=\"getStatusBadgeClass()\">\n <span [ngClass]=\"getStatusTextClass()\">{{ liveStatus }}</span>\n </div>\n\n <ng-container *ngIf=\"!isLive\">\n <cqa-segment-control \n [segments]=\"segments\" \n [value]=\"currentView\"\n (valueChange)=\"onSegmentChange($event)\">\n </cqa-segment-control>\n \n <div *ngIf=\"!isFullScreen\" \n class=\"cqa-p-1 cqa-cursor-pointer hover:cqa-bg-gray-100 cqa-rounded-sm cqa-transition-colors\"\n (click)=\"toggleFullScreen()\"\n title=\"Expand\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M6.25 1.25H8.75V3.75\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.74992 1.25L5.83325 4.16667\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M1.25 8.74967L4.16667 5.83301\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M3.75 8.75H1.25V6.25\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n\n <div *ngIf=\"isFullScreen\" \n class=\"cqa-p-1 cqa-cursor-pointer hover:cqa-bg-gray-100 cqa-rounded-sm cqa-transition-colors\"\n (click)=\"toggleFullScreen()\"\n title=\"Exit full screen\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M8.75 6.25H6.25V8.75\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.25008 6.25L9.16675 9.16667\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M0.833252 0.833008L3.74992 3.74967\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M1.25 3.75H3.75V1.25\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n </ng-container>\n </div>\n </div>\n </div>\n <div class=\"cqa-w-full cqa-bg-[#F3F4F6] cqa-h-[calc(100%-41px)]\">\n <ng-container *ngIf=\"!isCorrectDeviceFrameAvailable\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\">\n <cqa-empty-state\n [title]=\"deviceErrorEmptyStateConfig.title\"\n [description]=\"deviceErrorEmptyStateConfig.description\"\n [imageUrl]=\"deviceErrorEmptyStateConfig.imageUrl\"\n ></cqa-empty-state>\n </div>\n </ng-container>\n <ng-container *ngIf=\"hasDeviceFrame\">\n <!-- Live Content View -->\n <div *ngIf=\"isLive\" class=\"cqa-h-full cqa-flex cqa-flex-col cqa-justify-center cqa-relative\">\n <ng-container *ngIf=\"hasDeviceFrame;\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-p-4': platformType === 'browser'}\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser', 'cqa-max-h-[500px] cqa-h-full': platformType !== 'browser' || !isLive, 'cqa-h-auto': isLive && platformType === 'browser' }\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-max-h-full cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-z-20': platformType === 'browser', 'cqa-bg-white': platformType !== 'browser'}\">\n <!-- Loading State -->\n <div *ngIf=\"isContentVideoLoading\" class=\"cqa-p-10 cqa-text-center cqa-h-full cqa-flex cqa-flex-col cqa-items-center cqa-justify-center\">\n <div class=\"cqa-mb-4\">\n <mat-progress-spinner mode=\"indeterminate\" diameter=\"40\"></mat-progress-spinner>\n </div>\n <p class=\"cqa-text-gray-400 cqa-text-sm\">{{ liveLoadingLabel }}</p>\n </div>\n \n <!-- Live Content (when not loading) -->\n <div *ngIf=\"!isContentVideoLoading\" class=\"cqa-w-full cqa-h-full cqa-flex cqa-flex-col cqa-items-center cqa-justify-center cqa-relative\">\n <div *ngIf=\"liveStatus === 'Failed' && failedStatusMessage\" class=\"cqa-p-6 cqa-text-center cqa-w-full\">\n <div class=\"cqa-inline-flex cqa-items-center cqa-gap-2 cqa-px-4 cqa-py-3 cqa-bg-[#FCD9D9] cqa-border cqa-border-[#F9BFBF] cqa-rounded-lg\">\n <mat-icon style=\"width: 18px; height: 18px; color: #C63535; font-size: 18px;\">error</mat-icon>\n <p class=\"cqa-text-[#C63535] cqa-text-sm cqa-font-medium cqa-m-0\">{{ failedStatusMessage }}</p>\n </div>\n </div>\n <ng-content *ngIf=\"liveStatus !== 'Failed' || !failedStatusMessage\"></ng-content>\n </div>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n \n <!-- Normal Video View (when not live) -->\n <div *ngIf=\"!isLive && currentView === 'video'\" class=\"cqa-h-full cqa-flex cqa-flex-col cqa-justify-center\">\n <div class=\"cqa-w-full cqa-py-4 cqa-flex cqa-items-center cqa-max-h-[calc(100%-35px)]\" *ngIf=\"videoUrl\" [ngClass]=\"{'!cqa-h-full': platformType === 'device', 'cqa-mt-auto': hasDeviceFrame}\">\n <ng-container *ngIf=\"hasDeviceFrame\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-p-4': platformType === 'browser'}\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center cqa-max-h-[500px]\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser'}\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-max-h-full cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-bg-white': platformType !== 'browser'}\">\n <video\n #vplayer\n class=\"cqa-object-contain cqa-w-full cqa-h-full cqa-block cqa-bg-[##F2F2F2]\"\n [src]=\"videoUrl\"\n type=\"video/webm\"\n [ngClass]=\"{'cqa-z-20': platformType === 'browser'}\"\n (loadedmetadata)=\"onVideoMetadataLoaded()\"\n (canplay)=\"onVideoCanPlay()\"\n (ended)=\"onVideoEnded()\"\n ></video>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!videoUrl\">\n No video recording found\n </div>\n \n <div class=\"cqa-px-2 cqa-py-2 cqa-bg-white\" style=\"border-top: 1px solid #E5E7EB;\" [ngClass]=\"{'cqa-mt-auto': hasDeviceFrame}\" *ngIf=\"videoUrl && !isLive\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <button \n type=\"button\"\n class=\"cqa-bg-transparent cqa-border-none cqa-cursor-pointer !cqa-px-0 cqa-flex cqa-items-center cqa-justify-center hover:cqa-opacity-70 cqa-transition-opacity cqa-outline-none\"\n style=\"pointer-events: auto;\"\n (click)=\"togglePlay()\">\n <span *ngIf=\"!isPlaying\" class=\"cqa-flex cqa-items-center cqa-justify-center\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M3 2L13 8L3 14V2Z\" fill=\"#374151\"/>\n </svg>\n </span>\n <span *ngIf=\"isPlaying\" class=\"cqa-flex cqa-items-center cqa-justify-center\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"3\" y=\"2\" width=\"3\" height=\"12\" fill=\"#374151\"/>\n <rect x=\"10\" y=\"2\" width=\"3\" height=\"12\" fill=\"#374151\"/>\n </svg>\n </span>\n </button>\n \n <span class=\"cqa-text-[#9CA3AF] cqa-text-[9px] cqa-font-normal cqa-whitespace-nowrap cqa-select-none cqa-mr-[20px]\">\n {{ formatTime(vplayer?.nativeElement?.currentTime || 0) }}\n </span>\n \n <div \n #timelineBar\n class=\"cqa-relative cqa-h-1 cqa-bg-gray-200 cqa-rounded-full cqa-cursor-pointer cqa-flex-1\"\n (click)=\"onTimelineClick($event)\">\n \n <div \n *ngFor=\"let step of stepMarkers\" \n class=\"cqa-absolute cqa-w-1 cqa-h-full cqa-top-0 cqa-rounded-sm\"\n [style.left.%]=\"getStepLeftPosition(step)\"\n [style.background]=\"getStepColor(step)\"\n style=\"pointer-events: none; z-index: 20;\">\n </div>\n \n <div \n class=\"cqa-absolute cqa-left-0 cqa-top-0 cqa-h-full cqa-bg-green-500 cqa-rounded-full\"\n [style.width.%]=\"progress\"\n [style.transition]=\"dragging ? 'none' : 'width 100ms'\"\n style=\"pointer-events: none; z-index: 2;\">\n </div>\n \n <div \n class=\"cqa-absolute cqa-top-1/2 cqa-w-3 cqa-h-3 cqa-bg-green-600 cqa-rounded-full cqa-cursor-grab active:cqa-cursor-grabbing cqa-shadow-md\"\n [style.left.%]=\"progress\"\n style=\"transform: translate(-50%, -50%); z-index: 10;\"\n (mousedown)=\"startDrag($event)\">\n </div>\n </div>\n </div>\n </div>\n </div>\n \n <div *ngIf=\"!isLive && currentView === 'screenshots'\" class=\"cqa-h-full\">\n <div class=\"cqa-w-full cqa-py-4 cqa-h-full cqa-flex cqa-items-center\" *ngIf=\"screenShotUrl\">\n <ng-container *ngIf=\"hasDeviceFrame\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-p-4': platformType === 'browser'}\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center cqa-max-h-[500px]\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser'}\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-max-h-full cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-bg-white': platformType !== 'browser'}\">\n <img\n [src]=\"screenShotUrl\"\n alt=\"Screenshot\"\n [ngClass]=\"{'cqa-z-20': platformType === 'browser'}\"\n class=\"cqa-object-contain cqa-w-full cqa-h-full cqa-block cqa-bg-[##F2F2F2]\"\n />\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!screenShotUrl\">\n No screenshot available\n </div>\n </div>\n \n <div *ngIf=\"!isLive && currentView === 'trace'\" class=\"cqa-h-full cqa-flex cqa-flex-col cqa-justify-center\">\n <div class=\"cqa-w-full cqa-h-full cqa-py-4 cqa-flex cqa-items-center cqa-relative\" *ngIf=\"traceViewUrl\" [ngClass]=\"{'!cqa-h-full': platformType === 'device'}\">\n <iframe \n [src]=\"safeTraceUrl\" \n title=\"Trace Viewer\"\n class=\"cqa-object-contain cqa-w-full cqa-min-h-[250px] cqa-max-h-full cqa-block cqa-bg-[##F2F2F2]\"\n frameborder=\"0\"\n allowfullscreen\n width=\"100%\"\n height=\"100%\"\n loading=\"lazy\"\n (load)=\"onTraceViewerLoad()\"\n (error)=\"onTraceViewerError()\">\n </iframe>\n \n <div *ngIf=\"traceViewerLoading\" class=\"cqa-absolute cqa-inset-0 cqa-bg-[#F3F4F6] cqa-flex cqa-items-center cqa-justify-center cqa-z-10\">\n <div class=\"cqa-text-center cqa-text-gray-400 cqa-text-sm\">\n Loading trace viewer...\n </div>\n </div>\n \n <div *ngIf=\"traceViewerError\" class=\"cqa-absolute cqa-inset-0 cqa-bg-[#F3F4F6] cqa-flex cqa-items-center cqa-justify-center cqa-z-10\">\n <div class=\"cqa-text-center cqa-text-gray-400 cqa-text-sm\">\n Failed to load trace viewer\n </div>\n </div>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!traceViewUrl\">\n No trace available\n </div>\n </div> \n </ng-container>\n </div>\n</div>", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: SegmentControlComponent, selector: "cqa-segment-control", inputs: ["segments", "value", "disabled"], outputs: ["valueChange"] }, { type: EmptyStateComponent, selector: "cqa-empty-state", inputs: ["preset", "imageUrl", "title", "description", "actions"], outputs: ["actionClick"] }, { type: i5.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "diameter", "strokeWidth", "mode", "value"], exportAs: ["matProgressSpinner"] }], directives: [{ type: i2$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
10179
+ SimulatorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: SimulatorComponent, selector: "cqa-simulator", inputs: { videoUrl: "videoUrl", videoUrls: "videoUrls", videoCurrentDuration: "videoCurrentDuration", stepMarkers: "stepMarkers", screenShotUrl: "screenShotUrl", traceViewUrl: "traceViewUrl", platformName: "platformName", platformType: "platformType", deviceName: "deviceName", isLive: "isLive", liveStatus: "liveStatus", liveLoadingLabel: "liveLoadingLabel", isContentVideoLoading: "isContentVideoLoading", failedStatusMessage: "failedStatusMessage", selectedView: "selectedView", hideVideoTab: "hideVideoTab" }, outputs: { videoTimeUpdate: "videoTimeUpdate", videoPlay: "videoPlay", videoPause: "videoPause" }, viewQueries: [{ propertyName: "vplayerRef", first: true, predicate: ["vplayer"], descendants: true }, { propertyName: "timelineBar", first: true, predicate: ["timelineBar"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-ui-root\" style=\"background-color: #F3F4F6; height: 100%; display: flex; flex-direction: column;\" [ngStyle]=\"{\n position: isFullScreen ? 'fixed' : null,\n inset: isFullScreen ? '1rem' : null,\n zIndex: isFullScreen ? '50' : null,\n boxShadow: isFullScreen ? '0px 13px 25px -12px rgba(0, 0, 0, 0.25)' : null,\n borderRadius: isFullScreen ? '.5rem' : null,\n border: isFullScreen ? '1px solid #E5E7EB' : null,\n width: isFullScreen ? 'calc(100% - 32px)' : null,\n height: isFullScreen ? 'calc(100% - 32px)' : '100%',\n overflow: isFullScreen ? 'hidden' : null\n}\">\n <div class=\"cqa-w-full cqa-py-1 cqa-px-2 cqa-bg-[#FFFFFF]\" style=\"border-bottom: 1px solid #E5E7EB;box-shadow: 0px 1px 2px 0px #0000000D;\">\n <div class=\"cqa-w-full cqa-flex cqa-items-center cqa-justify-between\">\n <div class=\"cqa-flex cqa-items-center\">\n <div *ngIf=\"isLive\" class=\"cqa-h-[21px] cqa-inline-flex cqa-items-center cqa-gap-1.5 cqa-mr-2 cqa-px-[9px] cqa-py-[3px] cqa-bg-[#FCD9D9] cqa-rounded-[6px]\" style=\"border: 1px solid #F9BFBF;\">\n <span class=\"cqa-relative cqa-w-2 cqa-h-2 cqa-rounded-full cqa-bg-[#F47F7F]\" style=\"flex-shrink: 0;\">\n <span class=\"cqa-absolute cqa-inset-0 cqa-rounded-full cqa-bg-[#F47F7F] cqa-opacity-75 cqa-animate-ping\"></span>\n </span>\n <span class=\"cqa-text-[10px] cqa-font-medium cqa-text-[#C63535] cqa-leading-[15px]\">Live</span>\n </div>\n <mat-icon *ngIf=\"platformType === 'browser'\" style=\"width: 10px; height: 10px;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <g clip-path=\"url(#clip0_935_15847)\">\n <path\n d=\"M0.625 5C0.625 6.16032 1.08594 7.27312 1.90641 8.09359C2.72688 8.91406 3.83968 9.375 5 9.375C6.16032 9.375 7.27312 8.91406 8.09359 8.09359C8.91406 7.27312 9.375 6.16032 9.375 5C9.375 3.83968 8.91406 2.72688 8.09359 1.90641C7.27312 1.08594 6.16032 0.625 5 0.625C3.83968 0.625 2.72688 1.08594 1.90641 1.90641C1.08594 2.72688 0.625 3.83968 0.625 5Z\"\n stroke=\"#9CA3AF\" stroke-width=\"0.6\" stroke-linejoin=\"round\" />\n <path\n d=\"M3.125 5C3.125 3.83968 3.32254 2.72688 3.67417 1.90641C4.02581 1.08594 4.50272 0.625 5 0.625C5.49728 0.625 5.97419 1.08594 6.32582 1.90641C6.67746 2.72688 6.875 3.83968 6.875 5C6.875 6.16032 6.67746 7.27312 6.32582 8.09359C5.97419 8.91406 5.49728 9.375 5 9.375C4.50272 9.375 4.02581 8.91406 3.67417 8.09359C3.32254 7.27312 3.125 6.16032 3.125 5Z\"\n stroke=\"#9CA3AF\" stroke-width=\"0.6\" stroke-linejoin=\"round\" />\n <path d=\"M0.9375 6.45866H9.0625M0.9375 3.54199H9.0625\" stroke=\"#9CA3AF\" stroke-width=\"0.6\"\n stroke-linecap=\"round\" />\n </g>\n <defs>\n <clipPath id=\"clip0_935_15847\">\n <rect width=\"10\" height=\"10\" fill=\"white\" />\n </clipPath>\n </defs>\n </svg>\n </mat-icon>\n <mat-icon *ngIf=\"platformType === 'device'\" style=\"width: 10px; height: 10px;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M7.08325 0.833008H2.91659C2.45635 0.833008 2.08325 1.2061 2.08325 1.66634V8.33301C2.08325 8.79324 2.45635 9.16634 2.91659 9.16634H7.08325C7.54349 9.16634 7.91658 8.79324 7.91658 8.33301V1.66634C7.91658 1.2061 7.54349 0.833008 7.08325 0.833008Z\" stroke=\"#6B7280\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M5 7.5H5.00417\" stroke=\"#6B7280\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </mat-icon>\n <p class=\"cqa-text-sm !cqa-text-[10px] cqa-text-[#6B7280] cqa-ml-2\">\n {{ platformName }}\n <span\n *ngIf=\"platformType === 'browser'\"\n class=\"cqa-ml-1\"\n matTooltip=\"Screen size: 1920x1080\"\n matTooltipPosition=\"below\"\n >\n \u00B7 <span class=\"cqa-ml-1\">1920x1080</span>\n </span>\n </p>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div *ngIf=\"isLive\" [ngClass]=\"getStatusBadgeClass()\">\n <span [ngClass]=\"getStatusTextClass()\">{{ liveStatus }}</span>\n </div>\n\n <ng-container *ngIf=\"!isLive\">\n <cqa-segment-control \n [segments]=\"segments\" \n [value]=\"currentView\"\n (valueChange)=\"onSegmentChange($event)\">\n </cqa-segment-control>\n \n <div *ngIf=\"!isFullScreen\" \n class=\"cqa-p-1 cqa-cursor-pointer hover:cqa-bg-gray-100 cqa-rounded-sm cqa-transition-colors\"\n (click)=\"toggleFullScreen()\"\n title=\"Expand\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M6.25 1.25H8.75V3.75\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.74992 1.25L5.83325 4.16667\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M1.25 8.74967L4.16667 5.83301\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M3.75 8.75H1.25V6.25\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n\n <div *ngIf=\"isFullScreen\" \n class=\"cqa-p-1 cqa-cursor-pointer hover:cqa-bg-gray-100 cqa-rounded-sm cqa-transition-colors\"\n (click)=\"toggleFullScreen()\"\n title=\"Exit full screen\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M8.75 6.25H6.25V8.75\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.25008 6.25L9.16675 9.16667\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M0.833252 0.833008L3.74992 3.74967\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M1.25 3.75H3.75V1.25\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n </ng-container>\n </div>\n </div>\n </div>\n <div class=\"cqa-w-full cqa-bg-[#F3F4F6] cqa-h-[calc(100%-41px)]\">\n <!-- Live Content View -->\n <div *ngIf=\"isLive\" class=\"cqa-h-full cqa-flex cqa-flex-col cqa-justify-center cqa-relative\">\n <ng-container *ngIf=\"hasDeviceFrame;\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-p-4': platformType === 'browser'}\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser', 'cqa-max-h-[500px] cqa-h-full': platformType !== 'browser' || !isLive, 'cqa-h-auto': isLive && platformType === 'browser' }\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-max-h-full cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-z-20': platformType === 'browser', 'cqa-bg-white': platformType !== 'browser'}\">\n <!-- Loading State -->\n <div *ngIf=\"isContentVideoLoading\" class=\"cqa-p-10 cqa-text-center cqa-h-full cqa-flex cqa-flex-col cqa-items-center cqa-justify-center\">\n <div class=\"cqa-mb-4\">\n <mat-progress-spinner mode=\"indeterminate\" diameter=\"40\"></mat-progress-spinner>\n </div>\n <p class=\"cqa-text-gray-400 cqa-text-sm\">{{ liveLoadingLabel }}</p>\n </div>\n\n <!-- Live Content (when not loading) -->\n <div *ngIf=\"!isContentVideoLoading\" class=\"cqa-w-full cqa-h-full cqa-flex cqa-flex-col cqa-items-center cqa-justify-center cqa-relative\">\n <div *ngIf=\"liveStatus === 'Failed' && failedStatusMessage\" class=\"cqa-p-6 cqa-text-center cqa-w-full\">\n <div class=\"cqa-inline-flex cqa-items-center cqa-gap-2 cqa-px-4 cqa-py-3 cqa-bg-[#FCD9D9] cqa-border cqa-border-[#F9BFBF] cqa-rounded-lg\">\n <mat-icon style=\"width: 18px; height: 18px; color: #C63535; font-size: 18px;\">error</mat-icon>\n <p class=\"cqa-text-[#C63535] cqa-text-sm cqa-font-medium cqa-m-0\">{{ failedStatusMessage }}</p>\n </div>\n </div>\n <ng-content *ngIf=\"liveStatus !== 'Failed' || !failedStatusMessage\"></ng-content>\n </div>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n\n <!-- Normal Video View (when not live) -->\n <div *ngIf=\"!isLive && currentView === 'video'\" class=\"cqa-h-full cqa-flex cqa-flex-col cqa-justify-center\">\n <div class=\"cqa-w-full cqa-py-4 cqa-flex cqa-items-center cqa-max-h-[calc(100%-35px)]\" *ngIf=\"currentVideoUrl\" [ngClass]=\"{'!cqa-h-full': platformType === 'device', 'cqa-mt-auto': hasDeviceFrame}\">\n <ng-container *ngIf=\"hasDeviceFrame\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-p-4': platformType === 'browser'}\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center cqa-max-h-[500px]\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser'}\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-max-h-full cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-bg-white': platformType !== 'browser'}\">\n <video\n #vplayer\n class=\"cqa-object-cover cqa-w-full cqa-h-full cqa-block cqa-bg-[##F2F2F2]\"\n [src]=\"currentVideoUrl\"\n type=\"video/webm\"\n [ngClass]=\"{'cqa-z-20': platformType === 'browser'}\"\n (loadedmetadata)=\"onVideoMetadataLoaded()\"\n (canplay)=\"onVideoCanPlay()\"\n (ended)=\"onVideoEnded()\"\n ></video>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!currentVideoUrl\">\n No video recording found\n </div>\n \n <div class=\"cqa-px-2 cqa-py-2 cqa-bg-white\" style=\"border-top: 1px solid #E5E7EB;\" [ngClass]=\"{'cqa-mt-auto': hasDeviceFrame}\" *ngIf=\"currentVideoUrl && !isLive\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <button \n *ngIf=\"hasMultipleVideos\"\n type=\"button\"\n class=\"cqa-bg-transparent cqa-border-none cqa-cursor-pointer !cqa-px-0 cqa-flex cqa-items-center cqa-justify-center hover:cqa-opacity-70 cqa-transition-opacity cqa-outline-none\"\n style=\"pointer-events: auto;\"\n [disabled]=\"currentVideoIndex === 0\"\n [ngClass]=\"{'cqa-opacity-50 cqa-cursor-not-allowed': currentVideoIndex === 0}\"\n (click)=\"prevVideo()\"\n matTooltip=\"Previous video\"\n matTooltipPosition=\"above\">\n <mat-icon class=\"cqa-w-4 cqa-h-4 !cqa-text-[16px] cqa-text-[#374151]\" [ngClass]=\"{'cqa-opacity-50 cqa-cursor-not-allowed': currentVideoIndex === 0}\">skip_previous</mat-icon>\n </button>\n\n <button \n type=\"button\"\n class=\"cqa-bg-transparent cqa-border-none cqa-cursor-pointer !cqa-px-0 cqa-flex cqa-items-center cqa-justify-center hover:cqa-opacity-70 cqa-transition-opacity cqa-outline-none\"\n style=\"pointer-events: auto;\"\n (click)=\"togglePlay()\"\n matTooltip=\"{{ isPlaying ? 'Pause' : 'Play' }}\"\n matTooltipPosition=\"above\">\n <span *ngIf=\"!isPlaying\" class=\"cqa-flex cqa-items-center cqa-justify-center\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M3 2L13 8L3 14V2Z\" fill=\"#374151\"/>\n </svg>\n </span>\n <span *ngIf=\"isPlaying\" class=\"cqa-flex cqa-items-center cqa-justify-center\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"3\" y=\"2\" width=\"3\" height=\"12\" fill=\"#374151\"/>\n <rect x=\"10\" y=\"2\" width=\"3\" height=\"12\" fill=\"#374151\"/>\n </svg>\n </span>\n </button>\n \n <button \n *ngIf=\"hasMultipleVideos\"\n type=\"button\"\n class=\"cqa-bg-transparent cqa-border-none cqa-cursor-pointer !cqa-px-0 cqa-flex cqa-items-center cqa-justify-center hover:cqa-opacity-70 cqa-transition-opacity cqa-outline-none\"\n style=\"pointer-events: auto;\"\n [disabled]=\"videoUrls && (currentVideoIndex >= videoUrls.length - 1)\"\n [ngClass]=\"{'cqa-opacity-50 cqa-cursor-not-allowed': videoUrls && (currentVideoIndex >= videoUrls.length - 1)}\"\n (click)=\"nextVideo()\"\n matTooltip=\"Next video\"\n matTooltipPosition=\"above\">\n <mat-icon class=\"cqa-w-4 cqa-h-4 !cqa-text-[16px] cqa-text-[#374151]\" [ngClass]=\"{'cqa-opacity-50 cqa-cursor-not-allowed': videoUrls && (currentVideoIndex >= videoUrls.length - 1)}\">skip_next</mat-icon>\n </button>\n\n <span class=\"cqa-text-[#9CA3AF] cqa-text-[9px] cqa-font-normal cqa-whitespace-nowrap cqa-select-none cqa-mr-[20px]\">\n {{ formatTime(vplayer?.nativeElement?.currentTime || 0) }}\n </span>\n \n <div \n #timelineBar\n class=\"cqa-relative cqa-h-1 cqa-bg-gray-200 cqa-rounded-full cqa-cursor-pointer cqa-flex-1\"\n (click)=\"onTimelineClick($event)\">\n \n <div \n *ngFor=\"let step of stepMarkers\" \n class=\"cqa-absolute cqa-w-1 cqa-h-full cqa-top-0 cqa-rounded-sm\"\n [style.left.%]=\"getStepLeftPosition(step)\"\n [style.background]=\"getStepColor(step)\"\n style=\"pointer-events: none; z-index: 20;\">\n </div>\n \n <div \n class=\"cqa-absolute cqa-left-0 cqa-top-0 cqa-h-full cqa-bg-green-500 cqa-rounded-full\"\n [style.width.%]=\"progress\"\n [style.transition]=\"dragging ? 'none' : 'width 100ms'\"\n style=\"pointer-events: none; z-index: 2;\">\n </div>\n \n <div \n class=\"cqa-absolute cqa-top-1/2 cqa-w-3 cqa-h-3 cqa-bg-green-600 cqa-rounded-full cqa-cursor-grab active:cqa-cursor-grabbing cqa-shadow-md\"\n [style.left.%]=\"progress\"\n style=\"transform: translate(-50%, -50%); z-index: 10;\"\n (mousedown)=\"startDrag($event)\">\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"!isLive && currentView === 'screenshots'\" class=\"cqa-h-full\">\n <div class=\"cqa-w-full cqa-py-4 cqa-h-full cqa-flex cqa-items-center\" *ngIf=\"screenShotUrl\">\n <ng-container *ngIf=\"hasDeviceFrame\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-p-4': platformType === 'browser'}\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center cqa-max-h-[500px]\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser', '!cqa-h-auto': platformType === 'browser', 'cqa-h-full': platformType !== 'browser'}\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n [ngClass]=\"{'cqa-max-h-[inherit]': platformType === 'browser', 'cqa-max-h-full': platformType !== 'browser'}\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-bg-white': platformType !== 'browser'}\">\n <img\n [src]=\"screenShotUrl\"\n alt=\"Screenshot\"\n [ngClass]=\"{'cqa-z-20': platformType === 'browser'}\"\n class=\"cqa-object-contain cqa-w-full cqa-h-full cqa-block cqa-bg-[##F2F2F2]\"\n />\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!screenShotUrl\">\n No screenshot available\n </div>\n </div>\n\n <div *ngIf=\"!isLive && currentView === 'trace'\" class=\"cqa-h-full cqa-flex cqa-flex-col cqa-justify-center\">\n <div class=\"cqa-w-full cqa-h-full cqa-py-4 cqa-flex cqa-items-center cqa-relative\" *ngIf=\"traceViewUrl\" [ngClass]=\"{'!cqa-h-full': platformType === 'device'}\">\n <iframe \n [src]=\"safeTraceUrl\" \n title=\"Trace Viewer\"\n class=\"cqa-object-contain cqa-w-full cqa-min-h-[250px] cqa-max-h-full cqa-block cqa-bg-[##F2F2F2]\"\n frameborder=\"0\"\n allowfullscreen\n width=\"100%\"\n height=\"100%\"\n loading=\"lazy\"\n (load)=\"onTraceViewerLoad()\"\n (error)=\"onTraceViewerError()\">\n </iframe>\n \n <div *ngIf=\"traceViewerLoading\" class=\"cqa-absolute cqa-inset-0 cqa-bg-[#F3F4F6] cqa-flex cqa-items-center cqa-justify-center cqa-z-10\">\n <div class=\"cqa-text-center cqa-text-gray-400 cqa-text-sm\">\n Loading trace viewer...\n </div>\n </div>\n \n <div *ngIf=\"traceViewerError\" class=\"cqa-absolute cqa-inset-0 cqa-bg-[#F3F4F6] cqa-flex cqa-items-center cqa-justify-center cqa-z-10\">\n <div class=\"cqa-text-center cqa-text-gray-400 cqa-text-sm\">\n Failed to load trace viewer\n </div>\n </div>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!traceViewUrl\">\n No trace available\n </div>\n </div> \n </div>\n</div>", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: SegmentControlComponent, selector: "cqa-segment-control", inputs: ["segments", "value", "disabled"], outputs: ["valueChange"] }, { type: i4$1.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "diameter", "strokeWidth", "mode", "value"], exportAs: ["matProgressSpinner"] }], directives: [{ type: i2$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
10114
10180
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: SimulatorComponent, decorators: [{
10115
10181
  type: Component,
10116
- args: [{ selector: 'cqa-simulator', template: "<div class=\"cqa-ui-root\" style=\"background-color: #F3F4F6; height: 100%; display: flex; flex-direction: column;\" [ngStyle]=\"{\n position: isFullScreen ? 'fixed' : null,\n inset: isFullScreen ? '1rem' : null,\n zIndex: isFullScreen ? '50' : null,\n boxShadow: isFullScreen ? '0px 13px 25px -12px rgba(0, 0, 0, 0.25)' : null,\n borderRadius: isFullScreen ? '.5rem' : null,\n border: isFullScreen ? '1px solid #E5E7EB' : null,\n width: isFullScreen ? 'calc(100% - 32px)' : null,\n height: isFullScreen ? 'calc(100% - 32px)' : '100%',\n overflow: isFullScreen ? 'hidden' : null\n}\">\n <div class=\"cqa-w-full cqa-py-1 cqa-px-2 cqa-bg-[#FFFFFF]\" style=\"border-bottom: 1px solid #E5E7EB;box-shadow: 0px 1px 2px 0px #0000000D;\">\n <div class=\"cqa-w-full cqa-flex cqa-items-center cqa-justify-between\">\n <div class=\"cqa-flex cqa-items-center\">\n <div *ngIf=\"isLive\" class=\"cqa-h-[21px] cqa-inline-flex cqa-items-center cqa-gap-1.5 cqa-mr-2 cqa-px-[9px] cqa-py-[3px] cqa-bg-[#FCD9D9] cqa-rounded-[6px]\" style=\"border: 1px solid #F9BFBF;\">\n <span class=\"cqa-relative cqa-w-2 cqa-h-2 cqa-rounded-full cqa-bg-[#F47F7F]\" style=\"flex-shrink: 0;\">\n <span class=\"cqa-absolute cqa-inset-0 cqa-rounded-full cqa-bg-[#F47F7F] cqa-opacity-75 cqa-animate-ping\"></span>\n </span>\n <span class=\"cqa-text-[10px] cqa-font-medium cqa-text-[#C63535] cqa-leading-[15px]\">Live</span>\n </div>\n <mat-icon *ngIf=\"platformType === 'browser'\" style=\"width: 10px; height: 10px;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <g clip-path=\"url(#clip0_935_15847)\">\n <path\n d=\"M0.625 5C0.625 6.16032 1.08594 7.27312 1.90641 8.09359C2.72688 8.91406 3.83968 9.375 5 9.375C6.16032 9.375 7.27312 8.91406 8.09359 8.09359C8.91406 7.27312 9.375 6.16032 9.375 5C9.375 3.83968 8.91406 2.72688 8.09359 1.90641C7.27312 1.08594 6.16032 0.625 5 0.625C3.83968 0.625 2.72688 1.08594 1.90641 1.90641C1.08594 2.72688 0.625 3.83968 0.625 5Z\"\n stroke=\"#9CA3AF\" stroke-width=\"0.6\" stroke-linejoin=\"round\" />\n <path\n d=\"M3.125 5C3.125 3.83968 3.32254 2.72688 3.67417 1.90641C4.02581 1.08594 4.50272 0.625 5 0.625C5.49728 0.625 5.97419 1.08594 6.32582 1.90641C6.67746 2.72688 6.875 3.83968 6.875 5C6.875 6.16032 6.67746 7.27312 6.32582 8.09359C5.97419 8.91406 5.49728 9.375 5 9.375C4.50272 9.375 4.02581 8.91406 3.67417 8.09359C3.32254 7.27312 3.125 6.16032 3.125 5Z\"\n stroke=\"#9CA3AF\" stroke-width=\"0.6\" stroke-linejoin=\"round\" />\n <path d=\"M0.9375 6.45866H9.0625M0.9375 3.54199H9.0625\" stroke=\"#9CA3AF\" stroke-width=\"0.6\"\n stroke-linecap=\"round\" />\n </g>\n <defs>\n <clipPath id=\"clip0_935_15847\">\n <rect width=\"10\" height=\"10\" fill=\"white\" />\n </clipPath>\n </defs>\n </svg>\n </mat-icon>\n <mat-icon *ngIf=\"platformType === 'device'\" style=\"width: 10px; height: 10px;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M7.08325 0.833008H2.91659C2.45635 0.833008 2.08325 1.2061 2.08325 1.66634V8.33301C2.08325 8.79324 2.45635 9.16634 2.91659 9.16634H7.08325C7.54349 9.16634 7.91658 8.79324 7.91658 8.33301V1.66634C7.91658 1.2061 7.54349 0.833008 7.08325 0.833008Z\" stroke=\"#6B7280\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M5 7.5H5.00417\" stroke=\"#6B7280\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </mat-icon>\n <p class=\"cqa-text-sm !cqa-text-[10px] cqa-text-[#6B7280] cqa-ml-2\">{{ platformName }}</p>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div *ngIf=\"isLive\" [ngClass]=\"getStatusBadgeClass()\">\n <span [ngClass]=\"getStatusTextClass()\">{{ liveStatus }}</span>\n </div>\n\n <ng-container *ngIf=\"!isLive\">\n <cqa-segment-control \n [segments]=\"segments\" \n [value]=\"currentView\"\n (valueChange)=\"onSegmentChange($event)\">\n </cqa-segment-control>\n \n <div *ngIf=\"!isFullScreen\" \n class=\"cqa-p-1 cqa-cursor-pointer hover:cqa-bg-gray-100 cqa-rounded-sm cqa-transition-colors\"\n (click)=\"toggleFullScreen()\"\n title=\"Expand\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M6.25 1.25H8.75V3.75\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.74992 1.25L5.83325 4.16667\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M1.25 8.74967L4.16667 5.83301\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M3.75 8.75H1.25V6.25\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n\n <div *ngIf=\"isFullScreen\" \n class=\"cqa-p-1 cqa-cursor-pointer hover:cqa-bg-gray-100 cqa-rounded-sm cqa-transition-colors\"\n (click)=\"toggleFullScreen()\"\n title=\"Exit full screen\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M8.75 6.25H6.25V8.75\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.25008 6.25L9.16675 9.16667\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M0.833252 0.833008L3.74992 3.74967\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M1.25 3.75H3.75V1.25\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n </ng-container>\n </div>\n </div>\n </div>\n <div class=\"cqa-w-full cqa-bg-[#F3F4F6] cqa-h-[calc(100%-41px)]\">\n <ng-container *ngIf=\"!isCorrectDeviceFrameAvailable\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\">\n <cqa-empty-state\n [title]=\"deviceErrorEmptyStateConfig.title\"\n [description]=\"deviceErrorEmptyStateConfig.description\"\n [imageUrl]=\"deviceErrorEmptyStateConfig.imageUrl\"\n ></cqa-empty-state>\n </div>\n </ng-container>\n <ng-container *ngIf=\"hasDeviceFrame\">\n <!-- Live Content View -->\n <div *ngIf=\"isLive\" class=\"cqa-h-full cqa-flex cqa-flex-col cqa-justify-center cqa-relative\">\n <ng-container *ngIf=\"hasDeviceFrame;\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-p-4': platformType === 'browser'}\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser', 'cqa-max-h-[500px] cqa-h-full': platformType !== 'browser' || !isLive, 'cqa-h-auto': isLive && platformType === 'browser' }\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-max-h-full cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-z-20': platformType === 'browser', 'cqa-bg-white': platformType !== 'browser'}\">\n <!-- Loading State -->\n <div *ngIf=\"isContentVideoLoading\" class=\"cqa-p-10 cqa-text-center cqa-h-full cqa-flex cqa-flex-col cqa-items-center cqa-justify-center\">\n <div class=\"cqa-mb-4\">\n <mat-progress-spinner mode=\"indeterminate\" diameter=\"40\"></mat-progress-spinner>\n </div>\n <p class=\"cqa-text-gray-400 cqa-text-sm\">{{ liveLoadingLabel }}</p>\n </div>\n \n <!-- Live Content (when not loading) -->\n <div *ngIf=\"!isContentVideoLoading\" class=\"cqa-w-full cqa-h-full cqa-flex cqa-flex-col cqa-items-center cqa-justify-center cqa-relative\">\n <div *ngIf=\"liveStatus === 'Failed' && failedStatusMessage\" class=\"cqa-p-6 cqa-text-center cqa-w-full\">\n <div class=\"cqa-inline-flex cqa-items-center cqa-gap-2 cqa-px-4 cqa-py-3 cqa-bg-[#FCD9D9] cqa-border cqa-border-[#F9BFBF] cqa-rounded-lg\">\n <mat-icon style=\"width: 18px; height: 18px; color: #C63535; font-size: 18px;\">error</mat-icon>\n <p class=\"cqa-text-[#C63535] cqa-text-sm cqa-font-medium cqa-m-0\">{{ failedStatusMessage }}</p>\n </div>\n </div>\n <ng-content *ngIf=\"liveStatus !== 'Failed' || !failedStatusMessage\"></ng-content>\n </div>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n \n <!-- Normal Video View (when not live) -->\n <div *ngIf=\"!isLive && currentView === 'video'\" class=\"cqa-h-full cqa-flex cqa-flex-col cqa-justify-center\">\n <div class=\"cqa-w-full cqa-py-4 cqa-flex cqa-items-center cqa-max-h-[calc(100%-35px)]\" *ngIf=\"videoUrl\" [ngClass]=\"{'!cqa-h-full': platformType === 'device', 'cqa-mt-auto': hasDeviceFrame}\">\n <ng-container *ngIf=\"hasDeviceFrame\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-p-4': platformType === 'browser'}\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center cqa-max-h-[500px]\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser'}\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-max-h-full cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-bg-white': platformType !== 'browser'}\">\n <video\n #vplayer\n class=\"cqa-object-contain cqa-w-full cqa-h-full cqa-block cqa-bg-[##F2F2F2]\"\n [src]=\"videoUrl\"\n type=\"video/webm\"\n [ngClass]=\"{'cqa-z-20': platformType === 'browser'}\"\n (loadedmetadata)=\"onVideoMetadataLoaded()\"\n (canplay)=\"onVideoCanPlay()\"\n (ended)=\"onVideoEnded()\"\n ></video>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!videoUrl\">\n No video recording found\n </div>\n \n <div class=\"cqa-px-2 cqa-py-2 cqa-bg-white\" style=\"border-top: 1px solid #E5E7EB;\" [ngClass]=\"{'cqa-mt-auto': hasDeviceFrame}\" *ngIf=\"videoUrl && !isLive\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <button \n type=\"button\"\n class=\"cqa-bg-transparent cqa-border-none cqa-cursor-pointer !cqa-px-0 cqa-flex cqa-items-center cqa-justify-center hover:cqa-opacity-70 cqa-transition-opacity cqa-outline-none\"\n style=\"pointer-events: auto;\"\n (click)=\"togglePlay()\">\n <span *ngIf=\"!isPlaying\" class=\"cqa-flex cqa-items-center cqa-justify-center\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M3 2L13 8L3 14V2Z\" fill=\"#374151\"/>\n </svg>\n </span>\n <span *ngIf=\"isPlaying\" class=\"cqa-flex cqa-items-center cqa-justify-center\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"3\" y=\"2\" width=\"3\" height=\"12\" fill=\"#374151\"/>\n <rect x=\"10\" y=\"2\" width=\"3\" height=\"12\" fill=\"#374151\"/>\n </svg>\n </span>\n </button>\n \n <span class=\"cqa-text-[#9CA3AF] cqa-text-[9px] cqa-font-normal cqa-whitespace-nowrap cqa-select-none cqa-mr-[20px]\">\n {{ formatTime(vplayer?.nativeElement?.currentTime || 0) }}\n </span>\n \n <div \n #timelineBar\n class=\"cqa-relative cqa-h-1 cqa-bg-gray-200 cqa-rounded-full cqa-cursor-pointer cqa-flex-1\"\n (click)=\"onTimelineClick($event)\">\n \n <div \n *ngFor=\"let step of stepMarkers\" \n class=\"cqa-absolute cqa-w-1 cqa-h-full cqa-top-0 cqa-rounded-sm\"\n [style.left.%]=\"getStepLeftPosition(step)\"\n [style.background]=\"getStepColor(step)\"\n style=\"pointer-events: none; z-index: 20;\">\n </div>\n \n <div \n class=\"cqa-absolute cqa-left-0 cqa-top-0 cqa-h-full cqa-bg-green-500 cqa-rounded-full\"\n [style.width.%]=\"progress\"\n [style.transition]=\"dragging ? 'none' : 'width 100ms'\"\n style=\"pointer-events: none; z-index: 2;\">\n </div>\n \n <div \n class=\"cqa-absolute cqa-top-1/2 cqa-w-3 cqa-h-3 cqa-bg-green-600 cqa-rounded-full cqa-cursor-grab active:cqa-cursor-grabbing cqa-shadow-md\"\n [style.left.%]=\"progress\"\n style=\"transform: translate(-50%, -50%); z-index: 10;\"\n (mousedown)=\"startDrag($event)\">\n </div>\n </div>\n </div>\n </div>\n </div>\n \n <div *ngIf=\"!isLive && currentView === 'screenshots'\" class=\"cqa-h-full\">\n <div class=\"cqa-w-full cqa-py-4 cqa-h-full cqa-flex cqa-items-center\" *ngIf=\"screenShotUrl\">\n <ng-container *ngIf=\"hasDeviceFrame\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-p-4': platformType === 'browser'}\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center cqa-max-h-[500px]\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser'}\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-max-h-full cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-bg-white': platformType !== 'browser'}\">\n <img\n [src]=\"screenShotUrl\"\n alt=\"Screenshot\"\n [ngClass]=\"{'cqa-z-20': platformType === 'browser'}\"\n class=\"cqa-object-contain cqa-w-full cqa-h-full cqa-block cqa-bg-[##F2F2F2]\"\n />\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!screenShotUrl\">\n No screenshot available\n </div>\n </div>\n \n <div *ngIf=\"!isLive && currentView === 'trace'\" class=\"cqa-h-full cqa-flex cqa-flex-col cqa-justify-center\">\n <div class=\"cqa-w-full cqa-h-full cqa-py-4 cqa-flex cqa-items-center cqa-relative\" *ngIf=\"traceViewUrl\" [ngClass]=\"{'!cqa-h-full': platformType === 'device'}\">\n <iframe \n [src]=\"safeTraceUrl\" \n title=\"Trace Viewer\"\n class=\"cqa-object-contain cqa-w-full cqa-min-h-[250px] cqa-max-h-full cqa-block cqa-bg-[##F2F2F2]\"\n frameborder=\"0\"\n allowfullscreen\n width=\"100%\"\n height=\"100%\"\n loading=\"lazy\"\n (load)=\"onTraceViewerLoad()\"\n (error)=\"onTraceViewerError()\">\n </iframe>\n \n <div *ngIf=\"traceViewerLoading\" class=\"cqa-absolute cqa-inset-0 cqa-bg-[#F3F4F6] cqa-flex cqa-items-center cqa-justify-center cqa-z-10\">\n <div class=\"cqa-text-center cqa-text-gray-400 cqa-text-sm\">\n Loading trace viewer...\n </div>\n </div>\n \n <div *ngIf=\"traceViewerError\" class=\"cqa-absolute cqa-inset-0 cqa-bg-[#F3F4F6] cqa-flex cqa-items-center cqa-justify-center cqa-z-10\">\n <div class=\"cqa-text-center cqa-text-gray-400 cqa-text-sm\">\n Failed to load trace viewer\n </div>\n </div>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!traceViewUrl\">\n No trace available\n </div>\n </div> \n </ng-container>\n </div>\n</div>", styles: [] }]
10182
+ args: [{ selector: 'cqa-simulator', template: "<div class=\"cqa-ui-root\" style=\"background-color: #F3F4F6; height: 100%; display: flex; flex-direction: column;\" [ngStyle]=\"{\n position: isFullScreen ? 'fixed' : null,\n inset: isFullScreen ? '1rem' : null,\n zIndex: isFullScreen ? '50' : null,\n boxShadow: isFullScreen ? '0px 13px 25px -12px rgba(0, 0, 0, 0.25)' : null,\n borderRadius: isFullScreen ? '.5rem' : null,\n border: isFullScreen ? '1px solid #E5E7EB' : null,\n width: isFullScreen ? 'calc(100% - 32px)' : null,\n height: isFullScreen ? 'calc(100% - 32px)' : '100%',\n overflow: isFullScreen ? 'hidden' : null\n}\">\n <div class=\"cqa-w-full cqa-py-1 cqa-px-2 cqa-bg-[#FFFFFF]\" style=\"border-bottom: 1px solid #E5E7EB;box-shadow: 0px 1px 2px 0px #0000000D;\">\n <div class=\"cqa-w-full cqa-flex cqa-items-center cqa-justify-between\">\n <div class=\"cqa-flex cqa-items-center\">\n <div *ngIf=\"isLive\" class=\"cqa-h-[21px] cqa-inline-flex cqa-items-center cqa-gap-1.5 cqa-mr-2 cqa-px-[9px] cqa-py-[3px] cqa-bg-[#FCD9D9] cqa-rounded-[6px]\" style=\"border: 1px solid #F9BFBF;\">\n <span class=\"cqa-relative cqa-w-2 cqa-h-2 cqa-rounded-full cqa-bg-[#F47F7F]\" style=\"flex-shrink: 0;\">\n <span class=\"cqa-absolute cqa-inset-0 cqa-rounded-full cqa-bg-[#F47F7F] cqa-opacity-75 cqa-animate-ping\"></span>\n </span>\n <span class=\"cqa-text-[10px] cqa-font-medium cqa-text-[#C63535] cqa-leading-[15px]\">Live</span>\n </div>\n <mat-icon *ngIf=\"platformType === 'browser'\" style=\"width: 10px; height: 10px;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <g clip-path=\"url(#clip0_935_15847)\">\n <path\n d=\"M0.625 5C0.625 6.16032 1.08594 7.27312 1.90641 8.09359C2.72688 8.91406 3.83968 9.375 5 9.375C6.16032 9.375 7.27312 8.91406 8.09359 8.09359C8.91406 7.27312 9.375 6.16032 9.375 5C9.375 3.83968 8.91406 2.72688 8.09359 1.90641C7.27312 1.08594 6.16032 0.625 5 0.625C3.83968 0.625 2.72688 1.08594 1.90641 1.90641C1.08594 2.72688 0.625 3.83968 0.625 5Z\"\n stroke=\"#9CA3AF\" stroke-width=\"0.6\" stroke-linejoin=\"round\" />\n <path\n d=\"M3.125 5C3.125 3.83968 3.32254 2.72688 3.67417 1.90641C4.02581 1.08594 4.50272 0.625 5 0.625C5.49728 0.625 5.97419 1.08594 6.32582 1.90641C6.67746 2.72688 6.875 3.83968 6.875 5C6.875 6.16032 6.67746 7.27312 6.32582 8.09359C5.97419 8.91406 5.49728 9.375 5 9.375C4.50272 9.375 4.02581 8.91406 3.67417 8.09359C3.32254 7.27312 3.125 6.16032 3.125 5Z\"\n stroke=\"#9CA3AF\" stroke-width=\"0.6\" stroke-linejoin=\"round\" />\n <path d=\"M0.9375 6.45866H9.0625M0.9375 3.54199H9.0625\" stroke=\"#9CA3AF\" stroke-width=\"0.6\"\n stroke-linecap=\"round\" />\n </g>\n <defs>\n <clipPath id=\"clip0_935_15847\">\n <rect width=\"10\" height=\"10\" fill=\"white\" />\n </clipPath>\n </defs>\n </svg>\n </mat-icon>\n <mat-icon *ngIf=\"platformType === 'device'\" style=\"width: 10px; height: 10px;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M7.08325 0.833008H2.91659C2.45635 0.833008 2.08325 1.2061 2.08325 1.66634V8.33301C2.08325 8.79324 2.45635 9.16634 2.91659 9.16634H7.08325C7.54349 9.16634 7.91658 8.79324 7.91658 8.33301V1.66634C7.91658 1.2061 7.54349 0.833008 7.08325 0.833008Z\" stroke=\"#6B7280\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M5 7.5H5.00417\" stroke=\"#6B7280\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </mat-icon>\n <p class=\"cqa-text-sm !cqa-text-[10px] cqa-text-[#6B7280] cqa-ml-2\">\n {{ platformName }}\n <span\n *ngIf=\"platformType === 'browser'\"\n class=\"cqa-ml-1\"\n matTooltip=\"Screen size: 1920x1080\"\n matTooltipPosition=\"below\"\n >\n \u00B7 <span class=\"cqa-ml-1\">1920x1080</span>\n </span>\n </p>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div *ngIf=\"isLive\" [ngClass]=\"getStatusBadgeClass()\">\n <span [ngClass]=\"getStatusTextClass()\">{{ liveStatus }}</span>\n </div>\n\n <ng-container *ngIf=\"!isLive\">\n <cqa-segment-control \n [segments]=\"segments\" \n [value]=\"currentView\"\n (valueChange)=\"onSegmentChange($event)\">\n </cqa-segment-control>\n \n <div *ngIf=\"!isFullScreen\" \n class=\"cqa-p-1 cqa-cursor-pointer hover:cqa-bg-gray-100 cqa-rounded-sm cqa-transition-colors\"\n (click)=\"toggleFullScreen()\"\n title=\"Expand\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M6.25 1.25H8.75V3.75\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M8.74992 1.25L5.83325 4.16667\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M1.25 8.74967L4.16667 5.83301\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M3.75 8.75H1.25V6.25\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n\n <div *ngIf=\"isFullScreen\" \n class=\"cqa-p-1 cqa-cursor-pointer hover:cqa-bg-gray-100 cqa-rounded-sm cqa-transition-colors\"\n (click)=\"toggleFullScreen()\"\n title=\"Exit full screen\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M8.75 6.25H6.25V8.75\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6.25008 6.25L9.16675 9.16667\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M0.833252 0.833008L3.74992 3.74967\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M1.25 3.75H3.75V1.25\" stroke=\"#9CA3AF\" stroke-width=\"0.833333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n </ng-container>\n </div>\n </div>\n </div>\n <div class=\"cqa-w-full cqa-bg-[#F3F4F6] cqa-h-[calc(100%-41px)]\">\n <!-- Live Content View -->\n <div *ngIf=\"isLive\" class=\"cqa-h-full cqa-flex cqa-flex-col cqa-justify-center cqa-relative\">\n <ng-container *ngIf=\"hasDeviceFrame;\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-p-4': platformType === 'browser'}\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser', 'cqa-max-h-[500px] cqa-h-full': platformType !== 'browser' || !isLive, 'cqa-h-auto': isLive && platformType === 'browser' }\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-max-h-full cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-z-20': platformType === 'browser', 'cqa-bg-white': platformType !== 'browser'}\">\n <!-- Loading State -->\n <div *ngIf=\"isContentVideoLoading\" class=\"cqa-p-10 cqa-text-center cqa-h-full cqa-flex cqa-flex-col cqa-items-center cqa-justify-center\">\n <div class=\"cqa-mb-4\">\n <mat-progress-spinner mode=\"indeterminate\" diameter=\"40\"></mat-progress-spinner>\n </div>\n <p class=\"cqa-text-gray-400 cqa-text-sm\">{{ liveLoadingLabel }}</p>\n </div>\n\n <!-- Live Content (when not loading) -->\n <div *ngIf=\"!isContentVideoLoading\" class=\"cqa-w-full cqa-h-full cqa-flex cqa-flex-col cqa-items-center cqa-justify-center cqa-relative\">\n <div *ngIf=\"liveStatus === 'Failed' && failedStatusMessage\" class=\"cqa-p-6 cqa-text-center cqa-w-full\">\n <div class=\"cqa-inline-flex cqa-items-center cqa-gap-2 cqa-px-4 cqa-py-3 cqa-bg-[#FCD9D9] cqa-border cqa-border-[#F9BFBF] cqa-rounded-lg\">\n <mat-icon style=\"width: 18px; height: 18px; color: #C63535; font-size: 18px;\">error</mat-icon>\n <p class=\"cqa-text-[#C63535] cqa-text-sm cqa-font-medium cqa-m-0\">{{ failedStatusMessage }}</p>\n </div>\n </div>\n <ng-content *ngIf=\"liveStatus !== 'Failed' || !failedStatusMessage\"></ng-content>\n </div>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n\n <!-- Normal Video View (when not live) -->\n <div *ngIf=\"!isLive && currentView === 'video'\" class=\"cqa-h-full cqa-flex cqa-flex-col cqa-justify-center\">\n <div class=\"cqa-w-full cqa-py-4 cqa-flex cqa-items-center cqa-max-h-[calc(100%-35px)]\" *ngIf=\"currentVideoUrl\" [ngClass]=\"{'!cqa-h-full': platformType === 'device', 'cqa-mt-auto': hasDeviceFrame}\">\n <ng-container *ngIf=\"hasDeviceFrame\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-p-4': platformType === 'browser'}\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center cqa-max-h-[500px]\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser'}\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-max-h-full cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-bg-white': platformType !== 'browser'}\">\n <video\n #vplayer\n class=\"cqa-object-cover cqa-w-full cqa-h-full cqa-block cqa-bg-[##F2F2F2]\"\n [src]=\"currentVideoUrl\"\n type=\"video/webm\"\n [ngClass]=\"{'cqa-z-20': platformType === 'browser'}\"\n (loadedmetadata)=\"onVideoMetadataLoaded()\"\n (canplay)=\"onVideoCanPlay()\"\n (ended)=\"onVideoEnded()\"\n ></video>\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!currentVideoUrl\">\n No video recording found\n </div>\n \n <div class=\"cqa-px-2 cqa-py-2 cqa-bg-white\" style=\"border-top: 1px solid #E5E7EB;\" [ngClass]=\"{'cqa-mt-auto': hasDeviceFrame}\" *ngIf=\"currentVideoUrl && !isLive\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <button \n *ngIf=\"hasMultipleVideos\"\n type=\"button\"\n class=\"cqa-bg-transparent cqa-border-none cqa-cursor-pointer !cqa-px-0 cqa-flex cqa-items-center cqa-justify-center hover:cqa-opacity-70 cqa-transition-opacity cqa-outline-none\"\n style=\"pointer-events: auto;\"\n [disabled]=\"currentVideoIndex === 0\"\n [ngClass]=\"{'cqa-opacity-50 cqa-cursor-not-allowed': currentVideoIndex === 0}\"\n (click)=\"prevVideo()\"\n matTooltip=\"Previous video\"\n matTooltipPosition=\"above\">\n <mat-icon class=\"cqa-w-4 cqa-h-4 !cqa-text-[16px] cqa-text-[#374151]\" [ngClass]=\"{'cqa-opacity-50 cqa-cursor-not-allowed': currentVideoIndex === 0}\">skip_previous</mat-icon>\n </button>\n\n <button \n type=\"button\"\n class=\"cqa-bg-transparent cqa-border-none cqa-cursor-pointer !cqa-px-0 cqa-flex cqa-items-center cqa-justify-center hover:cqa-opacity-70 cqa-transition-opacity cqa-outline-none\"\n style=\"pointer-events: auto;\"\n (click)=\"togglePlay()\"\n matTooltip=\"{{ isPlaying ? 'Pause' : 'Play' }}\"\n matTooltipPosition=\"above\">\n <span *ngIf=\"!isPlaying\" class=\"cqa-flex cqa-items-center cqa-justify-center\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M3 2L13 8L3 14V2Z\" fill=\"#374151\"/>\n </svg>\n </span>\n <span *ngIf=\"isPlaying\" class=\"cqa-flex cqa-items-center cqa-justify-center\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"3\" y=\"2\" width=\"3\" height=\"12\" fill=\"#374151\"/>\n <rect x=\"10\" y=\"2\" width=\"3\" height=\"12\" fill=\"#374151\"/>\n </svg>\n </span>\n </button>\n \n <button \n *ngIf=\"hasMultipleVideos\"\n type=\"button\"\n class=\"cqa-bg-transparent cqa-border-none cqa-cursor-pointer !cqa-px-0 cqa-flex cqa-items-center cqa-justify-center hover:cqa-opacity-70 cqa-transition-opacity cqa-outline-none\"\n style=\"pointer-events: auto;\"\n [disabled]=\"videoUrls && (currentVideoIndex >= videoUrls.length - 1)\"\n [ngClass]=\"{'cqa-opacity-50 cqa-cursor-not-allowed': videoUrls && (currentVideoIndex >= videoUrls.length - 1)}\"\n (click)=\"nextVideo()\"\n matTooltip=\"Next video\"\n matTooltipPosition=\"above\">\n <mat-icon class=\"cqa-w-4 cqa-h-4 !cqa-text-[16px] cqa-text-[#374151]\" [ngClass]=\"{'cqa-opacity-50 cqa-cursor-not-allowed': videoUrls && (currentVideoIndex >= videoUrls.length - 1)}\">skip_next</mat-icon>\n </button>\n\n <span class=\"cqa-text-[#9CA3AF] cqa-text-[9px] cqa-font-normal cqa-whitespace-nowrap cqa-select-none cqa-mr-[20px]\">\n {{ formatTime(vplayer?.nativeElement?.currentTime || 0) }}\n </span>\n \n <div \n #timelineBar\n class=\"cqa-relative cqa-h-1 cqa-bg-gray-200 cqa-rounded-full cqa-cursor-pointer cqa-flex-1\"\n (click)=\"onTimelineClick($event)\">\n \n <div \n *ngFor=\"let step of stepMarkers\" \n class=\"cqa-absolute cqa-w-1 cqa-h-full cqa-top-0 cqa-rounded-sm\"\n [style.left.%]=\"getStepLeftPosition(step)\"\n [style.background]=\"getStepColor(step)\"\n style=\"pointer-events: none; z-index: 20;\">\n </div>\n \n <div \n class=\"cqa-absolute cqa-left-0 cqa-top-0 cqa-h-full cqa-bg-green-500 cqa-rounded-full\"\n [style.width.%]=\"progress\"\n [style.transition]=\"dragging ? 'none' : 'width 100ms'\"\n style=\"pointer-events: none; z-index: 2;\">\n </div>\n \n <div \n class=\"cqa-absolute cqa-top-1/2 cqa-w-3 cqa-h-3 cqa-bg-green-600 cqa-rounded-full cqa-cursor-grab active:cqa-cursor-grabbing cqa-shadow-md\"\n [style.left.%]=\"progress\"\n style=\"transform: translate(-50%, -50%); z-index: 10;\"\n (mousedown)=\"startDrag($event)\">\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"!isLive && currentView === 'screenshots'\" class=\"cqa-h-full\">\n <div class=\"cqa-w-full cqa-py-4 cqa-h-full cqa-flex cqa-items-center\" *ngIf=\"screenShotUrl\">\n <ng-container *ngIf=\"hasDeviceFrame\">\n <div class=\"cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" [ngClass]=\"{'cqa-p-4': platformType === 'browser'}\">\n <div class=\"cqa-relative cqa-h-full cqa-w-auto cqa-flex cqa-items-center cqa-justify-center cqa-max-h-[500px]\" [ngClass]=\"{'cqa-rounded-md cqa-overflow-hidden': platformType === 'browser', '!cqa-h-auto': platformType === 'browser', 'cqa-h-full': platformType !== 'browser'}\">\n <img\n [src]=\"deviceMockupImage\"\n alt=\"Device mockup\"\n class=\"cqa-h-full cqa-w-auto cqa-object-contain cqa-block cqa-pointer-events-none cqa-z-10\"\n [ngClass]=\"{'cqa-max-h-[inherit]': platformType === 'browser', 'cqa-max-h-full': platformType !== 'browser'}\"\n />\n <div class=\"cqa-absolute cqa-flex cqa-flex-col\" [ngStyle]=\"deviceScreenStyle\" [ngClass]=\"{'cqa-bg-white': platformType !== 'browser'}\">\n <img\n [src]=\"screenShotUrl\"\n alt=\"Screenshot\"\n [ngClass]=\"{'cqa-z-20': platformType === 'browser'}\"\n class=\"cqa-object-contain cqa-w-full cqa-h-full cqa-block cqa-bg-[##F2F2F2]\"\n />\n </div>\n </div>\n </div>\n </ng-container>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!screenShotUrl\">\n No screenshot available\n </div>\n </div>\n\n <div *ngIf=\"!isLive && currentView === 'trace'\" class=\"cqa-h-full cqa-flex cqa-flex-col cqa-justify-center\">\n <div class=\"cqa-w-full cqa-h-full cqa-py-4 cqa-flex cqa-items-center cqa-relative\" *ngIf=\"traceViewUrl\" [ngClass]=\"{'!cqa-h-full': platformType === 'device'}\">\n <iframe \n [src]=\"safeTraceUrl\" \n title=\"Trace Viewer\"\n class=\"cqa-object-contain cqa-w-full cqa-min-h-[250px] cqa-max-h-full cqa-block cqa-bg-[##F2F2F2]\"\n frameborder=\"0\"\n allowfullscreen\n width=\"100%\"\n height=\"100%\"\n loading=\"lazy\"\n (load)=\"onTraceViewerLoad()\"\n (error)=\"onTraceViewerError()\">\n </iframe>\n \n <div *ngIf=\"traceViewerLoading\" class=\"cqa-absolute cqa-inset-0 cqa-bg-[#F3F4F6] cqa-flex cqa-items-center cqa-justify-center cqa-z-10\">\n <div class=\"cqa-text-center cqa-text-gray-400 cqa-text-sm\">\n Loading trace viewer...\n </div>\n </div>\n \n <div *ngIf=\"traceViewerError\" class=\"cqa-absolute cqa-inset-0 cqa-bg-[#F3F4F6] cqa-flex cqa-items-center cqa-justify-center cqa-z-10\">\n <div class=\"cqa-text-center cqa-text-gray-400 cqa-text-sm\">\n Failed to load trace viewer\n </div>\n </div>\n </div>\n \n <div class=\"cqa-p-10 cqa-text-center cqa-text-gray-400 cqa-text-sm cqa-h-full cqa-flex cqa-items-center cqa-justify-center\" *ngIf=\"!traceViewUrl\">\n No trace available\n </div>\n </div> \n </div>\n</div>", styles: [] }]
10117
10183
  }], ctorParameters: function () { return [{ type: i1$1.DomSanitizer }]; }, propDecorators: { videoUrl: [{
10118
10184
  type: Input
10185
+ }], videoUrls: [{
10186
+ type: Input
10119
10187
  }], videoCurrentDuration: [{
10120
10188
  type: Input
10121
10189
  }], stepMarkers: [{
@@ -10150,9 +10218,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
10150
10218
  type: Output
10151
10219
  }], videoPause: [{
10152
10220
  type: Output
10153
- }], vplayer: [{
10221
+ }], vplayerRef: [{
10154
10222
  type: ViewChild,
10155
- args: ['vplayer', { static: false }]
10223
+ args: ['vplayer']
10156
10224
  }], timelineBar: [{
10157
10225
  type: ViewChild,
10158
10226
  args: ['timelineBar', { static: false }]