@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,98 @@
1
+ import type { Handler, HandlerResult, NormalizedPointerEvent } from '../handler';
2
+ import { Emap } from '../../map/map';
3
+ export interface VertexEditOptions {
4
+ /** Polygon hover fill. Default 'rgba(0,0,0,0.15)'. */
5
+ polygonFillColor?: string;
6
+ }
7
+ export declare class VertexEditHandler implements Handler<VertexEditOptions> {
8
+ readonly name = "vertexEdit";
9
+ private readonly _map;
10
+ private _enabled;
11
+ /** Injected by HandlerManager.register (cursor recompute on mode flips). */
12
+ _manager?: {
13
+ refreshCursor(): void;
14
+ };
15
+ private _polygonFillColor;
16
+ private _hoveredFeature;
17
+ private _hoverVertexCoords;
18
+ private _hoverVertexIds;
19
+ private _hoverType;
20
+ private _hoverInsertionId;
21
+ private _dragging;
22
+ /** Shapes of neighboring polygons sharing the hovered arc (for shared-edge highlight) */
23
+ private _neighborShapes;
24
+ /** Coordinate of the dragged node before mouse-down, captured for VertexMoveCommand. */
25
+ private _dragFromCoords;
26
+ private _onMapMoveBound;
27
+ constructor(map: Emap, opts?: VertexEditOptions);
28
+ isEnabled(): boolean;
29
+ enable(): void;
30
+ getCursor(): string | null;
31
+ disable(): void;
32
+ setOptions(o: Partial<VertexEditOptions>): void;
33
+ getOptions(): Readonly<VertexEditOptions>;
34
+ handlePointer(ev: NormalizedPointerEvent): HandlerResult;
35
+ /** Redraw on map move/zoom (vertices stay fixed to geography) */
36
+ private _onMapMove;
37
+ /**
38
+ * Right-click handler: show a context menu to delete the hovered vertex.
39
+ * Guard rules (same as mapshaper):
40
+ * - Must be hovering a vertex (not an interpolated edge point)
41
+ * - Not currently dragging
42
+ * - Vertex must NOT be an arc endpoint (deleting an endpoint breaks topology)
43
+ */
44
+ private _onContextMenu;
45
+ /** Delete the currently hovered vertex from the arc collection */
46
+ private _deleteHoveredVertex;
47
+ /**
48
+ * Re-initialize the source's DisplayArcs after an arc-mutating edit so that
49
+ * the simplified LOD copy reflects the new vertex layout.
50
+ */
51
+ private _refreshSourceDisplayArcs;
52
+ /**
53
+ * Bump the dataset's `editVersion` after a live in-place arc mutation.
54
+ * The spatial-index cache in `feature-query` keys on `editVersion`, so
55
+ * this is what tells the next `queryFeatures` call that bboxes may
56
+ * have changed and the index must rebuild. Cheap (a number
57
+ * increment); only the next query pays the actual rebuild cost.
58
+ *
59
+ * The matching command's `do()/undo()` also bump, but those run on
60
+ * undo / redo — not on initial commit, since `pushCommand` skips
61
+ * `do()` per the memento contract.
62
+ */
63
+ private _bumpSourceEditVersion;
64
+ /**
65
+ * Show a minimal context menu at (x, y) in viewport coords.
66
+ * Auto-dismissed when user clicks anywhere else. Static appearance lives
67
+ * in `src/ui/controls.css` as `.emap-ctx-menu` / `.emap-ctx-menu-item`
68
+ * (themable via `--emap-*` tokens on `:root`); only the dynamic
69
+ * `left`/`top` coords are set inline here.
70
+ */
71
+ private _showContextMenu;
72
+ private _onMouseMove;
73
+ /**
74
+ * Use MapshaperAdapter.findNearestVertices to discover ALL vertex indices
75
+ * that share the same topological node (identical coordinates across all arcs).
76
+ */
77
+ private _findNearestVertices;
78
+ /**
79
+ * Find the closest point along any segment edge (not just vertices).
80
+ * Uses mapshaper's forEachSegmentInShape + findClosestPointOnSeg.
81
+ * Called as fallback when no existing vertex is within hover threshold.
82
+ */
83
+ private _findInterpolatedPoint;
84
+ /**
85
+ * Find all shapes (polygons) in the source that share any arc with the hovered vertex/edge.
86
+ * Handles two cases:
87
+ * - Vertex hover: hoverVertexIds → arcIds via findArcIdFromVertexId
88
+ * - Edge hover (interpolated): hoverInsertionId - 1 → arcId via findArcIdFromVertexId
89
+ * Only runs when geometry is polygon. Populates _neighborShapes.
90
+ */
91
+ private _findNeighborShapes;
92
+ /** Update the edit vertex state on the map so render() draws vertex dots (and polygon fill) */
93
+ private _updateEditState;
94
+ private _onMouseDown;
95
+ private _pushVertexInsertCommand;
96
+ private _handleDrag;
97
+ private _finishDrag;
98
+ }
@@ -0,0 +1,40 @@
1
+ import type { NormalizedPointerEvent } from './handler';
2
+ export interface PointerMoveEvent {
3
+ /** Element-local pixel coords (= the normalized event's `point`). */
4
+ point: {
5
+ x: number;
6
+ y: number;
7
+ };
8
+ /** `host.unproject(point.x, point.y)` — source-data coordinates. */
9
+ mapCoord: [number, number];
10
+ /** The DOM event that produced this (typed `Event`; a PointerEvent at runtime). */
11
+ originalEvent: Event;
12
+ }
13
+ type Cb = (e: PointerMoveEvent) => void;
14
+ /** Minimal surface the dispatcher needs from Emap (keeps it unit-testable). */
15
+ export interface PointerEventMapHost {
16
+ unproject(x: number, y: number): [number, number];
17
+ }
18
+ /**
19
+ * Delegated pointer-move event registry. Fed normalized pointer events by
20
+ * `HandlerManager`'s sink (non-gesture move) via `Emap._syncPointerSink`.
21
+ * Move-only by design (P8 §17.3) — `click` is covered by P3
22
+ * `feature:click`; `down`/`up`/`wheel`/`dblclick`/`contextmenu` have no
23
+ * consumer. No hit-test, no filter (it is not feature-scoped).
24
+ */
25
+ export declare class PointerEventDispatcher {
26
+ private _host;
27
+ private _reg;
28
+ /** Maps user cb → its once-wrapper so `off(type, userCb)` resolves the wrap. */
29
+ private _onceWrap;
30
+ private _onChange?;
31
+ constructor(_host: PointerEventMapHost);
32
+ /** Install a callback invoked whenever the registry changes (drives sink install/teardown). */
33
+ setOnChange(fn: () => void): void;
34
+ hasListeners(): boolean;
35
+ on(type: string, cb: Cb): void;
36
+ once(type: string, cb: Cb): void;
37
+ off(type: string, cb: Cb): void;
38
+ dispatch(ev: NormalizedPointerEvent): void;
39
+ }
40
+ export {};
@@ -5,6 +5,7 @@ export declare class Timer extends EventDispatcher {
5
5
  private _tickTime;
6
6
  private _startTime;
7
7
  private _duration;
8
+ private _frame;
8
9
  constructor();
9
10
  start(ms?: number): void;
10
11
  stop(): void;
package/dist/emap.css CHANGED
@@ -1,3 +1,22 @@
1
+ /* emap design tokens — defaults are the verbatim legacy literals so default
2
+ * rendering is byte-identical. Override on :root (or any ancestor selector)
3
+ * to theme. Introduced in DX P4 for the context menu; future phases may
4
+ * migrate existing controls to consume these tokens. */
5
+ :root {
6
+ /* Accent (current usage: box-select stroke, lasso stroke, button-active bg). */
7
+ --emap-accent: #0078ff;
8
+ --emap-accent-soft: rgba(0, 120, 255, 0.1);
9
+ /* Surface — panels, menus, dropdowns. */
10
+ --emap-surface-bg: #fff;
11
+ --emap-surface-border: #ccc;
12
+ --emap-surface-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
13
+ /* Generic radius + hover/danger + font. */
14
+ --emap-radius: 4px;
15
+ --emap-hover-bg: #f5f5f5;
16
+ --emap-danger: #d32;
17
+ --emap-font: 13px/1.5 system-ui, sans-serif;
18
+ }
19
+
1
20
  /* Navigation Controls */
2
21
  .emap-ctrl-group {
3
22
  background-color: #fff;
@@ -114,10 +133,6 @@
114
133
  color: #fff;
115
134
  }
116
135
 
117
- .emap-edit-active {
118
- cursor: crosshair;
119
- }
120
-
121
136
  /* Draw Feature Controls */
122
137
  .emap-ctrl-draw {
123
138
  font-size: 14px;
@@ -128,10 +143,6 @@
128
143
  color: #fff;
129
144
  }
130
145
 
131
- .emap-draw-active {
132
- cursor: crosshair;
133
- }
134
-
135
146
  /* Box Select rubber-band rectangle. Defaults are inlined by BoxSelectControl
136
147
  for option override; this rule lets users restyle via CSS too. */
137
148
  .emap-box-select {
@@ -155,3 +166,26 @@
155
166
  .emap-lasso-select {
156
167
  z-index: 5;
157
168
  }
169
+
170
+ /* Right-click context menu — opened on right-click over a selected vertex
171
+ * by VertexEditHandler. Dynamic position/left/top are set inline; every
172
+ * other property is tokenised here. */
173
+ .emap-ctx-menu {
174
+ position: fixed;
175
+ z-index: 9999;
176
+ min-width: 120px;
177
+ background: var(--emap-surface-bg);
178
+ border: 1px solid var(--emap-surface-border);
179
+ border-radius: var(--emap-radius);
180
+ box-shadow: var(--emap-surface-shadow);
181
+ padding: 4px 0;
182
+ font: var(--emap-font);
183
+ }
184
+ .emap-ctx-menu-item {
185
+ padding: 6px 16px;
186
+ cursor: pointer;
187
+ color: var(--emap-danger);
188
+ }
189
+ .emap-ctx-menu-item:hover {
190
+ background: var(--emap-hover-bg);
191
+ }