@angular-helpers/openlayers 0.2.0 → 0.4.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.
@@ -1,27 +1,181 @@
1
1
  import { Coordinate, Feature, OlFeature } from '@angular-helpers/openlayers/core';
2
2
  import * as i0 from '@angular/core';
3
3
 
4
+ /**
5
+ * Configuration for an ellipse polygon centered at `center`.
6
+ * Coordinates are emitted in EPSG:4326 (lon/lat) using a local tangent-plane
7
+ * approximation; accuracy degrades for radii > ~100 km or near the poles.
8
+ */
4
9
  interface EllipseConfig {
10
+ /** Ellipse center as `[lon, lat]` in EPSG:4326. */
5
11
  center: Coordinate;
12
+ /** Semi-major axis in meters. Must be > 0. */
6
13
  semiMajor: number;
14
+ /** Semi-minor axis in meters. Must be > 0. */
7
15
  semiMinor: number;
16
+ /**
17
+ * Rotation in radians, counter-clockwise from East. Default: 0
18
+ * (semi-major axis points East).
19
+ */
8
20
  rotation?: number;
21
+ /**
22
+ * Number of vertices used to approximate the ellipse. Default: 64.
23
+ * Minimum: 8.
24
+ */
25
+ segments?: number;
26
+ /** Custom feature properties to attach to the output feature. */
27
+ properties?: Record<string, unknown>;
9
28
  }
29
+ /**
30
+ * Configuration for a circular sector (pie-slice) polygon.
31
+ * Same projection caveats as `EllipseConfig`.
32
+ */
10
33
  interface SectorConfig {
34
+ /** Sector apex / center as `[lon, lat]` in EPSG:4326. */
11
35
  center: Coordinate;
36
+ /** Sector radius in meters. Must be > 0. */
12
37
  radius: number;
38
+ /** Start angle in radians (0 = East, CCW positive). */
13
39
  startAngle: number;
40
+ /**
41
+ * End angle in radians. Must satisfy `startAngle < endAngle <= startAngle + 2π`.
42
+ */
14
43
  endAngle: number;
44
+ /**
45
+ * Number of vertices along the arc. Default: 32. Minimum: 4. The output
46
+ * polygon has `segments + 3` vertices (apex + arc + apex closer).
47
+ */
48
+ segments?: number;
49
+ /** Custom feature properties to attach to the output feature. */
50
+ properties?: Record<string, unknown>;
15
51
  }
