@zwishing/emap 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +212 -1
  2. package/FEATURES.md +455 -0
  3. package/README.md +415 -210
  4. package/dist/core/event-map.d.ts +67 -0
  5. package/dist/core/feature-event-dispatcher.d.ts +70 -0
  6. package/dist/core/handler-manager.d.ts +49 -0
  7. package/dist/core/handler.d.ts +48 -0
  8. package/dist/core/handlers/box-select.d.ts +54 -0
  9. package/dist/core/handlers/click-select.d.ts +31 -0
  10. package/dist/core/handlers/drag-pan.d.ts +28 -0
  11. package/dist/core/handlers/draw-feature.d.ts +76 -0
  12. package/dist/core/handlers/lasso-select.d.ts +57 -0
  13. package/dist/core/handlers/scroll-zoom.d.ts +24 -0
  14. package/dist/core/handlers/select-geometry.d.ts +24 -0
  15. package/dist/core/handlers/select-mode.d.ts +14 -0
  16. package/dist/core/handlers/transform-feature.d.ts +41 -0
  17. package/dist/core/handlers/vertex-edit.d.ts +98 -0
  18. package/dist/core/pointer-event-dispatcher.d.ts +40 -0
  19. package/dist/core/tween.d.ts +1 -0
  20. package/dist/emap.css +42 -8
  21. package/dist/emap.js +2 -2
  22. package/dist/emap.mjs +1 -1
  23. package/dist/geo/camera.d.ts +100 -0
  24. package/dist/geo/projection.d.ts +8 -1
  25. package/dist/geo/viewport.d.ts +18 -0
  26. package/dist/index.d.ts +26 -2
  27. package/dist/map/edit-state-store.d.ts +1 -1
  28. package/dist/map/map.d.ts +89 -2
  29. package/dist/map/selection.d.ts +5 -2
  30. package/dist/renderer/edit-overlay-renderer.d.ts +2 -1
  31. package/dist/source/source.d.ts +2 -2
  32. package/dist/source/topology-source.d.ts +7 -2
  33. package/dist/ui/box-select-control.d.ts +13 -37
  34. package/dist/ui/draw-feature-control.d.ts +6 -71
  35. package/dist/ui/lasso-select-control.d.ts +14 -61
  36. package/dist/ui/status-control.d.ts +2 -2
  37. package/dist/ui/vertex-edit-control.d.ts +5 -100
  38. package/package.json +5 -1
  39. package/dist/core/drag-pan-handler.d.ts +0 -28
