@tileflow/core 0.1.0-alpha.31 → 0.1.0-alpha.32

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
@@ -2174,8 +2174,19 @@ var tileflowCaptureSceneSchema = z3.object({
2174
2174
  viewport: tileflowCaptureViewportSchema,
2175
2175
  target: tileflowCaptureTargetSchema.optional()
2176
2176
  }).strict();
2177
+ function tileflowCaptureSceneFitIssue(scene) {
2178
+ if (scene.camera.type !== "bounds" || scene.camera.padding === void 0) return void 0;
2179
+ const room = Math.min(scene.viewport.width, scene.viewport.height);
2180
+ if (scene.camera.padding * 2 < room) return void 0;
2181
+ return {
2182
+ message: `Expected bounds padding less than half the viewport's shorter side (${room / 2} pixels)`,
2183
+ path: ["camera", "padding"]
2184
+ };
2185
+ }
2177
2186
  function normalizeTileflowCaptureScene(input) {
2178
2187
  const scene = tileflowCaptureSceneSchema.parse(input);
2188
+ const fit = tileflowCaptureSceneFitIssue(scene);
2189
+ if (fit) throw new RangeError(`${fit.path.join(".")}: ${fit.message}`);
2179
2190
  const camera = scene.camera.type === "center" ? {
2180
2191
  type: scene.camera.type,
2181
2192
  center: scene.camera.center,
@@ -2391,6 +2402,7 @@ var canonicalLayers = {
2391
2402
  boundary: "boundary",
2392
2403
  building: "building",
2393
2404
  businessCorridor: "business_corridor",
2405
+ canopy: "canopy",
2394
2406
  globalLandcover: "globallandcover",
2395
2407
  houseNumber: "housenumber",
2396
2408
  landcover: "landcover",
@@ -2412,8 +2424,10 @@ var canonicalFields = {
2412
2424
  adminLevel: "admin_level",
2413
2425
  bicycle: "bicycle",
2414
2426
  brunnel: "brunnel",
2415
- buildingKind: "building_kind",
2416
2427
  buildingTone: "building_tone",
2428
+ canopyClearanceAtZoom15: "clearance_px_z15",
2429
+ canopyCoverPercent: "cover_pct",
2430
+ canopyRank: "rank",
2417
2431
  capital: "capital",
2418
2432
  circularClearanceExtraAtZoom15: "clearance_extra_px_z15",
2419
2433
  circularInnerRadiusMeters: "inner_radius_m",
@@ -2424,9 +2438,9 @@ var canonicalFields = {
2424
2438
  class: "class",
2425
2439
  crossing: "crossing",
2426
2440
  circumference: "circumference",
2427
- classificationConfidence: "classification_confidence",
2428
2441
  confidence: "confidence",
2429
2442
  diameterCrown: "diameter_crown",
2443
+ direction: "direction",
2430
2444
  disputed: "disputed",
2431
2445
  elevation: "ele",
2432
2446
  elevationFeet: "ele_ft",
@@ -2434,7 +2448,6 @@ var canonicalFields = {
2434
2448
  foot: "foot",
2435
2449
  height: "height",
2436
2450
  hide3d: "hide_3d",
2437
- hasBusiness: "has_business",
2438
2451
  hasParts: "has_parts",
2439
2452
  horse: "horse",
2440
2453
  houseNumber: "housenumber",
@@ -2469,7 +2482,6 @@ var canonicalFields = {
2469
2482
  ref: "ref",
2470
2483
  refLength: "ref_length",
2471
2484
  renderHeight: "render_height",
2472
- renderMinZoom: "render_min_zoom",
2473
2485
  renderMinHeight: "render_min_height",
2474
2486
  service: "service",
2475
2487
  species: "species",
@@ -2492,6 +2504,7 @@ function openMapTiles(options = {}) {
2492
2504
  delete fields.bathymetryMinDepth;
2493
2505
  delete fields.bathymetrySortKey;
2494
2506
  }
2507
+ if (options.capabilities?.canopy === false) delete layers.canopy;
2495
2508
  if (options.capabilities?.globalLandcover === false) delete layers.globalLandcover;
2496
2509
  if (options.capabilities?.tree === false) delete layers.tree;
2497
2510
  return {
@@ -2509,14 +2522,6 @@ function tileflowWorldV1Schema(options = {}) {
2509
2522
  ...options,
2510
2523
  capabilities: { ...options.capabilities, bathymetry: true, globalLandcover: true },
2511
2524
  fields: {
2512
- circularClearanceExtraAtZoom15: "clearance_extra_px_z15",
2513
- circularInnerRadiusMeters: "inner_radius_m",
2514
- circularKind: "circle_kind",
2515
- circularOuterRadiusMeters: "outer_radius_m",
2516
- circularRadiusAtZoom15: "radius_px_z15",
2517
- circularRadiusMeters: "radius_m",
2518
- direction: "direction",
2519
- hasParts: "has_parts",
2520
2525
  shieldKind: "shield_kind",
2521
2526
  shieldLineLengthMeters: "shield_line_length_m",
2522
2527
  shieldNetwork: "shield_network",
@@ -2547,6 +2552,7 @@ function validateTileflowWorldV1Tilejson(tilejson, schema = tileflowWorldV1Schem
2547
2552
  const road = requireTilejsonLayer(layers, schema.layers.road, issues);
2548
2553
  const roadName = requireTilejsonLayer(layers, schema.layers.roadName, issues);
2549
2554
  const roadShield = requireTilejsonLayer(layers, schema.layers.roadShield, issues);
2555
+ const canopy = optionalTilejsonLayer(layers, schema.layers.canopy, issues);
2550
2556
  if (bathymetry2) {
2551
2557
  if (bathymetry2.minzoom !== 0 || bathymetry2.maxzoom !== 9) {
2552
2558
  issues.push(`Tileflow World V1 ${schema.layers.bathymetry} must declare z0-z9.`);
@@ -2719,6 +2725,18 @@ function validateTileflowWorldV1Tilejson(tilejson, schema = tileflowWorldV1Schem
2719
2725
  requireTilejsonField(roadShield, schema.layers.roadShield, field2, ["Number"], issues);
2720
2726
  }
2721
2727
  }
2728
+ if (canopy && schema.layers.canopy) {
2729
+ if (canopy.minzoom !== 14 || canopy.maxzoom !== 15) {
2730
+ issues.push(`Tileflow World V1 ${schema.layers.canopy} must declare native z14-z15.`);
2731
+ }
2732
+ for (const field2 of [
2733
+ schema.fields.canopyRank,
2734
+ schema.fields.canopyClearanceAtZoom15,
2735
+ schema.fields.canopyCoverPercent
2736
+ ]) {
2737
+ requireTilejsonField(canopy, schema.layers.canopy, field2, ["Number"], issues);
2738
+ }
2739
+ }
2722
2740
  return issues;
2723
2741
  }
2724
2742
  function requireTilejsonLayer(layers, id2, issues) {
@@ -2735,6 +2753,13 @@ function requireTilejsonLayer(layers, id2, issues) {
2735
2753
  }
2736
2754
  return matches[0];
2737
2755
  }
2756
+ function optionalTilejsonLayer(layers, id2, issues) {
2757
+ if (id2 === void 0) return void 0;
2758
+ const declared = layers.some(
2759
+ (layer) => typeof layer === "object" && layer !== null && layer.id === id2
2760
+ );
2761
+ return declared ? requireTilejsonLayer(layers, id2, issues) : void 0;
2762
+ }
2738
2763
  function requireNativeZoom15(layer, layerId, issues) {
2739
2764
  if (layer.minzoom !== 15 || layer.maxzoom !== 15) {
2740
2765
  issues.push(`Tileflow World V1 ${layerId} must declare native z15.`);
@@ -2839,7 +2864,7 @@ function resolveTileflowData(data, options = {}) {
2839
2864
  };
2840
2865
  }
2841
2866
  function isCanonicalOpenMapTilesSchema(schema) {
2842
- return (schema.semantics?.parkLayer ?? "mixed") === "mixed" && Object.entries(canonicalLayers).every(
2867
+ return schema.semantics.parkLayer === "mixed" && Object.entries(canonicalLayers).every(
2843
2868
  ([key, value]) => schema.layers[key] === value
2844
2869
  ) && Object.entries(canonicalFields).every(
2845
2870
  ([key, value]) => schema.fields[key] === value
@@ -2857,6 +2882,7 @@ function dataIdentity(kind, schema, version, url) {
2857
2882
  capabilities: {
2858
2883
  businessCorridor: Boolean(schema.layers.businessCorridor),
2859
2884
  bathymetry: Boolean(schema.layers.bathymetry),
2885
+ canopy: Boolean(schema.layers.canopy),
2860
2886
  globalLandcover: Boolean(schema.layers.globalLandcover),
2861
2887
  tree: Boolean(schema.layers.tree)
2862
2888
  }
@@ -3013,7 +3039,7 @@ function validateOpenMapTilesSchema(schema) {
3013
3039
  `Tileflow requires OpenMapTiles contract version ${openMapTilesContractVersion}.`
3014
3040
  );
3015
3041
  }
3016
- const parkLayer = schema.semantics?.parkLayer ?? "mixed";
3042
+ const parkLayer = schema.semantics?.parkLayer;
3017
3043
  if (parkLayer !== "mixed" && parkLayer !== "protected-only") {
3018
3044
  throw new Error("Tileflow OpenMapTiles semantics.parkLayer is invalid.");
3019
3045
  }
@@ -3942,7 +3968,7 @@ function applyTextStyle(layer, style) {
3942
3968
  layout["text-variable-anchor"] = [...style.variableAnchors];
3943
3969
  }
3944
3970
  if (style.justify !== void 0) layout["text-justify"] = style.justify;
3945
- if (style.allowOverlap !== void 0) layout["text-allow-overlap"] = style.allowOverlap;
3971
+ setOverlap(layout, "text", style);
3946
3972
  if (style.ignorePlacement !== void 0) layout["text-ignore-placement"] = style.ignorePlacement;
3947
3973
  if (style.keepUpright !== void 0) layout["text-keep-upright"] = style.keepUpright;
3948
3974
  if (style.optional !== void 0) layout["text-optional"] = style.optional;
@@ -4012,7 +4038,7 @@ function applyIconStyle(layer, style) {
4012
4038
  if (style.rotationAlignment !== void 0) {
4013
4039
  layout["icon-rotation-alignment"] = style.rotationAlignment;
4014
4040
  }
4015
- if (style.allowOverlap !== void 0) layout["icon-allow-overlap"] = style.allowOverlap;
4041
+ setOverlap(layout, "icon", style);
4016
4042
  if (style.ignorePlacement !== void 0) layout["icon-ignore-placement"] = style.ignorePlacement;
4017
4043
  if (style.keepUpright !== void 0) layout["icon-keep-upright"] = style.keepUpright;
4018
4044
  if (style.optional !== void 0) layout["icon-optional"] = style.optional;
@@ -4130,6 +4156,18 @@ function withoutRange(value) {
4130
4156
  const { maxZoom: _maxZoom, minZoom: _minZoom, visible: _visible, ...rest } = value;
4131
4157
  return rest;
4132
4158
  }
4159
+ function setOverlap(layout, part, style) {
4160
+ if (style.overlap !== void 0) layout[`${part}-overlap`] = style.overlap;
4161
+ else if (style.allowOverlap !== void 0) layout[`${part}-allow-overlap`] = style.allowOverlap;
4162
+ if (layout[`${part}-overlap`] !== void 0) delete layout[`${part}-allow-overlap`];
4163
+ }
4164
+ function withoutGovernedAllowOverlap(layout) {
4165
+ const result = { ...layout };
4166
+ for (const part of ["icon", "text"]) {
4167
+ if (result[`${part}-overlap`] !== void 0) delete result[`${part}-allow-overlap`];
4168
+ }
4169
+ return result;
4170
+ }
4133
4171
  function setPaint(paint, property, value) {
4134
4172
  if (value !== void 0) paint[property] = toMapLibreStyleValue(value);
4135
4173
  }
@@ -4668,15 +4706,6 @@ function buildingColorExpression(context) {
4668
4706
  colors.destination,
4669
4707
  ["==", ["coalesce", ["get", fields.buildingTone], ""], "commercial"],
4670
4708
  colors.commercial,
4671
- // Defensive compatibility for immutable V8.9 archives. New candidates emit building_tone.
4672
- [
4673
- "any",
4674
- ["==", ["get", fields.hasBusiness], true],
4675
- ["==", ["get", fields.hasBusiness], 1],
4676
- ["==", ["get", fields.hasBusiness], "1"],
4677
- ["==", ["coalesce", ["get", fields.buildingKind], "generic"], "commercial"]
4678
- ],
4679
- colors.commercial,
4680
4709
  colors.generic
4681
4710
  ];
4682
4711
  }
@@ -6757,7 +6786,7 @@ function createPoiLayer(options) {
6757
6786
  ["==", ["get", options.categoryField], options.category],
6758
6787
  ["has", options.filterRankField],
6759
6788
  [">=", filterRank, 0],
6760
- ["<=", filterRank, options.density],
6789
+ ["<=", filterRank, poiRankThreshold(options.density)],
6761
6790
  ["has", options.sizeRankField],
6762
6791
  [">=", sizeRank, 0],
6763
6792
  ["<=", sizeRank, 16]
@@ -6765,6 +6794,9 @@ function createPoiLayer(options) {
6765
6794
  layout: { "symbol-sort-key": poiSortKey(options.filterRankField, options.sizeRankField) }
6766
6795
  };
6767
6796
  }
6797
+ function poiRankThreshold(density) {
6798
+ return ["+", ["step", ["zoom"], 0, 16, 1, 17, 2], density];
6799
+ }
6768
6800
  function numericPoiField(field2, fallback) {
6769
6801
  return ["to-number", ["get", field2], fallback];
6770
6802
  }
@@ -7704,9 +7736,7 @@ function compileSidewalks(request, context, contributions) {
7704
7736
  }
7705
7737
  function compileRoundabouts(request, context, contributions) {
7706
7738
  const { fields, layers } = context.data.schema;
7707
- if (!layers.circularFeature || !fields.circularKind || !fields.circularRadiusAtZoom15 || !fields.circularRadiusMeters || !fields.circularOuterRadiusMeters || !fields.circularInnerRadiusMeters) {
7708
- return;
7709
- }
7739
+ if (!layers.circularFeature) return;
7710
7740
  const circularFields = {
7711
7741
  circularInnerRadiusMeters: fields.circularInnerRadiusMeters,
7712
7742
  circularOuterRadiusMeters: fields.circularOuterRadiusMeters,
@@ -7780,7 +7810,7 @@ function compileRoundabouts(request, context, contributions) {
7780
7810
  }
7781
7811
  function compileCrossings(request, context, contributions) {
7782
7812
  const { fields, layers } = context.data.schema;
7783
- if (!request || !layers.streetFurniture || !fields.direction) return;
7813
+ if (!request || !layers.streetFurniture) return;
7784
7814
  const config = mergeTileflowDesign(
7785
7815
  {
7786
7816
  allowOverlap: true,
@@ -7846,7 +7876,7 @@ function circularRoadInnerRadius(fields, casing) {
7846
7876
  ["/", values.innerRadiusMeters, values.radiusMeters]
7847
7877
  ];
7848
7878
  const baseWidth = circularRoadBaseWidth(fields.class);
7849
- const fallbackWidth = level === 15 ? baseWidth : ["*", baseWidth, circularRoadLegacyScale(level)];
7879
+ const fallbackWidth = level === 15 ? baseWidth : ["*", baseWidth, circularRoadFallbackScale(level)];
7850
7880
  const fallbackInnerRadius = ["-", centerlineRadius, ["/", fallbackWidth, 2]];
7851
7881
  const innerRadius = ["case", values.hasPhysicalRadii, physicalInnerRadius, fallbackInnerRadius];
7852
7882
  stops.push(level, [
@@ -7868,7 +7898,7 @@ function circularRoadStrokeWidth(fields, casing) {
7868
7898
  centerlineRadius,
7869
7899
  ["/", ["-", values.outerRadiusMeters, values.innerRadiusMeters], values.radiusMeters]
7870
7900
  ];
7871
- const fallbackWidth = level === 15 ? baseWidth : ["*", baseWidth, circularRoadLegacyScale(level)];
7901
+ const fallbackWidth = level === 15 ? baseWidth : ["*", baseWidth, circularRoadFallbackScale(level)];
7872
7902
  stops.push(level, [
7873
7903
  "case",
7874
7904
  values.hasPhysicalRadii,
@@ -7917,7 +7947,7 @@ function circularRoadValues(fields) {
7917
7947
  radiusMeters
7918
7948
  };
7919
7949
  }
7920
- function circularRoadLegacyScale(level) {
7950
+ function circularRoadFallbackScale(level) {
7921
7951
  const interpolationBase = 1.35;
7922
7952
  const progress = (interpolationBase ** (level - 15) - 1) / (interpolationBase ** (22 - 15) - 1);
7923
7953
  return 1 + progress * 1.2;
@@ -8524,7 +8554,7 @@ function cloneJson16(value) {
8524
8554
  // src/modules/vegetation/compiler.ts
8525
8555
  init_values();
8526
8556
  function compileVegetation(request, context) {
8527
- const minZoom = request?.flat?.minZoom ?? request?.minZoom ?? 16;
8557
+ const minZoom = request?.flat?.minZoom ?? 16;
8528
8558
  const mode = request?.mode ?? "3d";
8529
8559
  const config = mergeTileflowDesign(
8530
8560
  {
@@ -8544,7 +8574,6 @@ function compileVegetation(request, context) {
8544
8574
  strokeOpacity: 0.55,
8545
8575
  strokeWidth: 0.8
8546
8576
  },
8547
- minZoom,
8548
8577
  mode,
8549
8578
  threeDimensional: {
8550
8579
  barkColor: context.colors.vegetation.tree.bark,
@@ -11364,10 +11393,10 @@ function applyRefinement(previous, refinement) {
11364
11393
  style: {
11365
11394
  ...previous.style,
11366
11395
  ...patch.style?.placement === void 0 ? {} : {
11367
- placement: {
11396
+ placement: withoutGovernedAllowOverlap({
11368
11397
  ...previous.style.placement ?? {},
11369
11398
  ...patch.style.placement
11370
- }
11399
+ })
11371
11400
  },
11372
11401
  ...patch.style?.appearance === void 0 ? {} : {
11373
11402
  appearance: {
@@ -12288,6 +12317,7 @@ var textStyleSchema = z6.object({
12288
12317
  offset: numberOffsetValueSchema.optional(),
12289
12318
  optional: z6.boolean().optional(),
12290
12319
  opacity: numberValueSchema.optional(),
12320
+ overlap: z6.enum(["always", "cooperative", "never"]).optional(),
12291
12321
  padding: numberValueSchema.optional(),
12292
12322
  pitchAlignment: z6.enum(["auto", "map", "viewport"]).optional(),
12293
12323
  radialOffset: numberValueSchema.optional(),
@@ -12333,6 +12363,7 @@ var iconStyleSchema = z6.object({
12333
12363
  opacity: numberValueSchema.optional(),
12334
12364
  keepUpright: z6.boolean().optional(),
12335
12365
  optional: z6.boolean().optional(),
12366
+ overlap: z6.enum(["always", "cooperative", "never"]).optional(),
12336
12367
  padding: numberValueSchema.optional(),
12337
12368
  pitchAlignment: z6.enum(["auto", "map", "viewport"]).optional(),
12338
12369
  rotate: numberValueSchema.optional(),
@@ -12905,7 +12936,6 @@ var modulesSchema = z6.object({
12905
12936
  type: z6.literal("vegetation"),
12906
12937
  enabled: z6.boolean().optional(),
12907
12938
  flat: circleStyleSchema.optional(),
12908
- minZoom: zoomNumberSchema.optional(),
12909
12939
  mode: z6.enum(["3d", "flat"]).optional(),
12910
12940
  renderStack: renderStackSchema.optional(),
12911
12941
  threeDimensional: z6.object({
@@ -12941,6 +12971,7 @@ var layerBindingsSchema = z6.object({
12941
12971
  building: z6.string().trim().min(1),
12942
12972
  bathymetry: z6.string().trim().min(1).optional(),
12943
12973
  businessCorridor: z6.string().trim().min(1).optional(),
12974
+ canopy: z6.string().trim().min(1).optional(),
12944
12975
  circularFeature: z6.string().trim().min(1).optional(),
12945
12976
  globalLandcover: z6.string().trim().min(1).optional(),
12946
12977
  houseNumber: z6.string().trim().min(1),
@@ -12968,34 +12999,34 @@ var fieldBindingsSchema = z6.object({
12968
12999
  bathymetryMinDepth: z6.string().trim().min(1).optional(),
12969
13000
  bathymetrySortKey: z6.string().trim().min(1).optional(),
12970
13001
  brunnel: z6.string().trim().min(1),
12971
- buildingKind: z6.string().trim().min(1),
12972
13002
  buildingTone: z6.string().trim().min(1),
13003
+ canopyClearanceAtZoom15: z6.string().trim().min(1),
13004
+ canopyCoverPercent: z6.string().trim().min(1),
13005
+ canopyRank: z6.string().trim().min(1),
12973
13006
  capital: z6.string().trim().min(1),
12974
- circularClearanceExtraAtZoom15: z6.string().trim().min(1).optional(),
12975
- circularKind: z6.string().trim().min(1).optional(),
12976
- circularRadiusAtZoom15: z6.string().trim().min(1).optional(),
12977
- circularRadiusMeters: z6.string().trim().min(1).optional(),
12978
- circularInnerRadiusMeters: z6.string().trim().min(1).optional(),
12979
- circularOuterRadiusMeters: z6.string().trim().min(1).optional(),
13007
+ circularClearanceExtraAtZoom15: z6.string().trim().min(1),
13008
+ circularKind: z6.string().trim().min(1),
13009
+ circularRadiusAtZoom15: z6.string().trim().min(1),
13010
+ circularRadiusMeters: z6.string().trim().min(1),
13011
+ circularInnerRadiusMeters: z6.string().trim().min(1),
13012
+ circularOuterRadiusMeters: z6.string().trim().min(1),
12980
13013
  class: z6.string().trim().min(1),
12981
13014
  crossing: z6.string().trim().min(1),
12982
- classificationConfidence: z6.string().trim().min(1),
12983
13015
  confidence: z6.string().trim().min(1),
12984
13016
  circumference: z6.string().trim().min(1),
12985
13017
  diameterCrown: z6.string().trim().min(1),
12986
13018
  disputed: z6.string().trim().min(1),
12987
- direction: z6.string().trim().min(1).optional(),
13019
+ direction: z6.string().trim().min(1),
12988
13020
  elevation: z6.string().trim().min(1),
12989
13021
  elevationFeet: z6.string().trim().min(1),
12990
13022
  expressway: z6.string().trim().min(1),
12991
13023
  foot: z6.string().trim().min(1),
12992
13024
  height: z6.string().trim().min(1),
12993
- hasBusiness: z6.string().trim().min(1),
12994
- hasParts: z6.string().trim().min(1).optional(),
13025
+ hasParts: z6.string().trim().min(1),
12995
13026
  hide3d: z6.string().trim().min(1),
12996
13027
  horse: z6.string().trim().min(1),
12997
13028
  houseNumber: z6.string().trim().min(1),
12998
- importanceTier: z6.string().trim().min(1).optional(),
13029
+ importanceTier: z6.string().trim().min(1),
12999
13030
  iata: z6.string().trim().min(1),
13000
13031
  icao: z6.string().trim().min(1),
13001
13032
  indoor: z6.string().trim().min(1),
@@ -13026,7 +13057,6 @@ var fieldBindingsSchema = z6.object({
13026
13057
  ref: z6.string().trim().min(1),
13027
13058
  refLength: z6.string().trim().min(1),
13028
13059
  renderHeight: z6.string().trim().min(1),
13029
- renderMinZoom: z6.string().trim().min(1),
13030
13060
  renderMinHeight: z6.string().trim().min(1),
13031
13061
  shieldKind: z6.string().trim().min(1).optional(),
13032
13062
  shieldLineLengthMeters: z6.string().trim().min(1).optional(),
@@ -13052,6 +13082,7 @@ var openMapTilesSchema = z6.object({
13052
13082
  capabilities: schema.layers === void 0 ? void 0 : {
13053
13083
  businessCorridor: schema.layers.businessCorridor !== void 0,
13054
13084
  bathymetry: schema.layers.bathymetry !== void 0,
13085
+ canopy: schema.layers.canopy !== void 0,
13055
13086
  globalLandcover: schema.layers.globalLandcover !== void 0,
13056
13087
  tree: schema.layers.tree !== void 0
13057
13088
  },
@@ -16340,8 +16371,8 @@ function validateMapScenes(map, mapId) {
16340
16371
  );
16341
16372
  }
16342
16373
  const result = tileflowCaptureSceneSchema.safeParse({ ...input, map: mapId });
16343
- if (!result.success) {
16344
- const issue = result.error.issues[0];
16374
+ const issue = result.success ? tileflowCaptureSceneFitIssue(result.data) : result.error.issues[0];
16375
+ if (!result.success || issue) {
16345
16376
  throw new Error(
16346
16377
  `Invalid Tileflow map "${map.id}". scenes.${sceneName}${issue?.path.length ? `.${issue.path.join(".")}` : ""}: ${issue?.message ?? "Invalid scene"}`
16347
16378
  );
@@ -125,6 +125,11 @@ type TileflowTextJustify = 'auto' | 'center' | 'left' | 'right';
125
125
  type TileflowIconAnchor = TileflowTextAnchor;
126
126
  type TileflowAlignment = 'auto' | 'map' | 'viewport';
127
127
  type TileflowIconTextFit = 'both' | 'height' | 'none' | 'width';
128
+ /**
129
+ * How a symbol part treats collisions with symbols placed before it. `never` hides it, `always`
130
+ * shows it, and `cooperative` shows it unless the earlier symbol was placed with `never`.
131
+ */
132
+ type TileflowSymbolOverlap = 'always' | 'cooperative' | 'never';
128
133
  /** Visibility and zoom bounds shared by every visual primitive. */
129
134
  type TileflowLayerRange = {
130
135
  maxZoom?: number;
@@ -221,6 +226,12 @@ type TileflowTextLayout = {
221
226
  maxWidth?: TileflowNumberStyleValue;
222
227
  offset?: TileflowNumberOffsetStyleValue;
223
228
  optional?: boolean;
229
+ /**
230
+ * Overlap mode. Takes precedence over `allowOverlap`, so the compiled layer carries only the mode.
231
+ * Native artifacts, whose renderer has no overlap modes, use `allowOverlap: false` for `never`
232
+ * and `true` otherwise.
233
+ */
234
+ overlap?: TileflowSymbolOverlap;
224
235
  padding?: TileflowNumberStyleValue;
225
236
  pitchAlignment?: TileflowAlignment;
226
237
  radialOffset?: TileflowNumberStyleValue;
@@ -246,6 +257,12 @@ type TileflowIconLayout = {
246
257
  keepUpright?: boolean;
247
258
  offset?: TileflowNumberOffsetStyleValue;
248
259
  optional?: boolean;
260
+ /**
261
+ * Overlap mode. Takes precedence over `allowOverlap`, so the compiled layer carries only the mode.
262
+ * Native artifacts, whose renderer has no overlap modes, use `allowOverlap: false` for `never`
263
+ * and `true` otherwise.
264
+ */
265
+ overlap?: TileflowSymbolOverlap;
249
266
  padding?: TileflowNumberStyleValue;
250
267
  pitchAlignment?: TileflowAlignment;
251
268
  rotate?: TileflowNumberStyleValue;
@@ -787,4 +804,4 @@ type TileflowRuntimeManifest = {
787
804
  version: typeof tileflowRuntimeManifestVersion;
788
805
  };
789
806
 
790
- export { type TileflowManifestFetchOptions as $, type TileflowAreaStyle as A, type TileflowBackgroundPaint as B, type TileflowCirclePaint as C, type TileflowColor as D, type TileflowColorStyleValue as E, type TileflowExtrusionPaint as F, type TileflowFillPaint as G, type TileflowIconAnchor as H, type TileflowIconLayout as I, type TileflowIconPaint as J, type TileflowIconStyle as K, type TileflowIconTextFit as L, type MapLibreStyle as M, type TileflowImageStyleValue as N, type TileflowLabelDetail as O, type TileflowLabelLanguage as P, type TileflowLabelStyles as Q, type TileflowLayerRange as R, type TileflowLight as S, type TileflowRuntimeManifest as T, type TileflowLineCap as U, type ValidationMessage as V, type TileflowLineHatchStyle as W, type TileflowLineJoin as X, type TileflowLineLayout as Y, type TileflowLinePaint as Z, type TileflowLineStackStyle as _, type TileflowRuntimeColorScheme as a, type TileflowTextBackground as a$, type TileflowManifestLoadOptions as a0, type TileflowMapMode as a1, type TileflowMapModeOptions as a2, type TileflowMarkerSymbolStyle as a3, type TileflowMountainBikeScale as a4, type TileflowNumberInsetsStyleValue as a5, type TileflowNumberStyleValue as a6, type TileflowPlaceLabelClass as a7, type TileflowPoiCategory as a8, type TileflowPoiCategoryStyle as a9, type TileflowRoadWeight as aA, type TileflowRuntimeCenterLike as aB, type TileflowRuntimeManifestMap as aC, type TileflowRuntimeSource as aD, type TileflowRuntimeSourceValidation as aE, type TileflowRuntimeStyle as aF, type TileflowRuntimeStyleOptions as aG, type TileflowRuntimeViewOptions as aH, type TileflowSessionController as aI, type TileflowSessionGrantResponse as aJ, type TileflowStringStyleValue as aK, type TileflowStructuralStyleValue as aL, type TileflowStyleFontFace as aM, type TileflowStyleValue as aN, type TileflowSymbolPlacement as aO, type TileflowSymbolPlacementStyle as aP, type TileflowSymbolZOrder as aQ, type TileflowTerrain as aR, type TileflowTerrainConfig as aS, type TileflowTerrainContourLabelStyle as aT, type TileflowTerrainContourLineStyle as aU, type TileflowTerrainContoursConfig as aV, type TileflowTerrainEncoding as aW, type TileflowTerrainHillshadeStyle as aX, type TileflowTerrainLayerRange as aY, type TileflowTerrainMode as aZ, type TileflowTextAnchor as a_, type TileflowPoiColorMode as aa, type TileflowPoiDensity as ab, type TileflowPriorityOrder as ac, type TileflowProjection as ad, type TileflowResolvedRuntimeTheme as ae, type TileflowRoadAreaStyle as af, type TileflowRoadClass as ag, type TileflowRoadClassStyle as ah, type TileflowRoadCrossingStyle as ai, type TileflowRoadDetail as aj, type TileflowRoadExtras as ak, type TileflowRoadHierarchy as al, type TileflowRoadLabelDetail as am, type TileflowRoadLayerStyle as an, type TileflowRoadModifier as ao, type TileflowRoadOutline as ap, type TileflowRoadRestriction as aq, type TileflowRoadRoundaboutStyle as ar, type TileflowRoadServiceType as as, type TileflowRoadShieldDetail as at, type TileflowRoadShieldStyles as au, type TileflowRoadSidewalkStyle as av, type TileflowRoadStructure as aw, type TileflowRoadTreatmentLayerStyle as ax, type TileflowRoadTreatmentLineStyle as ay, type TileflowRoadTreatmentStyle as az, type TileflowRuntimeManifestMapEntry as b, type TileflowTextJustify as b0, type TileflowTextLayout as b1, type TileflowTextPaint as b2, type TileflowTextStyle as b3, type TileflowThemeBlendSelection as b4, type TileflowThemeColorAlpha as b5, type TileflowThemeColorMix as b6, type TileflowThemeColorValue as b7, type TileflowThemeFontValue as b8, type TileflowThemeImageValue as b9, resolveTileflowAnalyticsRequestUrl as bA, resolveTileflowManifestMap as bB, resolveTileflowMapMode as bC, resolveTileflowRuntimeStyle as bD, resolveTileflowRuntimeTheme as bE, resolveTileflowRuntimeThemeBlend as bF, resolveTileflowRuntimeView as bG, resolveTileflowStaticImageUrl as bH, shouldLoadTileflowManifest as bI, startTileflowSession as bJ, tileflowPoiCategories as bK, tileflowStyleFontFaceLimits as bL, tileflowStyleFontFacesMetadataKey as bM, tileflowThemeBlendLimits as bN, tileflowThemeTokenCategories as bO, token as bP, validateTileflowRuntimeSource as bQ, validateTileflowThemeBlendSelection as bR, validateTileflowThemeSelection as bS, zoom as bT, type TileflowTypographyStyle as bU, type ResolvedTileflowTypography as bV, normalizeTileflowSurfaceId as bW, type TileflowThemeNumberValue as ba, type TileflowThemeSelection as bb, type TileflowThemeTokenCategory as bc, type TileflowThemeValue as bd, type TileflowViewConfig as be, type TileflowWaterLabelClass as bf, type TileflowZoomInterpolation as bg, type TileflowZoomValue as bh, type ValidationResult as bi, assertValidTileflowRuntimeSource as bj, clearTileflowManifestCache as bk, color as bl, createTileflowSessionController as bm, createTileflowSessionId as bn, defaultTileflowManifestUrl as bo, defaultTileflowRuntimeView as bp, fixed as bq, getTileflowAnalyticsApiUrl as br, getTileflowStyleFontFaces as bs, inferTileflowAnalyticsFromStyleUrl as bt, loadTileflowManifest as bu, mergeTileflowAnalytics as bv, nearestTileflowBlendTheme as bw, normalizeTileflowRuntimeCenter as bx, normalizeTileflowStaticImageSize as by, normalizeTileflowUrl as bz, type TileflowRuntimeManifestTheme as c, type TileflowRuntimeSystemThemes as d, tileflowRuntimeManifestVersion as e, type TileflowExpression as f, type TileflowFixedValue as g, type TileflowThemeTokenReference as h, type TileflowThemeColorOperation as i, type TileflowBackgroundStyle as j, type TileflowCircleStyle as k, type TileflowExtrusionStyle as l, type TileflowFillStyle as m, type TileflowLineStyle as n, type TileflowSymbolStyle as o, type TileflowRoadsModuleOptions as p, type TileflowRoadsModuleConfig as q, type TileflowLabelsModuleOptions as r, type TileflowLabelsModuleConfig as s, tileflowRuntimeManifestLimits as t, type TileflowPoiModuleOptions as u, type TileflowPoiModuleConfig as v, type MapLibreSprite as w, type TileflowAerodromeCodeDetail as x, type TileflowAlignment as y, type TileflowAnalytics as z };
807
+ export { type TileflowManifestFetchOptions as $, type TileflowAreaStyle as A, type TileflowBackgroundPaint as B, type TileflowCirclePaint as C, type TileflowColor as D, type TileflowColorStyleValue as E, type TileflowExtrusionPaint as F, type TileflowFillPaint as G, type TileflowIconAnchor as H, type TileflowIconLayout as I, type TileflowIconPaint as J, type TileflowIconStyle as K, type TileflowIconTextFit as L, type MapLibreStyle as M, type TileflowImageStyleValue as N, type TileflowLabelDetail as O, type TileflowLabelLanguage as P, type TileflowLabelStyles as Q, type TileflowLayerRange as R, type TileflowLight as S, type TileflowRuntimeManifest as T, type TileflowLineCap as U, type ValidationMessage as V, type TileflowLineHatchStyle as W, type TileflowLineJoin as X, type TileflowLineLayout as Y, type TileflowLinePaint as Z, type TileflowLineStackStyle as _, type TileflowRuntimeColorScheme as a, type TileflowTextAnchor as a$, type TileflowManifestLoadOptions as a0, type TileflowMapMode as a1, type TileflowMapModeOptions as a2, type TileflowMarkerSymbolStyle as a3, type TileflowMountainBikeScale as a4, type TileflowNumberInsetsStyleValue as a5, type TileflowNumberStyleValue as a6, type TileflowPlaceLabelClass as a7, type TileflowPoiCategory as a8, type TileflowPoiCategoryStyle as a9, type TileflowRoadWeight as aA, type TileflowRuntimeCenterLike as aB, type TileflowRuntimeManifestMap as aC, type TileflowRuntimeSource as aD, type TileflowRuntimeSourceValidation as aE, type TileflowRuntimeStyle as aF, type TileflowRuntimeStyleOptions as aG, type TileflowRuntimeViewOptions as aH, type TileflowSessionController as aI, type TileflowSessionGrantResponse as aJ, type TileflowStringStyleValue as aK, type TileflowStructuralStyleValue as aL, type TileflowStyleFontFace as aM, type TileflowStyleValue as aN, type TileflowSymbolOverlap as aO, type TileflowSymbolPlacement as aP, type TileflowSymbolPlacementStyle as aQ, type TileflowSymbolZOrder as aR, type TileflowTerrain as aS, type TileflowTerrainConfig as aT, type TileflowTerrainContourLabelStyle as aU, type TileflowTerrainContourLineStyle as aV, type TileflowTerrainContoursConfig as aW, type TileflowTerrainEncoding as aX, type TileflowTerrainHillshadeStyle as aY, type TileflowTerrainLayerRange as aZ, type TileflowTerrainMode as a_, type TileflowPoiColorMode as aa, type TileflowPoiDensity as ab, type TileflowPriorityOrder as ac, type TileflowProjection as ad, type TileflowResolvedRuntimeTheme as ae, type TileflowRoadAreaStyle as af, type TileflowRoadClass as ag, type TileflowRoadClassStyle as ah, type TileflowRoadCrossingStyle as ai, type TileflowRoadDetail as aj, type TileflowRoadExtras as ak, type TileflowRoadHierarchy as al, type TileflowRoadLabelDetail as am, type TileflowRoadLayerStyle as an, type TileflowRoadModifier as ao, type TileflowRoadOutline as ap, type TileflowRoadRestriction as aq, type TileflowRoadRoundaboutStyle as ar, type TileflowRoadServiceType as as, type TileflowRoadShieldDetail as at, type TileflowRoadShieldStyles as au, type TileflowRoadSidewalkStyle as av, type TileflowRoadStructure as aw, type TileflowRoadTreatmentLayerStyle as ax, type TileflowRoadTreatmentLineStyle as ay, type TileflowRoadTreatmentStyle as az, type TileflowRuntimeManifestMapEntry as b, type TileflowTextBackground as b0, type TileflowTextJustify as b1, type TileflowTextLayout as b2, type TileflowTextPaint as b3, type TileflowTextStyle as b4, type TileflowThemeBlendSelection as b5, type TileflowThemeColorAlpha as b6, type TileflowThemeColorMix as b7, type TileflowThemeColorValue as b8, type TileflowThemeFontValue as b9, normalizeTileflowUrl as bA, resolveTileflowAnalyticsRequestUrl as bB, resolveTileflowManifestMap as bC, resolveTileflowMapMode as bD, resolveTileflowRuntimeStyle as bE, resolveTileflowRuntimeTheme as bF, resolveTileflowRuntimeThemeBlend as bG, resolveTileflowRuntimeView as bH, resolveTileflowStaticImageUrl as bI, shouldLoadTileflowManifest as bJ, startTileflowSession as bK, tileflowPoiCategories as bL, tileflowStyleFontFaceLimits as bM, tileflowStyleFontFacesMetadataKey as bN, tileflowThemeBlendLimits as bO, tileflowThemeTokenCategories as bP, token as bQ, validateTileflowRuntimeSource as bR, validateTileflowThemeBlendSelection as bS, validateTileflowThemeSelection as bT, zoom as bU, type TileflowTypographyStyle as bV, type ResolvedTileflowTypography as bW, normalizeTileflowSurfaceId as bX, type TileflowThemeImageValue as ba, type TileflowThemeNumberValue as bb, type TileflowThemeSelection as bc, type TileflowThemeTokenCategory as bd, type TileflowThemeValue as be, type TileflowViewConfig as bf, type TileflowWaterLabelClass as bg, type TileflowZoomInterpolation as bh, type TileflowZoomValue as bi, type ValidationResult as bj, assertValidTileflowRuntimeSource as bk, clearTileflowManifestCache as bl, color as bm, createTileflowSessionController as bn, createTileflowSessionId as bo, defaultTileflowManifestUrl as bp, defaultTileflowRuntimeView as bq, fixed as br, getTileflowAnalyticsApiUrl as bs, getTileflowStyleFontFaces as bt, inferTileflowAnalyticsFromStyleUrl as bu, loadTileflowManifest as bv, mergeTileflowAnalytics as bw, nearestTileflowBlendTheme as bx, normalizeTileflowRuntimeCenter as by, normalizeTileflowStaticImageSize as bz, type TileflowRuntimeManifestTheme as c, type TileflowRuntimeSystemThemes as d, tileflowRuntimeManifestVersion as e, type TileflowExpression as f, type TileflowFixedValue as g, type TileflowThemeTokenReference as h, type TileflowThemeColorOperation as i, type TileflowBackgroundStyle as j, type TileflowCircleStyle as k, type TileflowExtrusionStyle as l, type TileflowFillStyle as m, type TileflowLineStyle as n, type TileflowSymbolStyle as o, type TileflowRoadsModuleOptions as p, type TileflowRoadsModuleConfig as q, type TileflowLabelsModuleOptions as r, type TileflowLabelsModuleConfig as s, tileflowRuntimeManifestLimits as t, type TileflowPoiModuleOptions as u, type TileflowPoiModuleConfig as v, type MapLibreSprite as w, type TileflowAerodromeCodeDetail as x, type TileflowAlignment as y, type TileflowAnalytics as z };
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
- import { T as TileflowRuntimeManifest } from './manifest-types-CTT2eLbp.js';
3
- export { a as TileflowRuntimeColorScheme, b as TileflowRuntimeManifestMapEntry, c as TileflowRuntimeManifestTheme, d as TileflowRuntimeSystemThemes, t as tileflowRuntimeManifestLimits, e as tileflowRuntimeManifestVersion } from './manifest-types-CTT2eLbp.js';
2
+ import { T as TileflowRuntimeManifest } from './manifest-types-E7m23eXL.js';
3
+ export { a as TileflowRuntimeColorScheme, b as TileflowRuntimeManifestMapEntry, c as TileflowRuntimeManifestTheme, d as TileflowRuntimeSystemThemes, t as tileflowRuntimeManifestLimits, e as tileflowRuntimeManifestVersion } from './manifest-types-E7m23eXL.js';
4
4
 
5
5
  declare const tileflowRuntimeManifestSchema: z.ZodType<TileflowRuntimeManifest>;
6
6
  declare function parseTileflowRuntimeManifest(input: unknown): TileflowRuntimeManifest;
@@ -62,7 +62,6 @@ declare const tileflowNativeProfileLimits: Readonly<{
62
62
  }>;
63
63
  /** Fixed output budget for a prepared native-v1 style, never a raw input allowance. */
64
64
  declare const tileflowNativePreparedStyleLimits: Readonly<{
65
- maximumNodes: 540000;
66
65
  maximumStyleBytes: number;
67
66
  maximumDepth: 64;
68
67
  maximumSources: 128;
@@ -70,6 +69,7 @@ declare const tileflowNativePreparedStyleLimits: Readonly<{
70
69
  maximumIssues: 32;
71
70
  maximumFontFaces: 16;
72
71
  maximumFontBytes: number;
72
+ maximumNodes: 540000;
73
73
  }>;
74
74
 
75
75
  declare const tileflowNativeBuildRecordFileName = "native-build.json";
@@ -81,17 +81,24 @@ declare const tileflowNativeStyleTransformationSchema: z.ZodLazy<z.core.$ZodObje
81
81
  inputLayers: z.ZodNumber;
82
82
  outputLayers: z.ZodNumber;
83
83
  projection: z.ZodEnum<{
84
- none: "none";
85
- "mercator-to-implicit": "mercator-to-implicit";
86
84
  "globe-to-mercator": "globe-to-mercator";
85
+ "mercator-to-implicit": "mercator-to-implicit";
86
+ none: "none";
87
87
  }>;
88
88
  layers: z.ZodArray<z.ZodLazy<z.core.$ZodObject<{
89
89
  inputLayer: z.ZodNumber;
90
90
  outputStart: z.ZodNumber;
91
91
  outputCount: z.ZodNumber;
92
92
  properties: z.ZodArray<z.ZodEnum<{
93
- "line-dasharray": "line-dasharray";
94
93
  "line-cap": "line-cap";
94
+ "line-dasharray": "line-dasharray";
95
+ }>>;
96
+ }, z.core.$strict>>>;
97
+ symbolOverlap: z.ZodArray<z.ZodLazy<z.core.$ZodObject<{
98
+ inputLayer: z.ZodNumber;
99
+ properties: z.ZodArray<z.ZodEnum<{
100
+ "icon-overlap": "icon-overlap";
101
+ "text-overlap": "text-overlap";
95
102
  }>>;
96
103
  }, z.core.$strict>>>;
97
104
  }, z.core.$strict>>;
@@ -116,17 +123,24 @@ declare const tileflowNativeBuildRecordSchema: z.ZodLazy<z.core.$ZodObject<{
116
123
  inputLayers: z.ZodNumber;
117
124
  outputLayers: z.ZodNumber;
118
125
  projection: z.ZodEnum<{
119
- none: "none";
120
- "mercator-to-implicit": "mercator-to-implicit";
121
126
  "globe-to-mercator": "globe-to-mercator";
127
+ "mercator-to-implicit": "mercator-to-implicit";
128
+ none: "none";
122
129
  }>;
123
130
  layers: z.ZodArray<z.ZodLazy<z.core.$ZodObject<{
124
131
  inputLayer: z.ZodNumber;
125
132
  outputStart: z.ZodNumber;
126
133
  outputCount: z.ZodNumber;
127
134
  properties: z.ZodArray<z.ZodEnum<{
128
- "line-dasharray": "line-dasharray";
129
135
  "line-cap": "line-cap";
136
+ "line-dasharray": "line-dasharray";
137
+ }>>;
138
+ }, z.core.$strict>>>;
139
+ symbolOverlap: z.ZodArray<z.ZodLazy<z.core.$ZodObject<{
140
+ inputLayer: z.ZodNumber;
141
+ properties: z.ZodArray<z.ZodEnum<{
142
+ "icon-overlap": "icon-overlap";
143
+ "text-overlap": "text-overlap";
130
144
  }>>;
131
145
  }, z.core.$strict>>>;
132
146
  }, z.core.$strict>>>;
@@ -135,21 +149,21 @@ type TileflowNativeBuildRecord = z.infer<typeof tileflowNativeBuildRecordSchema>
135
149
  declare function createTileflowNativeBuildRecord(buildManifestSha256: string, transformations?: readonly TileflowNativeStyleTransformation[]): TileflowNativeBuildRecord;
136
150
 
137
151
  declare const tileflowNativeDiagnosticCodeSchema: z.ZodEnum<{
138
- NATIVE_UNSUPPORTED_STYLE: "NATIVE_UNSUPPORTED_STYLE";
139
- NATIVE_UNSUPPORTED_SOURCE: "NATIVE_UNSUPPORTED_SOURCE";
140
152
  NATIVE_FONT_UNAVAILABLE: "NATIVE_FONT_UNAVAILABLE";
141
153
  NATIVE_MANIFEST_REQUIRED: "NATIVE_MANIFEST_REQUIRED";
142
154
  NATIVE_RENDERER_UNSUPPORTED: "NATIVE_RENDERER_UNSUPPORTED";
155
+ NATIVE_UNSUPPORTED_SOURCE: "NATIVE_UNSUPPORTED_SOURCE";
156
+ NATIVE_UNSUPPORTED_STYLE: "NATIVE_UNSUPPORTED_STYLE";
143
157
  }>;
144
158
  type TileflowNativeDiagnosticCode = z.infer<typeof tileflowNativeDiagnosticCodeSchema>;
145
159
  /** Uses the command diagnostic fields; renderer/profile are bounded additional context. */
146
160
  declare const tileflowNativeDiagnosticSchema: z.ZodLazy<z.core.$ZodObject<{
147
161
  code: z.ZodEnum<{
148
- NATIVE_UNSUPPORTED_STYLE: "NATIVE_UNSUPPORTED_STYLE";
149
- NATIVE_UNSUPPORTED_SOURCE: "NATIVE_UNSUPPORTED_SOURCE";
150
162
  NATIVE_FONT_UNAVAILABLE: "NATIVE_FONT_UNAVAILABLE";
151
163
  NATIVE_MANIFEST_REQUIRED: "NATIVE_MANIFEST_REQUIRED";
152
164
  NATIVE_RENDERER_UNSUPPORTED: "NATIVE_RENDERER_UNSUPPORTED";
165
+ NATIVE_UNSUPPORTED_SOURCE: "NATIVE_UNSUPPORTED_SOURCE";
166
+ NATIVE_UNSUPPORTED_STYLE: "NATIVE_UNSUPPORTED_STYLE";
153
167
  }>;
154
168
  phase: z.ZodLiteral<"native-compatibility">;
155
169
  severity: z.ZodLiteral<"error">;
@@ -8809,6 +8809,13 @@ var layerTransformationSchema = strictNativeObject({
8809
8809
  "Expected unique, ordered properties"
8810
8810
  )
8811
8811
  });
8812
+ var symbolOverlapTransformationSchema = strictNativeObject({
8813
+ inputLayer: layerCountSchema,
8814
+ properties: z4.array(z4.enum(["icon-overlap", "text-overlap"])).min(1).max(2).refine(
8815
+ (properties2) => properties2.length === 1 || properties2[0] === "icon-overlap" && properties2[1] === "text-overlap",
8816
+ "Expected unique, ordered properties"
8817
+ )
8818
+ });
8812
8819
  var tileflowNativeStyleTransformationSchema = strictNativeObject({
8813
8820
  map: tileflowPortableIdSchema,
8814
8821
  theme: tileflowThemeNameSchema,
@@ -8817,7 +8824,8 @@ var tileflowNativeStyleTransformationSchema = strictNativeObject({
8817
8824
  inputLayers: layerCountSchema,
8818
8825
  outputLayers: layerCountSchema,
8819
8826
  projection: z4.enum(["none", "mercator-to-implicit", "globe-to-mercator"]),
8820
- layers: z4.array(layerTransformationSchema).max(tileflowNativeProfileLimits.maximumLayers)
8827
+ layers: z4.array(layerTransformationSchema).max(tileflowNativeProfileLimits.maximumLayers),
8828
+ symbolOverlap: z4.array(symbolOverlapTransformationSchema).max(tileflowNativeProfileLimits.maximumLayers)
8821
8829
  }).superRefine((style, context) => {
8822
8830
  let previous = -1;
8823
8831
  let added = 0;
@@ -8839,6 +8847,18 @@ var tileflowNativeStyleTransformationSchema = strictNativeObject({
8839
8847
  message: "Layer counts do not match transformation spans"
8840
8848
  });
8841
8849
  }
8850
+ const partitioned = new Set(style.layers.map(({ inputLayer }) => inputLayer));
8851
+ previous = -1;
8852
+ for (const [index, layer] of style.symbolOverlap.entries()) {
8853
+ if (layer.inputLayer <= previous || layer.inputLayer >= style.inputLayers || partitioned.has(layer.inputLayer)) {
8854
+ context.addIssue({
8855
+ code: "custom",
8856
+ path: ["symbolOverlap", index],
8857
+ message: "Invalid symbol overlap layer"
8858
+ });
8859
+ }
8860
+ previous = layer.inputLayer;
8861
+ }
8842
8862
  });
8843
8863
  var tileflowNativeBuildRecordSchema = strictNativeObject({
8844
8864
  schemaVersion: z4.literal(2),
package/dist/runtime.d.ts CHANGED
@@ -1 +1 @@
1
- export { z as TileflowAnalytics, $ as TileflowManifestFetchOptions, a0 as TileflowManifestLoadOptions, a1 as TileflowMapMode, a2 as TileflowMapModeOptions, ae as TileflowResolvedRuntimeTheme, aB as TileflowRuntimeCenterLike, a as TileflowRuntimeColorScheme, T as TileflowRuntimeManifest, aC as TileflowRuntimeManifestMap, b as TileflowRuntimeManifestMapEntry, c as TileflowRuntimeManifestTheme, aD as TileflowRuntimeSource, aE as TileflowRuntimeSourceValidation, aF as TileflowRuntimeStyle, aG as TileflowRuntimeStyleOptions, d as TileflowRuntimeSystemThemes, aH as TileflowRuntimeViewOptions, aI as TileflowSessionController, aJ as TileflowSessionGrantResponse, aM as TileflowStyleFontFace, b4 as TileflowThemeBlendSelection, bb as TileflowThemeSelection, bj as assertValidTileflowRuntimeSource, bk as clearTileflowManifestCache, bm as createTileflowSessionController, bn as createTileflowSessionId, bo as defaultTileflowManifestUrl, bp as defaultTileflowRuntimeView, br as getTileflowAnalyticsApiUrl, bs as getTileflowStyleFontFaces, bt as inferTileflowAnalyticsFromStyleUrl, bu as loadTileflowManifest, bv as mergeTileflowAnalytics, bw as nearestTileflowBlendTheme, bx as normalizeTileflowRuntimeCenter, by as normalizeTileflowStaticImageSize, bW as normalizeTileflowSurfaceId, bz as normalizeTileflowUrl, bA as resolveTileflowAnalyticsRequestUrl, bB as resolveTileflowManifestMap, bC as resolveTileflowMapMode, bD as resolveTileflowRuntimeStyle, bE as resolveTileflowRuntimeTheme, bF as resolveTileflowRuntimeThemeBlend, bG as resolveTileflowRuntimeView, bH as resolveTileflowStaticImageUrl, bI as shouldLoadTileflowManifest, bJ as startTileflowSession, bL as tileflowStyleFontFaceLimits, bM as tileflowStyleFontFacesMetadataKey, bN as tileflowThemeBlendLimits, bQ as validateTileflowRuntimeSource, bR as validateTileflowThemeBlendSelection, bS as validateTileflowThemeSelection } from './manifest-types-CTT2eLbp.js';
1
+ export { z as TileflowAnalytics, $ as TileflowManifestFetchOptions, a0 as TileflowManifestLoadOptions, a1 as TileflowMapMode, a2 as TileflowMapModeOptions, ae as TileflowResolvedRuntimeTheme, aB as TileflowRuntimeCenterLike, a as TileflowRuntimeColorScheme, T as TileflowRuntimeManifest, aC as TileflowRuntimeManifestMap, b as TileflowRuntimeManifestMapEntry, c as TileflowRuntimeManifestTheme, aD as TileflowRuntimeSource, aE as TileflowRuntimeSourceValidation, aF as TileflowRuntimeStyle, aG as TileflowRuntimeStyleOptions, d as TileflowRuntimeSystemThemes, aH as TileflowRuntimeViewOptions, aI as TileflowSessionController, aJ as TileflowSessionGrantResponse, aM as TileflowStyleFontFace, b5 as TileflowThemeBlendSelection, bc as TileflowThemeSelection, bk as assertValidTileflowRuntimeSource, bl as clearTileflowManifestCache, bn as createTileflowSessionController, bo as createTileflowSessionId, bp as defaultTileflowManifestUrl, bq as defaultTileflowRuntimeView, bs as getTileflowAnalyticsApiUrl, bt as getTileflowStyleFontFaces, bu as inferTileflowAnalyticsFromStyleUrl, bv as loadTileflowManifest, bw as mergeTileflowAnalytics, bx as nearestTileflowBlendTheme, by as normalizeTileflowRuntimeCenter, bz as normalizeTileflowStaticImageSize, bX as normalizeTileflowSurfaceId, bA as normalizeTileflowUrl, bB as resolveTileflowAnalyticsRequestUrl, bC as resolveTileflowManifestMap, bD as resolveTileflowMapMode, bE as resolveTileflowRuntimeStyle, bF as resolveTileflowRuntimeTheme, bG as resolveTileflowRuntimeThemeBlend, bH as resolveTileflowRuntimeView, bI as resolveTileflowStaticImageUrl, bJ as shouldLoadTileflowManifest, bK as startTileflowSession, bM as tileflowStyleFontFaceLimits, bN as tileflowStyleFontFacesMetadataKey, bO as tileflowThemeBlendLimits, bR as validateTileflowRuntimeSource, bS as validateTileflowThemeBlendSelection, bT as validateTileflowThemeSelection } from './manifest-types-E7m23eXL.js';
@@ -220,10 +220,11 @@ The `vegetation` module binds individual-tree points from the optional OpenMapTi
220
220
  extension. Its default `mode: '3d'` emits a portable circle fallback plus metadata for runtimes
221
221
  that can upgrade the points to instanced 3D trees. `mode: 'flat'` keeps the MapLibre circles, and
222
222
  `flat` exposes the complete `CircleStyle` fallback. `threeDimensional` controls bark color,
223
- broadleaf and conifer palettes, and independent height and crown scales. The legacy `minZoom`
224
- shortcut remains available; `flat.minZoom` takes precedence when both are present. The binding
225
- includes height, crown diameter, genus, leaf type, and species fields so compatible runtimes can
226
- preserve source measurements and botanical form without hard-coding raw property names. The
223
+ broadleaf and conifer palettes, and independent height and crown scales. `flat.minZoom` sets the
224
+ first zoom with trees. The binding includes height, crown diameter, genus, leaf type, and species
225
+ fields so compatible runtimes can preserve source measurements and botanical form without
226
+ hard-coding raw property names. The module does not draw the unrelated, decorative `canopy` layer;
227
+ render passes can, as in the [canopy grove recipe](data-is-separate-from-design.md). The
227
228
  pitched-scene stack follows physical height: pedestrian and transport surfaces, transport markings,
228
229
  buildings, then vegetation, so street paint never floats over 3D geometry. Text draws last: road
229
230
  names, route shields, junction numbers, and place, water, aerodrome, and POI annotations stay above