@tileflow/react-native 0.1.0-alpha.1 → 0.1.0-alpha.3

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.js CHANGED
@@ -2,8 +2,8 @@ var __defProp = Object.defineProperty;
2
2
  var __typeError = (msg) => {
3
3
  throw TypeError(msg);
4
4
  };
5
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
+ var __defNormalProp = (obj, key2, value) => key2 in obj ? __defProp(obj, key2, { enumerable: true, configurable: true, writable: true, value }) : obj[key2] = value;
6
+ var __publicField = (obj, key2, value) => __defNormalProp(obj, typeof key2 !== "symbol" ? key2 + "" : key2, value);
7
7
  var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
8
8
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
9
9
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
@@ -53,11 +53,11 @@ function nativeInteractionDiagnostic(code) {
53
53
  message: messages[code]
54
54
  });
55
55
  }
56
- function nativeInteractionField(value, key) {
56
+ function nativeInteractionField(value, key2) {
57
57
  if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error();
58
58
  const prototype = Object.getPrototypeOf(value);
59
59
  if (prototype !== null && prototype !== Object.prototype) throw new Error();
60
- const descriptor = Object.getOwnPropertyDescriptor(value, key);
60
+ const descriptor = Object.getOwnPropertyDescriptor(value, key2);
61
61
  if (!descriptor) return void 0;
62
62
  if (!("value" in descriptor) || !descriptor.enumerable) throw new Error();
63
63
  return descriptor.value;
@@ -92,18 +92,18 @@ function snapshotNativeInteractionJson(input) {
92
92
  if (keys2.length > length2 + 1) throw new Error();
93
93
  const result2 = new Array(length2);
94
94
  let sawLength = false;
95
- for (const key of keys2) {
96
- if (typeof key !== "string") throw new Error();
97
- if (key === "length") {
95
+ for (const key2 of keys2) {
96
+ if (typeof key2 !== "string") throw new Error();
97
+ if (key2 === "length") {
98
98
  sawLength = true;
99
99
  continue;
100
100
  }
101
- const index = Number(key);
102
- if (!Number.isSafeInteger(index) || index < 0 || index >= length2 || String(index) !== key)
101
+ const index = Number(key2);
102
+ if (!Number.isSafeInteger(index) || index < 0 || index >= length2 || String(index) !== key2)
103
103
  throw new Error();
104
- const descriptor = Object.getOwnPropertyDescriptor(value, key);
104
+ const descriptor = Object.getOwnPropertyDescriptor(value, key2);
105
105
  if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) throw new Error();
106
- Object.defineProperty(result2, key, {
106
+ Object.defineProperty(result2, key2, {
107
107
  value: copy(descriptor.value, depth + 1),
108
108
  enumerable: true,
109
109
  configurable: true,
@@ -118,12 +118,12 @@ function snapshotNativeInteractionJson(input) {
118
118
  throw new Error();
119
119
  properties2 += keys.length;
120
120
  const result = {};
121
- for (const key of keys) {
122
- if (typeof key !== "string" || key === "__proto__" || key === "prototype" || key === "constructor")
121
+ for (const key2 of keys) {
122
+ if (typeof key2 !== "string" || key2 === "__proto__" || key2 === "prototype" || key2 === "constructor")
123
123
  throw new Error();
124
- const descriptor = Object.getOwnPropertyDescriptor(value, key);
124
+ const descriptor = Object.getOwnPropertyDescriptor(value, key2);
125
125
  if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) throw new Error();
126
- result[key] = copy(descriptor.value, depth + 1);
126
+ result[key2] = copy(descriptor.value, depth + 1);
127
127
  }
128
128
  return Object.freeze(result);
129
129
  };
@@ -148,9 +148,9 @@ function nativeInteractionValuesEqual(left, right) {
148
148
  const a = Object.keys(left).sort();
149
149
  const b = Object.keys(right).sort();
150
150
  return a.length === b.length && a.every(
151
- (key, index) => key === b[index] && nativeInteractionValuesEqual(
152
- Object.getOwnPropertyDescriptor(left, key)?.value,
153
- Object.getOwnPropertyDescriptor(right, key)?.value
151
+ (key2, index) => key2 === b[index] && nativeInteractionValuesEqual(
152
+ Object.getOwnPropertyDescriptor(left, key2)?.value,
153
+ Object.getOwnPropertyDescriptor(right, key2)?.value
154
154
  )
155
155
  );
156
156
  }
@@ -267,8 +267,8 @@ function parseManifest(style) {
267
267
  if (priorityInput.length !== 4 || !priorityInput.every(representation) || new Set(priorityInput).size !== 4)
268
268
  throw new Error();
269
269
  const fieldsInput = nativeInteractionField(poi, "fields");
270
- const readField = (key) => {
271
- const value = nativeInteractionField(fieldsInput, key);
270
+ const readField = (key2) => {
271
+ const value = nativeInteractionField(fieldsInput, key2);
272
272
  if (!name(value)) throw new Error();
273
273
  return value;
274
274
  };
@@ -332,9 +332,9 @@ function featureId(value) {
332
332
  return typeof value === "string" && value.length > 0 && value.length <= tileflowInteractionLimits2.maxFeatureIdLength ? value : void 0;
333
333
  }
334
334
  function properties(input, fields) {
335
- const read = (key) => {
335
+ const read = (key2) => {
336
336
  try {
337
- return nativeInteractionField(input, fields[key]);
337
+ return nativeInteractionField(input, fields[key2]);
338
338
  } catch {
339
339
  return void 0;
340
340
  }
@@ -342,18 +342,18 @@ function properties(input, fields) {
342
342
  const result = {};
343
343
  const c = read("category");
344
344
  if (category(c)) result.category = c;
345
- for (const [key, output, max] of [
345
+ for (const [key2, output, max] of [
346
346
  ["filterRank", "filter_rank", 5],
347
347
  ["sizeRank", "size_rank", 16]
348
348
  ]) {
349
- const value = read(key);
349
+ const value = read(key2);
350
350
  if (typeof value === "number" && Number.isSafeInteger(value) && value >= 0 && value <= max)
351
351
  result[output] = value;
352
352
  }
353
- for (const key of ["name", "type", "icon"]) {
354
- const value = read(key);
355
- if (typeof value === "string" && value.length <= tileflowInteractionLimits2.maxContentTextLength && (key === "name" || /^[a-z0-9]+(?:_[a-z0-9]+)*$/u.test(value)))
356
- result[key] = value;
353
+ for (const key2 of ["name", "type", "icon"]) {
354
+ const value = read(key2);
355
+ if (typeof value === "string" && value.length <= tileflowInteractionLimits2.maxContentTextLength && (key2 === "name" || /^[a-z0-9]+(?:_[a-z0-9]+)*$/u.test(value)))
356
+ result[key2] = value;
357
357
  }
358
358
  return Object.freeze(result);
359
359
  }
@@ -1098,9 +1098,9 @@ function createMountedMapInteractions(getStyle, changed) {
1098
1098
  if (disposed) return;
1099
1099
  const version = ++propsVersion;
1100
1100
  let invalidCallback = false;
1101
- const callback = (key) => {
1101
+ const callback = (key2) => {
1102
1102
  try {
1103
- const descriptor = Object.getOwnPropertyDescriptor(props, key);
1103
+ const descriptor = Object.getOwnPropertyDescriptor(props, key2);
1104
1104
  if (!descriptor) return void 0;
1105
1105
  if (!("value" in descriptor) || !descriptor.enumerable || descriptor.value !== void 0 && typeof descriptor.value !== "function")
1106
1106
  throw new Error();
@@ -1262,9 +1262,9 @@ function createMapLifecycle(create, retire) {
1262
1262
  if (refreshAgain && active && active !== epoch) refresh(active);
1263
1263
  }
1264
1264
  };
1265
- const forScene = (key) => {
1265
+ const forScene = (key2) => {
1266
1266
  const epoch = active;
1267
- return epoch?.owner.getSnapshot().renderer?.key === key ? epoch : void 0;
1267
+ return epoch?.owner.getSnapshot().renderer?.key === key2 ? epoch : void 0;
1268
1268
  };
1269
1269
  return Object.freeze({
1270
1270
  getSnapshot: () => snapshot,
@@ -1318,29 +1318,29 @@ function createMapLifecycle(create, retire) {
1318
1318
  unbindInteractionHost(host) {
1319
1319
  active?.interactions.unbind(host);
1320
1320
  },
1321
- beginTouch(key) {
1322
- forScene(key)?.interactions.beginTouch();
1321
+ beginTouch(key2) {
1322
+ forScene(key2)?.interactions.beginTouch();
1323
1323
  },
1324
- claimMarker(key, annotation) {
1325
- forScene(key)?.interactions.claimMarker(annotation);
1324
+ claimMarker(key2, annotation) {
1325
+ forScene(key2)?.interactions.claimMarker(annotation);
1326
1326
  },
1327
- markerPress(key, annotation) {
1328
- forScene(key)?.interactions.markerPress(annotation);
1327
+ markerPress(key2, annotation) {
1328
+ forScene(key2)?.interactions.markerPress(annotation);
1329
1329
  },
1330
- mapPress(key, input) {
1331
- void forScene(key)?.interactions.mapPress(input).catch(() => void 0);
1330
+ mapPress(key2, input) {
1331
+ void forScene(key2)?.interactions.mapPress(input).catch(() => void 0);
1332
1332
  },
1333
- interactionDiagnostic(key, code) {
1334
- forScene(key)?.interactions.report(code);
1333
+ interactionDiagnostic(key2, code) {
1334
+ forScene(key2)?.interactions.report(code);
1335
1335
  },
1336
- rootMounted(key, root) {
1337
- active?.owner.rootMounted(key, root);
1336
+ rootMounted(key2, root) {
1337
+ active?.owner.rootMounted(key2, root);
1338
1338
  },
1339
- nativeStyleLoaded(key, root) {
1340
- active?.owner.nativeStyleLoaded(key, root);
1339
+ nativeStyleLoaded(key2, root) {
1340
+ active?.owner.nativeStyleLoaded(key2, root);
1341
1341
  },
1342
- layoutChanged(key) {
1343
- active?.owner.layoutChanged(key);
1342
+ layoutChanged(key2) {
1343
+ active?.owner.layoutChanged(key2);
1344
1344
  },
1345
1345
  background() {
1346
1346
  active?.interactions.background();
@@ -1637,11 +1637,11 @@ function hasReservedNativeContext(url) {
1637
1637
  const query = url.indexOf("?");
1638
1638
  if (query < 0) return false;
1639
1639
  return url.slice(query + 1).split("&").some((part) => {
1640
- const key = part.split("=", 1)[0].replace(
1640
+ const key2 = part.split("=", 1)[0].replace(
1641
1641
  /%([0-9a-f]{2})/giu,
1642
1642
  (_, hex) => String.fromCharCode(Number.parseInt(hex, 16))
1643
1643
  );
1644
- return key.toLowerCase().startsWith("__tf_native");
1644
+ return key2.toLowerCase().startsWith("__tf_native");
1645
1645
  });
1646
1646
  }
1647
1647
  function nativeResourceOrigin(url) {
@@ -2341,7 +2341,7 @@ function normalizeBinding(value) {
2341
2341
  return Object.freeze({ kind: "direct" });
2342
2342
  }
2343
2343
  if (value.kind !== "hosted" || Object.keys(value).some(
2344
- (key) => !["kind", "apiOrigin", "credential", "mapId", "surfaceId"].includes(key)
2344
+ (key2) => !["kind", "apiOrigin", "credential", "mapId", "surfaceId"].includes(key2)
2345
2345
  ) || typeof value.credential !== "string" || !MOBILE_CREDENTIAL.test(value.credential) || typeof value.mapId !== "string" || !MAP_ID.test(value.mapId)) {
2346
2346
  throw new Error();
2347
2347
  }
@@ -2395,7 +2395,7 @@ function snapshotIdle(binding, session, lifecycle) {
2395
2395
  });
2396
2396
  }
2397
2397
  function parseSuccess(value, binding, expectedSessionId, expectedSurfaceId) {
2398
- if (!isRecord(value) || Object.keys(value).length !== SUCCESS_KEYS.size || Object.keys(value).some((key) => !SUCCESS_KEYS.has(key)) || value.ok !== true || value.kind !== "native" || value.version !== 1 || value.usageMode !== "session" || value.counted !== false || value.mapId !== binding.mapId || value.sessionId !== expectedSessionId || value.surfaceId !== expectedSurfaceId || typeof value.surfaceId !== "string" || !SURFACE_ID.test(value.surfaceId) || secretShaped(value.surfaceId) || typeof value.credentialId !== "string" || !CREDENTIAL_ID.test(value.credentialId) || !positiveRevision(value.credentialRevision) || !positiveRevision(value.deliveryPolicyRevision) || typeof value.grant !== "string" || value.grant.length === 0 || value.grant.length > GRANT_CHARACTER_LIMIT || !NATIVE_GRANT.test(value.grant) || !["disabled", "shadow", "enforced"].includes(String(value.meterMode)) || !["unmetered", "ordinary", "unbilled_fail_open"].includes(String(value.disposition)) || value.disposition === "unmetered" && value.meterMode !== "disabled") {
2398
+ if (!isRecord(value) || Object.keys(value).length !== SUCCESS_KEYS.size || Object.keys(value).some((key2) => !SUCCESS_KEYS.has(key2)) || value.ok !== true || value.kind !== "native" || value.version !== 1 || value.usageMode !== "session" || value.counted !== false || value.mapId !== binding.mapId || value.sessionId !== expectedSessionId || value.surfaceId !== expectedSurfaceId || typeof value.surfaceId !== "string" || !SURFACE_ID.test(value.surfaceId) || secretShaped(value.surfaceId) || typeof value.credentialId !== "string" || !CREDENTIAL_ID.test(value.credentialId) || !positiveRevision(value.credentialRevision) || !positiveRevision(value.deliveryPolicyRevision) || typeof value.grant !== "string" || value.grant.length === 0 || value.grant.length > GRANT_CHARACTER_LIMIT || !NATIVE_GRANT.test(value.grant) || !["disabled", "shadow", "enforced"].includes(String(value.meterMode)) || !["unmetered", "ordinary", "unbilled_fail_open"].includes(String(value.disposition)) || value.disposition === "unmetered" && value.meterMode !== "disabled") {
2399
2399
  throw new HostedNativeSessionError("NATIVE_SESSION_RESPONSE_INVALID");
2400
2400
  }
2401
2401
  const issuedAtMs = parseExactIso(value.issuedAt);
@@ -2493,7 +2493,7 @@ function positiveRevision(value) {
2493
2493
  return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
2494
2494
  }
2495
2495
  function isExactRestart(value, expectedSessionId) {
2496
- return isRecord(value) && Object.keys(value).length === RESTART_KEYS.size && Object.keys(value).every((key) => RESTART_KEYS.has(key)) && value.code === "COMMERCIAL_SESSION_RESTART_REQUIRED" && typeof value.error === "string" && value.error.length > 0 && value.error.length <= 500 && value.retryWithNewSession === true && value.sessionId === expectedSessionId;
2496
+ return isRecord(value) && Object.keys(value).length === RESTART_KEYS.size && Object.keys(value).every((key2) => RESTART_KEYS.has(key2)) && value.code === "COMMERCIAL_SESSION_RESTART_REQUIRED" && typeof value.error === "string" && value.error.length > 0 && value.error.length <= 500 && value.retryWithNewSession === true && value.sessionId === expectedSessionId;
2497
2497
  }
2498
2498
  async function readBoundedResponse(response, abort) {
2499
2499
  let reader;
@@ -2933,10 +2933,11 @@ function createNativeAdmissionOwner(options) {
2933
2933
  if (options.sessionFetch) boundFetch = options.sessionFetch(registered.context);
2934
2934
  let retirement;
2935
2935
  let retirementNotified = false;
2936
- const catalog = createNativeAdmissionCatalog(resources, registered.context, (additions) => {
2937
- if (!bridge.extendContext) return Promise.reject(cancel("NATIVE_ADMISSION_UNAVAILABLE"));
2938
- return bridge.extendContext(ack.installation, registered.context, additions);
2939
- });
2936
+ const catalog = createNativeAdmissionCatalog(
2937
+ resources,
2938
+ registered.context,
2939
+ (additions) => bridge.extendContext(ack.installation, registered.context, additions)
2940
+ );
2940
2941
  const context = {
2941
2942
  id: registered.context,
2942
2943
  generation: registered.generation,
@@ -3217,6 +3218,8 @@ function createAdmissionInstallation(create) {
3217
3218
  // src/mounted-map-owner.ts
3218
3219
  import {
3219
3220
  createTileflowNativeSourceController,
3221
+ nearestTileflowBlendTheme,
3222
+ planTileflowThemeBlend,
3220
3223
  resolveTileflowNativeManifestUrl as resolveTileflowNativeManifestUrl5
3221
3224
  } from "@tileflow/core/native";
3222
3225
 
@@ -3252,18 +3255,18 @@ function ownRecord(value, allowed2) {
3252
3255
  const keys = Reflect.ownKeys(value);
3253
3256
  if (keys.length > allowed2.length) return fail();
3254
3257
  const copy = /* @__PURE__ */ Object.create(null);
3255
- for (const key of keys) {
3256
- if (typeof key !== "string" || !allowed2.includes(key)) return fail();
3257
- const property = Object.getOwnPropertyDescriptor(value, key);
3258
+ for (const key2 of keys) {
3259
+ if (typeof key2 !== "string" || !allowed2.includes(key2)) return fail();
3260
+ const property = Object.getOwnPropertyDescriptor(value, key2);
3258
3261
  if (!property?.enumerable || !("value" in property)) return fail();
3259
- copy[key] = property.value;
3262
+ copy[key2] = property.value;
3260
3263
  }
3261
3264
  return copy;
3262
3265
  }
3263
3266
  function requireCompleteView(value) {
3264
3267
  if (!value || typeof value !== "object") return fail();
3265
- for (const key of ["center", "zoom", "bearing", "pitch"]) {
3266
- const property = Object.getOwnPropertyDescriptor(value, key);
3268
+ for (const key2 of ["center", "zoom", "bearing", "pitch"]) {
3269
+ const property = Object.getOwnPropertyDescriptor(value, key2);
3267
3270
  if (!property || !("value" in property) || property.value === void 0) return fail();
3268
3271
  }
3269
3272
  }
@@ -3351,11 +3354,11 @@ function configurationRecord(value) {
3351
3354
  const keys = Reflect.ownKeys(value);
3352
3355
  if (keys.length > 32) return invalid2();
3353
3356
  const result = /* @__PURE__ */ Object.create(null);
3354
- for (const key of keys) {
3355
- if (typeof key !== "string") return invalid2();
3356
- const descriptor = Object.getOwnPropertyDescriptor(value, key);
3357
+ for (const key2 of keys) {
3358
+ if (typeof key2 !== "string") return invalid2();
3359
+ const descriptor = Object.getOwnPropertyDescriptor(value, key2);
3357
3360
  if (!descriptor || !("value" in descriptor)) return invalid2();
3358
- result[key] = descriptor.value;
3361
+ result[key2] = descriptor.value;
3359
3362
  }
3360
3363
  return result;
3361
3364
  }
@@ -3397,7 +3400,7 @@ function field(value, name3) {
3397
3400
  }
3398
3401
  function names(value, maximum2) {
3399
3402
  const keys = Reflect.ownKeys(record(value));
3400
- if (!keys.length || keys.length > maximum2 || keys.some((key) => typeof key !== "string"))
3403
+ if (!keys.length || keys.length > maximum2 || keys.some((key2) => typeof key2 !== "string"))
3401
3404
  throw new Error();
3402
3405
  return keys;
3403
3406
  }
@@ -3529,6 +3532,8 @@ var nativePreparationLimits = Object.freeze({
3529
3532
  tileJsonBytes: 1048576,
3530
3533
  depth: 64,
3531
3534
  nodes: 54e4,
3535
+ /** A blend style is planned locally from validated styles; split layers make it larger. */
3536
+ blendNodes: 216e4,
3532
3537
  sources: 128,
3533
3538
  layers: 4096,
3534
3539
  fontFaces: 16,
@@ -3611,11 +3616,11 @@ function nativeJsonBytes(value) {
3611
3616
  }
3612
3617
  return bytes;
3613
3618
  }
3614
- function freezeNativePreparedJson(value) {
3619
+ function freezeNativePreparedJson(value, maximumNodes = nativePreparationLimits.nodes) {
3615
3620
  let nodes = 0;
3616
3621
  const parents = /* @__PURE__ */ new Set();
3617
3622
  const visit = (input, depth) => {
3618
- if (++nodes > nativePreparationLimits.nodes || depth > nativePreparationLimits.depth)
3623
+ if (++nodes > maximumNodes || depth > nativePreparationLimits.depth)
3619
3624
  throw new NativePreparationError();
3620
3625
  if (input === null || typeof input === "boolean") return;
3621
3626
  if (typeof input === "number" && Number.isFinite(input)) return;
@@ -3626,17 +3631,17 @@ function freezeNativePreparedJson(value) {
3626
3631
  if (!array3 && Object.getPrototypeOf(input) !== Object.prototype && Object.getPrototypeOf(input) !== null)
3627
3632
  throw new NativePreparationError();
3628
3633
  const keys = Reflect.ownKeys(input);
3629
- if (array3 && (input.length > nativePreparationLimits.nodes || Object.keys(input).length !== input.length))
3634
+ if (array3 && (input.length > maximumNodes || Object.keys(input).length !== input.length))
3630
3635
  throw new NativePreparationError();
3631
3636
  parents.add(input);
3632
- for (const key of keys) {
3633
- if (array3 && key === "length") continue;
3634
- if (typeof key !== "string" || key === "__proto__" || key === "toJSON")
3637
+ for (const key2 of keys) {
3638
+ if (array3 && key2 === "length") continue;
3639
+ if (typeof key2 !== "string" || key2 === "__proto__" || key2 === "toJSON")
3635
3640
  throw new NativePreparationError();
3636
- const property = Object.getOwnPropertyDescriptor(input, key);
3641
+ const property = Object.getOwnPropertyDescriptor(input, key2);
3637
3642
  if (!property || !property.enumerable || !("value" in property))
3638
3643
  throw new NativePreparationError();
3639
- visit(key, depth + 1);
3644
+ visit(key2, depth + 1);
3640
3645
  visit(property.value, depth + 1);
3641
3646
  }
3642
3647
  parents.delete(input);
@@ -3822,13 +3827,13 @@ function snapshotNativeMapOptions(value) {
3822
3827
  const keys = Reflect.ownKeys(value);
3823
3828
  if (keys.length > allowed.size) throw new Error();
3824
3829
  const result = {};
3825
- for (const key of keys) {
3826
- if (typeof key !== "string" || !allowed.has(key)) throw new Error();
3827
- const property = Object.getOwnPropertyDescriptor(value, key);
3830
+ for (const key2 of keys) {
3831
+ if (typeof key2 !== "string" || !allowed.has(key2)) throw new Error();
3832
+ const property = Object.getOwnPropertyDescriptor(value, key2);
3828
3833
  if (!property || !property.enumerable || !("value" in property)) throw new Error();
3829
3834
  if (property.value === void 0) continue;
3830
3835
  if (typeof property.value !== "boolean") throw new Error();
3831
- result[key] = property.value;
3836
+ result[key2] = property.value;
3832
3837
  }
3833
3838
  return Object.freeze(result);
3834
3839
  } catch {
@@ -3893,10 +3898,10 @@ function createMapCameraController(port, onError = () => void 0) {
3893
3898
  }
3894
3899
  function failed(run) {
3895
3900
  if (!current(run)) return;
3896
- const own2 = revision;
3901
+ const own3 = revision;
3897
3902
  pending = void 0;
3898
3903
  retire(run);
3899
- if (disposed || revision !== own2) return;
3904
+ if (disposed || revision !== own3) return;
3900
3905
  try {
3901
3906
  void Promise.resolve(report?.(new CameraControllerError("CAMERA_COMMAND_FAILED"))).catch(
3902
3907
  () => void 0
@@ -3947,9 +3952,9 @@ function createMapCameraController(port, onError = () => void 0) {
3947
3952
  function update(input) {
3948
3953
  assertUsable();
3949
3954
  if (!mounted) throw new CameraControllerError("CAMERA_NOT_MOUNTED");
3950
- const own2 = advance();
3955
+ const own3 = advance();
3951
3956
  const next = snapshotCameraProps(input);
3952
- if (disposed || revision !== own2) return;
3957
+ if (disposed || revision !== own3) return;
3953
3958
  if (next.mode !== mode) throw new CameraControllerError("CAMERA_MODE_CHANGE");
3954
3959
  props = next;
3955
3960
  reconcile();
@@ -3960,9 +3965,9 @@ function createMapCameraController(port, onError = () => void 0) {
3960
3965
  update(input);
3961
3966
  return;
3962
3967
  }
3963
- const own2 = advance();
3968
+ const own3 = advance();
3964
3969
  const next = snapshotCameraProps(input, fallbacks);
3965
- if (disposed || revision !== own2) return;
3970
+ if (disposed || revision !== own3) return;
3966
3971
  mode = next.mode;
3967
3972
  props = next;
3968
3973
  live = next.view;
@@ -3994,9 +3999,9 @@ function createMapCameraController(port, onError = () => void 0) {
3994
3999
  changeGesture(identity, input) {
3995
4000
  const active = gesture;
3996
4001
  if (disposed || !active || active.token !== identity) return;
3997
- const own2 = advance();
4002
+ const own3 = advance();
3998
4003
  const view = snapshotCameraView(input);
3999
- if (disposed || gesture !== active || revision !== own2) return;
4004
+ if (disposed || gesture !== active || revision !== own3) return;
4000
4005
  live = view;
4001
4006
  if (sameCameraView(active.lastEmitted, view)) return;
4002
4007
  active.lastEmitted = view;
@@ -4005,9 +4010,9 @@ function createMapCameraController(port, onError = () => void 0) {
4005
4010
  endGesture(identity, input) {
4006
4011
  const active = gesture;
4007
4012
  if (disposed || !active || active.token !== identity) return;
4008
- const own2 = advance();
4013
+ const own3 = advance();
4009
4014
  const view = snapshotCameraView(input);
4010
- if (disposed || gesture !== active || revision !== own2) return;
4015
+ if (disposed || gesture !== active || revision !== own3) return;
4011
4016
  live = view;
4012
4017
  gesture = void 0;
4013
4018
  const waiting = { token: identity, notifying: true };
@@ -4042,9 +4047,9 @@ function createMapCameraController(port, onError = () => void 0) {
4042
4047
  observeCommand(identity, input) {
4043
4048
  const run = pending;
4044
4049
  if (!run || !current(run) || run.command.token !== identity) return;
4045
- const own2 = advance();
4050
+ const own3 = advance();
4046
4051
  const view = snapshotCameraView(input);
4047
- if (!current(run) || revision !== own2) return;
4052
+ if (!current(run) || revision !== own3) return;
4048
4053
  live = view;
4049
4054
  },
4050
4055
  /** Called explicitly by the renderer owner after replacing style/source on this instance. */
@@ -4177,13 +4182,13 @@ function createNativeInteractionStyleOwner(changed) {
4177
4182
  get() {
4178
4183
  return proof?.isCurrent() ? proof : void 0;
4179
4184
  },
4180
- publish(key, token, style, current) {
4185
+ publish(key2, token, style, current) {
4181
4186
  revoke?.();
4182
4187
  let live = true;
4183
4188
  revoke = () => {
4184
4189
  live = false;
4185
4190
  };
4186
- proof = Object.freeze({ key, token, style, isCurrent: () => live && current() });
4191
+ proof = Object.freeze({ key: key2, token, style, isCurrent: () => live && current() });
4187
4192
  notify();
4188
4193
  },
4189
4194
  retire() {
@@ -4266,6 +4271,160 @@ function createNativeReadiness(notify) {
4266
4271
  });
4267
4272
  }
4268
4273
 
4274
+ // src/native-theme-blend.ts
4275
+ import {
4276
+ fillTileflowThemeBlendTemplate
4277
+ } from "@tileflow/core/native";
4278
+ var nativeBlendLabelFadeMs = 450;
4279
+ var minimumStep = 25e-4;
4280
+ var imageSteps = 32;
4281
+ function createNativeThemeBlender(plan, port, options) {
4282
+ const clamp = (value) => Math.min(plan.themes - 1, Math.max(0, Number.isFinite(value) ? value : 0));
4283
+ const ground = plan.paints.filter((paint) => paint.follows === "position");
4284
+ const symbols = plan.paints.filter((paint) => paint.follows === "dominant");
4285
+ const patterns = plan.images.filter((image) => image.follows === "position");
4286
+ const shownPaints = /* @__PURE__ */ new Map();
4287
+ const shownSwitches = /* @__PURE__ */ new Map();
4288
+ const shownImages = /* @__PURE__ */ new Map();
4289
+ let shownLight;
4290
+ const baked = clamp(options.baked);
4291
+ let position = baked;
4292
+ let dominant = Math.round(baked);
4293
+ let target = baked;
4294
+ let stepped = baked;
4295
+ let scheduled = false;
4296
+ let disposed = false;
4297
+ let queue = Promise.resolve();
4298
+ for (const paint of ground)
4299
+ shownPaints.set(paint, key(fillTileflowThemeBlendTemplate(paint.template, baked)));
4300
+ for (const paint of symbols)
4301
+ shownPaints.set(paint, key(fillTileflowThemeBlendTemplate(paint.template, dominant)));
4302
+ for (const entry of plan.switches) shownSwitches.set(entry, key(entry.values[dominant] ?? null));
4303
+ for (const image of patterns) shownImages.set(image, imageKey(image, baked));
4304
+ if (plan.light !== void 0) shownLight = key(fillTileflowThemeBlendTemplate(plan.light, baked));
4305
+ function groundValues(at) {
4306
+ const paint = [];
4307
+ for (const entry of ground) {
4308
+ const value = fillTileflowThemeBlendTemplate(entry.template, at);
4309
+ const shown = key(value);
4310
+ if (shownPaints.get(entry) === shown) continue;
4311
+ shownPaints.set(entry, shown);
4312
+ paint.push([entry.layer, entry.property, value]);
4313
+ }
4314
+ const images = [];
4315
+ for (const image of patterns) {
4316
+ const shown = imageKey(image, at);
4317
+ if (shownImages.get(image) === shown) continue;
4318
+ shownImages.set(image, shown);
4319
+ const [index, t] = imageMix(image, at);
4320
+ images.push([image.names[0], image.names[index], image.names[index + 1], t]);
4321
+ }
4322
+ let light2;
4323
+ if (plan.light !== void 0) {
4324
+ const value = fillTileflowThemeBlendTemplate(plan.light, at);
4325
+ const shown = key(value);
4326
+ if (shown !== shownLight) {
4327
+ shownLight = shown;
4328
+ light2 = value;
4329
+ }
4330
+ }
4331
+ if (!paint.length && !images.length && light2 === void 0) return void 0;
4332
+ return { paint, images, ...light2 === void 0 ? {} : { light: light2 } };
4333
+ }
4334
+ function nearestValues(theme) {
4335
+ const paint = [];
4336
+ const layout = [];
4337
+ for (const entry of symbols) {
4338
+ const value = fillTileflowThemeBlendTemplate(entry.template, theme);
4339
+ const shown = key(value);
4340
+ if (shownPaints.get(entry) === shown) continue;
4341
+ shownPaints.set(entry, shown);
4342
+ paint.push([entry.layer, entry.property, value]);
4343
+ }
4344
+ for (const entry of plan.switches) {
4345
+ const value = entry.values[theme] ?? null;
4346
+ const shown = key(value);
4347
+ if (shownSwitches.get(entry) === shown) continue;
4348
+ shownSwitches.set(entry, shown);
4349
+ (entry.group === "paint" ? paint : layout).push([entry.layer, entry.property, value]);
4350
+ }
4351
+ if (!paint.length && !layout.length) return void 0;
4352
+ return { paint, layout };
4353
+ }
4354
+ async function step() {
4355
+ scheduled = false;
4356
+ if (disposed) return;
4357
+ const goal = target;
4358
+ stepped = goal;
4359
+ const reachesTheme = goal % 1 === 0 && goal !== position;
4360
+ if (Math.abs(goal - position) >= minimumStep || reachesTheme) {
4361
+ position = goal;
4362
+ const values = groundValues(position);
4363
+ if (values) await port.apply(values);
4364
+ }
4365
+ const nearest = Math.round(goal);
4366
+ if (nearest !== dominant && !disposed) {
4367
+ dominant = nearest;
4368
+ const values = nearestValues(nearest);
4369
+ if (values) {
4370
+ const covered = await port.cover(nativeBlendLabelFadeMs).catch(() => false);
4371
+ if (disposed) return;
4372
+ await port.apply(values);
4373
+ if (covered) void port.reveal(nativeBlendLabelFadeMs).catch(() => void 0);
4374
+ }
4375
+ }
4376
+ }
4377
+ function schedule() {
4378
+ if (scheduled || disposed) return;
4379
+ scheduled = true;
4380
+ queue = queue.then(step).then(
4381
+ () => {
4382
+ if (!disposed && target !== stepped) schedule();
4383
+ },
4384
+ () => {
4385
+ if (disposed) return;
4386
+ disposed = true;
4387
+ options.failed();
4388
+ }
4389
+ );
4390
+ }
4391
+ return Object.freeze({
4392
+ get position() {
4393
+ return position;
4394
+ },
4395
+ get dominant() {
4396
+ return dominant;
4397
+ },
4398
+ set(next) {
4399
+ if (disposed) return;
4400
+ target = clamp(next);
4401
+ schedule();
4402
+ },
4403
+ /** Resolves once every scheduled batch has been sent. */
4404
+ async whenIdle() {
4405
+ for (; ; ) {
4406
+ const pending = queue;
4407
+ await pending;
4408
+ if (pending === queue && !scheduled) return;
4409
+ }
4410
+ },
4411
+ dispose() {
4412
+ disposed = true;
4413
+ }
4414
+ });
4415
+ }
4416
+ function key(value) {
4417
+ return JSON.stringify(value) ?? "undefined";
4418
+ }
4419
+ function imageMix(image, at) {
4420
+ const quantized = Math.round(at * imageSteps) / imageSteps;
4421
+ const index = Math.min(image.names.length - 2, Math.max(0, Math.floor(quantized)));
4422
+ return [index, Math.min(1, Math.max(0, quantized - index))];
4423
+ }
4424
+ function imageKey(image, at) {
4425
+ return imageMix(image, at).join(":");
4426
+ }
4427
+
4269
4428
  // src/native-renderer-owner.ts
4270
4429
  var blank = Object.freeze({ version: 8, sources: Object.freeze({}), layers: Object.freeze([]) });
4271
4430
  var selection = (target) => Object.freeze({
@@ -4275,7 +4434,7 @@ var selection = (target) => Object.freeze({
4275
4434
  colorScheme: target.source.theme.colorScheme
4276
4435
  })
4277
4436
  });
4278
- function createNativeRendererOwner(key, initialTarget, initialCamera, ports2) {
4437
+ function createNativeRendererOwner(key2, initialTarget, initialCamera, ports2) {
4279
4438
  let disposed = false;
4280
4439
  let terminal = false;
4281
4440
  let foreground = true;
@@ -4302,10 +4461,17 @@ function createNativeRendererOwner(key, initialTarget, initialCamera, ports2) {
4302
4461
  let gesture;
4303
4462
  let settlement;
4304
4463
  let cameraProps = initialCamera;
4464
+ let transitionMs = 0;
4465
+ let drawn = false;
4466
+ let covering = false;
4467
+ let coverMs = 0;
4468
+ let revealing;
4469
+ let blender;
4470
+ let blendPosition;
4305
4471
  const initial = snapshotCameraProps(initialCamera, { manifestView: initialTarget.source.map.view });
4306
4472
  const initialView = initial.view;
4307
4473
  let snapshot = Object.freeze({
4308
- key,
4474
+ key: key2,
4309
4475
  style: blank,
4310
4476
  initialView,
4311
4477
  revision
@@ -4336,6 +4502,38 @@ function createNativeRendererOwner(key, initialTarget, initialCamera, ports2) {
4336
4502
  }
4337
4503
  };
4338
4504
  const readiness = createNativeReadiness((status) => {
4505
+ if (disposed) return;
4506
+ if (status === "ready" && covering) reveal();
4507
+ else publishReadiness(status);
4508
+ });
4509
+ function reveal() {
4510
+ const version = transaction;
4511
+ const nativeSurface = surface;
4512
+ if (revealing?.version === version) return;
4513
+ if (!nativeSurface?.reveal) {
4514
+ covering = false;
4515
+ if (readiness.ready) publishReadiness("ready");
4516
+ return;
4517
+ }
4518
+ const work = nativeSurface.reveal(coverMs).catch(() => nativeSurface.discardCover?.()).catch(() => void 0);
4519
+ revealing = { version, work };
4520
+ track(
4521
+ work.then(() => {
4522
+ if (revealing?.work === work) revealing = void 0;
4523
+ if (disposed || version !== transaction) return;
4524
+ covering = false;
4525
+ if (readiness.ready) publishReadiness("ready");
4526
+ })
4527
+ );
4528
+ }
4529
+ function discardCover() {
4530
+ if (!covering) return;
4531
+ covering = false;
4532
+ revealing = void 0;
4533
+ const nativeSurface = surface;
4534
+ if (nativeSurface?.discardCover) track(nativeSurface.discardCover().catch(() => void 0));
4535
+ }
4536
+ function publishReadiness(status) {
4339
4537
  if (disposed) return;
4340
4538
  const version = transaction;
4341
4539
  if (status === "ready" && pendingSuccess && !rollback) {
@@ -4352,11 +4550,12 @@ function createNativeRendererOwner(key, initialTarget, initialCamera, ports2) {
4352
4550
  });
4353
4551
  }
4354
4552
  } else emit({ type: "readiness-change", generation: eventGeneration, status });
4355
- });
4553
+ }
4356
4554
  const cameraPort = createNativeCameraPort({
4357
4555
  applyCamera(command, view) {
4358
- if (!surface || disposed || terminal || !loaded || !foreground)
4556
+ if (!surface || disposed || terminal || !foreground)
4359
4557
  return Promise.reject(new NativePreparationError());
4558
+ if (!loaded) return Promise.resolve(Object.freeze({ command, view }));
4360
4559
  return surface.applyCamera(command, view);
4361
4560
  },
4362
4561
  cancelCamera(command) {
@@ -4374,7 +4573,7 @@ function createNativeRendererOwner(key, initialTarget, initialCamera, ports2) {
4374
4573
  const expected = token;
4375
4574
  const generation = eventGeneration;
4376
4575
  interactionStyles.publish(
4377
- key,
4576
+ key2,
4378
4577
  expected,
4379
4578
  style,
4380
4579
  () => !disposed && !terminal && foreground && !preloading && styleAccepted && loaded && surface === nativeSurface && token === expected && snapshot.style === style && transaction === version && eventGeneration === generation
@@ -4397,6 +4596,9 @@ function createNativeRendererOwner(key, initialTarget, initialCamera, ports2) {
4397
4596
  if (disposed || terminal || !foreground || !styleAccepted || loaded || version !== transaction)
4398
4597
  return;
4399
4598
  loaded = true;
4599
+ drawn = true;
4600
+ if (covering) reveal();
4601
+ startBlender(version);
4400
4602
  publishInteractionStyle(version);
4401
4603
  if (disposed || version !== transaction || !foreground) return;
4402
4604
  emit({ type: "load", generation: eventGeneration, selection: selection(active) });
@@ -4418,8 +4620,45 @@ function createNativeRendererOwner(key, initialTarget, initialCamera, ports2) {
4418
4620
  fail2();
4419
4621
  }
4420
4622
  }
4623
+ function stopBlender() {
4624
+ blender?.dispose();
4625
+ blender = void 0;
4626
+ }
4627
+ function startBlender(version) {
4628
+ const blend = active.blend;
4629
+ const nativeSurface = surface;
4630
+ if (!blend || blender || !nativeSurface?.applyThemeValues || version !== transaction) return;
4631
+ const style = token;
4632
+ const owned2 = () => !disposed && !terminal && version === transaction && surface === nativeSurface;
4633
+ blender = createNativeThemeBlender(
4634
+ blend.plan,
4635
+ {
4636
+ apply(values) {
4637
+ if (!owned2()) return Promise.resolve();
4638
+ return nativeSurface.applyThemeValues(style, values);
4639
+ },
4640
+ cover(duration) {
4641
+ if (!owned2() || !foreground || !nativeSurface.cover) return Promise.resolve(false);
4642
+ return nativeSurface.cover(duration);
4643
+ },
4644
+ reveal(duration) {
4645
+ if (!nativeSurface.reveal) return Promise.resolve();
4646
+ return nativeSurface.reveal(duration);
4647
+ }
4648
+ },
4649
+ {
4650
+ baked: blend.position,
4651
+ failed() {
4652
+ if (owned2()) fail2();
4653
+ }
4654
+ }
4655
+ );
4656
+ if (blendPosition !== void 0) blender.set(blendPosition);
4657
+ }
4421
4658
  function apply(target, restoring) {
4422
4659
  if (disposed) return;
4660
+ stopBlender();
4661
+ blendPosition = target.blend?.position;
4423
4662
  const version = ++transaction;
4424
4663
  if (styleSequence >= Number.MAX_SAFE_INTEGER) {
4425
4664
  terminal = true;
@@ -4444,8 +4683,17 @@ function createNativeRendererOwner(key, initialTarget, initialCamera, ports2) {
4444
4683
  readiness.begin(expected);
4445
4684
  if (!surface) return;
4446
4685
  const nativeSurface = surface;
4686
+ const duration = restoring || !drawn || !foreground ? 0 : transitionMs;
4447
4687
  const work = Promise.resolve().then(async () => {
4448
4688
  if (disposed || version !== transaction) return;
4689
+ if (duration > 0 && nativeSurface.cover) {
4690
+ const covered = await nativeSurface.cover(duration).catch(() => false);
4691
+ if (covered && !disposed) {
4692
+ covering = true;
4693
+ coverMs = duration;
4694
+ }
4695
+ if (disposed || version !== transaction || surface !== nativeSurface) return;
4696
+ }
4449
4697
  await nativeSurface.expectStyle(expected);
4450
4698
  if (disposed || version !== transaction || surface !== nativeSurface) return;
4451
4699
  const layers = target.style.layers;
@@ -4453,21 +4701,24 @@ function createNativeRendererOwner(key, initialTarget, initialCamera, ports2) {
4453
4701
  (layer) => !layer || typeof layer !== "object" || typeof layer.id !== "string" || layer.id.startsWith("__tileflow_native_style_")
4454
4702
  ))
4455
4703
  throw new NativePreparationError();
4456
- const style = freezeNativePreparedJson({
4457
- ...target.style,
4458
- layers: [
4459
- ...layers,
4460
- {
4461
- id: `__tileflow_native_style_${expected}`,
4462
- type: "background",
4463
- paint: {
4464
- "background-color": "rgba(0,0,0,0)",
4465
- "background-opacity": 1
4704
+ const style = freezeNativePreparedJson(
4705
+ {
4706
+ ...target.style,
4707
+ layers: [
4708
+ ...layers,
4709
+ {
4710
+ id: `__tileflow_native_style_${expected}`,
4711
+ type: "background",
4712
+ paint: {
4713
+ "background-color": "rgba(0,0,0,0)",
4714
+ "background-opacity": 1
4715
+ }
4466
4716
  }
4467
- }
4468
- ]
4469
- });
4470
- snapshot = Object.freeze({ key, style, initialView, revision: ++revision });
4717
+ ]
4718
+ },
4719
+ target.blend ? nativePreparationLimits.blendNodes : nativePreparationLimits.nodes
4720
+ );
4721
+ snapshot = Object.freeze({ key: key2, style, initialView, revision: ++revision });
4471
4722
  if (!restoring)
4472
4723
  emit({
4473
4724
  type: "theme-change",
@@ -4489,6 +4740,8 @@ function createNativeRendererOwner(key, initialTarget, initialCamera, ports2) {
4489
4740
  const previous = committed;
4490
4741
  const version = transaction;
4491
4742
  interactionStyles.retire();
4743
+ discardCover();
4744
+ stopBlender();
4492
4745
  if (disposed || version !== transaction) return;
4493
4746
  emit({ type: "renderer-error", generation });
4494
4747
  if (disposed || version !== transaction) return;
@@ -4574,6 +4827,20 @@ function createNativeRendererOwner(key, initialTarget, initialCamera, ports2) {
4574
4827
  get currentTarget() {
4575
4828
  return committed;
4576
4829
  },
4830
+ /** The latest target applied, which may still be loading. */
4831
+ get activeTarget() {
4832
+ return terminal ? void 0 : active;
4833
+ },
4834
+ /** Moves a blend target to another position; ignored while no blend is shown. */
4835
+ setBlendPosition(position) {
4836
+ if (disposed || !Number.isFinite(position)) return;
4837
+ blendPosition = position;
4838
+ if (active.blend) blender?.set(position);
4839
+ },
4840
+ /** Cross-fade length for later style replacements, in milliseconds; 0 changes at once. */
4841
+ setTransition(duration) {
4842
+ transitionMs = Number.isSafeInteger(duration) && duration > 0 && duration <= 5e3 ? duration : 0;
4843
+ },
4577
4844
  bindRoot(rootTag) {
4578
4845
  if (disposed || !Number.isSafeInteger(rootTag) || rootTag < 1 || root !== void 0 && root !== rootTag)
4579
4846
  return;
@@ -4629,7 +4896,16 @@ function createNativeRendererOwner(key, initialTarget, initialCamera, ports2) {
4629
4896
  apply(target, false);
4630
4897
  },
4631
4898
  reuseTarget(source) {
4632
- if (disposed || !committed || terminal) return;
4899
+ if (disposed || terminal) return;
4900
+ if (active !== committed || !committed) {
4901
+ active = { ...active, source };
4902
+ eventGeneration = source.generation;
4903
+ preloading = false;
4904
+ interruptCamera();
4905
+ invalidate();
4906
+ publishInteractionStyle(transaction);
4907
+ return;
4908
+ }
4633
4909
  active = { ...committed, source };
4634
4910
  committed = active;
4635
4911
  const target = active;
@@ -4751,6 +5027,7 @@ function createNativeRendererOwner(key, initialTarget, initialCamera, ports2) {
4751
5027
  async whenIdle() {
4752
5028
  for (; ; ) {
4753
5029
  await cameraPort.whenIdle();
5030
+ await blender?.whenIdle();
4754
5031
  if (!tasks.size) return;
4755
5032
  await Promise.allSettled([...tasks]);
4756
5033
  }
@@ -4760,6 +5037,7 @@ function createNativeRendererOwner(key, initialTarget, initialCamera, ports2) {
4760
5037
  disposed = true;
4761
5038
  ++transaction;
4762
5039
  ++barrierEpoch;
5040
+ stopBlender();
4763
5041
  interactionStyles.retire();
4764
5042
  readiness.dispose();
4765
5043
  camera.dispose();
@@ -4856,9 +5134,7 @@ function owned(url, scope, policy) {
4856
5134
  let tilesetId;
4857
5135
  const base = /^\/base\/[0-9a-f]{64}\/(.+)$/u.exec(path)?.[1];
4858
5136
  if (scope === "style") {
4859
- const prefix = `/maps/${policy.mapId}/`;
4860
- const legacy = path.startsWith(prefix) && /^[a-z0-9][a-z0-9-]{0,63}\.json$/u.test(path.slice(prefix.length));
4861
- if (!legacy && !nativeVersionedStyleMatchesMap(url, policy.mapId)) throw invalid3();
5137
+ if (!nativeVersionedStyleMatchesMap(url, policy.mapId)) throw invalid3();
4862
5138
  } else if (scope === "tilejson" || scope === "tile") {
4863
5139
  const match = /^\/(?:v1\/)?tiles\/([A-Za-z0-9._:-]{1,255})\/(.+)$/u.exec(path);
4864
5140
  if (!match || !policy.tilesetIds.includes(match[1])) throw invalid3();
@@ -4950,9 +5226,9 @@ function fontMetadata(input, developmentOrigin) {
4950
5226
  if (!record2(value)) throw invalid3();
4951
5227
  const keys = Reflect.ownKeys(value);
4952
5228
  if (keys.some(
4953
- (key) => typeof key !== "string" || !["id", "family", "url", "source", "format", "style", "weight"].includes(key)
4954
- ) || keys.some((key) => {
4955
- const descriptor = Object.getOwnPropertyDescriptor(value, key);
5229
+ (key2) => typeof key2 !== "string" || !["id", "family", "url", "source", "format", "style", "weight"].includes(key2)
5230
+ ) || keys.some((key2) => {
5231
+ const descriptor = Object.getOwnPropertyDescriptor(value, key2);
4956
5232
  return !descriptor?.enumerable || !("value" in descriptor);
4957
5233
  }))
4958
5234
  throw invalid3();
@@ -4991,7 +5267,7 @@ function validateFontFaces(faces, documentUrl, metadata, add, rewrites, policy,
4991
5267
  for (const definition of definitions) {
4992
5268
  if (++count > nativePreparationLimits.fontFaces || !record2(definition)) throw invalid3();
4993
5269
  const keys = Object.keys(definition).sort();
4994
- if (keys.length !== 4 || !["font-family", "font-style", "font-weight", "url"].every((key) => keys.includes(key)))
5270
+ if (keys.length !== 4 || !["font-family", "font-style", "font-weight", "url"].every((key2) => keys.includes(key2)))
4995
5271
  throw invalid3();
4996
5272
  if (typeof definition["font-family"] !== "string" || !fontStyles.has(String(definition["font-style"])) || typeof definition["font-weight"] !== "number" || !Number.isInteger(definition["font-weight"]) || !fontWeights.has(String(definition["font-weight"])))
4997
5273
  throw invalid3();
@@ -5064,7 +5340,7 @@ async function projectNativeResources(ports2) {
5064
5340
  const styleUrl = resolveUrl(ports2.styleUrl, ports2.styleUrl);
5065
5341
  const document = await read(styleUrl, "style");
5066
5342
  const style = JSON.parse(JSON.stringify(document.value));
5067
- if (style.version !== 8 || !record2(style.sources) || !Array.isArray(style.layers) || Object.keys(style).some((key) => !roots.has(key)) || Object.keys(style.sources).length > nativePreparationLimits.sources || style.layers.length > nativePreparationLimits.layers)
5343
+ if (style.version !== 8 || !record2(style.sources) || !Array.isArray(style.layers) || Object.keys(style).some((key2) => !roots.has(key2)) || Object.keys(style.sources).length > nativePreparationLimits.sources || style.layers.length > nativePreparationLimits.layers)
5068
5344
  throw invalid3();
5069
5345
  const rewrites = [];
5070
5346
  for (const sourceId of Object.keys(style.sources).sort()) {
@@ -5080,9 +5356,9 @@ async function projectNativeResources(ports2) {
5080
5356
  throw invalid3();
5081
5357
  declaringUrl = tileJson.url;
5082
5358
  delete source.url;
5083
- for (const key of ["tiles", "bounds", "minzoom", "maxzoom", "scheme", "attribution"]) {
5084
- if (source[key] === void 0 && tileJson.value[key] !== void 0)
5085
- source[key] = JSON.parse(JSON.stringify(tileJson.value[key]));
5359
+ for (const key2 of ["tiles", "bounds", "minzoom", "maxzoom", "scheme", "attribution"]) {
5360
+ if (source[key2] === void 0 && tileJson.value[key2] !== void 0)
5361
+ source[key2] = JSON.parse(JSON.stringify(tileJson.value[key2]));
5086
5362
  }
5087
5363
  }
5088
5364
  if (!Array.isArray(source.tiles) || source.tiles.length < 1 || source.tiles.length > 16)
@@ -5188,14 +5464,72 @@ function projectMapSourceState(state) {
5188
5464
  });
5189
5465
  }
5190
5466
 
5467
+ // src/theme-motion-input.ts
5468
+ import { validateTileflowThemeBlendSelection } from "@tileflow/core/native";
5469
+ var maximumTransitionMs = 5e3;
5470
+ function own(value, keys) {
5471
+ const prototype = Object.getPrototypeOf(value);
5472
+ if (Array.isArray(value) || prototype !== Object.prototype && prototype !== null)
5473
+ throw new NativePreparationError();
5474
+ const result = {};
5475
+ for (const key2 of Reflect.ownKeys(value)) {
5476
+ if (typeof key2 !== "string" || !keys.includes(key2)) throw new NativePreparationError();
5477
+ const property = Object.getOwnPropertyDescriptor(value, key2);
5478
+ if (!property || !("value" in property)) throw new NativePreparationError();
5479
+ result[key2] = property.value;
5480
+ }
5481
+ return result;
5482
+ }
5483
+ function snapshotThemeTransition(value) {
5484
+ if (value === void 0) return 0;
5485
+ if (!value || typeof value !== "object") throw new NativePreparationError();
5486
+ const { duration = 0 } = own(value, ["duration"]);
5487
+ if (typeof duration !== "number" || !Number.isFinite(duration) || duration < 0 || duration > maximumTransitionMs)
5488
+ throw new NativePreparationError();
5489
+ return Math.round(duration);
5490
+ }
5491
+ function snapshotThemeBlend(value) {
5492
+ if (value === void 0) return void 0;
5493
+ if (!value || typeof value !== "object") throw new NativePreparationError();
5494
+ const { themes, position } = own(value, ["themes", "position"]);
5495
+ if (!Array.isArray(themes)) throw new NativePreparationError();
5496
+ const blend = { themes: Object.freeze([...themes]), position };
5497
+ if (!validateTileflowThemeBlendSelection(blend)) throw new NativePreparationError();
5498
+ return Object.freeze(blend);
5499
+ }
5500
+ function themeBlendKey(blend) {
5501
+ return JSON.stringify(blend.themes);
5502
+ }
5503
+
5191
5504
  // src/mounted-map-owner.ts
5505
+ function themeSource(source, name3) {
5506
+ const theme = Object.hasOwn(source.map.themes, name3) ? source.map.themes[name3] : void 0;
5507
+ if (!theme) throw new NativePreparationError();
5508
+ return { ...source, theme: { ...theme, name: name3 } };
5509
+ }
5510
+ function themeIdentity(source) {
5511
+ return JSON.stringify([source.theme.name, source.theme.styleUrl, source.theme.revision ?? null]);
5512
+ }
5513
+ function heldStyle(targets, source) {
5514
+ const identity = themeIdentity(source);
5515
+ for (const target of targets) {
5516
+ if (!target) continue;
5517
+ if (!target.blend && themeIdentity(target.source) === identity) return target.style;
5518
+ const held = target.blend?.styles.get(identity);
5519
+ if (held) return held;
5520
+ }
5521
+ return void 0;
5522
+ }
5523
+ function sameTheme(shown, source) {
5524
+ return shown.theme.name === source.theme.name && shown.theme.styleUrl === source.theme.styleUrl && shown.theme.revision === source.theme.revision;
5525
+ }
5192
5526
  function cameraInput(props) {
5193
5527
  const result = {};
5194
- for (const key of ["view", "initialView", "onViewChange"]) {
5195
- const property = Object.getOwnPropertyDescriptor(props, key);
5528
+ for (const key2 of ["view", "initialView", "onViewChange"]) {
5529
+ const property = Object.getOwnPropertyDescriptor(props, key2);
5196
5530
  if (!property) continue;
5197
5531
  if (!("value" in property)) throw new NativePreparationError();
5198
- result[key] = property.value;
5532
+ result[key2] = property.value;
5199
5533
  }
5200
5534
  const input = result;
5201
5535
  snapshotCameraProps(input);
@@ -5207,7 +5541,7 @@ function snapshotSource(value) {
5207
5541
  const prototype = Object.getPrototypeOf(value);
5208
5542
  if (prototype !== Object.prototype && prototype !== null) return void 0;
5209
5543
  const keys = Reflect.ownKeys(value);
5210
- if (!keys.includes("map") || !keys.includes("manifestUrl") || keys.some((key) => !["map", "manifestUrl", "developmentOrigin"].includes(String(key))))
5544
+ if (!keys.includes("map") || !keys.includes("manifestUrl") || keys.some((key2) => !["map", "manifestUrl", "developmentOrigin"].includes(String(key2))))
5211
5545
  return void 0;
5212
5546
  const map = Object.getOwnPropertyDescriptor(value, "map");
5213
5547
  const url = Object.getOwnPropertyDescriptor(value, "manifestUrl");
@@ -5232,6 +5566,11 @@ function createMountedMapOwner(ports2) {
5232
5566
  let props;
5233
5567
  let camera = {};
5234
5568
  let mapOptions = Object.freeze({});
5569
+ let transitionMs = 0;
5570
+ let blendSelection;
5571
+ let blendTheme;
5572
+ const blending = () => ports2.surfaces.blending?.() !== false;
5573
+ const selectionTheme = () => blendSelection ? blendTheme : props?.theme;
5235
5574
  let sourceKey;
5236
5575
  let sourceObject;
5237
5576
  let selectedTheme;
@@ -5431,24 +5770,21 @@ function createMountedMapOwner(ports2) {
5431
5770
  const job = { live: true, operations: /* @__PURE__ */ new Set() };
5432
5771
  epoch.job = job;
5433
5772
  let styleReadFailed = false;
5773
+ const blend = blending() ? blendSelection : void 0;
5434
5774
  const owns = () => !disposed && foreground && current === epoch && epoch.live && job.live && epoch.job === job && core.state === source;
5435
5775
  const work = Promise.resolve().then(async () => {
5436
5776
  if (!owns()) return;
5437
5777
  epoch.hosted.validate(source);
5438
5778
  const map = await context(epoch, source);
5439
5779
  if (!owns()) return;
5440
- const previous = epoch.renderer?.currentTarget;
5441
- if (previous && previous.source.theme.name === source.theme.name && previous.source.theme.styleUrl === source.theme.styleUrl && previous.source.theme.revision === source.theme.revision) {
5442
- epoch.renderer.reuseTarget(source);
5443
- return;
5444
- }
5445
- const policy = await map.prepare();
5446
- if (!owns()) return;
5447
- const prepared = await projectNativeResources({
5448
- styleUrl: source.theme.styleUrl,
5449
- developmentOrigin: source.source.developmentOrigin,
5780
+ const renderer = epoch.renderer;
5781
+ const shown = renderer?.activeTarget;
5782
+ const held = [shown, renderer?.currentTarget];
5783
+ const project = async (theme, policy) => (await projectNativeResources({
5784
+ styleUrl: theme.theme.styleUrl,
5785
+ developmentOrigin: theme.source.developmentOrigin,
5450
5786
  policy,
5451
- fontFaces: source.theme.fontFaces?.map((face) => ({
5787
+ fontFaces: theme.theme.fontFaces?.map((face) => ({
5452
5788
  family: face.family,
5453
5789
  source: face.source,
5454
5790
  ...face.style === void 0 ? {} : { style: face.style },
@@ -5473,36 +5809,81 @@ function createMountedMapOwner(ports2) {
5473
5809
  maximumBytes,
5474
5810
  owns
5475
5811
  );
5476
- if (url === source.theme.styleUrl) assertHostedNativeStyleDocument(source, document);
5812
+ if (url === theme.theme.styleUrl)
5813
+ assertHostedNativeStyleDocument(theme, document);
5477
5814
  return document;
5478
5815
  } catch {
5479
- if (url === source.theme.styleUrl && resource?.scope === "style")
5816
+ if (url === theme.theme.styleUrl && resource?.scope === "style")
5480
5817
  styleReadFailed = true;
5481
5818
  throw new NativePreparationError();
5482
5819
  }
5483
5820
  }
5484
- });
5821
+ })).style;
5822
+ let target;
5823
+ if (blend) {
5824
+ const themes = blend.themes.map((name3) => themeSource(source, name3));
5825
+ const key2 = JSON.stringify(themes.map(themeIdentity));
5826
+ if (renderer && shown?.blend?.key === key2) {
5827
+ renderer.reuseTarget(source);
5828
+ if (blendSelection) renderer.setBlendPosition(blendSelection.position);
5829
+ return;
5830
+ }
5831
+ const policy = await map.prepare();
5832
+ if (!owns()) return;
5833
+ const styles = [];
5834
+ for (const theme of themes) {
5835
+ styles.push(heldStyle(held, theme) ?? await project(theme, policy));
5836
+ if (!owns()) return;
5837
+ }
5838
+ const plan = planTileflowThemeBlend(styles, {
5839
+ featureSwitches: "layers",
5840
+ iconImages: "switch"
5841
+ });
5842
+ const position = blendSelection && themeBlendKey(blendSelection) === themeBlendKey(blend) ? blendSelection.position : blend.position;
5843
+ target = {
5844
+ source,
5845
+ style: plan.styleAt(position),
5846
+ blend: {
5847
+ key: key2,
5848
+ plan,
5849
+ position,
5850
+ styles: new Map(themes.map((theme, index) => [themeIdentity(theme), styles[index]]))
5851
+ }
5852
+ };
5853
+ } else {
5854
+ if (renderer && shown && !shown.blend && sameTheme(shown.source, source)) {
5855
+ renderer.reuseTarget(source);
5856
+ return;
5857
+ }
5858
+ const style = heldStyle(held, source);
5859
+ if (renderer && style) {
5860
+ renderer.setTarget({ source, style });
5861
+ notify();
5862
+ return;
5863
+ }
5864
+ const policy = await map.prepare();
5865
+ if (!owns()) return;
5866
+ target = { source, style: await project(source, policy) };
5867
+ }
5485
5868
  if (!owns()) return;
5486
5869
  ports2.surfaces.available?.();
5487
- if (!epoch.renderer)
5488
- epoch.renderer = createNativeRendererOwner(
5489
- map.context,
5490
- { source, style: prepared.style },
5491
- camera,
5492
- {
5493
- surfaces: ports2.surfaces,
5494
- emit(event) {
5495
- if (current === epoch && epoch.live && !disposed) emit(event);
5496
- },
5497
- changed() {
5498
- if (current === epoch && epoch.live) notify();
5499
- },
5500
- interactionsChanged() {
5501
- if (current === epoch && epoch.live && !disposed) notify();
5502
- }
5870
+ if (!epoch.renderer) {
5871
+ epoch.renderer = createNativeRendererOwner(map.context, target, camera, {
5872
+ surfaces: ports2.surfaces,
5873
+ emit(event) {
5874
+ if (current === epoch && epoch.live && !disposed) emit(event);
5875
+ },
5876
+ changed() {
5877
+ if (current === epoch && epoch.live) notify();
5878
+ },
5879
+ interactionsChanged() {
5880
+ if (current === epoch && epoch.live && !disposed) notify();
5503
5881
  }
5504
- );
5505
- else epoch.renderer.setTarget({ source, style: prepared.style });
5882
+ });
5883
+ epoch.renderer.setTransition(transitionMs);
5884
+ } else epoch.renderer.setTarget(target);
5885
+ if (target.blend && blendSelection)
5886
+ epoch.renderer.setBlendPosition(blendSelection.position);
5506
5887
  notify();
5507
5888
  }).catch(() => {
5508
5889
  if (!owns()) return;
@@ -5510,7 +5891,7 @@ function createMountedMapOwner(ports2) {
5510
5891
  cancelJob(epoch);
5511
5892
  epoch.cache.clear();
5512
5893
  if (!disposed && foreground && current === epoch && epoch.live && props) {
5513
- track(core.replace(props.source, { theme: props.theme, colorScheme }));
5894
+ track(core.replace(props.source, { theme: selectionTheme(), colorScheme }));
5514
5895
  }
5515
5896
  return;
5516
5897
  }
@@ -5547,7 +5928,7 @@ function createMountedMapOwner(ports2) {
5547
5928
  function select() {
5548
5929
  if (disposed || !props || !current?.live) return;
5549
5930
  current.hosted.select();
5550
- track(core.replace(props.source, { theme: props.theme, colorScheme }));
5931
+ track(core.replace(props.source, { theme: selectionTheme(), colorScheme }));
5551
5932
  }
5552
5933
  function appearance(theme) {
5553
5934
  if (theme === "system" === Boolean(appearanceRelease)) return;
@@ -5606,16 +5987,27 @@ function createMountedMapOwner(ports2) {
5606
5987
  props = source ? { ...next, source } : next;
5607
5988
  let options;
5608
5989
  let input;
5990
+ let transition;
5991
+ let blend;
5609
5992
  try {
5610
5993
  options = snapshotNativeMapOptions(next.mapOptions);
5611
5994
  input = cameraInput(next);
5995
+ transition = snapshotThemeTransition(next.themeTransition);
5996
+ blend = snapshotThemeBlend(next.themeBlend);
5612
5997
  } catch {
5613
5998
  rendererError();
5614
5999
  return;
5615
6000
  }
5616
- const key = source && JSON.stringify(source);
5617
- const changedSource = !initialized || key !== sourceKey || key === void 0 && sourceObject !== next.source;
5618
- const changedTheme = !initialized || next.theme !== selectedTheme;
6001
+ transitionMs = transition;
6002
+ current?.renderer?.setTransition(transition);
6003
+ const previousBlend = blendSelection;
6004
+ const nearest = blend ? nearestTileflowBlendTheme(blend) : void 0;
6005
+ const changedBlend = Boolean(blend) !== Boolean(previousBlend) || blend && previousBlend && themeBlendKey(blend) !== themeBlendKey(previousBlend) || blend && !blending() && nearest !== blendTheme;
6006
+ blendSelection = blend;
6007
+ if (changedBlend || !blend) blendTheme = nearest;
6008
+ const key2 = source && JSON.stringify(source);
6009
+ const changedSource = !initialized || key2 !== sourceKey || key2 === void 0 && sourceObject !== next.source;
6010
+ const changedTheme = !initialized || !blend && next.theme !== selectedTheme;
5619
6011
  const changedOptions = JSON.stringify(options) !== JSON.stringify(mapOptions);
5620
6012
  camera = input;
5621
6013
  mapOptions = options;
@@ -5624,7 +6016,7 @@ function createMountedMapOwner(ports2) {
5624
6016
  current = void 0;
5625
6017
  if (previous) void retire(previous).catch(() => void 0);
5626
6018
  current = createEpoch(source?.developmentOrigin);
5627
- sourceKey = key;
6019
+ sourceKey = key2;
5628
6020
  sourceObject = next.source;
5629
6021
  }
5630
6022
  selectedTheme = next.theme;
@@ -5634,19 +6026,20 @@ function createMountedMapOwner(ports2) {
5634
6026
  } catch {
5635
6027
  colorScheme = void 0;
5636
6028
  }
5637
- if (changedSource || changedTheme) select();
6029
+ if (changedSource || changedTheme || changedBlend) select();
6030
+ else if (blend && blending()) current?.renderer?.setBlendPosition(blend.position);
5638
6031
  if (changedOptions || changedSource) notify();
5639
6032
  current?.renderer?.afterCommit(camera);
5640
6033
  },
5641
- rootMounted(key, root) {
5642
- if (!disposed && current?.renderer?.snapshot.key === key) current.renderer.bindRoot(root);
6034
+ rootMounted(key2, root) {
6035
+ if (!disposed && current?.renderer?.snapshot.key === key2) current.renderer.bindRoot(root);
5643
6036
  },
5644
- nativeStyleLoaded(key, root) {
5645
- if (disposed || current?.renderer?.snapshot.key !== key) return;
6037
+ nativeStyleLoaded(key2, root) {
6038
+ if (disposed || current?.renderer?.snapshot.key !== key2) return;
5646
6039
  void current.renderer.attach(root).catch(() => void 0);
5647
6040
  },
5648
- layoutChanged(key) {
5649
- if (!disposed && current?.renderer?.snapshot.key === key) current.renderer.layoutChanged();
6041
+ layoutChanged(key2) {
6042
+ if (!disposed && current?.renderer?.snapshot.key === key2) current.renderer.layoutChanged();
5650
6043
  },
5651
6044
  background() {
5652
6045
  nativeLifecycle(false);
@@ -5827,10 +6220,7 @@ function createNativeAdmissionWire(native, listen) {
5827
6220
  return Object.freeze({ installation: ack.installation });
5828
6221
  },
5829
6222
  registerContext: (id, registration) => safe(() => native.registerContext(id, registration)),
5830
- extendContext: (id, context, resources) => safe(() => {
5831
- if (!native.extendContext) throw unavailable();
5832
- return native.extendContext(id, context, resources);
5833
- }),
6223
+ extendContext: (id, context, resources) => safe(() => native.extendContext(id, context, resources)),
5834
6224
  retireContext(id, context) {
5835
6225
  if (id === installation2?.id) retireContext(context);
5836
6226
  return safe(() => native.retireContext(id, context));
@@ -5977,6 +6367,7 @@ function createReactNativeAdmissionTransport() {
5977
6367
  for (const name3 of [
5978
6368
  "install",
5979
6369
  "registerContext",
6370
+ "extendContext",
5980
6371
  "retireContext",
5981
6372
  "completeBatch",
5982
6373
  "remove",
@@ -6145,9 +6536,9 @@ function createHostedNativeBindingResolver(readConfiguration) {
6145
6536
  });
6146
6537
  void result.catch(() => void 0);
6147
6538
  const previous = active;
6148
- const own2 = { reject };
6149
- active = own2;
6150
- const current = () => !disposed && generation === sequence && active === own2;
6539
+ const own3 = { reject };
6540
+ active = own3;
6541
+ const current = () => !disposed && generation === sequence && active === own3;
6151
6542
  previous?.reject(new NativeConfigurationError("NATIVE_CONFIGURATION_REPLACED"));
6152
6543
  let metadata;
6153
6544
  try {
@@ -6519,25 +6910,54 @@ var methods = [
6519
6910
  "retireRoot"
6520
6911
  ];
6521
6912
  var positive = (value) => typeof value === "number" && Number.isSafeInteger(value) && value > 0;
6522
- function own(value, name3) {
6913
+ var motionDuration = (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0 && value <= 5e3;
6914
+ var nativeThemeValueLimits = Object.freeze({ values: 8192, images: 64, depth: 32 });
6915
+ var layerOrImage = (value) => typeof value === "string" && value.length > 0 && value.length <= 512;
6916
+ var propertyName = (value) => typeof value === "string" && /^[a-z][a-z-]{0,63}$/u.test(value);
6917
+ function plain(value, depth) {
6918
+ if (value === null || typeof value === "boolean" || typeof value === "string") return true;
6919
+ if (typeof value === "number") return Number.isFinite(value);
6920
+ if (depth >= nativeThemeValueLimits.depth || !value || typeof value !== "object") return false;
6921
+ if (Array.isArray(value)) return value.every((item2) => plain(item2, depth + 1));
6922
+ const prototype = Object.getPrototypeOf(value);
6923
+ if (prototype !== Object.prototype && prototype !== null) return false;
6924
+ return Object.values(value).every((item2) => plain(item2, depth + 1));
6925
+ }
6926
+ function themeValues(values) {
6927
+ if (!values || typeof values !== "object" || Array.isArray(values)) return false;
6928
+ const { paint = [], layout = [], images = [], light: light2 } = values;
6929
+ if (Object.keys(values).some((key2) => !["paint", "layout", "images", "light"].includes(key2)) || !Array.isArray(paint) || !Array.isArray(layout) || !Array.isArray(images) || paint.length + layout.length > nativeThemeValueLimits.values || images.length > nativeThemeValueLimits.images)
6930
+ return false;
6931
+ for (const entry of [...paint, ...layout]) {
6932
+ if (!Array.isArray(entry) || entry.length !== 3 || !layerOrImage(entry[0]) || !propertyName(entry[1]) || !plain(entry[2], 0))
6933
+ return false;
6934
+ }
6935
+ for (const entry of images) {
6936
+ if (!Array.isArray(entry) || entry.length !== 4 || !layerOrImage(entry[0]) || !layerOrImage(entry[1]) || !layerOrImage(entry[2]) || typeof entry[3] !== "number" || !(entry[3] >= 0 && entry[3] <= 1))
6937
+ return false;
6938
+ }
6939
+ if (light2 === void 0) return true;
6940
+ return Boolean(light2) && typeof light2 === "object" && !Array.isArray(light2) && plain(light2, 0);
6941
+ }
6942
+ function own2(value, name3) {
6523
6943
  if (!value || typeof value !== "object" || Array.isArray(value)) throw new NativeSurfaceError();
6524
6944
  const property = Object.getOwnPropertyDescriptor(value, name3);
6525
6945
  if (!property || !("value" in property)) throw new NativeSurfaceError();
6526
6946
  return property.value;
6527
6947
  }
6528
6948
  function eventFromNative(value) {
6529
- const surface = own(value, "surface");
6530
- const style = own(value, "style");
6531
- const sequence = own(value, "sequence");
6532
- const layout = own(value, "layout");
6533
- const kind = own(value, "kind");
6949
+ const surface = own2(value, "surface");
6950
+ const style = own2(value, "style");
6951
+ const sequence = own2(value, "sequence");
6952
+ const layout = own2(value, "layout");
6953
+ const kind = own2(value, "kind");
6534
6954
  if (!isNativeToken(surface) || !isNativeToken(style) || !positive(sequence) || !positive(layout))
6535
6955
  throw new NativeSurfaceError();
6536
6956
  const keys = Reflect.ownKeys(value);
6537
6957
  if (kind === "gesture-start" || kind === "gesture-change" || kind === "gesture-end") {
6538
- const gesture = own(value, "gesture");
6958
+ const gesture = own2(value, "gesture");
6539
6959
  if (!positive(gesture) || keys.length !== 7 || keys.some(
6540
- (key) => typeof key !== "string" || !["surface", "style", "sequence", "layout", "kind", "gesture", "view"].includes(key)
6960
+ (key2) => typeof key2 !== "string" || !["surface", "style", "sequence", "layout", "kind", "gesture", "view"].includes(key2)
6541
6961
  ))
6542
6962
  throw new NativeSurfaceError();
6543
6963
  return Object.freeze({
@@ -6547,11 +6967,11 @@ function eventFromNative(value) {
6547
6967
  layout,
6548
6968
  kind,
6549
6969
  gesture,
6550
- view: snapshotCameraView(own(value, "view"))
6970
+ view: snapshotCameraView(own2(value, "view"))
6551
6971
  });
6552
6972
  }
6553
6973
  if (!["style", "render", "invalidate", "error"].includes(String(kind)) || keys.length !== 5 || keys.some(
6554
- (key) => typeof key !== "string" || !["surface", "style", "sequence", "layout", "kind"].includes(key)
6974
+ (key2) => typeof key2 !== "string" || !["surface", "style", "sequence", "layout", "kind"].includes(key2)
6555
6975
  ))
6556
6976
  throw new NativeSurfaceError();
6557
6977
  return Object.freeze({ surface, style, sequence, layout, kind });
@@ -6579,6 +6999,14 @@ function createNativeSurfaceTransport(locate, listen) {
6579
6999
  available() {
6580
7000
  module();
6581
7001
  },
7002
+ /** Whether the native build can apply blend values; older builds cannot. */
7003
+ blending() {
7004
+ try {
7005
+ return typeof module().applyThemeValues === "function";
7006
+ } catch {
7007
+ return false;
7008
+ }
7009
+ },
6582
7010
  async attach(root, notify, failure3) {
6583
7011
  if (!positive(root) || reservations >= 16) throw new NativeSurfaceError();
6584
7012
  const native = module();
@@ -6629,7 +7057,7 @@ function createNativeSurfaceTransport(locate, listen) {
6629
7057
  unsubscribe = listen((value) => {
6630
7058
  if (!live || !id) return;
6631
7059
  try {
6632
- if (own(value, "surface") !== id) return;
7060
+ if (own2(value, "surface") !== id) return;
6633
7061
  } catch {
6634
7062
  return;
6635
7063
  }
@@ -6710,6 +7138,37 @@ function createNativeSurfaceTransport(locate, listen) {
6710
7138
  if (ack?.cancelled !== true) throw new NativeSurfaceError();
6711
7139
  return Object.freeze({ cancelled: true });
6712
7140
  },
7141
+ ...typeof native.coverSurface === "function" && typeof native.revealSurface === "function" && typeof native.discardSurfaceCover === "function" ? {
7142
+ async cover(duration) {
7143
+ check();
7144
+ if (!motionDuration(duration)) throw new NativeSurfaceError();
7145
+ const ack = await safe(() => native.coverSurface(surface, duration));
7146
+ check();
7147
+ if (typeof ack?.covered !== "boolean") throw new NativeSurfaceError();
7148
+ return ack.covered;
7149
+ },
7150
+ async reveal(duration) {
7151
+ check();
7152
+ if (!motionDuration(duration)) throw new NativeSurfaceError();
7153
+ const ack = await safe(() => native.revealSurface(surface, duration));
7154
+ if (ack?.revealed !== true) throw new NativeSurfaceError();
7155
+ },
7156
+ async discardCover() {
7157
+ const ack = await safe(() => native.discardSurfaceCover(surface));
7158
+ if (ack?.discarded !== true) throw new NativeSurfaceError();
7159
+ }
7160
+ } : {},
7161
+ ...typeof native.applyThemeValues === "function" ? {
7162
+ async applyThemeValues(style, values) {
7163
+ check();
7164
+ if (!isNativeToken(style) || !themeValues(values)) throw new NativeSurfaceError();
7165
+ const ack = await safe(() => native.applyThemeValues(surface, style, values));
7166
+ check();
7167
+ if (!Number.isSafeInteger(ack?.applied) || ack.applied < 0)
7168
+ throw new NativeSurfaceError();
7169
+ return ack.applied;
7170
+ }
7171
+ } : {},
6713
7172
  retire() {
6714
7173
  if (retirement) return retirement;
6715
7174
  live = false;
@@ -6845,6 +7304,10 @@ function NativeScene({
6845
7304
  lifecycle.unbindInteractionHost(host);
6846
7305
  };
6847
7306
  }, [host, lifecycle]);
7307
+ const mapStyle = useMemo2(
7308
+ () => JSON.stringify(scene.style),
7309
+ [scene.style]
7310
+ );
6848
7311
  const [initialViewState] = useState(() => {
6849
7312
  const center = [scene.initialView.center[0], scene.initialView.center[1]];
6850
7313
  Object.freeze(center);
@@ -6894,7 +7357,7 @@ function NativeScene({
6894
7357
  ...mapOptions,
6895
7358
  ref: nativeMap,
6896
7359
  style: fill,
6897
- mapStyle: scene.style,
7360
+ mapStyle,
6898
7361
  onPress: (event) => {
6899
7362
  if (!host.current()) return;
6900
7363
  try {