@@ -0,0 +1,100 @@
1
+ export interface CameraOptions {
2
+ /** Target centre in projected/data coords (= P8 `mapCoord` space). */
3
+ center?: [number, number];
4
+ /** Target zoom (WebMercator convenience; converted via host.scaleFromZoom). */
5
+ zoom?: number;
6
+ /** Target scale (= |mx|); CRS-agnostic. Takes precedence over `zoom`. */
7
+ scale?: number;
8
+ }
9
+ export interface AnimationOptions {
10
+ /** ms. Default 1000 for ease/fly. Ignored when animate:false. */
11
+ duration?: number;
12
+ /** t∈[0,1] → eased t. Default Tween.sineInOut. */
13
+ easing?: (t: number) => number;
14
+ /** false (or duration:0) ⇒ jump (no animation). Default true. */
15
+ animate?: boolean;
16
+ }
17
+ export interface FlyToOptions extends CameraOptions, AnimationOptions {
18
+ /** van-Wijk curvature. Default 1.42. */
19
+ curve?: number;
20
+ /** Average flight speed (screenfuls/sec). Overrides duration if set. */
21
+ speed?: number;
22
+ }
23
+ export interface FitBoundsOptions extends AnimationOptions {
24
+ /** Pixels of inset on every side. Default 0. */
25
+ padding?: number;
26
+ /** Clamp the fitted scale to <= scale(maxZoom-equivalent). */
27
+ maxScale?: number;
28
+ }
29
+ export interface CameraState {
30
+ center: [number, number];
31
+ scale: number;
32
+ }
33
+ /** Minimal surface Camera needs (keeps it unit-testable, no Emap import). */
34
+ export interface CameraHost {
35
+ getCameraState(): CameraState;
36
+ applyCameraState(center: [number, number], scale: number): void;
37
+ /** zoom→scale (NaN if not meaningful for the CRS). */
38
+ scaleFromZoom(zoom: number): number;
39
+ getViewportSize(): {
40
+ width: number;
41
+ height: number;
42
+ };
43
+ fire(type: string, e: {
44
+ center: [number, number];
45
+ zoom: number;
46
+ originalEvent: null;
47
+ }): void;
48
+ requestRender(): void;
49
+ /**
50
+ * Stop the viewport's kinetic zoomIn/zoomOut tween, if any. Optional so
51
+ * host stubs (and CRS-agnostic tests) need not implement it; the real
52
+ * Emap host wires it to `Viewport.cancelZoomAnimation`. Without this a
53
+ * `zoomIn()` tween still running when a camera method fires would keep
54
+ * overwriting the transform and fight the camera destination.
55
+ */
56
+ cancelZoomAnimation?(): void;
57
+ }
58
+ /**
59
+ * Camera — animated view controller (DX P9). Drives the host viewport via
60
+ * the existing `Tween`. State is `{center (data coords), scale}`; `zoom`
61
+ * is an optional WebMercator convenience. 2D only (no bearing/pitch).
62
+ * One active animation at a time (last-call-wins; see `easeTo`/`stop`).
63
+ */
64
+ export declare class Camera {
65
+ private _host;
66
+ private _tween;
67
+ private _activeEnd;
68
+ constructor(_host: CameraHost);
69
+ /** Resolve a CameraOptions to a concrete target {center,scale}. */
70
+ private _resolve;
71
+ private _payload;
72
+ /** True while an animation is running. */
73
+ isMoving(): boolean;
74
+ /** Instant move. Fires the movestart/move/moveend (+zoom*) lifecycle synchronously. */
75
+ jumpTo(o: CameraOptions): void;
76
+ /**
77
+ * Animated move. Lerps centre linearly and scale in log space over
78
+ * `duration` ms with `easing`. `animate:false`/`duration:0` ⇒ jump.
79
+ * Last-call-wins: supersedes any running animation (its terminal
80
+ * events fire first, via `_cancel`).
81
+ */
82
+ easeTo(o: CameraOptions & AnimationOptions): void;
83
+ setCenter(center: [number, number]): void;
84
+ setZoom(zoom: number): void;
85
+ zoomTo(zoom: number, o?: AnimationOptions): void;
86
+ panTo(center: [number, number], o?: AnimationOptions): void;
87
+ /** Pan by a pixel offset (converted to a data-coord centre shift). */
88
+ panBy(offset: [number, number], o?: AnimationOptions): void;
89
+ /** Fit a Bounds (data coords) into the viewport with optional padding. */
90
+ fitBounds(b: import('./bounds').Bounds, o?: FitBoundsOptions): void;
91
+ /**
92
+ * van-Wijk (2004) parabolic flight: for a far move, zoom out, pan, zoom
93
+ * back in. Reduces to easeTo for near moves. `curve` default 1.42.
94
+ */
95
+ flyTo(o: FlyToOptions): void;
96
+ /** Cancel a running animation, firing its terminal events at the current state. */
97
+ private _cancel;
98
+ /** Public: stop any running animation (no-op when idle). */
99
+ stop(): void;
100
+ }
@@ -16,9 +16,16 @@ export declare class Projection {
16
16
  getCenter(cx: number, cy: number): [number, number];
17
17
  /**
18
18
  * Compute a zoom level from the scale factor.
19
- * Only meaningful for Web Mercator.
19
+ * Only meaningful for Web Mercator — returns `0` for other CRS
20
+ * (not a sentinel; prefer the {@link getScale} round-trip to detect CRS).
20
21
  */
21
22
  getZoom(mx: number): number;
23
+ /**
24
+ * Inverse of `getZoom`: the scale factor (|mx|) for a given zoom.
25
+ * Only meaningful for Web Mercator — returns `NaN` otherwise so callers
26
+ * can detect "zoom not applicable for this CRS" and fall back to scale.
27
+ */
28
+ getScale(zoom: number): number;
22
29
  /**
23
30
  * Reproject all sources to a target CRS.
24
31
  * Returns the merged extent of all reprojected layers.
@@ -26,6 +26,24 @@ export declare class Viewport {
26
26
  updateSize(width: number, height: number): void;
27
27
  setExtent(bounds: Bounds): void;
28
28
  reset(): void;
29
+ /**
30
+ * Current camera state in projected/data coordinates. `center` is the
31
+ * data point at the viewport centre (same space as `unproject` and
32
+ * `getExtent`, before any CRS/geographic mapping). `scale` is `|mx|`.
33
+ */
34
+ getCameraState(): {
35
+ center: [number, number];
36
+ scale: number;
37
+ };
38
+ /**
39
+ * Set the transform so `center` (data coords) sits at the viewport
40
+ * centre at `scale` (= |mx|), preserving the existing flipY (my<0)
41
+ * convention, then re-apply pan/zoom constraints. Additive primitive
42
+ * for the Camera; does not touch `setExtent`/`reset` state. Callers own
43
+ * the render / `onViewChange` trigger after this call (the Camera fires
44
+ * the move/zoom lifecycle itself).
45
+ */
46
+ applyCameraState(center: [number, number], scale: number): void;
29
47
  clearInitialState(): void;
30
48
  private _updateTransform;
31
49
  pan(dx: number, dy: number): void;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import './shim';
2
2
  import 'mapshaper';
3
3
  export { Emap } from './map/map';
4
- export type { MapOptions, ExpressionEvaluationPolicy, QueryFeaturesOptions, QueriedFeature, FeatureRef, HighlightFeatureRef, HighlightStyle, FeatureTranslateSession, FeatureAffineSession, ClipEraseOptions, DissolveOptions, CleanOptions, BufferOptions, ApplyExpressionOptions, ExplodeOptions, InnerlinesOptions, FilterOptions, FilterIslandsOptions, FilterSliversOptions, FilterGeomOptions, AffineLayerOptions, DataFillOptions, SnapOptions, MosaicOptions, UnionOptions, DivideOptions, PointsOptions, PointsMode, LinesOptions, PolygonsOptions, SimplifyOptions, SimplifyMethod, ProjectOptions, RebuildTopologyOptions, RenameLayerOptions, MergeLayersOptions, SplitLayerOptions, DropLayerOptions, SortFeaturesOptions, UniqueFeaturesOptions, FilterFieldsOptions, RenameFieldsOptions, JoinTableOptions, JoinTableData, CheckGeometryOptions, GeometryCheckReport, IntersectionPointsLayerOptions, ExportSnapshotOptions, LoadSnapshotOptions, } from './map/map';
4
+ export type { MapOptions, ExpressionEvaluationPolicy, QueryFeaturesOptions, QueriedFeature, FeatureRef, HighlightFeatureRef, HighlightStyle, FeatureTranslateSession, FeatureAffineSession, DragSessionOptions, ClipEraseOptions, DissolveOptions, CleanOptions, BufferOptions, ApplyExpressionOptions, ExplodeOptions, InnerlinesOptions, FilterOptions, FilterIslandsOptions, FilterSliversOptions, FilterGeomOptions, AffineLayerOptions, DataFillOptions, SnapOptions, MosaicOptions, UnionOptions, DivideOptions, PointsOptions, PointsMode, LinesOptions, PolygonsOptions, SimplifyOptions, SimplifyMethod, ProjectOptions, RebuildTopologyOptions, RenameLayerOptions, MergeLayersOptions, SplitLayerOptions, DropLayerOptions, SortFeaturesOptions, UniqueFeaturesOptions, FilterFieldsOptions, RenameFieldsOptions, JoinTableOptions, JoinTableData, CheckGeometryOptions, GeometryCheckReport, IntersectionPointsLayerOptions, ExportSnapshotOptions, LoadSnapshotOptions, } from './map/map';
5
5
  export type { LayerSpecification, LayerType, LayerPaint, LayerLayout, FillPaint, LinePaint, CirclePaint, } from './map/layer';
6
6
  export { resolveStrokeStyle, resolvePointStyle } from './map/layer';
7
7
  export { HighlightManager } from './map/highlight-manager';
@@ -31,7 +31,31 @@ export { CanvasPainter } from './renderer/canvas-painter';
31
31
  export { EditOverlayRenderer } from './renderer/edit-overlay-renderer';
32
32
  export { EventDispatcher } from './core/events';
33
33
  export type { EventListener } from './core/events';
34
- export { DragPanHandler } from './core/drag-pan-handler';
34
+ export type { EmapEventMap, CameraEvent } from './core/event-map';
35
+ export type { CameraOptions, AnimationOptions, FlyToOptions, FitBoundsOptions } from './geo/camera';
36
+ export { HandlerManager } from './core/handler-manager';
37
+ export { isHandler } from './core/handler';
38
+ export type { Handler, HandlerResult, NormalizedPointerEvent, PointerModifiers } from './core/handler';
39
+ export { DragPanHandler } from './core/handlers/drag-pan';
40
+ export type { DragPanOptions } from './core/handlers/drag-pan';
41
+ export { ScrollZoomHandler } from './core/handlers/scroll-zoom';
42
+ export type { ScrollZoomOptions } from './core/handlers/scroll-zoom';
43
+ export { ClickSelectHandler } from './core/handlers/click-select';
44
+ export type { SelectHandlerOptions } from './core/handlers/click-select';
45
+ export { BoxSelectHandler } from './core/handlers/box-select';
46
+ export type { BoxSelectHandlerOptions } from './core/handlers/box-select';
47
+ export { LassoSelectHandler } from './core/handlers/lasso-select';
48
+ export type { LassoSelectHandlerOptions, LassoStyle } from './core/handlers/lasso-select';
49
+ export { resolveMode } from './core/handlers/select-mode';
50
+ export type { ModifierCombo } from './core/handlers/select-mode';
51
+ export type { FeatureEvent, FeatureEventFilter } from './core/feature-event-dispatcher';
52
+ export type { PointerMoveEvent } from './core/pointer-event-dispatcher';
53
+ export { VertexEditHandler } from './core/handlers/vertex-edit';
54
+ export type { VertexEditOptions } from './core/handlers/vertex-edit';
55
+ export { DrawFeatureHandler } from './core/handlers/draw-feature';
56
+ export type { DrawFeatureOptions } from './core/handlers/draw-feature';
57
+ export { TransformFeatureHandler } from './core/handlers/transform-feature';
58
+ export type { TransformFeatureOptions } from './core/handlers/transform-feature';
35
59
  export type { EditCommand } from './edit/edit-command';
36
60
  export { EditHistory } from './edit/edit-history';
37
61
  export type { HistoryStateSnapshot, EditHistoryOptions } from './edit/edit-history';
@@ -1,5 +1,5 @@
1
1
  import type { EditVertexState, EditDrawState } from './types';
2
- export type EditMode = 'none' | 'vertex' | 'draw';
2
+ export type EditMode = 'none' | 'vertex' | 'draw' | 'transform';
3
3
  export interface EditStateSnapshot {
4
4
  mode: EditMode;
5
5
  vertex: EditVertexState | null;
package/dist/map/map.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { EventDispatcher } from '../core/events';
2
2
  import { Bounds } from '../geo/bounds';
3
3
  import { AffineTransform } from '../geo/transform';
4
+ import { type CameraOptions, type AnimationOptions, type FlyToOptions, type FitBoundsOptions } from '../geo/camera';
4
5
  import { Painter } from '../renderer/painter';
5
6
  import { MapshaperOps } from './mapshaper-ops';
6
7
  import { EditSessions } from './edit-sessions';
@@ -8,10 +9,23 @@ import { AttributeOps } from './attribute-ops';
8
9
  import { type EditMode } from './edit-state-store';
9
10
  import { LayerRegistry } from './layer-registry';
10
11
  import { TopologySource } from '../source/source';
12
+ import type { ScrollZoomOptions } from '../core/handlers/scroll-zoom';
13
+ import type { DragPanOptions } from '../core/handlers/drag-pan';
14
+ import { type SelectHandlerOptions } from '../core/handlers/click-select';
15
+ import { type BoxSelectHandlerOptions } from '../core/handlers/box-select';
16
+ import { type LassoSelectHandlerOptions } from '../core/handlers/lasso-select';
17
+ import { type VertexEditOptions } from '../core/handlers/vertex-edit';
18
+ import { type DrawFeatureOptions } from '../core/handlers/draw-feature';
19
+ import { type TransformFeatureOptions } from '../core/handlers/transform-feature';
20
+ import type { Handler } from '../core/handler';
11
21
  import { MapshaperWorkerPool } from '../core/mapshaper-worker-pool';
22
+ import { type FeatureEvent, type FeatureEventFilter } from '../core/feature-event-dispatcher';
23
+ import { type PointerMoveEvent } from '../core/pointer-event-dispatcher';
24
+ import { type EventListener } from '../core/events';
25
+ import type { EmapEventMap } from '../core/event-map';
12
26
  import { FeatureAccessor } from './feature-accessor';
13
27
  import { ValidatorRegistry } from '../validation/registry';
14
- import { Selection, SelectMode, SelectionDiff } from './selection';
28
+ import { Selection, type SelectMode, SelectionDiff } from './selection';
15
29
  import { EditHistory } from '../edit/edit-history';
16
30
  import type { EditCommand } from '../edit/edit-command';
17
31
  import { Transaction, type TransactionInternal } from '../edit/transaction';
@@ -28,6 +42,7 @@ export declare class Emap extends EventDispatcher {
28
42
  private _editOverlay;
29
43
  private _viewport;
30
44
  private _projection;
45
+ private _camera;
31
46
  _sources: globalThis.Map<string, TopologySource>;
32
47
  /**
33
48
  * Single resolution surface for `(sourceId, layerId) → MapshaperLayer`.
@@ -44,8 +59,17 @@ export declare class Emap extends EventDispatcher {
44
59
  private _effectiveLayersCache;
45
60
  private _defaultLayersDirty;
46
61
  private _layerArcFlagsCache;
47
- private _mouseWheel;
62
+ private _handlers;
63
+ private _featureEvents;
64
+ private _pointerEvents;
65
+ private _scrollZoom;
48
66
  private _dragPan;
67
+ private _clickSelect;
68
+ private _boxSelect;
69
+ private _lassoSelect;
70
+ private _vertexEdit;
71
+ private _drawFeature;
72
+ private _transformFeature;
49
73
  private _pendingRender;
50
74
  private _rafId;
51
75
  private _controlContainers;
@@ -117,6 +141,33 @@ export declare class Emap extends EventDispatcher {
117
141
  setExpressionPolicy(policy: ExpressionEvaluationPolicy): void;
118
142
  getExpressionPolicy(): ExpressionEvaluationPolicy;
119
143
  _allowExpressionEvaluation(values: Array<string | undefined>, operation: string): boolean;
144
+ on(type: 'mousemove', listener: (e: PointerMoveEvent) => void): this;
145
+ on<K extends keyof EmapEventMap>(type: K, listener: (e: {
146
+ type: K;
147
+ } & EmapEventMap[K]) => void): this;
148
+ on<T = Record<string, unknown>>(type: string, listener: EventListener<T>): this;
149
+ on(type: string, listener: (e: FeatureEvent) => void): this;
150
+ on(type: string, filter: FeatureEventFilter, listener: (e: FeatureEvent) => void): this;
151
+ off(type: 'mousemove', listener: (e: PointerMoveEvent) => void): this;
152
+ off<K extends keyof EmapEventMap>(type: K, listener: (e: {
153
+ type: K;
154
+ } & EmapEventMap[K]) => void): this;
155
+ off<T = Record<string, unknown>>(type: string, listener: EventListener<T>): this;
156
+ off(type: string, listener: (e: FeatureEvent) => void): this;
157
+ once(type: 'mousemove', listener: (e: PointerMoveEvent) => void): this;
158
+ once<K extends keyof EmapEventMap>(type: K, listener: (e: {
159
+ type: K;
160
+ } & EmapEventMap[K]) => void): this;
161
+ once<T = Record<string, unknown>>(type: string, listener: EventListener<T>): this;
162
+ once(type: string, listener: (e: FeatureEvent) => void): this;
163
+ once(type: string, filter: FeatureEventFilter, listener: (e: FeatureEvent) => void): this;
164
+ /**
165
+ * Install ONE HandlerManager sink while ≥1 feature OR pointer listener
166
+ * exists; it fans out to both dispatchers (feature events first, then
167
+ * pointer-move — independent, order fixed for determinism). Cleared when
168
+ * neither has listeners, so default `new Emap()` pays nothing.
169
+ */
170
+ private _syncPointerSink;
120
171
  getCanvasContainer(): HTMLElement;
121
172
  getEditMode(): EditMode;
122
173
  setEditMode(mode: EditMode): void;
@@ -186,6 +237,22 @@ export declare class Emap extends EventDispatcher {
186
237
  reproject(targetCrs: string): Promise<void>;
187
238
  getCenter(): [number, number];
188
239
  getZoom(): number;
240
+ /** The drag-to-pan interaction handler. */
241
+ get dragPan(): Handler<DragPanOptions>;
242
+ /** The scroll-wheel zoom interaction handler. */
243
+ get scrollZoom(): Handler<ScrollZoomOptions>;
244
+ /** The click-to-select interaction handler (disabled by default). */
245
+ get clickSelect(): Handler<SelectHandlerOptions>;
246
+ /** The box-select interaction handler (disabled by default). */
247
+ get boxSelect(): Handler<BoxSelectHandlerOptions>;
248
+ /** The lasso-select interaction handler (disabled by default). */
249
+ get lassoSelect(): Handler<LassoSelectHandlerOptions>;
250
+ /** The vertex-edit interaction handler (disabled by default). */
251
+ get vertexEdit(): Handler<VertexEditOptions>;
252
+ /** The draw-feature interaction handler (disabled by default). */
253
+ get drawFeature(): Handler<DrawFeatureOptions>;
254
+ /** The transform-feature interaction handler (disabled by default). */
255
+ get transformFeature(): Handler<TransformFeatureOptions>;
189
256
  getTransform(): AffineTransform;
190
257
  getExtent(): Bounds;
191
258
  setExtent(bounds: Bounds): void;
@@ -194,6 +261,26 @@ export declare class Emap extends EventDispatcher {
194
261
  removeControl(control: Control): void;
195
262
  zoomIn(): void;
196
263
  zoomOut(): void;
264
+ /** Instant camera move. Fires movestart/move/moveend (+zoom*). */
265
+ jumpTo(o: CameraOptions): this;
266
+ /** Set centre (projected/data coords) instantly. */
267
+ setCenter(center: [number, number]): this;
268
+ /** Set zoom (WebMercator) instantly. */
269
+ setZoom(zoom: number): this;
270
+ /** Animated move (centre+zoom/scale). */
271
+ easeTo(o: CameraOptions & AnimationOptions): this;
272
+ /** Animated pan to a centre. */
273
+ panTo(center: [number, number], o?: AnimationOptions): this;
274
+ /** Animated pan by a pixel offset. */
275
+ panBy(offset: [number, number], o?: AnimationOptions): this;
276
+ /** Animated zoom to a level. */
277
+ zoomTo(zoom: number, o?: AnimationOptions): this;
278
+ /** van-Wijk parabolic flight. */
279
+ flyTo(o: FlyToOptions): this;
280
+ /** Fit a Bounds into the viewport with optional padding. */
281
+ fitBounds(b: import('../geo/bounds').Bounds, o?: FitBoundsOptions): this;
282
+ /** Cancel any running camera animation (no-op when idle). */
283
+ stop(): this;
197
284
  _scheduleRender(): void;
198
285
  private _doRender;
199
286
  render(): void;
@@ -1,6 +1,9 @@
1
1
  import type { FeatureRef } from './map';
2
- /** Mutation modes for {@link Selection.apply}. */
3
- export type SelectMode = 'replace' | 'add' | 'toggle';
2
+ import type { SelectMode } from '../core/handlers/select-mode';
3
+ /** Mutation modes for {@link Selection.apply}. Canonical declaration lives
4
+ * in `core/handlers/select-mode.ts`; re-exported here for back-compat
5
+ * (the public `@/map/selection` path is unchanged). */
6
+ export type { SelectMode } from '../core/handlers/select-mode';
4
7
  /** Diff produced by every selection mutation. */
5
8
  export interface SelectionDiff {
6
9
  /** Refs newly present after the mutation */
@@ -1,5 +1,6 @@
1
1
  import type { EditPainter } from './painter';
2
2
  import type { EditVertexState, EditDrawState } from '../map/types';
3
+ import type { EditMode } from '../map/edit-state-store';
3
4
  /**
4
5
  * Draws edit-mode-only decorations on top of the regular layer pass:
5
6
  * - polygon fill highlight while editing a polygon's vertices
@@ -17,6 +18,6 @@ export declare class EditOverlayRenderer {
17
18
  * Render the edit-mode overlay for the current frame. No-op when
18
19
  * `editMode === 'none'` or the relevant state object is `null`.
19
20
  */
20
- render(editMode: 'none' | 'vertex' | 'draw', vertexState: EditVertexState | null, drawState: EditDrawState | null): void;
21
+ render(editMode: EditMode, vertexState: EditVertexState | null, drawState: EditDrawState | null): void;
21
22
  private _renderVertexOverlay;
22
23
  }
@@ -1,5 +1,5 @@
1
1
  import { EventDispatcher } from '../core/events';
2
- import type { ArcCollection, MapshaperDataset } from '../types/mapshaper-types';
2
+ import type { ArcCollection, MapshaperDataset, MapshaperLayer } from '../types/mapshaper-types';
3
3
  import type { DisplayArcs } from './display-arcs';
4
4
  import type { Bounds } from '../geo/bounds';
5
5
  export interface Source extends EventDispatcher {
@@ -16,7 +16,7 @@ export interface ExportOptions {
16
16
  export interface TopologySource extends Source {
17
17
  type: 'topology';
18
18
  getArcs(): ArcCollection | undefined;
19
- getLayers(): any[];
19
+ getLayers(): MapshaperLayer[];
20
20
  /**
21
21
  * Returns the live mapshaper dataset reference owned by this source.
22
22
  *
@@ -115,11 +115,16 @@ export declare class TopologySource extends EventDispatcher implements ITopology
115
115
  setData(data: TopologySourceInput): Promise<TopologySource>;
116
116
  private _updateData;
117
117
  /**
118
- * Settle the {@link setData} deferred for the given load version. Ignored
118
+ * Resolve the {@link setData} deferred for the given load version. Ignored
119
119
  * if a newer call has already replaced it (the superseding `setData`
120
120
  * resolved the old deferred early).
121
121
  */
122
- private _settlePending;
122
+ private _resolvePending;
123
+ /**
124
+ * Reject the {@link setData} deferred for the given load version. Ignored
125
+ * if a newer call has already replaced it.
126
+ */
127
+ private _rejectPending;
123
128
  private _hasSupportedExtension;
124
129
  private _filenameFromContentType;
125
130
  getDataset(): MapshaperDataset | undefined;
@@ -1,14 +1,7 @@
1
1
  import type { Control } from './control';
2
2
  import type { Emap } from '../map/map';
3
- /** Visual style for the rubber-band rectangle. */
4
- export interface BoxSelectStyle {
5
- /** Stroke color. Default `'#0078ff'`. */
6
- stroke?: string;
7
- /** Stroke width in CSS pixels. Default `1.5`. */
8
- strokeWidth?: number;
9
- /** Fill color. Default `'rgba(0, 120, 255, 0.1)'`. */
10
- fill?: string;
11
- }
3
+ export type { BoxSelectStyle } from '../core/handlers/box-select';
4
+ import type { BoxSelectStyle } from '../core/handlers/box-select';
12
5
  export interface BoxSelectControlOptions {
13
6
  /**
14
7
  * Restrict the selection to a subset of layer ids. When omitted, every
@@ -24,44 +17,27 @@ export interface BoxSelectControlOptions {
24
17
  dragThreshold?: number;
25
18
  }
26
19
  /**
27
- * Shift+drag rubber-band feature selection. Reuses
28
- * `Emap.queryFeatures(bbox)` for hit-testing and `Emap.select` for
29
- * selection state management.
30
- *
31
- * Modifier-key conventions (layered on top of shift):
32
- * - shift only mode `'replace'`
33
- * - shift + ctrl/meta → mode `'add'`
34
- * - shift + alt → mode `'toggle'`
35
- *
36
- * Tiny drags (< `dragThreshold` px diagonal) cancel without selecting.
20
+ * Thin shell over the `map.boxSelect` handler (DX P2c). The handler owns
21
+ * the shift+drag gesture, the `.emap-box-select` rubber-band overlay,
22
+ * hit-testing, and selection; this control just forwards options and
23
+ * proxies enable/disable, returning a 0×0 anchor for `addControl`
24
+ * placement. Public class, options, anchor DOM, and selection behaviour
25
+ * are unchanged from the pre-P2c control.
37
26
  *
38
- * Coordinates with `DragPanHandler`: the handler now skips shift-modified
39
- * mousedowns, leaving shift+drag for this control.
27
+ * Modifier conventions (on top of shift): shift→`replace`,
28
+ * shift+ctrl/meta→`add`, shift+alt→`toggle`. Mutually exclusive with
29
+ * lasso-select — `onAdd` propagates the handler's throw if `lassoSelect`
30
+ * is already enabled.
40
31
  */
41
32
  export declare class BoxSelectControl implements Control {
42
33
  private _options;
43
- private _dragThreshold;
44
34
  private _enabled;
45
- private _map;
35
+ private _handler;
46
36
  private _container;
47
- private _overlay;
48
- private _canvasContainer;
49
- private _startPx;
50
- private _onMouseDownBound;
51
- private _onMouseMoveBound;
52
- private _onMouseUpBound;
53
37
  constructor(options?: BoxSelectControlOptions);
54
38
  onAdd(map: Emap): HTMLElement;
55
39
  onRemove(): void;
56
- /** Disable the control — shift+drag becomes a no-op until re-enabled. */
57
40
  disable(): void;
58
41
  enable(): void;
59
42
  isEnabled(): boolean;
60
- private _onMouseDown;
61
- private _onMouseMove;
62
- private _onMouseUp;
63
- private _cancelDrag;
64
- private _cleanupDrag;
65
- private _eventToContainerPx;
66
- private _modeFromEvent;
67
43
  }
@@ -1,82 +1,17 @@
1
- import { Control } from './control';
2
- import { Emap } from '../map/map';
3
- export type DrawGeometryType = 'polygon' | 'polyline' | 'point';
4
- export interface DrawFeatureControlOptions {
5
- /** Target source ID where new features will be added */
6
- source: string;
7
- /** Target layer name within the source (optional, defaults to first matching geometry layer) */
8
- sourceLayer?: string;
9
- /** Geometry type to draw */
10
- type: DrawGeometryType;
11
- /** Pixel threshold for vertex snapping (default: 10) */
12
- snapThreshold?: number;
13
- /**
14
- * Sources to snap against. Defaults to `[options.source]` so the existing
15
- * single-source behaviour is preserved when omitted. Pass `['a', 'b']` to
16
- * also snap onto another source (e.g. drawing in source A while tracing
17
- * along reference data in source B).
18
- */
19
- snapSources?: string[];
20
- /** Enable vertex snap (default `true`). */
21
- snapToVertex?: boolean;
22
- /**
23
- * Enable edge snap — perpendicular projection onto an arc segment
24
- * (default `true`). Disable to restrict snap to existing vertices only.
25
- */
26
- snapToEdge?: boolean;
27
- /** CSS color for the drawing line (default: '#0078ff') */
28
- drawColor?: string;
29
- /**
30
- * Button icon. A `string` is rendered as text via `textContent` (safe;
31
- * covers unicode glyphs like the defaults below). Pass a `Node` to render
32
- * a pre-built DOM element such as an `<svg>` — caller is responsible for
33
- * its own escaping.
34
- */
1
+ import type { DrawFeatureOptions } from '../core/handlers/draw-feature';
2
+ import type { Control } from './control';
3
+ import type { Emap } from '../map/map';
4
+ export type { DrawGeometryType } from '../core/handlers/draw-feature';
5
+ export interface DrawFeatureControlOptions extends DrawFeatureOptions {
35
6
  icon?: string | Node;
36
7
  }
37
8
  export declare class DrawFeatureControl implements Control {
38
- private _options;
9
+ private _opts;
39
10
  private _map;
40
11
  private _container;
41
12
  private _btn;
42
- private _active;
43
- private _vertices;
44
- private _cursorCoord;
45
- private _snapCoord;
46
- private _snapKind;
47
- private _snapThreshold;
48
- private _onMouseMoveBound;
49
- private _onClickBound;
50
- private _onDblClickBound;
51
- private _onKeyDownBound;
52
- private _onMoveHandlerBound;
53
13
  constructor(options: DrawFeatureControlOptions);
54
14
  onAdd(map: Emap): HTMLElement;
55
15
  onRemove(): void;
56
16
  private _toggle;
57
- private _activate;
58
- private _deactivate;
59
- /** Deactivate UI without firing setEditMode (used when another mode takes over) */
60
- private _deactivateQuiet;
61
- private _clearDrawState;
62
- private _onMapMove;
63
- private _onMouseMove;
64
- private _onClick;
65
- private _onDblClick;
66
- private _onKeyDown;
67
- private _findSnapTarget;
68
- private _commitFeature;
69
- private _resolveTargetLayer;
70
- private _appendArc;
71
- private _updateDrawState;
72
17
  }
73
- /**
74
- * Closest point on segment `[a, b]` to point `p`, all in 2-D pixel space.
75
- * Parameter `t = ((p-a)·(b-a)) / |b-a|²` is clamped to `[0, 1]` so the
76
- * returned point is always on the segment (not its infinite line). For a
77
- * zero-length segment, returns endpoint `a` and `dist(p, a)`.
78
- */
79
- export declare function projectPointOnSegment(p: [number, number], a: [number, number], b: [number, number]): {
80
- point: [number, number];
81
- dist: number;
82
- };