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

visgl / react-map-gl / 12938415134

23 Jan 2025 09:29PM UTC coverage: 84.961%. First build
12938415134

Pull #2468

github

web-flow
Merge 501696250 into 929b8fb60
Pull Request #2468: [v8] Align type names across modules

882 of 1099 branches covered (80.25%)

Branch coverage included in aggregate %.

359 of 396 new or added lines in 19 files covered. (90.66%)

5406 of 6302 relevant lines covered (85.78%)

24.02 hits per line

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

86.79
/modules/react-mapbox/src/components/source.ts
1
import * as React from 'react';
1✔
2
import {useContext, useEffect, useMemo, useState, useRef, cloneElement} from 'react';
1✔
3
import {MapContext} from './map';
1✔
4
import assert from '../utils/assert';
1✔
5
import {deepEqual} from '../utils/deep-equal';
1✔
6

1✔
7
import type {
1✔
8
  GeoJSONSourceImplementation,
1✔
9
  ImageSourceImplemtation,
1✔
10
  AnySourceImplementation
1✔
11
} from '../types/internal';
1✔
12
import type {AnySource, ImageSource, VectorSource} from '../types/style-spec';
1✔
13
import type {MapInstance} from '../types/lib';
1✔
14

1✔
15
export type SourceProps = AnySource & {
1✔
16
  id?: string;
1✔
17
  children?: any;
1✔
18
};
1✔
19

1✔
20
let sourceCounter = 0;
1✔
21

1✔
22
function createSource(map: MapInstance, id: string, props: SourceProps) {
4✔
23
  // @ts-ignore
4✔
24
  if (map.style && map.style._loaded) {
4✔
25
    const options = {...props};
4✔
26
    delete options.id;
4✔
27
    delete options.children;
4✔
28
    // @ts-ignore
4✔
29
    map.addSource(id, options);
4✔
30
    return map.getSource(id);
4✔
31
  }
4!
32
  return null;
×
33
}
×
34

1✔
35
/* eslint-disable complexity */
1✔
36
function updateSource(source: AnySourceImplementation, props: SourceProps, prevProps: SourceProps) {
9✔
37
  assert(props.id === prevProps.id, 'source id changed');
9✔
38
  assert(props.type === prevProps.type, 'source type changed');
9✔
39

9✔
40
  let changedKey = '';
9✔
41
  let changedKeyCount = 0;
9✔
42

9✔
43
  for (const key in props) {
9✔
44
    if (key !== 'children' && key !== 'id' && !deepEqual(prevProps[key], props[key])) {
32✔
45
      changedKey = key;
1✔
46
      changedKeyCount++;
1✔
47
    }
1✔
48
  }
32✔
49

9✔
50
  if (!changedKeyCount) {
9✔
51
    return;
8✔
52
  }
8✔
53

1✔
54
  const type = props.type;
1✔
55

1✔
56
  if (type === 'geojson') {
1✔
57
    (source as GeoJSONSourceImplementation).setData(props.data);
1✔
58
  } else if (type === 'image') {
9!
59
    (source as ImageSourceImplemtation).updateImage({
×
60
      url: props.url,
×
61
      coordinates: props.coordinates
×
62
    });
×
63
  } else if ('setCoordinates' in source && changedKeyCount === 1 && changedKey === 'coordinates') {
×
NEW
64
    source.setCoordinates((props as unknown as ImageSource).coordinates);
×
65
  } else if ('setUrl' in source && changedKey === 'url') {
×
NEW
66
    source.setUrl((props as VectorSource).url);
×
67
  } else if ('setTiles' in source && changedKey === 'tiles') {
×
NEW
68
    source.setTiles((props as VectorSource).tiles);
×
69
  } else {
×
70
    // eslint-disable-next-line
×
71
    console.warn(`Unable to update <Source> prop: ${changedKey}`);
×
72
  }
×
73
}
9✔
74
/* eslint-enable complexity */
1✔
75

1✔
76
export function Source(props: SourceProps) {
1✔
77
  const map = useContext(MapContext).map.getMap();
13✔
78
  const propsRef = useRef(props);
13✔
79
  const [, setStyleLoaded] = useState(0);
13✔
80

13✔
81
  const id = useMemo(() => props.id || `jsx-source-${sourceCounter++}`, []);
13!
82

13✔
83
  useEffect(() => {
13✔
84
    if (map) {
2✔
85
      /* global setTimeout */
2✔
86
      const forceUpdate = () => setTimeout(() => setStyleLoaded(version => version + 1), 0);
2✔
87
      map.on('styledata', forceUpdate);
2✔
88
      forceUpdate();
2✔
89

2✔
90
      return () => {
2✔
91
        map.off('styledata', forceUpdate);
2✔
92
        // @ts-ignore
2✔
93
        if (map.style && map.style._loaded && map.getSource(id)) {
2✔
94
          // Parent effects are destroyed before child ones, see
2✔
95
          // https://github.com/facebook/react/issues/16728
2✔
96
          // Source can only be removed after all child layers are removed
2✔
97
          const allLayers = map.getStyle()?.layers;
2✔
98
          if (allLayers) {
2✔
99
            for (const layer of allLayers) {
2✔
100
              // @ts-ignore (2339) source does not exist on all layer types
1✔
101
              if (layer.source === id) {
1✔
102
                map.removeLayer(layer.id);
1✔
103
              }
1✔
104
            }
1✔
105
          }
2✔
106
          map.removeSource(id);
2✔
107
        }
2✔
108
      };
2✔
109
    }
2!
110
    return undefined;
×
111
  }, [map]);
13✔
112

13✔
113
  // @ts-ignore
13✔
114
  let source = map && map.style && map.getSource(id);
13✔
115
  if (source) {
13✔
116
    updateSource(source, props, propsRef.current);
9✔
117
  } else {
13✔
118
    source = createSource(map, id, props);
4✔
119
  }
4✔
120
  propsRef.current = props;
13✔
121

13✔
122
  return (
13✔
123
    (source &&
13✔
124
      React.Children.map(
13✔
125
        props.children,
13✔
126
        child =>
13✔
127
          child &&
7✔
128
          cloneElement(child, {
7✔
129
            source: id
7✔
130
          })
7✔
131
      )) ||
13✔
132
    null
6✔
133
  );
13✔
134
}
13✔
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