@orbat-mapper/tactical-draw 0.2.0-alpha.30 → 0.2.0-alpha.32

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.
package/dist/index.d.mts CHANGED
@@ -166,6 +166,17 @@ interface IconResource {
166
166
  width: number;
167
167
  height: number;
168
168
  anchor: [number, number];
169
+ /**
170
+ * Direct visible mark used to rank icon picks, in unscaled canvas coordinates.
171
+ * Hits elsewhere in the full canvas measure their distance from this rectangle;
172
+ * omit it to preserve whole-canvas distance-zero behavior.
173
+ */
174
+ coreRect?: {
175
+ x: number;
176
+ y: number;
177
+ width: number;
178
+ height: number;
179
+ };
169
180
  }
170
181
  /**
171
182
  * Click-style hit event delivered by {@link MapAdapter.onPick}.
@@ -254,6 +265,9 @@ interface MapAdapter {
254
265
  * end of a pan or pinch-zoom gesture.
255
266
  *
256
267
  * Hit tolerance is pointer-type aware: 4 px for mouse/pen, 12 px for touch.
268
+ * Outline-only polygon interiors additionally have bounded inward selection
269
+ * reach from visible viewport-clipped boundaries: 24 px for mouse/pen and
270
+ * 36 px for touch. A visible solid or patterned fill owns its full interior.
257
271
  *
258
272
  * Returns an unsubscribe function. The returned function and the optional
259
273
  * `signal` are both honoured; either teardown path stops further events,
@@ -443,6 +457,8 @@ declare abstract class BaseMapAdapter<TLayerHandle, TEventToken, TViewToken> imp
443
457
  }
444
458
  //#endregion
445
459
  //#region src/pick-utils.d.ts
460
+ type PickPointerType = "mouse" | "pen" | "touch";
461
+ declare function pickPointerType(originalEvent: unknown): PickPointerType;
446
462
  declare function pickHitTolerance(originalEvent: unknown): number;
447
463
  declare function tryControlMeasureIdFromFeature(feature: Feature): string | null;
448
464
  /**
@@ -453,6 +469,119 @@ declare function tryControlMeasureIdFromFeature(feature: Feature): string | null
453
469
  */
454
470
  declare function bindAbortable(signal: AbortSignal | undefined, attach: () => () => void): () => void;
455
471
  //#endregion