52
+ /**
53
+ * Configuration for a donut (annular ring) polygon — a disk with a
54
+ * concentric circular hole. Useful for range rings, exclusion zones,
55
+ * and similar GIS military primitives.
56
+ *
57
+ * The output `Feature<Polygon>` has TWO rings: an outer ring (CCW) and
58
+ * an inner ring (CW per the GeoJSON right-hand rule), so renderers that
59
+ * follow the spec fill only the band between the radii.
60
+ */
61
+ interface DonutConfig {
62
+ /** Donut center as `[lon, lat]` in EPSG:4326. */
63
+ center: Coordinate;
64
+ /** Outer radius in meters. Must be > `innerRadius`. */
65
+ outerRadius: number;
66
+ /** Inner radius in meters. Must be > 0 and < `outerRadius`. */
67
+ innerRadius: number;
68
+ /**
69
+ * Number of vertices per ring. Default: 64. Minimum: 8. Both rings use
70
+ * the same segment count.
71
+ */
72
+ segments?: number;
73
+ /** Custom feature properties to attach to the output feature. */
74
+ properties?: Record<string, unknown>;
75
+ }
76
+ /**
77
+ * Subset of `milsymbol`'s `SymbolOptions` exposed by this package.
78
+ * `sidc` is the only required field; everything else is optional and
79
+ * forwarded verbatim to `new Symbol(sidc, options)`.
80
+ */
16
81
  interface MilSymbolConfig {
82
+ /** MIL-STD-2525 SIDC code. Required. */
17
83
  sidc: string;
84
+ /** Symbol position as `[lon, lat]` in EPSG:4326. Required. */
18
85
  position: Coordinate;
86
+ /** Symbol size in pixels. Default (set by `milsymbol`): 30. */
87
+ size?: number;
88
+ /** Mono-color override (e.g. `'#000'`). */
89
+ monoColor?: string;
90
+ /** Outline color. */
91
+ outlineColor?: string;
92
+ /** Icon (interior glyph) color. */
93
+ iconColor?: string;
94
+ /** Additional information field (top of the symbol). */
95
+ additionalInformation?: string;
96
+ /** Staff comments field. */
97
+ staffComments?: string;
98
+ /** Quantity field. */
99
+ quantity?: number;
100
+ /** Unique designation field (unit identifier). */
101
+ uniqueDesignation?: string;
102
+ /** Custom feature properties merged into the output feature's `properties`. */
103
+ properties?: Record<string, unknown>;
104
+ }
105
+ /**
106
+ * Result of resolving a `MilSymbolConfig` against `milsymbol`. Embedded
107
+ * into the output feature's `style.icon` so that `<ol-vector-layer>` can
108
+ * render it as an `ol/style/Icon`.
109
+ */
110
+ interface MilSymbolStyleResult {
111
+ /** `data:image/svg+xml;base64,...` URL produced from `Symbol.asSVG()`. */
112
+ src: string;
113
+ /** Pixel `[width, height]` from `Symbol.getSize()`. */
114
+ size: [number, number];
115
+ /**
116
+ * Anchor in fractional coordinates `[x, y]` (0..1), computed from
117
+ * `Symbol.getAnchor()` divided by the size. `[0.5, 0.5]` centers the
118
+ * icon on the feature.
119
+ */
120
+ anchor: [number, number];
19
121
  }
20
122
 
123
+ /**
124
+ * Service exposing geometry helpers and MIL-STD-2525 symbology rendering.
125
+ *
126
+ * - `createEllipse`, `createSector`, `createDonut` are **pure math** and
127
+ * have no runtime dependencies beyond the bundled types.
128
+ * - `createMilSymbol` uses the milsymbol library via dynamic ESM import.
129
+ */
21
130
  declare class OlMilitaryService {
131
+ private idCounter;
132
+ private mlLoader;
133
+ private msModule;
134
+ /**
135
+ * Build a `Feature<Polygon>` approximating an ellipse centered at
136
+ * `config.center`. See {@link EllipseConfig} for parameter semantics.
137
+ */
22
138
  createEllipse(config: EllipseConfig): Feature;
139
+ /**
140
+ * Build a `Feature<Polygon>` for a circular sector (pie slice).
141
+ * See {@link SectorConfig} for parameter semantics.
142
+ */
23
143
  createSector(config: SectorConfig): Feature;
24
- addMilSymbol(config: MilSymbolConfig): Feature;
144
+ /**
145
+ * Build a `Feature<Polygon>` for a donut (annular ring). The output has
146
+ * two rings: an outer ring wound counter-clockwise and an inner ring
147
+ * wound clockwise so the GeoJSON right-hand rule renders the hole.
148
+ */
149
+ createDonut(config: DonutConfig): Feature;
150
+ /**
151
+ * Pre-load the optional `milsymbol` peer dependency so subsequent calls
152
+ * to `createMilSymbol` / `createMilSymbolSync` resolve immediately.
153
+ * Idempotent — multiple calls share the same promise.
154
+ */
155
+ preloadMilsymbol(): Promise<void>;
156
+ /**
157
+ * Build a MIL-STD-2525 symbol feature asynchronously.
158
+ * Lazy-loads `milsymbol` on the first call.
159
+ */
160
+ createMilSymbol(config: MilSymbolConfig): Promise<Feature>;
161
+ /**
162
+ * Build a MIL-STD-2525 symbol feature synchronously.
163
+ * Throws if `milsymbol` has not been preloaded via `preloadMilsymbol()`
164
+ * or a previous `createMilSymbol()` call.
165
+ */
166
+ createMilSymbolSync(config: MilSymbolConfig): Feature;
167
+ /**
168
+ * Project an `(dx, dy)` meter offset from `center` to lon/lat using a
169
+ * local tangent-plane (equirectangular) approximation. Acceptable for
170
+ * the radii typical in military symbology (<100 km from center).
171
+ */
172
+ private offsetMetersToLonLat;
173
+ private nextId;
174
+ private buildSymbolFeature;
175
+ private symbolToStyleResult;
176
+ private encodeBase64Utf8;
177
+ private assertSidc;
178
+ private assertBrowser;
25
179
  static ɵfac: i0.ɵɵFactoryDeclaration<OlMilitaryService, never>;
26
180
  static ɵprov: i0.ɵɵInjectableDeclaration<OlMilitaryService>;
27
181
  }
