@orbat-mapper/control-measures 0.2.0-alpha.24 → 0.2.0-alpha.26

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.
@@ -721,6 +721,18 @@ interface ControlMeasureStyle {
721
721
  * cannot draw a pattern degrade to solid.
722
722
  */
723
723
  fillPattern?: FillPattern;
724
+ /**
725
+ * Display-time graphic opacity multiplier in `[0, 1]`; absent = fully
726
+ * opaque. Unlike `color`'s alpha, this fades the whole graphic — stroke,
727
+ * fill, patterns, and baked labels — as one knob, independent of the
728
+ * authored color. The resolver folds it into each resolved part's color
729
+ * alpha (`final alpha = opacity × color alpha`) rather than adding a new
730
+ * paint channel, so adapters and `toSimpleStyle` need no changes.
731
+ * Display-only: hit-testing and selection reason about color alpha, not
732
+ * this multiplier, so a graphic at `opacity: 0` stays fully selectable.
733
+ * Out-of-range values clamp to `[0, 1]`. See ADR-0040.
734
+ */
735
+ opacity?: number;
724
736
  }
725
737
  /**
726
738
  * How a filled part's interior is painted. See `ControlMeasureStyle.fillPattern`.
@@ -982,6 +994,10 @@ interface FeaturePartProps {
982
994
  textAnchor?: "start" | "end";
983
995
  /** Render an opaque light backdrop behind text placed over patterned geometry. */
984
996
  textBackground?: boolean;
997
+ /** Render a contrast-aware halo behind the glyphs so text stays legible on busy backgrounds. */
998
+ textHalo?: boolean;
999
+ /** Halo color contrasting with the resolved text color; present only when `textHalo` is set. */
1000
+ textHaloColor?: string;
985
1001
  /** Canonical field key for a text-amplifier label that may be repositioned. */
986
1002
  amplifierField?: TextAmplifierKey;
987
1003
  /** Stable key used to persist a user-adjusted anchor for any rendered label. */
@@ -1656,6 +1672,8 @@ interface GenericTextOptions {
1656
1672
  * @default 200
1657
1673
  */
1658
1674
  maxSizePixels?: number;
1675
+ /** Contrasting halo behind the glyphs so the text stays legible on busy backgrounds. @default false */
1676
+ halo?: boolean;
1659
1677
  }
1660
1678
  declare const DEFAULT_GENERIC_TEXT_OPTIONS: GenericTextOptions;
1661
1679
  declare function createGenericText(coordinates: Position[], options?: GenericTextOptions): FeatureCollection<Point, Record<string, unknown>>;
