@orbat-mapper/tactical-draw 0.10.0 → 0.10.2
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 +23 -0
- package/dist/index.mjs +37 -12
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -1662,6 +1662,12 @@ declare class TacticalDraw {
|
|
|
1662
1662
|
private transformCounter;
|
|
1663
1663
|
/** Snapshot of the host's latest authoritative Graphic membership and order. */
|
|
1664
1664
|
private lastRenderedMeasures;
|
|
1665
|
+
/**
|
|
1666
|
+
* Id index over {@link lastRenderedMeasures}, rebuilt alongside it so
|
|
1667
|
+
* per-id lookups (e.g. {@link renderHighlights}) are O(1) instead of an
|
|
1668
|
+
* O(document) linear scan on every highlighted id, every frame.
|
|
1669
|
+
*/
|
|
1670
|
+
private lastRenderedMeasuresById;
|
|
1665
1671
|
/** Whether any last-rendered graphic reads the whole camera, not just scale. */
|
|
1666
1672
|
private lastRenderedHasViewDependent;
|
|
1667
1673
|
private snapGeometryFeatures;
|
|
@@ -1703,6 +1709,15 @@ declare class TacticalDraw {
|
|
|
1703
1709
|
* that removes outlines when the set transitions to empty.
|
|
1704
1710
|
*/
|
|
1705
1711
|
private hasHighlightOutlines;
|
|
1712
|
+
/**
|
|
1713
|
+
* Coalesces bursts of {@link setHighlightedGraphics} (e.g. hover across a
|
|
1714
|
+
* list of rows) into at most one {@link renderHighlights} per animation
|
|
1715
|
+
* frame. Every other caller — `render()`, view-change, session start /
|
|
1716
|
+
* settle — needs highlight state updated synchronously and in step with
|
|
1717
|
+
* its own write, so those call {@link flushHighlights} instead, which
|
|
1718
|
+
* cancels any pending coalesced frame before rendering immediately.
|
|
1719
|
+
*/
|
|
1720
|
+
private readonly highlightCoalescer;
|
|
1706
1721
|
constructor(adapter: MapAdapter, options?: TacticalDrawOptions);
|
|
1707
1722
|
setPinPresentation(defaults: PinPresentationPatch): void;
|
|
1708
1723
|
setPinOverride(id: string, patch: PinOverridePatch): void;
|
|
@@ -1830,6 +1845,14 @@ declare class TacticalDraw {
|
|
|
1830
1845
|
* "locked selection" chrome.
|
|
1831
1846
|
*/
|
|
1832
1847
|
setHighlightedGraphics(ids: readonly string[]): void;
|
|
1848
|
+
/**
|
|
1849
|
+
* Cancel any pending coalesced highlight frame and re-project highlights
|
|
1850
|
+
* immediately. Used by every caller other than `setHighlightedGraphics`
|
|
1851
|
+
* (`render()`, view-change, session start / settle) so their own
|
|
1852
|
+
* synchronous effects and the highlight layer update together, with no
|
|
1853
|
+
* frame of lag and no stale coalesced call left to fire afterwards.
|
|
1854
|
+
*/
|
|
1855
|
+
private flushHighlights;
|
|
1833
1856
|
/**
|
|
1834
1857
|
* Project the current {@link highlightedIds} into one outline `LineString`
|
|
1835
1858
|
* per graphic and reconcile them onto the highlight layer. Idempotent and
|
package/dist/index.mjs
CHANGED
|
@@ -7644,6 +7644,12 @@ var TacticalDraw = class {
|
|
|
7644
7644
|
transformCounter = 0;
|
|
7645
7645
|
/** Snapshot of the host's latest authoritative Graphic membership and order. */
|
|
7646
7646
|
lastRenderedMeasures = [];
|
|
7647
|
+
/**
|
|
7648
|
+
* Id index over {@link lastRenderedMeasures}, rebuilt alongside it so
|
|
7649
|
+
* per-id lookups (e.g. {@link renderHighlights}) are O(1) instead of an
|
|
7650
|
+
* O(document) linear scan on every highlighted id, every frame.
|
|
7651
|
+
*/
|
|
7652
|
+
lastRenderedMeasuresById = /* @__PURE__ */ new Map();
|
|
7647
7653
|
/** Whether any last-rendered graphic reads the whole camera, not just scale. */
|
|
7648
7654
|
lastRenderedHasViewDependent = false;
|
|
7649
7655
|
snapGeometryFeatures = [];
|
|
@@ -7685,6 +7691,15 @@ var TacticalDraw = class {
|
|
|
7685
7691
|
* that removes outlines when the set transitions to empty.
|
|
7686
7692
|
*/
|
|
7687
7693
|
hasHighlightOutlines = false;
|
|
7694
|
+
/**
|
|
7695
|
+
* Coalesces bursts of {@link setHighlightedGraphics} (e.g. hover across a
|
|
7696
|
+
* list of rows) into at most one {@link renderHighlights} per animation
|
|
7697
|
+
* frame. Every other caller — `render()`, view-change, session start /
|
|
7698
|
+
* settle — needs highlight state updated synchronously and in step with
|
|
7699
|
+
* its own write, so those call {@link flushHighlights} instead, which
|
|
7700
|
+
* cancels any pending coalesced frame before rendering immediately.
|
|
7701
|
+
*/
|
|
7702
|
+
highlightCoalescer = createFrameCoalescer(() => this.renderHighlights());
|
|
7688
7703
|
constructor(adapter, options) {
|
|
7689
7704
|
this.adapter = adapter;
|
|
7690
7705
|
this.offsetDragModifier = options?.offsetDragModifier ?? false;
|
|
@@ -7717,7 +7732,7 @@ var TacticalDraw = class {
|
|
|
7717
7732
|
this.invalidateGraphicGroupCache(false);
|
|
7718
7733
|
this.refreshActiveEditPresentation();
|
|
7719
7734
|
this.reconcileGraphicsStack();
|
|
7720
|
-
this.
|
|
7735
|
+
this.flushHighlights();
|
|
7721
7736
|
});
|
|
7722
7737
|
}
|
|
7723
7738
|
setPinPresentation(defaults) {
|
|
@@ -7951,7 +7966,7 @@ var TacticalDraw = class {
|
|
|
7951
7966
|
const resolutionChanged = !Object.is(resolution, this.lastViewResolution);
|
|
7952
7967
|
this.lastViewResolution = resolution;
|
|
7953
7968
|
if (!this.hasRendered) return;
|
|
7954
|
-
this.
|
|
7969
|
+
this.flushHighlights();
|
|
7955
7970
|
const nativePointSymbolScaling = this.adapter.scalesGroundPointSymbolsNatively === true;
|
|
7956
7971
|
if (!resolutionChanged && !this.lastRenderedHasViewDependent) return;
|
|
7957
7972
|
const excluded = this.graphicsStackExcludedIds();
|
|
@@ -8040,6 +8055,7 @@ var TacticalDraw = class {
|
|
|
8040
8055
|
}
|
|
8041
8056
|
}
|
|
8042
8057
|
this.lastRenderedMeasures = measures.slice();
|
|
8058
|
+
this.lastRenderedMeasuresById = new Map(this.lastRenderedMeasures.map((g) => [g.id, g]));
|
|
8043
8059
|
this.lastRenderedHasViewDependent = this.lastRenderedMeasures.some((g) => !this.renderGraphicGroup(g).pin && graphicViewDependence(g, this.adapter.scalesGroundPointSymbolsNatively === true) === "view");
|
|
8044
8060
|
this.graphicStack.acknowledgeHostRender(measures);
|
|
8045
8061
|
if (activeEdit && "syncHostMembership" in activeEdit && measures.some((graphic) => graphic.id === activeEdit.measureId && graphic.kind === activeEdit.graphicKind)) activeEdit.syncHostMembership(true);
|
|
@@ -8058,7 +8074,7 @@ var TacticalDraw = class {
|
|
|
8058
8074
|
});
|
|
8059
8075
|
else if (this.activeInteraction.isStarting) this.activeInteraction.cancel("removed");
|
|
8060
8076
|
}
|
|
8061
|
-
this.
|
|
8077
|
+
this.flushHighlights();
|
|
8062
8078
|
}
|
|
8063
8079
|
/**
|
|
8064
8080
|
* Replace the passive selection-highlight set with `ids`. Declarative and
|
|
@@ -8073,6 +8089,17 @@ var TacticalDraw = class {
|
|
|
8073
8089
|
setHighlightedGraphics(ids) {
|
|
8074
8090
|
this.assertAlive();
|
|
8075
8091
|
this.highlightedIds = ids.slice();
|
|
8092
|
+
this.highlightCoalescer.schedule();
|
|
8093
|
+
}
|
|
8094
|
+
/**
|
|
8095
|
+
* Cancel any pending coalesced highlight frame and re-project highlights
|
|
8096
|
+
* immediately. Used by every caller other than `setHighlightedGraphics`
|
|
8097
|
+
* (`render()`, view-change, session start / settle) so their own
|
|
8098
|
+
* synchronous effects and the highlight layer update together, with no
|
|
8099
|
+
* frame of lag and no stale coalesced call left to fire afterwards.
|
|
8100
|
+
*/
|
|
8101
|
+
flushHighlights() {
|
|
8102
|
+
this.highlightCoalescer.cancel();
|
|
8076
8103
|
this.renderHighlights();
|
|
8077
8104
|
}
|
|
8078
8105
|
/**
|
|
@@ -8098,7 +8125,7 @@ var TacticalDraw = class {
|
|
|
8098
8125
|
const pinGroups = [];
|
|
8099
8126
|
for (const id of this.highlightedIds) {
|
|
8100
8127
|
if (excluded.has(id)) continue;
|
|
8101
|
-
const graphic = this.
|
|
8128
|
+
const graphic = this.lastRenderedMeasuresById.get(id);
|
|
8102
8129
|
if (!graphic) continue;
|
|
8103
8130
|
if (isPointSymbol(graphic)) {
|
|
8104
8131
|
const pin = this.renderGraphicGroup(graphic).pin;
|
|
@@ -8151,16 +8178,13 @@ var TacticalDraw = class {
|
|
|
8151
8178
|
if (!this.images) return null;
|
|
8152
8179
|
return imageFootprint(graphic, renderImageForAdapter(this.adapter, this.images, graphic).render, this.adapter)?.box ?? null;
|
|
8153
8180
|
}
|
|
8154
|
-
const
|
|
8155
|
-
|
|
8156
|
-
symbolColors: this.symbolColors
|
|
8157
|
-
});
|
|
8158
|
-
if (graphic.kind === "text") return fitTextFootprintFromFeatures(render.features, (lonLat) => this.adapter.getPixelFromCoordinate(lonLat), {
|
|
8181
|
+
const features = this.renderGraphicGroup(graphic).features;
|
|
8182
|
+
if (graphic.kind === "text") return fitTextFootprintFromFeatures(features, (lonLat) => this.adapter.getPixelFromCoordinate(lonLat), {
|
|
8159
8183
|
resolution: this.adapter.getResolution(),
|
|
8160
8184
|
bearing
|
|
8161
8185
|
});
|
|
8162
8186
|
const positions = [];
|
|
8163
|
-
for (const feature of
|
|
8187
|
+
for (const feature of features) if (feature.geometry) collectFeaturePositions(feature.geometry, positions);
|
|
8164
8188
|
const pixels = [];
|
|
8165
8189
|
for (const position of positions) {
|
|
8166
8190
|
const pixel = this.adapter.getPixelFromCoordinate(position);
|
|
@@ -8221,7 +8245,7 @@ var TacticalDraw = class {
|
|
|
8221
8245
|
clearSlot();
|
|
8222
8246
|
this.clearSnapResult();
|
|
8223
8247
|
if (extraSettle) extraSettle();
|
|
8224
|
-
this.
|
|
8248
|
+
this.flushHighlights();
|
|
8225
8249
|
};
|
|
8226
8250
|
this.activeInteraction.begin();
|
|
8227
8251
|
try {
|
|
@@ -8235,7 +8259,7 @@ var TacticalDraw = class {
|
|
|
8235
8259
|
this.activeInteraction.set(handle);
|
|
8236
8260
|
if (activate && !handle.settled) {
|
|
8237
8261
|
deactivate = activate(handle) ?? null;
|
|
8238
|
-
this.
|
|
8262
|
+
this.flushHighlights();
|
|
8239
8263
|
}
|
|
8240
8264
|
}
|
|
8241
8265
|
handle.promise.then(clearSlot, clearSlot);
|
|
@@ -8782,6 +8806,7 @@ var TacticalDraw = class {
|
|
|
8782
8806
|
this.unsubscribePins();
|
|
8783
8807
|
if (this.destroyed) return;
|
|
8784
8808
|
this.destroyed = true;
|
|
8809
|
+
this.highlightCoalescer.cancel();
|
|
8785
8810
|
if (this.activeInteraction.isActive) {
|
|
8786
8811
|
this.activeEdit = null;
|
|
8787
8812
|
this.activeTransform = null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orbat-mapper/tactical-draw",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.2",
|
|
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",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@orbat-mapper/control-measures": "^0.
|
|
42
|
+
"@orbat-mapper/control-measures": "^0.28.0"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"vitest": ">=4.0.0"
|