@guardian/interactive-component-library 0.1.0-alpha.57 → 0.1.0-alpha.58
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.
|
@@ -3,9 +3,9 @@ import { useRef, useMemo, useId, useState, useLayoutEffect, useEffect, useCallba
|
|
|
3
3
|
import { forwardRef, createPortal } from "preact/compat";
|
|
4
4
|
import { scaleLinear as scaleLinear$1 } from "d3-scale";
|
|
5
5
|
import { toChildArray, createElement, cloneElement, createContext } from "preact";
|
|
6
|
-
import { geoStream, geoAlbers, geoPath, geoContains, geoMercator } from "d3-geo";
|
|
7
|
-
import { zoomIdentity,
|
|
8
|
-
import { namespace, matcher, selector, selectorAll, selection, style, select } from "d3-selection";
|
|
6
|
+
import { geoStream, geoAlbers, geoPath, geoContains, geoMercator, geoIdentity, geoAlbersUsa } from "d3-geo";
|
|
7
|
+
import { zoomIdentity, ZoomTransform, zoom } from "d3-zoom";
|
|
8
|
+
import { namespace, matcher, selector, selectorAll, selection, style as style$1, select } from "d3-selection";
|
|
9
9
|
const svg$9 = "_svg_b5io0_1";
|
|
10
10
|
const group = "_group_b5io0_5";
|
|
11
11
|
const rotated = "_rotated_b5io0_10";
|
|
@@ -331,9 +331,9 @@ function StackedBar({
|
|
|
331
331
|
labelType === LabelType.hanging && !hideLabels && hangingLabelConfig.map((config, i) => renderLabel(config, i))
|
|
332
332
|
] });
|
|
333
333
|
}
|
|
334
|
-
const svg$8 = "
|
|
335
|
-
const previous = "
|
|
336
|
-
const next = "
|
|
334
|
+
const svg$8 = "_svg_8bh9o_6";
|
|
335
|
+
const previous = "_previous_8bh9o_12";
|
|
336
|
+
const next = "_next_8bh9o_16";
|
|
337
337
|
const defaultStyles$u = {
|
|
338
338
|
svg: svg$8,
|
|
339
339
|
previous,
|
|
@@ -497,25 +497,27 @@ const defaultStyles$r = {
|
|
|
497
497
|
circle: circle$1,
|
|
498
498
|
pulse
|
|
499
499
|
};
|
|
500
|
-
const CircleIcon = ({ color: color2, pulse: pulse2 = false, styles: styles2 }) => {
|
|
500
|
+
const CircleIcon = ({ color: color2, pulse: pulse2 = false, diameter = 11, styles: styles2 }) => {
|
|
501
501
|
styles2 = mergeStyles(defaultStyles$r, styles2);
|
|
502
|
+
let radius = diameter / 2;
|
|
503
|
+
let padding = 2;
|
|
502
504
|
return /* @__PURE__ */ jsx(
|
|
503
505
|
"svg",
|
|
504
506
|
{
|
|
505
507
|
style: styles2.svg,
|
|
506
508
|
fill: "none",
|
|
507
|
-
height:
|
|
508
|
-
viewBox:
|
|
509
|
-
width:
|
|
509
|
+
height: diameter + padding,
|
|
510
|
+
viewBox: `0 0 ${diameter + padding} ${diameter + padding}`,
|
|
511
|
+
width: diameter + padding,
|
|
510
512
|
xmlns: "http://www.w3.org/2000/svg",
|
|
511
513
|
children: /* @__PURE__ */ jsx(
|
|
512
|
-
"
|
|
514
|
+
"circle",
|
|
513
515
|
{
|
|
514
516
|
className: [styles2.circle, pulse2 && styles2.pulse].join(" "),
|
|
515
517
|
style: { fill: color2 },
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
518
|
+
r: radius,
|
|
519
|
+
cx: radius + padding / 2,
|
|
520
|
+
cy: radius + padding / 2
|
|
519
521
|
}
|
|
520
522
|
)
|
|
521
523
|
}
|
|
@@ -1143,6 +1145,19 @@ function AdSlot({ name: name2, sizeMapping, styles: styles2 }) {
|
|
|
1143
1145
|
}
|
|
1144
1146
|
) });
|
|
1145
1147
|
}
|
|
1148
|
+
const style = {
|
|
1149
|
+
"aspect-ratio-box": "_aspect-ratio-box_1e5oy_1"
|
|
1150
|
+
};
|
|
1151
|
+
function AspectRatioBox({ heightAsProportionOfWidth, children }) {
|
|
1152
|
+
return /* @__PURE__ */ jsx(
|
|
1153
|
+
"div",
|
|
1154
|
+
{
|
|
1155
|
+
className: style["aspect-ratio-box"],
|
|
1156
|
+
style: { "--aspect-ratio": heightAsProportionOfWidth },
|
|
1157
|
+
children: /* @__PURE__ */ jsx("div", { style: { position: "absolute", width: "100%", height: "100%" }, children })
|
|
1158
|
+
}
|
|
1159
|
+
);
|
|
1160
|
+
}
|
|
1146
1161
|
const sortAscending = (accessor) => {
|
|
1147
1162
|
return (a, b) => {
|
|
1148
1163
|
const valueA = a[accessor];
|
|
@@ -2736,7 +2751,7 @@ function bboxFeature$1(bounds) {
|
|
|
2736
2751
|
};
|
|
2737
2752
|
return feature;
|
|
2738
2753
|
}
|
|
2739
|
-
const MapContext = createContext();
|
|
2754
|
+
const MapContext$1 = createContext();
|
|
2740
2755
|
function SVGMapProvider({
|
|
2741
2756
|
id: id2,
|
|
2742
2757
|
mapRef,
|
|
@@ -2815,20 +2830,20 @@ function SVGMapProvider({
|
|
|
2815
2830
|
findFeatureAtPoint
|
|
2816
2831
|
};
|
|
2817
2832
|
mapRef.current = context;
|
|
2818
|
-
return /* @__PURE__ */ jsx(MapContext.Provider, { value: context, children });
|
|
2833
|
+
return /* @__PURE__ */ jsx(MapContext$1.Provider, { value: context, children });
|
|
2819
2834
|
}
|
|
2820
2835
|
const path = "_path_1cwd5_9";
|
|
2821
2836
|
const defaultStyles$1 = {
|
|
2822
2837
|
path
|
|
2823
2838
|
};
|
|
2824
2839
|
function CompositionBorders({ styles: styles2 }) {
|
|
2825
|
-
const context = useContext(MapContext);
|
|
2840
|
+
const context = useContext(MapContext$1);
|
|
2826
2841
|
const { projection } = context;
|
|
2827
2842
|
styles2 = mergeStyles(defaultStyles$1, styles2);
|
|
2828
2843
|
return /* @__PURE__ */ jsx("path", { className: styles2.path, d: projection.getCompositionBorders() });
|
|
2829
2844
|
}
|
|
2830
2845
|
function SVGRenderer({ children }) {
|
|
2831
|
-
const { id: id2, config, size, selectedFeature, padding } = useContext(MapContext);
|
|
2846
|
+
const { id: id2, config, size, selectedFeature, padding } = useContext(MapContext$1);
|
|
2832
2847
|
return /* @__PURE__ */ jsx(
|
|
2833
2848
|
"svg",
|
|
2834
2849
|
{
|
|
@@ -3266,7 +3281,7 @@ function Polygon$1({
|
|
|
3266
3281
|
zIndex = 0,
|
|
3267
3282
|
styles: styles2
|
|
3268
3283
|
}) {
|
|
3269
|
-
const context = useContext(MapContext);
|
|
3284
|
+
const context = useContext(MapContext$1);
|
|
3270
3285
|
const [searchIndex, setSearchIndex] = useState();
|
|
3271
3286
|
useEffect(() => {
|
|
3272
3287
|
if (!context.path) return;
|
|
@@ -3324,7 +3339,7 @@ function Polygon$1({
|
|
|
3324
3339
|
}) });
|
|
3325
3340
|
}
|
|
3326
3341
|
function Line({ id: id2, features, stroke = null, strokeWidth = 1, styles: styles2 }) {
|
|
3327
|
-
const context = useContext(MapContext);
|
|
3342
|
+
const context = useContext(MapContext$1);
|
|
3328
3343
|
const draw = (ctx, path2) => {
|
|
3329
3344
|
for (const feature of features) {
|
|
3330
3345
|
ctx.beginPath();
|
|
@@ -3365,7 +3380,7 @@ function Line({ id: id2, features, stroke = null, strokeWidth = 1, styles: style
|
|
|
3365
3380
|
}) });
|
|
3366
3381
|
}
|
|
3367
3382
|
function Prerendered({ url }) {
|
|
3368
|
-
const context = useContext(MapContext);
|
|
3383
|
+
const context = useContext(MapContext$1);
|
|
3369
3384
|
const { width, height } = context.contentSize;
|
|
3370
3385
|
return /* @__PURE__ */ jsx("image", { width, height, href: url });
|
|
3371
3386
|
}
|
|
@@ -3379,7 +3394,7 @@ function Point$1({
|
|
|
3379
3394
|
zIndex = 0,
|
|
3380
3395
|
styles: styles2
|
|
3381
3396
|
}) {
|
|
3382
|
-
const context = useContext(MapContext);
|
|
3397
|
+
const context = useContext(MapContext$1);
|
|
3383
3398
|
useEffect(() => {
|
|
3384
3399
|
function findFeatureAtPoint(point) {
|
|
3385
3400
|
for (const [index, feature] of features.entries()) {
|
|
@@ -3597,6 +3612,254 @@ function sizeForElement(element) {
|
|
|
3597
3612
|
}
|
|
3598
3613
|
return size;
|
|
3599
3614
|
}
|
|
3615
|
+
function bboxFeature(bounds) {
|
|
3616
|
+
const minLon = bounds[0][0];
|
|
3617
|
+
const minLat = bounds[0][1];
|
|
3618
|
+
const maxLon = bounds[1][0];
|
|
3619
|
+
const maxLat = bounds[1][1];
|
|
3620
|
+
const feature = {
|
|
3621
|
+
type: "Feature",
|
|
3622
|
+
properties: {},
|
|
3623
|
+
geometry: {
|
|
3624
|
+
coordinates: [
|
|
3625
|
+
[
|
|
3626
|
+
[minLon, maxLat],
|
|
3627
|
+
[maxLon, maxLat],
|
|
3628
|
+
[maxLon, minLat],
|
|
3629
|
+
[minLon, minLat],
|
|
3630
|
+
[minLon, maxLat]
|
|
3631
|
+
]
|
|
3632
|
+
],
|
|
3633
|
+
type: "Polygon"
|
|
3634
|
+
}
|
|
3635
|
+
};
|
|
3636
|
+
return feature;
|
|
3637
|
+
}
|
|
3638
|
+
const BASE_RESOLUTION = 156543.03392;
|
|
3639
|
+
function zoomLevelToZoomScale(zoomLevel, initialResolution) {
|
|
3640
|
+
const resolution = BASE_RESOLUTION / Math.pow(2, zoomLevel);
|
|
3641
|
+
const zoomScale = initialResolution / resolution;
|
|
3642
|
+
return zoomScale;
|
|
3643
|
+
}
|
|
3644
|
+
function zoomLevelForResolution(currentResolution) {
|
|
3645
|
+
const zoomLevel = Math.log2(BASE_RESOLUTION / currentResolution);
|
|
3646
|
+
return zoomLevel;
|
|
3647
|
+
}
|
|
3648
|
+
function haversineDistance(lat1, lon1, lat2, lon2) {
|
|
3649
|
+
const R2 = 6371e3;
|
|
3650
|
+
const toRadians = (degrees2) => degrees2 * Math.PI / 180;
|
|
3651
|
+
const dLat = toRadians(lat2 - lat1);
|
|
3652
|
+
const dLon = toRadians(lon2 - lon1);
|
|
3653
|
+
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
|
|
3654
|
+
const c2 = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
3655
|
+
return R2 * c2;
|
|
3656
|
+
}
|
|
3657
|
+
function resolutionForExtent(extent, viewportSize) {
|
|
3658
|
+
const [lonMin, latMin, lonMax, latMax] = extent;
|
|
3659
|
+
const latMid = (latMin + latMax) / 2;
|
|
3660
|
+
const distance = haversineDistance(latMid, lonMin, latMid, lonMax);
|
|
3661
|
+
const resolution = distance / viewportSize[0];
|
|
3662
|
+
return resolution;
|
|
3663
|
+
}
|
|
3664
|
+
const Projection = {
|
|
3665
|
+
geoIdentity: geoIdentity(),
|
|
3666
|
+
geoMercator: geoMercator(),
|
|
3667
|
+
geoAlbersUS: geoAlbersUsa().scale(1070).translate([487.5, 305]),
|
|
3668
|
+
geoAlbersUKComposite: geoAlbersUk(),
|
|
3669
|
+
geoAlbersEngland: geoAlbers().center([0, 52.7]).rotate([1.1743, 0]).parallels([50, 54])
|
|
3670
|
+
};
|
|
3671
|
+
function validateGeometries(geometries) {
|
|
3672
|
+
if (!Array.isArray(geometries)) {
|
|
3673
|
+
throw new Error("geometries must be an array");
|
|
3674
|
+
}
|
|
3675
|
+
geometries.forEach((geometry) => {
|
|
3676
|
+
var _a;
|
|
3677
|
+
if (!geometry.type) {
|
|
3678
|
+
throw new Error("geometry must have a type");
|
|
3679
|
+
}
|
|
3680
|
+
if (!((_a = geometry.coordinates) == null ? void 0 : _a.length)) {
|
|
3681
|
+
throw new Error("geometry must have coordinates");
|
|
3682
|
+
}
|
|
3683
|
+
});
|
|
3684
|
+
}
|
|
3685
|
+
function generateDebugUrl(feature, convertToGeoJSON = true) {
|
|
3686
|
+
const featureGeoJSON = convertToGeoJSON ? feature.getGeoJSON() : feature;
|
|
3687
|
+
const featureCollection = {
|
|
3688
|
+
type: "FeatureCollection",
|
|
3689
|
+
features: [featureGeoJSON]
|
|
3690
|
+
};
|
|
3691
|
+
const jsonString = encodeURIComponent(JSON.stringify(featureCollection));
|
|
3692
|
+
return `https://geojson.io/#data=data:application/json,${jsonString}`;
|
|
3693
|
+
}
|
|
3694
|
+
class View {
|
|
3695
|
+
constructor({
|
|
3696
|
+
projection = Projection.geoIdentity,
|
|
3697
|
+
extent,
|
|
3698
|
+
minZoom = 1,
|
|
3699
|
+
maxZoom = 10,
|
|
3700
|
+
padding = { top: 0, right: 0, bottom: 0, left: 0 }
|
|
3701
|
+
}, debug = false) {
|
|
3702
|
+
this.debug = debug;
|
|
3703
|
+
projection.revision = 0;
|
|
3704
|
+
this.projection = projection;
|
|
3705
|
+
this.extent = extent;
|
|
3706
|
+
this.minZoom = minZoom;
|
|
3707
|
+
this.maxZoom = maxZoom;
|
|
3708
|
+
this._transform = zoomIdentity;
|
|
3709
|
+
this._padding = padding;
|
|
3710
|
+
this._viewPortSize = [0, 0];
|
|
3711
|
+
this.pixelRatio = window.devicePixelRatio;
|
|
3712
|
+
}
|
|
3713
|
+
set viewPortSize(size) {
|
|
3714
|
+
const previousSize = this._viewPortSize;
|
|
3715
|
+
this._viewPortSize = size;
|
|
3716
|
+
if (previousSize !== size) {
|
|
3717
|
+
if (this.extent) {
|
|
3718
|
+
this.fitExtent(this.extent);
|
|
3719
|
+
}
|
|
3720
|
+
}
|
|
3721
|
+
}
|
|
3722
|
+
get viewPortSize() {
|
|
3723
|
+
return this._viewPortSize;
|
|
3724
|
+
}
|
|
3725
|
+
set transform(transform) {
|
|
3726
|
+
this._transform = transform;
|
|
3727
|
+
}
|
|
3728
|
+
get transform() {
|
|
3729
|
+
return new ZoomTransform(
|
|
3730
|
+
this._transform.k,
|
|
3731
|
+
this._transform.x * this.pixelRatio,
|
|
3732
|
+
this._transform.y * this.pixelRatio
|
|
3733
|
+
);
|
|
3734
|
+
}
|
|
3735
|
+
// map size in pixels (i.e. scaled by device pixel ratio)
|
|
3736
|
+
get mapSize() {
|
|
3737
|
+
return scaleSize(this.viewPortSize, this.pixelRatio);
|
|
3738
|
+
}
|
|
3739
|
+
get padding() {
|
|
3740
|
+
return this._padding;
|
|
3741
|
+
}
|
|
3742
|
+
// padding in pixels (i.e. scaled by device pixel ratio)
|
|
3743
|
+
get scaledPadding() {
|
|
3744
|
+
const scaledPadding = { ...this._padding };
|
|
3745
|
+
return scalePadding(scaledPadding, this.pixelRatio);
|
|
3746
|
+
}
|
|
3747
|
+
get baseResolution() {
|
|
3748
|
+
const baseExtent = this.getVisibleExtent(zoomIdentity, this.projection);
|
|
3749
|
+
const baseResolution = resolutionForExtent(baseExtent, this.viewPortSize);
|
|
3750
|
+
return baseResolution;
|
|
3751
|
+
}
|
|
3752
|
+
// calculates the upper and lower zoom scales
|
|
3753
|
+
get scaleExtent() {
|
|
3754
|
+
const maxScale = zoomLevelToZoomScale(this.maxZoom, this.baseResolution);
|
|
3755
|
+
return [1, maxScale];
|
|
3756
|
+
}
|
|
3757
|
+
setProjection(projection) {
|
|
3758
|
+
this.projection = projection;
|
|
3759
|
+
this.fitObject(bboxFeature(this.extent));
|
|
3760
|
+
}
|
|
3761
|
+
// only set the raw projection when it has already been configured with projection.fitExtent()
|
|
3762
|
+
setRawProjection(projection) {
|
|
3763
|
+
this.projection = projection;
|
|
3764
|
+
}
|
|
3765
|
+
fitExtent(extent) {
|
|
3766
|
+
const extentFeature = bboxFeature(extent);
|
|
3767
|
+
this.fitObject(extentFeature);
|
|
3768
|
+
if (this.debug) {
|
|
3769
|
+
console.log("Fit extent", extent, generateDebugUrl(extentFeature, false));
|
|
3770
|
+
}
|
|
3771
|
+
}
|
|
3772
|
+
fitObject(geoJSON) {
|
|
3773
|
+
this.projection.fitExtent(this.getMapExtent(), geoJSON);
|
|
3774
|
+
++this.projection.revision;
|
|
3775
|
+
}
|
|
3776
|
+
// returns bounds relative to the viewport
|
|
3777
|
+
boundsForExtent(extent) {
|
|
3778
|
+
const SW = this.projection([extent[0], extent[1]]);
|
|
3779
|
+
const NE = this.projection([extent[2], extent[3]]);
|
|
3780
|
+
const minX = SW[0] / this.pixelRatio;
|
|
3781
|
+
const minY = NE[1] / this.pixelRatio;
|
|
3782
|
+
const maxX = NE[0] / this.pixelRatio;
|
|
3783
|
+
const maxY = SW[1] / this.pixelRatio;
|
|
3784
|
+
const width = maxX - minX;
|
|
3785
|
+
const height = maxY - minY;
|
|
3786
|
+
return [
|
|
3787
|
+
[minX, minY],
|
|
3788
|
+
[width, height]
|
|
3789
|
+
];
|
|
3790
|
+
}
|
|
3791
|
+
invert(point) {
|
|
3792
|
+
const { projection, pixelRatio, transform } = this.getState();
|
|
3793
|
+
const scaledPoint = [point[0] * pixelRatio, point[1] * pixelRatio];
|
|
3794
|
+
const untransformedPoint = transform.invert(scaledPoint);
|
|
3795
|
+
const mapCoordinate = projection.invert(untransformedPoint);
|
|
3796
|
+
return mapCoordinate;
|
|
3797
|
+
}
|
|
3798
|
+
// bounds is defined as [[minX, minY], [maxX, maxY]]
|
|
3799
|
+
invertBounds(bounds) {
|
|
3800
|
+
const topLeft = bounds[0];
|
|
3801
|
+
const topRight = [bounds[1][0], bounds[0][1]];
|
|
3802
|
+
const bottomRight = [bounds[1][0], bounds[1][1]];
|
|
3803
|
+
const bottomLeft = [bounds[0][0], bounds[1][1]];
|
|
3804
|
+
const points = [topLeft, topRight, bottomRight, bottomLeft, topLeft];
|
|
3805
|
+
return points.map((d2) => this.invert(d2));
|
|
3806
|
+
}
|
|
3807
|
+
// map resolution (meters per pixel)
|
|
3808
|
+
getResolution() {
|
|
3809
|
+
return resolutionForExtent(
|
|
3810
|
+
this.getVisibleExtent(this.transform, this.projection),
|
|
3811
|
+
this.viewPortSize
|
|
3812
|
+
);
|
|
3813
|
+
}
|
|
3814
|
+
// map zoom level (0 = the entire world)
|
|
3815
|
+
getZoomLevel() {
|
|
3816
|
+
return zoomLevelForResolution(this.getResolution());
|
|
3817
|
+
}
|
|
3818
|
+
//
|
|
3819
|
+
/**
|
|
3820
|
+
* Function that returns the extent of the view in screen coordinates
|
|
3821
|
+
* The extent is defined as [[minX, minY], [maxX, maxY]]
|
|
3822
|
+
* @function getMapExtent
|
|
3823
|
+
* @returns {[[number, number], [number, number]]}
|
|
3824
|
+
*/
|
|
3825
|
+
getMapExtent() {
|
|
3826
|
+
const mapSizeInPixels = this.mapSize;
|
|
3827
|
+
const paddingInPixels = this.scaledPadding;
|
|
3828
|
+
return [
|
|
3829
|
+
[paddingInPixels.left, paddingInPixels.top],
|
|
3830
|
+
sizeMinusPadding(mapSizeInPixels, {
|
|
3831
|
+
...paddingInPixels,
|
|
3832
|
+
left: 0,
|
|
3833
|
+
top: 0
|
|
3834
|
+
})
|
|
3835
|
+
];
|
|
3836
|
+
}
|
|
3837
|
+
// visible extent in map coordinates
|
|
3838
|
+
getVisibleExtent(transform, projection) {
|
|
3839
|
+
if (this.projection === Projection.geoIdentity) {
|
|
3840
|
+
const [width2, height2] = this.mapSize;
|
|
3841
|
+
return [0, 0, width2, height2];
|
|
3842
|
+
}
|
|
3843
|
+
const [width, height] = this.mapSize;
|
|
3844
|
+
const southWest = projection.invert(transform.invert([0, height]));
|
|
3845
|
+
const northEast = projection.invert(transform.invert([width, 0]));
|
|
3846
|
+
return [southWest[0], southWest[1], northEast[0], northEast[1]];
|
|
3847
|
+
}
|
|
3848
|
+
getState() {
|
|
3849
|
+
const transform = this.transform;
|
|
3850
|
+
const projection = this.projection;
|
|
3851
|
+
return {
|
|
3852
|
+
transform,
|
|
3853
|
+
projection,
|
|
3854
|
+
zoomLevel: transform.k,
|
|
3855
|
+
pixelRatio: this.pixelRatio,
|
|
3856
|
+
padding: this.padding,
|
|
3857
|
+
viewPortSize: this.viewPortSize,
|
|
3858
|
+
sizeInPixels: scaleSize(this.viewPortSize, this.pixelRatio),
|
|
3859
|
+
visibleExtent: this.getVisibleExtent(transform, projection)
|
|
3860
|
+
};
|
|
3861
|
+
}
|
|
3862
|
+
}
|
|
3600
3863
|
function arrayEquals(arr1, arr2) {
|
|
3601
3864
|
const len1 = arr1.length;
|
|
3602
3865
|
if (len1 !== arr2.length) {
|
|
@@ -5265,7 +5528,7 @@ function transition_selection() {
|
|
|
5265
5528
|
function styleNull(name2, interpolate2) {
|
|
5266
5529
|
var string00, string10, interpolate0;
|
|
5267
5530
|
return function() {
|
|
5268
|
-
var string0 = style(this, name2), string1 = (this.style.removeProperty(name2), style(this, name2));
|
|
5531
|
+
var string0 = style$1(this, name2), string1 = (this.style.removeProperty(name2), style$1(this, name2));
|
|
5269
5532
|
return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : interpolate0 = interpolate2(string00 = string0, string10 = string1);
|
|
5270
5533
|
};
|
|
5271
5534
|
}
|
|
@@ -5277,15 +5540,15 @@ function styleRemove(name2) {
|
|
|
5277
5540
|
function styleConstant(name2, interpolate2, value1) {
|
|
5278
5541
|
var string00, string1 = value1 + "", interpolate0;
|
|
5279
5542
|
return function() {
|
|
5280
|
-
var string0 = style(this, name2);
|
|
5543
|
+
var string0 = style$1(this, name2);
|
|
5281
5544
|
return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate2(string00 = string0, value1);
|
|
5282
5545
|
};
|
|
5283
5546
|
}
|
|
5284
5547
|
function styleFunction(name2, interpolate2, value) {
|
|
5285
5548
|
var string00, string10, interpolate0;
|
|
5286
5549
|
return function() {
|
|
5287
|
-
var string0 = style(this, name2), value1 = value(this), string1 = value1 + "";
|
|
5288
|
-
if (value1 == null) string1 = value1 = (this.style.removeProperty(name2), style(this, name2));
|
|
5550
|
+
var string0 = style$1(this, name2), value1 = value(this), string1 = value1 + "";
|
|
5551
|
+
if (value1 == null) string1 = value1 = (this.style.removeProperty(name2), style$1(this, name2));
|
|
5289
5552
|
return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate2(string00 = string0, value1));
|
|
5290
5553
|
};
|
|
5291
5554
|
}
|
|
@@ -5476,18 +5739,19 @@ function selection_transition(name2) {
|
|
|
5476
5739
|
selection.prototype.interrupt = selection_interrupt;
|
|
5477
5740
|
selection.prototype.transition = selection_transition;
|
|
5478
5741
|
let Map$2 = class Map2 {
|
|
5479
|
-
constructor(
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5742
|
+
constructor(config) {
|
|
5743
|
+
if (config.debug) {
|
|
5744
|
+
console.log("Map config", config);
|
|
5745
|
+
}
|
|
5746
|
+
this.options = config;
|
|
5747
|
+
this.view = new View(config.view, config.debug);
|
|
5748
|
+
this.target = config.target;
|
|
5483
5749
|
this.layers = [];
|
|
5484
5750
|
this.dispatcher = new Dispatcher(this);
|
|
5485
5751
|
this._viewport = document.createElement("div");
|
|
5486
5752
|
this._viewport.className = "gv-map";
|
|
5487
5753
|
this._viewport.style.position = "relative";
|
|
5488
5754
|
this._viewport.style.overflow = "hidden";
|
|
5489
|
-
this._viewport.style.top = 0;
|
|
5490
|
-
this._viewport.style.left = 0;
|
|
5491
5755
|
this._viewport.style.width = "100%";
|
|
5492
5756
|
this._viewport.style.height = "100%";
|
|
5493
5757
|
this.target.appendChild(this._viewport);
|
|
@@ -5497,7 +5761,7 @@ let Map$2 = class Map2 {
|
|
|
5497
5761
|
});
|
|
5498
5762
|
this._resizeObserver.observe(this.target);
|
|
5499
5763
|
this._viewport.addEventListener("touchmove", (event) => {
|
|
5500
|
-
if (event.targetTouches.length < 2 && this.
|
|
5764
|
+
if (event.targetTouches.length < 2 && this._collaborativeGesturesEnabled) {
|
|
5501
5765
|
this._filterEventCallback(true);
|
|
5502
5766
|
}
|
|
5503
5767
|
});
|
|
@@ -5520,6 +5784,10 @@ let Map$2 = class Map2 {
|
|
|
5520
5784
|
return this._isTransitioning;
|
|
5521
5785
|
}
|
|
5522
5786
|
/** PUBLIC METHODS */
|
|
5787
|
+
collaborativeGesturesEnabled(enabled) {
|
|
5788
|
+
if (enabled === void 0) return this._collaborativeGesturesEnabled;
|
|
5789
|
+
this._collaborativeGesturesEnabled = enabled;
|
|
5790
|
+
}
|
|
5523
5791
|
onFilterEvent(callback) {
|
|
5524
5792
|
this._filterEventCallback = callback;
|
|
5525
5793
|
}
|
|
@@ -5595,6 +5863,18 @@ let Map$2 = class Map2 {
|
|
|
5595
5863
|
);
|
|
5596
5864
|
select(this._viewport).transition().duration(500).call(this._zoomBehaviour.transform, newTransform, focalPoint);
|
|
5597
5865
|
}
|
|
5866
|
+
/** @param {import("./layers").Layer[]} layers */
|
|
5867
|
+
hasLayers(layers) {
|
|
5868
|
+
if (layers.length !== this.layers.length) {
|
|
5869
|
+
return false;
|
|
5870
|
+
}
|
|
5871
|
+
for (let i = 0; i < layers.length; i++) {
|
|
5872
|
+
if (layers[i] !== this.layers[i]) {
|
|
5873
|
+
return false;
|
|
5874
|
+
}
|
|
5875
|
+
}
|
|
5876
|
+
return true;
|
|
5877
|
+
}
|
|
5598
5878
|
async resetZoom(options) {
|
|
5599
5879
|
return this.zoomTo(1, options);
|
|
5600
5880
|
}
|
|
@@ -5691,201 +5971,13 @@ let Map$2 = class Map2 {
|
|
|
5691
5971
|
_renderFrame() {
|
|
5692
5972
|
const frameState = {
|
|
5693
5973
|
size: this.size,
|
|
5694
|
-
viewState: this.view.getState()
|
|
5974
|
+
viewState: this.view.getState(),
|
|
5975
|
+
debug: this.options.debug || false
|
|
5695
5976
|
};
|
|
5696
5977
|
this._renderer.renderFrame(frameState);
|
|
5697
5978
|
this._animationFrameRequestID = null;
|
|
5698
5979
|
}
|
|
5699
5980
|
};
|
|
5700
|
-
function bboxFeature(bounds) {
|
|
5701
|
-
const minLon = bounds[0][0];
|
|
5702
|
-
const minLat = bounds[0][1];
|
|
5703
|
-
const maxLon = bounds[1][0];
|
|
5704
|
-
const maxLat = bounds[1][1];
|
|
5705
|
-
const feature = {
|
|
5706
|
-
type: "Feature",
|
|
5707
|
-
properties: {},
|
|
5708
|
-
geometry: {
|
|
5709
|
-
coordinates: [
|
|
5710
|
-
[
|
|
5711
|
-
[minLon, maxLat],
|
|
5712
|
-
[maxLon, maxLat],
|
|
5713
|
-
[maxLon, minLat],
|
|
5714
|
-
[minLon, minLat],
|
|
5715
|
-
[minLon, maxLat]
|
|
5716
|
-
]
|
|
5717
|
-
],
|
|
5718
|
-
type: "Polygon"
|
|
5719
|
-
}
|
|
5720
|
-
};
|
|
5721
|
-
return feature;
|
|
5722
|
-
}
|
|
5723
|
-
const BASE_RESOLUTION = 156543.03392;
|
|
5724
|
-
function zoomLevelToZoomScale(zoomLevel, initialResolution) {
|
|
5725
|
-
const resolution = BASE_RESOLUTION / Math.pow(2, zoomLevel);
|
|
5726
|
-
const zoomScale = initialResolution / resolution;
|
|
5727
|
-
return zoomScale;
|
|
5728
|
-
}
|
|
5729
|
-
function zoomLevelForResolution(currentResolution) {
|
|
5730
|
-
const zoomLevel = Math.log2(BASE_RESOLUTION / currentResolution);
|
|
5731
|
-
return zoomLevel;
|
|
5732
|
-
}
|
|
5733
|
-
function haversineDistance(lat1, lon1, lat2, lon2) {
|
|
5734
|
-
const R2 = 6371e3;
|
|
5735
|
-
const toRadians = (degrees2) => degrees2 * Math.PI / 180;
|
|
5736
|
-
const dLat = toRadians(lat2 - lat1);
|
|
5737
|
-
const dLon = toRadians(lon2 - lon1);
|
|
5738
|
-
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
|
|
5739
|
-
const c2 = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
5740
|
-
return R2 * c2;
|
|
5741
|
-
}
|
|
5742
|
-
function resolutionForExtent(extent, viewportSize) {
|
|
5743
|
-
const [lonMin, latMin, lonMax, latMax] = extent;
|
|
5744
|
-
const latMid = (latMin + latMax) / 2;
|
|
5745
|
-
const distance = haversineDistance(latMid, lonMin, latMid, lonMax);
|
|
5746
|
-
const resolution = distance / viewportSize[0];
|
|
5747
|
-
return resolution;
|
|
5748
|
-
}
|
|
5749
|
-
class View {
|
|
5750
|
-
constructor({ projection, extent, minZoom, maxZoom, padding }) {
|
|
5751
|
-
projection.revision = 0;
|
|
5752
|
-
this.projection = projection;
|
|
5753
|
-
this.extent = extent;
|
|
5754
|
-
this.minZoom = minZoom;
|
|
5755
|
-
this.maxZoom = maxZoom;
|
|
5756
|
-
this._transform = zoomIdentity;
|
|
5757
|
-
this._padding = padding;
|
|
5758
|
-
this._viewPortSize = [0, 0];
|
|
5759
|
-
this.pixelRatio = window.devicePixelRatio;
|
|
5760
|
-
}
|
|
5761
|
-
set viewPortSize(size) {
|
|
5762
|
-
const previousSize = this._viewPortSize;
|
|
5763
|
-
this._viewPortSize = size;
|
|
5764
|
-
if (previousSize !== size) {
|
|
5765
|
-
this.fitObject(bboxFeature(this.extent));
|
|
5766
|
-
const initialExtent = this.getVisibleExtent(zoomIdentity, this.projection);
|
|
5767
|
-
this.initialResolution = resolutionForExtent(initialExtent, size);
|
|
5768
|
-
}
|
|
5769
|
-
}
|
|
5770
|
-
get viewPortSize() {
|
|
5771
|
-
return this._viewPortSize;
|
|
5772
|
-
}
|
|
5773
|
-
set transform(transform) {
|
|
5774
|
-
this._transform = transform;
|
|
5775
|
-
}
|
|
5776
|
-
get transform() {
|
|
5777
|
-
return new ZoomTransform(
|
|
5778
|
-
this._transform.k,
|
|
5779
|
-
this._transform.x * this.pixelRatio,
|
|
5780
|
-
this._transform.y * this.pixelRatio
|
|
5781
|
-
);
|
|
5782
|
-
}
|
|
5783
|
-
// map size in pixels (i.e. scaled by device pixel ratio)
|
|
5784
|
-
get mapSize() {
|
|
5785
|
-
return scaleSize(this.viewPortSize, this.pixelRatio);
|
|
5786
|
-
}
|
|
5787
|
-
get padding() {
|
|
5788
|
-
return this._padding;
|
|
5789
|
-
}
|
|
5790
|
-
// padding in pixels (i.e. scaled by device pixel ratio)
|
|
5791
|
-
get scaledPadding() {
|
|
5792
|
-
const scaledPadding = { ...this._padding };
|
|
5793
|
-
return scalePadding(scaledPadding, this.pixelRatio);
|
|
5794
|
-
}
|
|
5795
|
-
// calculates the upper and lower zoom scales
|
|
5796
|
-
get scaleExtent() {
|
|
5797
|
-
const maxScale = zoomLevelToZoomScale(this.maxZoom, this.initialResolution);
|
|
5798
|
-
return [1, maxScale];
|
|
5799
|
-
}
|
|
5800
|
-
setProjection(projection) {
|
|
5801
|
-
this.projection = projection;
|
|
5802
|
-
this.fitObject(bboxFeature(this.extent));
|
|
5803
|
-
}
|
|
5804
|
-
// only set the raw projection when it has already been configured with projection.fitExtent()
|
|
5805
|
-
setRawProjection(projection) {
|
|
5806
|
-
this.projection = projection;
|
|
5807
|
-
}
|
|
5808
|
-
fitObject(geoJSON) {
|
|
5809
|
-
this.projection.fitExtent(this.getMapExtent(), geoJSON);
|
|
5810
|
-
++this.projection.revision;
|
|
5811
|
-
}
|
|
5812
|
-
// returns bounds relative to the viewport
|
|
5813
|
-
boundsForExtent(extent) {
|
|
5814
|
-
const SW = this.projection([extent[0], extent[1]]);
|
|
5815
|
-
const NE = this.projection([extent[2], extent[3]]);
|
|
5816
|
-
const minX = SW[0] / this.pixelRatio;
|
|
5817
|
-
const minY = NE[1] / this.pixelRatio;
|
|
5818
|
-
const maxX = NE[0] / this.pixelRatio;
|
|
5819
|
-
const maxY = SW[1] / this.pixelRatio;
|
|
5820
|
-
const width = maxX - minX;
|
|
5821
|
-
const height = maxY - minY;
|
|
5822
|
-
return [
|
|
5823
|
-
[minX, minY],
|
|
5824
|
-
[width, height]
|
|
5825
|
-
];
|
|
5826
|
-
}
|
|
5827
|
-
invert(point) {
|
|
5828
|
-
const { projection, pixelRatio, transform } = this.getState();
|
|
5829
|
-
const scaledPoint = [point[0] * pixelRatio, point[1] * pixelRatio];
|
|
5830
|
-
const untransformedPoint = transform.invert(scaledPoint);
|
|
5831
|
-
const mapCoordinate = projection.invert(untransformedPoint);
|
|
5832
|
-
return mapCoordinate;
|
|
5833
|
-
}
|
|
5834
|
-
// bounds is defined as [[minX, minY], [maxX, maxY]]
|
|
5835
|
-
invertBounds(bounds) {
|
|
5836
|
-
const topLeft = bounds[0];
|
|
5837
|
-
const topRight = [bounds[1][0], bounds[0][1]];
|
|
5838
|
-
const bottomRight = [bounds[1][0], bounds[1][1]];
|
|
5839
|
-
const bottomLeft = [bounds[0][0], bounds[1][1]];
|
|
5840
|
-
const points = [topLeft, topRight, bottomRight, bottomLeft, topLeft];
|
|
5841
|
-
return points.map((d2) => this.invert(d2));
|
|
5842
|
-
}
|
|
5843
|
-
// map resolution (meters per pixel)
|
|
5844
|
-
getResolution() {
|
|
5845
|
-
return resolutionForExtent(
|
|
5846
|
-
this.getVisibleExtent(this.transform, this.projection),
|
|
5847
|
-
this.viewPortSize
|
|
5848
|
-
);
|
|
5849
|
-
}
|
|
5850
|
-
// map zoom level (0 = the entire world)
|
|
5851
|
-
getZoomLevel() {
|
|
5852
|
-
return zoomLevelForResolution(this.getResolution());
|
|
5853
|
-
}
|
|
5854
|
-
// get extent for drawn map
|
|
5855
|
-
getMapExtent() {
|
|
5856
|
-
const mapSizeInPixels = this.mapSize;
|
|
5857
|
-
const paddingInPixels = this.scaledPadding;
|
|
5858
|
-
return [
|
|
5859
|
-
[paddingInPixels.left, paddingInPixels.top],
|
|
5860
|
-
sizeMinusPadding(mapSizeInPixels, {
|
|
5861
|
-
...paddingInPixels,
|
|
5862
|
-
left: 0,
|
|
5863
|
-
top: 0
|
|
5864
|
-
})
|
|
5865
|
-
];
|
|
5866
|
-
}
|
|
5867
|
-
// visible extent in map coordinates
|
|
5868
|
-
getVisibleExtent(transform, projection) {
|
|
5869
|
-
const [width, height] = this.mapSize;
|
|
5870
|
-
const southWest = projection.invert(transform.invert([0, height]));
|
|
5871
|
-
const northEast = projection.invert(transform.invert([width, 0]));
|
|
5872
|
-
return [southWest[0], southWest[1], northEast[0], northEast[1]];
|
|
5873
|
-
}
|
|
5874
|
-
getState() {
|
|
5875
|
-
const transform = this.transform;
|
|
5876
|
-
const projection = this.projection;
|
|
5877
|
-
return {
|
|
5878
|
-
transform,
|
|
5879
|
-
projection,
|
|
5880
|
-
zoomLevel: transform.k,
|
|
5881
|
-
pixelRatio: this.pixelRatio,
|
|
5882
|
-
padding: this.padding,
|
|
5883
|
-
viewPortSize: this.viewPortSize,
|
|
5884
|
-
sizeInPixels: scaleSize(this.viewPortSize, this.pixelRatio),
|
|
5885
|
-
visibleExtent: this.getVisibleExtent(transform, projection)
|
|
5886
|
-
};
|
|
5887
|
-
}
|
|
5888
|
-
}
|
|
5889
5981
|
const mapContainer = "_mapContainer_1ogf3_9";
|
|
5890
5982
|
const helpTextContainer = "_helpTextContainer_1ogf3_15";
|
|
5891
5983
|
const helpText = "_helpText_1ogf3_15";
|
|
@@ -5898,18 +5990,33 @@ const styles$3 = {
|
|
|
5898
5990
|
desktopHelpText,
|
|
5899
5991
|
mobileHelpText: mobileHelpText$1
|
|
5900
5992
|
};
|
|
5993
|
+
const MapContext = createContext(null);
|
|
5994
|
+
function MapProvider({ map, children }) {
|
|
5995
|
+
const registeredLayers = [];
|
|
5996
|
+
const registerLayer = (layer) => {
|
|
5997
|
+
registeredLayers.push(layer);
|
|
5998
|
+
};
|
|
5999
|
+
useEffect(() => {
|
|
6000
|
+
if (map && !map.hasLayers(registeredLayers)) {
|
|
6001
|
+
map.setLayers(registeredLayers);
|
|
6002
|
+
}
|
|
6003
|
+
}, [map, children]);
|
|
6004
|
+
return /* @__PURE__ */ jsx(MapContext.Provider, { value: { registerLayer }, children });
|
|
6005
|
+
}
|
|
5901
6006
|
const mobileHelpText = "Use two fingers to zoom";
|
|
5902
6007
|
const Map$1 = forwardRef(
|
|
5903
6008
|
({ config, inModalState = false, onLoad, children }, ref) => {
|
|
5904
|
-
const { layers } = children;
|
|
5905
6009
|
const targetRef = useRef();
|
|
5906
|
-
const [map, setMap] = useState(
|
|
6010
|
+
const [map, setMap] = useState(
|
|
6011
|
+
/** @type {_Map | null} */
|
|
6012
|
+
null
|
|
6013
|
+
);
|
|
5907
6014
|
const [zoomHelpText, setZoomHelpText] = useState("");
|
|
5908
6015
|
const [showHelpText, setShowHelpText] = useState(false);
|
|
5909
6016
|
useEffect(() => {
|
|
5910
6017
|
var _a;
|
|
5911
6018
|
const map2 = new Map$2({
|
|
5912
|
-
|
|
6019
|
+
...config,
|
|
5913
6020
|
target: targetRef.current
|
|
5914
6021
|
});
|
|
5915
6022
|
map2.collaborativeGesturesEnabled = true;
|
|
@@ -5925,7 +6032,7 @@ const Map$1 = forwardRef(
|
|
|
5925
6032
|
map2.destroy();
|
|
5926
6033
|
setMap(null);
|
|
5927
6034
|
};
|
|
5928
|
-
}, [config
|
|
6035
|
+
}, [config]);
|
|
5929
6036
|
useEffect(() => {
|
|
5930
6037
|
if (!map) return;
|
|
5931
6038
|
let timeoutID;
|
|
@@ -5955,27 +6062,25 @@ const Map$1 = forwardRef(
|
|
|
5955
6062
|
}
|
|
5956
6063
|
};
|
|
5957
6064
|
}, [map, ref, onLoad]);
|
|
5958
|
-
useEffect(() => {
|
|
5959
|
-
if (map && layers !== map.layers) {
|
|
5960
|
-
map.setLayers(layers);
|
|
5961
|
-
}
|
|
5962
|
-
}, [map, layers]);
|
|
5963
6065
|
useEffect(() => {
|
|
5964
6066
|
if (!map) return;
|
|
5965
6067
|
map.collaborativeGesturesEnabled = !inModalState;
|
|
5966
6068
|
}, [map, inModalState]);
|
|
5967
|
-
return /* @__PURE__ */
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
|
|
6069
|
+
return /* @__PURE__ */ jsxs("figure", { ref: targetRef, className: styles$3.mapContainer, children: [
|
|
6070
|
+
/* @__PURE__ */ jsxs(
|
|
6071
|
+
"div",
|
|
6072
|
+
{
|
|
6073
|
+
className: styles$3.helpTextContainer,
|
|
6074
|
+
style: { opacity: showHelpText ? 1 : 0 },
|
|
6075
|
+
"aria-hidden": true,
|
|
6076
|
+
children: [
|
|
6077
|
+
/* @__PURE__ */ jsx("p", { className: [styles$3.helpText, styles$3.desktopHelpText].join(" "), children: zoomHelpText }),
|
|
6078
|
+
/* @__PURE__ */ jsx("p", { className: [styles$3.helpText, styles$3.mobileHelpText].join(" "), children: mobileHelpText })
|
|
6079
|
+
]
|
|
6080
|
+
}
|
|
6081
|
+
),
|
|
6082
|
+
/* @__PURE__ */ jsx(MapProvider, { map, children })
|
|
6083
|
+
] });
|
|
5979
6084
|
}
|
|
5980
6085
|
);
|
|
5981
6086
|
function IconMinus() {
|
|
@@ -6079,11 +6184,6 @@ function ZoomControl({ resetEnabled, onZoomIn, onZoomOut, onReset }) {
|
|
|
6079
6184
|
)
|
|
6080
6185
|
] });
|
|
6081
6186
|
}
|
|
6082
|
-
const Projection = {
|
|
6083
|
-
geoAlbersUKComposite: geoAlbersUk(),
|
|
6084
|
-
geoAlbersEngland: geoAlbers().center([0, 52.7]).rotate([1.1743, 0]).parallels([50, 54]),
|
|
6085
|
-
geoMercator: geoMercator()
|
|
6086
|
-
};
|
|
6087
6187
|
class FeatureRenderer {
|
|
6088
6188
|
constructor() {
|
|
6089
6189
|
this.drawingFunction = geoPath();
|
|
@@ -6100,6 +6200,17 @@ class FeatureRenderer {
|
|
|
6100
6200
|
this.drawingFunction.context(context);
|
|
6101
6201
|
context.beginPath();
|
|
6102
6202
|
const geometries = feature.getProjectedGeometries(projection);
|
|
6203
|
+
if (frameState.debug) {
|
|
6204
|
+
try {
|
|
6205
|
+
validateGeometries(geometries);
|
|
6206
|
+
} catch {
|
|
6207
|
+
console.error(
|
|
6208
|
+
`Invalid geometry. Feature skipped during rendering. Click here to inspect geometry: ${generateDebugUrl(feature)}
|
|
6209
|
+
`,
|
|
6210
|
+
feature
|
|
6211
|
+
);
|
|
6212
|
+
}
|
|
6213
|
+
}
|
|
6103
6214
|
for (const geometry of geometries) {
|
|
6104
6215
|
this.drawingFunction(geometry);
|
|
6105
6216
|
}
|
|
@@ -6229,10 +6340,10 @@ class TextLayerRenderer {
|
|
|
6229
6340
|
}
|
|
6230
6341
|
}
|
|
6231
6342
|
class Style {
|
|
6232
|
-
constructor(
|
|
6233
|
-
this.stroke =
|
|
6234
|
-
this.fill =
|
|
6235
|
-
this.text =
|
|
6343
|
+
constructor(properties) {
|
|
6344
|
+
this.stroke = properties == null ? void 0 : properties.stroke;
|
|
6345
|
+
this.fill = properties == null ? void 0 : properties.fill;
|
|
6346
|
+
this.text = properties == null ? void 0 : properties.text;
|
|
6236
6347
|
}
|
|
6237
6348
|
clone() {
|
|
6238
6349
|
return new Style({
|
|
@@ -6462,10 +6573,50 @@ class VectorSource {
|
|
|
6462
6573
|
}
|
|
6463
6574
|
}
|
|
6464
6575
|
class TextLayer {
|
|
6576
|
+
/** @param {TextLayerComponentProps} props */
|
|
6577
|
+
static Component({
|
|
6578
|
+
features,
|
|
6579
|
+
style: style2,
|
|
6580
|
+
minZoom,
|
|
6581
|
+
opacity,
|
|
6582
|
+
declutter,
|
|
6583
|
+
drawCollisionBoxes
|
|
6584
|
+
}) {
|
|
6585
|
+
const { registerLayer } = useContext(MapContext);
|
|
6586
|
+
const layer = useMemo(
|
|
6587
|
+
() => TextLayer.with(features, {
|
|
6588
|
+
style: style2,
|
|
6589
|
+
minZoom,
|
|
6590
|
+
opacity,
|
|
6591
|
+
declutter,
|
|
6592
|
+
drawCollisionBoxes
|
|
6593
|
+
}),
|
|
6594
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
6595
|
+
[features, minZoom, opacity, declutter, drawCollisionBoxes]
|
|
6596
|
+
);
|
|
6597
|
+
registerLayer(layer);
|
|
6598
|
+
useEffect(() => {
|
|
6599
|
+
layer.style = style2;
|
|
6600
|
+
}, [style2]);
|
|
6601
|
+
return null;
|
|
6602
|
+
}
|
|
6603
|
+
/**
|
|
6604
|
+
* @param {import("../Feature").Feature[]} features
|
|
6605
|
+
* @param {TextLayerOptions} options
|
|
6606
|
+
*/
|
|
6465
6607
|
static with(features, options) {
|
|
6466
6608
|
const source = new VectorSource({ features });
|
|
6467
6609
|
return new TextLayer({ source, ...options });
|
|
6468
6610
|
}
|
|
6611
|
+
/**
|
|
6612
|
+
* @param {Object} params
|
|
6613
|
+
* @param {VectorSource} params.source
|
|
6614
|
+
* @param {Style} [params.style=undefined]
|
|
6615
|
+
* @param {number} [params.minZoom=0]
|
|
6616
|
+
* @param {number} [params.opacity=1]
|
|
6617
|
+
* @param {boolean} [params.declutter=true]
|
|
6618
|
+
* @param {boolean} [params.drawCollisionBoxes=false]
|
|
6619
|
+
*/
|
|
6469
6620
|
constructor({
|
|
6470
6621
|
source,
|
|
6471
6622
|
style: style2,
|
|
@@ -6594,10 +6745,41 @@ class VectorLayerRenderer {
|
|
|
6594
6745
|
}
|
|
6595
6746
|
}
|
|
6596
6747
|
class VectorLayer {
|
|
6748
|
+
/** @param {VectorLayerComponentProps} props */
|
|
6749
|
+
static Component({ features, style: style2, minZoom, opacity, hitDetectionEnabled }) {
|
|
6750
|
+
const { registerLayer } = useContext(MapContext);
|
|
6751
|
+
const layer = useMemo(
|
|
6752
|
+
() => VectorLayer.with(features, {
|
|
6753
|
+
style: style2,
|
|
6754
|
+
minZoom,
|
|
6755
|
+
opacity,
|
|
6756
|
+
hitDetectionEnabled
|
|
6757
|
+
}),
|
|
6758
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
6759
|
+
[features, minZoom, opacity, hitDetectionEnabled]
|
|
6760
|
+
);
|
|
6761
|
+
registerLayer(layer);
|
|
6762
|
+
useEffect(() => {
|
|
6763
|
+
layer.style = style2;
|
|
6764
|
+
}, [style2]);
|
|
6765
|
+
return null;
|
|
6766
|
+
}
|
|
6767
|
+
/**
|
|
6768
|
+
* @param {import("../Feature").Feature[]} features
|
|
6769
|
+
* @param {VectorLayerOptions} options
|
|
6770
|
+
*/
|
|
6597
6771
|
static with(features, options) {
|
|
6598
6772
|
const source = new VectorSource({ features });
|
|
6599
6773
|
return new VectorLayer({ source, ...options });
|
|
6600
6774
|
}
|
|
6775
|
+
/**
|
|
6776
|
+
* @param {Object} params
|
|
6777
|
+
* @param {VectorSource} params.source
|
|
6778
|
+
* @param {Style | (() => Style)} [params.style=undefined]
|
|
6779
|
+
* @param {number} [params.minZoom=0]
|
|
6780
|
+
* @param {number} [params.opacity=1]
|
|
6781
|
+
* @param {boolean} [params.hitDetectionEnabled=false]
|
|
6782
|
+
*/
|
|
6601
6783
|
constructor({
|
|
6602
6784
|
source,
|
|
6603
6785
|
style: style2,
|
|
@@ -6755,7 +6937,7 @@ function interpolateFeatures(currentFeatures, newFeatures, { interpolate: interp
|
|
|
6755
6937
|
break;
|
|
6756
6938
|
}
|
|
6757
6939
|
}
|
|
6758
|
-
feature.
|
|
6940
|
+
feature.setGeometry(geometries);
|
|
6759
6941
|
features.push(feature);
|
|
6760
6942
|
}
|
|
6761
6943
|
return features;
|
|
@@ -6819,6 +7001,15 @@ function interpolateStroke(strokeA, strokeB, interpolateColors, interpolateNumbe
|
|
|
6819
7001
|
};
|
|
6820
7002
|
}
|
|
6821
7003
|
class Feature {
|
|
7004
|
+
/**
|
|
7005
|
+
* Represents a feature on the map
|
|
7006
|
+
* @constructor
|
|
7007
|
+
* @param {Object} props - The properties for the feature.
|
|
7008
|
+
* @property {string} id - The unique identifier of the feature
|
|
7009
|
+
* @property {Array} geometries - The geometries of the feature
|
|
7010
|
+
* @property {Object} properties - The properties of the feature
|
|
7011
|
+
* @property {import("./styles").Style | import("./styles").StyleFunction} style - The style of the feature
|
|
7012
|
+
*/
|
|
6822
7013
|
constructor({ id: id2, geometries, properties, style: style2 }) {
|
|
6823
7014
|
this.id = id2;
|
|
6824
7015
|
this.geometries = geometries;
|
|
@@ -6828,14 +7019,14 @@ class Feature {
|
|
|
6828
7019
|
}
|
|
6829
7020
|
getExtent() {
|
|
6830
7021
|
if (this._extent) return this._extent;
|
|
6831
|
-
const extent = this.geometries.reduce((combinedExtent,
|
|
6832
|
-
if (!combinedExtent) return
|
|
6833
|
-
return combineExtents(
|
|
7022
|
+
const extent = this.geometries.reduce((combinedExtent, geometries) => {
|
|
7023
|
+
if (!combinedExtent) return geometries.extent;
|
|
7024
|
+
return combineExtents(geometries.extent, combinedExtent);
|
|
6834
7025
|
}, null);
|
|
6835
7026
|
this._extent = extent;
|
|
6836
7027
|
return extent;
|
|
6837
7028
|
}
|
|
6838
|
-
|
|
7029
|
+
setgeometries(geometries) {
|
|
6839
7030
|
this.geometries = geometries;
|
|
6840
7031
|
this._extent = void 0;
|
|
6841
7032
|
}
|
|
@@ -6856,8 +7047,8 @@ class Feature {
|
|
|
6856
7047
|
if (!containsCoordinate(this.getExtent(), coordinate)) {
|
|
6857
7048
|
return false;
|
|
6858
7049
|
}
|
|
6859
|
-
for (const
|
|
6860
|
-
if (geoContains(
|
|
7050
|
+
for (const geometries of this.geometries) {
|
|
7051
|
+
if (geoContains(geometries.getGeoJSON(), coordinate)) {
|
|
6861
7052
|
return true;
|
|
6862
7053
|
}
|
|
6863
7054
|
}
|
|
@@ -6871,14 +7062,83 @@ class Feature {
|
|
|
6871
7062
|
style: this.style
|
|
6872
7063
|
});
|
|
6873
7064
|
}
|
|
7065
|
+
/**
|
|
7066
|
+
* Returns the geometries as a GeoJSON object
|
|
7067
|
+
* @returns {Object} The GeoJSON representation of the geometries
|
|
7068
|
+
*/
|
|
7069
|
+
getGeoJSON() {
|
|
7070
|
+
const geometries = this.geometries.map((d2) => d2.getGeoJSON());
|
|
7071
|
+
if (geometries.length === 1) return geometries[0];
|
|
7072
|
+
return {
|
|
7073
|
+
type: "Feature",
|
|
7074
|
+
geometry: this._getGeometryGeoJSON(),
|
|
7075
|
+
properties: this.properties
|
|
7076
|
+
};
|
|
7077
|
+
}
|
|
7078
|
+
_getGeometryGeoJSON() {
|
|
7079
|
+
const geometries = this.geometries.map((d2) => d2.getGeoJSON());
|
|
7080
|
+
if (geometries.length === 0) throw new Error("Feature has no geometries");
|
|
7081
|
+
if (geometries.length === 1) return geometries[0];
|
|
7082
|
+
if (geometries[0].type === "Polygon") {
|
|
7083
|
+
return {
|
|
7084
|
+
type: "MultiPolygon",
|
|
7085
|
+
coordinates: geometries.map((d2) => d2.coordinates)
|
|
7086
|
+
};
|
|
7087
|
+
} else if (geometries[0].type === "LineString") {
|
|
7088
|
+
return {
|
|
7089
|
+
type: "MultiLineString",
|
|
7090
|
+
coordinates: geometries.map((d2) => d2.coordinates)
|
|
7091
|
+
};
|
|
7092
|
+
} else if (geometries[0].type === "Point") {
|
|
7093
|
+
return {
|
|
7094
|
+
type: "MultiPoint",
|
|
7095
|
+
coordinates: geometries.map((d2) => d2.coordinates)
|
|
7096
|
+
};
|
|
7097
|
+
}
|
|
7098
|
+
throw new Error("Could not determine geometry type");
|
|
7099
|
+
}
|
|
6874
7100
|
}
|
|
6875
|
-
class
|
|
6876
|
-
|
|
7101
|
+
class Geometry {
|
|
7102
|
+
/**
|
|
7103
|
+
* Represents vector geometry
|
|
7104
|
+
* @constructor
|
|
7105
|
+
* @param {Object} options
|
|
7106
|
+
* @param {string} options.type - The type of geometry (e.g., 'Point', 'LineString', 'Polygon')
|
|
7107
|
+
* @param {Array} options.extent - The extent of the geometry (e.g., [xmin, ymin, xmax, ymax])
|
|
7108
|
+
* @param {Array} options.coordinates - The coordinates of the geometry (e.g., [[x1, y1], [x2, y2], ...])
|
|
7109
|
+
*/
|
|
7110
|
+
constructor({ type, extent, coordinates }) {
|
|
6877
7111
|
this.type = type;
|
|
6878
7112
|
this.extent = extent;
|
|
6879
7113
|
this.coordinates = coordinates;
|
|
6880
7114
|
this.getProjected = memoise(this._getProjected).bind(this);
|
|
6881
7115
|
}
|
|
7116
|
+
/**
|
|
7117
|
+
* Returns the geometry as a GeoJSON object
|
|
7118
|
+
* @function
|
|
7119
|
+
* @param {import("../projection").Projection} projection - The projection to use for the geometry
|
|
7120
|
+
* @returns {Object} A GeoJSON representation of the projected geometry
|
|
7121
|
+
* @private
|
|
7122
|
+
*/
|
|
7123
|
+
// eslint-disable-next-line no-unused-vars
|
|
7124
|
+
_getProjected(projection) {
|
|
7125
|
+
throw new Error("Not implemented");
|
|
7126
|
+
}
|
|
7127
|
+
/**
|
|
7128
|
+
* Returns the geometry as a GeoJSON object
|
|
7129
|
+
* @returns {Object} The GeoJSON representation of the geometry
|
|
7130
|
+
*/
|
|
7131
|
+
getGeoJSON() {
|
|
7132
|
+
return {
|
|
7133
|
+
type: this.type,
|
|
7134
|
+
coordinates: this.coordinates
|
|
7135
|
+
};
|
|
7136
|
+
}
|
|
7137
|
+
}
|
|
7138
|
+
class LineString extends Geometry {
|
|
7139
|
+
constructor({ type = "LineString", extent, coordinates }) {
|
|
7140
|
+
super({ type, extent, coordinates });
|
|
7141
|
+
}
|
|
6882
7142
|
_getProjected(projection) {
|
|
6883
7143
|
const projected = [];
|
|
6884
7144
|
for (const point of this.coordinates) {
|
|
@@ -6890,23 +7150,26 @@ class LineString {
|
|
|
6890
7150
|
};
|
|
6891
7151
|
}
|
|
6892
7152
|
}
|
|
6893
|
-
class Polygon {
|
|
7153
|
+
class Polygon extends Geometry {
|
|
6894
7154
|
constructor({ type = "Polygon", extent, coordinates }) {
|
|
6895
|
-
|
|
6896
|
-
this.extent = extent;
|
|
6897
|
-
this.coordinates = coordinates;
|
|
6898
|
-
this.getProjected = memoise(this._getProjected).bind(this);
|
|
7155
|
+
super({ type, extent, coordinates });
|
|
6899
7156
|
}
|
|
6900
|
-
|
|
6901
|
-
_getProjected(projection, _revision) {
|
|
7157
|
+
_getProjected(projection) {
|
|
6902
7158
|
const projected = [];
|
|
6903
7159
|
const rings = this.coordinates;
|
|
6904
7160
|
for (const ring of rings) {
|
|
6905
7161
|
const projectedRing = [];
|
|
6906
7162
|
for (const point of ring) {
|
|
6907
|
-
|
|
7163
|
+
const projectedPoint = projection(point);
|
|
7164
|
+
if (projectedPoint) {
|
|
7165
|
+
projectedRing.push(projectedPoint);
|
|
7166
|
+
} else {
|
|
7167
|
+
break;
|
|
7168
|
+
}
|
|
7169
|
+
}
|
|
7170
|
+
if (projectedRing.length > 0) {
|
|
7171
|
+
projected.push(projectedRing);
|
|
6908
7172
|
}
|
|
6909
|
-
projected.push(projectedRing);
|
|
6910
7173
|
}
|
|
6911
7174
|
return {
|
|
6912
7175
|
type: this.type,
|
|
@@ -6922,12 +7185,6 @@ class Polygon {
|
|
|
6922
7185
|
setCoordinates(coordinates) {
|
|
6923
7186
|
this.coordinates = coordinates;
|
|
6924
7187
|
}
|
|
6925
|
-
getGeoJSON() {
|
|
6926
|
-
return {
|
|
6927
|
-
type: this.type,
|
|
6928
|
-
coordinates: this.coordinates
|
|
6929
|
-
};
|
|
6930
|
-
}
|
|
6931
7188
|
clone() {
|
|
6932
7189
|
return new Polygon({
|
|
6933
7190
|
extent: this.extent,
|
|
@@ -6935,12 +7192,10 @@ class Polygon {
|
|
|
6935
7192
|
});
|
|
6936
7193
|
}
|
|
6937
7194
|
}
|
|
6938
|
-
class Point {
|
|
7195
|
+
class Point extends Geometry {
|
|
6939
7196
|
constructor({ type = "Point", coordinates }) {
|
|
6940
|
-
|
|
7197
|
+
super({ type, extent: null, coordinates });
|
|
6941
7198
|
this.extent = [...coordinates, ...coordinates];
|
|
6942
|
-
this.coordinates = coordinates;
|
|
6943
|
-
this.getProjected = memoise(this._getProjected).bind(this);
|
|
6944
7199
|
}
|
|
6945
7200
|
_getProjected(projection) {
|
|
6946
7201
|
return {
|
|
@@ -7463,6 +7718,7 @@ function useTouchOrHover() {
|
|
|
7463
7718
|
export {
|
|
7464
7719
|
AdSlot,
|
|
7465
7720
|
ArrowButton,
|
|
7721
|
+
AspectRatioBox,
|
|
7466
7722
|
Button,
|
|
7467
7723
|
ChangeBar,
|
|
7468
7724
|
Chevron,
|