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