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

visgl / react-map-gl / 5897929321

18 Aug 2023 01:56AM UTC coverage: 83.538% (-0.2%) from 83.762%
5897929321

push

github

web-flow
Import style and event types from specific base libraries (#2252)

271 of 336 branches covered (80.65%)

Branch coverage included in aggregate %.

270 of 270 new or added lines in 10 files covered. (100.0%)

2388 of 2847 relevant lines covered (83.88%)

11.02 hits per line

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

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

1✔
8
import type {
1✔
9
  MapInstance,
1✔
10
  ISource,
1✔
11
  CustomSource,
1✔
12
  GeoJSONSourceImplementation,
1✔
13
  ImageSourceImplemtation,
1✔
14
  AnySourceImplementation
1✔
15
} from '../types';
1✔
16
import type {GeoJSONSource, ImageSource, VectorSource} from '../types/style-spec-maplibre';
1✔
17

1✔
18
export type SourceProps<SourceT> = (SourceT | CustomSource) & {
1✔
19
  id?: string;
1✔
20
  children?: any;
1✔
21
};
1✔
22

1✔
23
let sourceCounter = 0;
1✔
24

1✔
25
function createSource<SourceT extends ISource>(
6✔
26
  map: MapInstance,
6✔
27
  id: string,
6✔
28
  props: SourceProps<SourceT>
6✔
29
) {
6✔
30
  // @ts-ignore
6✔
31
  if (map.style && map.style._loaded) {
6✔
32
    const options = {...props};
4✔
33
    delete options.id;
4✔
34
    delete options.children;
4✔
35
    // @ts-ignore
4✔
36
    map.addSource(id, options);
4✔
37
    return map.getSource(id);
4✔
38
  }
4✔
39
  return null;
2✔
40
}
2✔
41

1✔
42
/* eslint-disable complexity */
1✔
43
function updateSource<SourceT extends ISource>(
5✔
44
  source: AnySourceImplementation,
5✔
45
  props: SourceProps<SourceT>,
5✔
46
  prevProps: SourceProps<SourceT>
5✔
47
) {
5✔
48
  assert(props.id === prevProps.id, 'source id changed');
5✔
49
  assert(props.type === prevProps.type, 'source type changed');
5✔
50

5✔
51
  let changedKey = '';
5✔
52
  let changedKeyCount = 0;
5✔
53

5✔
54
  for (const key in props) {
5✔
55
    if (key !== 'children' && key !== 'id' && !deepEqual(prevProps[key], props[key])) {
18✔
56
      changedKey = key;
1✔
57
      changedKeyCount++;
1✔
58
    }
1✔
59
  }
18✔
60

5✔
61
  if (!changedKeyCount) {
5✔
62
    return;
4✔
63
  }
4✔
64

1✔
65
  const type = props.type;
1✔
66

1✔
67
  if (type === 'geojson') {
1✔
68
    (source as GeoJSONSourceImplementation).setData(
1✔
69
      (props as unknown as GeoJSONSource).data as any
1✔
70
    );
1✔
71
  } else if (type === 'image') {
5!
72
    (source as ImageSourceImplemtation).updateImage({
×
73
      url: (props as unknown as ImageSource).url,
×
74
      coordinates: (props as unknown as ImageSource).coordinates
×
75
    });
×
76
  } else if ('setCoordinates' in source && changedKeyCount === 1 && changedKey === 'coordinates') {
×
77
    source.setCoordinates((props as ImageSource).coordinates);
×
78
  } else if ('setUrl' in source) {
×
79
    // Added in 1.12.0:
×
80
    // vectorTileSource.setTiles
×
81
    // vectorTileSource.setUrl
×
82
    switch (changedKey) {
×
83
      case 'url':
×
84
        source.setUrl((props as VectorSource).url);
×
85
        break;
×
86
      case 'tiles':
×
87
        source.setTiles((props as VectorSource).tiles);
×
88
        break;
×
89
      default:
×
90
    }
×
91
  } else {
×
92
    // eslint-disable-next-line
×
93
    console.warn(`Unable to update <Source> prop: ${changedKey}`);
×
94
  }
×
95
}
5✔
96
/* eslint-enable complexity */
1✔
97

1✔
98
function Source<SourceT extends ISource>(props: SourceProps<SourceT>) {
11✔
99
  const map = useContext(MapContext).map.getMap();
11✔
100
  const propsRef = useRef(props);
11✔
101
  const [, setStyleLoaded] = useState(0);
11✔
102

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

11✔
105
  useEffect(() => {
11✔
106
    if (map) {
2✔
107
      /* global setTimeout */
2✔
108
      const forceUpdate = () => setTimeout(() => setStyleLoaded(version => version + 1), 0);
2✔
109
      map.on('styledata', forceUpdate);
2✔
110
      forceUpdate();
2✔
111

2✔
112
      return () => {
2✔
113
        map.off('styledata', forceUpdate);
2✔
114
        // @ts-ignore
2✔
115
        if (map.style && map.style._loaded && map.getSource(id)) {
2✔
116
          // Parent effects are destroyed before child ones, see
2✔
117
          // https://github.com/facebook/react/issues/16728
2✔
118
          // Source can only be removed after all child layers are removed
2✔
119
          const allLayers = map.getStyle()?.layers;
2!
120
          if (allLayers) {
2✔
121
            for (const layer of allLayers) {
2✔
122
              // @ts-ignore (2339) source does not exist on all layer types
1✔
123
              if (layer.source === id) {
1✔
124
                map.removeLayer(layer.id);
1✔
125
              }
1✔
126
            }
1✔
127
          }
2✔
128
          map.removeSource(id);
2✔
129
        }
2✔
130
      };
2✔
131
    }
2✔
132
    return undefined;
×
133
  }, [map]);
11✔
134

11✔
135
  // @ts-ignore
11✔
136
  let source = map && map.style && map.getSource(id);
11✔
137
  if (source) {
11✔
138
    updateSource(source, props, propsRef.current);
5✔
139
  } else {
11✔
140
    source = createSource(map, id, props);
6✔
141
  }
6✔
142
  propsRef.current = props;
11✔
143

11✔
144
  return (
11✔
145
    (source &&
11✔
146
      React.Children.map(
9✔
147
        props.children,
9✔
148
        child =>
9✔
149
          child &&
5✔
150
          cloneElement(child, {
5✔
151
            source: id
5✔
152
          })
5✔
153
      )) ||
11✔
154
    null
6✔
155
  );
11✔
156
}
11✔
157

1✔
158
export default Source;
1✔
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