@eric-emg/symphiq-components 1.2.249 → 1.2.251

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.
@@ -54818,6 +54818,7 @@ function PacingStatusBadgeComponent_Conditional_0_Template(rf, ctx) { if (rf & 1
54818
54818
  } if (rf & 2) {
54819
54819
  const ctx_r0 = i0.ɵɵnextContext();
54820
54820
  i0.ɵɵclassMap(ctx_r0.containerSizeClasses());
54821
+ i0.ɵɵstyleProp("transform", ctx_r0.rotationStyle());
54821
54822
  i0.ɵɵproperty("ngClass", ctx_r0.containerClasses());
54822
54823
  i0.ɵɵadvance();
54823
54824
  i0.ɵɵclassMap(ctx_r0.overlaySizeClasses());
@@ -54844,6 +54845,7 @@ function PacingStatusBadgeComponent_Conditional_1_Template(rf, ctx) { if (rf & 1
54844
54845
  } if (rf & 2) {
54845
54846
  const ctx_r0 = i0.ɵɵnextContext();
54846
54847
  i0.ɵɵclassMap(ctx_r0.fullBadgeSizeClasses());
54848
+ i0.ɵɵstyleProp("transform", ctx_r0.fullBadgeRotationStyle());
54847
54849
  i0.ɵɵproperty("ngClass", ctx_r0.badgeClasses());
54848
54850
  i0.ɵɵadvance();
54849
54851
  i0.ɵɵclassMap(ctx_r0.iconSizeClasses());
@@ -54854,7 +54856,8 @@ function PacingStatusBadgeComponent_Conditional_1_Template(rf, ctx) { if (rf & 1
54854
54856
  i0.ɵɵtextInterpolate(ctx_r0.displayText());
54855
54857
  } }
54856
54858
  class PacingStatusBadgeComponent {
54857
- constructor() {
54859
+ constructor(elementRef) {
54860
+ this.elementRef = elementRef;
54858
54861
  this.viewMode = input(ViewModeEnum.LIGHT, ...(ngDevMode ? [{ debugName: "viewMode" }] : []));
54859
54862
  this.pacingPercentage = input(0, ...(ngDevMode ? [{ debugName: "pacingPercentage" }] : []));
54860
54863
  this.status = input('on-pace', ...(ngDevMode ? [{ debugName: "status" }] : []));
@@ -54862,6 +54865,9 @@ class PacingStatusBadgeComponent {
54862
54865
  this.isCompact = input(false, ...(ngDevMode ? [{ debugName: "isCompact" }] : []));
54863
54866
  this.showEmphasizedPercentage = input(false, ...(ngDevMode ? [{ debugName: "showEmphasizedPercentage" }] : []));
54864
54867
  this.animatedValue = signal(0, ...(ngDevMode ? [{ debugName: "animatedValue" }] : []));
54868
+ this.animationProgress = signal(0, ...(ngDevMode ? [{ debugName: "animationProgress" }] : []));
54869
+ this.hasAnimated = signal(false, ...(ngDevMode ? [{ debugName: "hasAnimated" }] : []));
54870
+ this.observer = null;
54865
54871
  this.displayInfo = computed(() => {
54866
54872
  const isDark = this.viewMode() === ViewModeEnum.DARK;
54867
54873
  return getPacingDisplayInfo(this.pacingPercentage(), this.status(), isDark);
@@ -54870,14 +54876,28 @@ class PacingStatusBadgeComponent {
54870
54876
  const info = this.displayInfo();
54871
54877
  return `${info.bgClass} ${info.borderClass} border`;
54872
54878
  }, ...(ngDevMode ? [{ debugName: "containerClasses" }] : []));
54879
+ this.targetRotation = computed(() => {
54880
+ const status = this.status();
54881
+ return status === 'ahead' ? -1 : status === 'behind' ? 1 : 0;
54882
+ }, ...(ngDevMode ? [{ debugName: "targetRotation" }] : []));
54883
+ this.rotationStyle = computed(() => {
54884
+ const progress = this.animationProgress();
54885
+ const target = this.targetRotation();
54886
+ const currentRotation = progress * target;
54887
+ return `rotate(${currentRotation}deg)`;
54888
+ }, ...(ngDevMode ? [{ debugName: "rotationStyle" }] : []));
54889
+ this.fullBadgeRotationStyle = computed(() => {
54890
+ const progress = this.animationProgress();
54891
+ const target = this.targetRotation();
54892
+ const currentRotation = progress * target;
54893
+ return `rotate(${currentRotation}deg)`;
54894
+ }, ...(ngDevMode ? [{ debugName: "fullBadgeRotationStyle" }] : []));
54873
54895
  this.containerSizeClasses = computed(() => {
54874
54896
  const compact = this.isCompact();
54875
- const status = this.status();
54876
- const tiltClass = status === 'ahead' ? '-rotate-1' : status === 'behind' ? 'rotate-1' : '';
54877
54897
  const baseClasses = 'inline-flex flex-row items-center rounded-xl border-2 overflow-visible transition-transform hover:rotate-0';
54878
54898
  return compact
54879
- ? `${baseClasses} pl-1.5 ${tiltClass}`
54880
- : `${baseClasses} pl-2 ${tiltClass}`;
54899
+ ? `${baseClasses} pl-1.5`
54900
+ : `${baseClasses} pl-2`;
54881
54901
  }, ...(ngDevMode ? [{ debugName: "containerSizeClasses" }] : []));
54882
54902
  this.badgeClasses = computed(() => {
54883
54903
  const info = this.displayInfo();
@@ -54893,9 +54913,7 @@ class PacingStatusBadgeComponent {
54893
54913
  }, ...(ngDevMode ? [{ debugName: "sizeClasses" }] : []));
54894
54914
  this.fullBadgeSizeClasses = computed(() => {
54895
54915
  const isCompact = this.isCompact();
54896
- const status = this.status();
54897
- const tiltClass = status === 'ahead' ? '-rotate-1' : status === 'behind' ? 'rotate-1' : '';
54898
- const baseClasses = `inline-flex items-center gap-1.5 rounded-xl border-2 font-bold tracking-wide shadow-md transition-all hover:rotate-0 ${tiltClass}`;
54916
+ const baseClasses = 'inline-flex items-center gap-1.5 rounded-xl border-2 font-bold tracking-wide shadow-md transition-all hover:rotate-0';
54899
54917
  if (isCompact) {
54900
54918
  return `${baseClasses} px-2.5 py-1 text-xs`;
54901
54919
  }
@@ -54964,14 +54982,34 @@ class PacingStatusBadgeComponent {
54964
54982
  this.overlaySizeClasses = computed(() => {
54965
54983
  const compact = this.isCompact();
54966
54984
  return compact
54967
- ? 'px-2 py-1.5 rounded-lg text-sm font-extrabold tracking-wide shadow-md transition-all duration-200 -my-1 -mr-1 z-10 inline-flex items-center gap-0.5'
54968
- : 'px-2.5 py-2 rounded-lg text-sm font-extrabold tracking-wide shadow-md transition-all duration-200 -my-1.5 -mr-1 z-10 inline-flex items-center gap-1';
54985
+ ? 'px-2 py-1.5 rounded-lg text-sm font-extrabold tracking-wide shadow-md transition-all duration-200 -my-1 -mr-1 z-10 inline-flex items-center gap-0.5 tabular-nums'
54986
+ : 'px-2.5 py-2 rounded-lg text-sm font-extrabold tracking-wide shadow-md transition-all duration-200 -my-1.5 -mr-1 z-10 inline-flex items-center gap-1 tabular-nums';
54969
54987
  }, ...(ngDevMode ? [{ debugName: "overlaySizeClasses" }] : []));
54988
+ this.setupIntersectionObserver();
54970
54989
  effect(() => {
54971
54990
  const target = Math.abs(this.pacingPercentage());
54972
- this.animateValue(target);
54991
+ if (this.hasAnimated()) {
54992
+ this.animateValue(target);
54993
+ }
54973
54994
  });
54974
54995
  }
54996
+ ngOnDestroy() {
54997
+ if (this.observer) {
54998
+ this.observer.disconnect();
54999
+ }
55000
+ }
55001
+ setupIntersectionObserver() {
55002
+ this.observer = new IntersectionObserver((entries) => {
55003
+ entries.forEach((entry) => {
55004
+ if (entry.isIntersecting && !this.hasAnimated()) {
55005
+ this.hasAnimated.set(true);
55006
+ const target = Math.abs(this.pacingPercentage());
55007
+ this.animateValue(target);
55008
+ }
55009
+ });
55010
+ }, { threshold: 0.1 });
55011
+ this.observer.observe(this.elementRef.nativeElement);
55012
+ }
54975
55013
  animateValue(target) {
54976
55014
  const start = 0;
54977
55015
  const duration = 800;
@@ -54982,15 +55020,16 @@ class PacingStatusBadgeComponent {
54982
55020
  const easeOutQuart = 1 - Math.pow(1 - progress, 4);
54983
55021
  const current = start + (target - start) * easeOutQuart;
54984
55022
  this.animatedValue.set(current);
55023
+ this.animationProgress.set(progress);
54985
55024
  if (progress < 1) {
54986
55025
  requestAnimationFrame(animate);
54987
55026
  }
54988
55027
  };
54989
55028
  requestAnimationFrame(animate);
54990
55029
  }
54991
- static { this.ɵfac = function PacingStatusBadgeComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || PacingStatusBadgeComponent)(); }; }
54992
- static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: PacingStatusBadgeComponent, selectors: [["symphiq-pacing-status-badge"]], inputs: { viewMode: [1, "viewMode"], pacingPercentage: [1, "pacingPercentage"], status: [1, "status"], showAsFullText: [1, "showAsFullText"], isCompact: [1, "isCompact"], showEmphasizedPercentage: [1, "showEmphasizedPercentage"] }, decls: 2, vars: 1, consts: [[3, "ngClass", "class"], [3, "ngClass"]], template: function PacingStatusBadgeComponent_Template(rf, ctx) { if (rf & 1) {
54993
- i0.ɵɵconditionalCreate(0, PacingStatusBadgeComponent_Conditional_0_Template, 8, 14, "div", 0)(1, PacingStatusBadgeComponent_Conditional_1_Template, 5, 8, "div", 0);
55030
+ static { this.ɵfac = function PacingStatusBadgeComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || PacingStatusBadgeComponent)(i0.ɵɵdirectiveInject(i0.ElementRef)); }; }
55031
+ static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: PacingStatusBadgeComponent, selectors: [["symphiq-pacing-status-badge"]], inputs: { viewMode: [1, "viewMode"], pacingPercentage: [1, "pacingPercentage"], status: [1, "status"], showAsFullText: [1, "showAsFullText"], isCompact: [1, "isCompact"], showEmphasizedPercentage: [1, "showEmphasizedPercentage"] }, decls: 2, vars: 1, consts: [[3, "ngClass", "class", "transform"], [3, "ngClass"]], template: function PacingStatusBadgeComponent_Template(rf, ctx) { if (rf & 1) {
55032
+ i0.ɵɵconditionalCreate(0, PacingStatusBadgeComponent_Conditional_0_Template, 8, 16, "div", 0)(1, PacingStatusBadgeComponent_Conditional_1_Template, 5, 10, "div", 0);
54994
55033
  } if (rf & 2) {
54995
55034
  i0.ɵɵconditional(ctx.showEmphasizedPercentage() && ctx.hasPercentage() ? 0 : 1);
54996
55035
  } }, dependencies: [CommonModule, i1$1.NgClass], encapsulation: 2, changeDetection: 0 }); }
@@ -55004,7 +55043,11 @@ class PacingStatusBadgeComponent {
55004
55043
  changeDetection: ChangeDetectionStrategy.OnPush,
55005
55044
  template: `
55006
55045
  @if (showEmphasizedPercentage() && hasPercentage()) {
55007
- <div [ngClass]="containerClasses()" [class]="containerSizeClasses()">
55046
+ <div
55047
+ [ngClass]="containerClasses()"
55048
+ [class]="containerSizeClasses()"
55049
+ [style.transform]="rotationStyle()"
55050
+ >
55008
55051
  <div [ngClass]="overlayBadgeClasses()" [class]="overlaySizeClasses()">
55009
55052
  <span [ngClass]="iconClasses()" [class]="iconSizeClasses()">
55010
55053
  {{ iconSymbol() }}
@@ -55021,6 +55064,7 @@ class PacingStatusBadgeComponent {
55021
55064
  <div
55022
55065
  [ngClass]="badgeClasses()"
55023
55066
  [class]="fullBadgeSizeClasses()"
55067
+ [style.transform]="fullBadgeRotationStyle()"
55024
55068
  >
55025
55069
  <span [ngClass]="iconClasses()" [class]="iconSizeClasses()">
55026
55070
  {{ iconSymbol() }}
@@ -55030,18 +55074,22 @@ class PacingStatusBadgeComponent {
55030
55074
  }
55031
55075
  `
55032
55076
  }]
55033
- }], () => [], { viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], pacingPercentage: [{ type: i0.Input, args: [{ isSignal: true, alias: "pacingPercentage", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], showAsFullText: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAsFullText", required: false }] }], isCompact: [{ type: i0.Input, args: [{ isSignal: true, alias: "isCompact", required: false }] }], showEmphasizedPercentage: [{ type: i0.Input, args: [{ isSignal: true, alias: "showEmphasizedPercentage", required: false }] }] }); })();
55034
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PacingStatusBadgeComponent, { className: "PacingStatusBadgeComponent", filePath: "lib/components/revenue-calculator-dashboard/pacing-status-badge.component.ts", lineNumber: 39 }); })();
55077
+ }], () => [{ type: i0.ElementRef }], { viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], pacingPercentage: [{ type: i0.Input, args: [{ isSignal: true, alias: "pacingPercentage", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], showAsFullText: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAsFullText", required: false }] }], isCompact: [{ type: i0.Input, args: [{ isSignal: true, alias: "isCompact", required: false }] }], showEmphasizedPercentage: [{ type: i0.Input, args: [{ isSignal: true, alias: "showEmphasizedPercentage", required: false }] }] }); })();
55078
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PacingStatusBadgeComponent, { className: "PacingStatusBadgeComponent", filePath: "lib/components/revenue-calculator-dashboard/pacing-status-badge.component.ts", lineNumber: 44 }); })();
55035
55079
 
55036
55080
  class TargetChangeBadgeComponent {
55037
- constructor() {
55081
+ constructor(elementRef) {
55082
+ this.elementRef = elementRef;
55038
55083
  this.viewMode = input(ViewModeEnum.LIGHT, ...(ngDevMode ? [{ debugName: "viewMode" }] : []));
55039
55084
  this.percentageChange = input(0, ...(ngDevMode ? [{ debugName: "percentageChange" }] : []));
55040
55085
  this.metric = input('', ...(ngDevMode ? [{ debugName: "metric" }] : []));
55041
55086
  this.priorYear = input(new Date().getFullYear() - 1, ...(ngDevMode ? [{ debugName: "priorYear" }] : []));
55042
55087
  this.isCompact = input(false, ...(ngDevMode ? [{ debugName: "isCompact" }] : []));
55043
55088
  this.animatedValue = signal(0, ...(ngDevMode ? [{ debugName: "animatedValue" }] : []));
55089
+ this.animationProgress = signal(0, ...(ngDevMode ? [{ debugName: "animationProgress" }] : []));
55090
+ this.hasAnimated = signal(false, ...(ngDevMode ? [{ debugName: "hasAnimated" }] : []));
55044
55091
  this.isDark = computed(() => this.viewMode() === ViewModeEnum.DARK, ...(ngDevMode ? [{ debugName: "isDark" }] : []));
55092
+ this.observer = null;
55045
55093
  this.isIncreaseBad = computed(() => {
55046
55094
  const metricStr = this.metric();
55047
55095
  if (!metricStr)
@@ -55072,14 +55120,22 @@ class TargetChangeBadgeComponent {
55072
55120
  : 'bg-purple-50 border-purple-200';
55073
55121
  }, ...(ngDevMode ? [{ debugName: "containerClasses" }] : []));
55074
55122
  this.isIncrease = computed(() => this.percentageChange() > 0, ...(ngDevMode ? [{ debugName: "isIncrease" }] : []));
55123
+ this.targetRotation = computed(() => {
55124
+ const change = this.percentageChange();
55125
+ return change > 0 ? -1 : change < 0 ? 1 : 0;
55126
+ }, ...(ngDevMode ? [{ debugName: "targetRotation" }] : []));
55127
+ this.rotationStyle = computed(() => {
55128
+ const progress = this.animationProgress();
55129
+ const target = this.targetRotation();
55130
+ const currentRotation = progress * target;
55131
+ return `rotate(${currentRotation}deg)`;
55132
+ }, ...(ngDevMode ? [{ debugName: "rotationStyle" }] : []));
55075
55133
  this.containerSizeClasses = computed(() => {
55076
55134
  const compact = this.isCompact();
55077
- const change = this.percentageChange();
55078
- const tiltClass = change > 0 ? '-rotate-1' : change < 0 ? 'rotate-1' : '';
55079
55135
  const baseClasses = 'inline-flex flex-row items-center rounded-xl border-2 overflow-visible transition-transform hover:rotate-0';
55080
55136
  return compact
55081
- ? `${baseClasses} pl-1.5 ${tiltClass}`
55082
- : `${baseClasses} pl-2 ${tiltClass}`;
55137
+ ? `${baseClasses} pl-1.5`
55138
+ : `${baseClasses} pl-2`;
55083
55139
  }, ...(ngDevMode ? [{ debugName: "containerSizeClasses" }] : []));
55084
55140
  this.overlayClasses = computed(() => {
55085
55141
  const dark = this.isDark();
@@ -55090,8 +55146,8 @@ class TargetChangeBadgeComponent {
55090
55146
  this.overlaySizeClasses = computed(() => {
55091
55147
  const compact = this.isCompact();
55092
55148
  return compact
55093
- ? 'px-2 py-1.5 rounded-lg text-sm font-extrabold tracking-wide shadow-md transition-all duration-200 -my-1 -mr-1 z-10 inline-flex items-center gap-0.5'
55094
- : 'px-2.5 py-2 rounded-lg font-extrabold text-base tracking-wide shadow-md transition-all duration-200 -my-1.5 -mr-1 z-10 inline-flex items-center gap-1';
55149
+ ? 'px-2 py-1.5 rounded-lg text-sm font-extrabold tracking-wide shadow-md transition-all duration-200 -my-1 -mr-1 z-10 inline-flex items-center gap-0.5 tabular-nums'
55150
+ : 'px-2.5 py-2 rounded-lg font-extrabold text-base tracking-wide shadow-md transition-all duration-200 -my-1.5 -mr-1 z-10 inline-flex items-center gap-1 tabular-nums';
55095
55151
  }, ...(ngDevMode ? [{ debugName: "overlaySizeClasses" }] : []));
55096
55152
  this.iconSizeClass = computed(() => {
55097
55153
  return this.isCompact() ? 'text-sm' : 'text-base';
@@ -55102,11 +55158,31 @@ class TargetChangeBadgeComponent {
55102
55158
  ? 'px-2.5 py-0.5 text-xs font-semibold inline-block'
55103
55159
  : 'px-3 py-0.5 font-semibold text-xs inline-block';
55104
55160
  }, ...(ngDevMode ? [{ debugName: "descriptionSizeClasses" }] : []));
55161
+ this.setupIntersectionObserver();
55105
55162
  effect(() => {
55106
55163
  const target = this.percentageChange();
55107
- this.animateValue(target);
55164
+ if (this.hasAnimated()) {
55165
+ this.animateValue(target);
55166
+ }
55108
55167
  });
55109
55168
  }
55169
+ ngOnDestroy() {
55170
+ if (this.observer) {
55171
+ this.observer.disconnect();
55172
+ }
55173
+ }
55174
+ setupIntersectionObserver() {
55175
+ this.observer = new IntersectionObserver((entries) => {
55176
+ entries.forEach((entry) => {
55177
+ if (entry.isIntersecting && !this.hasAnimated()) {
55178
+ this.hasAnimated.set(true);
55179
+ const target = this.percentageChange();
55180
+ this.animateValue(target);
55181
+ }
55182
+ });
55183
+ }, { threshold: 0.1 });
55184
+ this.observer.observe(this.elementRef.nativeElement);
55185
+ }
55110
55186
  animateValue(target) {
55111
55187
  const start = 0;
55112
55188
  const duration = 800;
@@ -55117,14 +55193,15 @@ class TargetChangeBadgeComponent {
55117
55193
  const easeOutQuart = 1 - Math.pow(1 - progress, 4);
55118
55194
  const current = start + (target - start) * easeOutQuart;
55119
55195
  this.animatedValue.set(current);
55196
+ this.animationProgress.set(progress);
55120
55197
  if (progress < 1) {
55121
55198
  requestAnimationFrame(animate);
55122
55199
  }
55123
55200
  };
55124
55201
  requestAnimationFrame(animate);
55125
55202
  }
55126
- static { this.ɵfac = function TargetChangeBadgeComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TargetChangeBadgeComponent)(); }; }
55127
- static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TargetChangeBadgeComponent, selectors: [["symphiq-target-change-badge"]], inputs: { viewMode: [1, "viewMode"], percentageChange: [1, "percentageChange"], metric: [1, "metric"], priorYear: [1, "priorYear"], isCompact: [1, "isCompact"] }, decls: 7, vars: 13, consts: [[3, "ngClass"]], template: function TargetChangeBadgeComponent_Template(rf, ctx) { if (rf & 1) {
55203
+ static { this.ɵfac = function TargetChangeBadgeComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TargetChangeBadgeComponent)(i0.ɵɵdirectiveInject(i0.ElementRef)); }; }
55204
+ static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TargetChangeBadgeComponent, selectors: [["symphiq-target-change-badge"]], inputs: { viewMode: [1, "viewMode"], percentageChange: [1, "percentageChange"], metric: [1, "metric"], priorYear: [1, "priorYear"], isCompact: [1, "isCompact"] }, decls: 7, vars: 15, consts: [[3, "ngClass"]], template: function TargetChangeBadgeComponent_Template(rf, ctx) { if (rf & 1) {
55128
55205
  i0.ɵɵelementStart(0, "div", 0)(1, "div", 0)(2, "span");
55129
55206
  i0.ɵɵtext(3);
55130
55207
  i0.ɵɵelementEnd();
@@ -55135,6 +55212,7 @@ class TargetChangeBadgeComponent {
55135
55212
  i0.ɵɵelementEnd()();
55136
55213
  } if (rf & 2) {
55137
55214
  i0.ɵɵclassMap(ctx.containerSizeClasses());
55215
+ i0.ɵɵstyleProp("transform", ctx.rotationStyle());
55138
55216
  i0.ɵɵproperty("ngClass", ctx.containerClasses());
55139
55217
  i0.ɵɵadvance();
55140
55218
  i0.ɵɵclassMap(ctx.overlaySizeClasses());
@@ -55159,7 +55237,11 @@ class TargetChangeBadgeComponent {
55159
55237
  imports: [CommonModule],
55160
55238
  changeDetection: ChangeDetectionStrategy.OnPush,
55161
55239
  template: `
55162
- <div [ngClass]="containerClasses()" [class]="containerSizeClasses()">
55240
+ <div
55241
+ [ngClass]="containerClasses()"
55242
+ [class]="containerSizeClasses()"
55243
+ [style.transform]="rotationStyle()"
55244
+ >
55163
55245
  <div [ngClass]="overlayClasses()" [class]="overlaySizeClasses()">
55164
55246
  <span [class]="iconSizeClass()">{{ iconSymbol() }}</span>
55165
55247
  {{ animatedPercentageText() }}
@@ -55170,8 +55252,8 @@ class TargetChangeBadgeComponent {
55170
55252
  </div>
55171
55253
  `
55172
55254
  }]
55173
- }], () => [], { viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], percentageChange: [{ type: i0.Input, args: [{ isSignal: true, alias: "percentageChange", required: false }] }], metric: [{ type: i0.Input, args: [{ isSignal: true, alias: "metric", required: false }] }], priorYear: [{ type: i0.Input, args: [{ isSignal: true, alias: "priorYear", required: false }] }], isCompact: [{ type: i0.Input, args: [{ isSignal: true, alias: "isCompact", required: false }] }] }); })();
55174
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TargetChangeBadgeComponent, { className: "TargetChangeBadgeComponent", filePath: "lib/components/revenue-calculator-dashboard/target-change-badge.component.ts", lineNumber: 23 }); })();
55255
+ }], () => [{ type: i0.ElementRef }], { viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], percentageChange: [{ type: i0.Input, args: [{ isSignal: true, alias: "percentageChange", required: false }] }], metric: [{ type: i0.Input, args: [{ isSignal: true, alias: "metric", required: false }] }], priorYear: [{ type: i0.Input, args: [{ isSignal: true, alias: "priorYear", required: false }] }], isCompact: [{ type: i0.Input, args: [{ isSignal: true, alias: "isCompact", required: false }] }] }); })();
55256
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TargetChangeBadgeComponent, { className: "TargetChangeBadgeComponent", filePath: "lib/components/revenue-calculator-dashboard/target-change-badge.component.ts", lineNumber: 27 }); })();
55175
55257
 
