leaflet-polydraw 1.0.0 → 1.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.
Files changed (53) hide show
  1. package/README.md +2 -0
  2. package/dist/icons/icon-bbox.svg +10 -45
  3. package/dist/icons/icon-cancel.svg +7 -0
  4. package/dist/icons/icon-collapse.svg +79 -0
  5. package/dist/icons/icon-confirm.svg +20 -0
  6. package/dist/icons/icon-double-elbows.svg +11 -0
  7. package/dist/icons/icon-draw.svg +55 -1
  8. package/dist/icons/icon-erase.svg +14 -2
  9. package/dist/icons/icon-p2p-draw.svg +113 -0
  10. package/dist/icons/icon-p2p-subtract.svg +108 -0
  11. package/dist/icons/icon-polydraw2.svg +60 -0
  12. package/dist/icons/icon-resize.svg +7 -0
  13. package/dist/icons/icon-rotate.svg +3 -0
  14. package/dist/icons/icon-simplify2.svg +12 -44
  15. package/dist/leaflet-polydraw.css +1 -1
  16. package/dist/polydraw.es.js +1335 -234
  17. package/dist/polydraw.es.js.map +1 -1
  18. package/dist/polydraw.umd.min.js +1 -1
  19. package/dist/polydraw.umd.min.js.map +1 -1
  20. package/dist/styles/polydraw.css +38 -5
  21. package/dist/types/buttons.d.ts +1 -1
  22. package/dist/types/buttons.d.ts.map +1 -1
  23. package/dist/types/config.d.ts +3 -0
  24. package/dist/types/config.d.ts.map +1 -0
  25. package/dist/types/enums.d.ts +2 -1
  26. package/dist/types/enums.d.ts.map +1 -1
  27. package/dist/types/index.d.ts +1 -1
  28. package/dist/types/managers/mode-manager.d.ts.map +1 -1
  29. package/dist/types/managers/polygon-draw-manager.d.ts.map +1 -1
  30. package/dist/types/managers/polygon-interaction-manager.d.ts +6 -0
  31. package/dist/types/managers/polygon-interaction-manager.d.ts.map +1 -1
  32. package/dist/types/polydraw.d.ts +17 -7
  33. package/dist/types/polydraw.d.ts.map +1 -1
  34. package/dist/types/polygon.util.d.ts +2 -0
  35. package/dist/types/polygon.util.d.ts.map +1 -1
  36. package/dist/types/popup-factory.d.ts +30 -0
  37. package/dist/types/popup-factory.d.ts.map +1 -0
  38. package/dist/types/transform/polygon-transform-controller.d.ts +32 -0
  39. package/dist/types/transform/polygon-transform-controller.d.ts.map +1 -0
  40. package/dist/types/transform/transform-overlay.d.ts +34 -0
  41. package/dist/types/transform/transform-overlay.d.ts.map +1 -0
  42. package/dist/types/transform/transform-types.d.ts +44 -0
  43. package/dist/types/transform/transform-types.d.ts.map +1 -0
  44. package/dist/types/transform/transform-utils.d.ts +26 -0
  45. package/dist/types/transform/transform-utils.d.ts.map +1 -0
  46. package/dist/types/types/polydraw-interfaces.d.ts +121 -34
  47. package/dist/types/types/polydraw-interfaces.d.ts.map +1 -1
  48. package/dist/types/utils/config-merge.util.d.ts +2 -0
  49. package/dist/types/utils/config-merge.util.d.ts.map +1 -0
  50. package/dist/types/utils.d.ts +1 -1
  51. package/dist/types/utils.d.ts.map +1 -1
  52. package/package.json +7 -7
  53. package/dist/icons/icon-add-elbow.svg +0 -128
@@ -3,40 +3,6 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
  var _a, _b;
5
5
  import * as L$1 from "leaflet";
