@eric-emg/symphiq-components 1.2.45 → 1.2.47

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.
@@ -21425,11 +21425,7 @@ class SymphiqFunnelAnalysisDashboardComponent {
21425
21425
  }, ...(ngDevMode ? [{ debugName: "chartsById" }] : []));
21426
21426
  // Pre-computed styling classes
21427
21427
  this.headerClass = computed(() => {
21428
- const scrolled = this.isScrolled();
21429
- const baseClass = scrolled
21430
- ? (this.isLightMode() ? 'bg-white/95 backdrop-blur-xl border-b border-slate-300 shadow-lg' : 'bg-slate-900/95 backdrop-blur-xl border-b border-slate-700 shadow-2xl')
21431
- : (this.isLightMode() ? 'bg-white/90 backdrop-blur-md border-b border-slate-200 shadow-sm' : 'bg-slate-900/80 backdrop-blur-md border-b border-slate-800 shadow-lg');
21432
- return `${baseClass} transition-all duration-300`;
21428
+ return 'bg-transparent transition-all duration-300';
21433
21429
  }, ...(ngDevMode ? [{ debugName: "headerClass" }] : []));
21434
21430
  this.headerTitleClass = computed(() => this.isLightMode() ? 'text-slate-900' : 'text-white', ...(ngDevMode ? [{ debugName: "headerTitleClass" }] : []));
21435
21431
  this.headerSubtitleClass = computed(() => this.isLightMode() ? 'text-slate-600' : 'text-slate-400', ...(ngDevMode ? [{ debugName: "headerSubtitleClass" }] : []));
@@ -21632,27 +21628,23 @@ class SymphiqFunnelAnalysisDashboardComponent {
21632
21628
  // Manage overall assessment loading state during view mode transitions
21633
21629
  }
21634
21630
  ngAfterViewInit() {
21635
- console.log('[DASHBOARD v5] ngAfterViewInit called', {
21636
- embedded: this.embedded(),
21637
- scrollContainerId: this.scrollContainerId(),
21638
- isScrolled: this.isScrolled(),
21639
- viewMode: this.viewMode()
21640
- });
21631
+ console.log('[DASHBOARD v6] ngAfterViewInit - event-driven scroll approach');
21641
21632
  // Ensure modal has data after view is initialized
21642
21633
  if (this.modalComponent) {
21643
21634
  this.modalComponent.setMetricsAndInsights(this.allMetrics(), this.insights(), this.allCharts());
21644
21635
  }
21645
- // Set up container scroll listener when in embedded mode
21636
+ // v6 - Pure event-driven scroll detection
21637
+ // No initial state checking, no timeouts, no ResizeObserver
21638
+ // Header state only updates on actual scroll events
21646
21639
  if (this.embedded()) {
21647
21640
  let container = null;
21648
- // If a scroll container ID is provided, use that element
21649
21641
  if (this.scrollContainerId()) {
21650
21642
  const setupScrollContainer = () => {
21651
21643
  const element = document.getElementById(this.scrollContainerId());
21652
- console.log('[SCROLL DEBUG v2] setupScrollContainer attempt', {
21644
+ console.log('[SCROLL v6] Setup attempt', {
21653
21645
  scrollContainerId: this.scrollContainerId(),
21654
- elementFound: !!element,
21655
- elementTag: element?.tagName
21646
+ found: !!element,
21647
+ tag: element?.tagName
21656
21648
  });
21657
21649
  if (!element) {
21658
21650
  return false;
@@ -21660,104 +21652,16 @@ class SymphiqFunnelAnalysisDashboardComponent {
21660
21652
  // Check if this is an Ionic ion-content element
21661
21653
  if (element.tagName.toLowerCase() === 'ion-content') {
21662
21654
  const ionContent = element;
21663
- // Get the scrollable element from Ionic
21664
21655
  if (typeof ionContent.getScrollElement === 'function') {
21665
21656
  ionContent.getScrollElement().then((scrollElement) => {
21666
- console.log('[SCROLL DEBUG v2] Ionic scroll element found', {
21667
- scrollTop: scrollElement.scrollTop,
21668
- scrollHeight: scrollElement.scrollHeight,
21669
- clientHeight: scrollElement.clientHeight
21670
- });
21671
- // Store reference for use in scrollToSection and tooltips
21657
+ console.log('[SCROLL v6] Ionic scroll element ready - attaching listeners');
21658
+ // Store reference for tooltips and programmatic scrolling
21672
21659
  this.embeddedScrollContainer = scrollElement;
21673
21660
  this.tooltipService.setScrollContainer(scrollElement);
21674
- // Helper function to check and update scroll state
21675
- const checkInitialScroll = () => {
21676
- const currentScrollTop = scrollElement.scrollTop;
21677
- const scrollHeight = scrollElement.scrollHeight;
21678
- const clientHeight = scrollElement.clientHeight;
21679
- console.log('[SCROLL DEBUG v5] Checking initial scroll position', {
21680
- scrollTop: currentScrollTop,
21681
- scrollHeight,
21682
- clientHeight,
21683
- shouldCollapse: currentScrollTop > 50
21684
- });
21685
- // Only make a decision if we have substantial content
21686
- if (scrollHeight < 500) {
21687
- console.log('[SCROLL DEBUG v5] Content too small, skipping check');
21688
- return;
21689
- }
21690
- if (currentScrollTop > 50) {
21691
- console.log('[SCROLL DEBUG v5] Collapsing header due to scroll position', { currentScrollTop });
21692
- this.isScrolled.set(true);
21693
- }
21694
- else {
21695
- console.log('[SCROLL DEBUG v5] Expanding header due to scroll position', { currentScrollTop });
21696
- this.isScrolled.set(false);
21697
- }
21698
- };
21699
- // Use ResizeObserver to detect when content has finished rendering
21700
- // Only check scroll position once content has substantial height
21701
- const MIN_CONTENT_HEIGHT = 500; // Content should be at least this tall before we check scroll
21702
- let lastHeight = scrollElement.scrollHeight;
21703
- let stableCount = 0;
21704
- let scrollCheckTimeout = null;
21705
- const resizeObserver = new ResizeObserver(() => {
21706
- const currentHeight = scrollElement.scrollHeight;
21707
- console.log('[SCROLL DEBUG v5] Content height changed', {
21708
- lastHeight,
21709
- currentHeight,
21710
- stableCount,
21711
- minHeightReached: currentHeight >= MIN_CONTENT_HEIGHT
21712
- });
21713
- // Clear any pending scroll check
21714
- if (scrollCheckTimeout) {
21715
- clearTimeout(scrollCheckTimeout);
21716
- }
21717
- // Only start checking when we have substantial content
21718
- if (currentHeight >= MIN_CONTENT_HEIGHT) {
21719
- if (currentHeight === lastHeight) {
21720
- stableCount++;
21721
- // Height has been stable for 2 consecutive observations
21722
- if (stableCount >= 2) {
21723
- console.log('[SCROLL DEBUG v5] Content height stabilized, scheduling scroll check');
21724
- // Wait longer for Ionic to restore scroll position
21725
- scrollCheckTimeout = setTimeout(() => {
21726
- console.log('[SCROLL DEBUG v5] Performing delayed scroll check after stabilization');
21727
- checkInitialScroll();
21728
- }, 150);
21729
- resizeObserver.disconnect();
21730
- }
21731
- }
21732
- else {
21733
- stableCount = 0;
21734
- lastHeight = currentHeight;
21735
- // Schedule a check after height change
21736
- scrollCheckTimeout = setTimeout(() => {
21737
- console.log('[SCROLL DEBUG v5] Checking scroll after height change');
21738
- checkInitialScroll();
21739
- }, 100);
21740
- }
21741
- }
21742
- else {
21743
- // Reset tracking if height drops below threshold (component being destroyed)
21744
- stableCount = 0;
21745
- lastHeight = currentHeight;
21746
- }
21747
- });
21748
- // Observe the scroll element for size changes
21749
- resizeObserver.observe(scrollElement);
21750
- // Check immediately if we already have content, but allow time for scroll restoration
21751
- if (scrollElement.scrollHeight >= MIN_CONTENT_HEIGHT) {
21752
- scrollCheckTimeout = setTimeout(() => {
21753
- console.log('[SCROLL DEBUG v5] Initial scroll check after delay');
21754
- checkInitialScroll();
21755
- }, 200);
21756
- }
21757
- // Attach scroll listeners
21661
+ // v6 - Attach scroll event listeners
21758
21662
  scrollElement.addEventListener('scroll', () => this.onContainerScroll(scrollElement), { passive: true });
21759
21663
  ionContent.addEventListener('ionScroll', () => this.onContainerScroll(scrollElement), { passive: true });
21760
- // Polling fallback for reliable scroll detection
21664
+ // Add polling as fallback since Ionic scroll events can be unreliable
21761
21665
  let lastScrollTop = 0;
21762
21666
  const pollScroll = () => {
21763
21667
  const currentScrollTop = scrollElement.scrollTop;
@@ -21768,140 +21672,33 @@ class SymphiqFunnelAnalysisDashboardComponent {
21768
21672
  requestAnimationFrame(pollScroll);
21769
21673
  };
21770
21674
  requestAnimationFrame(pollScroll);
21675
+ console.log('[SCROLL v6] Event listeners and polling attached');
21771
21676
  }).catch((error) => {
21772
- console.error('Error getting Ionic scroll element:', error);
21677
+ console.error('[SCROLL v6] Error getting Ionic scroll element:', error);
21773
21678
  });
21774
21679
  return true;
21775
21680
  }
21776
21681
  else {
21777
21682
  // Fallback for older Ionic versions
21778
- console.log('[SCROLL DEBUG v2] Using fallback for older Ionic', {
21779
- scrollTop: element.scrollTop
21780
- });
21683
+ console.log('[SCROLL v6] Using fallback for older Ionic');
21781
21684
  this.embeddedScrollContainer = element;
21782
21685
  this.tooltipService.setScrollContainer(element);
21783
- // Helper function to check and update scroll state
21784
- const checkInitialScroll = () => {
21785
- const currentScrollTop = element.scrollTop;
21786
- console.log('[SCROLL DEBUG v2] Checking initial scroll position (fallback)', {
21787
- scrollTop: currentScrollTop,
21788
- shouldCollapse: currentScrollTop > 50
21789
- });
21790
- if (currentScrollTop > 50) {
21791
- console.log('[SCROLL DEBUG v2] Collapsing header due to scroll position', { currentScrollTop });
21792
- this.isScrolled.set(true);
21793
- }
21794
- else {
21795
- console.log('[SCROLL DEBUG v2] Expanding header due to scroll position', { currentScrollTop });
21796
- this.isScrolled.set(false);
21797
- }
21798
- };
21799
- // Use ResizeObserver to detect when content has finished rendering
21800
- const MIN_CONTENT_HEIGHT = 500;
21801
- let lastHeight = element.scrollHeight;
21802
- let stableCount = 0;
21803
- const resizeObserver = new ResizeObserver(() => {
21804
- const currentHeight = element.scrollHeight;
21805
- console.log('[SCROLL DEBUG v2] Content height changed (fallback)', {
21806
- lastHeight,
21807
- currentHeight,
21808
- stableCount,
21809
- minHeightReached: currentHeight >= MIN_CONTENT_HEIGHT
21810
- });
21811
- if (currentHeight >= MIN_CONTENT_HEIGHT) {
21812
- if (currentHeight === lastHeight) {
21813
- stableCount++;
21814
- if (stableCount >= 2) {
21815
- console.log('[SCROLL DEBUG v2] Content height stabilized (fallback), checking scroll position');
21816
- checkInitialScroll();
21817
- resizeObserver.disconnect();
21818
- }
21819
- }
21820
- else {
21821
- stableCount = 0;
21822
- lastHeight = currentHeight;
21823
- checkInitialScroll();
21824
- }
21825
- }
21826
- else {
21827
- stableCount = 0;
21828
- lastHeight = currentHeight;
21829
- }
21830
- });
21831
- resizeObserver.observe(element);
21832
- if (element.scrollHeight >= MIN_CONTENT_HEIGHT) {
21833
- checkInitialScroll();
21834
- }
21835
21686
  element.addEventListener('scroll', () => this.onContainerScroll(element), { passive: true });
21836
21687
  return true;
21837
21688
  }
21838
21689
  }
21839
21690
  else {
21840
21691
  // Regular HTML element
21841
- console.log('[SCROLL DEBUG v2] Regular HTML element setup', {
21842
- scrollTop: element.scrollTop
21843
- });
21692
+ console.log('[SCROLL v6] Regular HTML element');
21844
21693
  this.embeddedScrollContainer = element;
21845
21694
  this.tooltipService.setScrollContainer(element);
21846
- // Helper function to check and update scroll state
21847
- const checkInitialScroll = () => {
21848
- const currentScrollTop = element.scrollTop;
21849
- console.log('[SCROLL DEBUG v2] Checking initial scroll position (regular)', {
21850
- scrollTop: currentScrollTop,
21851
- shouldCollapse: currentScrollTop > 50
21852
- });
21853
- if (currentScrollTop > 50) {
21854
- console.log('[SCROLL DEBUG v2] Collapsing header due to scroll position', { currentScrollTop });
21855
- this.isScrolled.set(true);
21856
- }
21857
- else {
21858
- console.log('[SCROLL DEBUG v2] Expanding header due to scroll position', { currentScrollTop });
21859
- this.isScrolled.set(false);
21860
- }
21861
- };
21862
- // Use ResizeObserver to detect when content has finished rendering
21863
- const MIN_CONTENT_HEIGHT = 500;
21864
- let lastHeight = element.scrollHeight;
21865
- let stableCount = 0;
21866
- const resizeObserver = new ResizeObserver(() => {
21867
- const currentHeight = element.scrollHeight;
21868
- console.log('[SCROLL DEBUG v2] Content height changed (regular)', {
21869
- lastHeight,
21870
- currentHeight,
21871
- stableCount,
21872
- minHeightReached: currentHeight >= MIN_CONTENT_HEIGHT
21873
- });
21874
- if (currentHeight >= MIN_CONTENT_HEIGHT) {
21875
- if (currentHeight === lastHeight) {
21876
- stableCount++;
21877
- if (stableCount >= 2) {
21878
- console.log('[SCROLL DEBUG v2] Content height stabilized (regular), checking scroll position');
21879
- checkInitialScroll();
21880
- resizeObserver.disconnect();
21881
- }
21882
- }
21883
- else {
21884
- stableCount = 0;
21885
- lastHeight = currentHeight;
21886
- checkInitialScroll();
21887
- }
21888
- }
21889
- else {
21890
- stableCount = 0;
21891
- lastHeight = currentHeight;
21892
- }
21893
- });
21894
- resizeObserver.observe(element);
21895
- if (element.scrollHeight >= MIN_CONTENT_HEIGHT) {
21896
- checkInitialScroll();
21897
- }
21898
21695
  element.addEventListener('scroll', () => this.onContainerScroll(element), { passive: true });
21899
21696
  return true;
21900
21697
  }
21901
21698
  };
21902
21699
  // Try to set up immediately
21903
21700
  if (!setupScrollContainer()) {
21904
- // If not found, retry with delays (element might not be in DOM yet)
21701
+ // Retry if element not found yet
21905
21702
  let retries = 0;
21906
21703
  const maxRetries = 10;
21907
21704
  const retryInterval = setInterval(() => {
@@ -21909,7 +21706,7 @@ class SymphiqFunnelAnalysisDashboardComponent {
21909
21706
  if (setupScrollContainer() || retries >= maxRetries) {
21910
21707
  clearInterval(retryInterval);
21911
21708
  if (retries >= maxRetries) {
21912
- console.warn(`Scroll container with id "${this.scrollContainerId()}" not found after ${maxRetries} retries.`);
21709
+ console.warn(`[SCROLL v6] Container "${this.scrollContainerId()}" not found after ${maxRetries} retries`);
21913
21710
  }
21914
21711
  }
21915
21712
  }, 100);
@@ -22134,11 +21931,9 @@ class SymphiqFunnelAnalysisDashboardComponent {
22134
21931
  return;
22135
21932
  }
22136
21933
  const scrollPosition = container.scrollTop;
22137
- console.log('[SCROLL DEBUG] onContainerScroll', {
21934
+ console.log('[SCROLL v6] onContainerScroll', {
22138
21935
  scrollPosition,
22139
- isScrolled: this.isScrolled(),
22140
- isProgrammaticScroll: this.isProgrammaticScroll,
22141
- lastScrollPosition: this.lastScrollPosition
21936
+ currentState: this.isScrolled()
22142
21937
  });
22143
21938
  // Update scroll progress for smooth bar animation
22144
21939
  const containerHeight = container.clientHeight;
@@ -22146,39 +21941,23 @@ class SymphiqFunnelAnalysisDashboardComponent {
22146
21941
  const maxScroll = scrollHeight - containerHeight;
22147
21942
  const progress = maxScroll > 0 ? (scrollPosition / maxScroll) * 100 : 0;
22148
21943
  this.scrollProgress.set(Math.min(100, Math.max(0, progress)));
22149
- // Skip header state updates during programmatic scrolling or cooldown
21944
+ // Skip header state updates during programmatic scrolling
22150
21945
  if (this.isProgrammaticScroll) {
22151
- console.log('[SCROLL DEBUG] Skipping - programmatic scroll');
21946
+ console.log('[SCROLL v6] Skipping - programmatic scroll');
22152
21947
  return;
22153
21948
  }
22154
- const now = Date.now();
22155
- const timeSinceLastChange = now - this.lastStateChangeTime;
22156
- if (timeSinceLastChange < this.STATE_CHANGE_COOLDOWN) {
22157
- console.log('[SCROLL DEBUG] Skipping - within cooldown', { timeSinceLastChange });
22158
- return;
22159
- }
22160
- if (this.scrollTimeout) {
22161
- clearTimeout(this.scrollTimeout);
22162
- }
22163
- // Use hysteresis to prevent bounce
21949
+ // v6 - Simple threshold-based state changes with hysteresis
22164
21950
  const COLLAPSE_THRESHOLD = 50;
22165
21951
  const EXPAND_THRESHOLD = 30;
22166
21952
  const currentState = this.isScrolled();
22167
- let newState = currentState;
22168
21953
  if (!currentState && scrollPosition > COLLAPSE_THRESHOLD) {
22169
- newState = true;
22170
- console.log('[SCROLL DEBUG] Should collapse header', { scrollPosition, COLLAPSE_THRESHOLD });
21954
+ console.log('[SCROLL v6] Collapsing header', { scrollPosition });
21955
+ this.isScrolled.set(true);
22171
21956
  }
22172
21957
  else if (currentState && scrollPosition < EXPAND_THRESHOLD) {
22173
- newState = false;
22174
- console.log('[SCROLL DEBUG] Should expand header', { scrollPosition, EXPAND_THRESHOLD });
22175
- }
22176
- if (newState !== currentState) {
22177
- console.log('[SCROLL DEBUG] Changing header state', { from: currentState, to: newState });
22178
- this.isScrolled.set(newState);
22179
- this.lastStateChangeTime = Date.now();
21958
+ console.log('[SCROLL v6] Expanding header', { scrollPosition });
21959
+ this.isScrolled.set(false);
22180
21960
  }
22181
- this.lastScrollPosition = scrollPosition;
22182
21961
  }
22183
21962
  onScroll() {
22184
21963
  if (this.embedded()) {