@tileflow/core 0.1.0-alpha.41 → 0.1.0-alpha.43

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.
Files changed (51) hide show
  1. package/README.md +51 -69
  2. package/THIRD_PARTY_NOTICES.md +1 -1
  3. package/dist/{3d-CzLTD0RK.d.ts → 3d-CW5Ls0An.d.ts} +32 -2
  4. package/dist/3d.d.ts +1 -1
  5. package/dist/3d.js +337 -34
  6. package/dist/browser.d.ts +119 -7
  7. package/dist/browser.js +754 -61
  8. package/dist/build.d.ts +8 -4
  9. package/dist/build.js +284 -4
  10. package/dist/config-reference.json +4005 -2284
  11. package/dist/{icon-composition-HUh_Lj8Z.d.ts → icon-composition-Bbw9umUA.d.ts} +46 -3
  12. package/dist/index.d.ts +22 -5
  13. package/dist/index.js +254 -6
  14. package/dist/{manifest-types-DnhSJjCM.d.ts → manifest-types-CwjHd4qc.d.ts} +10 -0
  15. package/dist/manifest.d.ts +2 -2
  16. package/dist/native-profile.d.ts +4 -0
  17. package/dist/native-profile.js +2 -0
  18. package/dist/native.d.ts +87 -1
  19. package/dist/native.js +980 -460
  20. package/dist/runtime.d.ts +1 -1
  21. package/dist/worker/camera-tile-worker.global.js +2 -2
  22. package/package.json +4 -5
  23. package/docs/application-tile-reading.md +0 -86
  24. package/docs/authoring-model.md +0 -269
  25. package/docs/boundary-areas-and-choropleths.md +0 -217
  26. package/docs/buildings-3d.md +0 -608
  27. package/docs/camera-moves-and-tile-cache.md +0 -112
  28. package/docs/capture-scenes.md +0 -40
  29. package/docs/capture-shots.md +0 -173
  30. package/docs/cartographic-defaults.md +0 -210
  31. package/docs/compiled-style-performance.md +0 -286
  32. package/docs/data-is-separate-from-design.md +0 -610
  33. package/docs/depth-markers.md +0 -65
  34. package/docs/dynamic-style-images.md +0 -100
  35. package/docs/globe-atmosphere.md +0 -113
  36. package/docs/hosted-session-authorization.md +0 -106
  37. package/docs/map-and-terrain-examples.md +0 -156
  38. package/docs/map-emphasis.md +0 -89
  39. package/docs/native-artifact-profile.md +0 -152
  40. package/docs/native-resource-urls.md +0 -369
  41. package/docs/nautical-marks.md +0 -308
  42. package/docs/public-api-and-browser-subpath.md +0 -101
  43. package/docs/route-drawing.md +0 -191
  44. package/docs/shared-visual-primitives.md +0 -101
  45. package/docs/street-lights.md +0 -127
  46. package/docs/street-sky.md +0 -156
  47. package/docs/style-states.md +0 -73
  48. package/docs/sun-and-light.md +0 -167
  49. package/docs/theme-transitions-and-blends.md +0 -317
  50. package/docs/themes-and-module-styles.md +0 -156
  51. package/docs/trees-3d.md +0 -295