6
- const mergePolygons = true;
7
- const kinks$1 = false;
8
- const modes = { "draw": true, "subtract": true, "deleteAll": true, "p2p": true, "attachElbow": true, "dragElbow": true, "dragPolygons": true, "edgeDeletion": true };
9
- const dragPolygons = { "opacity": 0.7, "dragCursor": "move", "hoverCursor": "grab", "markerBehavior": "hide", "markerAnimationDuration": 200, "modifierSubtract": { "keys": { "windows": "ctrlKey", "mac": "metaKey", "linux": "ctrlKey" }, "hideMarkersOnDrag": true } };
10
- const edgeDeletion = { "keys": { "windows": "ctrlKey", "mac": "metaKey", "linux": "ctrlKey" }, "minVertices": 3 };
11
- const markers = { "deleteMarker": true, "infoMarker": true, "menuMarker": true, "coordsTitle": true, "zIndexOffset": 0, "markerIcon": { "styleClasses": ["polygon-marker"], "zIndexOffset": null }, "holeIcon": { "styleClasses": ["polygon-marker", "hole"], "zIndexOffset": null }, "markerInfoIcon": { "position": 3, "showArea": true, "showPerimeter": true, "useMetrics": true, "usePerimeterMinValue": false, "areaLabel": "Area", "perimeterLabel": "Perimeter", "values": { "min": { "metric": "50", "imperial": "100" }, "unknown": { "metric": "-", "imperial": "-" } }, "units": { "unknownUnit": "", "metric": { "onlyMetrics": true, "perimeter": { "m": "m", "km": "km" }, "area": { "m2": "m²", "km2": "km²", "daa": "daa", "ha": "ha" } }, "imperial": { "perimeter": { "feet": "ft", "yards": "yd", "miles": "mi" }, "area": { "feet2": "ft²", "yards2": "yd²", "acres": "ac", "miles2": "mi²" } } }, "styleClasses": ["polygon-marker", "info"], "zIndexOffset": 1e4 }, "markerMenuIcon": { "position": 7, "styleClasses": ["polygon-marker", "menu"], "zIndexOffset": 1e4 }, "markerDeleteIcon": { "position": 5, "styleClasses": ["polygon-marker", "delete"], "zIndexOffset": 1e4 }, "holeMarkers": { "menuMarker": false, "deleteMarker": true, "infoMarker": false }, "visualOptimization": { "sharpAngleThreshold": 30, "thresholdBoundingBox": 0.05, "thresholdDistance": 0.05, "useDistance": true, "useBoundingBox": false, "useAngles": false } };
12
- const polyLineOptions = { "opacity": 1, "smoothFactor": 0, "noClip": true, "clickable": false, "weight": 2 };
13
- const subtractLineOptions = { "opacity": 1, "smoothFactor": 0, "noClip": true, "clickable": false, "weight": 2 };
14
- const polygonOptions = { "smoothFactor": 0.3, "noClip": true };
15
- const holeOptions = { "weight": 2, "opacity": 1, "fillOpacity": 0.5 };
16
- const polygonCreation = { "method": "concaveman", "simplification": { "mode": "simple", "tolerance": 1e-5, "highQuality": false } };
17
- const simplification = { "simplifyTolerance": { "tolerance": 1e-4, "highQuality": false, "mutate": false }, "dynamicMode": { "fractionGuard": 0.9, "multiplier": 2 } };
18
- const menuOperations = { "simplify": { "processHoles": true }, "doubleElbows": { "processHoles": true }, "bbox": { "processHoles": true } };
19
- const boundingBox = { "addMidPointMarkers": true };
20
- const bezier$1 = { "resolution": 1e4, "sharpness": 0.75 };
21
- const colors = { "dragPolygons": { "subtract": "#D9460F" }, "p2p": { "closingMarker": "#4CAF50" }, "edgeHover": "#7a9441", "edgeDeletion": { "hover": "#D9460F" }, "polyline": "#50622b", "subtractLine": "#D9460F", "polygon": { "border": "#50622b", "fill": "#b4cd8a" }, "hole": { "border": "#aa0000", "fill": "#ffcccc" }, "styles": { "controlButton": { "backgroundColor": "#fff", "color": "#000" }, "controlButtonHover": { "backgroundColor": "#f4f4f4" }, "controlButtonActive": { "backgroundColor": "rgb(128, 218, 255)", "color": "#fff" }, "indicatorActive": { "backgroundColor": "#ffcc00" }, "p2pMarker": { "backgroundColor": "#fff", "borderColor": "#50622b" } } };
22
- const defaultConfig = {
23
- mergePolygons,
24
- kinks: kinks$1,
25
- modes,
26
- dragPolygons,
27
- edgeDeletion,
28
- markers,
29
- polyLineOptions,
30
- subtractLineOptions,
31
- polygonOptions,
32
- holeOptions,
33
- polygonCreation,
34
- simplification,
35
- menuOperations,
36
- boundingBox,
37
- bezier: bezier$1,
38
- colors
39
- };
40
6
  var LeafletVersion = /* @__PURE__ */ ((LeafletVersion2) => {
41
7
  LeafletVersion2["V1"] = "1.x";
42
8
  LeafletVersion2["V2"] = "2.x";
@@ -50,6 +16,7 @@ var DrawMode = /* @__PURE__ */ ((DrawMode2) => {
50
16
  DrawMode2[DrawMode2["AppendMarker"] = 8] = "AppendMarker";
51
17
  DrawMode2[DrawMode2["LoadPredefined"] = 16] = "LoadPredefined";
52
18
  DrawMode2[DrawMode2["PointToPoint"] = 32] = "PointToPoint";
19
+ DrawMode2[DrawMode2["PointToPointSubtract"] = 64] = "PointToPointSubtract";
53
20
  return DrawMode2;
54
21
  })(DrawMode || {});
55
22
  var MarkerPosition = /* @__PURE__ */ ((MarkerPosition2) => {
@@ -64,6 +31,244 @@ var MarkerPosition = /* @__PURE__ */ ((MarkerPosition2) => {
64
31
  MarkerPosition2[MarkerPosition2["Hole"] = 8] = "Hole";
65
32
  return MarkerPosition2;
66
33
  })(MarkerPosition || {});
34
+ const defaultConfig = {
35
+ mergePolygons: true,
36
+ kinks: false,
37
+ modes: {
38
+ draw: true,
39
+ subtract: true,
40
+ deleteAll: true,
41
+ p2p: true,
42
+ p2pSubtract: true,
43
+ attachElbow: true,
44
+ dragElbow: true,
45
+ dragPolygons: true,
46
+ edgeDeletion: true
47
+ },
48
+ defaultMode: DrawMode.Off,
49
+ dragPolygons: {
50
+ opacity: 0.7,
51
+ dragCursor: "move",
52
+ hoverCursor: "grab",
53
+ markerBehavior: "hide",
54
+ markerAnimationDuration: 200,
55
+ modifierSubtract: {
56
+ keys: {
57
+ windows: "ctrlKey",
58
+ mac: "metaKey",
59
+ linux: "ctrlKey"
60
+ },
61
+ hideMarkersOnDrag: true
62
+ }
63
+ },
64
+ edgeDeletion: {
65
+ keys: {
66
+ windows: "ctrlKey",
67
+ mac: "metaKey",
68
+ linux: "ctrlKey"
69
+ },
70
+ minVertices: 3
71
+ },
72
+ markers: {
73
+ deleteMarker: true,
74
+ infoMarker: true,
75
+ menuMarker: true,
76
+ coordsTitle: true,
77
+ zIndexOffset: 0,
78
+ markerIcon: {
79
+ styleClasses: ["polygon-marker"],
80
+ zIndexOffset: null
81
+ },
82
+ holeIcon: {
83
+ styleClasses: ["polygon-marker", "hole"],
84
+ zIndexOffset: null
85
+ },
86
+ markerInfoIcon: {
87
+ position: 3,
88
+ showArea: true,
89
+ showPerimeter: true,
90
+ useMetrics: true,
91
+ usePerimeterMinValue: false,
92
+ areaLabel: "Area",
93
+ perimeterLabel: "Perimeter",
94
+ values: {
95
+ min: {
96
+ metric: "50",
97
+ imperial: "100"
98
+ },
99
+ unknown: {
100
+ metric: "-",
101
+ imperial: "-"
102
+ }
103
+ },
104
+ units: {
105
+ unknownUnit: "",
106
+ metric: {
107
+ onlyMetrics: true,
108
+ perimeter: {
109
+ m: "m",
110
+ km: "km"
111
+ },
112
+ area: {
113
+ m2: "m²",
114
+ km2: "km²",
115
+ daa: "daa",
116
+ ha: "ha"
117
+ }
118
+ },
119
+ imperial: {
120
+ perimeter: {
121
+ feet: "ft",
122
+ yards: "yd",
123
+ miles: "mi"
124
+ },
125
+ area: {
126
+ feet2: "ft²",
127
+ yards2: "yd²",
128
+ acres: "ac",
129
+ miles2: "mi²"
130
+ }
131
+ }
132
+ },
133
+ styleClasses: ["polygon-marker", "info"],
134
+ zIndexOffset: 1e4
135
+ },
136
+ markerMenuIcon: {
137
+ position: 1,
138
+ styleClasses: ["polygon-marker", "menu"],
139
+ zIndexOffset: 1e4
140
+ },
141
+ markerDeleteIcon: {
142
+ position: 5,
143
+ styleClasses: ["polygon-marker", "delete"],
144
+ zIndexOffset: 1e4
145
+ },
146
+ holeMarkers: {
147
+ menuMarker: false,
148
+ deleteMarker: true,
149
+ infoMarker: false
150
+ },
151
+ visualOptimization: {
152
+ sharpAngleThreshold: 30,
153
+ thresholdBoundingBox: 0.05,
154
+ thresholdDistance: 0.05,
155
+ useDistance: true,
156
+ useBoundingBox: false,
157
+ useAngles: false
158
+ }
159
+ },
160
+ polyLineOptions: {
161
+ opacity: 1,
162
+ weight: 2
163
+ },
164
+ subtractLineOptions: {
165
+ opacity: 1,
166
+ weight: 2
167
+ },
168
+ polygonOptions: {
169
+ weight: 2,
170
+ opacity: 1,
171
+ fillOpacity: 0.2,
172
+ smoothFactor: 0.3,
173
+ noClip: true
174
+ },
175
+ holeOptions: {
176
+ weight: 2,
177
+ opacity: 1,
178
+ fillOpacity: 0.5
179
+ },
180
+ polygonCreation: {
181
+ method: "concaveman",
182
+ simplification: {
183
+ mode: "simple",
184
+ tolerance: 1e-5,
185
+ highQuality: false
186
+ }
187
+ },
188
+ simplification: {
189
+ simplifyTolerance: {
190
+ tolerance: 1e-4,
191
+ highQuality: false,
192
+ mutate: false
193
+ },
194
+ dynamicMode: {
195
+ fractionGuard: 0.9,
196
+ multiplier: 2
197
+ }
198
+ },
199
+ menuOperations: {
200
+ simplify: {
201
+ enabled: true,
202
+ processHoles: true
203
+ },
204
+ doubleElbows: {
205
+ enabled: true,
206
+ processHoles: true
207
+ },
208
+ bbox: {
209
+ enabled: true,
210
+ processHoles: true
211
+ },
212
+ bezier: {
213
+ enabled: true
214
+ },
215
+ scale: {
216
+ enabled: true
217
+ },
218
+ rotate: {
219
+ enabled: true
220
+ }
221
+ },
222
+ boundingBox: {
223
+ addMidPointMarkers: true
224
+ },
225
+ bezier: {
226
+ resolution: 1e4,
227
+ sharpness: 0.75
228
+ },
229
+ colors: {
230
+ dragPolygons: {
231
+ subtract: "#D9460F"
232
+ },
233
+ p2p: {
234
+ closingMarker: "#4CAF50"
235
+ },
236
+ edgeHover: "#7a9441",
237
+ edgeDeletion: {
238
+ hover: "#D9460F"
239
+ },
240
+ polyline: "#50622b",
241
+ subtractLine: "#D9460F",
242
+ polygon: {
243
+ border: "#50622b",
244
+ fill: "#b4cd8a"
245
+ },
246
+ hole: {
247
+ border: "#aa0000",
248
+ fill: "#ffcccc"
249
+ },
250
+ styles: {
251
+ controlButton: {
252
+ backgroundColor: "#fff",
253
+ color: "#000"
254
+ },
255
+ controlButtonHover: {
256
+ backgroundColor: "#f4f4f4"
257
+ },
258
+ controlButtonActive: {
259
+ backgroundColor: "rgb(128, 218, 255)",
260
+ color: "#fff"
261
+ },
262
+ indicatorActive: {
263
+ backgroundColor: "#ffcc00"
264
+ },
265
+ p2pMarker: {
266
+ backgroundColor: "#fff",
267
+ borderColor: "#50622b"
268
+ }
269
+ }
270
+ }
271
+ };
67
272
  const EARTH_RADIUS = {
68
273
  /**
69
274
  * Mean radius in meters - good enough for this tool's precision requirements
@@ -17753,7 +17958,35 @@ class LeafletAdapter {
17753
17958
  }
17754
17959
  }
17755
17960
  const leafletAdapter = new LeafletAdapter();
17756
- function createButtons(container, subContainer, config, onActivateToggle, onDrawClick, onSubtractClick, onEraseClick, onPointToPointClick) {
17961
+ const iconPolydraw2Svg = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n<!-- Generated by Pixelmator Pro 3.7 -->\n\n<svg\n width="512"\n height="512"\n viewBox="0 0 512 512"\n version="1.1"\n id="svg1"\n sodipodi:docname="icon-polydraw2.svg"\n inkscape:version="1.4.2 (ebf0e940, 2025-05-08)"\n xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"\n xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"\n xmlns="http://www.w3.org/2000/svg"\n xmlns:svg="http://www.w3.org/2000/svg">\n <defs\n id="defs1" />\n <sodipodi:namedview\n id="namedview1"\n pagecolor="#ffffff"\n bordercolor="#000000"\n borderopacity="0.25"\n inkscape:showpageshadow="2"\n inkscape:pageopacity="0.0"\n inkscape:pagecheckerboard="0"\n inkscape:deskcolor="#d1d1d1"\n inkscape:zoom="2.1854905"\n inkscape:cx="327.38645"\n inkscape:cy="233.586"\n inkscape:window-width="1728"\n inkscape:window-height="1084"\n inkscape:window-x="0"\n inkscape:window-y="33"\n inkscape:window-maximized="0"\n inkscape:current-layer="svg1" />\n <path\n id="Shape"\n fill="#000000"\n fill-rule="evenodd"\n stroke="none"\n d="M 73.574318 425.686768 C 72.433441 425.875031 69.474998 425.094574 67 423.952454 C 64.525002 422.810333 61.487499 420.925354 60.25 419.763611 C 58 417.651367 58 417.651367 58 348.144531 C 58 278.637695 58 278.637695 64.15226 268.068848 C 67.536011 262.255981 73.313545 252.549988 76.991226 246.5 C 80.668915 240.450012 89.670906 225.375 96.995644 213 C 104.320389 200.625 112.662483 186.674988 115.533646 182 C 118.4048 177.325012 128.697449 160.120361 138.406174 143.767456 C 148.114914 127.414551 163.517715 101.539551 172.634628 86.267456 C 181.751526 70.995361 190.896469 56.245453 192.956696 53.489868 C 195.254944 50.415955 198.736298 47.372833 201.964966 45.615601 C 205.547699 43.665619 209.185913 42.598907 213.363663 42.27356 C 218.336411 41.886292 220.809326 42.291656 226.404907 44.411316 C 230.202591 45.849945 237.402588 49.329651 242.404907 52.144043 C 247.407211 54.958435 255.774994 59.756927 261 62.807404 C 266.225006 65.857849 274.774994 70.941406 280 74.104187 C 285.225006 77.266937 292.061249 81.349854 295.191681 83.177338 C 298.322083 85.004791 304.593597 88.698059 309.128387 91.384552 C 313.663147 94.071075 319.525085 98.281769 322.154938 100.741699 C 325.42041 103.796173 327.611938 107.003418 329.066864 110.857117 C 330.739197 115.286774 331.103424 118.018188 330.760925 123.56131 C 330.43689 128.805359 329.575104 132.072418 327.412292 136.25589 C 325.810547 139.354187 318.023956 152.826599 310.108765 166.19458 C 302.193604 179.562561 293.868591 193.52121 291.608765 197.213776 C 289.348938 200.906342 284.985504 208.106354 281.912231 213.213776 C 278.838959 218.321198 270.711334 231.950012 263.8508 243.5 C 256.990295 255.049988 247.400177 271.25 242.539444 279.5 C 237.678696 287.75 231.360229 298.325012 228.498383 303 C 225.636551 307.674988 220.191147 316.829224 216.397522 323.342712 C 212.603882 329.856201 205.890396 341.105133 201.478653 348.340332 C 193.756912 361.003967 193.215347 361.63028 186.978653 365.109344 C 183.41539 367.097076 171.620941 373.526276 160.768753 379.396423 C 149.916565 385.266602 131.916565 395.056671 120.768745 401.1521 C 109.620934 407.247559 94.90844 415.184448 88.074318 418.789642 C 81.240189 422.394806 74.715187 425.498535 73.574318 425.686768 Z M 116 376.754456 C 118.096039 376.543518 128.525452 371.474579 142 364.117859 C 154.375 357.361481 165.393753 350.964722 166.486115 349.902863 C 167.980591 348.450134 168.219772 347.57196 167.452347 346.355347 C 166.891403 345.466064 160.147644 341.00293 152.466217 336.437256 C 144.784805 331.871613 135.350006 326.168945 131.5 323.764709 C 127.650002 321.360443 116.453964 314.692322 106.619926 308.946655 C 96.785881 303.200989 87.533401 297.970886 86.058846 297.324219 C 84.417702 296.604492 82.819748 296.493042 81.938927 297.036957 C 80.957619 297.642883 80.340988 300.480957 80 305.960907 C 79.724998 310.380402 79.653214 323.273193 79.840477 334.611572 C 80.180962 355.226837 80.180962 355.226837 83.340477 358.518677 C 85.078217 360.329193 92.349998 365.252136 99.5 369.458588 C 110.254417 375.785583 113.104576 377.045837 116 376.754456 Z M 184.979996 329 C 185.880753 329 187.322388 328.4375 188.183624 327.75 C 189.044861 327.0625 191.986755 322.899994 194.721161 318.5 C 197.455582 314.100006 212.197037 289.575012 227.47995 264 C 242.762863 238.424988 257.119476 214.503387 259.383514 210.840851 C 261.647583 207.178284 265.524994 200.687805 268 196.417542 C 270.475006 192.147247 273.957123 186.14389 275.738068 183.076691 C 277.523224 180.002289 278.981506 176.072205 278.988068 174.317993 C 278.999237 171.335541 278.294434 170.703522 267.75 164.240753 C 261.5625 160.448364 253.125 155.321045 249 152.84668 C 244.875 150.372314 235.754837 144.907379 228.732956 140.702332 C 221.71109 136.497284 212.486084 130.958221 208.232956 128.39328 C 203.979828 125.828369 197.371674 121.899323 193.548157 119.662079 C 189.72464 117.424835 185.418167 115.421448 183.978195 115.210114 C 181.979828 114.916809 180.644867 115.640442 178.338669 118.267059 C 176.676895 120.159729 172.969727 125.711395 170.10054 130.604126 C 167.231339 135.496857 162.066681 144.159821 158.62352 149.855194 C 155.180359 155.550537 149.634521 164.775543 146.299438 170.355194 C 142.964355 175.934845 136.29039 187.024994 131.468384 195 C 126.646393 202.975006 120.571129 213.100006 117.967812 217.5 C 115.364487 221.899994 109.518463 231.575012 104.976639 239 C 100.434822 246.424988 94.708519 255.988464 92.251534 260.252167 C 88.991837 265.908813 87.948189 268.65741 88.390656 270.420349 C 88.845047 272.230804 92.629936 274.990234 103.491547 281.429932 C 111.463524 286.156433 124.176689 293.686981 131.743027 298.16452 C 139.309357 302.642059 149.324997 308.65036 154 311.516296 C 158.675003 314.382263 167.189499 319.488525 172.921127 322.863556 C 178.65274 326.238586 184.079239 329 184.979996 329 Z M 285.661102 134.977844 C 287.97934 134.99408 289.512512 134.179626 291.411102 131.923279 C 292.908417 130.143829 294 127.609955 294 125.913757 C 294 123.644043 293.152191 122.405426 290.25 120.435181 C 288.1875 119.034973 283.720306 116.145264 280.322876 114.01358 C 276.925446 111.881897 270.400452 107.99884 265.822876 105.384521 C 261.2453 102.770203 255.024994 98.976471 252 96.954041 C 248.975006 94.93161 244.25 92.081146 241.5 90.61969 C 238.75 89.158264 233.350006 85.931335 229.5 83.448761 C 224.476532 80.209473 221.661926 79.01474 219.531921 79.217499 C 217.432587 79.417297 215.882141 80.515015 214.234802 82.967804 C 212.798111 85.106964 212.019608 87.555267 212.202881 89.357971 C 212.456848 91.855927 213.807068 93.077637 221.5 97.770203 C 226.449997 100.789642 237.024994 107.196594 245 112.007874 C 252.975006 116.819153 264.674988 123.950684 271 127.855682 C 278.806824 132.675537 283.515167 134.962799 285.661102 134.977844 Z" />\n <path\n id="path1"\n fill="#000000"\n fill-rule="evenodd"\n stroke="none"\n d="M 479.5 119.5 C 479.5 153.5 479.5 153.5 472.5 153.761627 C 468.649994 153.905518 461.225006 154.708954 456 155.547028 C 450.774994 156.385132 443.466675 157.966583 439.759277 159.061371 C 436.05188 160.156189 430.343719 162.619598 427.074493 164.535645 C 423.805267 166.451691 419.672913 169.245789 417.891449 170.744781 C 416.110016 172.243774 412.965179 176.08078 410.902954 179.271454 C 408.507751 182.977295 406.493622 187.858795 405.326721 192.786346 C 403.980774 198.469788 403.509888 204.334198 403.537537 215.067841 C 403.560455 223.970093 404.286011 234.276245 405.403107 241.567841 C 406.408508 248.130524 408.366913 258.674988 409.755096 265 C 411.14325 271.325012 412.907196 279.200012 413.674927 282.5 C 414.442657 285.799988 416.815094 297.049988 418.946991 307.5 C 421.078888 317.950012 423.76297 332.401184 424.911591 339.613708 C 426.481873 349.47406 427 357.319122 427 371.235504 C 427 387.630524 426.716309 390.871338 424.515106 399.621765 C 423.148407 405.05481 420.216461 413.182556 417.999634 417.683472 C 415.167511 423.433655 411.734741 428.242035 406.454742 433.854706 C 401.146912 439.496948 395.939392 443.700836 388.720215 448.171234 C 383.099091 451.652039 375.575012 455.78241 372 457.349823 C 368.424988 458.917206 361.261017 461.749329 356.080017 463.643402 C 350.899017 465.537445 342.574005 467.951355 337.580017 469.007568 C 332.585999 470.063812 324 471.644897 318.5 472.521088 C 311.866943 473.57782 299.745911 474.237183 282.5 474.479462 C 268.200012 474.680359 252 474.489349 246.5 474.054932 C 241 473.620544 230.875 472.51828 224 471.605438 C 217.125 470.692596 207.424561 469.276886 202.443451 468.459412 C 197.462357 467.641907 190.037354 466.282959 185.943451 465.439453 C 181.849548 464.595978 176.25 463.281586 173.5 462.518616 C 170.75 461.755646 165.800003 460.43631 162.5 459.586731 C 159.199997 458.737183 152 456.93927 146.5 455.59137 C 141 454.243469 130.649994 451.291107 123.5 449.030579 C 116.349998 446.77002 108.587502 444.226166 106.25 443.377533 C 103.345978 442.323242 102 441.251038 102 439.992004 C 102 438.763947 105.25164 436.022705 111.75 431.772461 C 117.112503 428.265137 124.951981 423.494568 129.171066 421.171265 C 136.842117 416.947052 136.842117 416.947052 147.671066 419.885193 C 153.626984 421.50116 166.824997 424.88266 177 427.399658 C 187.175003 429.916656 200.449997 432.864655 206.5 433.950775 C 212.550003 435.036896 221.550003 436.377319 226.5 436.929504 C 231.449997 437.481689 241.350006 438.46051 248.5 439.104675 C 256.607147 439.835083 270.156616 440.060425 284.5 439.703461 C 297.763824 439.373352 311.521454 438.469299 317 437.56781 C 322.225006 436.708008 331 434.605408 336.5 432.895386 C 342 431.185333 349.424988 428.45224 353 426.821869 C 356.575012 425.191498 361.75 422.78241 364.5 421.468353 C 367.25 420.154297 372.440887 416.632446 376.035309 413.642029 C 379.923035 410.407593 383.626404 406.239136 385.176788 403.352478 C 386.610199 400.683624 388.82962 395.208862 390.108826 391.18631 C 392.043091 385.103973 392.427551 381.771362 392.392365 371.391907 C 392.368134 364.243286 391.617584 354.764648 390.63559 349.205566 C 389.692627 343.867493 388.22879 335.674988 387.382629 331 C 386.536469 326.325012 384.929169 318.225006 383.810822 313 C 382.692505 307.774994 380.661194 299 379.296814 293.5 C 377.932434 288 375.796661 278.774994 374.55069 273 C 373.304718 267.225006 371.555939 258 370.66452 252.5 C 369.773102 247 368.583893 238.419525 368.021881 233.432281 C 367.459839 228.445038 367.007843 219.445038 367.017456 213.432281 C 367.027069 207.419525 367.668945 198.633209 368.443848 193.907166 C 369.21875 189.181091 370.563477 182.881104 371.432129 179.907166 C 372.300781 176.933228 374.471405 171.682648 376.255737 168.239197 C 378.0401 164.795746 381.511963 159.235352 383.971008 155.882751 C 386.430054 152.530182 392.055054 146.895081 396.471008 143.360352 C 400.886963 139.825592 408.100006 135.196167 412.5 133.072693 C 416.899994 130.949249 424.549988 127.878998 429.5 126.249969 C 434.450012 124.620911 444.125 122.492981 451 121.521179 C 457.875 120.549408 467.100006 119.697083 471.5 119.627167 L 479.5 119.5 Z" />\n <path\n id="path2"\n fill="#B6BCC4"\n fill-rule="evenodd"\n stroke="none"\n d="M 116 375.742615 C 113.270905 375.979401 110.6278 374.942505 104 371.035126 C 99.324997 368.278992 92.867485 364.331085 89.649971 362.261993 C 86.432457 360.192871 83.16996 357.284851 82.399971 355.799683 C 81.305717 353.689026 81 347.452454 81 327.240784 C 81 306.114777 81.26738 301.027008 82.460983 299.441132 C 83.890869 297.541321 84.034538 297.562286 89.210983 300.426575 C 92.119942 302.036163 97.425003 305.010712 101 307.036682 C 104.574997 309.062622 110.100868 312.245667 113.279701 314.110107 C 116.458542 315.974548 123.533379 320.200012 129.001572 323.5 C 134.469757 326.799988 142.838348 331.745026 147.59845 334.488953 C 152.358566 337.232849 158.333725 340.837097 160.876587 342.498352 C 163.445404 344.176575 165.630447 346.4263 165.793533 347.560852 C 166.040268 349.277313 162.373489 351.662323 142.793533 362.520905 C 128.02803 370.709534 118.218613 375.55014 116 375.742615 Z" />\n <path\n id="path3"\n fill="#aaffaa"\n fill-rule="evenodd"\n stroke="none"\n d="M 185.255783 329 C 184.243942 329 179.609955 326.806396 174.958038 324.125366 C 170.306122 321.444336 152.324997 310.802734 135 300.477417 C 117.675003 290.152069 100.349998 279.633148 96.5 277.102051 C 90.249817 272.99295 89.471245 272.125092 89.231583 269 C 89.029724 266.367798 90.047935 263.640442 93.338226 258 C 95.744507 253.875 114.914024 221.924988 135.937164 187 C 156.960297 152.075012 175.408127 121.924988 176.932327 120 C 179.126877 117.228363 180.520828 116.438263 183.630585 116.203308 C 187.107788 115.940613 189.902344 117.306458 208.028793 128.128174 C 219.287949 134.850037 238.175003 146.155121 250 153.25058 C 261.825012 160.346039 273.075012 167.400116 275 168.926331 C 277.098694 170.590271 278.626709 172.762299 278.816498 174.351379 C 279.006622 175.943481 277.794708 179.496368 275.780823 183.250732 C 273.937134 186.687836 254.255646 219.779419 232.044174 256.787598 C 209.832703 293.795776 190.632736 325.183258 189.377579 326.537598 C 188.122437 327.891907 186.267624 329 185.255783 329 Z" />\n</svg>\n';
17962
+ const iconP2PSubtractSvg = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n<!-- Generated by Pixelmator Pro 3.7 -->\n\n<svg\n width="512"\n height="512"\n viewBox="0 0 512 512"\n version="1.1"\n id="svg1"\n sodipodi:docname="icon-p2p-subtract.svg"\n inkscape:version="1.4.2 (ebf0e940, 2025-05-08)"\n xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"\n xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"\n xmlns="http://www.w3.org/2000/svg"\n xmlns:svg="http://www.w3.org/2000/svg">\n <defs\n id="defs1" />\n <sodipodi:namedview\n id="namedview1"\n pagecolor="#ffffff"\n bordercolor="#000000"\n borderopacity="0.25"\n inkscape:showpageshadow="2"\n inkscape:pageopacity="0.0"\n inkscape:pagecheckerboard="0"\n inkscape:deskcolor="#d1d1d1"\n inkscape:zoom="0.57779708"\n inkscape:cx="236.24211"\n inkscape:cy="80.478081"\n inkscape:window-width="1200"\n inkscape:window-height="770"\n inkscape:window-x="218"\n inkscape:window-y="226"\n inkscape:window-maximized="0"\n inkscape:current-layer="svg1"\n showguides="true">\n <sodipodi:guide\n position="294.40467,66.478038"\n orientation="0,-1"\n id="guide1"\n inkscape:locked="false" />\n <sodipodi:guide\n position="443.95598,219.9443"\n orientation="1,0"\n id="guide2"\n inkscape:locked="false" />\n <sodipodi:guide\n position="479.19058,322.51614"\n orientation="1,0"\n id="guide3"\n inkscape:locked="false" />\n <sodipodi:guide\n position="292.83869,31.243437"\n orientation="0,-1"\n id="guide4"\n inkscape:locked="false" />\n <sodipodi:guide\n position="263.86802,466.58651"\n orientation="0,-1"\n id="guide5"\n inkscape:locked="false" />\n <sodipodi:guide\n position="261.51904,432.1349"\n orientation="0,-1"\n id="guide6"\n inkscape:locked="false" />\n <sodipodi:guide\n position="32.885628,329.56306"\n orientation="1,0"\n id="guide7"\n inkscape:locked="false" />\n </sodipodi:namedview>\n <path\n id="path2"\n fill="#000000"\n fill-rule="evenodd"\n stroke="none"\n d="m 193.81183,478.59424 c -90.05259,0.005 -55.41437,-0.20995 -62.99516,-0.88359 -3.1082,-0.2762 -27.10921,-21.64334 -46.819084,-41.47757 -19.70986,-19.83423 -38.405351,-39.29924 -41.545547,-43.25557 -3.140161,-3.95634 -6.620273,-10.71524 -7.733575,-15.01969 -1.731782,-6.69578 -1.640384,-9.15249 0.632805,-17.00722 2.629257,-9.08499 3.6462,-10.16288 97.354641,-103.18631 67.81987,-67.32409 96.74165,-95.00594 101.89931,-97.5306 4.69396,-2.29769 10.02467,-3.49792 15.30881,-3.44687 5.93187,0.0573 10.33676,1.33387 16.41655,4.7576 5.37383,3.02609 23.90609,20.08661 52.45656,48.29048 24.28094,23.98618 46.73845,47.41164 49.90564,52.05662 4.53335,6.64854 5.89358,10.35999 6.39341,17.4445 0.53601,7.59755 -0.0725,10.28802 -3.90756,17.27501 -3.19113,5.81394 -24.29994,28.16258 -70.95801,75.12564 -36.52859,36.76731 -66.37253,67.62363 -66.92611,68.17388 -19.82934,19.70981 -39.70971,38.18329 -39.48268,38.68369 z M 278.39348,341.263 c -68.04391,-67.49005 -88.70387,-86.89199 -89.81039,-86.65746 -1.10652,0.23458 -27.94601,26.11747 -59.64337,57.51756 -31.697381,31.40008 -57.438314,57.93966 -57.202104,58.97682 0.23622,1.03714 15.75768,17.2724 34.492134,36.07839 34.06266,34.19266 34.06266,34.19266 53.59952,34.19266 19.53691,0 19.53691,0 55.27489,-35.28546 19.65593,-19.40699 41.93704,-41.9313 49.51367,-50.05396 z m 60.93865,-60.02398 c -66.90002,-66.62079 -87.2881,-86.35609 -88.46817,-86.83735 -1.29064,-0.52641 -8.78712,5.68385 -18.81344,15.58544 l -16.66788,16.46053 44.40871,44.02713 c 24.42482,24.21491 44.78655,44.02712 45.24827,44.02712 0.46173,0 8.36641,-7.48416 17.56604,-16.63144 z"\n style="stroke-width:1.5931"\n sodipodi:nodetypes="csssssssscssssssccsssssssccsscsscc" />\n <path\n style="fill:#800000;fill-opacity:1;stroke:#010101;stroke-width:7.48758"\n d="m 214.60419,225.76607 35.34452,-32.835 89.30798,87.87273 -34.08219,33.77315 z"\n id="path3" />\n <path\n style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:35;stroke-dasharray:none;stroke-opacity:1"\n d="m 238.70454,480.61597 240.58456,-0.0328 0,-435.375911 L 32.679361,44.8696 32.918466,80.474658 444.02166,79.593154 443.68404,445.58764 274.55795,445.01091 Z"\n id="path7"\n sodipodi:nodetypes="ccccccccc" />\n <circle\n style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:35;stroke-dasharray:none;stroke-opacity:1"\n id="path8"\n cx="460.39642"\n cy="461.54739"\n r="39.133694" />\n <circle\n style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:35;stroke-dasharray:none;stroke-opacity:1"\n id="path8-8"\n cx="460.77478"\n cy="65.833855"\n r="39.133694" />\n <circle\n style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:35;stroke-dasharray:none;stroke-opacity:1"\n id="path8-8-0"\n cx="67.175827"\n cy="62.81522"\n r="39.133694" />\n</svg>\n';
17963
+ const iconDrawSvg = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n<!-- Generated by Pixelmator Pro 3.7 -->\n\n<svg\n width="512"\n height="512"\n viewBox="0 0 512 512"\n version="1.1"\n id="svg1"\n sodipodi:docname="icon-draw.svg"\n inkscape:version="1.4.2 (ebf0e940, 2025-05-08)"\n xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"\n xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"\n xmlns="http://www.w3.org/2000/svg"\n xmlns:svg="http://www.w3.org/2000/svg">\n <defs\n id="defs1" />\n <sodipodi:namedview\n id="namedview1"\n pagecolor="#ffffff"\n bordercolor="#000000"\n borderopacity="0.25"\n inkscape:showpageshadow="2"\n inkscape:pageopacity="0.0"\n inkscape:pagecheckerboard="0"\n inkscape:deskcolor="#d1d1d1"\n inkscape:zoom="1.4901425"\n inkscape:cx="137.2352"\n inkscape:cy="249.97609"\n inkscape:window-width="1728"\n inkscape:window-height="1056"\n inkscape:window-x="0"\n inkscape:window-y="61"\n inkscape:window-maximized="0"\n inkscape:current-layer="svg1" />\n <path\n id="Shape"\n fill="#000000"\n fill-rule="evenodd"\n stroke="none"\n d="M 73.574318 425.686768 C 72.433441 425.875031 69.474998 425.094574 67 423.952454 C 64.525002 422.810333 61.487499 420.925354 60.25 419.763611 C 58 417.651367 58 417.651367 58 348.144531 C 58 278.637695 58 278.637695 64.15226 268.068848 C 67.536011 262.255981 73.313545 252.549988 76.991226 246.5 C 80.668915 240.450012 89.670906 225.375 96.995644 213 C 104.320389 200.625 112.662483 186.674988 115.533646 182 C 118.4048 177.325012 128.697449 160.120361 138.406174 143.767456 C 148.114914 127.414551 163.517715 101.539551 172.634628 86.267456 C 181.751526 70.995361 190.896469 56.245453 192.956696 53.489868 C 195.254944 50.415955 198.736298 47.372833 201.964966 45.615601 C 205.547699 43.665619 209.185913 42.598907 213.363663 42.27356 C 218.336411 41.886292 220.809326 42.291656 226.404907 44.411316 C 230.202591 45.849945 237.402588 49.329651 242.404907 52.144043 C 247.407211 54.958435 255.774994 59.756927 261 62.807404 C 266.225006 65.857849 274.774994 70.941406 280 74.104187 C 285.225006 77.266937 292.061249 81.349854 295.191681 83.177338 C 298.322083 85.004791 304.593597 88.698059 309.128387 91.384552 C 313.663147 94.071075 319.525085 98.281769 322.154938 100.741699 C 325.42041 103.796173 327.611938 107.003418 329.066864 110.857117 C 330.739197 115.286774 331.103424 118.018188 330.760925 123.56131 C 330.43689 128.805359 329.575104 132.072418 327.412292 136.25589 C 325.810547 139.354187 318.023956 152.826599 310.108765 166.19458 C 302.193604 179.562561 293.868591 193.52121 291.608765 197.213776 C 289.348938 200.906342 284.985504 208.106354 281.912231 213.213776 C 278.838959 218.321198 270.711334 231.950012 263.8508 243.5 C 256.990295 255.049988 247.400177 271.25 242.539444 279.5 C 237.678696 287.75 231.360229 298.325012 228.498383 303 C 225.636551 307.674988 220.191147 316.829224 216.397522 323.342712 C 212.603882 329.856201 205.890396 341.105133 201.478653 348.340332 C 193.756912 361.003967 193.215347 361.63028 186.978653 365.109344 C 183.41539 367.097076 171.620941 373.526276 160.768753 379.396423 C 149.916565 385.266602 131.916565 395.056671 120.768745 401.1521 C 109.620934 407.247559 94.90844 415.184448 88.074318 418.789642 C 81.240189 422.394806 74.715187 425.498535 73.574318 425.686768 Z M 116 376.754456 C 118.096039 376.543518 128.525452 371.474579 142 364.117859 C 154.375 357.361481 165.393753 350.964722 166.486115 349.902863 C 167.980591 348.450134 168.219772 347.57196 167.452347 346.355347 C 166.891403 345.466064 160.147644 341.00293 152.466217 336.437256 C 144.784805 331.871613 135.350006 326.168945 131.5 323.764709 C 127.650002 321.360443 116.453964 314.692322 106.619926 308.946655 C 96.785881 303.200989 87.533401 297.970886 86.058846 297.324219 C 84.417702 296.604492 82.819748 296.493042 81.938927 297.036957 C 80.957619 297.642883 80.340988 300.480957 80 305.960907 C 79.724998 310.380402 79.653214 323.273193 79.840477 334.611572 C 80.180962 355.226837 80.180962 355.226837 83.340477 358.518677 C 85.078217 360.329193 92.349998 365.252136 99.5 369.458588 C 110.254417 375.785583 113.104576 377.045837 116 376.754456 Z M 184.979996 329 C 185.880753 329 187.322388 328.4375 188.183624 327.75 C 189.044861 327.0625 191.986755 322.899994 194.721161 318.5 C 197.455582 314.100006 212.197037 289.575012 227.47995 264 C 242.762863 238.424988 257.119476 214.503387 259.383514 210.840851 C 261.647583 207.178284 265.524994 200.687805 268 196.417542 C 270.475006 192.147247 273.957123 186.14389 275.738068 183.076691 C 277.523224 180.002289 278.981506 176.072205 278.988068 174.317993 C 278.999237 171.335541 278.294434 170.703522 267.75 164.240753 C 261.5625 160.448364 253.125 155.321045 249 152.84668 C 244.875 150.372314 235.754837 144.907379 228.732956 140.702332 C 221.71109 136.497284 212.486084 130.958221 208.232956 128.39328 C 203.979828 125.828369 197.371674 121.899323 193.548157 119.662079 C 189.72464 117.424835 185.418167 115.421448 183.978195 115.210114 C 181.979828 114.916809 180.644867 115.640442 178.338669 118.267059 C 176.676895 120.159729 172.969727 125.711395 170.10054 130.604126 C 167.231339 135.496857 162.066681 144.159821 158.62352 149.855194 C 155.180359 155.550537 149.634521 164.775543 146.299438 170.355194 C 142.964355 175.934845 136.29039 187.024994 131.468384 195 C 126.646393 202.975006 120.571129 213.100006 117.967812 217.5 C 115.364487 221.899994 109.518463 231.575012 104.976639 239 C 100.434822 246.424988 94.708519 255.988464 92.251534 260.252167 C 88.991837 265.908813 87.948189 268.65741 88.390656 270.420349 C 88.845047 272.230804 92.629936 274.990234 103.491547 281.429932 C 111.463524 286.156433 124.176689 293.686981 131.743027 298.16452 C 139.309357 302.642059 149.324997 308.65036 154 311.516296 C 158.675003 314.382263 167.189499 319.488525 172.921127 322.863556 C 178.65274 326.238586 184.079239 329 184.979996 329 Z M 285.661102 134.977844 C 287.97934 134.99408 289.512512 134.179626 291.411102 131.923279 C 292.908417 130.143829 294 127.609955 294 125.913757 C 294 123.644043 293.152191 122.405426 290.25 120.435181 C 288.1875 119.034973 283.720306 116.145264 280.322876 114.01358 C 276.925446 111.881897 270.400452 107.99884 265.822876 105.384521 C 261.2453 102.770203 255.024994 98.976471 252 96.954041 C 248.975006 94.93161 244.25 92.081146 241.5 90.61969 C 238.75 89.158264 233.350006 85.931335 229.5 83.448761 C 224.476532 80.209473 221.661926 79.01474 219.531921 79.217499 C 217.432587 79.417297 215.882141 80.515015 214.234802 82.967804 C 212.798111 85.106964 212.019608 87.555267 212.202881 89.357971 C 212.456848 91.855927 213.807068 93.077637 221.5 97.770203 C 226.449997 100.789642 237.024994 107.196594 245 112.007874 C 252.975006 116.819153 264.674988 123.950684 271 127.855682 C 278.806824 132.675537 283.515167 134.962799 285.661102 134.977844 Z"\n style="stroke:#000000;stroke-opacity:1;stroke-width:20;stroke-dasharray:none" />\n <path\n id="path1"\n fill="#000000"\n fill-rule="evenodd"\n stroke="none"\n d="M 479.5 119.5 C 479.5 153.5 479.5 153.5 472.5 153.761627 C 468.649994 153.905518 461.225006 154.708954 456 155.547028 C 450.774994 156.385132 443.466675 157.966583 439.759277 159.061371 C 436.05188 160.156189 430.343719 162.619598 427.074493 164.535645 C 423.805267 166.451691 419.672913 169.245789 417.891449 170.744781 C 416.110016 172.243774 412.965179 176.08078 410.902954 179.271454 C 408.507751 182.977295 406.493622 187.858795 405.326721 192.786346 C 403.980774 198.469788 403.509888 204.334198 403.537537 215.067841 C 403.560455 223.970093 404.286011 234.276245 405.403107 241.567841 C 406.408508 248.130524 408.366913 258.674988 409.755096 265 C 411.14325 271.325012 412.907196 279.200012 413.674927 282.5 C 414.442657 285.799988 416.815094 297.049988 418.946991 307.5 C 421.078888 317.950012 423.76297 332.401184 424.911591 339.613708 C 426.481873 349.47406 427 357.319122 427 371.235504 C 427 387.630524 426.716309 390.871338 424.515106 399.621765 C 423.148407 405.05481 420.216461 413.182556 417.999634 417.683472 C 415.167511 423.433655 411.734741 428.242035 406.454742 433.854706 C 401.146912 439.496948 395.939392 443.700836 388.720215 448.171234 C 383.099091 451.652039 375.575012 455.78241 372 457.349823 C 368.424988 458.917206 361.261017 461.749329 356.080017 463.643402 C 350.899017 465.537445 342.574005 467.951355 337.580017 469.007568 C 332.585999 470.063812 324 471.644897 318.5 472.521088 C 311.866943 473.57782 299.745911 474.237183 282.5 474.479462 C 268.200012 474.680359 252 474.489349 246.5 474.054932 C 241 473.620544 230.875 472.51828 224 471.605438 C 217.125 470.692596 207.424561 469.276886 202.443451 468.459412 C 197.462357 467.641907 190.037354 466.282959 185.943451 465.439453 C 181.849548 464.595978 176.25 463.281586 173.5 462.518616 C 170.75 461.755646 165.800003 460.43631 162.5 459.586731 C 159.199997 458.737183 152 456.93927 146.5 455.59137 C 141 454.243469 130.649994 451.291107 123.5 449.030579 C 116.349998 446.77002 108.587502 444.226166 106.25 443.377533 C 103.345978 442.323242 102 441.251038 102 439.992004 C 102 438.763947 105.25164 436.022705 111.75 431.772461 C 117.112503 428.265137 124.951981 423.494568 129.171066 421.171265 C 136.842117 416.947052 136.842117 416.947052 147.671066 419.885193 C 153.626984 421.50116 166.824997 424.88266 177 427.399658 C 187.175003 429.916656 200.449997 432.864655 206.5 433.950775 C 212.550003 435.036896 221.550003 436.377319 226.5 436.929504 C 231.449997 437.481689 241.350006 438.46051 248.5 439.104675 C 256.607147 439.835083 270.156616 440.060425 284.5 439.703461 C 297.763824 439.373352 311.521454 438.469299 317 437.56781 C 322.225006 436.708008 331 434.605408 336.5 432.895386 C 342 431.185333 349.424988 428.45224 353 426.821869 C 356.575012 425.191498 361.75 422.78241 364.5 421.468353 C 367.25 420.154297 372.440887 416.632446 376.035309 413.642029 C 379.923035 410.407593 383.626404 406.239136 385.176788 403.352478 C 386.610199 400.683624 388.82962 395.208862 390.108826 391.18631 C 392.043091 385.103973 392.427551 381.771362 392.392365 371.391907 C 392.368134 364.243286 391.617584 354.764648 390.63559 349.205566 C 389.692627 343.867493 388.22879 335.674988 387.382629 331 C 386.536469 326.325012 384.929169 318.225006 383.810822 313 C 382.692505 307.774994 380.661194 299 379.296814 293.5 C 377.932434 288 375.796661 278.774994 374.55069 273 C 373.304718 267.225006 371.555939 258 370.66452 252.5 C 369.773102 247 368.583893 238.419525 368.021881 233.432281 C 367.459839 228.445038 367.007843 219.445038 367.017456 213.432281 C 367.027069 207.419525 367.668945 198.633209 368.443848 193.907166 C 369.21875 189.181091 370.563477 182.881104 371.432129 179.907166 C 372.300781 176.933228 374.471405 171.682648 376.255737 168.239197 C 378.0401 164.795746 381.511963 159.235352 383.971008 155.882751 C 386.430054 152.530182 392.055054 146.895081 396.471008 143.360352 C 400.886963 139.825592 408.100006 135.196167 412.5 133.072693 C 416.899994 130.949249 424.549988 127.878998 429.5 126.249969 C 434.450012 124.620911 444.125 122.492981 451 121.521179 C 457.875 120.549408 467.100006 119.697083 471.5 119.627167 L 479.5 119.5 Z" />\n <path\n id="path2"\n fill="#B6BCC4"\n fill-rule="evenodd"\n stroke="none"\n d="M 116 375.742615 C 113.270905 375.979401 110.6278 374.942505 104 371.035126 C 99.324997 368.278992 92.867485 364.331085 89.649971 362.261993 C 86.432457 360.192871 83.16996 357.284851 82.399971 355.799683 C 81.305717 353.689026 81 347.452454 81 327.240784 C 81 306.114777 81.26738 301.027008 82.460983 299.441132 C 83.890869 297.541321 84.034538 297.562286 89.210983 300.426575 C 92.119942 302.036163 97.425003 305.010712 101 307.036682 C 104.574997 309.062622 110.100868 312.245667 113.279701 314.110107 C 116.458542 315.974548 123.533379 320.200012 129.001572 323.5 C 134.469757 326.799988 142.838348 331.745026 147.59845 334.488953 C 152.358566 337.232849 158.333725 340.837097 160.876587 342.498352 C 163.445404 344.176575 165.630447 346.4263 165.793533 347.560852 C 166.040268 349.277313 162.373489 351.662323 142.793533 362.520905 C 128.02803 370.709534 118.218613 375.55014 116 375.742615 Z" />\n</svg>\n';
17964
+ const iconSubtractSvg = '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path fill-rule="evenodd" clip-rule="evenodd" d="M15.0722 3.9967L20.7508 9.83395L17.0544 13.5304L13.0758 17.5H21.0041V19H7.93503L4.00195 15.0669L15.0722 3.9967ZM10.952 17.5L15.4628 12.9994L11.8268 9.3634L6.12327 15.0669L8.55635 17.5H10.952Z" fill="#1F2328"></path> </g></svg>\n';
17965
+ const iconP2PDrawSvg = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n<!-- Generated by Pixelmator Pro 3.7 -->\n\n<svg\n width="512"\n height="512"\n viewBox="0 0 512 512"\n version="1.1"\n id="svg1"\n sodipodi:docname="icon-p2p-draw.svg"\n inkscape:version="1.4.2 (ebf0e940, 2025-05-08)"\n xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"\n xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"\n xmlns="http://www.w3.org/2000/svg"\n xmlns:svg="http://www.w3.org/2000/svg">\n <defs\n id="defs1" />\n <sodipodi:namedview\n id="namedview1"\n pagecolor="#ffffff"\n bordercolor="#000000"\n borderopacity="0.25"\n inkscape:showpageshadow="2"\n inkscape:pageopacity="0.0"\n inkscape:pagecheckerboard="0"\n inkscape:deskcolor="#d1d1d1"\n inkscape:zoom="0.54892083"\n inkscape:cx="330.64878"\n inkscape:cy="521.93319"\n inkscape:window-width="1200"\n inkscape:window-height="770"\n inkscape:window-x="197"\n inkscape:window-y="106"\n inkscape:window-maximized="0"\n inkscape:current-layer="svg1"\n showguides="true">\n <sodipodi:guide\n position="294.40467,66.478038"\n orientation="0,-1"\n id="guide1"\n inkscape:locked="false" />\n <sodipodi:guide\n position="443.95598,219.9443"\n orientation="1,0"\n id="guide2"\n inkscape:locked="false" />\n <sodipodi:guide\n position="479.19058,322.51614"\n orientation="1,0"\n id="guide3"\n inkscape:locked="false" />\n <sodipodi:guide\n position="292.83869,31.243437"\n orientation="0,-1"\n id="guide4"\n inkscape:locked="false" />\n <sodipodi:guide\n position="263.86802,466.58651"\n orientation="0,-1"\n id="guide5"\n inkscape:locked="false" />\n <sodipodi:guide\n position="261.51904,432.1349"\n orientation="0,-1"\n id="guide6"\n inkscape:locked="false" />\n <sodipodi:guide\n position="32.885628,329.56306"\n orientation="1,0"\n id="guide7"\n inkscape:locked="false" />\n </sodipodi:namedview>\n <path\n style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:35;stroke-dasharray:none;stroke-opacity:1"\n d="m 155.32706,480.61597 323.96204,-0.0328 V 45.207259 L 32.679361,44.8696 32.918466,80.474658 444.02166,79.593154 443.68404,445.58764 274.55795,445.01091 Z"\n id="path7"\n sodipodi:nodetypes="ccccccccc" />\n <circle\n style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:35;stroke-dasharray:none;stroke-opacity:1"\n id="path8"\n cx="460.39642"\n cy="461.54739"\n r="39.133694" />\n <circle\n style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:35;stroke-dasharray:none;stroke-opacity:1"\n id="path8-8"\n cx="460.77478"\n cy="65.833855"\n r="39.133694" />\n <circle\n style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:35;stroke-dasharray:none;stroke-opacity:1"\n id="path8-8-0"\n cx="67.175827"\n cy="62.81522"\n r="39.133694" />\n <path\n id="path2"\n fill="#000000"\n fill-rule="evenodd"\n stroke="none"\n d="m 78.98285,469.62959 c -2.15438,0.59403 -4.66097,-0.18539 -6.41628,-1.99508 -1.75454,-1.80897 -2.51146,-4.39507 -1.93619,-6.61526 0.51947,-2.00492 2.03533,-7.53933 3.36857,-12.29873 1.33325,-4.75939 4.30224,-15.27334 6.59779,-23.36429 2.29555,-8.09095 6.15891,-21.33074 8.58529,-29.42169 2.42637,-8.09095 6.68243,-22.49895 9.45793,-32.01774 2.77548,-9.51878 6.84771,-23.53737 9.04937,-31.15238 2.20168,-7.61501 5.9929,-20.46541 8.42494,-28.55636 2.43204,-8.09095 5.73937,-19.44463 7.34962,-25.23035 1.61019,-5.78571 4.963,-13.27069 7.45058,-16.63326 3.19549,-4.31937 8.82764,-8.13446 19.19001,-12.99886 8.06689,-3.78683 22.22096,-10.28684 31.45345,-14.44449 9.23249,-4.15765 20.18557,-9.15989 24.34021,-11.11606 4.15463,-1.95616 10.95307,-5.04935 15.10771,-6.87384 4.15464,-1.82444 8.50009,-4.18148 9.65667,-5.23786 1.67549,-1.53041 1.53724,-3.40502 -0.68062,-9.22612 -2.27058,-5.95966 -2.43594,-8.49812 -0.89757,-13.77907 1.22082,-4.19103 5.93592,-10.61436 13.37263,-18.21733 6.77176,-6.92313 13.88209,-12.5016 17.32193,-13.59009 4.56226,-1.44363 7.10301,-1.27942 11.64815,0.75263 3.42626,1.5319 23.38864,20.75839 48.61827,46.82593 23.54283,24.3248 45.07136,47.06101 47.84109,50.52486 3.87236,4.84285 5.0359,8.02217 5.0359,13.76037 0,6.66353 -0.98839,8.54701 -9.23249,17.59373 -5.07785,5.57218 -11.80914,12.26634 -14.95838,14.87589 -4.16093,3.44791 -7.61435,4.74461 -12.63592,4.74461 -3.8005,0 -8.65254,-1.25835 -10.78224,-2.79631 -2.1797,-1.57404 -4.50585,-2.14145 -5.3218,-1.29801 -0.79727,0.82403 -5.18683,10.45458 -9.75461,21.4012 -4.56774,10.94662 -11.46849,27.28897 -15.33492,36.3164 -3.86636,9.02739 -10.0263,22.88636 -13.68865,30.79773 -4.61767,9.97496 -8.2174,15.36144 -11.7432,17.57213 -2.79644,1.75334 -10.87912,5.15636 -17.96148,7.56231 -7.0824,2.40588 -20.43095,6.74835 -29.66344,9.64992 -9.2325,2.90152 -25.66143,8.03285 -36.50872,11.40295 -10.8473,3.37012 -31.2427,9.76063 -45.32314,14.20118 -14.08045,4.4406 -32.77692,10.28616 -41.54781,12.9901 -8.77088,2.70399 -17.53807,5.35501 -19.48265,5.89124 z m 33.10612,-25.66048 c 3.12446,-0.52416 14.55766,-3.75462 25.40714,-7.17876 10.84946,-3.4242 33.51103,-10.53042 50.35905,-15.79168 16.84799,-5.2612 39.69735,-12.37246 50.77636,-15.80282 14.11491,-4.3703 21.4678,-7.59596 24.56816,-10.77783 2.43353,-2.49749 8.0037,-13.10782 12.3782,-23.57846 4.37444,-10.47065 10.39747,-24.87865 13.3844,-32.01773 2.98694,-7.13909 8.32653,-19.60006 11.86571,-27.69101 3.53919,-8.09095 6.70998,-17.0473 7.04619,-19.90292 0.55531,-4.71704 -2.16136,-8.0423 -29.69233,-36.34445 -16.66695,-17.1338 -31.77968,-31.39614 -33.58378,-31.69408 -1.80414,-0.29788 -24.6359,9.2685 -50.73726,21.25867 -26.10136,11.99017 -49.09048,23.38251 -51.08698,25.31628 -1.99652,1.93377 -4.8623,7.74509 -6.36841,12.91403 -1.50609,5.16898 -4.69492,16.21648 -7.08629,24.55002 -2.39131,8.33358 -6.53304,22.55059 -9.20379,31.59346 -2.67075,9.04286 -9.07606,30.84953 -14.23398,48.45926 -5.15796,17.60974 -10.02791,34.72173 -10.82216,38.02655 -0.79426,3.30483 -1.1287,6.33395 -0.7432,6.73146 0.38545,0.39738 3.17643,-1.23918 6.20211,-3.63684 3.02568,-2.39771 17.96511,-17.53251 33.19873,-33.63296 15.23362,-16.1004 31.64089,-33.57371 36.46062,-38.82946 8.52144,-9.29247 8.71621,-9.73111 7.06247,-15.9062 -1.16333,-4.34377 -1.14253,-8.48706 0.0656,-13.11331 1.09469,-4.19134 4.27547,-9.10021 8.36474,-12.90922 3.64809,-3.39805 9.2643,-6.66174 12.56077,-7.29928 4.51031,-0.87242 7.90041,-0.1587 13.9207,2.93089 4.84417,2.48596 9.2219,6.36014 11.18725,9.90054 1.77588,3.19904 3.29934,9.20131 3.38545,13.33846 0.0891,4.28531 -1.16789,10.05847 -2.92143,13.41647 -1.69287,3.24193 -6.10927,7.65094 -9.81417,9.79783 -5.66863,3.2847 -8.24032,3.72914 -16.22634,2.80428 -9.49006,-1.09911 -9.49006,-1.09911 -49.7773,40.47775 -22.15799,22.86729 -40.57747,42.46953 -40.93217,43.56045 -0.43839,1.34819 1.17468,1.67829 5.03591,1.03061 z m 90.33008,-98.22453 c 3.35455,0 6.05979,-1.50174 8.52436,-4.73208 2.60114,-3.40941 3.33739,-6.13886 2.63399,-9.76503 -0.53698,-2.76815 -2.29563,-6.0656 -3.90813,-7.32768 -1.61249,-1.26211 -5.13852,-2.31954 -7.83556,-2.34981 -2.69703,-0.0303 -6.28515,1.23389 -7.97352,2.80925 -1.80844,1.68737 -3.06977,5.24293 -3.06977,8.65344 0,3.48156 1.33823,7.16888 3.35727,9.25053 1.84652,1.90378 5.56862,3.46138 8.27136,3.46138 z m 133.61012,-53.65133 c 1.97597,0 7.95481,-4.72004 14.17476,-11.19037 10.06607,-10.47129 10.6202,-11.45446 8.62363,-15.30071 -1.17346,-2.26069 -22.06639,-24.65026 -46.42867,-49.7546 -28.88352,-29.76325 -45.48253,-45.6442 -47.70791,-45.6442 -1.91767,0 -7.85057,4.5222 -13.54224,10.32229 -7.35863,7.49881 -9.99677,11.39096 -9.64468,14.22899 0.30251,2.43813 17.51825,21.46819 45.79618,50.62263 29.62007,30.53813 46.49498,46.71597 48.72893,46.71597 z"\n style="stroke:#010101;stroke-width:17.0446;stroke-dasharray:none;stroke-opacity:1" />\n <path\n style="fill:#008000;fill-opacity:1;stroke:none;stroke-width:18.6862;stroke-dasharray:none;stroke-opacity:1"\n d="m 243.54683,189.37604 16.45863,-15.44233 96.74466,96.71773 -16.45865,16.25509 z"\n id="path3" />\n <circle\n style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:35;stroke-dasharray:none;stroke-opacity:1"\n id="path9"\n cx="201.17783"\n cy="332.21527"\n r="13.593097" />\n</svg>\n';
17966
+ const iconEraseSvg = '<?xml version="1.0" encoding="utf-8"?>\n<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"\n viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">\n<style type="text/css">\n .st0{fill:#000000}\n .st1{fill:#333333;fill-opacity:0;}\n</style>\n<title>trash</title>\n<rect class="st1" width="48" height="48"/>\n<polygon class="st0" points="26.6,10 26.6,7.8 21.4,7.8 21.4,10 12.6,10 12.6,12.8 35.4,12.8 35.4,10 "/>\n<path class="st0" d="M35.4,15.4H12.6v4.3h1.8V37c0,1.1,0.9,2,2,2h15.2c1.1,0,2-0.9,2-2V19.7h1.8V15.4z M19.7,34.2c0,0.5-0.4,1-1,1\n c-0.5,0-1-0.4-1-1V22.6c0-0.5,0.4-1,1-1c0.5,0,1,0.4,1,1V34.2z M25.3,33.8c0,0.7-0.6,1.3-1.3,1.3c-0.7,0-1.3-0.6-1.3-1.3V23\n c0-0.7,0.6-1.3,1.3-1.3c0.7,0,1.3,0.6,1.3,1.3V33.8z M30.3,34.2c0,0.5-0.4,1-1,1c-0.5,0-1-0.4-1-1V22.6c0-0.5,0.4-1,1-1\n c0.5,0,1,0.4,1,1V34.2z"/>\n</svg>\n';
17967
+ const iconCollapseSvg = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n<!-- Generated by Pixelmator Pro 3.7 -->\n\n<svg\n width="512"\n height="512"\n viewBox="0 0 512 512"\n version="1.1"\n id="svg1"\n sodipodi:docname="icon-collapse.svg"\n inkscape:version="1.4.2 (ebf0e940, 2025-05-08)"\n xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"\n xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"\n xmlns="http://www.w3.org/2000/svg"\n xmlns:svg="http://www.w3.org/2000/svg">\n <defs\n id="defs1" />\n <sodipodi:namedview\n id="namedview1"\n pagecolor="#ffffff"\n bordercolor="#000000"\n borderopacity="0.25"\n inkscape:showpageshadow="2"\n inkscape:pageopacity="0.0"\n inkscape:pagecheckerboard="0"\n inkscape:deskcolor="#d1d1d1"\n inkscape:zoom="3.390154"\n inkscape:cx="264.14729"\n inkscape:cy="179.04791"\n inkscape:window-width="1352"\n inkscape:window-height="797"\n inkscape:window-x="66"\n inkscape:window-y="34"\n inkscape:window-maximized="0"\n inkscape:current-layer="svg1"\n showguides="true">\n <sodipodi:guide\n position="166.90161,256"\n orientation="0,1"\n id="guide2"\n inkscape:locked="false"\n inkscape:label=""\n inkscape:color="rgb(0,134,229)" />\n <sodipodi:guide\n position="256,314.14084"\n orientation="-1,0"\n id="guide3"\n inkscape:locked="false"\n inkscape:label=""\n inkscape:color="rgb(0,134,229)" />\n <sodipodi:guide\n position="299.13272,431.6881"\n orientation="0,-1"\n id="guide4"\n inkscape:locked="false" />\n <sodipodi:guide\n position="80,297.83494"\n orientation="-1,0"\n id="guide5"\n inkscape:locked="false"\n inkscape:label=""\n inkscape:color="rgb(0,134,229)" />\n <sodipodi:guide\n position="432,400.26171"\n orientation="-1,0"\n id="guide6"\n inkscape:locked="false"\n inkscape:label=""\n inkscape:color="rgb(0,134,229)" />\n </sodipodi:namedview>\n <path\n style="fill:none;stroke:#000000;stroke-width:25;stroke-dasharray:none;stroke-opacity:1"\n d="M 80.032872,292.14907 255.78789,117.55799 431.54291,292.14907 v 0 0"\n id="path6" />\n <path\n style="fill:none;stroke:#000000;stroke-width:25;stroke-dasharray:none;stroke-opacity:1"\n d="M 80.104821,394.53856 255.85984,219.94748 431.61486,394.53856 v 0 0"\n id="path6-5" />\n</svg>\n';
17968
+ const sanitizeSvg = (svg) => svg.replace(/<\?xml[^>]*\?>\s*/g, "").replace(/<!--[\s\S]*?-->/g, "").trim();
17969
+ const icons = {
17970
+ activate: sanitizeSvg(iconPolydraw2Svg),
17971
+ draw: sanitizeSvg(iconDrawSvg),
17972
+ subtract: sanitizeSvg(iconSubtractSvg),
17973
+ p2p: sanitizeSvg(iconP2PDrawSvg),
17974
+ p2pSubtract: sanitizeSvg(iconP2PSubtractSvg),
17975
+ erase: sanitizeSvg(iconEraseSvg),
17976
+ collapse: sanitizeSvg(iconCollapseSvg)
17977
+ };
17978
+ const setButtonIcon = (button, svgMarkup) => {
17979
+ button.innerHTML = svgMarkup;
17980
+ const svgElement = button.querySelector("svg");
17981
+ if (!svgElement) return;
17982
+ svgElement.setAttribute("width", "24");
17983
+ svgElement.setAttribute("height", "24");
17984
+ svgElement.style.pointerEvents = "none";
17985
+ svgElement.querySelectorAll("*").forEach((el) => {
17986
+ el.style.pointerEvents = "none";
17987
+ });
17988
+ };
17989
+ function createButtons(container, subContainer, config, onActivateToggle, onDrawClick, onSubtractClick, onEraseClick, onPointToPointClick, onPointToPointSubtractClick) {
17757
17990
  const activate = leafletAdapter.domUtil.create(
17758
17991
  "a",
17759
17992
  "icon-activate",
@@ -17761,7 +17994,9 @@ function createButtons(container, subContainer, config, onActivateToggle, onDraw
17761
17994
  );
17762
17995
  activate.href = "#";
17763
17996
  activate.title = "Activate";
17764
- activate.innerHTML = '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path d="M5 17V7M5 17C3.89543 17 3 17.8954 3 19C3 20.1046 3.89543 21 5 21C6.10457 21 7 20.1046 7 19M5 17C6.10457 17 7 17.8954 7 19M5 7C6.10457 7 7 6.10457 7 5M5 7C3.89543 7 3 6.10457 3 5C3 3.89543 3.89543 3 5 3C6.10457 3 7 3.89543 7 5M7 5H17M17 5C17 6.10457 17.8954 7 19 7C20.1046 7 21 6.10457 21 5C21 3.89543 20.1046 3 19 3C17.8954 3 17 3.89543 17 5ZM7 19H17M17 19C17 20.1046 17.8954 21 19 21C20.1046 21 21 20.1046 21 19C21 17.8954 20.1046 17 19 17C17.8954 17 17 17.8954 17 19ZM17.9247 6.6737L15.1955 10.3776M15.1955 13.6223L17.9222 17.3223M16 12C16 13.1046 15.1046 14 14 14C12.8954 14 12 13.1046 12 12C12 10.8954 12.8954 10 14 10C15.1046 10 16 10.8954 16 12Z" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path> </g></svg>';
17997
+ setButtonIcon(activate, icons.activate);
17998
+ activate.dataset.activeIcon = icons.activate;
17999
+ activate.dataset.collapsedIcon = icons.collapse;
17765
18000
  L$1.DomEvent.on(activate, "mousedown", L$1.DomEvent.stopPropagation);
17766
18001
  L$1.DomEvent.on(activate, "touchstart", L$1.DomEvent.stopPropagation);
17767
18002
  L$1.DomEvent.on(activate, "click", L$1.DomEvent.stop).on(activate, "click", onActivateToggle);
@@ -17769,10 +18004,12 @@ function createButtons(container, subContainer, config, onActivateToggle, onDraw
17769
18004
  const draw = leafletAdapter.domUtil.create("a", "icon-draw", subContainer);
17770
18005
  draw.href = "#";
17771
18006
  draw.title = "Draw";
17772
- draw.innerHTML = '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path d="M15 7.49996L17.5 9.99996M7.5 20L19.25 8.24996C19.9404 7.5596 19.9404 6.44032 19.25 5.74996V5.74996C18.5596 5.0596 17.4404 5.05961 16.75 5.74996L5 17.5V20H7.5ZM7.5 20H15.8787C17.0503 20 18 19.0502 18 17.8786V17.8786C18 17.316 17.7765 16.7765 17.3787 16.3786L17 16M4.5 4.99996C6.5 2.99996 10 3.99996 10 5.99996C10 8.5 4 8.5 4 11C4 11.8759 4.53314 12.5256 5.22583 13" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path> </g></svg>';
18007
+ setButtonIcon(draw, icons.draw);
17773
18008
  L$1.DomEvent.on(draw, "mousedown", L$1.DomEvent.stopPropagation);
17774
18009
  L$1.DomEvent.on(draw, "touchstart", L$1.DomEvent.stopPropagation);
17775
- L$1.DomEvent.on(draw, "click", L$1.DomEvent.stop).on(draw, "click", onDrawClick);
18010
+ L$1.DomEvent.on(draw, "click", L$1.DomEvent.stopPropagation);
18011
+ L$1.DomEvent.on(draw, "click", L$1.DomEvent.stop);
18012
+ L$1.DomEvent.on(draw, "click", onDrawClick);
17776
18013
  }
17777
18014
  if (config.modes.subtract) {
17778
18015
  const subtract = leafletAdapter.domUtil.create(
@@ -17782,19 +18019,38 @@ function createButtons(container, subContainer, config, onActivateToggle, onDraw
17782
18019
  );
17783
18020
  subtract.href = "#";
17784
18021
  subtract.title = "Subtract";
17785
- subtract.innerHTML = '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path fill-rule="evenodd" clip-rule="evenodd" d="M15.0722 3.9967L20.7508 9.83395L17.0544 13.5304L13.0758 17.5H21.0041V19H7.93503L4.00195 15.0669L15.0722 3.9967ZM10.952 17.5L15.4628 12.9994L11.8268 9.3634L6.12327 15.0669L8.55635 17.5H10.952Z" fill="#1F2328"></path> </g></svg>';
18022
+ setButtonIcon(subtract, icons.subtract);
17786
18023
  L$1.DomEvent.on(subtract, "mousedown", L$1.DomEvent.stopPropagation);
17787
18024
  L$1.DomEvent.on(subtract, "touchstart", L$1.DomEvent.stopPropagation);
17788
- L$1.DomEvent.on(subtract, "click", L$1.DomEvent.stop).on(subtract, "click", onSubtractClick);
18025
+ L$1.DomEvent.on(subtract, "click", L$1.DomEvent.stopPropagation);
18026
+ L$1.DomEvent.on(subtract, "click", L$1.DomEvent.stop);
18027
+ L$1.DomEvent.on(subtract, "click", onSubtractClick);
17789
18028
  }
17790
18029
  if (config.modes.p2p) {
17791
18030
  const p2p = leafletAdapter.domUtil.create("a", "icon-p2p", subContainer);
17792
18031
  p2p.href = "#";
17793
18032
  p2p.title = "Point to Point";
17794
- p2p.innerHTML = '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path d="M5 17V7M5 17C3.89543 17 3 17.8954 3 19C3 20.1046 3.89543 21 5 21C6.10457 21 7 20.1046 7 19M5 17C6.10457 17 7 17.8954 7 19M5 7C6.10457 7 7 6.10457 7 5M5 7C3.89543 7 3 6.10457 3 5C3 3.89543 3.89543 3 5 3C6.10457 3 7 3.89543 7 5M7 5H17M17 5C17 6.10457 17.8954 7 19 7C20.1046 7 21 6.10457 21 5C21 3.89543 20.1046 3 19 3C17.8954 3 17 3.89543 17 5ZM7 19H17M17 19C17 20.1046 17.8954 21 19 21C20.1046 21 21 20.1046 21 19C21 17.8954 20.1046 17 19 17C17.8954 17 17 17.8954 17 19ZM17.9247 6.6737L15.1955 10.3776M15.1955 13.6223L17.9222 17.3223M16 12C16 13.1046 15.1046 14 14 14C12.8954 14 12 13.1046 12 12C12 10.8954 12.8954 10 14 10C15.1046 10 16 10.8954 16 12Z" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path> </g></svg>';
18033
+ setButtonIcon(p2p, icons.p2p);
17795
18034
  L$1.DomEvent.on(p2p, "mousedown", L$1.DomEvent.stopPropagation);
17796
18035
  L$1.DomEvent.on(p2p, "touchstart", L$1.DomEvent.stopPropagation);
17797
- L$1.DomEvent.on(p2p, "click", L$1.DomEvent.stop).on(p2p, "click", onPointToPointClick);
18036
+ L$1.DomEvent.on(p2p, "click", L$1.DomEvent.stopPropagation);
18037
+ L$1.DomEvent.on(p2p, "click", L$1.DomEvent.stop);
18038
+ L$1.DomEvent.on(p2p, "click", onPointToPointClick);
18039
+ }
18040
+ if (config.modes.p2pSubtract) {
18041
+ const p2pSubtract = leafletAdapter.domUtil.create(
18042
+ "a",
18043
+ "icon-p2p-subtract",
18044
+ subContainer
18045
+ );
18046
+ p2pSubtract.href = "#";
18047
+ p2pSubtract.title = "Point to Point Subtract";
18048
+ setButtonIcon(p2pSubtract, icons.p2pSubtract);
18049
+ L$1.DomEvent.on(p2pSubtract, "mousedown", L$1.DomEvent.stopPropagation);
18050
+ L$1.DomEvent.on(p2pSubtract, "touchstart", L$1.DomEvent.stopPropagation);
18051
+ L$1.DomEvent.on(p2pSubtract, "click", L$1.DomEvent.stopPropagation);
18052
+ L$1.DomEvent.on(p2pSubtract, "click", L$1.DomEvent.stop);
18053
+ L$1.DomEvent.on(p2pSubtract, "click", onPointToPointSubtractClick);
17798
18054
  }
17799
18055
  if (config.modes.deleteAll) {
17800
18056
  const erase = leafletAdapter.domUtil.create(
@@ -17804,25 +18060,12 @@ function createButtons(container, subContainer, config, onActivateToggle, onDraw
17804
18060
  );
17805
18061
  erase.href = "#";
17806
18062
  erase.title = "Erase All";
17807
- erase.innerHTML = `<?xml version="1.0" encoding="utf-8"?>
17808
- <!-- Generator: Adobe Illustrator 21.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
17809
- <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
17810
- viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
17811
- <style type="text/css">
17812
- .st0{fill:#000000}
17813
- .st1{fill:#333333;fill-opacity:0;}
17814
- </style>
17815
- <title>trash</title>
17816
- <rect class="st1" width="48" height="48"/>
17817
- <polygon class="st0" points="26.6,10 26.6,7.8 21.4,7.8 21.4,10 12.6,10 12.6,12.8 35.4,12.8 35.4,10 "/>
17818
- <path class="st0" d="M35.4,15.4H12.6v4.3h1.8V37c0,1.1,0.9,2,2,2h15.2c1.1,0,2-0.9,2-2V19.7h1.8V15.4z M19.7,34.2c0,0.5-0.4,1-1,1
17819
- c-0.5,0-1-0.4-1-1V22.6c0-0.5,0.4-1,1-1c0.5,0,1,0.4,1,1V34.2z M25.3,33.8c0,0.7-0.6,1.3-1.3,1.3c-0.7,0-1.3-0.6-1.3-1.3V23
17820
- c0-0.7,0.6-1.3,1.3-1.3c0.7,0,1.3,0.6,1.3,1.3V33.8z M30.3,34.2c0,0.5-0.4,1-1,1c-0.5,0-1-0.4-1-1V22.6c0-0.5,0.4-1,1-1
17821
- c0.5,0,1,0.4,1,1V34.2z"/>
17822
- </svg>`;
18063
+ setButtonIcon(erase, icons.erase);
17823
18064
  L$1.DomEvent.on(erase, "mousedown", L$1.DomEvent.stopPropagation);
17824
18065
  L$1.DomEvent.on(erase, "touchstart", L$1.DomEvent.stopPropagation);
17825
- L$1.DomEvent.on(erase, "click", L$1.DomEvent.stop).on(erase, "click", onEraseClick);
18066
+ L$1.DomEvent.on(erase, "click", L$1.DomEvent.stopPropagation);
18067
+ L$1.DomEvent.on(erase, "click", L$1.DomEvent.stop);
18068
+ L$1.DomEvent.on(erase, "click", onEraseClick);
17826
18069
  }
17827
18070
  }
17828
18071
  class PolygonUtil {
@@ -17938,6 +18181,60 @@ class PolygonUtil {
17938
18181
  lng: centerOfMass2.geometry.coordinates[0]
17939
18182
  };
17940
18183
  }
18184
+ static getCenterOfPolygonByIndexWithOffsetFromCenterOfMass(polygon2, index) {
18185
+ const centerOfMass2 = this.turfHelper.getCenterOfMass(polygon2);
18186
+ const centerLatLng = {
18187
+ lat: centerOfMass2.geometry.coordinates[1],
18188
+ lng: centerOfMass2.geometry.coordinates[0]
18189
+ };
18190
+ const centerOfPolygonMarker = this.getPolygonLatLngAtIndex(polygon2, index) ?? centerLatLng;
18191
+ const offset = {
18192
+ lat: centerOfPolygonMarker.lat - centerLatLng.lat,
18193
+ lng: centerOfPolygonMarker.lng - centerLatLng.lng
18194
+ };
18195
+ const offsetFraction = 0.5;
18196
+ const adjustedLat = centerLatLng.lat + offset.lat * offsetFraction;
18197
+ const adjustedLng = centerLatLng.lng + offset.lng * offsetFraction;
18198
+ const newCenterOfMass = {
18199
+ geometry: {
18200
+ coordinates: [adjustedLng, adjustedLat]
18201
+ }
18202
+ };
18203
+ return {
18204
+ lat: newCenterOfMass.geometry.coordinates[1],
18205
+ lng: newCenterOfMass.geometry.coordinates[0]
18206
+ };
18207
+ }
18208
+ static getPolygonLatLngAtIndex(polygon2, index) {
18209
+ const geometry = polygon2.geometry;
18210
+ if (!geometry) {
18211
+ return null;
18212
+ }
18213
+ let coordinates;
18214
+ if (geometry.type === "Polygon") {
18215
+ coordinates = geometry.coordinates[0];
18216
+ } else if (geometry.type === "MultiPolygon") {
18217
+ coordinates = geometry.coordinates[0][0];
18218
+ } else {
18219
+ return null;
18220
+ }
18221
+ if (!coordinates || coordinates.length === 0) {
18222
+ return null;
18223
+ }
18224
+ if (coordinates.length > 1) {
18225
+ const first = coordinates[0];
18226
+ const last = coordinates[coordinates.length - 1];
18227
+ if (first[0] === last[0] && first[1] === last[1]) {
18228
+ coordinates = coordinates.slice(0, coordinates.length - 1);
18229
+ }
18230
+ }
18231
+ if (coordinates.length === 0) {
18232
+ return null;
18233
+ }
18234
+ const normalizedIndex = (index % coordinates.length + coordinates.length) % coordinates.length;
18235
+ const selected = coordinates[normalizedIndex];
18236
+ return { lat: selected[1], lng: selected[0] };
18237
+ }
17941
18238
  }
17942
18239
  __publicField(PolygonUtil, "turfHelper", new TurfHelper(defaultConfig));
17943
18240
  class PolygonInfo {
@@ -18246,6 +18543,7 @@ class ModeManager {
18246
18543
  this.setDrawingModeState();
18247
18544
  break;
18248
18545
  case DrawMode.PointToPoint:
18546
+ case DrawMode.PointToPointSubtract:
18249
18547
  this.setPointToPointModeState();
18250
18548
  break;
18251
18549
  }
@@ -18538,7 +18836,7 @@ class PolygonDrawManager {
18538
18836
  * Handle double-click to complete point-to-point polygon
18539
18837
  */
18540
18838
  handleDoubleClick(e) {
18541
- if (this.modeManager.getCurrentMode() !== DrawMode.PointToPoint) {
18839
+ if (this.modeManager.getCurrentMode() !== DrawMode.PointToPoint && this.modeManager.getCurrentMode() !== DrawMode.PointToPointSubtract) {
18542
18840
  return;
18543
18841
  }
18544
18842
  if (this.p2pMarkers.length >= 3) {
@@ -18549,7 +18847,7 @@ class PolygonDrawManager {
18549
18847
  * Handle double-tap to complete point-to-point polygon (touch devices)
18550
18848
  */
18551
18849
  handleDoubleTap(_e) {
18552
- if (this.modeManager.getCurrentMode() !== DrawMode.PointToPoint) {
18850
+ if (this.modeManager.getCurrentMode() !== DrawMode.PointToPoint && this.modeManager.getCurrentMode() !== DrawMode.PointToPointSubtract) {
18553
18851
  return;
18554
18852
  }
18555
18853
  if (this.p2pMarkers.length >= 3) {
@@ -18577,7 +18875,7 @@ class PolygonDrawManager {
18577
18875
  this.resetTracer();
18578
18876
  this.eventManager.emit("polydraw:polygon:created", {
18579
18877
  polygon: geoPos,
18580
- mode: DrawMode.PointToPoint,
18878
+ mode: this.modeManager.getCurrentMode(),
18581
18879
  isPointToPoint: true
18582
18880
  });
18583
18881
  } catch (error) {
@@ -18628,6 +18926,7 @@ class PolygonDrawManager {
18628
18926
  if (this.isTouchDevice()) {
18629
18927
  tolerance *= 5;
18630
18928
  }
18929
+ tolerance *= 3;
18631
18930
  const latDiff = Math.abs(clickLatLng.lat - firstPoint.lat);
18632
18931
  const lngDiff = Math.abs(clickLatLng.lng - firstPoint.lng);
18633
18932
  const isClicking = latDiff < tolerance && lngDiff < tolerance;
@@ -18647,8 +18946,10 @@ class PolygonDrawManager {
18647
18946
  this.tracer.setLatLngs(latlngs);
18648
18947
  if (this.p2pMarkers.length >= 2) {
18649
18948
  try {
18949
+ const currentMode = this.modeManager.getCurrentMode();
18950
+ const lineColor = currentMode === DrawMode.PointToPointSubtract ? this.config.colors.subtractLine : this.config.colors.polyline;
18650
18951
  this.tracer.setStyle({
18651
- color: this.config.colors.polyline,
18952
+ color: lineColor,
18652
18953
  dashArray: "5, 5"
18653
18954
  });
18654
18955
  } catch (error) {
@@ -18686,7 +18987,8 @@ class PolygonDrawManager {
18686
18987
  * Check if currently in point-to-point drawing mode
18687
18988
  */
18688
18989
  isInPointToPointMode() {
18689
- return this.modeManager.getCurrentMode() === DrawMode.PointToPoint;
18990
+ const mode = this.modeManager.getCurrentMode();
18991
+ return mode === DrawMode.PointToPoint || mode === DrawMode.PointToPointSubtract;
18690
18992
  }
18691
18993
  /**
18692
18994
  * Get current tracer points count
@@ -19107,6 +19409,687 @@ class IconFactory {
19107
19409
  return leafletAdapter.createDivIcon({ className: classes });
19108
19410
  }
19109
19411
  }
19412
+ var TransformHandleType = /* @__PURE__ */ ((TransformHandleType2) => {
19413
+ TransformHandleType2["TopLeft"] = "top-left";
19414
+ TransformHandleType2["Top"] = "top";
19415
+ TransformHandleType2["TopRight"] = "top-right";
19416
+ TransformHandleType2["Right"] = "right";
19417
+ TransformHandleType2["BottomRight"] = "bottom-right";
19418
+ TransformHandleType2["Bottom"] = "bottom";
19419
+ TransformHandleType2["BottomLeft"] = "bottom-left";
19420
+ TransformHandleType2["Left"] = "left";
19421
+ TransformHandleType2["Rotate"] = "rotate";
19422
+ TransformHandleType2["Pivot"] = "pivot";
19423
+ return TransformHandleType2;
19424
+ })(TransformHandleType || {});
19425
+ const cancelIconSvg = '<?xml version="1.0" encoding="UTF-8"?>\n<svg width="512" height="512" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">\n <circle cx="256" cy="256" r="236" fill="#212A32"/>\n <circle cx="256" cy="256" r="190" fill="#ffffff"/>\n <path id="path2" fill="#800000" fill-rule="evenodd" stroke="none"\n d="M 156 373.906311 C 140.875 373.871002 127.9375 373.615112 127.25 373.337708 C 126.5625 373.060303 126 372.072937 126 371.143555 C 126 370.214203 146.628433 343.53772 171.840973 311.862488 C 197.053513 280.187286 217.991867 253.463562 218.370667 252.47644 C 218.806335 251.341125 218.221786 249.464233 216.779678 247.368073 C 215.525864 245.545563 196.612503 221.361847 174.75 193.626465 C 152.887497 165.891052 135 142.531311 135 141.715881 C 135 140.900421 136.012497 139.961914 137.25 139.63028 C 138.487503 139.298645 152.408203 139.021179 168.184906 139.013641 C 184.588272 139.005859 197.976456 139.420746 199.454529 139.982727 C 201.182831 140.639801 210.486664 152.319733 227.533463 175.232727 C 241.555283 194.079712 253.994949 210.166199 255.177185 210.980438 C 257.208252 212.379272 257.562622 212.186401 261.607452 207.480438 C 263.961853 204.74118 276.052643 189 288.47583 172.5 C 300.899048 156 312.286682 141.714874 313.781738 140.75528 C 316.198669 139.203949 319.554993 139.009949 344.058868 139.00528 C 366.27774 139.001007 371.993561 139.274811 373.557343 140.418274 C 375.458923 141.808746 375.448914 141.90155 373.046875 145.150452 C 371.699341 146.973114 352.828827 170.746307 331.112396 197.979767 C 309.395966 225.213257 291.465973 248.396271 291.267914 249.497589 C 291.012512 250.91803 304.435944 268.61731 337.453918 310.395416 C 363.05426 342.787903 384 370.077271 384 371.038422 C 384 371.999603 383.288208 373.059174 382.418213 373.393005 C 381.548218 373.726868 367.485718 373.993347 351.168213 373.98526 C 329.591888 373.974548 320.854309 373.633606 319.132629 372.73526 C 317.830597 372.055847 302.980591 353.049988 286.132629 330.5 C 260.059052 295.602051 255.12793 289.5 253 289.5 C 250.878326 289.5 245.808807 295.701355 219.5 330.479431 C 202.449997 353.018127 187.375 372.023987 186 372.714691 C 184.165009 373.636475 176.184906 373.95343 156 373.906311 Z"/>\n</svg>';
19426
+ const confirmIconSvg = '<?xml version="1.0" encoding="UTF-8"?>\n<svg width="512" height="512" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">\n <circle cx="256" cy="256" r="236" fill="#212A32"/>\n <circle cx="256" cy="256" r="190" fill="#ffffff"/>\n <path id="check" fill="#008000" fill-rule="evenodd" stroke="none"\n d="M 223.844696 360 C 222.79425 360 204.506973 341.170593 178.987274 313.812744 \n C 144.992401 277.369232 135.966232 267.145691 136.201645 265.351257 \n C 136.396179 263.868408 143.092361 257.073425 155.444672 245.824249 \n C 166.363129 235.880859 175.214264 228.571442 176.336426 228.571442 \n C 177.515594 228.571442 181.716553 232.304138 186.987961 238.035706 \n C 191.775406 243.241058 201.629044 254.024994 208.884933 262 \n C 216.140823 269.975006 222.682266 276.635315 223.421478 276.80072 \n C 224.16246 276.966553 247.742722 250.494751 275.976837 217.800751 \n C 304.143097 185.185333 328.050385 157.879608 329.104156 157.121368 \n C 330.785767 155.911316 331.44046 156.0336 334.457672 158.121368 \n C 336.348328 159.429626 345.368622 167.190216 354.502747 175.367126 \n C 367.688812 187.171356 371.047394 190.689819 370.805115 192.445557 \n C 370.635864 193.67218 338.242889 231.469543 298.059082 277.32843 \n C 253.148834 328.581238 224.944153 360 223.844696 360 Z"/>\n</svg>';
19427
+ class TransformOverlay {
19428
+ constructor(map, callbacks, mode, onCancel, onConfirm) {
19429
+ __publicField(this, "map");
19430
+ __publicField(this, "pane");
19431
+ __publicField(this, "root");
19432
+ __publicField(this, "draggingHandle", null);
19433
+ __publicField(this, "callbacks");
19434
+ __publicField(this, "rafId", null);
19435
+ __publicField(this, "mode");
19436
+ __publicField(this, "onCancel");
19437
+ __publicField(this, "onConfirm");
19438
+ __publicField(this, "cancelBtn", null);
19439
+ __publicField(this, "confirmBtn", null);
19440
+ __publicField(this, "currentBBox", null);
19441
+ __publicField(this, "currentRotation", 0);
19442
+ this.map = map;
19443
+ this.callbacks = callbacks;
19444
+ this.mode = mode;
19445
+ this.onCancel = onCancel;
19446
+ this.onConfirm = onConfirm;
19447
+ const paneName = "polydraw-transform";
19448
+ let pane = this.map.getPane ? this.map.getPane(paneName) : void 0;
19449
+ if (!pane) pane = this.map.createPane(paneName);
19450
+ pane.style.zIndex = "650";
19451
+ pane.style.pointerEvents = "none";
19452
+ this.pane = pane;
19453
+ this.root = document.createElement("div");
19454
+ this.root.className = "polydraw-transform-root";
19455
+ this.root.style.position = "absolute";
19456
+ this.root.style.left = "0px";
19457
+ this.root.style.top = "0px";
19458
+ this.pane.appendChild(this.root);
19459
+ }
19460
+ destroy() {
19461
+ if (this.rafId != null) {
19462
+ cancelAnimationFrame(this.rafId);
19463
+ this.rafId = null;
19464
+ }
19465
+ this.root.remove();
19466
+ }
19467
+ update(bbox2, pivot, rotation = 0) {
19468
+ if (this.rafId != null) return;
19469
+ this.rafId = requestAnimationFrame(() => {
19470
+ this.rafId = null;
19471
+ this.render(bbox2, pivot, rotation);
19472
+ if (this.cancelBtn || this.confirmBtn) {
19473
+ const isRotateDrag = this.draggingHandle === TransformHandleType.Rotate && this.mode === "rotate";
19474
+ if (!isRotateDrag) {
19475
+ this.updateButtonPositions(bbox2, rotation);
19476
+ }
19477
+ }
19478
+ });
19479
+ }
19480
+ render(bbox2, _pivot, rotation = 0) {
19481
+ const cancelBtn = this.cancelBtn;
19482
+ const confirmBtn = this.confirmBtn;
19483
+ this.root.innerHTML = "";
19484
+ this.currentBBox = bbox2;
19485
+ this.currentRotation = rotation;
19486
+ this.cancelBtn = cancelBtn;
19487
+ this.confirmBtn = confirmBtn;
19488
+ const width = bbox2.maxX - bbox2.minX;
19489
+ const height = bbox2.maxY - bbox2.minY;
19490
+ const centerX = bbox2.minX + width / 2;
19491
+ const centerY = bbox2.minY + height / 2;
19492
+ const box = document.createElement("div");
19493
+ box.className = "polydraw-transform-box";
19494
+ Object.assign(box.style, {
19495
+ position: "absolute",
19496
+ left: `${centerX}px`,
19497
+ top: `${centerY}px`,
19498
+ width: `${width}px`,
19499
+ height: `${height}px`,
19500
+ marginLeft: `${-width / 2}px`,
19501
+ marginTop: `${-height / 2}px`,
19502
+ border: "1px dashed #2b90d9",
19503
+ pointerEvents: "none",
19504
+ transformOrigin: "center center",
19505
+ transform: `rotate(${rotation * 180 / Math.PI}deg)`
19506
+ });
19507
+ this.root.appendChild(box);
19508
+ const makeHandle = (type, x, y) => {
19509
+ const dx = x - centerX;
19510
+ const dy = y - centerY;
19511
+ const cos2 = Math.cos(rotation);
19512
+ const sin2 = Math.sin(rotation);
19513
+ const rotX = centerX + dx * cos2 - dy * sin2;
19514
+ const rotY = centerY + dx * sin2 + dy * cos2;
19515
+ const h = document.createElement("div");
19516
+ h.className = `polydraw-transform-handle handle-${type}`;
19517
+ Object.assign(h.style, {
19518
+ position: "absolute",
19519
+ left: `${rotX - 5}px`,
19520
+ top: `${rotY - 5}px`,
19521
+ width: "10px",
19522
+ height: "10px",
19523
+ borderRadius: "2px",
19524
+ background: "#2b90d9",
19525
+ boxShadow: "0 0 0 1px #fff",
19526
+ cursor: this.cursorForHandle(type),
19527
+ pointerEvents: "auto"
19528
+ });
19529
+ L$1.DomEvent.on(h, "mousedown", (e) => this.startDrag(type, { x: rotX, y: rotY }, e));
19530
+ L$1.DomEvent.on(h, "touchstart", (e) => this.startDrag(type, { x: rotX, y: rotY }, e));
19531
+ this.root.appendChild(h);
19532
+ };
19533
+ if (this.mode === "scale") {
19534
+ makeHandle(TransformHandleType.TopLeft, bbox2.minX, bbox2.minY);
19535
+ makeHandle(TransformHandleType.TopRight, bbox2.maxX, bbox2.minY);
19536
+ makeHandle(TransformHandleType.BottomRight, bbox2.maxX, bbox2.maxY);
19537
+ makeHandle(TransformHandleType.BottomLeft, bbox2.minX, bbox2.maxY);
19538
+ makeHandle(TransformHandleType.Top, centerX, bbox2.minY);
19539
+ makeHandle(TransformHandleType.Right, bbox2.maxX, centerY);
19540
+ makeHandle(TransformHandleType.Bottom, centerX, bbox2.maxY);
19541
+ makeHandle(TransformHandleType.Left, bbox2.minX, centerY);
19542
+ } else {
19543
+ makeHandle(TransformHandleType.Rotate, bbox2.minX, bbox2.minY);
19544
+ makeHandle(TransformHandleType.Rotate, bbox2.maxX, bbox2.minY);
19545
+ makeHandle(TransformHandleType.Rotate, bbox2.maxX, bbox2.maxY);
19546
+ makeHandle(TransformHandleType.Rotate, bbox2.minX, bbox2.maxY);
19547
+ }
19548
+ if (!this.cancelBtn && !this.confirmBtn) {
19549
+ this.updateButtonPositions(bbox2, rotation);
19550
+ } else {
19551
+ this.updateButtonPositions(bbox2, rotation);
19552
+ if (this.cancelBtn) this.root.appendChild(this.cancelBtn);
19553
+ if (this.confirmBtn) this.root.appendChild(this.confirmBtn);
19554
+ }
19555
+ }
19556
+ cursorForHandle(type) {
19557
+ switch (type) {
19558
+ case TransformHandleType.Top:
19559
+ case TransformHandleType.Bottom:
19560
+ return "ns-resize";
19561
+ case TransformHandleType.Left:
19562
+ case TransformHandleType.Right:
19563
+ return "ew-resize";
19564
+ case TransformHandleType.TopLeft:
19565
+ case TransformHandleType.BottomRight:
19566
+ return "nwse-resize";
19567
+ case TransformHandleType.TopRight:
19568
+ case TransformHandleType.BottomLeft:
19569
+ return "nesw-resize";
19570
+ case TransformHandleType.Rotate:
19571
+ return "grab";
19572
+ case TransformHandleType.Pivot:
19573
+ return "move";
19574
+ default:
19575
+ return "default";
19576
+ }
19577
+ }
19578
+ startDrag(type, start, evt) {
19579
+ var _a2, _b2;
19580
+ (_a2 = evt.stopPropagation) == null ? void 0 : _a2.call(evt);
19581
+ (_b2 = evt.preventDefault) == null ? void 0 : _b2.call(evt);
19582
+ this.draggingHandle = type;
19583
+ if (type === TransformHandleType.Rotate && this.mode === "rotate") {
19584
+ this.hideButtons();
19585
+ }
19586
+ const onMove = (e) => this.onDrag(e);
19587
+ const onUp = (e) => this.endDrag(e);
19588
+ L$1.DomEvent.on(document, "mousemove", onMove);
19589
+ L$1.DomEvent.on(document, "mouseup", onUp);
19590
+ L$1.DomEvent.on(document, "touchmove", onMove);
19591
+ L$1.DomEvent.on(document, "touchend", onUp);
19592
+ this.callbacks.onStartHandleDrag(type, start, evt);
19593
+ }
19594
+ onDrag(evt) {
19595
+ if (this.draggingHandle == null) return;
19596
+ const pos = this.getMouseLayerPoint(evt);
19597
+ this.callbacks.onDragHandle(this.draggingHandle, pos, evt);
19598
+ }
19599
+ endDrag(evt) {
19600
+ if (this.draggingHandle == null) return;
19601
+ const type = this.draggingHandle;
19602
+ const wasRotateDrag = type === TransformHandleType.Rotate && this.mode === "rotate";
19603
+ this.draggingHandle = null;
19604
+ const pos = this.getMouseLayerPoint(evt);
19605
+ this.callbacks.onEndHandleDrag(type, pos, evt);
19606
+ if (wasRotateDrag && this.currentBBox) {
19607
+ this.updateButtonPositions(this.currentBBox, this.currentRotation);
19608
+ this.showButtons();
19609
+ }
19610
+ L$1.DomEvent.off(document, "mousemove", this.onDrag);
19611
+ L$1.DomEvent.off(document, "touchmove", this.onDrag);
19612
+ }
19613
+ getMouseLayerPoint(evt) {
19614
+ const containerPoint = this.map.mouseEventToContainerPoint ? this.map.mouseEventToContainerPoint(evt) : leafletAdapter.domEvent.getMousePosition(evt, this.map.getContainer());
19615
+ const layerPoint = this.map.containerPointToLayerPoint(containerPoint);
19616
+ return { x: layerPoint.x, y: layerPoint.y };
19617
+ }
19618
+ updateButtonPositions(bbox2, rotation) {
19619
+ const width = bbox2.maxX - bbox2.minX;
19620
+ const height = bbox2.maxY - bbox2.minY;
19621
+ const centerX = bbox2.minX + width / 2;
19622
+ const centerY = bbox2.minY + height / 2;
19623
+ const corners = [
19624
+ { x: bbox2.minX, y: bbox2.minY },
19625
+ // top-left
19626
+ { x: bbox2.maxX, y: bbox2.minY },
19627
+ // top-right
19628
+ { x: bbox2.maxX, y: bbox2.maxY },
19629
+ // bottom-right
19630
+ { x: bbox2.minX, y: bbox2.maxY }
19631
+ // bottom-left
19632
+ ];
19633
+ const cos2 = Math.cos(rotation);
19634
+ const sin2 = Math.sin(rotation);
19635
+ let topRightCorner = { x: 0, y: Infinity };
19636
+ let minY = Infinity;
19637
+ for (const corner of corners) {
19638
+ const dx = corner.x - centerX;
19639
+ const dy = corner.y - centerY;
19640
+ const rotX = centerX + dx * cos2 - dy * sin2;
19641
+ const rotY = centerY + dx * sin2 + dy * cos2;
19642
+ const isHigher = rotY < minY;
19643
+ const isSameHeight = Math.abs(rotY - minY) < 1;
19644
+ const isMoreRight = rotX > topRightCorner.x;
19645
+ if (isHigher || isSameHeight && isMoreRight) {
19646
+ minY = rotY;
19647
+ topRightCorner = { x: rotX, y: rotY };
19648
+ }
19649
+ }
19650
+ const rotTopRightX = topRightCorner.x;
19651
+ const rotTopRightY = topRightCorner.y;
19652
+ const buttonY = rotTopRightY - 28;
19653
+ const confirmX = rotTopRightX + 5;
19654
+ const cancelX = rotTopRightX - 29;
19655
+ const cancelSvg = cancelIconSvg;
19656
+ const confirmSvg = confirmIconSvg;
19657
+ if (this.onCancel && !this.cancelBtn) {
19658
+ this.cancelBtn = document.createElement("div");
19659
+ this.cancelBtn.className = "polydraw-transform-cancel";
19660
+ this.cancelBtn.innerHTML = cancelSvg;
19661
+ L$1.DomEvent.on(this.cancelBtn, "mousedown", (e) => {
19662
+ var _a2, _b2;
19663
+ (_a2 = e.stopPropagation) == null ? void 0 : _a2.call(e);
19664
+ (_b2 = e.preventDefault) == null ? void 0 : _b2.call(e);
19665
+ this.onCancel && this.onCancel();
19666
+ });
19667
+ L$1.DomEvent.on(this.cancelBtn, "touchstart", (e) => {
19668
+ var _a2, _b2;
19669
+ (_a2 = e.stopPropagation) == null ? void 0 : _a2.call(e);
19670
+ (_b2 = e.preventDefault) == null ? void 0 : _b2.call(e);
19671
+ this.onCancel && this.onCancel();
19672
+ });
19673
+ this.root.appendChild(this.cancelBtn);
19674
+ }
19675
+ if (this.onConfirm && !this.confirmBtn) {
19676
+ this.confirmBtn = document.createElement("div");
19677
+ this.confirmBtn.className = "polydraw-transform-confirm";
19678
+ this.confirmBtn.innerHTML = confirmSvg;
19679
+ L$1.DomEvent.on(this.confirmBtn, "mousedown", (e) => {
19680
+ var _a2, _b2;
19681
+ (_a2 = e.stopPropagation) == null ? void 0 : _a2.call(e);
19682
+ (_b2 = e.preventDefault) == null ? void 0 : _b2.call(e);
19683
+ this.onConfirm && this.onConfirm();
19684
+ });
19685
+ L$1.DomEvent.on(this.confirmBtn, "touchstart", (e) => {
19686
+ var _a2, _b2;
19687
+ (_a2 = e.stopPropagation) == null ? void 0 : _a2.call(e);
19688
+ (_b2 = e.preventDefault) == null ? void 0 : _b2.call(e);
19689
+ this.onConfirm && this.onConfirm();
19690
+ });
19691
+ this.root.appendChild(this.confirmBtn);
19692
+ }
19693
+ if (this.cancelBtn) {
19694
+ Object.assign(this.cancelBtn.style, {
19695
+ position: "absolute",
19696
+ left: `${cancelX}px`,
19697
+ top: `${buttonY}px`
19698
+ });
19699
+ }
19700
+ if (this.confirmBtn) {
19701
+ Object.assign(this.confirmBtn.style, {
19702
+ position: "absolute",
19703
+ left: `${confirmX}px`,
19704
+ top: `${buttonY}px`
19705
+ });
19706
+ }
19707
+ }
19708
+ hideButtons() {
19709
+ if (this.cancelBtn) this.cancelBtn.style.display = "none";
19710
+ if (this.confirmBtn) this.confirmBtn.style.display = "none";
19711
+ }
19712
+ showButtons() {
19713
+ if (this.cancelBtn) this.cancelBtn.style.display = "";
19714
+ if (this.confirmBtn) this.confirmBtn.style.display = "";
19715
+ }
19716
+ }
19717
+ function latLngToPixel(map, ll) {
19718
+ const p = map.latLngToLayerPoint(ll);
19719
+ return { x: p.x, y: p.y };
19720
+ }
19721
+ function pixelToLatLng(map, p) {
19722
+ const ll = map.layerPointToLatLng(leafletAdapter.createPoint(p.x, p.y));
19723
+ return { lat: ll.lat, lng: ll.lng };
19724
+ }
19725
+ function getPixelBBox(rings) {
19726
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
19727
+ for (const poly of rings) {
19728
+ for (const ring of poly) {
19729
+ for (const pt of ring) {
19730
+ if (pt.x < minX) minX = pt.x;
19731
+ if (pt.y < minY) minY = pt.y;
19732
+ if (pt.x > maxX) maxX = pt.x;
19733
+ if (pt.y > maxY) maxY = pt.y;
19734
+ }
19735
+ }
19736
+ }
19737
+ return { minX, minY, maxX, maxY };
19738
+ }
19739
+ function getPixelCentroid(bbox2) {
19740
+ return { x: (bbox2.minX + bbox2.maxX) / 2, y: (bbox2.minY + bbox2.maxY) / 2 };
19741
+ }
19742
+ function rotatePointAround(p, pivot, radians2) {
19743
+ const cos2 = Math.cos(radians2);
19744
+ const sin2 = Math.sin(radians2);
19745
+ const dx = p.x - pivot.x;
19746
+ const dy = p.y - pivot.y;
19747
+ return { x: pivot.x + dx * cos2 - dy * sin2, y: pivot.y + dx * sin2 + dy * cos2 };
19748
+ }
19749
+ function scalePointAround(p, pivot, scaleX, scaleY) {
19750
+ const dx = p.x - pivot.x;
19751
+ const dy = p.y - pivot.y;
19752
+ return { x: pivot.x + dx * scaleX, y: pivot.y + dy * scaleY };
19753
+ }
19754
+ function applyTransform(rings, pivot, scaleX, scaleY, rotation) {
19755
+ return rings.map(
19756
+ (poly) => poly.map(
19757
+ (ring) => ring.map(
19758
+ (pt) => rotatePointAround(scalePointAround(pt, pivot, scaleX, scaleY), pivot, rotation)
19759
+ )
19760
+ )
19761
+ );
19762
+ }
19763
+ function ensureClosedLatLngRing(ll) {
19764
+ if (ll.length === 0) return ll;
19765
+ const first = ll[0];
19766
+ const last = ll[ll.length - 1];
19767
+ if (first.lat === last.lat && first.lng === last.lng) return ll;
19768
+ return [...ll, { lat: first.lat, lng: first.lng }];
19769
+ }
19770
+ function normalizeLatLngs(input) {
19771
+ if (!Array.isArray(input)) {
19772
+ return [[input]];
19773
+ }
19774
+ const a = input;
19775
+ if (a.length === 0) return [];
19776
+ if (!Array.isArray(a[0])) {
19777
+ return [[input]];
19778
+ }
19779
+ if (!Array.isArray(a[0][0])) {
19780
+ return [input];
19781
+ }
19782
+ return input;
19783
+ }
19784
+ function projectLatLngs(map, latLngs) {
19785
+ const rings = [];
19786
+ const ringLengths = [];
19787
+ for (const poly of latLngs) {
19788
+ const polyRings = [];
19789
+ const lengths = [];
19790
+ for (const ring of poly) {
19791
+ const pts = ring.map((ll) => latLngToPixel(map, { lat: ll.lat, lng: ll.lng }));
19792
+ polyRings.push(pts);
19793
+ lengths.push(ring.length);
19794
+ }
19795
+ rings.push(polyRings);
19796
+ ringLengths.push(lengths);
19797
+ }
19798
+ return { rings, ringLengths };
19799
+ }
19800
+ function unprojectToLatLngs(map, rings, templateLatLngs) {
19801
+ const out = [];
19802
+ for (let i = 0; i < rings.length; i++) {
19803
+ const poly = [];
19804
+ for (let j = 0; j < rings[i].length; j++) {
19805
+ const ringPts = rings[i][j];
19806
+ const ll = ringPts.map((p) => pixelToLatLng(map, p));
19807
+ const templ = templateLatLngs[i][j];
19808
+ const isClosed = templ.length > 2 && templ[0].lat === templ[templ.length - 1].lat && templ[0].lng === templ[templ.length - 1].lng;
19809
+ poly.push(isClosed ? ensureClosedLatLngRing(ll) : ll);
19810
+ }
19811
+ out.push(poly);
19812
+ }
19813
+ return out;
19814
+ }
19815
+ function snapAngleRadians(angle, stepDeg = 15) {
19816
+ const step = stepDeg * Math.PI / 180;
19817
+ return Math.round(angle / step) * step;
19818
+ }
19819
+ class PolygonTransformController {
19820
+ constructor(map, featureGroup, mode = "scale", onExit) {
19821
+ __publicField(this, "map");
19822
+ __publicField(this, "polygon");
19823
+ __publicField(this, "overlay");
19824
+ __publicField(this, "state");
19825
+ __publicField(this, "normalizedLatLngs");
19826
+ __publicField(this, "wasMapDraggingEnabled", false);
19827
+ __publicField(this, "mode");
19828
+ __publicField(this, "onExit");
19829
+ __publicField(this, "rotateStartAngle", null);
19830
+ __publicField(this, "rotateBaseRotation", 0);
19831
+ __publicField(this, "onKeyDown", (e) => {
19832
+ if (e.key === "Escape") {
19833
+ this.handleCancel();
19834
+ }
19835
+ });
19836
+ __publicField(this, "updateOverlay", () => {
19837
+ const scaledRings = this.state.originalPixelRings.map(
19838
+ (poly) => poly.map(
19839
+ (ring) => ring.map(
19840
+ (pt) => scalePointAround(pt, this.state.pivot, this.state.scaleX, this.state.scaleY)
19841
+ )
19842
+ )
19843
+ );
19844
+ const bbox2 = getPixelBBox(scaledRings);
19845
+ this.overlay.update(bbox2, this.state.pivot, this.state.rotation);
19846
+ });
19847
+ this.map = map;
19848
+ this.mode = mode;
19849
+ this.onExit = onExit;
19850
+ const polygon2 = featureGroup.getLayers().find((l) => l instanceof L$1.Polygon);
19851
+ if (!polygon2) throw new Error("FeatureGroup does not contain a polygon");
19852
+ this.polygon = polygon2;
19853
+ const originalLatLngs = this.polygon.getLatLngs();
19854
+ this.normalizedLatLngs = normalizeLatLngs(originalLatLngs);
19855
+ const proj = projectLatLngs(this.map, this.normalizedLatLngs);
19856
+ const bbox2 = getPixelBBox(proj.rings);
19857
+ const pivot = getPixelCentroid(bbox2);
19858
+ this.state = {
19859
+ isActive: true,
19860
+ originalLatLngs,
19861
+ originalPixelRings: proj.rings,
19862
+ pivot,
19863
+ scaleX: 1,
19864
+ scaleY: 1,
19865
+ rotation: 0,
19866
+ uniformScale: false,
19867
+ snapRotation: false,
19868
+ scaleFromPivot: false
19869
+ };
19870
+ this.overlay = new TransformOverlay(
19871
+ this.map,
19872
+ {
19873
+ onStartHandleDrag: (type, start, e) => this.onStartDrag(type, start, e),
19874
+ onDragHandle: (type, current, e) => this.onDrag(type, current, e),
19875
+ onEndHandleDrag: (_type, _end, _e) => {
19876
+ }
19877
+ },
19878
+ this.mode,
19879
+ () => this.handleCancel(),
19880
+ () => this.handleConfirm()
19881
+ );
19882
+ this.updateOverlay();
19883
+ this.map.on("zoom viewreset move", this.updateOverlay, this);
19884
+ if (this.map.dragging) {
19885
+ const dragging = this.map.dragging;
19886
+ if (typeof dragging.enabled === "function") {
19887
+ this.wasMapDraggingEnabled = dragging.enabled();
19888
+ }
19889
+ dragging.disable();
19890
+ }
19891
+ document.addEventListener("keydown", this.onKeyDown);
19892
+ }
19893
+ destroy() {
19894
+ document.removeEventListener("keydown", this.onKeyDown);
19895
+ this.map.off("zoom viewreset move", this.updateOverlay, this);
19896
+ this.overlay.destroy();
19897
+ this.state.isActive = false;
19898
+ if (this.map.dragging) {
19899
+ const dragging = this.map.dragging;
19900
+ if (this.wasMapDraggingEnabled && typeof dragging.enable === "function") {
19901
+ dragging.enable();
19902
+ }
19903
+ }
19904
+ }
19905
+ onStartDrag(type, start, evt) {
19906
+ const isMac = navigator.userAgent.toLowerCase().includes("mac");
19907
+ const ctrlOrCmd = isMac ? evt.metaKey : evt.ctrlKey;
19908
+ this.state.uniformScale = !!evt.shiftKey;
19909
+ this.state.scaleFromPivot = !!evt.altKey;
19910
+ this.state.snapRotation = !!ctrlOrCmd;
19911
+ if (type === TransformHandleType.Rotate) {
19912
+ const c = this.state.scaleFromPivot ? this.state.pivot : getPixelCentroid(getPixelBBox(this.state.originalPixelRings));
19913
+ const startAngle = Math.atan2(start.y - c.y, start.x - c.x);
19914
+ this.rotateStartAngle = startAngle;
19915
+ this.rotateBaseRotation = this.state.rotation || 0;
19916
+ }
19917
+ }
19918
+ onDrag(type, current, _evt) {
19919
+ const origBBox = getPixelBBox(this.state.originalPixelRings);
19920
+ switch (type) {
19921
+ case TransformHandleType.Rotate: {
19922
+ const rotationCenter = this.state.scaleFromPivot ? this.state.pivot : getPixelCentroid(origBBox);
19923
+ this.handleRotateDrag(current, rotationCenter);
19924
+ break;
19925
+ }
19926
+ case TransformHandleType.Pivot:
19927
+ this.handlePivotDrag(current);
19928
+ break;
19929
+ default: {
19930
+ const scaleCenter = this.state.scaleFromPivot ? this.state.pivot : getPixelCentroid(origBBox);
19931
+ this.handleScaleDrag(type, current, origBBox, scaleCenter);
19932
+ break;
19933
+ }
19934
+ }
19935
+ this.preview();
19936
+ }
19937
+ handleRotateDrag(current, center2) {
19938
+ if (this.mode !== "rotate") return;
19939
+ const angle = Math.atan2(current.y - center2.y, current.x - center2.x);
19940
+ let theta;
19941
+ if (this.rotateStartAngle != null) {
19942
+ const delta = angle - this.rotateStartAngle;
19943
+ theta = this.rotateBaseRotation + delta;
19944
+ } else {
19945
+ theta = angle;
19946
+ }
19947
+ this.state.rotation = this.state.snapRotation ? snapAngleRadians(theta, 15) : theta;
19948
+ }
19949
+ handlePivotDrag(current) {
19950
+ this.state.pivot = current;
19951
+ }
19952
+ handleScaleDrag(type, current, origBBox, center2) {
19953
+ if (this.mode !== "scale") return;
19954
+ const width = origBBox.maxX - origBBox.minX;
19955
+ const height = origBBox.maxY - origBBox.minY;
19956
+ let scaleX = this.state.scaleX;
19957
+ let scaleY = this.state.scaleY;
19958
+ switch (type) {
19959
+ case TransformHandleType.Left:
19960
+ case TransformHandleType.TopLeft:
19961
+ case TransformHandleType.BottomLeft:
19962
+ scaleX = (center2.x - current.x) / (center2.x - origBBox.minX || 1);
19963
+ break;
19964
+ case TransformHandleType.Right:
19965
+ case TransformHandleType.TopRight:
19966
+ case TransformHandleType.BottomRight:
19967
+ scaleX = (current.x - center2.x) / (origBBox.maxX - center2.x || 1);
19968
+ break;
19969
+ }
19970
+ switch (type) {
19971
+ case TransformHandleType.Top:
19972
+ case TransformHandleType.TopLeft:
19973
+ case TransformHandleType.TopRight:
19974
+ scaleY = (center2.y - current.y) / (center2.y - origBBox.minY || 1);
19975
+ break;
19976
+ case TransformHandleType.Bottom:
19977
+ case TransformHandleType.BottomLeft:
19978
+ case TransformHandleType.BottomRight:
19979
+ scaleY = (current.y - center2.y) / (origBBox.maxY - center2.y || 1);
19980
+ break;
19981
+ }
19982
+ if (type === TransformHandleType.Left || type === TransformHandleType.Right) {
19983
+ scaleY = this.state.scaleY;
19984
+ }
19985
+ if (type === TransformHandleType.Top || type === TransformHandleType.Bottom) {
19986
+ scaleX = this.state.scaleX;
19987
+ }
19988
+ if (this.state.uniformScale) {
19989
+ const uniform = Math.abs(width) > Math.abs(height) ? Math.sign(scaleX) * Math.abs(scaleX) : Math.sign(scaleY) * Math.abs(scaleY);
19990
+ scaleX = uniform;
19991
+ scaleY = uniform;
19992
+ }
19993
+ const hasValidScaleX = Number.isFinite(scaleX) && Math.abs(scaleX) > 1e-3;
19994
+ const hasValidScaleY = Number.isFinite(scaleY) && Math.abs(scaleY) > 1e-3;
19995
+ if (hasValidScaleX) {
19996
+ this.state.scaleX = scaleX;
19997
+ }
19998
+ if (hasValidScaleY) {
19999
+ this.state.scaleY = scaleY;
20000
+ }
20001
+ }
20002
+ preview() {
20003
+ const transformed = applyTransform(
20004
+ this.state.originalPixelRings,
20005
+ this.state.pivot,
20006
+ this.state.scaleX,
20007
+ this.state.scaleY,
20008
+ this.state.rotation
20009
+ );
20010
+ const ll = unprojectToLatLngs(this.map, transformed, this.normalizedLatLngs);
20011
+ this.polygon.setLatLngs(ll);
20012
+ this.updateOverlay();
20013
+ }
20014
+ apply() {
20015
+ const coords = this.polygon.getLatLngs();
20016
+ return normalizeLatLngs(coords);
20017
+ }
20018
+ cancel() {
20019
+ this.polygon.setLatLngs(this.state.originalLatLngs);
20020
+ }
20021
+ handleCancel() {
20022
+ this.cancel();
20023
+ this.destroy();
20024
+ if (this.onExit) this.onExit();
20025
+ }
20026
+ handleConfirm() {
20027
+ if (this.onExit) this.onExit();
20028
+ this.destroy();
20029
+ }
20030
+ }
20031
+ class PopupFactory {
20032
+ /**
20033
+ * Creates a menu button element.
20034
+ * @param id Unique identifier for the button.
20035
+ * @param title Tooltip text.
20036
+ * @param cssClasses Additional CSS classes to apply.
20037
+ * @param options Optional configuration (alpha banner, etc.).
20038
+ * @returns HTMLDivElement representing the menu button.
20039
+ */
20040
+ static createMenuButton(id, title, cssClasses, options) {
20041
+ const button = document.createElement("div");
20042
+ button.classList.add("marker-menu-button", ...cssClasses);
20043
+ button.title = title;
20044
+ button.setAttribute("data-action-id", id);
20045
+ if (options == null ? void 0 : options.alphaBanner) {
20046
+ const alphaBanner = document.createElement("span");
20047
+ alphaBanner.classList.add("alpha-banner");
20048
+ alphaBanner.textContent = "ALPHA";
20049
+ button.appendChild(alphaBanner);
20050
+ }
20051
+ return button;
20052
+ }
20053
+ /**
20054
+ * Builds a menu popup container structure.
20055
+ * @param buttons Array of button elements to include.
20056
+ * @returns HTMLDivElement containing the complete menu structure.
20057
+ */
20058
+ static buildMenuPopup(buttons) {
20059
+ const outerWrapper = document.createElement("div");
20060
+ outerWrapper.classList.add("alter-marker-outer-wrapper");
20061
+ const wrapper = document.createElement("div");
20062
+ wrapper.classList.add("alter-marker-wrapper");
20063
+ const markerContent = document.createElement("div");
20064
+ markerContent.classList.add("content");
20065
+ const markerContentWrapper = document.createElement("div");
20066
+ markerContentWrapper.classList.add("marker-menu-content");
20067
+ buttons.forEach((button) => {
20068
+ markerContentWrapper.appendChild(button);
20069
+ });
20070
+ markerContent.appendChild(markerContentWrapper);
20071
+ wrapper.appendChild(markerContent);
20072
+ outerWrapper.appendChild(wrapper);
20073
+ return outerWrapper;
20074
+ }
20075
+ /**
20076
+ * Builds an info popup container structure.
20077
+ * @param content HTML element to display inside the popup.
20078
+ * @returns HTMLDivElement containing the complete info popup structure.
20079
+ */
20080
+ static buildInfoPopup(content) {
20081
+ const outerWrapper = document.createElement("div");
20082
+ outerWrapper.classList.add("info-marker-outer-wrapper");
20083
+ const wrapper = document.createElement("div");
20084
+ wrapper.classList.add("info-marker-wrapper");
20085
+ const markerContent = document.createElement("div");
20086
+ markerContent.classList.add("content");
20087
+ markerContent.appendChild(content);
20088
+ wrapper.appendChild(markerContent);
20089
+ outerWrapper.appendChild(wrapper);
20090
+ return outerWrapper;
20091
+ }
20092
+ }
19110
20093
  class PolygonInteractionManager {
19111
20094
  constructor(dependencies, featureGroupAccess) {
19112
20095
  __publicField(this, "markerFeatureGroupMap", /* @__PURE__ */ new WeakMap());
@@ -19124,6 +20107,8 @@ class PolygonInteractionManager {
19124
20107
  __publicField(this, "currentModifierDragMode", false);
19125
20108
  __publicField(this, "isModifierKeyHeld", false);
19126
20109
  __publicField(this, "_openMenuPopup", null);
20110
+ __publicField(this, "transformModeActive", false);
20111
+ __publicField(this, "transformControllers", /* @__PURE__ */ new WeakMap());
19127
20112
  // Read-only access to feature groups
19128
20113
  __publicField(this, "getFeatureGroups");
19129
20114
  __publicField(this, "removeFeatureGroup");
@@ -19208,6 +20193,12 @@ class PolygonInteractionManager {
19208
20193
  this.getFeatureGroups = featureGroupAccess.getFeatureGroups;
19209
20194
  this.removeFeatureGroup = featureGroupAccess.removeFeatureGroup;
19210
20195
  }
20196
+ /**
20197
+ * Strongly typed helper to emit polygon updated events without casts.
20198
+ */
20199
+ emitPolygonUpdated(data) {
20200
+ this.eventManager.emit("polydraw:polygon:updated", data);
20201
+ }
19211
20202
  /**
19212
20203
  * Add markers to a polygon feature group
19213
20204
  */
@@ -19313,7 +20304,10 @@ class PolygonInteractionManager {
19313
20304
  marker.options.zIndexOffset = this.config.markers.markerMenuIcon.zIndexOffset ?? this.config.markers.zIndexOffset;
19314
20305
  marker.on("click", () => {
19315
20306
  const polygonGeoJSON = this.getPolygonGeoJSONFromFeatureGroup(featureGroup);
19316
- const centerOfMass2 = PolygonUtil.getCenterOfMass(polygonGeoJSON);
20307
+ const centerOfMass2 = PolygonUtil.getCenterOfPolygonByIndexWithOffsetFromCenterOfMass(
20308
+ polygonGeoJSON,
20309
+ menuMarkerIdx
20310
+ );
19317
20311
  const menuPopup = this.generateMenuMarkerPopup(latlngs, featureGroup);
19318
20312
  menuPopup.setLatLng(centerOfMass2).openOn(this.map);
19319
20313
  });
@@ -19323,12 +20317,22 @@ class PolygonInteractionManager {
19323
20317
  if (!popupContent) return;
19324
20318
  setTimeout(() => {
19325
20319
  const mapContainer = this.map.getContainer();
19326
- const mapBounds = mapContainer.getBoundingClientRect();
19327
20320
  const popupBounds = popupContent.getBoundingClientRect();
20321
+ const mapBounds = mapContainer.getBoundingClientRect();
20322
+ let adjustX = 0;
20323
+ let adjustY = 0;
19328
20324
  if (popupBounds.left < mapBounds.left) {
19329
- popupContent.style.transform = `translateX(${mapBounds.left - popupBounds.left}px)`;
20325
+ adjustX = mapBounds.left - popupBounds.left;
19330
20326
  } else if (popupBounds.right > mapBounds.right) {
19331
- popupContent.style.transform = `translateX(${mapBounds.right - popupBounds.right}px)`;
20327
+ adjustX = mapBounds.right - popupBounds.right;
20328
+ }
20329
+ if (popupBounds.top < mapBounds.top) {
20330
+ adjustY = mapBounds.top - popupBounds.top;
20331
+ } else if (popupBounds.bottom > mapBounds.bottom) {
20332
+ adjustY = mapBounds.bottom - popupBounds.bottom;
20333
+ }
20334
+ if (adjustX !== 0 || adjustY !== 0) {
20335
+ popupContent.style.transform = `translate(${adjustX}px, ${adjustY}px)`;
19332
20336
  }
19333
20337
  }, 0);
19334
20338
  const container2 = this.map.getContainer();
@@ -19350,7 +20354,10 @@ class PolygonInteractionManager {
19350
20354
  marker.options.zIndexOffset = this.config.markers.markerInfoIcon.zIndexOffset ?? this.config.markers.zIndexOffset;
19351
20355
  marker.on("click", () => {
19352
20356
  const infoPopup = this.generateInfoMarkerPopup(area2, perimeter);
19353
- const centerOfMass2 = PolygonUtil.getCenterOfMass(polygonGeoJSON);
20357
+ const centerOfMass2 = PolygonUtil.getCenterOfPolygonByIndexWithOffsetFromCenterOfMass(
20358
+ polygonGeoJSON,
20359
+ infoMarkerIdx
20360
+ );
19354
20361
  infoPopup.setLatLng(centerOfMass2).openOn(this.map);
19355
20362
  });
19356
20363
  marker.on("popupopen", (e) => {
@@ -19634,7 +20641,7 @@ class PolygonInteractionManager {
19634
20641
  });
19635
20642
  const newPolygon = this.turfHelper.getMultiPolygon([coords]);
19636
20643
  this.removeFeatureGroup(featureGroup);
19637
- this.eventManager.emit("polydraw:polygon:updated", {
20644
+ this.emitPolygonUpdated({
19638
20645
  operation: "removeHole",
19639
20646
  polygon: newPolygon
19640
20647
  });
@@ -19760,6 +20767,9 @@ class PolygonInteractionManager {
19760
20767
  this.currentDragPolygon = polygon2;
19761
20768
  });
19762
20769
  polygon2.on("pointerdown", (e) => {
20770
+ if (this.transformModeActive) {
20771
+ return;
20772
+ }
19763
20773
  if (!this.modeManager.isInOffMode()) {
19764
20774
  L$1.DomEvent.stopPropagation(e);
19765
20775
  this.map.fire("pointerdown", e);
@@ -19900,7 +20910,7 @@ class PolygonInteractionManager {
19900
20910
  const polydrawPolygon = parentPolygon;
19901
20911
  const optimizationLevel = polydrawPolygon._polydrawOptimizationLevel || 0;
19902
20912
  this.removeFeatureGroup(parentFeatureGroup);
19903
- this.eventManager.emit("polydraw:polygon:updated", {
20913
+ this.emitPolygonUpdated({
19904
20914
  operation: "addVertex",
19905
20915
  polygon: newPolygon,
19906
20916
  optimizationLevel
@@ -20000,7 +21010,7 @@ class PolygonInteractionManager {
20000
21010
  this.removeFeatureGroup(currentFeatureGroup);
20001
21011
  }
20002
21012
  const newPolygon = this.turfHelper.getMultiPolygon([coords]);
20003
- this.eventManager.emit("polydraw:polygon:updated", {
21013
+ this.emitPolygonUpdated({
20004
21014
  operation: "removeVertex",
20005
21015
  polygon: newPolygon
20006
21016
  });
@@ -20025,7 +21035,7 @@ class PolygonInteractionManager {
20025
21035
  }
20026
21036
  const posarrays = polygonLayer.getLatLngs();
20027
21037
  let length2 = 0;
20028
- const markers2 = layers.filter((layer) => layer instanceof L$1.Marker);
21038
+ const markers = layers.filter((layer) => layer instanceof L$1.Marker);
20029
21039
  if (posarrays.length > 1) {
20030
21040
  for (let index = 0; index < posarrays.length; index++) {
20031
21041
  testarray = [];
@@ -20034,16 +21044,16 @@ class PolygonInteractionManager {
20034
21044
  if (posarrays[0].length > 1) {
20035
21045
  for (let i = 0; i < posarrays[0].length; i++) {
20036
21046
  for (let j = 0; j < posarrays[0][i].length; j++) {
20037
- if (markers2[j]) {
20038
- testarray.push(markers2[j].getLatLng());
21047
+ if (markers[j]) {
21048
+ testarray.push(markers[j].getLatLng());
20039
21049
  }
20040
21050
  }
20041
21051
  hole.push(testarray);
20042
21052
  }
20043
21053
  } else {
20044
21054
  for (let j = 0; j < posarrays[0][0].length; j++) {
20045
- if (markers2[j]) {
20046
- testarray.push(markers2[j].getLatLng());
21055
+ if (markers[j]) {
21056
+ testarray.push(markers[j].getLatLng());
20047
21057
  }
20048
21058
  }
20049
21059
  hole.push(testarray);
@@ -20052,8 +21062,8 @@ class PolygonInteractionManager {
20052
21062
  } else {
20053
21063
  length2 += posarrays[index - 1].length;
20054
21064
  for (let j = length2; j < posarrays[index][0].length + length2; j++) {
20055
- if (markers2[j]) {
20056
- testarray.push(markers2[j].getLatLng());
21065
+ if (markers[j]) {
21066
+ testarray.push(markers[j].getLatLng());
20057
21067
  }
20058
21068
  }
20059
21069
  hole.push(testarray);
@@ -20068,22 +21078,22 @@ class PolygonInteractionManager {
20068
21078
  if (index === 0) {
20069
21079
  if (posarrays[0][index].length > 1) {
20070
21080
  for (let j = 0; j < posarrays[0][index].length; j++) {
20071
- if (markers2[j]) {
20072
- testarray.push(markers2[j].getLatLng());
21081
+ if (markers[j]) {
21082
+ testarray.push(markers[j].getLatLng());
20073
21083
  }
20074
21084
  }
20075
21085
  } else {
20076
21086
  for (let j = 0; j < posarrays[0][0].length; j++) {
20077
- if (markers2[j]) {
20078
- testarray.push(markers2[j].getLatLng());
21087
+ if (markers[j]) {
21088
+ testarray.push(markers[j].getLatLng());
20079
21089
  }
20080
21090
  }
20081
21091
  }
20082
21092
  } else {
20083
21093
  length22 += posarrays[0][index - 1].length;
20084
21094
  for (let j = length22; j < posarrays[0][index].length + length22; j++) {
20085
- if (markers2[j]) {
20086
- testarray.push(markers2[j].getLatLng());
21095
+ if (markers[j]) {
21096
+ testarray.push(markers[j].getLatLng());
20087
21097
  }
20088
21098
  }
20089
21099
  }
@@ -20106,7 +21116,7 @@ class PolygonInteractionManager {
20106
21116
  if (this.turfHelper.hasKinks(feature2)) {
20107
21117
  const unkink = this.turfHelper.getKinks(feature2);
20108
21118
  for (const polygon2 of unkink) {
20109
- this.eventManager.emit("polydraw:polygon:updated", {
21119
+ this.emitPolygonUpdated({
20110
21120
  operation: "markerDrag",
20111
21121
  polygon: this.turfHelper.getTurfPolygon(polygon2),
20112
21122
  allowMerge: true,
@@ -20116,7 +21126,7 @@ class PolygonInteractionManager {
20116
21126
  });
20117
21127
  }
20118
21128
  } else {
20119
- this.eventManager.emit("polydraw:polygon:updated", {
21129
+ this.emitPolygonUpdated({
20120
21130
  operation: "markerDrag",
20121
21131
  polygon: feature2,
20122
21132
  allowMerge: true,
@@ -20133,7 +21143,7 @@ class PolygonInteractionManager {
20133
21143
  if (this.turfHelper.hasKinks(feature2)) {
20134
21144
  const unkink = this.turfHelper.getKinks(feature2);
20135
21145
  for (const polygon2 of unkink) {
20136
- this.eventManager.emit("polydraw:polygon:updated", {
21146
+ this.emitPolygonUpdated({
20137
21147
  operation: "markerDrag",
20138
21148
  polygon: this.turfHelper.getTurfPolygon(polygon2),
20139
21149
  allowMerge: false
@@ -20141,7 +21151,7 @@ class PolygonInteractionManager {
20141
21151
  });
20142
21152
  }
20143
21153
  } else {
20144
- this.eventManager.emit("polydraw:polygon:updated", {
21154
+ this.emitPolygonUpdated({
20145
21155
  operation: "markerDrag",
20146
21156
  polygon: feature2,
20147
21157
  allowMerge: false
@@ -20250,7 +21260,7 @@ class PolygonInteractionManager {
20250
21260
  }
20251
21261
  this.removeFeatureGroup(featureGroup);
20252
21262
  const feature2 = this.turfHelper.getTurfPolygon(newGeoJSON);
20253
- this.eventManager.emit("polydraw:polygon:updated", {
21263
+ this.emitPolygonUpdated({
20254
21264
  operation: "polygonDrag",
20255
21265
  polygon: feature2,
20256
21266
  allowMerge: true
@@ -20402,7 +21412,7 @@ class PolygonInteractionManager {
20402
21412
  const coords = this.turfHelper.getCoords(difference3);
20403
21413
  for (const coordSet of coords) {
20404
21414
  const individualPolygon = this.turfHelper.getMultiPolygon([coordSet]);
20405
- this.eventManager.emit("polydraw:polygon:updated", {
21415
+ this.emitPolygonUpdated({
20406
21416
  operation: "modifierSubtract",
20407
21417
  polygon: this.turfHelper.getTurfPolygon(individualPolygon),
20408
21418
  allowMerge: false
@@ -20414,7 +21424,7 @@ class PolygonInteractionManager {
20414
21424
  if (!isTestEnvironment()) {
20415
21425
  console.warn("Failed to perform difference operation:", differenceError);
20416
21426
  }
20417
- this.eventManager.emit("polydraw:polygon:updated", {
21427
+ this.emitPolygonUpdated({
20418
21428
  operation: "modifierSubtractFallback",
20419
21429
  polygon: existingPolygon,
20420
21430
  allowMerge: false
@@ -20522,25 +21532,25 @@ class PolygonInteractionManager {
20522
21532
  );
20523
21533
  return nearestPointIdx;
20524
21534
  }
20525
- ensureMarkerSeparation(polygonLength, markers2) {
21535
+ ensureMarkerSeparation(polygonLength, markers) {
20526
21536
  const enabledMarkers = [];
20527
- if (markers2.menu.enabled) {
20528
- enabledMarkers.push({ type: "menu", index: markers2.menu.index });
21537
+ if (markers.menu.enabled) {
21538
+ enabledMarkers.push({ type: "menu", index: markers.menu.index });
20529
21539
  }
20530
- if (markers2.delete.enabled) {
20531
- enabledMarkers.push({ type: "delete", index: markers2.delete.index });
21540
+ if (markers.delete.enabled) {
21541
+ enabledMarkers.push({ type: "delete", index: markers.delete.index });
20532
21542
  }
20533
- if (markers2.info.enabled) {
20534
- enabledMarkers.push({ type: "info", index: markers2.info.index });
21543
+ if (markers.info.enabled) {
21544
+ enabledMarkers.push({ type: "info", index: markers.info.index });
20535
21545
  }
20536
21546
  if (enabledMarkers.length < 2) {
20537
21547
  return {
20538
- menu: markers2.menu.index,
20539
- delete: markers2.delete.index,
20540
- info: markers2.info.index
21548
+ menu: markers.menu.index,
21549
+ delete: markers.delete.index,
21550
+ info: markers.info.index
20541
21551
  };
20542
21552
  }
20543
- const resolvedIndices = { ...markers2 };
21553
+ const resolvedIndices = { ...markers };
20544
21554
  const usedIndices = /* @__PURE__ */ new Set();
20545
21555
  const processingOrder = ["info", "delete", "menu"];
20546
21556
  for (const markerType of processingOrder) {
@@ -20612,120 +21622,126 @@ class PolygonInteractionManager {
20612
21622
  });
20613
21623
  }
20614
21624
  generateMenuMarkerPopup(latLngs, featureGroup) {
20615
- const outerWrapper = document.createElement("div");
20616
- outerWrapper.classList.add("alter-marker-outer-wrapper");
20617
- const wrapper = document.createElement("div");
20618
- wrapper.classList.add("alter-marker-wrapper");
20619
- const markerContent = document.createElement("div");
20620
- markerContent.classList.add("content");
20621
- const markerContentWrapper = document.createElement("div");
20622
- markerContentWrapper.classList.add("marker-menu-content");
20623
- const simplify3 = document.createElement("div");
20624
- simplify3.classList.add("marker-menu-button", "simplify");
20625
- simplify3.title = "Simplify";
20626
- const doubleElbows = document.createElement("div");
20627
- doubleElbows.classList.add("marker-menu-button", "double-elbows");
20628
- doubleElbows.title = "DoubleElbows";
20629
- const bbox2 = document.createElement("div");
20630
- bbox2.classList.add("marker-menu-button", "bbox");
20631
- bbox2.title = "Bounding box";
20632
- const bezier2 = document.createElement("div");
20633
- bezier2.classList.add("marker-menu-button", "bezier");
20634
- bezier2.title = "Curve";
20635
- const alphaBanner = document.createElement("span");
20636
- alphaBanner.classList.add("alpha-banner");
20637
- alphaBanner.textContent = "ALPHA";
20638
- bezier2.appendChild(alphaBanner);
20639
- const separator = document.createElement("div");
20640
- separator.classList.add("separator");
20641
- outerWrapper.appendChild(wrapper);
20642
- wrapper.appendChild(markerContent);
20643
- markerContent.appendChild(markerContentWrapper);
20644
- markerContentWrapper.appendChild(simplify3);
20645
- markerContentWrapper.appendChild(separator.cloneNode());
20646
- markerContentWrapper.appendChild(doubleElbows);
20647
- markerContentWrapper.appendChild(separator.cloneNode());
20648
- markerContentWrapper.appendChild(bbox2);
20649
- markerContentWrapper.appendChild(separator.cloneNode());
20650
- markerContentWrapper.appendChild(bezier2);
21625
+ const buttons = [];
21626
+ const menuOps = this.config.menuOperations;
21627
+ if (menuOps.simplify.enabled) {
21628
+ buttons.push(PopupFactory.createMenuButton("simplify", "Simplify", ["simplify"]));
21629
+ }
21630
+ if (menuOps.doubleElbows.enabled) {
21631
+ buttons.push(
21632
+ PopupFactory.createMenuButton("doubleElbows", "DoubleElbows", ["double-elbows"])
21633
+ );
21634
+ }
21635
+ if (menuOps.bbox.enabled) {
21636
+ buttons.push(PopupFactory.createMenuButton("bbox", "Bounding box", ["bbox"]));
21637
+ }
21638
+ if (menuOps.bezier.enabled) {
21639
+ buttons.push(
21640
+ PopupFactory.createMenuButton("bezier", "Curve", ["bezier"], {
21641
+ alphaBanner: true
21642
+ })
21643
+ );
21644
+ }
21645
+ if (menuOps.scale.enabled) {
21646
+ buttons.push(PopupFactory.createMenuButton("scale", "Scale", ["transform-scale"]));
21647
+ }
21648
+ if (menuOps.rotate.enabled) {
21649
+ buttons.push(PopupFactory.createMenuButton("rotate", "Rotate", ["transform-rotate"]));
21650
+ }
21651
+ const outerWrapper = PopupFactory.buildMenuPopup(buttons);
20651
21652
  const closePopupIfOpen = () => {
20652
21653
  if (this._openMenuPopup) {
20653
21654
  this.map.closePopup(this._openMenuPopup);
20654
21655
  this._openMenuPopup = null;
20655
21656
  }
20656
21657
  };
20657
- simplify3.addEventListener("touchend", (e) => {
20658
- e.preventDefault();
20659
- e.stopPropagation();
20660
- this.eventManager.emit("polydraw:menu:action", {
20661
- action: "simplify",
20662
- latLngs,
20663
- featureGroup
20664
- });
20665
- closePopupIfOpen();
20666
- });
20667
- simplify3.onclick = () => {
20668
- this.eventManager.emit("polydraw:menu:action", {
20669
- action: "simplify",
20670
- latLngs,
20671
- featureGroup
21658
+ const attachMenuActionHandler = (button, action) => {
21659
+ button.addEventListener("touchend", (e) => {
21660
+ e.preventDefault();
21661
+ e.stopPropagation();
21662
+ this.eventManager.emit("polydraw:menu:action", {
21663
+ action,
21664
+ latLngs,
21665
+ featureGroup
21666
+ });
21667
+ closePopupIfOpen();
20672
21668
  });
20673
- closePopupIfOpen();
21669
+ button.onclick = () => {
21670
+ this.eventManager.emit("polydraw:menu:action", {
21671
+ action,
21672
+ latLngs,
21673
+ featureGroup
21674
+ });
21675
+ closePopupIfOpen();
21676
+ };
20674
21677
  };
20675
- bbox2.addEventListener("touchend", (e) => {
20676
- e.preventDefault();
20677
- e.stopPropagation();
20678
- this.eventManager.emit("polydraw:menu:action", {
20679
- action: "bbox",
20680
- latLngs,
20681
- featureGroup
20682
- });
20683
- closePopupIfOpen();
20684
- });
20685
- bbox2.onclick = () => {
20686
- this.eventManager.emit("polydraw:menu:action", {
20687
- action: "bbox",
20688
- latLngs,
20689
- featureGroup
20690
- });
20691
- closePopupIfOpen();
21678
+ const startTransform = (mode) => {
21679
+ const existing = this.transformControllers.get(featureGroup);
21680
+ if (existing) {
21681
+ existing.cancel();
21682
+ existing.destroy();
21683
+ this.transformControllers.delete(featureGroup);
21684
+ }
21685
+ try {
21686
+ const controller = new PolygonTransformController(this.map, featureGroup, mode, () => {
21687
+ try {
21688
+ const polygonLayer = featureGroup.getLayers().find((l) => l instanceof L$1.Polygon);
21689
+ if (!polygonLayer) return;
21690
+ const newGeoJSON = polygonLayer.toGeoJSON();
21691
+ this.removeFeatureGroup(featureGroup);
21692
+ this.emitPolygonUpdated({
21693
+ operation: "transform",
21694
+ polygon: this.turfHelper.getTurfPolygon(newGeoJSON),
21695
+ allowMerge: true
21696
+ });
21697
+ } finally {
21698
+ controller.destroy();
21699
+ this.transformControllers.delete(featureGroup);
21700
+ this.transformModeActive = false;
21701
+ }
21702
+ });
21703
+ this.transformControllers.set(featureGroup, controller);
21704
+ const polyLayer = featureGroup.getLayers().find((l) => l instanceof L$1.Polygon);
21705
+ if (polyLayer) this.setMarkerVisibility(polyLayer, false);
21706
+ this.transformModeActive = true;
21707
+ } catch {
21708
+ }
20692
21709
  };
20693
- doubleElbows.addEventListener("touchend", (e) => {
20694
- e.preventDefault();
20695
- e.stopPropagation();
20696
- this.eventManager.emit("polydraw:menu:action", {
20697
- action: "doubleElbows",
20698
- latLngs,
20699
- featureGroup
20700
- });
20701
- closePopupIfOpen();
20702
- });
20703
- doubleElbows.onclick = () => {
20704
- this.eventManager.emit("polydraw:menu:action", {
20705
- action: "doubleElbows",
20706
- latLngs,
20707
- featureGroup
21710
+ const attachTransformHandler = (button, mode) => {
21711
+ button.addEventListener("touchend", (e) => {
21712
+ e.preventDefault();
21713
+ e.stopPropagation();
21714
+ startTransform(mode);
21715
+ closePopupIfOpen();
20708
21716
  });
20709
- closePopupIfOpen();
21717
+ button.onclick = () => {
21718
+ startTransform(mode);
21719
+ closePopupIfOpen();
21720
+ };
20710
21721
  };
20711
- bezier2.addEventListener("touchend", (e) => {
20712
- e.preventDefault();
20713
- e.stopPropagation();
20714
- this.eventManager.emit("polydraw:menu:action", {
20715
- action: "bezier",
20716
- latLngs,
20717
- featureGroup
20718
- });
20719
- closePopupIfOpen();
21722
+ buttons.forEach((button) => {
21723
+ const actionId = button.getAttribute("data-action-id");
21724
+ switch (actionId) {
21725
+ case "simplify":
21726
+ attachMenuActionHandler(button, "simplify");
21727
+ break;
21728
+ case "doubleElbows":
21729
+ attachMenuActionHandler(button, "doubleElbows");
21730
+ break;
21731
+ case "bbox":
21732
+ attachMenuActionHandler(button, "bbox");
21733
+ break;
21734
+ case "bezier":
21735
+ attachMenuActionHandler(button, "bezier");
21736
+ break;
21737
+ case "scale":
21738
+ attachTransformHandler(button, "scale");
21739
+ break;
21740
+ case "rotate":
21741
+ attachTransformHandler(button, "rotate");
21742
+ break;
21743
+ }
20720
21744
  });
20721
- bezier2.onclick = () => {
20722
- this.eventManager.emit("polydraw:menu:action", {
20723
- action: "bezier",
20724
- latLngs,
20725
- featureGroup
20726
- });
20727
- closePopupIfOpen();
20728
- };
20729
21745
  L$1.DomEvent.disableClickPropagation(outerWrapper);
20730
21746
  outerWrapper.style.pointerEvents = "auto";
20731
21747
  outerWrapper.querySelectorAll(".marker-menu-button").forEach((btn) => {
@@ -21610,12 +22626,12 @@ class PolygonMutationManager {
21610
22626
  getMarkerIndex(latlngs, position) {
21611
22627
  return 0;
21612
22628
  }
21613
- ensureMarkerSeparation(polygonLength, markers2) {
22629
+ ensureMarkerSeparation(polygonLength, markers) {
21614
22630
  var _a2, _b2, _c;
21615
22631
  return {
21616
- menu: ((_a2 = markers2.menu) == null ? void 0 : _a2.index) ?? 0,
21617
- delete: ((_b2 = markers2.delete) == null ? void 0 : _b2.index) ?? 1,
21618
- info: ((_c = markers2.info) == null ? void 0 : _c.index) ?? 2
22632
+ menu: ((_a2 = markers.menu) == null ? void 0 : _a2.index) ?? 0,
22633
+ delete: ((_b2 = markers.delete) == null ? void 0 : _b2.index) ?? 1,
22634
+ info: ((_c = markers.info) == null ? void 0 : _c.index) ?? 2
21619
22635
  };
21620
22636
  }
21621
22637
  findAlternativeMarkerPosition(polygonLength, originalIndex, usedIndices) {
@@ -22133,6 +23149,23 @@ class CoordinateUtils {
22133
23149
  // return false;
22134
23150
  // }
22135
23151
  }
23152
+ function deepMerge(target, ...sources) {
23153
+ if (!sources.length) return target;
23154
+ for (const source of sources) {
23155
+ if (!source) continue;
23156
+ for (const key in source) {
23157
+ const sourceValue = source[key];
23158
+ const targetValue = target[key];
23159
+ if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue)) {
23160
+ const base = targetValue && typeof targetValue === "object" && !Array.isArray(targetValue) ? targetValue : {};
23161
+ target[key] = deepMerge(base, sourceValue);
23162
+ } else if (sourceValue !== void 0) {
23163
+ target[key] = sourceValue;
23164
+ }
23165
+ }
23166
+ }
23167
+ return target;
23168
+ }
22136
23169
  class Polydraw extends L$1.Control {
22137
23170
  constructor(options) {
22138
23171
  super(options);
@@ -22167,14 +23200,14 @@ class Polydraw extends L$1.Control {
22167
23200
  __publicField(this, "_handleActivateToggle", () => {
22168
23201
  const container = this.getContainer();
22169
23202
  if (!container) return;
22170
- const activate = container.querySelector(".icon-activate");
22171
- if (leafletAdapter.domUtil.hasClass(activate, "active")) {
22172
- leafletAdapter.domUtil.removeClass(activate, "active");
23203
+ const activateButton = container.querySelector(".icon-activate");
23204
+ if (leafletAdapter.domUtil.hasClass(activateButton, "active")) {
23205
+ leafletAdapter.domUtil.removeClass(activateButton, "active");
22173
23206
  if (this.subContainer) {
22174
23207
  this.subContainer.style.maxHeight = "0px";
22175
23208
  }
22176
23209
  } else {
22177
- leafletAdapter.domUtil.addClass(activate, "active");
23210
+ leafletAdapter.domUtil.addClass(activateButton, "active");
22178
23211
  if (this.subContainer) {
22179
23212
  this.subContainer.style.maxHeight = "250px";
22180
23213
  }
@@ -22228,6 +23261,18 @@ class Polydraw extends L$1.Control {
22228
23261
  this.setDrawMode(DrawMode.PointToPoint);
22229
23262
  this.polygonInformation.saveCurrentState();
22230
23263
  });
23264
+ __publicField(this, "_handlePointToPointSubtractClick", (e) => {
23265
+ if (e) {
23266
+ e.preventDefault();
23267
+ e.stopPropagation();
23268
+ }
23269
+ if (this.modeManager.getCurrentMode() === DrawMode.PointToPointSubtract) {
23270
+ this.setDrawMode(DrawMode.Off);
23271
+ return;
23272
+ }
23273
+ this.setDrawMode(DrawMode.PointToPointSubtract);
23274
+ this.polygonInformation.saveCurrentState();
23275
+ });
22231
23276
  /**
22232
23277
  * Handle marker hover when modifier key is held - event handler version
22233
23278
  */
@@ -22251,11 +23296,11 @@ class Polydraw extends L$1.Control {
22251
23296
  element.classList.remove("edge-deletion-hover");
22252
23297
  }
22253
23298
  });
22254
- this.config = defaultConfig;
23299
+ const baseDefaults = structuredClone(defaultConfig);
23300
+ this.config = deepMerge(baseDefaults, (options == null ? void 0 : options.config) ?? {});
22255
23301
  if (options == null ? void 0 : options.configPath) {
22256
23302
  this.loadExternalConfig(options.configPath, options == null ? void 0 : options.config);
22257
23303
  } else {
22258
- this.config = { ...defaultConfig, ...(options == null ? void 0 : options.config) || {} };
22259
23304
  this.initializeComponents();
22260
23305
  }
22261
23306
  }
@@ -22279,6 +23324,7 @@ class Polydraw extends L$1.Control {
22279
23324
  this.initializeUI(container);
22280
23325
  this.createTracer();
22281
23326
  this.initializeManagers();
23327
+ this.setDrawMode(this.config.defaultMode);
22282
23328
  this.setupEventListeners();
22283
23329
  return container;
22284
23330
  }
@@ -22352,6 +23398,29 @@ class Polydraw extends L$1.Control {
22352
23398
  }
22353
23399
  }
22354
23400
  }
23401
+ /**
23402
+ * Adds predefined polygons from GeoJSON to the map.
23403
+ * @param geojsonFeatures - An array of GeoJSON Polygon or MultiPolygon features.
23404
+ * @param options - Optional parameters, including visual optimization level.
23405
+ */
23406
+ async addPredefinedGeoJSONs(geojsonFeatures, options) {
23407
+ for (const geojsonFeature of geojsonFeatures) {
23408
+ const { type, coordinates } = geojsonFeature.geometry;
23409
+ if (type === "MultiPolygon") {
23410
+ for (const polygonCoords of coordinates) {
23411
+ const latLngs = polygonCoords.map(
23412
+ (ring) => ring.map((point2) => L$1.latLng(point2[1], point2[0]))
23413
+ );
23414
+ await this.addPredefinedPolygon([latLngs], options);
23415
+ }
23416
+ } else if (type === "Polygon") {
23417
+ const latLngs = coordinates.map(
23418
+ (ring) => ring.map((point2) => L$1.latLng(point2[1], point2[0]))
23419
+ );
23420
+ await this.addPredefinedPolygon([latLngs], options);
23421
+ }
23422
+ }
23423
+ }
22355
23424
  /**
22356
23425
  * Sets the current drawing mode.
22357
23426
  * @param mode - The drawing mode to set.
@@ -22359,12 +23428,12 @@ class Polydraw extends L$1.Control {
22359
23428
  setDrawMode(mode) {
22360
23429
  const previousMode = this.drawMode;
22361
23430
  this._updateDrawModeState(mode);
22362
- if (previousMode === DrawMode.PointToPoint && mode !== DrawMode.PointToPoint) {
23431
+ if ((previousMode === DrawMode.PointToPoint || previousMode === DrawMode.PointToPointSubtract) && mode !== DrawMode.PointToPoint && mode !== DrawMode.PointToPointSubtract) {
22363
23432
  this.polygonDrawManager.clearP2pMarkers();
22364
23433
  this.stopDraw();
22365
23434
  } else if (mode === DrawMode.Off) {
22366
23435
  this.stopDraw();
22367
- } else if (mode !== DrawMode.PointToPoint) {
23436
+ } else if (mode !== DrawMode.PointToPoint && mode !== DrawMode.PointToPointSubtract) {
22368
23437
  this.stopDraw();
22369
23438
  }
22370
23439
  if (this.map) {
@@ -22441,7 +23510,8 @@ class Polydraw extends L$1.Control {
22441
23510
  this._handleDrawClick,
22442
23511
  this._handleSubtractClick,
22443
23512
  this._handleEraseClick,
22444
- this._handlePointToPointClick
23513
+ this._handlePointToPointClick,
23514
+ this._handlePointToPointSubtractClick
22445
23515
  );
22446
23516
  this.ensureButtonTouchResponsiveness(container);
22447
23517
  const uiUpdateListener = (mode) => {
@@ -22484,10 +23554,14 @@ class Polydraw extends L$1.Control {
22484
23554
  this.eventManager.on("polydraw:polygon:created", async (data) => {
22485
23555
  this.stopDraw();
22486
23556
  if (data.isPointToPoint) {
22487
- await this.polygonMutationManager.addPolygon(data.polygon, {
22488
- simplify: false,
22489
- noMerge: false
22490
- });
23557
+ if (data.mode === DrawMode.PointToPointSubtract) {
23558
+ await this.polygonMutationManager.subtractPolygon(data.polygon);
23559
+ } else {
23560
+ await this.polygonMutationManager.addPolygon(data.polygon, {
23561
+ simplify: false,
23562
+ noMerge: false
23563
+ });
23564
+ }
22491
23565
  } else {
22492
23566
  await this.handleFreehandDrawCompletion(data.polygon);
22493
23567
  }
@@ -22495,7 +23569,7 @@ class Polydraw extends L$1.Control {
22495
23569
  });
22496
23570
  this.eventManager.on("polydraw:draw:cancel", () => {
22497
23571
  this.stopDraw();
22498
- this.setDrawMode(DrawMode.Off);
23572
+ this.setDrawMode(this.config.defaultMode);
22499
23573
  });
22500
23574
  }
22501
23575
  /**
@@ -22547,18 +23621,18 @@ class Polydraw extends L$1.Control {
22547
23621
  );
22548
23622
  }
22549
23623
  const externalConfig = await response.json();
22550
- this.config = {
22551
- ...defaultConfig,
22552
- ...externalConfig,
22553
- ...inlineConfig || {}
22554
- };
23624
+ this.config = deepMerge(
23625
+ structuredClone(defaultConfig),
23626
+ externalConfig ?? {},
23627
+ inlineConfig ?? {}
23628
+ );
22555
23629
  this.initializeComponents();
22556
23630
  } catch (error) {
22557
23631
  console.warn(
22558
23632
  "Failed to load external config, falling back to default + inline config:",
22559
23633
  error
22560
23634
  );
22561
- this.config = { ...defaultConfig, ...inlineConfig || {} };
23635
+ this.config = deepMerge(structuredClone(defaultConfig), inlineConfig ?? {});
22562
23636
  this.initializeComponents();
22563
23637
  }
22564
23638
  }
@@ -22611,6 +23685,12 @@ class Polydraw extends L$1.Control {
22611
23685
  dashArray: "5, 5"
22612
23686
  });
22613
23687
  break;
23688
+ case DrawMode.PointToPointSubtract:
23689
+ this.tracer.setStyle({
23690
+ color: this.config.colors.subtractLine,
23691
+ dashArray: "5, 5"
23692
+ });
23693
+ break;
22614
23694
  }
22615
23695
  } catch (error) {
22616
23696
  }
@@ -22790,7 +23870,7 @@ class Polydraw extends L$1.Control {
22790
23870
  * @param event - The touch event
22791
23871
  */
22792
23872
  handleDoubleTap(event) {
22793
- if (this.modeManager.getCurrentMode() !== DrawMode.PointToPoint) {
23873
+ if (this.modeManager.getCurrentMode() !== DrawMode.PointToPoint && this.modeManager.getCurrentMode() !== DrawMode.PointToPointSubtract) {
22794
23874
  return;
22795
23875
  }
22796
23876
  this.polygonDrawManager.handleDoubleTap(event);
@@ -22815,7 +23895,7 @@ class Polydraw extends L$1.Control {
22815
23895
  console.log("No coordinates extracted");
22816
23896
  return;
22817
23897
  }
22818
- if (this.modeManager.getCurrentMode() === DrawMode.PointToPoint) {
23898
+ if (this.modeManager.getCurrentMode() === DrawMode.PointToPoint || this.modeManager.getCurrentMode() === DrawMode.PointToPointSubtract) {
22819
23899
  console.log("Point-to-Point mode, calling handlePointToPointClick");
22820
23900
  this.polygonDrawManager.handlePointToPointClick(clickLatLng);
22821
23901
  return;
@@ -22955,7 +24035,7 @@ class Polydraw extends L$1.Control {
22955
24035
  */
22956
24036
  handleKeyDown(e) {
22957
24037
  if (e.key === "Escape") {
22958
- if (this.modeManager.getCurrentMode() === DrawMode.PointToPoint) {
24038
+ if (this.modeManager.getCurrentMode() === DrawMode.PointToPoint || this.modeManager.getCurrentMode() === DrawMode.PointToPointSubtract) {
22959
24039
  this.polygonDrawManager.cancelPointToPointDrawing();
22960
24040
  }
22961
24041
  }
@@ -23011,7 +24091,7 @@ class Polydraw extends L$1.Control {
23011
24091
  * @param e - The mouse event.
23012
24092
  */
23013
24093
  handleDoubleClick(e) {
23014
- if (this.modeManager.getCurrentMode() !== DrawMode.PointToPoint) {
24094
+ if (this.modeManager.getCurrentMode() !== DrawMode.PointToPoint && this.modeManager.getCurrentMode() !== DrawMode.PointToPointSubtract) {
23015
24095
  return;
23016
24096
  }
23017
24097
  this.polygonDrawManager.handleDoubleClick(e);
@@ -23060,11 +24140,32 @@ class Polydraw extends L$1.Control {
23060
24140
  if (!activateButton) return;
23061
24141
  const hasPolygons = this.arrayOfFeatureGroups.length > 0;
23062
24142
  const isPanelClosed = !leafletAdapter.domUtil.hasClass(activateButton, "active");
23063
- if (hasPolygons && isPanelClosed) {
24143
+ const iconMarkup = leafletAdapter.domUtil.hasClass(activateButton, "active") ? activateButton.dataset.collapsedIcon : activateButton.dataset.activeIcon;
24144
+ if (iconMarkup) {
24145
+ this.applyActivateButtonIcon(activateButton, iconMarkup);
24146
+ }
24147
+ const hasIndicator = hasPolygons && isPanelClosed;
24148
+ if (hasIndicator) {
23064
24149
  leafletAdapter.domUtil.addClass(activateButton, "polydraw-indicator-active");
23065
24150
  } else {
23066
24151
  leafletAdapter.domUtil.removeClass(activateButton, "polydraw-indicator-active");
23067
24152
  }
24153
+ const baseBackground = this.config.colors.styles.controlButton.backgroundColor;
24154
+ const baseColor = this.config.colors.styles.controlButton.color;
24155
+ const indicatorBackground = this.config.colors.styles.indicatorActive.backgroundColor;
24156
+ activateButton.style.backgroundColor = hasIndicator ? indicatorBackground : baseBackground;
24157
+ activateButton.style.color = baseColor;
24158
+ }
24159
+ applyActivateButtonIcon(button, svgMarkup) {
24160
+ button.innerHTML = svgMarkup;
24161
+ const svgElement = button.querySelector("svg");
24162
+ if (!svgElement) return;
24163
+ svgElement.setAttribute("width", "24");
24164
+ svgElement.setAttribute("height", "24");
24165
+ svgElement.style.pointerEvents = "none";
24166
+ svgElement.querySelectorAll("*").forEach((el) => {
24167
+ el.style.pointerEvents = "none";
24168
+ });
23068
24169
  }
23069
24170
  }
23070
24171
  if (typeof L$1 !== "undefined" && L$1.control) {