55176
55258
  const _forTrack0$j = ($index, $item) => $item.stageMetric.metric;
55177
55259
  const _forTrack1$3 = ($index, $item) => $item.calc.metric;
@@ -56759,7 +56841,8 @@ class LineChartComponent {
56759
56841
  // Check for explicit keywords
56760
56842
  if (name.includes('last year') ||
56761
56843
  name.includes('prior year') ||
56762
- name.includes('previous year')) {
56844
+ name.includes('previous year') ||
56845
+ name.includes('comparison')) {
56763
56846
  return true;
56764
56847
  }
56765
56848
  // Check for year patterns - extract any 4-digit year and compare to current year
@@ -56770,6 +56853,13 @@ class LineChartComponent {
56770
56853
  }
56771
56854
  return false;
56772
56855
  }
56856
+ isProjectionSeries(seriesData) {
56857
+ if (!seriesData || !seriesData.name) {
56858
+ return false;
56859
+ }
56860
+ const name = seriesData.name.toLowerCase();
56861
+ return name.includes('projection') || name.includes('projected') || name.includes('target');
56862
+ }
56773
56863
  extractMetricName(seriesName) {
56774
56864
  // Extract metric name from series name by removing year patterns
56775
56865
  // e.g., "Purchase Revenue (2025)" -> "Purchase Revenue"
@@ -56968,8 +57058,9 @@ class LineChartComponent {
56968
57058
  seriesColorValue = axisColors[yaxisLabel] || axisColorPalette[index % axisColorPalette.length];
56969
57059
  }
56970
57060
  const seriesColor = color(seriesColorValue);
56971
- // Check if this is a prior year series for YoY charts
57061
+ // Check if this is a prior year or projection series for YoY charts
56972
57062
  const isPriorYear = isYoYChart && this.isPriorYearSeries(seriesData);
57063
+ const isProjection = this.isProjectionSeries(seriesData);
56973
57064
  if (!this.chartElement || !this.root)
56974
57065
  return;
56975
57066
  const series = this.chartElement.series.push(LineSeries.new(this.root, {
@@ -56981,7 +57072,7 @@ class LineChartComponent {
56981
57072
  stroke: seriesColor
56982
57073
  }));
56983
57074
  // Store valueFormat and prior year flag in userData for tooltip formatting
56984
- series.set('userData', { valueFormat: seriesData.valueFormat, isPriorYear });
57075
+ series.set('userData', { valueFormat: seriesData.valueFormat, isPriorYear, isProjection });
56985
57076
  // Disable individual series tooltips - use floating tooltip instead
56986
57077
  series.set('tooltip', undefined);
56987
57078
  // Configure stroke styling based on series type
@@ -56999,6 +57090,16 @@ class LineChartComponent {
56999
57090
  stroke.set('strokeOpacity', 0.5);
57000
57091
  });
57001
57092
  }
