UNPKG

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
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