@orbat-mapper/tactical-draw 0.13.2 → 0.14.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.
- package/dist/index.d.mts +99 -9
- package/dist/index.mjs +770 -62
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -519,19 +519,84 @@ declare function normalizeImageGraphic(image: ImageGraphic): ImageGraphic;
|
|
|
519
519
|
declare function imageOpacity(image: ImageGraphic): number;
|
|
520
520
|
declare function validateImageGraphic(image: ImageGraphic): void;
|
|
521
521
|
//#endregion
|
|
522
|
+
//#region src/marker.d.ts
|
|
523
|
+
/** Displayed icon height; same pixel/meter contract as point-symbol sizes. */
|
|
524
|
+
type MarkerSize = PointSymbolSize;
|
|
525
|
+
interface MarkerStyle {
|
|
526
|
+
/** Host-interpreted tint, handed to {@link MarkerCapability.render}. */
|
|
527
|
+
color?: string;
|
|
528
|
+
/** 0–1 display multiplier applied by TacticalDraw. */
|
|
529
|
+
opacity?: number;
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* Persisted generic marker (e.g. a pin) whose icon is supplied by the
|
|
533
|
+
* host application. TacticalDraw treats `symbolId` as opaque (ADR-0059).
|
|
534
|
+
*/
|
|
535
|
+
interface Marker {
|
|
536
|
+
id: string;
|
|
537
|
+
kind: "marker";
|
|
538
|
+
/** Host-defined icon identifier resolved by the {@link MarkerCapability}. */
|
|
539
|
+
symbolId: string;
|
|
540
|
+
position: Position;
|
|
541
|
+
/** Normalized radians clockwise from geographic north, around the icon anchor. */
|
|
542
|
+
rotation: number;
|
|
543
|
+
size: MarkerSize;
|
|
544
|
+
/** Optional text; the capability decides whether and how to draw it. */
|
|
545
|
+
label?: string;
|
|
546
|
+
style?: MarkerStyle;
|
|
547
|
+
properties?: Record<string, unknown>;
|
|
548
|
+
schemaVersion: 1;
|
|
549
|
+
}
|
|
550
|
+
interface MarkerAnchor {
|
|
551
|
+
x: number;
|
|
552
|
+
y: number;
|
|
553
|
+
}
|
|
554
|
+
/** Host-prepared marker icon in canonical SVG units. */
|
|
555
|
+
interface MarkerIcon {
|
|
556
|
+
/**
|
|
557
|
+
* Content-derived identity for adapter-wide icon reuse: equal ids must mean
|
|
558
|
+
* identical SVG. Include anything that changes the drawing (symbol, color, label).
|
|
559
|
+
*/
|
|
560
|
+
resourceId: string;
|
|
561
|
+
/** Self-contained SVG markup. Producing safe content is the host's responsibility. */
|
|
562
|
+
svg: string;
|
|
563
|
+
width: number;
|
|
564
|
+
height: number;
|
|
565
|
+
/** Point placed at `Marker.position` (e.g. a pin's tip); rotation and scale pivot here. */
|
|
566
|
+
anchor: MarkerAnchor;
|
|
567
|
+
}
|
|
568
|
+
interface MarkerRender extends MarkerIcon {
|
|
569
|
+
/** False when the capability did not recognize `symbolId` and a placeholder is shown. */
|
|
570
|
+
available: boolean;
|
|
571
|
+
}
|
|
572
|
+
interface MarkerCapability {
|
|
573
|
+
/** Return `undefined` for an unknown `symbolId`; TacticalDraw renders a placeholder. */
|
|
574
|
+
render(marker: Marker): MarkerIcon | undefined;
|
|
575
|
+
/** Monotonic host-owned revision; bump it when icon resolution changes. */
|
|
576
|
+
readonly generation?: number;
|
|
577
|
+
}
|
|
578
|
+
declare function isMarker(graphic: unknown): graphic is Marker;
|
|
579
|
+
declare function cloneMarker(marker: Marker): Marker;
|
|
580
|
+
declare function markerOpacity(marker: Marker): number;
|
|
581
|
+
declare function validateMarker(marker: Marker): void;
|
|
582
|
+
declare function normalizeMarker(marker: Marker): Marker;
|
|
583
|
+
//#endregion
|
|
522
584
|
//#region src/graphic.d.ts
|
|
523
|
-
type Graphic = ControlMeasure | PointSymbol | ImageGraphic;
|
|
524
|
-
type GraphicRender = ControlMeasureRender | PointSymbolRender | ImageRender;
|
|
585
|
+
type Graphic = ControlMeasure | PointSymbol | ImageGraphic | Marker;
|
|
586
|
+
type GraphicRender = ControlMeasureRender | PointSymbolRender | ImageRender | MarkerRender;
|
|
525
587
|
interface GraphicSnapshot<G extends Graphic = Graphic> {
|
|
526
588
|
graphic: G;
|
|
527
|
-
render: G extends PointSymbol ? PointSymbolRender : G extends ImageGraphic ? ImageRender : ControlMeasureRender;
|
|
589
|
+
render: G extends PointSymbol ? PointSymbolRender : G extends ImageGraphic ? ImageRender : G extends Marker ? MarkerRender : ControlMeasureRender;
|
|
528
590
|
}
|
|
529
591
|
/**
|
|
530
592
|
* A graphic whose identity is one geographic anchor + size + rotation,
|
|
531
|
-
* rather than a control-point geometry: `PointSymbol` or `
|
|
593
|
+
* rather than a control-point geometry: `PointSymbol`, `ImageGraphic`, or `Marker`.
|
|
532
594
|
*/
|
|
533
|
-
type AnchoredGraphic = PointSymbol | ImageGraphic;
|
|
595
|
+
type AnchoredGraphic = PointSymbol | ImageGraphic | Marker;
|
|
534
596
|
declare function isAnchoredGraphic(graphic: Graphic): graphic is AnchoredGraphic;
|
|
597
|
+
/** A graphic that can take view-owned pin presentation (ADR-0056): a point symbol or marker. */
|
|
598
|
+
type PinnableGraphic = PointSymbol | Marker;
|
|
599
|
+
declare function isPinnableGraphic(graphic: Graphic): graphic is PinnableGraphic;
|
|
535
600
|
//#endregion
|
|
536
601
|
//#region src/tactical-draw/abort.d.ts
|
|
537
602
|
/**
|
|
@@ -1413,6 +1478,11 @@ type DrawPointSymbolDraft = Pick<PointSymbol, "kind" | "sidc"> & Partial<Omit<Po
|
|
|
1413
1478
|
//#region src/tactical-draw/image-draw-controller.d.ts
|
|
1414
1479
|
type DrawImageDraft = Pick<ImageGraphic, "kind" | "resourceId" | "intrinsicSize"> & Partial<Omit<ImageGraphic, "kind" | "resourceId" | "intrinsicSize">>;
|
|
1415
1480
|
//#endregion
|
|
1481
|
+
//#region src/tactical-draw/marker-draw-controller.d.ts
|
|
1482
|
+
type DrawMarkerDraft = Pick<Marker, "kind" | "symbolId"> & Partial<Omit<Marker, "kind" | "symbolId">>;
|
|
1483
|
+
/** Default icon height for a drawn marker when the draft omits `size`. */
|
|
1484
|
+
declare const DEFAULT_MARKER_SIZE: MarkerSize;
|
|
1485
|
+
//#endregion
|
|
1416
1486
|
//#region src/tactical-draw/tactical-draw.d.ts
|
|
1417
1487
|
/**
|
|
1418
1488
|
* Host-supplied layer slot ids. Any omitted slot is allocated by the façade and
|
|
@@ -1450,6 +1520,8 @@ interface TacticalDrawOptions {
|
|
|
1450
1520
|
pointSymbols?: PointSymbolCapability;
|
|
1451
1521
|
/** Synchronous host-supplied resolver for first-class Image resources. */
|
|
1452
1522
|
images?: ImageCapability;
|
|
1523
|
+
/** Synchronous host-supplied icon resolver for generic Markers (ADR-0059). */
|
|
1524
|
+
markers?: MarkerCapability;
|
|
1453
1525
|
/**
|
|
1454
1526
|
* Façade-level default style passed through to `renderControlMeasure` as the
|
|
1455
1527
|
* third (lowest priority) style layer per StyleResolver (#44). Shallow-merged
|
|
@@ -1483,7 +1555,7 @@ interface EditOptions {
|
|
|
1483
1555
|
* Called synchronously once when the edit starts, before any pointer event
|
|
1484
1556
|
* is processed. Lets a host wire commit / cancel buttons to the active edit.
|
|
1485
1557
|
*/
|
|
1486
|
-
onSession?: (session: EditSession | GraphicEditSession<PointSymbol> | GraphicEditSession<ImageGraphic>) => void;
|
|
1558
|
+
onSession?: (session: EditSession | GraphicEditSession<PointSymbol> | GraphicEditSession<ImageGraphic> | GraphicEditSession<Marker>) => void;
|
|
1487
1559
|
/**
|
|
1488
1560
|
* Default `true`. When `true`, a click on empty map (or on another graphics
|
|
1489
1561
|
* layer measure) closes the active edit. Clicks on preview / handle
|
|
@@ -1639,6 +1711,7 @@ declare class TacticalDraw {
|
|
|
1639
1711
|
private offsetDragModifier;
|
|
1640
1712
|
private readonly pointSymbols;
|
|
1641
1713
|
private readonly images;
|
|
1714
|
+
private readonly markers;
|
|
1642
1715
|
private snappingOptions;
|
|
1643
1716
|
private readonly resolveSnap;
|
|
1644
1717
|
private readonly graphicStack;
|
|
@@ -1717,6 +1790,7 @@ declare class TacticalDraw {
|
|
|
1717
1790
|
*/
|
|
1718
1791
|
private lastSeenPointSymbolGeneration;
|
|
1719
1792
|
private lastSeenImageGeneration;
|
|
1793
|
+
private lastSeenMarkerGeneration;
|
|
1720
1794
|
/**
|
|
1721
1795
|
* Ids of graphics currently carrying a passive selection-highlight outline
|
|
1722
1796
|
* ({@link setHighlightedGraphics}). Declarative set-replace, no session —
|
|
@@ -1725,6 +1799,8 @@ declare class TacticalDraw {
|
|
|
1725
1799
|
*/
|
|
1726
1800
|
private highlightedIds;
|
|
1727
1801
|
private pinBodies;
|
|
1802
|
+
/** Resolved marker icons, so pin, highlight and view rebuilds don't re-ask the host. */
|
|
1803
|
+
private markerRenders;
|
|
1728
1804
|
readonly pins: PinPresentationStore;
|
|
1729
1805
|
private unsubscribePins;
|
|
1730
1806
|
/**
|
|
@@ -1756,9 +1832,11 @@ declare class TacticalDraw {
|
|
|
1756
1832
|
* handler and the adapter-capability change in `handleViewChange` need it.
|
|
1757
1833
|
*/
|
|
1758
1834
|
private refreshActiveEditPresentation;
|
|
1835
|
+
/** The capability's icon for a marker snapshot, resolved once per snapshot. */
|
|
1836
|
+
private markerRender;
|
|
1759
1837
|
/**
|
|
1760
|
-
* Whether a point symbol should render as a billboard pin rather
|
|
1761
|
-
* ordinary
|
|
1838
|
+
* Whether a point symbol or marker should render as a billboard pin rather
|
|
1839
|
+
* than an ordinary icon: its own presentation opts in, and the adapter
|
|
1762
1840
|
* currently supports rendering pins. Pass an already-resolved
|
|
1763
1841
|
* `presentation` to skip re-resolving it when a caller has one in hand.
|
|
1764
1842
|
*/
|
|
@@ -1945,6 +2023,7 @@ declare class TacticalDraw {
|
|
|
1945
2023
|
*/
|
|
1946
2024
|
draw(draft: DrawPointSymbolDraft, options?: DrawOptions): Promise<GraphicSnapshot<PointSymbol>>;
|
|
1947
2025
|
draw(draft: DrawImageDraft, options?: DrawOptions): Promise<GraphicSnapshot<ImageGraphic>>;
|
|
2026
|
+
draw(draft: DrawMarkerDraft, options?: DrawOptions): Promise<GraphicSnapshot<Marker>>;
|
|
1948
2027
|
draw<K extends ControlMeasureKind>(draft: DrawMeasureDraft<K>, options?: DrawOptions): Promise<GraphicSnapshot<ControlMeasure<K>>>;
|
|
1949
2028
|
/**
|
|
1950
2029
|
* Start an interactive edit on a single control measure. Returns a Promise
|
|
@@ -1963,6 +2042,7 @@ declare class TacticalDraw {
|
|
|
1963
2042
|
*/
|
|
1964
2043
|
edit(graphic: PointSymbol, options?: EditOptions): Promise<GraphicSnapshot<PointSymbol>>;
|
|
1965
2044
|
edit(graphic: ImageGraphic, options?: EditOptions): Promise<GraphicSnapshot<ImageGraphic>>;
|
|
2045
|
+
edit(graphic: Marker, options?: EditOptions): Promise<GraphicSnapshot<Marker>>;
|
|
1966
2046
|
edit(measure: ControlMeasure, options?: EditOptions): Promise<GraphicSnapshot<ControlMeasure>>;
|
|
1967
2047
|
/**
|
|
1968
2048
|
* Start an interactive group transform (multi-select) over `measures`
|
|
@@ -2183,6 +2263,9 @@ declare class PointSymbolCapabilityRequiredError extends Error {
|
|
|
2183
2263
|
declare class ImageCapabilityRequiredError extends Error {
|
|
2184
2264
|
constructor();
|
|
2185
2265
|
}
|
|
2266
|
+
declare class MarkerCapabilityRequiredError extends Error {
|
|
2267
|
+
constructor();
|
|
2268
|
+
}
|
|
2186
2269
|
//#endregion
|
|
2187
2270
|
//#region src/tactical-draw/transform-box.d.ts
|
|
2188
2271
|
/**
|
|
@@ -2238,6 +2321,13 @@ interface ImageFootprint {
|
|
|
2238
2321
|
}
|
|
2239
2322
|
declare function imageFootprint(image: ImageGraphic, render: ImageRender, adapter: Pick<MapAdapter, "getBearing" | "getPixelFromCoordinate" | "getResolution">): ImageFootprint | null;
|
|
2240
2323
|
//#endregion
|
|
2324
|
+
//#region src/tactical-draw/marker-rendering.d.ts
|
|
2325
|
+
type MarkerFootprint = Omit<PointSymbolFootprint, "connector">;
|
|
2326
|
+
/** Resolve a marker's icon, substituting the built-in placeholder for unknown symbols. */
|
|
2327
|
+
declare function resolveMarkerRender(capability: MarkerCapability, marker: Marker): MarkerRender;
|
|
2328
|
+
/** Complete rotated footprint for selection and transform chrome. */
|
|
2329
|
+
declare function markerFootprint(marker: Marker, render: MarkerRender, adapter: PointSymbolProjection): MarkerFootprint | null;
|
|
2330
|
+
//#endregion
|
|
2241
2331
|
//#region src/world-wrap.d.ts
|
|
2242
2332
|
/**
|
|
2243
2333
|
* Shift `lng` by whole world widths (360°) onto the copy nearest `refLng`.
|
|
@@ -2252,4 +2342,4 @@ declare function nearestWorldCopyLng(lng: number, refLng: number): number;
|
|
|
2252
2342
|
/** `nearestWorldCopyLng` applied to a lon/lat position. */
|
|
2253
2343
|
declare function nearestWorldCopyPosition(position: Position, refLng: number): Position;
|
|
2254
2344
|
//#endregion
|
|
2255
|
-
export { type AnchoredGraphic, BaseMapAdapter, type CombinedAbort, DEFAULT_LABEL_SIZE_PIXELS, DEFAULT_PIN_PRESENTATION, DEFAULT_TEXT_SIZE_MAX_PIXELS, DEFAULT_TEXT_SIZE_MIN_PIXELS, type DrawImageDraft, type DrawMeasureDraft, type DrawOptions, type DrawPointSymbolDraft, type DrawSession, type EditChangeEvent, type EditManyOptions, type EditMode, type EditOptions, type EditPointerDriver, type EditSession, type FeatureGroup, type Graphic, type GraphicEditChangeEvent, type GraphicEditSession, type GraphicGeometrySnappingOptions, type GraphicRender, type GraphicSnapshot, type GuideStyle, HATCH_PATTERNS, type HandleStyle, type HatchPattern, type IconResource, type ImageCapability, ImageCapabilityRequiredError, type ImageFootprint, type ImageGraphic, type ImageGraphicStyle, type ImageIntrinsicSize, type ImageOverlayResource, type ImageRender, type ImageResource, type ImageSize, type InteractionHit, type InteractionStyle, type LabelExtent, type LayerId, MINE_PATTERN_TILE_SIZE, type MapAdapter, type MapCursor, type MapEvent, type MapEventHandler, type MergedPickFeature, type NativeEventEntry, type OffsetDragModifier, type PickCandidate, type PickCandidateHit, type PickCandidateHitKind, type PickCandidateInput, type PickEvaluationContext, type PickEvent, type PickHandler, type PickOptions, type PickPointerType, PinFootprint, PinOverridePatch, PinPresentation, PinPresentationCapability, PinPresentationPatch, PinPresentationState, PinPresentationStatus, PinPresentationStatusEvent, PinPresentationStore, PinRender, type PixelCoordinate, type PointSymbol, type PointSymbolAnchor, type PointSymbolCapability, PointSymbolCapabilityRequiredError, type PointSymbolColors, type PointSymbolConnector, type PointSymbolFootprint, type PointSymbolGraphicModifiers, type PointSymbolOffset, type PointSymbolOffsetControls, type PointSymbolOffsetLayout, type PointSymbolOffsetStyle, type PointSymbolPlacement, type PointSymbolProjection, type PointSymbolRender, type PointSymbolSize, type PointSymbolStyle, type PointSymbolView, type PointerCallback, PointerCallbackHub, type PointerEventInfo, type ResolvedPickPresentation, type Rgba, 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, TEXT_HALO_COLOR, 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, alignPointSymbolIndicator, bindAbortable, cloneImageGraphic, clonePointSymbol, coerceHandleStyle, combinePinScale, combineWithHostSignal, convertPointSymbolPlacement, effectivePointSymbolPixelSize, evaluatePickCandidates, fillPatternImageDimension, fillPatternImageId, getSizeAnchor, hitTestFeature, hitTestIconFeature, ignoreAbort, imageFootprint, imageOpacity, isAnchoredGraphic, isImageGraphic, isMinePattern, isPointSymbol, isTacticalDrawAbortError, isValidPinNumber, makeFillPatternImage, mergeNativeAndCachedPickFeatures, movePointSymbolLocation, nearestWorldCopyLng, nearestWorldCopyPosition, normalizeImageGraphic, parseColor, pickHitTolerance, pickPointerType, pinDistanceScale, pinZoomScale, placePointSymbol, pointSymbolFootprint, pointSymbolResource, renderOrderToVisualOrder, resizePointSymbolSize, resolveGroundTextSizePixels, resolvePickPresentation, resolvePinPresentation, resolvePointSymbolOffset, resolveTextHaloWidth, resolveTextSizePixels, scalePointSymbolLayout, tryControlMeasureIdFromFeature, validateImageGraphic };
|
|
2345
|
+
export { type AnchoredGraphic, BaseMapAdapter, type CombinedAbort, DEFAULT_LABEL_SIZE_PIXELS, DEFAULT_MARKER_SIZE, DEFAULT_PIN_PRESENTATION, DEFAULT_TEXT_SIZE_MAX_PIXELS, DEFAULT_TEXT_SIZE_MIN_PIXELS, type DrawImageDraft, type DrawMarkerDraft, type DrawMeasureDraft, type DrawOptions, type DrawPointSymbolDraft, type DrawSession, type EditChangeEvent, type EditManyOptions, type EditMode, type EditOptions, type EditPointerDriver, type EditSession, type FeatureGroup, type Graphic, type GraphicEditChangeEvent, type GraphicEditSession, type GraphicGeometrySnappingOptions, type GraphicRender, type GraphicSnapshot, type GuideStyle, HATCH_PATTERNS, type HandleStyle, type HatchPattern, type IconResource, type ImageCapability, ImageCapabilityRequiredError, type ImageFootprint, type ImageGraphic, type ImageGraphicStyle, type ImageIntrinsicSize, type ImageOverlayResource, type ImageRender, type ImageResource, type ImageSize, type InteractionHit, type InteractionStyle, type LabelExtent, type LayerId, MINE_PATTERN_TILE_SIZE, type MapAdapter, type MapCursor, type MapEvent, type MapEventHandler, type Marker, type MarkerAnchor, type MarkerCapability, MarkerCapabilityRequiredError, type MarkerFootprint, type MarkerIcon, type MarkerRender, type MarkerSize, type MarkerStyle, type MergedPickFeature, type NativeEventEntry, type OffsetDragModifier, type PickCandidate, type PickCandidateHit, type PickCandidateHitKind, type PickCandidateInput, type PickEvaluationContext, type PickEvent, type PickHandler, type PickOptions, type PickPointerType, PinFootprint, PinOverridePatch, PinPresentation, PinPresentationCapability, PinPresentationPatch, PinPresentationState, PinPresentationStatus, PinPresentationStatusEvent, PinPresentationStore, PinRender, type PinnableGraphic, type PixelCoordinate, type PointSymbol, type PointSymbolAnchor, type PointSymbolCapability, PointSymbolCapabilityRequiredError, type PointSymbolColors, type PointSymbolConnector, type PointSymbolFootprint, type PointSymbolGraphicModifiers, type PointSymbolOffset, type PointSymbolOffsetControls, type PointSymbolOffsetLayout, type PointSymbolOffsetStyle, type PointSymbolPlacement, type PointSymbolProjection, type PointSymbolRender, type PointSymbolSize, type PointSymbolStyle, type PointSymbolView, type PointerCallback, PointerCallbackHub, type PointerEventInfo, type ResolvedPickPresentation, type Rgba, 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, TEXT_HALO_COLOR, 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, alignPointSymbolIndicator, bindAbortable, cloneImageGraphic, cloneMarker, clonePointSymbol, coerceHandleStyle, combinePinScale, combineWithHostSignal, convertPointSymbolPlacement, effectivePointSymbolPixelSize, evaluatePickCandidates, fillPatternImageDimension, fillPatternImageId, getSizeAnchor, hitTestFeature, hitTestIconFeature, ignoreAbort, imageFootprint, imageOpacity, isAnchoredGraphic, isImageGraphic, isMarker, isMinePattern, isPinnableGraphic, isPointSymbol, isTacticalDrawAbortError, isValidPinNumber, makeFillPatternImage, markerFootprint, markerOpacity, mergeNativeAndCachedPickFeatures, movePointSymbolLocation, nearestWorldCopyLng, nearestWorldCopyPosition, normalizeImageGraphic, normalizeMarker, parseColor, pickHitTolerance, pickPointerType, pinDistanceScale, pinZoomScale, placePointSymbol, pointSymbolFootprint, pointSymbolResource, renderOrderToVisualOrder, resizePointSymbolSize, resolveGroundTextSizePixels, resolveMarkerRender, resolvePickPresentation, resolvePinPresentation, resolvePointSymbolOffset, resolveTextHaloWidth, resolveTextSizePixels, scalePointSymbolLayout, tryControlMeasureIdFromFeature, validateImageGraphic, validateMarker };
|
package/dist/index.mjs
CHANGED
|
@@ -1448,6 +1448,10 @@ function pointInBox(box, pixel) {
|
|
|
1448
1448
|
const [lx, ly] = rotate(pixel[0] - center[0], pixel[1] - center[1], -angle);
|
|
1449
1449
|
return Math.abs(lx) <= halfWidth && Math.abs(ly) <= halfHeight;
|
|
1450
1450
|
}
|
|
1451
|
+
/** Screen angle in radians from `anchor` to `pixel`, for rotate drags pivoting on an anchor. */
|
|
1452
|
+
function pointerAngle(pixel, anchor) {
|
|
1453
|
+
return Math.atan2(pixel[1] - anchor[1], pixel[0] - anchor[0]);
|
|
1454
|
+
}
|
|
1451
1455
|
/** Plain 2D distance between two pixel coordinates. */
|
|
1452
1456
|
function pixelDistance$1(a, b) {
|
|
1453
1457
|
return Math.hypot(a[0] - b[0], a[1] - b[1]);
|
|
@@ -1716,9 +1720,55 @@ function normalizeImageRotation(value) {
|
|
|
1716
1720
|
return (value % turn + turn) % turn;
|
|
1717
1721
|
}
|
|
1718
1722
|
//#endregion
|
|
1723
|
+
//#region src/tactical-draw/rotation.ts
|
|
1724
|
+
/** Excalidraw-style rotation increment used while Shift is held. */
|
|
1725
|
+
const CONSTRAINED_ROTATION_STEP = Math.PI / 12;
|
|
1726
|
+
/** Normalize radians to the canonical clockwise [0, 2π) range. */
|
|
1727
|
+
function normalizeRotation(angle) {
|
|
1728
|
+
const turn = Math.PI * 2;
|
|
1729
|
+
return (angle % turn + turn) % turn;
|
|
1730
|
+
}
|
|
1731
|
+
/** Snap an absolute rotation angle to the nearest 15-degree increment. */
|
|
1732
|
+
function constrainRotation(angle) {
|
|
1733
|
+
return Math.round(angle / CONSTRAINED_ROTATION_STEP) * CONSTRAINED_ROTATION_STEP;
|
|
1734
|
+
}
|
|
1735
|
+
//#endregion
|
|
1736
|
+
//#region src/marker.ts
|
|
1737
|
+
function isMarker(graphic) {
|
|
1738
|
+
return typeof graphic === "object" && graphic !== null && "kind" in graphic && graphic.kind === "marker";
|
|
1739
|
+
}
|
|
1740
|
+
function cloneMarker(marker) {
|
|
1741
|
+
return structuredClone(marker);
|
|
1742
|
+
}
|
|
1743
|
+
function markerOpacity(marker) {
|
|
1744
|
+
const opacity = marker.style?.opacity ?? 1;
|
|
1745
|
+
if (!Number.isFinite(opacity)) throw new TypeError("Marker.style.opacity must be finite");
|
|
1746
|
+
return Math.max(0, Math.min(1, opacity));
|
|
1747
|
+
}
|
|
1748
|
+
function validateMarker(marker) {
|
|
1749
|
+
if (!marker.id) throw new TypeError("Marker.id must not be empty");
|
|
1750
|
+
if (!marker.symbolId) throw new TypeError("Marker.symbolId must not be empty");
|
|
1751
|
+
if (!Number.isFinite(marker.size.value) || marker.size.value <= 0) throw new TypeError("Marker.size.value must be a positive finite number");
|
|
1752
|
+
if (marker.size.unit !== "pixels" && marker.size.unit !== "meters") throw new TypeError("Marker.size.unit must be \"pixels\" or \"meters\"");
|
|
1753
|
+
if (!Number.isFinite(marker.rotation)) throw new TypeError("Marker.rotation must be finite");
|
|
1754
|
+
if (marker.schemaVersion !== 1) throw new TypeError("Marker.schemaVersion must be 1");
|
|
1755
|
+
markerOpacity(marker);
|
|
1756
|
+
if (!Array.isArray(marker.position) || marker.position.length < 2 || !Number.isFinite(marker.position[0]) || !Number.isFinite(marker.position[1])) throw new TypeError("Marker.position must be a finite geographic position");
|
|
1757
|
+
}
|
|
1758
|
+
function normalizeMarker(marker) {
|
|
1759
|
+
validateMarker(marker);
|
|
1760
|
+
const next = cloneMarker(marker);
|
|
1761
|
+
next.rotation = normalizeRotation(next.rotation);
|
|
1762
|
+
if (next.style?.opacity !== void 0) next.style.opacity = markerOpacity(next);
|
|
1763
|
+
return next;
|
|
1764
|
+
}
|
|
1765
|
+
//#endregion
|
|
1719
1766
|
//#region src/graphic.ts
|
|
1720
1767
|
function isAnchoredGraphic(graphic) {
|
|
1721
|
-
return isPointSymbol(graphic) || isImageGraphic(graphic);
|
|
1768
|
+
return isPointSymbol(graphic) || isImageGraphic(graphic) || isMarker(graphic);
|
|
1769
|
+
}
|
|
1770
|
+
function isPinnableGraphic(graphic) {
|
|
1771
|
+
return isPointSymbol(graphic) || isMarker(graphic);
|
|
1722
1772
|
}
|
|
1723
1773
|
//#endregion
|
|
1724
1774
|
//#region src/tactical-draw/active-interaction.ts
|
|
@@ -3298,19 +3348,6 @@ function pickHandle(handles, pixel, tolerance, toPixel) {
|
|
|
3298
3348
|
return null;
|
|
3299
3349
|
}
|
|
3300
3350
|
//#endregion
|
|
3301
|
-
//#region src/tactical-draw/rotation.ts
|
|
3302
|
-
/** Excalidraw-style rotation increment used while Shift is held. */
|
|
3303
|
-
const CONSTRAINED_ROTATION_STEP = Math.PI / 12;
|
|
3304
|
-
/** Normalize radians to the canonical clockwise [0, 2π) range. */
|
|
3305
|
-
function normalizeRotation(angle) {
|
|
3306
|
-
const turn = Math.PI * 2;
|
|
3307
|
-
return (angle % turn + turn) % turn;
|
|
3308
|
-
}
|
|
3309
|
-
/** Snap an absolute rotation angle to the nearest 15-degree increment. */
|
|
3310
|
-
function constrainRotation(angle) {
|
|
3311
|
-
return Math.round(angle / CONSTRAINED_ROTATION_STEP) * CONSTRAINED_ROTATION_STEP;
|
|
3312
|
-
}
|
|
3313
|
-
//#endregion
|
|
3314
3351
|
//#region src/tactical-draw/handle-drag.ts
|
|
3315
3352
|
function clonePoints(points) {
|
|
3316
3353
|
return points.map((p) => [...p]);
|
|
@@ -5687,6 +5724,13 @@ var ImageCapabilityRequiredError = class ImageCapabilityRequiredError extends Er
|
|
|
5687
5724
|
Object.setPrototypeOf(this, ImageCapabilityRequiredError.prototype);
|
|
5688
5725
|
}
|
|
5689
5726
|
};
|
|
5727
|
+
var MarkerCapabilityRequiredError = class MarkerCapabilityRequiredError extends Error {
|
|
5728
|
+
constructor() {
|
|
5729
|
+
super("TacticalDraw: marker capability is not configured");
|
|
5730
|
+
this.name = "MarkerCapabilityRequiredError";
|
|
5731
|
+
Object.setPrototypeOf(this, MarkerCapabilityRequiredError.prototype);
|
|
5732
|
+
}
|
|
5733
|
+
};
|
|
5690
5734
|
//#endregion
|
|
5691
5735
|
//#region src/tactical-draw/point-symbol-rendering.ts
|
|
5692
5736
|
/** Complete rotated logical footprint for selection and transform chrome. */
|
|
@@ -5910,6 +5954,147 @@ function missingResource(image) {
|
|
|
5910
5954
|
};
|
|
5911
5955
|
}
|
|
5912
5956
|
//#endregion
|
|
5957
|
+
//#region src/tactical-draw/marker-rendering.ts
|
|
5958
|
+
const PLACEHOLDER_SIZE = 24;
|
|
5959
|
+
const PLACEHOLDER = {
|
|
5960
|
+
resourceId: "__td_missing_marker__",
|
|
5961
|
+
svg: `<svg xmlns="http://www.w3.org/2000/svg" width="${PLACEHOLDER_SIZE}" height="${PLACEHOLDER_SIZE}" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" fill="#f3f4f6" fill-opacity="0.85" stroke="#6b7280" stroke-width="2" stroke-dasharray="3 2"/><text x="12" y="16.5" text-anchor="middle" font-family="sans-serif" font-size="13" font-weight="bold" fill="#6b7280">?</text></svg>`,
|
|
5962
|
+
width: PLACEHOLDER_SIZE,
|
|
5963
|
+
height: PLACEHOLDER_SIZE,
|
|
5964
|
+
anchor: {
|
|
5965
|
+
x: PLACEHOLDER_SIZE / 2,
|
|
5966
|
+
y: PLACEHOLDER_SIZE / 2
|
|
5967
|
+
}
|
|
5968
|
+
};
|
|
5969
|
+
/** Resolve a marker's icon, substituting the built-in placeholder for unknown symbols. */
|
|
5970
|
+
function resolveMarkerRender(capability, marker) {
|
|
5971
|
+
validateMarker(marker);
|
|
5972
|
+
const icon = capability.render(marker);
|
|
5973
|
+
if (!icon) return {
|
|
5974
|
+
...PLACEHOLDER,
|
|
5975
|
+
anchor: { ...PLACEHOLDER.anchor },
|
|
5976
|
+
available: false
|
|
5977
|
+
};
|
|
5978
|
+
validateMarkerIcon(icon);
|
|
5979
|
+
return {
|
|
5980
|
+
resourceId: icon.resourceId,
|
|
5981
|
+
svg: icon.svg,
|
|
5982
|
+
width: icon.width,
|
|
5983
|
+
height: icon.height,
|
|
5984
|
+
anchor: {
|
|
5985
|
+
x: icon.anchor.x,
|
|
5986
|
+
y: icon.anchor.y
|
|
5987
|
+
},
|
|
5988
|
+
available: true
|
|
5989
|
+
};
|
|
5990
|
+
}
|
|
5991
|
+
/**
|
|
5992
|
+
* Markers reuse the point-symbol icon path (ADR-0030) by presenting the icon
|
|
5993
|
+
* height as the "octagon" size, so `Marker.size` sizes the whole icon.
|
|
5994
|
+
*/
|
|
5995
|
+
function asPointSymbol(marker, render) {
|
|
5996
|
+
return [{
|
|
5997
|
+
id: marker.id,
|
|
5998
|
+
kind: "point-symbol",
|
|
5999
|
+
sidc: "",
|
|
6000
|
+
position: marker.position,
|
|
6001
|
+
rotation: marker.rotation,
|
|
6002
|
+
size: marker.size,
|
|
6003
|
+
style: { opacity: markerOpacity(marker) },
|
|
6004
|
+
...marker.properties ? { properties: marker.properties } : {}
|
|
6005
|
+
}, asPointSymbolRender(render)];
|
|
6006
|
+
}
|
|
6007
|
+
/**
|
|
6008
|
+
* Canonical icon-resource height. Engines rasterize an icon resource at its
|
|
6009
|
+
* declared size and then scale the bitmap, so a small host icon (e.g. a 44-unit
|
|
6010
|
+
* pin) would blur when enlarged. Presenting every marker at this height means
|
|
6011
|
+
* engines scale the bitmap down for typical sizes, like milsymbol's 100-unit
|
|
6012
|
+
* octagon does for point symbols.
|
|
6013
|
+
*/
|
|
6014
|
+
const MARKER_RESOURCE_HEIGHT = 256;
|
|
6015
|
+
const symbolRenders = /* @__PURE__ */ new WeakMap();
|
|
6016
|
+
function asPointSymbolRender(render) {
|
|
6017
|
+
let symbolRender = symbolRenders.get(render);
|
|
6018
|
+
if (!symbolRender) {
|
|
6019
|
+
symbolRender = supersample(render);
|
|
6020
|
+
symbolRenders.set(render, symbolRender);
|
|
6021
|
+
}
|
|
6022
|
+
return symbolRender;
|
|
6023
|
+
}
|
|
6024
|
+
function supersample(render) {
|
|
6025
|
+
const k = Math.max(1, MARKER_RESOURCE_HEIGHT / render.height);
|
|
6026
|
+
const width = render.width * k;
|
|
6027
|
+
const height = render.height * k;
|
|
6028
|
+
const svg = k === 1 ? render.svg : `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${render.width} ${render.height}">${render.svg}</svg>`;
|
|
6029
|
+
return {
|
|
6030
|
+
resourceId: render.resourceId,
|
|
6031
|
+
svg,
|
|
6032
|
+
octagonSize: height,
|
|
6033
|
+
width,
|
|
6034
|
+
height,
|
|
6035
|
+
anchor: {
|
|
6036
|
+
x: render.anchor.x * k,
|
|
6037
|
+
y: render.anchor.y * k
|
|
6038
|
+
},
|
|
6039
|
+
octagonAnchor: {
|
|
6040
|
+
x: width / 2,
|
|
6041
|
+
y: height / 2
|
|
6042
|
+
},
|
|
6043
|
+
valid: render.available
|
|
6044
|
+
};
|
|
6045
|
+
}
|
|
6046
|
+
function markerFeature(marker, render, resolution) {
|
|
6047
|
+
const feature = pointSymbolFeature(...asPointSymbol(marker, render), resolution);
|
|
6048
|
+
feature.id = `${marker.id}:marker`;
|
|
6049
|
+
feature.properties.graphicKind = "marker";
|
|
6050
|
+
feature.properties.markerAvailable = render.available;
|
|
6051
|
+
return feature;
|
|
6052
|
+
}
|
|
6053
|
+
function markerResource(render) {
|
|
6054
|
+
return pointSymbolResource(asPointSymbolRender(render));
|
|
6055
|
+
}
|
|
6056
|
+
/**
|
|
6057
|
+
* The upright body a marker shows in pin presentation (ADR-0056): its icon
|
|
6058
|
+
* resource plus the canonical height the pin's `sizePixels` scales against.
|
|
6059
|
+
* The pin stem attaches below the icon, centred on the marker's anchor.
|
|
6060
|
+
*/
|
|
6061
|
+
function markerPinBody(render) {
|
|
6062
|
+
const symbolRender = asPointSymbolRender(render);
|
|
6063
|
+
return {
|
|
6064
|
+
resource: pointSymbolResource(symbolRender),
|
|
6065
|
+
octagonSize: symbolRender.octagonSize
|
|
6066
|
+
};
|
|
6067
|
+
}
|
|
6068
|
+
/** Complete rotated footprint for selection and transform chrome. */
|
|
6069
|
+
function markerFootprint(marker, render, adapter) {
|
|
6070
|
+
const footprint = pointSymbolFootprint(...asPointSymbol(marker, render), adapter);
|
|
6071
|
+
return footprint ? {
|
|
6072
|
+
box: footprint.box,
|
|
6073
|
+
corners: footprint.corners
|
|
6074
|
+
} : null;
|
|
6075
|
+
}
|
|
6076
|
+
/**
|
|
6077
|
+
* Whether a marker's rendered icon depends on map resolution: meter sizes carry
|
|
6078
|
+
* a resolution-derived `iconScale` unless the engine scales ground icons itself.
|
|
6079
|
+
*/
|
|
6080
|
+
function markerScalesWithResolution(marker, nativeGroundScaling) {
|
|
6081
|
+
return marker.size.unit === "meters" && !nativeGroundScaling;
|
|
6082
|
+
}
|
|
6083
|
+
/** Pass an already-resolved `render` to skip asking the capability again. */
|
|
6084
|
+
function renderMarkerForAdapter(adapter, capability, marker, render = resolveMarkerRender(capability, marker)) {
|
|
6085
|
+
return {
|
|
6086
|
+
render,
|
|
6087
|
+
features: [markerFeature(marker, render, adapter.getResolution())],
|
|
6088
|
+
resource: markerResource(render)
|
|
6089
|
+
};
|
|
6090
|
+
}
|
|
6091
|
+
function validateMarkerIcon(icon) {
|
|
6092
|
+
if (!icon.resourceId) throw new TypeError("MarkerIcon.resourceId must not be empty");
|
|
6093
|
+
if (typeof icon.svg !== "string" || !icon.svg) throw new TypeError("MarkerIcon.svg must be a non-empty SVG string");
|
|
6094
|
+
for (const [value, name] of [[icon.width, "width"], [icon.height, "height"]]) if (!Number.isFinite(value) || value <= 0) throw new TypeError(`MarkerIcon.${name} must be a positive finite number`);
|
|
6095
|
+
if (!Number.isFinite(icon.anchor?.x) || !Number.isFinite(icon.anchor?.y)) throw new TypeError("MarkerIcon.anchor must be finite");
|
|
6096
|
+
}
|
|
6097
|
+
//#endregion
|
|
5913
6098
|
//#region src/tactical-draw/frame-coalescer.ts
|
|
5914
6099
|
/**
|
|
5915
6100
|
* @param run Callback invoked with the latest scheduled args, at most once per frame.
|
|
@@ -5990,9 +6175,9 @@ function defaultGroupSizeAnchor(graphics) {
|
|
|
5990
6175
|
* a live session without a session boundary
|
|
5991
6176
|
*/
|
|
5992
6177
|
function runGroupTransform(opts) {
|
|
5993
|
-
const { adapter, capability, imageCapability, graphics, graphicsLayer, previewLayer, handlesLayer, graphicsStyle, symbolColors, signal, closeOnClickAway = true, interactionStyle, onSession, handleIdPrefix, publishWorkingGraphics, settleWorkingGraphics, isOnGraphicsLayer, onSettled, onClickAwayGraphicsPick } = opts;
|
|
6178
|
+
const { adapter, capability, imageCapability, markerCapability, graphics, graphicsLayer, previewLayer, handlesLayer, graphicsStyle, symbolColors, signal, closeOnClickAway = true, interactionStyle, onSession, handleIdPrefix, publishWorkingGraphics, settleWorkingGraphics, isOnGraphicsLayer, onSettled, onClickAwayGraphicsPick } = opts;
|
|
5994
6179
|
assertCapabilityFor(graphics);
|
|
5995
|
-
|
|
6180
|
+
validateHostResources(graphics);
|
|
5996
6181
|
const renderOpts = {
|
|
5997
6182
|
graphicsStyle,
|
|
5998
6183
|
symbolColors
|
|
@@ -6002,10 +6187,14 @@ function runGroupTransform(opts) {
|
|
|
6002
6187
|
function assertCapabilityFor(list) {
|
|
6003
6188
|
if (!capability && list.some(isPointSymbol)) throw new PointSymbolCapabilityRequiredError();
|
|
6004
6189
|
if (!imageCapability && list.some(isImageGraphic)) throw new ImageCapabilityRequiredError();
|
|
6190
|
+
if (!markerCapability && list.some(isMarker)) throw new MarkerCapabilityRequiredError();
|
|
6005
6191
|
}
|
|
6006
6192
|
/** Validate host integration before listeners, layers, or interaction state are created. */
|
|
6007
|
-
function
|
|
6008
|
-
for (const graphic of list)
|
|
6193
|
+
function validateHostResources(list) {
|
|
6194
|
+
for (const graphic of list) {
|
|
6195
|
+
if (isImageGraphic(graphic)) renderImageForAdapter(adapter, imageCapability, graphic);
|
|
6196
|
+
if (isMarker(graphic)) resolveMarkerRender(markerCapability, graphic);
|
|
6197
|
+
}
|
|
6009
6198
|
}
|
|
6010
6199
|
function isPointSymbolMember(member) {
|
|
6011
6200
|
return isPointSymbol(member.graphic);
|
|
@@ -6013,6 +6202,9 @@ function runGroupTransform(opts) {
|
|
|
6013
6202
|
function isImageMember(member) {
|
|
6014
6203
|
return isImageGraphic(member.graphic);
|
|
6015
6204
|
}
|
|
6205
|
+
function isMarkerMember(member) {
|
|
6206
|
+
return isMarker(member.graphic);
|
|
6207
|
+
}
|
|
6016
6208
|
function isAnchoredMember(member) {
|
|
6017
6209
|
return isAnchoredGraphic(member.graphic);
|
|
6018
6210
|
}
|
|
@@ -6093,6 +6285,13 @@ function runGroupTransform(opts) {
|
|
|
6093
6285
|
image.rotation = member.workingRotation;
|
|
6094
6286
|
return image;
|
|
6095
6287
|
}
|
|
6288
|
+
function buildWorkingMarker(member) {
|
|
6289
|
+
const marker = cloneMarker(member.graphic);
|
|
6290
|
+
marker.position = [...member.workingPoints[0]];
|
|
6291
|
+
marker.size = resizePointSymbolSize(marker.size, member.workingSize);
|
|
6292
|
+
marker.rotation = member.workingRotation;
|
|
6293
|
+
return marker;
|
|
6294
|
+
}
|
|
6096
6295
|
/** Build the working measure for member `i` with a given options override. */
|
|
6097
6296
|
function buildWorkingMeasureWith(member, override) {
|
|
6098
6297
|
const measure = member.graphic;
|
|
@@ -6120,6 +6319,13 @@ function runGroupTransform(opts) {
|
|
|
6120
6319
|
render: renderImageForAdapter(adapter, imageCapability, image).render
|
|
6121
6320
|
};
|
|
6122
6321
|
}
|
|
6322
|
+
if (isMarkerMember(member)) {
|
|
6323
|
+
const marker = buildWorkingMarker(member);
|
|
6324
|
+
return {
|
|
6325
|
+
graphic: cloneMarker(marker),
|
|
6326
|
+
render: resolveMarkerRender(markerCapability, marker)
|
|
6327
|
+
};
|
|
6328
|
+
}
|
|
6123
6329
|
const working = buildWorkingMeasureWith(member, override);
|
|
6124
6330
|
const committed = getControlMeasureMetadata(working.kind).uniformSizing || sizeAnchor === "screen" ? working : bakePixelSizeToGround(working, adapter);
|
|
6125
6331
|
return {
|
|
@@ -6132,6 +6338,7 @@ function runGroupTransform(opts) {
|
|
|
6132
6338
|
const member = members[i];
|
|
6133
6339
|
if (isPointSymbolMember(member)) return buildWorkingPointSymbol(member);
|
|
6134
6340
|
if (isImageMember(member)) return buildWorkingImage(member);
|
|
6341
|
+
if (isMarkerMember(member)) return buildWorkingMarker(member);
|
|
6135
6342
|
return buildWorkingMeasureWith(member, member.optionsOverride);
|
|
6136
6343
|
}
|
|
6137
6344
|
let dirty = false;
|
|
@@ -6276,6 +6483,24 @@ function runGroupTransform(opts) {
|
|
|
6276
6483
|
features = [plan.feature];
|
|
6277
6484
|
const footprint = imageFootprint(image, plan.render, adapter);
|
|
6278
6485
|
if (footprint) boxPixels = footprint.corners;
|
|
6486
|
+
} else if (isMarkerMember(member)) {
|
|
6487
|
+
const marker = buildWorkingMarker(member);
|
|
6488
|
+
pinGroup = opts.renderPin?.(marker);
|
|
6489
|
+
const pinFootprint = pinGroup?.pin && adapter.getPinFootprint?.(marker.id);
|
|
6490
|
+
const render = pinFootprint ? void 0 : resolveMarkerRender(markerCapability, marker);
|
|
6491
|
+
if (pinGroup?.pin) {
|
|
6492
|
+
features = pinGroup.features;
|
|
6493
|
+
iconResources = pinGroup.iconResources;
|
|
6494
|
+
} else {
|
|
6495
|
+
const plan = renderMarkerForAdapter(adapter, markerCapability, marker, render);
|
|
6496
|
+
features = plan.features;
|
|
6497
|
+
iconResources = [plan.resource];
|
|
6498
|
+
}
|
|
6499
|
+
if (pinFootprint) boxPixels = boxCorners(boxFromPixelBounds(pinFootprint.min, pinFootprint.max));
|
|
6500
|
+
else {
|
|
6501
|
+
const footprint = markerFootprint(marker, render, adapter);
|
|
6502
|
+
if (footprint) boxPixels = footprint.corners;
|
|
6503
|
+
}
|
|
6279
6504
|
} else try {
|
|
6280
6505
|
if (isPointSymbolMember(member)) {
|
|
6281
6506
|
const symbol = buildWorkingPointSymbol(member);
|
|
@@ -6835,7 +7060,7 @@ function runGroupTransform(opts) {
|
|
|
6835
7060
|
}
|
|
6836
7061
|
//#endregion
|
|
6837
7062
|
//#region src/tactical-draw/point-symbol-draw-controller.ts
|
|
6838
|
-
const PREVIEW_ID$
|
|
7063
|
+
const PREVIEW_ID$2 = "__td_point_symbol_preview__";
|
|
6839
7064
|
function runPointSymbolDraw(options) {
|
|
6840
7065
|
const { adapter, capability, draft, previewLayer, generateId, signal, onSettled, snap } = options;
|
|
6841
7066
|
let latestPosition = draft.position;
|
|
@@ -6852,9 +7077,9 @@ function runPointSymbolDraw(options) {
|
|
|
6852
7077
|
});
|
|
6853
7078
|
const renderPreview = () => {
|
|
6854
7079
|
if (!latestPosition) return;
|
|
6855
|
-
const plan = renderPointSymbolForAdapter(adapter, capability, build(PREVIEW_ID$
|
|
7080
|
+
const plan = renderPointSymbolForAdapter(adapter, capability, build(PREVIEW_ID$2, latestPosition));
|
|
6856
7081
|
ctx.writeLayer(previewLayer, [{
|
|
6857
|
-
id: PREVIEW_ID$
|
|
7082
|
+
id: PREVIEW_ID$2,
|
|
6858
7083
|
features: plan.features,
|
|
6859
7084
|
iconResources: [plan.resource]
|
|
6860
7085
|
}]);
|
|
@@ -7130,7 +7355,6 @@ function runPointSymbolEdit(opts) {
|
|
|
7130
7355
|
return settleEmitter.register(listener);
|
|
7131
7356
|
}
|
|
7132
7357
|
};
|
|
7133
|
-
const pointerAngle = (pixel, anchor) => Math.atan2(pixel[1] - anchor[1], pixel[0] - anchor[0]);
|
|
7134
7358
|
const snapTranslate = (position, fallbackPixel, info) => snap?.({
|
|
7135
7359
|
coordinate: position,
|
|
7136
7360
|
pixel: driver.toPixel(position) ?? fallbackPixel,
|
|
@@ -7326,7 +7550,7 @@ function runPointSymbolEdit(opts) {
|
|
|
7326
7550
|
}
|
|
7327
7551
|
//#endregion
|
|
7328
7552
|
//#region src/tactical-draw/image-draw-controller.ts
|
|
7329
|
-
const PREVIEW_ID = "__td_image_preview__";
|
|
7553
|
+
const PREVIEW_ID$1 = "__td_image_preview__";
|
|
7330
7554
|
const DEFAULT_IMAGE_WIDTH_PIXELS = 128;
|
|
7331
7555
|
function runImageDraw(options) {
|
|
7332
7556
|
const { adapter, capability, draft, previewLayer, generateId, signal, onSettled, snap } = options;
|
|
@@ -7354,9 +7578,9 @@ function runImageDraw(options) {
|
|
|
7354
7578
|
const planFor = (id, position) => renderImageForAdapter(adapter, capability, build(id, position));
|
|
7355
7579
|
const renderPreview = () => {
|
|
7356
7580
|
if (!latestPosition) return;
|
|
7357
|
-
const plan = planFor(PREVIEW_ID, latestPosition);
|
|
7581
|
+
const plan = planFor(PREVIEW_ID$1, latestPosition);
|
|
7358
7582
|
ctx.writeLayer(previewLayer, [{
|
|
7359
|
-
id: PREVIEW_ID,
|
|
7583
|
+
id: PREVIEW_ID$1,
|
|
7360
7584
|
features: [plan.feature],
|
|
7361
7585
|
iconResources: [],
|
|
7362
7586
|
...plan.overlay ? { imageOverlays: [plan.overlay] } : {}
|
|
@@ -7656,6 +7880,382 @@ function runImageEdit(opts) {
|
|
|
7656
7880
|
};
|
|
7657
7881
|
}
|
|
7658
7882
|
//#endregion
|
|
7883
|
+
//#region src/tactical-draw/marker-draw-controller.ts
|
|
7884
|
+
/** Default icon height for a drawn marker when the draft omits `size`. */
|
|
7885
|
+
const DEFAULT_MARKER_SIZE = {
|
|
7886
|
+
value: 32,
|
|
7887
|
+
unit: "pixels"
|
|
7888
|
+
};
|
|
7889
|
+
const PREVIEW_ID = "__td_marker_preview__";
|
|
7890
|
+
function runMarkerDraw(options) {
|
|
7891
|
+
const { adapter, capability, draft, previewLayer, generateId, signal, onSettled, snap } = options;
|
|
7892
|
+
let latestPosition = draft.position;
|
|
7893
|
+
let ctx;
|
|
7894
|
+
const savedCursor = "";
|
|
7895
|
+
const build = (id, position) => ({
|
|
7896
|
+
...structuredClone(draft),
|
|
7897
|
+
id,
|
|
7898
|
+
kind: "marker",
|
|
7899
|
+
position: [...position],
|
|
7900
|
+
rotation: normalizeRotation(draft.rotation ?? 0),
|
|
7901
|
+
size: structuredClone(draft.size ?? DEFAULT_MARKER_SIZE),
|
|
7902
|
+
schemaVersion: 1
|
|
7903
|
+
});
|
|
7904
|
+
let previewRender;
|
|
7905
|
+
const renderPreview = () => {
|
|
7906
|
+
if (!latestPosition) return;
|
|
7907
|
+
const preview = build(PREVIEW_ID, latestPosition);
|
|
7908
|
+
previewRender ??= resolveMarkerRender(capability, preview);
|
|
7909
|
+
const plan = renderMarkerForAdapter(adapter, capability, preview, previewRender);
|
|
7910
|
+
ctx.writeLayer(previewLayer, [{
|
|
7911
|
+
id: PREVIEW_ID,
|
|
7912
|
+
features: plan.features,
|
|
7913
|
+
iconResources: [plan.resource]
|
|
7914
|
+
}]);
|
|
7915
|
+
};
|
|
7916
|
+
const handlePointerMove = (event) => {
|
|
7917
|
+
latestPosition = snappedDrawPosition(snap, event);
|
|
7918
|
+
renderPreview();
|
|
7919
|
+
};
|
|
7920
|
+
const handleClick = (event) => {
|
|
7921
|
+
latestPosition = snappedDrawPosition(snap, event);
|
|
7922
|
+
ctx.commit(() => {
|
|
7923
|
+
const graphic = build(draft.id ?? generateId(), latestPosition);
|
|
7924
|
+
return {
|
|
7925
|
+
graphic,
|
|
7926
|
+
render: resolveMarkerRender(capability, graphic)
|
|
7927
|
+
};
|
|
7928
|
+
});
|
|
7929
|
+
};
|
|
7930
|
+
return runInteraction({
|
|
7931
|
+
adapter,
|
|
7932
|
+
signal,
|
|
7933
|
+
layers: [previewLayer],
|
|
7934
|
+
onViewChange: renderPreview,
|
|
7935
|
+
onSettled,
|
|
7936
|
+
attach(interaction) {
|
|
7937
|
+
ctx = interaction;
|
|
7938
|
+
interaction.onTeardown(() => {
|
|
7939
|
+
adapter.off("pointermove", handlePointerMove);
|
|
7940
|
+
adapter.off("click", handleClick);
|
|
7941
|
+
adapter.setCursor(savedCursor);
|
|
7942
|
+
});
|
|
7943
|
+
adapter.setCursor("crosshair");
|
|
7944
|
+
adapter.on("pointermove", handlePointerMove);
|
|
7945
|
+
adapter.on("click", handleClick);
|
|
7946
|
+
renderPreview();
|
|
7947
|
+
}
|
|
7948
|
+
});
|
|
7949
|
+
}
|
|
7950
|
+
//#endregion
|
|
7951
|
+
//#region src/tactical-draw/marker-edit-controller.ts
|
|
7952
|
+
function normaliseMarkerModes(input) {
|
|
7953
|
+
const modes = input ?? ["transform"];
|
|
7954
|
+
for (const mode of modes) if (mode !== "transform" && mode !== "delete") throw new TypeError(`Marker editing does not support mode "${mode}"`);
|
|
7955
|
+
return modes.includes("delete") ? ["delete"] : [...new Set(modes)];
|
|
7956
|
+
}
|
|
7957
|
+
function runMarkerEdit(opts) {
|
|
7958
|
+
const { adapter, capability, marker, graphicsLayer, previewLayer, handlesLayer, signal, closeOnClickAway = true, interactionStyle, onSession, handleIdPrefix, settleToGraphics, publishWorkingGraphic, wasOnGraphicsLayer, onSettled, onClickAwayGraphicsPick, snap } = opts;
|
|
7959
|
+
validateMarker(marker);
|
|
7960
|
+
let modes = normaliseMarkerModes(opts.modes);
|
|
7961
|
+
let usesGraphicStack = wasOnGraphicsLayer;
|
|
7962
|
+
let pinEditing = !!opts.renderPin && opts.modes === void 0;
|
|
7963
|
+
let pinDrag = null;
|
|
7964
|
+
let working = cloneMarker(marker);
|
|
7965
|
+
let dirty = false;
|
|
7966
|
+
let box = null;
|
|
7967
|
+
let drag = null;
|
|
7968
|
+
let ctx;
|
|
7969
|
+
let driver;
|
|
7970
|
+
let shell;
|
|
7971
|
+
const changeEmitter = createChangeEmitter({
|
|
7972
|
+
listenerErrorsMessage: "GraphicEditSession.onChange errors",
|
|
7973
|
+
isSettled: () => ctx.settled,
|
|
7974
|
+
abort: () => ctx.fail(new TacticalDrawAbortError("session")),
|
|
7975
|
+
close: () => ctx.commit(snapshot)
|
|
7976
|
+
});
|
|
7977
|
+
const commitEmitter = createCommitEmitter("GraphicEditSession.onCommit listener errors");
|
|
7978
|
+
const settleEmitter = createSettleEmitter("GraphicEditSession.onSettled listener errors");
|
|
7979
|
+
const captureHistory = () => ({ working: cloneMarker(working) });
|
|
7980
|
+
const renders = /* @__PURE__ */ new WeakMap();
|
|
7981
|
+
const renderOf = (value) => {
|
|
7982
|
+
let render = renders.get(value);
|
|
7983
|
+
if (!render) {
|
|
7984
|
+
render = resolveMarkerRender(capability, value);
|
|
7985
|
+
renders.set(value, render);
|
|
7986
|
+
}
|
|
7987
|
+
return render;
|
|
7988
|
+
};
|
|
7989
|
+
const snapshotOf = (value) => ({
|
|
7990
|
+
graphic: cloneMarker(value),
|
|
7991
|
+
render: renderOf(value)
|
|
7992
|
+
});
|
|
7993
|
+
const snapshot = () => snapshotOf(working);
|
|
7994
|
+
const pinActive = () => pinEditing && !!opts.renderPin && opts.canRenderPin?.() === true;
|
|
7995
|
+
const render = (publishGraphic = true) => {
|
|
7996
|
+
if (ctx.settled) return;
|
|
7997
|
+
if (pinActive()) {
|
|
7998
|
+
const group = opts.renderPin(working);
|
|
7999
|
+
publishWorkingGraphic(group);
|
|
8000
|
+
ctx.writeLayer(previewLayer, usesGraphicStack ? [] : [group]);
|
|
8001
|
+
ctx.writeLayer(handlesLayer, group.pin ? [{
|
|
8002
|
+
id: `${handleIdPrefix}:pin`,
|
|
8003
|
+
features: [],
|
|
8004
|
+
iconResources: [],
|
|
8005
|
+
pin: {
|
|
8006
|
+
...group.pin,
|
|
8007
|
+
highlightOnly: true
|
|
8008
|
+
}
|
|
8009
|
+
}] : []);
|
|
8010
|
+
box = null;
|
|
8011
|
+
return;
|
|
8012
|
+
}
|
|
8013
|
+
const plan = renderMarkerForAdapter(adapter, capability, working, renderOf(working));
|
|
8014
|
+
const footprint = markerFootprint(working, plan.render, adapter);
|
|
8015
|
+
const padding = interactionStyle?.boxPadding ?? 0;
|
|
8016
|
+
const nextBox = footprint ? {
|
|
8017
|
+
...footprint.box,
|
|
8018
|
+
halfWidth: Math.max(1, footprint.box.halfWidth) + padding,
|
|
8019
|
+
halfHeight: Math.max(1, footprint.box.halfHeight) + padding
|
|
8020
|
+
} : null;
|
|
8021
|
+
const handles = [];
|
|
8022
|
+
if (modes.includes("transform") && nextBox) handles.push(boxOutlineFeature(nextBox, (pixel) => driver.fromPixel(pixel), `${handleIdPrefix}:box-outline`, interactionStyle?.boxOutline), ...toFeatures(boxToHandles(nextBox, (pixel) => driver.fromPixel(pixel)), handleIdPrefix, interactionStyle));
|
|
8023
|
+
const group = {
|
|
8024
|
+
id: working.id,
|
|
8025
|
+
features: plan.features,
|
|
8026
|
+
iconResources: [plan.resource]
|
|
8027
|
+
};
|
|
8028
|
+
if (publishGraphic) {
|
|
8029
|
+
publishWorkingGraphic(group);
|
|
8030
|
+
ctx.writeLayer(previewLayer, usesGraphicStack ? [] : [group]);
|
|
8031
|
+
}
|
|
8032
|
+
box = nextBox;
|
|
8033
|
+
ctx.writeLayer(handlesLayer, [{
|
|
8034
|
+
id: `__td_marker_edit_handles__:${working.id}`,
|
|
8035
|
+
features: handles,
|
|
8036
|
+
iconResources: []
|
|
8037
|
+
}]);
|
|
8038
|
+
};
|
|
8039
|
+
const emitChange = (previousState, source, onAccepted) => changeEmitter.emit({
|
|
8040
|
+
source,
|
|
8041
|
+
graphic: snapshot(),
|
|
8042
|
+
previous: snapshotOf(previousState.working),
|
|
8043
|
+
session
|
|
8044
|
+
}, {
|
|
8045
|
+
rollback() {
|
|
8046
|
+
working = cloneMarker(previousState.working);
|
|
8047
|
+
dirty = !deepEqual(working, marker);
|
|
8048
|
+
render();
|
|
8049
|
+
},
|
|
8050
|
+
onAccepted
|
|
8051
|
+
});
|
|
8052
|
+
const history = createSessionHistory({
|
|
8053
|
+
initial: captureHistory(),
|
|
8054
|
+
clone: (value) => ({ working: cloneMarker(value.working) }),
|
|
8055
|
+
equals: (a, b) => deepEqual(a.working, b.working),
|
|
8056
|
+
isCurrent: (value) => deepEqual(working, value.working),
|
|
8057
|
+
apply(from, to, source) {
|
|
8058
|
+
working = cloneMarker(to.working);
|
|
8059
|
+
dirty = !deepEqual(working, marker);
|
|
8060
|
+
render();
|
|
8061
|
+
return emitChange(from, source);
|
|
8062
|
+
}
|
|
8063
|
+
});
|
|
8064
|
+
/** `next` must be a fresh snapshot the caller no longer mutates. */
|
|
8065
|
+
const apply = (next, source, label) => {
|
|
8066
|
+
const previous = captureHistory();
|
|
8067
|
+
working = next;
|
|
8068
|
+
dirty = !deepEqual(working, marker);
|
|
8069
|
+
render();
|
|
8070
|
+
emitChange(previous, source, () => history.record(captureHistory(), label));
|
|
8071
|
+
};
|
|
8072
|
+
const session = {
|
|
8073
|
+
history,
|
|
8074
|
+
graphic: cloneMarker(marker),
|
|
8075
|
+
get workingGraphic() {
|
|
8076
|
+
return cloneMarker(working);
|
|
8077
|
+
},
|
|
8078
|
+
get dirty() {
|
|
8079
|
+
return dirty;
|
|
8080
|
+
},
|
|
8081
|
+
get modes() {
|
|
8082
|
+
return modes;
|
|
8083
|
+
},
|
|
8084
|
+
close: () => ctx.commit(snapshot),
|
|
8085
|
+
abort: () => ctx.fail(new TacticalDrawAbortError("session")),
|
|
8086
|
+
setModes(next) {
|
|
8087
|
+
if (ctx.settled) return;
|
|
8088
|
+
modes = normaliseMarkerModes(next);
|
|
8089
|
+
pinEditing = false;
|
|
8090
|
+
render();
|
|
8091
|
+
},
|
|
8092
|
+
updateGraphic(updater) {
|
|
8093
|
+
if (ctx.settled) return;
|
|
8094
|
+
const next = normalizeMarker(updater(cloneMarker(working)));
|
|
8095
|
+
if (next.kind !== "marker" || next.id !== marker.id) throw new TypeError("updateGraphic must preserve marker kind and id");
|
|
8096
|
+
renderOf(next);
|
|
8097
|
+
apply(next, "programmatic", "Update graphic");
|
|
8098
|
+
},
|
|
8099
|
+
onChange(listener) {
|
|
8100
|
+
if (ctx.settled) return () => {};
|
|
8101
|
+
return changeEmitter.register(listener);
|
|
8102
|
+
},
|
|
8103
|
+
onCommit(listener) {
|
|
8104
|
+
if (ctx.settled) return () => {};
|
|
8105
|
+
return commitEmitter.register(listener);
|
|
8106
|
+
},
|
|
8107
|
+
onSettled(listener) {
|
|
8108
|
+
return settleEmitter.register(listener);
|
|
8109
|
+
}
|
|
8110
|
+
};
|
|
8111
|
+
const snapTranslate = (position, pixel, info) => snap?.({
|
|
8112
|
+
coordinate: position,
|
|
8113
|
+
pixel,
|
|
8114
|
+
interaction: "translate",
|
|
8115
|
+
graphicId: marker.id,
|
|
8116
|
+
originalEvent: info?.native
|
|
8117
|
+
})?.coordinate ?? position;
|
|
8118
|
+
const transformed = (pixel, info) => {
|
|
8119
|
+
if (pinDrag) {
|
|
8120
|
+
const attachment = [pinDrag.attachment[0] + pixel[0] - pinDrag.down[0], pinDrag.attachment[1] + pixel[1] - pinDrag.down[1]];
|
|
8121
|
+
const position = adapter.movePinFromPixel?.(working.id, attachment);
|
|
8122
|
+
if (!position) return null;
|
|
8123
|
+
return {
|
|
8124
|
+
...cloneMarker(pinDrag.start),
|
|
8125
|
+
position: snapTranslate(position, attachment, info)
|
|
8126
|
+
};
|
|
8127
|
+
}
|
|
8128
|
+
if (!drag) return null;
|
|
8129
|
+
const next = cloneMarker(drag.start);
|
|
8130
|
+
if (drag.kind === "body") {
|
|
8131
|
+
const position = driver.fromPixel([drag.anchor[0] + pixel[0] - drag.down[0], drag.anchor[1] + pixel[1] - drag.down[1]]);
|
|
8132
|
+
next.position = snapTranslate(position, driver.toPixel(position) ?? pixel, info);
|
|
8133
|
+
} else if (drag.kind === "rotate") {
|
|
8134
|
+
const rotation = drag.start.rotation + pointerAngle(pixel, drag.anchor) - drag.startPointerAngle;
|
|
8135
|
+
next.rotation = normalizeRotation(info?.shiftKey ? constrainRotation(rotation) : rotation);
|
|
8136
|
+
} else {
|
|
8137
|
+
const distance = pixelDistance$1(pixel, drag.anchor);
|
|
8138
|
+
next.size = resizePointSymbolSize(drag.start.size, Math.max(.1, drag.start.size.value * (distance / drag.startDistance)));
|
|
8139
|
+
}
|
|
8140
|
+
return next;
|
|
8141
|
+
};
|
|
8142
|
+
const onDown = (pixel, info) => {
|
|
8143
|
+
if (pinActive()) {
|
|
8144
|
+
if (ctx.settled) return;
|
|
8145
|
+
const footprint = adapter.getPinFootprint?.(working.id);
|
|
8146
|
+
if (footprint && adapter.pickPin?.(working.id, pixel, info?.hitTolerance ?? 12)) {
|
|
8147
|
+
pinDrag = {
|
|
8148
|
+
start: cloneMarker(working),
|
|
8149
|
+
down: [...pixel],
|
|
8150
|
+
attachment: footprint.attachment
|
|
8151
|
+
};
|
|
8152
|
+
driver.setDragPanEnabled(false);
|
|
8153
|
+
}
|
|
8154
|
+
return;
|
|
8155
|
+
}
|
|
8156
|
+
if (ctx.settled || !box || !modes.includes("transform")) return;
|
|
8157
|
+
const hit = pickBoxHandle(box, pixel, info?.hitTolerance ?? 12);
|
|
8158
|
+
if (!hit) return;
|
|
8159
|
+
const anchor = driver.toPixel(working.position);
|
|
8160
|
+
if (!anchor) return;
|
|
8161
|
+
drag = {
|
|
8162
|
+
kind: hit.kind,
|
|
8163
|
+
down: [...pixel],
|
|
8164
|
+
start: cloneMarker(working),
|
|
8165
|
+
anchor,
|
|
8166
|
+
startPointerAngle: pointerAngle(pixel, anchor),
|
|
8167
|
+
startDistance: Math.max(1, pixelDistance$1(pixel, anchor))
|
|
8168
|
+
};
|
|
8169
|
+
driver.setDragPanEnabled(false);
|
|
8170
|
+
};
|
|
8171
|
+
const onMove = (pixel, info) => {
|
|
8172
|
+
const next = transformed(pixel, info);
|
|
8173
|
+
if (!next) return;
|
|
8174
|
+
working = next;
|
|
8175
|
+
render();
|
|
8176
|
+
};
|
|
8177
|
+
const onUp = (pixel, info) => {
|
|
8178
|
+
if (pinDrag) {
|
|
8179
|
+
const next = transformed(pixel, info);
|
|
8180
|
+
const { start, down } = pinDrag;
|
|
8181
|
+
pinDrag = null;
|
|
8182
|
+
driver.setDragPanEnabled(true);
|
|
8183
|
+
shell.suppressNextClickAway();
|
|
8184
|
+
working = cloneMarker(start);
|
|
8185
|
+
if (next && !withinClickSlop(pixel, down)) apply(next, "gesture", "Move marker");
|
|
8186
|
+
else render();
|
|
8187
|
+
return;
|
|
8188
|
+
}
|
|
8189
|
+
if (!drag) return;
|
|
8190
|
+
const current = drag;
|
|
8191
|
+
const next = transformed(pixel, info);
|
|
8192
|
+
drag = null;
|
|
8193
|
+
shell.suppressNextClickAway();
|
|
8194
|
+
driver.setDragPanEnabled(true);
|
|
8195
|
+
working = cloneMarker(current.start);
|
|
8196
|
+
if (!next) return;
|
|
8197
|
+
if (current.kind === "body" && withinClickSlop(pixel, current.down)) {
|
|
8198
|
+
render();
|
|
8199
|
+
return;
|
|
8200
|
+
}
|
|
8201
|
+
apply(next, "gesture", `${current.kind[0].toUpperCase()}${current.kind.slice(1)}`);
|
|
8202
|
+
};
|
|
8203
|
+
const handle = runEditInteraction({
|
|
8204
|
+
adapter,
|
|
8205
|
+
signal,
|
|
8206
|
+
layers: [previewLayer, handlesLayer],
|
|
8207
|
+
graphicsLayer,
|
|
8208
|
+
previewLayer,
|
|
8209
|
+
handlesLayer,
|
|
8210
|
+
closeOnClickAway,
|
|
8211
|
+
onViewChange: () => {
|
|
8212
|
+
if (pinActive()) return;
|
|
8213
|
+
render(markerScalesWithResolution(working, adapter.scalesGroundPointSymbolsNatively === true));
|
|
8214
|
+
},
|
|
8215
|
+
onBeforeTeardown: (settlement) => settleToGraphics(settlement.status === "committed" ? settlement.value.graphic : void 0),
|
|
8216
|
+
onDown,
|
|
8217
|
+
onMove,
|
|
8218
|
+
onUp,
|
|
8219
|
+
ownsGraphic: (id) => id === marker.id,
|
|
8220
|
+
close: () => ctx.commit(snapshot),
|
|
8221
|
+
onForeignPick: onClickAwayGraphicsPick,
|
|
8222
|
+
historySettle: () => history.settle(),
|
|
8223
|
+
facadeOnSettled: onSettled,
|
|
8224
|
+
emitSettle: (settlement) => settleFromInteraction(settlement, commitEmitter, settleEmitter),
|
|
8225
|
+
attach(interaction, createdDriver, createdShell) {
|
|
8226
|
+
ctx = interaction;
|
|
8227
|
+
driver = createdDriver;
|
|
8228
|
+
shell = createdShell;
|
|
8229
|
+
render();
|
|
8230
|
+
onSession?.(session);
|
|
8231
|
+
}
|
|
8232
|
+
});
|
|
8233
|
+
return {
|
|
8234
|
+
promise: handle.promise,
|
|
8235
|
+
refreshPresentation: () => render(),
|
|
8236
|
+
get settled() {
|
|
8237
|
+
return handle.settled;
|
|
8238
|
+
},
|
|
8239
|
+
get usesGraphicStack() {
|
|
8240
|
+
return usesGraphicStack;
|
|
8241
|
+
},
|
|
8242
|
+
measureId: marker.id,
|
|
8243
|
+
graphicKind: "marker",
|
|
8244
|
+
abort: handle.abort,
|
|
8245
|
+
syncHostMembership(present) {
|
|
8246
|
+
if (handle.settled || usesGraphicStack === present) return;
|
|
8247
|
+
const previous = usesGraphicStack;
|
|
8248
|
+
usesGraphicStack = present;
|
|
8249
|
+
try {
|
|
8250
|
+
render();
|
|
8251
|
+
} catch (error) {
|
|
8252
|
+
usesGraphicStack = previous;
|
|
8253
|
+
throw error;
|
|
8254
|
+
}
|
|
8255
|
+
}
|
|
8256
|
+
};
|
|
8257
|
+
}
|
|
8258
|
+
//#endregion
|
|
7659
8259
|
//#region src/tactical-draw/graphic-stack-coordinator.ts
|
|
7660
8260
|
/**
|
|
7661
8261
|
* Combines host-owned Graphic order with live or settled render overrides.
|
|
@@ -7720,6 +8320,7 @@ var TacticalDraw = class {
|
|
|
7720
8320
|
offsetDragModifier;
|
|
7721
8321
|
pointSymbols;
|
|
7722
8322
|
images;
|
|
8323
|
+
markers;
|
|
7723
8324
|
snappingOptions;
|
|
7724
8325
|
resolveSnap;
|
|
7725
8326
|
graphicStack = new GraphicStackCoordinator();
|
|
@@ -7798,6 +8399,7 @@ var TacticalDraw = class {
|
|
|
7798
8399
|
*/
|
|
7799
8400
|
lastSeenPointSymbolGeneration;
|
|
7800
8401
|
lastSeenImageGeneration;
|
|
8402
|
+
lastSeenMarkerGeneration;
|
|
7801
8403
|
/**
|
|
7802
8404
|
* Ids of graphics currently carrying a passive selection-highlight outline
|
|
7803
8405
|
* ({@link setHighlightedGraphics}). Declarative set-replace, no session —
|
|
@@ -7806,6 +8408,8 @@ var TacticalDraw = class {
|
|
|
7806
8408
|
*/
|
|
7807
8409
|
highlightedIds = [];
|
|
7808
8410
|
pinBodies = /* @__PURE__ */ new WeakMap();
|
|
8411
|
+
/** Resolved marker icons, so pin, highlight and view rebuilds don't re-ask the host. */
|
|
8412
|
+
markerRenders = /* @__PURE__ */ new WeakMap();
|
|
7809
8413
|
pins = new PinPresentationStore();
|
|
7810
8414
|
unsubscribePins;
|
|
7811
8415
|
/**
|
|
@@ -7836,6 +8440,8 @@ var TacticalDraw = class {
|
|
|
7836
8440
|
this.images = options?.images;
|
|
7837
8441
|
this.lastSeenPointSymbolGeneration = this.pointSymbols?.generation;
|
|
7838
8442
|
this.lastSeenImageGeneration = this.images?.generation;
|
|
8443
|
+
this.markers = options?.markers;
|
|
8444
|
+
this.lastSeenMarkerGeneration = this.markers?.generation;
|
|
7839
8445
|
this.snappingOptions = options?.snapping;
|
|
7840
8446
|
this.resolveSnap = createSnapResolver(adapter, () => this.lastRenderedMeasures, () => this.snapGeometryFeatures, () => this.snappingOptions);
|
|
7841
8447
|
const owned = /* @__PURE__ */ new Set();
|
|
@@ -7892,9 +8498,18 @@ var TacticalDraw = class {
|
|
|
7892
8498
|
refreshActiveEditPresentation() {
|
|
7893
8499
|
if (this.activeEdit && "refreshPresentation" in this.activeEdit) this.activeEdit.refreshPresentation();
|
|
7894
8500
|
}
|
|
8501
|
+
/** The capability's icon for a marker snapshot, resolved once per snapshot. */
|
|
8502
|
+
markerRender(marker) {
|
|
8503
|
+
let render = this.markerRenders.get(marker);
|
|
8504
|
+
if (!render) {
|
|
8505
|
+
render = resolveMarkerRender(this.markers, marker);
|
|
8506
|
+
this.markerRenders.set(marker, render);
|
|
8507
|
+
}
|
|
8508
|
+
return render;
|
|
8509
|
+
}
|
|
7895
8510
|
/**
|
|
7896
|
-
* Whether a point symbol should render as a billboard pin rather
|
|
7897
|
-
* ordinary
|
|
8511
|
+
* Whether a point symbol or marker should render as a billboard pin rather
|
|
8512
|
+
* than an ordinary icon: its own presentation opts in, and the adapter
|
|
7898
8513
|
* currently supports rendering pins. Pass an already-resolved
|
|
7899
8514
|
* `presentation` to skip re-resolving it when a caller has one in hand.
|
|
7900
8515
|
*/
|
|
@@ -7939,7 +8554,7 @@ var TacticalDraw = class {
|
|
|
7939
8554
|
if (cached.dependence === "none") return cached.group;
|
|
7940
8555
|
if (cached.dependence === "resolution" && Object.is(cached.resolution, this.adapter.getResolution())) return cached.group;
|
|
7941
8556
|
}
|
|
7942
|
-
const presentation =
|
|
8557
|
+
const presentation = isPinnableGraphic(graphic) ? this.pins.resolve(graphic.id) : void 0;
|
|
7943
8558
|
const dependence = presentation && this.graphicUsesPinPresentation(graphic, presentation) ? "none" : graphicViewDependence(graphic, this.adapter.scalesGroundPointSymbolsNatively === true);
|
|
7944
8559
|
const resolution = dependence === "none" ? void 0 : this.adapter.getResolution();
|
|
7945
8560
|
const group = this.buildGraphicGroup(graphic, presentation);
|
|
@@ -7969,34 +8584,13 @@ var TacticalDraw = class {
|
|
|
7969
8584
|
}
|
|
7970
8585
|
});
|
|
7971
8586
|
this.pinBodies.set(graphic, body);
|
|
7972
|
-
|
|
7973
|
-
|
|
7974
|
-
|
|
7975
|
-
|
|
7976
|
-
|
|
7977
|
-
|
|
7978
|
-
|
|
7979
|
-
geometry: {
|
|
7980
|
-
type: "Point",
|
|
7981
|
-
coordinates: [...graphic.position]
|
|
7982
|
-
},
|
|
7983
|
-
properties: {
|
|
7984
|
-
graphicId: graphic.id,
|
|
7985
|
-
graphicKind: "point-symbol",
|
|
7986
|
-
pinPresentation: true
|
|
7987
|
-
}
|
|
7988
|
-
}],
|
|
7989
|
-
iconResources: [],
|
|
7990
|
-
pin: {
|
|
7991
|
-
id: graphic.id,
|
|
7992
|
-
position: graphic.position,
|
|
7993
|
-
resource,
|
|
7994
|
-
octagonSize: body.octagonSize,
|
|
7995
|
-
presentation,
|
|
7996
|
-
opacity: (graphic.style?.opacity ?? 1) * (graphic.style?.overallOpacity ?? 1),
|
|
7997
|
-
...graphic.graphicModifiers?.direction !== void 0 ? { direction: graphic.rotation + graphic.graphicModifiers.direction } : {}
|
|
7998
|
-
}
|
|
7999
|
-
};
|
|
8587
|
+
return pinGroup(graphic, revision, {
|
|
8588
|
+
resource: pointSymbolResource(body),
|
|
8589
|
+
octagonSize: body.octagonSize,
|
|
8590
|
+
presentation,
|
|
8591
|
+
opacity: (graphic.style?.opacity ?? 1) * (graphic.style?.overallOpacity ?? 1),
|
|
8592
|
+
...graphic.graphicModifiers?.direction !== void 0 ? { direction: graphic.rotation + graphic.graphicModifiers.direction } : {}
|
|
8593
|
+
});
|
|
8000
8594
|
}
|
|
8001
8595
|
const plan = renderPointSymbolForAdapter(this.adapter, this.pointSymbols, graphic);
|
|
8002
8596
|
return {
|
|
@@ -8017,6 +8611,23 @@ var TacticalDraw = class {
|
|
|
8017
8611
|
revision
|
|
8018
8612
|
};
|
|
8019
8613
|
}
|
|
8614
|
+
if (isMarker(graphic)) {
|
|
8615
|
+
if (!this.markers) throw new MarkerCapabilityRequiredError();
|
|
8616
|
+
const presentation = resolved ?? this.pins.resolve(graphic.id);
|
|
8617
|
+
const render = this.markerRender(graphic);
|
|
8618
|
+
if (this.graphicUsesPinPresentation(graphic, presentation)) return pinGroup(graphic, revision, {
|
|
8619
|
+
...markerPinBody(render),
|
|
8620
|
+
presentation,
|
|
8621
|
+
opacity: markerOpacity(graphic)
|
|
8622
|
+
});
|
|
8623
|
+
const plan = renderMarkerForAdapter(this.adapter, this.markers, graphic, render);
|
|
8624
|
+
return {
|
|
8625
|
+
id: graphic.id,
|
|
8626
|
+
features: plan.features,
|
|
8627
|
+
iconResources: [plan.resource],
|
|
8628
|
+
revision
|
|
8629
|
+
};
|
|
8630
|
+
}
|
|
8020
8631
|
const render = renderMeasureForAdapter(this.adapter, graphic, {
|
|
8021
8632
|
graphicsStyle: this.graphicsStyle,
|
|
8022
8633
|
symbolColors: this.symbolColors
|
|
@@ -8034,17 +8645,22 @@ var TacticalDraw = class {
|
|
|
8034
8645
|
* resolution-independent graphics remain cache hits.
|
|
8035
8646
|
*/
|
|
8036
8647
|
invalidateGraphicGroupCache(clearBodies = true) {
|
|
8037
|
-
if (clearBodies)
|
|
8648
|
+
if (clearBodies) {
|
|
8649
|
+
this.pinBodies = /* @__PURE__ */ new WeakMap();
|
|
8650
|
+
this.markerRenders = /* @__PURE__ */ new WeakMap();
|
|
8651
|
+
}
|
|
8038
8652
|
this.graphicGroupCache = /* @__PURE__ */ new WeakMap();
|
|
8039
8653
|
}
|
|
8040
8654
|
/** Refresh capability-dependent renders before any caller-visible state is mutated. */
|
|
8041
8655
|
refreshCapabilityGenerations() {
|
|
8042
8656
|
const currentPointSymbolGeneration = this.pointSymbols?.generation;
|
|
8043
8657
|
const currentImageGeneration = this.images?.generation;
|
|
8044
|
-
|
|
8658
|
+
const currentMarkerGeneration = this.markers?.generation;
|
|
8659
|
+
if (currentPointSymbolGeneration !== this.lastSeenPointSymbolGeneration || currentImageGeneration !== this.lastSeenImageGeneration || currentMarkerGeneration !== this.lastSeenMarkerGeneration) {
|
|
8045
8660
|
this.invalidateGraphicGroupCache();
|
|
8046
8661
|
this.lastSeenPointSymbolGeneration = currentPointSymbolGeneration;
|
|
8047
8662
|
this.lastSeenImageGeneration = currentImageGeneration;
|
|
8663
|
+
this.lastSeenMarkerGeneration = currentMarkerGeneration;
|
|
8048
8664
|
}
|
|
8049
8665
|
}
|
|
8050
8666
|
/** Submit one complete grouped desired state for the host stack plus overrides. */
|
|
@@ -8161,7 +8777,7 @@ var TacticalDraw = class {
|
|
|
8161
8777
|
seen.add(m.id);
|
|
8162
8778
|
}
|
|
8163
8779
|
this.refreshCapabilityGenerations();
|
|
8164
|
-
for (const graphic of measures) if (isImageGraphic(graphic)) this.renderGraphicGroup(graphic);
|
|
8780
|
+
for (const graphic of measures) if (isImageGraphic(graphic) || isMarker(graphic)) this.renderGraphicGroup(graphic);
|
|
8165
8781
|
const activeEdit = this.activeEdit;
|
|
8166
8782
|
const constructingSession = activeEdit ? null : this.activeInteraction.session;
|
|
8167
8783
|
const constructingGraphic = constructingSession && "workingGraphic" in constructingSession ? constructingSession.workingGraphic : void 0;
|
|
@@ -8251,7 +8867,7 @@ var TacticalDraw = class {
|
|
|
8251
8867
|
if (excluded.has(id)) continue;
|
|
8252
8868
|
const graphic = this.lastRenderedMeasuresById.get(id);
|
|
8253
8869
|
if (!graphic) continue;
|
|
8254
|
-
if (
|
|
8870
|
+
if (isPinnableGraphic(graphic)) {
|
|
8255
8871
|
const pin = this.renderGraphicGroup(graphic).pin;
|
|
8256
8872
|
if (pin) {
|
|
8257
8873
|
pinGroups.push({
|
|
@@ -8302,6 +8918,10 @@ var TacticalDraw = class {
|
|
|
8302
8918
|
if (!this.images) return null;
|
|
8303
8919
|
return imageFootprint(graphic, renderImageForAdapter(this.adapter, this.images, graphic).render, this.adapter)?.box ?? null;
|
|
8304
8920
|
}
|
|
8921
|
+
if (isMarker(graphic)) {
|
|
8922
|
+
if (!this.markers) return null;
|
|
8923
|
+
return markerFootprint(graphic, this.markerRender(graphic), this.adapter)?.box ?? null;
|
|
8924
|
+
}
|
|
8305
8925
|
const features = this.renderGraphicGroup(graphic).features;
|
|
8306
8926
|
if (graphic.kind === "text") return fitTextFootprintFromFeatures(features, (lonLat) => this.adapter.getPixelFromCoordinate(lonLat), {
|
|
8307
8927
|
resolution: this.adapter.getResolution(),
|
|
@@ -8413,6 +9033,21 @@ var TacticalDraw = class {
|
|
|
8413
9033
|
}
|
|
8414
9034
|
draw(draft, options) {
|
|
8415
9035
|
this.assertAlive();
|
|
9036
|
+
if (draft.kind === "marker") {
|
|
9037
|
+
if (!this.markers) throw new MarkerCapabilityRequiredError();
|
|
9038
|
+
const preempt = this.guardAndPreempt();
|
|
9039
|
+
if (preempt) return preempt;
|
|
9040
|
+
return this.runWithSlot((onSettled) => runMarkerDraw({
|
|
9041
|
+
adapter: this.adapter,
|
|
9042
|
+
capability: this.markers,
|
|
9043
|
+
draft,
|
|
9044
|
+
previewLayer: this.previewLayer,
|
|
9045
|
+
generateId: this.generateId,
|
|
9046
|
+
signal: options?.signal,
|
|
9047
|
+
onSettled,
|
|
9048
|
+
snap: this.resolveSnap
|
|
9049
|
+
}), null);
|
|
9050
|
+
}
|
|
8416
9051
|
if (draft.kind === "image") {
|
|
8417
9052
|
if (!this.images) throw new ImageCapabilityRequiredError();
|
|
8418
9053
|
const preempt = this.guardAndPreempt();
|
|
@@ -8502,6 +9137,47 @@ var TacticalDraw = class {
|
|
|
8502
9137
|
}
|
|
8503
9138
|
edit(measure, options) {
|
|
8504
9139
|
this.assertAlive();
|
|
9140
|
+
if (isMarker(measure)) {
|
|
9141
|
+
normaliseMarkerModes(options?.modes);
|
|
9142
|
+
if (!this.markers) throw new MarkerCapabilityRequiredError();
|
|
9143
|
+
const preempt = this.guardAndPreempt();
|
|
9144
|
+
if (preempt) return preempt;
|
|
9145
|
+
const wasOnGraphicsLayer = this.lastRenderedMeasures.some((g) => g.id === measure.id);
|
|
9146
|
+
const handleIdPrefix = `__td_edit_${++this.editCounter}__`;
|
|
9147
|
+
return this.runWithSlot((onSettled) => runMarkerEdit({
|
|
9148
|
+
adapter: this.adapter,
|
|
9149
|
+
capability: this.markers,
|
|
9150
|
+
marker: measure,
|
|
9151
|
+
...this.graphicUsesPinPresentation(measure) ? {
|
|
9152
|
+
renderPin: (marker) => this.buildGraphicGroup(marker),
|
|
9153
|
+
canRenderPin: () => this.graphicUsesPinPresentation(measure)
|
|
9154
|
+
} : {},
|
|
9155
|
+
graphicsLayer: this.graphicsLayer,
|
|
9156
|
+
previewLayer: this.previewLayer,
|
|
9157
|
+
handlesLayer: this.handlesLayer,
|
|
9158
|
+
signal: options?.signal,
|
|
9159
|
+
closeOnClickAway: options?.closeOnClickAway,
|
|
9160
|
+
modes: options?.modes,
|
|
9161
|
+
interactionStyle: this.resolveInteractionStyle(options?.interactionStyle),
|
|
9162
|
+
onSession: this.trackSession(options?.onSession),
|
|
9163
|
+
handleIdPrefix,
|
|
9164
|
+
settleToGraphics: (settled) => this.settleWorkingGraphics([{
|
|
9165
|
+
id: measure.id,
|
|
9166
|
+
committed: settled
|
|
9167
|
+
}]),
|
|
9168
|
+
publishWorkingGraphic: (group) => this.publishWorkingGraphics([group]),
|
|
9169
|
+
wasOnGraphicsLayer,
|
|
9170
|
+
onSettled,
|
|
9171
|
+
onClickAwayGraphicsPick: (event) => this.dispatchHostPick(this.graphicsLayer, event),
|
|
9172
|
+
snap: this.resolveSnap
|
|
9173
|
+
}), (handle) => {
|
|
9174
|
+
handle.syncHostMembership(this.lastRenderedMeasures.some((graphic) => graphic.id === handle.measureId && isMarker(graphic)));
|
|
9175
|
+
this.activeEdit = handle;
|
|
9176
|
+
return () => {
|
|
9177
|
+
if (this.activeEdit === handle) this.activeEdit = null;
|
|
9178
|
+
};
|
|
9179
|
+
});
|
|
9180
|
+
}
|
|
8505
9181
|
if (isImageGraphic(measure)) {
|
|
8506
9182
|
normaliseImageModes(options?.modes);
|
|
8507
9183
|
if (!this.images) throw new ImageCapabilityRequiredError();
|
|
@@ -8643,6 +9319,7 @@ var TacticalDraw = class {
|
|
|
8643
9319
|
}
|
|
8644
9320
|
if (measures.some(isPointSymbol) && !this.pointSymbols) throw new PointSymbolCapabilityRequiredError();
|
|
8645
9321
|
if (measures.some(isImageGraphic) && !this.images) throw new ImageCapabilityRequiredError();
|
|
9322
|
+
if (measures.some(isMarker) && !this.markers) throw new MarkerCapabilityRequiredError();
|
|
8646
9323
|
const preempt = this.guardAndPreempt();
|
|
8647
9324
|
if (preempt) return preempt;
|
|
8648
9325
|
const isOnGraphicsLayer = (id) => this.lastRenderedMeasures.some((m) => m.id === id);
|
|
@@ -8658,7 +9335,8 @@ var TacticalDraw = class {
|
|
|
8658
9335
|
adapter: this.adapter,
|
|
8659
9336
|
capability: this.pointSymbols,
|
|
8660
9337
|
imageCapability: this.images,
|
|
8661
|
-
|
|
9338
|
+
markerCapability: this.markers,
|
|
9339
|
+
...this.pointSymbols || this.markers ? { renderPin: (graphic) => this.buildGraphicGroup(graphic) } : {},
|
|
8662
9340
|
graphics: measures,
|
|
8663
9341
|
graphicsLayer: this.graphicsLayer,
|
|
8664
9342
|
previewLayer: this.previewLayer,
|
|
@@ -9037,6 +9715,35 @@ var TacticalDraw = class {
|
|
|
9037
9715
|
}
|
|
9038
9716
|
};
|
|
9039
9717
|
/**
|
|
9718
|
+
* The graphics-stack group for a pin-presented point symbol or marker
|
|
9719
|
+
* (ADR-0056): a pickable ground point plus the adapter-drawn billboard.
|
|
9720
|
+
*/
|
|
9721
|
+
function pinGroup(graphic, revision, pin) {
|
|
9722
|
+
return {
|
|
9723
|
+
id: graphic.id,
|
|
9724
|
+
revision,
|
|
9725
|
+
features: [{
|
|
9726
|
+
type: "Feature",
|
|
9727
|
+
id: `${graphic.id}:pin`,
|
|
9728
|
+
geometry: {
|
|
9729
|
+
type: "Point",
|
|
9730
|
+
coordinates: [...graphic.position]
|
|
9731
|
+
},
|
|
9732
|
+
properties: {
|
|
9733
|
+
graphicId: graphic.id,
|
|
9734
|
+
graphicKind: graphic.kind,
|
|
9735
|
+
pinPresentation: true
|
|
9736
|
+
}
|
|
9737
|
+
}],
|
|
9738
|
+
iconResources: [],
|
|
9739
|
+
pin: {
|
|
9740
|
+
id: graphic.id,
|
|
9741
|
+
position: graphic.position,
|
|
9742
|
+
...pin
|
|
9743
|
+
}
|
|
9744
|
+
};
|
|
9745
|
+
}
|
|
9746
|
+
/**
|
|
9040
9747
|
* Classify what live view state a graphic's render reads. Offset point symbols
|
|
9041
9748
|
* resolve their body and connector in pixel space, so they depend on the whole
|
|
9042
9749
|
* camera rather than on scale alone.
|
|
@@ -9047,6 +9754,7 @@ function graphicViewDependence(graphic, nativePointSymbolScaling) {
|
|
|
9047
9754
|
return graphic.size.unit === "meters" && !nativePointSymbolScaling ? "resolution" : "none";
|
|
9048
9755
|
}
|
|
9049
9756
|
if (isImageGraphic(graphic)) return "none";
|
|
9757
|
+
if (isMarker(graphic)) return markerScalesWithResolution(graphic, nativePointSymbolScaling) ? "resolution" : "none";
|
|
9050
9758
|
return measureRendersFromViewState(graphic) ? "resolution" : "none";
|
|
9051
9759
|
}
|
|
9052
9760
|
function normalisePointEditModes(modes) {
|
|
@@ -9431,4 +10139,4 @@ function nearestWorldCopyPosition(position, refLng) {
|
|
|
9431
10139
|
return [nearestWorldCopyLng(position[0], refLng), ...position.slice(1)];
|
|
9432
10140
|
}
|
|
9433
10141
|
//#endregion
|
|
9434
|
-
export { BaseMapAdapter, DEFAULT_LABEL_SIZE_PIXELS, DEFAULT_PIN_PRESENTATION, DEFAULT_TEXT_SIZE_MAX_PIXELS, DEFAULT_TEXT_SIZE_MIN_PIXELS, HATCH_PATTERNS, ImageCapabilityRequiredError, MINE_PATTERN_TILE_SIZE, PinPresentationStore, PointSymbolCapabilityRequiredError, PointerCallbackHub, TEXT_HALO_COLOR, TOUCH_HIT_TOLERANCE_PX, TacticalDraw, TacticalDrawAbortError, TacticalDrawDestroyedError, alignPointSymbolIndicator, bindAbortable, cloneImageGraphic, clonePointSymbol, coerceHandleStyle, combinePinScale, combineWithHostSignal, convertPointSymbolPlacement, effectivePointSymbolPixelSize, evaluatePickCandidates, fillPatternImageDimension, fillPatternImageId, getSizeAnchor, hitTestFeature, hitTestIconFeature, ignoreAbort, imageFootprint, imageOpacity, isAnchoredGraphic, isImageGraphic, isMinePattern, isPointSymbol, isTacticalDrawAbortError, isValidPinNumber, makeFillPatternImage, mergeNativeAndCachedPickFeatures, movePointSymbolLocation, nearestWorldCopyLng, nearestWorldCopyPosition, normalizeImageGraphic, parseColor, pickHitTolerance, pickPointerType, pinDistanceScale, pinZoomScale, placePointSymbol, pointSymbolFootprint, pointSymbolResource, renderOrderToVisualOrder, resizePointSymbolSize, resolveGroundTextSizePixels, resolvePickPresentation, resolvePinPresentation, resolvePointSymbolOffset, resolveTextHaloWidth, resolveTextSizePixels, scalePointSymbolLayout, tryControlMeasureIdFromFeature, validateImageGraphic };
|
|
10142
|
+
export { BaseMapAdapter, DEFAULT_LABEL_SIZE_PIXELS, DEFAULT_MARKER_SIZE, DEFAULT_PIN_PRESENTATION, DEFAULT_TEXT_SIZE_MAX_PIXELS, DEFAULT_TEXT_SIZE_MIN_PIXELS, HATCH_PATTERNS, ImageCapabilityRequiredError, MINE_PATTERN_TILE_SIZE, MarkerCapabilityRequiredError, PinPresentationStore, PointSymbolCapabilityRequiredError, PointerCallbackHub, TEXT_HALO_COLOR, TOUCH_HIT_TOLERANCE_PX, TacticalDraw, TacticalDrawAbortError, TacticalDrawDestroyedError, alignPointSymbolIndicator, bindAbortable, cloneImageGraphic, cloneMarker, clonePointSymbol, coerceHandleStyle, combinePinScale, combineWithHostSignal, convertPointSymbolPlacement, effectivePointSymbolPixelSize, evaluatePickCandidates, fillPatternImageDimension, fillPatternImageId, getSizeAnchor, hitTestFeature, hitTestIconFeature, ignoreAbort, imageFootprint, imageOpacity, isAnchoredGraphic, isImageGraphic, isMarker, isMinePattern, isPinnableGraphic, isPointSymbol, isTacticalDrawAbortError, isValidPinNumber, makeFillPatternImage, markerFootprint, markerOpacity, mergeNativeAndCachedPickFeatures, movePointSymbolLocation, nearestWorldCopyLng, nearestWorldCopyPosition, normalizeImageGraphic, normalizeMarker, parseColor, pickHitTolerance, pickPointerType, pinDistanceScale, pinZoomScale, placePointSymbol, pointSymbolFootprint, pointSymbolResource, renderOrderToVisualOrder, resizePointSymbolSize, resolveGroundTextSizePixels, resolveMarkerRender, resolvePickPresentation, resolvePinPresentation, resolvePointSymbolOffset, resolveTextHaloWidth, resolveTextSizePixels, scalePointSymbolLayout, tryControlMeasureIdFromFeature, validateImageGraphic, validateMarker };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orbat-mapper/tactical-draw",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Engine-agnostic draw/edit core for tactical control measures (MIL-STD-2525 / APP-6). The MapAdapter ABI and bring-your-own-engine entry point for the tactical-draw package family.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Orbat Mapper",
|