@eric-emg/symphiq-components 1.2.34 → 1.2.36
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.
- package/fesm2022/symphiq-components.mjs +253 -284
- package/fesm2022/symphiq-components.mjs.map +1 -1
- package/index.d.ts +20 -6
- package/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@ import { Injectable, signal, input, ChangeDetectionStrategy, Component, output,
|
|
|
5
5
|
import { BehaviorSubject } from 'rxjs';
|
|
6
6
|
import * as i1 from '@angular/common';
|
|
7
7
|
import { NgClass, CommonModule } from '@angular/common';
|
|
8
|
-
import * as
|
|
8
|
+
import * as i6 from '@angular/forms';
|
|
9
9
|
import { FormsModule } from '@angular/forms';
|
|
10
10
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
11
11
|
import { trigger, transition, style, animate } from '@angular/animations';
|
|
@@ -163,23 +163,45 @@ class TooltipService {
|
|
|
163
163
|
content: null,
|
|
164
164
|
position: 'top',
|
|
165
165
|
targetRect: null,
|
|
166
|
-
visible: false
|
|
166
|
+
visible: false,
|
|
167
|
+
scrollContainer: null,
|
|
168
|
+
checkHideCallback: undefined
|
|
167
169
|
});
|
|
168
170
|
this.tooltipState$ = this.tooltipState.asObservable();
|
|
171
|
+
this.scrollContainer = null;
|
|
172
|
+
this.isTooltipHovered = false;
|
|
169
173
|
}
|
|
170
|
-
|
|
174
|
+
setScrollContainer(container) {
|
|
175
|
+
this.scrollContainer = container;
|
|
176
|
+
}
|
|
177
|
+
setTooltipHovered(hovered) {
|
|
178
|
+
this.isTooltipHovered = hovered;
|
|
179
|
+
}
|
|
180
|
+
isHoveredOverTooltip() {
|
|
181
|
+
return this.isTooltipHovered;
|
|
182
|
+
}
|
|
183
|
+
triggerHideCheck() {
|
|
184
|
+
const callback = this.tooltipState.value.checkHideCallback;
|
|
185
|
+
if (callback) {
|
|
186
|
+
callback();
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
show(type, content, targetRect, position = 'top', mousePosition, checkHideCallback) {
|
|
171
190
|
// Auto-adjust position if too close to screen edges
|
|
172
191
|
let adjustedPosition = position;
|
|
173
192
|
// Use different thresholds based on tooltip type
|
|
174
193
|
// Insight tooltips can be quite tall, so need more space
|
|
175
194
|
const HORIZONTAL_THRESHOLD = 200;
|
|
176
195
|
const VERTICAL_THRESHOLD = type === 'insight' ? 350 : 200;
|
|
196
|
+
// Get viewport dimensions - use scroll container if available, otherwise window
|
|
197
|
+
const viewportWidth = this.scrollContainer?.clientWidth || window.innerWidth;
|
|
198
|
+
const viewportHeight = this.scrollContainer?.clientHeight || window.innerHeight;
|
|
177
199
|
// Check left edge
|
|
178
200
|
if (position === 'left' && targetRect.left < HORIZONTAL_THRESHOLD) {
|
|
179
201
|
adjustedPosition = 'right';
|
|
180
202
|
}
|
|
181
203
|
// Check right edge
|
|
182
|
-
if (position === 'right' && (
|
|
204
|
+
if (position === 'right' && (viewportWidth - targetRect.right) < HORIZONTAL_THRESHOLD) {
|
|
183
205
|
adjustedPosition = 'left';
|
|
184
206
|
}
|
|
185
207
|
// Check top edge
|
|
@@ -187,12 +209,12 @@ class TooltipService {
|
|
|
187
209
|
adjustedPosition = 'bottom';
|
|
188
210
|
}
|
|
189
211
|
// Check bottom edge - prioritize flipping to top if not enough space
|
|
190
|
-
if (position === 'bottom' && (
|
|
212
|
+
if (position === 'bottom' && (viewportHeight - targetRect.bottom) < VERTICAL_THRESHOLD) {
|
|
191
213
|
adjustedPosition = 'top';
|
|
192
214
|
}
|
|
193
215
|
// Smart auto-detection for 'top' position tooltips near bottom
|
|
194
216
|
if (position === 'top') {
|
|
195
|
-
const spaceBelow =
|
|
217
|
+
const spaceBelow = viewportHeight - targetRect.bottom;
|
|
196
218
|
const spaceAbove = targetRect.top;
|
|
197
219
|
// If more space above and not enough space below, keep it on top
|
|
198
220
|
// If more space below, switch to bottom
|
|
@@ -203,15 +225,27 @@ class TooltipService {
|
|
|
203
225
|
adjustedPosition = 'bottom';
|
|
204
226
|
}
|
|
205
227
|
}
|
|
206
|
-
this.tooltipState.next({
|
|
228
|
+
this.tooltipState.next({
|
|
229
|
+
type,
|
|
230
|
+
content,
|
|
231
|
+
position: adjustedPosition,
|
|
232
|
+
targetRect,
|
|
233
|
+
mousePosition,
|
|
234
|
+
visible: true,
|
|
235
|
+
scrollContainer: this.scrollContainer,
|
|
236
|
+
checkHideCallback
|
|
237
|
+
});
|
|
207
238
|
}
|
|
208
239
|
hide() {
|
|
240
|
+
this.isTooltipHovered = false;
|
|
209
241
|
this.tooltipState.next({
|
|
210
242
|
type: null,
|
|
211
243
|
content: null,
|
|
212
244
|
position: 'top',
|
|
213
245
|
targetRect: null,
|
|
214
|
-
visible: false
|
|
246
|
+
visible: false,
|
|
247
|
+
scrollContainer: this.scrollContainer,
|
|
248
|
+
checkHideCallback: undefined
|
|
215
249
|
});
|
|
216
250
|
}
|
|
217
251
|
updatePosition(targetRect) {
|
|
@@ -1456,6 +1490,11 @@ class TooltipDirective {
|
|
|
1456
1490
|
this.isHovered.set(false);
|
|
1457
1491
|
this.scheduleHide();
|
|
1458
1492
|
}
|
|
1493
|
+
onMouseEnterAgain() {
|
|
1494
|
+
// If user returns to element while tooltip is still visible, cancel hide
|
|
1495
|
+
this.clearHideTimeout();
|
|
1496
|
+
this.isHovered.set(true);
|
|
1497
|
+
}
|
|
1459
1498
|
onFocus() {
|
|
1460
1499
|
this.clearHideTimeout();
|
|
1461
1500
|
this.isHovered.set(true);
|
|
@@ -1475,14 +1514,17 @@ class TooltipDirective {
|
|
|
1475
1514
|
const position = this.tooltipPosition();
|
|
1476
1515
|
if (content && this.isHovered()) {
|
|
1477
1516
|
const mousePos = position === 'auto' ? { x: this.mouseX, y: this.mouseY } : undefined;
|
|
1478
|
-
|
|
1517
|
+
// Pass a callback that the tooltip can use to trigger hide checks
|
|
1518
|
+
const checkHideCallback = () => this.scheduleHide();
|
|
1519
|
+
this.tooltipService.show(type, content, rect, position, mousePos, checkHideCallback);
|
|
1479
1520
|
}
|
|
1480
1521
|
}, this.tooltipDelay());
|
|
1481
1522
|
}
|
|
1482
1523
|
scheduleHide() {
|
|
1483
1524
|
this.clearHideTimeout();
|
|
1484
1525
|
this.hideTimeout = setTimeout(() => {
|
|
1485
|
-
if
|
|
1526
|
+
// Only hide if neither the element nor the tooltip is hovered
|
|
1527
|
+
if (!this.isHovered() && !this.tooltipService.isHoveredOverTooltip()) {
|
|
1486
1528
|
this.tooltipService.hide();
|
|
1487
1529
|
}
|
|
1488
1530
|
}, 100);
|
|
@@ -1506,7 +1548,7 @@ class TooltipDirective {
|
|
|
1506
1548
|
}
|
|
1507
1549
|
static { this.ɵfac = function TooltipDirective_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TooltipDirective)(); }; }
|
|
1508
1550
|
static { this.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: TooltipDirective, selectors: [["", "libSymphiqTooltip", ""]], hostBindings: function TooltipDirective_HostBindings(rf, ctx) { if (rf & 1) {
|
|
1509
|
-
i0.ɵɵlistener("mouseenter", function TooltipDirective_mouseenter_HostBindingHandler(
|
|
1551
|
+
i0.ɵɵlistener("mouseenter", function TooltipDirective_mouseenter_HostBindingHandler() { return ctx.onMouseEnterAgain(); })("mousemove", function TooltipDirective_mousemove_HostBindingHandler($event) { return ctx.onMouseMove($event); })("mouseleave", function TooltipDirective_mouseleave_HostBindingHandler() { return ctx.onMouseLeave(); })("focus", function TooltipDirective_focus_HostBindingHandler() { return ctx.onFocus(); })("blur", function TooltipDirective_blur_HostBindingHandler() { return ctx.onBlur(); });
|
|
1510
1552
|
} }, inputs: { symphiqTooltip: [1, "libSymphiqTooltip", "symphiqTooltip"], tooltipType: [1, "tooltipType"], tooltipPosition: [1, "tooltipPosition"], tooltipDelay: [1, "tooltipDelay"] } }); }
|
|
1511
1553
|
}
|
|
1512
1554
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TooltipDirective, [{
|
|
@@ -1524,6 +1566,9 @@ class TooltipDirective {
|
|
|
1524
1566
|
}], onMouseLeave: [{
|
|
1525
1567
|
type: HostListener,
|
|
1526
1568
|
args: ['mouseleave']
|
|
1569
|
+
}], onMouseEnterAgain: [{
|
|
1570
|
+
type: HostListener,
|
|
1571
|
+
args: ['mouseenter']
|
|
1527
1572
|
}], onFocus: [{
|
|
1528
1573
|
type: HostListener,
|
|
1529
1574
|
args: ['focus']
|
|
@@ -10778,110 +10823,110 @@ const _c0$6 = () => [];
|
|
|
10778
10823
|
function TooltipContainerComponent_Conditional_0_Case_3_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
10779
10824
|
i0.ɵɵelement(0, "symphiq-metric-value-tooltip", 6);
|
|
10780
10825
|
} if (rf & 2) {
|
|
10781
|
-
const
|
|
10782
|
-
i0.ɵɵproperty("content",
|
|
10826
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
10827
|
+
i0.ɵɵproperty("content", ctx_r1.metricContent())("isLightMode", ctx_r1.isLightMode());
|
|
10783
10828
|
} }
|
|
10784
10829
|
function TooltipContainerComponent_Conditional_0_Case_3_Template(rf, ctx) { if (rf & 1) {
|
|
10785
10830
|
i0.ɵɵconditionalCreate(0, TooltipContainerComponent_Conditional_0_Case_3_Conditional_0_Template, 1, 2, "symphiq-metric-value-tooltip", 6);
|
|
10786
10831
|
} if (rf & 2) {
|
|
10787
|
-
const
|
|
10788
|
-
i0.ɵɵconditional(
|
|
10832
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
10833
|
+
i0.ɵɵconditional(ctx_r1.metricContent() ? 0 : -1);
|
|
10789
10834
|
} }
|
|
10790
10835
|
function TooltipContainerComponent_Conditional_0_Case_4_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
10791
10836
|
i0.ɵɵelement(0, "symphiq-status-badge-tooltip", 6);
|
|
10792
10837
|
} if (rf & 2) {
|
|
10793
|
-
const
|
|
10794
|
-
i0.ɵɵproperty("content",
|
|
10838
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
10839
|
+
i0.ɵɵproperty("content", ctx_r1.statusContent())("isLightMode", ctx_r1.isLightMode());
|
|
10795
10840
|
} }
|
|
10796
10841
|
function TooltipContainerComponent_Conditional_0_Case_4_Template(rf, ctx) { if (rf & 1) {
|
|
10797
10842
|
i0.ɵɵconditionalCreate(0, TooltipContainerComponent_Conditional_0_Case_4_Conditional_0_Template, 1, 2, "symphiq-status-badge-tooltip", 6);
|
|
10798
10843
|
} if (rf & 2) {
|
|
10799
|
-
const
|
|
10800
|
-
i0.ɵɵconditional(
|
|
10844
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
10845
|
+
i0.ɵɵconditional(ctx_r1.statusContent() ? 0 : -1);
|
|
10801
10846
|
} }
|
|
10802
10847
|
function TooltipContainerComponent_Conditional_0_Case_5_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
10803
10848
|
i0.ɵɵelement(0, "symphiq-trend-indicator-tooltip", 6);
|
|
10804
10849
|
} if (rf & 2) {
|
|
10805
|
-
const
|
|
10806
|
-
i0.ɵɵproperty("content",
|
|
10850
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
10851
|
+
i0.ɵɵproperty("content", ctx_r1.trendContent())("isLightMode", ctx_r1.isLightMode());
|
|
10807
10852
|
} }
|
|
10808
10853
|
function TooltipContainerComponent_Conditional_0_Case_5_Template(rf, ctx) { if (rf & 1) {
|
|
10809
10854
|
i0.ɵɵconditionalCreate(0, TooltipContainerComponent_Conditional_0_Case_5_Conditional_0_Template, 1, 2, "symphiq-trend-indicator-tooltip", 6);
|
|
10810
10855
|
} if (rf & 2) {
|
|
10811
|
-
const
|
|
10812
|
-
i0.ɵɵconditional(
|
|
10856
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
10857
|
+
i0.ɵɵconditional(ctx_r1.trendContent() ? 0 : -1);
|
|
10813
10858
|
} }
|
|
10814
10859
|
function TooltipContainerComponent_Conditional_0_Case_6_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
10815
10860
|
i0.ɵɵelement(0, "symphiq-priority-badge-tooltip", 6);
|
|
10816
10861
|
} if (rf & 2) {
|
|
10817
|
-
const
|
|
10818
|
-
i0.ɵɵproperty("content",
|
|
10862
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
10863
|
+
i0.ɵɵproperty("content", ctx_r1.priorityContent())("isLightMode", ctx_r1.isLightMode());
|
|
10819
10864
|
} }
|
|
10820
10865
|
function TooltipContainerComponent_Conditional_0_Case_6_Template(rf, ctx) { if (rf & 1) {
|
|
10821
10866
|
i0.ɵɵconditionalCreate(0, TooltipContainerComponent_Conditional_0_Case_6_Conditional_0_Template, 1, 2, "symphiq-priority-badge-tooltip", 6);
|
|
10822
10867
|
} if (rf & 2) {
|
|
10823
|
-
const
|
|
10824
|
-
i0.ɵɵconditional(
|
|
10868
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
10869
|
+
i0.ɵɵconditional(ctx_r1.priorityContent() ? 0 : -1);
|
|
10825
10870
|
} }
|
|
10826
10871
|
function TooltipContainerComponent_Conditional_0_Case_7_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
10827
10872
|
i0.ɵɵelement(0, "symphiq-badge-tooltip", 6);
|
|
10828
10873
|
} if (rf & 2) {
|
|
10829
|
-
const
|
|
10830
|
-
i0.ɵɵproperty("content",
|
|
10874
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
10875
|
+
i0.ɵɵproperty("content", ctx_r1.badgeContent())("isLightMode", ctx_r1.isLightMode());
|
|
10831
10876
|
} }
|
|
10832
10877
|
function TooltipContainerComponent_Conditional_0_Case_7_Template(rf, ctx) { if (rf & 1) {
|
|
10833
10878
|
i0.ɵɵconditionalCreate(0, TooltipContainerComponent_Conditional_0_Case_7_Conditional_0_Template, 1, 2, "symphiq-badge-tooltip", 6);
|
|
10834
10879
|
} if (rf & 2) {
|
|
10835
|
-
const
|
|
10836
|
-
i0.ɵɵconditional(
|
|
10880
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
10881
|
+
i0.ɵɵconditional(ctx_r1.badgeContent() ? 0 : -1);
|
|
10837
10882
|
} }
|
|
10838
10883
|
function TooltipContainerComponent_Conditional_0_Case_8_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
10839
10884
|
i0.ɵɵelement(0, "symphiq-breakdown-row-tooltip", 6);
|
|
10840
10885
|
} if (rf & 2) {
|
|
10841
|
-
const
|
|
10842
|
-
i0.ɵɵproperty("content",
|
|
10886
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
10887
|
+
i0.ɵɵproperty("content", ctx_r1.breakdownContent())("isLightMode", ctx_r1.isLightMode());
|
|
10843
10888
|
} }
|
|
10844
10889
|
function TooltipContainerComponent_Conditional_0_Case_8_Template(rf, ctx) { if (rf & 1) {
|
|
10845
10890
|
i0.ɵɵconditionalCreate(0, TooltipContainerComponent_Conditional_0_Case_8_Conditional_0_Template, 1, 2, "symphiq-breakdown-row-tooltip", 6);
|
|
10846
10891
|
} if (rf & 2) {
|
|
10847
|
-
const
|
|
10848
|
-
i0.ɵɵconditional(
|
|
10892
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
10893
|
+
i0.ɵɵconditional(ctx_r1.breakdownContent() ? 0 : -1);
|
|
10849
10894
|
} }
|
|
10850
10895
|
function TooltipContainerComponent_Conditional_0_Case_9_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
10851
10896
|
i0.ɵɵelement(0, "symphiq-competitive-benchmark-tooltip", 6);
|
|
10852
10897
|
} if (rf & 2) {
|
|
10853
|
-
const
|
|
10854
|
-
i0.ɵɵproperty("content",
|
|
10898
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
10899
|
+
i0.ɵɵproperty("content", ctx_r1.competitiveContent())("isLightMode", ctx_r1.isLightMode());
|
|
10855
10900
|
} }
|
|
10856
10901
|
function TooltipContainerComponent_Conditional_0_Case_9_Template(rf, ctx) { if (rf & 1) {
|
|
10857
10902
|
i0.ɵɵconditionalCreate(0, TooltipContainerComponent_Conditional_0_Case_9_Conditional_0_Template, 1, 2, "symphiq-competitive-benchmark-tooltip", 6);
|
|
10858
10903
|
} if (rf & 2) {
|
|
10859
|
-
const
|
|
10860
|
-
i0.ɵɵconditional(
|
|
10904
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
10905
|
+
i0.ɵɵconditional(ctx_r1.competitiveContent() ? 0 : -1);
|
|
10861
10906
|
} }
|
|
10862
10907
|
function TooltipContainerComponent_Conditional_0_Case_10_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
10863
10908
|
i0.ɵɵelement(0, "symphiq-insights-list-tooltip", 6);
|
|
10864
10909
|
} if (rf & 2) {
|
|
10865
|
-
const
|
|
10866
|
-
i0.ɵɵproperty("content",
|
|
10910
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
10911
|
+
i0.ɵɵproperty("content", ctx_r1.insightsListContent())("isLightMode", ctx_r1.isLightMode());
|
|
10867
10912
|
} }
|
|
10868
10913
|
function TooltipContainerComponent_Conditional_0_Case_10_Template(rf, ctx) { if (rf & 1) {
|
|
10869
10914
|
i0.ɵɵconditionalCreate(0, TooltipContainerComponent_Conditional_0_Case_10_Conditional_0_Template, 1, 2, "symphiq-insights-list-tooltip", 6);
|
|
10870
10915
|
} if (rf & 2) {
|
|
10871
|
-
const
|
|
10872
|
-
i0.ɵɵconditional(
|
|
10916
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
10917
|
+
i0.ɵɵconditional(ctx_r1.insightsListContent() ? 0 : -1);
|
|
10873
10918
|
} }
|
|
10874
10919
|
function TooltipContainerComponent_Conditional_0_Case_11_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
10875
10920
|
i0.ɵɵelement(0, "symphiq-narrative-tooltip", 6);
|
|
10876
10921
|
} if (rf & 2) {
|
|
10877
|
-
const
|
|
10878
|
-
i0.ɵɵproperty("content",
|
|
10922
|
+
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
10923
|
+
i0.ɵɵproperty("content", ctx_r1.narrativeContent())("isLightMode", ctx_r1.isLightMode());
|
|
10879
10924
|
} }
|
|
10880
10925
|
function TooltipContainerComponent_Conditional_0_Case_11_Template(rf, ctx) { if (rf & 1) {
|
|
10881
10926
|
i0.ɵɵconditionalCreate(0, TooltipContainerComponent_Conditional_0_Case_11_Conditional_0_Template, 1, 2, "symphiq-narrative-tooltip", 6);
|
|
10882
10927
|
} if (rf & 2) {
|
|
10883
|
-
const
|
|
10884
|
-
i0.ɵɵconditional(
|
|
10928
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
10929
|
+
i0.ɵɵconditional(ctx_r1.narrativeContent() ? 0 : -1);
|
|
10885
10930
|
} }
|
|
10886
10931
|
function TooltipContainerComponent_Conditional_0_Case_12_Conditional_1_For_1_Template(rf, ctx) { if (rf & 1) {
|
|
10887
10932
|
i0.ɵɵelementStart(0, "div", 7)(1, "div", 8);
|
|
@@ -10891,18 +10936,18 @@ function TooltipContainerComponent_Conditional_0_Case_12_Conditional_1_For_1_Tem
|
|
|
10891
10936
|
i0.ɵɵtext(4);
|
|
10892
10937
|
i0.ɵɵelementEnd()();
|
|
10893
10938
|
} if (rf & 2) {
|
|
10894
|
-
const
|
|
10939
|
+
const section_r3 = ctx.$implicit;
|
|
10895
10940
|
i0.ɵɵadvance(2);
|
|
10896
|
-
i0.ɵɵtextInterpolate(
|
|
10941
|
+
i0.ɵɵtextInterpolate(section_r3.title);
|
|
10897
10942
|
i0.ɵɵadvance(2);
|
|
10898
|
-
i0.ɵɵtextInterpolate(
|
|
10943
|
+
i0.ɵɵtextInterpolate(section_r3.content);
|
|
10899
10944
|
} }
|
|
10900
10945
|
function TooltipContainerComponent_Conditional_0_Case_12_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
10901
10946
|
i0.ɵɵrepeaterCreate(0, TooltipContainerComponent_Conditional_0_Case_12_Conditional_1_For_1_Template, 5, 2, "div", 7, i0.ɵɵrepeaterTrackByIndex);
|
|
10902
10947
|
} if (rf & 2) {
|
|
10903
10948
|
i0.ɵɵnextContext(2);
|
|
10904
|
-
const
|
|
10905
|
-
i0.ɵɵrepeater(
|
|
10949
|
+
const content_r4 = i0.ɵɵreadContextLet(2);
|
|
10950
|
+
i0.ɵɵrepeater(content_r4["sections"] || i0.ɵɵpureFunction0(0, _c0$6));
|
|
10906
10951
|
} }
|
|
10907
10952
|
function TooltipContainerComponent_Conditional_0_Case_12_Template(rf, ctx) { if (rf & 1) {
|
|
10908
10953
|
i0.ɵɵelementStart(0, "div", 3);
|
|
@@ -10910,25 +10955,25 @@ function TooltipContainerComponent_Conditional_0_Case_12_Template(rf, ctx) { if
|
|
|
10910
10955
|
i0.ɵɵelementEnd();
|
|
10911
10956
|
} if (rf & 2) {
|
|
10912
10957
|
i0.ɵɵnextContext();
|
|
10913
|
-
const
|
|
10914
|
-
const
|
|
10915
|
-
i0.ɵɵproperty("ngClass",
|
|
10958
|
+
const content_r4 = i0.ɵɵreadContextLet(2);
|
|
10959
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
10960
|
+
i0.ɵɵproperty("ngClass", ctx_r1.textClass());
|
|
10916
10961
|
i0.ɵɵadvance();
|
|
10917
|
-
i0.ɵɵconditional(
|
|
10962
|
+
i0.ɵɵconditional(content_r4 && typeof content_r4 === "object" && "sections" in content_r4 ? 1 : -1);
|
|
10918
10963
|
} }
|
|
10919
10964
|
function TooltipContainerComponent_Conditional_0_Case_13_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
10920
10965
|
i0.ɵɵtext(0);
|
|
10921
10966
|
} if (rf & 2) {
|
|
10922
10967
|
i0.ɵɵnextContext(2);
|
|
10923
|
-
const
|
|
10924
|
-
i0.ɵɵtextInterpolate1(" ",
|
|
10968
|
+
const content_r4 = i0.ɵɵreadContextLet(2);
|
|
10969
|
+
i0.ɵɵtextInterpolate1(" ", content_r4["text"], " ");
|
|
10925
10970
|
} }
|
|
10926
10971
|
function TooltipContainerComponent_Conditional_0_Case_13_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
10927
10972
|
i0.ɵɵtext(0);
|
|
10928
10973
|
} if (rf & 2) {
|
|
10929
10974
|
i0.ɵɵnextContext(2);
|
|
10930
|
-
const
|
|
10931
|
-
i0.ɵɵtextInterpolate1(" ",
|
|
10975
|
+
const content_r4 = i0.ɵɵreadContextLet(2);
|
|
10976
|
+
i0.ɵɵtextInterpolate1(" ", content_r4, " ");
|
|
10932
10977
|
} }
|
|
10933
10978
|
function TooltipContainerComponent_Conditional_0_Case_13_Template(rf, ctx) { if (rf & 1) {
|
|
10934
10979
|
i0.ɵɵelementStart(0, "div", 4);
|
|
@@ -10936,11 +10981,11 @@ function TooltipContainerComponent_Conditional_0_Case_13_Template(rf, ctx) { if
|
|
|
10936
10981
|
i0.ɵɵelementEnd();
|
|
10937
10982
|
} if (rf & 2) {
|
|
10938
10983
|
i0.ɵɵnextContext();
|
|
10939
|
-
const
|
|
10940
|
-
const
|
|
10941
|
-
i0.ɵɵproperty("ngClass",
|
|
10984
|
+
const content_r4 = i0.ɵɵreadContextLet(2);
|
|
10985
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
10986
|
+
i0.ɵɵproperty("ngClass", ctx_r1.textClass());
|
|
10942
10987
|
i0.ɵɵadvance();
|
|
10943
|
-
i0.ɵɵconditional(
|
|
10988
|
+
i0.ɵɵconditional(content_r4 && typeof content_r4 === "object" && "text" in content_r4 ? 1 : 2);
|
|
10944
10989
|
} }
|
|
10945
10990
|
function TooltipContainerComponent_Conditional_0_Case_14_Template(rf, ctx) { if (rf & 1) {
|
|
10946
10991
|
i0.ɵɵelementStart(0, "div", 5);
|
|
@@ -10948,28 +10993,30 @@ function TooltipContainerComponent_Conditional_0_Case_14_Template(rf, ctx) { if
|
|
|
10948
10993
|
i0.ɵɵelementEnd();
|
|
10949
10994
|
} if (rf & 2) {
|
|
10950
10995
|
i0.ɵɵnextContext();
|
|
10951
|
-
const
|
|
10952
|
-
const
|
|
10953
|
-
i0.ɵɵproperty("ngClass",
|
|
10996
|
+
const content_r4 = i0.ɵɵreadContextLet(2);
|
|
10997
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
10998
|
+
i0.ɵɵproperty("ngClass", ctx_r1.textClass());
|
|
10954
10999
|
i0.ɵɵadvance();
|
|
10955
|
-
i0.ɵɵtextInterpolate1(" ",
|
|
11000
|
+
i0.ɵɵtextInterpolate1(" ", content_r4, " ");
|
|
10956
11001
|
} }
|
|
10957
11002
|
function TooltipContainerComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
11003
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
10958
11004
|
i0.ɵɵelementStart(0, "div", 1)(1, "div", 2);
|
|
11005
|
+
i0.ɵɵlistener("mouseenter", function TooltipContainerComponent_Conditional_0_Template_div_mouseenter_1_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onTooltipMouseEnter()); })("mouseleave", function TooltipContainerComponent_Conditional_0_Template_div_mouseleave_1_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.onTooltipMouseLeave()); });
|
|
10959
11006
|
i0.ɵɵdeclareLet(2);
|
|
10960
11007
|
i0.ɵɵconditionalCreate(3, TooltipContainerComponent_Conditional_0_Case_3_Template, 1, 1)(4, TooltipContainerComponent_Conditional_0_Case_4_Template, 1, 1)(5, TooltipContainerComponent_Conditional_0_Case_5_Template, 1, 1)(6, TooltipContainerComponent_Conditional_0_Case_6_Template, 1, 1)(7, TooltipContainerComponent_Conditional_0_Case_7_Template, 1, 1)(8, TooltipContainerComponent_Conditional_0_Case_8_Template, 1, 1)(9, TooltipContainerComponent_Conditional_0_Case_9_Template, 1, 1)(10, TooltipContainerComponent_Conditional_0_Case_10_Template, 1, 1)(11, TooltipContainerComponent_Conditional_0_Case_11_Template, 1, 1)(12, TooltipContainerComponent_Conditional_0_Case_12_Template, 2, 2, "div", 3)(13, TooltipContainerComponent_Conditional_0_Case_13_Template, 3, 2, "div", 4)(14, TooltipContainerComponent_Conditional_0_Case_14_Template, 2, 2, "div", 5);
|
|
10961
11008
|
i0.ɵɵelementEnd()();
|
|
10962
11009
|
} if (rf & 2) {
|
|
10963
11010
|
let tmp_7_0;
|
|
10964
|
-
const
|
|
10965
|
-
i0.ɵɵstyleProp("left",
|
|
10966
|
-
i0.ɵɵproperty("ngClass",
|
|
11011
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
11012
|
+
i0.ɵɵstyleProp("left", ctx_r1.tooltipLeft(), "px")("top", ctx_r1.tooltipTop(), "px");
|
|
11013
|
+
i0.ɵɵproperty("ngClass", ctx_r1.containerClass())("@fadeInScale", undefined);
|
|
10967
11014
|
i0.ɵɵadvance();
|
|
10968
|
-
i0.ɵɵproperty("ngClass",
|
|
11015
|
+
i0.ɵɵproperty("ngClass", ctx_r1.contentClass());
|
|
10969
11016
|
i0.ɵɵadvance();
|
|
10970
|
-
i0.ɵɵstoreLet(
|
|
11017
|
+
i0.ɵɵstoreLet(ctx_r1.tooltipContent());
|
|
10971
11018
|
i0.ɵɵadvance();
|
|
10972
|
-
i0.ɵɵconditional((tmp_7_0 =
|
|
11019
|
+
i0.ɵɵconditional((tmp_7_0 = ctx_r1.tooltipType()) === "metric" ? 3 : tmp_7_0 === "status" ? 4 : tmp_7_0 === "trend" ? 5 : tmp_7_0 === "priority" ? 6 : tmp_7_0 === "badge" ? 7 : tmp_7_0 === "breakdown" ? 8 : tmp_7_0 === "competitive" ? 9 : tmp_7_0 === "insightsList" ? 10 : tmp_7_0 === "narrative" ? 11 : tmp_7_0 === "insight" ? 12 : tmp_7_0 === "text" ? 13 : 14);
|
|
10973
11020
|
} }
|
|
10974
11021
|
class TooltipContainerComponent {
|
|
10975
11022
|
constructor() {
|
|
@@ -10983,7 +11030,8 @@ class TooltipContainerComponent {
|
|
|
10983
11030
|
position: 'top',
|
|
10984
11031
|
targetRect: null,
|
|
10985
11032
|
mousePosition: undefined,
|
|
10986
|
-
visible: false
|
|
11033
|
+
visible: false,
|
|
11034
|
+
scrollContainer: null
|
|
10987
11035
|
}, ...(ngDevMode ? [{ debugName: "tooltipStateSignal" }] : []));
|
|
10988
11036
|
this.isVisible = computed(() => this.tooltipStateSignal().visible, ...(ngDevMode ? [{ debugName: "isVisible" }] : []));
|
|
10989
11037
|
this.tooltipType = computed(() => this.tooltipStateSignal().type, ...(ngDevMode ? [{ debugName: "tooltipType" }] : []));
|
|
@@ -10991,6 +11039,7 @@ class TooltipContainerComponent {
|
|
|
10991
11039
|
this.tooltipPosition = computed(() => this.tooltipStateSignal().position, ...(ngDevMode ? [{ debugName: "tooltipPosition" }] : []));
|
|
10992
11040
|
this.targetRect = computed(() => this.tooltipStateSignal().targetRect, ...(ngDevMode ? [{ debugName: "targetRect" }] : []));
|
|
10993
11041
|
this.mousePosition = computed(() => this.tooltipStateSignal().mousePosition, ...(ngDevMode ? [{ debugName: "mousePosition" }] : []));
|
|
11042
|
+
this.scrollContainer = computed(() => this.tooltipStateSignal().scrollContainer, ...(ngDevMode ? [{ debugName: "scrollContainer" }] : []));
|
|
10994
11043
|
// Type-safe content accessors for each tooltip type
|
|
10995
11044
|
this.metricContent = computed(() => {
|
|
10996
11045
|
const content = this.tooltipContent();
|
|
@@ -11036,6 +11085,8 @@ class TooltipContainerComponent {
|
|
|
11036
11085
|
return true;
|
|
11037
11086
|
const position = this.tooltipPosition();
|
|
11038
11087
|
const tooltipWidth = 384;
|
|
11088
|
+
const container = this.scrollContainer();
|
|
11089
|
+
const viewportWidth = container?.clientWidth || window.innerWidth;
|
|
11039
11090
|
// For 'auto' positioning, always center horizontally
|
|
11040
11091
|
if (position === 'auto') {
|
|
11041
11092
|
return true;
|
|
@@ -11044,7 +11095,7 @@ class TooltipContainerComponent {
|
|
|
11044
11095
|
const centerPosition = rect.left + rect.width / 2;
|
|
11045
11096
|
const halfWidth = tooltipWidth / 2;
|
|
11046
11097
|
const wouldGoOffLeft = centerPosition - halfWidth < 10;
|
|
11047
|
-
const wouldGoOffRight = centerPosition + halfWidth >
|
|
11098
|
+
const wouldGoOffRight = centerPosition + halfWidth > viewportWidth - 10;
|
|
11048
11099
|
return !wouldGoOffLeft && !wouldGoOffRight;
|
|
11049
11100
|
}
|
|
11050
11101
|
return false;
|
|
@@ -11066,7 +11117,8 @@ class TooltipContainerComponent {
|
|
|
11066
11117
|
this.tooltipStateSignal.set({
|
|
11067
11118
|
...state,
|
|
11068
11119
|
mousePosition: state.mousePosition || undefined,
|
|
11069
|
-
content: state.content ?? undefined
|
|
11120
|
+
content: state.content ?? undefined,
|
|
11121
|
+
scrollContainer: state.scrollContainer || null
|
|
11070
11122
|
});
|
|
11071
11123
|
});
|
|
11072
11124
|
effect(() => {
|
|
@@ -11078,6 +11130,14 @@ class TooltipContainerComponent {
|
|
|
11078
11130
|
}
|
|
11079
11131
|
});
|
|
11080
11132
|
}
|
|
11133
|
+
onTooltipMouseEnter() {
|
|
11134
|
+
this.tooltipService.setTooltipHovered(true);
|
|
11135
|
+
}
|
|
11136
|
+
onTooltipMouseLeave() {
|
|
11137
|
+
this.tooltipService.setTooltipHovered(false);
|
|
11138
|
+
// Trigger the hide check callback from the directive
|
|
11139
|
+
this.tooltipService.triggerHideCheck();
|
|
11140
|
+
}
|
|
11081
11141
|
calculateLeft() {
|
|
11082
11142
|
const rect = this.targetRect();
|
|
11083
11143
|
if (!rect)
|
|
@@ -11085,6 +11145,8 @@ class TooltipContainerComponent {
|
|
|
11085
11145
|
const position = this.tooltipPosition();
|
|
11086
11146
|
const mousePos = this.mousePosition();
|
|
11087
11147
|
const tooltipWidth = 384;
|
|
11148
|
+
const container = this.scrollContainer();
|
|
11149
|
+
const viewportWidth = container?.clientWidth || window.innerWidth;
|
|
11088
11150
|
// Handle 'auto' positioning with mouse coordinates
|
|
11089
11151
|
if (position === 'auto' && mousePos) {
|
|
11090
11152
|
const halfWidth = tooltipWidth / 2;
|
|
@@ -11093,8 +11155,8 @@ class TooltipContainerComponent {
|
|
|
11093
11155
|
if (leftPos - halfWidth < 10) {
|
|
11094
11156
|
leftPos = halfWidth + 10;
|
|
11095
11157
|
}
|
|
11096
|
-
else if (leftPos + halfWidth >
|
|
11097
|
-
leftPos =
|
|
11158
|
+
else if (leftPos + halfWidth > viewportWidth - 10) {
|
|
11159
|
+
leftPos = viewportWidth - halfWidth - 10;
|
|
11098
11160
|
}
|
|
11099
11161
|
return leftPos;
|
|
11100
11162
|
}
|
|
@@ -11105,14 +11167,14 @@ class TooltipContainerComponent {
|
|
|
11105
11167
|
const halfWidth = tooltipWidth / 2;
|
|
11106
11168
|
// Check if centered tooltip would go off screen
|
|
11107
11169
|
const wouldGoOffLeft = centerPosition - halfWidth < 10;
|
|
11108
|
-
const wouldGoOffRight = centerPosition + halfWidth >
|
|
11170
|
+
const wouldGoOffRight = centerPosition + halfWidth > viewportWidth - 10;
|
|
11109
11171
|
if (wouldGoOffLeft) {
|
|
11110
11172
|
// Align to left edge with padding
|
|
11111
11173
|
return 10;
|
|
11112
11174
|
}
|
|
11113
11175
|
else if (wouldGoOffRight) {
|
|
11114
11176
|
// Align to right edge with padding
|
|
11115
|
-
return
|
|
11177
|
+
return viewportWidth - tooltipWidth - 10;
|
|
11116
11178
|
}
|
|
11117
11179
|
else {
|
|
11118
11180
|
// Center normally (transform will be applied)
|
|
@@ -11130,7 +11192,7 @@ class TooltipContainerComponent {
|
|
|
11130
11192
|
case 'right': {
|
|
11131
11193
|
const rightPosition = rect.right + 8;
|
|
11132
11194
|
// If tooltip would go off right edge, position it to the left instead
|
|
11133
|
-
if (rightPosition + tooltipWidth >
|
|
11195
|
+
if (rightPosition + tooltipWidth > viewportWidth - 10) {
|
|
11134
11196
|
return rect.left - tooltipWidth - 8;
|
|
11135
11197
|
}
|
|
11136
11198
|
return rightPosition;
|
|
@@ -11146,6 +11208,8 @@ class TooltipContainerComponent {
|
|
|
11146
11208
|
const position = this.tooltipPosition();
|
|
11147
11209
|
const mousePos = this.mousePosition();
|
|
11148
11210
|
const type = this.tooltipType();
|
|
11211
|
+
const container = this.scrollContainer();
|
|
11212
|
+
const viewportHeight = container?.clientHeight || window.innerHeight;
|
|
11149
11213
|
// Estimate tooltip height based on type
|
|
11150
11214
|
let estimatedHeight = 100;
|
|
11151
11215
|
if (type === 'insight') {
|
|
@@ -11159,7 +11223,7 @@ class TooltipContainerComponent {
|
|
|
11159
11223
|
const offset = 20; // Offset from mouse cursor
|
|
11160
11224
|
let topPos = mousePos.y + offset;
|
|
11161
11225
|
// If tooltip would go off bottom of screen, position above cursor
|
|
11162
|
-
if (topPos + estimatedHeight >
|
|
11226
|
+
if (topPos + estimatedHeight > viewportHeight - 10) {
|
|
11163
11227
|
topPos = mousePos.y - estimatedHeight - offset;
|
|
11164
11228
|
}
|
|
11165
11229
|
// Ensure it doesn't go off top
|
|
@@ -11180,7 +11244,7 @@ class TooltipContainerComponent {
|
|
|
11180
11244
|
case 'bottom': {
|
|
11181
11245
|
const bottomPosition = rect.bottom + 8;
|
|
11182
11246
|
// If tooltip would go off bottom of screen, position it above instead
|
|
11183
|
-
if (bottomPosition + estimatedHeight >
|
|
11247
|
+
if (bottomPosition + estimatedHeight > viewportHeight - 10) {
|
|
11184
11248
|
return rect.top - estimatedHeight - 8;
|
|
11185
11249
|
}
|
|
11186
11250
|
return bottomPosition;
|
|
@@ -11189,7 +11253,7 @@ class TooltipContainerComponent {
|
|
|
11189
11253
|
case 'right': {
|
|
11190
11254
|
const centerPosition = rect.top + rect.height / 2 - estimatedHeight / 2;
|
|
11191
11255
|
// Keep within viewport
|
|
11192
|
-
const maxTop =
|
|
11256
|
+
const maxTop = viewportHeight - estimatedHeight - 10;
|
|
11193
11257
|
return Math.max(10, Math.min(centerPosition, maxTop));
|
|
11194
11258
|
}
|
|
11195
11259
|
default:
|
|
@@ -11197,7 +11261,7 @@ class TooltipContainerComponent {
|
|
|
11197
11261
|
}
|
|
11198
11262
|
}
|
|
11199
11263
|
static { this.ɵfac = function TooltipContainerComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || TooltipContainerComponent)(); }; }
|
|
11200
|
-
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TooltipContainerComponent, selectors: [["symphiq-tooltip-container"]], decls: 1, vars: 1, consts: [[1, "fixed", "z-[100]", "pointer-events-none", 3, "left", "top", "ngClass"], [1, "fixed", "z-[100]", "pointer-events-none", 3, "ngClass"], [1, "rounded-lg", "shadow-2xl", "border", "backdrop-blur-xl", "px-4", "py-3", "max-w-sm", 3, "ngClass"], [1, "text-sm", "space-y-3", 3, "ngClass"], [1, "text-sm", "whitespace-pre-line", "leading-relaxed", 3, "ngClass"], [1, "text-sm", "whitespace-pre-line", 3, "ngClass"], [3, "content", "isLightMode"], [1, "space-y-2"], [1, "font-semibold"], [1, "whitespace-pre-line", "leading-relaxed"]], template: function TooltipContainerComponent_Template(rf, ctx) { if (rf & 1) {
|
|
11264
|
+
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: TooltipContainerComponent, selectors: [["symphiq-tooltip-container"]], decls: 1, vars: 1, consts: [[1, "fixed", "z-[100]", "pointer-events-none", 3, "left", "top", "ngClass"], [1, "fixed", "z-[100]", "pointer-events-none", 3, "ngClass"], [1, "rounded-lg", "shadow-2xl", "border", "backdrop-blur-xl", "px-4", "py-3", "max-w-sm", "pointer-events-auto", 3, "mouseenter", "mouseleave", "ngClass"], [1, "text-sm", "space-y-3", 3, "ngClass"], [1, "text-sm", "whitespace-pre-line", "leading-relaxed", 3, "ngClass"], [1, "text-sm", "whitespace-pre-line", 3, "ngClass"], [3, "content", "isLightMode"], [1, "space-y-2"], [1, "font-semibold"], [1, "whitespace-pre-line", "leading-relaxed"]], template: function TooltipContainerComponent_Template(rf, ctx) { if (rf & 1) {
|
|
11201
11265
|
i0.ɵɵconditionalCreate(0, TooltipContainerComponent_Conditional_0_Template, 15, 9, "div", 0);
|
|
11202
11266
|
} if (rf & 2) {
|
|
11203
11267
|
i0.ɵɵconditional(ctx.isVisible() ? 0 : -1);
|
|
@@ -11258,7 +11322,11 @@ class TooltipContainerComponent {
|
|
|
11258
11322
|
[ngClass]="containerClass()"
|
|
11259
11323
|
class="fixed z-[100] pointer-events-none"
|
|
11260
11324
|
@fadeInScale>
|
|
11261
|
-
<div
|
|
11325
|
+
<div
|
|
11326
|
+
[ngClass]="contentClass()"
|
|
11327
|
+
class="rounded-lg shadow-2xl border backdrop-blur-xl px-4 py-3 max-w-sm pointer-events-auto"
|
|
11328
|
+
(mouseenter)="onTooltipMouseEnter()"
|
|
11329
|
+
(mouseleave)="onTooltipMouseLeave()">
|
|
11262
11330
|
@let content = tooltipContent();
|
|
11263
11331
|
@switch (tooltipType()) {
|
|
11264
11332
|
@case ('metric') {
|
|
@@ -11357,7 +11425,7 @@ class TooltipContainerComponent {
|
|
|
11357
11425
|
`
|
|
11358
11426
|
}]
|
|
11359
11427
|
}], () => [], null); })();
|
|
11360
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TooltipContainerComponent, { className: "TooltipContainerComponent", filePath: "lib/components/funnel-analysis-dashboard/tooltip/tooltip-container.component.ts", lineNumber:
|
|
11428
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(TooltipContainerComponent, { className: "TooltipContainerComponent", filePath: "lib/components/funnel-analysis-dashboard/tooltip/tooltip-container.component.ts", lineNumber: 173 }); })();
|
|
11361
11429
|
|
|
11362
11430
|
function MobileFABComponent_Conditional_1_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
11363
11431
|
i0.ɵɵnamespaceSVG();
|
|
@@ -19172,7 +19240,7 @@ class SearchBarComponent {
|
|
|
19172
19240
|
i0.ɵɵconditionalCreate(0, SearchBarComponent_Conditional_0_Template, 17, 10, "div", 1);
|
|
19173
19241
|
} if (rf & 2) {
|
|
19174
19242
|
i0.ɵɵconditional(ctx.searchService.isSearchOpen() ? 0 : -1);
|
|
19175
|
-
} }, dependencies: [CommonModule, i1.NgClass, FormsModule,
|
|
19243
|
+
} }, dependencies: [CommonModule, i1.NgClass, FormsModule, i6.DefaultValueAccessor, i6.NgControlStatus, i6.NgModel], styles: ["[_nghost-%COMP%]{display:contents}"], changeDetection: 0 }); }
|
|
19176
19244
|
}
|
|
19177
19245
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SearchBarComponent, [{
|
|
19178
19246
|
type: Component,
|
|
@@ -21007,10 +21075,11 @@ function SymphiqFunnelAnalysisDashboardComponent_Conditional_80_Template(rf, ctx
|
|
|
21007
21075
|
i0.ɵɵproperty("metrics", ctx_r2.competitiveMetrics())("allCharts", ctx_r2.allCharts())("isLightMode", ctx_r2.isLightMode())("isCompactMode", ctx_r2.viewModeService.isCompact());
|
|
21008
21076
|
} }
|
|
21009
21077
|
class SymphiqFunnelAnalysisDashboardComponent {
|
|
21010
|
-
constructor(funnelOrderService, viewModeService, searchService) {
|
|
21078
|
+
constructor(funnelOrderService, viewModeService, searchService, tooltipService) {
|
|
21011
21079
|
this.funnelOrderService = funnelOrderService;
|
|
21012
21080
|
this.viewModeService = viewModeService;
|
|
21013
21081
|
this.searchService = searchService;
|
|
21082
|
+
this.tooltipService = tooltipService;
|
|
21014
21083
|
// Input signals (Angular 20 signal-based inputs)
|
|
21015
21084
|
this.requestedByUser = input(...(ngDevMode ? [undefined, { debugName: "requestedByUser" }] : []));
|
|
21016
21085
|
this.viewMode = input(ViewModeEnum.LIGHT, ...(ngDevMode ? [{ debugName: "viewMode" }] : []));
|
|
@@ -21040,6 +21109,7 @@ class SymphiqFunnelAnalysisDashboardComponent {
|
|
|
21040
21109
|
this.isProgrammaticScroll = false;
|
|
21041
21110
|
this.lastStateChangeTime = 0;
|
|
21042
21111
|
this.STATE_CHANGE_COOLDOWN = 500; // milliseconds
|
|
21112
|
+
this.embeddedScrollContainer = null;
|
|
21043
21113
|
// Mobile navigation sections
|
|
21044
21114
|
this.navSections = [
|
|
21045
21115
|
{ id: 'overview', label: 'Overview', icon: 'overview' },
|
|
@@ -21360,169 +21430,80 @@ class SymphiqFunnelAnalysisDashboardComponent {
|
|
|
21360
21430
|
// Set up container scroll listener when in embedded mode
|
|
21361
21431
|
if (this.embedded()) {
|
|
21362
21432
|
let container = null;
|
|
21363
|
-
console.log('[Scroll Debug v6] Embedded mode detected, setting up scroll listener');
|
|
21364
|
-
console.log('[Scroll Debug v6] scrollContainerId:', this.scrollContainerId());
|
|
21365
21433
|
// If a scroll container ID is provided, use that element
|
|
21366
21434
|
if (this.scrollContainerId()) {
|
|
21367
|
-
const
|
|
21368
|
-
|
|
21369
|
-
|
|
21370
|
-
|
|
21371
|
-
|
|
21372
|
-
console.log('[Scroll Debug] Found external scroll container:', element);
|
|
21373
|
-
console.log('[Scroll Debug] Container tag name:', element.tagName);
|
|
21435
|
+
const setupScrollContainer = () => {
|
|
21436
|
+
const element = document.getElementById(this.scrollContainerId());
|
|
21437
|
+
if (!element) {
|
|
21438
|
+
return false;
|
|
21439
|
+
}
|
|
21374
21440
|
// Check if this is an Ionic ion-content element
|
|
21375
21441
|
if (element.tagName.toLowerCase() === 'ion-content') {
|
|
21376
|
-
console.log('[Scroll Debug] Detected Ionic ion-content, attempting to get scrollable element');
|
|
21377
|
-
// Try to get the scroll element from Ionic's ion-content
|
|
21378
|
-
// Ionic stores the scrollable element in the component itself
|
|
21379
21442
|
const ionContent = element;
|
|
21380
|
-
//
|
|
21443
|
+
// Get the scrollable element from Ionic
|
|
21381
21444
|
if (typeof ionContent.getScrollElement === 'function') {
|
|
21382
|
-
console.log('[Scroll Debug] Using getScrollElement() method');
|
|
21383
21445
|
ionContent.getScrollElement().then((scrollElement) => {
|
|
21384
|
-
|
|
21385
|
-
|
|
21386
|
-
|
|
21387
|
-
|
|
21388
|
-
scrollTop: scrollElement.scrollTop,
|
|
21389
|
-
hasOverflow: scrollElement.scrollHeight > scrollElement.clientHeight
|
|
21390
|
-
};
|
|
21391
|
-
console.log('[Scroll Debug] Ionic scroll element dimensions:', dimensions);
|
|
21392
|
-
if (!dimensions.hasOverflow) {
|
|
21393
|
-
console.warn('[Scroll Debug] ⚠️ WARNING: Scroll element has no overflow! Content may still be loading.');
|
|
21394
|
-
console.warn('[Scroll Debug] The dashboard content needs to be taller than', dimensions.clientHeight, 'px to enable scrolling');
|
|
21395
|
-
// Diagnostic: Check the dashboard component's actual rendered height
|
|
21396
|
-
setTimeout(() => {
|
|
21397
|
-
const dashboardEl = this.dashboardContainer?.nativeElement;
|
|
21398
|
-
if (dashboardEl) {
|
|
21399
|
-
const styles = window.getComputedStyle(dashboardEl);
|
|
21400
|
-
console.log('[Scroll Debug] Dashboard container computed styles:', {
|
|
21401
|
-
height: styles.height,
|
|
21402
|
-
minHeight: styles.minHeight,
|
|
21403
|
-
maxHeight: styles.maxHeight,
|
|
21404
|
-
display: styles.display,
|
|
21405
|
-
position: styles.position,
|
|
21406
|
-
overflow: styles.overflow,
|
|
21407
|
-
scrollHeight: dashboardEl.scrollHeight,
|
|
21408
|
-
clientHeight: dashboardEl.clientHeight,
|
|
21409
|
-
offsetHeight: dashboardEl.offsetHeight
|
|
21410
|
-
});
|
|
21411
|
-
// Check children
|
|
21412
|
-
const children = Array.from(dashboardEl.children);
|
|
21413
|
-
console.log('[Scroll Debug] Dashboard has', children.length, 'direct children');
|
|
21414
|
-
children.forEach((child, idx) => {
|
|
21415
|
-
const childStyles = window.getComputedStyle(child);
|
|
21416
|
-
console.log(`[Scroll Debug] Child ${idx}:`, {
|
|
21417
|
-
tagName: child.tagName,
|
|
21418
|
-
height: childStyles.height,
|
|
21419
|
-
display: childStyles.display,
|
|
21420
|
-
clientHeight: child.clientHeight,
|
|
21421
|
-
scrollHeight: child.scrollHeight
|
|
21422
|
-
});
|
|
21423
|
-
});
|
|
21424
|
-
// Check if content is actually rendering
|
|
21425
|
-
const hasVisibleContent = dashboardEl.scrollHeight > 100;
|
|
21426
|
-
if (!hasVisibleContent) {
|
|
21427
|
-
console.error('[Scroll Debug] ⚠️ CRITICAL: Dashboard has minimal content! Check if funnelAnalysis data is loaded.');
|
|
21428
|
-
}
|
|
21429
|
-
}
|
|
21430
|
-
}, 100);
|
|
21431
|
-
// Set up a MutationObserver to detect when content becomes scrollable
|
|
21432
|
-
const observer = new MutationObserver(() => {
|
|
21433
|
-
const newScrollHeight = scrollElement.scrollHeight;
|
|
21434
|
-
const newClientHeight = scrollElement.clientHeight;
|
|
21435
|
-
if (newScrollHeight > newClientHeight) {
|
|
21436
|
-
console.log('[Scroll Debug] ✓ Content is now scrollable!', {
|
|
21437
|
-
clientHeight: newClientHeight,
|
|
21438
|
-
scrollHeight: newScrollHeight,
|
|
21439
|
-
hasOverflow: true
|
|
21440
|
-
});
|
|
21441
|
-
observer.disconnect();
|
|
21442
|
-
}
|
|
21443
|
-
});
|
|
21444
|
-
observer.observe(scrollElement, {
|
|
21445
|
-
childList: true,
|
|
21446
|
-
subtree: true,
|
|
21447
|
-
attributes: true
|
|
21448
|
-
});
|
|
21449
|
-
console.log('[Scroll Debug] Monitoring for content changes...');
|
|
21450
|
-
}
|
|
21451
|
-
// Attach to BOTH the inner scroll element AND the ion-content itself
|
|
21446
|
+
// Store reference for use in scrollToSection and tooltips
|
|
21447
|
+
this.embeddedScrollContainer = scrollElement;
|
|
21448
|
+
this.tooltipService.setScrollContainer(scrollElement);
|
|
21449
|
+
// Attach scroll listeners
|
|
21452
21450
|
scrollElement.addEventListener('scroll', () => this.onContainerScroll(scrollElement), { passive: true });
|
|
21453
|
-
|
|
21454
|
-
//
|
|
21455
|
-
ionContent.addEventListener('ionScroll', (event) => {
|
|
21456
|
-
console.log('[Scroll Debug] ionScroll event fired:', event.detail?.scrollTop);
|
|
21457
|
-
this.onContainerScroll(scrollElement);
|
|
21458
|
-
}, { passive: true });
|
|
21459
|
-
console.log('[Scroll Debug] Attached ionScroll listener to ion-content');
|
|
21460
|
-
// FALLBACK: Poll scroll position directly from scrollElement
|
|
21461
|
-
// This ensures we catch scroll events even if neither 'scroll' nor 'ionScroll' fire
|
|
21451
|
+
ionContent.addEventListener('ionScroll', () => this.onContainerScroll(scrollElement), { passive: true });
|
|
21452
|
+
// Polling fallback for reliable scroll detection
|
|
21462
21453
|
let lastScrollTop = 0;
|
|
21463
|
-
let pollCount = 0;
|
|
21464
21454
|
const pollScroll = () => {
|
|
21465
|
-
pollCount++;
|
|
21466
21455
|
const currentScrollTop = scrollElement.scrollTop;
|
|
21467
21456
|
if (currentScrollTop !== lastScrollTop) {
|
|
21468
|
-
console.log('[Scroll Debug v6] Poll #', pollCount, '- Scroll detected:', lastScrollTop, '->', currentScrollTop);
|
|
21469
21457
|
lastScrollTop = currentScrollTop;
|
|
21470
21458
|
this.onContainerScroll(scrollElement);
|
|
21471
21459
|
}
|
|
21472
21460
|
requestAnimationFrame(pollScroll);
|
|
21473
21461
|
};
|
|
21474
21462
|
requestAnimationFrame(pollScroll);
|
|
21475
|
-
console.log('[Scroll Debug v6] Started polling scrollElement.scrollTop directly');
|
|
21476
|
-
// Test if scroll event fires by manually triggering a test
|
|
21477
|
-
console.log('[Scroll Debug] Testing scroll event by programmatically scrolling to 1px...');
|
|
21478
|
-
scrollElement.scrollTop = 1;
|
|
21479
|
-
setTimeout(() => {
|
|
21480
|
-
if (scrollElement.scrollTop === 1) {
|
|
21481
|
-
console.log('[Scroll Debug] ✓ Scroll position changed successfully');
|
|
21482
|
-
scrollElement.scrollTop = 0; // Reset
|
|
21483
|
-
}
|
|
21484
|
-
else {
|
|
21485
|
-
console.warn('[Scroll Debug] ⚠️ Could not change scroll position - element may not be scrollable');
|
|
21486
|
-
}
|
|
21487
|
-
}, 50);
|
|
21488
21463
|
}).catch((error) => {
|
|
21489
|
-
console.error('
|
|
21464
|
+
console.error('Error getting Ionic scroll element:', error);
|
|
21490
21465
|
});
|
|
21466
|
+
return true;
|
|
21491
21467
|
}
|
|
21492
21468
|
else {
|
|
21493
|
-
|
|
21494
|
-
|
|
21495
|
-
|
|
21469
|
+
// Fallback for older Ionic versions
|
|
21470
|
+
this.embeddedScrollContainer = element;
|
|
21471
|
+
this.tooltipService.setScrollContainer(element);
|
|
21472
|
+
element.addEventListener('scroll', () => this.onContainerScroll(element), { passive: true });
|
|
21473
|
+
return true;
|
|
21496
21474
|
}
|
|
21497
21475
|
}
|
|
21498
21476
|
else {
|
|
21499
21477
|
// Regular HTML element
|
|
21500
|
-
|
|
21501
|
-
|
|
21502
|
-
|
|
21503
|
-
|
|
21504
|
-
scrollTop: container.scrollTop,
|
|
21505
|
-
hasOverflow: container.scrollHeight > container.clientHeight
|
|
21506
|
-
});
|
|
21478
|
+
this.embeddedScrollContainer = element;
|
|
21479
|
+
this.tooltipService.setScrollContainer(element);
|
|
21480
|
+
element.addEventListener('scroll', () => this.onContainerScroll(element), { passive: true });
|
|
21481
|
+
return true;
|
|
21507
21482
|
}
|
|
21483
|
+
};
|
|
21484
|
+
// Try to set up immediately
|
|
21485
|
+
if (!setupScrollContainer()) {
|
|
21486
|
+
// If not found, retry with delays (element might not be in DOM yet)
|
|
21487
|
+
let retries = 0;
|
|
21488
|
+
const maxRetries = 10;
|
|
21489
|
+
const retryInterval = setInterval(() => {
|
|
21490
|
+
retries++;
|
|
21491
|
+
if (setupScrollContainer() || retries >= maxRetries) {
|
|
21492
|
+
clearInterval(retryInterval);
|
|
21493
|
+
if (retries >= maxRetries) {
|
|
21494
|
+
console.warn(`Scroll container with id "${this.scrollContainerId()}" not found after ${maxRetries} retries.`);
|
|
21495
|
+
}
|
|
21496
|
+
}
|
|
21497
|
+
}, 100);
|
|
21508
21498
|
}
|
|
21509
21499
|
}
|
|
21510
21500
|
else if (this.dashboardContainer) {
|
|
21511
21501
|
// Fall back to internal dashboard container
|
|
21512
21502
|
container = this.dashboardContainer.nativeElement;
|
|
21513
|
-
|
|
21514
|
-
|
|
21515
|
-
// Only attach listener for non-Ionic elements (Ionic handled above)
|
|
21516
|
-
if (container) {
|
|
21517
|
-
console.log('[Scroll Debug] Attaching scroll listener to container');
|
|
21503
|
+
this.embeddedScrollContainer = container;
|
|
21504
|
+
this.tooltipService.setScrollContainer(container);
|
|
21518
21505
|
container.addEventListener('scroll', () => this.onContainerScroll(container), { passive: true });
|
|
21519
21506
|
}
|
|
21520
|
-
else if (!this.scrollContainerId() || document.getElementById(this.scrollContainerId())?.tagName.toLowerCase() !== 'ion-content') {
|
|
21521
|
-
console.warn('[Scroll Debug] No scroll container found!');
|
|
21522
|
-
}
|
|
21523
|
-
}
|
|
21524
|
-
else {
|
|
21525
|
-
console.log('[Scroll Debug] Not in embedded mode, using window scroll');
|
|
21526
21507
|
}
|
|
21527
21508
|
}
|
|
21528
21509
|
handleSearchResult(result) {
|
|
@@ -21732,66 +21713,42 @@ class SymphiqFunnelAnalysisDashboardComponent {
|
|
|
21732
21713
|
}
|
|
21733
21714
|
onContainerScroll(container) {
|
|
21734
21715
|
if (!this.embedded()) {
|
|
21735
|
-
console.log('[Scroll Debug] onContainerScroll called but not in embedded mode, returning');
|
|
21736
21716
|
return;
|
|
21737
21717
|
}
|
|
21738
21718
|
const scrollPosition = container.scrollTop;
|
|
21739
|
-
// Update scroll progress
|
|
21719
|
+
// Update scroll progress for smooth bar animation
|
|
21740
21720
|
const containerHeight = container.clientHeight;
|
|
21741
21721
|
const scrollHeight = container.scrollHeight;
|
|
21742
21722
|
const maxScroll = scrollHeight - containerHeight;
|
|
21743
21723
|
const progress = maxScroll > 0 ? (scrollPosition / maxScroll) * 100 : 0;
|
|
21744
|
-
console.log('[Scroll Debug] Container scroll event:', {
|
|
21745
|
-
scrollPosition,
|
|
21746
|
-
containerHeight,
|
|
21747
|
-
scrollHeight,
|
|
21748
|
-
maxScroll,
|
|
21749
|
-
progress: progress.toFixed(2) + '%',
|
|
21750
|
-
currentScrollProgress: this.scrollProgress(),
|
|
21751
|
-
isScrolled: this.isScrolled()
|
|
21752
|
-
});
|
|
21753
21724
|
this.scrollProgress.set(Math.min(100, Math.max(0, progress)));
|
|
21754
|
-
// Skip header state updates during programmatic scrolling
|
|
21725
|
+
// Skip header state updates during programmatic scrolling or cooldown
|
|
21755
21726
|
if (this.isProgrammaticScroll) {
|
|
21756
|
-
console.log('[Scroll Debug] Skipping header update - programmatic scroll');
|
|
21757
21727
|
return;
|
|
21758
21728
|
}
|
|
21759
|
-
// Check if we're in cooldown period after a recent state change
|
|
21760
21729
|
const now = Date.now();
|
|
21761
21730
|
const timeSinceLastChange = now - this.lastStateChangeTime;
|
|
21762
21731
|
if (timeSinceLastChange < this.STATE_CHANGE_COOLDOWN) {
|
|
21763
|
-
console.log('[Scroll Debug] Skipping header update - in cooldown period', timeSinceLastChange + 'ms');
|
|
21764
21732
|
return;
|
|
21765
21733
|
}
|
|
21766
|
-
// Clear any pending timeout
|
|
21767
21734
|
if (this.scrollTimeout) {
|
|
21768
21735
|
clearTimeout(this.scrollTimeout);
|
|
21769
21736
|
}
|
|
21770
|
-
// Use hysteresis
|
|
21771
|
-
const COLLAPSE_THRESHOLD =
|
|
21772
|
-
const EXPAND_THRESHOLD =
|
|
21737
|
+
// Use hysteresis to prevent bounce
|
|
21738
|
+
const COLLAPSE_THRESHOLD = 50;
|
|
21739
|
+
const EXPAND_THRESHOLD = 30;
|
|
21773
21740
|
const currentState = this.isScrolled();
|
|
21774
|
-
// Determine new state based on current position and hysteresis logic
|
|
21775
21741
|
let newState = currentState;
|
|
21776
|
-
// If currently expanded and we scroll past collapse threshold, collapse
|
|
21777
21742
|
if (!currentState && scrollPosition > COLLAPSE_THRESHOLD) {
|
|
21778
21743
|
newState = true;
|
|
21779
|
-
console.log('[Scroll Debug] Triggering COLLAPSE - scrollPosition:', scrollPosition, '> threshold:', COLLAPSE_THRESHOLD);
|
|
21780
21744
|
}
|
|
21781
|
-
// If currently collapsed and we scroll back above expand threshold, expand
|
|
21782
21745
|
else if (currentState && scrollPosition < EXPAND_THRESHOLD) {
|
|
21783
21746
|
newState = false;
|
|
21784
|
-
console.log('[Scroll Debug] Triggering EXPAND - scrollPosition:', scrollPosition, '< threshold:', EXPAND_THRESHOLD);
|
|
21785
21747
|
}
|
|
21786
|
-
// Only update state if it actually changed
|
|
21787
21748
|
if (newState !== currentState) {
|
|
21788
|
-
console.log('[Scroll Debug] State change detected:', currentState, '->', newState);
|
|
21789
21749
|
this.isScrolled.set(newState);
|
|
21790
21750
|
this.lastStateChangeTime = Date.now();
|
|
21791
21751
|
}
|
|
21792
|
-
else {
|
|
21793
|
-
console.log('[Scroll Debug] No state change needed. Current state:', currentState, 'Position:', scrollPosition);
|
|
21794
|
-
}
|
|
21795
21752
|
this.lastScrollPosition = scrollPosition;
|
|
21796
21753
|
}
|
|
21797
21754
|
onScroll() {
|
|
@@ -21820,11 +21777,11 @@ class SymphiqFunnelAnalysisDashboardComponent {
|
|
|
21820
21777
|
clearTimeout(this.scrollTimeout);
|
|
21821
21778
|
}
|
|
21822
21779
|
// Use hysteresis (two different thresholds) to prevent bounce loop
|
|
21823
|
-
// When scrolling down, collapse at
|
|
21824
|
-
// When scrolling up, expand at
|
|
21825
|
-
// This
|
|
21826
|
-
const COLLAPSE_THRESHOLD =
|
|
21827
|
-
const EXPAND_THRESHOLD =
|
|
21780
|
+
// When scrolling down, collapse at 50px
|
|
21781
|
+
// When scrolling up, expand at 30px
|
|
21782
|
+
// This 20px gap prevents rapid toggling when hovering near a single threshold
|
|
21783
|
+
const COLLAPSE_THRESHOLD = 50;
|
|
21784
|
+
const EXPAND_THRESHOLD = 30;
|
|
21828
21785
|
const currentState = this.isScrolled();
|
|
21829
21786
|
// Determine new state based on current position and hysteresis logic
|
|
21830
21787
|
let newState = currentState;
|
|
@@ -21859,48 +21816,60 @@ class SymphiqFunnelAnalysisDashboardComponent {
|
|
|
21859
21816
|
this.lastScrollPosition = scrollPosition;
|
|
21860
21817
|
}
|
|
21861
21818
|
scrollToTop() {
|
|
21862
|
-
// Set flag to prevent header state changes during smooth scroll
|
|
21863
21819
|
this.isProgrammaticScroll = true;
|
|
21864
|
-
|
|
21865
|
-
|
|
21866
|
-
|
|
21867
|
-
|
|
21868
|
-
|
|
21820
|
+
if (this.embedded() && this.embeddedScrollContainer) {
|
|
21821
|
+
this.embeddedScrollContainer.scrollTo({
|
|
21822
|
+
top: 0,
|
|
21823
|
+
behavior: 'smooth'
|
|
21824
|
+
});
|
|
21825
|
+
}
|
|
21826
|
+
else {
|
|
21827
|
+
window.scrollTo({
|
|
21828
|
+
top: 0,
|
|
21829
|
+
behavior: 'smooth'
|
|
21830
|
+
});
|
|
21831
|
+
}
|
|
21869
21832
|
setTimeout(() => {
|
|
21870
21833
|
this.isProgrammaticScroll = false;
|
|
21871
|
-
// At top of page, header should be expanded
|
|
21872
21834
|
this.isScrolled.set(false);
|
|
21873
21835
|
}, 800);
|
|
21874
21836
|
}
|
|
21875
21837
|
scrollToSection(sectionId) {
|
|
21876
21838
|
const element = document.getElementById(sectionId);
|
|
21877
|
-
if (element)
|
|
21878
|
-
|
|
21879
|
-
|
|
21880
|
-
|
|
21839
|
+
if (!element)
|
|
21840
|
+
return;
|
|
21841
|
+
const offset = sectionId === 'overall-section' ? 50 : 100;
|
|
21842
|
+
this.isProgrammaticScroll = true;
|
|
21843
|
+
if (this.embedded() && this.embeddedScrollContainer) {
|
|
21844
|
+
// For embedded mode: calculate relative scroll position
|
|
21845
|
+
const elementTop = element.offsetTop;
|
|
21846
|
+
const scrollTop = elementTop - offset;
|
|
21847
|
+
this.embeddedScrollContainer.scrollTo({
|
|
21848
|
+
top: scrollTop,
|
|
21849
|
+
behavior: 'smooth'
|
|
21850
|
+
});
|
|
21851
|
+
}
|
|
21852
|
+
else {
|
|
21853
|
+
// For window mode: use getBoundingClientRect
|
|
21881
21854
|
const elementPosition = element.getBoundingClientRect().top + window.pageYOffset;
|
|
21882
21855
|
const offsetPosition = elementPosition - offset;
|
|
21883
|
-
// Set flag to prevent header state changes during smooth scroll
|
|
21884
|
-
this.isProgrammaticScroll = true;
|
|
21885
21856
|
window.scrollTo({
|
|
21886
21857
|
top: offsetPosition,
|
|
21887
21858
|
behavior: 'smooth'
|
|
21888
21859
|
});
|
|
21889
|
-
// Clear flag after smooth scroll completes (approximate duration)
|
|
21890
|
-
setTimeout(() => {
|
|
21891
|
-
this.isProgrammaticScroll = false;
|
|
21892
|
-
// Manually set the correct header state after scroll completes
|
|
21893
|
-
// Use hysteresis thresholds: collapse at 150px, expand below 100px
|
|
21894
|
-
const finalPosition = window.scrollY;
|
|
21895
|
-
if (finalPosition > 150) {
|
|
21896
|
-
this.isScrolled.set(true);
|
|
21897
|
-
}
|
|
21898
|
-
else if (finalPosition < 100) {
|
|
21899
|
-
this.isScrolled.set(false);
|
|
21900
|
-
}
|
|
21901
|
-
// If between 100-150, leave current state unchanged
|
|
21902
|
-
}, 800);
|
|
21903
21860
|
}
|
|
21861
|
+
setTimeout(() => {
|
|
21862
|
+
this.isProgrammaticScroll = false;
|
|
21863
|
+
const finalPosition = this.embedded() && this.embeddedScrollContainer
|
|
21864
|
+
? this.embeddedScrollContainer.scrollTop
|
|
21865
|
+
: window.scrollY;
|
|
21866
|
+
if (finalPosition > 50) {
|
|
21867
|
+
this.isScrolled.set(true);
|
|
21868
|
+
}
|
|
21869
|
+
else if (finalPosition < 30) {
|
|
21870
|
+
this.isScrolled.set(false);
|
|
21871
|
+
}
|
|
21872
|
+
}, 800);
|
|
21904
21873
|
}
|
|
21905
21874
|
handleMobileNavigation(sectionId) {
|
|
21906
21875
|
this.activeNavSection.set(sectionId);
|
|
@@ -21943,7 +21912,7 @@ class SymphiqFunnelAnalysisDashboardComponent {
|
|
|
21943
21912
|
}
|
|
21944
21913
|
return value.toLocaleString('en-US', { maximumFractionDigits: 0 });
|
|
21945
21914
|
}
|
|
21946
|
-
static { this.ɵfac = function SymphiqFunnelAnalysisDashboardComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SymphiqFunnelAnalysisDashboardComponent)(i0.ɵɵdirectiveInject(FunnelOrderService), i0.ɵɵdirectiveInject(ViewModeService), i0.ɵɵdirectiveInject(SearchService)); }; }
|
|
21915
|
+
static { this.ɵfac = function SymphiqFunnelAnalysisDashboardComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SymphiqFunnelAnalysisDashboardComponent)(i0.ɵɵdirectiveInject(FunnelOrderService), i0.ɵɵdirectiveInject(ViewModeService), i0.ɵɵdirectiveInject(SearchService), i0.ɵɵdirectiveInject(TooltipService)); }; }
|
|
21947
21916
|
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SymphiqFunnelAnalysisDashboardComponent, selectors: [["symphiq-funnel-analysis-dashboard"]], viewQuery: function SymphiqFunnelAnalysisDashboardComponent_Query(rf, ctx) { if (rf & 1) {
|
|
21948
21917
|
i0.ɵɵviewQuery(ModalComponent, 5);
|
|
21949
21918
|
i0.ɵɵviewQuery(_c0$4, 5);
|
|
@@ -22157,7 +22126,7 @@ class SymphiqFunnelAnalysisDashboardComponent {
|
|
|
22157
22126
|
i0.ɵɵproperty("isLightMode", ctx.isLightMode())("isCompactMode", ctx.viewModeService.isCompact())("isExpanded", ctx.fabExpanded());
|
|
22158
22127
|
i0.ɵɵadvance();
|
|
22159
22128
|
i0.ɵɵproperty("isLightMode", ctx.isLightMode())("sections", ctx.navSections)("activeSection", ctx.activeNavSection());
|
|
22160
|
-
} }, dependencies: [CommonModule, i1.NgClass, FormsModule,
|
|
22129
|
+
} }, dependencies: [CommonModule, i1.NgClass, FormsModule, i6.NgSelectOption, i6.ɵNgSelectMultipleOption, i6.SelectControlValueAccessor, i6.NgControlStatus, i6.NgModel, OverallAssessmentComponent,
|
|
22161
22130
|
InsightCardComponent,
|
|
22162
22131
|
MetricCardComponent,
|
|
22163
22132
|
BreakdownSectionComponent,
|
|
@@ -22944,7 +22913,7 @@ class SymphiqFunnelAnalysisDashboardComponent {
|
|
|
22944
22913
|
|
|
22945
22914
|
</div>
|
|
22946
22915
|
`, styles: [":host{display:block;min-height:100%}.bg-gradient-radial{background:radial-gradient(circle,var(--tw-gradient-stops))}.bento-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:1.5rem;grid-auto-flow:dense}@media (min-width: 768px){.bento-grid{grid-template-columns:repeat(6,1fr)}}.bento-small{grid-column:span 2;grid-row:span 1}.bento-medium{grid-column:span 3;grid-row:span 1}.bento-large{grid-column:span 4;grid-row:span 1}.bento-featured{grid-column:span 6;grid-row:span 1}@media (max-width: 767px){.bento-small,.bento-medium,.bento-large,.bento-featured{grid-column:span 1}}.masonry-grid{column-count:1;column-gap:1.5rem}@media (min-width: 768px){.masonry-grid{column-count:2}}@media (min-width: 1280px){.masonry-grid{column-count:3}}.masonry-grid>div{break-inside:avoid;margin-bottom:1.5rem}.masonry-featured{column-span:all}.scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}.scrollbar-hide::-webkit-scrollbar{display:none}@media (max-width: 640px){.animate-fade-in-up{animation-duration:.4s}}\n"] }]
|
|
22947
|
-
}], () => [{ type: FunnelOrderService }, { type: ViewModeService }, { type: SearchService }], { modalComponent: [{
|
|
22916
|
+
}], () => [{ type: FunnelOrderService }, { type: ViewModeService }, { type: SearchService }, { type: TooltipService }], { modalComponent: [{
|
|
22948
22917
|
type: ViewChild,
|
|
22949
22918
|
args: [ModalComponent]
|
|
22950
22919
|
}], dashboardContainer: [{
|
|
@@ -22954,7 +22923,7 @@ class SymphiqFunnelAnalysisDashboardComponent {
|
|
|
22954
22923
|
type: HostListener,
|
|
22955
22924
|
args: ['window:scroll', ['$event']]
|
|
22956
22925
|
}] }); })();
|
|
22957
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SymphiqFunnelAnalysisDashboardComponent, { className: "SymphiqFunnelAnalysisDashboardComponent", filePath: "lib/components/funnel-analysis-dashboard/symphiq-funnel-analysis-dashboard.component.ts", lineNumber:
|
|
22926
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SymphiqFunnelAnalysisDashboardComponent, { className: "SymphiqFunnelAnalysisDashboardComponent", filePath: "lib/components/funnel-analysis-dashboard/symphiq-funnel-analysis-dashboard.component.ts", lineNumber: 916 }); })();
|
|
22958
22927
|
|
|
22959
22928
|
/**
|
|
22960
22929
|
* Shared Theme Color Utilities
|