57093
+ else if (isProjection) {
57094
+ // Apply dotted line for projection data
57095
+ series.strokes.template.setAll({
57096
+ strokeDasharray: [10, 5],
57097
+ strokeWidth: 3
57098
+ });
57099
+ series.strokes.each((stroke) => {
57100
+ stroke.set('strokeDasharray', [10, 5]);
57101
+ });
57102
+ }
57002
57103
  // Add bullets with larger hit area for better hover detection
57003
57104
  series.bullets.push(() => {
57004
57105
  const bulletConfig = {
@@ -57346,12 +57447,12 @@ const _forTrack0$i = ($index, $item) => $item.metric;
57346
57447
  function MetricReportModalComponent_Conditional_0_Conditional_12_Template(rf, ctx) { if (rf & 1) {
57347
57448
  i0.ɵɵelementStart(0, "button", 11);
57348
57449
  i0.ɵɵnamespaceSVG();
57349
- i0.ɵɵelementStart(1, "svg", 32);
57350
- i0.ɵɵelement(2, "path", 33);
57450
+ i0.ɵɵelementStart(1, "svg", 33);
57451
+ i0.ɵɵelement(2, "path", 34);
57351
57452
  i0.ɵɵelementEnd()();
57352
57453
  } if (rf & 2) {
57353
57454
  const ctx_r1 = i0.ɵɵnextContext(2);
57354
- i0.ɵɵproperty("ngClass", ctx_r1.headerInfoIconClasses())("libSymphiqTooltip", ctx_r1.metricData().description);
57455
+ i0.ɵɵproperty("ngClass", ctx_r1.headerInfoIconClasses())("libSymphiqTooltip", ctx_r1.getMarkdownTooltipContent(ctx_r1.metricData().description, ctx_r1.metricTitle()));
57355
57456
  } }
57356
57457
  function MetricReportModalComponent_Conditional_0_Conditional_32_Template(rf, ctx) { if (rf & 1) {
57357
57458
  i0.ɵɵelement(0, "symphiq-target-change-badge", 23);
@@ -57361,13 +57462,13 @@ function MetricReportModalComponent_Conditional_0_Conditional_32_Template(rf, ct
57361
57462
  i0.ɵɵproperty("viewMode", ctx_r1.viewMode())("percentageChange", ctx_r1.ytdChangePercentage())("metric", ((tmp_4_0 = ctx_r1.metricData()) == null ? null : tmp_4_0.metric) || "")("priorYear", ctx_r1.priorYear())("isCompact", true);
57362
57463
  } }
57363
57464
  function MetricReportModalComponent_Conditional_0_Conditional_48_Template(rf, ctx) { if (rf & 1) {
57364
- i0.ɵɵelementStart(0, "div")(1, "p", 24);
57465
+ i0.ɵɵelementStart(0, "div")(1, "p", 25);
57365
57466
  i0.ɵɵtext(2);
57366
57467
  i0.ɵɵelementEnd();
57367
57468
  i0.ɵɵelementStart(3, "p", 22);
57368
57469
  i0.ɵɵtext(4);
57369
57470
  i0.ɵɵelementEnd();
57370
- i0.ɵɵelement(5, "symphiq-pacing-status-badge", 34);
57471
+ i0.ɵɵelement(5, "symphiq-pacing-status-badge", 35);
57371
57472
  i0.ɵɵelementEnd();
57372
57473
  } if (rf & 2) {
57373
57474
  let tmp_5_0;
@@ -57384,13 +57485,13 @@ function MetricReportModalComponent_Conditional_0_Conditional_48_Template(rf, ct
57384
57485
  i0.ɵɵproperty("viewMode", ctx_r1.viewMode())("pacingPercentage", ctx_r1.pacingInfo().pacingPercentage)("status", ctx_r1.pacingInfo().status)("showAsFullText", false)("isCompact", true)("showEmphasizedPercentage", true);
57385
57486
  } }
57386
57487
  function MetricReportModalComponent_Conditional_0_Conditional_64_Template(rf, ctx) { if (rf & 1) {
57387
- i0.ɵɵelementStart(0, "div", 25);
57388
- i0.ɵɵelement(1, "symphiq-pacing-status-badge", 34);
57488
+ i0.ɵɵelementStart(0, "div", 26);
57489
+ i0.ɵɵelement(1, "symphiq-pacing-status-badge", 35);
57389
57490
  i0.ɵɵelementEnd();
57390
- i0.ɵɵelementStart(2, "div", 25)(3, "p", 28);
57491
+ i0.ɵɵelementStart(2, "div", 26)(3, "p", 29);
57391
57492
  i0.ɵɵtext(4);
57392
57493
  i0.ɵɵelementEnd()();
57393
- i0.ɵɵelement(5, "symphiq-progress-to-target-chart", 35);
57494
+ i0.ɵɵelement(5, "symphiq-progress-to-target-chart", 36);
57394
57495
  } if (rf & 2) {
57395
57496
  const ctx_r1 = i0.ɵɵnextContext(2);
57396
57497
  i0.ɵɵadvance();
@@ -57403,10 +57504,10 @@ function MetricReportModalComponent_Conditional_0_Conditional_64_Template(rf, ct
57403
57504
  i0.ɵɵproperty("data", ctx_r1.progressToTargetData())("viewMode", ctx_r1.viewMode());
57404
57505
  } }
57405
57506
  function MetricReportModalComponent_Conditional_0_Conditional_65_For_15_Conditional_5_Template(rf, ctx) { if (rf & 1) {
57406
- i0.ɵɵelementStart(0, "button", 45);
57507
+ i0.ɵɵelementStart(0, "button", 46);
57407
57508
  i0.ɵɵnamespaceSVG();
57408
- i0.ɵɵelementStart(1, "svg", 51);
57409
- i0.ɵɵelement(2, "path", 33);
57509
+ i0.ɵɵelementStart(1, "svg", 52);
57510
+ i0.ɵɵelement(2, "path", 34);
57410
57511
  i0.ɵɵelementEnd()();
57411
57512
  } if (rf & 2) {
57412
57513
  const metric_r3 = i0.ɵɵnextContext().$implicit;
@@ -57414,20 +57515,20 @@ function MetricReportModalComponent_Conditional_0_Conditional_65_For_15_Conditio
57414
57515
  i0.ɵɵproperty("ngClass", ctx_r1.infoIconClasses())("libSymphiqTooltip", ctx_r1.getMarkdownTooltipContent(metric_r3.description, ctx_r1.getMetricTitle(metric_r3)));
57415
57516
  } }
57416
57517
  function MetricReportModalComponent_Conditional_0_Conditional_65_For_15_Template(rf, ctx) { if (rf & 1) {
57417
- i0.ɵɵelementStart(0, "tr", 41)(1, "td", 42)(2, "div", 43)(3, "span", 44);
57518
+ i0.ɵɵelementStart(0, "tr", 42)(1, "td", 43)(2, "div", 44)(3, "span", 45);
57418
57519
  i0.ɵɵtext(4);
57419
57520
  i0.ɵɵelementEnd();
57420
- i0.ɵɵconditionalCreate(5, MetricReportModalComponent_Conditional_0_Conditional_65_For_15_Conditional_5_Template, 3, 2, "button", 45);
57521
+ i0.ɵɵconditionalCreate(5, MetricReportModalComponent_Conditional_0_Conditional_65_For_15_Conditional_5_Template, 3, 2, "button", 46);
57421
57522
  i0.ɵɵelementEnd()();
57422
- i0.ɵɵelementStart(6, "td", 46)(7, "span", 47);
57523
+ i0.ɵɵelementStart(6, "td", 47)(7, "span", 48);
57423
57524
  i0.ɵɵtext(8);
57424
57525
  i0.ɵɵelementEnd()();
57425
- i0.ɵɵelementStart(9, "td", 46)(10, "div", 48)(11, "span", 44);
57526
+ i0.ɵɵelementStart(9, "td", 47)(10, "div", 49)(11, "span", 45);
57426
57527
  i0.ɵɵtext(12);
57427
57528
  i0.ɵɵelementEnd();
57428
57529
  i0.ɵɵnamespaceSVG();
57429
- i0.ɵɵelementStart(13, "svg", 49);
57430
- i0.ɵɵelement(14, "path", 50);
57530
+ i0.ɵɵelementStart(13, "svg", 50);
57531
+ i0.ɵɵelement(14, "path", 51);
57431
57532
  i0.ɵɵelementEnd()()()();
57432
57533
  } if (rf & 2) {
57433
57534
  const metric_r3 = ctx.$implicit;
@@ -57450,17 +57551,17 @@ function MetricReportModalComponent_Conditional_0_Conditional_65_Template(rf, ct
57450
57551
  i0.ɵɵelementStart(0, "div", 16)(1, "h4", 17);
57451
57552
  i0.ɵɵtext(2, " Contributing Metric Targets ");
57452
57553
  i0.ɵɵelementEnd();
57453
- i0.ɵɵelementStart(3, "div", 36)(4, "table", 37)(5, "thead")(6, "tr", 38)(7, "th", 39);
57554
+ i0.ɵɵelementStart(3, "div", 37)(4, "table", 38)(5, "thead")(6, "tr", 39)(7, "th", 40);
57454
57555
  i0.ɵɵtext(8, "Metric");
57455
57556
  i0.ɵɵelementEnd();
57456
- i0.ɵɵelementStart(9, "th", 40);
57557
+ i0.ɵɵelementStart(9, "th", 41);
57457
57558
  i0.ɵɵtext(10, "Target");
57458
57559
  i0.ɵɵelementEnd();
57459
- i0.ɵɵelementStart(11, "th", 40);
57560
+ i0.ɵɵelementStart(11, "th", 41);
57460
57561
  i0.ɵɵtext(12, "Improve by");
57461
57562
  i0.ɵɵelementEnd()()();
57462
57563
  i0.ɵɵelementStart(13, "tbody");
57463
- i0.ɵɵrepeaterCreate(14, MetricReportModalComponent_Conditional_0_Conditional_65_For_15_Template, 15, 7, "tr", 41, _forTrack0$i);
57564
+ i0.ɵɵrepeaterCreate(14, MetricReportModalComponent_Conditional_0_Conditional_65_For_15_Template, 15, 7, "tr", 42, _forTrack0$i);
57464
57565
  i0.ɵɵelementEnd()()()();
57465
57566
  } if (rf & 2) {
57466
57567
  const ctx_r1 = i0.ɵɵnextContext(2);
@@ -57473,19 +57574,19 @@ function MetricReportModalComponent_Conditional_0_Conditional_65_Template(rf, ct
57473
57574
  i0.ɵɵrepeater(ctx_r1.contributingMetrics());
57474
57575
  } }
57475
57576
  function MetricReportModalComponent_Conditional_0_Conditional_66_Template(rf, ctx) { if (rf & 1) {
57476
- i0.ɵɵelementStart(0, "div", 29)(1, "h4", 17);
57577
+ i0.ɵɵelementStart(0, "div", 30)(1, "h4", 17);
57477
57578
  i0.ɵɵtext(2, " Pace ");
57478
57579
  i0.ɵɵelementEnd();
57479
- i0.ɵɵelementStart(3, "div", 52);
57480
- i0.ɵɵelement(4, "symphiq-line-chart", 53);
57580
+ i0.ɵɵelementStart(3, "div", 53);
57581
+ i0.ɵɵelement(4, "symphiq-line-chart", 54);
57481
57582
  i0.ɵɵelementEnd();
57482
- i0.ɵɵelementStart(5, "p", 54);
57583
+ i0.ɵɵelementStart(5, "p", 55);
57483
57584
  i0.ɵɵtext(6);
57484
57585
  i0.ɵɵelementEnd();
57485
- i0.ɵɵelementStart(7, "p", 55);
57586
+ i0.ɵɵelementStart(7, "p", 56);
57486
57587
  i0.ɵɵtext(8);
57487
57588
  i0.ɵɵelementEnd();
57488
- i0.ɵɵelementStart(9, "p", 55);
57589
+ i0.ɵɵelementStart(9, "p", 56);
57489
57590
  i0.ɵɵtext(10);
57490
57591
  i0.ɵɵelementEnd()();
57491
57592
  } if (rf & 2) {
@@ -57559,40 +57660,40 @@ function MetricReportModalComponent_Conditional_0_Template(rf, ctx) { if (rf & 1
57559
57660
  i0.ɵɵelementStart(39, "p", 21);
57560
57661
  i0.ɵɵtext(40);
57561
57662
  i0.ɵɵelementEnd()();
57562
- i0.ɵɵelementStart(41, "p", 10);
57663
+ i0.ɵɵelementStart(41, "p", 24);
57563
57664
  i0.ɵɵtext(42);
57564
57665
  i0.ɵɵelementEnd()();
57565
- i0.ɵɵelementStart(43, "div")(44, "p", 24);
57666
+ i0.ɵɵelementStart(43, "div")(44, "p", 25);
57566
57667
  i0.ɵɵtext(45);
57567
57668
  i0.ɵɵelementEnd();
57568
- i0.ɵɵelementStart(46, "p", 10);
57669
+ i0.ɵɵelementStart(46, "p", 24);
57569
57670
  i0.ɵɵtext(47);
57570
57671
  i0.ɵɵelementEnd()();
57571
57672
  i0.ɵɵconditionalCreate(48, MetricReportModalComponent_Conditional_0_Conditional_48_Template, 6, 10, "div");
57572
- i0.ɵɵelementStart(49, "div")(50, "p", 24);
57673
+ i0.ɵɵelementStart(49, "div")(50, "p", 25);
57573
57674
  i0.ɵɵtext(51);
57574
57675
  i0.ɵɵelementEnd();
57575
- i0.ɵɵelementStart(52, "p", 10);
57676
+ i0.ɵɵelementStart(52, "p", 24);
57576
57677
  i0.ɵɵtext(53);
57577
57678
  i0.ɵɵelementEnd()()()();
57578
57679
  i0.ɵɵelementStart(54, "div", 16)(55, "h4", 17);
57579
57680
  i0.ɵɵtext(56, " Target Analysis ");
57580
57681
  i0.ɵɵelementEnd();
57581
- i0.ɵɵelementStart(57, "div", 25)(58, "p", 26);
57682
+ i0.ɵɵelementStart(57, "div", 26)(58, "p", 27);
57582
57683
  i0.ɵɵtext(59, " Your Target ");
57583
57684
  i0.ɵɵelementEnd();
57584
- i0.ɵɵelementStart(60, "p", 27);
57685
+ i0.ɵɵelementStart(60, "p", 28);
57585
57686
  i0.ɵɵtext(61);
57586
57687
  i0.ɵɵelementEnd();
57587
- i0.ɵɵelementStart(62, "p", 28);
57688
+ i0.ɵɵelementStart(62, "p", 29);
57588
57689
  i0.ɵɵtext(63);
57589
57690
  i0.ɵɵelementEnd()();
57590
57691
  i0.ɵɵconditionalCreate(64, MetricReportModalComponent_Conditional_0_Conditional_64_Template, 6, 10);
57591
57692
  i0.ɵɵelementEnd();
57592
57693
  i0.ɵɵconditionalCreate(65, MetricReportModalComponent_Conditional_0_Conditional_65_Template, 16, 3, "div", 16);
57593
- i0.ɵɵconditionalCreate(66, MetricReportModalComponent_Conditional_0_Conditional_66_Template, 11, 12, "div", 29);
57694
+ i0.ɵɵconditionalCreate(66, MetricReportModalComponent_Conditional_0_Conditional_66_Template, 11, 12, "div", 30);
57594
57695
  i0.ɵɵelementEnd();
57595
- i0.ɵɵelementStart(67, "div", 30)(68, "button", 31);
57696
+ i0.ɵɵelementStart(67, "div", 31)(68, "button", 32);
57596
57697
  i0.ɵɵlistener("click", function MetricReportModalComponent_Conditional_0_Template_button_click_68_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.close()); });
57597
57698
  i0.ɵɵtext(69, " Close ");
57598
57699
  i0.ɵɵelementEnd()()()()();
@@ -57862,7 +57963,7 @@ class MetricReportModalComponent {
57862
57963
  const metric = this.metricTitle();
57863
57964
  const currentYear = this.currentYear();
57864
57965
  const priorYear = this.priorYear();
57865
- return `This chart shows the ${metric} performance trend for ${currentYear} (solid line), compared to ${priorYear} (dashed line), with the target projection (dotted line) for the remainder of the year.`;
57966
+ return `This chart shows the ${metric} performance trend for ${currentYear} (solid yellow line, this month includes projections), compared to ${priorYear} (dashed green line), with the target projection (dotted blue line) for the remainder of the year.`;
57866
57967
  }, ...(ngDevMode ? [{ debugName: "chartLegendDescription" }] : []));
57867
57968
  this.chartDescriptionSentence1 = computed(() => {
57868
57969
  const metricData = this.metricData();
@@ -57893,6 +57994,7 @@ class MetricReportModalComponent {
57893
57994
  chartType: 'LINE',
57894
57995
  title: 'Pace',
57895
57996
  description: '',
57997
+ lineChartUseCase: LineChartUseCaseEnum.THIS_YEAR_VS_LAST_YEAR,
57896
57998
  lineChartData: {
57897
57999
  series: [
57898
58000
  {
@@ -58118,7 +58220,7 @@ class MetricReportModalComponent {
58118
58220
  : 'bg-slate-700 hover:bg-slate-600 text-white';
58119
58221
  }
58120
58222
  static { this.ɵfac = function MetricReportModalComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MetricReportModalComponent)(); }; }
58121
- static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MetricReportModalComponent, selectors: [["symphiq-metric-report-modal"]], inputs: { viewMode: [1, "viewMode"], metricEnum: [1, "metricEnum"], metricData: [1, "metricData"], contributingMetrics: [1, "contributingMetrics"], pacingMetrics: [1, "pacingMetrics"], isOpen: [1, "isOpen"] }, outputs: { closed: "closed" }, decls: 1, vars: 1, consts: [[1, "fixed", "inset-0", "overflow-y-auto", "z-50"], [1, "fixed", "inset-0", "overflow-y-auto", "z-50", 3, "click"], [1, "flex", "items-center", "justify-center", "min-h-screen", "px-4", "pt-4", "pb-20", "text-center", "sm:block", "sm:p-0"], ["aria-hidden", "true", 1, "fixed", "inset-0", "backdrop-blur-md", 3, "ngClass"], ["aria-hidden", "true", 1, "hidden", "sm:inline-block", "sm:align-middle", "sm:h-screen"], [1, "relative", "inline-block", "align-bottom", "rounded-2xl", "text-left", "overflow-hidden", "shadow-xl", "sm:my-8", "sm:align-middle", "sm:w-full", "sm:max-w-4xl", "border", "backdrop-blur-xl", 3, "click", "ngClass"], [1, "px-6", "py-5", "border-b", "backdrop-blur-sm", "sticky", "top-0", "z-10", 3, "ngClass"], [1, "flex", "items-start", "justify-between"], [1, "flex-1"], [1, "flex", "items-center", "gap-3", "mb-2"], [1, "text-xl", "font-bold", 3, "ngClass"], ["type", "button", "tooltipType", "markdown", "tooltipPosition", "right", 1, "flex-shrink-0", "w-7", "h-7", "rounded-full", "inline-flex", "items-center", "justify-center", "transition-colors", "self-center", 3, "ngClass", "libSymphiqTooltip"], [1, "ml-4", "transition-all", "rounded-lg", "p-1", "hover:scale-110", "active:scale-90", 3, "click", "ngClass"], ["fill", "none", "stroke", "currentColor", "viewBox", "0 0 24 24", 1, "w-6", "h-6"], ["stroke-linecap", "round", "stroke-linejoin", "round", "stroke-width", "2", "d", "M6 18L18 6M6 6l12 12"], [1, "px-6", "py-6", "max-h-[70vh]", "overflow-y-auto", "backdrop-blur-sm", 3, "ngClass"], [1, "rounded-xl", "p-6", "mb-6", 3, "ngClass"], [1, "text-sm", "font-semibold", "uppercase", "tracking-wider", "mb-4", 3, "ngClass"], [1, "grid", "grid-cols-1", "sm:grid-cols-2", "lg:grid-cols-3", "gap-6"], [1, "mb-1.5"], [1, "text-xs", "font-medium", "uppercase", "tracking-wider", 3, "ngClass"], [1, "text-xs", 3, "ngClass"], [1, "text-xl", "font-bold", "mb-2", 3, "ngClass"], [3, "viewMode", "percentageChange", "metric", "priorYear", "isCompact"], [1, "text-xs", "font-medium", "uppercase", "tracking-wider", "mb-1.5", 3, "ngClass"], [1, "mb-4"], [1, "text-xs", "font-medium", "uppercase", "tracking-wider", "mb-2", 3, "ngClass"], [1, "text-3xl", "font-extrabold", "mb-3", 3, "ngClass"], [1, "text-sm", "leading-relaxed", 3, "ngClass"], [1, "rounded-xl", "p-6", 3, "ngClass"], [1, "px-6", "py-4", "border-t", 3, "ngClass"], [1, "w-full", "px-4", "py-2", "rounded-lg", "transition-all", "font-medium", "hover:scale-[1.02]", "active:scale-[0.98]", 3, "click", "ngClass"], ["fill", "none", "stroke", "currentColor", "viewBox", "0 0 24 24", 1, "w-4", "h-4"], ["stroke-linecap", "round", "stroke-linejoin", "round", "stroke-width", "2", "d", "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"], [3, "viewMode", "pacingPercentage", "status", "showAsFullText", "isCompact", "showEmphasizedPercentage"], [3, "data", "viewMode"], [1, "overflow-x-auto"], [1, "w-full"], [1, "border-b", 3, "ngClass"], [1, "text-left", "py-3", "px-4", "text-xs", "font-semibold", "uppercase", "tracking-wider"], [1, "text-right", "py-3", "px-4", "text-xs", "font-semibold", "uppercase", "tracking-wider"], [1, "border-b", "transition-colors", 3, "ngClass"], [1, "py-3", "px-4"], [1, "flex", "items-center", "gap-2"], [1, "text-sm", "font-medium"], ["type", "button", "tooltipType", "markdown", "tooltipPosition", "right", 1, "flex-shrink-0", "w-5", "h-5", "rounded-full", "inline-flex", "items-center", "justify-center", "transition-colors", 3, "ngClass", "libSymphiqTooltip"], [1, "py-3", "px-4", "text-right"], [1, "text-sm", "font-semibold", 3, "ngClass"], [1, "flex", "items-center", "justify-end", "gap-2"], ["fill", "none", "stroke", "currentColor", "viewBox", "0 0 24 24", 1, "w-4", "h-4", "text-emerald-500"], ["stroke-linecap", "round", "stroke-linejoin", "round", "stroke-width", "2"], ["fill", "none", "stroke", "currentColor", "viewBox", "0 0 24 24", 1, "w-3", "h-3"], [1, "min-h-[400px]"], [3, "chart", "showAxisLabels", "viewMode", "currencySymbol"], [1, "text-sm", "leading-relaxed", "mt-4", 3, "ngClass"], [1, "text-sm", "leading-relaxed", "mt-2", 3, "ngClass"]], template: function MetricReportModalComponent_Template(rf, ctx) { if (rf & 1) {
58223
+ static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MetricReportModalComponent, selectors: [["symphiq-metric-report-modal"]], inputs: { viewMode: [1, "viewMode"], metricEnum: [1, "metricEnum"], metricData: [1, "metricData"], contributingMetrics: [1, "contributingMetrics"], pacingMetrics: [1, "pacingMetrics"], isOpen: [1, "isOpen"] }, outputs: { closed: "closed" }, decls: 1, vars: 1, consts: [[1, "fixed", "inset-0", "overflow-y-auto", "z-50"], [1, "fixed", "inset-0", "overflow-y-auto", "z-50", 3, "click"], [1, "flex", "items-center", "justify-center", "min-h-screen", "px-4", "pt-4", "pb-20", "text-center", "sm:block", "sm:p-0"], ["aria-hidden", "true", 1, "fixed", "inset-0", "backdrop-blur-md", 3, "ngClass"], ["aria-hidden", "true", 1, "hidden", "sm:inline-block", "sm:align-middle", "sm:h-screen"], [1, "relative", "inline-block", "align-bottom", "rounded-2xl", "text-left", "overflow-hidden", "shadow-xl", "sm:my-8", "sm:align-middle", "sm:w-full", "sm:max-w-4xl", "border", "backdrop-blur-xl", 3, "click", "ngClass"], [1, "px-6", "py-5", "border-b", "backdrop-blur-sm", "sticky", "top-0", "z-10", 3, "ngClass"], [1, "flex", "items-start", "justify-between"], [1, "flex-1"], [1, "flex", "items-center", "gap-3", "mb-2"], [1, "text-xl", "font-bold", "leading-none", 3, "ngClass"], ["type", "button", "tooltipType", "markdown", "tooltipPosition", "right", 1, "flex-shrink-0", "w-7", "h-7", "rounded-full", "inline-flex", "items-center", "justify-center", "transition-colors", 3, "ngClass", "libSymphiqTooltip"], [1, "ml-4", "transition-all", "rounded-lg", "p-1", "hover:scale-110", "active:scale-90", 3, "click", "ngClass"], ["fill", "none", "stroke", "currentColor", "viewBox", "0 0 24 24", 1, "w-6", "h-6"], ["stroke-linecap", "round", "stroke-linejoin", "round", "stroke-width", "2", "d", "M6 18L18 6M6 6l12 12"], [1, "px-6", "py-6", "max-h-[70vh]", "overflow-y-auto", "backdrop-blur-sm", 3, "ngClass"], [1, "rounded-xl", "p-6", "mb-6", 3, "ngClass"], [1, "text-sm", "font-semibold", "uppercase", "tracking-wider", "mb-4", 3, "ngClass"], [1, "grid", "grid-cols-1", "sm:grid-cols-2", "lg:grid-cols-3", "gap-6"], [1, "mb-1.5"], [1, "text-xs", "font-medium", "uppercase", "tracking-wider", 3, "ngClass"], [1, "text-xs", 3, "ngClass"], [1, "text-xl", "font-bold", "mb-2", 3, "ngClass"], [3, "viewMode", "percentageChange", "metric", "priorYear", "isCompact"], [1, "text-xl", "font-bold", 3, "ngClass"], [1, "text-xs", "font-medium", "uppercase", "tracking-wider", "mb-1.5", 3, "ngClass"], [1, "mb-4"], [1, "text-xs", "font-medium", "uppercase", "tracking-wider", "mb-2", 3, "ngClass"], [1, "text-3xl", "font-extrabold", "mb-3", 3, "ngClass"], [1, "text-sm", "leading-relaxed", 3, "ngClass"], [1, "rounded-xl", "p-6", 3, "ngClass"], [1, "px-6", "py-4", "border-t", 3, "ngClass"], [1, "w-full", "px-4", "py-2", "rounded-lg", "transition-all", "font-medium", "hover:scale-[1.02]", "active:scale-[0.98]", 3, "click", "ngClass"], ["fill", "none", "stroke", "currentColor", "viewBox", "0 0 24 24", 1, "w-4", "h-4"], ["stroke-linecap", "round", "stroke-linejoin", "round", "stroke-width", "2", "d", "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"], [3, "viewMode", "pacingPercentage", "status", "showAsFullText", "isCompact", "showEmphasizedPercentage"], [3, "data", "viewMode"], [1, "overflow-x-auto"], [1, "w-full"], [1, "border-b", 3, "ngClass"], [1, "text-left", "py-3", "px-4", "text-xs", "font-semibold", "uppercase", "tracking-wider"], [1, "text-right", "py-3", "px-4", "text-xs", "font-semibold", "uppercase", "tracking-wider"], [1, "border-b", "transition-colors", 3, "ngClass"], [1, "py-3", "px-4"], [1, "flex", "items-center", "gap-2"], [1, "text-sm", "font-medium"], ["type", "button", "tooltipType", "markdown", "tooltipPosition", "right", 1, "flex-shrink-0", "w-5", "h-5", "rounded-full", "inline-flex", "items-center", "justify-center", "transition-colors", 3, "ngClass", "libSymphiqTooltip"], [1, "py-3", "px-4", "text-right"], [1, "text-sm", "font-semibold", 3, "ngClass"], [1, "flex", "items-center", "justify-end", "gap-2"], ["fill", "none", "stroke", "currentColor", "viewBox", "0 0 24 24", 1, "w-4", "h-4", "text-emerald-500"], ["stroke-linecap", "round", "stroke-linejoin", "round", "stroke-width", "2"], ["fill", "none", "stroke", "currentColor", "viewBox", "0 0 24 24", 1, "w-3", "h-3"], [1, "min-h-[400px]"], [3, "chart", "showAxisLabels", "viewMode", "currencySymbol"], [1, "text-sm", "leading-relaxed", "mt-4", 3, "ngClass"], [1, "text-sm", "leading-relaxed", "mt-2", 3, "ngClass"]], template: function MetricReportModalComponent_Template(rf, ctx) { if (rf & 1) {
58122
58224
  i0.ɵɵconditionalCreate(0, MetricReportModalComponent_Conditional_0_Template, 70, 51, "div", 0);
58123
58225
  } if (rf & 2) {
58124
58226
  i0.ɵɵconditional(ctx.isOpen() ? 0 : -1);
@@ -58171,310 +58273,310 @@ class MetricReportModalComponent {
58171
58273
  ])
58172
58274
  ])
58173
58275
  ],
58174
- template: `
58175
- @if (isOpen()) {
58176
- <div class="fixed inset-0 overflow-y-auto z-50" (click)="close()">
58177
- <div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
58178
- <div
58179
- [ngClass]="backdropClasses()"
58180
- class="fixed inset-0 backdrop-blur-md"
58181
- aria-hidden="true"
58182
- @fadeIn>
58183
- </div>
58184
-
58185
- <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
58186
-
58187
- <div
58188
- (click)="$event.stopPropagation()"
58189
- [ngClass]="modalContainerClasses()"
58190
- class="relative inline-block align-bottom rounded-2xl text-left overflow-hidden shadow-xl sm:my-8 sm:align-middle sm:w-full sm:max-w-4xl border backdrop-blur-xl"
58191
- @slideUpFade>
58192
-
58193
- <!-- Header -->
58194
- <div [ngClass]="headerClasses()" class="px-6 py-5 border-b backdrop-blur-sm sticky top-0 z-10">
58195
- <div class="flex items-start justify-between">
58196
- <div class="flex-1">
58197
- <div class="flex items-center gap-3 mb-2">
58198
- <h3 [ngClass]="titleClasses()" class="text-xl font-bold">
58199
- {{ metricTitle() }}
58200
- </h3>
58201
- @if (metricData()?.description) {
58202
- <button
58203
- type="button"
58204
- [ngClass]="headerInfoIconClasses()"
58205
- class="flex-shrink-0 w-7 h-7 rounded-full inline-flex items-center justify-center transition-colors self-center"
58206
- [libSymphiqTooltip]="metricData()!.description!"
58207
- tooltipType="markdown"
58208
- tooltipPosition="right">
58209
- <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
58210
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
58211
- </svg>
58212
- </button>
58213
- }
58214
- </div>
58215
- </div>
58216
- <button
58217
- (click)="close()"
58218
- [ngClass]="closeButtonClasses()"
58219
- class="ml-4 transition-all rounded-lg p-1 hover:scale-110 active:scale-90">
58220
- <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
58221
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
58222
- </svg>
58223
- </button>
58224
- </div>
58225
- </div>
58226
-
58227
- <!-- Content -->
58228
- <div [ngClass]="contentClasses()" class="px-6 py-6 max-h-[70vh] overflow-y-auto backdrop-blur-sm">
58229
- <symphiq-tooltip-container />
58230
-
58231
- <!-- At a Glance Summary -->
58232
- <div [ngClass]="sectionCardClasses()" class="rounded-xl p-6 mb-6">
58233
- <h4 [ngClass]="sectionTitleClasses()" class="text-sm font-semibold uppercase tracking-wider mb-4">
58234
- At a Glance
58235
- </h4>
58236
- <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
58237
- <!-- YTD Value -->
58238
- <div>
58239
- <div class="mb-1.5">
58240
- <p [ngClass]="labelClasses()" class="text-xs font-medium uppercase tracking-wider">
58241
- Year to date
58242
- </p>
58243
- <p [ngClass]="dateLabelClasses()" class="text-xs">
58244
- {{ ytdStartDate() }}
58245
- </p>
58246
- <p [ngClass]="dateLabelClasses()" class="text-xs">
58247
- {{ ytdEndDate() }}
58248
- </p>
58249
- </div>
58250
- <p [ngClass]="valueClasses()" class="text-xl font-bold mb-2">
58251
- {{ formatMetricValue(ytdValue(), metricData()?.metric || '') }}
58252
- </p>
58253
- @if (ytdChangePercentage() !== null) {
58254
- <symphiq-target-change-badge
58255
- [viewMode]="viewMode()"
58256
- [percentageChange]="ytdChangePercentage()!"
58257
- [metric]="metricData()?.metric || ''"
58258
- [priorYear]="priorYear()"
58259
- [isCompact]="true"
58260
- />
58261
- }
58262
- </div>
58263
-
58264
- <!-- Same Period Last Year -->
58265
- <div>
58266
- <div class="mb-1.5">
58267
- <p [ngClass]="labelClasses()" class="text-xs font-medium uppercase tracking-wider">
58268
- Same period last year
58269
- </p>
58270
- <p [ngClass]="dateLabelClasses()" class="text-xs">
58271
- {{ priorYearStartDate() }}
58272
- </p>
58273
- <p [ngClass]="dateLabelClasses()" class="text-xs">
58274
- {{ priorYearEndDate() }}
58275
- </p>
58276
- </div>
58277
- <p [ngClass]="valueClasses()" class="text-xl font-bold">
58278
- {{ formatMetricValue(samePeriodLastYearValue(), metricData()?.metric || '') }}
58279
- </p>
58280
- </div>
58281
-
58282
- <!-- Full Last Year -->
58283
- <div>
58284
- <p [ngClass]="labelClasses()" class="text-xs font-medium uppercase tracking-wider mb-1.5">
58285
- Full {{ priorYear() }} Actual
58286
- </p>
58287
- <p [ngClass]="valueClasses()" class="text-xl font-bold">
58288
- {{ formatMetricValue(metricData()?.currentValue || 0, metricData()?.metric || '') }}
58289
- </p>
58290
- </div>
58291
-
58292
- <!-- Current Pace -->
58293
- @if (pacingInfo()) {
58294
- <div>
58295
- <p [ngClass]="labelClasses()" class="text-xs font-medium uppercase tracking-wider mb-1.5">
58296
- Pace for {{ currentYear() }}
58297
- </p>
58298
- <p [ngClass]="projectedValueClasses()" class="text-xl font-bold mb-2">
58299
- {{ formatMetricValue(pacingInfo()!.projectedValue, metricData()?.metric || '', false) }}
58300
- </p>
58301
- <symphiq-pacing-status-badge
58302
- [viewMode]="viewMode()"
58303
- [pacingPercentage]="pacingInfo()!.pacingPercentage"
58304
- [status]="pacingInfo()!.status"
58305
- [showAsFullText]="false"
58306
- [isCompact]="true"
58307
- [showEmphasizedPercentage]="true"
58308
- />
58309
- </div>
58310
- }
58311
-
58312
- <!-- Current Target -->
58313
- <div>
58314
- <p [ngClass]="labelClasses()" class="text-xs font-medium uppercase tracking-wider mb-1.5">
58315
- {{ currentYear() }} Target
58316
- </p>
58317
- <p [ngClass]="targetValueClasses()" class="text-xl font-bold">
58318
- {{ formatMetricValue(metricData()?.targetValue || 0, metricData()?.metric || '', false) }}
58319
- </p>
58320
- </div>
58321
- </div>
58322
- </div>
58323
-
58324
- <!-- Target Analysis -->
58325
- <div [ngClass]="sectionCardClasses()" class="rounded-xl p-6 mb-6">
58326
- <h4 [ngClass]="sectionTitleClasses()" class="text-sm font-semibold uppercase tracking-wider mb-4">
58327
- Target Analysis
58328
- </h4>
58329
-
58330
- <div class="mb-4">
58331
- <p [ngClass]="labelClasses()" class="text-xs font-medium uppercase tracking-wider mb-2">
58332
- Your Target
58333
- </p>
58334
- <p [ngClass]="targetValueClasses()" class="text-3xl font-extrabold mb-3">
58335
- {{ formatMetricValue(metricData()?.targetValue || 0, metricData()?.metric || '', false) }}
58336
- </p>
58337
- <p [ngClass]="descriptionClasses()" class="text-sm leading-relaxed">
58338
- Your target represents a {{ formatPercentage(Math.abs(metricData()?.percentageIncrease || 0), 1) }}
58339
- {{ (metricData()?.percentageIncrease || 0) >= 0 ? 'increase' : 'decrease' }}
58340
- from your {{ priorYear() }} actual of
58341
- {{ formatMetricValue(metricData()?.currentValue || 0, metricData()?.metric || '') }}.
58342
- </p>
58343
- </div>
58344
-
58345
- @if (pacingInfo()) {
58346
- <div class="mb-4">
58347
- <symphiq-pacing-status-badge
58348
- [viewMode]="viewMode()"
58349
- [pacingPercentage]="pacingInfo()!.pacingPercentage"
58350
- [status]="pacingInfo()!.status"
58351
- [showAsFullText]="true"
58352
- [isCompact]="false"
58353
- [showEmphasizedPercentage]="true"
58354
- />
58355
- </div>
58356
-
58357
- <div class="mb-4">
58358
- <p [ngClass]="descriptionClasses()" class="text-sm leading-relaxed">
58359
- {{ gapAnalysisText() }}
58360
- </p>
58361
- </div>
58362
-
58363
- <!-- Progress to Target Chart -->
58364
- <symphiq-progress-to-target-chart
58365
- [data]="progressToTargetData()"
58366
- [viewMode]="viewMode()"
58367
- />
58368
- }
58369
- </div>
58370
-
58371
- <!-- Contributing Metrics Table (only for funnel stage metrics) -->
58372
- @if (contributingMetrics().length > 0) {
58373
- <div [ngClass]="sectionCardClasses()" class="rounded-xl p-6 mb-6">
58374
- <h4 [ngClass]="sectionTitleClasses()" class="text-sm font-semibold uppercase tracking-wider mb-4">
58375
- Contributing Metric Targets
58376
- </h4>
58377
- <div class="overflow-x-auto">
58378
- <table class="w-full">
58379
- <thead>
58380
- <tr [ngClass]="tableHeaderClasses()" class="border-b">
58381
- <th class="text-left py-3 px-4 text-xs font-semibold uppercase tracking-wider">Metric</th>
58382
- <th class="text-right py-3 px-4 text-xs font-semibold uppercase tracking-wider">Target</th>
58383
- <th class="text-right py-3 px-4 text-xs font-semibold uppercase tracking-wider">Improve by</th>
58384
- </tr>
58385
- </thead>
58386
- <tbody>
58387
- @for (metric of contributingMetrics(); track metric.metric) {
58388
- <tr [ngClass]="tableRowClasses()" class="border-b transition-colors">
58389
- <td class="py-3 px-4">
58390
- <div class="flex items-center gap-2">
58391
- <span class="text-sm font-medium">{{ getMetricTitle(metric) }}</span>
58392
- @if (metric.description) {
58393
- <button
58394
- type="button"
58395
- [ngClass]="infoIconClasses()"
58396
- class="flex-shrink-0 w-5 h-5 rounded-full inline-flex items-center justify-center transition-colors"
58397
- [libSymphiqTooltip]="getMarkdownTooltipContent(metric.description, getMetricTitle(metric))"
58398
- tooltipType="markdown"
58399
- tooltipPosition="right">
58400
- <svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
58401
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
58402
- </svg>
58403
- </button>
58404
- }
58405
- </div>
58406
- </td>
58407
- <td class="py-3 px-4 text-right">
58408
- <span [ngClass]="targetValueClasses()" class="text-sm font-semibold">
58409
- {{ formatMetricValue(metric.targetValue, metric.metric, false) }}
58410
- </span>
58411
- </td>
58412
- <td class="py-3 px-4 text-right">
58413
- <div class="flex items-center justify-end gap-2">
58414
- <span class="text-sm font-medium">
58415
- {{ formatPercentage(Math.abs(metric.percentageIncrease), 1) }}
58416
- </span>
58417
- <svg
58418
- class="w-4 h-4 text-emerald-500"
58419
- fill="none"
58420
- stroke="currentColor"
58421
- viewBox="0 0 24 24">
58422
- <path
58423
- stroke-linecap="round"
58424
- stroke-linejoin="round"
58425
- stroke-width="2"
58426
- [attr.d]="metric.percentageIncrease >= 0 ? 'M5 10l7-7m0 0l7 7m-7-7v18' : 'M19 14l-7 7m0 0l-7-7m7 7V3'" />
58427
- </svg>
58428
- </div>
58429
- </td>
58430
- </tr>
58431
- }
58432
- </tbody>
58433
- </table>
58434
- </div>
58435
- </div>
58436
- }
58437
-
58438
- <!-- Pacing Chart -->
58439
- @if (pacingChartData()) {
58440
- <div [ngClass]="sectionCardClasses()" class="rounded-xl p-6">
58441
- <h4 [ngClass]="sectionTitleClasses()" class="text-sm font-semibold uppercase tracking-wider mb-4">
58442
- Pace
58443
- </h4>
58444
- <div class="min-h-[400px]">
58445
- <symphiq-line-chart
58446
- [chart]="pacingChartData()!"
58447
- [showAxisLabels]="true"
58448
- [viewMode]="viewMode()"
58449
- [currencySymbol]="'$'"
58450
- />
58451
- </div>
58452
- <p [ngClass]="descriptionClasses()" class="text-sm leading-relaxed mt-4">
58453
- {{ chartLegendDescription() }}
58454
- </p>
58455
- <p [ngClass]="descriptionClasses()" class="text-sm leading-relaxed mt-2">
58456
- {{ chartDescriptionSentence1() }}
58457
- </p>
58458
- <p [ngClass]="descriptionClasses()" class="text-sm leading-relaxed mt-2">
58459
- {{ chartDescriptionSentence2() }}
58460
- </p>
58461
- </div>
58462
- }
58463
- </div>
58464
-
58465
- <!-- Footer -->
58466
- <div [ngClass]="footerClasses()" class="px-6 py-4 border-t">
58467
- <button
58468
- (click)="close()"
58469
- [ngClass]="closeFooterButtonClasses()"
58470
- class="w-full px-4 py-2 rounded-lg transition-all font-medium hover:scale-[1.02] active:scale-[0.98]">
58471
- Close
58472
- </button>
58473
- </div>
58474
- </div>
58475
- </div>
58476
- </div>
58477
- }
58276
+ template: `
58277
+ @if (isOpen()) {
58278
+ <div class="fixed inset-0 overflow-y-auto z-50" (click)="close()">
58279
+ <div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
58280
+ <div
58281
+ [ngClass]="backdropClasses()"
58282
+ class="fixed inset-0 backdrop-blur-md"
58283
+ aria-hidden="true"
58284
+ @fadeIn>
58285
+ </div>
58286
+
58287
+ <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
58288
+
58289
+ <div
58290
+ (click)="$event.stopPropagation()"
58291
+ [ngClass]="modalContainerClasses()"
58292
+ class="relative inline-block align-bottom rounded-2xl text-left overflow-hidden shadow-xl sm:my-8 sm:align-middle sm:w-full sm:max-w-4xl border backdrop-blur-xl"
58293
+ @slideUpFade>
58294
+
58295
+ <!-- Header -->
58296
+ <div [ngClass]="headerClasses()" class="px-6 py-5 border-b backdrop-blur-sm sticky top-0 z-10">
58297
+ <div class="flex items-start justify-between">
58298
+ <div class="flex-1">
58299
+ <div class="flex items-center gap-3 mb-2">
58300
+ <h3 [ngClass]="titleClasses()" class="text-xl font-bold leading-none">
58301
+ {{ metricTitle() }}
58302
+ </h3>
58303
+ @if (metricData()?.description) {
58304
+ <button
58305
+ type="button"
58306
+ [ngClass]="headerInfoIconClasses()"
58307
+ class="flex-shrink-0 w-7 h-7 rounded-full inline-flex items-center justify-center transition-colors"
58308
+ [libSymphiqTooltip]="getMarkdownTooltipContent(metricData()!.description!, metricTitle())"
58309
+ tooltipType="markdown"
58310
+ tooltipPosition="right">
58311
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
58312
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
58313
+ </svg>
58314
+ </button>
58315
+ }
58316
+ </div>
58317
+ </div>
58318
+ <button
58319
+ (click)="close()"
58320
+ [ngClass]="closeButtonClasses()"
58321
+ class="ml-4 transition-all rounded-lg p-1 hover:scale-110 active:scale-90">
58322
+ <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
58323
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
58324
+ </svg>
58325
+ </button>
58326
+ </div>
58327
+ </div>
58328
+
58329
+ <!-- Content -->
58330
+ <div [ngClass]="contentClasses()" class="px-6 py-6 max-h-[70vh] overflow-y-auto backdrop-blur-sm">
58331
+ <symphiq-tooltip-container />
58332
+
58333
+ <!-- At a Glance Summary -->
58334
+ <div [ngClass]="sectionCardClasses()" class="rounded-xl p-6 mb-6">
58335
+ <h4 [ngClass]="sectionTitleClasses()" class="text-sm font-semibold uppercase tracking-wider mb-4">
58336
+ At a Glance
58337
+ </h4>
58338
+ <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
58339
+ <!-- YTD Value -->
58340
+ <div>
58341
+ <div class="mb-1.5">
58342
+ <p [ngClass]="labelClasses()" class="text-xs font-medium uppercase tracking-wider">
58343
+ Year to date
58344
+ </p>
58345
+ <p [ngClass]="dateLabelClasses()" class="text-xs">
58346
+ {{ ytdStartDate() }}
58347
+ </p>
58348
+ <p [ngClass]="dateLabelClasses()" class="text-xs">
58349
+ {{ ytdEndDate() }}
58350
+ </p>
58351
+ </div>
58352
+ <p [ngClass]="valueClasses()" class="text-xl font-bold mb-2">
58353
+ {{ formatMetricValue(ytdValue(), metricData()?.metric || '') }}
58354
+ </p>
58355
+ @if (ytdChangePercentage() !== null) {
58356
+ <symphiq-target-change-badge
58357
+ [viewMode]="viewMode()"
58358
+ [percentageChange]="ytdChangePercentage()!"
58359
+ [metric]="metricData()?.metric || ''"
58360
+ [priorYear]="priorYear()"
58361
+ [isCompact]="true"
58362
+ />
58363
+ }
58364
+ </div>
58365
+
58366
+ <!-- Same Period Last Year -->
58367
+ <div>
58368
+ <div class="mb-1.5">
58369
+ <p [ngClass]="labelClasses()" class="text-xs font-medium uppercase tracking-wider">
58370
+ Same period last year
58371
+ </p>
58372
+ <p [ngClass]="dateLabelClasses()" class="text-xs">
58373
+ {{ priorYearStartDate() }}
58374
+ </p>
58375
+ <p [ngClass]="dateLabelClasses()" class="text-xs">
58376
+ {{ priorYearEndDate() }}
58377
+ </p>
58378
+ </div>
58379
+ <p [ngClass]="valueClasses()" class="text-xl font-bold">
58380
+ {{ formatMetricValue(samePeriodLastYearValue(), metricData()?.metric || '') }}
58381
+ </p>
58382
+ </div>
58383
+
58384
+ <!-- Full Last Year -->
58385
+ <div>
58386
+ <p [ngClass]="labelClasses()" class="text-xs font-medium uppercase tracking-wider mb-1.5">
58387
+ Full {{ priorYear() }} Actual
58388
+ </p>
58389
+ <p [ngClass]="valueClasses()" class="text-xl font-bold">
58390
+ {{ formatMetricValue(metricData()?.currentValue || 0, metricData()?.metric || '') }}
58391
+ </p>
58392
+ </div>
58393
+
58394
+ <!-- Current Pace -->
58395
+ @if (pacingInfo()) {
58396
+ <div>
58397
+ <p [ngClass]="labelClasses()" class="text-xs font-medium uppercase tracking-wider mb-1.5">
58398
+ Pace for {{ currentYear() }}
58399
+ </p>
58400
+ <p [ngClass]="projectedValueClasses()" class="text-xl font-bold mb-2">
58401
+ {{ formatMetricValue(pacingInfo()!.projectedValue, metricData()?.metric || '', false) }}
58402
+ </p>
58403
+ <symphiq-pacing-status-badge
58404
+ [viewMode]="viewMode()"
58405
+ [pacingPercentage]="pacingInfo()!.pacingPercentage"
58406
+ [status]="pacingInfo()!.status"
58407
+ [showAsFullText]="false"
58408
+ [isCompact]="true"
58409
+ [showEmphasizedPercentage]="true"
58410
+ />
58411
+ </div>
58412
+ }
58413
+
58414
+ <!-- Current Target -->
58415
+ <div>
58416
+ <p [ngClass]="labelClasses()" class="text-xs font-medium uppercase tracking-wider mb-1.5">
58417
+ {{ currentYear() }} Target
58418
+ </p>
58419
+ <p [ngClass]="targetValueClasses()" class="text-xl font-bold">
58420
+ {{ formatMetricValue(metricData()?.targetValue || 0, metricData()?.metric || '', false) }}
58421
+ </p>
58422
+ </div>
58423
+ </div>
58424
+ </div>
58425
+
58426
+ <!-- Target Analysis -->
58427
+ <div [ngClass]="sectionCardClasses()" class="rounded-xl p-6 mb-6">
58428
+ <h4 [ngClass]="sectionTitleClasses()" class="text-sm font-semibold uppercase tracking-wider mb-4">
58429
+ Target Analysis
58430
+ </h4>
58431
+
58432
+ <div class="mb-4">
58433
+ <p [ngClass]="labelClasses()" class="text-xs font-medium uppercase tracking-wider mb-2">
58434
+ Your Target
58435
+ </p>
58436
+ <p [ngClass]="targetValueClasses()" class="text-3xl font-extrabold mb-3">
58437
+ {{ formatMetricValue(metricData()?.targetValue || 0, metricData()?.metric || '', false) }}
58438
+ </p>
58439
+ <p [ngClass]="descriptionClasses()" class="text-sm leading-relaxed">
58440
+ Your target represents a {{ formatPercentage(Math.abs(metricData()?.percentageIncrease || 0), 1) }}
58441
+ {{ (metricData()?.percentageIncrease || 0) >= 0 ? 'increase' : 'decrease' }}
58442
+ from your {{ priorYear() }} actual of
58443
+ {{ formatMetricValue(metricData()?.currentValue || 0, metricData()?.metric || '') }}.
58444
+ </p>
58445
+ </div>
58446
+
58447
+ @if (pacingInfo()) {
58448
+ <div class="mb-4">
58449
+ <symphiq-pacing-status-badge
58450
+ [viewMode]="viewMode()"
58451
+ [pacingPercentage]="pacingInfo()!.pacingPercentage"
58452
+ [status]="pacingInfo()!.status"
58453
+ [showAsFullText]="true"
58454
+ [isCompact]="false"
58455
+ [showEmphasizedPercentage]="true"
58456
+ />
58457
+ </div>
58458
+
58459
+ <div class="mb-4">
58460
+ <p [ngClass]="descriptionClasses()" class="text-sm leading-relaxed">
58461
+ {{ gapAnalysisText() }}
58462
+ </p>
58463
+ </div>
58464
+
58465
+ <!-- Progress to Target Chart -->
58466
+ <symphiq-progress-to-target-chart
58467
+ [data]="progressToTargetData()"
58468
+ [viewMode]="viewMode()"
58469
+ />
58470
+ }
58471
+ </div>
58472
+
58473
+ <!-- Contributing Metrics Table (only for funnel stage metrics) -->
58474
+ @if (contributingMetrics().length > 0) {
58475
+ <div [ngClass]="sectionCardClasses()" class="rounded-xl p-6 mb-6">
58476
+ <h4 [ngClass]="sectionTitleClasses()" class="text-sm font-semibold uppercase tracking-wider mb-4">
58477
+ Contributing Metric Targets
58478
+ </h4>
58479
+ <div class="overflow-x-auto">
58480
+ <table class="w-full">
58481
+ <thead>
58482
+ <tr [ngClass]="tableHeaderClasses()" class="border-b">
58483
+ <th class="text-left py-3 px-4 text-xs font-semibold uppercase tracking-wider">Metric</th>
58484
+ <th class="text-right py-3 px-4 text-xs font-semibold uppercase tracking-wider">Target</th>
58485
+ <th class="text-right py-3 px-4 text-xs font-semibold uppercase tracking-wider">Improve by</th>
58486
+ </tr>
58487
+ </thead>
58488
+ <tbody>
58489
+ @for (metric of contributingMetrics(); track metric.metric) {
58490
+ <tr [ngClass]="tableRowClasses()" class="border-b transition-colors">
58491
+ <td class="py-3 px-4">
58492
+ <div class="flex items-center gap-2">
58493
+ <span class="text-sm font-medium">{{ getMetricTitle(metric) }}</span>
58494
+ @if (metric.description) {
58495
+ <button
58496
+ type="button"
58497
+ [ngClass]="infoIconClasses()"
58498
+ class="flex-shrink-0 w-5 h-5 rounded-full inline-flex items-center justify-center transition-colors"
58499
+ [libSymphiqTooltip]="getMarkdownTooltipContent(metric.description, getMetricTitle(metric))"
58500
+ tooltipType="markdown"
58501
+ tooltipPosition="right">
58502
+ <svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
58503
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
58504
+ </svg>
58505
+ </button>
58506
+ }
58507
+ </div>
58508
+ </td>
58509
+ <td class="py-3 px-4 text-right">
58510
+ <span [ngClass]="targetValueClasses()" class="text-sm font-semibold">
58511
+ {{ formatMetricValue(metric.targetValue, metric.metric, false) }}
58512
+ </span>
58513
+ </td>
58514
+ <td class="py-3 px-4 text-right">
58515
+ <div class="flex items-center justify-end gap-2">
58516
+ <span class="text-sm font-medium">
58517
+ {{ formatPercentage(Math.abs(metric.percentageIncrease), 1) }}
58518
+ </span>
58519
+ <svg
58520
+ class="w-4 h-4 text-emerald-500"
58521
+ fill="none"
58522
+ stroke="currentColor"
58523
+ viewBox="0 0 24 24">
58524
+ <path
58525
+ stroke-linecap="round"
58526
+ stroke-linejoin="round"
58527
+ stroke-width="2"
58528
+ [attr.d]="metric.percentageIncrease >= 0 ? 'M5 10l7-7m0 0l7 7m-7-7v18' : 'M19 14l-7 7m0 0l-7-7m7 7V3'" />
58529
+ </svg>
58530
+ </div>
58531
+ </td>
58532
+ </tr>
58533
+ }
58534
+ </tbody>
58535
+ </table>
58536
+ </div>
58537
+ </div>
58538
+ }
58539
+
58540
+ <!-- Pacing Chart -->
58541
+ @if (pacingChartData()) {
58542
+ <div [ngClass]="sectionCardClasses()" class="rounded-xl p-6">
58543
+ <h4 [ngClass]="sectionTitleClasses()" class="text-sm font-semibold uppercase tracking-wider mb-4">
58544
+ Pace
58545
+ </h4>
58546
+ <div class="min-h-[400px]">
58547
+ <symphiq-line-chart
58548
+ [chart]="pacingChartData()!"
58549
+ [showAxisLabels]="true"
58550
+ [viewMode]="viewMode()"
58551
+ [currencySymbol]="'$'"
58552
+ />
58553
+ </div>
58554
+ <p [ngClass]="descriptionClasses()" class="text-sm leading-relaxed mt-4">
58555
+ {{ chartLegendDescription() }}
58556
+ </p>
58557
+ <p [ngClass]="descriptionClasses()" class="text-sm leading-relaxed mt-2">
58558
+ {{ chartDescriptionSentence1() }}
58559
+ </p>
58560
+ <p [ngClass]="descriptionClasses()" class="text-sm leading-relaxed mt-2">
58561
+ {{ chartDescriptionSentence2() }}
58562
+ </p>
58563
+ </div>
58564
+ }
58565
+ </div>
58566
+
58567
+ <!-- Footer -->
58568
+ <div [ngClass]="footerClasses()" class="px-6 py-4 border-t">
58569
+ <button
58570
+ (click)="close()"
58571
+ [ngClass]="closeFooterButtonClasses()"
58572
+ class="w-full px-4 py-2 rounded-lg transition-all font-medium hover:scale-[1.02] active:scale-[0.98]">
58573
+ Close
58574
+ </button>
58575
+ </div>
58576
+ </div>
58577
+ </div>
58578
+ </div>
58579
+ }
58478
58580
  `
58479
58581
  }]
58480
58582
  }], null, { viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], metricEnum: [{ type: i0.Input, args: [{ isSignal: true, alias: "metricEnum", required: false }] }], metricData: [{ type: i0.Input, args: [{ isSignal: true, alias: "metricData", required: false }] }], contributingMetrics: [{ type: i0.Input, args: [{ isSignal: true, alias: "contributingMetrics", required: false }] }], pacingMetrics: [{ type: i0.Input, args: [{ isSignal: true, alias: "pacingMetrics", required: false }] }], isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }] }); })();