@eric-emg/symphiq-components 1.2.17 → 1.2.20
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/README.md +20 -0
- package/fesm2022/symphiq-components.mjs +77 -6
- package/fesm2022/symphiq-components.mjs.map +1 -1
- package/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/styles.css +4 -0
package/README.md
CHANGED
|
@@ -82,6 +82,26 @@ Embedded mode:
|
|
|
82
82
|
|
|
83
83
|
**Note:** When `embedded` is `true` and you have a custom scrolling container outside the dashboard component, you should provide the `scrollContainerId` input with the ID of that container element. If `scrollContainerId` is not provided, the component will fall back to using its internal container for scroll tracking.
|
|
84
84
|
|
|
85
|
+
#### Ionic Framework Support
|
|
86
|
+
|
|
87
|
+
The component automatically detects and supports **Ionic `<ion-content>` elements**:
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
@Component({
|
|
91
|
+
template: `
|
|
92
|
+
<ion-content id="mainContent">
|
|
93
|
+
<symphiq-funnel-analysis-dashboard
|
|
94
|
+
[funnelAnalysis]="data"
|
|
95
|
+
[embedded]="true"
|
|
96
|
+
[scrollContainerId]="'mainContent'">
|
|
97
|
+
</symphiq-funnel-analysis-dashboard>
|
|
98
|
+
</ion-content>
|
|
99
|
+
`
|
|
100
|
+
})
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
When an `ion-content` element is detected, the component will automatically call `getScrollElement()` to attach the scroll listener to the correct internal scrollable element within the shadow DOM.
|
|
104
|
+
|
|
85
105
|
### Preview Component
|
|
86
106
|
|
|
87
107
|
The library includes a compact preview component for displaying funnel analysis summaries:
|
|
@@ -21360,21 +21360,74 @@ class SymphiqFunnelAnalysisDashboardComponent {
|
|
|
21360
21360
|
// Set up container scroll listener when in embedded mode
|
|
21361
21361
|
if (this.embedded()) {
|
|
21362
21362
|
let container = null;
|
|
21363
|
+
console.log('[Scroll Debug] Embedded mode detected, setting up scroll listener');
|
|
21364
|
+
console.log('[Scroll Debug] scrollContainerId:', this.scrollContainerId());
|
|
21363
21365
|
// If a scroll container ID is provided, use that element
|
|
21364
21366
|
if (this.scrollContainerId()) {
|
|
21365
|
-
|
|
21366
|
-
if (!
|
|
21367
|
-
console.warn(`Scroll container with id "${this.scrollContainerId()}" not found. Scroll tracking will not work.`);
|
|
21367
|
+
const element = document.getElementById(this.scrollContainerId());
|
|
21368
|
+
if (!element) {
|
|
21369
|
+
console.warn(`[Scroll Debug] Scroll container with id "${this.scrollContainerId()}" not found. Scroll tracking will not work.`);
|
|
21370
|
+
}
|
|
21371
|
+
else {
|
|
21372
|
+
console.log('[Scroll Debug] Found external scroll container:', element);
|
|
21373
|
+
console.log('[Scroll Debug] Container tag name:', element.tagName);
|
|
21374
|
+
// Check if this is an Ionic ion-content element
|
|
21375
|
+
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
|
+
const ionContent = element;
|
|
21380
|
+
// Method 1: Try getScrollElement() method (Ionic 4+)
|
|
21381
|
+
if (typeof ionContent.getScrollElement === 'function') {
|
|
21382
|
+
console.log('[Scroll Debug] Using getScrollElement() method');
|
|
21383
|
+
ionContent.getScrollElement().then((scrollElement) => {
|
|
21384
|
+
console.log('[Scroll Debug] Got Ionic scroll element:', scrollElement);
|
|
21385
|
+
console.log('[Scroll Debug] Ionic scroll element dimensions:', {
|
|
21386
|
+
clientHeight: scrollElement.clientHeight,
|
|
21387
|
+
scrollHeight: scrollElement.scrollHeight,
|
|
21388
|
+
scrollTop: scrollElement.scrollTop,
|
|
21389
|
+
hasOverflow: scrollElement.scrollHeight > scrollElement.clientHeight
|
|
21390
|
+
});
|
|
21391
|
+
scrollElement.addEventListener('scroll', () => this.onContainerScroll(scrollElement), { passive: true });
|
|
21392
|
+
console.log('[Scroll Debug] Attached scroll listener to Ionic scroll element');
|
|
21393
|
+
}).catch((error) => {
|
|
21394
|
+
console.error('[Scroll Debug] Error getting Ionic scroll element:', error);
|
|
21395
|
+
});
|
|
21396
|
+
}
|
|
21397
|
+
else {
|
|
21398
|
+
console.warn('[Scroll Debug] ion-content does not have getScrollElement() method');
|
|
21399
|
+
// Fallback: attach to ion-content itself (may not work)
|
|
21400
|
+
container = element;
|
|
21401
|
+
}
|
|
21402
|
+
}
|
|
21403
|
+
else {
|
|
21404
|
+
// Regular HTML element
|
|
21405
|
+
container = element;
|
|
21406
|
+
console.log('[Scroll Debug] Container dimensions:', {
|
|
21407
|
+
clientHeight: container.clientHeight,
|
|
21408
|
+
scrollHeight: container.scrollHeight,
|
|
21409
|
+
scrollTop: container.scrollTop,
|
|
21410
|
+
hasOverflow: container.scrollHeight > container.clientHeight
|
|
21411
|
+
});
|
|
21412
|
+
}
|
|
21368
21413
|
}
|
|
21369
|
-
console.info(`Scroll container with id "${this.scrollContainerId()}" found!`);
|
|
21370
21414
|
}
|
|
21371
21415
|
else if (this.dashboardContainer) {
|
|
21372
21416
|
// Fall back to internal dashboard container
|
|
21373
21417
|
container = this.dashboardContainer.nativeElement;
|
|
21418
|
+
console.log('[Scroll Debug] Using internal dashboard container:', container);
|
|
21374
21419
|
}
|
|
21420
|
+
// Only attach listener for non-Ionic elements (Ionic handled above)
|
|
21375
21421
|
if (container) {
|
|
21422
|
+
console.log('[Scroll Debug] Attaching scroll listener to container');
|
|
21376
21423
|
container.addEventListener('scroll', () => this.onContainerScroll(container), { passive: true });
|
|
21377
21424
|
}
|
|
21425
|
+
else if (!this.scrollContainerId() || document.getElementById(this.scrollContainerId())?.tagName.toLowerCase() !== 'ion-content') {
|
|
21426
|
+
console.warn('[Scroll Debug] No scroll container found!');
|
|
21427
|
+
}
|
|
21428
|
+
}
|
|
21429
|
+
else {
|
|
21430
|
+
console.log('[Scroll Debug] Not in embedded mode, using window scroll');
|
|
21378
21431
|
}
|
|
21379
21432
|
}
|
|
21380
21433
|
handleSearchResult(result) {
|
|
@@ -21584,6 +21637,7 @@ class SymphiqFunnelAnalysisDashboardComponent {
|
|
|
21584
21637
|
}
|
|
21585
21638
|
onContainerScroll(container) {
|
|
21586
21639
|
if (!this.embedded()) {
|
|
21640
|
+
console.log('[Scroll Debug] onContainerScroll called but not in embedded mode, returning');
|
|
21587
21641
|
return;
|
|
21588
21642
|
}
|
|
21589
21643
|
const scrollPosition = container.scrollTop;
|
|
@@ -21592,15 +21646,26 @@ class SymphiqFunnelAnalysisDashboardComponent {
|
|
|
21592
21646
|
const scrollHeight = container.scrollHeight;
|
|
21593
21647
|
const maxScroll = scrollHeight - containerHeight;
|
|
21594
21648
|
const progress = maxScroll > 0 ? (scrollPosition / maxScroll) * 100 : 0;
|
|
21649
|
+
console.log('[Scroll Debug] Container scroll event:', {
|
|
21650
|
+
scrollPosition,
|
|
21651
|
+
containerHeight,
|
|
21652
|
+
scrollHeight,
|
|
21653
|
+
maxScroll,
|
|
21654
|
+
progress: progress.toFixed(2) + '%',
|
|
21655
|
+
currentScrollProgress: this.scrollProgress(),
|
|
21656
|
+
isScrolled: this.isScrolled()
|
|
21657
|
+
});
|
|
21595
21658
|
this.scrollProgress.set(Math.min(100, Math.max(0, progress)));
|
|
21596
21659
|
// Skip header state updates during programmatic scrolling
|
|
21597
21660
|
if (this.isProgrammaticScroll) {
|
|
21661
|
+
console.log('[Scroll Debug] Skipping header update - programmatic scroll');
|
|
21598
21662
|
return;
|
|
21599
21663
|
}
|
|
21600
21664
|
// Check if we're in cooldown period after a recent state change
|
|
21601
21665
|
const now = Date.now();
|
|
21602
21666
|
const timeSinceLastChange = now - this.lastStateChangeTime;
|
|
21603
21667
|
if (timeSinceLastChange < this.STATE_CHANGE_COOLDOWN) {
|
|
21668
|
+
console.log('[Scroll Debug] Skipping header update - in cooldown period', timeSinceLastChange + 'ms');
|
|
21604
21669
|
return;
|
|
21605
21670
|
}
|
|
21606
21671
|
// Clear any pending timeout
|
|
@@ -21616,16 +21681,22 @@ class SymphiqFunnelAnalysisDashboardComponent {
|
|
|
21616
21681
|
// If currently expanded and we scroll past collapse threshold, collapse
|
|
21617
21682
|
if (!currentState && scrollPosition > COLLAPSE_THRESHOLD) {
|
|
21618
21683
|
newState = true;
|
|
21684
|
+
console.log('[Scroll Debug] Triggering COLLAPSE - scrollPosition:', scrollPosition, '> threshold:', COLLAPSE_THRESHOLD);
|
|
21619
21685
|
}
|
|
21620
21686
|
// If currently collapsed and we scroll back above expand threshold, expand
|
|
21621
21687
|
else if (currentState && scrollPosition < EXPAND_THRESHOLD) {
|
|
21622
21688
|
newState = false;
|
|
21689
|
+
console.log('[Scroll Debug] Triggering EXPAND - scrollPosition:', scrollPosition, '< threshold:', EXPAND_THRESHOLD);
|
|
21623
21690
|
}
|
|
21624
21691
|
// Only update state if it actually changed
|
|
21625
21692
|
if (newState !== currentState) {
|
|
21693
|
+
console.log('[Scroll Debug] State change detected:', currentState, '->', newState);
|
|
21626
21694
|
this.isScrolled.set(newState);
|
|
21627
21695
|
this.lastStateChangeTime = Date.now();
|
|
21628
21696
|
}
|
|
21697
|
+
else {
|
|
21698
|
+
console.log('[Scroll Debug] No state change needed. Current state:', currentState, 'Position:', scrollPosition);
|
|
21699
|
+
}
|
|
21629
21700
|
this.lastScrollPosition = scrollPosition;
|
|
21630
21701
|
}
|
|
21631
21702
|
onScroll() {
|
|
@@ -23504,7 +23575,7 @@ class SymphiqFunnelAnalysisPreviewComponent {
|
|
|
23504
23575
|
this.onViewAnalysis.emit();
|
|
23505
23576
|
}
|
|
23506
23577
|
static { this.ɵfac = function SymphiqFunnelAnalysisPreviewComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SymphiqFunnelAnalysisPreviewComponent)(); }; }
|
|
23507
|
-
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SymphiqFunnelAnalysisPreviewComponent, selectors: [["symphiq-funnel-analysis-preview"]], inputs: { analysisInput: [1, "funnelAnalysis", "analysisInput"], viewMode: [1, "viewMode"] }, outputs: { onViewAnalysis: "onViewAnalysis" }, decls: 34, vars: 40, consts: [[1, "w-full", "sm:max-w-md", "
|
|
23578
|
+
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SymphiqFunnelAnalysisPreviewComponent, selectors: [["symphiq-funnel-analysis-preview"]], inputs: { analysisInput: [1, "funnelAnalysis", "analysisInput"], viewMode: [1, "viewMode"] }, outputs: { onViewAnalysis: "onViewAnalysis" }, decls: 34, vars: 40, consts: [[1, "w-full", "sm:max-w-md", "rounded-xl", "border", "shadow-lg", "backdrop-blur-lg", "transition-all", "duration-300", "sm:hover:shadow-xl", "sm:hover:scale-[1.01]", "overflow-hidden"], [1, "px-3", "py-2", "sm:px-4", "sm:py-3", "border-b", "flex", "items-center", "justify-between", "gap-2", "sm:gap-3"], [1, "flex-1", "min-w-0"], [1, "text-sm", "font-bold", "truncate"], [1, "text-xs", "truncate", "cursor-help", 3, "libSymphiqTooltip", "tooltipPosition"], [1, "flex", "items-center", "gap-1.5", "sm:gap-2", "flex-shrink-0"], ["tooltipType", "badge", 1, "px-2", "py-1", "rounded", "text-center", "min-w-[44px]", "min-h-[44px]", "flex", "items-center", "justify-center", 3, "libSymphiqTooltip", "tooltipPosition"], [1, "text-lg", "font-bold"], [1, "p-3", "sm:p-4", "space-y-2.5", "sm:space-y-3"], ["tooltipType", "metric", 1, "rounded-lg", "p-2.5", "sm:p-3", "border", "transition-all", "duration-200", "sm:hover:scale-105", "cursor-help", "active:scale-[0.98]", 3, "class", "libSymphiqTooltip", "tooltipPosition"], [1, "grid", "grid-cols-2", "gap-1.5", "sm:gap-2"], ["tooltipType", "metric", 1, "rounded-lg", "p-1.5", "sm:p-2", "border", "transition-all", "duration-200", "sm:hover:scale-105", "active:scale-[0.98]", 3, "class", "libSymphiqTooltip", "tooltipPosition"], [1, "rounded-lg", "p-2.5", "sm:p-3", "border", "transition-all", "duration-200", "sm:hover:scale-105", "active:scale-[0.98]", 3, "class"], [1, "rounded-lg", "p-2.5", "sm:p-3", "border", "transition-all", "duration-200", "sm:hover:scale-105", "active:scale-[0.98]"], [1, "flex", "items-center", "justify-between", "mb-2"], [1, "flex", "items-center", "gap-1.5", "sm:gap-2"], [1, "text-lg"], [1, "text-xs", "sm:text-sm", "font-bold"], ["tooltipType", "competitive", 1, "px-2", "py-0.5", "rounded", "text-xs", "font-bold", 3, "class", "animate-pulse", "libSymphiqTooltip", "tooltipPosition"], ["tooltipType", "narrative", 1, "text-xs", "leading-relaxed", "line-clamp-3", "cursor-help", 3, "libSymphiqTooltip", "tooltipPosition"], [1, "px-3", "py-1.5", "sm:px-4", "sm:py-2", "border-t"], [1, "w-full", "py-2.5", "sm:py-2", "rounded-lg", "font-semibold", "text-xs", "transition-all", "duration-300", "sm:hover:scale-105", "active:scale-[0.98]", "flex", "items-center", "justify-center", "gap-2", "group", "cursor-pointer", "min-h-[44px]", 3, "click"], ["fill", "none", "stroke", "currentColor", "viewBox", "0 0 24 24", 1, "w-3", "h-3", "transition-transform", "duration-300", "group-hover:translate-x-1"], ["stroke-linecap", "round", "stroke-linejoin", "round", "stroke-width", "2", "d", "M13 7l5 5m0 0l-5 5m5-5H6"], ["tooltipType", "metric", 1, "rounded-lg", "p-2.5", "sm:p-3", "border", "transition-all", "duration-200", "sm:hover:scale-105", "cursor-help", "active:scale-[0.98]", 3, "libSymphiqTooltip", "tooltipPosition"], ["fill", "none", "stroke", "currentColor", "viewBox", "0 0 24 24", 1, "w-3.5", "h-3.5", "sm:w-4", "sm:h-4"], ["stroke-linecap", "round", "stroke-linejoin", "round", "stroke-width", "2", "d", "M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z"], [1, "text-xs", "font-semibold"], ["tooltipType", "status", 1, "px-2", "py-1", "rounded", "text-xs", "font-bold", "flex", "items-center", "gap-1", "relative", "z-10", "min-h-[32px]", 3, "mouseenter", "mouseleave", "libSymphiqTooltip", "tooltipPosition"], [1, "flex", "items-baseline", "justify-between"], [1, "text-lg", "sm:text-xl", "font-bold"], [1, "flex", "items-center", "gap-1"], ["fill", "currentColor", "viewBox", "0 0 20 20", 1, "w-3", "h-3"], ["fill-rule", "evenodd", "d", "M5.293 9.707a1 1 0 010-1.414l4-4a1 1 0 011.414 0l4 4a1 1 0 01-1.414 1.414L11 7.414V15a1 1 0 11-2 0V7.414L6.707 9.707a1 1 0 01-1.414 0z", "clip-rule", "evenodd"], ["tooltipType", "metric", 1, "rounded-lg", "p-1.5", "sm:p-2", "border", "transition-all", "duration-200", "sm:hover:scale-105", "active:scale-[0.98]", 3, "libSymphiqTooltip", "tooltipPosition"], [1, "flex", "items-center", "justify-between", "mb-1"], [1, "text-xs", "font-medium", "truncate", "flex-1"], [1, "w-2", "h-2", "rounded-full", "flex-shrink-0"], [1, "flex", "items-center", "justify-between"], ["stroke-linecap", "round", "stroke-linejoin", "round", "stroke-width", "2", "d", "M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"], ["tooltipType", "insightsList", 1, "px-2", "py-0.5", "rounded", "text-xs", "font-bold", 3, "libSymphiqTooltip", "tooltipPosition"], ["tooltipType", "competitive", 1, "px-2", "py-0.5", "rounded", "text-xs", "font-bold", 3, "libSymphiqTooltip", "tooltipPosition"]], template: function SymphiqFunnelAnalysisPreviewComponent_Template(rf, ctx) { if (rf & 1) {
|
|
23508
23579
|
i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2)(3, "h3", 3);
|
|
23509
23580
|
i0.ɵɵtext(4, "Funnel Analysis");
|
|
23510
23581
|
i0.ɵɵelementEnd();
|
|
@@ -23594,7 +23665,7 @@ class SymphiqFunnelAnalysisPreviewComponent {
|
|
|
23594
23665
|
args: [{ selector: 'symphiq-funnel-analysis-preview', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, TooltipDirective, TooltipContainerComponent], template: `
|
|
23595
23666
|
<div
|
|
23596
23667
|
[class]="containerClass()"
|
|
23597
|
-
class="w-full sm:max-w-md
|
|
23668
|
+
class="w-full sm:max-w-md rounded-xl border shadow-lg backdrop-blur-lg transition-all duration-300 sm:hover:shadow-xl sm:hover:scale-[1.01] overflow-hidden">
|
|
23598
23669
|
|
|
23599
23670
|
<!-- Compact Header -->
|
|
23600
23671
|
<div [class]="headerClass()" class="px-3 py-2 sm:px-4 sm:py-3 border-b flex items-center justify-between gap-2 sm:gap-3">
|