@@ -30,4 +184,4 @@ declare function withMilitary(): OlFeature<'military'>;
30
184
  declare function provideMilitary(): OlFeature<'military'>;
31
185
 
32
186
  export { OlMilitaryService, provideMilitary, withMilitary };
33
- export type { EllipseConfig, MilSymbolConfig, SectorConfig };
187
+ export type { DonutConfig, EllipseConfig, MilSymbolConfig, MilSymbolStyleResult, SectorConfig };
@@ -1,29 +1,214 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { Type, Binding, Injector } from '@angular/core';
1
3
  import { Coordinate, OlFeature } from '@angular-helpers/openlayers/core';
2
- import * as i0 from '@angular/core';
3
4
 
4
- type OverlayPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'top-center' | 'bottom-center' | 'left-center' | 'right-center';
5
+ /**
6
+ * Anchor of the overlay element relative to its `position` coordinate.
7
+ * Mirrors the values accepted by `ol/Overlay#setPositioning`.
8
+ */
9
+ type OverlayPositioning = 'bottom-left' | 'bottom-center' | 'bottom-right' | 'center-left' | 'center-center' | 'center-right' | 'top-left' | 'top-center' | 'top-right';
10
+ /**
11
+ * Common positioning options shared by every popup mode.
12
+ */
5
13
  interface OverlayConfig {
6
- position?: OverlayPosition;
14
+ positioning?: OverlayPositioning;
7
15
  offset?: [number, number];
16
+ className?: string;
17
+ autoPan?: boolean;
8
18
  }