package/dist/index.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { $ as DEFAULT_OBSTACLE_BYPASS_DIFFICULT_OPTIONS, $n as DEFAULT_DIRECTION_OF_ATTACK_AVIATION_OPTIONS, $t as DEFAULT_SUPPORT_BY_FIRE_OPTIONS, A as roundToFixed, An as PickupZoneOptions, Ar as LabelPlacementOverride, At as DEFAULT_COVER_OPTIONS, B as cloneControlMeasure, Bn as EncirclementOptions, Bt as DEFAULT_BREACH_OPTIONS, C as BaselineFrame, Cn as DEFAULT_MAIN_ATTACK_OPTIONS, Cr as ControlMeasureMetadata, Ct as DEFAULT_SCREEN_OPTIONS, D as createBaselineFrame, Dn as AreaOfOperationsOptions, Dr as AmplifierPlacements, Dt as DEFAULT_DELAY_OPTIONS, E as BaselineFrameOrigin, En as computeInitialWidthPoint, Er as AmplifierPlacement, Et as GuardOptions, F as applyBoxTransformOptions, Fn as AssemblyAreaOptions, Fr as canonicalTextAmplifierKey, Ft as CanalizeOptions, G as ControlMeasureKind, Gn as StyleHints, Gt as DEFAULT_HANDOVER_LINE_OPTIONS, H as CONTROL_MEASURE_IDS, Hn as FinalProtectiveFireOptions, Ht as DEFAULT_BLOCK_MISSION_TASK_OPTIONS, I as freezeOrientationOptions, In as DEFAULT_ASSEMBLY_AREA_OPTIONS, Ir as normalizeTextAmplifiers, It as DEFAULT_CANALIZE_OPTIONS, J as getControlMeasureMetadataByValue, Jn as PrincipalDirectionOfFireOptions, Jt as PhaseLineOptions, K as OptionsByKind, Kn as controlMeasureIdFromFeature, Kt as HandoverLineOptions, L as RenderOptions, Ln as AreaDefenseOptions, Lr as resolveAmplifierPlacement, Lt as BypassOptions, M as SimpleStyleRender, Mn as LandingZoneOptions, Mr as TextAmplifierField, Mt as TacticalArrowOptions, N as toSimpleStyle, Nn as DEFAULT_JOINT_TACTICAL_ACTION_AREA_OPTIONS, Nr as TextAmplifierKey, Nt as ClearOptions, O as EPSILON, On as DEFAULT_AREA_OF_OPERATIONS_OPTIONS, Or as CanonicalTextAmplifiers, Ot as DelayOptions, P as resolveStyleHints, Pn as JointTacticalActionAreaOptions, Pr as TextAmplifiers, Pt as DEFAULT_CLEAR_OPTIONS, Q as ObstacleBypassImpossibleOptions, Qn as DirectionOfMainAttackOptions, Qt as DEFAULT_ATTACK_BY_FIRE_OPTIONS, R as renderControlMeasure, Rn as DEFAULT_AREA_DEFENSE_OPTIONS, Rr as AnchorTransformEvent, Rt as DEFAULT_BYPASS_OPTIONS, S as snapToMidpointPerpendicular, Sn as SupportingAttackOptions, Sr as ControlMeasureGeometryType, St as DEFAULT_ANTITANK_DITCH_OPTIONS, T as BaselineFrameOptions, Tn as calculateMetrics, Tr as TextAmplifierDescriptor, Tt as DEFAULT_GUARD_OPTIONS, U as CONTROL_MEASURE_METADATA, Un as ControlMeasureRender, Ut as BattleHandoverLineOptions, V as isKind, Vn as DEFAULT_FINAL_PROTECTIVE_FIRE_OPTIONS, Vt as BlockMissionTaskOptions, W as ControlMeasureId, Wn as FeaturePartProps, Wt as DEFAULT_BATTLE_HANDOVER_LINE_OPTIONS, X as listControlMeasureMetadata, Xn as DirectionOfSupportingAttackOptions, Xt as FLOTOptions, Y as getDefaultOptions, Yn as DEFAULT_DIRECTION_OF_SUPPORTING_ATTACK_OPTIONS, Yt as DEFAULT_FLOT_OPTIONS, Z as DEFAULT_OBSTACLE_BYPASS_IMPOSSIBLE_OPTIONS, Zn as DEFAULT_DIRECTION_OF_MAIN_ATTACK_OPTIONS, Zt as AttackByFireOptions, _ as MidpointPerpendicularDrawRuleOptions, _n as DEFAULT_BLOCK_ARROW_OPTIONS, _r as unproject, _t as DEFAULT_FORTIFIED_LINE_OPTIONS, a as supportByFireDrawRule, an as DEFAULT_GENERIC_TEXT_OPTIONS, ar as ControlMeasureStyle, at as DEFAULT_FIX_OPTIONS, b as getMidpointPerpendicularSignedDistance, bn as DEFAULT_CLASSIC_ARROW_OPTIONS, br as BoxTransformDelta, bt as DEFAULT_ANTITANK_WALL_OPTIONS, c as line23DrawRule, cn as GenericCircleOptions, cr as GenericC2LineOptions, ct as DisruptOptions, d as ambushDrawRule, dn as DEFAULT_GENERIC_POLYGON_OPTIONS, dr as DEFAULT_LIGHT_LINE_OPTIONS, dt as DEFAULT_TURNING_MOVEMENT_OPTIONS, en as SupportByFireOptions, er as DirectionOfAttackAviationOptions, et as ObstacleBypassDifficultOptions, f as attackByFireDrawRule, fn as GenericPolygonOptions, fr as LightLineOptions, ft as TurningMovementOptions, g as blockDrawRule, gn as BlockArrowOptions, gr as project, gt as FortifiedAreaOptions, h as disruptDrawRule, hn as BlockArrowHeadStyle, hr as haversineDistance, ht as DEFAULT_FORTIFIED_AREA_OPTIONS, i as axis1DrawRule, in as DEFAULT_AIRBORNE_ATTACK_OPTIONS, ir as DEFAULT_BATTLE_POSITION_OPTIONS, it as TurnOptions, j as SimpleStyleProps, jn as DEFAULT_LANDING_ZONE_OPTIONS, jr as TEXT_AMPLIFIER_FIELDS, jt as DEFAULT_TACTICAL_ARROW_OPTIONS, k as getMetersPerPixel, kn as DEFAULT_PICKUP_ZONE_OPTIONS, kr as GeneratedLabelKey, kt as CoverOptions, l as turnDrawRule, ln as DEFAULT_GENERIC_RECTANGLE_OPTIONS, lr as DEFAULT_ENGINEER_WORK_LINE_OPTIONS, lt as BlockOptions, m as centerRadiusDrawRule, mn as GenericLineOptions, mr as Point2D, mt as FrontalAttackOptions, n as DEFAULT_AMBUSH_OPTIONS, nn as DEFAULT_ATTACK_HELICOPTER_OPTIONS, nr as StrongPointOptions, nt as ObstacleBypassEasyOptions, o as line26DrawRule, on as GenericTextOptions, or as FillPattern, ot as FixOptions, p as point12DrawRule, pn as DEFAULT_GENERIC_LINE_OPTIONS, pr as LabelSizeOptions, pt as DEFAULT_FRONTAL_ATTACK_OPTIONS, q as getControlMeasureMetadata, qn as DEFAULT_PRINCIPAL_DIRECTION_OF_FIRE_OPTIONS, qt as DEFAULT_PHASE_LINE_OPTIONS, r as rectangleDrawRule, rn as AirborneAttackOptions, rr as BattlePositionOptions, rt as DEFAULT_TURN_OPTIONS, s as line24DrawRule, sn as DEFAULT_GENERIC_CIRCLE_OPTIONS, sr as DEFAULT_GENERIC_C2_LINE_OPTIONS, st as DEFAULT_DISRUPT_OPTIONS, t as AmbushOptions, tn as AttackHelicopterOptions, tr as DEFAULT_STRONG_POINT_OPTIONS, tt as DEFAULT_OBSTACLE_BYPASS_EASY_OPTIONS, u as line1DrawRule, un as GenericRectangleOptions, ur as EngineerWorkLineOptions, ut as DEFAULT_BLOCK_OPTIONS, v as computeDefaultMidpointPerpendicularPoint, vn as ClassicArrowHeadStyle, vr as BoundaryOptions, vt as FortifiedLineOptions, w as BaselineFrameNormal, wn as MainAttackOptions, wr as ParamDescriptor, wt as ScreenOptions, x as pointOnMidpointPerpendicularAxis, xn as DEFAULT_SUPPORTING_ATTACK_OPTIONS, xr as ControlMeasureGeometry, xt as AntitankDitchOptions, y as createMidpointPerpendicularDrawRule, yn as ClassicArrowOptions, yr as DEFAULT_BOUNDARY_OPTIONS, yt as AntitankWallOptions, z as ControlMeasure, zn as DEFAULT_ENCIRCLEMENT_OPTIONS, zr as ControlMeasureDrawRule, zt as BreachOptions } from "./index-Nf6JP0Tz.mjs";
1
+ import { $ as DEFAULT_OBSTACLE_BYPASS_DIFFICULT_OPTIONS, $n as DEFAULT_DIRECTION_OF_ATTACK_AVIATION_OPTIONS, $t as DEFAULT_SUPPORT_BY_FIRE_OPTIONS, A as roundToFixed, An as PickupZoneOptions, Ar as LabelPlacementOverride, At as DEFAULT_COVER_OPTIONS, B as cloneControlMeasure, Bn as EncirclementOptions, Bt as DEFAULT_BREACH_OPTIONS, C as BaselineFrame, Cn as DEFAULT_MAIN_ATTACK_OPTIONS, Cr as ControlMeasureMetadata, Ct as DEFAULT_SCREEN_OPTIONS, D as createBaselineFrame, Dn as AreaOfOperationsOptions, Dr as AmplifierPlacements, Dt as DEFAULT_DELAY_OPTIONS, E as BaselineFrameOrigin, En as computeInitialWidthPoint, Er as AmplifierPlacement, Et as GuardOptions, F as applyBoxTransformOptions, Fn as AssemblyAreaOptions, Fr as canonicalTextAmplifierKey, Ft as CanalizeOptions, G as ControlMeasureKind, Gn as StyleHints, Gt as DEFAULT_HANDOVER_LINE_OPTIONS, H as CONTROL_MEASURE_IDS, Hn as FinalProtectiveFireOptions, Ht as DEFAULT_BLOCK_MISSION_TASK_OPTIONS, I as freezeOrientationOptions, In as DEFAULT_ASSEMBLY_AREA_OPTIONS, Ir as normalizeTextAmplifiers, It as DEFAULT_CANALIZE_OPTIONS, J as getControlMeasureMetadataByValue, Jn as PrincipalDirectionOfFireOptions, Jt as PhaseLineOptions, K as OptionsByKind, Kn as controlMeasureIdFromFeature, Kt as HandoverLineOptions, L as RenderOptions, Ln as AreaDefenseOptions, Lr as resolveAmplifierPlacement, Lt as BypassOptions, M as SimpleStyleRender, Mn as LandingZoneOptions, Mr as TextAmplifierField, Mt as TacticalArrowOptions, N as toSimpleStyle, Nn as DEFAULT_JOINT_TACTICAL_ACTION_AREA_OPTIONS, Nr as TextAmplifierKey, Nt as ClearOptions, O as EPSILON, On as DEFAULT_AREA_OF_OPERATIONS_OPTIONS, Or as CanonicalTextAmplifiers, Ot as DelayOptions, P as resolveStyleHints, Pn as JointTacticalActionAreaOptions, Pr as TextAmplifiers, Pt as DEFAULT_CLEAR_OPTIONS, Q as ObstacleBypassImpossibleOptions, Qn as DirectionOfMainAttackOptions, Qt as DEFAULT_ATTACK_BY_FIRE_OPTIONS, R as renderControlMeasure, Rn as DEFAULT_AREA_DEFENSE_OPTIONS, Rr as AnchorTransformEvent, Rt as DEFAULT_BYPASS_OPTIONS, S as snapToMidpointPerpendicular, Sn as SupportingAttackOptions, Sr as ControlMeasureGeometryType, St as DEFAULT_ANTITANK_DITCH_OPTIONS, T as BaselineFrameOptions, Tn as calculateMetrics, Tr as TextAmplifierDescriptor, Tt as DEFAULT_GUARD_OPTIONS, U as CONTROL_MEASURE_METADATA, Un as ControlMeasureRender, Ut as BattleHandoverLineOptions, V as isKind, Vn as DEFAULT_FINAL_PROTECTIVE_FIRE_OPTIONS, Vt as BlockMissionTaskOptions, W as ControlMeasureId, Wn as FeaturePartProps, Wt as DEFAULT_BATTLE_HANDOVER_LINE_OPTIONS, X as listControlMeasureMetadata, Xn as DirectionOfSupportingAttackOptions, Xt as FLOTOptions, Y as getDefaultOptions, Yn as DEFAULT_DIRECTION_OF_SUPPORTING_ATTACK_OPTIONS, Yt as DEFAULT_FLOT_OPTIONS, Z as DEFAULT_OBSTACLE_BYPASS_IMPOSSIBLE_OPTIONS, Zn as DEFAULT_DIRECTION_OF_MAIN_ATTACK_OPTIONS, Zt as AttackByFireOptions, _ as MidpointPerpendicularDrawRuleOptions, _n as DEFAULT_BLOCK_ARROW_OPTIONS, _r as unproject, _t as DEFAULT_FORTIFIED_LINE_OPTIONS, a as supportByFireDrawRule, an as DEFAULT_GENERIC_TEXT_OPTIONS, ar as ControlMeasureStyle, at as DEFAULT_FIX_OPTIONS, b as getMidpointPerpendicularSignedDistance, bn as DEFAULT_CLASSIC_ARROW_OPTIONS, br as BoxTransformDelta, bt as DEFAULT_ANTITANK_WALL_OPTIONS, c as line23DrawRule, cn as GenericCircleOptions, cr as GenericC2LineOptions, ct as DisruptOptions, d as ambushDrawRule, dn as DEFAULT_GENERIC_POLYGON_OPTIONS, dr as DEFAULT_LIGHT_LINE_OPTIONS, dt as DEFAULT_TURNING_MOVEMENT_OPTIONS, en as SupportByFireOptions, er as DirectionOfAttackAviationOptions, et as ObstacleBypassDifficultOptions, f as attackByFireDrawRule, fn as GenericPolygonOptions, fr as LightLineOptions, ft as TurningMovementOptions, g as blockDrawRule, gn as BlockArrowOptions, gr as project, gt as FortifiedAreaOptions, h as disruptDrawRule, hn as BlockArrowHeadStyle, hr as haversineDistance, ht as DEFAULT_FORTIFIED_AREA_OPTIONS, i as axis1DrawRule, in as DEFAULT_AIRBORNE_ATTACK_OPTIONS, ir as DEFAULT_BATTLE_POSITION_OPTIONS, it as TurnOptions, j as SimpleStyleProps, jn as DEFAULT_LANDING_ZONE_OPTIONS, jr as TEXT_AMPLIFIER_FIELDS, jt as DEFAULT_TACTICAL_ARROW_OPTIONS, k as getMetersPerPixel, kn as DEFAULT_PICKUP_ZONE_OPTIONS, kr as GeneratedLabelKey, kt as CoverOptions, l as turnDrawRule, ln as DEFAULT_GENERIC_RECTANGLE_OPTIONS, lr as DEFAULT_ENGINEER_WORK_LINE_OPTIONS, lt as BlockOptions, m as centerRadiusDrawRule, mn as GenericLineOptions, mr as Point2D, mt as FrontalAttackOptions, n as DEFAULT_AMBUSH_OPTIONS, nn as DEFAULT_ATTACK_HELICOPTER_OPTIONS, nr as StrongPointOptions, nt as ObstacleBypassEasyOptions, o as line26DrawRule, on as GenericTextOptions, or as FillPattern, ot as FixOptions, p as point12DrawRule, pn as DEFAULT_GENERIC_LINE_OPTIONS, pr as LabelSizeOptions, pt as DEFAULT_FRONTAL_ATTACK_OPTIONS, q as getControlMeasureMetadata, qn as DEFAULT_PRINCIPAL_DIRECTION_OF_FIRE_OPTIONS, qt as DEFAULT_PHASE_LINE_OPTIONS, r as rectangleDrawRule, rn as AirborneAttackOptions, rr as BattlePositionOptions, rt as DEFAULT_TURN_OPTIONS, s as line24DrawRule, sn as DEFAULT_GENERIC_CIRCLE_OPTIONS, sr as DEFAULT_GENERIC_C2_LINE_OPTIONS, st as DEFAULT_DISRUPT_OPTIONS, t as AmbushOptions, tn as AttackHelicopterOptions, tr as DEFAULT_STRONG_POINT_OPTIONS, tt as DEFAULT_OBSTACLE_BYPASS_EASY_OPTIONS, u as line1DrawRule, un as GenericRectangleOptions, ur as EngineerWorkLineOptions, ut as DEFAULT_BLOCK_OPTIONS, v as computeDefaultMidpointPerpendicularPoint, vn as ClassicArrowHeadStyle, vr as BoundaryOptions, vt as FortifiedLineOptions, w as BaselineFrameNormal, wn as MainAttackOptions, wr as ParamDescriptor, wt as ScreenOptions, x as pointOnMidpointPerpendicularAxis, xn as DEFAULT_SUPPORTING_ATTACK_OPTIONS, xr as ControlMeasureGeometry, xt as AntitankDitchOptions, y as createMidpointPerpendicularDrawRule, yn as ClassicArrowOptions, yr as DEFAULT_BOUNDARY_OPTIONS, yt as AntitankWallOptions, z as ControlMeasure, zn as DEFAULT_ENCIRCLEMENT_OPTIONS, zr as ControlMeasureDrawRule, zt as BreachOptions } from "./index-BxApuW__.mjs";
2
2
  export { type AirborneAttackOptions, type AmbushOptions, type AmplifierPlacement, type AmplifierPlacements, type AnchorTransformEvent, type AntitankDitchOptions, type AntitankWallOptions, type AreaDefenseOptions, type AreaOfOperationsOptions, type AssemblyAreaOptions, type AttackByFireOptions, type AttackHelicopterOptions, type BaselineFrame, type BaselineFrameNormal, type BaselineFrameOptions, type BaselineFrameOrigin, type BattleHandoverLineOptions, type BattlePositionOptions, type BlockArrowHeadStyle, type BlockArrowOptions, type BlockMissionTaskOptions, type BlockOptions, type BoundaryOptions, type BoxTransformDelta, type BreachOptions, type BypassOptions, CONTROL_MEASURE_IDS, CONTROL_MEASURE_METADATA, type CanalizeOptions, type CanonicalTextAmplifiers, type ClassicArrowHeadStyle, type ClassicArrowOptions, type ClearOptions, type ControlMeasure, type ControlMeasureDrawRule, type ControlMeasureGeometry, type ControlMeasureGeometryType, type ControlMeasureId, type ControlMeasureKind, type ControlMeasureMetadata, type ControlMeasureRender, type ControlMeasureStyle, type CoverOptions, DEFAULT_AIRBORNE_ATTACK_OPTIONS, DEFAULT_AMBUSH_OPTIONS, DEFAULT_ANTITANK_DITCH_OPTIONS, DEFAULT_ANTITANK_WALL_OPTIONS, DEFAULT_AREA_DEFENSE_OPTIONS, DEFAULT_AREA_OF_OPERATIONS_OPTIONS, DEFAULT_ASSEMBLY_AREA_OPTIONS, DEFAULT_ATTACK_BY_FIRE_OPTIONS, DEFAULT_ATTACK_HELICOPTER_OPTIONS, DEFAULT_BATTLE_HANDOVER_LINE_OPTIONS, DEFAULT_BATTLE_POSITION_OPTIONS, DEFAULT_BLOCK_ARROW_OPTIONS, DEFAULT_BLOCK_MISSION_TASK_OPTIONS, DEFAULT_BLOCK_OPTIONS, DEFAULT_BOUNDARY_OPTIONS, DEFAULT_BREACH_OPTIONS, DEFAULT_BYPASS_OPTIONS, DEFAULT_CANALIZE_OPTIONS, DEFAULT_CLASSIC_ARROW_OPTIONS, DEFAULT_CLEAR_OPTIONS, DEFAULT_COVER_OPTIONS, DEFAULT_DELAY_OPTIONS, DEFAULT_DIRECTION_OF_ATTACK_AVIATION_OPTIONS, DEFAULT_DIRECTION_OF_MAIN_ATTACK_OPTIONS, DEFAULT_DIRECTION_OF_SUPPORTING_ATTACK_OPTIONS, DEFAULT_DISRUPT_OPTIONS, DEFAULT_ENCIRCLEMENT_OPTIONS, DEFAULT_ENGINEER_WORK_LINE_OPTIONS, DEFAULT_FINAL_PROTECTIVE_FIRE_OPTIONS, DEFAULT_FIX_OPTIONS, DEFAULT_FLOT_OPTIONS, DEFAULT_FORTIFIED_AREA_OPTIONS, DEFAULT_FORTIFIED_LINE_OPTIONS, DEFAULT_FRONTAL_ATTACK_OPTIONS, DEFAULT_GENERIC_C2_LINE_OPTIONS, DEFAULT_GENERIC_CIRCLE_OPTIONS, DEFAULT_GENERIC_LINE_OPTIONS, DEFAULT_GENERIC_POLYGON_OPTIONS, DEFAULT_GENERIC_RECTANGLE_OPTIONS, DEFAULT_GENERIC_TEXT_OPTIONS, DEFAULT_GUARD_OPTIONS, DEFAULT_HANDOVER_LINE_OPTIONS, DEFAULT_JOINT_TACTICAL_ACTION_AREA_OPTIONS, DEFAULT_LANDING_ZONE_OPTIONS, DEFAULT_LIGHT_LINE_OPTIONS, DEFAULT_MAIN_ATTACK_OPTIONS, DEFAULT_OBSTACLE_BYPASS_DIFFICULT_OPTIONS, DEFAULT_OBSTACLE_BYPASS_EASY_OPTIONS, DEFAULT_OBSTACLE_BYPASS_IMPOSSIBLE_OPTIONS, DEFAULT_PHASE_LINE_OPTIONS, DEFAULT_PICKUP_ZONE_OPTIONS, DEFAULT_PRINCIPAL_DIRECTION_OF_FIRE_OPTIONS, DEFAULT_SCREEN_OPTIONS, DEFAULT_STRONG_POINT_OPTIONS, DEFAULT_SUPPORTING_ATTACK_OPTIONS, DEFAULT_SUPPORT_BY_FIRE_OPTIONS, DEFAULT_TACTICAL_ARROW_OPTIONS, DEFAULT_TURNING_MOVEMENT_OPTIONS, DEFAULT_TURN_OPTIONS, type DelayOptions, type DirectionOfAttackAviationOptions, type DirectionOfMainAttackOptions, type DirectionOfSupportingAttackOptions, type DisruptOptions, EPSILON, type EncirclementOptions, type EngineerWorkLineOptions, type FLOTOptions, type FeaturePartProps, type FillPattern, type FinalProtectiveFireOptions, type FixOptions, type FortifiedAreaOptions, type FortifiedLineOptions, type FrontalAttackOptions, type GeneratedLabelKey, type GenericC2LineOptions, type GenericCircleOptions, type GenericLineOptions, type GenericPolygonOptions, type GenericRectangleOptions, type GenericTextOptions, type GuardOptions, type HandoverLineOptions, type JointTacticalActionAreaOptions, type LabelPlacementOverride, type LabelSizeOptions, type LandingZoneOptions, type LightLineOptions, type MainAttackOptions, type MidpointPerpendicularDrawRuleOptions, type ObstacleBypassDifficultOptions, type ObstacleBypassEasyOptions, type ObstacleBypassImpossibleOptions, type OptionsByKind, type ParamDescriptor, type PhaseLineOptions, type PickupZoneOptions, type Point2D, type PrincipalDirectionOfFireOptions, type RenderOptions, type ScreenOptions, type SimpleStyleProps, type SimpleStyleRender, type StrongPointOptions, type StyleHints, type SupportByFireOptions, type SupportingAttackOptions, TEXT_AMPLIFIER_FIELDS, type TacticalArrowOptions, type TextAmplifierDescriptor, type TextAmplifierField, type TextAmplifierKey, type TextAmplifiers, type TurnOptions, type TurningMovementOptions, ambushDrawRule, applyBoxTransformOptions, attackByFireDrawRule, axis1DrawRule, blockDrawRule, calculateMetrics, canonicalTextAmplifierKey, centerRadiusDrawRule, cloneControlMeasure, computeDefaultMidpointPerpendicularPoint, computeInitialWidthPoint, controlMeasureIdFromFeature, createBaselineFrame, createMidpointPerpendicularDrawRule, disruptDrawRule, freezeOrientationOptions, getControlMeasureMetadata, getControlMeasureMetadataByValue, getDefaultOptions, getMetersPerPixel, getMidpointPerpendicularSignedDistance, haversineDistance, isKind, line1DrawRule, line23DrawRule, line24DrawRule, line26DrawRule, listControlMeasureMetadata, normalizeTextAmplifiers, point12DrawRule, pointOnMidpointPerpendicularAxis, project, rectangleDrawRule, renderControlMeasure, resolveAmplifierPlacement, resolveStyleHints, roundToFixed, snapToMidpointPerpendicular, supportByFireDrawRule, toSimpleStyle, turnDrawRule, unproject };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as DEFAULT_BOUNDARY_OPTIONS, A as DEFAULT_FLOT_OPTIONS, At as centerRadiusDrawRule, B as DEFAULT_GENERIC_TEXT_OPTIONS, Bt as computeInitialWidthPoint, C as DEFAULT_SCREEN_OPTIONS, Ct as line24DrawRule, D as DEFAULT_BATTLE_HANDOVER_LINE_OPTIONS, Dt as ambushDrawRule, E as DEFAULT_FORTIFIED_LINE_OPTIONS, Et as line1DrawRule, F as DEFAULT_GUARD_OPTIONS, Ft as getMidpointPerpendicularSignedDistance, G as DEFAULT_CLASSIC_ARROW_OPTIONS, Gt as getMetersPerPixel, H as DEFAULT_GENERIC_POLYGON_OPTIONS, Ht as project, I as DEFAULT_DELAY_OPTIONS, It as pointOnMidpointPerpendicularAxis, J as DEFAULT_BREACH_OPTIONS, K as DEFAULT_CANALIZE_OPTIONS, Kt as roundToFixed, L as DEFAULT_COVER_OPTIONS, Lt as snapToMidpointPerpendicular, M as DEFAULT_FINAL_PROTECTIVE_FIRE_OPTIONS, Mt as blockDrawRule, N as DEFAULT_ENCIRCLEMENT_OPTIONS, Nt as computeDefaultMidpointPerpendicularPoint, O as DEFAULT_HANDOVER_LINE_OPTIONS, Ot as attackByFireDrawRule, P as DEFAULT_DISRUPT_OPTIONS, Pt as createMidpointPerpendicularDrawRule, Q as DEFAULT_LIGHT_LINE_OPTIONS, R as DEFAULT_TACTICAL_ARROW_OPTIONS, Rt as createBaselineFrame, S as DEFAULT_JOINT_TACTICAL_ACTION_AREA_OPTIONS, St as line26DrawRule, T as DEFAULT_FORTIFIED_AREA_OPTIONS, Tt as turnDrawRule, U as DEFAULT_GENERIC_LINE_OPTIONS, Ut as unproject, V as DEFAULT_GENERIC_RECTANGLE_OPTIONS, Vt as haversineDistance, W as DEFAULT_GENERIC_CIRCLE_OPTIONS, Wt as EPSILON, X as DEFAULT_GENERIC_C2_LINE_OPTIONS, Y as DEFAULT_BLOCK_MISSION_TASK_OPTIONS, Z as DEFAULT_ENGINEER_WORK_LINE_OPTIONS, _ as DEFAULT_OBSTACLE_BYPASS_IMPOSSIBLE_OPTIONS, _t as DEFAULT_AMBUSH_OPTIONS, a as DEFINITIONS, at as DEFAULT_ANTITANK_WALL_OPTIONS, b as DEFAULT_MAIN_ATTACK_OPTIONS, bt as axis1DrawRule, c as getDefaultOptions, ct as DEFAULT_AREA_OF_OPERATIONS_OPTIONS, d as DEFAULT_TURN_OPTIONS, dt as canonicalTextAmplifierKey, et as DEFAULT_BLOCK_ARROW_OPTIONS, f as DEFAULT_SUPPORTING_ATTACK_OPTIONS, ft as normalizeTextAmplifiers, g as DEFAULT_PICKUP_ZONE_OPTIONS, gt as DEFAULT_DIRECTION_OF_ATTACK_AVIATION_OPTIONS, h as DEFAULT_PRINCIPAL_DIRECTION_OF_FIRE_OPTIONS, ht as DEFAULT_DIRECTION_OF_MAIN_ATTACK_OPTIONS, i as CONTROL_MEASURE_METADATA, it as DEFAULT_ATTACK_BY_FIRE_OPTIONS, j as DEFAULT_FIX_OPTIONS, jt as disruptDrawRule, k as DEFAULT_PHASE_LINE_OPTIONS, kt as point12DrawRule, l as listControlMeasureMetadata, lt as DEFAULT_AREA_DEFENSE_OPTIONS, m as DEFAULT_STRONG_POINT_OPTIONS, mt as DEFAULT_DIRECTION_OF_SUPPORTING_ATTACK_OPTIONS, n as resolveStyleHints, nt as DEFAULT_BATTLE_POSITION_OPTIONS, o as getControlMeasureMetadata, ot as DEFAULT_ANTITANK_DITCH_OPTIONS, p as DEFAULT_SUPPORT_BY_FIRE_OPTIONS, pt as resolveAmplifierPlacement, q as DEFAULT_BYPASS_OPTIONS, r as CONTROL_MEASURE_IDS, rt as DEFAULT_ATTACK_HELICOPTER_OPTIONS, s as getControlMeasureMetadataByValue, st as DEFAULT_ASSEMBLY_AREA_OPTIONS, t as renderControlMeasure, tt as DEFAULT_BLOCK_OPTIONS, u as DEFAULT_TURNING_MOVEMENT_OPTIONS, ut as TEXT_AMPLIFIER_FIELDS, v as DEFAULT_OBSTACLE_BYPASS_EASY_OPTIONS, vt as DEFAULT_AIRBORNE_ATTACK_OPTIONS, w as DEFAULT_FRONTAL_ATTACK_OPTIONS, wt as line23DrawRule, x as DEFAULT_LANDING_ZONE_OPTIONS, xt as supportByFireDrawRule, y as DEFAULT_OBSTACLE_BYPASS_DIFFICULT_OPTIONS, yt as rectangleDrawRule, z as DEFAULT_CLEAR_OPTIONS, zt as calculateMetrics } from "./renderControlMeasure-TWiLtFXu.mjs";
