@biodiv-platform/naksha-maplibre-draw 5.0.7 → 5.0.9
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/dist/esm/index.js +475 -210
- package/dist/index.d.ts +6 -0
- package/dist/index.js +484 -219
- package/package.json +7 -8
package/dist/index.js
CHANGED
|
@@ -49,10 +49,14 @@ module.exports = __toCommonJS(src_exports);
|
|
|
49
49
|
|
|
50
50
|
// src/components/map.tsx
|
|
51
51
|
var import_maplibre_gl2 = __toESM(require("maplibre-gl"));
|
|
52
|
+
var import_react3 = require("react");
|
|
52
53
|
|
|
53
54
|
// src/components/setup-draw.tsx
|
|
54
55
|
var import_terra_draw = require("terra-draw");
|
|
55
56
|
var import_terra_draw_maplibre_gl_adapter = require("terra-draw-maplibre-gl-adapter");
|
|
57
|
+
var import_twind = require("twind");
|
|
58
|
+
var import_react = __toESM(require("react"));
|
|
59
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
56
60
|
function setupDraw(map) {
|
|
57
61
|
return new import_terra_draw.TerraDraw({
|
|
58
62
|
tracked: true,
|
|
@@ -143,9 +147,50 @@ function setupDraw(map) {
|
|
|
143
147
|
]
|
|
144
148
|
});
|
|
145
149
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
var
|
|
150
|
+
var ensureModeProperty = (features) => {
|
|
151
|
+
return features.map((feature) => {
|
|
152
|
+
var _a, _b;
|
|
153
|
+
if ((_a = feature.properties) == null ? void 0 : _a.mode)
|
|
154
|
+
return feature;
|
|
155
|
+
const type = (_b = feature.geometry) == null ? void 0 : _b.type;
|
|
156
|
+
const mode = type === "Point" ? "point" : type === "Polygon" ? "polygon" : type === "LineString" ? "linestring" : "unknown";
|
|
157
|
+
return __spreadProps(__spreadValues({}, feature), {
|
|
158
|
+
properties: __spreadProps(__spreadValues({}, feature.properties), { mode })
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
};
|
|
162
|
+
var IconButton = import_react.default.forwardRef(
|
|
163
|
+
(props, ref) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", __spreadValues({
|
|
164
|
+
ref,
|
|
165
|
+
type: "button",
|
|
166
|
+
className: import_twind.tw`h-8 px-3 py-2 rounded-md focus:outline-none 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`
|
|
167
|
+
}, props))
|
|
168
|
+
);
|
|
169
|
+
var MapStyleSwitcher = ({
|
|
170
|
+
currentStyleIdx,
|
|
171
|
+
onStyleChange,
|
|
172
|
+
mapStyles
|
|
173
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
174
|
+
style: {
|
|
175
|
+
position: "absolute",
|
|
176
|
+
left: 12,
|
|
177
|
+
bottom: 12,
|
|
178
|
+
background: "rgba(255,255,255,0.95)",
|
|
179
|
+
padding: "8px",
|
|
180
|
+
borderRadius: "6px",
|
|
181
|
+
zIndex: 1e3,
|
|
182
|
+
boxShadow: "0 2px 4px rgba(0,0,0,0.2)"
|
|
183
|
+
},
|
|
184
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", {
|
|
185
|
+
value: currentStyleIdx,
|
|
186
|
+
onChange: (e) => onStyleChange(Number(e.target.value)),
|
|
187
|
+
style: { fontSize: 14, padding: "4px" },
|
|
188
|
+
children: mapStyles.map((style, idx) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", {
|
|
189
|
+
value: idx,
|
|
190
|
+
children: style.text || `Style ${idx + 1}`
|
|
191
|
+
}, style.key || idx))
|
|
192
|
+
})
|
|
193
|
+
});
|
|
149
194
|
|
|
150
195
|
// src/components/setup-maplibre.tsx
|
|
151
196
|
var import_maplibre_gl = __toESM(require("maplibre-gl"));
|
|
@@ -174,9 +219,12 @@ function setupMaplibreMap({
|
|
|
174
219
|
});
|
|
175
220
|
}
|
|
176
221
|
|
|
222
|
+
// src/components/map-buttons/map-buttons.tsx
|
|
223
|
+
var import_react2 = require("react");
|
|
224
|
+
|
|
177
225
|
// src/components/icon-buttons/icons.tsx
|
|
178
|
-
var
|
|
179
|
-
var
|
|
226
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
227
|
+
var PencilOpenIcon = () => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", {
|
|
180
228
|
xmlns: "http://www.w3.org/2000/svg",
|
|
181
229
|
width: "24",
|
|
182
230
|
height: "24",
|
|
@@ -187,15 +235,101 @@ var SelectIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
|
|
|
187
235
|
strokeLinecap: "round",
|
|
188
236
|
strokeLinejoin: "round",
|
|
189
237
|
children: [
|
|
190
|
-
/* @__PURE__ */ (0,
|
|
238
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", {
|
|
239
|
+
d: "M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
|
|
240
|
+
}),
|
|
241
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", {
|
|
242
|
+
d: "m15 5 4 4"
|
|
243
|
+
})
|
|
244
|
+
]
|
|
245
|
+
});
|
|
246
|
+
var PencilCloseIcon = () => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", {
|
|
247
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
248
|
+
width: "24",
|
|
249
|
+
height: "24",
|
|
250
|
+
viewBox: "0 0 24 24",
|
|
251
|
+
fill: "none",
|
|
252
|
+
stroke: "currentColor",
|
|
253
|
+
strokeWidth: "1.5",
|
|
254
|
+
strokeLinecap: "round",
|
|
255
|
+
strokeLinejoin: "round",
|
|
256
|
+
children: [
|
|
257
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", {
|
|
258
|
+
d: "m10 10-6.157 6.162a2 2 0 0 0-.5.833l-1.322 4.36a.5.5 0 0 0 .622.624l4.358-1.323a2 2 0 0 0 .83-.5L14 13.982"
|
|
259
|
+
}),
|
|
260
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", {
|
|
261
|
+
d: "m12.829 7.172 4.359-4.346a1 1 0 1 1 3.986 3.986l-4.353 4.353"
|
|
262
|
+
}),
|
|
263
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", {
|
|
264
|
+
d: "m15 5 4 4"
|
|
265
|
+
}),
|
|
266
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", {
|
|
267
|
+
d: "m2 2 20 20"
|
|
268
|
+
})
|
|
269
|
+
]
|
|
270
|
+
});
|
|
271
|
+
var LocateIcon = () => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", {
|
|
272
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
273
|
+
width: "24",
|
|
274
|
+
height: "24",
|
|
275
|
+
viewBox: "0 0 24 24",
|
|
276
|
+
fill: "none",
|
|
277
|
+
stroke: "currentColor",
|
|
278
|
+
strokeWidth: "1.5",
|
|
279
|
+
strokeLinecap: "round",
|
|
280
|
+
strokeLinejoin: "round",
|
|
281
|
+
children: [
|
|
282
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", {
|
|
283
|
+
x1: "2",
|
|
284
|
+
x2: "5",
|
|
285
|
+
y1: "12",
|
|
286
|
+
y2: "12"
|
|
287
|
+
}),
|
|
288
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", {
|
|
289
|
+
x1: "19",
|
|
290
|
+
x2: "22",
|
|
291
|
+
y1: "12",
|
|
292
|
+
y2: "12"
|
|
293
|
+
}),
|
|
294
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", {
|
|
295
|
+
x1: "12",
|
|
296
|
+
x2: "12",
|
|
297
|
+
y1: "2",
|
|
298
|
+
y2: "5"
|
|
299
|
+
}),
|
|
300
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", {
|
|
301
|
+
x1: "12",
|
|
302
|
+
x2: "12",
|
|
303
|
+
y1: "19",
|
|
304
|
+
y2: "22"
|
|
305
|
+
}),
|
|
306
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", {
|
|
307
|
+
cx: "12",
|
|
308
|
+
cy: "12",
|
|
309
|
+
r: "7"
|
|
310
|
+
})
|
|
311
|
+
]
|
|
312
|
+
});
|
|
313
|
+
var SelectIcon = () => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", {
|
|
314
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
315
|
+
width: "24",
|
|
316
|
+
height: "24",
|
|
317
|
+
viewBox: "0 0 24 24",
|
|
318
|
+
fill: "none",
|
|
319
|
+
stroke: "currentColor",
|
|
320
|
+
strokeWidth: "1.5",
|
|
321
|
+
strokeLinecap: "round",
|
|
322
|
+
strokeLinejoin: "round",
|
|
323
|
+
children: [
|
|
324
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", {
|
|
191
325
|
d: "M12.586 12.586 19 19"
|
|
192
326
|
}),
|
|
193
|
-
/* @__PURE__ */ (0,
|
|
327
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", {
|
|
194
328
|
d: "M3.688 3.037a.497.497 0 0 0-.651.651l6.5 15.999a.501.501 0 0 0 .947-.062l1.569-6.083a2 2 0 0 1 1.448-1.479l6.124-1.579a.5.5 0 0 0 .063-.947z"
|
|
195
329
|
})
|
|
196
330
|
]
|
|
197
331
|
});
|
|
198
|
-
var PointIcon = () => /* @__PURE__ */ (0,
|
|
332
|
+
var PointIcon = () => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", {
|
|
199
333
|
xmlns: "http://www.w3.org/2000/svg",
|
|
200
334
|
width: "24",
|
|
201
335
|
height: "24",
|
|
@@ -206,150 +340,143 @@ var PointIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
|
|
|
206
340
|
strokeLinecap: "round",
|
|
207
341
|
strokeLinejoin: "round",
|
|
208
342
|
children: [
|
|
209
|
-
/* @__PURE__ */ (0,
|
|
343
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", {
|
|
210
344
|
d: "M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"
|
|
211
345
|
}),
|
|
212
|
-
/* @__PURE__ */ (0,
|
|
346
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", {
|
|
213
347
|
cx: "12",
|
|
214
348
|
cy: "10",
|
|
215
349
|
r: "3"
|
|
216
350
|
})
|
|
217
351
|
]
|
|
218
352
|
});
|
|
219
|
-
var LineIcon = () => /* @__PURE__ */ (0,
|
|
353
|
+
var LineIcon = () => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", {
|
|
220
354
|
width: "16",
|
|
221
355
|
height: "16",
|
|
222
356
|
viewBox: "0 0 24 24",
|
|
223
357
|
fill: "none",
|
|
224
358
|
stroke: "currentColor",
|
|
225
359
|
strokeWidth: "2",
|
|
226
|
-
children: /* @__PURE__ */ (0,
|
|
360
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", {
|
|
227
361
|
x1: "4",
|
|
228
362
|
y1: "20",
|
|
229
363
|
x2: "20",
|
|
230
364
|
y2: "4"
|
|
231
365
|
})
|
|
232
366
|
});
|
|
233
|
-
var PolygonIcon = () => /* @__PURE__ */ (0,
|
|
367
|
+
var PolygonIcon = () => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", {
|
|
234
368
|
width: "16",
|
|
235
369
|
height: "16",
|
|
236
370
|
viewBox: "0 0 24 24",
|
|
237
371
|
fill: "none",
|
|
238
372
|
stroke: "currentColor",
|
|
239
373
|
strokeWidth: "2",
|
|
240
|
-
children: /* @__PURE__ */ (0,
|
|
374
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("polygon", {
|
|
241
375
|
points: "12,2 22,8 18,22 6,22 2,8"
|
|
242
376
|
})
|
|
243
377
|
});
|
|
244
|
-
var
|
|
378
|
+
var RectangleIcon = () => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", {
|
|
379
|
+
width: "16",
|
|
380
|
+
height: "16",
|
|
381
|
+
viewBox: "0 0 24 24",
|
|
382
|
+
fill: "none",
|
|
383
|
+
stroke: "currentColor",
|
|
384
|
+
strokeWidth: "2",
|
|
385
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", {
|
|
386
|
+
x: "4",
|
|
387
|
+
y: "4",
|
|
388
|
+
width: "16",
|
|
389
|
+
height: "16"
|
|
390
|
+
})
|
|
391
|
+
});
|
|
392
|
+
var CircleIcon = () => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", {
|
|
245
393
|
width: "16",
|
|
246
394
|
height: "16",
|
|
247
395
|
viewBox: "0 0 24 24",
|
|
248
396
|
fill: "none",
|
|
249
397
|
stroke: "currentColor",
|
|
250
398
|
strokeWidth: "2",
|
|
251
|
-
children: /* @__PURE__ */ (0,
|
|
399
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", {
|
|
400
|
+
cx: "12",
|
|
401
|
+
cy: "12",
|
|
402
|
+
r: "10"
|
|
403
|
+
})
|
|
404
|
+
});
|
|
405
|
+
var FreeHandIcon = () => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", {
|
|
406
|
+
width: "16",
|
|
407
|
+
height: "16",
|
|
408
|
+
viewBox: "0 0 24 24",
|
|
409
|
+
fill: "none",
|
|
410
|
+
stroke: "currentColor",
|
|
411
|
+
strokeWidth: "2",
|
|
412
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", {
|
|
413
|
+
d: "M3 16c1-3 4-5 7-4 3 1 5 3 7 2 2-1 3-4 1-6-1-2-4-2-6-1"
|
|
414
|
+
})
|
|
415
|
+
});
|
|
416
|
+
var DeleteIcon = () => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", {
|
|
417
|
+
width: "16",
|
|
418
|
+
height: "16",
|
|
419
|
+
viewBox: "0 0 24 24",
|
|
420
|
+
fill: "none",
|
|
421
|
+
stroke: "currentColor",
|
|
422
|
+
strokeWidth: "2",
|
|
423
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", {
|
|
252
424
|
d: "M3 6h18M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"
|
|
253
425
|
})
|
|
254
426
|
});
|
|
255
427
|
|
|
256
|
-
// src/components/map-button/
|
|
257
|
-
var
|
|
428
|
+
// src/components/map-button/map-button.tsx
|
|
429
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
430
|
+
var BUTTON_STYLE = {
|
|
431
|
+
display: "flex",
|
|
432
|
+
justifyContent: "center",
|
|
433
|
+
alignItems: "center",
|
|
434
|
+
width: 30,
|
|
435
|
+
height: 30,
|
|
436
|
+
padding: 0,
|
|
437
|
+
borderRadius: 4
|
|
438
|
+
};
|
|
258
439
|
var MapButton = ({
|
|
259
440
|
mode,
|
|
260
441
|
currentMode,
|
|
261
|
-
|
|
442
|
+
onClick,
|
|
262
443
|
icon,
|
|
263
|
-
tooltip
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
},
|
|
279
|
-
children: icon
|
|
280
|
-
});
|
|
281
|
-
};
|
|
282
|
-
var MapButton_default = MapButton;
|
|
283
|
-
|
|
284
|
-
// src/components/map-buttons/MapButtons.tsx
|
|
285
|
-
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
286
|
-
var MapButtons = ({
|
|
287
|
-
mode,
|
|
288
|
-
changeMode
|
|
289
|
-
}) => {
|
|
290
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", {
|
|
291
|
-
style: {
|
|
292
|
-
position: "absolute",
|
|
293
|
-
top: "10px",
|
|
294
|
-
left: "10px",
|
|
295
|
-
display: "flex",
|
|
296
|
-
flexDirection: "column",
|
|
297
|
-
gap: "6px",
|
|
298
|
-
zIndex: 1e3,
|
|
299
|
-
backgroundColor: "rgba(255, 255, 255, 0.9)",
|
|
300
|
-
padding: "8px",
|
|
301
|
-
borderRadius: "6px",
|
|
302
|
-
boxShadow: "0 2px 6px rgba(0,0,0,0.2)"
|
|
303
|
-
},
|
|
304
|
-
children: [
|
|
305
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MapButton_default, {
|
|
306
|
-
mode: "select",
|
|
307
|
-
icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SelectIcon, {}),
|
|
308
|
-
currentMode: mode,
|
|
309
|
-
changeMode,
|
|
310
|
-
tooltip: "Select"
|
|
311
|
-
}),
|
|
312
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MapButton_default, {
|
|
313
|
-
mode: "point",
|
|
314
|
-
icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PointIcon, {}),
|
|
315
|
-
currentMode: mode,
|
|
316
|
-
changeMode,
|
|
317
|
-
tooltip: "Point"
|
|
318
|
-
}),
|
|
319
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MapButton_default, {
|
|
320
|
-
mode: "linestring",
|
|
321
|
-
icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(LineIcon, {}),
|
|
322
|
-
currentMode: mode,
|
|
323
|
-
changeMode,
|
|
324
|
-
tooltip: "Line"
|
|
325
|
-
}),
|
|
326
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MapButton_default, {
|
|
327
|
-
mode: "polygon",
|
|
328
|
-
icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PolygonIcon, {}),
|
|
329
|
-
currentMode: mode,
|
|
330
|
-
changeMode,
|
|
331
|
-
tooltip: "Polygon"
|
|
332
|
-
})
|
|
333
|
-
]
|
|
334
|
-
});
|
|
335
|
-
};
|
|
336
|
-
var MapButtons_default = MapButtons;
|
|
444
|
+
tooltip,
|
|
445
|
+
disabled
|
|
446
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(IconButton, {
|
|
447
|
+
type: "button",
|
|
448
|
+
title: tooltip,
|
|
449
|
+
disabled,
|
|
450
|
+
onClick: () => !disabled && onClick(mode != null ? mode : ""),
|
|
451
|
+
style: __spreadProps(__spreadValues({}, BUTTON_STYLE), {
|
|
452
|
+
backgroundColor: disabled ? "#d3d3d3" : currentMode === mode ? "#02cf87" : "#f0f0f0",
|
|
453
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
454
|
+
opacity: disabled ? 0.6 : 1
|
|
455
|
+
}),
|
|
456
|
+
children: icon
|
|
457
|
+
});
|
|
458
|
+
var map_button_default = MapButton;
|
|
337
459
|
|
|
338
|
-
// src/components/
|
|
339
|
-
var import_react = require("react");
|
|
460
|
+
// src/components/map-buttons/map-buttons.tsx
|
|
340
461
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
341
|
-
|
|
462
|
+
function MapButtons({
|
|
463
|
+
mode,
|
|
464
|
+
setMode,
|
|
465
|
+
onClick,
|
|
342
466
|
draw,
|
|
343
|
-
onFeaturesChange
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
467
|
+
onFeaturesChange,
|
|
468
|
+
isMultiple = true,
|
|
469
|
+
autoFocus
|
|
470
|
+
}) {
|
|
471
|
+
const [expanded, setExpanded] = (0, import_react2.useState)(false);
|
|
472
|
+
const [hasFeatures, setHasFeatures] = (0, import_react2.useState)(false);
|
|
473
|
+
const updateHasFeatures = (0, import_react2.useCallback)(
|
|
474
|
+
() => setHasFeatures(draw.getSnapshot().length > 0),
|
|
475
|
+
[draw]
|
|
476
|
+
);
|
|
477
|
+
(0, import_react2.useEffect)(() => {
|
|
347
478
|
if (!draw)
|
|
348
479
|
return;
|
|
349
|
-
const updateHasFeatures = () => {
|
|
350
|
-
const snapshot = draw.getSnapshot();
|
|
351
|
-
setHasFeatures(snapshot.length > 0);
|
|
352
|
-
};
|
|
353
480
|
draw.on("finish", updateHasFeatures);
|
|
354
481
|
draw.on("change", updateHasFeatures);
|
|
355
482
|
updateHasFeatures();
|
|
@@ -357,174 +484,312 @@ var ClearButton = ({
|
|
|
357
484
|
draw.off("finish", updateHasFeatures);
|
|
358
485
|
draw.off("change", updateHasFeatures);
|
|
359
486
|
};
|
|
360
|
-
}, [draw]);
|
|
361
|
-
const
|
|
362
|
-
if (!
|
|
487
|
+
}, [draw, updateHasFeatures]);
|
|
488
|
+
const handleGeolocation = (0, import_react2.useCallback)(() => {
|
|
489
|
+
if (!("geolocation" in navigator)) {
|
|
490
|
+
alert("Geolocation is not supported in this browser.");
|
|
363
491
|
return;
|
|
492
|
+
}
|
|
493
|
+
navigator.geolocation.getCurrentPosition(
|
|
494
|
+
(pos) => {
|
|
495
|
+
const coords = [
|
|
496
|
+
pos.coords.longitude,
|
|
497
|
+
pos.coords.latitude
|
|
498
|
+
];
|
|
499
|
+
const pt = {
|
|
500
|
+
type: "Feature",
|
|
501
|
+
geometry: { type: "Point", coordinates: coords },
|
|
502
|
+
properties: { mode: "point", source: "geolocation" }
|
|
503
|
+
};
|
|
504
|
+
if (!isMultiple)
|
|
505
|
+
draw.clear();
|
|
506
|
+
draw.addFeatures([pt]);
|
|
507
|
+
onFeaturesChange == null ? void 0 : onFeaturesChange(draw.getSnapshot());
|
|
508
|
+
autoFocus == null ? void 0 : autoFocus([pt]);
|
|
509
|
+
},
|
|
510
|
+
(error) => {
|
|
511
|
+
alert("Error getting geolocation");
|
|
512
|
+
console.error(error);
|
|
513
|
+
}
|
|
514
|
+
);
|
|
515
|
+
setMode("current-location");
|
|
516
|
+
}, [draw, isMultiple, onFeaturesChange, autoFocus]);
|
|
517
|
+
const handleClear = (0, import_react2.useCallback)(() => {
|
|
364
518
|
draw.clear();
|
|
365
519
|
setHasFeatures(false);
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
};
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
520
|
+
setMode("static");
|
|
521
|
+
onFeaturesChange == null ? void 0 : onFeaturesChange([]);
|
|
522
|
+
}, [draw, onFeaturesChange]);
|
|
523
|
+
const buttons = (0, import_react2.useMemo)(
|
|
524
|
+
() => [
|
|
525
|
+
{
|
|
526
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LocateIcon, {}),
|
|
527
|
+
mode: "current-location",
|
|
528
|
+
onClick: handleGeolocation,
|
|
529
|
+
tooltip: "Use current location"
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SelectIcon, {}),
|
|
533
|
+
mode: "select",
|
|
534
|
+
onClick,
|
|
535
|
+
tooltip: "Select"
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PointIcon, {}),
|
|
539
|
+
mode: "point",
|
|
540
|
+
onClick,
|
|
541
|
+
tooltip: "Point"
|
|
542
|
+
},
|
|
543
|
+
{
|
|
544
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LineIcon, {}),
|
|
545
|
+
mode: "linestring",
|
|
546
|
+
onClick,
|
|
547
|
+
tooltip: "Linestring"
|
|
548
|
+
},
|
|
549
|
+
{
|
|
550
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PolygonIcon, {}),
|
|
551
|
+
mode: "polygon",
|
|
552
|
+
onClick,
|
|
553
|
+
tooltip: "Polygon"
|
|
554
|
+
},
|
|
555
|
+
{
|
|
556
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RectangleIcon, {}),
|
|
557
|
+
mode: "rectangle",
|
|
558
|
+
onClick,
|
|
559
|
+
tooltip: "Reactangle"
|
|
560
|
+
},
|
|
561
|
+
{
|
|
562
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CircleIcon, {}),
|
|
563
|
+
mode: "circle",
|
|
564
|
+
onClick,
|
|
565
|
+
tooltip: "Circle"
|
|
566
|
+
},
|
|
567
|
+
{
|
|
568
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FreeHandIcon, {}),
|
|
569
|
+
mode: "freehand",
|
|
570
|
+
onClick,
|
|
571
|
+
tooltip: "Freehand"
|
|
572
|
+
},
|
|
573
|
+
{
|
|
574
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DeleteIcon, {}),
|
|
575
|
+
mode: "clear",
|
|
576
|
+
onClick: handleClear,
|
|
577
|
+
tooltip: "Clear all features",
|
|
578
|
+
disabled: !hasFeatures
|
|
579
|
+
}
|
|
580
|
+
],
|
|
581
|
+
[onClick, handleGeolocation, handleClear, hasFeatures]
|
|
582
|
+
);
|
|
583
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", {
|
|
373
584
|
style: {
|
|
585
|
+
position: "absolute",
|
|
586
|
+
top: 10,
|
|
587
|
+
left: 10,
|
|
374
588
|
display: "flex",
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
padding:
|
|
380
|
-
borderRadius:
|
|
381
|
-
|
|
382
|
-
cursor: hasFeatures ? "pointer" : "not-allowed"
|
|
589
|
+
flexDirection: "column",
|
|
590
|
+
gap: 6,
|
|
591
|
+
zIndex: 1e3,
|
|
592
|
+
backgroundColor: "rgba(255,255,255,0.9)",
|
|
593
|
+
padding: 8,
|
|
594
|
+
borderRadius: 6,
|
|
595
|
+
boxShadow: "0 2px 6px rgba(0,0,0,0.2)"
|
|
383
596
|
},
|
|
384
|
-
children:
|
|
597
|
+
children: [
|
|
598
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(IconButton, {
|
|
599
|
+
onClick: () => setExpanded((v) => !v),
|
|
600
|
+
style: {
|
|
601
|
+
display: "flex",
|
|
602
|
+
justifyContent: "center",
|
|
603
|
+
alignItems: "center",
|
|
604
|
+
width: 30,
|
|
605
|
+
height: 30,
|
|
606
|
+
padding: 0,
|
|
607
|
+
borderRadius: 4,
|
|
608
|
+
backgroundColor: "#d3d3d3"
|
|
609
|
+
},
|
|
610
|
+
title: "Expand or collapse tools",
|
|
611
|
+
children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PencilCloseIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PencilOpenIcon, {})
|
|
612
|
+
}),
|
|
613
|
+
expanded && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", {
|
|
614
|
+
style: { display: "flex", flexDirection: "column", gap: 6 },
|
|
615
|
+
children: buttons.map((btn, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(map_button_default, {
|
|
616
|
+
icon: btn.icon,
|
|
617
|
+
mode: btn.mode,
|
|
618
|
+
currentMode: mode,
|
|
619
|
+
onClick: btn.onClick,
|
|
620
|
+
tooltip: btn.tooltip,
|
|
621
|
+
disabled: btn.disabled
|
|
622
|
+
}, i))
|
|
623
|
+
})
|
|
624
|
+
]
|
|
385
625
|
});
|
|
386
|
-
}
|
|
387
|
-
var
|
|
626
|
+
}
|
|
627
|
+
var map_buttons_default = MapButtons;
|
|
388
628
|
|
|
389
629
|
// src/components/map.tsx
|
|
390
|
-
var import_naksha_commons = require("@biodiv-platform/naksha-commons");
|
|
391
630
|
var import_bbox = __toESM(require("@turf/bbox"));
|
|
631
|
+
var import_naksha_commons = require("@biodiv-platform/naksha-commons");
|
|
392
632
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
393
|
-
var ensureModeProperty = (features) => {
|
|
394
|
-
return features.map((feature) => {
|
|
395
|
-
var _a, _b;
|
|
396
|
-
if ((_a = feature.properties) == null ? void 0 : _a.mode)
|
|
397
|
-
return feature;
|
|
398
|
-
const geometryType = (_b = feature.geometry) == null ? void 0 : _b.type;
|
|
399
|
-
const mode = geometryType === "Point" ? "point" : geometryType === "Polygon" ? "polygon" : geometryType === "LineString" ? "linestring" : "unknown";
|
|
400
|
-
return __spreadProps(__spreadValues({}, feature), {
|
|
401
|
-
properties: __spreadProps(__spreadValues({}, feature.properties), { mode })
|
|
402
|
-
});
|
|
403
|
-
});
|
|
404
|
-
};
|
|
405
633
|
var Map = (props) => {
|
|
406
|
-
|
|
407
|
-
const
|
|
408
|
-
const [
|
|
409
|
-
const [
|
|
410
|
-
const
|
|
411
|
-
const
|
|
412
|
-
|
|
413
|
-
|
|
634
|
+
var _a;
|
|
635
|
+
const mapRef = (0, import_react3.useRef)(null);
|
|
636
|
+
const [map, setMap] = (0, import_react3.useState)();
|
|
637
|
+
const [mode, setMode] = (0, import_react3.useState)("static");
|
|
638
|
+
const [draw, setDraw] = (0, import_react3.useState)();
|
|
639
|
+
const drawRef = (0, import_react3.useRef)();
|
|
640
|
+
const { isMultiple, features = [], onFeaturesChange } = props;
|
|
641
|
+
const [selectedMapStyleIdx, setSelectedMapStyleIdx] = (0, import_react3.useState)(
|
|
642
|
+
(props == null ? void 0 : props.mapStyle) || 0
|
|
643
|
+
);
|
|
644
|
+
const mapTile = props.mapStyles ? props.mapStyles : import_naksha_commons.defaultMapStyles;
|
|
645
|
+
const mapStyle = (_a = mapTile[selectedMapStyleIdx]) == null ? void 0 : _a.style;
|
|
646
|
+
const mapStyleConfig = mapTile[selectedMapStyleIdx];
|
|
647
|
+
const storedFeaturesRef = (0, import_react3.useRef)([]);
|
|
648
|
+
const autoFocus = (0, import_react3.useCallback)(
|
|
649
|
+
(features2) => {
|
|
650
|
+
if (!(features2 == null ? void 0 : features2.length) || !map)
|
|
651
|
+
return;
|
|
652
|
+
const _bbox = (0, import_bbox.default)({ type: "FeatureCollection", features: features2 });
|
|
653
|
+
map.fitBounds(_bbox, {
|
|
654
|
+
padding: 40,
|
|
655
|
+
duration: 1e3,
|
|
656
|
+
maxZoom: 15
|
|
657
|
+
});
|
|
658
|
+
},
|
|
659
|
+
[map]
|
|
660
|
+
);
|
|
661
|
+
(0, import_react3.useEffect)(() => {
|
|
662
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
663
|
+
if (features && features.length > 0) {
|
|
664
|
+
storedFeaturesRef.current = ensureModeProperty(features);
|
|
665
|
+
}
|
|
414
666
|
const maplibreMap = setupMaplibreMap({
|
|
415
667
|
containerId: "maplibre-map",
|
|
416
|
-
latitude: (_b = (
|
|
668
|
+
latitude: (_b = (_a2 = props.defaultViewState) == null ? void 0 : _a2.latitude) != null ? _b : 0,
|
|
417
669
|
longitude: (_d = (_c = props.defaultViewState) == null ? void 0 : _c.longitude) != null ? _d : 0,
|
|
418
670
|
zoom: (_f = (_e = props.defaultViewState) == null ? void 0 : _e.zoom) != null ? _f : 0,
|
|
419
671
|
pitch: (_h = (_g = props.defaultViewState) == null ? void 0 : _g.pitch) != null ? _h : 0,
|
|
420
672
|
bearing: (_j = (_i = props.defaultViewState) == null ? void 0 : _i.bearing) != null ? _j : 0,
|
|
421
673
|
mapstyle: mapStyle
|
|
422
674
|
});
|
|
675
|
+
if ("maxZoom" in mapStyleConfig && mapStyleConfig.maxZoom) {
|
|
676
|
+
maplibreMap.setMaxZoom(mapStyleConfig.maxZoom);
|
|
677
|
+
}
|
|
423
678
|
const navControl = new import_maplibre_gl2.default.NavigationControl({
|
|
424
679
|
showCompass: true,
|
|
425
680
|
showZoom: true,
|
|
426
681
|
visualizePitch: true
|
|
427
682
|
});
|
|
683
|
+
const fullscreen = new import_maplibre_gl2.default.FullscreenControl({});
|
|
428
684
|
maplibreMap.addControl(navControl, "bottom-right");
|
|
429
|
-
maplibreMap.
|
|
685
|
+
maplibreMap.addControl(fullscreen, "bottom-right");
|
|
686
|
+
maplibreMap.once("style.load", () => {
|
|
687
|
+
setMap(maplibreMap);
|
|
688
|
+
});
|
|
430
689
|
return () => {
|
|
431
|
-
if (
|
|
690
|
+
if (drawRef.current) {
|
|
691
|
+
storedFeaturesRef.current = drawRef.current.getSnapshot();
|
|
692
|
+
}
|
|
693
|
+
if (drawRef.current) {
|
|
694
|
+
try {
|
|
695
|
+
drawRef.current.stop();
|
|
696
|
+
} catch (e) {
|
|
697
|
+
console.warn("terraDraw stop failed", e);
|
|
698
|
+
}
|
|
699
|
+
drawRef.current = void 0;
|
|
700
|
+
setDraw(void 0);
|
|
701
|
+
}
|
|
702
|
+
if (maplibreMap) {
|
|
432
703
|
maplibreMap.removeControl(navControl);
|
|
704
|
+
maplibreMap.removeControl(fullscreen);
|
|
705
|
+
maplibreMap.remove();
|
|
433
706
|
}
|
|
434
707
|
};
|
|
435
|
-
}, []);
|
|
436
|
-
const
|
|
437
|
-
(
|
|
438
|
-
if (!(features == null ? void 0 : features.length) || !map)
|
|
439
|
-
return;
|
|
440
|
-
const _bbox = (0, import_bbox.default)({
|
|
441
|
-
type: "FeatureCollection",
|
|
442
|
-
features
|
|
443
|
-
});
|
|
444
|
-
map.fitBounds(_bbox, { padding: 40, duration: 1e3 });
|
|
445
|
-
},
|
|
446
|
-
[map]
|
|
708
|
+
}, [mapStyle]);
|
|
709
|
+
const filterUserFeatures = (features2) => features2.filter(
|
|
710
|
+
(f) => f.geometry.type !== "Point" || f.properties.mode !== "static" && f.properties.mode !== "select"
|
|
447
711
|
);
|
|
448
|
-
(0,
|
|
449
|
-
var _a;
|
|
712
|
+
(0, import_react3.useEffect)(() => {
|
|
450
713
|
if (!map)
|
|
451
714
|
return;
|
|
452
715
|
const terraDraw = setupDraw(map);
|
|
453
716
|
terraDraw.start();
|
|
717
|
+
drawRef.current = terraDraw;
|
|
454
718
|
setDraw(terraDraw);
|
|
455
719
|
const handleChange = () => {
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
const
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
720
|
+
let snapshot = terraDraw.getSnapshot();
|
|
721
|
+
let userFeatures = filterUserFeatures(snapshot);
|
|
722
|
+
if (!isMultiple && userFeatures.length > 1) {
|
|
723
|
+
const lastFeature = userFeatures.at(-1);
|
|
724
|
+
const toRemove = userFeatures.slice(0, -1).map((f) => f.id).filter((id) => Boolean(id));
|
|
725
|
+
if (toRemove.length > 0) {
|
|
726
|
+
try {
|
|
727
|
+
terraDraw.removeFeatures(toRemove);
|
|
728
|
+
} catch (e) {
|
|
729
|
+
console.warn("removeFeatures failed", e);
|
|
730
|
+
}
|
|
466
731
|
}
|
|
732
|
+
userFeatures = [lastFeature];
|
|
467
733
|
}
|
|
468
|
-
|
|
469
|
-
autoFocus(
|
|
734
|
+
onFeaturesChange == null ? void 0 : onFeaturesChange(userFeatures);
|
|
735
|
+
autoFocus(userFeatures);
|
|
470
736
|
};
|
|
471
737
|
terraDraw.on("finish", handleChange);
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
}
|
|
480
|
-
terraDraw.addFeatures(initialFeatures);
|
|
481
|
-
autoFocus(initialFeatures);
|
|
738
|
+
setTimeout(() => {
|
|
739
|
+
if (terraDraw.getSnapshot().length === 0) {
|
|
740
|
+
let featuresToAdd = [];
|
|
741
|
+
if (storedFeaturesRef.current.length > 0) {
|
|
742
|
+
featuresToAdd = storedFeaturesRef.current;
|
|
743
|
+
} else if (features && features.length > 0) {
|
|
744
|
+
featuresToAdd = ensureModeProperty(features);
|
|
482
745
|
}
|
|
483
|
-
|
|
484
|
-
|
|
746
|
+
if (!isMultiple && featuresToAdd.length > 1) {
|
|
747
|
+
featuresToAdd = [featuresToAdd.at(-1)];
|
|
748
|
+
}
|
|
749
|
+
if (featuresToAdd.length > 0) {
|
|
750
|
+
terraDraw.addFeatures(featuresToAdd);
|
|
751
|
+
autoFocus(featuresToAdd);
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
}, 100);
|
|
485
755
|
return () => {
|
|
486
756
|
terraDraw.off("finish", handleChange);
|
|
487
|
-
terraDraw.stop();
|
|
488
757
|
};
|
|
489
|
-
}, [map
|
|
490
|
-
const changeMode = (0,
|
|
758
|
+
}, [map]);
|
|
759
|
+
const changeMode = (0, import_react3.useCallback)(
|
|
491
760
|
(newMode) => {
|
|
492
761
|
draw == null ? void 0 : draw.setMode(newMode);
|
|
493
762
|
setMode(newMode);
|
|
494
763
|
},
|
|
495
764
|
[draw]
|
|
496
765
|
);
|
|
497
|
-
|
|
766
|
+
const handleStyleChange = (idx) => {
|
|
767
|
+
if (drawRef.current) {
|
|
768
|
+
storedFeaturesRef.current = drawRef.current.getSnapshot();
|
|
769
|
+
}
|
|
770
|
+
setSelectedMapStyleIdx(idx);
|
|
771
|
+
setMode("static");
|
|
772
|
+
};
|
|
773
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", {
|
|
498
774
|
ref: mapRef,
|
|
499
775
|
id: "maplibre-map",
|
|
500
|
-
style: { width: "100%", height: "100%" },
|
|
501
|
-
children:
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
padding: "8px",
|
|
518
|
-
borderRadius: "6px",
|
|
519
|
-
boxShadow: "0 2px 6px rgba(0,0,0,0.2)"
|
|
520
|
-
},
|
|
521
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ClearButton_default, {
|
|
522
|
-
draw,
|
|
523
|
-
onFeaturesChange: props.onFeaturesChange
|
|
524
|
-
})
|
|
525
|
-
})
|
|
526
|
-
]
|
|
527
|
-
})
|
|
776
|
+
style: { width: "100%", height: "100%", position: "relative" },
|
|
777
|
+
children: [
|
|
778
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MapStyleSwitcher, {
|
|
779
|
+
currentStyleIdx: selectedMapStyleIdx,
|
|
780
|
+
onStyleChange: handleStyleChange,
|
|
781
|
+
mapStyles: mapTile
|
|
782
|
+
}),
|
|
783
|
+
draw && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(map_buttons_default, {
|
|
784
|
+
mode,
|
|
785
|
+
setMode,
|
|
786
|
+
onClick: changeMode,
|
|
787
|
+
draw,
|
|
788
|
+
onFeaturesChange,
|
|
789
|
+
isMultiple,
|
|
790
|
+
autoFocus
|
|
791
|
+
})
|
|
792
|
+
]
|
|
528
793
|
});
|
|
529
794
|
};
|
|
530
795
|
var map_default = Map;
|