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

keplergl / kepler.gl / 22361650031

24 Feb 2026 05:09PM UTC coverage: 61.612% (-0.2%) from 61.806%
22361650031

Pull #3219

github

web-flow
Merge 1d9b34cb5 into cc33b0c8f
Pull Request #3219: Update kepler-jupyter to use kepler.gl v3.2.0

6382 of 12288 branches covered (51.94%)

Branch coverage included in aggregate %.

13078 of 19297 relevant lines covered (67.77%)

81.44 hits per line

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

61.11
/src/components/src/loading-indicator.tsx
1
// SPDX-License-Identifier: MIT
2
// Copyright contributors to the kepler.gl project
3

4
import React, {PropsWithChildren, useRef, useEffect} from 'react';
5
import styled, {withTheme, keyframes} from 'styled-components';
6

7
import {getNumRasterTilesBeingLoaded, getNumVectorTilesBeingLoaded} from '@kepler.gl/layers';
8

9
type StyledContainerProps = {
10
  $isVisible?: boolean;
11
  $left: number;
12
};
13

14
const spin = keyframes`
7✔
15
  0% { transform: rotate(0deg); }
16
  100% { transform: rotate(360deg); }
17
`;
18

19
const Spinner = styled.div`
7✔
20
  display: inline-block;
21
  width: 14px;
22
  height: 14px;
23
  margin-right: 8px;
24
  border: 2px solid ${props => props.theme.textColorHl};
21✔
25
  border-top-color: transparent;
26
  border-radius: 50%;
27
  animation: ${spin} 0.8s linear infinite;
28
  vertical-align: middle;
29
`;
30

31
export const StyledContainer = styled.div<StyledContainerProps>`
7✔
32
  position: absolute;
33
  left: ${props => props.$left}px;
21✔
34
  bottom: ${props => props.theme.sidePanel.margin.left}px;
21✔
35
  z-index: 1;
36
  color: ${props => props.theme.textColor};
21✔
37
  opacity: ${props => (props.$isVisible ? 1 : 0)};
21!
38
  transition: opacity 0.5s ease-in-out;
39
  background-color: ${props => props.theme.sidePanelBg};
21✔
40
  padding: 8px 12px;
41
  font-size: 13px;
42
  font-weight: 500;
43
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
44
  backdrop-filter: blur(4px);
45
  display: flex;
46
  align-items: center;
47
  pointer-events: none;
48
`;
49

50
type LoadingIndicatorProps = {
51
  isVisible?: boolean;
52
  activeSidePanel?: boolean;
53
  sidePanelWidth?: number;
54
};
55

56
/** Extra adjustment for the loading indicator when side panel is visible */
57
const LEFT_POSITION_ADJUSTMENT = 3;
7✔
58

59
const LoadingIndicator: React.FC<LoadingIndicatorProps & {theme: any}> = ({
7✔
60
  isVisible,
61
  activeSidePanel,
62
  sidePanelWidth,
63
  theme
64
}) => {
65
  const left =
66
    (activeSidePanel ? (sidePanelWidth || 0) + LEFT_POSITION_ADJUSTMENT : 0) +
21!
67
    theme.sidePanel.margin.left;
68

69
  // Helper message to track number of tiles that are being loaded
70
  const numRasterTilesInProgress = getNumRasterTilesBeingLoaded();
21✔
71
  const numVectorTilesInProgress = getNumVectorTilesBeingLoaded();
21✔
72

73
  let extraMessage = '';
21✔
74
  if (numRasterTilesInProgress > 0 && numVectorTilesInProgress > 0) {
21!
75
    // Both types loading: show combined count
76
    const totalTiles = numRasterTilesInProgress + numVectorTilesInProgress;
×
77
    extraMessage = `${totalTiles} tile${totalTiles === 1 ? ' is' : 's are'} being loaded`;
×
78
  } else if (numRasterTilesInProgress > 0) {
21!
79
    // Only raster tiles loading
80
    extraMessage = `${numRasterTilesInProgress} raster tile${
×
81
      numRasterTilesInProgress === 1 ? ' is' : 's are'
×
82
    } being loaded`;
83
  } else if (numVectorTilesInProgress > 0) {
21!
84
    // Only vector tiles loading
85
    extraMessage = `${numVectorTilesInProgress} vector tile${
×
86
      numVectorTilesInProgress === 1 ? ' is' : 's are'
×
87
    } being loaded`;
88
  }
89

90
  // Preserve the last message during fade-out
91
  const lastMessageRef = useRef(extraMessage);
21✔
92
  useEffect(() => {
21✔
93
    if (isVisible && extraMessage) {
21!
94
      lastMessageRef.current = extraMessage;
×
95
    }
96
  }, [isVisible, extraMessage]);
97

98
  const displayMessage = isVisible ? extraMessage : lastMessageRef.current;
21!
99

100
  return (
21✔
101
    <StyledContainer $isVisible={isVisible} $left={left}>
102
      <Spinner />
103
      <span>{`Loading... ${displayMessage}`}</span>
104
    </StyledContainer>
105
  );
106
};
107

108
export default withTheme(LoadingIndicator) as React.FC<PropsWithChildren<LoadingIndicatorProps>>;
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

© 2026 Coveralls, Inc