1
+ import { $ as DEFAULT_BOUNDARY_OPTIONS, A as DEFAULT_FLOT_OPTIONS, At as centerRadiusDrawRule, B as DEFAULT_GENERIC_TEXT_OPTIONS, Bt as computeInitialWidthPoint, C as DEFAULT_SCREEN_OPTIONS, Ct as line24DrawRule, D as DEFAULT_BATTLE_HANDOVER_LINE_OPTIONS, Dt as ambushDrawRule, E as DEFAULT_FORTIFIED_LINE_OPTIONS, Et as line1DrawRule, F as DEFAULT_GUARD_OPTIONS, Ft as getMidpointPerpendicularSignedDistance, G as DEFAULT_CLASSIC_ARROW_OPTIONS, Gt as getMetersPerPixel, H as DEFAULT_GENERIC_POLYGON_OPTIONS, Ht as project, I as DEFAULT_DELAY_OPTIONS, It as pointOnMidpointPerpendicularAxis, J as DEFAULT_BREACH_OPTIONS, K as DEFAULT_CANALIZE_OPTIONS, Kt as roundToFixed, L as DEFAULT_COVER_OPTIONS, Lt as snapToMidpointPerpendicular, M as DEFAULT_FINAL_PROTECTIVE_FIRE_OPTIONS, Mt as blockDrawRule, N as DEFAULT_ENCIRCLEMENT_OPTIONS, Nt as computeDefaultMidpointPerpendicularPoint, O as DEFAULT_HANDOVER_LINE_OPTIONS, Ot as attackByFireDrawRule, P as DEFAULT_DISRUPT_OPTIONS, Pt as createMidpointPerpendicularDrawRule, Q as DEFAULT_LIGHT_LINE_OPTIONS, R as DEFAULT_TACTICAL_ARROW_OPTIONS, Rt as createBaselineFrame, S as DEFAULT_JOINT_TACTICAL_ACTION_AREA_OPTIONS, St as line26DrawRule, T as DEFAULT_FORTIFIED_AREA_OPTIONS, Tt as turnDrawRule, U as DEFAULT_GENERIC_LINE_OPTIONS, Ut as unproject, V as DEFAULT_GENERIC_RECTANGLE_OPTIONS, Vt as haversineDistance, W as DEFAULT_GENERIC_CIRCLE_OPTIONS, Wt as EPSILON, X as DEFAULT_GENERIC_C2_LINE_OPTIONS, Y as DEFAULT_BLOCK_MISSION_TASK_OPTIONS, Z as DEFAULT_ENGINEER_WORK_LINE_OPTIONS, _ as DEFAULT_OBSTACLE_BYPASS_IMPOSSIBLE_OPTIONS, _t as DEFAULT_AMBUSH_OPTIONS, a as DEFINITIONS, at as DEFAULT_ANTITANK_WALL_OPTIONS, b as DEFAULT_MAIN_ATTACK_OPTIONS, bt as axis1DrawRule, c as getDefaultOptions, ct as DEFAULT_AREA_OF_OPERATIONS_OPTIONS, d as DEFAULT_TURN_OPTIONS, dt as canonicalTextAmplifierKey, et as DEFAULT_BLOCK_ARROW_OPTIONS, f as DEFAULT_SUPPORTING_ATTACK_OPTIONS, ft as normalizeTextAmplifiers, g as DEFAULT_PICKUP_ZONE_OPTIONS, gt as DEFAULT_DIRECTION_OF_ATTACK_AVIATION_OPTIONS, h as DEFAULT_PRINCIPAL_DIRECTION_OF_FIRE_OPTIONS, ht as DEFAULT_DIRECTION_OF_MAIN_ATTACK_OPTIONS, i as CONTROL_MEASURE_METADATA, it as DEFAULT_ATTACK_BY_FIRE_OPTIONS, j as DEFAULT_FIX_OPTIONS, jt as disruptDrawRule, k as DEFAULT_PHASE_LINE_OPTIONS, kt as point12DrawRule, l as listControlMeasureMetadata, lt as DEFAULT_AREA_DEFENSE_OPTIONS, m as DEFAULT_STRONG_POINT_OPTIONS, mt as DEFAULT_DIRECTION_OF_SUPPORTING_ATTACK_OPTIONS, n as resolveStyleHints, nt as DEFAULT_BATTLE_POSITION_OPTIONS, o as getControlMeasureMetadata, ot as DEFAULT_ANTITANK_DITCH_OPTIONS, p as DEFAULT_SUPPORT_BY_FIRE_OPTIONS, pt as resolveAmplifierPlacement, q as DEFAULT_BYPASS_OPTIONS, r as CONTROL_MEASURE_IDS, rt as DEFAULT_ATTACK_HELICOPTER_OPTIONS, s as getControlMeasureMetadataByValue, st as DEFAULT_ASSEMBLY_AREA_OPTIONS, t as renderControlMeasure, tt as DEFAULT_BLOCK_OPTIONS, u as DEFAULT_TURNING_MOVEMENT_OPTIONS, ut as TEXT_AMPLIFIER_FIELDS, v as DEFAULT_OBSTACLE_BYPASS_EASY_OPTIONS, vt as DEFAULT_AIRBORNE_ATTACK_OPTIONS, w as DEFAULT_FRONTAL_ATTACK_OPTIONS, wt as line23DrawRule, x as DEFAULT_LANDING_ZONE_OPTIONS, xt as supportByFireDrawRule, y as DEFAULT_OBSTACLE_BYPASS_DIFFICULT_OPTIONS, yt as rectangleDrawRule, z as DEFAULT_CLEAR_OPTIONS, zt as calculateMetrics } from "./renderControlMeasure-f_N1HeUd.mjs";
2
2
  //#region src/freeze-orientation.ts
