@eric-emg/symphiq-components 1.2.44 → 1.2.46

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