mirror of
https://github.com/maputnik/editor.git
synced 2025-12-26 08:00:01 +00:00
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.8.3 to 5.9.2. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/microsoft/TypeScript/releases">typescript's releases</a>.</em></p> <blockquote> <h2>TypeScript 5.9</h2> <p>Release notes pending.</p> <!-- raw HTML omitted --> <ul> <li><a href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=milestone%3A%22TypeScript+5.9.0%22+is%3Aclosed+">fixed issues query for Typescript 5.9.0 (Beta)</a>.</li> <li><a href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=milestone%3A%22TypeScript+5.9.1%22+is%3Aclosed+">fixed issues query for Typescript 5.9.1 (RC)</a>.</li> <li>[[No specific changes for TypeScript 5.9.2 (Stable)]]</li> </ul> <p>Downloads are available on:</p> <ul> <li><a href="https://www.npmjs.com/package/typescript">npm</a></li> </ul> <h2>TypeScript 5.9 RC</h2> <p>For release notes, check out the <a href="https://devblogs.microsoft.com/typescript/announcing-typescript-5-9-rc/">release announcement</a></p> <ul> <li><a href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=milestone%3A%22TypeScript+5.9.0%22+is%3Aclosed+">fixed issues query for Typescript 5.9.0 (Beta)</a>.</li> <li><a href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=milestone%3A%22TypeScript+5.9.1%22+is%3Aclosed+">fixed issues query for Typescript 5.9.1 (RC)</a>.</li> </ul> <p>Downloads are available on:</p> <ul> <li><a href="https://www.npmjs.com/package/typescript">npm</a></li> </ul> <h2>TypeScript 5.9 Beta</h2> <p>For release notes, check out the <a href="https://devblogs.microsoft.com/typescript/announcing-typescript-5-9-beta/">release announcement</a>.</p> <ul> <li><a href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=milestone%3A%22TypeScript+5.9.0%22+is%3Aclosed+">fixed issues query for Typescript 5.9.0 (Beta)</a>.</li> </ul> <p>Downloads are available on:</p> <ul> <li><a href="https://www.npmjs.com/package/typescript">npm</a></li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="be86783155"><code>be86783</code></a> Give more specific errors for <code>verbatimModuleSyntax</code> (<a href="https://redirect.github.com/microsoft/TypeScript/issues/62113">#62113</a>)</li> <li><a href="22ef57786f"><code>22ef577</code></a> LEGO: Pull request from lego/hb_5378966c-b857-470a-8675-daebef4a6da1_20250714...</li> <li><a href="d5a414cd1d"><code>d5a414c</code></a> Don't use <code>noErrorTruncation</code> when printing types with <code>maximumLength</code> set (#...</li> <li><a href="f14b5c8a2f"><code>f14b5c8</code></a> Remove unused and confusing dom.iterable.d.ts file (<a href="https://redirect.github.com/microsoft/TypeScript/issues/62037">#62037</a>)</li> <li><a href="2778e84ed8"><code>2778e84</code></a> Restore AbortSignal.abort (<a href="https://redirect.github.com/microsoft/TypeScript/issues/62086">#62086</a>)</li> <li><a href="65cb4bd2d5"><code>65cb4bd</code></a> LEGO: Pull request from lego/hb_5378966c-b857-470a-8675-daebef4a6da1_20250710...</li> <li><a href="9e20e032ef"><code>9e20e03</code></a> Clear out checker-level stacks on pop (<a href="https://redirect.github.com/microsoft/TypeScript/issues/62016">#62016</a>)</li> <li><a href="87740bc7fe"><code>87740bc</code></a> Fix for Issue 61081 (<a href="https://redirect.github.com/microsoft/TypeScript/issues/61221">#61221</a>)</li> <li><a href="833a8d492c"><code>833a8d4</code></a> Fix Symbol completion priority and cursor positioning (<a href="https://redirect.github.com/microsoft/TypeScript/issues/61945">#61945</a>)</li> <li><a href="0018c9ff12"><code>0018c9f</code></a> LEGO: Pull request from lego/hb_5378966c-b857-470a-8675-daebef4a6da1_20250702...</li> <li>Additional commits viewable in <a href="https://github.com/microsoft/TypeScript/compare/v5.8.3...v5.9.2">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) You can trigger a rebase of this PR by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> > **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Harel M <harel.mazor@gmail.com>
305 lines
9.7 KiB
TypeScript
305 lines
9.7 KiB
TypeScript
import React from "react";
|
|
import {createRoot} from "react-dom/client";
|
|
import MapLibreGl, {type LayerSpecification, type LngLat, type Map, type MapOptions, type SourceSpecification, type StyleSpecification} from "maplibre-gl";
|
|
import MaplibreInspect from "@maplibre/maplibre-gl-inspect";
|
|
import colors from "@maplibre/maplibre-gl-inspect/lib/colors";
|
|
import MapMaplibreGlLayerPopup from "./MapMaplibreGlLayerPopup";
|
|
import MapMaplibreGlFeaturePropertyPopup, { type InspectFeature } from "./MapMaplibreGlFeaturePropertyPopup";
|
|
import Color from "color";
|
|
import ZoomControl from "../libs/zoomcontrol";
|
|
import { type HighlightedLayer, colorHighlightedLayer } from "../libs/highlight";
|
|
import "maplibre-gl/dist/maplibre-gl.css";
|
|
import "../maplibregl.css";
|
|
import "../libs/maplibre-rtl";
|
|
import MaplibreGeocoder, { type MaplibreGeocoderApi, type MaplibreGeocoderApiConfig } from "@maplibre/maplibre-gl-geocoder";
|
|
import "@maplibre/maplibre-gl-geocoder/dist/maplibre-gl-geocoder.css";
|
|
import { withTranslation, type WithTranslation } from "react-i18next";
|
|
import i18next from "i18next";
|
|
import { Protocol } from "pmtiles";
|
|
|
|
function buildInspectStyle(originalMapStyle: StyleSpecification, coloredLayers: HighlightedLayer[], highlightedLayer?: HighlightedLayer) {
|
|
const backgroundLayer = {
|
|
"id": "background",
|
|
"type": "background",
|
|
"paint": {
|
|
"background-color": "#1c1f24",
|
|
}
|
|
} as LayerSpecification;
|
|
|
|
const layer = colorHighlightedLayer(highlightedLayer);
|
|
if(layer) {
|
|
coloredLayers.push(layer);
|
|
}
|
|
|
|
const sources: {[key:string]: SourceSpecification} = {};
|
|
|
|
Object.keys(originalMapStyle.sources).forEach(sourceId => {
|
|
const source = originalMapStyle.sources[sourceId];
|
|
if(source.type !== "raster" && source.type !== "raster-dem") {
|
|
sources[sourceId] = source;
|
|
}
|
|
});
|
|
|
|
const inspectStyle = {
|
|
...originalMapStyle,
|
|
sources: sources,
|
|
layers: [backgroundLayer].concat(coloredLayers as LayerSpecification[])
|
|
};
|
|
return inspectStyle;
|
|
}
|
|
|
|
type MapMaplibreGlInternalProps = {
|
|
onDataChange?(event: {map: Map | null}): unknown
|
|
onLayerSelect(index: number): void
|
|
mapStyle: StyleSpecification
|
|
inspectModeEnabled: boolean
|
|
highlightedLayer?: HighlightedLayer
|
|
options?: Partial<MapOptions> & {
|
|
showTileBoundaries?: boolean
|
|
showCollisionBoxes?: boolean
|
|
showOverdrawInspector?: boolean
|
|
}
|
|
replaceAccessTokens(mapStyle: StyleSpecification): StyleSpecification
|
|
onChange(value: {center: LngLat, zoom: number}): unknown
|
|
} & WithTranslation;
|
|
|
|
type MapMaplibreGlState = {
|
|
map: Map | null;
|
|
inspect: MaplibreInspect | null;
|
|
geocoder: MaplibreGeocoder | null;
|
|
zoomControl: ZoomControl | null;
|
|
zoom?: number;
|
|
};
|
|
|
|
class MapMaplibreGlInternal extends React.Component<MapMaplibreGlInternalProps, MapMaplibreGlState> {
|
|
static defaultProps = {
|
|
onMapLoaded: () => {},
|
|
onDataChange: () => {},
|
|
onLayerSelect: () => {},
|
|
onChange: () => {},
|
|
options: {} as MapOptions,
|
|
};
|
|
container: HTMLDivElement | null = null;
|
|
|
|
constructor(props: MapMaplibreGlInternalProps) {
|
|
super(props);
|
|
this.state = {
|
|
map: null,
|
|
inspect: null,
|
|
geocoder: null,
|
|
zoomControl: null,
|
|
};
|
|
i18next.on("languageChanged", () => {
|
|
this.forceUpdate();
|
|
});
|
|
}
|
|
|
|
|
|
shouldComponentUpdate(nextProps: MapMaplibreGlInternalProps, nextState: MapMaplibreGlState) {
|
|
let should = false;
|
|
try {
|
|
should = JSON.stringify(this.props) !== JSON.stringify(nextProps) || JSON.stringify(this.state) !== JSON.stringify(nextState);
|
|
} catch(_e) {
|
|
// no biggie, carry on
|
|
}
|
|
return should;
|
|
}
|
|
|
|
componentDidUpdate() {
|
|
const map = this.state.map;
|
|
|
|
const styleWithTokens = this.props.replaceAccessTokens(this.props.mapStyle);
|
|
if (map) {
|
|
// Maplibre GL now does diffing natively so we don't need to calculate
|
|
// the necessary operations ourselves!
|
|
// We also need to update the style for inspect to work properly
|
|
map.setStyle(styleWithTokens, {diff: true});
|
|
map.showTileBoundaries = this.props.options?.showTileBoundaries!;
|
|
map.showCollisionBoxes = this.props.options?.showCollisionBoxes!;
|
|
map.showOverdrawInspector = this.props.options?.showOverdrawInspector!;
|
|
}
|
|
|
|
if(this.state.inspect && this.props.inspectModeEnabled !== this.state.inspect._showInspectMap) {
|
|
this.state.inspect.toggleInspector();
|
|
}
|
|
if (this.state.inspect && this.props.inspectModeEnabled) {
|
|
this.state.inspect.setOriginalStyle(styleWithTokens);
|
|
// In case the sources are the same, there's a need to refresh the style
|
|
setTimeout(() => {
|
|
this.state.inspect!.render();
|
|
}, 500);
|
|
}
|
|
|
|
}
|
|
|
|
componentDidMount() {
|
|
const mapOpts = {
|
|
...this.props.options,
|
|
container: this.container!,
|
|
style: this.props.mapStyle,
|
|
hash: true,
|
|
maxZoom: 24,
|
|
// setting to always load glyphs of CJK fonts from server
|
|
// https://maplibre.org/maplibre-gl-js/docs/examples/local-ideographs/
|
|
localIdeographFontFamily: false
|
|
} satisfies MapOptions;
|
|
|
|
const protocol = new Protocol({metadata: true});
|
|
MapLibreGl.addProtocol("pmtiles",protocol.tile);
|
|
const map = new MapLibreGl.Map(mapOpts);
|
|
|
|
const mapViewChange = () => {
|
|
const center = map.getCenter();
|
|
const zoom = map.getZoom();
|
|
this.props.onChange({center, zoom});
|
|
};
|
|
mapViewChange();
|
|
|
|
map.showTileBoundaries = mapOpts.showTileBoundaries!;
|
|
map.showCollisionBoxes = mapOpts.showCollisionBoxes!;
|
|
map.showOverdrawInspector = mapOpts.showOverdrawInspector!;
|
|
|
|
const geocoder = this.initGeocoder(map);
|
|
|
|
const zoomControl = new ZoomControl();
|
|
map.addControl(zoomControl, "top-right");
|
|
|
|
const nav = new MapLibreGl.NavigationControl({visualizePitch:true});
|
|
map.addControl(nav, "top-right");
|
|
|
|
const tmpNode = document.createElement("div");
|
|
const root = createRoot(tmpNode);
|
|
|
|
const inspectPopup = new MapLibreGl.Popup({
|
|
closeOnClick: false
|
|
});
|
|
|
|
const inspect = new MaplibreInspect({
|
|
popup: inspectPopup,
|
|
showMapPopup: true,
|
|
showMapPopupOnHover: false,
|
|
showInspectMapPopupOnHover: true,
|
|
showInspectButton: false,
|
|
blockHoverPopupOnClick: true,
|
|
assignLayerColor: (layerId: string, alpha: number) => {
|
|
return Color(colors.brightColor(layerId, alpha)).desaturate(0.5).string();
|
|
},
|
|
buildInspectStyle: (originalMapStyle: StyleSpecification, coloredLayers: HighlightedLayer[]) => buildInspectStyle(originalMapStyle, coloredLayers, this.props.highlightedLayer),
|
|
renderPopup: (features: InspectFeature[]) => {
|
|
if(this.props.inspectModeEnabled) {
|
|
inspectPopup.once("open", () => {
|
|
root.render(<MapMaplibreGlFeaturePropertyPopup features={features} />);
|
|
});
|
|
return tmpNode;
|
|
} else {
|
|
inspectPopup.once("open", () => {
|
|
root.render(<MapMaplibreGlLayerPopup
|
|
features={features}
|
|
onLayerSelect={this.onLayerSelectById}
|
|
zoom={this.state.zoom}
|
|
/>,);
|
|
});
|
|
return tmpNode;
|
|
}
|
|
}
|
|
});
|
|
map.addControl(inspect);
|
|
|
|
map.on("style.load", () => {
|
|
this.setState({
|
|
map,
|
|
inspect,
|
|
geocoder,
|
|
zoomControl,
|
|
zoom: map.getZoom()
|
|
});
|
|
});
|
|
|
|
map.on("data", e => {
|
|
if(e.dataType !== "tile") return;
|
|
this.props.onDataChange!({
|
|
map: this.state.map
|
|
});
|
|
});
|
|
|
|
map.on("error", e => {
|
|
console.log("ERROR", e);
|
|
});
|
|
|
|
map.on("zoom", _e => {
|
|
this.setState({
|
|
zoom: map.getZoom()
|
|
});
|
|
});
|
|
|
|
map.on("dragend", mapViewChange);
|
|
map.on("zoomend", mapViewChange);
|
|
}
|
|
|
|
onLayerSelectById = (id: string) => {
|
|
const index = this.props.mapStyle.layers.findIndex(layer => layer.id === id);
|
|
this.props.onLayerSelect(index);
|
|
};
|
|
|
|
initGeocoder(map: Map) {
|
|
const geocoderConfig = {
|
|
forwardGeocode: async (config: MaplibreGeocoderApiConfig) => {
|
|
const features = [];
|
|
try {
|
|
const request = `https://nominatim.openstreetmap.org/search?q=${config.query}&format=geojson&polygon_geojson=1&addressdetails=1`;
|
|
const response = await fetch(request);
|
|
const geojson = await response.json();
|
|
for (const feature of geojson.features) {
|
|
const center = [
|
|
feature.bbox[0] +
|
|
(feature.bbox[2] - feature.bbox[0]) / 2,
|
|
feature.bbox[1] +
|
|
(feature.bbox[3] - feature.bbox[1]) / 2
|
|
];
|
|
const point = {
|
|
type: "Feature",
|
|
geometry: {
|
|
type: "Point",
|
|
coordinates: center
|
|
},
|
|
place_name: feature.properties.display_name,
|
|
properties: feature.properties,
|
|
text: feature.properties.display_name,
|
|
place_type: ["place"],
|
|
center
|
|
};
|
|
features.push(point);
|
|
}
|
|
} catch (e) {
|
|
console.error(`Failed to forwardGeocode with error: ${e}`);
|
|
}
|
|
return {
|
|
features
|
|
};
|
|
},
|
|
} as unknown as MaplibreGeocoderApi;
|
|
const geocoder = new MaplibreGeocoder(geocoderConfig, {
|
|
placeholder: this.props.t("Search"),
|
|
maplibregl: MapLibreGl,
|
|
});
|
|
map.addControl(geocoder, "top-left");
|
|
return geocoder;
|
|
}
|
|
|
|
render() {
|
|
const t = this.props.t;
|
|
this.state.geocoder?.setPlaceholder(t("Search"));
|
|
this.state.zoomControl?.setLabel(t("Zoom:"));
|
|
return <div
|
|
className="maputnik-map__map"
|
|
role="region"
|
|
aria-label={t("Map view")}
|
|
ref={x => {this.container = x;}}
|
|
data-wd-key="maplibre:map"
|
|
></div>;
|
|
}
|
|
}
|
|
|
|
const MapMaplibreGl = withTranslation()(MapMaplibreGlInternal);
|
|
export default MapMaplibreGl;
|