3
3
  /**
4
4
  * Dispatches to a measure kind's `freezeOrientation` hook (see
@@ -1,4 +1,4 @@
1
- import { Pr as TextAmplifiers, W as ControlMeasureId, or as FillPattern } from "../index-Nf6JP0Tz.mjs";
1
+ import { Pr as TextAmplifiers, W as ControlMeasureId, or as FillPattern } from "../index-BxApuW__.mjs";
2
2
  import { FeatureCollection, Geometry } from "geojson";
3
3
 
4
4
  //#region src/preview/index.d.ts
@@ -68,6 +68,8 @@ interface PreviewShape {
68
68
  textAnchor?: "start" | "end";
69
69
  /** Whether the text needs an opaque readability backdrop. */
70
70
  textBackground?: boolean;
71
+ /** Whether the text needs a white halo behind its glyphs. */
72
+ textHalo?: boolean;
71
73
  /** Multi-line justification within the text block, mirroring the label
72
74
  * feature's `textJustify`. The block itself still centers on (`cx`, `cy`). */
73
75
  textJustify?: "left" | "center" | "right";
@@ -1,4 +1,4 @@
1
- import { a as DEFINITIONS, t as renderControlMeasure } from "../renderControlMeasure-TWiLtFXu.mjs";
1
+ import { a as DEFINITIONS, t as renderControlMeasure } from "../renderControlMeasure-f_N1HeUd.mjs";
2
2
  //#region src/preview/index.ts
