@orbat-mapper/tactical-draw-adapter-maplibre 0.2.0-alpha.21 → 0.2.0-alpha.23
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 +14 -1
- package/dist/index.mjs +58 -4
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -17,7 +17,20 @@ interface MapLibreGroupBundle {
|
|
|
17
17
|
readonly sourceId: string;
|
|
18
18
|
readonly layerIds: Map<PaintChannel, string>;
|
|
19
19
|
features: readonly Feature[];
|
|
20
|
-
|
|
20
|
+
/** Features most recently submitted to the native source, after MapLibre-specific promotion. */
|
|
21
|
+
sourceFeatures: readonly Feature[];
|
|
22
|
+
/** Whether the native source has received its first complete dataset. */
|
|
23
|
+
sourceInitialized: boolean;
|
|
24
|
+
/** Unset while the stored value describes older features than `features` holds. */
|
|
25
|
+
featureSignature: string | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Last `FeatureGroup.revision` seen for this bundle, when the producer
|
|
28
|
+
* supplied one. Two consecutive groups with the same `revision` are known
|
|
29
|
+
* to carry byte-identical `features`, so it stands in for `featureSignature`
|
|
30
|
+
* without paying to re-stringify the whole group. A missing revision on
|
|
31
|
+
* either side falls back to the signature comparison — see `applyFeatureGroups`.
|
|
32
|
+
*/
|
|
33
|
+
revision?: number;
|
|
21
34
|
requiredIconIds: ReadonlySet<string>;
|
|
22
35
|
}
|
|
23
36
|
type MapLibreEventToken = (e: any) => void;
|
package/dist/index.mjs
CHANGED
|
@@ -28,6 +28,49 @@ function sameOrder(a, b) {
|
|
|
28
28
|
return true;
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
|
+
* Replace the contents of shared-id features while adding/removing ids that
|
|
32
|
+
* entered or left a stable group bundle. Remove stale keys explicitly instead
|
|
33
|
+
* of combining `removeAllProperties` with `addOrUpdateProperties`: MapLibre's
|
|
34
|
+
* tile-index diff treats the former as exclusive and otherwise drops the
|
|
35
|
+
* replacement properties, including the promoted feature id.
|
|
36
|
+
*/
|
|
37
|
+
function buildGeoJSONSourceDiff(previousFeatures, nextFeatures) {
|
|
38
|
+
const previousById = new Map(previousFeatures.map((feature) => [feature.id, feature]));
|
|
39
|
+
const nextById = new Map(nextFeatures.map((feature) => [feature.id, feature]));
|
|
40
|
+
const remove = previousFeatures.filter((feature) => !nextById.has(feature.id)).map((feature) => feature.id);
|
|
41
|
+
const add = [];
|
|
42
|
+
const update = [];
|
|
43
|
+
for (const feature of nextFeatures) {
|
|
44
|
+
const previous = previousById.get(feature.id);
|
|
45
|
+
if (!previous) {
|
|
46
|
+
add.push(feature);
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (feature.geometry === null) {
|
|
50
|
+
remove.push(feature.id);
|
|
51
|
+
add.push(feature);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const previousProperties = previous.properties ?? {};
|
|
55
|
+
const nextProperties = feature.properties ?? {};
|
|
56
|
+
const removeProperties = Object.keys(previousProperties).filter((key) => !Object.hasOwn(nextProperties, key));
|
|
57
|
+
update.push({
|
|
58
|
+
id: feature.id,
|
|
59
|
+
newGeometry: feature.geometry,
|
|
60
|
+
...removeProperties.length > 0 ? { removeProperties } : {},
|
|
61
|
+
addOrUpdateProperties: Object.entries(nextProperties).map(([key, value]) => ({
|
|
62
|
+
key,
|
|
63
|
+
value
|
|
64
|
+
}))
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
...remove.length > 0 ? { remove } : {},
|
|
69
|
+
...add.length > 0 ? { add } : {},
|
|
70
|
+
...update.length > 0 ? { update } : {}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
31
74
|
* Find the largest subset of bundles whose relative order already matches the
|
|
32
75
|
* desired stack. Reorders then move only the remaining bundles.
|
|
33
76
|
*/
|
|
@@ -800,12 +843,19 @@ var MapLibreAdapter = class extends BaseMapAdapter {
|
|
|
800
843
|
bundle = this.createGroupBundle(layerId, handle);
|
|
801
844
|
handle.groupBundles.set(group.id, bundle);
|
|
802
845
|
}
|
|
803
|
-
|
|
804
|
-
|
|
846
|
+
let contentChanged;
|
|
847
|
+
if (!isNewBundle && bundle.revision !== void 0 && group.revision !== void 0) {
|
|
848
|
+
contentChanged = bundle.revision !== group.revision;
|
|
849
|
+
if (contentChanged) bundle.featureSignature = void 0;
|
|
850
|
+
} else {
|
|
851
|
+
const featureSignature = JSON.stringify(group.features);
|
|
852
|
+
contentChanged = isNewBundle || bundle.featureSignature !== featureSignature;
|
|
853
|
+
bundle.featureSignature = featureSignature;
|
|
854
|
+
}
|
|
805
855
|
const requiredIconIds = this.requiredIconIds(group);
|
|
806
856
|
const resourcesChanged = bundle.requiredIconIds.size !== requiredIconIds.size || [...bundle.requiredIconIds].some((id) => !requiredIconIds.has(id));
|
|
807
857
|
bundle.features = group.features;
|
|
808
|
-
bundle.
|
|
858
|
+
bundle.revision = group.revision;
|
|
809
859
|
bundle.requiredIconIds = requiredIconIds;
|
|
810
860
|
if (this.reconcileGroupChannels(handle, bundle, groupPaintChannels(group.features, handle.style))) bundlesNeedingOrder.add(group.id);
|
|
811
861
|
if (contentChanged || resourcesChanged) this.updateGroupBundleSource(bundle);
|
|
@@ -824,6 +874,8 @@ var MapLibreAdapter = class extends BaseMapAdapter {
|
|
|
824
874
|
sourceId,
|
|
825
875
|
layerIds: /* @__PURE__ */ new Map(),
|
|
826
876
|
features: [],
|
|
877
|
+
sourceFeatures: [],
|
|
878
|
+
sourceInitialized: false,
|
|
827
879
|
featureSignature: "[]",
|
|
828
880
|
requiredIconIds: /* @__PURE__ */ new Set()
|
|
829
881
|
};
|
|
@@ -917,10 +969,12 @@ var MapLibreAdapter = class extends BaseMapAdapter {
|
|
|
917
969
|
const source = this.map.getSource(bundle.sourceId);
|
|
918
970
|
if (!source) return;
|
|
919
971
|
const features = [...bundle.requiredIconIds].every((id) => this.map.hasImage(id)) ? bundle.features.map((feature) => this.promoteFeature(feature)) : [];
|
|
920
|
-
const result = source.setData({
|
|
972
|
+
const result = bundle.sourceInitialized && typeof source.updateData === "function" ? source.updateData(buildGeoJSONSourceDiff(bundle.sourceFeatures, features), true) : source.setData({
|
|
921
973
|
type: "FeatureCollection",
|
|
922
974
|
features
|
|
923
975
|
}, true);
|
|
976
|
+
bundle.sourceFeatures = features;
|
|
977
|
+
bundle.sourceInitialized = true;
|
|
924
978
|
if (isPromiseLike(result)) Promise.resolve(result).catch(() => {});
|
|
925
979
|
}
|
|
926
980
|
orderGroupBundles(handle, previousGroupIds, desiredGroupIds, forcedGroupIds) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orbat-mapper/tactical-draw-adapter-maplibre",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.23",
|
|
4
4
|
"description": "MapLibre GL JS engine adapter for @orbat-mapper/tactical-draw. Draw and edit tactical control measures (MIL-STD-2525 / APP-6) on a MapLibre map.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Orbat Mapper",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"access": "public"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@orbat-mapper/
|
|
41
|
-
"@orbat-mapper/
|
|
40
|
+
"@orbat-mapper/tactical-draw": "^0.2.0-alpha.38",
|
|
41
|
+
"@orbat-mapper/control-measures": "^0.2.0-alpha.26"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"maplibre-gl": ">=5.8.0 <6.0.0"
|