@sindicum/libre-draw 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/LibreDraw.d.ts +19 -1
- package/dist/core/FeatureStore.d.ts +1 -8
- package/dist/index.d.ts +1 -1
- package/dist/libre-draw.cjs +1 -1
- package/dist/libre-draw.cjs.map +1 -1
- package/dist/libre-draw.js +43 -23
- package/dist/libre-draw.js.map +1 -1
- package/dist/types/features.d.ts +7 -0
- package/dist/types/index.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -63,6 +63,7 @@ new LibreDraw(map: maplibregl.Map, options?: LibreDrawOptions)
|
|
|
63
63
|
| `setMode(mode)` | Set active mode: `'idle'`, `'draw'`, or `'select'` |
|
|
64
64
|
| `getMode()` | Get the current mode |
|
|
65
65
|
| `getFeatures()` | Get all features as an array |
|
|
66
|
+
| `toGeoJSON()` | Export all features as a GeoJSON FeatureCollection |
|
|
66
67
|
| `getFeatureById(id)` | Get a single feature by ID |
|
|
67
68
|
| `setFeatures(geojson)` | Replace all features with a GeoJSON FeatureCollection |
|
|
68
69
|
| `addFeatures(features)` | Add an array of GeoJSON Feature objects |
|
package/dist/LibreDraw.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Map as MaplibreMap } from 'maplibre-gl';
|
|
2
|
-
import type { LibreDrawFeature, LibreDrawEventMap, LibreDrawOptions } from './types';
|
|
2
|
+
import type { LibreDrawFeature, FeatureCollection, LibreDrawEventMap, LibreDrawOptions } from './types';
|
|
3
3
|
import type { ModeName } from './core/ModeManager';
|
|
4
4
|
/**
|
|
5
5
|
* LibreDraw - A MapLibre GL JS polygon drawing and editing library.
|
|
@@ -100,6 +100,24 @@ export declare class LibreDraw {
|
|
|
100
100
|
* ```
|
|
101
101
|
*/
|
|
102
102
|
getFeatures(): LibreDrawFeature[];
|
|
103
|
+
/**
|
|
104
|
+
* Export all features as a GeoJSON FeatureCollection.
|
|
105
|
+
*
|
|
106
|
+
* Returns a standard GeoJSON FeatureCollection containing all polygon
|
|
107
|
+
* features currently in the store.
|
|
108
|
+
*
|
|
109
|
+
* @returns A GeoJSON {@link FeatureCollection}.
|
|
110
|
+
*
|
|
111
|
+
* @throws {LibreDrawError} If this instance has been destroyed.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```ts
|
|
115
|
+
* const geojson = draw.toGeoJSON();
|
|
116
|
+
* console.log(JSON.stringify(geojson));
|
|
117
|
+
* // { "type": "FeatureCollection", "features": [...] }
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
toGeoJSON(): FeatureCollection;
|
|
103
121
|
/**
|
|
104
122
|
* Replace all features in the store with the given GeoJSON FeatureCollection.
|
|
105
123
|
*
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
import type { LibreDrawFeature, FeatureStoreInterface } from '../types/features';
|
|
2
|
-
/**
|
|
3
|
-
* A GeoJSON FeatureCollection containing LibreDraw polygons.
|
|
4
|
-
*/
|
|
5
|
-
export interface FeatureCollection {
|
|
6
|
-
type: 'FeatureCollection';
|
|
7
|
-
features: LibreDrawFeature[];
|
|
8
|
-
}
|
|
1
|
+
import type { LibreDrawFeature, FeatureStoreInterface, FeatureCollection } from '../types/features';
|
|
9
2
|
/**
|
|
10
3
|
* Internal store for managing LibreDraw features.
|
|
11
4
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { LibreDraw } from './LibreDraw';
|
|
2
|
-
export type { Position, PolygonGeometry, FeatureProperties, LibreDrawFeature, ActionType, Action, } from './types';
|
|
2
|
+
export type { Position, PolygonGeometry, FeatureProperties, LibreDrawFeature, FeatureCollection, ActionType, Action, } from './types';
|
|
3
3
|
export type { LibreDrawEventMap, CreateEvent, UpdateEvent, DeleteEvent, SelectionChangeEvent, ModeChangeEvent, } from './types';
|
|
4
4
|
export type { LibreDrawOptions, ToolbarOptions, ToolbarPosition, ToolbarControls, } from './types';
|
|
5
5
|
export type { NormalizedInputEvent, InputType, } from './types';
|
package/dist/libre-draw.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class ue{constructor(e){this.feature=e,this.type="create"}apply(e){e.add(this.feature)}revert(e){e.remove(this.feature.id)}}class ${constructor(e,t,s){this.id=e,this.oldFeature=t,this.newFeature=s,this.type="update"}apply(e){e.update(this.id,this.newFeature)}revert(e){e.update(this.id,this.oldFeature)}}class oe{constructor(e){this.feature=e,this.type="delete"}apply(e){e.remove(this.feature.id)}revert(e){e.add(this.feature)}}class ge{constructor(){this.listeners=new Map}on(e,t){let s=this.listeners.get(e);s||(s=new Set,this.listeners.set(e,s)),s.add(t)}off(e,t){const s=this.listeners.get(e);s&&s.delete(t)}emit(e,t){const s=this.listeners.get(e);if(s)for(const i of s)i(t)}removeAllListeners(){this.listeners.clear()}}class R{constructor(){this.features=new Map}add(e){const t=e.id||crypto.randomUUID(),s={...e,id:t};return this.features.set(t,s),s}update(e,t){this.features.has(e)&&this.features.set(e,{...t,id:e})}remove(e){const t=this.features.get(e);return t&&this.features.delete(e),t}getAll(){return Array.from(this.features.values())}getById(e){return this.features.get(e)}clear(){this.features.clear()}setAll(e){this.features.clear();for(const t of e){const s=t.id||crypto.randomUUID();this.features.set(s,{...t,id:s})}}toGeoJSON(){return{type:"FeatureCollection",features:this.getAll()}}static cloneFeature(e){return{id:e.id,type:"Feature",geometry:{type:"Polygon",coordinates:e.geometry.coordinates.map(t=>t.map(s=>[...s]))},properties:{...e.properties}}}}class fe{constructor(e=100){this.undoStack=[],this.redoStack=[],this.limit=e}push(e){this.undoStack.push(e),this.redoStack=[],this.undoStack.length>this.limit&&this.undoStack.shift()}undo(e){const t=this.undoStack.pop();return t?(t.revert(e),this.redoStack.push(t),!0):!1}redo(e){const t=this.redoStack.pop();return t?(t.apply(e),this.undoStack.push(t),!0):!1}canUndo(){return this.undoStack.length>0}canRedo(){return this.redoStack.length>0}clear(){this.undoStack=[],this.redoStack=[]}}class pe{constructor(){this.modes=new Map,this.currentModeName="idle"}registerMode(e,t){this.modes.set(e,t)}setOnModeChange(e){this.onModeChange=e}setMode(e){if(e===this.currentModeName)return;const t=this.currentModeName,s=this.modes.get(this.currentModeName);s&&s.deactivate(),this.currentModeName=e;const i=this.modes.get(e);i&&i.activate(),this.onModeChange&&this.onModeChange(e,t)}getMode(){return this.currentModeName}getCurrentMode(){return this.modes.get(this.currentModeName)}}class v extends Error{constructor(e){super(e),this.name="LibreDrawError"}}function z(r,e,t){const s=(e[1]-r[1])*(t[0]-e[0])-(e[0]-r[0])*(t[1]-e[1]);return Math.abs(s)<1e-10?0:s>0?1:2}function j(r,e,t){return e[0]<=Math.max(r[0],t[0])&&e[0]>=Math.min(r[0],t[0])&&e[1]<=Math.max(r[1],t[1])&&e[1]>=Math.min(r[1],t[1])}function X(r,e){return Math.abs(r[0]-e[0])<1e-10&&Math.abs(r[1]-e[1])<1e-10}function q(r,e,t,s){if(X(r,t)||X(r,s)||X(e,t)||X(e,s))return!1;const i=z(r,e,t),n=z(r,e,s),o=z(t,s,r),l=z(t,s,e);return!!(i!==n&&o!==l||i===0&&j(r,t,e)||n===0&&j(r,s,e)||o===0&&j(t,r,s)||l===0&&j(t,e,s))}function ae(r){const e=r.length-1;if(e<3)return!1;for(let t=0;t<e;t++)for(let s=t+2;s<e;s++)if(!(t===0&&s===e-1)&&q(r[t],r[t+1],r[s],r[s+1]))return!0;return!1}function ye(r,e){if(r.length<2)return!1;const t=r[r.length-1];for(let s=0;s<r.length-2;s++)if(q(t,e,r[s],r[s+1]))return!0;return!1}function J(r){if(r.length<3)return!1;const e=r[0],t=r[r.length-1];for(let s=1;s<r.length-2;s++)if(q(t,e,r[s],r[s+1]))return!0;return!1}function me(r,e){return r[0]===e[0]&&r[1]===e[1]}function be(r){const[e,t]=r;if(typeof e!="number"||typeof t!="number")throw new v(`Invalid coordinate: expected [number, number], got [${typeof e}, ${typeof t}]`);if(e<-180||e>180)throw new v(`Invalid longitude: ${e}. Must be between -180 and 180.`);if(t<-90||t>90)throw new v(`Invalid latitude: ${t}. Must be between -90 and 90.`)}function ve(r){if(!Array.isArray(r))throw new v("Ring must be an array of positions.");if(r.length<4)throw new v(`Ring must have at least 4 positions (got ${r.length}). A valid polygon ring requires 3 unique vertices plus a closing vertex.`);const e=r[0],t=r[r.length-1];if(!me(e,t))throw new v("Ring is not closed. The first and last positions must be identical.");for(const s of r){if(!Array.isArray(s)||s.length<2)throw new v("Each position in a ring must be an array of at least 2 numbers.");be(s)}if(ae(r))throw new v("Ring has self-intersections. Polygon edges must not cross each other.")}function le(r){if(r==null||typeof r!="object")throw new v("Feature must be a non-null object.");const e=r;if(e.type!=="Feature")throw new v(`Feature.type must be "Feature", got "${String(e.type)}".`);if(e.geometry===null||e.geometry===void 0||typeof e.geometry!="object")throw new v("Feature.geometry must be a non-null object.");const t=e.geometry;if(t.type!=="Polygon")throw new v(`Feature.geometry.type must be "Polygon", got "${String(t.type)}".`);if(!Array.isArray(t.coordinates))throw new v("Feature.geometry.coordinates must be an array.");const s=t.coordinates;if(s.length===0)throw new v("Polygon must have at least one ring (outer ring).");for(const i of s)ve(i);return r}function Ee(r){if(r==null||typeof r!="object")throw new v("GeoJSON must be a non-null object.");const e=r;if(e.type!=="FeatureCollection")throw new v(`GeoJSON.type must be "FeatureCollection", got "${String(e.type)}".`);if(!Array.isArray(e.features))throw new v("GeoJSON.features must be an array.");const t=r,s=[];for(let i=0;i<t.features.length;i++)try{s.push(le(t.features[i]))}catch(n){throw n instanceof v?new v(`Invalid feature at index ${i}: ${n.message}`):n}return{type:"FeatureCollection",features:s}}class Ie{activate(){}deactivate(){}onPointerDown(e){}onPointerMove(e){}onPointerUp(e){}onDoubleClick(e){}onLongPress(e){}onKeyDown(e,t){}}const we=10,W=3;class Se{constructor(e){this.vertices=[],this.isActive=!1,this.callbacks=e}activate(){this.isActive=!0,this.vertices=[]}deactivate(){this.isActive=!1,this.vertices=[],this.callbacks.clearPreview()}onPointerDown(e){if(!this.isActive)return;const t=[e.lngLat.lng,e.lngLat.lat];if(this.vertices.length>=W){const s=this.vertices[0],i=this.callbacks.getScreenPoint({lng:s[0],lat:s[1]}),n=e.point.x-i.x,o=e.point.y-i.y;if(Math.sqrt(n*n+o*o)<=we){if(J(this.vertices))return;this.finalizePolygon();return}}ye(this.vertices,t)||(this.vertices.push(t),this.updatePreview(e))}onPointerMove(e){!this.isActive||this.vertices.length===0||this.updatePreview(e)}onPointerUp(e){}onDoubleClick(e){this.isActive&&(this.vertices.length>W&&this.vertices.pop(),this.vertices.length>=W&&(J(this.vertices)||this.finalizePolygon()),e.originalEvent.preventDefault(),e.originalEvent.stopPropagation())}onLongPress(e){this.isActive&&this.vertices.length>0&&(this.vertices.pop(),this.vertices.length===0?this.callbacks.clearPreview():this.callbacks.renderPreview(this.buildPreviewCoordinates()))}onKeyDown(e,t){this.isActive&&e==="Escape"&&this.cancelDrawing()}buildPreviewCoordinates(e){const t=[...this.vertices];return e&&t.push(e),t.length>0&&t.push([...t[0]]),t}updatePreview(e){const t=[e.lngLat.lng,e.lngLat.lat],s=this.buildPreviewCoordinates(t);this.callbacks.renderPreview(s)}finalizePolygon(){if(this.vertices.length<W)return;const e=[...this.vertices,[...this.vertices[0]]],t={id:crypto.randomUUID(),type:"Feature",geometry:{type:"Polygon",coordinates:[e]},properties:{}},s=this.callbacks.addFeatureToStore(t),i=new ue(s);this.callbacks.pushToHistory(i),this.callbacks.emitEvent("create",{feature:s}),this.callbacks.renderFeatures(),this.vertices=[],this.callbacks.clearPreview()}cancelDrawing(){this.vertices=[],this.callbacks.clearPreview()}}const N=11102230246251565e-32,F=134217729,Te=(3+8*N)*N;function Y(r,e,t,s,i){let n,o,l,h,d=e[0],u=s[0],a=0,c=0;u>d==u>-d?(n=d,d=e[++a]):(n=u,u=s[++c]);let g=0;if(a<r&&c<t)for(u>d==u>-d?(o=d+n,l=n-(o-d),d=e[++a]):(o=u+n,l=n-(o-u),u=s[++c]),n=o,l!==0&&(i[g++]=l);a<r&&c<t;)u>d==u>-d?(o=n+d,h=o-n,l=n-(o-h)+(d-h),d=e[++a]):(o=n+u,h=o-n,l=n-(o-h)+(u-h),u=s[++c]),n=o,l!==0&&(i[g++]=l);for(;a<r;)o=n+d,h=o-n,l=n-(o-h)+(d-h),d=e[++a],n=o,l!==0&&(i[g++]=l);for(;c<t;)o=n+u,h=o-n,l=n-(o-h)+(u-h),u=s[++c],n=o,l!==0&&(i[g++]=l);return(n!==0||g===0)&&(i[g++]=n),g}function Me(r,e){let t=e[0];for(let s=1;s<r;s++)t+=e[s];return t}function H(r){return new Float64Array(r)}const Pe=(3+16*N)*N,ke=(2+12*N)*N,Fe=(9+64*N)*N*N,O=H(4),Q=H(8),Z=H(12),ee=H(16),D=H(4);function De(r,e,t,s,i,n,o){let l,h,d,u,a,c,g,y,p,m,f,b,T,I,M,P,C,k;const L=r-i,x=t-i,V=e-n,A=s-n;I=L*A,c=F*L,g=c-(c-L),y=L-g,c=F*A,p=c-(c-A),m=A-p,M=y*m-(I-g*p-y*p-g*m),P=V*x,c=F*V,g=c-(c-V),y=V-g,c=F*x,p=c-(c-x),m=x-p,C=y*m-(P-g*p-y*p-g*m),f=M-C,a=M-f,O[0]=M-(f+a)+(a-C),b=I+f,a=b-I,T=I-(b-a)+(f-a),f=T-P,a=T-f,O[1]=T-(f+a)+(a-P),k=b+f,a=k-b,O[2]=b-(k-a)+(f-a),O[3]=k;let _=Me(4,O),U=ke*o;if(_>=U||-_>=U||(a=r-L,l=r-(L+a)+(a-i),a=t-x,d=t-(x+a)+(a-i),a=e-V,h=e-(V+a)+(a-n),a=s-A,u=s-(A+a)+(a-n),l===0&&h===0&&d===0&&u===0)||(U=Fe*o+Te*Math.abs(_),_+=L*u+A*l-(V*d+x*h),_>=U||-_>=U))return _;I=l*A,c=F*l,g=c-(c-l),y=l-g,c=F*A,p=c-(c-A),m=A-p,M=y*m-(I-g*p-y*p-g*m),P=h*x,c=F*h,g=c-(c-h),y=h-g,c=F*x,p=c-(c-x),m=x-p,C=y*m-(P-g*p-y*p-g*m),f=M-C,a=M-f,D[0]=M-(f+a)+(a-C),b=I+f,a=b-I,T=I-(b-a)+(f-a),f=T-P,a=T-f,D[1]=T-(f+a)+(a-P),k=b+f,a=k-b,D[2]=b-(k-a)+(f-a),D[3]=k;const ce=Y(4,O,4,D,Q);I=L*u,c=F*L,g=c-(c-L),y=L-g,c=F*u,p=c-(c-u),m=u-p,M=y*m-(I-g*p-y*p-g*m),P=V*d,c=F*V,g=c-(c-V),y=V-g,c=F*d,p=c-(c-d),m=d-p,C=y*m-(P-g*p-y*p-g*m),f=M-C,a=M-f,D[0]=M-(f+a)+(a-C),b=I+f,a=b-I,T=I-(b-a)+(f-a),f=T-P,a=T-f,D[1]=T-(f+a)+(a-P),k=b+f,a=k-b,D[2]=b-(k-a)+(f-a),D[3]=k;const he=Y(ce,Q,4,D,Z);I=l*u,c=F*l,g=c-(c-l),y=l-g,c=F*u,p=c-(c-u),m=u-p,M=y*m-(I-g*p-y*p-g*m),P=h*d,c=F*h,g=c-(c-h),y=h-g,c=F*d,p=c-(c-d),m=d-p,C=y*m-(P-g*p-y*p-g*m),f=M-C,a=M-f,D[0]=M-(f+a)+(a-C),b=I+f,a=b-I,T=I-(b-a)+(f-a),f=T-P,a=T-f,D[1]=T-(f+a)+(a-P),k=b+f,a=k-b,D[2]=b-(k-a)+(f-a),D[3]=k;const de=Y(he,Z,4,D,ee);return ee[de-1]}function Ce(r,e,t,s,i,n){const o=(e-n)*(t-i),l=(r-i)*(s-n),h=o-l,d=Math.abs(o+l);return Math.abs(h)>=Pe*d?h:-De(r,e,t,s,i,n,d)}function Le(r,e){var t,s,i=0,n,o,l,h,d,u,a,c=r[0],g=r[1],y=e.length;for(t=0;t<y;t++){s=0;var p=e[t],m=p.length-1;if(u=p[0],u[0]!==p[m][0]&&u[1]!==p[m][1])throw new Error("First and last coordinates in a ring must be the same");for(o=u[0]-c,l=u[1]-g,s;s<m;s++){if(a=p[s+1],h=a[0]-c,d=a[1]-g,l===0&&d===0){if(h<=0&&o>=0||o<=0&&h>=0)return 0}else if(d>=0&&l<=0||d<=0&&l>=0){if(n=Ce(o,h,l,d,0,0),n===0)return 0;(n>0&&d>0&&l<=0||n<0&&d<=0&&l>0)&&i++}u=a,l=d,o=h}}return i%2!==0}function xe(r,e,t={}){const s={type:"Feature"};return(t.id===0||t.id)&&(s.id=t.id),t.bbox&&(s.bbox=t.bbox),s.properties={},s.geometry=r,s}function te(r,e,t={}){if(!r)throw new Error("coordinates is required");if(!Array.isArray(r))throw new Error("coordinates must be an Array");if(r.length<2)throw new Error("coordinates must be at least 2 numbers long");if(!se(r[0])||!se(r[1]))throw new Error("coordinates must contain numbers");return xe({type:"Point",coordinates:r},e,t)}function se(r){return!isNaN(r)&&r!==null&&!Array.isArray(r)}function Ve(r){if(!r)throw new Error("coord is required");if(!Array.isArray(r)){if(r.type==="Feature"&&r.geometry!==null&&r.geometry.type==="Point")return[...r.geometry.coordinates];if(r.type==="Point")return[...r.coordinates]}if(Array.isArray(r)&&r.length>=2&&!Array.isArray(r[0])&&!Array.isArray(r[1]))return[...r];throw new Error("coord must be GeoJSON Point or an Array of numbers")}function Ae(r){return r.type==="Feature"?r.geometry:r}function _e(r,e,t={}){if(!r)throw new Error("point is required");if(!e)throw new Error("polygon is required");const s=Ve(r),i=Ae(e),n=i.type,o=e.bbox;let l=i.coordinates;if(o&&Re(s,o)===!1)return!1;n==="Polygon"&&(l=[l]);let h=!1;for(var d=0;d<l.length;++d){const u=Le(s,l[d]);if(u===0)return!t.ignoreBoundary;u&&(h=!0)}return h}function Re(r,e){return e[0]<=r[0]&&e[1]<=r[1]&&e[2]>=r[0]&&e[3]>=r[1]}var ie=_e;const re=10,Ne=24,ne=3;class Oe{constructor(e,t){this.selectedIds=new Set,this.isActive=!1,this.dragging=!1,this.dragVertexIndex=-1,this.dragStartFeature=null,this.draggingPolygon=!1,this.dragPolygonStartLngLat=null,this.highlightedVertexIndex=-1,this.callbacks=e,this.onSelectionChange=t}activate(){this.isActive=!0}deactivate(){this.isActive=!1,this.highlightedVertexIndex=-1,this.endDrag(),this.selectedIds.size>0&&(this.selectedIds.clear(),this.callbacks.clearVertices(),this.notifySelectionChange())}getSelectedIds(){return Array.from(this.selectedIds)}selectFeature(e){if(!this.isActive)return!1;const t=this.callbacks.getFeatureById(e);return t?(this.highlightedVertexIndex=-1,this.endDrag(),this.selectedIds.clear(),this.selectedIds.add(e),this.showVertexHandles(t),this.notifySelectionChange(),this.callbacks.renderFeatures(),!0):!1}clearSelection(){this.isActive&&this.selectedIds.size!==0&&(this.highlightedVertexIndex=-1,this.endDrag(),this.selectedIds.clear(),this.callbacks.clearVertices(),this.notifySelectionChange(),this.callbacks.renderFeatures())}onPointerDown(e){if(!this.isActive)return;const t=this.getFirstSelectedId();if(t){const o=this.callbacks.getFeatureById(t);if(o){const l=this.getVertices(o),h=this.getThreshold(e),d=this.findNearestVertex(l,e.point,h);if(d>=0){this.startDrag(o,d);return}const u=this.computeMidpoints(l),a=this.findNearestPoint(u,e.point,h);if(a>=0){const g=R.cloneFeature(o),y=this.insertVertex(o,a+1,u[a]);this.callbacks.updateFeatureInStore(t,y),this.showVertexHandles(y),this.startDrag(y,a+1),this.dragStartFeature=g;return}const c=te([e.lngLat.lng,e.lngLat.lat]);if(ie(c,o.geometry)){this.startPolygonDrag(o,e.lngLat);return}}}this.highlightedVertexIndex=-1;const s=te([e.lngLat.lng,e.lngLat.lat]),i=this.callbacks.getAllFeatures();let n;for(let o=i.length-1;o>=0;o--){const l=i[o],h=l.geometry;if(ie(s,h)){n=l;break}}n?this.selectedIds.has(n.id)?(this.selectedIds.delete(n.id),this.callbacks.clearVertices()):(this.selectedIds.clear(),this.selectedIds.add(n.id),this.showVertexHandles(n)):(this.selectedIds.clear(),this.callbacks.clearVertices()),this.notifySelectionChange(),this.callbacks.renderFeatures()}onPointerMove(e){if(!this.isActive)return;if(this.dragging){const l=this.getFirstSelectedId();if(!l)return;const h=this.callbacks.getFeatureById(l);if(!h)return;const d=[e.lngLat.lng,e.lngLat.lat],u=this.moveVertex(h,this.dragVertexIndex,d);if(ae(u.geometry.coordinates[0]))return;this.callbacks.updateFeatureInStore(l,u),this.callbacks.renderFeatures(),this.showVertexHandles(u);return}if(this.draggingPolygon){const l=this.getFirstSelectedId();if(!l||!this.dragStartFeature||!this.dragPolygonStartLngLat)return;const h=e.lngLat.lng-this.dragPolygonStartLngLat.lng,d=e.lngLat.lat-this.dragPolygonStartLngLat.lat,u=this.movePolygon(this.dragStartFeature,h,d);this.callbacks.updateFeatureInStore(l,u),this.callbacks.renderFeatures(),this.showVertexHandles(u);return}const t=this.getFirstSelectedId();if(!t)return;const s=this.callbacks.getFeatureById(t);if(!s)return;const i=this.getVertices(s),n=this.getThreshold(e),o=this.findNearestVertex(i,e.point,n);o!==this.highlightedVertexIndex&&(this.highlightedVertexIndex=o,this.showVertexHandles(s))}onPointerUp(e){if(!this.isActive||!this.dragging&&!this.draggingPolygon)return;const t=this.getFirstSelectedId();if(!t||!this.dragStartFeature){this.endDrag();return}const s=this.callbacks.getFeatureById(t);if(s){const i=new $(t,this.dragStartFeature,R.cloneFeature(s));this.callbacks.pushToHistory(i),this.callbacks.emitEvent("update",{feature:s,oldFeature:this.dragStartFeature})}this.endDrag()}onDoubleClick(e){if(!this.isActive)return;const t=this.getFirstSelectedId();if(!t)return;const s=this.callbacks.getFeatureById(t);if(!s)return;const i=this.getVertices(s),n=this.getThreshold(e),o=this.findNearestVertex(i,e.point,n);if(o>=0&&i.length>ne){const l=R.cloneFeature(s),h=this.removeVertex(s,o);this.callbacks.updateFeatureInStore(t,h);const d=new $(t,l,R.cloneFeature(h));this.callbacks.pushToHistory(d),this.callbacks.emitEvent("update",{feature:h,oldFeature:l}),this.callbacks.renderFeatures(),this.showVertexHandles(h),e.originalEvent.preventDefault(),e.originalEvent.stopPropagation()}}onLongPress(e){if(!this.isActive)return;const t=this.getFirstSelectedId();if(!t)return;const s=this.callbacks.getFeatureById(t);if(!s)return;const i=this.getVertices(s),n=this.getThreshold(e),o=this.findNearestVertex(i,e.point,n);if(o>=0&&i.length>ne){const l=R.cloneFeature(s),h=this.removeVertex(s,o);this.callbacks.updateFeatureInStore(t,h);const d=new $(t,l,R.cloneFeature(h));this.callbacks.pushToHistory(d),this.callbacks.emitEvent("update",{feature:h,oldFeature:l}),this.callbacks.renderFeatures(),this.showVertexHandles(h)}}onKeyDown(e,t){this.isActive&&(e==="Delete"||e==="Backspace")&&this.deleteSelected()}getThreshold(e){return e.inputType==="touch"?Ne:re}getVertices(e){const t=e.geometry.coordinates[0];return t.slice(0,t.length-1)}findNearestVertex(e,t,s){return this.findNearestPoint(e,t,s)}findNearestPoint(e,t,s=re){let i=1/0,n=-1;for(let o=0;o<e.length;o++){const l=this.callbacks.getScreenPoint({lng:e[o][0],lat:e[o][1]}),h=t.x-l.x,d=t.y-l.y,u=Math.sqrt(h*h+d*d);u<=s&&u<i&&(i=u,n=o)}return n}computeMidpoints(e){const t=[];for(let s=0;s<e.length;s++){const i=(s+1)%e.length;t.push([(e[s][0]+e[i][0])/2,(e[s][1]+e[i][1])/2])}return t}startDrag(e,t){this.dragging=!0,this.dragVertexIndex=t,this.dragStartFeature=R.cloneFeature(e),this.callbacks.setDragPan(!1)}startPolygonDrag(e,t){this.draggingPolygon=!0,this.dragPolygonStartLngLat=t,this.dragStartFeature=R.cloneFeature(e),this.callbacks.setDragPan(!1)}endDrag(){(this.dragging||this.draggingPolygon)&&this.callbacks.setDragPan(!0),this.dragging=!1,this.dragVertexIndex=-1,this.dragStartFeature=null,this.draggingPolygon=!1,this.dragPolygonStartLngLat=null,this.highlightedVertexIndex=-1}moveVertex(e,t,s){const i=[...e.geometry.coordinates[0]];return i[t]=s,t===0&&(i[i.length-1]=s),t===i.length-1&&(i[0]=s),{...e,geometry:{type:"Polygon",coordinates:[i]}}}movePolygon(e,t,s){const i=e.geometry.coordinates[0].map(n=>[n[0]+t,n[1]+s]);return{...e,geometry:{type:"Polygon",coordinates:[i]}}}insertVertex(e,t,s){const i=[...e.geometry.coordinates[0]];return i.splice(t,0,s),{...e,geometry:{type:"Polygon",coordinates:[i]}}}removeVertex(e,t){const i=this.getVertices(e).filter((o,l)=>l!==t),n=[...i,[...i[0]]];return{...e,geometry:{type:"Polygon",coordinates:[n]}}}refreshVertexHandles(){if(!this.isActive)return;const e=this.getFirstSelectedId();if(!e)return;const t=this.callbacks.getFeatureById(e);t?this.showVertexHandles(t):(this.selectedIds.delete(e),this.callbacks.clearVertices(),this.notifySelectionChange())}showVertexHandles(e){const t=this.getVertices(e),s=this.computeMidpoints(t);this.callbacks.renderVertices(e.id,t,s,this.highlightedVertexIndex>=0?this.highlightedVertexIndex:void 0)}getFirstSelectedId(){return this.selectedIds.values().next().value}deleteSelected(){if(this.selectedIds.size===0)return;const e=Array.from(this.selectedIds);for(const t of e){const s=this.callbacks.getFeatureById(t);if(s){this.callbacks.removeFeatureFromStore(t);const i=new oe(s);this.callbacks.pushToHistory(i),this.callbacks.emitEvent("delete",{feature:s})}}this.selectedIds.clear(),this.callbacks.clearVertices(),this.notifySelectionChange(),this.callbacks.renderFeatures()}notifySelectionChange(){const e=this.getSelectedIds();this.callbacks.emitEvent("selectionchange",{selectedIds:e}),this.onSelectionChange&&this.onSelectionChange(e)}}class Ue{constructor(e,t){this.handleMouseDown=s=>{this.callbacks.onPointerDown(this.normalize(s))},this.handleMouseMove=s=>{this.callbacks.onPointerMove(this.normalize(s))},this.handleMouseUp=s=>{this.callbacks.onPointerUp(this.normalize(s))},this.handleDblClick=s=>{this.callbacks.onDoubleClick(this.normalize(s))},this.map=e,this.callbacks=t,this.canvas=e.getCanvasContainer()}enable(){this.canvas.addEventListener("mousedown",this.handleMouseDown),this.canvas.addEventListener("mousemove",this.handleMouseMove),this.canvas.addEventListener("mouseup",this.handleMouseUp),this.canvas.addEventListener("dblclick",this.handleDblClick)}disable(){this.canvas.removeEventListener("mousedown",this.handleMouseDown),this.canvas.removeEventListener("mousemove",this.handleMouseMove),this.canvas.removeEventListener("mouseup",this.handleMouseUp),this.canvas.removeEventListener("dblclick",this.handleDblClick)}destroy(){this.disable()}normalize(e){const t=this.canvas.getBoundingClientRect(),s=e.clientX-t.left,i=e.clientY-t.top,n=this.map.unproject([s,i]);return{lngLat:{lng:n.lng,lat:n.lat},point:{x:s,y:i},originalEvent:e,inputType:"mouse"}}}const Be=300,He=500,ze=15;class je{constructor(e,t){this.lastTapTime=0,this.longPressTimer=null,this.touchStartPos=null,this.isPinching=!1,this.handleTouchStart=s=>{if(s.touches.length>=2){this.isPinching=!0,this.cancelLongPress();return}this.isPinching=!1;const i=this.normalize(s);this.touchStartPos={x:i.point.x,y:i.point.y},this.cancelLongPress(),this.longPressTimer=setTimeout(()=>{this.touchStartPos&&(this.callbacks.onLongPress(i),this.touchStartPos=null)},He),this.callbacks.onPointerDown(i)},this.handleTouchMove=s=>{if(this.isPinching||s.touches.length>=2){this.cancelLongPress();return}const i=this.normalize(s);if(this.touchStartPos){const n=i.point.x-this.touchStartPos.x,o=i.point.y-this.touchStartPos.y;Math.sqrt(n*n+o*o)>ze&&this.cancelLongPress()}this.callbacks.onPointerMove(i)},this.handleTouchEnd=s=>{if(this.cancelLongPress(),this.isPinching){s.touches.length===0&&(this.isPinching=!1);return}if(s.changedTouches.length===0)return;const i=this.normalizeChangedTouch(s),n=Date.now();n-this.lastTapTime<Be?(this.callbacks.onDoubleClick(i),this.lastTapTime=0):this.lastTapTime=n,this.touchStartPos&&(this.callbacks.onPointerUp(i),this.touchStartPos=null)},this.map=e,this.callbacks=t,this.canvas=e.getCanvasContainer()}enable(){this.canvas.addEventListener("touchstart",this.handleTouchStart,{passive:!1}),this.canvas.addEventListener("touchmove",this.handleTouchMove,{passive:!1}),this.canvas.addEventListener("touchend",this.handleTouchEnd)}disable(){this.canvas.removeEventListener("touchstart",this.handleTouchStart),this.canvas.removeEventListener("touchmove",this.handleTouchMove),this.canvas.removeEventListener("touchend",this.handleTouchEnd),this.cancelLongPress()}destroy(){this.disable()}cancelLongPress(){this.longPressTimer!==null&&(clearTimeout(this.longPressTimer),this.longPressTimer=null)}normalize(e){const t=e.touches[0],s=this.canvas.getBoundingClientRect(),i=t.clientX-s.left,n=t.clientY-s.top,o=this.map.unproject([i,n]);return{lngLat:{lng:o.lng,lat:o.lat},point:{x:i,y:n},originalEvent:e,inputType:"touch"}}normalizeChangedTouch(e){const t=e.changedTouches[0],s=this.canvas.getBoundingClientRect(),i=t.clientX-s.left,n=t.clientY-s.top,o=this.map.unproject([i,n]);return{lngLat:{lng:o.lng,lat:o.lat},point:{x:i,y:n},originalEvent:e,inputType:"touch"}}}const K=class K{constructor(e){this.handleKeyDown=t=>{K.RELEVANT_KEYS.has(t.key)&&this.callbacks.onKeyDown(t.key,t)},this.callbacks=e}enable(){document.addEventListener("keydown",this.handleKeyDown)}disable(){document.removeEventListener("keydown",this.handleKeyDown)}destroy(){this.disable()}};K.RELEVANT_KEYS=new Set(["Escape","Delete","Backspace"]);let G=K;class Xe{constructor(e,t){this.getActiveMode=t;const s={onPointerDown:i=>{var n;(n=this.getActiveMode())==null||n.onPointerDown(i)},onPointerMove:i=>{var n;(n=this.getActiveMode())==null||n.onPointerMove(i)},onPointerUp:i=>{var n;(n=this.getActiveMode())==null||n.onPointerUp(i)},onDoubleClick:i=>{var n;(n=this.getActiveMode())==null||n.onDoubleClick(i)},onLongPress:i=>{var n;(n=this.getActiveMode())==null||n.onLongPress(i)}};this.mouseInput=new Ue(e,s),this.touchInput=new je(e,s),this.keyboardInput=new G({onKeyDown:(i,n)=>{var o;(o=this.getActiveMode())==null||o.onKeyDown(i,n)}})}enable(){this.mouseInput.enable(),this.touchInput.enable(),this.keyboardInput.enable()}disable(){this.mouseInput.disable(),this.touchInput.disable(),this.keyboardInput.disable()}destroy(){this.mouseInput.destroy(),this.touchInput.destroy(),this.keyboardInput.destroy()}}const E={FEATURES:"libre-draw-features",PREVIEW:"libre-draw-preview",EDIT_VERTICES:"libre-draw-edit-vertices"},B={type:"FeatureCollection",features:[]};class We{constructor(e){this.initialized=!1,this.map=e}initialize(){this.initialized||(this.map.getSource(E.FEATURES)||this.map.addSource(E.FEATURES,{type:"geojson",data:B}),this.map.getSource(E.PREVIEW)||this.map.addSource(E.PREVIEW,{type:"geojson",data:B}),this.map.getSource(E.EDIT_VERTICES)||this.map.addSource(E.EDIT_VERTICES,{type:"geojson",data:B}),this.initialized=!0)}updateFeatures(e){const t=this.map.getSource(E.FEATURES);t&&t.setData(e)}updatePreview(e){const t=this.map.getSource(E.PREVIEW);t&&t.setData(e)}clearPreview(){this.updatePreview(B)}updateEditVertices(e){const t=this.map.getSource(E.EDIT_VERTICES);t&&t.setData(e)}clearEditVertices(){this.updateEditVertices(B)}destroy(){this.map.getSource(E.FEATURES)&&this.map.removeSource(E.FEATURES),this.map.getSource(E.PREVIEW)&&this.map.removeSource(E.PREVIEW),this.map.getSource(E.EDIT_VERTICES)&&this.map.removeSource(E.EDIT_VERTICES),this.initialized=!1}}const S={FILL:"libre-draw-fill",OUTLINE:"libre-draw-outline",VERTICES:"libre-draw-vertices",PREVIEW:"libre-draw-preview",EDIT_VERTICES:"libre-draw-edit-vertices",EDIT_MIDPOINTS:"libre-draw-edit-midpoints"},w={FILL:"#3bb2d0",FILL_OPACITY:.2,FILL_SELECTED:"#fbb03b",FILL_SELECTED_OPACITY:.4,OUTLINE:"#3bb2d0",OUTLINE_WIDTH:2,OUTLINE_SELECTED:"#fbb03b",VERTEX_COLOR:"#ffffff",VERTEX_STROKE:"#3bb2d0",VERTEX_RADIUS:4,PREVIEW_OUTLINE:"#3bb2d0",PREVIEW_OUTLINE_DASH:[2,2],EDIT_VERTEX_COLOR:"#ffffff",EDIT_VERTEX_STROKE:"#3bb2d0",EDIT_VERTEX_RADIUS:5,EDIT_VERTEX_STROKE_WIDTH:2,MIDPOINT_COLOR:"#3bb2d0",MIDPOINT_OPACITY:.5,MIDPOINT_RADIUS:3};class Ke{constructor(e,t){this.selectedIds=new Set,this.pendingRender=!1,this.pendingFeatures=null,this.initialized=!1,this.map=e,this.sourceManager=t}initialize(){this.initialized||(this.sourceManager.initialize(),this.map.getLayer(S.FILL)||this.map.addLayer({id:S.FILL,type:"fill",source:E.FEATURES,paint:{"fill-color":["case",["boolean",["get","_selected"],!1],w.FILL_SELECTED,w.FILL],"fill-opacity":["case",["boolean",["get","_selected"],!1],w.FILL_SELECTED_OPACITY,w.FILL_OPACITY]}}),this.map.getLayer(S.OUTLINE)||this.map.addLayer({id:S.OUTLINE,type:"line",source:E.FEATURES,paint:{"line-color":["case",["boolean",["get","_selected"],!1],w.OUTLINE_SELECTED,w.OUTLINE],"line-width":w.OUTLINE_WIDTH}}),this.map.getLayer(S.VERTICES)||this.map.addLayer({id:S.VERTICES,type:"circle",source:E.FEATURES,filter:["==","$type","Point"],paint:{"circle-radius":w.VERTEX_RADIUS,"circle-color":w.VERTEX_COLOR,"circle-stroke-color":w.VERTEX_STROKE,"circle-stroke-width":2}}),this.map.getLayer(S.PREVIEW)||this.map.addLayer({id:S.PREVIEW,type:"line",source:E.PREVIEW,paint:{"line-color":w.PREVIEW_OUTLINE,"line-width":2,"line-dasharray":w.PREVIEW_OUTLINE_DASH}}),this.map.getLayer(S.EDIT_MIDPOINTS)||this.map.addLayer({id:S.EDIT_MIDPOINTS,type:"circle",source:E.EDIT_VERTICES,filter:["==",["get","_type"],"midpoint"],paint:{"circle-radius":w.MIDPOINT_RADIUS,"circle-color":w.MIDPOINT_COLOR,"circle-opacity":w.MIDPOINT_OPACITY}}),this.map.getLayer(S.EDIT_VERTICES)||this.map.addLayer({id:S.EDIT_VERTICES,type:"circle",source:E.EDIT_VERTICES,filter:["==",["get","_type"],"vertex"],paint:{"circle-radius":["case",["boolean",["get","_highlighted"],!1],7,w.EDIT_VERTEX_RADIUS],"circle-color":["case",["boolean",["get","_highlighted"],!1],"#ff4444",w.EDIT_VERTEX_COLOR],"circle-stroke-color":["case",["boolean",["get","_highlighted"],!1],"#cc0000",w.EDIT_VERTEX_STROKE],"circle-stroke-width":w.EDIT_VERTEX_STROKE_WIDTH}}),this.initialized=!0)}render(e){this.pendingFeatures=e,this.pendingRender||(this.pendingRender=!0,requestAnimationFrame(()=>{this.performRender(),this.pendingRender=!1}))}renderPreview(e){if(e.length<2){this.clearPreview();return}const t=e.map(i=>[i[0],i[1]]),s={type:"FeatureCollection",features:[{type:"Feature",properties:{},geometry:{type:"LineString",coordinates:t}}]};this.sourceManager.updatePreview(s)}clearPreview(){this.sourceManager.clearPreview()}renderVertices(e,t,s){const i=[];for(let n=0;n<e.length;n++){const o=e[n];i.push({type:"Feature",properties:{_type:"vertex",_highlighted:n===s},geometry:{type:"Point",coordinates:[o[0],o[1]]}})}for(const n of t)i.push({type:"Feature",properties:{_type:"midpoint"},geometry:{type:"Point",coordinates:[n[0],n[1]]}});this.sourceManager.updateEditVertices({type:"FeatureCollection",features:i})}clearVertices(){this.sourceManager.clearEditVertices()}setSelectedIds(e){this.selectedIds=new Set(e)}destroy(){const e=[S.EDIT_VERTICES,S.EDIT_MIDPOINTS,S.PREVIEW,S.VERTICES,S.OUTLINE,S.FILL];for(const t of e)this.map.getLayer(t)&&this.map.removeLayer(t);this.sourceManager.destroy(),this.initialized=!1}performRender(){if(!this.pendingFeatures)return;const t={type:"FeatureCollection",features:this.pendingFeatures.map(s=>({type:"Feature",id:s.id,properties:{...s.properties,_id:s.id,_selected:this.selectedIds.has(s.id)},geometry:s.geometry}))};this.sourceManager.updateFeatures(t),this.pendingFeatures=null}}class $e{constructor(e){this.options=e,this.element=document.createElement("button"),this.element.type="button",this.element.title=e.title,this.element.setAttribute("aria-label",e.title),this.element.dataset.libreDrawButton=e.id,this.applyStyles(),this.iconContainer=document.createElement("span"),this.iconContainer.style.display="flex",this.iconContainer.style.alignItems="center",this.iconContainer.style.justifyContent="center",this.setIcon(e.icon),this.element.appendChild(this.iconContainer),this.element.addEventListener("click",t=>{t.preventDefault(),t.stopPropagation(),this.element.disabled||e.onClick()})}getElement(){return this.element}setActive(e){e?(this.element.style.backgroundColor="#3bb2d0",this.element.style.color="#ffffff"):(this.element.style.backgroundColor="#ffffff",this.element.style.color="#333333"),this.element.setAttribute("aria-pressed",String(e))}setDisabled(e){this.element.disabled=e,this.element.style.opacity=e?"0.4":"1",this.element.style.cursor=e?"not-allowed":"pointer"}destroy(){this.element.remove()}setIcon(e){const i=new DOMParser().parseFromString(e,"image/svg+xml").documentElement;for(;this.iconContainer.firstChild;)this.iconContainer.removeChild(this.iconContainer.firstChild);this.iconContainer.appendChild(document.importNode(i,!0))}applyStyles(){const e=this.element.style;e.display="flex",e.alignItems="center",e.justifyContent="center",e.width="44px",e.height="44px",e.padding="0",e.margin="0",e.border="1px solid #ddd",e.borderRadius="4px",e.backgroundColor="#ffffff",e.color="#333333",e.cursor="pointer",e.outline="none",e.transition="background-color 0.15s, color 0.15s",e.boxSizing="border-box"}}const Ye='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2l8.5 6.2-3.2 9.8H6.7L3.5 8.2z"/></svg>',Ge='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z"/><path d="M13 13l6 6"/></svg>',qe='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/><line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/></svg>',Je='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 14 4 9 9 4"/><path d="M20 20v-7a4 4 0 00-4-4H4"/></svg>',Qe='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 14 20 9 15 4"/><path d="M4 20v-7a4 4 0 014-4h12"/></svg>',Ze={draw:!0,select:!0,delete:!0,undo:!0,redo:!0};class et{constructor(e,t,s={}){this.buttons=new Map,this.map=e,this.callbacks=t,this.options=s,this.container=document.createElement("div"),this.container.className="libre-draw-toolbar",this.applyContainerStyles(),this.createButtons(),this.mount()}setActiveMode(e){const t=this.buttons.get("draw"),s=this.buttons.get("select");t&&t.setActive(e==="draw"),s&&s.setActive(e==="select")}setHistoryState(e,t){const s=this.buttons.get("undo"),i=this.buttons.get("redo");s&&s.setDisabled(!e),i&&i.setDisabled(!t)}destroy(){for(const e of this.buttons.values())e.destroy();this.buttons.clear(),this.container.remove()}createButtons(){const e={...Ze,...this.options.controls};e.draw&&this.addButton("draw",Ye,"Draw polygon",()=>{this.callbacks.onDrawClick()},!0),e.select&&this.addButton("select",Ge,"Select feature",()=>{this.callbacks.onSelectClick()},!0),e.delete&&this.addButton("delete",qe,"Delete selected",()=>{this.callbacks.onDeleteClick()}),e.undo&&this.addButton("undo",Je,"Undo",()=>{this.callbacks.onUndoClick()}),e.redo&&this.addButton("redo",Qe,"Redo",()=>{this.callbacks.onRedoClick()})}addButton(e,t,s,i,n){const o=new $e({id:e,icon:t,title:s,onClick:i,isToggle:n});this.buttons.set(e,o),this.container.appendChild(o.getElement())}mount(){const e=this.options.position||"top-right",t=this.map.getContainer(),s=t.querySelector(`.maplibregl-ctrl-${e}`);s?s.appendChild(this.container):t.appendChild(this.container)}applyContainerStyles(){const e=this.container.style;e.display="flex",e.flexDirection="column",e.gap="4px",e.padding="4px",e.backgroundColor="rgba(255, 255, 255, 0.9)",e.borderRadius="4px",e.boxShadow="0 1px 4px rgba(0, 0, 0, 0.3)",e.zIndex="1",e.pointerEvents="auto"}}class tt{constructor(e,t={}){this.toolbar=null,this.destroyed=!1,this.map=e,this.eventBus=new ge,this.featureStore=new R,this.historyManager=new fe(t.historyLimit??100),this.modeManager=new pe,this.sourceManager=new We(e),this.renderManager=new Ke(e,this.sourceManager);const s=new Se({addFeatureToStore:i=>this.featureStore.add(i),pushToHistory:i=>{this.historyManager.push(i),this.updateToolbarHistoryState()},emitEvent:(i,n)=>this.eventBus.emit(i,n),renderPreview:i=>this.renderManager.renderPreview(i),clearPreview:()=>this.renderManager.clearPreview(),renderFeatures:()=>this.renderAllFeatures(),getScreenPoint:i=>{const n=e.project([i.lng,i.lat]);return{x:n.x,y:n.y}}});if(this.selectMode=new Oe({removeFeatureFromStore:i=>this.featureStore.remove(i),pushToHistory:i=>{this.historyManager.push(i),this.updateToolbarHistoryState()},emitEvent:(i,n)=>this.eventBus.emit(i,n),renderFeatures:()=>this.renderAllFeatures(),getFeatureById:i=>this.featureStore.getById(i),getAllFeatures:()=>this.featureStore.getAll(),getScreenPoint:i=>{const n=e.project([i.lng,i.lat]);return{x:n.x,y:n.y}},updateFeatureInStore:(i,n)=>this.featureStore.update(i,n),renderVertices:(i,n,o,l)=>this.renderManager.renderVertices(n,o,l),clearVertices:()=>this.renderManager.clearVertices(),setDragPan:i=>{i?e.dragPan.enable():e.dragPan.disable()}},i=>{this.renderManager.setSelectedIds(i)}),this.modeManager.registerMode("idle",new Ie),this.modeManager.registerMode("draw",s),this.modeManager.registerMode("select",this.selectMode),this.modeManager.setOnModeChange((i,n)=>{this.eventBus.emit("modechange",{mode:i,previousMode:n}),this.toolbar&&this.toolbar.setActiveMode(i),i==="draw"?(e.dragPan.disable(),e.doubleClickZoom.disable()):i==="select"?e.doubleClickZoom.disable():(e.dragPan.enable(),e.doubleClickZoom.enable())}),this.inputHandler=new Xe(e,()=>this.modeManager.getCurrentMode()),t.toolbar!==!1&&t.toolbar!==void 0){const i=typeof t.toolbar=="object"?t.toolbar:{};this.createToolbar(i)}e.isStyleLoaded()?this.initialize():e.once("load",()=>{this.initialize()})}setMode(e){this.assertNotDestroyed(),this.modeManager.setMode(e)}getMode(){return this.assertNotDestroyed(),this.modeManager.getMode()}getFeatures(){return this.assertNotDestroyed(),this.featureStore.getAll()}setFeatures(e){this.assertNotDestroyed();const t=Ee(e);this.featureStore.setAll(t.features),this.historyManager.clear(),this.renderAllFeatures(),this.updateToolbarHistoryState()}addFeatures(e){this.assertNotDestroyed();for(const t of e){const s=le(t);this.featureStore.add(s)}this.renderAllFeatures()}getSelectedFeatureIds(){return this.assertNotDestroyed(),this.selectMode.getSelectedIds()}getFeatureById(e){return this.assertNotDestroyed(),this.featureStore.getById(e)}deleteFeature(e){this.assertNotDestroyed();const t=this.featureStore.getById(e);if(!t)return;this.selectMode.getSelectedIds().includes(e)&&this.selectMode.clearSelection(),this.featureStore.remove(e);const i=new oe(t);return this.historyManager.push(i),this.eventBus.emit("delete",{feature:t}),this.renderAllFeatures(),this.updateToolbarHistoryState(),t}selectFeature(e){if(this.assertNotDestroyed(),!this.featureStore.getById(e))throw new v(`Feature not found: ${e}`);this.modeManager.getMode()!=="select"&&this.modeManager.setMode("select"),this.selectMode.selectFeature(e)}clearSelection(){this.assertNotDestroyed(),this.selectMode.clearSelection()}undo(){this.assertNotDestroyed();const e=this.historyManager.undo(this.featureStore);return e&&(this.renderAllFeatures(),this.selectMode.refreshVertexHandles(),this.updateToolbarHistoryState()),e}redo(){this.assertNotDestroyed();const e=this.historyManager.redo(this.featureStore);return e&&(this.renderAllFeatures(),this.selectMode.refreshVertexHandles(),this.updateToolbarHistoryState()),e}on(e,t){this.assertNotDestroyed(),this.eventBus.on(e,t)}off(e,t){this.assertNotDestroyed(),this.eventBus.off(e,t)}destroy(){this.destroyed||(this.destroyed=!0,this.modeManager.setMode("idle"),this.inputHandler.destroy(),this.renderManager.destroy(),this.eventBus.removeAllListeners(),this.historyManager.clear(),this.featureStore.clear(),this.toolbar&&(this.toolbar.destroy(),this.toolbar=null))}initialize(){this.destroyed||(this.renderManager.initialize(),this.inputHandler.enable())}renderAllFeatures(){const e=this.featureStore.getAll();this.renderManager.render(e)}createToolbar(e){this.toolbar=new et(this.map,{onDrawClick:()=>{const t=this.modeManager.getMode();this.modeManager.setMode(t==="draw"?"idle":"draw")},onSelectClick:()=>{const t=this.modeManager.getMode();this.modeManager.setMode(t==="select"?"idle":"select")},onDeleteClick:()=>{if(this.modeManager.getMode()==="select"){const t=this.selectMode.getSelectedIds();for(const s of t)this.deleteFeature(s)}},onUndoClick:()=>{this.undo()},onRedoClick:()=>{this.redo()}},e),this.toolbar.setActiveMode(this.modeManager.getMode()),this.toolbar.setHistoryState(this.historyManager.canUndo(),this.historyManager.canRedo())}updateToolbarHistoryState(){this.toolbar&&this.toolbar.setHistoryState(this.historyManager.canUndo(),this.historyManager.canRedo())}assertNotDestroyed(){if(this.destroyed)throw new v("This LibreDraw instance has been destroyed.")}}exports.LibreDraw=tt;exports.LibreDrawError=v;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class ue{constructor(e){this.feature=e,this.type="create"}apply(e){e.add(this.feature)}revert(e){e.remove(this.feature.id)}}class ${constructor(e,t,s){this.id=e,this.oldFeature=t,this.newFeature=s,this.type="update"}apply(e){e.update(this.id,this.newFeature)}revert(e){e.update(this.id,this.oldFeature)}}class oe{constructor(e){this.feature=e,this.type="delete"}apply(e){e.remove(this.feature.id)}revert(e){e.add(this.feature)}}class ge{constructor(){this.listeners=new Map}on(e,t){let s=this.listeners.get(e);s||(s=new Set,this.listeners.set(e,s)),s.add(t)}off(e,t){const s=this.listeners.get(e);s&&s.delete(t)}emit(e,t){const s=this.listeners.get(e);if(s)for(const i of s)i(t)}removeAllListeners(){this.listeners.clear()}}class R{constructor(){this.features=new Map}add(e){const t=e.id||crypto.randomUUID(),s={...e,id:t};return this.features.set(t,s),s}update(e,t){this.features.has(e)&&this.features.set(e,{...t,id:e})}remove(e){const t=this.features.get(e);return t&&this.features.delete(e),t}getAll(){return Array.from(this.features.values())}getById(e){return this.features.get(e)}clear(){this.features.clear()}setAll(e){this.features.clear();for(const t of e){const s=t.id||crypto.randomUUID();this.features.set(s,{...t,id:s})}}toGeoJSON(){return{type:"FeatureCollection",features:this.getAll()}}static cloneFeature(e){return{id:e.id,type:"Feature",geometry:{type:"Polygon",coordinates:e.geometry.coordinates.map(t=>t.map(s=>[...s]))},properties:{...e.properties}}}}class fe{constructor(e=100){this.undoStack=[],this.redoStack=[],this.limit=e}push(e){this.undoStack.push(e),this.redoStack=[],this.undoStack.length>this.limit&&this.undoStack.shift()}undo(e){const t=this.undoStack.pop();return t?(t.revert(e),this.redoStack.push(t),!0):!1}redo(e){const t=this.redoStack.pop();return t?(t.apply(e),this.undoStack.push(t),!0):!1}canUndo(){return this.undoStack.length>0}canRedo(){return this.redoStack.length>0}clear(){this.undoStack=[],this.redoStack=[]}}class pe{constructor(){this.modes=new Map,this.currentModeName="idle"}registerMode(e,t){this.modes.set(e,t)}setOnModeChange(e){this.onModeChange=e}setMode(e){if(e===this.currentModeName)return;const t=this.currentModeName,s=this.modes.get(this.currentModeName);s&&s.deactivate(),this.currentModeName=e;const i=this.modes.get(e);i&&i.activate(),this.onModeChange&&this.onModeChange(e,t)}getMode(){return this.currentModeName}getCurrentMode(){return this.modes.get(this.currentModeName)}}class v extends Error{constructor(e){super(e),this.name="LibreDrawError"}}function z(r,e,t){const s=(e[1]-r[1])*(t[0]-e[0])-(e[0]-r[0])*(t[1]-e[1]);return Math.abs(s)<1e-10?0:s>0?1:2}function j(r,e,t){return e[0]<=Math.max(r[0],t[0])&&e[0]>=Math.min(r[0],t[0])&&e[1]<=Math.max(r[1],t[1])&&e[1]>=Math.min(r[1],t[1])}function X(r,e){return Math.abs(r[0]-e[0])<1e-10&&Math.abs(r[1]-e[1])<1e-10}function J(r,e,t,s){if(X(r,t)||X(r,s)||X(e,t)||X(e,s))return!1;const i=z(r,e,t),n=z(r,e,s),o=z(t,s,r),l=z(t,s,e);return!!(i!==n&&o!==l||i===0&&j(r,t,e)||n===0&&j(r,s,e)||o===0&&j(t,r,s)||l===0&&j(t,e,s))}function ae(r){const e=r.length-1;if(e<3)return!1;for(let t=0;t<e;t++)for(let s=t+2;s<e;s++)if(!(t===0&&s===e-1)&&J(r[t],r[t+1],r[s],r[s+1]))return!0;return!1}function ye(r,e){if(r.length<2)return!1;const t=r[r.length-1];for(let s=0;s<r.length-2;s++)if(J(t,e,r[s],r[s+1]))return!0;return!1}function q(r){if(r.length<3)return!1;const e=r[0],t=r[r.length-1];for(let s=1;s<r.length-2;s++)if(J(t,e,r[s],r[s+1]))return!0;return!1}function me(r,e){return r[0]===e[0]&&r[1]===e[1]}function be(r){const[e,t]=r;if(typeof e!="number"||typeof t!="number")throw new v(`Invalid coordinate: expected [number, number], got [${typeof e}, ${typeof t}]`);if(e<-180||e>180)throw new v(`Invalid longitude: ${e}. Must be between -180 and 180.`);if(t<-90||t>90)throw new v(`Invalid latitude: ${t}. Must be between -90 and 90.`)}function ve(r){if(!Array.isArray(r))throw new v("Ring must be an array of positions.");if(r.length<4)throw new v(`Ring must have at least 4 positions (got ${r.length}). A valid polygon ring requires 3 unique vertices plus a closing vertex.`);const e=r[0],t=r[r.length-1];if(!me(e,t))throw new v("Ring is not closed. The first and last positions must be identical.");for(const s of r){if(!Array.isArray(s)||s.length<2)throw new v("Each position in a ring must be an array of at least 2 numbers.");be(s)}if(ae(r))throw new v("Ring has self-intersections. Polygon edges must not cross each other.")}function le(r){if(r==null||typeof r!="object")throw new v("Feature must be a non-null object.");const e=r;if(e.type!=="Feature")throw new v(`Feature.type must be "Feature", got "${String(e.type)}".`);if(e.geometry===null||e.geometry===void 0||typeof e.geometry!="object")throw new v("Feature.geometry must be a non-null object.");const t=e.geometry;if(t.type!=="Polygon")throw new v(`Feature.geometry.type must be "Polygon", got "${String(t.type)}".`);if(!Array.isArray(t.coordinates))throw new v("Feature.geometry.coordinates must be an array.");const s=t.coordinates;if(s.length===0)throw new v("Polygon must have at least one ring (outer ring).");for(const i of s)ve(i);return r}function Ee(r){if(r==null||typeof r!="object")throw new v("GeoJSON must be a non-null object.");const e=r;if(e.type!=="FeatureCollection")throw new v(`GeoJSON.type must be "FeatureCollection", got "${String(e.type)}".`);if(!Array.isArray(e.features))throw new v("GeoJSON.features must be an array.");const t=r,s=[];for(let i=0;i<t.features.length;i++)try{s.push(le(t.features[i]))}catch(n){throw n instanceof v?new v(`Invalid feature at index ${i}: ${n.message}`):n}return{type:"FeatureCollection",features:s}}class Ie{activate(){}deactivate(){}onPointerDown(e){}onPointerMove(e){}onPointerUp(e){}onDoubleClick(e){}onLongPress(e){}onKeyDown(e,t){}}const we=10,W=3;class Se{constructor(e){this.vertices=[],this.isActive=!1,this.callbacks=e}activate(){this.isActive=!0,this.vertices=[]}deactivate(){this.isActive=!1,this.vertices=[],this.callbacks.clearPreview()}onPointerDown(e){if(!this.isActive)return;const t=[e.lngLat.lng,e.lngLat.lat];if(this.vertices.length>=W){const s=this.vertices[0],i=this.callbacks.getScreenPoint({lng:s[0],lat:s[1]}),n=e.point.x-i.x,o=e.point.y-i.y;if(Math.sqrt(n*n+o*o)<=we){if(q(this.vertices))return;this.finalizePolygon();return}}ye(this.vertices,t)||(this.vertices.push(t),this.updatePreview(e))}onPointerMove(e){!this.isActive||this.vertices.length===0||this.updatePreview(e)}onPointerUp(e){}onDoubleClick(e){this.isActive&&(this.vertices.length>W&&this.vertices.pop(),this.vertices.length>=W&&(q(this.vertices)||this.finalizePolygon()),e.originalEvent.preventDefault(),e.originalEvent.stopPropagation())}onLongPress(e){this.isActive&&this.vertices.length>0&&(this.vertices.pop(),this.vertices.length===0?this.callbacks.clearPreview():this.callbacks.renderPreview(this.buildPreviewCoordinates()))}onKeyDown(e,t){this.isActive&&e==="Escape"&&this.cancelDrawing()}buildPreviewCoordinates(e){const t=[...this.vertices];return e&&t.push(e),t.length>0&&t.push([...t[0]]),t}updatePreview(e){const t=[e.lngLat.lng,e.lngLat.lat],s=this.buildPreviewCoordinates(t);this.callbacks.renderPreview(s)}finalizePolygon(){if(this.vertices.length<W)return;const e=[...this.vertices,[...this.vertices[0]]],t={id:crypto.randomUUID(),type:"Feature",geometry:{type:"Polygon",coordinates:[e]},properties:{}},s=this.callbacks.addFeatureToStore(t),i=new ue(s);this.callbacks.pushToHistory(i),this.callbacks.emitEvent("create",{feature:s}),this.callbacks.renderFeatures(),this.vertices=[],this.callbacks.clearPreview()}cancelDrawing(){this.vertices=[],this.callbacks.clearPreview()}}const N=11102230246251565e-32,F=134217729,Te=(3+8*N)*N;function Y(r,e,t,s,i){let n,o,l,h,d=e[0],u=s[0],a=0,c=0;u>d==u>-d?(n=d,d=e[++a]):(n=u,u=s[++c]);let g=0;if(a<r&&c<t)for(u>d==u>-d?(o=d+n,l=n-(o-d),d=e[++a]):(o=u+n,l=n-(o-u),u=s[++c]),n=o,l!==0&&(i[g++]=l);a<r&&c<t;)u>d==u>-d?(o=n+d,h=o-n,l=n-(o-h)+(d-h),d=e[++a]):(o=n+u,h=o-n,l=n-(o-h)+(u-h),u=s[++c]),n=o,l!==0&&(i[g++]=l);for(;a<r;)o=n+d,h=o-n,l=n-(o-h)+(d-h),d=e[++a],n=o,l!==0&&(i[g++]=l);for(;c<t;)o=n+u,h=o-n,l=n-(o-h)+(u-h),u=s[++c],n=o,l!==0&&(i[g++]=l);return(n!==0||g===0)&&(i[g++]=n),g}function Me(r,e){let t=e[0];for(let s=1;s<r;s++)t+=e[s];return t}function H(r){return new Float64Array(r)}const Pe=(3+16*N)*N,ke=(2+12*N)*N,Fe=(9+64*N)*N*N,O=H(4),Q=H(8),Z=H(12),ee=H(16),D=H(4);function De(r,e,t,s,i,n,o){let l,h,d,u,a,c,g,y,p,m,f,b,T,I,M,P,C,k;const L=r-i,x=t-i,V=e-n,A=s-n;I=L*A,c=F*L,g=c-(c-L),y=L-g,c=F*A,p=c-(c-A),m=A-p,M=y*m-(I-g*p-y*p-g*m),P=V*x,c=F*V,g=c-(c-V),y=V-g,c=F*x,p=c-(c-x),m=x-p,C=y*m-(P-g*p-y*p-g*m),f=M-C,a=M-f,O[0]=M-(f+a)+(a-C),b=I+f,a=b-I,T=I-(b-a)+(f-a),f=T-P,a=T-f,O[1]=T-(f+a)+(a-P),k=b+f,a=k-b,O[2]=b-(k-a)+(f-a),O[3]=k;let _=Me(4,O),U=ke*o;if(_>=U||-_>=U||(a=r-L,l=r-(L+a)+(a-i),a=t-x,d=t-(x+a)+(a-i),a=e-V,h=e-(V+a)+(a-n),a=s-A,u=s-(A+a)+(a-n),l===0&&h===0&&d===0&&u===0)||(U=Fe*o+Te*Math.abs(_),_+=L*u+A*l-(V*d+x*h),_>=U||-_>=U))return _;I=l*A,c=F*l,g=c-(c-l),y=l-g,c=F*A,p=c-(c-A),m=A-p,M=y*m-(I-g*p-y*p-g*m),P=h*x,c=F*h,g=c-(c-h),y=h-g,c=F*x,p=c-(c-x),m=x-p,C=y*m-(P-g*p-y*p-g*m),f=M-C,a=M-f,D[0]=M-(f+a)+(a-C),b=I+f,a=b-I,T=I-(b-a)+(f-a),f=T-P,a=T-f,D[1]=T-(f+a)+(a-P),k=b+f,a=k-b,D[2]=b-(k-a)+(f-a),D[3]=k;const ce=Y(4,O,4,D,Q);I=L*u,c=F*L,g=c-(c-L),y=L-g,c=F*u,p=c-(c-u),m=u-p,M=y*m-(I-g*p-y*p-g*m),P=V*d,c=F*V,g=c-(c-V),y=V-g,c=F*d,p=c-(c-d),m=d-p,C=y*m-(P-g*p-y*p-g*m),f=M-C,a=M-f,D[0]=M-(f+a)+(a-C),b=I+f,a=b-I,T=I-(b-a)+(f-a),f=T-P,a=T-f,D[1]=T-(f+a)+(a-P),k=b+f,a=k-b,D[2]=b-(k-a)+(f-a),D[3]=k;const he=Y(ce,Q,4,D,Z);I=l*u,c=F*l,g=c-(c-l),y=l-g,c=F*u,p=c-(c-u),m=u-p,M=y*m-(I-g*p-y*p-g*m),P=h*d,c=F*h,g=c-(c-h),y=h-g,c=F*d,p=c-(c-d),m=d-p,C=y*m-(P-g*p-y*p-g*m),f=M-C,a=M-f,D[0]=M-(f+a)+(a-C),b=I+f,a=b-I,T=I-(b-a)+(f-a),f=T-P,a=T-f,D[1]=T-(f+a)+(a-P),k=b+f,a=k-b,D[2]=b-(k-a)+(f-a),D[3]=k;const de=Y(he,Z,4,D,ee);return ee[de-1]}function Ce(r,e,t,s,i,n){const o=(e-n)*(t-i),l=(r-i)*(s-n),h=o-l,d=Math.abs(o+l);return Math.abs(h)>=Pe*d?h:-De(r,e,t,s,i,n,d)}function Le(r,e){var t,s,i=0,n,o,l,h,d,u,a,c=r[0],g=r[1],y=e.length;for(t=0;t<y;t++){s=0;var p=e[t],m=p.length-1;if(u=p[0],u[0]!==p[m][0]&&u[1]!==p[m][1])throw new Error("First and last coordinates in a ring must be the same");for(o=u[0]-c,l=u[1]-g,s;s<m;s++){if(a=p[s+1],h=a[0]-c,d=a[1]-g,l===0&&d===0){if(h<=0&&o>=0||o<=0&&h>=0)return 0}else if(d>=0&&l<=0||d<=0&&l>=0){if(n=Ce(o,h,l,d,0,0),n===0)return 0;(n>0&&d>0&&l<=0||n<0&&d<=0&&l>0)&&i++}u=a,l=d,o=h}}return i%2!==0}function xe(r,e,t={}){const s={type:"Feature"};return(t.id===0||t.id)&&(s.id=t.id),t.bbox&&(s.bbox=t.bbox),s.properties={},s.geometry=r,s}function te(r,e,t={}){if(!r)throw new Error("coordinates is required");if(!Array.isArray(r))throw new Error("coordinates must be an Array");if(r.length<2)throw new Error("coordinates must be at least 2 numbers long");if(!se(r[0])||!se(r[1]))throw new Error("coordinates must contain numbers");return xe({type:"Point",coordinates:r},e,t)}function se(r){return!isNaN(r)&&r!==null&&!Array.isArray(r)}function Ve(r){if(!r)throw new Error("coord is required");if(!Array.isArray(r)){if(r.type==="Feature"&&r.geometry!==null&&r.geometry.type==="Point")return[...r.geometry.coordinates];if(r.type==="Point")return[...r.coordinates]}if(Array.isArray(r)&&r.length>=2&&!Array.isArray(r[0])&&!Array.isArray(r[1]))return[...r];throw new Error("coord must be GeoJSON Point or an Array of numbers")}function Ae(r){return r.type==="Feature"?r.geometry:r}function _e(r,e,t={}){if(!r)throw new Error("point is required");if(!e)throw new Error("polygon is required");const s=Ve(r),i=Ae(e),n=i.type,o=e.bbox;let l=i.coordinates;if(o&&Re(s,o)===!1)return!1;n==="Polygon"&&(l=[l]);let h=!1;for(var d=0;d<l.length;++d){const u=Le(s,l[d]);if(u===0)return!t.ignoreBoundary;u&&(h=!0)}return h}function Re(r,e){return e[0]<=r[0]&&e[1]<=r[1]&&e[2]>=r[0]&&e[3]>=r[1]}var ie=_e;const re=10,Ne=24,ne=3;class Oe{constructor(e,t){this.selectedIds=new Set,this.isActive=!1,this.dragging=!1,this.dragVertexIndex=-1,this.dragStartFeature=null,this.draggingPolygon=!1,this.dragPolygonStartLngLat=null,this.highlightedVertexIndex=-1,this.callbacks=e,this.onSelectionChange=t}activate(){this.isActive=!0}deactivate(){this.isActive=!1,this.highlightedVertexIndex=-1,this.endDrag(),this.selectedIds.size>0&&(this.selectedIds.clear(),this.callbacks.clearVertices(),this.notifySelectionChange())}getSelectedIds(){return Array.from(this.selectedIds)}selectFeature(e){if(!this.isActive)return!1;const t=this.callbacks.getFeatureById(e);return t?(this.highlightedVertexIndex=-1,this.endDrag(),this.selectedIds.clear(),this.selectedIds.add(e),this.showVertexHandles(t),this.notifySelectionChange(),this.callbacks.renderFeatures(),!0):!1}clearSelection(){this.isActive&&this.selectedIds.size!==0&&(this.highlightedVertexIndex=-1,this.endDrag(),this.selectedIds.clear(),this.callbacks.clearVertices(),this.notifySelectionChange(),this.callbacks.renderFeatures())}onPointerDown(e){if(!this.isActive)return;const t=this.getFirstSelectedId();if(t){const o=this.callbacks.getFeatureById(t);if(o){const l=this.getVertices(o),h=this.getThreshold(e),d=this.findNearestVertex(l,e.point,h);if(d>=0){this.startDrag(o,d);return}const u=this.computeMidpoints(l),a=this.findNearestPoint(u,e.point,h);if(a>=0){const g=R.cloneFeature(o),y=this.insertVertex(o,a+1,u[a]);this.callbacks.updateFeatureInStore(t,y),this.showVertexHandles(y),this.startDrag(y,a+1),this.dragStartFeature=g;return}const c=te([e.lngLat.lng,e.lngLat.lat]);if(ie(c,o.geometry)){this.startPolygonDrag(o,e.lngLat);return}}}this.highlightedVertexIndex=-1;const s=te([e.lngLat.lng,e.lngLat.lat]),i=this.callbacks.getAllFeatures();let n;for(let o=i.length-1;o>=0;o--){const l=i[o],h=l.geometry;if(ie(s,h)){n=l;break}}n?this.selectedIds.has(n.id)?(this.selectedIds.delete(n.id),this.callbacks.clearVertices()):(this.selectedIds.clear(),this.selectedIds.add(n.id),this.showVertexHandles(n)):(this.selectedIds.clear(),this.callbacks.clearVertices()),this.notifySelectionChange(),this.callbacks.renderFeatures()}onPointerMove(e){if(!this.isActive)return;if(this.dragging){const l=this.getFirstSelectedId();if(!l)return;const h=this.callbacks.getFeatureById(l);if(!h)return;const d=[e.lngLat.lng,e.lngLat.lat],u=this.moveVertex(h,this.dragVertexIndex,d);if(ae(u.geometry.coordinates[0]))return;this.callbacks.updateFeatureInStore(l,u),this.callbacks.renderFeatures(),this.showVertexHandles(u);return}if(this.draggingPolygon){const l=this.getFirstSelectedId();if(!l||!this.dragStartFeature||!this.dragPolygonStartLngLat)return;const h=e.lngLat.lng-this.dragPolygonStartLngLat.lng,d=e.lngLat.lat-this.dragPolygonStartLngLat.lat,u=this.movePolygon(this.dragStartFeature,h,d);this.callbacks.updateFeatureInStore(l,u),this.callbacks.renderFeatures(),this.showVertexHandles(u);return}const t=this.getFirstSelectedId();if(!t)return;const s=this.callbacks.getFeatureById(t);if(!s)return;const i=this.getVertices(s),n=this.getThreshold(e),o=this.findNearestVertex(i,e.point,n);o!==this.highlightedVertexIndex&&(this.highlightedVertexIndex=o,this.showVertexHandles(s))}onPointerUp(e){if(!this.isActive||!this.dragging&&!this.draggingPolygon)return;const t=this.getFirstSelectedId();if(!t||!this.dragStartFeature){this.endDrag();return}const s=this.callbacks.getFeatureById(t);if(s){const i=new $(t,this.dragStartFeature,R.cloneFeature(s));this.callbacks.pushToHistory(i),this.callbacks.emitEvent("update",{feature:s,oldFeature:this.dragStartFeature})}this.endDrag()}onDoubleClick(e){if(!this.isActive)return;const t=this.getFirstSelectedId();if(!t)return;const s=this.callbacks.getFeatureById(t);if(!s)return;const i=this.getVertices(s),n=this.getThreshold(e),o=this.findNearestVertex(i,e.point,n);if(o>=0&&i.length>ne){const l=R.cloneFeature(s),h=this.removeVertex(s,o);this.callbacks.updateFeatureInStore(t,h);const d=new $(t,l,R.cloneFeature(h));this.callbacks.pushToHistory(d),this.callbacks.emitEvent("update",{feature:h,oldFeature:l}),this.callbacks.renderFeatures(),this.showVertexHandles(h),e.originalEvent.preventDefault(),e.originalEvent.stopPropagation()}}onLongPress(e){if(!this.isActive)return;const t=this.getFirstSelectedId();if(!t)return;const s=this.callbacks.getFeatureById(t);if(!s)return;const i=this.getVertices(s),n=this.getThreshold(e),o=this.findNearestVertex(i,e.point,n);if(o>=0&&i.length>ne){const l=R.cloneFeature(s),h=this.removeVertex(s,o);this.callbacks.updateFeatureInStore(t,h);const d=new $(t,l,R.cloneFeature(h));this.callbacks.pushToHistory(d),this.callbacks.emitEvent("update",{feature:h,oldFeature:l}),this.callbacks.renderFeatures(),this.showVertexHandles(h)}}onKeyDown(e,t){this.isActive&&(e==="Delete"||e==="Backspace")&&this.deleteSelected()}getThreshold(e){return e.inputType==="touch"?Ne:re}getVertices(e){const t=e.geometry.coordinates[0];return t.slice(0,t.length-1)}findNearestVertex(e,t,s){return this.findNearestPoint(e,t,s)}findNearestPoint(e,t,s=re){let i=1/0,n=-1;for(let o=0;o<e.length;o++){const l=this.callbacks.getScreenPoint({lng:e[o][0],lat:e[o][1]}),h=t.x-l.x,d=t.y-l.y,u=Math.sqrt(h*h+d*d);u<=s&&u<i&&(i=u,n=o)}return n}computeMidpoints(e){const t=[];for(let s=0;s<e.length;s++){const i=(s+1)%e.length;t.push([(e[s][0]+e[i][0])/2,(e[s][1]+e[i][1])/2])}return t}startDrag(e,t){this.dragging=!0,this.dragVertexIndex=t,this.dragStartFeature=R.cloneFeature(e),this.callbacks.setDragPan(!1)}startPolygonDrag(e,t){this.draggingPolygon=!0,this.dragPolygonStartLngLat=t,this.dragStartFeature=R.cloneFeature(e),this.callbacks.setDragPan(!1)}endDrag(){(this.dragging||this.draggingPolygon)&&this.callbacks.setDragPan(!0),this.dragging=!1,this.dragVertexIndex=-1,this.dragStartFeature=null,this.draggingPolygon=!1,this.dragPolygonStartLngLat=null,this.highlightedVertexIndex=-1}moveVertex(e,t,s){const i=[...e.geometry.coordinates[0]];return i[t]=s,t===0&&(i[i.length-1]=s),t===i.length-1&&(i[0]=s),{...e,geometry:{type:"Polygon",coordinates:[i]}}}movePolygon(e,t,s){const i=e.geometry.coordinates[0].map(n=>[n[0]+t,n[1]+s]);return{...e,geometry:{type:"Polygon",coordinates:[i]}}}insertVertex(e,t,s){const i=[...e.geometry.coordinates[0]];return i.splice(t,0,s),{...e,geometry:{type:"Polygon",coordinates:[i]}}}removeVertex(e,t){const i=this.getVertices(e).filter((o,l)=>l!==t),n=[...i,[...i[0]]];return{...e,geometry:{type:"Polygon",coordinates:[n]}}}refreshVertexHandles(){if(!this.isActive)return;const e=this.getFirstSelectedId();if(!e)return;const t=this.callbacks.getFeatureById(e);t?this.showVertexHandles(t):(this.selectedIds.delete(e),this.callbacks.clearVertices(),this.notifySelectionChange())}showVertexHandles(e){const t=this.getVertices(e),s=this.computeMidpoints(t);this.callbacks.renderVertices(e.id,t,s,this.highlightedVertexIndex>=0?this.highlightedVertexIndex:void 0)}getFirstSelectedId(){return this.selectedIds.values().next().value}deleteSelected(){if(this.selectedIds.size===0)return;const e=Array.from(this.selectedIds);for(const t of e){const s=this.callbacks.getFeatureById(t);if(s){this.callbacks.removeFeatureFromStore(t);const i=new oe(s);this.callbacks.pushToHistory(i),this.callbacks.emitEvent("delete",{feature:s})}}this.selectedIds.clear(),this.callbacks.clearVertices(),this.notifySelectionChange(),this.callbacks.renderFeatures()}notifySelectionChange(){const e=this.getSelectedIds();this.callbacks.emitEvent("selectionchange",{selectedIds:e}),this.onSelectionChange&&this.onSelectionChange(e)}}class Ue{constructor(e,t){this.handleMouseDown=s=>{this.callbacks.onPointerDown(this.normalize(s))},this.handleMouseMove=s=>{this.callbacks.onPointerMove(this.normalize(s))},this.handleMouseUp=s=>{this.callbacks.onPointerUp(this.normalize(s))},this.handleDblClick=s=>{this.callbacks.onDoubleClick(this.normalize(s))},this.map=e,this.callbacks=t,this.canvas=e.getCanvasContainer()}enable(){this.canvas.addEventListener("mousedown",this.handleMouseDown),this.canvas.addEventListener("mousemove",this.handleMouseMove),this.canvas.addEventListener("mouseup",this.handleMouseUp),this.canvas.addEventListener("dblclick",this.handleDblClick)}disable(){this.canvas.removeEventListener("mousedown",this.handleMouseDown),this.canvas.removeEventListener("mousemove",this.handleMouseMove),this.canvas.removeEventListener("mouseup",this.handleMouseUp),this.canvas.removeEventListener("dblclick",this.handleDblClick)}destroy(){this.disable()}normalize(e){const t=this.canvas.getBoundingClientRect(),s=e.clientX-t.left,i=e.clientY-t.top,n=this.map.unproject([s,i]);return{lngLat:{lng:n.lng,lat:n.lat},point:{x:s,y:i},originalEvent:e,inputType:"mouse"}}}const Be=300,He=500,ze=15;class je{constructor(e,t){this.lastTapTime=0,this.longPressTimer=null,this.touchStartPos=null,this.isPinching=!1,this.handleTouchStart=s=>{if(s.touches.length>=2){this.isPinching=!0,this.cancelLongPress();return}this.isPinching=!1;const i=this.normalize(s);this.touchStartPos={x:i.point.x,y:i.point.y},this.cancelLongPress(),this.longPressTimer=setTimeout(()=>{this.touchStartPos&&(this.callbacks.onLongPress(i),this.touchStartPos=null)},He),this.callbacks.onPointerDown(i)},this.handleTouchMove=s=>{if(this.isPinching||s.touches.length>=2){this.cancelLongPress();return}const i=this.normalize(s);if(this.touchStartPos){const n=i.point.x-this.touchStartPos.x,o=i.point.y-this.touchStartPos.y;Math.sqrt(n*n+o*o)>ze&&this.cancelLongPress()}this.callbacks.onPointerMove(i)},this.handleTouchEnd=s=>{if(this.cancelLongPress(),this.isPinching){s.touches.length===0&&(this.isPinching=!1);return}if(s.changedTouches.length===0)return;const i=this.normalizeChangedTouch(s),n=Date.now();n-this.lastTapTime<Be?(this.callbacks.onDoubleClick(i),this.lastTapTime=0):this.lastTapTime=n,this.touchStartPos&&(this.callbacks.onPointerUp(i),this.touchStartPos=null)},this.map=e,this.callbacks=t,this.canvas=e.getCanvasContainer()}enable(){this.canvas.addEventListener("touchstart",this.handleTouchStart,{passive:!1}),this.canvas.addEventListener("touchmove",this.handleTouchMove,{passive:!1}),this.canvas.addEventListener("touchend",this.handleTouchEnd)}disable(){this.canvas.removeEventListener("touchstart",this.handleTouchStart),this.canvas.removeEventListener("touchmove",this.handleTouchMove),this.canvas.removeEventListener("touchend",this.handleTouchEnd),this.cancelLongPress()}destroy(){this.disable()}cancelLongPress(){this.longPressTimer!==null&&(clearTimeout(this.longPressTimer),this.longPressTimer=null)}normalize(e){const t=e.touches[0],s=this.canvas.getBoundingClientRect(),i=t.clientX-s.left,n=t.clientY-s.top,o=this.map.unproject([i,n]);return{lngLat:{lng:o.lng,lat:o.lat},point:{x:i,y:n},originalEvent:e,inputType:"touch"}}normalizeChangedTouch(e){const t=e.changedTouches[0],s=this.canvas.getBoundingClientRect(),i=t.clientX-s.left,n=t.clientY-s.top,o=this.map.unproject([i,n]);return{lngLat:{lng:o.lng,lat:o.lat},point:{x:i,y:n},originalEvent:e,inputType:"touch"}}}const K=class K{constructor(e){this.handleKeyDown=t=>{K.RELEVANT_KEYS.has(t.key)&&this.callbacks.onKeyDown(t.key,t)},this.callbacks=e}enable(){document.addEventListener("keydown",this.handleKeyDown)}disable(){document.removeEventListener("keydown",this.handleKeyDown)}destroy(){this.disable()}};K.RELEVANT_KEYS=new Set(["Escape","Delete","Backspace"]);let G=K;class Xe{constructor(e,t){this.getActiveMode=t;const s={onPointerDown:i=>{var n;(n=this.getActiveMode())==null||n.onPointerDown(i)},onPointerMove:i=>{var n;(n=this.getActiveMode())==null||n.onPointerMove(i)},onPointerUp:i=>{var n;(n=this.getActiveMode())==null||n.onPointerUp(i)},onDoubleClick:i=>{var n;(n=this.getActiveMode())==null||n.onDoubleClick(i)},onLongPress:i=>{var n;(n=this.getActiveMode())==null||n.onLongPress(i)}};this.mouseInput=new Ue(e,s),this.touchInput=new je(e,s),this.keyboardInput=new G({onKeyDown:(i,n)=>{var o;(o=this.getActiveMode())==null||o.onKeyDown(i,n)}})}enable(){this.mouseInput.enable(),this.touchInput.enable(),this.keyboardInput.enable()}disable(){this.mouseInput.disable(),this.touchInput.disable(),this.keyboardInput.disable()}destroy(){this.mouseInput.destroy(),this.touchInput.destroy(),this.keyboardInput.destroy()}}const E={FEATURES:"libre-draw-features",PREVIEW:"libre-draw-preview",EDIT_VERTICES:"libre-draw-edit-vertices"},B={type:"FeatureCollection",features:[]};class We{constructor(e){this.initialized=!1,this.map=e}initialize(){this.initialized||(this.map.getSource(E.FEATURES)||this.map.addSource(E.FEATURES,{type:"geojson",data:B}),this.map.getSource(E.PREVIEW)||this.map.addSource(E.PREVIEW,{type:"geojson",data:B}),this.map.getSource(E.EDIT_VERTICES)||this.map.addSource(E.EDIT_VERTICES,{type:"geojson",data:B}),this.initialized=!0)}updateFeatures(e){const t=this.map.getSource(E.FEATURES);t&&t.setData(e)}updatePreview(e){const t=this.map.getSource(E.PREVIEW);t&&t.setData(e)}clearPreview(){this.updatePreview(B)}updateEditVertices(e){const t=this.map.getSource(E.EDIT_VERTICES);t&&t.setData(e)}clearEditVertices(){this.updateEditVertices(B)}destroy(){this.map.getSource(E.FEATURES)&&this.map.removeSource(E.FEATURES),this.map.getSource(E.PREVIEW)&&this.map.removeSource(E.PREVIEW),this.map.getSource(E.EDIT_VERTICES)&&this.map.removeSource(E.EDIT_VERTICES),this.initialized=!1}}const S={FILL:"libre-draw-fill",OUTLINE:"libre-draw-outline",VERTICES:"libre-draw-vertices",PREVIEW:"libre-draw-preview",EDIT_VERTICES:"libre-draw-edit-vertices",EDIT_MIDPOINTS:"libre-draw-edit-midpoints"},w={FILL:"#3bb2d0",FILL_OPACITY:.2,FILL_SELECTED:"#fbb03b",FILL_SELECTED_OPACITY:.4,OUTLINE:"#3bb2d0",OUTLINE_WIDTH:2,OUTLINE_SELECTED:"#fbb03b",VERTEX_COLOR:"#ffffff",VERTEX_STROKE:"#3bb2d0",VERTEX_RADIUS:4,PREVIEW_OUTLINE:"#3bb2d0",PREVIEW_OUTLINE_DASH:[2,2],EDIT_VERTEX_COLOR:"#ffffff",EDIT_VERTEX_STROKE:"#3bb2d0",EDIT_VERTEX_RADIUS:5,EDIT_VERTEX_STROKE_WIDTH:2,MIDPOINT_COLOR:"#3bb2d0",MIDPOINT_OPACITY:.5,MIDPOINT_RADIUS:3};class Ke{constructor(e,t){this.selectedIds=new Set,this.pendingRender=!1,this.pendingFeatures=null,this.initialized=!1,this.map=e,this.sourceManager=t}initialize(){this.initialized||(this.sourceManager.initialize(),this.map.getLayer(S.FILL)||this.map.addLayer({id:S.FILL,type:"fill",source:E.FEATURES,paint:{"fill-color":["case",["boolean",["get","_selected"],!1],w.FILL_SELECTED,w.FILL],"fill-opacity":["case",["boolean",["get","_selected"],!1],w.FILL_SELECTED_OPACITY,w.FILL_OPACITY]}}),this.map.getLayer(S.OUTLINE)||this.map.addLayer({id:S.OUTLINE,type:"line",source:E.FEATURES,paint:{"line-color":["case",["boolean",["get","_selected"],!1],w.OUTLINE_SELECTED,w.OUTLINE],"line-width":w.OUTLINE_WIDTH}}),this.map.getLayer(S.VERTICES)||this.map.addLayer({id:S.VERTICES,type:"circle",source:E.FEATURES,filter:["==","$type","Point"],paint:{"circle-radius":w.VERTEX_RADIUS,"circle-color":w.VERTEX_COLOR,"circle-stroke-color":w.VERTEX_STROKE,"circle-stroke-width":2}}),this.map.getLayer(S.PREVIEW)||this.map.addLayer({id:S.PREVIEW,type:"line",source:E.PREVIEW,paint:{"line-color":w.PREVIEW_OUTLINE,"line-width":2,"line-dasharray":w.PREVIEW_OUTLINE_DASH}}),this.map.getLayer(S.EDIT_MIDPOINTS)||this.map.addLayer({id:S.EDIT_MIDPOINTS,type:"circle",source:E.EDIT_VERTICES,filter:["==",["get","_type"],"midpoint"],paint:{"circle-radius":w.MIDPOINT_RADIUS,"circle-color":w.MIDPOINT_COLOR,"circle-opacity":w.MIDPOINT_OPACITY}}),this.map.getLayer(S.EDIT_VERTICES)||this.map.addLayer({id:S.EDIT_VERTICES,type:"circle",source:E.EDIT_VERTICES,filter:["==",["get","_type"],"vertex"],paint:{"circle-radius":["case",["boolean",["get","_highlighted"],!1],7,w.EDIT_VERTEX_RADIUS],"circle-color":["case",["boolean",["get","_highlighted"],!1],"#ff4444",w.EDIT_VERTEX_COLOR],"circle-stroke-color":["case",["boolean",["get","_highlighted"],!1],"#cc0000",w.EDIT_VERTEX_STROKE],"circle-stroke-width":w.EDIT_VERTEX_STROKE_WIDTH}}),this.initialized=!0)}render(e){this.pendingFeatures=e,this.pendingRender||(this.pendingRender=!0,requestAnimationFrame(()=>{this.performRender(),this.pendingRender=!1}))}renderPreview(e){if(e.length<2){this.clearPreview();return}const t=e.map(i=>[i[0],i[1]]),s={type:"FeatureCollection",features:[{type:"Feature",properties:{},geometry:{type:"LineString",coordinates:t}}]};this.sourceManager.updatePreview(s)}clearPreview(){this.sourceManager.clearPreview()}renderVertices(e,t,s){const i=[];for(let n=0;n<e.length;n++){const o=e[n];i.push({type:"Feature",properties:{_type:"vertex",_highlighted:n===s},geometry:{type:"Point",coordinates:[o[0],o[1]]}})}for(const n of t)i.push({type:"Feature",properties:{_type:"midpoint"},geometry:{type:"Point",coordinates:[n[0],n[1]]}});this.sourceManager.updateEditVertices({type:"FeatureCollection",features:i})}clearVertices(){this.sourceManager.clearEditVertices()}setSelectedIds(e){this.selectedIds=new Set(e)}destroy(){const e=[S.EDIT_VERTICES,S.EDIT_MIDPOINTS,S.PREVIEW,S.VERTICES,S.OUTLINE,S.FILL];for(const t of e)this.map.getLayer(t)&&this.map.removeLayer(t);this.sourceManager.destroy(),this.initialized=!1}performRender(){if(!this.pendingFeatures)return;const t={type:"FeatureCollection",features:this.pendingFeatures.map(s=>({type:"Feature",id:s.id,properties:{...s.properties,_id:s.id,_selected:this.selectedIds.has(s.id)},geometry:s.geometry}))};this.sourceManager.updateFeatures(t),this.pendingFeatures=null}}class $e{constructor(e){this.options=e,this.element=document.createElement("button"),this.element.type="button",this.element.title=e.title,this.element.setAttribute("aria-label",e.title),this.element.dataset.libreDrawButton=e.id,this.applyStyles(),this.iconContainer=document.createElement("span"),this.iconContainer.style.display="flex",this.iconContainer.style.alignItems="center",this.iconContainer.style.justifyContent="center",this.setIcon(e.icon),this.element.appendChild(this.iconContainer),this.element.addEventListener("click",t=>{t.preventDefault(),t.stopPropagation(),this.element.disabled||e.onClick()})}getElement(){return this.element}setActive(e){e?(this.element.style.backgroundColor="#3bb2d0",this.element.style.color="#ffffff"):(this.element.style.backgroundColor="#ffffff",this.element.style.color="#333333"),this.element.setAttribute("aria-pressed",String(e))}setDisabled(e){this.element.disabled=e,this.element.style.opacity=e?"0.4":"1",this.element.style.cursor=e?"not-allowed":"pointer"}destroy(){this.element.remove()}setIcon(e){const i=new DOMParser().parseFromString(e,"image/svg+xml").documentElement;for(;this.iconContainer.firstChild;)this.iconContainer.removeChild(this.iconContainer.firstChild);this.iconContainer.appendChild(document.importNode(i,!0))}applyStyles(){const e=this.element.style;e.display="flex",e.alignItems="center",e.justifyContent="center",e.width="44px",e.height="44px",e.padding="0",e.margin="0",e.border="1px solid #ddd",e.borderRadius="4px",e.backgroundColor="#ffffff",e.color="#333333",e.cursor="pointer",e.outline="none",e.transition="background-color 0.15s, color 0.15s",e.boxSizing="border-box"}}const Ye='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2l8.5 6.2-3.2 9.8H6.7L3.5 8.2z"/></svg>',Ge='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z"/><path d="M13 13l6 6"/></svg>',Je='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/><line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/></svg>',qe='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 14 4 9 9 4"/><path d="M20 20v-7a4 4 0 00-4-4H4"/></svg>',Qe='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 14 20 9 15 4"/><path d="M4 20v-7a4 4 0 014-4h12"/></svg>',Ze={draw:!0,select:!0,delete:!0,undo:!0,redo:!0};class et{constructor(e,t,s={}){this.buttons=new Map,this.map=e,this.callbacks=t,this.options=s,this.container=document.createElement("div"),this.container.className="libre-draw-toolbar",this.applyContainerStyles(),this.createButtons(),this.mount()}setActiveMode(e){const t=this.buttons.get("draw"),s=this.buttons.get("select");t&&t.setActive(e==="draw"),s&&s.setActive(e==="select")}setHistoryState(e,t){const s=this.buttons.get("undo"),i=this.buttons.get("redo");s&&s.setDisabled(!e),i&&i.setDisabled(!t)}destroy(){for(const e of this.buttons.values())e.destroy();this.buttons.clear(),this.container.remove()}createButtons(){const e={...Ze,...this.options.controls};e.draw&&this.addButton("draw",Ye,"Draw polygon",()=>{this.callbacks.onDrawClick()},!0),e.select&&this.addButton("select",Ge,"Select feature",()=>{this.callbacks.onSelectClick()},!0),e.delete&&this.addButton("delete",Je,"Delete selected",()=>{this.callbacks.onDeleteClick()}),e.undo&&this.addButton("undo",qe,"Undo",()=>{this.callbacks.onUndoClick()}),e.redo&&this.addButton("redo",Qe,"Redo",()=>{this.callbacks.onRedoClick()})}addButton(e,t,s,i,n){const o=new $e({id:e,icon:t,title:s,onClick:i,isToggle:n});this.buttons.set(e,o),this.container.appendChild(o.getElement())}mount(){const e=this.options.position||"top-right",t=this.map.getContainer(),s=t.querySelector(`.maplibregl-ctrl-${e}`);s?s.appendChild(this.container):t.appendChild(this.container)}applyContainerStyles(){const e=this.container.style;e.display="flex",e.flexDirection="column",e.gap="4px",e.padding="4px",e.backgroundColor="rgba(255, 255, 255, 0.9)",e.borderRadius="4px",e.boxShadow="0 1px 4px rgba(0, 0, 0, 0.3)",e.zIndex="1",e.pointerEvents="auto"}}class tt{constructor(e,t={}){this.toolbar=null,this.destroyed=!1,this.map=e,this.eventBus=new ge,this.featureStore=new R,this.historyManager=new fe(t.historyLimit??100),this.modeManager=new pe,this.sourceManager=new We(e),this.renderManager=new Ke(e,this.sourceManager);const s=new Se({addFeatureToStore:i=>this.featureStore.add(i),pushToHistory:i=>{this.historyManager.push(i),this.updateToolbarHistoryState()},emitEvent:(i,n)=>this.eventBus.emit(i,n),renderPreview:i=>this.renderManager.renderPreview(i),clearPreview:()=>this.renderManager.clearPreview(),renderFeatures:()=>this.renderAllFeatures(),getScreenPoint:i=>{const n=e.project([i.lng,i.lat]);return{x:n.x,y:n.y}}});if(this.selectMode=new Oe({removeFeatureFromStore:i=>this.featureStore.remove(i),pushToHistory:i=>{this.historyManager.push(i),this.updateToolbarHistoryState()},emitEvent:(i,n)=>this.eventBus.emit(i,n),renderFeatures:()=>this.renderAllFeatures(),getFeatureById:i=>this.featureStore.getById(i),getAllFeatures:()=>this.featureStore.getAll(),getScreenPoint:i=>{const n=e.project([i.lng,i.lat]);return{x:n.x,y:n.y}},updateFeatureInStore:(i,n)=>this.featureStore.update(i,n),renderVertices:(i,n,o,l)=>this.renderManager.renderVertices(n,o,l),clearVertices:()=>this.renderManager.clearVertices(),setDragPan:i=>{i?e.dragPan.enable():e.dragPan.disable()}},i=>{this.renderManager.setSelectedIds(i)}),this.modeManager.registerMode("idle",new Ie),this.modeManager.registerMode("draw",s),this.modeManager.registerMode("select",this.selectMode),this.modeManager.setOnModeChange((i,n)=>{this.eventBus.emit("modechange",{mode:i,previousMode:n}),this.toolbar&&this.toolbar.setActiveMode(i),i==="draw"?(e.dragPan.disable(),e.doubleClickZoom.disable()):i==="select"?e.doubleClickZoom.disable():(e.dragPan.enable(),e.doubleClickZoom.enable())}),this.inputHandler=new Xe(e,()=>this.modeManager.getCurrentMode()),t.toolbar!==!1&&t.toolbar!==void 0){const i=typeof t.toolbar=="object"?t.toolbar:{};this.createToolbar(i)}e.isStyleLoaded()?this.initialize():e.once("load",()=>{this.initialize()})}setMode(e){this.assertNotDestroyed(),this.modeManager.setMode(e)}getMode(){return this.assertNotDestroyed(),this.modeManager.getMode()}getFeatures(){return this.assertNotDestroyed(),this.featureStore.getAll()}toGeoJSON(){return this.assertNotDestroyed(),this.featureStore.toGeoJSON()}setFeatures(e){this.assertNotDestroyed();const t=Ee(e);this.featureStore.setAll(t.features),this.historyManager.clear(),this.renderAllFeatures(),this.updateToolbarHistoryState()}addFeatures(e){this.assertNotDestroyed();for(const t of e){const s=le(t);this.featureStore.add(s)}this.renderAllFeatures()}getSelectedFeatureIds(){return this.assertNotDestroyed(),this.selectMode.getSelectedIds()}getFeatureById(e){return this.assertNotDestroyed(),this.featureStore.getById(e)}deleteFeature(e){this.assertNotDestroyed();const t=this.featureStore.getById(e);if(!t)return;this.selectMode.getSelectedIds().includes(e)&&this.selectMode.clearSelection(),this.featureStore.remove(e);const i=new oe(t);return this.historyManager.push(i),this.eventBus.emit("delete",{feature:t}),this.renderAllFeatures(),this.updateToolbarHistoryState(),t}selectFeature(e){if(this.assertNotDestroyed(),!this.featureStore.getById(e))throw new v(`Feature not found: ${e}`);this.modeManager.getMode()!=="select"&&this.modeManager.setMode("select"),this.selectMode.selectFeature(e)}clearSelection(){this.assertNotDestroyed(),this.selectMode.clearSelection()}undo(){this.assertNotDestroyed();const e=this.historyManager.undo(this.featureStore);return e&&(this.renderAllFeatures(),this.selectMode.refreshVertexHandles(),this.updateToolbarHistoryState()),e}redo(){this.assertNotDestroyed();const e=this.historyManager.redo(this.featureStore);return e&&(this.renderAllFeatures(),this.selectMode.refreshVertexHandles(),this.updateToolbarHistoryState()),e}on(e,t){this.assertNotDestroyed(),this.eventBus.on(e,t)}off(e,t){this.assertNotDestroyed(),this.eventBus.off(e,t)}destroy(){this.destroyed||(this.destroyed=!0,this.modeManager.setMode("idle"),this.inputHandler.destroy(),this.renderManager.destroy(),this.eventBus.removeAllListeners(),this.historyManager.clear(),this.featureStore.clear(),this.toolbar&&(this.toolbar.destroy(),this.toolbar=null))}initialize(){this.destroyed||(this.renderManager.initialize(),this.inputHandler.enable())}renderAllFeatures(){const e=this.featureStore.getAll();this.renderManager.render(e)}createToolbar(e){this.toolbar=new et(this.map,{onDrawClick:()=>{const t=this.modeManager.getMode();this.modeManager.setMode(t==="draw"?"idle":"draw")},onSelectClick:()=>{const t=this.modeManager.getMode();this.modeManager.setMode(t==="select"?"idle":"select")},onDeleteClick:()=>{if(this.modeManager.getMode()==="select"){const t=this.selectMode.getSelectedIds();for(const s of t)this.deleteFeature(s)}},onUndoClick:()=>{this.undo()},onRedoClick:()=>{this.redo()}},e),this.toolbar.setActiveMode(this.modeManager.getMode()),this.toolbar.setHistoryState(this.historyManager.canUndo(),this.historyManager.canRedo())}updateToolbarHistoryState(){this.toolbar&&this.toolbar.setHistoryState(this.historyManager.canUndo(),this.historyManager.canRedo())}assertNotDestroyed(){if(this.destroyed)throw new v("This LibreDraw instance has been destroyed.")}}exports.LibreDraw=tt;exports.LibreDrawError=v;
|
|
2
2
|
//# sourceMappingURL=libre-draw.cjs.map
|