3
3
  /** Side length (SVG units) of the repeating hatch tile in {@link PREVIEW_FILL_PATTERNS}. */
4
4
  const PREVIEW_PATTERN_TILE = 8;
@@ -331,6 +331,7 @@ function collectShapes(g, tx, out, bboxArea, textLimits, props) {
331
331
  const labelRotation = typeof labelProps.rotation === "number" ? labelProps.rotation : void 0;
332
332
  const labelAnchor = labelProps.textAnchor === "start" || labelProps.textAnchor === "end" ? labelProps.textAnchor : void 0;
333
333
  const textBackground = labelProps.textBackground === true ? true : void 0;
334
+ const textHalo = labelProps.textHalo === true ? true : void 0;
334
335
  const textJustify = labelProps.textJustify === "left" || labelProps.textJustify === "center" || labelProps.textJustify === "right" ? labelProps.textJustify : void 0;
335
336
  const textStyle = labelProps.textStyle === "regular" || labelProps.textStyle === "italic" || labelProps.textStyle === "light" || labelProps.textStyle === "caps" ? labelProps.textStyle : void 0;
336
337
  const styleProps = labelProps.style && typeof labelProps.style === "object" ? labelProps.style : {};
@@ -351,6 +352,7 @@ function collectShapes(g, tx, out, bboxArea, textLimits, props) {
351
352
  heightPx,
352
353
  textAnchor: labelAnchor,
353
354
  textBackground,
355
+ textHalo,
354
356
  textJustify,
355
357
  textStyle
356
358
  });
