leaflet-anvil 0.1.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.
package/dist/index.js ADDED
@@ -0,0 +1,2090 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
31
+
32
+ // src/index.ts
33
+ var index_exports = {};
34
+ __export(index_exports, {
35
+ ANVIL_EVENTS: () => ANVIL_EVENTS,
36
+ Anvil: () => Anvil,
37
+ AnvilControl: () => AnvilControl,
38
+ anvilControl: () => anvilControl
39
+ });
40
+ module.exports = __toCommonJS(index_exports);
41
+ var L22 = __toESM(require("leaflet"));
42
+
43
+ // src/events.ts
44
+ var ANVIL_EVENTS = {
45
+ CREATED: "anvil:created",
46
+ EDITED: "anvil:edited",
47
+ DELETED: "anvil:deleted",
48
+ SPLIT: "anvil:split",
49
+ UNION: "anvil:union",
50
+ SUBTRACT: "anvil:subtract",
51
+ MODE_CHANGE: "anvil:modechange"
52
+ };
53
+
54
+ // src/modes/mode-manager.ts
55
+ var ModeManager = class {
56
+ constructor(map) {
57
+ this.map = map;
58
+ __publicField(this, "currentMode", null);
59
+ __publicField(this, "modes", /* @__PURE__ */ new Map());
60
+ }
61
+ addMode(name, mode) {
62
+ this.modes.set(name, mode);
63
+ }
64
+ enable(name) {
65
+ const mode = this.modes.get(name);
66
+ if (!mode) {
67
+ console.warn(`Anvil ModeManager: Mode "${name}" not found.`);
68
+ return;
69
+ }
70
+ if (this.currentMode === mode) return;
71
+ this.disable();
72
+ this.currentMode = mode;
73
+ this.currentMode.enable();
74
+ this.map.fire(ANVIL_EVENTS.MODE_CHANGE, { mode: name });
75
+ }
76
+ disable() {
77
+ if (this.currentMode) {
78
+ this.currentMode.disable();
79
+ this.currentMode = null;
80
+ this.map.fire(ANVIL_EVENTS.MODE_CHANGE, { mode: null });
81
+ }
82
+ }
83
+ };
84
+
85
+ // src/modes/draw-polygon-mode.ts
86
+ var L3 = __toESM(require("leaflet"));
87
+
88
+ // src/utils/snapping.ts
89
+ var L = __toESM(require("leaflet"));
90
+ function getSnapLatLng(map, latlng, store, options, additionalPoints = [], skipLayer) {
91
+ if (!options.snapping) return latlng;
92
+ const snapDistance = options.snapDistance || 10;
93
+ const basePoint = map.latLngToContainerPoint(latlng);
94
+ let closestPoint = null;
95
+ let minDistance = snapDistance;
96
+ const skipLayers = Array.isArray(skipLayer) ? skipLayer : skipLayer ? [skipLayer] : [];
97
+ const bounds = map.getBounds().pad(0.1);
98
+ store.getGroup().eachLayer((layer) => {
99
+ if (skipLayers.includes(layer)) return;
100
+ if (layer.getBounds && !bounds.intersects(layer.getBounds())) return;
101
+ const pointsToCheck = [];
102
+ if (layer instanceof L.Marker || layer instanceof L.CircleMarker || layer instanceof L.Circle) {
103
+ pointsToCheck.push(layer.getLatLng());
104
+ } else if (layer instanceof L.Polyline) {
105
+ const latlngs = layer.getLatLngs();
106
+ const flatten5 = (arr) => {
107
+ let result = [];
108
+ arr.forEach((item) => {
109
+ if (Array.isArray(item)) {
110
+ result = result.concat(flatten5(item));
111
+ } else if (item instanceof L.LatLng) {
112
+ result.push(item);
113
+ }
114
+ });
115
+ return result;
116
+ };
117
+ pointsToCheck.push(...flatten5(latlngs));
118
+ }
119
+ pointsToCheck.forEach((p) => {
120
+ const containerPoint = map.latLngToContainerPoint(p);
121
+ const dist = basePoint.distanceTo(containerPoint);
122
+ if (dist < minDistance) {
123
+ minDistance = dist;
124
+ closestPoint = p;
125
+ }
126
+ });
127
+ });
128
+ additionalPoints.forEach((p) => {
129
+ const containerPoint = map.latLngToContainerPoint(p);
130
+ const dist = basePoint.distanceTo(containerPoint);
131
+ if (dist < minDistance) {
132
+ minDistance = dist;
133
+ closestPoint = p;
134
+ }
135
+ });
136
+ return closestPoint || latlng;
137
+ }
138
+
139
+ // src/utils/geometry.ts
140
+ var L2 = __toESM(require("leaflet"));
141
+ function segmentsIntersect(a, b, c, d) {
142
+ const crossProduct = (p1, p2, p3) => {
143
+ return (p2.y - p1.y) * (p3.x - p2.x) - (p2.x - p1.x) * (p3.y - p2.y);
144
+ };
145
+ const cp1 = crossProduct(a, b, c);
146
+ const cp2 = crossProduct(a, b, d);
147
+ const cp3 = crossProduct(c, d, a);
148
+ const cp4 = crossProduct(c, d, b);
149
+ if ((cp1 > 0 && cp2 < 0 || cp1 < 0 && cp2 > 0) && (cp3 > 0 && cp4 < 0 || cp3 < 0 && cp4 > 0)) {
150
+ return true;
151
+ }
152
+ return false;
153
+ }
154
+ function causesSelfIntersection(map, points, nextPoint, isClosing = false) {
155
+ if (points.length < 2) return false;
156
+ const p2 = map.latLngToLayerPoint(nextPoint);
157
+ const p1 = map.latLngToLayerPoint(points[points.length - 1]);
158
+ const limit = points.length - 2;
159
+ for (let i = 0; i < limit; i++) {
160
+ const a = map.latLngToLayerPoint(points[i]);
161
+ const b = map.latLngToLayerPoint(points[i + 1]);
162
+ if (segmentsIntersect(p1, p2, a, b)) {
163
+ return true;
164
+ }
165
+ }
166
+ if (isClosing) {
167
+ }
168
+ return false;
169
+ }
170
+ function isSelfIntersecting(map, latlngs, isPolygon) {
171
+ const flatten5 = (arr) => {
172
+ if (!Array.isArray(arr)) return [];
173
+ if (arr[0] instanceof L2.LatLng) return arr;
174
+ return arr.reduce((acc, val) => acc.concat(flatten5(val)), []);
175
+ };
176
+ const points = flatten5(latlngs);
177
+ if (points.length < 4) return false;
178
+ const projectedPoints = points.map((p) => map.latLngToLayerPoint(p));
179
+ const len = projectedPoints.length;
180
+ for (let i = 0; i < len; i++) {
181
+ const a = projectedPoints[i];
182
+ const b = projectedPoints[(i + 1) % len];
183
+ if (!isPolygon && i === len - 1) break;
184
+ for (let j = i + 2; j < len; j++) {
185
+ if (isPolygon && (j + 1) % len === i) continue;
186
+ if (!isPolygon && j === len - 1) break;
187
+ const c = projectedPoints[j];
188
+ const d = projectedPoints[(j + 1) % len];
189
+ if (segmentsIntersect(a, b, c, d)) return true;
190
+ }
191
+ }
192
+ return false;
193
+ }
194
+
195
+ // src/modes/draw-polygon-mode.ts
196
+ var DrawPolygonMode = class {
197
+ constructor(map, options = {}, store) {
198
+ this.map = map;
199
+ this.options = options;
200
+ this.store = store;
201
+ __publicField(this, "points", []);
202
+ __publicField(this, "markers", []);
203
+ __publicField(this, "polyline", null);
204
+ __publicField(this, "ghostLine", null);
205
+ }
206
+ enable() {
207
+ this.map.on("click", this.onClick, this);
208
+ this.map.on("mousemove", this.onMouseMove, this);
209
+ L3.DomEvent.on(window, "keydown", this.onKeyDown, this);
210
+ this.map.getContainer().style.cursor = "crosshair";
211
+ }
212
+ disable() {
213
+ this.map.off("click", this.onClick, this);
214
+ this.map.off("mousemove", this.onMouseMove, this);
215
+ L3.DomEvent.off(window, "keydown", this.onKeyDown, this);
216
+ this.map.getContainer().style.cursor = "";
217
+ this.reset();
218
+ }
219
+ onClick(e) {
220
+ const latlng = this.store ? getSnapLatLng(this.map, e.latlng, this.store, this.options, this.points) : e.latlng;
221
+ if (this.points.length > 0 && this.isFirstPoint(latlng)) {
222
+ if (this.options.preventSelfIntersection && causesSelfIntersection(this.map, this.points, this.points[0])) {
223
+ return;
224
+ }
225
+ this.finish();
226
+ return;
227
+ }
228
+ if (this.options.preventSelfIntersection && causesSelfIntersection(this.map, this.points, latlng)) {
229
+ return;
230
+ }
231
+ this.points.push(latlng);
232
+ this.updateDrawing();
233
+ }
234
+ isFirstPoint(latlng) {
235
+ if (this.points.length < 3) return false;
236
+ const firstPoint = this.points[0];
237
+ if (latlng.equals(firstPoint)) return true;
238
+ const containerPoint = this.map.latLngToContainerPoint(latlng);
239
+ const firstContainerPoint = this.map.latLngToContainerPoint(firstPoint);
240
+ return containerPoint.distanceTo(firstContainerPoint) < (this.options.snapDistance || 10);
241
+ }
242
+ onMouseMove(e) {
243
+ if (this.points.length === 0) return;
244
+ const snapLatLng = this.store ? getSnapLatLng(this.map, e.latlng, this.store, this.options, this.points) : e.latlng;
245
+ const lastPoint = this.points[this.points.length - 1];
246
+ if (!this.ghostLine) {
247
+ this.ghostLine = L3.polyline([lastPoint, snapLatLng], {
248
+ dashArray: "5, 5",
249
+ color: "#3388ff",
250
+ weight: 2
251
+ }).addTo(this.map);
252
+ } else {
253
+ this.ghostLine.setLatLngs([lastPoint, snapLatLng]);
254
+ }
255
+ }
256
+ onKeyDown(e) {
257
+ if (e.key === "Escape") {
258
+ this.reset();
259
+ }
260
+ }
261
+ updateDrawing() {
262
+ if (this.polyline) {
263
+ this.polyline.setLatLngs(this.points);
264
+ } else {
265
+ this.polyline = L3.polyline(this.points, { color: "#3388ff" }).addTo(this.map);
266
+ }
267
+ if (this.points.length === 1 && this.markers.length === 0) {
268
+ const marker4 = L3.circleMarker(this.points[0], {
269
+ radius: 5,
270
+ fillColor: "#fff",
271
+ fillOpacity: 1,
272
+ color: "#3388ff",
273
+ weight: 2
274
+ }).addTo(this.map);
275
+ marker4.on("click", (e) => {
276
+ L3.DomEvent.stopPropagation(e);
277
+ this.finish();
278
+ });
279
+ this.markers.push(marker4);
280
+ }
281
+ }
282
+ finish() {
283
+ if (this.points.length < 3) return;
284
+ const polygon7 = L3.polygon(this.points).addTo(this.map);
285
+ this.map.fire(ANVIL_EVENTS.CREATED, { layer: polygon7 });
286
+ this.reset();
287
+ }
288
+ reset() {
289
+ if (this.polyline) this.map.removeLayer(this.polyline);
290
+ if (this.ghostLine) this.map.removeLayer(this.ghostLine);
291
+ this.markers.forEach((m) => this.map.removeLayer(m));
292
+ this.points = [];
293
+ this.markers = [];
294
+ this.polyline = null;
295
+ this.ghostLine = null;
296
+ }
297
+ };
298
+
299
+ // src/modes/draw-polyline-mode.ts
300
+ var L4 = __toESM(require("leaflet"));
301
+ var DrawPolylineMode = class {
302
+ constructor(map, options = {}, store) {
303
+ this.map = map;
304
+ this.options = options;
305
+ this.store = store;
306
+ __publicField(this, "points", []);
307
+ __publicField(this, "polyline", null);
308
+ __publicField(this, "ghostLine", null);
309
+ }
310
+ enable() {
311
+ this.map.on("click", this.onClick, this);
312
+ this.map.on("mousemove", this.onMouseMove, this);
313
+ this.map.on("dblclick", this.onDoubleClick, this);
314
+ L4.DomEvent.on(window, "keydown", this.onKeyDown, this);
315
+ this.map.doubleClickZoom.disable();
316
+ this.map.getContainer().style.cursor = "crosshair";
317
+ }
318
+ disable() {
319
+ this.map.off("click", this.onClick, this);
320
+ this.map.off("mousemove", this.onMouseMove, this);
321
+ this.map.off("dblclick", this.onDoubleClick, this);
322
+ L4.DomEvent.off(window, "keydown", this.onKeyDown, this);
323
+ this.map.doubleClickZoom.enable();
324
+ this.map.getContainer().style.cursor = "";
325
+ this.reset();
326
+ }
327
+ onClick(e) {
328
+ const latlng = this.store ? getSnapLatLng(this.map, e.latlng, this.store, this.options, this.points) : e.latlng;
329
+ if (this.options.preventSelfIntersection && causesSelfIntersection(this.map, this.points, latlng)) {
330
+ return;
331
+ }
332
+ this.points.push(latlng);
333
+ this.updateDrawing();
334
+ }
335
+ onMouseMove(e) {
336
+ if (this.points.length === 0) return;
337
+ const snapLatLng = this.store ? getSnapLatLng(this.map, e.latlng, this.store, this.options, this.points) : e.latlng;
338
+ const lastPoint = this.points[this.points.length - 1];
339
+ if (!this.ghostLine) {
340
+ this.ghostLine = L4.polyline([lastPoint, e.latlng], {
341
+ dashArray: "5, 5",
342
+ color: "#3388ff",
343
+ weight: 2
344
+ }).addTo(this.map);
345
+ } else {
346
+ this.ghostLine.setLatLngs([lastPoint, snapLatLng]);
347
+ }
348
+ }
349
+ onDoubleClick(e) {
350
+ L4.DomEvent.stopPropagation(e);
351
+ this.finish();
352
+ }
353
+ onKeyDown(e) {
354
+ if (e.key === "Escape") {
355
+ this.reset();
356
+ } else if (e.key === "Enter") {
357
+ this.finish();
358
+ }
359
+ }
360
+ updateDrawing() {
361
+ if (this.polyline) {
362
+ this.polyline.setLatLngs(this.points);
363
+ } else {
364
+ this.polyline = L4.polyline(this.points, { color: "#3388ff" }).addTo(this.map);
365
+ }
366
+ }
367
+ finish() {
368
+ if (this.points.length < 2) return;
369
+ const polyline6 = L4.polyline(this.points).addTo(this.map);
370
+ this.map.fire(ANVIL_EVENTS.CREATED, { layer: polyline6 });
371
+ this.reset();
372
+ }
373
+ reset() {
374
+ if (this.polyline) this.map.removeLayer(this.polyline);
375
+ if (this.ghostLine) this.map.removeLayer(this.ghostLine);
376
+ this.points = [];
377
+ this.polyline = null;
378
+ this.ghostLine = null;
379
+ }
380
+ };
381
+
382
+ // src/modes/draw-marker-mode.ts
383
+ var L5 = __toESM(require("leaflet"));
384
+ var DrawMarkerMode = class {
385
+ constructor(map, options = {}, store) {
386
+ this.map = map;
387
+ this.options = options;
388
+ this.store = store;
389
+ }
390
+ enable() {
391
+ this.map.on("click", this.onClick, this);
392
+ this.map.getContainer().style.cursor = "crosshair";
393
+ }
394
+ disable() {
395
+ this.map.off("click", this.onClick, this);
396
+ this.map.getContainer().style.cursor = "";
397
+ }
398
+ onClick(e) {
399
+ const latlng = this.store ? getSnapLatLng(this.map, e.latlng, this.store, this.options) : e.latlng;
400
+ const marker4 = L5.marker(latlng).addTo(this.map);
401
+ this.map.fire(ANVIL_EVENTS.CREATED, { layer: marker4 });
402
+ }
403
+ };
404
+
405
+ // src/modes/draw-rectangle-mode.ts
406
+ var L6 = __toESM(require("leaflet"));
407
+ var DrawRectangleMode = class {
408
+ constructor(map, options = {}, store) {
409
+ this.map = map;
410
+ this.options = options;
411
+ this.store = store;
412
+ __publicField(this, "rectangle", null);
413
+ __publicField(this, "startLatLng", null);
414
+ }
415
+ enable() {
416
+ this.map.on("mousedown", this.onMouseDown, this);
417
+ this.map.on("mousemove", this.onMouseMove, this);
418
+ this.map.on("mouseup", this.onMouseUp, this);
419
+ this.map.dragging.disable();
420
+ this.map.getContainer().style.cursor = "crosshair";
421
+ }
422
+ disable() {
423
+ this.map.off("mousedown", this.onMouseDown, this);
424
+ this.map.off("mousemove", this.onMouseMove, this);
425
+ this.map.off("mouseup", this.onMouseUp, this);
426
+ this.map.dragging.enable();
427
+ this.map.getContainer().style.cursor = "";
428
+ this.reset();
429
+ }
430
+ onMouseDown(e) {
431
+ this.startLatLng = this.store ? getSnapLatLng(this.map, e.latlng, this.store, this.options) : e.latlng;
432
+ }
433
+ onMouseMove(e) {
434
+ if (!this.startLatLng) return;
435
+ const currentLatLng = this.store ? getSnapLatLng(this.map, e.latlng, this.store, this.options) : e.latlng;
436
+ const bounds = L6.latLngBounds(this.startLatLng, currentLatLng);
437
+ if (!this.rectangle) {
438
+ this.rectangle = L6.rectangle(bounds, { color: "#3388ff", weight: 2 }).addTo(this.map);
439
+ } else {
440
+ this.rectangle.setBounds(bounds);
441
+ }
442
+ }
443
+ onMouseUp(e) {
444
+ if (!this.startLatLng) return;
445
+ const currentLatLng = this.store ? getSnapLatLng(this.map, e.latlng, this.store, this.options) : e.latlng;
446
+ const bounds = L6.latLngBounds(this.startLatLng, currentLatLng);
447
+ const rectangle3 = L6.rectangle(bounds).addTo(this.map);
448
+ this.map.fire(ANVIL_EVENTS.CREATED, { layer: rectangle3 });
449
+ this.reset();
450
+ }
451
+ reset() {
452
+ if (this.rectangle) this.map.removeLayer(this.rectangle);
453
+ this.rectangle = null;
454
+ this.startLatLng = null;
455
+ }
456
+ };
457
+
458
+ // src/modes/draw-square-mode.ts
459
+ var L7 = __toESM(require("leaflet"));
460
+ var DrawSquareMode = class {
461
+ constructor(map, options = {}, store) {
462
+ this.map = map;
463
+ this.options = options;
464
+ this.store = store;
465
+ __publicField(this, "rectangle", null);
466
+ __publicField(this, "startLatLng", null);
467
+ }
468
+ enable() {
469
+ this.map.on("mousedown", this.onMouseDown, this);
470
+ this.map.on("mousemove", this.onMouseMove, this);
471
+ this.map.on("mouseup", this.onMouseUp, this);
472
+ this.map.dragging.disable();
473
+ this.map.getContainer().style.cursor = "crosshair";
474
+ }
475
+ disable() {
476
+ this.map.off("mousedown", this.onMouseDown, this);
477
+ this.map.off("mousemove", this.onMouseMove, this);
478
+ this.map.off("mouseup", this.onMouseUp, this);
479
+ this.map.dragging.enable();
480
+ this.map.getContainer().style.cursor = "";
481
+ this.reset();
482
+ }
483
+ onMouseDown(e) {
484
+ this.startLatLng = this.store ? getSnapLatLng(this.map, e.latlng, this.store, this.options) : e.latlng;
485
+ }
486
+ onMouseMove(e) {
487
+ if (!this.startLatLng) return;
488
+ const currentLatLng = this.store ? getSnapLatLng(this.map, e.latlng, this.store, this.options) : e.latlng;
489
+ const squareBounds = this.getSquareBounds(this.startLatLng, currentLatLng);
490
+ if (!this.rectangle) {
491
+ this.rectangle = L7.rectangle(squareBounds, { color: "#3388ff", weight: 2 }).addTo(this.map);
492
+ } else {
493
+ this.rectangle.setBounds(squareBounds);
494
+ }
495
+ }
496
+ onMouseUp(e) {
497
+ if (!this.startLatLng) return;
498
+ const currentLatLng = this.store ? getSnapLatLng(this.map, e.latlng, this.store, this.options) : e.latlng;
499
+ const squareBounds = this.getSquareBounds(this.startLatLng, currentLatLng);
500
+ const polygon7 = L7.polygon([
501
+ squareBounds.getNorthWest(),
502
+ squareBounds.getNorthEast(),
503
+ squareBounds.getSouthEast(),
504
+ squareBounds.getSouthWest()
505
+ ]).addTo(this.map);
506
+ this.map.fire(ANVIL_EVENTS.CREATED, { layer: polygon7 });
507
+ this.reset();
508
+ }
509
+ getSquareBounds(start, end) {
510
+ const startPoint = this.map.latLngToContainerPoint(start);
511
+ const endPoint = this.map.latLngToContainerPoint(end);
512
+ const dx = endPoint.x - startPoint.x;
513
+ const dy = endPoint.y - startPoint.y;
514
+ const side = Math.max(Math.abs(dx), Math.abs(dy));
515
+ const newEndPoint = L7.point(
516
+ startPoint.x + side * Math.sign(dx),
517
+ startPoint.y + side * Math.sign(dy)
518
+ );
519
+ return L7.latLngBounds(start, this.map.containerPointToLatLng(newEndPoint));
520
+ }
521
+ reset() {
522
+ if (this.rectangle) this.map.removeLayer(this.rectangle);
523
+ this.rectangle = null;
524
+ this.startLatLng = null;
525
+ }
526
+ };
527
+
528
+ // src/modes/draw-triangle-mode.ts
529
+ var L8 = __toESM(require("leaflet"));
530
+ var DrawTriangleMode = class {
531
+ constructor(map, options = {}, store) {
532
+ this.map = map;
533
+ this.options = options;
534
+ this.store = store;
535
+ __publicField(this, "ghostTriangle", null);
536
+ __publicField(this, "startLatLng", null);
537
+ }
538
+ enable() {
539
+ this.map.on("mousedown", this.onMouseDown, this);
540
+ this.map.on("mousemove", this.onMouseMove, this);
541
+ this.map.on("mouseup", this.onMouseUp, this);
542
+ this.map.dragging.disable();
543
+ this.map.getContainer().style.cursor = "crosshair";
544
+ }
545
+ disable() {
546
+ this.map.off("mousedown", this.onMouseDown, this);
547
+ this.map.off("mousemove", this.onMouseMove, this);
548
+ this.map.off("mouseup", this.onMouseUp, this);
549
+ this.map.dragging.enable();
550
+ this.map.getContainer().style.cursor = "";
551
+ this.reset();
552
+ }
553
+ onMouseDown(e) {
554
+ this.startLatLng = this.store ? getSnapLatLng(this.map, e.latlng, this.store, this.options) : e.latlng;
555
+ }
556
+ onMouseMove(e) {
557
+ if (!this.startLatLng) return;
558
+ const currentLatLng = this.store ? getSnapLatLng(this.map, e.latlng, this.store, this.options) : e.latlng;
559
+ const trianglePoints = this.getTrianglePoints(this.startLatLng, currentLatLng);
560
+ if (!this.ghostTriangle) {
561
+ this.ghostTriangle = L8.polygon(trianglePoints, { color: "#3388ff", weight: 2 }).addTo(this.map);
562
+ } else {
563
+ this.ghostTriangle.setLatLngs(trianglePoints);
564
+ }
565
+ }
566
+ onMouseUp(e) {
567
+ if (!this.startLatLng) return;
568
+ const currentLatLng = this.store ? getSnapLatLng(this.map, e.latlng, this.store, this.options) : e.latlng;
569
+ const trianglePoints = this.getTrianglePoints(this.startLatLng, currentLatLng);
570
+ const polygon7 = L8.polygon(trianglePoints).addTo(this.map);
571
+ this.map.fire(ANVIL_EVENTS.CREATED, { layer: polygon7 });
572
+ this.reset();
573
+ }
574
+ getTrianglePoints(start, end) {
575
+ const midLng = (start.lng + end.lng) / 2;
576
+ const tip = L8.latLng(end.lat, midLng);
577
+ const baseLeft = L8.latLng(start.lat, start.lng);
578
+ const baseRight = L8.latLng(start.lat, end.lng);
579
+ return [
580
+ tip,
581
+ baseRight,
582
+ baseLeft
583
+ ];
584
+ }
585
+ reset() {
586
+ if (this.ghostTriangle) this.map.removeLayer(this.ghostTriangle);
587
+ this.ghostTriangle = null;
588
+ this.startLatLng = null;
589
+ }
590
+ };
591
+
592
+ // src/modes/draw-circle-mode.ts
593
+ var L9 = __toESM(require("leaflet"));
594
+ var DrawCircleMode = class {
595
+ constructor(map, options = {}, store) {
596
+ this.map = map;
597
+ this.options = options;
598
+ this.store = store;
599
+ __publicField(this, "circle", null);
600
+ __publicField(this, "centerLatLng", null);
601
+ }
602
+ enable() {
603
+ this.map.on("mousedown", this.onMouseDown, this);
604
+ this.map.on("mousemove", this.onMouseMove, this);
605
+ this.map.on("mouseup", this.onMouseUp, this);
606
+ this.map.dragging.disable();
607
+ this.map.getContainer().style.cursor = "crosshair";
608
+ }
609
+ disable() {
610
+ this.map.off("mousedown", this.onMouseDown, this);
611
+ this.map.off("mousemove", this.onMouseMove, this);
612
+ this.map.off("mouseup", this.onMouseUp, this);
613
+ this.map.dragging.enable();
614
+ this.map.getContainer().style.cursor = "";
615
+ this.reset();
616
+ }
617
+ onMouseDown(e) {
618
+ this.centerLatLng = this.store ? getSnapLatLng(this.map, e.latlng, this.store, this.options) : e.latlng;
619
+ }
620
+ onMouseMove(e) {
621
+ if (!this.centerLatLng) return;
622
+ const currentLatLng = this.store ? getSnapLatLng(this.map, e.latlng, this.store, this.options) : e.latlng;
623
+ const radius = this.map.distance(this.centerLatLng, currentLatLng);
624
+ if (!this.circle) {
625
+ this.circle = L9.circle(this.centerLatLng, { radius, color: "#3388ff", weight: 2 }).addTo(this.map);
626
+ } else {
627
+ this.circle.setRadius(radius);
628
+ }
629
+ }
630
+ onMouseUp(e) {
631
+ if (!this.centerLatLng) return;
632
+ const currentLatLng = this.store ? getSnapLatLng(this.map, e.latlng, this.store, this.options) : e.latlng;
633
+ const radius = this.map.distance(this.centerLatLng, currentLatLng);
634
+ const circle2 = L9.circle(this.centerLatLng, { radius }).addTo(this.map);
635
+ this.map.fire(ANVIL_EVENTS.CREATED, { layer: circle2 });
636
+ this.reset();
637
+ }
638
+ reset() {
639
+ if (this.circle) this.map.removeLayer(this.circle);
640
+ this.circle = null;
641
+ this.centerLatLng = null;
642
+ }
643
+ };
644
+
645
+ // src/modes/freehand-mode.ts
646
+ var L10 = __toESM(require("leaflet"));
647
+ var turf = __toESM(require("@turf/turf"));
648
+ var FreehandMode = class {
649
+ constructor(map, _store, options = {}) {
650
+ this.map = map;
651
+ this.options = options;
652
+ __publicField(this, "points", []);
653
+ __publicField(this, "polyline", null);
654
+ __publicField(this, "isDrawing", false);
655
+ }
656
+ enable() {
657
+ this.map.dragging.disable();
658
+ this.map.on("mousedown", this.onMouseDown, this);
659
+ this.map.on("mousemove", this.onMouseMove, this);
660
+ this.map.on("mouseup", this.onMouseUp, this);
661
+ L10.DomEvent.on(window, "keydown", this.onKeyDown, this);
662
+ this.map.getContainer().style.cursor = "crosshair";
663
+ }
664
+ disable() {
665
+ this.map.dragging.enable();
666
+ this.map.off("mousedown", this.onMouseDown, this);
667
+ this.map.off("mousemove", this.onMouseMove, this);
668
+ this.map.off("mouseup", this.onMouseUp, this);
669
+ L10.DomEvent.off(window, "keydown", this.onKeyDown, this);
670
+ this.map.getContainer().style.cursor = "";
671
+ this.resetDrawing();
672
+ }
673
+ onMouseDown(e) {
674
+ this.isDrawing = true;
675
+ this.points = [e.latlng];
676
+ this.updateDrawing();
677
+ }
678
+ onMouseMove(e) {
679
+ if (!this.isDrawing) return;
680
+ const lastPoint = this.points[this.points.length - 1];
681
+ if (lastPoint.distanceTo(e.latlng) > 5) {
682
+ this.points.push(e.latlng);
683
+ this.updateDrawing();
684
+ }
685
+ }
686
+ onMouseUp() {
687
+ if (!this.isDrawing) return;
688
+ this.finish();
689
+ }
690
+ onKeyDown(e) {
691
+ if (e.key === "Escape") {
692
+ this.resetDrawing();
693
+ }
694
+ }
695
+ updateDrawing() {
696
+ if (this.polyline) {
697
+ this.polyline.setLatLngs(this.points);
698
+ } else {
699
+ this.polyline = L10.polyline(this.points, {
700
+ color: "#3388ff",
701
+ weight: 3,
702
+ opacity: 0.8,
703
+ dashArray: "5, 5"
704
+ }).addTo(this.map);
705
+ }
706
+ }
707
+ finish() {
708
+ if (this.points.length < 3) {
709
+ this.resetDrawing();
710
+ return;
711
+ }
712
+ const lineGeo = L10.polyline(this.points).toGeoJSON();
713
+ const tolerance = this.options.freehandTolerance || 1e-5;
714
+ const simplified = turf.simplify(lineGeo, { tolerance, highQuality: true });
715
+ const finalCoords = turf.getCoords(simplified);
716
+ if (finalCoords.length > 0 && (finalCoords[0][0] !== finalCoords[finalCoords.length - 1][0] || finalCoords[0][1] !== finalCoords[finalCoords.length - 1][1])) {
717
+ finalCoords.push(finalCoords[0]);
718
+ }
719
+ const finalPolygon = L10.polygon(finalCoords.map((c) => [c[1], c[0]])).addTo(this.map);
720
+ this.map.fire(ANVIL_EVENTS.CREATED, { layer: finalPolygon });
721
+ this.resetDrawing();
722
+ }
723
+ resetDrawing() {
724
+ if (this.polyline) this.map.removeLayer(this.polyline);
725
+ this.polyline = null;
726
+ this.points = [];
727
+ this.isDrawing = false;
728
+ }
729
+ };
730
+
731
+ // src/modes/cut-mode.ts
732
+ var L11 = __toESM(require("leaflet"));
733
+ var turf2 = __toESM(require("@turf/turf"));
734
+ var CutMode = class {
735
+ constructor(map, store, options = {}) {
736
+ this.map = map;
737
+ this.store = store;
738
+ this.options = options;
739
+ __publicField(this, "points", []);
740
+ __publicField(this, "markers", []);
741
+ __publicField(this, "polyline", null);
742
+ __publicField(this, "ghostLine", null);
743
+ }
744
+ enable() {
745
+ this.map.on("click", this.onMapClick, this);
746
+ this.map.on("mousemove", this.onMouseMove, this);
747
+ L11.DomEvent.on(window, "keydown", this.onKeyDown, this);
748
+ this.map.getContainer().style.cursor = "crosshair";
749
+ }
750
+ disable() {
751
+ this.map.off("click", this.onMapClick, this);
752
+ this.map.off("mousemove", this.onMouseMove, this);
753
+ L11.DomEvent.off(window, "keydown", this.onKeyDown, this);
754
+ this.resetDrawing();
755
+ this.map.getContainer().style.cursor = "";
756
+ }
757
+ onMapClick(e) {
758
+ const latlng = getSnapLatLng(this.map, e.latlng, this.store, this.options, this.points);
759
+ if (this.points.length > 0 && this.isFirstPoint(latlng)) {
760
+ this.finish();
761
+ return;
762
+ }
763
+ this.points.push(latlng);
764
+ this.updateDrawing();
765
+ }
766
+ isFirstPoint(latlng) {
767
+ if (this.points.length < 3) return false;
768
+ const firstPoint = this.points[0];
769
+ const containerPoint = this.map.latLngToContainerPoint(latlng);
770
+ const firstContainerPoint = this.map.latLngToContainerPoint(firstPoint);
771
+ return containerPoint.distanceTo(firstContainerPoint) < 15;
772
+ }
773
+ onMouseMove(e) {
774
+ if (this.points.length === 0) return;
775
+ const snapLatLng = getSnapLatLng(this.map, e.latlng, this.store, this.options, this.points);
776
+ const lastPoint = this.points[this.points.length - 1];
777
+ if (!this.ghostLine) {
778
+ this.ghostLine = L11.polyline([lastPoint, snapLatLng], {
779
+ dashArray: "5, 5",
780
+ color: "#ff0000",
781
+ weight: 2
782
+ }).addTo(this.map);
783
+ } else {
784
+ this.ghostLine.setLatLngs([lastPoint, snapLatLng]);
785
+ }
786
+ }
787
+ onKeyDown(e) {
788
+ if (e.key === "Escape") {
789
+ this.resetDrawing();
790
+ }
791
+ }
792
+ updateDrawing() {
793
+ if (this.polyline) {
794
+ this.polyline.setLatLngs(this.points);
795
+ } else {
796
+ this.polyline = L11.polyline(this.points, { color: "#ff0000" }).addTo(this.map);
797
+ }
798
+ if (this.points.length === 1 && this.markers.length === 0) {
799
+ const marker4 = L11.circleMarker(this.points[0], {
800
+ radius: 6,
801
+ fillColor: "#fff",
802
+ fillOpacity: 1,
803
+ color: "#ff0000",
804
+ weight: 2
805
+ }).addTo(this.map);
806
+ marker4.on("click", (e) => {
807
+ L11.DomEvent.stopPropagation(e);
808
+ if (this.points.length >= 3) this.finish();
809
+ });
810
+ this.markers.push(marker4);
811
+ }
812
+ }
813
+ finish() {
814
+ if (this.points.length < 3) return;
815
+ const holeGeo = L11.polygon(this.points).toGeoJSON();
816
+ const intersectedLayers = [];
817
+ this.store.getGroup().eachLayer((layer) => {
818
+ if (layer instanceof L11.Polygon) {
819
+ const polyGeo = layer.toGeoJSON();
820
+ if (turf2.booleanIntersects(polyGeo, holeGeo)) {
821
+ intersectedLayers.push(layer);
822
+ }
823
+ }
824
+ });
825
+ if (intersectedLayers.length === 0) {
826
+ this.resetDrawing();
827
+ return;
828
+ }
829
+ intersectedLayers.forEach((polygon7) => {
830
+ const polyGeo = polygon7.toGeoJSON();
831
+ const result = turf2.difference(turf2.featureCollection([polyGeo, holeGeo]));
832
+ if (result) {
833
+ this.map.fire(ANVIL_EVENTS.DELETED, { layer: polygon7 });
834
+ this.map.removeLayer(polygon7);
835
+ const flattened = turf2.flatten(result);
836
+ flattened.features.forEach((f) => {
837
+ const l = L11.geoJSON(f).getLayers()[0];
838
+ l.addTo(this.map);
839
+ this.map.fire(ANVIL_EVENTS.CREATED, { layer: l });
840
+ });
841
+ }
842
+ });
843
+ this.resetDrawing();
844
+ }
845
+ resetDrawing() {
846
+ if (this.polyline) this.map.removeLayer(this.polyline);
847
+ if (this.ghostLine) this.map.removeLayer(this.ghostLine);
848
+ this.markers.forEach((m) => this.map.removeLayer(m));
849
+ this.points = [];
850
+ this.markers = [];
851
+ this.polyline = null;
852
+ this.ghostLine = null;
853
+ }
854
+ };
855
+
856
+ // src/modes/split-mode.ts
857
+ var L12 = __toESM(require("leaflet"));
858
+ var turf3 = __toESM(require("@turf/turf"));
859
+ var SplitMode = class {
860
+ constructor(map, store, options = {}) {
861
+ this.map = map;
862
+ this.store = store;
863
+ this.options = options;
864
+ __publicField(this, "points", []);
865
+ __publicField(this, "markers", []);
866
+ __publicField(this, "polyline", null);
867
+ __publicField(this, "ghostLine", null);
868
+ }
869
+ enable() {
870
+ this.map.on("click", this.onMapClick, this);
871
+ this.map.on("mousemove", this.onMouseMove, this);
872
+ L12.DomEvent.on(window, "keydown", this.onKeyDown, this);
873
+ this.map.getContainer().style.cursor = "crosshair";
874
+ }
875
+ disable() {
876
+ this.map.off("click", this.onMapClick, this);
877
+ this.map.off("mousemove", this.onMouseMove, this);
878
+ L12.DomEvent.off(window, "keydown", this.onKeyDown, this);
879
+ this.map.getContainer().style.cursor = "";
880
+ this.resetDrawing();
881
+ }
882
+ onMapClick(e) {
883
+ const latlng = getSnapLatLng(this.map, e.latlng, this.store, this.options, this.points);
884
+ if (this.points.length > 0) {
885
+ const lastPoint = this.points[this.points.length - 1];
886
+ const p = this.map.latLngToContainerPoint(latlng);
887
+ const lp = this.map.latLngToContainerPoint(lastPoint);
888
+ if (p.distanceTo(lp) < 15 && this.points.length >= 2) {
889
+ this.finish();
890
+ return;
891
+ }
892
+ }
893
+ this.points.push(latlng);
894
+ this.updateDrawing();
895
+ }
896
+ onMouseMove(e) {
897
+ if (this.points.length === 0) return;
898
+ const snapLatLng = getSnapLatLng(this.map, e.latlng, this.store, this.options, this.points);
899
+ const lastPoint = this.points[this.points.length - 1];
900
+ if (!this.ghostLine) {
901
+ this.ghostLine = L12.polyline([lastPoint, snapLatLng], {
902
+ dashArray: "5, 5",
903
+ color: "#ff3300",
904
+ weight: 2
905
+ }).addTo(this.map);
906
+ } else {
907
+ this.ghostLine.setLatLngs([lastPoint, snapLatLng]);
908
+ }
909
+ }
910
+ onKeyDown(e) {
911
+ if (e.key === "Escape") {
912
+ this.resetDrawing();
913
+ }
914
+ }
915
+ updateDrawing() {
916
+ if (this.polyline) {
917
+ this.polyline.setLatLngs(this.points);
918
+ } else {
919
+ this.polyline = L12.polyline(this.points, { color: "#ff3300", weight: 3 }).addTo(this.map);
920
+ }
921
+ const lastPoint = this.points[this.points.length - 1];
922
+ if (this.markers.length === 0) {
923
+ const marker4 = L12.marker(lastPoint, {
924
+ icon: L12.divIcon({
925
+ className: "anvil-split-finish",
926
+ html: '<div style="width: 10px; height: 10px; background: #ff3300; border: 2px solid white; border-radius: 50%;"></div>',
927
+ iconSize: [10, 10],
928
+ iconAnchor: [5, 5]
929
+ })
930
+ }).addTo(this.map);
931
+ marker4.on("click", (e) => {
932
+ L12.DomEvent.stopPropagation(e);
933
+ this.finish();
934
+ });
935
+ this.markers.push(marker4);
936
+ } else {
937
+ this.markers[0].setLatLng(lastPoint);
938
+ }
939
+ }
940
+ finish() {
941
+ if (this.points.length < 2) {
942
+ this.resetDrawing();
943
+ return;
944
+ }
945
+ const lineGeo = L12.polyline(this.points).toGeoJSON();
946
+ const coords = turf3.getCoords(lineGeo);
947
+ const layersToSplit = [];
948
+ this.store.getGroup().eachLayer((layer) => {
949
+ if (layer instanceof L12.Polygon) {
950
+ const polyGeo = layer.toGeoJSON();
951
+ const intersections = turf3.lineIntersect(lineGeo, polyGeo);
952
+ if (intersections.features.length >= 2) {
953
+ layersToSplit.push(layer);
954
+ }
955
+ }
956
+ });
957
+ if (layersToSplit.length === 0) {
958
+ this.resetDrawing();
959
+ return;
960
+ }
961
+ const p1 = coords[0];
962
+ const p2 = coords[coords.length - 1];
963
+ const dx = p2[0] - p1[0];
964
+ const dy = p2[1] - p1[1];
965
+ const factor = 1e3;
966
+ const start = [p1[0] - dx * factor, p1[1] - dy * factor];
967
+ const end = [p2[0] + dx * factor, p2[1] + dy * factor];
968
+ const angle = Math.atan2(dy, dx);
969
+ const perp = angle + Math.PI / 2;
970
+ const width = 1e3;
971
+ const blade = turf3.polygon([[
972
+ start,
973
+ end,
974
+ [end[0] + Math.cos(perp) * width, end[1] + Math.sin(perp) * width],
975
+ [start[0] + Math.cos(perp) * width, start[1] + Math.sin(perp) * width],
976
+ start
977
+ ]]);
978
+ layersToSplit.forEach((polygon7) => {
979
+ const polyGeo = polygon7.toGeoJSON();
980
+ if (this.options.magnetic) {
981
+ const intersections = turf3.lineIntersect(lineGeo, polyGeo);
982
+ this.insertVerticesIntoNeighbors(intersections, polygon7);
983
+ }
984
+ const part1 = turf3.difference(turf3.featureCollection([polyGeo, blade]));
985
+ const part2 = turf3.intersect(turf3.featureCollection([polyGeo, blade]));
986
+ if (part1 && part2) {
987
+ const processResult = (result) => {
988
+ const flattened = turf3.flatten(result);
989
+ flattened.features.forEach((f) => {
990
+ const l = L12.geoJSON(f).getLayers()[0];
991
+ l.addTo(this.map);
992
+ this.map.fire(ANVIL_EVENTS.CREATED, { layer: l });
993
+ });
994
+ };
995
+ this.map.fire(ANVIL_EVENTS.DELETED, { layer: polygon7 });
996
+ this.map.removeLayer(polygon7);
997
+ processResult(part1);
998
+ processResult(part2);
999
+ }
1000
+ });
1001
+ this.resetDrawing();
1002
+ }
1003
+ insertVerticesIntoNeighbors(intersections, activePolygon) {
1004
+ const intersectionCoords = intersections.features.map((f) => turf3.getCoord(f));
1005
+ const layers = this.store.getGroup().getLayers();
1006
+ layers.forEach((layer) => {
1007
+ if (!(layer instanceof L12.Polyline) || layer === activePolygon) return;
1008
+ const latlngs = layer.getLatLngs();
1009
+ let changed = false;
1010
+ const processArr = (arr) => {
1011
+ if (arr.length === 0) return;
1012
+ if (arr[0] instanceof L12.LatLng || typeof arr[0].lat === "number") {
1013
+ const ring = arr;
1014
+ const isPolygon = layer instanceof L12.Polygon;
1015
+ const ringLen = ring.length;
1016
+ for (let i = ringLen - 1; i >= 0; i--) {
1017
+ if (i === ringLen - 1 && !isPolygon) continue;
1018
+ const p1 = ring[i];
1019
+ const p2 = ring[(i + 1) % ringLen];
1020
+ const a = this.map.latLngToContainerPoint(p1);
1021
+ const b = this.map.latLngToContainerPoint(p2);
1022
+ intersectionCoords.forEach((coord) => {
1023
+ const intersectLL = L12.latLng(coord[1], coord[0]);
1024
+ const p = this.map.latLngToContainerPoint(intersectLL);
1025
+ const closest = L12.LineUtil.closestPointOnSegment(p, a, b);
1026
+ if (p.distanceTo(closest) < 1) {
1027
+ const alreadyExists = ring.some(
1028
+ (ll) => this.map.latLngToContainerPoint(ll).distanceTo(p) < 1
1029
+ );
1030
+ if (!alreadyExists) {
1031
+ ring.splice(i + 1, 0, intersectLL);
1032
+ changed = true;
1033
+ }
1034
+ }
1035
+ });
1036
+ }
1037
+ } else {
1038
+ arr.forEach((item) => processArr(item));
1039
+ }
1040
+ };
1041
+ processArr(latlngs);
1042
+ if (changed) {
1043
+ layer.setLatLngs(latlngs);
1044
+ if (layer.redraw) layer.redraw();
1045
+ this.map.fire(ANVIL_EVENTS.EDITED, { layer });
1046
+ }
1047
+ });
1048
+ }
1049
+ resetDrawing() {
1050
+ if (this.polyline) this.map.removeLayer(this.polyline);
1051
+ if (this.ghostLine) this.map.removeLayer(this.ghostLine);
1052
+ this.markers.forEach((m) => this.map.removeLayer(m));
1053
+ this.points = [];
1054
+ this.markers = [];
1055
+ this.polyline = null;
1056
+ this.ghostLine = null;
1057
+ }
1058
+ };
1059
+
1060
+ // src/modes/drag-mode.ts
1061
+ var L13 = __toESM(require("leaflet"));
1062
+ var DragMode = class {
1063
+ constructor(map, store, options = {}) {
1064
+ this.map = map;
1065
+ this.store = store;
1066
+ this.options = options;
1067
+ __publicField(this, "draggingLayer", null);
1068
+ __publicField(this, "startLatLng", null);
1069
+ __publicField(this, "initialLatLngs", null);
1070
+ }
1071
+ enable() {
1072
+ this.store.getGroup().eachLayer((layer) => {
1073
+ if (layer instanceof L13.Path || layer instanceof L13.Marker) {
1074
+ layer.on("mousedown", this.onMouseDown, this);
1075
+ layer.getElement()?.style.setProperty("cursor", "move");
1076
+ }
1077
+ });
1078
+ }
1079
+ disable() {
1080
+ this.store.getGroup().eachLayer((layer) => {
1081
+ if (layer instanceof L13.Path || layer instanceof L13.Marker) {
1082
+ layer.off("mousedown", this.onMouseDown, this);
1083
+ layer.getElement()?.style.setProperty("cursor", "");
1084
+ }
1085
+ });
1086
+ this.stopDragging();
1087
+ }
1088
+ onMouseDown(e) {
1089
+ L13.DomEvent.stopPropagation(e);
1090
+ const layer = e.target;
1091
+ if (!this.store.hasLayer(layer)) {
1092
+ return;
1093
+ }
1094
+ this.draggingLayer = layer;
1095
+ this.startLatLng = e.latlng;
1096
+ if (this.draggingLayer instanceof L13.Marker) {
1097
+ this.initialLatLngs = this.draggingLayer.getLatLng();
1098
+ } else if (this.draggingLayer instanceof L13.Path) {
1099
+ if (this.draggingLayer instanceof L13.Circle) {
1100
+ this.initialLatLngs = this.draggingLayer.getLatLng();
1101
+ } else if (this.draggingLayer instanceof L13.Polyline) {
1102
+ this.initialLatLngs = JSON.parse(JSON.stringify(this.draggingLayer.getLatLngs()));
1103
+ }
1104
+ this.draggingLayer.setStyle({ weight: 4, color: "#ffcc00" });
1105
+ }
1106
+ this.map.on("mousemove", this.onMouseMove, this);
1107
+ this.map.on("mouseup", this.onMouseUp, this);
1108
+ this.map.dragging.disable();
1109
+ }
1110
+ onMouseMove(e) {
1111
+ if (!this.draggingLayer || !this.startLatLng) return;
1112
+ const currentLatLng = getSnapLatLng(
1113
+ this.map,
1114
+ e.latlng,
1115
+ this.store,
1116
+ this.options,
1117
+ [],
1118
+ this.draggingLayer
1119
+ );
1120
+ const deltaLat = currentLatLng.lat - this.startLatLng.lat;
1121
+ const deltaLng = currentLatLng.lng - this.startLatLng.lng;
1122
+ if (this.draggingLayer instanceof L13.Marker || this.draggingLayer instanceof L13.Circle) {
1123
+ const start = this.initialLatLngs;
1124
+ this.draggingLayer.setLatLng([start.lat + deltaLat, start.lng + deltaLng]);
1125
+ } else if (this.draggingLayer instanceof L13.Polyline) {
1126
+ const newLatLngs = this.moveLatLngs(this.initialLatLngs, deltaLat, deltaLng);
1127
+ this.draggingLayer.setLatLngs(newLatLngs);
1128
+ }
1129
+ }
1130
+ moveLatLngs(latlngs, deltaLat, deltaLng) {
1131
+ if (Array.isArray(latlngs)) {
1132
+ return latlngs.map((item) => this.moveLatLngs(item, deltaLat, deltaLng));
1133
+ }
1134
+ return L13.latLng(latlngs.lat + deltaLat, latlngs.lng + deltaLng);
1135
+ }
1136
+ onMouseUp() {
1137
+ if (this.draggingLayer) {
1138
+ if (this.draggingLayer instanceof L13.Path) {
1139
+ this.draggingLayer.setStyle({ weight: 3, color: "#3388ff" });
1140
+ }
1141
+ this.map.fire(ANVIL_EVENTS.EDITED, { layer: this.draggingLayer });
1142
+ }
1143
+ this.stopDragging();
1144
+ }
1145
+ stopDragging() {
1146
+ this.map.off("mousemove", this.onMouseMove, this);
1147
+ this.map.off("mouseup", this.onMouseUp, this);
1148
+ this.map.dragging.enable();
1149
+ this.draggingLayer = null;
1150
+ this.startLatLng = null;
1151
+ this.initialLatLngs = null;
1152
+ }
1153
+ };
1154
+
1155
+ // src/modes/scale-mode.ts
1156
+ var L14 = __toESM(require("leaflet"));
1157
+ var ScaleMode = class {
1158
+ constructor(map, store, options) {
1159
+ this.map = map;
1160
+ this.store = store;
1161
+ this.options = options;
1162
+ __publicField(this, "selectedLayer", null);
1163
+ __publicField(this, "centerLatLng", null);
1164
+ __publicField(this, "initialLatLngs", null);
1165
+ __publicField(this, "initialRadius", 0);
1166
+ __publicField(this, "initialDistance", 0);
1167
+ }
1168
+ enable() {
1169
+ this.store.getGroup().eachLayer((layer) => {
1170
+ if (layer instanceof L14.Path) {
1171
+ layer.on("mousedown", this.onMouseDown, this);
1172
+ layer.getElement()?.style.setProperty("cursor", "nwse-resize");
1173
+ }
1174
+ });
1175
+ }
1176
+ disable() {
1177
+ this.store.getGroup().eachLayer((layer) => {
1178
+ if (layer instanceof L14.Path) {
1179
+ layer.off("mousedown", this.onMouseDown, this);
1180
+ layer.getElement()?.style.setProperty("cursor", "");
1181
+ }
1182
+ });
1183
+ this.stopScaling();
1184
+ }
1185
+ onMouseDown(e) {
1186
+ L14.DomEvent.stopPropagation(e);
1187
+ const layer = e.target;
1188
+ if (!this.store.hasLayer(layer)) {
1189
+ return;
1190
+ }
1191
+ this.selectedLayer = layer;
1192
+ if (this.selectedLayer instanceof L14.Circle) {
1193
+ this.centerLatLng = this.selectedLayer.getLatLng();
1194
+ this.initialRadius = this.selectedLayer.getRadius();
1195
+ } else if (this.selectedLayer instanceof L14.Path) {
1196
+ const bounds = this.selectedLayer.getBounds();
1197
+ this.centerLatLng = bounds.getCenter();
1198
+ this.initialLatLngs = JSON.parse(JSON.stringify(this.selectedLayer.getLatLngs()));
1199
+ this.selectedLayer.setStyle({ weight: 4, color: "#ffcc00" });
1200
+ }
1201
+ if (this.centerLatLng) {
1202
+ this.initialDistance = this.map.distance(this.centerLatLng, e.latlng);
1203
+ this.map.on("mousemove", this.onMouseMove, this);
1204
+ this.map.on("mouseup", this.onMouseUp, this);
1205
+ this.map.dragging.disable();
1206
+ }
1207
+ }
1208
+ onMouseMove(e) {
1209
+ if (!this.selectedLayer || !this.centerLatLng || this.initialDistance === 0) return;
1210
+ const currentDistance = this.map.distance(this.centerLatLng, e.latlng);
1211
+ const ratio = currentDistance / this.initialDistance;
1212
+ if (this.selectedLayer instanceof L14.Circle) {
1213
+ this.selectedLayer.setRadius(this.initialRadius * ratio);
1214
+ } else if (this.selectedLayer instanceof L14.Path) {
1215
+ const newLatLngs = this.scaleLatLngs(this.initialLatLngs, this.centerLatLng, ratio);
1216
+ this.selectedLayer.setLatLngs(newLatLngs);
1217
+ }
1218
+ }
1219
+ scaleLatLngs(latlngs, center, ratio) {
1220
+ if (Array.isArray(latlngs)) {
1221
+ return latlngs.map((item) => this.scaleLatLngs(item, center, ratio));
1222
+ }
1223
+ const lat = center.lat + (latlngs.lat - center.lat) * ratio;
1224
+ const lng = center.lng + (latlngs.lng - center.lng) * ratio;
1225
+ return L14.latLng(lat, lng);
1226
+ }
1227
+ onMouseUp() {
1228
+ if (this.selectedLayer) {
1229
+ if (this.selectedLayer instanceof L14.Path) {
1230
+ this.selectedLayer.setStyle({ weight: 3, color: "#3388ff" });
1231
+ }
1232
+ this.map.fire(ANVIL_EVENTS.EDITED, { layer: this.selectedLayer });
1233
+ }
1234
+ this.stopScaling();
1235
+ }
1236
+ stopScaling() {
1237
+ this.map.off("mousemove", this.onMouseMove, this);
1238
+ this.map.off("mouseup", this.onMouseUp, this);
1239
+ this.map.dragging.enable();
1240
+ this.selectedLayer = null;
1241
+ this.centerLatLng = null;
1242
+ this.initialLatLngs = null;
1243
+ }
1244
+ };
1245
+
1246
+ // src/modes/rotate-mode.ts
1247
+ var L15 = __toESM(require("leaflet"));
1248
+ var RotateMode = class {
1249
+ constructor(map, store, options) {
1250
+ this.map = map;
1251
+ this.store = store;
1252
+ this.options = options;
1253
+ __publicField(this, "selectedLayer", null);
1254
+ __publicField(this, "centerLatLng", null);
1255
+ __publicField(this, "initialLatLngs", null);
1256
+ __publicField(this, "startAngle", 0);
1257
+ }
1258
+ enable() {
1259
+ this.store.getGroup().eachLayer((layer) => {
1260
+ if (layer instanceof L15.Path) {
1261
+ layer.on("mousedown", this.onMouseDown, this);
1262
+ layer.getElement()?.style.setProperty("cursor", "crosshair");
1263
+ }
1264
+ });
1265
+ }
1266
+ disable() {
1267
+ this.store.getGroup().eachLayer((layer) => {
1268
+ if (layer instanceof L15.Path) {
1269
+ layer.off("mousedown", this.onMouseDown, this);
1270
+ layer.getElement()?.style.setProperty("cursor", "");
1271
+ }
1272
+ });
1273
+ this.stopRotating();
1274
+ }
1275
+ onMouseDown(e) {
1276
+ L15.DomEvent.stopPropagation(e);
1277
+ const layer = e.target;
1278
+ if (!this.store.hasLayer(layer) || !(layer instanceof L15.Path) || layer instanceof L15.Circle) {
1279
+ return;
1280
+ }
1281
+ const pathLayer = layer;
1282
+ this.selectedLayer = pathLayer;
1283
+ const bounds = pathLayer.getBounds();
1284
+ this.centerLatLng = bounds.getCenter();
1285
+ this.initialLatLngs = JSON.parse(JSON.stringify(pathLayer.getLatLngs()));
1286
+ const point2 = this.map.latLngToContainerPoint(e.latlng);
1287
+ const centerPoint = this.map.latLngToContainerPoint(this.centerLatLng);
1288
+ this.startAngle = Math.atan2(point2.y - centerPoint.y, point2.x - centerPoint.x);
1289
+ pathLayer.setStyle({ weight: 4, color: "#ffcc00" });
1290
+ this.map.on("mousemove", this.onMouseMove, this);
1291
+ this.map.on("mouseup", this.onMouseUp, this);
1292
+ this.map.dragging.disable();
1293
+ }
1294
+ onMouseMove(e) {
1295
+ if (!this.selectedLayer || !this.centerLatLng) return;
1296
+ const point2 = this.map.latLngToContainerPoint(e.latlng);
1297
+ const centerPoint = this.map.latLngToContainerPoint(this.centerLatLng);
1298
+ const currentAngle = Math.atan2(point2.y - centerPoint.y, point2.x - centerPoint.x);
1299
+ const rotationAngle = currentAngle - this.startAngle;
1300
+ const newLatLngs = this.rotateLatLngs(this.initialLatLngs, this.centerLatLng, rotationAngle);
1301
+ this.selectedLayer.setLatLngs(newLatLngs);
1302
+ }
1303
+ rotateLatLngs(latlngs, center, angle) {
1304
+ if (Array.isArray(latlngs)) {
1305
+ return latlngs.map((item) => this.rotateLatLngs(item, center, angle));
1306
+ }
1307
+ const point2 = this.map.latLngToContainerPoint(latlngs);
1308
+ const centerPoint = this.map.latLngToContainerPoint(center);
1309
+ const cos = Math.cos(angle);
1310
+ const sin = Math.sin(angle);
1311
+ const dx = point2.x - centerPoint.x;
1312
+ const dy = point2.y - centerPoint.y;
1313
+ const nx = dx * cos - dy * sin + centerPoint.x;
1314
+ const ny = dx * sin + dy * cos + centerPoint.y;
1315
+ return this.map.containerPointToLatLng([nx, ny]);
1316
+ }
1317
+ onMouseUp() {
1318
+ if (this.selectedLayer) {
1319
+ this.selectedLayer.setStyle({ weight: 3, color: "#3388ff" });
1320
+ this.map.fire(ANVIL_EVENTS.EDITED, { layer: this.selectedLayer });
1321
+ }
1322
+ this.stopRotating();
1323
+ }
1324
+ stopRotating() {
1325
+ this.map.off("mousemove", this.onMouseMove, this);
1326
+ this.map.off("mouseup", this.onMouseUp, this);
1327
+ this.map.dragging.enable();
1328
+ this.selectedLayer = null;
1329
+ this.centerLatLng = null;
1330
+ this.initialLatLngs = null;
1331
+ }
1332
+ };
1333
+
1334
+ // src/modes/union-mode.ts
1335
+ var L16 = __toESM(require("leaflet"));
1336
+ var turf4 = __toESM(require("@turf/turf"));
1337
+ var UnionMode = class {
1338
+ constructor(map, store, options = {}) {
1339
+ this.map = map;
1340
+ this.store = store;
1341
+ this.options = options;
1342
+ __publicField(this, "firstLayer", null);
1343
+ }
1344
+ enable() {
1345
+ this.store.getGroup().eachLayer((layer) => {
1346
+ if (layer instanceof L16.Polygon) {
1347
+ layer.on("click", this.onLayerClick, this);
1348
+ layer.getElement()?.style.setProperty("cursor", "pointer");
1349
+ }
1350
+ });
1351
+ }
1352
+ disable() {
1353
+ this.store.getGroup().eachLayer((layer) => {
1354
+ if (layer instanceof L16.Polygon) {
1355
+ layer.off("click", this.onLayerClick, this);
1356
+ layer.getElement()?.style.setProperty("cursor", "");
1357
+ }
1358
+ });
1359
+ this.reset();
1360
+ }
1361
+ onLayerClick(e) {
1362
+ L16.DomEvent.stopPropagation(e);
1363
+ const layer = e.target;
1364
+ if (!this.firstLayer) {
1365
+ this.firstLayer = layer;
1366
+ this.firstLayer.setStyle({ color: "#ff00ff", weight: 4 });
1367
+ return;
1368
+ }
1369
+ if (this.firstLayer === layer) {
1370
+ this.reset();
1371
+ return;
1372
+ }
1373
+ const g1 = this.firstLayer.toGeoJSON();
1374
+ const g2 = layer.toGeoJSON();
1375
+ const united = turf4.union(turf4.featureCollection([g1, g2]));
1376
+ if (!united) {
1377
+ console.error("Union failed - results null");
1378
+ this.reset();
1379
+ return;
1380
+ }
1381
+ this.map.fire(ANVIL_EVENTS.DELETED, { layer: this.firstLayer });
1382
+ this.map.fire(ANVIL_EVENTS.DELETED, { layer });
1383
+ this.map.removeLayer(this.firstLayer);
1384
+ this.map.removeLayer(layer);
1385
+ const flattened = turf4.flatten(united);
1386
+ flattened.features.forEach((f) => {
1387
+ const newLayerGroup = L16.geoJSON(f, {
1388
+ style: this.options.pathOptions
1389
+ });
1390
+ const l = newLayerGroup.getLayers()[0];
1391
+ l.addTo(this.map);
1392
+ this.map.fire(ANVIL_EVENTS.CREATED, { layer: l });
1393
+ });
1394
+ this.firstLayer = null;
1395
+ }
1396
+ reset() {
1397
+ if (this.firstLayer) {
1398
+ this.firstLayer.setStyle({ color: "#3388ff", weight: 3, ...this.options.pathOptions });
1399
+ this.firstLayer = null;
1400
+ }
1401
+ }
1402
+ };
1403
+
1404
+ // src/modes/subtract-mode.ts
1405
+ var L17 = __toESM(require("leaflet"));
1406
+ var turf5 = __toESM(require("@turf/turf"));
1407
+ var SubtractMode = class {
1408
+ constructor(map, store, options = {}) {
1409
+ this.map = map;
1410
+ this.store = store;
1411
+ this.options = options;
1412
+ __publicField(this, "baseLayer", null);
1413
+ }
1414
+ enable() {
1415
+ this.store.getGroup().eachLayer((layer) => {
1416
+ if (layer instanceof L17.Polygon) {
1417
+ layer.on("click", this.onLayerClick, this);
1418
+ layer.getElement()?.style.setProperty("cursor", "pointer");
1419
+ }
1420
+ });
1421
+ }
1422
+ disable() {
1423
+ this.store.getGroup().eachLayer((layer) => {
1424
+ if (layer instanceof L17.Polygon) {
1425
+ layer.off("click", this.onLayerClick, this);
1426
+ layer.getElement()?.style.setProperty("cursor", "");
1427
+ }
1428
+ });
1429
+ this.reset();
1430
+ }
1431
+ onLayerClick(e) {
1432
+ L17.DomEvent.stopPropagation(e);
1433
+ const layer = e.target;
1434
+ if (!this.baseLayer) {
1435
+ this.baseLayer = layer;
1436
+ this.baseLayer.setStyle({ color: "#ff0000", weight: 4 });
1437
+ return;
1438
+ }
1439
+ if (this.baseLayer === layer) {
1440
+ this.reset();
1441
+ return;
1442
+ }
1443
+ const g1 = this.baseLayer.toGeoJSON();
1444
+ const g2 = layer.toGeoJSON();
1445
+ const diff = turf5.difference(turf5.featureCollection([g1, g2]));
1446
+ this.map.fire(ANVIL_EVENTS.DELETED, { layer: this.baseLayer });
1447
+ this.map.fire(ANVIL_EVENTS.DELETED, { layer });
1448
+ this.map.removeLayer(this.baseLayer);
1449
+ this.map.removeLayer(layer);
1450
+ if (diff) {
1451
+ const flattened = turf5.flatten(diff);
1452
+ flattened.features.forEach((f) => {
1453
+ const newLayerGroup = L17.geoJSON(f);
1454
+ const l = newLayerGroup.getLayers()[0];
1455
+ l.addTo(this.map);
1456
+ this.map.fire(ANVIL_EVENTS.CREATED, { layer: l });
1457
+ });
1458
+ }
1459
+ this.baseLayer = null;
1460
+ }
1461
+ reset() {
1462
+ if (this.baseLayer) {
1463
+ this.baseLayer.setStyle({ color: "#3388ff", weight: 3 });
1464
+ this.baseLayer = null;
1465
+ }
1466
+ }
1467
+ };
1468
+
1469
+ // src/modes/edit-mode.ts
1470
+ var L18 = __toESM(require("leaflet"));
1471
+ var EditMode = class {
1472
+ constructor(map, store, options = {}) {
1473
+ this.map = map;
1474
+ this.store = store;
1475
+ this.options = options;
1476
+ __publicField(this, "activeLayers", /* @__PURE__ */ new Set());
1477
+ __publicField(this, "markers", []);
1478
+ __publicField(this, "ghostMarker", null);
1479
+ __publicField(this, "segments", []);
1480
+ __publicField(this, "_isDragging", false);
1481
+ }
1482
+ enable() {
1483
+ this.store.getGroup().eachLayer((layer) => {
1484
+ if (layer instanceof L18.Path || layer instanceof L18.Marker) {
1485
+ layer.on("click", this.onLayerClick, this);
1486
+ layer.on("mousemove", this.onMouseMove, this);
1487
+ layer.getElement()?.style.setProperty("cursor", "pointer");
1488
+ }
1489
+ });
1490
+ this.map.on("click", this.onMapClick, this);
1491
+ this.map.on("mousemove", this.onMouseMove, this);
1492
+ }
1493
+ disable() {
1494
+ this.store.getGroup().eachLayer((layer) => {
1495
+ if (layer instanceof L18.Path || layer instanceof L18.Marker) {
1496
+ layer.off("click", this.onLayerClick, this);
1497
+ layer.off("mousemove", this.onMouseMove, this);
1498
+ layer.getElement()?.style.setProperty("cursor", "");
1499
+ if (layer instanceof L18.Path) {
1500
+ layer.setStyle({ color: "#3388ff", weight: 3, fillOpacity: 0.2 });
1501
+ }
1502
+ }
1503
+ });
1504
+ this.map.off("click", this.onMapClick, this);
1505
+ this.map.off("mousemove", this.onMouseMove, this);
1506
+ this.clearMarkers();
1507
+ this.activeLayers.clear();
1508
+ }
1509
+ onLayerClick(e) {
1510
+ L18.DomEvent.stopPropagation(e);
1511
+ const layer = e.target;
1512
+ const isMultiSelect = e.originalEvent.shiftKey || this.options.magnetic;
1513
+ if (!isMultiSelect) {
1514
+ if (this.activeLayers.has(layer) && this.activeLayers.size === 1) return;
1515
+ this.activeLayers.forEach((l) => {
1516
+ if (l instanceof L18.Path) l.setStyle({ color: "#3388ff", weight: 3 });
1517
+ });
1518
+ this.clearMarkers();
1519
+ this.activeLayers.clear();
1520
+ this.activeLayers.add(layer);
1521
+ } else {
1522
+ if (this.activeLayers.has(layer)) {
1523
+ this.activeLayers.delete(layer);
1524
+ if (layer instanceof L18.Path) layer.setStyle({ color: "#3388ff", weight: 3 });
1525
+ } else {
1526
+ this.activeLayers.add(layer);
1527
+ }
1528
+ this.clearMarkers();
1529
+ }
1530
+ this.activeLayers.forEach((l) => {
1531
+ if (l instanceof L18.Path) l.setStyle({ color: "#ff00ff", weight: 4 });
1532
+ });
1533
+ this.createMarkers();
1534
+ }
1535
+ onMapClick() {
1536
+ this.clearMarkers();
1537
+ this.activeLayers.clear();
1538
+ }
1539
+ createMarkers() {
1540
+ this.clearMarkers();
1541
+ if (this.activeLayers.size === 0) return;
1542
+ const vertexMap = /* @__PURE__ */ new Map();
1543
+ this.segments = [];
1544
+ const segmentMap = /* @__PURE__ */ new Map();
1545
+ const getPosKey = (ll) => `${ll.lat.toFixed(6)},${ll.lng.toFixed(6)}`;
1546
+ this.activeLayers.forEach((layer) => {
1547
+ if (layer instanceof L18.Marker) {
1548
+ this.handleMarkerEdit(layer);
1549
+ } else if (layer instanceof L18.Circle) {
1550
+ this.handleCircleEdit(layer);
1551
+ } else if (layer instanceof L18.Polyline) {
1552
+ const latlngs = layer.getLatLngs();
1553
+ const traverse = (arr, currentPath) => {
1554
+ if (!arr) return;
1555
+ if (Array.isArray(arr) && arr.length > 0 && (arr[0] instanceof L18.LatLng || typeof arr[0].lat === "number")) {
1556
+ const isPolygon = layer instanceof L18.Polygon;
1557
+ let ringLen = arr.length;
1558
+ if (isPolygon && ringLen > 1) {
1559
+ if (getPosKey(arr[0]) === getPosKey(arr[ringLen - 1])) {
1560
+ ringLen--;
1561
+ }
1562
+ }
1563
+ arr.forEach((ll, i) => {
1564
+ if (i >= ringLen) return;
1565
+ const key = getPosKey(ll);
1566
+ if (!vertexMap.has(key)) vertexMap.set(key, { latlng: ll, refs: [], marker: null });
1567
+ vertexMap.get(key).refs.push({ layer, path: [...currentPath, i] });
1568
+ if (i < ringLen - 1 || isPolygon) {
1569
+ const nextIndex = (i + 1) % ringLen;
1570
+ const nextLL = arr[nextIndex];
1571
+ if (getPosKey(ll) === getPosKey(nextLL)) return;
1572
+ const k1 = getPosKey(ll);
1573
+ const k2 = getPosKey(nextLL);
1574
+ const midKey = [k1, k2].sort().join("|");
1575
+ if (!segmentMap.has(midKey)) {
1576
+ segmentMap.set(midKey, { p1: ll, p2: nextLL, refs: [] });
1577
+ }
1578
+ segmentMap.get(midKey).refs.push({ layer, path: [...currentPath, i] });
1579
+ }
1580
+ });
1581
+ } else if (Array.isArray(arr)) {
1582
+ arr.forEach((item, i) => traverse(item, [...currentPath, i]));
1583
+ }
1584
+ };
1585
+ traverse(latlngs, []);
1586
+ }
1587
+ });
1588
+ this.segments = Array.from(segmentMap.values());
1589
+ vertexMap.forEach((group) => {
1590
+ const marker4 = this.createEditMarker(group.latlng);
1591
+ group.marker = marker4;
1592
+ this.markers.push(marker4);
1593
+ marker4.on("dragstart", () => {
1594
+ this._isDragging = true;
1595
+ });
1596
+ marker4.on("drag", (e) => {
1597
+ const mouseEvent = e;
1598
+ const skipLayersArray = Array.from(this.activeLayers);
1599
+ const additionalPoints = [
1600
+ ...this.markers.filter((m) => m !== marker4).map((m) => m.getLatLng()),
1601
+ ...Array.from(this.activeLayers).filter((l) => l instanceof L18.Marker).map((l) => l.getLatLng())
1602
+ ];
1603
+ const snapped = getSnapLatLng(this.map, mouseEvent.latlng, this.store, this.options, additionalPoints, skipLayersArray);
1604
+ if (this.options.preventSelfIntersection) {
1605
+ let wouldIntersect = false;
1606
+ group.refs.forEach((ref) => {
1607
+ const fullStructure = ref.layer.getLatLngs();
1608
+ let target = fullStructure;
1609
+ for (let i = 0; i < ref.path.length - 1; i++) {
1610
+ target = target[ref.path[i]];
1611
+ }
1612
+ const oldPos = target[ref.path[ref.path.length - 1]];
1613
+ target[ref.path[ref.path.length - 1]] = snapped;
1614
+ if (isSelfIntersecting(this.map, fullStructure, ref.layer instanceof L18.Polygon)) {
1615
+ wouldIntersect = true;
1616
+ }
1617
+ target[ref.path[ref.path.length - 1]] = oldPos;
1618
+ });
1619
+ if (wouldIntersect) return;
1620
+ }
1621
+ marker4.setLatLng(snapped);
1622
+ group.latlng = snapped;
1623
+ group.refs.forEach((ref) => {
1624
+ const fullStructure = ref.layer.getLatLngs();
1625
+ let target = fullStructure;
1626
+ for (let i = 0; i < ref.path.length - 1; i++) {
1627
+ target = target[ref.path[i]];
1628
+ }
1629
+ target[ref.path[ref.path.length - 1]] = snapped;
1630
+ ref.layer.setLatLngs(fullStructure);
1631
+ ref.layer.redraw();
1632
+ });
1633
+ });
1634
+ marker4.on("dragend", () => {
1635
+ this._isDragging = false;
1636
+ this.activeLayers.forEach((l) => this.map.fire(ANVIL_EVENTS.EDITED, { layer: l }));
1637
+ this.refreshMarkers();
1638
+ });
1639
+ marker4.on("contextmenu", (e) => {
1640
+ const mouseEvent = e;
1641
+ L18.DomEvent.stopPropagation(mouseEvent);
1642
+ this.deleteVertex(group);
1643
+ });
1644
+ });
1645
+ }
1646
+ deleteVertex(group) {
1647
+ const layersToDelete = /* @__PURE__ */ new Set();
1648
+ group.refs.forEach((ref) => {
1649
+ const fullStructure = ref.layer.getLatLngs();
1650
+ let target = fullStructure;
1651
+ for (let i = 0; i < ref.path.length - 1; i++) {
1652
+ target = target[ref.path[i]];
1653
+ }
1654
+ const index = ref.path[ref.path.length - 1];
1655
+ const isPolygon = ref.layer instanceof L18.Polygon;
1656
+ const minVertices = isPolygon ? 3 : 2;
1657
+ if (target.length > minVertices) {
1658
+ target.splice(index, 1);
1659
+ ref.layer.setLatLngs(fullStructure);
1660
+ ref.layer.redraw();
1661
+ this.map.fire(ANVIL_EVENTS.EDITED, { layer: ref.layer });
1662
+ } else {
1663
+ layersToDelete.add(ref.layer);
1664
+ }
1665
+ });
1666
+ layersToDelete.forEach((layer) => {
1667
+ this.activeLayers.delete(layer);
1668
+ this.map.removeLayer(layer);
1669
+ this.map.fire(ANVIL_EVENTS.DELETED, { layer });
1670
+ });
1671
+ this.refreshMarkers();
1672
+ }
1673
+ onMouseMove(e) {
1674
+ const mouseEvent = e;
1675
+ if (this.activeLayers.size === 0 || this.segments.length === 0 || this._isDragging) {
1676
+ if (!this._isDragging) this.removeGhost();
1677
+ return;
1678
+ }
1679
+ const mousePoint = this.map.latLngToContainerPoint(mouseEvent.latlng);
1680
+ const isOverVertex = this.markers.some((m) => {
1681
+ const p = this.map.latLngToContainerPoint(m.getLatLng());
1682
+ return p.distanceTo(mousePoint) < 15;
1683
+ });
1684
+ if (isOverVertex) {
1685
+ this.removeGhost();
1686
+ return;
1687
+ }
1688
+ let closestSeg = null;
1689
+ let minDistance = 24;
1690
+ let bestLatLng = null;
1691
+ this.segments.forEach((seg) => {
1692
+ const A = this.map.latLngToContainerPoint(seg.p1);
1693
+ const B = this.map.latLngToContainerPoint(seg.p2);
1694
+ const proj = L18.LineUtil.closestPointOnSegment(mousePoint, A, B);
1695
+ const dist = mousePoint.distanceTo(proj);
1696
+ if (dist < minDistance) {
1697
+ minDistance = dist;
1698
+ closestSeg = seg;
1699
+ bestLatLng = this.map.containerPointToLatLng(proj);
1700
+ }
1701
+ });
1702
+ if (closestSeg && bestLatLng) {
1703
+ this.showGhost(bestLatLng, closestSeg);
1704
+ } else {
1705
+ this.removeGhost();
1706
+ }
1707
+ }
1708
+ createEditMarker(latlng) {
1709
+ return L18.marker(latlng, {
1710
+ draggable: true,
1711
+ zIndexOffset: 2e3,
1712
+ icon: L18.divIcon({
1713
+ className: "anvil-edit-marker",
1714
+ html: '<div style="width: 12px; height: 12px; background: #fff; border: 2px solid #ff00ff; border-radius: 50%; box-sizing: border-box; box-shadow: 0 0 4px rgba(0,0,0,0.3);"></div>',
1715
+ iconSize: [12, 12],
1716
+ iconAnchor: [6, 6]
1717
+ })
1718
+ }).addTo(this.map);
1719
+ }
1720
+ showGhost(latlng, segment) {
1721
+ if (this.ghostMarker) {
1722
+ if (!this._isDragging) {
1723
+ this.ghostMarker.setLatLng(latlng);
1724
+ this.ghostMarker._activeSeg = segment;
1725
+ }
1726
+ return;
1727
+ }
1728
+ this.ghostMarker = L18.marker(latlng, {
1729
+ draggable: true,
1730
+ opacity: 0.7,
1731
+ zIndexOffset: 3e3,
1732
+ icon: L18.divIcon({
1733
+ className: "anvil-ghost-marker",
1734
+ html: '<div style="width: 10px; height: 10px; background: #ff00ff; border: 2px solid #fff; border-radius: 50%; box-sizing: border-box; box-shadow: 0 0 4px rgba(0,0,0,0.3);"></div>',
1735
+ iconSize: [10, 10],
1736
+ iconAnchor: [5, 5]
1737
+ })
1738
+ }).addTo(this.map);
1739
+ this.ghostMarker.on("dragstart", () => {
1740
+ this._isDragging = true;
1741
+ const activeSeg = this.ghostMarker._activeSeg || segment;
1742
+ const startLL = this.ghostMarker.getLatLng();
1743
+ activeSeg.refs.forEach((ref) => {
1744
+ const fullStructure = ref.layer.getLatLngs();
1745
+ let target = fullStructure;
1746
+ for (let i = 0; i < ref.path.length - 1; i++) {
1747
+ target = target[ref.path[i]];
1748
+ }
1749
+ target.splice(ref.path[ref.path.length - 1] + 1, 0, startLL);
1750
+ ref.layer.setLatLngs(fullStructure);
1751
+ });
1752
+ });
1753
+ this.ghostMarker.on("drag", (e) => {
1754
+ const mouseEvent = e;
1755
+ const skipLayersArray = Array.from(this.activeLayers);
1756
+ const additionalPoints = [
1757
+ ...this.markers.map((m) => m.getLatLng()),
1758
+ ...Array.from(this.activeLayers).filter((l) => l instanceof L18.Marker).map((l) => l.getLatLng())
1759
+ ];
1760
+ const snapped = getSnapLatLng(this.map, mouseEvent.latlng, this.store, this.options, additionalPoints, skipLayersArray);
1761
+ if (this.options.preventSelfIntersection) {
1762
+ let wouldIntersect = false;
1763
+ const activeSeg2 = this.ghostMarker._activeSeg || segment;
1764
+ activeSeg2.refs.forEach((ref) => {
1765
+ const fullStructure = ref.layer.getLatLngs();
1766
+ let target = fullStructure;
1767
+ for (let i = 0; i < ref.path.length - 1; i++) {
1768
+ target = target[ref.path[i]];
1769
+ }
1770
+ const oldPos = target[ref.path[ref.path.length - 1] + 1];
1771
+ target[ref.path[ref.path.length - 1] + 1] = snapped;
1772
+ if (isSelfIntersecting(this.map, fullStructure, ref.layer instanceof L18.Polygon)) {
1773
+ wouldIntersect = true;
1774
+ }
1775
+ target[ref.path[ref.path.length - 1] + 1] = oldPos;
1776
+ });
1777
+ if (wouldIntersect) return;
1778
+ }
1779
+ this.ghostMarker.setLatLng(snapped);
1780
+ const activeSeg = this.ghostMarker._activeSeg || segment;
1781
+ activeSeg.refs.forEach((ref) => {
1782
+ const fullStructure = ref.layer.getLatLngs();
1783
+ let target = fullStructure;
1784
+ for (let i = 0; i < ref.path.length - 1; i++) {
1785
+ target = target[ref.path[i]];
1786
+ }
1787
+ target[ref.path[ref.path.length - 1] + 1] = snapped;
1788
+ ref.layer.setLatLngs(fullStructure);
1789
+ ref.layer.redraw();
1790
+ });
1791
+ });
1792
+ this.ghostMarker.on("dragend", () => {
1793
+ this._isDragging = false;
1794
+ this.activeLayers.forEach((l) => this.map.fire(ANVIL_EVENTS.EDITED, { layer: l }));
1795
+ this.removeGhost();
1796
+ this.refreshMarkers();
1797
+ });
1798
+ }
1799
+ removeGhost() {
1800
+ if (this.ghostMarker && !this._isDragging) {
1801
+ this.map.removeLayer(this.ghostMarker);
1802
+ this.ghostMarker = null;
1803
+ }
1804
+ }
1805
+ handleMarkerEdit(marker4) {
1806
+ marker4.dragging?.enable();
1807
+ marker4.on("drag", (e) => {
1808
+ const mouseEvent = e;
1809
+ const additionalPoints = this.markers.map((m) => m.getLatLng());
1810
+ const snapped = getSnapLatLng(this.map, mouseEvent.latlng, this.store, this.options, additionalPoints, marker4);
1811
+ marker4.setLatLng(snapped);
1812
+ });
1813
+ marker4.on("dragend", () => {
1814
+ this.map.fire(ANVIL_EVENTS.EDITED, { layer: marker4 });
1815
+ });
1816
+ marker4.on("contextmenu", (e) => {
1817
+ const mouseEvent = e;
1818
+ L18.DomEvent.stopPropagation(mouseEvent);
1819
+ this.activeLayers.delete(marker4);
1820
+ this.map.removeLayer(marker4);
1821
+ this.map.fire(ANVIL_EVENTS.DELETED, { layer: marker4 });
1822
+ this.refreshMarkers();
1823
+ });
1824
+ }
1825
+ handleCircleEdit(circle2) {
1826
+ const marker4 = this.createEditMarker(circle2.getLatLng());
1827
+ marker4.on("drag", (e) => {
1828
+ const mouseEvent = e;
1829
+ const additionalPoints = this.markers.filter((m) => m !== marker4).map((m) => m.getLatLng());
1830
+ const snapped = getSnapLatLng(this.map, mouseEvent.latlng, this.store, this.options, additionalPoints, circle2);
1831
+ marker4.setLatLng(snapped);
1832
+ circle2.setLatLng(snapped);
1833
+ });
1834
+ marker4.on("dragend", () => {
1835
+ this.map.fire(ANVIL_EVENTS.EDITED, { layer: circle2 });
1836
+ });
1837
+ marker4.on("contextmenu", (e) => {
1838
+ const mouseEvent = e;
1839
+ L18.DomEvent.stopPropagation(mouseEvent);
1840
+ this.activeLayers.delete(circle2);
1841
+ this.map.removeLayer(circle2);
1842
+ this.map.fire(ANVIL_EVENTS.DELETED, { layer: circle2 });
1843
+ this.refreshMarkers();
1844
+ });
1845
+ this.markers.push(marker4);
1846
+ }
1847
+ clearMarkers() {
1848
+ this.activeLayers.forEach((layer) => {
1849
+ if (layer instanceof L18.Marker) {
1850
+ layer.dragging?.disable();
1851
+ layer.off("drag");
1852
+ layer.off("dragend");
1853
+ layer.off("contextmenu");
1854
+ }
1855
+ });
1856
+ this.markers.forEach((m) => this.map.removeLayer(m));
1857
+ this.markers = [];
1858
+ this.removeGhost();
1859
+ }
1860
+ refreshMarkers() {
1861
+ this.clearMarkers();
1862
+ this.createMarkers();
1863
+ }
1864
+ };
1865
+
1866
+ // src/modes/delete-mode.ts
1867
+ var L19 = __toESM(require("leaflet"));
1868
+ var DeleteMode = class {
1869
+ constructor(map, store) {
1870
+ this.map = map;
1871
+ this.store = store;
1872
+ }
1873
+ enable() {
1874
+ this.store.getGroup().eachLayer((layer) => {
1875
+ layer.on("click", this.onClick, this);
1876
+ if (layer instanceof L19.Path || layer instanceof L19.Marker) {
1877
+ layer.getElement()?.style.setProperty("cursor", "pointer");
1878
+ }
1879
+ });
1880
+ }
1881
+ disable() {
1882
+ this.store.getGroup().eachLayer((layer) => {
1883
+ layer.off("click", this.onClick, this);
1884
+ if (layer instanceof L19.Path || layer instanceof L19.Marker) {
1885
+ layer.getElement()?.style.setProperty("cursor", "");
1886
+ }
1887
+ });
1888
+ }
1889
+ onClick(e) {
1890
+ L19.DomEvent.stopPropagation(e);
1891
+ const layer = e.target;
1892
+ this.map.removeLayer(layer);
1893
+ this.map.fire(ANVIL_EVENTS.DELETED, { layer });
1894
+ }
1895
+ };
1896
+
1897
+ // src/layers/layer-store.ts
1898
+ var L20 = __toESM(require("leaflet"));
1899
+ var LayerStore = class {
1900
+ constructor(map, layerGroup) {
1901
+ __publicField(this, "group");
1902
+ this.group = layerGroup || L20.featureGroup();
1903
+ this.group.addTo(map);
1904
+ }
1905
+ addLayer(layer) {
1906
+ this.group.addLayer(layer);
1907
+ }
1908
+ removeLayer(layer) {
1909
+ this.group.removeLayer(layer);
1910
+ }
1911
+ hasLayer(layer) {
1912
+ return this.group.hasLayer(layer);
1913
+ }
1914
+ getGroup() {
1915
+ return this.group;
1916
+ }
1917
+ };
1918
+
1919
+ // src/anvil.ts
1920
+ var Anvil = class {
1921
+ constructor(map, options) {
1922
+ this.map = map;
1923
+ __publicField(this, "modeManager");
1924
+ __publicField(this, "store");
1925
+ __publicField(this, "options");
1926
+ this.options = { snapping: false, snapDistance: 10, preventSelfIntersection: false, ...options };
1927
+ this.store = new LayerStore(map, this.options.layerGroup);
1928
+ this.modeManager = new ModeManager(map);
1929
+ this.modeManager.addMode("draw:polygon", new DrawPolygonMode(this.map, this.options, this.store));
1930
+ this.modeManager.addMode("draw:polyline", new DrawPolylineMode(this.map, this.options, this.store));
1931
+ this.modeManager.addMode("draw:marker", new DrawMarkerMode(this.map, this.options, this.store));
1932
+ this.modeManager.addMode("draw:rectangle", new DrawRectangleMode(this.map, this.options, this.store));
1933
+ this.modeManager.addMode("draw:square", new DrawSquareMode(this.map, this.options, this.store));
1934
+ this.modeManager.addMode("draw:triangle", new DrawTriangleMode(this.map, this.options, this.store));
1935
+ this.modeManager.addMode("draw:circle", new DrawCircleMode(this.map, this.options, this.store));
1936
+ this.modeManager.addMode("draw:freehand", new FreehandMode(this.map, this.store, this.options));
1937
+ this.modeManager.addMode("cut", new CutMode(map, this.store, this.options));
1938
+ this.modeManager.addMode("split", new SplitMode(map, this.store, this.options));
1939
+ this.modeManager.addMode("union", new UnionMode(map, this.store, this.options));
1940
+ this.modeManager.addMode("subtract", new SubtractMode(map, this.store, this.options));
1941
+ this.modeManager.addMode("drag", new DragMode(map, this.store, this.options));
1942
+ this.modeManager.addMode("scale", new ScaleMode(map, this.store, this.options));
1943
+ this.modeManager.addMode("rotate", new RotateMode(map, this.store, this.options));
1944
+ this.modeManager.addMode("edit", new EditMode(this.map, this.store, this.options));
1945
+ this.modeManager.addMode("delete", new DeleteMode(map, this.store));
1946
+ this.map.on(ANVIL_EVENTS.CREATED, (e) => {
1947
+ this.store.addLayer(e.layer);
1948
+ });
1949
+ this.map.on(ANVIL_EVENTS.DELETED, (e) => {
1950
+ this.store.removeLayer(e.layer);
1951
+ });
1952
+ }
1953
+ enable(mode) {
1954
+ this.modeManager.enable(mode);
1955
+ }
1956
+ disable() {
1957
+ this.modeManager.disable();
1958
+ }
1959
+ getLayerGroup() {
1960
+ return this.store.getGroup();
1961
+ }
1962
+ };
1963
+
1964
+ // src/controls/anvil-control.ts
1965
+ var L21 = __toESM(require("leaflet"));
1966
+ var SVG_ATTRS = 'xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"';
1967
+ var ICONS = {
1968
+ // Marker: Map-Pin mit Punkt in der Mitte
1969
+ "draw:marker": `<svg ${SVG_ATTRS}><path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z"/><circle cx="12" cy="10" r="3"/></svg>`,
1970
+ // Polyline: Kurvige Route mit Endpunkten
1971
+ "draw:polyline": `<svg ${SVG_ATTRS}><path d="M9 19h8.5a3.5 3.5 0 0 0 0-7h-11a3.5 3.5 0 0 1 0-7H15"/><circle cx="18" cy="5" r="3"/><circle cx="6" cy="19" r="3"/></svg>`,
1972
+ // Polygon: Klassische unregelmäßige 5-Eck-Form
1973
+ "draw:polygon": `<svg ${SVG_ATTRS}><path d="m12 2 10 7-3 12H5l-3-12Z"/></svg>`,
1974
+ // Rectangle: Horizontales Rechteck
1975
+ "draw:rectangle": `<svg ${SVG_ATTRS}><rect width="20" height="12" x="2" y="6" rx="2"/></svg>`,
1976
+ // Square: Quadratisches Rechteck (1:1)
1977
+ "draw:square": `<svg ${SVG_ATTRS}><rect width="18" height="18" x="3" y="3" rx="2"/></svg>`,
1978
+ // Triangle: Gleichschenkliges Dreieck
1979
+ "draw:triangle": `<svg ${SVG_ATTRS}><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"/></svg>`,
1980
+ // Circle: Klassischer Kreis
1981
+ "draw:circle": `<svg ${SVG_ATTRS}><circle cx="12" cy="12" r="10"/></svg>`,
1982
+ // Freehand: Geschwungene Signatur-Linie
1983
+ "draw:freehand": `<svg ${SVG_ATTRS}><path d="m3 16 2 2 16-16"/><path d="M7 21h14"/><path d="M3 11c0 2 2 2 2 2z"/></svg>`,
1984
+ // Cut: Offene Schere
1985
+ "cut": `<svg ${SVG_ATTRS}><circle cx="6" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M20 4 8.12 15.88"/><path d="M14.47 14.48 20 20"/><path d="M8.12 8.12 12 12"/></svg>`,
1986
+ // Split: Linie, die eine Form teilt
1987
+ "split": `<svg ${SVG_ATTRS}><path d="M3 12h18"/><path d="M8 3v18"/><path d="M16 3v18"/><rect width="18" height="18" x="3" y="3" rx="2" stroke-dasharray="4 4" opacity="0.5"/></svg>`,
1988
+ // Union: Zwei verschmolzene Rechtecke
1989
+ "union": `<svg ${SVG_ATTRS}><path d="M8 4H4v4"/><path d="M4 12v4a2 2 0 0 0 2 2h4"/><path d="M14 18h4v-4"/><path d="M20 10V6a2 2 0 0 0-2-2h-4"/><path d="M14 10h-4v4" stroke-dasharray="2 2"/></svg>`,
1990
+ // Subtract: Hauptform mit "ausgeschnittenem" Bereich (Minus-Metapher)
1991
+ "subtract": `<svg ${SVG_ATTRS}><path d="M4 4h16v16H4z"/><path d="M10 10h10v10H10z" stroke-dasharray="2 2" opacity="0.7"/><path d="M15 6h-6"/></svg>`,
1992
+ // Drag: Vier-Wege-Pfeil (Move-Metapher)
1993
+ "drag": `<svg ${SVG_ATTRS}><path d="m5 9-3 3 3 3"/><path d="m9 5 3-3 3 3"/><path d="m15 19 3 3 3-3"/><path d="m19 9 3 3-3 3"/><path d="M2 12h20"/><path d="M12 2v20"/></svg>`,
1994
+ // Scale: Diagonal-Pfeile (Maximize-Metapher)
1995
+ "scale": `<svg ${SVG_ATTRS}><path d="M15 3h6v6"/><path d="M9 21H3v-6"/><path d="M21 3 14 10"/><path d="M3 21l7-7"/></svg>`,
1996
+ // Rotate: Kreispfeil mit Ziel-Icon
1997
+ "rotate": `<svg ${SVG_ATTRS}><path d="M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/></svg>`,
1998
+ // Edit: Stift, der über einen Pfad zeichnet
1999
+ "edit": `<svg ${SVG_ATTRS}><path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg>`,
2000
+ // Delete: Mülleimer mit Deckel und Schlitzen
2001
+ "delete": `<svg ${SVG_ATTRS}><path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/><line x1="10" x2="10" y1="11" y2="17"/><line x1="14" x2="14" y1="11" y2="17"/></svg>`,
2002
+ // Off: Durchgestrichener Kreis (Power-Off/Disable Metapher)
2003
+ "off": `<svg ${SVG_ATTRS}><circle cx="12" cy="12" r="10"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/></svg>`
2004
+ };
2005
+ var AnvilControl = class extends L21.Control {
2006
+ constructor(anvil, options) {
2007
+ super(L21.Util.extend({ position: "topleft" }, options));
2008
+ __publicField(this, "_btns", {});
2009
+ __publicField(this, "_anvil");
2010
+ this._anvil = anvil;
2011
+ }
2012
+ onAdd(map) {
2013
+ console.log("AnvilControl: triggering onAdd");
2014
+ const container = L21.DomUtil.create("div", "leaflet-bar anvil-toolbar");
2015
+ container.style.backgroundColor = "white";
2016
+ container.style.display = "flex";
2017
+ container.style.flexDirection = "column";
2018
+ const modes = [
2019
+ { id: "draw:marker", title: "Marker" },
2020
+ { id: "draw:polyline", title: "Line" },
2021
+ { id: "draw:polygon", title: "Polygon" },
2022
+ { id: "draw:rectangle", title: "Rectangle" },
2023
+ { id: "draw:square", title: "Square" },
2024
+ { id: "draw:triangle", title: "Triangle" },
2025
+ { id: "draw:circle", title: "Circle" },
2026
+ { id: "draw:freehand", title: "Freehand" },
2027
+ { id: "cut", title: "Cut" },
2028
+ { id: "split", title: "Split" },
2029
+ { id: "union", title: "Union" },
2030
+ { id: "subtract", title: "Subtract" },
2031
+ { id: "drag", title: "Drag" },
2032
+ { id: "scale", title: "Scale" },
2033
+ { id: "rotate", title: "Rotate" },
2034
+ { id: "edit", title: "Edit" },
2035
+ { id: "delete", title: "Delete" },
2036
+ { id: "off", title: "Turn Off" }
2037
+ ];
2038
+ modes.forEach((mode) => {
2039
+ const btn = L21.DomUtil.create("a", "anvil-control-btn", container);
2040
+ btn.innerHTML = ICONS[mode.id] || mode.title;
2041
+ btn.href = "#";
2042
+ btn.title = mode.title;
2043
+ btn.style.display = "flex";
2044
+ btn.style.alignItems = "center";
2045
+ btn.style.justifyContent = "center";
2046
+ btn.style.width = "30px";
2047
+ btn.style.height = "30px";
2048
+ btn.style.color = "#333";
2049
+ btn.style.cursor = "pointer";
2050
+ L21.DomEvent.disableClickPropagation(btn);
2051
+ L21.DomEvent.on(btn, "click", (e) => {
2052
+ L21.DomEvent.preventDefault(e);
2053
+ if (mode.id === "off") {
2054
+ this._anvil.disable();
2055
+ } else {
2056
+ this._anvil.enable(mode.id);
2057
+ }
2058
+ });
2059
+ this._btns[mode.id] = btn;
2060
+ });
2061
+ const updateFn = (m) => {
2062
+ for (const id in this._btns) {
2063
+ const active = id === m || id === "off" && !m;
2064
+ this._btns[id].style.backgroundColor = active ? "#eee" : "#fff";
2065
+ }
2066
+ };
2067
+ updateFn(null);
2068
+ map.on(ANVIL_EVENTS.MODE_CHANGE, (e) => updateFn(e.mode), this);
2069
+ return container;
2070
+ }
2071
+ };
2072
+ function anvilControl(anvil, options) {
2073
+ return new AnvilControl(anvil, options);
2074
+ }
2075
+
2076
+ // src/index.ts
2077
+ var leaflet = L22;
2078
+ leaflet.Anvil = Anvil;
2079
+ leaflet.anvil = (map, options) => new Anvil(map, options);
2080
+ if (leaflet.Control) {
2081
+ leaflet.Control.Anvil = (anvil, options) => anvilControl(anvil, options);
2082
+ leaflet.control.anvil = (anvil, options) => anvilControl(anvil, options);
2083
+ }
2084
+ // Annotate the CommonJS export names for ESM import in node:
2085
+ 0 && (module.exports = {
2086
+ ANVIL_EVENTS,
2087
+ Anvil,
2088
+ AnvilControl,
2089
+ anvilControl
2090
+ });