@tileflow/react-native 0.0.0-bootstrap.0 → 0.1.0-alpha.1
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/README.md +216 -4
- package/TileflowNativeAdmission.podspec +34 -0
- package/android/build.gradle +43 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/java/dev/tileflow/reactnative/AdmissionBootstrap.kt +144 -0
- package/android/src/main/java/dev/tileflow/reactnative/AdmissionBootstrapOkHttpNetwork.kt +89 -0
- package/android/src/main/java/dev/tileflow/reactnative/AdmissionCatalog.kt +137 -0
- package/android/src/main/java/dev/tileflow/reactnative/AdmissionDocumentScope.kt +22 -0
- package/android/src/main/java/dev/tileflow/reactnative/AdmissionEngine.kt +335 -0
- package/android/src/main/java/dev/tileflow/reactnative/AdmissionModuleProvider.kt +68 -0
- package/android/src/main/java/dev/tileflow/reactnative/AdmissionOkHttpNetwork.kt +86 -0
- package/android/src/main/java/dev/tileflow/reactnative/AdmissionProviderLease.kt +56 -0
- package/android/src/main/java/dev/tileflow/reactnative/AdmissionTypes.kt +85 -0
- package/android/src/main/java/dev/tileflow/reactnative/AdmissionUrl.kt +100 -0
- package/android/src/main/java/dev/tileflow/reactnative/HandlerAdmissionScheduler.kt +16 -0
- package/android/src/main/java/dev/tileflow/reactnative/MobileConfiguration.kt +95 -0
- package/android/src/main/java/dev/tileflow/reactnative/MobileConfigurationResources.kt +43 -0
- package/android/src/main/java/dev/tileflow/reactnative/NativeDocumentOkHttpNetwork.kt +101 -0
- package/android/src/main/java/dev/tileflow/reactnative/NativeDocumentRegistry.kt +136 -0
- package/android/src/main/java/dev/tileflow/reactnative/NativeSurfaceState.kt +115 -0
- package/android/src/main/java/dev/tileflow/reactnative/TileflowNativeAdmissionModule.kt +236 -0
- package/android/src/main/java/dev/tileflow/reactnative/TileflowNativeAdmissionPackage.kt +16 -0
- package/android/src/main/java/dev/tileflow/reactnative/TileflowNativeConfigurationModule.kt +43 -0
- package/android/src/main/java/dev/tileflow/reactnative/TileflowNativeDocumentsModule.kt +82 -0
- package/android/src/main/java/dev/tileflow/reactnative/TileflowNativeSurfaceModule.kt +277 -0
- package/android/src/main/res/raw/tileflow_configuration_keep.xml +3 -0
- package/dist/contract-DWs-lDPo.d.ts +144 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +6989 -0
- package/dist/internal/camera.d.ts +65 -0
- package/dist/internal/camera.js +325 -0
- package/dist/internal/hosted-binding.d.ts +18 -0
- package/dist/internal/hosted-binding.js +277 -0
- package/dist/internal/initial-view.d.ts +11 -0
- package/dist/internal/initial-view.js +8 -0
- package/dist/internal/interactions.d.ts +76 -0
- package/dist/internal/interactions.js +794 -0
- package/dist/internal/native-admission-bridge.d.ts +29 -0
- package/dist/internal/native-admission-bridge.js +351 -0
- package/dist/internal/native-admission.d.ts +78 -0
- package/dist/internal/native-admission.js +1614 -0
- package/dist/internal/native-appearance.d.ts +21 -0
- package/dist/internal/native-appearance.js +110 -0
- package/dist/internal/native-configuration-bridge.d.ts +9 -0
- package/dist/internal/native-configuration-bridge.js +343 -0
- package/dist/internal/session.d.ts +125 -0
- package/dist/internal/session.js +887 -0
- package/dist/internal/source-state.d.ts +11 -0
- package/dist/internal/source-state.js +26 -0
- package/dist/native-admission-contract-k7LKE1vW.d.ts +89 -0
- package/docs/native-admission.md +108 -0
- package/docs/native-configuration.md +210 -0
- package/docs/native-interactions.md +161 -0
- package/docs/native-location.md +148 -0
- package/ios/TFAdmissionBootstrap.h +17 -0
- package/ios/TFAdmissionBootstrap.mm +168 -0
- package/ios/TFAdmissionCatalog.h +13 -0
- package/ios/TFAdmissionCatalog.mm +193 -0
- package/ios/TFAdmissionDocumentScope.h +7 -0
- package/ios/TFAdmissionDocumentScope.mm +45 -0
- package/ios/TFAdmissionEngine.h +57 -0
- package/ios/TFAdmissionEngine.mm +371 -0
- package/ios/TFAdmissionInstallation.h +27 -0
- package/ios/TFAdmissionInstallation.mm +117 -0
- package/ios/TFAdmissionNetwork.h +16 -0
- package/ios/TFAdmissionNetwork.mm +268 -0
- package/ios/TFAdmissionURL.mm +116 -0
- package/ios/TFDocumentBounds.h +9 -0
- package/ios/TFDocumentBounds.mm +19 -0
- package/ios/TFMobileConfiguration.h +23 -0
- package/ios/TFMobileConfiguration.mm +139 -0
- package/ios/TFNativeAdmissionURLProtocol.mm +69 -0
- package/ios/TFNativeDocumentRegistry.h +28 -0
- package/ios/TFNativeDocumentRegistry.mm +193 -0
- package/ios/TFNativeDocumentURL.h +6 -0
- package/ios/TFNativeSurfaceState.h +28 -0
- package/ios/TFNativeSurfaceState.mm +128 -0
- package/ios/TileflowNativeAdmission.h +9 -0
- package/ios/TileflowNativeAdmission.mm +184 -0
- package/ios/TileflowNativeConfiguration.mm +41 -0
- package/ios/TileflowNativeDocuments.h +12 -0
- package/ios/TileflowNativeDocuments.mm +105 -0
- package/ios/TileflowNativeSurface.mm +403 -0
- package/ios/tileflow_native_admission.rb +45 -0
- package/package.json +51 -7
- package/react-native.config.cjs +13 -0
|
@@ -0,0 +1,794 @@
|
|
|
1
|
+
// src/native-interaction-input.ts
|
|
2
|
+
import {
|
|
3
|
+
tileflowInteractionJsonValueSchema,
|
|
4
|
+
tileflowInteractionLimits,
|
|
5
|
+
validateTileflowAnnotations,
|
|
6
|
+
validateTileflowInteractionBindings
|
|
7
|
+
} from "@tileflow/interactions";
|
|
8
|
+
var messages = {
|
|
9
|
+
DUPLICATE_ANNOTATION_ID: "Annotation IDs must be unique.",
|
|
10
|
+
INVALID_FIELD: "An interaction field is invalid.",
|
|
11
|
+
INVALID_ANNOTATION: "An annotation is invalid.",
|
|
12
|
+
INVALID_DOCUMENT: "The interaction document is invalid.",
|
|
13
|
+
LIMIT_EXCEEDED: "The portable interaction limit was exceeded.",
|
|
14
|
+
MISSING_VIEW: "The interaction view is unavailable.",
|
|
15
|
+
OVERLAY_FAILURE: "The interaction operation failed.",
|
|
16
|
+
SEMANTIC_MANIFEST_MISMATCH: "The current style cannot provide verified semantic POI queries.",
|
|
17
|
+
STALE_TARGET: "The interaction target is no longer available.",
|
|
18
|
+
UNSTABLE_FEATURE_IDENTITY: "A stable feature ID is unavailable.",
|
|
19
|
+
UNSUPPORTED_MODE: "This interaction input modality is unavailable.",
|
|
20
|
+
UNSUPPORTED_TARGET: "This interaction target is unavailable."
|
|
21
|
+
};
|
|
22
|
+
function nativeInteractionDiagnostic(code) {
|
|
23
|
+
return Object.freeze({
|
|
24
|
+
code,
|
|
25
|
+
level: code === "STALE_TARGET" || code === "UNSUPPORTED_TARGET" ? "warning" : "error",
|
|
26
|
+
message: messages[code]
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function nativeInteractionField(value, key) {
|
|
30
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error();
|
|
31
|
+
const prototype = Object.getPrototypeOf(value);
|
|
32
|
+
if (prototype !== null && prototype !== Object.prototype) throw new Error();
|
|
33
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
34
|
+
if (!descriptor) return void 0;
|
|
35
|
+
if (!("value" in descriptor) || !descriptor.enumerable) throw new Error();
|
|
36
|
+
return descriptor.value;
|
|
37
|
+
}
|
|
38
|
+
function snapshotNativeInteractionJson(input) {
|
|
39
|
+
if (!tileflowInteractionJsonValueSchema.safeParse(input).success) throw new Error();
|
|
40
|
+
let nodes = 0;
|
|
41
|
+
let properties2 = 0;
|
|
42
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
43
|
+
const copy = (value, depth) => {
|
|
44
|
+
if (++nodes > tileflowInteractionLimits.maxDocumentNodes || depth > tileflowInteractionLimits.maxDocumentDepth)
|
|
45
|
+
throw new Error();
|
|
46
|
+
if (value === null || typeof value === "boolean") return value;
|
|
47
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
48
|
+
if (typeof value === "string" && value.length <= tileflowInteractionLimits.maxDocumentBytes)
|
|
49
|
+
return value;
|
|
50
|
+
if (!value || typeof value !== "object" || seen.has(value)) throw new Error();
|
|
51
|
+
seen.add(value);
|
|
52
|
+
const array2 = Array.isArray(value);
|
|
53
|
+
const prototype = Object.getPrototypeOf(value);
|
|
54
|
+
if (array2 ? prototype !== Array.prototype : prototype !== Object.prototype && prototype !== null)
|
|
55
|
+
throw new Error();
|
|
56
|
+
if (array2) {
|
|
57
|
+
const lengthDescriptor = Object.getOwnPropertyDescriptor(value, "length");
|
|
58
|
+
if (!lengthDescriptor || !("value" in lengthDescriptor)) throw new Error();
|
|
59
|
+
const length = lengthDescriptor.value;
|
|
60
|
+
if (typeof length !== "number" || !Number.isSafeInteger(length) || length < 0 || length > tileflowInteractionLimits.maxDocumentProperties - properties2)
|
|
61
|
+
throw new Error();
|
|
62
|
+
if (length > 0 && depth >= tileflowInteractionLimits.maxDocumentDepth) throw new Error();
|
|
63
|
+
properties2 += length;
|
|
64
|
+
const keys2 = Reflect.ownKeys(value);
|
|
65
|
+
if (keys2.length > length + 1) throw new Error();
|
|
66
|
+
const result2 = new Array(length);
|
|
67
|
+
let sawLength = false;
|
|
68
|
+
for (const key of keys2) {
|
|
69
|
+
if (typeof key !== "string") throw new Error();
|
|
70
|
+
if (key === "length") {
|
|
71
|
+
sawLength = true;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const index = Number(key);
|
|
75
|
+
if (!Number.isSafeInteger(index) || index < 0 || index >= length || String(index) !== key)
|
|
76
|
+
throw new Error();
|
|
77
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
78
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) throw new Error();
|
|
79
|
+
Object.defineProperty(result2, key, {
|
|
80
|
+
value: copy(descriptor.value, depth + 1),
|
|
81
|
+
enumerable: true,
|
|
82
|
+
configurable: true,
|
|
83
|
+
writable: true
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
if (!sawLength) throw new Error();
|
|
87
|
+
return Object.freeze(result2);
|
|
88
|
+
}
|
|
89
|
+
const keys = Reflect.ownKeys(value);
|
|
90
|
+
if (keys.length > tileflowInteractionLimits.maxDocumentProperties - properties2)
|
|
91
|
+
throw new Error();
|
|
92
|
+
properties2 += keys.length;
|
|
93
|
+
const result = {};
|
|
94
|
+
for (const key of keys) {
|
|
95
|
+
if (typeof key !== "string" || key === "__proto__" || key === "prototype" || key === "constructor")
|
|
96
|
+
throw new Error();
|
|
97
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
98
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) throw new Error();
|
|
99
|
+
result[key] = copy(descriptor.value, depth + 1);
|
|
100
|
+
}
|
|
101
|
+
return Object.freeze(result);
|
|
102
|
+
};
|
|
103
|
+
const snapshot = copy(input, 0);
|
|
104
|
+
if (!tileflowInteractionJsonValueSchema.safeParse(snapshot).success) throw new Error();
|
|
105
|
+
return snapshot;
|
|
106
|
+
}
|
|
107
|
+
function freezeNativeInteractionValue(value) {
|
|
108
|
+
if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
109
|
+
for (const child of Object.values(value)) freezeNativeInteractionValue(child);
|
|
110
|
+
Object.freeze(value);
|
|
111
|
+
}
|
|
112
|
+
return value;
|
|
113
|
+
}
|
|
114
|
+
function nativeInteractionValuesEqual(left, right) {
|
|
115
|
+
if (left === right) return true;
|
|
116
|
+
if (!left || !right || typeof left !== "object" || typeof right !== "object") return false;
|
|
117
|
+
const array2 = Array.isArray(left);
|
|
118
|
+
if (array2 !== Array.isArray(right)) return false;
|
|
119
|
+
if (array2 && Object.getOwnPropertyDescriptor(left, "length")?.value !== Object.getOwnPropertyDescriptor(right, "length")?.value)
|
|
120
|
+
return false;
|
|
121
|
+
const a = Object.keys(left).sort();
|
|
122
|
+
const b = Object.keys(right).sort();
|
|
123
|
+
return a.length === b.length && a.every(
|
|
124
|
+
(key, index) => key === b[index] && nativeInteractionValuesEqual(
|
|
125
|
+
Object.getOwnPropertyDescriptor(left, key)?.value,
|
|
126
|
+
Object.getOwnPropertyDescriptor(right, key)?.value
|
|
127
|
+
)
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
function prepareNativeInteractionInputs(input, previous) {
|
|
131
|
+
let annotations = previous?.annotations ?? Object.freeze([]);
|
|
132
|
+
let bindings = previous?.bindings ?? Object.freeze([]);
|
|
133
|
+
const diagnostics = [];
|
|
134
|
+
const report = (code) => {
|
|
135
|
+
if (!diagnostics.some((value) => value.code === code))
|
|
136
|
+
diagnostics.push(nativeInteractionDiagnostic(code));
|
|
137
|
+
};
|
|
138
|
+
try {
|
|
139
|
+
const raw = nativeInteractionField(input, "annotations");
|
|
140
|
+
let result = validateTileflowAnnotations(raw === void 0 ? [] : raw);
|
|
141
|
+
if (result.ok)
|
|
142
|
+
result = validateTileflowAnnotations(snapshotNativeInteractionJson(result.annotations));
|
|
143
|
+
if (result.ok) {
|
|
144
|
+
if (!nativeInteractionValuesEqual(annotations, result.annotations))
|
|
145
|
+
annotations = freezeNativeInteractionValue(result.annotations);
|
|
146
|
+
} else for (const diagnostic of result.diagnostics) report(diagnostic.code);
|
|
147
|
+
} catch {
|
|
148
|
+
report("INVALID_DOCUMENT");
|
|
149
|
+
}
|
|
150
|
+
try {
|
|
151
|
+
const raw = nativeInteractionField(input, "interactions");
|
|
152
|
+
let result = validateTileflowInteractionBindings(raw === void 0 ? [] : raw);
|
|
153
|
+
if (result.ok)
|
|
154
|
+
result = validateTileflowInteractionBindings(snapshotNativeInteractionJson(result.bindings));
|
|
155
|
+
if (result.ok) {
|
|
156
|
+
if (!nativeInteractionValuesEqual(bindings, result.bindings))
|
|
157
|
+
bindings = freezeNativeInteractionValue(result.bindings);
|
|
158
|
+
} else for (const diagnostic of result.diagnostics) report(diagnostic.code);
|
|
159
|
+
} catch {
|
|
160
|
+
report("INVALID_DOCUMENT");
|
|
161
|
+
}
|
|
162
|
+
return Object.freeze({
|
|
163
|
+
annotations,
|
|
164
|
+
bindings,
|
|
165
|
+
diagnostics: Object.freeze(diagnostics)
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
function planNativeAnnotations(previous, next) {
|
|
169
|
+
const before = new Map(previous.map((annotation) => [annotation.id, annotation]));
|
|
170
|
+
const after = new Set(next.map((annotation) => annotation.id));
|
|
171
|
+
const create = [];
|
|
172
|
+
const update = [];
|
|
173
|
+
const retain = [];
|
|
174
|
+
for (const annotation of next) {
|
|
175
|
+
const old = before.get(annotation.id);
|
|
176
|
+
if (!old) create.push(annotation);
|
|
177
|
+
else if (nativeInteractionValuesEqual(old, annotation)) retain.push(annotation.id);
|
|
178
|
+
else update.push(Object.freeze({ id: annotation.id, previous: old, annotation }));
|
|
179
|
+
}
|
|
180
|
+
return Object.freeze({
|
|
181
|
+
create: Object.freeze(create),
|
|
182
|
+
update: Object.freeze(update),
|
|
183
|
+
retain: Object.freeze(retain),
|
|
184
|
+
remove: Object.freeze(
|
|
185
|
+
previous.filter((annotation) => !after.has(annotation.id)).map((annotation) => annotation.id)
|
|
186
|
+
),
|
|
187
|
+
order: Object.freeze(next.map((annotation) => annotation.id))
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// src/native-interaction-poi.ts
|
|
192
|
+
import {
|
|
193
|
+
tileflowInteractionLimits as tileflowInteractionLimits2,
|
|
194
|
+
tileflowPoiCategories
|
|
195
|
+
} from "@tileflow/interactions";
|
|
196
|
+
var nativePoiQueryLimit = 512;
|
|
197
|
+
var emptyDiagnostics = Object.freeze([]);
|
|
198
|
+
var stale = Object.freeze({ status: "stale", diagnostics: emptyDiagnostics });
|
|
199
|
+
var miss = Object.freeze({ status: "miss", diagnostics: emptyDiagnostics });
|
|
200
|
+
var failure = (code = "SEMANTIC_MANIFEST_MISMATCH") => Object.freeze({ status: "error", diagnostics: Object.freeze([nativeInteractionDiagnostic(code)]) });
|
|
201
|
+
function array(value, maximum) {
|
|
202
|
+
if (!Array.isArray(value) || Object.getPrototypeOf(value) !== Array.prototype) throw new Error();
|
|
203
|
+
const length = Object.getOwnPropertyDescriptor(value, "length")?.value;
|
|
204
|
+
if (typeof length !== "number" || !Number.isSafeInteger(length) || length < 0 || length > maximum)
|
|
205
|
+
throw new Error();
|
|
206
|
+
const result = [];
|
|
207
|
+
for (let index = 0; index < length; index++) {
|
|
208
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
|
|
209
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) throw new Error();
|
|
210
|
+
result.push(descriptor.value);
|
|
211
|
+
}
|
|
212
|
+
return result;
|
|
213
|
+
}
|
|
214
|
+
function name(value) {
|
|
215
|
+
return typeof value === "string" && value.length > 0 && value.length <= 256 && value !== "__proto__" && value !== "constructor" && value !== "prototype" && !Array.from(value).some(
|
|
216
|
+
(character) => character.charCodeAt(0) <= 31 || character.charCodeAt(0) === 127
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
function category(value) {
|
|
220
|
+
return typeof value === "string" && tileflowPoiCategories.some((candidate) => candidate === value);
|
|
221
|
+
}
|
|
222
|
+
function representation(value) {
|
|
223
|
+
return value === "combined" || value === "icon" || value === "label" || value === "marker";
|
|
224
|
+
}
|
|
225
|
+
function parseManifest(style) {
|
|
226
|
+
if (nativeInteractionField(style, "version") !== 8) throw new Error();
|
|
227
|
+
const metadata = nativeInteractionField(style, "metadata");
|
|
228
|
+
const artifact = snapshotNativeInteractionJson(nativeInteractionField(metadata, "tileflow:interaction-manifest"));
|
|
229
|
+
if (nativeInteractionField(artifact, "version") !== 2) throw new Error();
|
|
230
|
+
const poi = nativeInteractionField(nativeInteractionField(artifact, "domains"), "poi");
|
|
231
|
+
if (nativeInteractionField(poi, "identity") !== "maplibre-feature-id-if-present") throw new Error();
|
|
232
|
+
const hitTesting = nativeInteractionField(poi, "hitTesting");
|
|
233
|
+
if (nativeInteractionField(hitTesting, "order") !== "rendered-topmost" || nativeInteractionField(hitTesting, "frequency") !== "animation-frame")
|
|
234
|
+
throw new Error();
|
|
235
|
+
const deduplication = nativeInteractionField(poi, "deduplication");
|
|
236
|
+
const identity = array(nativeInteractionField(deduplication, "identity"), 3);
|
|
237
|
+
if (identity.length !== 3 || identity[0] !== "source" || identity[1] !== "source-layer" || identity[2] !== "feature-id")
|
|
238
|
+
throw new Error();
|
|
239
|
+
const priorityInput = array(nativeInteractionField(deduplication, "representationPriority"), 4);
|
|
240
|
+
if (priorityInput.length !== 4 || !priorityInput.every(representation) || new Set(priorityInput).size !== 4)
|
|
241
|
+
throw new Error();
|
|
242
|
+
const fieldsInput = nativeInteractionField(poi, "fields");
|
|
243
|
+
const readField = (key) => {
|
|
244
|
+
const value = nativeInteractionField(fieldsInput, key);
|
|
245
|
+
if (!name(value)) throw new Error();
|
|
246
|
+
return value;
|
|
247
|
+
};
|
|
248
|
+
const fields = Object.freeze({
|
|
249
|
+
category: readField("category"),
|
|
250
|
+
filterRank: readField("filterRank"),
|
|
251
|
+
icon: readField("icon"),
|
|
252
|
+
name: readField("name"),
|
|
253
|
+
sizeRank: readField("sizeRank"),
|
|
254
|
+
type: readField("type")
|
|
255
|
+
});
|
|
256
|
+
const physical = /* @__PURE__ */ new Map();
|
|
257
|
+
for (const layer of array(nativeInteractionField(style, "layers"), 4096)) {
|
|
258
|
+
const id = nativeInteractionField(layer, "id");
|
|
259
|
+
if (!name(id) || physical.has(id)) throw new Error();
|
|
260
|
+
physical.set(id, layer);
|
|
261
|
+
}
|
|
262
|
+
const sources = nativeInteractionField(style, "sources");
|
|
263
|
+
const inputs = array(nativeInteractionField(poi, "layers"), 256);
|
|
264
|
+
if (!inputs.length) throw new Error();
|
|
265
|
+
const layers = [];
|
|
266
|
+
const ids = /* @__PURE__ */ new Set();
|
|
267
|
+
let namespace;
|
|
268
|
+
for (const input of inputs) {
|
|
269
|
+
const layerId = nativeInteractionField(input, "layerId");
|
|
270
|
+
const source = nativeInteractionField(input, "source");
|
|
271
|
+
const sourceLayer = nativeInteractionField(input, "sourceLayer");
|
|
272
|
+
const layerCategory = nativeInteractionField(input, "category");
|
|
273
|
+
const kind = nativeInteractionField(input, "representation");
|
|
274
|
+
const priority = nativeInteractionField(input, "priority");
|
|
275
|
+
if (!name(layerId) || !name(source) || sourceLayer !== void 0 && !name(sourceLayer) || !category(layerCategory) || !representation(kind) || typeof priority !== "number" || !Number.isSafeInteger(priority) || priority < 0 || priority > 1e5 || ids.has(layerId) || nativeInteractionField(input, "anchor") !== "pointer-coordinate")
|
|
276
|
+
throw new Error();
|
|
277
|
+
const actual = physical.get(layerId);
|
|
278
|
+
if (!actual || nativeInteractionField(actual, "source") !== source || nativeInteractionField(actual, "source-layer") !== sourceLayer)
|
|
279
|
+
throw new Error();
|
|
280
|
+
const sourceDefinition = nativeInteractionField(sources, source);
|
|
281
|
+
if (!sourceDefinition || typeof sourceDefinition !== "object" || Array.isArray(sourceDefinition))
|
|
282
|
+
throw new Error();
|
|
283
|
+
if (namespace && (namespace.source !== source || namespace.sourceLayer !== sourceLayer))
|
|
284
|
+
throw new Error();
|
|
285
|
+
const layer = Object.freeze({
|
|
286
|
+
layerId,
|
|
287
|
+
source,
|
|
288
|
+
...sourceLayer === void 0 ? {} : { sourceLayer },
|
|
289
|
+
category: layerCategory,
|
|
290
|
+
representation: kind,
|
|
291
|
+
priority
|
|
292
|
+
});
|
|
293
|
+
namespace = layer;
|
|
294
|
+
ids.add(layerId);
|
|
295
|
+
layers.push(layer);
|
|
296
|
+
}
|
|
297
|
+
return Object.freeze({
|
|
298
|
+
layers: Object.freeze(layers.sort((left, right) => right.priority - left.priority)),
|
|
299
|
+
fields,
|
|
300
|
+
representationPriority: Object.freeze(priorityInput)
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
function featureId(value) {
|
|
304
|
+
if (typeof value === "number") return Number.isSafeInteger(value) ? value : void 0;
|
|
305
|
+
return typeof value === "string" && value.length > 0 && value.length <= tileflowInteractionLimits2.maxFeatureIdLength ? value : void 0;
|
|
306
|
+
}
|
|
307
|
+
function properties(input, fields) {
|
|
308
|
+
const read = (key) => {
|
|
309
|
+
try {
|
|
310
|
+
return nativeInteractionField(input, fields[key]);
|
|
311
|
+
} catch {
|
|
312
|
+
return void 0;
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
const result = {};
|
|
316
|
+
const c = read("category");
|
|
317
|
+
if (category(c)) result.category = c;
|
|
318
|
+
for (const [key, output, max] of [
|
|
319
|
+
["filterRank", "filter_rank", 5],
|
|
320
|
+
["sizeRank", "size_rank", 16]
|
|
321
|
+
]) {
|
|
322
|
+
const value = read(key);
|
|
323
|
+
if (typeof value === "number" && Number.isSafeInteger(value) && value >= 0 && value <= max)
|
|
324
|
+
result[output] = value;
|
|
325
|
+
}
|
|
326
|
+
for (const key of ["name", "type", "icon"]) {
|
|
327
|
+
const value = read(key);
|
|
328
|
+
if (typeof value === "string" && value.length <= tileflowInteractionLimits2.maxContentTextLength && (key === "name" || /^[a-z0-9]+(?:_[a-z0-9]+)*$/u.test(value)))
|
|
329
|
+
result[key] = value;
|
|
330
|
+
}
|
|
331
|
+
return Object.freeze(result);
|
|
332
|
+
}
|
|
333
|
+
function choose(features, manifest, bindings, coordinate, queried) {
|
|
334
|
+
const candidates = [];
|
|
335
|
+
const byIdentity = /* @__PURE__ */ new Map();
|
|
336
|
+
const allowed = new Set(queried);
|
|
337
|
+
for (const [renderedIndex, feature] of features.entries()) {
|
|
338
|
+
const id = nativeInteractionField(nativeInteractionField(feature, "layer"), "id");
|
|
339
|
+
const layer = manifest.layers.find((value) => value.layerId === id);
|
|
340
|
+
if (!layer || !allowed.has(layer.layerId)) continue;
|
|
341
|
+
if (nativeInteractionField(feature, "source") !== layer.source || nativeInteractionField(feature, "sourceLayer") !== layer.sourceLayer)
|
|
342
|
+
throw new Error();
|
|
343
|
+
const binding = bindings.find(
|
|
344
|
+
(value) => value.target.kind === "semantic-feature" && value.target.domain === "poi" && (!value.target.categories || value.target.categories.includes(layer.category))
|
|
345
|
+
);
|
|
346
|
+
if (!binding) continue;
|
|
347
|
+
const stable = featureId(nativeInteractionField(feature, "id"));
|
|
348
|
+
const target = freezeNativeInteractionValue({
|
|
349
|
+
kind: "semantic-feature",
|
|
350
|
+
domain: "poi",
|
|
351
|
+
coordinate,
|
|
352
|
+
bindingId: binding.id,
|
|
353
|
+
feature: {
|
|
354
|
+
category: layer.category,
|
|
355
|
+
...stable === void 0 ? {} : { id: stable },
|
|
356
|
+
properties: properties(nativeInteractionField(feature, "properties"), manifest.fields)
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
const candidate = { layer, renderedIndex, match: Object.freeze({ binding, target }) };
|
|
360
|
+
const identity = stable === void 0 ? void 0 : `${typeof stable}:${String(stable)}`;
|
|
361
|
+
const existingIndex = identity === void 0 ? void 0 : byIdentity.get(identity);
|
|
362
|
+
if (existingIndex === void 0) {
|
|
363
|
+
if (identity !== void 0) byIdentity.set(identity, candidates.length);
|
|
364
|
+
candidates.push(candidate);
|
|
365
|
+
} else {
|
|
366
|
+
const existing = candidates[existingIndex];
|
|
367
|
+
const nextPriority = manifest.representationPriority.indexOf(layer.representation);
|
|
368
|
+
const oldPriority = manifest.representationPriority.indexOf(existing.layer.representation);
|
|
369
|
+
if (nextPriority < oldPriority || nextPriority === oldPriority && layer.priority > existing.layer.priority)
|
|
370
|
+
candidates[existingIndex] = {
|
|
371
|
+
...candidate,
|
|
372
|
+
renderedIndex: Math.min(existing.renderedIndex, renderedIndex)
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
return candidates.sort(
|
|
377
|
+
(a, b) => a.renderedIndex - b.renderedIndex || b.layer.priority - a.layer.priority
|
|
378
|
+
)[0]?.match;
|
|
379
|
+
}
|
|
380
|
+
function createNativePoiAdapter() {
|
|
381
|
+
let disposed = false;
|
|
382
|
+
let generation = 0;
|
|
383
|
+
let intent = 0;
|
|
384
|
+
let lease;
|
|
385
|
+
let manifest;
|
|
386
|
+
let pending;
|
|
387
|
+
const inspect = (candidate, expected) => {
|
|
388
|
+
const live = () => !disposed && generation === expected && lease === candidate;
|
|
389
|
+
if (!live()) return "stale";
|
|
390
|
+
try {
|
|
391
|
+
const owned = candidate?.isCurrent() === true;
|
|
392
|
+
return live() && owned ? "current" : "stale";
|
|
393
|
+
} catch {
|
|
394
|
+
return live() ? "error" : "stale";
|
|
395
|
+
}
|
|
396
|
+
};
|
|
397
|
+
const stopPending = () => {
|
|
398
|
+
const job = pending;
|
|
399
|
+
pending = void 0;
|
|
400
|
+
if (!job) return;
|
|
401
|
+
job.live = false;
|
|
402
|
+
job.resolve(stale);
|
|
403
|
+
try {
|
|
404
|
+
job.cancel?.();
|
|
405
|
+
} catch {
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
const cancelQueries = () => {
|
|
409
|
+
++intent;
|
|
410
|
+
stopPending();
|
|
411
|
+
};
|
|
412
|
+
return Object.freeze({
|
|
413
|
+
get available() {
|
|
414
|
+
const parsed = manifest;
|
|
415
|
+
return !!parsed && inspect(lease, generation) === "current" && manifest === parsed;
|
|
416
|
+
},
|
|
417
|
+
supports(target) {
|
|
418
|
+
const parsed = manifest;
|
|
419
|
+
return !!parsed && inspect(lease, generation) === "current" && manifest === parsed && parsed.layers.some((layer) => layer.category === target.feature.category);
|
|
420
|
+
},
|
|
421
|
+
replaceStyle(next) {
|
|
422
|
+
if (disposed) return emptyDiagnostics;
|
|
423
|
+
const expected = ++generation;
|
|
424
|
+
manifest = void 0;
|
|
425
|
+
lease = next;
|
|
426
|
+
cancelQueries();
|
|
427
|
+
if (!next || inspect(next, expected) !== "current")
|
|
428
|
+
return next && generation === expected ? failure().diagnostics : emptyDiagnostics;
|
|
429
|
+
try {
|
|
430
|
+
const parsed = parseManifest(next.style);
|
|
431
|
+
if (inspect(next, expected) === "current") {
|
|
432
|
+
manifest = parsed;
|
|
433
|
+
return emptyDiagnostics;
|
|
434
|
+
}
|
|
435
|
+
} catch {
|
|
436
|
+
}
|
|
437
|
+
return generation === expected ? failure().diagnostics : emptyDiagnostics;
|
|
438
|
+
},
|
|
439
|
+
cancelQueries,
|
|
440
|
+
queryTouch(input, bindingsInput) {
|
|
441
|
+
const ticket = ++intent;
|
|
442
|
+
const expected = generation;
|
|
443
|
+
const invocationIsLive = () => !disposed && intent === ticket && generation === expected;
|
|
444
|
+
const answer = (value) => Promise.resolve(invocationIsLive() ? value : stale);
|
|
445
|
+
stopPending();
|
|
446
|
+
if (!invocationIsLive()) return Promise.resolve(stale);
|
|
447
|
+
const owner = lease;
|
|
448
|
+
const selected = manifest;
|
|
449
|
+
let point;
|
|
450
|
+
let coordinate;
|
|
451
|
+
try {
|
|
452
|
+
if (nativeInteractionField(input, "inputModality") !== "touch") return answer(failure("UNSUPPORTED_MODE"));
|
|
453
|
+
const p = array(nativeInteractionField(input, "point"), 2);
|
|
454
|
+
const c = array(nativeInteractionField(input, "coordinate"), 2);
|
|
455
|
+
if (p.length !== 2 || c.length !== 2 || !p.every(
|
|
456
|
+
(value) => typeof value === "number" && Number.isFinite(value) && value >= 0 && value <= 1e7
|
|
457
|
+
) || !c.every((value) => typeof value === "number" && Number.isFinite(value)) || typeof p[0] !== "number" || typeof p[1] !== "number" || typeof c[0] !== "number" || typeof c[1] !== "number" || c[0] < -180 || c[0] > 180 || c[1] < -90 || c[1] > 90)
|
|
458
|
+
throw new Error();
|
|
459
|
+
point = Object.freeze([p[0], p[1]]);
|
|
460
|
+
coordinate = Object.freeze([c[0], c[1]]);
|
|
461
|
+
} catch {
|
|
462
|
+
return answer(failure("INVALID_DOCUMENT"));
|
|
463
|
+
}
|
|
464
|
+
const prepared = prepareNativeInteractionInputs({ interactions: bindingsInput });
|
|
465
|
+
if (prepared.diagnostics.length)
|
|
466
|
+
return answer(Object.freeze({ status: "error", diagnostics: prepared.diagnostics }));
|
|
467
|
+
const bindings = prepared.bindings.filter(
|
|
468
|
+
(binding) => binding.target.kind === "semantic-feature" && binding.target.domain === "poi"
|
|
469
|
+
);
|
|
470
|
+
if (!bindings.length)
|
|
471
|
+
return answer(prepared.bindings.length ? failure("UNSUPPORTED_TARGET") : miss);
|
|
472
|
+
if (!owner || !selected) return answer(failure());
|
|
473
|
+
const ownership = inspect(owner, expected);
|
|
474
|
+
if (ownership !== "current") return answer(ownership === "error" ? failure() : stale);
|
|
475
|
+
const layers = selected.layers.filter(
|
|
476
|
+
(layer) => bindings.some(
|
|
477
|
+
(binding) => binding.target.kind === "semantic-feature" && (!binding.target.categories || binding.target.categories.includes(layer.category))
|
|
478
|
+
)
|
|
479
|
+
).map((layer) => layer.layerId);
|
|
480
|
+
if (!layers.length) return answer(miss);
|
|
481
|
+
if (!invocationIsLive()) return Promise.resolve(stale);
|
|
482
|
+
const request = Object.freeze({
|
|
483
|
+
point,
|
|
484
|
+
layers: Object.freeze(layers),
|
|
485
|
+
limit: nativePoiQueryLimit
|
|
486
|
+
});
|
|
487
|
+
let resolve;
|
|
488
|
+
const result = new Promise((yes) => {
|
|
489
|
+
resolve = yes;
|
|
490
|
+
});
|
|
491
|
+
const job = { live: true, resolve };
|
|
492
|
+
pending = job;
|
|
493
|
+
const finish = (value) => {
|
|
494
|
+
if (!job.live || pending !== job) return;
|
|
495
|
+
const ownership2 = inspect(owner, expected);
|
|
496
|
+
if (!job.live || pending !== job) return;
|
|
497
|
+
pending = void 0;
|
|
498
|
+
job.live = false;
|
|
499
|
+
resolve(
|
|
500
|
+
ownership2 === "error" ? failure() : ownership2 === "current" && invocationIsLive() ? value : stale
|
|
501
|
+
);
|
|
502
|
+
};
|
|
503
|
+
try {
|
|
504
|
+
const operation = owner.query(request);
|
|
505
|
+
const cancel = operation.cancel;
|
|
506
|
+
if (typeof cancel !== "function") throw new Error();
|
|
507
|
+
let cancelled = false;
|
|
508
|
+
job.cancel = () => {
|
|
509
|
+
if (!cancelled) {
|
|
510
|
+
cancelled = true;
|
|
511
|
+
cancel.call(operation);
|
|
512
|
+
}
|
|
513
|
+
};
|
|
514
|
+
void Promise.resolve(operation.result).then(
|
|
515
|
+
(value) => {
|
|
516
|
+
if (!job.live || pending !== job) return;
|
|
517
|
+
try {
|
|
518
|
+
const ownership2 = inspect(owner, expected);
|
|
519
|
+
if (ownership2 !== "current") {
|
|
520
|
+
finish(ownership2 === "error" ? failure() : stale);
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
if (nativeInteractionField(value, "request") !== request) throw new Error();
|
|
524
|
+
const raw = nativeInteractionField(value, "features");
|
|
525
|
+
const length = Array.isArray(raw) ? Object.getOwnPropertyDescriptor(raw, "length")?.value : void 0;
|
|
526
|
+
if (typeof length === "number" && length > nativePoiQueryLimit) {
|
|
527
|
+
finish(failure("LIMIT_EXCEEDED"));
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
const match = choose(
|
|
531
|
+
array(raw, nativePoiQueryLimit),
|
|
532
|
+
selected,
|
|
533
|
+
bindings,
|
|
534
|
+
coordinate,
|
|
535
|
+
layers
|
|
536
|
+
);
|
|
537
|
+
finish(
|
|
538
|
+
match ? Object.freeze({ status: "match", match, diagnostics: emptyDiagnostics }) : miss
|
|
539
|
+
);
|
|
540
|
+
} catch {
|
|
541
|
+
finish(failure());
|
|
542
|
+
}
|
|
543
|
+
},
|
|
544
|
+
() => finish(failure())
|
|
545
|
+
);
|
|
546
|
+
if (!job.live || pending !== job || inspect(owner, expected) !== "current") {
|
|
547
|
+
if (pending === job) cancelQueries();
|
|
548
|
+
else {
|
|
549
|
+
try {
|
|
550
|
+
job.cancel();
|
|
551
|
+
} catch {
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
} catch {
|
|
556
|
+
finish(failure());
|
|
557
|
+
try {
|
|
558
|
+
job.cancel?.();
|
|
559
|
+
} catch {
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
return result;
|
|
563
|
+
},
|
|
564
|
+
dispose() {
|
|
565
|
+
if (disposed) return;
|
|
566
|
+
disposed = true;
|
|
567
|
+
++generation;
|
|
568
|
+
lease = void 0;
|
|
569
|
+
manifest = void 0;
|
|
570
|
+
cancelQueries();
|
|
571
|
+
}
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// src/native-interaction-owner.ts
|
|
576
|
+
var ignoreFailure = (work) => {
|
|
577
|
+
try {
|
|
578
|
+
void Promise.resolve(work()).catch(() => void 0);
|
|
579
|
+
} catch {
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
function createNativeInteractionOwner(initial = {}, initialCallbacks = {}) {
|
|
583
|
+
let disposed = false;
|
|
584
|
+
let transaction = 0;
|
|
585
|
+
let queryGeneration = 0;
|
|
586
|
+
let revision = 0;
|
|
587
|
+
let callbacks = initialCallbacks;
|
|
588
|
+
let prepared;
|
|
589
|
+
let styleLease;
|
|
590
|
+
let styleDiagnostics = [];
|
|
591
|
+
let runtimeDiagnostics = [];
|
|
592
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
593
|
+
const semantic = createNativePoiAdapter();
|
|
594
|
+
const empty = prepareNativeInteractionInputs({});
|
|
595
|
+
let snapshot = Object.freeze({
|
|
596
|
+
...empty,
|
|
597
|
+
revision,
|
|
598
|
+
plan: planNativeAnnotations([], []),
|
|
599
|
+
disposed
|
|
600
|
+
});
|
|
601
|
+
const live = (version) => !disposed && transaction === version;
|
|
602
|
+
const activate = (target) => {
|
|
603
|
+
const value = freezeNativeInteractionValue({
|
|
604
|
+
type: "target:activate",
|
|
605
|
+
target,
|
|
606
|
+
coordinate: target.coordinate,
|
|
607
|
+
inputModality: "touch",
|
|
608
|
+
...target.bindingId === void 0 ? {} : { bindingId: target.bindingId }
|
|
609
|
+
});
|
|
610
|
+
ignoreFailure(() => callbacks.onInteractionEvent?.(value));
|
|
611
|
+
};
|
|
612
|
+
const commit = (data, plan, version) => {
|
|
613
|
+
if (!live(version)) return;
|
|
614
|
+
const previous = snapshot;
|
|
615
|
+
const diagnostics = [];
|
|
616
|
+
const semanticBindings = data.bindings.some(
|
|
617
|
+
(binding) => binding.target.kind === "semantic-feature" && binding.target.domain === "poi"
|
|
618
|
+
);
|
|
619
|
+
const unsupported = data.bindings.some(
|
|
620
|
+
(binding) => binding.target.kind !== "annotation" && (binding.target.kind !== "semantic-feature" || binding.target.domain !== "poi")
|
|
621
|
+
);
|
|
622
|
+
for (const diagnostic of [
|
|
623
|
+
...data.diagnostics,
|
|
624
|
+
...semanticBindings ? styleDiagnostics : [],
|
|
625
|
+
...runtimeDiagnostics,
|
|
626
|
+
...unsupported ? [nativeInteractionDiagnostic("UNSUPPORTED_TARGET")] : []
|
|
627
|
+
])
|
|
628
|
+
if (!diagnostics.some((value) => value.code === diagnostic.code))
|
|
629
|
+
diagnostics.push(diagnostic);
|
|
630
|
+
prepared = data;
|
|
631
|
+
if (previous.annotations === data.annotations && previous.bindings === data.bindings && nativeInteractionValuesEqual(previous.diagnostics, diagnostics))
|
|
632
|
+
return;
|
|
633
|
+
snapshot = Object.freeze({
|
|
634
|
+
...data,
|
|
635
|
+
diagnostics: Object.freeze(diagnostics),
|
|
636
|
+
revision: ++revision,
|
|
637
|
+
plan,
|
|
638
|
+
disposed: false
|
|
639
|
+
});
|
|
640
|
+
for (const listener of [...subscribers]) {
|
|
641
|
+
if (!live(version)) return;
|
|
642
|
+
if (subscribers.has(listener)) ignoreFailure(listener);
|
|
643
|
+
}
|
|
644
|
+
for (const diagnostic of diagnostics) {
|
|
645
|
+
if (!live(version)) return;
|
|
646
|
+
if (!previous.diagnostics.some((value) => value.code === diagnostic.code))
|
|
647
|
+
ignoreFailure(() => callbacks.onDiagnostic?.(diagnostic));
|
|
648
|
+
}
|
|
649
|
+
};
|
|
650
|
+
const report = (code) => {
|
|
651
|
+
if (disposed || !prepared) return;
|
|
652
|
+
const version = ++transaction;
|
|
653
|
+
runtimeDiagnostics = [nativeInteractionDiagnostic(code)];
|
|
654
|
+
commit(prepared, planNativeAnnotations(prepared.annotations, prepared.annotations), version);
|
|
655
|
+
};
|
|
656
|
+
const update = (input) => {
|
|
657
|
+
if (disposed) return;
|
|
658
|
+
const inspected = transaction;
|
|
659
|
+
const next = prepareNativeInteractionInputs(input, prepared);
|
|
660
|
+
if (!live(inspected)) return;
|
|
661
|
+
const changed = !prepared || next.annotations !== prepared.annotations || next.bindings !== prepared.bindings;
|
|
662
|
+
const same = !changed && !runtimeDiagnostics.length && nativeInteractionValuesEqual(next.diagnostics, prepared?.diagnostics);
|
|
663
|
+
if (same) return;
|
|
664
|
+
const version = ++transaction;
|
|
665
|
+
if (changed) {
|
|
666
|
+
++queryGeneration;
|
|
667
|
+
semantic.cancelQueries();
|
|
668
|
+
if (!live(version)) return;
|
|
669
|
+
}
|
|
670
|
+
runtimeDiagnostics = [];
|
|
671
|
+
commit(next, planNativeAnnotations(prepared?.annotations ?? [], next.annotations), version);
|
|
672
|
+
};
|
|
673
|
+
const dispose = () => {
|
|
674
|
+
if (disposed) return;
|
|
675
|
+
disposed = true;
|
|
676
|
+
++transaction;
|
|
677
|
+
++queryGeneration;
|
|
678
|
+
styleLease = void 0;
|
|
679
|
+
semantic.dispose();
|
|
680
|
+
subscribers.clear();
|
|
681
|
+
callbacks = {};
|
|
682
|
+
snapshot = Object.freeze({
|
|
683
|
+
...empty,
|
|
684
|
+
revision: ++revision,
|
|
685
|
+
plan: planNativeAnnotations(snapshot.annotations, []),
|
|
686
|
+
disposed: true
|
|
687
|
+
});
|
|
688
|
+
prepared = void 0;
|
|
689
|
+
styleDiagnostics = [];
|
|
690
|
+
runtimeDiagnostics = [];
|
|
691
|
+
};
|
|
692
|
+
update(initial);
|
|
693
|
+
return Object.freeze({
|
|
694
|
+
getSnapshot: () => snapshot,
|
|
695
|
+
subscribe(listener) {
|
|
696
|
+
if (disposed) return () => void 0;
|
|
697
|
+
if (subscribers.size >= 64) {
|
|
698
|
+
report("LIMIT_EXCEEDED");
|
|
699
|
+
return () => void 0;
|
|
700
|
+
}
|
|
701
|
+
subscribers.add(listener);
|
|
702
|
+
return () => {
|
|
703
|
+
subscribers.delete(listener);
|
|
704
|
+
};
|
|
705
|
+
},
|
|
706
|
+
setCallbacks(next) {
|
|
707
|
+
if (!disposed) callbacks = next;
|
|
708
|
+
},
|
|
709
|
+
update,
|
|
710
|
+
replaceStyle(next) {
|
|
711
|
+
if (disposed || !prepared) return;
|
|
712
|
+
const version = ++transaction;
|
|
713
|
+
++queryGeneration;
|
|
714
|
+
styleLease = next;
|
|
715
|
+
styleDiagnostics = semantic.replaceStyle(next);
|
|
716
|
+
if (!live(version)) return;
|
|
717
|
+
runtimeDiagnostics = [];
|
|
718
|
+
commit(prepared, planNativeAnnotations(prepared.annotations, prepared.annotations), version);
|
|
719
|
+
},
|
|
720
|
+
/** Rotate touch authority only while both leases prove the same still-owned style. */
|
|
721
|
+
renewTouchLease(next) {
|
|
722
|
+
if (disposed || !prepared) return false;
|
|
723
|
+
const inspected = transaction;
|
|
724
|
+
const previous = styleLease;
|
|
725
|
+
try {
|
|
726
|
+
if (!previous || previous.style !== next.style || !previous.isCurrent() || !next.isCurrent())
|
|
727
|
+
return false;
|
|
728
|
+
} catch {
|
|
729
|
+
return false;
|
|
730
|
+
}
|
|
731
|
+
if (!live(inspected) || styleLease !== previous) return false;
|
|
732
|
+
const version = ++transaction;
|
|
733
|
+
++queryGeneration;
|
|
734
|
+
styleLease = next;
|
|
735
|
+
styleDiagnostics = semantic.replaceStyle(next);
|
|
736
|
+
if (!live(version)) return false;
|
|
737
|
+
commit(prepared, planNativeAnnotations(prepared.annotations, prepared.annotations), version);
|
|
738
|
+
return live(version) && styleLease === next;
|
|
739
|
+
},
|
|
740
|
+
activateAnnotation(id, inputModality) {
|
|
741
|
+
if (disposed || !prepared) return;
|
|
742
|
+
if (inputModality !== "touch") {
|
|
743
|
+
report("UNSUPPORTED_MODE");
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
const version = ++transaction;
|
|
747
|
+
++queryGeneration;
|
|
748
|
+
semantic.cancelQueries();
|
|
749
|
+
if (!live(version)) return;
|
|
750
|
+
const annotation = prepared.annotations.find((value) => value.id === id);
|
|
751
|
+
if (!annotation) {
|
|
752
|
+
report("STALE_TARGET");
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
const binding = prepared.bindings.find(
|
|
756
|
+
(value) => value.target.kind === "annotation" && value.target.id === id
|
|
757
|
+
);
|
|
758
|
+
const target = freezeNativeInteractionValue({
|
|
759
|
+
kind: "annotation",
|
|
760
|
+
annotation,
|
|
761
|
+
coordinate: annotation.coordinate,
|
|
762
|
+
...binding ? { bindingId: binding.id } : {}
|
|
763
|
+
});
|
|
764
|
+
activate(target);
|
|
765
|
+
},
|
|
766
|
+
async activateTouch(input) {
|
|
767
|
+
if (disposed || !prepared) return;
|
|
768
|
+
const version = ++transaction;
|
|
769
|
+
const query = ++queryGeneration;
|
|
770
|
+
const result = await semantic.queryTouch(
|
|
771
|
+
input,
|
|
772
|
+
prepared.bindings.filter((binding) => binding.target.kind === "semantic-feature")
|
|
773
|
+
);
|
|
774
|
+
if (!live(version) || query !== queryGeneration || result.status === "stale") return;
|
|
775
|
+
if (result.status === "error") {
|
|
776
|
+
if (result.diagnostics[0]) report(result.diagnostics[0].code);
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
779
|
+
if (result.status === "match") activate(result.match.target);
|
|
780
|
+
},
|
|
781
|
+
/** Retires only touch intent; application selection remains untouched. */
|
|
782
|
+
cancelTouch() {
|
|
783
|
+
if (disposed) return;
|
|
784
|
+
++transaction;
|
|
785
|
+
++queryGeneration;
|
|
786
|
+
semantic.cancelQueries();
|
|
787
|
+
},
|
|
788
|
+
retireSource: dispose,
|
|
789
|
+
dispose
|
|
790
|
+
});
|
|
791
|
+
}
|
|
792
|
+
export {
|
|
793
|
+
createNativeInteractionOwner
|
|
794
|
+
};
|