472
+ //#region src/pick-candidates.d.ts
473
+ interface ScreenBounds {
474
+ minX: number;
475
+ minY: number;
476
+ maxX: number;
477
+ maxY: number;
478
+ }
479
+ interface RotatedScreenBounds {
480
+ center: PixelCoordinate;
481
+ halfWidth: number;
482
+ halfHeight: number;
483
+ angle: number;
484
+ }
485
+ type LabelExtent = ScreenBounds | RotatedScreenBounds;
486
+ interface ResolvedPickPresentation {
487
+ stroke?: {
488
+ color?: string;
489
+ width?: number;
490
+ dash?: readonly number[];
491
+ };
492
+ fill?: {
493
+ color?: string;
494
+ pattern?: string;
495
+ opacity: number;
496
+ };
497
+ point?: {
498
+ fillColor?: string;
499
+ radius?: number;
500
+ };
501
+ text?: TextStyleOptions;
502
+ }
503
+ type PickCandidateHitKind = "native" | "point" | "line" | "polygon-boundary" | "polygon-interior" | "icon" | "label";
504
+ interface PickCandidateHit {
505
+ kind: PickCandidateHitKind;
506
+ /** CSS-pixel distance to the visible mark, or null when only the engine knows the hit. */
507
+ distance: number | null;
508
+ }
509
+ /**
510
+ * Engine-neutral description of one rendered part eligible at a pointer location.
511
+ * This is deliberately richer than PickEvent but remains adapter-author plumbing:
512
+ * ordered candidates are not exposed by the public picking event.
513
+ */
514
+ interface PickCandidate {
515
+ feature: Feature;
516
+ graphicId: string | null;
517
+ renderedPartId: string | number | null;
518
+ hit: PickCandidateHit;
519
+ viewport: ScreenBounds;
520
+ presentation: ResolvedPickPresentation;
521
+ visualOrder: number;
522
+ iconFootprint?: readonly PixelCoordinate[];
523
+ labelExtent?: LabelExtent;
524
+ }
525
+ /** A rendered part supplied by an adapter or TacticalDraw for shared evaluation. */
526
+ interface PickCandidateInput {
527
+ feature: Feature;
528
+ /**
529
+ * Lower values mean visually topmost. Suppliers must normalize their
530
+ * native ordering to topmost-first before calling into evaluation.
531
+ */
532
+ visualOrder: number;
533
+ /** The engine already reported this part as hit; retained as a fallback for engine-only marks. */
534
+ nativeHit?: boolean;
535
+ icon?: IconResource;
536
+ labelExtent?: LabelExtent;
537
+ presentation?: ResolvedPickPresentation;
538
+ layerStyle?: StyleOptions;
539
+ }
540
+ /**
541
+ * The `visualOrder` for the feature at `index` of a render-ordered
542
+ * (bottom-first) list of `total` features: reversing the index makes the
543
+ * topmost-rendered feature the lowest, and therefore winning, order.
544
+ */
545
+ declare function renderOrderToVisualOrder(index: number, total: number): number;
546
+ interface MergedPickFeature {
547
+ feature: Feature;
548
+ visualOrder: number;
549
+ nativeHit: boolean;
550
+ }
551
+ /**
552
+ * Preserve native visual ordering/hit evidence while keeping cached source
553
+ * geometry authoritative. Native polygon geometry may be tile-clipped and
554
+ * therefore contain artificial edges that are not part of the graphic.
555
+ *
556
+ * Normalizes to the shared `visualOrder` contract (lower = visually
557
+ * topmost): native hits already arrive topmost-first from the engines and
558
+ * keep that order at the front. Cached-only features (not among the native
559
+ * hits) are appended after them, in reverse cache order — cache arrays are
560
+ * render order (bottom-first), so reversing yields topmost-first — with
561
+ * `visualOrder` numbering continuing on from the native section.
562
+ */
563
+ declare function mergeNativeAndCachedPickFeatures(nativeFeatures: readonly Feature[], cachedFeatures: readonly Feature[]): MergedPickFeature[];
564
+ interface PickEvaluationContext {
565
+ pixel: PixelCoordinate;
566
+ tolerance: number;
567
+ pointerType?: PickPointerType;
568
+ toPixel: (position: Position) => PixelCoordinate | null;
569
+ viewport: ScreenBounds;
570
+ bearing?: number;
571
+ }
572
+ /**
573
+ * Evaluate every relevant rendered part in screen space, then return the
574
+ * primary candidate under the visible-intent ranking policy: direct visible
575
+ * marks (strokes, points, icons, labels) outrank visibly filled interiors,
576
+ * which outrank inferred outline-only reach; competing direct marks rank by
577
+ * screen-space distance; visual topmost order is only the final tie-break.
578
+ * See `rankPickCandidates` for the full ordered list — that ordering stays
579
+ * internal adapter-author plumbing; the public pick event exposes only this
580
+ * primary candidate.
581
+ */
582
+ declare function evaluatePickCandidates(inputs: readonly PickCandidateInput[], context: PickEvaluationContext): PickCandidate | null;
583
+ declare function resolvePickPresentation(feature: Feature, layerStyle?: StyleOptions): ResolvedPickPresentation;
584
+ //#endregion
456
585
  //#region src/feature-style.d.ts
457
586
  /**
458
587
  * Coerce a raw `properties.style` value into a `HandleStyle` for the
@@ -474,6 +603,38 @@ declare const DEFAULT_TEXT_SIZE_MAX_PIXELS = 24;
474
603
  * clamp inside its per-zoom-stop style expression.
475
604
  */
476
605
  declare function resolveGroundTextSizePixels(textSizeMeters: number, resolution: number, text?: Pick<TextStyleOptions, "textSizeMinPixels" | "textSizeMaxPixels">): number;
