@biodiv-platform/naksha-maplibre-layers 5.0.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.
@@ -0,0 +1,2346 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __pow = Math.pow;
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __spreadValues = (a, b) => {
10
+ for (var prop in b || (b = {}))
11
+ if (__hasOwnProp.call(b, prop))
12
+ __defNormalProp(a, prop, b[prop]);
13
+ if (__getOwnPropSymbols)
14
+ for (var prop of __getOwnPropSymbols(b)) {
15
+ if (__propIsEnum.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ }
18
+ return a;
19
+ };
20
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
21
+ var __async = (__this, __arguments, generator) => {
22
+ return new Promise((resolve, reject) => {
23
+ var fulfilled = (value) => {
24
+ try {
25
+ step(generator.next(value));
26
+ } catch (e) {
27
+ reject(e);
28
+ }
29
+ };
30
+ var rejected = (value) => {
31
+ try {
32
+ step(generator.throw(value));
33
+ } catch (e) {
34
+ reject(e);
35
+ }
36
+ };
37
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
38
+ step((generator = generator.apply(__this, __arguments)).next());
39
+ });
40
+ };
41
+
42
+ // src/index.tsx
43
+ import { TranslationProvider } from "@biodiv-platform/naksha-commons";
44
+ import React14 from "react";
45
+ import { MapProvider } from "react-map-gl/maplibre";
46
+ import { setup } from "twind";
47
+
48
+ // locales/en.json
49
+ var en_default = {
50
+ are_you_sure: "Are you sure?",
51
+ base_style: "Base Style",
52
+ clear: "Clear Selection",
53
+ created_by: "Attribution",
54
+ created_on: "Created On",
55
+ delete: "Delete",
56
+ download: "Download",
57
+ find_layer_by_name: "Find layer by name",
58
+ infobar: "Attributes at Clicked Location",
59
+ information: "Information",
60
+ layer_selection: "Layer Selection",
61
+ layer_selection_all: "All Layers",
62
+ layer_selection_top: "Top Layer Only",
63
+ layers: "Layers",
64
+ legend: "Legend",
65
+ less: "Less",
66
+ license: "License",
67
+ list_layers: "List Layers",
68
+ pending: "Pending",
69
+ publish: "Publish",
70
+ raster_style_not_found: "Style not available for the given layer",
71
+ remove: "Remove",
72
+ selected: "Selected",
73
+ settings: "Settings",
74
+ square: "Square",
75
+ tags: "Tags",
76
+ toggle: "Toggle Publishing",
77
+ uploaded: "Uploaded",
78
+ uploader: "Uploader",
79
+ url: "URL",
80
+ visiblity: "Visiblity"
81
+ };
82
+
83
+ // locales/fr.json
84
+ var fr_default = {
85
+ are_you_sure: "\xCAtes-vous s\xFBr?",
86
+ base_style: "Style de base",
87
+ clear: "Effacer la s\xE9lection",
88
+ created_by: "Attribution",
89
+ created_on: "Cr\xE9\xE9 sur",
90
+ delete: "Effacer",
91
+ download: "T\xE9l\xE9charger",
92
+ find_layer_by_name: "Trouver la couche par nom",
93
+ infobar: "Attributs \xE0 l'emplacement cliqu\xE9",
94
+ information: "Informations",
95
+ layer_selection_all: "Toutes les couches",
96
+ layer_selection_top: "Couche sup\xE9rieure uniquement",
97
+ layer_selection: "S\xE9lection de calque",
98
+ layers: "Couches",
99
+ legend: "L\xE9gende",
100
+ less: "Moins",
101
+ license: "Licence",
102
+ list_layers: "Liste des couches",
103
+ pending: "En attente",
104
+ publish: "Publier",
105
+ remove: "Supprimer",
106
+ selected: "Choisie",
107
+ settings: "Param\xE8tres",
108
+ square: "Carr\xE9",
109
+ toggle: "Basculer la publication",
110
+ uploaded: "T\xE9l\xE9charg\xE9",
111
+ url: "url"
112
+ };
113
+
114
+ // locales/hi.json
115
+ var hi_default = {
116
+ are_you_sure: "\u0915\u094D\u092F\u093E \u0906\u092A\u0915\u094B \u092F\u0915\u0940\u0928 \u0939\u0948?",
117
+ base_style: "\u0906\u0927\u093E\u0930 \u0936\u0948\u0932\u0940",
118
+ clear: "\u091A\u092F\u0928 \u0938\u093E\u092B\u093C \u0915\u0930\u0947\u0902",
119
+ created_by: "\u0906\u0930\u094B\u092A\u0923",
120
+ created_on: "\u092A\u0930 \u092C\u0928\u093E\u092F\u093E",
121
+ delete: "\u0939\u091F\u093E\u090F\u0902",
122
+ download: "\u0921\u093E\u0909\u0928\u0932\u094B\u0921",
123
+ find_layer_by_name: "\u0928\u093E\u092E \u0938\u0947 \u092A\u0930\u0924 \u0916\u094B\u091C\u0947\u0902",
124
+ infobar: "\u0915\u094D\u0932\u093F\u0915 \u0915\u093F\u090F \u0917\u090F \u0938\u094D\u0925\u093E\u0928 \u092A\u0930 \u0935\u093F\u0936\u0947\u0937\u0924\u093E\u090F\u0902",
125
+ information: "\u091C\u093E\u0928\u0915\u093E\u0930\u0940",
126
+ layer_selection_all: "\u0938\u092D\u0940 \u092A\u0930\u0924\u0947\u0902",
127
+ layer_selection_top: "\u0915\u0947\u0935\u0932 \u0936\u0940\u0930\u094D\u0937 \u092A\u0930\u0924",
128
+ layer_selection: "\u092A\u0930\u0924 \u091A\u092F\u0928",
129
+ layers: "\u092A\u0930\u0924\u0947\u0902",
130
+ legend: "\u0915\u093F\u0902\u0935\u0926\u0902\u0924\u0940",
131
+ less: "\u0915\u092E",
132
+ license: "\u0932\u093E\u0907\u0938\u0947\u0902\u0938",
133
+ list_layers: "\u0938\u0942\u091A\u0940 \u092A\u0930\u0924\u0947\u0902",
134
+ pending: "\u0932\u0902\u092C\u093F\u0924",
135
+ publish: "\u092A\u094D\u0930\u0915\u093E\u0936\u093F\u0924",
136
+ remove: "\u0939\u091F\u093E\u0928\u093E",
137
+ selected: "\u091A\u092F\u0928\u093F\u0924",
138
+ settings: "\u0938\u092E\u093E\u092F\u094B\u091C\u0928",
139
+ square: "\u0938\u094D\u0915\u094D\u0935\u093E\u092F\u0930",
140
+ tags: "\u091F\u0948\u0917",
141
+ toggle: "\u092A\u094D\u0930\u0915\u093E\u0936\u0928 \u091F\u0949\u0917\u0932 \u0915\u0930\u0947\u0902",
142
+ uploaded: "\u0905\u092A\u0932\u094B\u0921 \u0915\u093F\u092F\u093E \u0917\u092F\u093E",
143
+ url: "\u092F\u0942\u0906\u0930\u090F\u0932"
144
+ };
145
+
146
+ // locales/index.ts
147
+ var locales_default = { en: en_default, fr: fr_default, hi: hi_default };
148
+
149
+ // src/components/map/index.tsx
150
+ import { defaultViewState as defaultViewState2 } from "@biodiv-platform/naksha-commons";
151
+ import { useMemo as useMemo7, useState as useState10 } from "react";
152
+ import MapGL, { NavigationControl } from "react-map-gl/maplibre";
153
+ import { tw as tw20 } from "twind";
154
+
155
+ // src/hooks/use-layers.tsx
156
+ import { defaultMapStyles, useDebounce } from "@biodiv-platform/naksha-commons";
157
+ import React, {
158
+ createContext,
159
+ useContext,
160
+ useEffect,
161
+ useMemo,
162
+ useState
163
+ } from "react";
164
+ import { useMap } from "react-map-gl/maplibre";
165
+
166
+ // src/services/naksha.ts
167
+ import cb from "colorbrewer";
168
+ import axios from "redaxios";
169
+
170
+ // src/utils/grid.ts
171
+ import BoundingBox from "boundingbox";
172
+ import { GeoHash } from "geohash";
173
+
174
+ // src/static/constants.tsx
175
+ import { MapStyles, defaultViewState } from "@biodiv-platform/naksha-commons";
176
+ var defaultNakshaProps = {
177
+ defaultViewState,
178
+ nakshaApiEndpoint: "/naksha-api/api",
179
+ geoserver: { endpoint: "/geoserver", workspace: "biodiv", store: "ibp" },
180
+ mapStyle: MapStyles.MAP_STREETS,
181
+ layers: [],
182
+ selectedLayers: []
183
+ };
184
+ var FALLBACK_THUMB = "data:image/svg+xml,%3Csvg fill='none' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 72 72'%3E%3Cpath fill='%23fff' d='M0 0h72v72H0z'/%3E%3Cpath d='M35.981 48.293l-13.853-10.77-3.045 2.368L36 53.048l16.917-13.157-3.064-2.387-13.872 10.789zM36 43.519l13.834-10.77 3.083-2.388L36 17.204 19.083 30.36l3.064 2.387L36 43.518z' fill='%23A0AEC0'/%3E%3C/svg%3E";
185
+ var overflowStyle = {
186
+ display: "-webkit-box",
187
+ WebkitLineClamp: 1,
188
+ WebkitBoxOrient: "vertical",
189
+ overflow: "hidden",
190
+ wordBreak: "break-word"
191
+ };
192
+ var overflowStyle2 = __spreadProps(__spreadValues({}, overflowStyle), {
193
+ WebkitLineClamp: 2
194
+ });
195
+ var PROPERTY_ID = "ogc_fid";
196
+ var LAYER_STATUS = {
197
+ ACTIVE: "Active",
198
+ PENDING: "Pending"
199
+ };
200
+ var SELECTION_STYLE = {
201
+ TOP: "layer_selection_top",
202
+ ALL: "layer_selection_all"
203
+ };
204
+
205
+ // src/utils/grid.ts
206
+ var getZoomConfig = (zoom) => {
207
+ if (zoom < 6)
208
+ return [4, 1, 39.2];
209
+ else if (zoom < 7)
210
+ return [5, 0, 19.6];
211
+ else if (zoom < 8)
212
+ return [5, 1, 9.8];
213
+ else if (zoom < 9)
214
+ return [5, -1, 4.9];
215
+ else if (zoom < 10)
216
+ return [6, 0, 2.45];
217
+ else if (zoom < 11)
218
+ return [6, 1, 1.225];
219
+ else if (zoom < 12)
220
+ return [7, 0, 0.612];
221
+ else if (zoom < 13)
222
+ return [7, 1, 0.306];
223
+ else if (zoom < 14)
224
+ return [7, -1, 0.153];
225
+ else if (zoom < 15)
226
+ return [8, 0, 0.077];
227
+ return [8, 1, 0.039];
228
+ };
229
+ var BASE32 = "0123456789bcdefghjkmnpqrstuvwxyz";
230
+ var aggregateGeohashKey = (key, level, binSize) => {
231
+ binSize = binSize || 16 / __pow(2, 1 - key.length & 1) / __pow(4, level);
232
+ const keyExceptLast = key.slice(0, -1);
233
+ const binnedCharAt = ~~(BASE32.indexOf(key.slice(-1)) / binSize);
234
+ return [
235
+ keyExceptLast + BASE32[binSize * binnedCharAt],
236
+ keyExceptLast + BASE32[binSize * (binnedCharAt + 1) - 1]
237
+ ];
238
+ };
239
+ var processRectangles = function(data, level) {
240
+ var counts = /* @__PURE__ */ new Map();
241
+ var bins = /* @__PURE__ */ new Map();
242
+ const features = [];
243
+ for (const [hash, count] of Object.entries(data)) {
244
+ const [kStart, kEnd] = aggregateGeohashKey(hash, level);
245
+ bins.set(kStart, kEnd);
246
+ if (!counts.has(kStart)) {
247
+ counts.set(kStart, 0);
248
+ }
249
+ counts.set(kStart, counts.get(kStart) + count);
250
+ }
251
+ counts.forEach((count, hash) => {
252
+ const bboxStart = GeoHash.decodeGeoHash(hash);
253
+ const bboxEnd = GeoHash.decodeGeoHash(bins.get(hash));
254
+ const feature = new BoundingBox({
255
+ minlat: bboxStart.latitude[0],
256
+ minlon: bboxStart.longitude[0],
257
+ maxlat: bboxEnd.latitude[1],
258
+ maxlon: bboxEnd.longitude[1]
259
+ }).toGeoJSON();
260
+ features.push(__spreadProps(__spreadValues({}, feature), { properties: { count, [PROPERTY_ID]: hash } }));
261
+ });
262
+ return features;
263
+ };
264
+ var processSquares = (data) => {
265
+ const features = [];
266
+ for (const [hash, count] of Object.entries(data)) {
267
+ const bbox = GeoHash.decodeGeoHash(hash);
268
+ const feature = new BoundingBox({
269
+ minlat: bbox.latitude[0],
270
+ minlon: bbox.longitude[0],
271
+ maxlat: bbox.latitude[1],
272
+ maxlon: bbox.longitude[1]
273
+ }).toGeoJSON();
274
+ features.push(__spreadProps(__spreadValues({}, feature), { properties: { count, [PROPERTY_ID]: hash } }));
275
+ }
276
+ return features;
277
+ };
278
+ var geohashToJSON = (data, level) => ({
279
+ type: "FeatureCollection",
280
+ features: Object.keys(data).length === 0 ? [] : level === -1 ? processSquares(data) : processRectangles(data, level)
281
+ });
282
+ var getDataBins = (data, binCount) => {
283
+ const sortedData = Object.values(data).sort((a, b) => a - b);
284
+ const cutoff = Math.floor(sortedData.length / binCount);
285
+ const tBins = new Array(binCount - 1).fill(0).map((_, index) => sortedData[cutoff * (index + 1)]);
286
+ tBins.push(sortedData[sortedData.length - 1]);
287
+ return tBins;
288
+ };
289
+
290
+ // src/utils/naksha.ts
291
+ import produce from "immer";
292
+ var parseGeoserverLayersXml = (layers, nakshaApiEndpoint, geoserver, selectedLayers) => __async(void 0, null, function* () {
293
+ const parsedLayers = [];
294
+ for (const l of layers) {
295
+ const isAdded = selectedLayers.includes(l.name);
296
+ const _l = __spreadProps(__spreadValues({}, l), {
297
+ id: l.name,
298
+ thumbnail: nakshaApiEndpoint + l.thumbnail,
299
+ source: {
300
+ type: l.layerType.toLowerCase() === "raster" ? "raster" : "vector",
301
+ scheme: "tms",
302
+ tiles: [
303
+ `${geoserver.endpoint}/gwc/service/tms/1.0.0/${geoserver.workspace}:${l.name}@EPSG%3A900913@pbf/{z}/{x}/{y}.pbf`
304
+ ]
305
+ },
306
+ data: { styles: [] },
307
+ isAdded
308
+ });
309
+ if (isAdded) {
310
+ const _ld = yield getLayerStyle(_l, 0, nakshaApiEndpoint, geoserver);
311
+ parsedLayers.push(__spreadProps(__spreadValues({}, _l), { data: _ld }));
312
+ } else {
313
+ parsedLayers.push(_l);
314
+ }
315
+ }
316
+ return parsedLayers;
317
+ });
318
+ var getLayerStyle = (layer, styleIndex, nakshaApiEndpoint, geoserver) => __async(void 0, null, function* () {
319
+ const nextSl = produce(layer.data, (_draft) => __async(void 0, null, function* () {
320
+ var _a;
321
+ if (_draft.styles.length === 0) {
322
+ const { success, data } = yield axGetGeoserverLayerStyleList(
323
+ layer.id,
324
+ nakshaApiEndpoint
325
+ );
326
+ if (success) {
327
+ _draft.layerName = data.layerName;
328
+ _draft.styles = data.styles;
329
+ _draft.summaryColumn = data.summaryColumn;
330
+ _draft.titleColumn = data.titleColumn;
331
+ _draft.propertyMap = Object.fromEntries(
332
+ data.styles.map((o) => [o.styleName, o.styleTitle])
333
+ );
334
+ }
335
+ }
336
+ if (_draft.styles[styleIndex] && !((_a = _draft.styles[styleIndex]) == null ? void 0 : _a.colors)) {
337
+ _draft.styles[styleIndex].colors = yield axGetGeoserverLayerStyle(
338
+ layer.id,
339
+ geoserver == null ? void 0 : geoserver.workspace,
340
+ _draft.styles[styleIndex].styleName,
341
+ nakshaApiEndpoint
342
+ );
343
+ }
344
+ _draft.styleIndex = styleIndex;
345
+ }));
346
+ return nextSl;
347
+ });
348
+
349
+ // src/services/naksha.ts
350
+ var axGetGeoserverLayers = (nakshaEndpointToken, nakshaApiEndpoint, geoserver, selectedLayers) => __async(void 0, null, function* () {
351
+ try {
352
+ const res = yield axios.get(`${nakshaApiEndpoint}/layer/all`, {
353
+ headers: { Authorization: nakshaEndpointToken }
354
+ });
355
+ const finalLayers = yield parseGeoserverLayersXml(
356
+ res.data,
357
+ nakshaApiEndpoint,
358
+ geoserver,
359
+ selectedLayers
360
+ );
361
+ return finalLayers;
362
+ } catch (e) {
363
+ console.error(e);
364
+ return [];
365
+ }
366
+ });
367
+ var axGetGeoserverLayerStyleList = (id, endpoint) => __async(void 0, null, function* () {
368
+ try {
369
+ const { data } = yield axios.get(`${endpoint}/layer/onClick/${id}`);
370
+ return { success: true, data };
371
+ } catch (e) {
372
+ console.error(e);
373
+ return { success: false };
374
+ }
375
+ });
376
+ var axGexGetRasterInfoWithLonLat = (endpoint, workspace, params) => __async(void 0, null, function* () {
377
+ const RasterInfoParams = {
378
+ service: "WMS",
379
+ version: "1.1.1",
380
+ request: "GetFeatureInfo",
381
+ info_format: "application/json",
382
+ width: 100,
383
+ height: 100,
384
+ x: 50,
385
+ y: 50,
386
+ srs: "EPSG:4326"
387
+ };
388
+ try {
389
+ const res = yield axios.get(`${endpoint}/${workspace}/wms`, {
390
+ params: __spreadValues(__spreadValues({}, params), RasterInfoParams)
391
+ });
392
+ return { success: true, data: res.data };
393
+ } catch (e) {
394
+ console.error(e);
395
+ return { success: false, data: [] };
396
+ }
397
+ });
398
+ var axToggleLayerPublishing = (nakshaEndpointToken, nakshaApiEndpoint, layerId, isActive) => __async(void 0, null, function* () {
399
+ try {
400
+ yield axios.put(
401
+ `${nakshaApiEndpoint}/layer/${isActive ? "active" : "pending"}/${layerId}`,
402
+ {},
403
+ { headers: { Authorization: nakshaEndpointToken } }
404
+ );
405
+ return true;
406
+ } catch (e) {
407
+ console.error(e);
408
+ return false;
409
+ }
410
+ });
411
+ var axDeleteLayer = (nakshaEndpointToken, nakshaApiEndpoint, layerId) => __async(void 0, null, function* () {
412
+ try {
413
+ yield axios.delete(`${nakshaApiEndpoint}/layer/${layerId}`, {
414
+ headers: { Authorization: nakshaEndpointToken }
415
+ });
416
+ return true;
417
+ } catch (e) {
418
+ console.error(e);
419
+ return false;
420
+ }
421
+ });
422
+ var axGetGeoserverLayerStyle = (layername, workspace, styleName, endpoint) => __async(void 0, null, function* () {
423
+ var _a, _b;
424
+ try {
425
+ const res = yield axios.get(
426
+ `${endpoint}/geoserver/workspaces/${workspace}/styles/${layername}_${styleName}.mbstyle`
427
+ );
428
+ return (_b = (_a = res.data) == null ? void 0 : _a.layers) == null ? void 0 : _b[0];
429
+ } catch (e) {
430
+ console.error(e);
431
+ return {};
432
+ }
433
+ });
434
+ var getGridLayerData = (fetcher, bounds, zoom, binCount = 6, colorScheme = "YlOrRd") => __async(void 0, null, function* () {
435
+ try {
436
+ const [geoAggegationPrecision, level, squareSize] = getZoomConfig(zoom);
437
+ const { _ne, _sw } = bounds;
438
+ const params = {
439
+ top: _ne.lat,
440
+ left: _sw.lng,
441
+ bottom: _sw.lat,
442
+ right: _ne.lng,
443
+ geoAggegationPrecision
444
+ };
445
+ const data = yield fetcher(params);
446
+ const geojson = geohashToJSON(data, level);
447
+ const bins = getDataBins(data, binCount);
448
+ const stops = bins.map((bin, index) => [
449
+ bin,
450
+ cb[colorScheme][binCount][index]
451
+ ]);
452
+ const paint2 = {
453
+ "fill-color": {
454
+ property: "count",
455
+ default: "yellow",
456
+ stops
457
+ },
458
+ "fill-outline-color": "rgba(0,0,0,0.2)",
459
+ "fill-opacity": 0.7
460
+ };
461
+ return { success: true, geojson, paint: paint2, stops, squareSize };
462
+ } catch (e) {
463
+ console.error(e);
464
+ return { success: false, geojson: {}, paint: {}, stops: [], squareSize: 0 };
465
+ }
466
+ });
467
+ var axDownloadLayer = (endpoint, token, layerName, layerTitle) => __async(void 0, null, function* () {
468
+ try {
469
+ yield axios.post(
470
+ `${endpoint}/layer/download`,
471
+ { layerName, layerTitle, attributeList: [], filterArray: [] },
472
+ { headers: { Authorization: token } }
473
+ );
474
+ } catch (e) {
475
+ console.error(e);
476
+ }
477
+ });
478
+
479
+ // src/hooks/use-layers.tsx
480
+ import { jsx } from "react/jsx-runtime";
481
+ var LayersContext = createContext(
482
+ {}
483
+ );
484
+ var LayersProvider = ({ mp: _mp, children }) => {
485
+ const [mp, setMP] = useState(_mp);
486
+ const { mapl } = useMap();
487
+ const [queryTerm, setQueryTerm] = useState("");
488
+ const queryTermDebounced = useDebounce(queryTerm, 500);
489
+ const [mapStyle, setMapStyle] = useState(
490
+ defaultMapStyles[(mp == null ? void 0 : mp.mapStyle) || 0].style
491
+ );
492
+ const [selectionStyle, setSelectionStyle] = useState(
493
+ SELECTION_STYLE.TOP
494
+ );
495
+ const [gridLegends, setGridLegends] = useState({});
496
+ const [isInfoBarOpen, setIsInfoBarOpen] = useState(true);
497
+ const [clickedLngLat, setClickedLngLat] = useState();
498
+ const [layers, setLayers] = useState(_mp.layers || []);
499
+ const [selectedLayerIds, setSelectedLayerIds] = useState(
500
+ mp.selectedLayers || []
501
+ );
502
+ const [hoverFeatures, setHoverFeatures] = useState();
503
+ const [selectedFeatures, setSelectedFeatures] = useState();
504
+ const selectedFeaturesId = useMemo(() => {
505
+ var _a;
506
+ const meta = {};
507
+ for (const qr of selectedFeatures || []) {
508
+ meta[qr.sourceLayer] = [
509
+ ...meta[qr.sourceLayer] || [],
510
+ (_a = qr == null ? void 0 : qr.properties) == null ? void 0 : _a[PROPERTY_ID]
511
+ ];
512
+ }
513
+ return Object.keys(meta).length ? meta : void 0;
514
+ }, [selectedFeatures]);
515
+ const selectedLayers = React.useMemo(() => {
516
+ const unsortedLayers = layers.filter(
517
+ (_layer) => selectedLayerIds.includes(_layer.id)
518
+ );
519
+ const sortedLayers = new Array(selectedLayerIds.length);
520
+ for (const layerToSort of unsortedLayers) {
521
+ const idx = selectedLayerIds.findIndex((l) => layerToSort.id === l);
522
+ if (idx > -1) {
523
+ sortedLayers[idx] = layerToSort;
524
+ }
525
+ }
526
+ return sortedLayers;
527
+ }, [layers, selectedLayerIds]);
528
+ const getLayerIndexById = (layerId) => {
529
+ return layers.findIndex((layer) => layer.id === layerId);
530
+ };
531
+ const updateLayerById = (layerId, updatedLayer) => {
532
+ setLayers(
533
+ (_layers) => _layers.map((l) => l.id === layerId ? __spreadValues(__spreadValues({}, l), updatedLayer) : l)
534
+ );
535
+ };
536
+ const toggleVectorLayer = (layerIndex, styleIndex, focus) => __async(void 0, null, function* () {
537
+ const layer = layers[layerIndex];
538
+ const layerData = yield getLayerStyle(
539
+ layer,
540
+ styleIndex,
541
+ mp.nakshaApiEndpoint,
542
+ mp.geoserver
543
+ );
544
+ updateLayerById(layer.id, { data: layerData });
545
+ focus && (mapl == null ? void 0 : mapl.fitBounds(layer.bbox, { padding: 40, duration: 1e3 }));
546
+ });
547
+ const updateLayerStyle = (layerId, styleIndex) => __async(void 0, null, function* () {
548
+ const layerIndex = getLayerIndexById(layerId);
549
+ toggleVectorLayer(layerIndex, styleIndex, false);
550
+ });
551
+ const onMapHover = (e) => __async(void 0, null, function* () {
552
+ var _a, _b, _c, _d;
553
+ if (!selectedLayerIds.length || !mapl)
554
+ return;
555
+ try {
556
+ const lastLayerId = selectedLayerIds[0];
557
+ const feats = mapl.queryRenderedFeatures(e.point, {
558
+ layers: [lastLayerId]
559
+ });
560
+ if (feats.length) {
561
+ const fId = ((_a = feats[0]) == null ? void 0 : _a.id) || ((_c = (_b = feats[0]) == null ? void 0 : _b.properties) == null ? void 0 : _c[PROPERTY_ID]);
562
+ if (fId === (hoverFeatures == null ? void 0 : hoverFeatures.id))
563
+ return;
564
+ const layer = layers[getLayerIndexById(lastLayerId)];
565
+ const hoverProperties = (_d = layer == null ? void 0 : layer.data) == null ? void 0 : _d.summaryColumn.map((sc) => {
566
+ var _a2, _b2, _c2;
567
+ return [
568
+ ((_b2 = (_a2 = layer.data) == null ? void 0 : _a2.propertyMap) == null ? void 0 : _b2[sc]) || sc,
569
+ (_c2 = feats[0].properties) == null ? void 0 : _c2[sc]
570
+ ];
571
+ });
572
+ setHoverFeatures({
573
+ id: fId,
574
+ title: layer.title,
575
+ data: hoverProperties
576
+ });
577
+ } else {
578
+ setHoverFeatures(void 0);
579
+ }
580
+ } catch (e2) {
581
+ }
582
+ });
583
+ const toggleLayer = (_0) => __async(void 0, [_0], function* ({
584
+ layerId,
585
+ add,
586
+ styleIndex = 0,
587
+ focus = true
588
+ }) {
589
+ var _a;
590
+ if (!add) {
591
+ setSelectedLayerIds(
592
+ selectedLayerIds.filter((_lyrId) => layerId !== _lyrId)
593
+ );
594
+ return;
595
+ }
596
+ const layerIndex = getLayerIndexById(layerId);
597
+ const sourceType = (_a = layers[layerIndex]) == null ? void 0 : _a.source.type;
598
+ yield toggleVectorLayer(layerIndex, styleIndex, focus);
599
+ setSelectedLayerIds((_slIds) => [
600
+ layerId,
601
+ ..._slIds.filter((lid) => lid !== layerId)
602
+ ]);
603
+ });
604
+ const clearAllLayers = () => __async(void 0, null, function* () {
605
+ return setSelectedLayerIds([]);
606
+ });
607
+ const updateMP = (key, value) => {
608
+ setMP(__spreadProps(__spreadValues({}, mp), { [key]: value }));
609
+ };
610
+ const toggleLayerPublishing = (layerId, layerStatus) => {
611
+ const isActive = layerStatus === LAYER_STATUS.PENDING;
612
+ axToggleLayerPublishing(
613
+ mp.nakshaEndpointToken,
614
+ mp.nakshaApiEndpoint,
615
+ layerId,
616
+ isActive
617
+ );
618
+ updateLayerById(layerId, {
619
+ layerStatus: isActive ? LAYER_STATUS.ACTIVE : LAYER_STATUS.PENDING
620
+ });
621
+ };
622
+ const deleteLayer = (layerId, message) => __async(void 0, null, function* () {
623
+ if (confirm(message)) {
624
+ axDeleteLayer(mp.nakshaEndpointToken, mp.nakshaApiEndpoint, layerId);
625
+ setLayers(layers.filter((l) => l.id !== layerId));
626
+ }
627
+ });
628
+ const zoomToExtent = (layerId) => {
629
+ const layerIndex = getLayerIndexById(layerId);
630
+ const layer = layers[layerIndex];
631
+ mapl == null ? void 0 : mapl.fitBounds(layer.bbox, { padding: 40, duration: 1e3 });
632
+ };
633
+ const getBBoxFromLngLat = () => {
634
+ return [
635
+ clickedLngLat.lng,
636
+ clickedLngLat.lat,
637
+ clickedLngLat.lng + 0.1,
638
+ clickedLngLat.lat + 0.1
639
+ ];
640
+ };
641
+ const handleSelectStyle = (value) => {
642
+ setSelectionStyle(value);
643
+ if (value === SELECTION_STYLE.TOP) {
644
+ featuresAtLatLng(value);
645
+ }
646
+ };
647
+ const featuresAtLatLng = (value) => {
648
+ if (!clickedLngLat)
649
+ return;
650
+ try {
651
+ const finalXY = mapl == null ? void 0 : mapl.project([clickedLngLat.lng, clickedLngLat.lat]);
652
+ let queryFeat = mapl == null ? void 0 : mapl.queryRenderedFeatures(finalXY, {
653
+ layers: selectionStyle === SELECTION_STYLE.TOP ? [selectedLayerIds[0]] : selectedLayerIds
654
+ });
655
+ if ((value || selectionStyle) === SELECTION_STYLE.ALL) {
656
+ const rasterLayerFeat = selectedLayers.filter((item) => item.layerType == "RASTER").map((item) => ({
657
+ sourceLayer: item.id,
658
+ layerType: "raster",
659
+ bbox: getBBoxFromLngLat()
660
+ }));
661
+ queryFeat = [...queryFeat, ...rasterLayerFeat];
662
+ }
663
+ setSelectedFeatures(
664
+ (selectedLayers == null ? void 0 : selectedLayers[0].layerType) === "RASTER" && selectionStyle !== SELECTION_STYLE.ALL ? selectedLayerIds.length && (queryFeat == null ? void 0 : queryFeat.length) ? queryFeat : [
665
+ {
666
+ sourceLayer: selectedLayerIds[0],
667
+ layerType: "raster",
668
+ bbox: getBBoxFromLngLat()
669
+ }
670
+ ] : queryFeat
671
+ );
672
+ } catch (e) {
673
+ console.error(e);
674
+ }
675
+ };
676
+ useEffect(() => {
677
+ if (mp.onSelectedLayersChange) {
678
+ mp.onSelectedLayersChange(selectedLayerIds);
679
+ }
680
+ }, [selectedLayerIds]);
681
+ useEffect(() => {
682
+ setTimeout(featuresAtLatLng, 300);
683
+ }, [clickedLngLat, selectionStyle, selectedLayerIds]);
684
+ return /* @__PURE__ */ jsx(LayersContext.Provider, {
685
+ value: {
686
+ mp,
687
+ updateMP,
688
+ layer: {
689
+ mapStyle,
690
+ featuresAtLatLng,
691
+ setMapStyle,
692
+ all: layers,
693
+ setAll: setLayers,
694
+ selectedIds: selectedLayerIds,
695
+ handleSelectStyle,
696
+ setSelectedIds: setSelectedLayerIds,
697
+ selectedLayers,
698
+ clearAll: clearAllLayers,
699
+ toggle: toggleLayer,
700
+ updateStyle: updateLayerStyle,
701
+ selectedFeatures,
702
+ selectedFeaturesId,
703
+ setSelectedFeatures,
704
+ togglePublish: toggleLayerPublishing,
705
+ delete: deleteLayer,
706
+ selectionStyle,
707
+ setSelectionStyle,
708
+ zoomToExtent,
709
+ gridLegends,
710
+ setGridLegends
711
+ },
712
+ query: {
713
+ term: queryTermDebounced,
714
+ setTerm: setQueryTerm,
715
+ clickedLngLat,
716
+ setClickedLngLat
717
+ },
718
+ isInfoBarOpen,
719
+ setIsInfoBarOpen,
720
+ hover: {
721
+ onHover: onMapHover,
722
+ features: hoverFeatures
723
+ }
724
+ },
725
+ children
726
+ });
727
+ };
728
+ function useLayers() {
729
+ return useContext(LayersContext);
730
+ }
731
+
732
+ // src/components/core/button.tsx
733
+ import React2 from "react";
734
+ import { tw as tw2 } from "twind";
735
+
736
+ // src/components/core/icons.tsx
737
+ import { tw } from "twind";
738
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
739
+ var SearchIcon = () => /* @__PURE__ */ jsx2("svg", {
740
+ fill: "none",
741
+ className: tw`w-5 h-5 text-gray-400`,
742
+ width: "24",
743
+ height: "24",
744
+ viewBox: "0 0 24 24",
745
+ children: /* @__PURE__ */ jsx2("path", {
746
+ stroke: "currentColor",
747
+ strokeLinecap: "round",
748
+ strokeLinejoin: "round",
749
+ strokeWidth: "2",
750
+ d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
751
+ })
752
+ });
753
+ var LayersIcon = () => /* @__PURE__ */ jsxs("svg", {
754
+ width: "18",
755
+ height: "18",
756
+ fill: "none",
757
+ stroke: "currentColor",
758
+ strokeLinecap: "round",
759
+ strokeLinejoin: "round",
760
+ strokeWidth: "2",
761
+ viewBox: "0 0 24 24",
762
+ children: [
763
+ /* @__PURE__ */ jsx2("path", {
764
+ d: "M12 2L2 7 12 12 22 7 12 2z"
765
+ }),
766
+ /* @__PURE__ */ jsx2("path", {
767
+ d: "M2 17L12 22 22 17"
768
+ }),
769
+ /* @__PURE__ */ jsx2("path", {
770
+ d: "M2 12L12 17 22 12"
771
+ })
772
+ ]
773
+ });
774
+ var InfoIcon = () => /* @__PURE__ */ jsxs("svg", {
775
+ width: "16",
776
+ height: "16",
777
+ viewBox: "0 0 24 24",
778
+ fill: "none",
779
+ stroke: "currentColor",
780
+ strokeWidth: "2",
781
+ strokeLinecap: "round",
782
+ strokeLinejoin: "round",
783
+ children: [
784
+ /* @__PURE__ */ jsx2("circle", {
785
+ cx: "12",
786
+ cy: "12",
787
+ r: "10"
788
+ }),
789
+ /* @__PURE__ */ jsx2("line", {
790
+ x1: "12",
791
+ y1: "16",
792
+ x2: "12",
793
+ y2: "12"
794
+ }),
795
+ /* @__PURE__ */ jsx2("line", {
796
+ x1: "12",
797
+ y1: "8",
798
+ x2: "12.01",
799
+ y2: "8"
800
+ })
801
+ ]
802
+ });
803
+ var SlidersIcon = () => /* @__PURE__ */ jsxs("svg", {
804
+ width: "18",
805
+ height: "18",
806
+ fill: "none",
807
+ stroke: "currentColor",
808
+ strokeLinecap: "round",
809
+ strokeLinejoin: "round",
810
+ strokeWidth: "2",
811
+ viewBox: "0 0 24 24",
812
+ children: [
813
+ /* @__PURE__ */ jsx2("path", {
814
+ d: "M4 21L4 14"
815
+ }),
816
+ /* @__PURE__ */ jsx2("path", {
817
+ d: "M4 10L4 3"
818
+ }),
819
+ /* @__PURE__ */ jsx2("path", {
820
+ d: "M12 21L12 12"
821
+ }),
822
+ /* @__PURE__ */ jsx2("path", {
823
+ d: "M12 8L12 3"
824
+ }),
825
+ /* @__PURE__ */ jsx2("path", {
826
+ d: "M20 21L20 16"
827
+ }),
828
+ /* @__PURE__ */ jsx2("path", {
829
+ d: "M20 12L20 3"
830
+ }),
831
+ /* @__PURE__ */ jsx2("path", {
832
+ d: "M1 14L7 14"
833
+ }),
834
+ /* @__PURE__ */ jsx2("path", {
835
+ d: "M9 8L15 8"
836
+ }),
837
+ /* @__PURE__ */ jsx2("path", {
838
+ d: "M17 16L23 16"
839
+ })
840
+ ]
841
+ });
842
+ function AttributionIcon() {
843
+ return /* @__PURE__ */ jsx2("svg", {
844
+ width: "14",
845
+ height: "14",
846
+ viewBox: "0 0 16 16",
847
+ style: { display: "inline-block" },
848
+ children: /* @__PURE__ */ jsx2("path", {
849
+ fillRule: "evenodd",
850
+ fill: "currentColor",
851
+ d: "M5.5 3.5a2 2 0 100 4 2 2 0 000-4zM2 5.5a3.5 3.5 0 115.898 2.549 5.507 5.507 0 013.034 4.084.75.75 0 11-1.482.235 4.001 4.001 0 00-7.9 0 .75.75 0 01-1.482-.236A5.507 5.507 0 013.102 8.05 3.49 3.49 0 012 5.5zM11 4a.75.75 0 100 1.5 1.5 1.5 0 01.666 2.844.75.75 0 00-.416.672v.352a.75.75 0 00.574.73c1.2.289 2.162 1.2 2.522 2.372a.75.75 0 101.434-.44 5.01 5.01 0 00-2.56-3.012A3 3 0 0011 4z"
852
+ })
853
+ });
854
+ }
855
+ function TagIcon() {
856
+ return /* @__PURE__ */ jsx2("svg", {
857
+ width: "14",
858
+ height: "14",
859
+ viewBox: "0 0 16 16",
860
+ style: { display: "inline-block" },
861
+ children: /* @__PURE__ */ jsx2("path", {
862
+ fillRule: "evenodd",
863
+ fill: "currentColor",
864
+ d: "M2.5 7.775V2.75a.25.25 0 01.25-.25h5.025a.25.25 0 01.177.073l6.25 6.25a.25.25 0 010 .354l-5.025 5.025a.25.25 0 01-.354 0l-6.25-6.25a.25.25 0 01-.073-.177zm-1.5 0V2.75C1 1.784 1.784 1 2.75 1h5.025c.464 0 .91.184 1.238.513l6.25 6.25a1.75 1.75 0 010 2.474l-5.026 5.026a1.75 1.75 0 01-2.474 0l-6.25-6.25A1.75 1.75 0 011 7.775zM6 5a1 1 0 100 2 1 1 0 000-2z"
865
+ })
866
+ });
867
+ }
868
+ function LicenseIcon() {
869
+ return /* @__PURE__ */ jsx2("svg", {
870
+ width: "14",
871
+ height: "14",
872
+ viewBox: "0 0 16 16",
873
+ style: { display: "inline-block" },
874
+ children: /* @__PURE__ */ jsx2("path", {
875
+ fillRule: "evenodd",
876
+ fill: "currentColor",
877
+ d: "M8.75.75a.75.75 0 00-1.5 0V2h-.984c-.305 0-.604.08-.869.23l-1.288.737A.25.25 0 013.984 3H1.75a.75.75 0 000 1.5h.428L.066 9.192a.75.75 0 00.154.838l.53-.53-.53.53v.001l.002.002.002.002.006.006.016.015.045.04a3.514 3.514 0 00.686.45A4.492 4.492 0 003 11c.88 0 1.556-.22 2.023-.454a3.515 3.515 0 00.686-.45l.045-.04.016-.015.006-.006.002-.002.001-.002L5.25 9.5l.53.53a.75.75 0 00.154-.838L3.822 4.5h.162c.305 0 .604-.08.869-.23l1.289-.737a.25.25 0 01.124-.033h.984V13h-2.5a.75.75 0 000 1.5h6.5a.75.75 0 000-1.5h-2.5V3.5h.984a.25.25 0 01.124.033l1.29.736c.264.152.563.231.868.231h.162l-2.112 4.692a.75.75 0 00.154.838l.53-.53-.53.53v.001l.002.002.002.002.006.006.016.015.045.04a3.517 3.517 0 00.686.45A4.492 4.492 0 0013 11c.88 0 1.556-.22 2.023-.454a3.512 3.512 0 00.686-.45l.045-.04.01-.01.006-.005.006-.006.002-.002.001-.002-.529-.531.53.53a.75.75 0 00.154-.838L13.823 4.5h.427a.75.75 0 000-1.5h-2.234a.25.25 0 01-.124-.033l-1.29-.736A1.75 1.75 0 009.735 2H8.75V.75zM1.695 9.227c.285.135.718.273 1.305.273s1.02-.138 1.305-.273L3 6.327l-1.305 2.9zm10 0c.285.135.718.273 1.305.273s1.02-.138 1.305-.273L13 6.327l-1.305 2.9z"
878
+ })
879
+ });
880
+ }
881
+ function EyeIcon() {
882
+ return /* @__PURE__ */ jsx2("svg", {
883
+ viewBox: "0 0 16 16",
884
+ width: "14",
885
+ height: "14",
886
+ style: { display: "inline-block" },
887
+ children: /* @__PURE__ */ jsx2("path", {
888
+ fillRule: "evenodd",
889
+ fill: "currentColor",
890
+ d: "M1.679 7.932c.412-.621 1.242-1.75 2.366-2.717C5.175 4.242 6.527 3.5 8 3.5c1.473 0 2.824.742 3.955 1.715 1.124.967 1.954 2.096 2.366 2.717a.119.119 0 010 .136c-.412.621-1.242 1.75-2.366 2.717C10.825 11.758 9.473 12.5 8 12.5c-1.473 0-2.824-.742-3.955-1.715C2.92 9.818 2.09 8.69 1.679 8.068a.119.119 0 010-.136zM8 2c-1.981 0-3.67.992-4.933 2.078C1.797 5.169.88 6.423.43 7.1a1.619 1.619 0 000 1.798c.45.678 1.367 1.932 2.637 3.024C4.329 13.008 6.019 14 8 14c1.981 0 3.67-.992 4.933-2.078 1.27-1.091 2.187-2.345 2.637-3.023a1.619 1.619 0 000-1.798c-.45-.678-1.367-1.932-2.637-3.023C11.671 2.992 9.981 2 8 2zm0 8a2 2 0 100-4 2 2 0 000 4z"
891
+ })
892
+ });
893
+ }
894
+ function ClockIcon() {
895
+ return /* @__PURE__ */ jsx2("svg", {
896
+ viewBox: "0 0 16 16",
897
+ width: "14",
898
+ height: "14",
899
+ style: { display: "inline-block" },
900
+ children: /* @__PURE__ */ jsx2("path", {
901
+ fillRule: "evenodd",
902
+ fill: "currentColor",
903
+ d: "M1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0zM8 0a8 8 0 100 16A8 8 0 008 0zm.5 4.75a.75.75 0 00-1.5 0v3.5a.75.75 0 00.471.696l2.5 1a.75.75 0 00.557-1.392L8.5 7.742V4.75z"
904
+ })
905
+ });
906
+ }
907
+ function DownloadIcon() {
908
+ return /* @__PURE__ */ jsx2("svg", {
909
+ viewBox: "0 0 16 16",
910
+ width: "16",
911
+ height: "16",
912
+ style: { display: "inline-block" },
913
+ children: /* @__PURE__ */ jsx2("path", {
914
+ fillRule: "evenodd",
915
+ fill: "currentColor",
916
+ d: "M7.47 10.78a.75.75 0 001.06 0l3.75-3.75a.75.75 0 00-1.06-1.06L8.75 8.44V1.75a.75.75 0 00-1.5 0v6.69L4.78 5.97a.75.75 0 00-1.06 1.06l3.75 3.75zM3.75 13a.75.75 0 000 1.5h8.5a.75.75 0 000-1.5h-8.5z"
917
+ })
918
+ });
919
+ }
920
+ function ZoomExtentIcon() {
921
+ return /* @__PURE__ */ jsx2("svg", {
922
+ viewBox: "0 0 24 24",
923
+ width: "16",
924
+ height: "16",
925
+ fill: "none",
926
+ stroke: "currentColor",
927
+ strokeWidth: "2",
928
+ strokeLinecap: "round",
929
+ strokeLinejoin: "round",
930
+ style: { display: "inline-block" },
931
+ children: /* @__PURE__ */ jsx2("path", {
932
+ d: "M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"
933
+ })
934
+ });
935
+ }
936
+ function ShareIcon() {
937
+ return /* @__PURE__ */ jsxs("svg", {
938
+ viewBox: "0 0 24 24",
939
+ width: "16",
940
+ height: "16",
941
+ fill: "none",
942
+ stroke: "currentColor",
943
+ strokeWidth: "2",
944
+ strokeLinecap: "round",
945
+ strokeLinejoin: "round",
946
+ style: { display: "inline-block" },
947
+ children: [
948
+ /* @__PURE__ */ jsx2("circle", {
949
+ cx: "18",
950
+ cy: "5",
951
+ r: "3"
952
+ }),
953
+ /* @__PURE__ */ jsx2("circle", {
954
+ cx: "6",
955
+ cy: "12",
956
+ r: "3"
957
+ }),
958
+ /* @__PURE__ */ jsx2("circle", {
959
+ cx: "18",
960
+ cy: "19",
961
+ r: "3"
962
+ }),
963
+ /* @__PURE__ */ jsx2("line", {
964
+ x1: "8.59",
965
+ y1: "13.51",
966
+ x2: "15.42",
967
+ y2: "17.49"
968
+ }),
969
+ /* @__PURE__ */ jsx2("line", {
970
+ x1: "15.41",
971
+ y1: "6.51",
972
+ x2: "8.59",
973
+ y2: "10.49"
974
+ })
975
+ ]
976
+ });
977
+ }
978
+ function GrabberIcon() {
979
+ return /* @__PURE__ */ jsx2("svg", {
980
+ viewBox: "0 0 16 16",
981
+ width: "16",
982
+ height: "16",
983
+ style: { display: "inline-block" },
984
+ children: /* @__PURE__ */ jsx2("path", {
985
+ fillRule: "evenodd",
986
+ d: "M10 13a1 1 0 100-2 1 1 0 000 2zm-4 0a1 1 0 100-2 1 1 0 000 2zm1-5a1 1 0 11-2 0 1 1 0 012 0zm3 1a1 1 0 100-2 1 1 0 000 2zm1-5a1 1 0 11-2 0 1 1 0 012 0zM6 5a1 1 0 100-2 1 1 0 000 2z"
987
+ })
988
+ });
989
+ }
990
+ function CrossHairIcon() {
991
+ return /* @__PURE__ */ jsxs("svg", {
992
+ style: { display: "inline-block" },
993
+ width: "18",
994
+ height: "18",
995
+ viewBox: "0 0 24 24",
996
+ fill: "none",
997
+ stroke: "currentColor",
998
+ strokeWidth: "2",
999
+ strokeLinecap: "round",
1000
+ strokeLinejoin: "round",
1001
+ children: [
1002
+ /* @__PURE__ */ jsx2("circle", {
1003
+ cx: "12",
1004
+ cy: "12",
1005
+ r: "10"
1006
+ }),
1007
+ /* @__PURE__ */ jsx2("line", {
1008
+ x1: "22",
1009
+ y1: "12",
1010
+ x2: "18",
1011
+ y2: "12"
1012
+ }),
1013
+ /* @__PURE__ */ jsx2("line", {
1014
+ x1: "6",
1015
+ y1: "12",
1016
+ x2: "2",
1017
+ y2: "12"
1018
+ }),
1019
+ /* @__PURE__ */ jsx2("line", {
1020
+ x1: "12",
1021
+ y1: "6",
1022
+ x2: "12",
1023
+ y2: "2"
1024
+ }),
1025
+ /* @__PURE__ */ jsx2("line", {
1026
+ x1: "12",
1027
+ y1: "22",
1028
+ x2: "12",
1029
+ y2: "18"
1030
+ })
1031
+ ]
1032
+ });
1033
+ }
1034
+ function DownIcon() {
1035
+ return /* @__PURE__ */ jsx2("svg", {
1036
+ width: "18",
1037
+ height: "18",
1038
+ viewBox: "0 0 24 24",
1039
+ fill: "none",
1040
+ stroke: "currentColor",
1041
+ strokeWidth: "2",
1042
+ strokeLinecap: "round",
1043
+ strokeLinejoin: "round",
1044
+ style: { display: "inline-block" },
1045
+ children: /* @__PURE__ */ jsx2("polyline", {
1046
+ points: "6 9 12 15 18 9"
1047
+ })
1048
+ });
1049
+ }
1050
+ function UpIcon() {
1051
+ return /* @__PURE__ */ jsx2("svg", {
1052
+ width: "18",
1053
+ height: "18",
1054
+ viewBox: "0 0 24 24",
1055
+ fill: "none",
1056
+ stroke: "currentColor",
1057
+ strokeWidth: "2",
1058
+ strokeLinecap: "round",
1059
+ strokeLinejoin: "round",
1060
+ style: { display: "inline-block" },
1061
+ children: /* @__PURE__ */ jsx2("polyline", {
1062
+ points: "18 15 12 9 6 15"
1063
+ })
1064
+ });
1065
+ }
1066
+
1067
+ // src/components/core/button.tsx
1068
+ import { jsx as jsx3 } from "react/jsx-runtime";
1069
+ var Button = React2.forwardRef((props, ref) => /* @__PURE__ */ jsx3("button", __spreadValues({
1070
+ ref,
1071
+ type: "button",
1072
+ className: tw2`h-8 px-3 py-2 rounded-md focus:outline-none focus:ring cursor-pointer text-md flex align-middle items-center gap-2 bg-gray-100 hover:bg-gray-200 text-gray-700 disabled:cursor-not-allowed disabled:bg-gray-100! disabled:opacity-50`
1073
+ }, props)));
1074
+ var CloseButton = (props) => /* @__PURE__ */ jsx3("button", __spreadValues({
1075
+ className: tw2`absolute top-0 right-0 h-12 w-12 bg-red-100 cursor-pointer hover:bg-red-200 text-red-800 text-lg`,
1076
+ children: "\u2715"
1077
+ }, props));
1078
+ var LayersButton = (props) => /* @__PURE__ */ jsx3("button", __spreadProps(__spreadValues({
1079
+ className: tw2`absolute top-4 left-4 rounded-lg z-10 h-10 w-10 bg-white cursor-pointer hover:bg-gray-100 text-gray-700 text-lg flex items-center justify-center`
1080
+ }, props), {
1081
+ children: /* @__PURE__ */ jsx3(LayersIcon, {})
1082
+ }));
1083
+ var InfobarButton = (props) => /* @__PURE__ */ jsx3("button", __spreadProps(__spreadValues({
1084
+ className: tw2`absolute top-4 right-4 rounded-lg z-10 h-10 w-10 bg-white cursor-pointer hover:bg-gray-100 text-gray-700 text-lg flex items-center justify-center`
1085
+ }, props), {
1086
+ children: /* @__PURE__ */ jsx3(InfoIcon, {})
1087
+ }));
1088
+
1089
+ // src/components/core/input.tsx
1090
+ import { tw as tw3 } from "twind";
1091
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
1092
+ var SelectInput = (props) => /* @__PURE__ */ jsxs2("div", {
1093
+ children: [
1094
+ props.label && /* @__PURE__ */ jsx4("label", {
1095
+ className: tw3`text-gray-700`,
1096
+ htmlFor: props.name,
1097
+ children: props.label
1098
+ }),
1099
+ /* @__PURE__ */ jsx4("select", __spreadValues({
1100
+ id: props.name,
1101
+ name: props.name,
1102
+ className: tw3`block w-full px-4 py-2 mt-2 text-gray-700 border bg-white border-gray-200 rounded-md focus:outline-none focus:ring appearance-none text-base`,
1103
+ style: {
1104
+ backgroundImage: `url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3E%3C/svg%3E")`,
1105
+ backgroundPosition: "right 0.75rem center",
1106
+ backgroundSize: "16px 12px",
1107
+ backgroundRepeat: "no-repeat"
1108
+ }
1109
+ }, props))
1110
+ ]
1111
+ });
1112
+ var SearchInput = (props) => /* @__PURE__ */ jsxs2("div", {
1113
+ className: "relative",
1114
+ children: [
1115
+ /* @__PURE__ */ jsx4("span", {
1116
+ className: tw3`absolute inset-y-0 left-0 flex items-center pl-3`,
1117
+ children: /* @__PURE__ */ jsx4(SearchIcon, {})
1118
+ }),
1119
+ /* @__PURE__ */ jsx4("input", __spreadValues({
1120
+ type: "search",
1121
+ className: tw3`w-full py-2 pl-10 pr-4 text-gray-700 bg-white border border-gray-300 text-base rounded-md focus:outline-none focus:ring`
1122
+ }, props))
1123
+ ]
1124
+ });
1125
+ var CheckboxInput = (props) => props.isLoading ? /* @__PURE__ */ jsx4("svg", {
1126
+ width: "20px",
1127
+ height: "20px",
1128
+ viewBox: "0 0 20 20",
1129
+ version: "1.1",
1130
+ className: tw3`inline text-gray-200 animate-spin dark:text-gray-600`,
1131
+ children: /* @__PURE__ */ jsx4("g", {
1132
+ stroke: "none",
1133
+ strokeWidth: "1",
1134
+ fill: "none",
1135
+ fillRule: "evenodd",
1136
+ children: /* @__PURE__ */ jsx4("g", {
1137
+ fill: "#212121",
1138
+ fillRule: "nonzero",
1139
+ children: /* @__PURE__ */ jsx4("path", {
1140
+ d: "M10,3 C6.13401,3 3,6.13401 3,10 C3,10.2761 2.77614,10.5 2.5,10.5 C2.22386,10.5 2,10.2761 2,10 C2,5.58172 5.58172,2 10,2 C14.4183,2 18,5.58172 18,10 C18,14.4183 14.4183,18 10,18 C9.72386,18 9.5,17.7761 9.5,17.5 C9.5,17.2239 9.72386,17 10,17 C13.866,17 17,13.866 17,10 C17,6.13401 13.866,3 10,3 Z"
1141
+ })
1142
+ })
1143
+ })
1144
+ }) : /* @__PURE__ */ jsx4("input", {
1145
+ type: "checkbox",
1146
+ className: tw3`w-5 h-5 border-gray-100 focus:outline-none focus:ring focus:ring-blue-300 focus:ring-opacity-80`,
1147
+ name: props.name,
1148
+ checked: props.checked,
1149
+ onChange: props.onChange
1150
+ });
1151
+
1152
+ // src/components/core/tabs.tsx
1153
+ import { Tabs, usePanelState, useTabState } from "@bumaga/tabs";
1154
+ import clsx from "clsx";
1155
+ import { tw as tw4 } from "twind";
1156
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
1157
+ var IconTab = ({ children, icon }) => {
1158
+ const { onClick, isActive } = useTabState();
1159
+ const classes = clsx([
1160
+ "flex items-center justify-center h-12 px-2 py-2 bg-transparent -mb-px border-b-2 -px-1 whitespace-nowrap focus:outline-none w-full cursor-pointer",
1161
+ {
1162
+ "text-blue-600 border-blue-500": isActive,
1163
+ "text-gray-700 border-gray-300 hover:border-gray-400": !isActive
1164
+ }
1165
+ ]);
1166
+ return /* @__PURE__ */ jsxs3("button", {
1167
+ className: tw4(classes),
1168
+ onClick,
1169
+ children: [
1170
+ icon,
1171
+ /* @__PURE__ */ jsx5("span", {
1172
+ className: tw4`ml-2 text-base`,
1173
+ children
1174
+ })
1175
+ ]
1176
+ });
1177
+ };
1178
+ var Panel = ({ children }) => {
1179
+ const isActive = usePanelState();
1180
+ return isActive ? /* @__PURE__ */ jsx5("div", {
1181
+ className: tw4`w-full flex flex-grow-1 overflow-auto`,
1182
+ children
1183
+ }) : null;
1184
+ };
1185
+ var TabHeader = ({ children }) => /* @__PURE__ */ jsx5("div", {
1186
+ className: tw4`flex flex-shrink-0 border-b border-gray-200 justify-around pr-12`,
1187
+ children
1188
+ });
1189
+
1190
+ // src/components/infobar/content.tsx
1191
+ import { useT as useT2 } from "@biodiv-platform/naksha-commons";
1192
+ import { tw as tw6 } from "twind";
1193
+
1194
+ // src/components/sidebar/settings/layer-selection.tsx
1195
+ import { useT } from "@biodiv-platform/naksha-commons";
1196
+ import { jsx as jsx6 } from "react/jsx-runtime";
1197
+ function LayerSelection({ hideLabel }) {
1198
+ const {
1199
+ layer: { selectionStyle, handleSelectStyle }
1200
+ } = useLayers();
1201
+ const { t } = useT();
1202
+ const handleOnSelectionStyleChange = (e) => {
1203
+ handleSelectStyle(e.target.value);
1204
+ };
1205
+ return /* @__PURE__ */ jsx6(SelectInput, {
1206
+ name: "layer_selection",
1207
+ label: hideLabel ? null : t("layer_selection"),
1208
+ defaultValue: selectionStyle,
1209
+ onChange: handleOnSelectionStyleChange,
1210
+ children: Object.values(SELECTION_STYLE).map((ss) => /* @__PURE__ */ jsx6("option", {
1211
+ value: ss,
1212
+ children: t(ss)
1213
+ }, ss))
1214
+ });
1215
+ }
1216
+
1217
+ // src/components/infobar/infobar-panel.tsx
1218
+ import clsx2 from "clsx";
1219
+ import { useEffect as useEffect2, useState as useState2 } from "react";
1220
+ import { tw as tw5 } from "twind";
1221
+ import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
1222
+ function InfoBarPanel({ data: payload }) {
1223
+ const [isOpen, setIsOpen] = useState2(true);
1224
+ const [layerInfo, setLayerInfo] = useState2({
1225
+ title: payload.sourceLayer,
1226
+ properties: []
1227
+ });
1228
+ const { layer, mp, query: { clickedLngLat } } = useLayers();
1229
+ const getPropertyData = () => __async(this, null, function* () {
1230
+ var _a, _b, _c, _d, _e, _f;
1231
+ let properties;
1232
+ const currentLayer = layer.selectedLayers.find(
1233
+ (l) => l.id === (payload.sourceLayer || payload.source)
1234
+ );
1235
+ if (currentLayer.layerType.toLowerCase() === "raster") {
1236
+ const { data } = yield axGexGetRasterInfoWithLonLat(
1237
+ (_a = mp.geoserver) == null ? void 0 : _a.endpoint,
1238
+ (_b = mp.geoserver) == null ? void 0 : _b.workspace,
1239
+ {
1240
+ bbox: payload.bbox.toString(),
1241
+ query_layers: `${(_c = mp.geoserver) == null ? void 0 : _c.workspace}:${currentLayer.id}`,
1242
+ layers: `${(_d = mp.geoserver) == null ? void 0 : _d.workspace}:${currentLayer.id}`
1243
+ }
1244
+ );
1245
+ properties = (data == null ? void 0 : data.features[0]) ? Object.entries((_e = data.features[0]) == null ? void 0 : _e.properties).map(([v, k]) => [
1246
+ k || "-"
1247
+ ]) : [];
1248
+ } else {
1249
+ properties = Object.entries(((_f = currentLayer == null ? void 0 : currentLayer.data) == null ? void 0 : _f.propertyMap) || {}).map(
1250
+ ([k, v]) => {
1251
+ var _a2;
1252
+ return [v, (_a2 = payload == null ? void 0 : payload.properties) == null ? void 0 : _a2[k]];
1253
+ }
1254
+ );
1255
+ }
1256
+ setLayerInfo({ title: currentLayer.title, properties });
1257
+ });
1258
+ useEffect2(() => {
1259
+ getPropertyData();
1260
+ }, [clickedLngLat]);
1261
+ return /* @__PURE__ */ jsxs4("div", {
1262
+ className: tw5`bg-gray-100 rounded-lg`,
1263
+ children: [
1264
+ /* @__PURE__ */ jsxs4("button", {
1265
+ className: tw5(
1266
+ clsx2([
1267
+ `px-4 h-10 flex items-center justify-between bg-gray-100 hover:bg-gray-200 transition-colors cursor-pointer w-full focus:outline-none focus:ring`,
1268
+ { "bg-gray-200 rounded-t-lg": isOpen, "rounded-lg": !isOpen }
1269
+ ])
1270
+ ),
1271
+ onClick: () => setIsOpen(!isOpen),
1272
+ children: [
1273
+ layerInfo.title,
1274
+ " ",
1275
+ isOpen ? /* @__PURE__ */ jsx7(UpIcon, {}) : /* @__PURE__ */ jsx7(DownIcon, {})
1276
+ ]
1277
+ }),
1278
+ isOpen && /* @__PURE__ */ jsx7("div", {
1279
+ className: tw5`px-4 py-3 flex flex-col gap-3`,
1280
+ children: layerInfo.properties.map(([k, v], index) => /* @__PURE__ */ jsxs4("div", {
1281
+ children: [
1282
+ /* @__PURE__ */ jsx7("div", {
1283
+ className: tw5`text-gray-600`,
1284
+ children: k
1285
+ }),
1286
+ /* @__PURE__ */ jsx7("div", {
1287
+ children: v
1288
+ })
1289
+ ]
1290
+ }, k + v + index))
1291
+ })
1292
+ ]
1293
+ });
1294
+ }
1295
+
1296
+ // src/components/infobar/content.tsx
1297
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
1298
+ function InfoBarContent({ onClose }) {
1299
+ var _a;
1300
+ const {
1301
+ layer: { selectedFeatures, selectedLayers, selectionStyle }
1302
+ } = useLayers();
1303
+ const { t } = useT2();
1304
+ return /* @__PURE__ */ jsxs5("div", {
1305
+ className: tw6`absolute top-0 right-0 bottom-0 left-0 md:top-4 md:right-4 md:bottom-4 md:left-auto bg-white rounded-lg overflow-hidden shadow-md md:max-w-sm w-full z-20 flex flex-col`,
1306
+ children: [
1307
+ /* @__PURE__ */ jsxs5("div", {
1308
+ className: "flex w-full",
1309
+ children: [
1310
+ /* @__PURE__ */ jsxs5("div", {
1311
+ className: tw6`h-12 px-4 flex items-center gap-3 flex-grow bg-gray-200`,
1312
+ children: [
1313
+ /* @__PURE__ */ jsx8(CrossHairIcon, {}),
1314
+ " ",
1315
+ t("infobar")
1316
+ ]
1317
+ }),
1318
+ /* @__PURE__ */ jsx8(CloseButton, {
1319
+ onClick: onClose
1320
+ })
1321
+ ]
1322
+ }),
1323
+ /* @__PURE__ */ jsx8("div", {
1324
+ className: tw6`bg-gray-100 p-4 flex-shrink-0 rt`,
1325
+ children: /* @__PURE__ */ jsx8(LayerSelection, {
1326
+ hideLabel: true
1327
+ })
1328
+ }),
1329
+ /* @__PURE__ */ jsx8("div", {
1330
+ className: tw6`flex flex-col flex-grow overflow-auto gap-3 p-4`,
1331
+ children: (_a = selectedFeatures.flat(1)) == null ? void 0 : _a.map((data) => {
1332
+ var _a2;
1333
+ return /* @__PURE__ */ jsx8(InfoBarPanel, {
1334
+ data
1335
+ }, ((_a2 = selectedLayers == null ? void 0 : selectedLayers[0]) == null ? void 0 : _a2.source.type) === "raster" || selectionStyle === SELECTION_STYLE.ALL ? data == null ? void 0 : data.sourceLayer : (data == null ? void 0 : data.sourceLayer) + (data == null ? void 0 : data.properties[PROPERTY_ID]));
1336
+ })
1337
+ })
1338
+ ]
1339
+ });
1340
+ }
1341
+
1342
+ // src/components/infobar/index.tsx
1343
+ import { jsx as jsx9 } from "react/jsx-runtime";
1344
+ function InfoBar() {
1345
+ var _a;
1346
+ const { layer, isInfoBarOpen, setIsInfoBarOpen } = useLayers();
1347
+ if (!((_a = layer.selectedFeatures) == null ? void 0 : _a.length))
1348
+ return null;
1349
+ const toggleOpen = () => setIsInfoBarOpen(!isInfoBarOpen);
1350
+ return isInfoBarOpen ? /* @__PURE__ */ jsx9(InfoBarContent, {
1351
+ onClose: toggleOpen
1352
+ }) : /* @__PURE__ */ jsx9(InfobarButton, {
1353
+ onClick: toggleOpen
1354
+ });
1355
+ }
1356
+
1357
+ // src/components/sidebar/index.tsx
1358
+ import { useEffect as useEffect3, useState as useState8 } from "react";
1359
+ import { useMap as useMap2 } from "react-map-gl/maplibre";
1360
+
1361
+ // src/components/sidebar/tabs.tsx
1362
+ import { useT as useT10 } from "@biodiv-platform/naksha-commons";
1363
+ import { tw as tw18 } from "twind";
1364
+
1365
+ // src/components/sidebar/layers/index.tsx
1366
+ import { tw as tw15 } from "twind";
1367
+
1368
+ // src/components/sidebar/layers/layer-list.tsx
1369
+ import React8, { useMemo as useMemo4 } from "react";
1370
+ import { useVirtual } from "react-virtual";
1371
+ import AutoSizer from "react-virtualized-auto-sizer";
1372
+ import { tw as tw13 } from "twind";
1373
+
1374
+ // src/components/sidebar/common/layer-item.tsx
1375
+ import { useT as useT6 } from "@biodiv-platform/naksha-commons";
1376
+ import { useMemo as useMemo3, useState as useState6 } from "react";
1377
+ import { SortableHandle } from "react-sortable-hoc";
1378
+ import { RWebShare } from "react-web-share";
1379
+ import { tw as tw12 } from "twind";
1380
+
1381
+ // src/components/core/highlighter.tsx
1382
+ import { Fragment, jsx as jsx10 } from "react/jsx-runtime";
1383
+ var Highlighted = ({ text = "", highlight = "" }) => {
1384
+ if (!highlight.trim()) {
1385
+ return /* @__PURE__ */ jsx10(Fragment, {
1386
+ children: text
1387
+ });
1388
+ }
1389
+ const regex = new RegExp(`(${highlight})`, "gi");
1390
+ const parts = text.split(regex);
1391
+ return /* @__PURE__ */ jsx10(Fragment, {
1392
+ children: parts.filter((part) => part).map(
1393
+ (part, i) => regex.test(part) ? /* @__PURE__ */ jsx10("mark", {
1394
+ children: part
1395
+ }, i) : /* @__PURE__ */ jsx10("span", {
1396
+ children: part
1397
+ }, i)
1398
+ )
1399
+ });
1400
+ };
1401
+
1402
+ // src/components/sidebar/common/grid-legend.tsx
1403
+ import { tw as tw8 } from "twind";
1404
+
1405
+ // src/components/sidebar/common/moreless.tsx
1406
+ import { useT as useT3 } from "@biodiv-platform/naksha-commons";
1407
+ import { useState as useState3 } from "react";
1408
+ import { tw as tw7 } from "twind";
1409
+ import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
1410
+ function MoreLess({ children }) {
1411
+ const [showMore, setShowMore] = useState3(false);
1412
+ const { t } = useT3();
1413
+ return /* @__PURE__ */ jsxs6("div", {
1414
+ children: [
1415
+ showMore && children,
1416
+ /* @__PURE__ */ jsx11("button", {
1417
+ onClick: () => setShowMore(!showMore),
1418
+ className: tw7`text-blue-600 focus:outline-none focus:outline focus:ring`,
1419
+ children: showMore ? t("less") : t("legend")
1420
+ })
1421
+ ]
1422
+ });
1423
+ }
1424
+
1425
+ // src/components/sidebar/common/grid-legend.tsx
1426
+ import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
1427
+ function GridLegend({ item }) {
1428
+ const { layer } = useLayers();
1429
+ const legendInfo = layer.gridLegends[item.id];
1430
+ if (!legendInfo)
1431
+ return null;
1432
+ return /* @__PURE__ */ jsx12(MoreLess, {
1433
+ children: /* @__PURE__ */ jsxs7("ul", {
1434
+ style: { margin: 0, padding: 0 },
1435
+ children: [
1436
+ legendInfo == null ? void 0 : legendInfo.stops.map(([stop, color], index, stopsArr) => {
1437
+ const prevStop = (stopsArr[index - 1] || [0])[0];
1438
+ if (prevStop === stop)
1439
+ return /* @__PURE__ */ jsx12("div", {}, color);
1440
+ return /* @__PURE__ */ jsxs7("li", {
1441
+ className: tw8`flex gap-2 items-center mb-1`,
1442
+ children: [
1443
+ /* @__PURE__ */ jsx12("svg", {
1444
+ viewBox: "0 0 24 24",
1445
+ height: "14",
1446
+ width: "14",
1447
+ focusable: "false",
1448
+ children: /* @__PURE__ */ jsx12("circle", {
1449
+ cx: "12",
1450
+ fill: color,
1451
+ cy: "12",
1452
+ r: "12",
1453
+ stroke: "none"
1454
+ })
1455
+ }),
1456
+ /* @__PURE__ */ jsxs7("div", {
1457
+ children: [
1458
+ prevStop,
1459
+ " - ",
1460
+ stop
1461
+ ]
1462
+ })
1463
+ ]
1464
+ }, color);
1465
+ }),
1466
+ /* @__PURE__ */ jsxs7("li", {
1467
+ children: [
1468
+ "1 Square = ",
1469
+ legendInfo == null ? void 0 : legendInfo.squareSize,
1470
+ " x ",
1471
+ legendInfo == null ? void 0 : legendInfo.squareSize,
1472
+ " km"
1473
+ ]
1474
+ })
1475
+ ]
1476
+ })
1477
+ });
1478
+ }
1479
+
1480
+ // src/components/sidebar/common/info-popover.tsx
1481
+ import { LICENSES, useT as useT4 } from "@biodiv-platform/naksha-commons";
1482
+ import { useState as useState4 } from "react";
1483
+ import { Popover } from "react-tiny-popover";
1484
+ import { tw as tw9 } from "twind";
1485
+ import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
1486
+ var LayerInfoLine = ({
1487
+ icon,
1488
+ name,
1489
+ title,
1490
+ link,
1491
+ children
1492
+ }) => {
1493
+ const content = /* @__PURE__ */ jsx13("span", {
1494
+ children: children || "-"
1495
+ });
1496
+ return /* @__PURE__ */ jsxs8("div", {
1497
+ className: tw9`flex gap-3 text-sm text-gray-600 break-all`,
1498
+ title: name && title && `${name}: ${title}`,
1499
+ children: [
1500
+ /* @__PURE__ */ jsx13("div", {
1501
+ children: icon
1502
+ }),
1503
+ link ? /* @__PURE__ */ jsx13("a", {
1504
+ className: tw9`text-blue-700 focus:outline-none focus:ring`,
1505
+ target: "_blank",
1506
+ rel: "noopener",
1507
+ href: link,
1508
+ children: content
1509
+ }) : content
1510
+ ]
1511
+ });
1512
+ };
1513
+ function InfoPopover({ item, containerStyle }) {
1514
+ var _a;
1515
+ const { t } = useT4();
1516
+ const { layer, mp } = useLayers();
1517
+ const license = item.license || "CC-BY";
1518
+ const createdOn = (item == null ? void 0 : item.createdDate) && new Date(item.createdDate).toLocaleDateString();
1519
+ const tags = (_a = item.tags) == null ? void 0 : _a.join(", ");
1520
+ return /* @__PURE__ */ jsxs8("div", {
1521
+ className: tw9`flex flex-col gap-1 bg-white p-4 rounded-lg w-72 border border-gray-300 border-solid`,
1522
+ style: containerStyle,
1523
+ children: [
1524
+ mp.managePublishing && item.layerStatus && /* @__PURE__ */ jsxs8(LayerInfoLine, {
1525
+ icon: /* @__PURE__ */ jsx13(EyeIcon, {}),
1526
+ name: t("visiblity"),
1527
+ title: item.layerStatus,
1528
+ children: [
1529
+ item.layerStatus,
1530
+ /* @__PURE__ */ jsx13("button", {
1531
+ className: tw9`text-blue-600 focus:outline-none ml-4`,
1532
+ onClick: () => layer.togglePublish(item.id, item == null ? void 0 : item.layerStatus),
1533
+ children: t("toggle")
1534
+ }),
1535
+ /* @__PURE__ */ jsx13("button", {
1536
+ className: tw9`text-red-600 focus:outline-none ml-4`,
1537
+ onClick: () => layer.delete(item.id, t("are_you_sure")),
1538
+ children: t("delete")
1539
+ })
1540
+ ]
1541
+ }),
1542
+ /* @__PURE__ */ jsx13(LayerInfoLine, {
1543
+ icon: /* @__PURE__ */ jsx13(AttributionIcon, {}),
1544
+ link: item.url,
1545
+ name: t("uploader"),
1546
+ title: item.createdBy,
1547
+ children: item.createdBy
1548
+ }),
1549
+ /* @__PURE__ */ jsx13(LayerInfoLine, {
1550
+ icon: /* @__PURE__ */ jsx13(AttributionIcon, {}),
1551
+ link: item.url,
1552
+ name: t("created_by"),
1553
+ title: item.attribution,
1554
+ children: item.attribution
1555
+ }),
1556
+ /* @__PURE__ */ jsx13(LayerInfoLine, {
1557
+ icon: /* @__PURE__ */ jsx13(ClockIcon, {}),
1558
+ name: t("created_on"),
1559
+ title: createdOn,
1560
+ children: createdOn
1561
+ }),
1562
+ /* @__PURE__ */ jsx13(LayerInfoLine, {
1563
+ icon: /* @__PURE__ */ jsx13(TagIcon, {}),
1564
+ name: t("tags"),
1565
+ title: tags,
1566
+ children: tags
1567
+ }),
1568
+ /* @__PURE__ */ jsx13(LayerInfoLine, {
1569
+ name: t("license"),
1570
+ title: license,
1571
+ link: license && LICENSES[license],
1572
+ icon: /* @__PURE__ */ jsx13(LicenseIcon, {}),
1573
+ children: license
1574
+ })
1575
+ ]
1576
+ });
1577
+ }
1578
+ var PopoverWrapper = ({ item }) => {
1579
+ const [isPopoverOpen, setIsPopoverOpen] = useState4(false);
1580
+ const togglePopover = () => setIsPopoverOpen(!isPopoverOpen);
1581
+ return /* @__PURE__ */ jsx13(Popover, {
1582
+ isOpen: isPopoverOpen,
1583
+ padding: 10,
1584
+ positions: ["right"],
1585
+ containerStyle: { zIndex: 99 },
1586
+ onClickOutside: togglePopover,
1587
+ content: /* @__PURE__ */ jsx13(InfoPopover, {
1588
+ item
1589
+ }),
1590
+ children: /* @__PURE__ */ jsx13(Button, {
1591
+ onClick: togglePopover,
1592
+ children: /* @__PURE__ */ jsx13(InfoIcon, {}),
1593
+ title: "Information"
1594
+ })
1595
+ });
1596
+ };
1597
+
1598
+ // src/components/sidebar/common/layer-item-style.tsx
1599
+ import { tw as tw11 } from "twind";
1600
+
1601
+ // src/components/sidebar/common/style-legend.tsx
1602
+ import { useMemo as useMemo2, useState as useState5 } from "react";
1603
+ import { useT as useT5 } from "@biodiv-platform/naksha-commons";
1604
+ import { tw as tw10 } from "twind";
1605
+ import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
1606
+ function StyleLegend({ item }) {
1607
+ var _a;
1608
+ const [showImage, setShowImage] = useState5(true);
1609
+ const { mp } = useLayers();
1610
+ const { t } = useT5();
1611
+ const legendStyles = useMemo2(
1612
+ () => {
1613
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
1614
+ return ((_f = (_e = (_d = (_c = (_b = (_a2 = item == null ? void 0 : item.data) == null ? void 0 : _a2.styles) == null ? void 0 : _b[item.data.styleIndex]) == null ? void 0 : _c.colors) == null ? void 0 : _d.paint) == null ? void 0 : _e["fill-color"]) == null ? void 0 : _f.stops) || ((_l = (_k = (_j = (_i = (_h = (_g = item == null ? void 0 : item.data) == null ? void 0 : _g.styles) == null ? void 0 : _h[item.data.styleIndex]) == null ? void 0 : _i.colors) == null ? void 0 : _j.paint) == null ? void 0 : _k["circle-color"]) == null ? void 0 : _l.stops) || [];
1615
+ },
1616
+ [item]
1617
+ );
1618
+ const vectorLegend = () => {
1619
+ return legendStyles.map(([title, color]) => /* @__PURE__ */ jsxs9("li", {
1620
+ className: tw10`flex gap-2 items-center mb-1`,
1621
+ children: [
1622
+ /* @__PURE__ */ jsx14("svg", {
1623
+ viewBox: "0 0 24 24",
1624
+ height: "14",
1625
+ width: "14",
1626
+ focusable: "false",
1627
+ children: /* @__PURE__ */ jsx14("circle", {
1628
+ cx: "12",
1629
+ fill: color,
1630
+ cy: "12",
1631
+ r: "12",
1632
+ stroke: "none"
1633
+ })
1634
+ }),
1635
+ /* @__PURE__ */ jsx14("div", {
1636
+ children: title
1637
+ })
1638
+ ]
1639
+ }, color));
1640
+ };
1641
+ return /* @__PURE__ */ jsx14("ul", {
1642
+ style: { margin: 0, padding: 0 },
1643
+ children: item.layerType !== "RASTER" ? vectorLegend() : showImage ? /* @__PURE__ */ jsx14("li", {
1644
+ children: /* @__PURE__ */ jsx14("img", {
1645
+ style: { margin: "5px" },
1646
+ onError: () => setShowImage(false),
1647
+ src: `${(_a = mp == null ? void 0 : mp.geoserver) == null ? void 0 : _a.endpoint}/wms?REQUEST=GetLegendGraphic&VERSION=1.0.0&WIDTH=20&HEIGHT=20&STRICT=false&layer=biodiv:${item.id}`
1648
+ })
1649
+ }) : /* @__PURE__ */ jsx14("div", {
1650
+ children: t("raster_style_not_found")
1651
+ })
1652
+ });
1653
+ }
1654
+
1655
+ // src/components/sidebar/common/layer-item-style.tsx
1656
+ import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
1657
+ function LayerItemStyle({ item }) {
1658
+ var _a, _b;
1659
+ if (!((_a = item.data) == null ? void 0 : _a.styles))
1660
+ return null;
1661
+ const { layer } = useLayers();
1662
+ const onStyleChange = (e) => {
1663
+ layer.updateStyle(item.id, Number(e.target.value));
1664
+ };
1665
+ return /* @__PURE__ */ jsxs10("div", {
1666
+ className: tw11`flex flex-col gap-4 pt-2`,
1667
+ children: [
1668
+ item.layerType !== "RASTER" && /* @__PURE__ */ jsx15(SelectInput, {
1669
+ onChange: onStyleChange,
1670
+ children: (_b = item.data) == null ? void 0 : _b.styles.map((opt, idx) => /* @__PURE__ */ jsx15("option", {
1671
+ value: idx,
1672
+ children: opt.styleTitle
1673
+ }, idx))
1674
+ }),
1675
+ /* @__PURE__ */ jsx15(MoreLess, {
1676
+ children: /* @__PURE__ */ jsx15(StyleLegend, {
1677
+ item
1678
+ })
1679
+ })
1680
+ ]
1681
+ });
1682
+ }
1683
+
1684
+ // src/components/sidebar/common/layer-item.tsx
1685
+ import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
1686
+ var DragHandle = SortableHandle(() => /* @__PURE__ */ jsx16("div", {
1687
+ className: tw12`mt-1 w-6 text-center cursor-move`,
1688
+ children: /* @__PURE__ */ jsx16(GrabberIcon, {})
1689
+ }));
1690
+ function LayerItem({ item, extended }) {
1691
+ const { t } = useT6();
1692
+ const { layer, query, mp, query: { setClickedLngLat }, setIsInfoBarOpen } = useLayers();
1693
+ const [isAdded, setIsAdded] = useState6(layer.selectedIds.includes(item.id));
1694
+ const [isLoading, setIsLoading] = useState6(false);
1695
+ const shareData = useMemo3(
1696
+ () => mp.canLayerShare ? {
1697
+ url: `${window.location.href.split("?")[0]}?layers=${item.id}`,
1698
+ title: item.title
1699
+ } : void 0,
1700
+ [item.id]
1701
+ );
1702
+ const onToggleLayer = () => __async(this, null, function* () {
1703
+ setIsLoading(true);
1704
+ setIsInfoBarOpen(true);
1705
+ layer.setSelectedFeatures([]);
1706
+ setClickedLngLat(null);
1707
+ yield layer.toggle({ layerId: item.id, add: !isAdded });
1708
+ setIsAdded(!isAdded);
1709
+ setIsLoading(false);
1710
+ });
1711
+ const onDownloadLayer = () => __async(this, null, function* () {
1712
+ yield axDownloadLayer(
1713
+ mp.nakshaApiEndpoint,
1714
+ mp.nakshaEndpointToken,
1715
+ item.id,
1716
+ item.title
1717
+ );
1718
+ mp == null ? void 0 : mp.onLayerDownload(item.id);
1719
+ });
1720
+ const handleOnZoom = () => layer.zoomToExtent(item.id);
1721
+ return /* @__PURE__ */ jsxs11("div", {
1722
+ className: tw12`z-20 p-3 bg-white`,
1723
+ style: { borderTop: "1px solid #e5e7eb" },
1724
+ children: [
1725
+ /* @__PURE__ */ jsxs11("div", {
1726
+ className: tw12`flex gap-3`,
1727
+ children: [
1728
+ /* @__PURE__ */ jsxs11("div", {
1729
+ className: tw12`flex-shrink-0`,
1730
+ children: [
1731
+ /* @__PURE__ */ jsx16(CheckboxInput, {
1732
+ name: item.id,
1733
+ checked: isAdded,
1734
+ onChange: onToggleLayer,
1735
+ isLoading
1736
+ }),
1737
+ extended && /* @__PURE__ */ jsx16(DragHandle, {})
1738
+ ]
1739
+ }),
1740
+ /* @__PURE__ */ jsx16("img", {
1741
+ className: tw12`flex-shrink-0 overflow-hidden h-16 w-16 p-1 mb-2 object-cover border border-gray-200 rounded`,
1742
+ src: item.thumbnail || FALLBACK_THUMB
1743
+ }),
1744
+ /* @__PURE__ */ jsxs11("div", {
1745
+ children: [
1746
+ /* @__PURE__ */ jsx16("div", {
1747
+ title: item.title,
1748
+ className: tw12`mb-1 leading-tight`,
1749
+ style: overflowStyle,
1750
+ children: /* @__PURE__ */ jsx16(Highlighted, {
1751
+ text: item.title,
1752
+ highlight: query.term
1753
+ })
1754
+ }),
1755
+ /* @__PURE__ */ jsx16("p", {
1756
+ title: item.description,
1757
+ className: tw12`text-gray-600 text-sm`,
1758
+ style: overflowStyle2,
1759
+ children: item.description
1760
+ })
1761
+ ]
1762
+ })
1763
+ ]
1764
+ }),
1765
+ /* @__PURE__ */ jsxs11("div", {
1766
+ className: tw12`flex justify-between`,
1767
+ children: [
1768
+ /* @__PURE__ */ jsxs11(Button, {
1769
+ onClick: onDownloadLayer,
1770
+ disabled: !item.isDownloadable,
1771
+ children: [
1772
+ /* @__PURE__ */ jsx16(DownloadIcon, {}),
1773
+ " ",
1774
+ t("download")
1775
+ ]
1776
+ }),
1777
+ /* @__PURE__ */ jsxs11("div", {
1778
+ className: tw12`flex gap-3`,
1779
+ children: [
1780
+ shareData && /* @__PURE__ */ jsx16(RWebShare, {
1781
+ data: shareData,
1782
+ children: /* @__PURE__ */ jsx16(Button, {
1783
+ title: "Share",
1784
+ children: /* @__PURE__ */ jsx16(ShareIcon, {})
1785
+ })
1786
+ }),
1787
+ extended && /* @__PURE__ */ jsx16(Button, {
1788
+ onClick: handleOnZoom,
1789
+ title: "Zoom To Extent",
1790
+ children: /* @__PURE__ */ jsx16(ZoomExtentIcon, {})
1791
+ }),
1792
+ /* @__PURE__ */ jsx16(PopoverWrapper, {
1793
+ item
1794
+ })
1795
+ ]
1796
+ })
1797
+ ]
1798
+ }),
1799
+ extended && /* @__PURE__ */ jsx16(LayerItemStyle, {
1800
+ item
1801
+ }),
1802
+ extended && item.source.type === "grid" && /* @__PURE__ */ jsx16(GridLegend, {
1803
+ item
1804
+ })
1805
+ ]
1806
+ });
1807
+ }
1808
+
1809
+ // src/components/sidebar/layers/layer-list.tsx
1810
+ import { jsx as jsx17 } from "react/jsx-runtime";
1811
+ function LayerList() {
1812
+ const { layer, query } = useLayers();
1813
+ const filteredLayers = useMemo4(
1814
+ () => query.term ? layer.all.filter(
1815
+ (_l) => _l.title.toLowerCase().includes(query.term.toLowerCase())
1816
+ ) : layer.all,
1817
+ [layer.all, query.term]
1818
+ );
1819
+ const parentRef = React8.useRef();
1820
+ const rowVirtualizer = useVirtual({
1821
+ size: filteredLayers.length,
1822
+ parentRef
1823
+ });
1824
+ return /* @__PURE__ */ jsx17("div", {
1825
+ className: tw13`flex-grow-1 relative`,
1826
+ children: /* @__PURE__ */ jsx17(AutoSizer, {
1827
+ disableWidth: true,
1828
+ children: (p) => /* @__PURE__ */ jsx17("div", {
1829
+ ref: parentRef,
1830
+ className: "List",
1831
+ style: { height: p.height, overflow: "auto" },
1832
+ children: /* @__PURE__ */ jsx17("div", {
1833
+ style: {
1834
+ height: rowVirtualizer.totalSize,
1835
+ width: "100%",
1836
+ position: "relative"
1837
+ },
1838
+ children: rowVirtualizer.virtualItems.map((virtualRow) => /* @__PURE__ */ jsx17("div", {
1839
+ ref: virtualRow.measureRef,
1840
+ className: tw13`absolute top-0 left-0 w-full`,
1841
+ style: { transform: `translateY(${virtualRow.start}px)` },
1842
+ children: /* @__PURE__ */ jsx17("div", {
1843
+ style: { height: 146 },
1844
+ children: /* @__PURE__ */ jsx17(LayerItem, {
1845
+ item: filteredLayers[virtualRow.index]
1846
+ })
1847
+ })
1848
+ }, virtualRow.index))
1849
+ })
1850
+ })
1851
+ })
1852
+ });
1853
+ }
1854
+
1855
+ // src/components/sidebar/layers/search.tsx
1856
+ import { useT as useT7 } from "@biodiv-platform/naksha-commons";
1857
+ import { tw as tw14 } from "twind";
1858
+ import { jsx as jsx18 } from "react/jsx-runtime";
1859
+ function LayerSearch() {
1860
+ const { t } = useT7();
1861
+ const { query } = useLayers();
1862
+ const handleOnSearchChange = (e) => query.setTerm(e.target.value);
1863
+ return /* @__PURE__ */ jsx18("div", {
1864
+ className: tw14`flex-shrink-0 border-b-2 p-4`,
1865
+ children: /* @__PURE__ */ jsx18(SearchInput, {
1866
+ name: "lyr_search",
1867
+ placeholder: t("find_layer_by_name"),
1868
+ onChange: handleOnSearchChange
1869
+ })
1870
+ });
1871
+ }
1872
+
1873
+ // src/components/sidebar/layers/index.tsx
1874
+ import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
1875
+ function LayersTabPanel() {
1876
+ return /* @__PURE__ */ jsxs12("div", {
1877
+ className: tw15`flex flex-col w-full`,
1878
+ children: [
1879
+ /* @__PURE__ */ jsx19(LayerSearch, {}),
1880
+ /* @__PURE__ */ jsx19(LayerList, {})
1881
+ ]
1882
+ });
1883
+ }
1884
+
1885
+ // src/utils/array-move.ts
1886
+ function arrayMoveMutable(array, fromIndex, toIndex) {
1887
+ const startIndex = fromIndex < 0 ? array.length + fromIndex : fromIndex;
1888
+ if (startIndex >= 0 && startIndex < array.length) {
1889
+ const endIndex = toIndex < 0 ? array.length + toIndex : toIndex;
1890
+ const [item] = array.splice(fromIndex, 1);
1891
+ array.splice(endIndex, 0, item);
1892
+ }
1893
+ }
1894
+ function arrayMoveImmutable(array, fromIndex, toIndex) {
1895
+ array = [...array];
1896
+ arrayMoveMutable(array, fromIndex, toIndex);
1897
+ return array;
1898
+ }
1899
+
1900
+ // src/components/sidebar/selected/selected-item-list.tsx
1901
+ import { SortableContainer, SortableElement } from "react-sortable-hoc";
1902
+ import { jsx as jsx20 } from "react/jsx-runtime";
1903
+ var SelectedItem = SortableElement(({ item, extended }) => /* @__PURE__ */ jsx20(LayerItem, {
1904
+ item,
1905
+ extended
1906
+ }));
1907
+ var SelectedItemList = SortableContainer(({ layerList }) => /* @__PURE__ */ jsx20("div", {
1908
+ children: layerList.map((item, index) => /* @__PURE__ */ jsx20(SelectedItem, {
1909
+ index,
1910
+ item,
1911
+ extended: true
1912
+ }, item.id))
1913
+ }));
1914
+
1915
+ // src/components/sidebar/selected/index.tsx
1916
+ import { useT as useT8 } from "@biodiv-platform/naksha-commons";
1917
+ import { tw as tw16 } from "twind";
1918
+ import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
1919
+ function SelectedTabPanel() {
1920
+ const { layer } = useLayers();
1921
+ const { t } = useT8();
1922
+ const onSortEnd = ({ oldIndex, newIndex }) => {
1923
+ layer.setSelectedIds(
1924
+ arrayMoveImmutable(layer.selectedIds, oldIndex, newIndex)
1925
+ );
1926
+ };
1927
+ return /* @__PURE__ */ jsxs13("div", {
1928
+ className: tw16`flex flex-col gap-3 w-full`,
1929
+ children: [
1930
+ layer.selectedIds.length > 0 && /* @__PURE__ */ jsx21("div", {
1931
+ className: tw16`p-3 pb-0`,
1932
+ children: /* @__PURE__ */ jsxs13(Button, {
1933
+ onClick: () => layer.clearAll(),
1934
+ children: [
1935
+ "\u2715 ",
1936
+ t("clear")
1937
+ ]
1938
+ })
1939
+ }),
1940
+ /* @__PURE__ */ jsx21(SelectedItemList, {
1941
+ layerList: layer.selectedLayers,
1942
+ useDragHandle: true,
1943
+ onSortEnd
1944
+ })
1945
+ ]
1946
+ });
1947
+ }
1948
+
1949
+ // src/components/sidebar/settings/index.tsx
1950
+ import { defaultMapStyles as defaultMapStyles2, useT as useT9 } from "@biodiv-platform/naksha-commons";
1951
+ import { tw as tw17 } from "twind";
1952
+ import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
1953
+ function SettingsTabPanel() {
1954
+ const { layer } = useLayers();
1955
+ const { t } = useT9();
1956
+ const handleOnStyleChange = (e) => layer.setMapStyle(e.target.value);
1957
+ return /* @__PURE__ */ jsxs14("div", {
1958
+ className: tw17`w-full p-4 flex flex-col gap-4`,
1959
+ children: [
1960
+ /* @__PURE__ */ jsx22(SelectInput, {
1961
+ name: "base_style",
1962
+ label: t("base_style"),
1963
+ defaultValue: layer.mapStyle,
1964
+ onChange: handleOnStyleChange,
1965
+ children: defaultMapStyles2.map((ms) => /* @__PURE__ */ jsx22("option", {
1966
+ value: ms.style,
1967
+ children: ms.text
1968
+ }, ms.key))
1969
+ }),
1970
+ /* @__PURE__ */ jsx22(LayerSelection, {})
1971
+ ]
1972
+ });
1973
+ }
1974
+
1975
+ // src/components/sidebar/tabs.tsx
1976
+ import { jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
1977
+ function SidebarTabs({ onClose }) {
1978
+ const { t } = useT10();
1979
+ return /* @__PURE__ */ jsxs15("div", {
1980
+ className: tw18`absolute top-0 right-0 bottom-0 left-0 md:right-auto md:top-4 md:left-4 md:bottom-4 bg-white rounded-lg shadow-md md:max-w-sm w-full z-20 overflow-hidden`,
1981
+ children: [
1982
+ /* @__PURE__ */ jsx23(CloseButton, {
1983
+ onClick: onClose
1984
+ }),
1985
+ /* @__PURE__ */ jsx23("div", {
1986
+ className: tw18`flex flex-col h-full`,
1987
+ children: /* @__PURE__ */ jsxs15(Tabs, {
1988
+ children: [
1989
+ /* @__PURE__ */ jsxs15(TabHeader, {
1990
+ children: [
1991
+ /* @__PURE__ */ jsx23(IconTab, {
1992
+ icon: /* @__PURE__ */ jsx23(LayersIcon, {}),
1993
+ children: t("layers")
1994
+ }),
1995
+ /* @__PURE__ */ jsx23(IconTab, {
1996
+ icon: /* @__PURE__ */ jsx23(LayersIcon, {}),
1997
+ children: t("selected")
1998
+ }),
1999
+ /* @__PURE__ */ jsx23(IconTab, {
2000
+ icon: /* @__PURE__ */ jsx23(SlidersIcon, {}),
2001
+ children: t("settings")
2002
+ })
2003
+ ]
2004
+ }),
2005
+ /* @__PURE__ */ jsx23(Panel, {
2006
+ children: /* @__PURE__ */ jsx23(LayersTabPanel, {})
2007
+ }),
2008
+ /* @__PURE__ */ jsx23(Panel, {
2009
+ children: /* @__PURE__ */ jsx23(SelectedTabPanel, {})
2010
+ }),
2011
+ /* @__PURE__ */ jsx23(Panel, {
2012
+ children: /* @__PURE__ */ jsx23(SettingsTabPanel, {})
2013
+ })
2014
+ ]
2015
+ })
2016
+ })
2017
+ ]
2018
+ });
2019
+ }
2020
+
2021
+ // src/components/sidebar/index.tsx
2022
+ import { jsx as jsx24 } from "react/jsx-runtime";
2023
+ function Sidebar() {
2024
+ const { mp, layer } = useLayers();
2025
+ const [isOpen, setIsOpen] = useState8(mp.showToC);
2026
+ const { mapl } = useMap2();
2027
+ const toggleOpen = () => setIsOpen(!isOpen);
2028
+ function loadToC() {
2029
+ return __async(this, null, function* () {
2030
+ const _layers = yield axGetGeoserverLayers(
2031
+ mp.nakshaEndpointToken,
2032
+ mp.nakshaApiEndpoint,
2033
+ mp.geoserver,
2034
+ mp.selectedLayers
2035
+ );
2036
+ const _newLayers = [...mp.layers || [], ..._layers];
2037
+ layer.setAll(_newLayers);
2038
+ if (layer.selectedIds.length) {
2039
+ const _layer = _newLayers.find((l) => l.id === layer.selectedIds[0]);
2040
+ (_layer == null ? void 0 : _layer.bbox) && (mapl == null ? void 0 : mapl.fitBounds(_layer.bbox, { padding: 40, duration: 1e3 }));
2041
+ }
2042
+ });
2043
+ }
2044
+ useEffect3(() => {
2045
+ if (mapl && mp.loadToC) {
2046
+ loadToC();
2047
+ }
2048
+ }, [mapl]);
2049
+ return isOpen ? /* @__PURE__ */ jsx24(SidebarTabs, {
2050
+ onClose: toggleOpen
2051
+ }) : /* @__PURE__ */ jsx24(LayersButton, {
2052
+ onClick: toggleOpen
2053
+ });
2054
+ }
2055
+
2056
+ // src/components/map/layers/index.tsx
2057
+ import { useMap as useMap4 } from "react-map-gl/maplibre";
2058
+
2059
+ // src/components/map/layers/grid/index.tsx
2060
+ import { useEffect as useEffect4, useState as useState9 } from "react";
2061
+ import { Layer, Source, useMap as useMap3 } from "react-map-gl/maplibre";
2062
+ import { jsx as jsx25 } from "react/jsx-runtime";
2063
+ function GridLayer({
2064
+ data,
2065
+ beforeId
2066
+ }) {
2067
+ const { layer } = useLayers();
2068
+ const { mapl } = useMap3();
2069
+ const [layerData, setLayerData] = useState9({ geojson: {}, paint: {} });
2070
+ const fetchGridData = () => __async(this, null, function* () {
2071
+ const { success, geojson, paint: paint2, stops, squareSize } = yield getGridLayerData(
2072
+ data.source.fetcher,
2073
+ mapl == null ? void 0 : mapl.getBounds(),
2074
+ mapl == null ? void 0 : mapl.getZoom()
2075
+ );
2076
+ if (success) {
2077
+ setLayerData({ geojson, paint: paint2 });
2078
+ layer.setGridLegends({
2079
+ [data.id]: { stops, squareSize }
2080
+ });
2081
+ }
2082
+ });
2083
+ useEffect4(() => {
2084
+ mapl == null ? void 0 : mapl.on("idle", fetchGridData);
2085
+ }, []);
2086
+ return /* @__PURE__ */ jsx25(Source, {
2087
+ id: data.id,
2088
+ type: "geojson",
2089
+ data: layerData.geojson,
2090
+ children: /* @__PURE__ */ jsx25(Layer, {
2091
+ beforeId,
2092
+ id: data.id,
2093
+ type: "fill",
2094
+ paint: layerData.paint
2095
+ })
2096
+ });
2097
+ }
2098
+
2099
+ // src/components/map/layers/vector/index.tsx
2100
+ import { useMemo as useMemo5 } from "react";
2101
+ import { Layer as Layer2, Source as Source2 } from "react-map-gl/maplibre";
2102
+ import { jsx as jsx26, jsxs as jsxs16 } from "react/jsx-runtime";
2103
+ var paint = {
2104
+ fill: {
2105
+ "line-color": "red",
2106
+ "line-width": 2
2107
+ },
2108
+ circle: {
2109
+ "circle-stroke-color": "red",
2110
+ "circle-stroke-width": 2,
2111
+ "circle-opacity": 0
2112
+ }
2113
+ };
2114
+ function VectorLayer({ layer: data, beforeId }) {
2115
+ var _a;
2116
+ const { layer } = useLayers();
2117
+ const layerProps = useMemo5(
2118
+ () => {
2119
+ var _a2, _b, _c, _d;
2120
+ return (_d = (_c = (_a2 = data.data) == null ? void 0 : _a2.styles) == null ? void 0 : _c[(_b = data.data) == null ? void 0 : _b.styleIndex]) == null ? void 0 : _d.colors;
2121
+ },
2122
+ [data, layer.selectedFeatures]
2123
+ );
2124
+ const highlightData = (_a = layer.selectedFeaturesId) == null ? void 0 : _a[data.id];
2125
+ return /* @__PURE__ */ jsxs16(Source2, __spreadProps(__spreadValues({}, data.source), {
2126
+ children: [
2127
+ layerProps && /* @__PURE__ */ jsx26(Layer2, __spreadValues({
2128
+ beforeId
2129
+ }, layerProps)),
2130
+ highlightData && layerProps && /* @__PURE__ */ jsx26(Layer2, __spreadProps(__spreadValues({}, layerProps), {
2131
+ beforeId,
2132
+ id: `hl_${data.id}`,
2133
+ filter: ["in", PROPERTY_ID, ...highlightData],
2134
+ type: layerProps.type === "fill" ? "line" : layerProps.type,
2135
+ paint: paint[layerProps.type]
2136
+ }))
2137
+ ]
2138
+ }));
2139
+ }
2140
+
2141
+ // src/components/map/layers/raster/index.tsx
2142
+ import { Layer as Layer3, Source as Source3 } from "react-map-gl/maplibre";
2143
+ import { jsx as jsx27 } from "react/jsx-runtime";
2144
+ function RasterLayer({
2145
+ data,
2146
+ beforeId
2147
+ }) {
2148
+ var _a;
2149
+ const { mp } = useLayers();
2150
+ return /* @__PURE__ */ jsx27(Source3, {
2151
+ id: data.id,
2152
+ type: "raster",
2153
+ tiles: [
2154
+ `${(_a = mp == null ? void 0 : mp.geoserver) == null ? void 0 : _a.endpoint}/wms?bbox={bbox-epsg-3857}&format=image/png&service=WMS&version=1.1.1&request=GetMap&srs=EPSG:3857&width=256&height=256&transparent=true&layers=biodiv:${data.id}`
2155
+ ],
2156
+ tileSize: 256,
2157
+ children: /* @__PURE__ */ jsx27(Layer3, {
2158
+ id: data.id,
2159
+ beforeId,
2160
+ type: "raster",
2161
+ source: "biodiv",
2162
+ layout: { visibility: "visible" },
2163
+ paint: {}
2164
+ })
2165
+ });
2166
+ }
2167
+
2168
+ // src/components/map/layers/index.tsx
2169
+ import { jsx as jsx28 } from "react/jsx-runtime";
2170
+ function MapLayer({
2171
+ layer,
2172
+ beforeId
2173
+ }) {
2174
+ const { mapl } = useMap4();
2175
+ if (!mapl) {
2176
+ return null;
2177
+ }
2178
+ switch (layer.source.type) {
2179
+ case "vector":
2180
+ return /* @__PURE__ */ jsx28(VectorLayer, {
2181
+ beforeId,
2182
+ layer
2183
+ });
2184
+ case "grid":
2185
+ return /* @__PURE__ */ jsx28(GridLayer, {
2186
+ beforeId,
2187
+ data: layer
2188
+ });
2189
+ case "raster":
2190
+ return /* @__PURE__ */ jsx28(RasterLayer, {
2191
+ beforeId,
2192
+ data: layer
2193
+ });
2194
+ default:
2195
+ return /* @__PURE__ */ jsx28(VectorLayer, {
2196
+ beforeId,
2197
+ layer
2198
+ });
2199
+ }
2200
+ }
2201
+
2202
+ // src/components/map/markers-list/index.tsx
2203
+ import { useMemo as useMemo6 } from "react";
2204
+ import { Marker } from "react-map-gl/maplibre";
2205
+ import { Fragment as Fragment2, jsx as jsx29 } from "react/jsx-runtime";
2206
+ var Marker1 = Marker;
2207
+ var MarkersList = () => {
2208
+ const { mp } = useLayers();
2209
+ const markersMemoized = useMemo6(() => mp.markers, [mp.markers]);
2210
+ return /* @__PURE__ */ jsx29(Fragment2, {
2211
+ children: markersMemoized == null ? void 0 : markersMemoized.map(({ latitude, longitude, colorHex }, index) => /* @__PURE__ */ jsx29(Marker1, {
2212
+ latitude,
2213
+ longitude,
2214
+ children: /* @__PURE__ */ jsx29("img", {
2215
+ style: { cursor: "pointer" },
2216
+ alt: "Marker",
2217
+ src: "https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png"
2218
+ })
2219
+ }, index))
2220
+ });
2221
+ };
2222
+ var markers_list_default = MarkersList;
2223
+
2224
+ // src/components/map/popup/index.tsx
2225
+ import clsx3 from "clsx";
2226
+ import { Popup } from "react-map-gl/maplibre";
2227
+ import { tw as tw19 } from "twind";
2228
+ import { jsx as jsx30, jsxs as jsxs17 } from "react/jsx-runtime";
2229
+ var Pop = Popup;
2230
+ function HoverPopup({ coordinates }) {
2231
+ const { hover } = useLayers();
2232
+ return (coordinates == null ? void 0 : coordinates.lat) && hover.features ? /* @__PURE__ */ jsx30(Pop, {
2233
+ latitude: coordinates.lat,
2234
+ longitude: coordinates.lng,
2235
+ closeButton: false,
2236
+ children: /* @__PURE__ */ jsxs17("table", {
2237
+ className: tw19`table-auto border`,
2238
+ children: [
2239
+ /* @__PURE__ */ jsx30("thead", {
2240
+ children: /* @__PURE__ */ jsx30("tr", {
2241
+ children: /* @__PURE__ */ jsx30("th", {
2242
+ className: tw19`bg-gray-200 py-1 px-2`,
2243
+ colSpan: 2,
2244
+ children: hover.features.title
2245
+ })
2246
+ })
2247
+ }),
2248
+ /* @__PURE__ */ jsx30("tbody", {
2249
+ children: hover.features.data.map(([k, v], idx) => /* @__PURE__ */ jsxs17("tr", {
2250
+ className: tw19(
2251
+ clsx3({
2252
+ "bg-gray-50": idx % 2 === 0,
2253
+ "border-gray-100 border-t": 1
2254
+ })
2255
+ ),
2256
+ children: [
2257
+ /* @__PURE__ */ jsx30("td", {
2258
+ className: tw19`py-1 px-2`,
2259
+ children: k
2260
+ }),
2261
+ /* @__PURE__ */ jsx30("td", {
2262
+ className: tw19`py-1 px-2 border-l border-gray-100`,
2263
+ children: v
2264
+ })
2265
+ ]
2266
+ }, k + v))
2267
+ })
2268
+ ]
2269
+ })
2270
+ }) : null;
2271
+ }
2272
+
2273
+ // src/components/map/index.tsx
2274
+ import { jsx as jsx31, jsxs as jsxs18 } from "react/jsx-runtime";
2275
+ var NavControl = NavigationControl;
2276
+ function Map2() {
2277
+ var _a;
2278
+ const { mp, layer, hover, query } = useLayers();
2279
+ const [coordinates, setCoordinates] = useState10();
2280
+ const viewState = useMemo7(
2281
+ () => mp.defaultViewState || defaultViewState2,
2282
+ [mp.defaultViewState]
2283
+ );
2284
+ const onMapClick = (e) => query.setClickedLngLat(e.lngLat);
2285
+ const handleOnMouseMove = (event) => {
2286
+ setCoordinates(event.lngLat);
2287
+ hover.onHover(event);
2288
+ };
2289
+ return /* @__PURE__ */ jsxs18("div", {
2290
+ className: tw20`h-full w-full relative bg-gray-100`,
2291
+ children: [
2292
+ mp.loadToC && /* @__PURE__ */ jsx31(Sidebar, {}),
2293
+ ((_a = layer.selectedFeatures) == null ? void 0 : _a.length) > 0 && /* @__PURE__ */ jsx31(InfoBar, {}),
2294
+ /* @__PURE__ */ jsxs18(MapGL, {
2295
+ id: "mapl",
2296
+ cursor: "default",
2297
+ initialViewState: viewState,
2298
+ style: { width: "100%", height: "100%" },
2299
+ mapStyle: layer.mapStyle,
2300
+ onClick: onMapClick,
2301
+ onMouseMove: handleOnMouseMove,
2302
+ children: [
2303
+ /* @__PURE__ */ jsx31(NavControl, {
2304
+ position: "bottom-right",
2305
+ showZoom: true,
2306
+ showCompass: true
2307
+ }),
2308
+ /* @__PURE__ */ jsx31(markers_list_default, {}),
2309
+ layer.selectedLayers.map((_l, index) => {
2310
+ const beforeId = index > 0 ? layer.selectedIds[index - 1] : void 0;
2311
+ return /* @__PURE__ */ jsx31(MapLayer, {
2312
+ layer: _l,
2313
+ beforeId
2314
+ }, _l.id);
2315
+ }),
2316
+ /* @__PURE__ */ jsx31(HoverPopup, {
2317
+ coordinates
2318
+ }, "popup")
2319
+ ]
2320
+ })
2321
+ ]
2322
+ });
2323
+ }
2324
+
2325
+ // src/index.tsx
2326
+ import { jsx as jsx32 } from "react/jsx-runtime";
2327
+ setup({ preflight: false });
2328
+ var NakshaMaplibreLayers = (props) => {
2329
+ const mp = React14.useMemo(
2330
+ () => __spreadValues(__spreadValues({}, defaultNakshaProps), props),
2331
+ [props]
2332
+ );
2333
+ return /* @__PURE__ */ jsx32(MapProvider, {
2334
+ children: /* @__PURE__ */ jsx32(TranslationProvider, {
2335
+ localeStrings: locales_default,
2336
+ lang: mp.lang,
2337
+ children: /* @__PURE__ */ jsx32(LayersProvider, {
2338
+ mp,
2339
+ children: /* @__PURE__ */ jsx32(Map2, {})
2340
+ })
2341
+ })
2342
+ });
2343
+ };
2344
+ export {
2345
+ NakshaMaplibreLayers
2346
+ };