@@ -7206,7 +7206,8 @@ const DEFAULT_GENERIC_TEXT_OPTIONS = {
7206
7206
  textStyle: "regular",
7207
7207
  rotation: 0,
7208
7208
  sizePixels: 24,
7209
- maxSizePixels: 200
7209
+ maxSizePixels: 200,
7210
+ halo: false
7210
7211
  };
7211
7212
  const GENERIC_TEXT_METADATA = {
7212
7213
  id: "text",
@@ -7274,6 +7275,12 @@ const GENERIC_TEXT_METADATA = {
7274
7275
  }
7275
7276
  ]
7276
7277
  },
7278
+ {
7279
+ key: "halo",
7280
+ label: "Halo",
7281
+ description: "Render a contrasting halo behind the text for legibility on busy backgrounds.",
7282
+ type: "boolean"
7283
+ },
7277
7284
  {
7278
7285
  key: "rotation",
7279
7286
  label: "Rotation",
@@ -7334,6 +7341,7 @@ function createGenericText(coordinates, options = {}) {
7334
7341
  ...textAnchor !== void 0 ? { textAnchor } : {},
7335
7342
  textStyle: merged.textStyle ?? "regular",
7336
7343
  ...merged.maxSizePixels !== void 0 ? { textMaxSizePixels: merged.maxSizePixels } : {},
7344
+ ...merged.halo === true ? { textHalo: true } : {},
7337
7345
  ...sizeProps
7338
7346
  },
7339
7347
  geometry: {
@@ -11664,6 +11672,82 @@ function getDefaultOptions(kind) {
11664
11672
  return structuredClone(DEFINITIONS[kind].defaultOptions);
11665
11673
  }
11666
11674
  //#endregion
11675
+ //#region src/internal/parse-color.ts
11676
+ /**
11677
+ * Shared tolerant CSS-color parser for the internal color helpers
11678
+ * (`color-opacity`, `halo-color`). Parses `#rgb`, `#rgba`, `#rrggbb`,
11679
+ * `#rrggbbaa` (case-insensitive) and `rgb()`/`rgba()` comma forms into 0-255
11680
+ * channels plus a 0-1 alpha (`1` when the color carries none). Returns
11681
+ * `undefined` for anything else (named colors, `hsl()`, garbage) so callers
11682
+ * can fall back rather than guess.
11683
+ */
11684
+ function parseColor(color) {
11685
+ const trimmed = color.trim();
11686
+ const hex = /^#([0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.exec(trimmed);
11687
+ if (hex) {
11688
+ const digits = hex[1].length <= 4 ? hex[1].replace(/./g, (c) => c + c) : hex[1];
11689
+ return {
11690
+ r: parseInt(digits.slice(0, 2), 16),
11691
+ g: parseInt(digits.slice(2, 4), 16),
11692
+ b: parseInt(digits.slice(4, 6), 16),
11693
+ a: digits.length === 8 ? parseInt(digits.slice(6, 8), 16) / 255 : 1
11694
+ };
11695
+ }
11696
+ const rgbFn = /^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*(?:,\s*([\d.]+)\s*)?\)$/i.exec(trimmed);
11697
+ if (rgbFn) return {
11698
+ r: Number(rgbFn[1]),
11699
+ g: Number(rgbFn[2]),
11700
+ b: Number(rgbFn[3]),
11701
+ a: rgbFn[4] !== void 0 ? Number(rgbFn[4]) : 1
11702
+ };
11703
+ }
11704
+ //#endregion
11705
+ //#region src/internal/halo-color.ts
11706
+ /**
11707
+ * Contrast-aware halo color for `textHalo` (felt.com-style): the halo must
11708
+ * read against the resolved text color, not just against the basemap, so a
11709
+ * dark label gets a white halo and a light label gets a near-black one.
11710
+ *
11711
+ * Accepts whatever `parseColor` does (hex and `rgb()`/`rgba()` forms; alpha
11712
+ * is ignored — contrast is about hue, not transparency); relative luminance
11713
+ * (0.2126R + 0.7152G + 0.0722B over 0-1 channels) below 0.5 is "dark" →
11714
+ * white halo, else "light" → `#1a1a1a` (near-black reads better than pure
11715
+ * black over imagery). Unparseable input defaults to white, matching the
11716
+ * common case of dark text on a busy background.
11717
+ */
11718
+ function contrastingHaloColor(color) {
11719
+ const rgb = parseColor(color);
11720
+ if (!rgb) return "#ffffff";
11721
+ return .2126 * (rgb.r / 255) + .7152 * (rgb.g / 255) + .0722 * (rgb.b / 255) < .5 ? "#ffffff" : "#1a1a1a";
11722
+ }
11723
+ //#endregion
11724
+ //#region src/internal/color-opacity.ts
11725
+ /**
11726
+ * Fold the whole-graphic opacity multiplier (ADR-0040) into a resolved color's
11727
+ * alpha channel: `finalAlpha = opacity × colorAlpha`. Used by
11728
+ * `resolveSymbolColor` so adapters and `toSimpleStyle` keep reading alpha from
11729
+ * the color and need no new paint channel.
11730
+ *
11731
+ * Self-safe, so it can be called unconditionally: `opacity` is clamped to
11732
+ * `[0, 1]` and a non-finite, absent, or `>= 1` opacity returns the color
11733
+ * unchanged (an "opaque" setting preserves the original string format).
11734
+ * Otherwise the color is parsed (`#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`,
11735
+ * `rgb()`/`rgba()`; a color with no alpha defaults to `1`) and re-emitted as
11736
+ * `rgba(r, g, b, a)` with `a` rounded to at most 3 decimals for stable output.
11737
+ * Unparseable input (named colors, `hsl()`, garbage) is returned unchanged —
11738
+ * best-effort dimming, matching `toSimpleStyle`'s "omitted rather than guessed"
11739
+ * tolerance. Pure function.
11740
+ */
11741
+ function foldGraphicOpacity(color, opacity) {
11742
+ if (!Number.isFinite(opacity)) return color;
11743
+ const multiplier = Math.min(1, Math.max(0, opacity));
11744
+ if (multiplier >= 1) return color;
11745
+ const parsed = parseColor(color);
11746
+ if (!parsed) return color;
11747
+ const alpha = Math.round(parsed.a * multiplier * 1e3) / 1e3;
11748
+ return `rgba(${parsed.r}, ${parsed.g}, ${parsed.b}, ${alpha})`;
11749
+ }
11750
+ //#endregion
11667
11751
  //#region src/styleResolver.ts
11668
11752
  /**
11669
11753
  * Three-layer style precedence for `renderControlMeasure`.
@@ -11703,16 +11787,25 @@ function resolveStyleHints(graphicsStyle, measureStyle, generatorStyle) {
11703
11787
  * intrinsic to the symbol and cannot be conjured by host styling. `color` is
11704
11788
  * input-only and is stripped from the result.
11705
11789
  *
11790
+ * Also folds the whole-graphic `opacity` multiplier (ADR-0040) into the
11791
+ * resolved `strokeColor` / `fillColor` alpha, after the `DEFAULT_SYMBOL_COLOR`
11792
+ * fallback so a dimmed zero-config render dims too. `opacity` is clamped to
11793
+ * `[0, 1]` (non-finite treated as absent) and is never present on the
11794
+ * returned `StyleHints` — it is consumed here, not passed through.
11795
+ *
11706
11796
  * Pure: the input is not mutated; a fresh object is always returned.
11707
11797
  */
11708
11798
  function resolveSymbolColor(merged, filled) {
11709
- const { color, strokeColor, fillColor, fillPattern, ...rest } = merged ?? {};
11799
+ const { color, strokeColor, fillColor, fillPattern, opacity, ...rest } = merged ?? {};
11800
+ const rawStroke = firstColor(strokeColor, color);
11801
+ const resolvedStroke = foldGraphicOpacity(rawStroke, opacity);
11710
11802
  const resolved = {
11711
11803
  ...rest,
11712
- strokeColor: firstColor(strokeColor, color)
11804
+ strokeColor: resolvedStroke
11713
11805
  };
11714
11806
  if (filled) {
11715
- resolved.fillColor = firstColor(fillColor, color);
11807
+ const rawFill = firstColor(fillColor, color);
11808
+ resolved.fillColor = rawFill === rawStroke ? resolvedStroke : foldGraphicOpacity(rawFill, opacity);
11716
11809
  if (fillPattern !== void 0) resolved.fillPattern = fillPattern;
11717
11810
  }
11718
11811
  return resolved;
@@ -11809,6 +11902,8 @@ function normalizeFeature(id, feature, index, generatedLabelOrdinal, measureStyl
11809
11902
  const textSizeMeters = typeof sourceProps.textSizeMeters === "number" ? sourceProps.textSizeMeters : void 0;
11810
11903
  const textAnchor = sourceProps.textAnchor === "start" || sourceProps.textAnchor === "end" ? sourceProps.textAnchor : void 0;
11811
11904
  const textBackground = sourceProps.textBackground === true ? true : void 0;
11905
+ const textHalo = sourceProps.textHalo === true ? true : void 0;
11906
+ const textHaloColor = textHalo ? contrastingHaloColor(style.strokeColor ?? "#000") : void 0;
11812
11907
  const textJustify = sourceProps.textJustify === "left" || sourceProps.textJustify === "center" || sourceProps.textJustify === "right" ? sourceProps.textJustify : void 0;
11813
11908
  const textStyle = sourceProps.textStyle === "regular" || sourceProps.textStyle === "italic" || sourceProps.textStyle === "light" || sourceProps.textStyle === "caps" ? sourceProps.textStyle : void 0;
11814
11909
  const textMaxSizePixels = typeof sourceProps.textMaxSizePixels === "number" ? sourceProps.textMaxSizePixels : void 0;
@@ -11831,6 +11926,8 @@ function normalizeFeature(id, feature, index, generatedLabelOrdinal, measureStyl
11831
11926
  ...resolvedRotation !== void 0 ? { rotation: resolvedRotation } : {},
11832
11927
  ...textAnchor !== void 0 ? { textAnchor } : {},
11833
11928
  ...textBackground !== void 0 ? { textBackground } : {},
11929
+ ...textHalo !== void 0 ? { textHalo } : {},
11930
+ ...textHaloColor !== void 0 ? { textHaloColor } : {},
11834
11931
  ...amplifierField !== void 0 ? { amplifierField } : {},
11835
11932
  ...labelPlacementKey !== void 0 ? { labelPlacementKey } : {},
11836
11933
  ...textSizePixels !== void 0 ? { textSizePixels } : {},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orbat-mapper/control-measures",
3
- "version": "0.2.0-alpha.24",
3
+ "version": "0.2.0-alpha.26",
4
4
  "description": "Library for drawing tactical graphics and control measures according to MIL-STD-2525 and APP-6 standards.",
5
5
  "license": "MIT",
6
6
  "author": "Orbat Mapper",