606
+ /**
607
+ * The size properties a Text graphic's feature carries (see `text.ts` /
608
+ * `FeaturePartProps`). Mutually exclusive size anchors: `textSizePixels`
609
+ * (screen-anchored) or `textSizeMeters` (ground-anchored). `textMaxSizePixels`
610
+ * is the ADR-0037 hide threshold; the min/max band fields are the amplifier
611
+ * -label clamp bounds, applied only when no max-size threshold is present.
612
+ */
613
+ interface TextSizeProps {
614
+ textSizeMeters?: number;
615
+ textSizePixels?: number;
616
+ textMaxSizePixels?: number;
617
+ textSizeMinPixels?: number;
618
+ textSizeMaxPixels?: number;
619
+ }
620
+ /**
621
+ * Resolve a Text graphic's on-screen size in pixels, honoring the
622
+ * `textMaxSizePixels` hide threshold (ADR-0037). Returns `null` — the "hidden"
623
+ * signal — when the graphic should render no text this frame; adapters emit no
624
+ * text style for a `null`. Distinct from [[resolveGroundTextSizePixels]], which
625
+ * keeps the 8–24 px clamp band for amplifier labels: this helper is the Text
626
+ * graphic's own sizing rule.
627
+ *
628
+ * - screen-anchored (`textSizePixels`): the fixed pixel size, never scaled or
629
+ * hidden by zoom.
630
+ * - ground-anchored (`textSizeMeters`) with a `textMaxSizePixels` threshold:
631
+ * *unclamped* `meters / resolution` (the 8–24 band does NOT apply), hidden
632
+ * (`null`) once that exceeds the threshold — text shrinks freely zooming out
633
+ * and vanishes rather than clamps zooming in.
634
+ * - ground-anchored without a threshold: falls back to the clamped band.
635
+ * - no usable size or resolution: `null`.
636
+ */
637
+ declare function resolveTextSizePixels(props: TextSizeProps, resolution: number): number | null;
477
638
  //#endregion
478
639
  //#region src/gestures/hit-test.d.ts
479
640
  type ToPixel = (lonLat: Position) => PixelCoordinate | null;
