• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

prabhuignoto / react-chrono / #92

18 Jun 2025 10:08AM UTC coverage: 90.727% (+0.9%) from 89.791%
#92

push

web-flow
Minor cleanup and expanding test coverage (#548)

* refactor: rename project to React Chrono UI and update related files

* fix: update tsconfig to reference the correct entry file for React Chrono UI

* feat: enhance styles with vendor prefixes and improve cross-browser support

* Add tests for useNewScrollPosition hook and TimelineHorizontal component

- Implement comprehensive tests for the useNewScrollPosition hook covering horizontal, vertical, and edge cases.
- Create a new test file for the TimelineHorizontal component, ensuring it renders correctly and handles various props and states.
- Update snapshots for timeline control and vertical components to reflect recent changes in class names.
- Modify vitest configuration to include all test files in the src directory.

* refactor: simplify transform handling in timeline styles

* refactor: clean up test imports and remove unused styles in timeline components

1783 of 2112 branches covered (84.42%)

Branch coverage included in aggregate %.

670 of 674 new or added lines in 12 files covered. (99.41%)

400 existing lines in 29 files now uncovered.

10564 of 11497 relevant lines covered (91.88%)

10.09 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.68
/src/hooks/useCardSize.ts
1
import { RefObject, useCallback, useEffect, useMemo, useState, useRef } from 'react';
1✔
2

3
interface UseCardSizeProps {
4
  containerRef: RefObject<HTMLElement | null>;
5
  detailsRef: RefObject<HTMLElement | null>;
6
  setStartWidth: (width: number) => void;
7
}
8

9
interface UseCardSizeReturn {
10
  cardActualHeight: number;
11
  detailsHeight: number;
12
  textContentLarge: boolean;
13
  updateCardSize: (node: HTMLElement | null) => void;
14
}
15

16
interface CardDimensions {
17
  cardHeight: number;
18
  detailsHeight: number;
19
  containerWidth: number;
20
}
21

22
// Memoized calculation function to prevent unnecessary recalculations
23
const calculateTextContentSize = (
1✔
24
  cardHeight: number,
45✔
25
  containerHeight: number,
45✔
26
  scrollHeight: number,
45✔
27
  clientHeight: number,
45✔
28
  detailsOffsetTop: number,
45✔
29
): boolean => {
45✔
30
  // Use cached values instead of DOM queries
31
  const hasSignificantOverflow = scrollHeight > clientHeight + 20;
45✔
32
  return (
45✔
33
    cardHeight + detailsOffsetTop > containerHeight + 20 ||
45✔
34
    hasSignificantOverflow
41✔
35
  );
36
};
45✔
37

38
export const useCardSize = ({
1✔
39
  containerRef,
59✔
40
  detailsRef,
59✔
41
  setStartWidth,
59✔
42
}: UseCardSizeProps): UseCardSizeReturn => {
59✔
43
  const [dimensions, setDimensions] = useState<CardDimensions>({
59✔
44
    cardHeight: 0,
59✔
45
    detailsHeight: 0,
59✔
46
    containerWidth: 0,
59✔
47
  });
59✔
48
  
49
  // Cache DOM measurements to avoid repeated calculations
50
  const measurementsCache = useRef<{
59✔
51
    scrollHeight: number;
52
    clientHeight: number;
53
    offsetTop: number;
54
    containerHeight: number;
55
  }>({ scrollHeight: 0, clientHeight: 0, offsetTop: 0, containerHeight: 0 });
59✔
56

57
  // Throttled resize observer for better performance
58
  useEffect(() => {
59✔
59
    let rafId: number;
41✔
60
    
61
    const observer = new ResizeObserver((entries) => {
41✔
62
      // Use RAF to batch DOM updates
63
      if (rafId) cancelAnimationFrame(rafId);
×
64
      
65
      rafId = requestAnimationFrame(() => {
×
66
        for (const entry of entries) {
×
67
          if (entry.target === containerRef.current) {
×
UNCOV
68
            setDimensions((prev) => ({
×
UNCOV
69
              ...prev,
×
UNCOV
70
              containerWidth: entry.contentRect.width,
×
UNCOV
71
            }));
×
UNCOV
72
          }
×
UNCOV
73
        }
×
UNCOV
74
      });
×
75
    });
41✔
76

77
    if (containerRef.current) {
41✔
78
      observer.observe(containerRef.current);
38✔
79
    }
38✔
80

81
    return () => {
41✔
82
      if (rafId) cancelAnimationFrame(rafId);
41!
83
      observer.disconnect();
41✔
84
    };
41✔
85
  }, [containerRef]);
59✔
86

87
  const updateCardSize = useCallback(
59✔
88
    (node: HTMLElement | null) => {
59✔
89
      if (!node || !detailsRef.current) return;
5✔
90

91
      const detailsEle = detailsRef.current;
4✔
92
      const { scrollHeight, offsetHeight, offsetTop } = detailsEle;
4✔
93
      const containerHeight = node.clientHeight;
4✔
94

95
      // Cache measurements
96
      measurementsCache.current = {
4✔
97
        scrollHeight,
4✔
98
        clientHeight: offsetHeight,
4✔
99
        offsetTop,
4✔
100
        containerHeight,
4✔
101
      };
4✔
102

103
      containerRef.current = node;
4✔
104
      setStartWidth(node.clientWidth);
4✔
105
      setDimensions({
4✔
106
        cardHeight: scrollHeight,
4✔
107
        detailsHeight: offsetHeight,
4✔
108
        containerWidth: node.clientWidth,
4✔
109
      });
4✔
110
    },
5✔
111
    [detailsRef, setStartWidth, containerRef],
59✔
112
  );
59✔
113

114
  // Optimized memoization with cached measurements
115
  const { cardActualHeight, detailsHeight, textContentLarge } = useMemo(
59✔
116
    () => {
59✔
117
      const cache = measurementsCache.current;
45✔
118
      return {
45✔
119
        cardActualHeight: dimensions.cardHeight,
45✔
120
        detailsHeight: dimensions.detailsHeight,
45✔
121
        textContentLarge: calculateTextContentSize(
45✔
122
          dimensions.cardHeight,
45✔
123
          dimensions.detailsHeight,
45✔
124
          cache.containerHeight,
45✔
125
          cache.scrollHeight,
45✔
126
          cache.clientHeight,
45✔
127
        ),
45✔
128
      };
45✔
129
    },
45✔
130
    [dimensions],
59✔
131
  );
59✔
132

133
  return {
59✔
134
    cardActualHeight,
59✔
135
    detailsHeight,
59✔
136
    textContentLarge,
59✔
137
    updateCardSize,
59✔
138
  };
59✔
139
};
59✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc