leaflet-polydraw
Version:
Advanced Leaflet plugin for freehand polygon drawing, with smart merging and powerful editing tools. Compatible with both Leaflet v1.x and v2.x.
537 lines • 19.3 kB
TypeScript
import * as L from 'leaflet';
import { DrawMode } from './enums';
import { type PolydrawEvent, type PolydrawEventCallback } from './managers/event-manager';
import { LayerManager, type LayerState } from './managers/layer-manager';
import './styles/polydraw.css';
import type { PolydrawConfig, HistoryAction, LayerDeleteResult, LayerInteraction, LayerPanelVisibility, LayerUpdateInput, PredefinedPolygonOptions, PolygonLayerDescriptorInput, PolygonGroupInput } from './types/polydraw-interfaces';
type PolydrawOptions = L.ControlOptions & {
config?: Partial<PolydrawConfig>;
configPath?: string;
};
type SetDrawModeOptions = {
preserveActiveDraw?: boolean;
};
declare class Polydraw extends L.Control {
private map;
private tracer;
private turfHelper;
private subContainer?;
private config;
private mapStateService;
private eventManager;
private polygonInformation;
private modeManager;
private polygonDrawManager;
private polygonMutationManager;
private historyManager;
private layerManager;
private layerPanel;
private arrayOfFeatureGroups;
private drawMode;
private drawModeListeners;
private _boundKeyDownHandler?;
private _boundKeyUpHandler?;
private isModifierKeyHeld;
private modifierModeOverride;
private isDrawingInProgress;
private mapEventsAttached;
private drawEventsAttached;
private controlEvents;
private lastControlPointerDown;
private _boundMouseMove?;
private _boundMouseUp?;
private _boundTouchMove?;
private _boundTouchEnd?;
private _boundTouchCancel?;
private _boundTouchStart?;
private _boundPointerDown?;
private _boundPointerMove?;
private _boundPointerUp?;
private _boundPointerCancel?;
private _boundContextMenu?;
private _lastTapTime;
private _lastTapLatLng;
private _tapTimeout;
private pointerEventsHandled;
private _configReady;
private _componentsInitialized;
private _isControlMounted;
private _isRestoringSnapshot;
private _coreEventListenersAttached;
private _coreEventSubscriptions;
private _initRequestId;
private _historySuppressionDepth;
private _lastAppliedVisibleMapOrder;
private originalMapTouchAction;
constructor(options?: PolydrawOptions);
/**
* Method called when the control is added to the map.
* It initializes the control, creates the UI, and sets up event listeners.
* @param _map - The map instance.
* @returns The control's container element.
*/
onAdd(_map: L.Map): HTMLElement;
/**
* Completes the initialization after config is ready.
* Handles both sync (no configPath) and async (configPath) cases.
*/
private completeInitialization;
/**
* Method called when the control is removed from the map.
* It handles the cleanup of layers, events, and handlers.
* @param _map - The map instance, unused but required by the L.Control interface.
*/
onRemove(_map: L.Map): void;
/**
* Perform comprehensive cleanup of all resources
* This method ensures proper cleanup of event listeners, managers, and DOM elements
*/
comprehensiveCleanup(): void;
/**
* Adds the control to the given map.
* @param map - The map instance.
* @returns The current instance of the control.
*/
addTo(map: L.Map): this;
/**
* Returns the array of feature groups currently managed by the control.
* @returns An array of L.FeatureGroup objects.
*/
getFeatureGroups(): L.FeatureGroup[];
/**
* Undo the last action
*/
undo(): Promise<void>;
private isPolygonAction;
private shouldCaptureHistory;
private saveHistory;
private isHistorySuppressed;
private startHistoryBatch;
private endHistoryBatch;
/**
* Redo the last undone action
*/
redo(): Promise<void>;
private resolvePredefinedLayerDescriptor;
private ensureLayerFromDescriptor;
private getInteractionTargetLayerId;
private ensureFeatureGroupMetadata;
/**
* Adds a predefined polygon to the map.
* @param geoborders - Flexible coordinate format: objects ({lat, lng}), arrays ([lat, lng] or [lng, lat]), strings ("lat,lng" or "N59 E10")
* @param options - Optional parameters, including visual optimization level.
*/
addPredefinedPolygon(geoborders: unknown[][][], options?: PredefinedPolygonOptions): Promise<void>;
/**
* Adds predefined polygons from GeoJSON to the map.
* @param geojsonFeatures - An array of GeoJSON Polygon or MultiPolygon features.
* @param options - Optional parameters, including visual optimization level.
*/
addPredefinedGeoJSONs(geojsonFeatures: GeoJSON.Feature<GeoJSON.Polygon | GeoJSON.MultiPolygon>[], options?: PredefinedPolygonOptions): Promise<void>;
/**
* Adds multiple groups of predefined polygons, each associated with a named, colored layer.
* @param groups - Array of polygon group inputs with layer info and polygon coordinates.
*/
addPredefinedPolygonGroups(groups: PolygonGroupInput[]): Promise<void>;
/**
* Returns the LayerManager instance for external layer manipulation.
*/
getLayerManager(): LayerManager;
/**
* Returns all configured layers.
*/
getAllLayers(): LayerState[];
/**
* Returns a single layer by id.
*/
getLayerById(layerId: string): LayerState | undefined;
/**
* Returns true if a layer exists.
*/
hasLayer(layerId: string): boolean;
/**
* Returns the active layer state.
*/
getActiveLayer(): LayerState | undefined;
/**
* Returns feature groups assigned to the given layer.
*/
getFeatureGroupsByLayer(layerId: string): L.FeatureGroup[];
/**
* Creates a new layer. Throws if the layer already exists.
*/
createLayer(input: PolygonLayerDescriptorInput): LayerState;
/**
* Creates or updates a layer descriptor idempotently.
*/
ensureLayer(input: PolygonLayerDescriptorInput): LayerState;
/**
* Updates layer properties. Returns updated state, or undefined if not found.
*/
updateLayer(layerId: string, patch: LayerUpdateInput): LayerState | undefined;
/**
* Deletes a non-default layer.
*/
deleteLayer(layerId: string): LayerDeleteResult;
/**
* Activates a layer.
*/
setActiveLayer(layerId: string): boolean;
/**
* Updates visibility for a layer.
*/
setLayerVisibility(layerId: string, visible: boolean): boolean;
/**
* Shows a layer.
*/
showLayer(layerId: string): boolean;
/**
* Hides a layer.
*/
hideLayer(layerId: string): boolean;
/**
* Updates a layer color.
*/
setLayerColor(layerId: string, color: string): boolean;
/**
* Updates interaction policy for a layer.
*/
setLayerInteraction(layerId: string, interaction: LayerInteraction): boolean;
/**
* Updates panel visibility policy for a layer.
*/
setLayerPanelVisibility(layerId: string, panel: LayerPanelVisibility): boolean;
/**
* Replaces layer metadata.
*/
setLayerMetadata(layerId: string, metadata: Record<string, unknown>): boolean;
/**
* Shallow-merges metadata into existing layer metadata.
*/
patchLayerMetadata(layerId: string, metadataPatch: Record<string, unknown>): boolean;
/**
* Returns a shallow copy of feature metadata for a feature group.
*/
getFeatureMetadata(featureGroup: L.FeatureGroup): Record<string, unknown> | undefined;
/**
* Replaces feature metadata for a feature group.
*/
setFeatureMetadata(featureGroup: L.FeatureGroup, metadata: Record<string, unknown>): boolean;
/**
* Shallow-merges metadata into feature metadata for a feature group.
*/
patchFeatureMetadata(featureGroup: L.FeatureGroup, metadataPatch: Record<string, unknown>): boolean;
/**
* Reorder layers by moving one layer to another layer's position.
*/
reorderLayer(layerId: string, targetLayerId: string): boolean;
/**
* Returns the id of the currently active layer.
*/
getActiveLayerId(): string;
/**
* Returns the layer id that the given feature group is assigned to, or undefined.
*/
getLayerForFeatureGroup(featureGroup: L.FeatureGroup): string | undefined;
/**
* Assigns a feature group to a layer. If the feature group is already
* assigned to another layer it is moved. Returns false if the target layer
* does not exist.
*/
assignFeatureGroupToLayer(featureGroup: L.FeatureGroup, layerId: string): boolean;
/**
* Moves a feature group from its current layer to the given layer.
* Alias for {@link assignFeatureGroupToLayer}.
*/
moveFeatureGroupToLayer(featureGroup: L.FeatureGroup, layerId: string): boolean;
/**
* Removes a feature group from whatever layer it is currently assigned to.
*/
removeFeatureGroupFromLayer(featureGroup: L.FeatureGroup): void;
/**
* Deletes all non-default layers and removes their feature groups from the map.
* The default layer is left empty. A single history snapshot is saved before clearing.
*/
clearLayers(): void;
/**
* Moves a layer to a specific 0-based position in the layer order.
* The default layer always occupies index 0; valid target indices for
* non-default layers start at 1. The index is clamped to the valid range.
*/
moveLayerToIndex(layerId: string, index: number): boolean;
/**
* Sets the full layer order by providing an ordered list of layer IDs.
* The default layer always stays first. Layers not included in the list are
* appended after the specified layers in their current relative order.
* Returns false if any specified ID does not exist or equals 'default'.
*/
setLayerOrder(layerIds: string[]): boolean;
private refreshAfterLayerStructureChange;
/**
* Begin a batch operation. A single history snapshot is saved before the
* batch starts; all individual history saves inside the batch are suppressed.
* Must be paired with {@link endBatch}.
* @param action - Optional history action label for the snapshot.
*/
beginBatch(action?: HistoryAction): void;
/**
* End a batch operation started with {@link beginBatch}.
*/
endBatch(): void;
/**
* Sets the current drawing mode.
* @param mode - The drawing mode to set.
*/
setDrawMode(mode: DrawMode, options?: SetDrawModeOptions): void;
/**
* Returns the current drawing mode.
* @returns The current DrawMode.
*/
getDrawMode(): DrawMode;
/**
* Registers an event listener for a given event type.
* @param event - The event type to listen for.
* @param callback - The callback function to execute when the event is triggered.
*/
on<T extends PolydrawEvent>(event: T, callback: PolydrawEventCallback<T>): void;
/**
* Unregisters an event listener for a given event type.
* @param event - The event type to stop listening for.
* @param callback - The callback function to remove.
*/
off<T extends PolydrawEvent>(event: T, callback: PolydrawEventCallback<T>): void;
/**
* Removes all feature groups from the map and clears the internal storage.
*/
removeAllFeatureGroups(): void;
private removeDefaultLayerFeatureGroups;
private removeFeatureGroupsFromMap;
/**
* Public method to perform comprehensive cleanup
* This can be called manually to clean up resources without removing the control from the map
*/
cleanup(): void;
/**
* Initializes the user interface, creates DOM elements, sets up buttons, and injects styles.
* @param container - The main control container element.
*/
private initializeUI;
/**
* Attaches listeners to polygonMutationManager and eventManager.
*/
private addCoreEventListener;
private removeCoreEventListeners;
private setupEventListeners;
/**
* Initializes and adds the tracer polyline to the map.
*/
private createTracer;
/**
* Applies the correct weight/opacity/color/dash style to the tracer for the given mode.
*/
private applyTracerStyle;
/**
* Returns base tracer styles depending on whether we're in subtract mode.
*/
private getTracerBaseStyle;
/**
* Sets up PolygonDrawManager and PolygonMutationManager with the map.
*/
private initializeManagers;
/**
* Loads an external configuration file and merges it with the default and inline configs.
* @param configPath - The path to the external configuration file.
* @param inlineConfig - An optional inline configuration object.
*/
private loadExternalConfig;
/**
* Initializes the core components of the Polydraw control.
*/
/**
* Updates the state of the drawing mode.
* @param mode - The new drawing mode.
*/
private _updateDrawModeState;
/**
* Updates the UI after a change in the drawing mode.
* @param mode - The new drawing mode.
*/
private _updateUIAfterDrawModeChange;
/**
* Updates map interactions based on the current drawing mode.
*/
private _handleActivateToggle;
private _handleDrawClick;
private _handleSubtractClick;
private _handleCloneClick;
private _handleEraseClick;
private _handlePointToPointClick;
private _handlePointToPointSubtractClick;
private _handleUndoClick;
private _handleRedoClick;
private shouldEnableDrawEvents;
private _updateMapInteractions;
private setMapDrawingTouchLock;
/**
* Restore the map state from a history snapshot
*/
private restoreFromSnapshot;
private initializeComponents;
/**
* Emits an event to notify listeners that the drawing mode has changed.
*/
private emitDrawModeChanged;
/**
* Update the draggable state of all existing markers when draw mode changes
*/
private updateMarkerDraggableState;
/**
* Update the layer panel visibility and contents
*/
private updateLayerPanel;
/**
* Reorder the global feature-group array to follow the current layer order
* and re-apply map draw order accordingly.
*/
private syncFeatureGroupOrderWithLayers;
private isSameFeatureGroupOrder;
/**
* Re-apply map layer order for visible feature groups. Layer order is stored and
* shown top-to-bottom, while Leaflet renders later-added layers on top.
*/
private reapplyFeatureGroupMapOrder;
/**
* Remove non-default layers that have no feature groups left.
*/
private cleanupEmptyLayers;
/**
* Stops the current drawing operation and resets the tracer.
*/
private stopDraw;
/**
* Enables or disables Leaflet's default map interactions.
* @param enableDragging - Whether to enable map dragging.
* @param enableDoubleClickZoom - Whether to enable double-click zoom.
* @param enableScrollWheelZoom - Whether to enable scroll wheel zoom.
*/
private setLeafletMapEvents;
/**
* Resets the tracer polyline by clearing its LatLngs.
*/
private resetTracker;
/**
* Attaches or detaches the mouse move and mouse up event listeners for drawing.
* @param onoff - A boolean indicating whether to attach or detach the events.
*/
private drawStartedEvents;
/**
* Attaches or detaches the main drawing event listeners.
* @param onoff - A boolean indicating whether to attach or detach the events.
*/
private events;
/**
* Handle touch start events with double-tap detection
* @param event - The touch event
*/
private handleTouchStart;
private isP2PDoubleTapClose;
/**
* Handle double-tap for touch devices
* @param event - The touch event
*/
private handleDoubleTap;
/**
* Handles the mouse down event to start a drawing operation.
* @param event - The mouse, touch, or pointer event.
*/
private mouseDown;
private isEventFromControl;
private extractPointerInfo;
private markControlPointerDown;
private clearControlPointerDown;
private isRecentControlPointer;
/**
* Handles the mouse move event to draw the tracer polyline.
* @param event - The mouse, touch, or pointer event.
*/
private mouseMove;
/**
* Handles the mouse up event to complete a drawing operation.
* @param event - The mouse, touch, or pointer event.
*/
private mouseUpLeave;
/**
* Handles the completion of a freehand drawing operation.
* @param geoPos - The GeoJSON feature representing the drawn polygon.
*/
private handleFreehandDrawCompletion;
/**
* Starts a drawing operation by attaching the necessary event listeners.
*/
private startDraw;
/**
* Sets up the keyboard event handlers for the document.
*/
private setupKeyboardHandlers;
/**
* Removes the keyboard event handlers from the document.
*/
private removeKeyboardHandlers;
/**
* Handles the key down event for keyboard shortcuts.
* @param e - The keyboard event.
*/
private handleKeyDown;
/**
* Handles the key up event for keyboard shortcuts.
* @param e - The keyboard event.
*/
private handleKeyUp;
private applyModifierModeOverride;
/**
* Update all markers to show/hide edge deletion visual feedback
*/
private updateAllMarkersForEdgeDeletion;
/**
* Update individual marker for edge deletion visual feedback
*/
private updateMarkerForEdgeDeletion;
/**
* Handle marker hover when modifier key is held - event handler version
*/
private onMarkerHoverForEdgeDeletionEvent;
/**
* Handle marker leave when modifier key is held - event handler version
*/
private onMarkerLeaveForEdgeDeletionEvent;
/**
* Handles the double-click event for point-to-point drawing.
* @param e - The mouse event.
*/
private handleDoubleClick;
/**
* Detect if modifier key is pressed (Ctrl on Windows/Linux, Cmd on Mac)
*/
private isModifierKeyPressed;
/**
* Ensures all buttons have proper touch responsiveness for Firefox Android
* @param container - The main control container element
*/
private ensureButtonTouchResponsiveness;
/**
* Updates the visual indicator on the activate button to show if there are active polygons.
*/
private updateActivateButtonIndicator;
private applyActivateButtonIcon;
}
type LeafletRegisterTarget = {
control?: {
polydraw?: (options?: PolydrawOptions) => Polydraw;
};
};
export declare const registerWithLeaflet: (leafletInstance?: LeafletRegisterTarget) => void;
export default Polydraw;
export { defaultConfig } from './config';
export { leafletAdapter } from './compatibility/leaflet-adapter';
export type { PolygonMenuAction, PolygonMenuActionContext, PolygonMenuActionResult, } from './types/polydraw-interfaces';
//# sourceMappingURL=polydraw.d.ts.map