@pnp/spfx-controls-react
Version:
Reusable React controls for SharePoint Framework solutions
204 lines • 11.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MaplibreWorldMap = void 0;
var tslib_1 = require("tslib");
/* eslint-disable @typescript-eslint/explicit-function-return-type */
/* eslint-disable @typescript-eslint/no-floating-promises */
require("maplibre-gl/dist/maplibre-gl.css");
var maplibre_1 = tslib_1.__importDefault(require("react-map-gl/maplibre"));
var react_1 = tslib_1.__importStar(require("react"));
var react_components_1 = require("@fluentui/react-components");
var MapNavigation_1 = tslib_1.__importDefault(require("./MapNavigation"));
var Marker_1 = tslib_1.__importDefault(require("./Marker"));
var css_1 = require("@emotion/css");
var ControlStrings_1 = tslib_1.__importDefault(require("ControlStrings"));
var useCleanMapStyle_1 = require("./useCleanMapStyle");
var MULTI_STYLE_URLS = {
satellite: function (key) {
return "https://api.maptiler.com/maps/satellite/style.json?key=".concat(key);
},
streets: function (key) {
return "https://api.maptiler.com/maps/streets/style.json?key=".concat(key);
},
topo: function (key) {
return "https://api.maptiler.com/maps/topo-v2/style.json?key=".concat(key);
},
demo: "https://demotiles.maplibre.org/style.json", // Free demo style (no key required)
};
var useStyles = function () { return ({
container: (0, css_1.css)({
padding: '20px',
}),
mapContainer: (0, css_1.css)({
position: 'relative',
marginTop: '20px',
}),
searchOverlay: (0, css_1.css)({
position: 'absolute',
zIndex: 1000,
maxWidth: '300px',
padding: '8px',
}),
searchResults: (0, css_1.css)({
marginTop: '4px',
fontSize: '12px',
color: '#666',
}),
}); };
/**
* Main Maplibre world map component.
* expects each data to already include a `coordinates: [lon, lat]` tuple.
*/
var MaplibreWorldMap = function (_a) {
var data = _a.data, onClick = _a.onClick, mapStyleUrl = _a.mapStyleUrl, mapKey = _a.mapKey, style = _a.style, _b = _a.fitPadding, fitPadding = _b === void 0 ? 20 : _b, theme = _a.theme, marker = _a.marker, title = _a.title, search = _a.search;
var mapRef = (0, react_1.useRef)(null);
var styles = useStyles();
// Determine the final map style URL based on provided props
var finalMapStyleUrl = (0, react_1.useMemo)(function () {
// If user provides both mapKey and mapStyleUrl, use the mapStyleUrl as-is (assuming it already includes the key)
if (mapKey && mapStyleUrl) {
// Check if the URL already contains a key parameter
if (mapStyleUrl.includes('?key=') || mapStyleUrl.includes('&key=')) {
return mapStyleUrl;
}
else {
// Add the key to the URL
var separator = mapStyleUrl.includes('?') ? '&' : '?';
return "".concat(mapStyleUrl).concat(separator, "key=").concat(mapKey);
}
}
// If only mapKey is provided, use the default streets style with the user's key
if (mapKey && !mapStyleUrl) {
return MULTI_STYLE_URLS.streets(mapKey);
}
// If only mapStyleUrl is provided, use it as-is
if (!mapKey && mapStyleUrl) {
return mapStyleUrl;
}
// If neither is provided, use the demo style (no key required)
return MULTI_STYLE_URLS.demo;
}, [mapKey, mapStyleUrl]);
var cleanStyle = (0, useCleanMapStyle_1.useCleanMapStyle)(finalMapStyleUrl);
var _c = (0, react_1.useState)(''), searchTerm = _c[0], setSearchTerm = _c[1];
var _d = (0, react_1.useState)(data), filteredData = _d[0], setFilteredData = _d[1];
var initialViewState = (0, react_1.useState)({ longitude: 0, latitude: 20, zoom: 1 })[0];
// Search configuration with defaults
var searchConfig = (0, react_1.useMemo)(function () {
var _a, _b, _c, _d;
return (tslib_1.__assign({ enabled: (_a = search === null || search === void 0 ? void 0 : search.enabled) !== null && _a !== void 0 ? _a : true, placeholder: (_b = search === null || search === void 0 ? void 0 : search.placeholder) !== null && _b !== void 0 ? _b : ControlStrings_1.default.worldMapSearchLocations, searchField: (_c = search === null || search === void 0 ? void 0 : search.searchField) !== null && _c !== void 0 ? _c : ControlStrings_1.default.worldMapSearchField, zoomLevel: (_d = search === null || search === void 0 ? void 0 : search.zoomLevel) !== null && _d !== void 0 ? _d : 8, position: tslib_1.__assign({ top: '10px', left: '10px' }, search === null || search === void 0 ? void 0 : search.position) }, search));
}, [search]);
// Reset to initial view when search is cleared
var resetToInitialView = (0, react_1.useCallback)(function () {
if (mapRef.current) {
if (data.length > 0) {
// Fit to all data
var lons = data.map(function (c) { return c.coordinates[0]; });
var lats = data.map(function (c) { return c.coordinates[1]; });
mapRef.current.getMap().fitBounds([
[Math.min.apply(Math, lons), Math.min.apply(Math, lats)],
[Math.max.apply(Math, lons), Math.max.apply(Math, lats)],
], { padding: fitPadding, duration: 1000 });
}
else {
// Reset to initial view state
mapRef.current.getMap().flyTo({
center: [initialViewState.longitude, initialViewState.latitude],
zoom: initialViewState.zoom,
duration: 1000,
});
}
}
}, [data, fitPadding, initialViewState]);
// Filter data based on search term
var handleSearch = (0, react_1.useCallback)(function (term) {
var _a, _b;
setSearchTerm(term);
if (!term.trim()) {
setFilteredData(data);
(_a = search === null || search === void 0 ? void 0 : search.onSearchChange) === null || _a === void 0 ? void 0 : _a.call(search, term, data);
resetToInitialView();
return;
}
var filtered = data.filter(function (item) {
var searchValue = typeof searchConfig.searchField === 'function'
? searchConfig.searchField(item)
: item[searchConfig.searchField];
return searchValue === null || searchValue === void 0 ? void 0 : searchValue.toLowerCase().includes(term.toLowerCase());
});
setFilteredData(filtered);
(_b = search === null || search === void 0 ? void 0 : search.onSearchChange) === null || _b === void 0 ? void 0 : _b.call(search, term, filtered);
// Auto-zoom to first result
if (filtered.length > 0 && mapRef.current) {
var firstResult = filtered[0];
mapRef.current.getMap().flyTo({
center: firstResult.coordinates,
zoom: searchConfig.zoomLevel,
duration: 1000,
});
}
}, [data, search, searchConfig, resetToInitialView]);
// Handle search clear
var handleSearchClear = (0, react_1.useCallback)(function () {
var _a;
setSearchTerm('');
setFilteredData(data);
(_a = search === null || search === void 0 ? void 0 : search.onSearchChange) === null || _a === void 0 ? void 0 : _a.call(search, '', data);
resetToInitialView();
}, [data, search, resetToInitialView]);
// Update filtered data when data prop changes
(0, react_1.useEffect)(function () {
if (!searchTerm.trim()) {
setFilteredData(data);
}
else {
handleSearch(searchTerm);
}
}, [data, searchTerm, handleSearch]);
var defaultMapStyles = (0, react_1.useMemo)(function () { return ({
width: '100%',
height: '600px',
fontFamily: theme === null || theme === void 0 ? void 0 : theme.fontFamilyBase,
paddingTop: '20px',
paddingBottom: '20px',
}); }, [theme]);
// Fit map to loaded markers
(0, react_1.useEffect)(function () {
if (!mapRef.current || filteredData.length === 0)
return;
var lons = filteredData.map(function (c) { return c.coordinates[0]; });
var lats = filteredData.map(function (c) { return c.coordinates[1]; });
mapRef.current.getMap().fitBounds([
[Math.min.apply(Math, lons), Math.min.apply(Math, lats)],
[Math.max.apply(Math, lons), Math.max.apply(Math, lats)],
], { padding: fitPadding });
}, [filteredData, fitPadding]);
if (!cleanStyle) {
return react_1.default.createElement(react_components_1.Text, null, ControlStrings_1.default.worldMapLoadintText);
}
return (react_1.default.createElement("div", { className: styles.container },
react_1.default.createElement(react_components_1.Subtitle1, null, title !== null && title !== void 0 ? title : ControlStrings_1.default.worldMapTitle),
react_1.default.createElement("div", { className: styles.mapContainer },
react_1.default.createElement(maplibre_1.default, { ref: mapRef, initialViewState: { longitude: 0, latitude: 20, zoom: 1 }, style: tslib_1.__assign({}, (style !== null && style !== void 0 ? style : defaultMapStyles)), mapStyle: cleanStyle, pixelRatio: window.devicePixelRatio },
react_1.default.createElement(MapNavigation_1.default, { mapRef: mapRef, initialViewState: { longitude: 0, latitude: 20, zoom: 1 } }),
filteredData.map(function (dataItem) { return (react_1.default.createElement(Marker_1.default, tslib_1.__assign({ key: dataItem.id, data: dataItem, onClick: function (e) { return onClick === null || onClick === void 0 ? void 0 : onClick(dataItem); } }, marker))); })),
searchConfig.enabled && (react_1.default.createElement("div", { className: styles.searchOverlay, style: {
top: searchConfig.position.top,
left: searchConfig.position.left,
right: searchConfig.position.right,
bottom: searchConfig.position.bottom,
} },
react_1.default.createElement(react_components_1.SearchBox, { placeholder: searchConfig.placeholder, value: searchTerm, onChange: function (_, data) { return handleSearch((data === null || data === void 0 ? void 0 : data.value) || ''); }, dismiss: {
onClick: handleSearchClear,
}, size: "medium", style: { width: '100%', minWidth: '250px' } }),
searchTerm && (react_1.default.createElement("div", { className: styles.searchResults },
filteredData.length,
' ',
filteredData.length === 1
? ControlStrings_1.default.worldMapLocationLabel
: ControlStrings_1.default.worldMapLocationPluralLabel,
' ',
ControlStrings_1.default.worldMapFoundLabel)))))));
};
exports.MaplibreWorldMap = MaplibreWorldMap;
exports.default = exports.MaplibreWorldMap;
//# sourceMappingURL=WorldMapControl.js.map