package/dist/index.js CHANGED
@@ -882,6 +882,9 @@ var init_visual_semantics = __esm({
882
882
  "blur",
883
883
  "brightnessScale",
884
884
  "crownScale",
885
+ "crownAnchor",
886
+ "sizeAnchor",
887
+ "sizeCompression",
885
888
  "contrast",
886
889
  "dash",
887
890
  "exaggeration",
@@ -889,6 +892,7 @@ var init_visual_semantics = __esm({
889
892
  "emissiveVariation",
890
893
  "emissiveHeight",
891
894
  "colorMix",
895
+ "colorScale",
892
896
  "metallic",
893
897
  "roughness",
894
898
  "horizonBlend",
@@ -897,6 +901,8 @@ var init_visual_semantics = __esm({
897
901
  "lightness",
898
902
  "fadeDuration",
899
903
  "gapWidth",
904
+ "groundOcclusion",
905
+ "groundOcclusionRadius",
900
906
  "haloBlur",
901
907
  "haloWidth",
902
908
  "height",
@@ -6007,6 +6013,28 @@ function compileLand(request, context) {
6007
6013
  target: "land.background"
6008
6014
  });
6009
6015
  }
6016
+ if (config.globalLandcoverUnderlay && schema.layers.globalLandcover && config.globalLandcover?.visible !== false) {
6017
+ const underlay = config.globalLandcoverUnderlay;
6018
+ contributions.push({
6019
+ kind: "layer",
6020
+ owner: "land",
6021
+ slot: "land",
6022
+ localOrder: 9,
6023
+ target: "land.globalLandcoverUnderlay",
6024
+ layer: {
6025
+ id: "tileflow-global-landcover-underlay",
6026
+ type: "raster",
6027
+ source: "tileflow-landcover-underlay",
6028
+ minzoom: underlay.minZoom ?? 0,
6029
+ maxzoom: underlay.maxZoom ?? 11,
6030
+ paint: {
6031
+ "raster-opacity": toMapLibreStyleValue(underlay.opacity ?? 1),
6032
+ "raster-fade-duration": 0,
6033
+ "raster-resampling": "linear"
6034
+ }
6035
+ }
6036
+ });
6037
+ }
6010
6038
  if (schema.layers.globalLandcover && config.globalLandcover?.visible !== false) {
6011
6039
  contributions.push({
6012
6040
  kind: "layer",
@@ -9013,6 +9041,7 @@ function resolvePoi(request) {
9013
9041
  density: request?.density ?? 2,
9014
9042
  detailZoom: request?.detailZoom ?? 17,
9015
9043
  densityByCategory: { ...request?.densityByCategory },
9044
+ maxRankByType: { ...request?.maxRankByType },
9016
9045
  icons: request?.icons ?? true,
9017
9046
  labels: request?.labels ?? true,
9018
9047
  minZoom: request?.minZoom ?? 0,
@@ -9500,6 +9529,9 @@ function compileCategory(category, request, semantics, context, language, select
9500
9529
  }
9501
9530
  function createPoiSelection(semantics, context, language) {
9502
9531
  const { fields: fields2 } = context.data.schema;
9532
+ const typeRankCaps = Object.entries(semantics.maxRankByType).sort(
9533
+ ([a], [b]) => a.localeCompare(b)
9534
+ );
9503
9535
  const shown = /* @__PURE__ */ new Map();
9504
9536
  const iconOnlyTypes = [...new Set(semantics.placement.iconOnlyTypes)];
9505
9537
  const iconOnly = () => iconOnlyTypes.length ? ["match", ["get", fields2.poiType], iconOnlyTypes, true, false] : ["literal", false];
@@ -9535,6 +9567,14 @@ function createPoiSelection(semantics, context, language) {
9535
9567
  [">=", sizeRank, 0],
9536
9568
  ["<=", sizeRank, 16]
9537
9569
  ];
9570
+ if (typeRankCaps.length) {
9571
+ result.push([
9572
+ "match",
9573
+ ["get", fields2.poiType],
9574
+ ...typeRankCaps.flatMap(([type, rank]) => [type, ["<=", filterRank, rank]]),
9575
+ true
9576
+ ]);
9577
+ }
9538
9578
  if (!semantics.icons || !semantics.labels) return result;
9539
9579
  const textless = categories.filter((category) => !shown.get(category)?.text);
9540
9580
  const iconless = categories.filter((category) => !shown.get(category)?.icon);
@@ -11814,6 +11854,9 @@ function readTileflowVegetation3D(metadata) {
11814
11854
  {
11815
11855
  heightScale: scale(own.heightScale),
11816
11856
  crownScale: scale(own.crownScale),
11857
+ ...typeof own.sizeAnchor === "number" && Number.isFinite(own.sizeAnchor) ? { sizeAnchor: clamp(own.sizeAnchor, [1, 45]) } : {},
11858
+ ...typeof own.crownAnchor === "number" && Number.isFinite(own.crownAnchor) ? { crownAnchor: clamp(own.crownAnchor, [1, 25]) } : {},
11859
+ ...typeof own.sizeCompression === "number" && Number.isFinite(own.sizeCompression) ? { sizeCompression: clamp(own.sizeCompression, [0, 1]) } : {},
11817
11860
  ...drawn.length > 0 ? { models: drawn } : {}
11818
11861
  }
11819
11862
  ]
@@ -11985,6 +12028,14 @@ function tileflowVegetationDescription(request, context) {
11985
12028
  {
11986
12029
  heightScale: number(own?.heightScale),
11987
12030
  crownScale: number(own?.crownScale),
12031
+ ...own?.sizeAnchor === void 0 ? {} : { sizeAnchor: number(own.sizeAnchor) },
12032
+ ...own?.crownAnchor === void 0 ? {} : { crownAnchor: number(own.crownAnchor) },
12033
+ ...own?.sizeCompression === void 0 ? {} : {
12034
+ sizeCompression: Math.max(
12035
+ 0,
12036
+ Math.min(1, Number(toMapLibreStyleValue(own.sizeCompression)) || 0)
12037
+ )
12038
+ },
11988
12039
  ...own?.models?.length ? { models: [...own.models] } : {}
11989
12040
  }
11990
12041
  ])
@@ -13734,8 +13785,12 @@ function readModelRoleLighting(value) {
13734
13785
  ...typeof entry.emissiveColor === "string" ? { emissiveColor: entry.emissiveColor } : {},
13735
13786
  ...typeof entry.color === "string" ? { color: entry.color } : {},
13736
13787
  ...entry.colorMix === void 0 ? {} : { colorMix: bounded(entry.colorMix, 0, 1, 1) },
13788
+ ...entry.colorScale === void 0 ? {} : { colorScale: bounded(entry.colorScale, 0, 1, 1) },
13737
13789
  ...entry.metallic === void 0 ? {} : { metallic: bounded(entry.metallic, 0, 1, 0) },
13738
13790
  ...entry.roughness === void 0 ? {} : { roughness: bounded(entry.roughness, 0, 1, 1) },
13791
+ ...entry.shading === "map" || entry.shading === "physical" ? { shading: entry.shading } : {},
13792
+ ...entry.ambientOcclusion === void 0 ? {} : { ambientOcclusion: bounded(entry.ambientOcclusion, 0, 1, 1) },
13793
+ ...entry.partColorMix === void 0 ? {} : { partColorMix: bounded(entry.partColorMix, 0, 1, 1) },
13739
13794
  ...readRoleColorVariation(entry.colorVariation),
13740
13795
  emissiveHeight: Array.isArray(gradient) && gradient.length === 5 && gradient.every(
13741
13796
  (v, i) => typeof v === "number" && Number.isFinite(v) && v <= 1 && v >= (i === 4 ? -1 : 0)
@@ -13819,6 +13874,8 @@ var tileflowDefaultBuildings3DDesign = Object.freeze({
13819
13874
  windows: false,
13820
13875
  shadows: true,
13821
13876
  occlusion: true,
13877
+ groundOcclusion: 0.16,
13878
+ groundOcclusionRadius: 3,
13822
13879
  modelOcclusion: 0.75
13823
13880
  });
13824
13881
  function tileflowBuildingsMetadata(design) {
@@ -13845,7 +13902,7 @@ function readTileflowBuildings3D(metadata) {
13845
13902
  },
13846
13903
  color: color3,
13847
13904
  edges: within(value.edges, 1, 0),
13848
- edgeRadius: within(value.edgeRadius, 1, defaults4.edgeRadius),
13905
+ edgeRadius: within(value.edgeRadius, 1.5, defaults4.edgeRadius),
13849
13906
  lighting: value.lighting === "style" ? "style" : defaults4.lighting,
13850
13907
  colorVariation: within(value.colorVariation, 1, 0),
13851
13908
  verticalGradient: value.verticalGradient !== false,
@@ -13858,7 +13915,12 @@ function readTileflowBuildings3D(metadata) {
13858
13915
  ...readTileflowBuildingsEntrance(value.entrance),
13859
13916
  shadows: typeof value.shadows === "boolean" ? value.shadows : defaults4.shadows,
13860
13917
  occlusion: typeof value.occlusion === "boolean" ? value.occlusion : defaults4.occlusion,
13918
+ groundOcclusion: within(value.groundOcclusion, 1, defaults4.groundOcclusion),
13919
+ groundOcclusionRadius: within(value.groundOcclusionRadius, 20, defaults4.groundOcclusionRadius),
13861
13920
  modelOcclusion: within(value.modelOcclusion, 1, defaults4.modelOcclusion),
13921
+ ...Array.isArray(value.flatLayers) && value.flatLayers.length <= 128 && value.flatLayers.every(
13922
+ (entry) => isRecord7(entry) && typeof entry.id === "string" && typeof entry.visible === "boolean"
13923
+ ) ? { flatLayers: value.flatLayers } : {},
13862
13924
  ...modelsOf(value.models),
13863
13925
  ...modelColorsOf(value.modelColors),
13864
13926
  ...landmarksOf(value.landmarks)
@@ -13916,6 +13978,9 @@ function isRecord7(value) {
13916
13978
  return typeof value === "object" && value !== null && !Array.isArray(value);
13917
13979
  }
13918
13980
 
13981
+ // src/camera.ts
13982
+ var tileflowCameraMetadataKey = "tileflow:camera";
13983
+
13919
13984
  // src/data/requirements.ts
13920
13985
  import { convertFilter } from "@maplibre/maplibre-gl-style-spec";
13921
13986
  function inferTileflowDataRequirements(style, options = {}) {
@@ -14082,6 +14147,60 @@ function compareCodeUnits4(left, right) {
14082
14147
  return left < right ? -1 : left > right ? 1 : 0;
14083
14148
  }
14084
14149
 
14150
+ // src/modules/roads/path-ground.ts
14151
+ var pathTarget = /^roads\.classes\.(pathway|footway|pedestrian|steps|cycleway)\.(surface|bridge|tunnel)\.(fill|casing|shadow)$/;
14152
+ function compilePathGroundFamilies(input, options) {
14153
+ if (!options || Number(options.opacity ?? 1) === 0) return { families: input, active: false };
14154
+ const scale = Number(options.widthScale ?? 1);
14155
+ const scaled = (value) => {
14156
+ if (Array.isArray(value) && value[0] === "interpolate" && Array.isArray(value[2]) && value[2][0] === "zoom")
14157
+ return value.map((v, i) => i >= 4 && i % 2 === 0 ? ["*", v, scale] : v);
14158
+ return ["*", value ?? 1, scale];
14159
+ };
14160
+ let active = false;
14161
+ let families = input.flatMap((family) => {
14162
+ const match3 = pathTarget.exec(family.target);
14163
+ if (!match3 || match3[2] !== "surface") return [family];
14164
+ const [, kind, , phase] = match3;
14165
+ const appearance = { ...family.style.appearance };
14166
+ if (phase === "casing") appearance["line-opacity"] = 0;
14167
+ else {
14168
+ appearance["line-color"] = options.groundColor;
14169
+ appearance["line-width"] = scaled(appearance["line-width"]);
14170
+ appearance["line-opacity"] = kind === "cycleway" && phase === "fill" ? 0 : Number(options.opacity ?? 1);
14171
+ }
14172
+ const base = { ...family, style: { ...family.style, appearance } };
14173
+ if (phase === "casing" || kind === "cycleway" && phase === "fill") return [base];
14174
+ active = true;
14175
+ const overlay = {
14176
+ ...base,
14177
+ family: void 0,
14178
+ key: base.key + ".onGreen",
14179
+ target: base.target + ".onGreen",
14180
+ feature: { ...base.feature, dataSource: "tileflow-path-ground" },
14181
+ style: { ...base.style, appearance: { ...appearance, "line-color": options.greenColor } },
14182
+ origins: base.origins.map((origin) => ({ ...origin, target: base.target + ".onGreen" }))
14183
+ };
14184
+ return [base, overlay];
14185
+ });
14186
+ for (const structure of ["surface", "bridge", "tunnel"]) {
14187
+ const move = (family) => {
14188
+ const match3 = pathTarget.exec(family.target.replace(/\.onGreen$/, ""));
14189
+ return match3?.[2] === structure && (match3[3] === "fill" || structure === "surface" && match3[3] === "shadow");
14190
+ };
14191
+ const paths = families.filter(move);
14192
+ families = families.filter((f) => !move(f));
14193
+ const anchor = families.findIndex(
14194
+ (f) => new RegExp(
14195
+ `^roads\\.classes\\.(track|service|minor|tertiary|secondary|primary|trunk|motorway)\\.${structure}\\.casing$`
14196
+ ).test(f.target)
14197
+ );
14198
+ if (anchor >= 0) families.splice(anchor, 0, ...paths);
14199
+ else families.push(...paths);
14200
+ }
14201
+ return { families, active };
14202
+ }
14203
+
14085
14204
  // src/notices.ts
14086
14205
  var tileflowNoticesMetadataKey = "tileflow:notices";
14087
14206
  var tileflowNoticeLimits = Object.freeze({
@@ -14120,6 +14239,26 @@ function isRecord8(value) {
14120
14239
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
14121
14240
  }
14122
14241
 
14242
+ // src/path-ground-protocol.ts
14243
+ var tileflowPathGroundProtocol = "tileflow-path-ground";
14244
+ var tileflowPathGroundSource = "tileflow-path-ground";
14245
+ function pathGroundSourceConfig(data) {
14246
+ return {
14247
+ ...data.url ? { url: data.url } : { tiles: data.tiles },
14248
+ minzoom: Math.max(12, data.minzoom ?? 0),
14249
+ maxzoom: data.maxzoom ?? 15,
14250
+ road: data.schema.layers.road,
14251
+ landcover: data.schema.layers.landcover,
14252
+ landuse: data.schema.layers.landuse,
14253
+ class: data.schema.fields.class,
14254
+ subclass: data.schema.fields.subclass,
14255
+ brunnel: data.schema.fields.brunnel
14256
+ };
14257
+ }
14258
+ function pathGroundProtocolUrl(source, tile = false) {
14259
+ return `${tileflowPathGroundProtocol}://source/${tile ? "{z}/{x}/{y}.pbf" : "index.json"}?source=${encodeURIComponent(JSON.stringify(source))}`;
14260
+ }
14261
+
14123
14262
  // src/resolved-map-schema.ts
14124
14263
  init_camera_limits();
14125
14264
  import { Color as Color3 } from "@maplibre/maplibre-gl-style-spec";
@@ -14991,10 +15130,18 @@ function physicalLayerIdForSemanticKey(semanticKey) {
14991
15130
  semanticKey
14992
15131
  );
14993
15132
  if (match3) return `tileflow-${match3[1]}-render-${match3[2].replaceAll(".", "-")}`;
15133
+ match3 = /^roads\.classes\.(pathway|footway|pedestrian|steps|cycleway)\.surface\.(shadow|fill)-on-green$/u.exec(
15134
+ semanticKey
15135
+ );
15136
+ if (match3) return `tileflow-road-surface-${match3[1]}-${match3[2]}-on-green`;
14994
15137
  match3 = /^roads\.classes\.([^.]+)\.(tunnel|surface|bridge)\.(shadow|casing|fill|hatch|rampFill)$/u.exec(
14995
15138
  semanticKey
14996
15139
  );
14997
15140
  if (match3) return `tileflow-road-${match3[2]}-${match3[1]}-${match3[3]}`;
15141
+ match3 = /^roads\.classes\.(pathway|footway|pedestrian|steps|cycleway)\.surface\.(shadow|fill)\.onGreen$/u.exec(
15142
+ semanticKey
15143
+ );
15144
+ if (match3) return `tileflow-road-surface-${match3[1]}-${match3[2]}-on-green`;
14998
15145
  match3 = /^roads\.cohorts\.(tunnel|surface|bridge)\.([^.]+)\.(shadow|casing|fill|rampFill)$/u.exec(
14999
15146
  semanticKey
15000
15147
  );
@@ -15082,6 +15229,7 @@ var exactPhysicalLayerIds = Object.freeze({
15082
15229
  "labels.junctions": "tileflow-label-road-junction",
15083
15230
  "land.background": "tileflow-background",
15084
15231
  "land.globalLandcover": "tileflow-global-landcover",
15232
+ "land.globalLandcoverUnderlay": "tileflow-global-landcover-underlay",
15085
15233
  poi: "tileflow-poi",
15086
15234
  "landforms.classes": "tileflow-landforms",
15087
15235
  "roads.crossings": "tileflow-road-crossing",
@@ -17254,6 +17402,19 @@ var landModuleSchema = z7.object({
17254
17402
  }).strict().optional(),
17255
17403
  enabled: z7.boolean().optional(),
17256
17404
  globalLandcover: fillStyleSchema.optional(),
17405
+ globalLandcoverUnderlay: z7.object({
17406
+ url: z7.string().min(1),
17407
+ coordinates: z7.tuple([
17408
+ z7.tuple([z7.number(), z7.number()]),
17409
+ z7.tuple([z7.number(), z7.number()]),
17410
+ z7.tuple([z7.number(), z7.number()]),
17411
+ z7.tuple([z7.number(), z7.number()])
17412
+ ]),
17413
+ attribution: z7.string().min(1),
17414
+ opacity: numberValueSchema.optional(),
17415
+ minZoom: z7.number().min(0).max(24).optional(),
17416
+ maxZoom: z7.number().min(0).max(24).optional()
17417
+ }).strict().optional(),
17257
17418
  landcover: z7.object({
17258
17419
  farmland: areaStyleSchema.optional(),
17259
17420
  flowerbed: areaStyleSchema.optional(),
@@ -17322,8 +17483,12 @@ var modelRoleLightingSchema = z7.object({
17322
17483
  emissiveColor: themeColorValueSchema.optional(),
17323
17484
  color: themeColorValueSchema.optional(),
17324
17485
  colorMix: boundedThemeNumberSchema(0, 1).optional(),
17486
+ colorScale: boundedThemeNumberSchema(0, 1).optional(),
17325
17487
  metallic: boundedThemeNumberSchema(0, 1).optional(),
17326
17488
  roughness: boundedThemeNumberSchema(0, 1).optional(),
17489
+ shading: z7.enum(["physical", "map"]).optional(),
17490
+ ambientOcclusion: boundedThemeNumberSchema(0, 1).optional(),
17491
+ partColorMix: boundedThemeNumberSchema(0, 1).optional(),
17327
17492
  colorVariation: z7.object({
17328
17493
  hue: z7.tuple([boundedThemeNumberSchema(0, 360), boundedThemeNumberSchema(0, 360)]),
17329
17494
  saturation: z7.tuple([boundedThemeNumberSchema(0, 100), boundedThemeNumberSchema(0, 100)]),
@@ -17350,7 +17515,7 @@ var buildingsModuleSchema = z7.object({
17350
17515
  lighting: z7.enum(["style", "sun"]).optional(),
17351
17516
  colorVariation: boundedThemeNumberSchema(0, 1).optional(),
17352
17517
  edges: boundedThemeNumberSchema(0, 1).optional(),
17353
- edgeRadius: z7.number().min(0).max(1).optional(),
17518
+ edgeRadius: z7.number().min(0).max(1.5).optional(),
17354
17519
  edgeColor: themeColorValueSchema.optional(),
17355
17520
  nightLight: boundedThemeNumberSchema(0, 2).optional(),
17356
17521
  floodLight: z7.object({
@@ -17372,7 +17537,10 @@ var buildingsModuleSchema = z7.object({
17372
17537
  logo: modelRoleLightingSchema.optional()
17373
17538
  }).strict().optional(),
17374
17539
  entrance: z7.object({ buildings: entranceBandSchema.optional(), models: entranceBandSchema.optional() }).strict().optional(),
17540
+ flatFootprints: z7.boolean().optional(),
17375
17541
  occlusion: z7.boolean().optional(),
17542
+ groundOcclusion: boundedThemeNumberSchema(0, 1).optional(),
17543
+ groundOcclusionRadius: boundedThemeNumberSchema(0, 20).optional(),
17376
17544
  modelOcclusion: boundedThemeNumberSchema(0, 1).optional(),
17377
17545
  shadows: z7.boolean().optional(),
17378
17546
  windows: z7.boolean().optional(),
@@ -17520,6 +17688,12 @@ var roadsModuleSchema = z7.object({
17520
17688
  "6": roadTreatmentStyleSchema.optional()
17521
17689
  }).strict().optional(),
17522
17690
  oneWayMarkers: z7.boolean().optional(),
17691
+ pathGround: z7.object({
17692
+ greenColor: themeColorValueSchema,
17693
+ groundColor: themeColorValueSchema,
17694
+ opacity: themeNumberValueSchema.optional(),
17695
+ widthScale: themeNumberValueSchema.optional()
17696
+ }).strict().optional(),
17523
17697
  outline: z7.enum(["none", "subtle", "strong"]).optional(),
17524
17698
  rampOrder: z7.enum(["below-roads", "by-class"]).describe(
17525
17699
  "Ramp fills draw below receiving roads by default. Use by-class to keep ramp fills in their road class order."
@@ -17621,6 +17795,17 @@ var poiModuleSchema = z7.object({
17621
17795
  type: z7.literal("poi"),
17622
17796
  detailZoom: z7.number().finite().gt(16).max(24).optional(),
17623
17797
  categories: z7.array(z7.enum(tileflowPoiCategories)).optional(),
17798
+ maxRankByType: z7.record(
17799
+ z7.string().regex(/^[a-z0-9]+(?:_[a-z0-9]+)*$/u, "Expected a World POI type"),
17800
+ z7.union([
17801
+ z7.literal(0),
17802
+ z7.literal(1),
17803
+ z7.literal(2),
17804
+ z7.literal(3),
17805
+ z7.literal(4),
17806
+ z7.literal(5)
17807
+ ])
17808
+ ).describe("Fixed maximum World filter rank per POI type, independent of zoom detail.").optional(),
17624
17809
  color: z7.enum(["uniform", "category"]).optional(),
17625
17810
  density: z7.union([z7.literal(1), z7.literal(2), z7.literal(3), z7.literal(4), z7.literal(5)]).describe(
17626
17811
  "POI density from 1 to 5. Defaults to 2; native collisions determine which eligible names fit."
@@ -17732,6 +17917,9 @@ var modulesSchema = z7.object({
17732
17917
  z7.object({
17733
17918
  crownScale: boundedThemeNumberSchema(0.1, 10).optional(),
17734
17919
  heightScale: boundedThemeNumberSchema(0.1, 10).optional(),
17920
+ sizeAnchor: boundedThemeNumberSchema(1, 45).optional(),
17921
+ crownAnchor: boundedThemeNumberSchema(1, 25).optional(),
17922
+ sizeCompression: boundedThemeNumberSchema(0, 1).optional(),
17735
17923
  models: z7.array(
17736
17924
  z7.string().max(64).regex(
17737
17925
  tileflowTreeModelIdPattern,
@@ -18387,6 +18575,7 @@ var systemThemesSchema = z7.object({ dark: tileflowThemeNameSchema, light: tilef
18387
18575
  var resolvedTileflowMapSchema = z7.object({
18388
18576
  atmosphere: atmosphereSchema.optional(),
18389
18577
  boundaryAreas: boundaryAreasSchema.optional(),
18578
+ camera: z7.object({ adaptivePerspective: z7.boolean().optional() }).strict().optional(),
18390
18579
  data: dataSchema.optional(),
18391
18580
  defaultTheme: tileflowThemeNameSchema,
18392
18581
  fonts: fontDirectoriesSchema.optional(),
@@ -20588,7 +20777,7 @@ function tileflowBuildings3DDesignOf(module, context, layers2, buildingModels, t
20588
20777
  ...own,
20589
20778
  emissiveStrength: number(own.emissiveStrength, 0),
20590
20779
  ...Object.fromEntries(
20591
- ["emissiveVariation", "colorMix", "metallic", "roughness"].filter((key) => own[key] !== void 0).map((key) => [key, number(own[key], 0)])
20780
+ ["emissiveVariation", "colorMix", "colorScale", "metallic", "roughness"].filter((key) => own[key] !== void 0).map((key) => [key, number(own[key], 0)])
20592
20781
  ),
20593
20782
  ...Array.isArray(own.emissiveHeight) ? { emissiveHeight: own.emissiveHeight.map((v) => number(v, 0)) } : {},
20594
20783
  ...isRecord13(own.colorVariation) ? {
@@ -20617,7 +20806,14 @@ function tileflowBuildings3DDesignOf(module, context, layers2, buildingModels, t
20617
20806
  ...readTileflowBuildingsEntrance(style.entrance),
20618
20807
  shadows: typeof style.shadows === "boolean" ? style.shadows : defaults4.shadows,
20619
20808
  occlusion: typeof style.occlusion === "boolean" ? style.occlusion : defaults4.occlusion,
20809
+ groundOcclusion: number(style.groundOcclusion, defaults4.groundOcclusion),
20810
+ groundOcclusionRadius: number(style.groundOcclusionRadius, defaults4.groundOcclusionRadius),
20620
20811
  modelOcclusion: number(style.modelOcclusion, defaults4.modelOcclusion),
20812
+ ...style.flatFootprints === false ? {
20813
+ flatLayers: layers2.filter(
20814
+ (layer) => layer.id.startsWith("tileflow-buildings-") && (layer.type === "fill" || layer.type === "line") && layer.metadata?.["tileflow:3d-toggle"] === void 0
20815
+ ).map((layer) => ({ id: layer.id, visible: layer.layout?.visibility !== "none" }))
20816
+ } : {},
20621
20817
  ...placedModels(style.models, buildingModels),
20622
20818
  ...modelColours(style.modelColors),
20623
20819
  ...landmarksOf2(style.landmarks, tileflowLandmarks)
@@ -20808,6 +21004,7 @@ function compileSemanticStyleInternal(input, options, inspect, onReport) {
20808
21004
  });
20809
21005
  const platformSourceIds = [
20810
21006
  data.sourceId,
21007
+ tileflowPathGroundSource,
20811
21008
  ...terrainSources.map(({ sourceId }) => sourceId),
20812
21009
  ...marineSources.map(({ sourceId }) => sourceId),
20813
21010
  ...boundaryAreas ? [boundaryAreas.sourceId] : []
@@ -20904,9 +21101,13 @@ function compileSemanticStyleInternal(input, options, inspect, onReport) {
20904
21101
  buildingTargetsOfOtherModes(modules.buildings)
20905
21102
  )
20906
21103
  );
21104
+ const pathGround = compilePathGroundFamilies(
21105
+ stackedFamilies,
21106
+ modules.roads?.enabled === false ? void 0 : modules.roads?.pathGround
21107
+ );
20907
21108
  const plannedFamilies = runCompilationPhase(
20908
21109
  "physical-planner",
20909
- () => planTileflowLayerFamilies(stackedFamilies)
21110
+ () => planTileflowLayerFamilies(pathGround.families)
20910
21111
  );
20911
21112
  const loweredDomainIR = runCompilationPhase(
20912
21113
  "lowering",
@@ -21063,7 +21264,10 @@ function compileSemanticStyleInternal(input, options, inspect, onReport) {
21063
21264
  const primarySource = {
21064
21265
  type: "vector",
21065
21266
  ...data.url !== void 0 ? { url: data.url } : { tiles: data.tiles },
21066
- attribution: data.attribution,
21267
+ attribution: [
21268
+ data.attribution,
21269
+ ...modules.land?.globalLandcoverUnderlay ? [modules.land.globalLandcoverUnderlay.attribution] : []
21270
+ ].filter(Boolean).join(" | "),
21067
21271
  ...data.bounds ? { bounds: data.bounds } : {},
21068
21272
  ...data.maxzoom === void 0 ? {} : { maxzoom: data.maxzoom },
21069
21273
  ...data.minzoom === void 0 ? {} : { minzoom: data.minzoom }
@@ -21074,6 +21278,19 @@ function compileSemanticStyleInternal(input, options, inspect, onReport) {
21074
21278
  };
21075
21279
  const sources = {
21076
21280
  [data.sourceId]: primarySource,
21281
+ ...pathGround.active ? {
21282
+ [tileflowPathGroundSource]: {
21283
+ type: "vector",
21284
+ url: pathGroundProtocolUrl(pathGroundSourceConfig(data))
21285
+ }
21286
+ } : {},
21287
+ ...modules.land?.enabled !== false && modules.land?.globalLandcoverUnderlay && data.schema.layers.globalLandcover && modules.land.globalLandcover?.visible !== false ? {
21288
+ "tileflow-landcover-underlay": {
21289
+ type: "image",
21290
+ url: modules.land.globalLandcoverUnderlay.url,
21291
+ coordinates: modules.land.globalLandcoverUnderlay.coordinates
21292
+ }
21293
+ } : {},
21077
21294
  ...marine?.bathymetry?.vector ? { [marine.bathymetry.vector.sourceId]: marine.bathymetry.vector.source } : {},
21078
21295
  ...marine?.bathymetry?.relief ? { [marine.bathymetry.relief.sourceId]: marine.bathymetry.relief.source } : {},
21079
21296
  ...marine?.nautical ? { [marine.nautical.sourceId]: marine.nautical.source } : {},
@@ -21181,6 +21398,12 @@ function compileSemanticStyleInternal(input, options, inspect, onReport) {
21181
21398
  [tileflowOverlayPlacementManifestMetadataKey]: overlayPlacementManifest,
21182
21399
  "tileflow:modules": Object.entries(modules).filter(([, module]) => !isRecord14(module) || module.enabled !== false).map(([name]) => name).sort(),
21183
21400
  ...config.view ? { "tileflow:view": config.view } : {},
21401
+ ...config.camera?.adaptivePerspective !== void 0 ? {
21402
+ [tileflowCameraMetadataKey]: {
21403
+ version: 1,
21404
+ adaptivePerspective: config.camera.adaptivePerspective
21405
+ }
21406
+ } : {},
21184
21407
  ...notices.length > 0 ? { [tileflowNoticesMetadataKey]: notices } : {},
21185
21408
  ...nauticalLights ? { [tileflowNauticalLightsMetadataKey]: nauticalLights } : {}
21186
21409
  }
@@ -21553,6 +21776,7 @@ var TileflowMapResolutionError = class extends Error {
21553
21776
  var tileflowMapMergeStrategies = {
21554
21777
  atmosphere: "atomic",
21555
21778
  boundaryAreas: "atomic",
21779
+ camera: "deep",
21556
21780
  data: "atomic",
21557
21781
  defaultTheme: "atomic",
21558
21782
  extends: "lineage",
@@ -25396,7 +25620,13 @@ function encodeTileflowModels(models, compressor) {
25396
25620
  return bufferViews.length - 1;
25397
25621
  }
25398
25622
  const mode = vertices ? "ATTRIBUTES" : "TRIANGLES";
25399
- const packed = compressor.encodeGltfBuffer(bytes, count, stride, mode);
25623
+ const packed = compressor.encodeGltfBuffer(
25624
+ bytes,
25625
+ count,
25626
+ stride,
25627
+ mode,
25628
+ vertices ? 1 : void 0
25629
+ );
25400
25630
  const byteOffset = addBlob(packed);
25401
25631
  const fallbackOffset = fallbackLength;
25402
25632
  fallbackLength += bytes.byteLength + (4 - bytes.byteLength % 4) % 4;
@@ -25844,6 +26074,24 @@ function quantise(mesh, compressor) {
25844
26074
  order = new Array(unique);
25845
26075
  for (const [index, vertex] of kept.entries())
25846
26076
  if (remap[index] !== 4294967295) order[remap[index]] = vertex;
26077
+ } else if (compressor) {
26078
+ for (const { from, count: length } of mesh.surface.ranges) {
26079
+ const range2 = indices.slice(from, from + length);
26080
+ const [remap, unique] = compressor.reorderMesh(range2, true, false);
26081
+ const global = new Uint32Array(unique);
26082
+ for (const [vertex, local] of remap.entries())
26083
+ if (local !== 4294967295) global[local] = vertex;
26084
+ for (const [at, local] of range2.entries()) indices[from + at] = global[local];
26085
+ }
26086
+ const renumber = new Uint32Array(kept.length).fill(4294967295);
26087
+ order = [];
26088
+ for (const [at, vertex] of indices.entries()) {
26089
+ if (renumber[vertex] === 4294967295) {
26090
+ renumber[vertex] = order.length;
26091
+ order.push(kept[vertex]);
26092
+ }
26093
+ indices[at] = renumber[vertex];
26094
+ }
25847
26095
  }
25848
26096
  const vertices = new Uint8Array(order.length * tileflowModelVertexBytes);
25849
26097
  const attributes = mesh.surface ? new Float32Array(order.length * 8) : void 0;
@@ -492,6 +492,14 @@ type TileflowRoadsModuleConfig = {
492
492
  modifiers?: Partial<Record<TileflowRoadModifier, TileflowRoadTreatmentStyle>>;
493
493
  mountainBike?: Partial<Record<TileflowMountainBikeScale, TileflowRoadTreatmentStyle>>;
494
494
  oneWayMarkers?: boolean;
495
+ /** Surface paths keep a ground-coloured fallback and white/green-ground clipped strokes. */
496
+ pathGround?: {
497
+ greenColor: TileflowThemeColorValue;
498
+ groundColor: TileflowThemeColorValue;
499
+ /** Zero disables derivation in this theme. */
500
+ opacity?: TileflowThemeNumberValue;
501
+ widthScale?: TileflowThemeNumberValue;
502
+ };
495
503
  outline?: TileflowRoadOutline;
496
504
  /** Draw ramp fills below receiving roads by default; `by-class` keeps their class's order. */
497
505
  rampOrder?: 'below-roads' | 'by-class';
@@ -586,6 +594,8 @@ type TileflowPoiModuleConfig = {
586
594
  density?: TileflowPoiDensity;
587
595
  /** Category overrides of density, with the same zoom-dependent detail allowance. */
588
596
  densityByCategory?: Partial<Record<TileflowPoiCategory, TileflowPoiDensity>>;
597
+ /** Fixed maximum World filter rank per POI type (0–5), independent of zoom detail. */
598
+ maxRankByType?: Readonly<Record<string, 0 | 1 | 2 | 3 | 4 | 5>>;
589
599
  /** Zoom for the second extra rank of POI detail. Must exceed 16; defaults to 17. */
590
600
  detailZoom?: number;
591
601
  icons?: boolean;
@@ -1,5 +1,5 @@
1
- import { T as TileflowRuntimeManifest } from './manifest-types-DnhSJjCM.js';
2
- export { a as TileflowRuntimeColorScheme, b as TileflowRuntimeManifestMapEntry, c as TileflowRuntimeManifestTheme, d as TileflowRuntimeSystemThemes, e as TileflowTimeOfDay, f as TileflowTimeOfDayVariants, t as tileflowRuntimeManifestLimits, g as tileflowRuntimeManifestVersion, h as tileflowTimeOfDayManifestVersion } from './manifest-types-DnhSJjCM.js';
1
+ import { T as TileflowRuntimeManifest } from './manifest-types-CwjHd4qc.js';
2
+ export { a as TileflowRuntimeColorScheme, b as TileflowRuntimeManifestMapEntry, c as TileflowRuntimeManifestTheme, d as TileflowRuntimeSystemThemes, e as TileflowTimeOfDay, f as TileflowTimeOfDayVariants, t as tileflowRuntimeManifestLimits, g as tileflowRuntimeManifestVersion, h as tileflowTimeOfDayManifestVersion } from './manifest-types-CwjHd4qc.js';
3
3
  import { z } from 'zod';
4
4
 
5
5
  declare const tileflowRuntimeManifestSchema: z.ZodType<TileflowRuntimeManifest>;
@@ -87,6 +87,8 @@ declare const tileflowNativeStyleTransformationSchema: z.ZodLazy<z.core.$ZodObje
87
87
  }>;
88
88
  /** Present when preparation removed a browser sky, which Native does not draw. */
89
89
  sky: z.ZodOptional<z.ZodLiteral<"removed">>;
90
+ /** Native keeps complete ground paths without the browser-derived green overlay. */
91
+ pathGround: z.ZodOptional<z.ZodLiteral<"ground-fallback">>;
90
92
  layers: z.ZodArray<z.ZodLazy<z.core.$ZodObject<{
91
93
  inputLayer: z.ZodNumber;
92
94
  outputStart: z.ZodNumber;
@@ -131,6 +133,8 @@ declare const tileflowNativeBuildRecordSchema: z.ZodLazy<z.core.$ZodObject<{
131
133
  }>;
132
134
  /** Present when preparation removed a browser sky, which Native does not draw. */
133
135
  sky: z.ZodOptional<z.ZodLiteral<"removed">>;
136
+ /** Native keeps complete ground paths without the browser-derived green overlay. */
137
+ pathGround: z.ZodOptional<z.ZodLiteral<"ground-fallback">>;
134
138
  layers: z.ZodArray<z.ZodLazy<z.core.$ZodObject<{
135
139
  inputLayer: z.ZodNumber;
136
140
  outputStart: z.ZodNumber;
@@ -8827,6 +8827,8 @@ var tileflowNativeStyleTransformationSchema = strictNativeObject({
8827
8827
  projection: z4.enum(["none", "mercator-to-implicit", "globe-to-mercator"]),
8828
8828
  /** Present when preparation removed a browser sky, which Native does not draw. */
8829
8829
  sky: z4.literal("removed").optional(),
8830
+ /** Native keeps complete ground paths without the browser-derived green overlay. */
8831
+ pathGround: z4.literal("ground-fallback").optional(),
8830
8832
  layers: z4.array(layerTransformationSchema).max(tileflowNativeProfileLimits.maximumLayers),
8831
8833
  symbolOverlap: z4.array(symbolOverlapTransformationSchema).max(tileflowNativeProfileLimits.maximumLayers)
8832
8834
  }).superRefine((style, context) => {