@211la/search-react 0.3.6 → 0.4.0
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/index.js +70 -98
- package/dist/types/Map.d.ts +19 -16
- package/dist/types/index.d.ts +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import React__default, { useState,
|
|
2
|
+
import React__default, { useRef, useMemo, useState, useCallback, useEffect } from 'react';
|
|
3
3
|
import { connectRefinementList, connectHits } from 'react-instantsearch-dom';
|
|
4
4
|
import { createConnector } from 'react-instantsearch-core';
|
|
5
|
-
import { GoogleApiWrapper,
|
|
5
|
+
import { GoogleApiWrapper, Map as Map$1, Marker, InfoWindow } from 'google-maps-react';
|
|
6
6
|
import PlacesAutocomplete, { geocodeByAddress, getLatLng } from 'react-places-autocomplete';
|
|
7
7
|
|
|
8
8
|
var trim = function (prefix, suffix, text) {
|
|
@@ -197,78 +197,6 @@ var connectSearchBoxFields = createConnector({
|
|
|
197
197
|
},
|
|
198
198
|
});
|
|
199
199
|
|
|
200
|
-
var groupBy = function (list, fn) {
|
|
201
|
-
// @ts-ignore
|
|
202
|
-
var buckets = {};
|
|
203
|
-
list.forEach(function (resource) {
|
|
204
|
-
var key = fn(resource);
|
|
205
|
-
if (!buckets[key]) {
|
|
206
|
-
buckets[key] = [];
|
|
207
|
-
}
|
|
208
|
-
buckets[key].push(resource);
|
|
209
|
-
});
|
|
210
|
-
return Object.keys(buckets).map(function (key) { return buckets[key]; });
|
|
211
|
-
};
|
|
212
|
-
var Map = function (props) {
|
|
213
|
-
var grouped = groupBy(props.hits, function (resource) { return resource.lat + "_" + resource.lng; }).map(function (resources) {
|
|
214
|
-
var hits = resources.map(function (resource) { return resource.hit; });
|
|
215
|
-
var _a = resources[0], lat = _a.lat, lng = _a.lng;
|
|
216
|
-
return { hits: hits, lat: lat, lng: lng, key: lat + "_" + lng };
|
|
217
|
-
});
|
|
218
|
-
var _a = useState(null), infoWindowContent = _a[0], setInfoWindowContent = _a[1];
|
|
219
|
-
// @ts-ignore
|
|
220
|
-
var makeInfoWindowSetter = function (hitGroup) {
|
|
221
|
-
return function (props, marker) {
|
|
222
|
-
if (!marker) {
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
setInfoWindowContent({
|
|
226
|
-
marker: marker,
|
|
227
|
-
hitGroup: hitGroup,
|
|
228
|
-
});
|
|
229
|
-
};
|
|
230
|
-
};
|
|
231
|
-
var closeInfoWindow = function () { return setInfoWindowContent(null); };
|
|
232
|
-
var UserInfoWindow = props.infoWindow;
|
|
233
|
-
var infoWindow = infoWindowContent && UserInfoWindow && (
|
|
234
|
-
// @ts-ignore
|
|
235
|
-
React.createElement(InfoWindow, { visible: true, google: props.google,
|
|
236
|
-
// @ts-ignore
|
|
237
|
-
onClose: closeInfoWindow, marker: infoWindowContent.marker },
|
|
238
|
-
React.createElement(UserInfoWindow, { hitGroup: infoWindowContent.hitGroup })));
|
|
239
|
-
var markers = grouped.map(function (resources) {
|
|
240
|
-
var key = resources.key, lat = resources.lat, lng = resources.lng;
|
|
241
|
-
return (
|
|
242
|
-
// @ts-ignore
|
|
243
|
-
React.createElement(Marker, { key: key, position: { lat: lat, lng: lng }, onClick: makeInfoWindowSetter(resources) }, ' '));
|
|
244
|
-
});
|
|
245
|
-
var mapRef = useRef(null);
|
|
246
|
-
var groupKey = grouped
|
|
247
|
-
.map(function (item) { return item.key; })
|
|
248
|
-
.sort(function (a, b) { return a.localeCompare(b); })
|
|
249
|
-
.join(';');
|
|
250
|
-
useEffect(function () {
|
|
251
|
-
if (mapRef.current === null) {
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
// data has changed. closing the window.
|
|
255
|
-
setInfoWindowContent(null);
|
|
256
|
-
// @ts-ignore
|
|
257
|
-
var bounds = new google.maps.LatLngBounds();
|
|
258
|
-
grouped.forEach(function (group) {
|
|
259
|
-
// @ts-ignore
|
|
260
|
-
bounds.extend(new google.maps.LatLng(group.lat, group.lng));
|
|
261
|
-
});
|
|
262
|
-
// @ts-ignore
|
|
263
|
-
mapRef.current.map.fitBounds(bounds);
|
|
264
|
-
}, [mapRef, groupKey]);
|
|
265
|
-
return (React.createElement(Map$1, { ref: mapRef, google: props.google, disableDefaultUI: props.disableDefaultUI },
|
|
266
|
-
markers,
|
|
267
|
-
infoWindow));
|
|
268
|
-
};
|
|
269
|
-
Map.defaultProps = {
|
|
270
|
-
disableDefaultUI: false,
|
|
271
|
-
};
|
|
272
200
|
var ifStringToInt = function (v) {
|
|
273
201
|
switch (typeof v) {
|
|
274
202
|
case 'string':
|
|
@@ -279,34 +207,78 @@ var ifStringToInt = function (v) {
|
|
|
279
207
|
return null;
|
|
280
208
|
}
|
|
281
209
|
};
|
|
282
|
-
|
|
210
|
+
function transform(hits, transformer) {
|
|
283
211
|
return hits
|
|
284
|
-
.
|
|
285
|
-
.
|
|
286
|
-
return
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
var defaultMapFunc = function (hit) {
|
|
291
|
-
return (hit.site.addresses || []).map(function (address) {
|
|
292
|
-
return {
|
|
293
|
-
lat: address.latitude,
|
|
294
|
-
lng: address.longitude,
|
|
295
|
-
hit: __assign(__assign({}, hit), { site: __assign(__assign({}, hit.site), { addresses: [address] }) }),
|
|
296
|
-
};
|
|
212
|
+
.map(transformer)
|
|
213
|
+
.filter(function (entry) {
|
|
214
|
+
return entry !== null &&
|
|
215
|
+
entry !== undefined &&
|
|
216
|
+
entry.lat !== null &&
|
|
217
|
+
entry.lng !== null;
|
|
297
218
|
});
|
|
219
|
+
}
|
|
220
|
+
var defaultTransformer = function (hit) {
|
|
221
|
+
if (!hit.addresses || hit.addresses.length === 0) {
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
var address = hit.addresses[0];
|
|
225
|
+
return {
|
|
226
|
+
lat: ifStringToInt(address.latitude),
|
|
227
|
+
lng: ifStringToInt(address.longitude),
|
|
228
|
+
hit: hit,
|
|
229
|
+
};
|
|
230
|
+
};
|
|
231
|
+
var Map = function (props) {
|
|
232
|
+
var mapRef = useRef(null);
|
|
233
|
+
var markers = useMemo(function () { return transform(props.hits, props.transformMarkers || defaultTransformer); }, [props.hits, props.transformMarkers]);
|
|
234
|
+
var _a = useState(null), selectedMarker = _a[0], setSelectedMarker = _a[1];
|
|
235
|
+
var handleMarkerClick = useCallback(function (marker, hit) {
|
|
236
|
+
if (props.onMarkerClick) {
|
|
237
|
+
props.onMarkerClick(hit);
|
|
238
|
+
}
|
|
239
|
+
setSelectedMarker({
|
|
240
|
+
marker: marker,
|
|
241
|
+
hit: hit,
|
|
242
|
+
});
|
|
243
|
+
}, [props.onMarkerClick, setSelectedMarker]);
|
|
244
|
+
var UserInfoWindow = props.infoWindow;
|
|
245
|
+
useEffect(function () {
|
|
246
|
+
if (mapRef.current === null) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
// Markers updated. Close the current window.
|
|
250
|
+
setSelectedMarker(null);
|
|
251
|
+
// Update bounds of the map
|
|
252
|
+
var bounds = markers.reduce(
|
|
253
|
+
//
|
|
254
|
+
function (bounds, marker) {
|
|
255
|
+
bounds.extend(new google.maps.LatLng(marker.lat, marker.lng));
|
|
256
|
+
return bounds;
|
|
257
|
+
}, new google.maps.LatLngBounds());
|
|
258
|
+
mapRef.current.map.fitBounds(bounds);
|
|
259
|
+
}, [mapRef, markers]);
|
|
260
|
+
return (React__default.createElement(Map$1, { ref: mapRef, google: props.google, disableDefaultUI: props.disableDefaultUI },
|
|
261
|
+
markers.map(function (data) { return (React__default.createElement(Marker, { key: data.hit.id, position: { lat: data.lat, lng: data.lng }, onClick: function (_, marker) {
|
|
262
|
+
if (marker) {
|
|
263
|
+
handleMarkerClick(marker, data.hit);
|
|
264
|
+
}
|
|
265
|
+
} })); }),
|
|
266
|
+
!!selectedMarker && !!UserInfoWindow && (React__default.createElement(InfoWindow, { map: mapRef.current.map, visible: true, google: props.google, marker: selectedMarker.marker },
|
|
267
|
+
React__default.createElement(UserInfoWindow, { hit: selectedMarker.hit })))));
|
|
298
268
|
};
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
269
|
+
/**
|
|
270
|
+
* Creates a map component to display search results on a map.
|
|
271
|
+
*
|
|
272
|
+
* @param apiKey Google Maps API key
|
|
273
|
+
* @param options Options to customize the map
|
|
274
|
+
*/
|
|
275
|
+
var connectMap = function (apiKey) {
|
|
276
|
+
var Renderer = GoogleApiWrapper({
|
|
303
277
|
apiKey: apiKey,
|
|
304
278
|
})(function (props) {
|
|
305
|
-
|
|
306
|
-
return React.createElement(Map, { google: props.google, hits: hits, infoWindow: infoWindow, disableDefaultUI: disableDefaultUI || false });
|
|
279
|
+
return (React__default.createElement(Map, { google: props.google, hits: props.hits, infoWindow: props === null || props === void 0 ? void 0 : props.infoWindow, disableDefaultUI: (props === null || props === void 0 ? void 0 : props.disableDefaultUI) || true, transformMarkers: props === null || props === void 0 ? void 0 : props.transformMarkers, onMarkerClick: props === null || props === void 0 ? void 0 : props.onMarkerClick }));
|
|
307
280
|
});
|
|
308
|
-
|
|
309
|
-
return connectHits(Elem);
|
|
281
|
+
return connectHits(Renderer);
|
|
310
282
|
};
|
|
311
283
|
|
|
312
284
|
/**
|
|
@@ -477,7 +449,7 @@ var connectTaxonomyRefinementList = createConnector({
|
|
|
477
449
|
var TaxonomyRefinementList = connectTaxonomyRefinementList(function (_a) {
|
|
478
450
|
var items = _a.items, refine = _a.refine;
|
|
479
451
|
return (React__default.createElement("div", { className: "ais-RefinementList" },
|
|
480
|
-
React__default.createElement("ul", { className: "ais-RefinementList-list" }, items.map(function (item) { return (React__default.createElement("li", { className: "ais-RefinementList-item" },
|
|
452
|
+
React__default.createElement("ul", { className: "ais-RefinementList-list" }, items.map(function (item) { return (React__default.createElement("li", { key: item.value, className: "ais-RefinementList-item" },
|
|
481
453
|
React__default.createElement("label", { className: "ais-RefinementList-label" },
|
|
482
454
|
React__default.createElement("input", { className: "ais-RefinementList-checkbox", type: "checkbox", value: item.value, onChange: function () {
|
|
483
455
|
refine(item.value);
|
|
@@ -485,4 +457,4 @@ var TaxonomyRefinementList = connectTaxonomyRefinementList(function (_a) {
|
|
|
485
457
|
React__default.createElement("span", { className: "ais-RefinementList-labelText" }, item.label))); }))));
|
|
486
458
|
});
|
|
487
459
|
|
|
488
|
-
export { ExactNumberFieldSearch, ExactStringFieldSearch, LocationDistanceFilter, PlaceAutocomplete, SearchBoxFields, StringFieldSearch, TaxonomyRefinementList, connectExactNumberFieldSearch, connectExactStringFieldSearch, connectGeolocation, connectResources, connectSearchBoxFields, connectStringFieldSearch, connectTaxonomyRefinementList, makeConnectFieldSearch
|
|
460
|
+
export { ExactNumberFieldSearch, ExactStringFieldSearch, LocationDistanceFilter, PlaceAutocomplete, SearchBoxFields, StringFieldSearch, TaxonomyRefinementList, connectExactNumberFieldSearch, connectExactStringFieldSearch, connectGeolocation, connectMap, connectResources, connectSearchBoxFields, connectStringFieldSearch, connectTaxonomyRefinementList, makeConnectFieldSearch };
|
package/dist/types/Map.d.ts
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { IndexedResource } from '@211la/search-client';
|
|
3
|
+
import type { Hit, HitsProvided } from 'react-instantsearch-core';
|
|
4
|
+
export declare type MarkerData = {
|
|
4
5
|
lat: number;
|
|
5
6
|
lng: number;
|
|
6
|
-
|
|
7
|
+
} & {
|
|
8
|
+
hit: Hit<IndexedResource>;
|
|
7
9
|
};
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
declare type LatLng = {
|
|
12
|
-
lat: number;
|
|
13
|
-
lng: number;
|
|
14
|
-
};
|
|
15
|
-
export declare type MakeMapOptions = {
|
|
16
|
-
mapFunc?: <T>(hit: any) => T[];
|
|
17
|
-
infoWindow?: React.ComponentType<InfoWindowProps>;
|
|
10
|
+
interface ConnectedMapProps extends HitsProvided<IndexedResource> {
|
|
11
|
+
google: any;
|
|
12
|
+
infoWindow?: any;
|
|
18
13
|
disableDefaultUI?: boolean;
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
transformMarkers?: any;
|
|
15
|
+
onMarkerClick?: any;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Creates a map component to display search results on a map.
|
|
19
|
+
*
|
|
20
|
+
* @param apiKey Google Maps API key
|
|
21
|
+
* @param options Options to customize the map
|
|
22
|
+
*/
|
|
23
|
+
export declare const connectMap: (apiKey: string) => React.ComponentClass<Omit<ConnectedMapProps, 'google' | 'hits'>>;
|
|
21
24
|
export {};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { makeConnectFieldSearch, connectExactStringFieldSearch, connectExactNumb
|
|
|
2
2
|
export { connectGeolocation } from './connectGeolocation';
|
|
3
3
|
export { connectResources } from './connectResources';
|
|
4
4
|
export { connectSearchBoxFields } from './connectSearchBoxFields';
|
|
5
|
-
export {
|
|
5
|
+
export { connectMap, MarkerData } from './Map';
|
|
6
6
|
export { LocationDistanceFilter } from './LocationDistanceFilter';
|
|
7
7
|
export { PlaceAutocomplete } from './PlaceAutocomplete';
|
|
8
8
|
export { SearchBoxFields } from './SearchBoxFields';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@211la/search-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/types/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"typescript": "^4.0.5"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"@211la/search-client": "^0.3.
|
|
36
|
+
"@211la/search-client": "^0.3.8",
|
|
37
37
|
"react": ">=16.8.0",
|
|
38
38
|
"react-dom": ">=16.8.0",
|
|
39
39
|
"react-instantsearch-core": ">=6.11.1",
|