radar-sdk-js 4.2.1-beta.2 → 4.3.0-beta.1

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.
package/dist/radar.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"radar.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"radar.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/types.d.ts CHANGED
@@ -344,15 +344,20 @@ export interface RadarSearchGeofencesParams {
344
344
  export interface RadarSearchGeofencesResponse extends RadarResponse {
345
345
  geofences: RadarGeofence[];
346
346
  }
347
- export interface RadarMapOptions extends maplibregl.MapOptions {
348
- container: string | HTMLElement;
347
+ export interface RadarMapOptions extends Omit<maplibregl.MapOptions, 'transformRequest'> {
348
+ languages?: string[];
349
+ navigatorFallbackLanguage?: string;
350
+ }
351
+ export interface RadarMarkerImage {
352
+ url?: string;
353
+ radarMarkerId?: string;
354
+ width?: number;
355
+ height?: number;
349
356
  }
350
- export interface RadarMarkerOptions {
351
- color?: string;
357
+ export interface RadarMarkerOptions extends maplibregl.MarkerOptions {
352
358
  text?: string;
353
359
  html?: string;
354
- element?: HTMLElement;
355
- scale?: number;
360
+ image?: RadarMarkerImage;
356
361
  }
357
362
  export interface RadarAutocompleteUIOptions {
358
363
  container: string | HTMLElement;
@@ -0,0 +1,6 @@
1
+ declare class RadarLogoControl {
2
+ link: HTMLAnchorElement | undefined;
3
+ onAdd(): HTMLAnchorElement;
4
+ onRemove(): void;
5
+ }
6
+ export default RadarLogoControl;
@@ -0,0 +1,11 @@
1
+ import maplibregl from 'maplibre-gl';
2
+ import RadarMarker from './RadarMarker';
3
+ import type { RadarMapOptions } from '../types';
4
+ declare class RadarMap extends maplibregl.Map {
5
+ _markers: RadarMarker[];
6
+ constructor(mapOptions: RadarMapOptions);
7
+ addMarker(marker: RadarMarker): void;
8
+ removeMarker(marker: RadarMarker): void;
9
+ getMarkers(): RadarMarker[];
10
+ }
11
+ export default RadarMap;
@@ -0,0 +1,11 @@
1
+ import maplibregl from 'maplibre-gl';
2
+ import type RadarMap from './RadarMap';
3
+ import type { RadarMarkerImage, RadarMarkerOptions } from '../types';
4
+ declare class RadarMarker extends maplibregl.Marker {
5
+ _map: RadarMap;
6
+ _image?: RadarMarkerImage;
7
+ constructor(markerOptions: RadarMarkerOptions);
8
+ addTo(map: RadarMap): this;
9
+ remove(): this;
10
+ }
11
+ export default RadarMarker;
package/dist/ui/map.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  /// <reference types="mapbox__point-geometry" />
2
+ import RadarMap from './RadarMap';
3
+ import RadarMarker from './RadarMarker';
2
4
  import type { RadarMapOptions, RadarMarkerOptions } from '../types';
3
5
  declare class MapUI {
4
6
  static getMapLibre(): {
@@ -45,7 +47,7 @@ declare class MapUI {
45
47
  addProtocol(customProtocol: string, loadFn: (requestParameters: import("maplibre-gl").RequestParameters, callback: import("maplibre-gl").ResponseCallback<any>) => import("maplibre-gl").Cancelable): void;
46
48
  removeProtocol(customProtocol: string): void;
47
49
  };
48
- static createMap(mapOptions: RadarMapOptions): maplibregl.Map;
49
- static createMarker(markerOptions?: RadarMarkerOptions): maplibregl.Marker;
50
+ static createMap(mapOptions: RadarMapOptions): RadarMap;
51
+ static createMarker(markerOptions?: RadarMarkerOptions): RadarMarker;
50
52
  }
51
53
  export default MapUI;
@@ -0,0 +1,2 @@
1
+ export declare const deepEqual: (obj1: any, obj2: any) => boolean;
2
+ export declare const uniq: <T extends unknown>(arr: T[]) => T[];
@@ -0,0 +1,2 @@
1
+ import { RadarMapOptions } from '../types';
2
+ export declare const transformMapStyle: (styleJSON: any, options: Pick<RadarMapOptions, 'languages' | 'navigatorFallbackLanguage'>) => any;
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- declare const _default: "4.2.1-beta.2";
1
+ declare const _default: "4.3.0-beta.1";
2
2
  export default _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "radar-sdk-js",
3
- "version": "4.2.1-beta.2",
3
+ "version": "4.3.0-beta.1",
4
4
  "description": "Web Javascript SDK for Radar, location infrastructure for mobile and web apps.",
5
5
  "homepage": "https://radar.com",
6
6
  "type": "module",
package/src/api/track.ts CHANGED
@@ -137,14 +137,14 @@ class TrackAPI {
137
137
  }),
138
138
  };
139
139
 
140
- const reqToken = await signJWT(payload, dk);
140
+ const token = await signJWT(payload, dk);
141
141
 
142
142
  response = await Http.request({
143
143
  host,
144
144
  method: 'POST',
145
145
  path: 'track',
146
146
  data: {
147
- token: reqToken,
147
+ token,
148
148
  },
149
149
  headers: {
150
150
  'X-Radar-Body-Is-Token': 'true',
@@ -160,33 +160,33 @@ class TrackAPI {
160
160
  sclVal,
161
161
  cslVal,
162
162
  };
163
- }
164
163
 
165
- let { user, events, token, expiresAt } = response;
166
- const location = { latitude, longitude, accuracy };
167
- let passed;
168
- let expiresIn;
169
- if (expiresAt) {
170
- expiresAt = new Date(expiresAt);
171
- passed = user?.fraud?.passed && user?.country?.passed && user?.state?.passed;
172
- expiresIn = (expiresAt.getTime() - Date.now()) / 1000;
173
- }
164
+ let { user, events, token, expiresAt } = response;
165
+ const location = { latitude, longitude, accuracy };
166
+ let passed;
167
+ let expiresIn;
168
+ if (expiresAt) {
169
+ expiresAt = new Date(expiresAt);
170
+ passed = user?.fraud?.passed && user?.country?.passed && user?.state?.passed;
171
+ expiresIn = (expiresAt.getTime() - Date.now()) / 1000;
172
+ }
174
173
 
175
- const trackRes = {
176
- user,
177
- events,
178
- location,
179
- token,
180
- expiresAt,
181
- expiresIn,
182
- passed,
183
- } as RadarTrackVerifiedResponse;
184
-
185
- if (options.debug) {
186
- trackRes.response = response;
187
- }
174
+ const trackRes = {
175
+ user,
176
+ events,
177
+ location,
178
+ token,
179
+ expiresAt,
180
+ expiresIn,
181
+ passed,
182
+ } as RadarTrackVerifiedResponse;
183
+
184
+ if (options.debug) {
185
+ trackRes.response = response;
186
+ }
188
187
 
189
- return trackRes;
188
+ return trackRes;
189
+ }
190
190
  }
191
191
 
192
192
  response = await Http.request({
package/src/http.ts CHANGED
@@ -31,13 +31,17 @@ class Http {
31
31
  path,
32
32
  data,
33
33
  host,
34
- headers,
34
+ version,
35
+ headers = {},
36
+ responseType,
35
37
  }: {
36
38
  method: HttpMethod;
37
39
  path: string;
38
40
  data?: any;
39
41
  host?: string;
42
+ version?: string;
40
43
  headers?: Record<string, string>;
44
+ responseType?: XMLHttpRequestResponseType;
41
45
  }) {
42
46
  return new Promise<HttpResponse>((resolve, reject) => {
43
47
  const options = Config.get();
@@ -51,8 +55,8 @@ class Http {
51
55
 
52
56
  // setup request URL
53
57
  const urlHost = host || options.host;
54
- const version = options.version;
55
- let url = `${urlHost}/${version}/${path}`;
58
+ const urlVersion = version || options.version;
59
+ let url = `${urlHost}/${urlVersion}/${path}`;
56
60
 
57
61
  // remove undefined values from request data
58
62
  let body: any = {};
@@ -78,32 +82,39 @@ class Http {
78
82
  const xhr = new XMLHttpRequest();
79
83
  xhr.open(method, url, true);
80
84
 
81
- // set standard headers
82
- xhr.setRequestHeader('Authorization', publishableKey);
83
- xhr.setRequestHeader('Content-Type', 'application/json');
84
- xhr.setRequestHeader('X-Radar-Device-Type', 'Web');
85
- xhr.setRequestHeader('X-Radar-SDK-Version', SDK_VERSION);
86
-
87
- // set passed custom headers if present
88
- if (headers) {
89
- Object.keys(headers).forEach(key => {
90
- const val = headers[key];
91
- xhr.setRequestHeader(key, val);
92
- });
93
- }
85
+ const defaultHeaders = {
86
+ 'Authorization': publishableKey,
87
+ 'Content-Type': 'application/json',
88
+ 'X-Radar-Device-Type': 'Web',
89
+ 'X-Radar-SDK-Version': SDK_VERSION,
90
+ };
94
91
 
95
- // set config custom headers if present
92
+ // set custom config headers if present
93
+ let configHeaders: { [key: string]: string } = {};
96
94
  if (typeof options.getRequestHeaders === 'function') {
97
- const headers: { [key: string]: string } = options.getRequestHeaders();
98
- Object.keys(headers || {}).forEach((key) => {
99
- xhr.setRequestHeader(key, headers[key]);
100
- });
95
+ configHeaders = options.getRequestHeaders();
96
+ }
97
+
98
+ // combines default headers with custom headers and config headers
99
+ const allHeaders = Object.assign(defaultHeaders, configHeaders, headers);
100
+
101
+ // set headers
102
+ Object.keys(allHeaders).forEach((key) => {
103
+ xhr.setRequestHeader(key, allHeaders[key]);
104
+ });
105
+
106
+ if (responseType) {
107
+ xhr.responseType = responseType;
101
108
  }
102
109
 
103
110
  xhr.onload = () => {
104
111
  let response: any;
105
112
  try {
106
- response = JSON.parse(xhr.response);
113
+ if (xhr.responseType === 'blob') {
114
+ response = { code: xhr.status, data: xhr.response };
115
+ } else {
116
+ response = JSON.parse(xhr.response);
117
+ }
107
118
  } catch (e) {
108
119
  return reject(new RadarServerError(response));
109
120
  }
@@ -152,7 +163,7 @@ class Http {
152
163
  }
153
164
  }
154
165
 
155
- xhr.onerror = function() {
166
+ xhr.onerror = function () {
156
167
  if (host && (host === 'http://localhost:52516' || host === 'https://radar-verify.com:52516')) {
157
168
  reject(new RadarVerifyAppError());
158
169
  } else {
@@ -160,7 +171,7 @@ class Http {
160
171
  }
161
172
  }
162
173
 
163
- xhr.ontimeout = function() {
174
+ xhr.ontimeout = function () {
164
175
  reject(new RadarVerifyAppError());
165
176
  }
166
177
 
package/src/types.ts CHANGED
@@ -459,16 +459,22 @@ export interface RadarSearchGeofencesResponse extends RadarResponse {
459
459
  geofences: RadarGeofence[];
460
460
  }
461
461
 
462
- export interface RadarMapOptions extends maplibregl.MapOptions {
463
- container: string | HTMLElement;
462
+ export interface RadarMapOptions extends Omit<maplibregl.MapOptions, 'transformRequest'> {
463
+ languages?: string[];
464
+ navigatorFallbackLanguage?: string;
465
+ }
466
+
467
+ export interface RadarMarkerImage {
468
+ url?: string;
469
+ radarMarkerId?: string;
470
+ width?: number;
471
+ height?: number;
464
472
  }
465
473
 
466
- export interface RadarMarkerOptions {
467
- color?: string;
474
+ export interface RadarMarkerOptions extends maplibregl.MarkerOptions {
468
475
  text?: string;
469
476
  html?: string;
470
- element?: HTMLElement;
471
- scale?: number;
477
+ image?: RadarMarkerImage;
472
478
  }
473
479
 
474
480
  export interface RadarAutocompleteUIOptions {
@@ -0,0 +1,24 @@
1
+ const RADAR_LOGO_URL = 'https://api.radar.io/maps/static/images/logo.svg';
2
+
3
+ class RadarLogoControl {
4
+ link: HTMLAnchorElement | undefined;
5
+
6
+ onAdd() {
7
+ const img = document.createElement('img');
8
+ img.src = RADAR_LOGO_URL;
9
+
10
+ this.link = document.createElement('a');
11
+ this.link.id = 'radar-map-logo';
12
+ this.link.href = 'https://radar.com?ref=powered_by_radar';
13
+ this.link.target = '_blank';
14
+ this.link.appendChild(img);
15
+
16
+ return this.link;
17
+ }
18
+
19
+ onRemove() {
20
+ this.link?.remove();
21
+ }
22
+ }
23
+
24
+ export default RadarLogoControl;
@@ -0,0 +1,155 @@
1
+ import maplibregl from 'maplibre-gl';
2
+
3
+ import RadarMarker from './RadarMarker';
4
+ import RadarLogoControl from './RadarLogoControl';
5
+
6
+ import Config from '../config';
7
+ import Logger from '../logger';
8
+ import SDK_VERSION from '../version';
9
+
10
+ import { transformMapStyle } from '../util/mapStyle';
11
+
12
+ import type { RadarOptions, RadarMapOptions } from '../types';
13
+
14
+ const DEFAULT_STYLE = 'radar-default-v1';
15
+
16
+ const RADAR_STYLES = [
17
+ 'radar-default-v1',
18
+ 'radar-light-v1',
19
+ 'radar-dark-v1',
20
+ ];
21
+
22
+ const defaultMapOptions: Partial<RadarMapOptions> = {
23
+ minZoom: 1,
24
+ maxZoom: 20,
25
+ attributionControl: false,
26
+ dragRotate: false,
27
+ touchPitch: false,
28
+ maplibreLogo: false,
29
+ navigatorFallbackLanguage: 'en',
30
+ };
31
+
32
+ const createStyleURL = (options: RadarOptions, style: string = DEFAULT_STYLE) => (
33
+ `${options.host}/maps/styles/${style}?publishableKey=${options.publishableKey}`
34
+ );
35
+
36
+ // check if style is a Radar style or a custom style
37
+ const isRadarStyle = (style: string) => {
38
+ if (RADAR_STYLES.includes(style)) { // Radar built-in style
39
+ return true;
40
+ }
41
+ if (!/^(http:|https:)/.test(style)) { // Radar custom style (not a URL)
42
+ return true;
43
+ }
44
+ return false;
45
+ };
46
+
47
+ // use formatted style URL if using one of Radar's out-of-the-box styles or is a Radar custom style
48
+ const getStyle = (options: RadarOptions, mapOptions: RadarMapOptions) => {
49
+ const style = mapOptions.style;
50
+
51
+ if (!style || (typeof style === 'string' && isRadarStyle(style))) {
52
+ return createStyleURL(options, style);
53
+ }
54
+
55
+ return mapOptions.style; // style object or URL
56
+ };
57
+
58
+ class RadarMap extends maplibregl.Map {
59
+ _markers: RadarMarker[] = [];
60
+
61
+ constructor(mapOptions: RadarMapOptions) {
62
+ const config = Config.get();
63
+
64
+ if (!config.publishableKey) {
65
+ Logger.warn('publishableKey not set. Call Radar.initialize() with key before creating a new map.');
66
+ }
67
+
68
+ // configure maplibre options
69
+ const style = getStyle(config, mapOptions);
70
+ const maplibreOptions: RadarMapOptions = Object.assign({},
71
+ defaultMapOptions,
72
+ mapOptions,
73
+ { style },
74
+ );
75
+ Logger.debug(`initialize map with options: ${JSON.stringify(maplibreOptions)}`);
76
+
77
+ (maplibreOptions as maplibregl.MapOptions).transformRequest = (url, resourceType) => {
78
+ if (resourceType === 'Style' && isRadarStyle(url)) {
79
+ url = createStyleURL(config, url);
80
+ }
81
+
82
+ let headers = {
83
+ 'Authorization': config.publishableKey,
84
+ 'X-Radar-Device-Type': 'Web',
85
+ 'X-Radar-SDK-Version': SDK_VERSION,
86
+ };
87
+ if (typeof config.getRequestHeaders === 'function') {
88
+ headers = Object.assign(headers, config.getRequestHeaders());
89
+ }
90
+
91
+ return { url, headers };
92
+ };
93
+
94
+ super(maplibreOptions);
95
+
96
+ const container = this.getContainer();
97
+ if (!container.style.width && !container.style.height) {
98
+ Logger.warn('map container does not have a set "width" or "height"');
99
+ }
100
+
101
+ // add radar logo
102
+ const radarLogo = new RadarLogoControl();
103
+ this.addControl(radarLogo, 'bottom-left');
104
+
105
+ // add attribution
106
+ const attribution = new maplibregl.AttributionControl({ compact: false });
107
+ this.addControl(attribution, 'bottom-right');
108
+
109
+ // add zoom controls
110
+ const nav = new maplibregl.NavigationControl({ showCompass: false });
111
+ this.addControl(nav, 'bottom-right');
112
+
113
+ // handle map resize actions
114
+ const onResize = () => {
115
+ const attrib = document.querySelector('.maplibregl-ctrl-attrib');
116
+ if (attrib) {
117
+ const width = this.getContainer().clientWidth;
118
+ if (width < 380) {
119
+ attrib.classList.add('hidden');
120
+ } else {
121
+ attrib.classList.remove('hidden');
122
+ }
123
+ }
124
+ };
125
+
126
+ const onStyleLoad = (e: maplibregl.MapStyleDataEvent) => {
127
+ const styleJSON = (e as any).style?.stylesheet; // for some reason, style does not exist in the types
128
+ if (!styleJSON) {
129
+ Logger.warn('style data not available');
130
+ return;
131
+ }
132
+
133
+ // transform text-field expressions to use local language
134
+ const newStyleJSON = transformMapStyle(styleJSON, maplibreOptions);
135
+ this.setStyle(newStyleJSON);
136
+ };
137
+ this.on('resize', onResize);
138
+ this.on('load', onResize);
139
+ this.on('styledata', onStyleLoad);
140
+ }
141
+
142
+ addMarker(marker: RadarMarker) {
143
+ this._markers.push(marker);
144
+ }
145
+
146
+ removeMarker(marker: RadarMarker) {
147
+ this._markers = this._markers.filter((mapMarker: RadarMarker) => mapMarker !== marker);
148
+ }
149
+
150
+ getMarkers(): RadarMarker[] {
151
+ return this._markers;
152
+ }
153
+ };
154
+
155
+ export default RadarMap;
@@ -0,0 +1,126 @@
1
+ import maplibregl from 'maplibre-gl';
2
+
3
+ import Http from '../http';
4
+ import Logger from '../logger';
5
+
6
+ import type RadarMap from './RadarMap';
7
+
8
+ import type { RadarMarkerImage, RadarMarkerOptions } from '../types';
9
+
10
+ const defaultMarkerOptions: maplibregl.MarkerOptions = {
11
+ color: '#000257',
12
+ };
13
+
14
+ const fileExtensionToContentType: Record<string, string> = {
15
+ svg: 'image/svg+xml',
16
+ png: 'image/png',
17
+ };
18
+
19
+ const getFileExtension = (file: string): string => {
20
+ return file.split('.').pop() || '';
21
+ }
22
+
23
+ const createImageElement = (options: RadarMarkerImage) => {
24
+ const element = document.createElement('img');
25
+ element.src = options.url!;
26
+
27
+ if (options.width) {
28
+ element.width = options.width;
29
+ }
30
+ if (options.height) {
31
+ element.height = options.height;
32
+ }
33
+ if (!options.width && !options.height) {
34
+ element.style.maxWidth = '64px';
35
+ element.style.maxHeight = '64px';
36
+ }
37
+ return element;
38
+ }
39
+ class RadarMarker extends maplibregl.Marker {
40
+ _map!: RadarMap;
41
+ _image?: RadarMarkerImage;
42
+
43
+ constructor(markerOptions: RadarMarkerOptions) {
44
+ const maplibreOptions: maplibregl.MarkerOptions = Object.assign({}, defaultMarkerOptions);
45
+
46
+ if (markerOptions.color) {
47
+ maplibreOptions.color = markerOptions.color;
48
+ }
49
+ if (markerOptions.element) {
50
+ maplibreOptions.element = markerOptions.element;
51
+ }
52
+ if (markerOptions.scale) {
53
+ maplibreOptions.scale = markerOptions.scale;
54
+ }
55
+
56
+ super(maplibreOptions);
57
+
58
+ if (markerOptions.image) {
59
+ this._image = markerOptions.image;
60
+
61
+ const originalElement = this._element.cloneNode(true);
62
+ this._element.childNodes.forEach((child) => {
63
+ child.remove();
64
+ });
65
+
66
+ const onSuccess = (blob: Blob) => {
67
+ const markerObject = URL.createObjectURL(blob);
68
+ this._element.replaceChildren(createImageElement({ url: markerObject }));
69
+ };
70
+
71
+ const onError = (err: any) => {
72
+ Logger.error(`Could not load marker: ${err.message} - falling back to default marker`);
73
+ this._element.replaceChildren(...Array.from(originalElement.childNodes));
74
+ }
75
+
76
+ if (markerOptions.image.url) {
77
+ fetch(markerOptions.image.url)
78
+ .then(res => {
79
+ if (res.status === 200) {
80
+ res.blob()
81
+ .then(onSuccess)
82
+ .catch(onError);
83
+ } else {
84
+ onError(new Error(res.statusText));
85
+ }
86
+ })
87
+ .catch(onError)
88
+ }
89
+
90
+ if (markerOptions.image.radarMarkerId) {
91
+ // fetch custom marker
92
+ Http.request({
93
+ method: 'GET',
94
+ version: 'maps',
95
+ path: `markers/${markerOptions.image.radarMarkerId}`,
96
+ responseType: 'blob',
97
+ })
98
+ .then(({ data }) => onSuccess(data))
99
+ .catch(onError);
100
+ }
101
+ }
102
+
103
+ // set popup text or HTML
104
+ if (markerOptions.text) {
105
+ const popup = new maplibregl.Popup({ offset: 35 }).setText(markerOptions.text);
106
+ this.setPopup(popup);
107
+ } else if (markerOptions.html) {
108
+ const popup = new maplibregl.Popup({ offset: 35 }).setHTML(markerOptions.html);
109
+ this.setPopup(popup);
110
+ }
111
+ }
112
+
113
+ addTo(map: RadarMap) {
114
+ map.addMarker(this);
115
+ return super.addTo(map);
116
+ }
117
+
118
+ remove() {
119
+ if (this._map) {
120
+ this._map.removeMarker(this);
121
+ }
122
+ return super.remove();
123
+ }
124
+ }
125
+
126
+ export default RadarMarker;