@@ -1860,7 +2021,11 @@ declare class TacticalDraw {
1860
2021
  * then `previewLayer`, then `graphicsLayer` — against each layer's current
1861
2022
  * `adapter.getLayerFeatures(...)` cache. The `guideLayer` is deliberately
1862
2023
  * excluded: it is non-interactive draw-guide scaffolding, never a
1863
- * legitimate "owned" click target.
2024
+ * legitimate "owned" click target. Within each layer, candidates follow
2025
+ * the shared visible-intent ranking (direct marks, then filled interiors,
2026
+ * then inferred outline-only reach, distance within direct marks, then
2027
+ * visual topmost order) — this explicit-affordance layer order is the
2028
+ * tier above all of it.
1864
2029
  *
1865
2030
  * `preview` and `graphics` each get a label text-extent fallback after the
1866
2031
  * geometry pass misses on that layer: for every `Point` feature carrying a
@@ -1871,7 +2036,7 @@ declare class TacticalDraw {
1871
2036
  * This matters most for the active preview, since a click can land
1872
2037
  * anywhere across a rotated/offset label during an edit.
1873
2038
  *
1874
- * `tolerance` defaults to `mapEventHitTolerance(options?.originalEvent)` —
2039
+ * `tolerance` defaults to `pickHitTolerance(options?.originalEvent)` —
1875
2040
  * pass the host's raw click event as `originalEvent` to get the same
1876
2041
  * pointer-type-aware tolerance (4px mouse/pen, 12px touch) `onPick` uses;
1877
2042
  * pass an explicit `tolerance` to override it outright.
@@ -2031,4 +2196,4 @@ declare function nearestWorldCopyLng(lng: number, refLng: number): number;
2031
2196
  /** `nearestWorldCopyLng` applied to a lon/lat position. */
2032
2197
  declare function nearestWorldCopyPosition(position: Position, refLng: number): Position;
2033
2198
  //#endregion
2034
- export { BaseMapAdapter, type CombinedAbort, DEFAULT_LABEL_SIZE_PIXELS, DEFAULT_TEXT_SIZE_MAX_PIXELS, DEFAULT_TEXT_SIZE_MIN_PIXELS, type DrawMeasureDraft, type DrawOptions, type DrawPointSymbolDraft, type DrawSession, type EditChangeEvent, type EditManyOptions, type EditMode, type EditOptions, type EditPointerDriver, type EditSession, type FeatureOps, type Graphic, type GraphicEditChangeEvent, type GraphicEditSession, type GraphicGeometrySnappingOptions, type GraphicRender, type GraphicSnapshot, type GuideStyle, HATCH_PATTERNS, type HandleStyle, type HatchPattern, type IconResource, type InteractionHit, type InteractionStyle, type LayerId, type MapAdapter, type MapCursor, type MapEvent, type MapEventHandler, type NativeEventEntry, type PickEvent, type PickHandler, type PickOptions, type PixelCoordinate, type PointSymbol, type PointSymbolAnchor, type PointSymbolCapability, PointSymbolCapabilityRequiredError, type PointSymbolColors, type PointSymbolFootprint, type PointSymbolGraphicModifiers, type PointSymbolRender, type PointSymbolSize, type PointSymbolStyle, type PointerCallback, PointerCallbackHub, type PointerEventInfo, type SessionChangeSource, type SessionHistory, type SessionHistoryState, type SettleReason, type SizeAnchor, type SnapCandidate, type SnapCandidateProvider, type SnapCandidateRequest, type SnapInteraction, type SnapResult, type SnappingOptions, type StyleOptions, TOUCH_HIT_TOLERANCE_PX, TacticalDraw, TacticalDrawAbortError, type TacticalDrawAbortReason, TacticalDrawDestroyedError, type TacticalDrawLayerOptions, type TacticalDrawOptions, type TextStyleOptions, type ToPixel, type TransformBox, type TransformChangeEvent, type TransformSession, type TransientChangeEvent, type TransientPhase, bindAbortable, clonePointSymbol, coerceHandleStyle, combineWithHostSignal, effectivePointSymbolPixelSize, fillPatternImageDimension, fillPatternImageId, getSizeAnchor, hitTestFeature, hitTestIconFeature, ignoreAbort, isPointSymbol, isTacticalDrawAbortError, makeFillPatternImage, nearestWorldCopyLng, nearestWorldCopyPosition, pickHitTolerance, pointSymbolFootprint, resizePointSymbolSize, resolveGroundTextSizePixels, tryControlMeasureIdFromFeature };
2199
+ export { BaseMapAdapter, type CombinedAbort, DEFAULT_LABEL_SIZE_PIXELS, DEFAULT_TEXT_SIZE_MAX_PIXELS, DEFAULT_TEXT_SIZE_MIN_PIXELS, type DrawMeasureDraft, type DrawOptions, type DrawPointSymbolDraft, type DrawSession, type EditChangeEvent, type EditManyOptions, type EditMode, type EditOptions, type EditPointerDriver, type EditSession, type FeatureOps, type Graphic, type GraphicEditChangeEvent, type GraphicEditSession, type GraphicGeometrySnappingOptions, type GraphicRender, type GraphicSnapshot, type GuideStyle, HATCH_PATTERNS, type HandleStyle, type HatchPattern, type IconResource, type InteractionHit, type InteractionStyle, type LabelExtent, type LayerId, type MapAdapter, type MapCursor, type MapEvent, type MapEventHandler, type MergedPickFeature, type NativeEventEntry, type PickCandidate, type PickCandidateHit, type PickCandidateHitKind, type PickCandidateInput, type PickEvaluationContext, type PickEvent, type PickHandler, type PickOptions, type PickPointerType, type PixelCoordinate, type PointSymbol, type PointSymbolAnchor, type PointSymbolCapability, PointSymbolCapabilityRequiredError, type PointSymbolColors, type PointSymbolFootprint, type PointSymbolGraphicModifiers, type PointSymbolRender, type PointSymbolSize, type PointSymbolStyle, type PointerCallback, PointerCallbackHub, type PointerEventInfo, type ResolvedPickPresentation, type RotatedScreenBounds, type ScreenBounds, type SessionChangeSource, type SessionHistory, type SessionHistoryState, type SettleReason, type SizeAnchor, type SnapCandidate, type SnapCandidateProvider, type SnapCandidateRequest, type SnapInteraction, type SnapResult, type SnappingOptions, type StyleOptions, TOUCH_HIT_TOLERANCE_PX, TacticalDraw, TacticalDrawAbortError, type TacticalDrawAbortReason, TacticalDrawDestroyedError, type TacticalDrawLayerOptions, type TacticalDrawOptions, type TextSizeProps, type TextStyleOptions, type ToPixel, type TransformBox, type TransformChangeEvent, type TransformSession, type TransientChangeEvent, type TransientPhase, bindAbortable, clonePointSymbol, coerceHandleStyle, combineWithHostSignal, effectivePointSymbolPixelSize, evaluatePickCandidates, fillPatternImageDimension, fillPatternImageId, getSizeAnchor, hitTestFeature, hitTestIconFeature, ignoreAbort, isPointSymbol, isTacticalDrawAbortError, makeFillPatternImage, mergeNativeAndCachedPickFeatures, nearestWorldCopyLng, nearestWorldCopyPosition, pickHitTolerance, pickPointerType, pointSymbolFootprint, renderOrderToVisualOrder, resizePointSymbolSize, resolveGroundTextSizePixels, resolvePickPresentation, resolveTextSizePixels, tryControlMeasureIdFromFeature };