@canopy-iiif/app 1.8.10 → 1.8.11
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/package.json +1 -1
- package/ui/dist/index.mjs +111 -16
- package/ui/dist/index.mjs.map +3 -3
- package/ui/dist/server.mjs +38 -3
- package/ui/dist/server.mjs.map +2 -2
- package/ui/styles/components/_map.scss +64 -9
- package/ui/styles/index.css +54 -9
package/package.json
CHANGED
package/ui/dist/index.mjs
CHANGED
|
@@ -46126,6 +46126,8 @@ var DEFAULT_TILE_LAYERS = [
|
|
|
46126
46126
|
maxZoom: 19
|
|
46127
46127
|
}
|
|
46128
46128
|
];
|
|
46129
|
+
var TRANSPARENT_TILE_LAYER_NAME = "Transparent";
|
|
46130
|
+
var TRANSPARENT_TILE_URL = "data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=";
|
|
46129
46131
|
var CUSTOM_MARKER_SIZE = 40;
|
|
46130
46132
|
var CUSTOM_MARKER_RADIUS = CUSTOM_MARKER_SIZE / 2;
|
|
46131
46133
|
var CUSTOM_MARKER_POPUP_OFFSET = -CUSTOM_MARKER_RADIUS + 6;
|
|
@@ -46437,6 +46439,24 @@ function extractManifestKeysFromIiif(resource, fallback) {
|
|
|
46437
46439
|
}
|
|
46438
46440
|
return fallbackKey ? [fallbackKey] : [];
|
|
46439
46441
|
}
|
|
46442
|
+
function createTransparentTileLayers(leaflet) {
|
|
46443
|
+
if (!leaflet) return [];
|
|
46444
|
+
try {
|
|
46445
|
+
return [
|
|
46446
|
+
{
|
|
46447
|
+
name: TRANSPARENT_TILE_LAYER_NAME,
|
|
46448
|
+
layer: leaflet.tileLayer(TRANSPARENT_TILE_URL, {
|
|
46449
|
+
attribution: "",
|
|
46450
|
+
maxZoom: 25,
|
|
46451
|
+
minZoom: 0,
|
|
46452
|
+
opacity: 0
|
|
46453
|
+
})
|
|
46454
|
+
}
|
|
46455
|
+
];
|
|
46456
|
+
} catch (_) {
|
|
46457
|
+
return [];
|
|
46458
|
+
}
|
|
46459
|
+
}
|
|
46440
46460
|
function buildTileLayers(inputLayers, leaflet) {
|
|
46441
46461
|
if (!leaflet) return [];
|
|
46442
46462
|
const layers = Array.isArray(inputLayers) && inputLayers.length ? inputLayers : DEFAULT_TILE_LAYERS;
|
|
@@ -46453,8 +46473,25 @@ function buildTileLayers(inputLayers, leaflet) {
|
|
|
46453
46473
|
};
|
|
46454
46474
|
}).filter(Boolean);
|
|
46455
46475
|
}
|
|
46456
|
-
function buildMarkerIcon(marker, leaflet, colorOverride) {
|
|
46476
|
+
function buildMarkerIcon(marker, leaflet, colorOverride, markerStyle) {
|
|
46457
46477
|
if (!leaflet) return null;
|
|
46478
|
+
if (markerStyle === "small") {
|
|
46479
|
+
const label = marker.keyLabel || marker.title || marker.summary || "";
|
|
46480
|
+
const safeLabel = label ? escapeHtml(label) : "";
|
|
46481
|
+
const color2 = colorOverride ? escapeHtml(colorOverride) : DEFAULT_ACCENT_HEX;
|
|
46482
|
+
const dotStyle = color2 ? ` style="background-color:${color2}"` : "";
|
|
46483
|
+
const html2 = `<div class="canopy-map__marker-label"><span class="canopy-map__marker-label-dot"${dotStyle}></span>` + (safeLabel ? `<span class="canopy-map__marker-label-text">${safeLabel}</span>` : "") + `</div>`;
|
|
46484
|
+
try {
|
|
46485
|
+
return leaflet.divIcon({
|
|
46486
|
+
className: "canopy-map__marker canopy-map__marker--label",
|
|
46487
|
+
html: html2,
|
|
46488
|
+
iconAnchor: [6, 6],
|
|
46489
|
+
popupAnchor: [0, 0]
|
|
46490
|
+
});
|
|
46491
|
+
} catch (_) {
|
|
46492
|
+
return null;
|
|
46493
|
+
}
|
|
46494
|
+
}
|
|
46458
46495
|
const hasThumbnail = Boolean(marker && marker.thumbnail);
|
|
46459
46496
|
const size = CUSTOM_MARKER_SIZE;
|
|
46460
46497
|
const anchor = CUSTOM_MARKER_RADIUS;
|
|
@@ -46476,12 +46513,13 @@ function buildMarkerIcon(marker, leaflet, colorOverride) {
|
|
|
46476
46513
|
return null;
|
|
46477
46514
|
}
|
|
46478
46515
|
}
|
|
46479
|
-
function buildClusterOptions(leaflet) {
|
|
46516
|
+
function buildClusterOptions(leaflet, maxClusterRadius) {
|
|
46480
46517
|
if (!leaflet) return null;
|
|
46481
46518
|
const size = CUSTOM_MARKER_SIZE;
|
|
46482
46519
|
const anchor = CUSTOM_MARKER_RADIUS;
|
|
46483
46520
|
return {
|
|
46484
46521
|
chunkedLoading: true,
|
|
46522
|
+
maxClusterRadius: typeof maxClusterRadius === "number" ? maxClusterRadius : void 0,
|
|
46485
46523
|
iconCreateFunction: (cluster) => {
|
|
46486
46524
|
const count = cluster && typeof cluster.getChildCount === "function" ? cluster.getChildCount() : 0;
|
|
46487
46525
|
return leaflet.divIcon({
|
|
@@ -46635,6 +46673,17 @@ function normalizeGeoReferences(value) {
|
|
|
46635
46673
|
const list = Array.isArray(value) ? value : value ? [value] : [];
|
|
46636
46674
|
return list.map((entry, index) => normalizeGeoReferenceEntry(entry, index)).filter(Boolean);
|
|
46637
46675
|
}
|
|
46676
|
+
function normalizeMarkerVariant(value) {
|
|
46677
|
+
if (!value) return null;
|
|
46678
|
+
try {
|
|
46679
|
+
const normalized = String(value).trim().toLowerCase();
|
|
46680
|
+
if (!normalized) return null;
|
|
46681
|
+
if (["small", "label", "inline"].includes(normalized)) return "small";
|
|
46682
|
+
return null;
|
|
46683
|
+
} catch (_) {
|
|
46684
|
+
return null;
|
|
46685
|
+
}
|
|
46686
|
+
}
|
|
46638
46687
|
function extractNavMarkers(data, allowedKeys) {
|
|
46639
46688
|
if (!data || !Array.isArray(data.manifests)) return [];
|
|
46640
46689
|
const keys2 = allowedKeys instanceof Set ? allowedKeys : /* @__PURE__ */ new Set();
|
|
@@ -46704,8 +46753,10 @@ function Map3({
|
|
|
46704
46753
|
legend = [],
|
|
46705
46754
|
geoReferences = [],
|
|
46706
46755
|
tileLayers = [],
|
|
46756
|
+
disableTileLayers = false,
|
|
46707
46757
|
scrollWheelZoom = false,
|
|
46708
46758
|
cluster = true,
|
|
46759
|
+
maxClusterRadius = null,
|
|
46709
46760
|
customPoints = [],
|
|
46710
46761
|
navDataset = null,
|
|
46711
46762
|
iiifContent = null,
|
|
@@ -46871,28 +46922,38 @@ function Map3({
|
|
|
46871
46922
|
if (!value || !label) return null;
|
|
46872
46923
|
return {
|
|
46873
46924
|
keyValue: String(value).trim(),
|
|
46874
|
-
label: String(label).trim()
|
|
46925
|
+
label: String(label).trim(),
|
|
46926
|
+
markerType: normalizeMarkerVariant(
|
|
46927
|
+
entry.markerType || entry.type || entry.variant
|
|
46928
|
+
)
|
|
46875
46929
|
};
|
|
46876
46930
|
}).filter(Boolean);
|
|
46877
46931
|
}, [resolvedKeyInput]);
|
|
46878
46932
|
const markerKeyData = React38.useMemo(() => {
|
|
46879
|
-
if (!normalizedLegendConfig.length) return { groups: [],
|
|
46880
|
-
const
|
|
46933
|
+
if (!normalizedLegendConfig.length) return { groups: [], metaMap: null };
|
|
46934
|
+
const metaMap = createMarkerMap();
|
|
46881
46935
|
const palette = generateLegendColors(normalizedLegendConfig.length);
|
|
46882
46936
|
const groups = normalizedLegendConfig.map((entry, index) => {
|
|
46883
46937
|
const color = palette[index] || palette[0] || DEFAULT_ACCENT_HEX;
|
|
46884
|
-
|
|
46938
|
+
metaMap.set(entry.keyValue, {
|
|
46939
|
+
color,
|
|
46940
|
+
markerType: entry.markerType || null
|
|
46941
|
+
});
|
|
46885
46942
|
return {
|
|
46886
46943
|
keyValue: entry.keyValue,
|
|
46887
46944
|
label: entry.label,
|
|
46888
|
-
color
|
|
46945
|
+
color,
|
|
46946
|
+
markerType: entry.markerType || null
|
|
46889
46947
|
};
|
|
46890
46948
|
});
|
|
46891
|
-
return { groups,
|
|
46949
|
+
return { groups, metaMap };
|
|
46892
46950
|
}, [normalizedLegendConfig]);
|
|
46893
46951
|
const markerKeyGroups = markerKeyData.groups;
|
|
46894
|
-
const
|
|
46895
|
-
const clusterOptions = React38.useMemo(
|
|
46952
|
+
const markerKeyMetaMap = markerKeyData.metaMap;
|
|
46953
|
+
const clusterOptions = React38.useMemo(
|
|
46954
|
+
() => buildClusterOptions(leafletLib, typeof maxClusterRadius === "number" ? maxClusterRadius : null),
|
|
46955
|
+
[leafletLib, maxClusterRadius]
|
|
46956
|
+
);
|
|
46896
46957
|
React38.useEffect(() => {
|
|
46897
46958
|
if (!containerRef.current || mapRef.current || !leafletLib) return void 0;
|
|
46898
46959
|
const map = leafletLib.map(containerRef.current, {
|
|
@@ -46900,7 +46961,7 @@ function Map3({
|
|
|
46900
46961
|
scrollWheelZoom: scrollWheelZoom === true
|
|
46901
46962
|
});
|
|
46902
46963
|
mapRef.current = map;
|
|
46903
|
-
const layers = buildTileLayers(tileLayers, leafletLib);
|
|
46964
|
+
const layers = disableTileLayers === true ? createTransparentTileLayers(leafletLib) : buildTileLayers(tileLayers, leafletLib);
|
|
46904
46965
|
const layerControlEntries = {};
|
|
46905
46966
|
layers.forEach((entry, index) => {
|
|
46906
46967
|
try {
|
|
@@ -46930,7 +46991,7 @@ function Map3({
|
|
|
46930
46991
|
mapRef.current = null;
|
|
46931
46992
|
layerRef.current = null;
|
|
46932
46993
|
};
|
|
46933
|
-
}, [tileLayers, scrollWheelZoom, cluster, clusterOptions, leafletLib]);
|
|
46994
|
+
}, [tileLayers, disableTileLayers, scrollWheelZoom, cluster, clusterOptions, leafletLib]);
|
|
46934
46995
|
React38.useEffect(() => {
|
|
46935
46996
|
const map = mapRef.current;
|
|
46936
46997
|
if (!map || !leafletLib) return void 0;
|
|
@@ -46980,14 +47041,39 @@ function Map3({
|
|
|
46980
47041
|
}
|
|
46981
47042
|
const bounds = [];
|
|
46982
47043
|
const popupCleanups = [];
|
|
47044
|
+
const hoverCleanups = [];
|
|
46983
47045
|
allMarkers.forEach((marker) => {
|
|
46984
47046
|
if (!marker || !Number.isFinite(marker.lat) || !Number.isFinite(marker.lng)) return;
|
|
46985
47047
|
const latlng = leafletLib.latLng(marker.lat, marker.lng);
|
|
46986
47048
|
bounds.push(latlng);
|
|
46987
|
-
const
|
|
46988
|
-
const
|
|
47049
|
+
const markerMeta = marker.type === "custom" && markerKeyMetaMap && marker.keyValue ? markerKeyMetaMap.get(String(marker.keyValue).trim()) : null;
|
|
47050
|
+
const colorOverride = markerMeta && markerMeta.color ? markerMeta.color : null;
|
|
47051
|
+
const markerStyle = markerMeta && markerMeta.markerType ? markerMeta.markerType : null;
|
|
47052
|
+
const icon = buildMarkerIcon(marker, leafletLib, colorOverride, markerStyle);
|
|
46989
47053
|
const leafletMarker = leafletLib.marker(latlng, icon ? { icon } : void 0);
|
|
46990
|
-
const
|
|
47054
|
+
const shouldShowPopup = markerStyle !== "small";
|
|
47055
|
+
const popup = shouldShowPopup ? renderPopup(marker) : null;
|
|
47056
|
+
const handleMouseOver = () => {
|
|
47057
|
+
const el = leafletMarker && leafletMarker.getElement && leafletMarker.getElement();
|
|
47058
|
+
if (el) el.classList.add("is-hovered");
|
|
47059
|
+
};
|
|
47060
|
+
const handleMouseOut = () => {
|
|
47061
|
+
const el = leafletMarker && leafletMarker.getElement && leafletMarker.getElement();
|
|
47062
|
+
if (el) el.classList.remove("is-hovered");
|
|
47063
|
+
};
|
|
47064
|
+
try {
|
|
47065
|
+
leafletMarker.on("mouseover", handleMouseOver);
|
|
47066
|
+
leafletMarker.on("mouseout", handleMouseOut);
|
|
47067
|
+
hoverCleanups.push(() => {
|
|
47068
|
+
try {
|
|
47069
|
+
leafletMarker.off("mouseover", handleMouseOver);
|
|
47070
|
+
leafletMarker.off("mouseout", handleMouseOut);
|
|
47071
|
+
} catch (_) {
|
|
47072
|
+
}
|
|
47073
|
+
handleMouseOut();
|
|
47074
|
+
});
|
|
47075
|
+
} catch (_) {
|
|
47076
|
+
}
|
|
46991
47077
|
if (popup && popup.element) {
|
|
46992
47078
|
try {
|
|
46993
47079
|
leafletMarker.bindPopup(popup.element);
|
|
@@ -47061,6 +47147,12 @@ function Map3({
|
|
|
47061
47147
|
} catch (_) {
|
|
47062
47148
|
}
|
|
47063
47149
|
});
|
|
47150
|
+
hoverCleanups.forEach((cleanup) => {
|
|
47151
|
+
try {
|
|
47152
|
+
cleanup();
|
|
47153
|
+
} catch (_) {
|
|
47154
|
+
}
|
|
47155
|
+
});
|
|
47064
47156
|
};
|
|
47065
47157
|
}, [allMarkers, defaultCenter, defaultZoom, leafletLib]);
|
|
47066
47158
|
const isLoadingMarkers = iiifTargets.loading || navState.loading;
|
|
@@ -47089,7 +47181,10 @@ function Map3({
|
|
|
47089
47181
|
return /* @__PURE__ */ React38.createElement(React38.Fragment, null, mapElement, /* @__PURE__ */ React38.createElement("div", { className: "canopy-map__key", "aria-label": "Map key" }, /* @__PURE__ */ React38.createElement("ul", { className: "canopy-map__key-list" }, markerKeyGroups.map((group) => /* @__PURE__ */ React38.createElement("li", { key: group.label, className: "canopy-map__key-item" }, /* @__PURE__ */ React38.createElement(
|
|
47090
47182
|
"span",
|
|
47091
47183
|
{
|
|
47092
|
-
className:
|
|
47184
|
+
className: [
|
|
47185
|
+
"canopy-map__key-dot",
|
|
47186
|
+
group.markerType === "small" ? "canopy-map__key-dot--small" : null
|
|
47187
|
+
].filter(Boolean).join(" "),
|
|
47093
47188
|
"aria-hidden": "true",
|
|
47094
47189
|
style: { backgroundColor: group.color || void 0 }
|
|
47095
47190
|
}
|