9
- interface PopupOptions {
19
+ /**
20
+ * Options for `OlPopupService.open()` — string / HTMLElement content.
21
+ */
22
+ interface PopupOpenOptions extends OverlayConfig {
23
+ /** Unique id for the popup. Generated when omitted. */
10
24
  id?: string;
25
+ /** Map coordinate where the popup is anchored. */
26
+ position: Coordinate;
27
+ /**
28
+ * Popup content. A `string` is rendered as text via `textContent` (no HTML parsing).
29
+ * Pass an `HTMLElement` when richer DOM is required.
30
+ */
11
31
  content: string | HTMLElement;
32
+ }
33
+ /**
34
+ * Options for `OlPopupService.openComponent()` — dynamic Angular component content.
35
+ *
36
+ * Internally uses `createComponent + hostElement` (Angular 16.2+) so consumers can wire
37
+ * `inputBinding` / `outputBinding` / `twoWayBinding` declaratively.
38
+ */
39
+ interface PopupComponentOptions<C> extends OverlayConfig {
40
+ id?: string;
12
41
  position: Coordinate;
42
+ /** The component class to instantiate. */
43
+ component: Type<C>;
44
+ /** Bindings created via `inputBinding`, `outputBinding`, `twoWayBinding`. */
45
+ bindings?: Binding[];
46
+ /** Optional host directives applied to the dynamically-created component. */
47
+ directives?: ReadonlyArray<Type<unknown> | {
48
+ readonly type: Type<unknown>;
49
+ readonly bindings?: Binding[];
50
+ }>;
51
+ /** Optional element injector for the component (defaults to the service's injector). */
52
+ injector?: Injector;
53
+ }
54
+ /**
55
+ * Handle returned by `OlPopupService.open()` and `openComponent()`.
56
+ * Use it to close the popup imperatively without going through the service.
57
+ */
58
+ interface PopupHandle {
59
+ readonly id: string;
60
+ close(): void;
61
+ }
62
+ /**
63
+ * @deprecated Use {@link PopupOpenOptions} instead. Kept for backwards compatibility
64
+ * with the v0.2.x stub API and removed in a future major version.
65
+ */
66
+ type PopupOptions = PopupOpenOptions & {
67
+ /** No-op flag retained for source compatibility. */
13
68
  autoClose?: boolean;
69
+ /** Whether to render the default close button (deprecated, prefer `<ol-popup>`). */
14
70
  closeButton?: boolean;
71
+ };
72
+ /**
73
+ * @deprecated Use {@link OverlayPositioning} instead.
74
+ */
75
+ type OverlayPosition = OverlayPositioning;
76
+
77
+ /**
78
+ * Declarative map popup that projects arbitrary Angular content via `<ng-content>`.
79
+ *
80
+ * The component's host element is used directly as the `ol/Overlay`'s element, so
81
+ * projected children stay inside Angular's component tree and benefit from change
82
+ * detection without any extra plumbing.
83
+ *
84
+ * @example
85
+ * ```html
86
+ * <ol-popup
87
+ * [position]="selectedCoord()"
88
+ * [closeButton]="true"
89
+ * [autoPan]="true"
90
+ * (closed)="clearSelection()"
91
+ * >
92
+ * <h3>{{ selected()?.name }}</h3>
93
+ * <p>{{ selected()?.description }}</p>
94
+ * </ol-popup>
95
+ * ```
96
+ */
97
+ declare class OlPopupComponent {
98
+ private readonly elementRef;
99
+ private readonly mapService;
100
+ private readonly zoneHelper;
101
+ /** Map coordinate where the popup is anchored. `null` hides the popup. */
102
+ readonly position: _angular_core.InputSignal<Coordinate>;
103
+ /** Pixel offset relative to `position`. */
104
+ readonly offset: _angular_core.InputSignal<[number, number]>;
105
+ /** Anchor of the popup element relative to `position`. */
106
+ readonly positioning: _angular_core.InputSignal<OverlayPositioning>;
107
+ /** Whether the map auto-pans to keep the popup in view. */
108
+ readonly autoPan: _angular_core.InputSignal<boolean>;
109
+ /** Whether to render the default close button. */
110
+ readonly closeButton: _angular_core.InputSignal<boolean>;
111
+ /** Emitted when the popup transitions from visible to hidden (close button or `position` set to null). */
112
+ readonly closed: _angular_core.OutputEmitterRef<void>;
113
+ private overlay;
114
+ private currentMap;
115
+ private wasVisible;
116
+ constructor();
117
+ /** @internal */
118
+ onCloseClick(): void;
119
+ private applyState;
120
+ private dispose;
121
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<OlPopupComponent, never>;
122
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<OlPopupComponent, "ol-popup", never, { "position": { "alias": "position"; "required": false; "isSignal": true; }; "offset": { "alias": "offset"; "required": false; "isSignal": true; }; "positioning": { "alias": "positioning"; "required": false; "isSignal": true; }; "autoPan": { "alias": "autoPan"; "required": false; "isSignal": true; }; "closeButton": { "alias": "closeButton"; "required": false; "isSignal": true; }; }, { "closed": "closed"; }, never, ["*"], true, never>;
123
+ }
124
+
125
+ /**
126
+ * Shows a floating tooltip whose text is read from a feature property when the
127
+ * pointer hovers over it. The tooltip element is appended to the map viewport
128
+ * and styled minimally; consumers can override via the `.ol-tooltip` CSS hook.
129
+ *
130
+ * @example
131
+ * ```html
132
+ * <ol-vector-layer
133
+ * id="cities"
134
+ * [features]="cities()"
135
+ * [olTooltip]="'name'"
136
+ * />
137
+ * ```
138
+ *
139
+ * Apply `[olTooltipLayer]` to limit detection to a single layer (matches the
140
+ * value of the layer's `id` property). Without it the tooltip reacts to any
141
+ * feature found at the cursor.
142
+ */
143
+ declare class OlTooltipDirective {
144
+ private readonly mapService;
145
+ private readonly zoneHelper;
146
+ /** Property key to read from the hovered feature. */
147
+ readonly olTooltip: _angular_core.InputSignal<string>;
148
+ /** Optional layer id; when set, only features on that layer trigger the tooltip. */
149
+ readonly olTooltipLayer: _angular_core.InputSignal<string>;
150
+ private element;
151
+ private listener;
152
+ private currentMap;
153
+ constructor();
154
+ private handlePointerMove;
155
+ private dispose;
156
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<OlTooltipDirective, never>;
157
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<OlTooltipDirective, "[olTooltip]", never, { "olTooltip": { "alias": "olTooltip"; "required": true; "isSignal": true; }; "olTooltipLayer": { "alias": "olTooltipLayer"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
15
158
  }
16
159
 
160
+ /**
161
+ * Manages OpenLayers popup overlays anchored to map coordinates.
162
+ *
163
+ * Three content modes:
164
+ * - `open()` — string text or `HTMLElement`
165
+ * - `openComponent()` — dynamic Angular component via `createComponent + hostElement`
166
+ * - The `<ol-popup>` component delegates `open()` internally for declarative usage.
167
+ *
168
+ * All calls are idempotent by `id`. Calls made before the underlying `ol/Map` is ready
169
+ * are queued and replayed in order once `OlMapService.onReady` fires.
170
+ */
17
171
  declare class OlPopupService {
18
- showPopup(options: PopupOptions): string;
19
- hidePopup(id: string): void;
20
- hideAllPopups(): void;
21
- static ɵfac: i0.ɵɵFactoryDeclaration<OlPopupService, never>;
22
- static ɵprov: i0.ɵɵInjectableDeclaration<OlPopupService>;
172
+ private readonly mapService;
173
+ private readonly zoneHelper;
174
+ private readonly envInjector;
175
+ private readonly appRef;
176
+ private readonly popups;
177
+ private readonly pending;
178
+ private flushSubscribed;
179
+ constructor();
180
+ /**
181
+ * Open a popup with `string` or `HTMLElement` content.
182
+ *
183
+ * Idempotent by `id`: a second call with the same id updates `position` and
184
+ * `content` of the existing popup instead of creating a duplicate.
185
+ */
186
+ open(options: PopupOpenOptions): PopupHandle;
187
+ /**
188
+ * Open a popup whose content is a dynamically-instantiated Angular component.
189
+ *
190
+ * Uses `createComponent({ environmentInjector, hostElement, bindings, directives })`
191
+ * (Angular 16.2+) and attaches the host view to `ApplicationRef` so change detection
192
+ * reaches the rendered component.
193
+ *
194
+ * Idempotent by `id`: a previous `ComponentRef` registered under the same id is
195
+ * destroyed before the new one is created.
196
+ */
197
+ openComponent<C>(options: PopupComponentOptions<C>): PopupHandle;
198
+ /** Close and dispose a single popup by id. No-op when the id is unknown. */
199
+ close(id: string): void;
200
+ /** Close every managed popup. */
201
+ closeAll(): void;
202
+ private queue;
203
+ private flushPending;
204
+ private createOrUpdate;
205
+ private createOrUpdateComponent;
206
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<OlPopupService, never>;
207
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<OlPopupService>;
23
208
  }
24
209
 
25
210
  declare function withOverlays(): OlFeature<'overlays'>;
26
211
  declare function provideOverlays(): OlFeature<'overlays'>;
27
212
 
28
- export { OlPopupService, provideOverlays, withOverlays };
29
- export type { OverlayConfig, OverlayPosition, PopupOptions };
213
+ export { OlPopupComponent, OlPopupService, OlTooltipDirective, provideOverlays, withOverlays };
214
+ export type { OverlayConfig, OverlayPosition, OverlayPositioning, PopupComponentOptions, PopupHandle, PopupOpenOptions, PopupOptions };