@tileflow/core 0.1.0-alpha.27 → 0.1.0-alpha.29

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
@@ -1664,12 +1664,12 @@ var init_model = __esm({
1664
1664
  }
1665
1665
  return result;
1666
1666
  }
1667
- #resolveTypographyStyle(style, path, defaults3) {
1667
+ #resolveTypographyStyle(style, path, defaults4) {
1668
1668
  const resolved = this.resolveTree(style ?? {}, path);
1669
- const font = resolved.font ?? defaults3.font;
1669
+ const font = resolved.font ?? defaults4.font;
1670
1670
  if (typeof font !== "string" || !font) throw themeTypeError(`${path}.font`, "font", font);
1671
1671
  assertFontName(font, `${path}.font`);
1672
- const fallbacks = resolved.fallbacks ?? defaults3.fallbacks;
1672
+ const fallbacks = resolved.fallbacks ?? defaults4.fallbacks;
1673
1673
  if (fallbacks !== void 0 && (!Array.isArray(fallbacks) || fallbacks.some((entry) => typeof entry !== "string" || !entry))) {
1674
1674
  throw themeTypeError(`${path}.fallbacks`, "font array", fallbacks);
1675
1675
  }
@@ -1685,9 +1685,9 @@ var init_model = __esm({
1685
1685
  seen.add(fallback);
1686
1686
  }
1687
1687
  }
1688
- const letterSpacing = resolved.letterSpacing ?? defaults3.letterSpacing;
1688
+ const letterSpacing = resolved.letterSpacing ?? defaults4.letterSpacing;
1689
1689
  if (letterSpacing !== void 0) assertFiniteNumber(letterSpacing, `${path}.letterSpacing`);
1690
- const transform = resolved.transform ?? defaults3.transform;
1690
+ const transform = resolved.transform ?? defaults4.transform;
1691
1691
  if (transform !== void 0 && !["lowercase", "none", "uppercase"].includes(String(transform))) {
1692
1692
  throw themeTypeError(`${path}.transform`, "text transform", transform);
1693
1693
  }
@@ -2319,6 +2319,50 @@ function asRecord(value) {
2319
2319
  // src/cartography/streets.ts
2320
2320
  import { validateStyleMin } from "@maplibre/maplibre-gl-style-spec";
2321
2321
 
2322
+ // src/atmosphere.ts
2323
+ var tileflowAtmosphereMetadataKey = "tileflow:atmosphere";
2324
+
2325
+ // src/atmosphere-compile.ts
2326
+ import { Color } from "@maplibre/maplibre-gl-style-spec";
2327
+ var defaults = {
2328
+ skyColor: "#07152b",
2329
+ horizonColor: "#83b9f4",
2330
+ fogColor: "#bad2eb",
2331
+ spaceColor: "#030916",
2332
+ starIntensity: 0.6,
2333
+ starParallax: 0.4
2334
+ };
2335
+ function resolveTileflowAtmosphere(value) {
2336
+ if (!value) return void 0;
2337
+ const options = { ...defaults, ...value === true ? {} : value };
2338
+ const normalize = (input) => {
2339
+ const color3 = typeof input === "string" ? Color.parse(input) : void 0;
2340
+ if (!color3 || color3.a !== 1)
2341
+ throw new Error("Atmosphere colors must resolve to opaque colors.");
2342
+ return `#${[color3.r, color3.g, color3.b].map(
2343
+ (channel) => Math.round(channel * 255).toString(16).padStart(2, "0")
2344
+ ).join("")}`;
2345
+ };
2346
+ return {
2347
+ ...options,
2348
+ skyColor: normalize(options.skyColor),
2349
+ horizonColor: normalize(options.horizonColor),
2350
+ fogColor: normalize(options.fogColor),
2351
+ spaceColor: normalize(options.spaceColor)
2352
+ };
2353
+ }
2354
+ function compileTileflowSky(options) {
2355
+ return {
2356
+ "sky-color": options.skyColor,
2357
+ "horizon-color": options.horizonColor,
2358
+ "fog-color": options.fogColor,
2359
+ "sky-horizon-blend": 0.12,
2360
+ "horizon-fog-blend": 0.5,
2361
+ "fog-ground-blend": 0.1,
2362
+ "atmosphere-blend": ["interpolate", ["linear"], ["zoom"], 0, 0.55, 3, 0.45, 5, 0.2, 7, 0]
2363
+ };
2364
+ }
2365
+
2322
2366
  // src/data/world-generation.ts
2323
2367
  var tileflowWorldGeneration = "v1";
2324
2368
  var tileflowWorldTileJsonUrl = "https://api.tileflow.dev/tiles/world/tiles.json";
@@ -2434,7 +2478,7 @@ var canonicalFields = {
2434
2478
  surface: "surface",
2435
2479
  toll: "toll"
2436
2480
  };
2437
- var defaultAttribution = "\xA9 OpenFreeMap, \xA9 OpenMapTiles, \xA9 OpenStreetMap contributors";
2481
+ var worldAttribution = '<a href="https://tileflow.dev/copyright">\xA9 Tileflow</a> <a href="https://www.openmaptiles.org/">\xA9 OpenMapTiles</a> <a href="https://www.openstreetmap.org/copyright">\xA9 OpenStreetMap</a>';
2438
2482
  function openMapTiles(options = {}) {
2439
2483
  const layers = { ...canonicalLayers, ...options.layers };
2440
2484
  const fields = { ...canonicalFields, ...options.fields };
@@ -2758,7 +2802,7 @@ function resolveTileflowData(data, options = {}) {
2758
2802
  );
2759
2803
  }
2760
2804
  return {
2761
- attribution: defaultAttribution,
2805
+ attribution: worldAttribution,
2762
2806
  generation: descriptor.generation,
2763
2807
  identity: dataIdentity(
2764
2808
  descriptor.type,
@@ -4340,7 +4384,7 @@ function tileflowRoadClassFilter(fields, roadClass) {
4340
4384
  }
4341
4385
 
4342
4386
  // src/modules/roads/index.ts
4343
- var defaults = {
4387
+ var defaults2 = {
4344
4388
  detail: "streets",
4345
4389
  disabledClasses: [],
4346
4390
  enabled: true,
@@ -4397,15 +4441,15 @@ function roads(options = {}) {
4397
4441
  }
4398
4442
  function resolveRoads(request) {
4399
4443
  return {
4400
- detail: request?.detail ?? defaults.detail,
4444
+ detail: request?.detail ?? defaults2.detail,
4401
4445
  disabledClasses: Object.entries(request?.classes ?? {}).filter(([, style]) => style?.enabled === false).map(([roadClass]) => roadClass),
4402
- enabled: request?.enabled ?? defaults.enabled,
4446
+ enabled: request?.enabled ?? defaults2.enabled,
4403
4447
  explicitClasses: Object.entries(request?.classes ?? {}).filter(([, style]) => style?.enabled !== false).map(([roadClass]) => roadClass),
4404
- extras: { paths: request?.extras?.paths ?? defaults.extras.paths },
4405
- hierarchy: request?.hierarchy ?? defaults.hierarchy,
4406
- oneWayMarkers: request?.oneWayMarkers ?? defaults.oneWayMarkers,
4407
- outline: request?.outline ?? defaults.outline,
4408
- weight: request?.weight ?? defaults.weight,
4448
+ extras: { paths: request?.extras?.paths ?? defaults2.extras.paths },
4449
+ hierarchy: request?.hierarchy ?? defaults2.hierarchy,
4450
+ oneWayMarkers: request?.oneWayMarkers ?? defaults2.oneWayMarkers,
4451
+ outline: request?.outline ?? defaults2.outline,
4452
+ weight: request?.weight ?? defaults2.weight,
4409
4453
  ...request?.widthScale ? {
4410
4454
  widthScale: {
4411
4455
  ...defaultRoadWidthScale,
@@ -4446,7 +4490,7 @@ function cloneJson8(value) {
4446
4490
  }
4447
4491
 
4448
4492
  // src/modules/labels/index.ts
4449
- var defaults2 = {
4493
+ var defaults3 = {
4450
4494
  aerodromeCodes: "iata",
4451
4495
  collisionPriority: "balanced",
4452
4496
  language: "auto",
@@ -4461,15 +4505,15 @@ function labels(options = {}) {
4461
4505
  }
4462
4506
  function resolveLabels(request) {
4463
4507
  return {
4464
- aerodromeCodes: request?.aerodromeCodes ?? defaults2.aerodromeCodes,
4465
- collisionPriority: request?.collisionPriority ?? defaults2.collisionPriority,
4466
- language: request?.language ?? defaults2.language,
4467
- junctions: request?.junctions ?? defaults2.junctions,
4468
- places: request?.places ?? defaults2.places,
4508
+ aerodromeCodes: request?.aerodromeCodes ?? defaults3.aerodromeCodes,
4509
+ collisionPriority: request?.collisionPriority ?? defaults3.collisionPriority,
4510
+ language: request?.language ?? defaults3.language,
4511
+ junctions: request?.junctions ?? defaults3.junctions,
4512
+ places: request?.places ?? defaults3.places,
4469
4513
  ...request?.roadClasses ? { roadClasses: [...request.roadClasses] } : {},
4470
- roads: request?.roads ?? defaults2.roads,
4471
- shields: request?.shields ?? defaults2.shields,
4472
- water: request?.water ?? defaults2.water
4514
+ roads: request?.roads ?? defaults3.roads,
4515
+ shields: request?.shields ?? defaults3.shields,
4516
+ water: request?.water ?? defaults3.water
4473
4517
  };
4474
4518
  }
4475
4519
  function visibleRoadLabelClasses(detail, roads2, explicitClasses) {
@@ -4538,7 +4582,7 @@ function compileLabels(request, roadRequest, context) {
4538
4582
  const { colors } = context;
4539
4583
  const rankField = context.data.schema.fields.rank;
4540
4584
  const capitalField = context.data.schema.fields.capital;
4541
- const defaults3 = {
4585
+ const defaults4 = {
4542
4586
  places: {
4543
4587
  continent: symbolStyle(context, "places", {
4544
4588
  minZoom: 0,
@@ -4687,7 +4731,7 @@ function compileLabels(request, roadRequest, context) {
4687
4731
  })
4688
4732
  };
4689
4733
  const styles = mergeTileflowDesign(
4690
- defaults3,
4734
+ defaults4,
4691
4735
  request?.styles
4692
4736
  );
4693
4737
  const result = [];
@@ -6158,7 +6202,7 @@ function compilePoi(request, context, language = "auto") {
6158
6202
  const categoryDensity = requestedCategoryStyle?.density ?? semantics.density;
6159
6203
  const { density: _density, ...categoryStyle } = requestedCategoryStyle ?? {};
6160
6204
  const categoryColor = semantics.color === "category" ? context.colors.poi[category] ?? context.colors.poi.label : context.colors.poi.label;
6161
- const defaults3 = {
6205
+ const defaults4 = {
6162
6206
  icon: {
6163
6207
  optional: !semantics.placement.coupleIconAndLabel,
6164
6208
  padding: semantics.placement.iconPadding,
@@ -6177,7 +6221,7 @@ function compilePoi(request, context, language = "auto") {
6177
6221
  ]) : 12
6178
6222
  })
6179
6223
  };
6180
- let style = mergeTileflowDesign(defaults3, categoryStyle);
6224
+ let style = mergeTileflowDesign(defaults4, categoryStyle);
6181
6225
  const markerStyle = style.marker ? resolveMarkerStyle(style) : void 0;
6182
6226
  const showText = semantics.labels && style.text.visible !== false;
6183
6227
  const showIcon = semantics.icons && style.icon.visible !== false;
@@ -6380,8 +6424,8 @@ var defaultColors = {
6380
6424
  textMuted: "#727B84",
6381
6425
  textHalo: "#FFFFFF"
6382
6426
  };
6383
- function resolveColors(overrides = {}, defaults3 = defaultColors, moduleOverrides = {}, moduleDefaults = {}) {
6384
- const defaultInput = defaults3;
6427
+ function resolveColors(overrides = {}, defaults4 = defaultColors, moduleOverrides = {}, moduleDefaults = {}) {
6428
+ const defaultInput = defaults4;
6385
6429
  const overrideInput = overrides;
6386
6430
  const defaultModules = moduleDefaults;
6387
6431
  const overrideModules = moduleOverrides;
@@ -6729,32 +6773,32 @@ function textFont(typography, domain) {
6729
6773
  const style = domain ? typography[domain] : typography;
6730
6774
  return [style.font, ...style.fallbacks ?? []];
6731
6775
  }
6732
- function resolveBaseColors(overrides, defaults3) {
6733
- const background = overrides.background ?? defaults3.background ?? defaultColors.background;
6734
- const land2 = overrides.land ?? defaults3.land ?? defaultColors.land;
6735
- const water2 = overrides.water ?? defaults3.water ?? defaultColors.water;
6736
- const park = overrides.park ?? defaults3.park ?? defaultColors.park;
6737
- const road = overrides.road ?? defaults3.road ?? defaultColors.road;
6738
- const text = overrides.text ?? defaults3.text ?? defaultColors.text;
6739
- const textMuted = overrides.textMuted ?? defaults3.textMuted ?? mix(text, background, 0.42);
6740
- const textHalo = overrides.textHalo ?? defaults3.textHalo ?? background;
6776
+ function resolveBaseColors(overrides, defaults4) {
6777
+ const background = overrides.background ?? defaults4.background ?? defaultColors.background;
6778
+ const land2 = overrides.land ?? defaults4.land ?? defaultColors.land;
6779
+ const water2 = overrides.water ?? defaults4.water ?? defaultColors.water;
6780
+ const park = overrides.park ?? defaults4.park ?? defaultColors.park;
6781
+ const road = overrides.road ?? defaults4.road ?? defaultColors.road;
6782
+ const text = overrides.text ?? defaults4.text ?? defaultColors.text;
6783
+ const textMuted = overrides.textMuted ?? defaults4.textMuted ?? mix(text, background, 0.42);
6784
+ const textHalo = overrides.textHalo ?? defaults4.textHalo ?? background;
6741
6785
  return {
6742
6786
  background,
6743
- boundary: overrides.boundary ?? defaults3.boundary ?? mix(text, background, 0.72),
6744
- building: overrides.building ?? defaults3.building ?? mix(land2, text, 0.08),
6787
+ boundary: overrides.boundary ?? defaults4.boundary ?? mix(text, background, 0.72),
6788
+ building: overrides.building ?? defaults4.building ?? mix(land2, text, 0.08),
6745
6789
  land: land2,
6746
6790
  park,
6747
6791
  road,
6748
- roadMajor: overrides.roadMajor ?? defaults3.roadMajor ?? mix(road, textMuted, 0.16),
6792
+ roadMajor: overrides.roadMajor ?? defaults4.roadMajor ?? mix(road, textMuted, 0.16),
6749
6793
  text,
6750
6794
  textHalo,
6751
6795
  textMuted,
6752
6796
  water: water2
6753
6797
  };
6754
6798
  }
6755
- function resolveGroup(defaults3, themeDefaults, overrides) {
6799
+ function resolveGroup(defaults4, themeDefaults, overrides) {
6756
6800
  return {
6757
- ...defaults3,
6801
+ ...defaults4,
6758
6802
  ...themeDefaults,
6759
6803
  ...overrides
6760
6804
  };
@@ -6878,13 +6922,13 @@ function compileRoads(request, context) {
6878
6922
  const semantics = resolveRoads(request);
6879
6923
  const visible = new Set(visibleRoadClasses(semantics));
6880
6924
  const metrics = roadStyleMetrics(semantics);
6881
- const defaults3 = defaultClassStyles(context, metrics, semantics);
6925
+ const defaults4 = defaultClassStyles(context, metrics, semantics);
6882
6926
  const contributions = [];
6883
6927
  const { sourceId: source, schema } = context.data;
6884
6928
  for (const [classIndex, roadClass] of roadClassOrder.entries()) {
6885
6929
  if (!visible.has(roadClass) || request?.classes?.[roadClass]?.enabled === false) continue;
6886
6930
  const classConfig = mergeTileflowDesign(
6887
- defaults3[roadClass],
6931
+ defaults4[roadClass],
6888
6932
  Object.fromEntries(
6889
6933
  ["tunnel", "surface", "bridge"].map((structure) => [
6890
6934
  structure,
@@ -9184,6 +9228,7 @@ function isPlainRecord2(value) {
9184
9228
  }
9185
9229
 
9186
9230
  // src/resolved-map-schema.ts
9231
+ import { Color as Color2 } from "@maplibre/maplibre-gl-style-spec";
9187
9232
  import { z as z6 } from "zod";
9188
9233
 
9189
9234
  // src/cartography/data-expression.ts
@@ -12801,6 +12846,24 @@ var terrainSchema = z6.union([
12801
12846
  url: z6.string().trim().min(1).optional()
12802
12847
  }).strict()
12803
12848
  ]);
12849
+ var atmosphereColorLiteralSchema = z6.string().refine((value) => Color2.parse(value)?.a === 1, "Expected an opaque color");
12850
+ var atmosphereColorSchema = z6.union([
12851
+ atmosphereColorLiteralSchema,
12852
+ fixedStringSchema.extend({ value: atmosphereColorLiteralSchema }),
12853
+ themeTokenReferenceSchema.extend({ category: z6.literal("color") }),
12854
+ themeColorOperationSchema
12855
+ ]);
12856
+ var atmosphereSchema = z6.union([
12857
+ z6.boolean(),
12858
+ z6.object({
12859
+ skyColor: atmosphereColorSchema.optional(),
12860
+ horizonColor: atmosphereColorSchema.optional(),
12861
+ fogColor: atmosphereColorSchema.optional(),
12862
+ spaceColor: atmosphereColorSchema.optional(),
12863
+ starIntensity: z6.number().finite().min(0).max(1).optional(),
12864
+ starParallax: z6.number().finite().min(0).max(1).optional()
12865
+ }).strict()
12866
+ ]);
12804
12867
  var viewSchema = z6.object({
12805
12868
  bearing: z6.number().finite().min(-180).max(180).optional(),
12806
12869
  center: z6.tuple([z6.number().finite().min(-180).max(180), z6.number().finite().min(-90).max(90)]).optional(),
@@ -12833,6 +12896,7 @@ var themesSchema = z6.record(tileflowThemeNameSchema, tileflowThemeSchema).super
12833
12896
  }).describe("tileflow-themes");
12834
12897
  var systemThemesSchema = z6.object({ dark: tileflowThemeNameSchema, light: tileflowThemeNameSchema }).strict();
12835
12898
  var resolvedTileflowMapSchema = z6.object({
12899
+ atmosphere: atmosphereSchema.optional(),
12836
12900
  data: dataSchema.optional(),
12837
12901
  defaultTheme: tileflowThemeNameSchema,
12838
12902
  fonts: fontDirectoriesSchema.optional(),
@@ -12858,6 +12922,13 @@ var resolvedTileflowMapSchema = z6.object({
12858
12922
  path: ["fonts"]
12859
12923
  });
12860
12924
  }
12925
+ if (map.atmosphere && map.projection !== "globe") {
12926
+ context.addIssue({
12927
+ code: "custom",
12928
+ message: "Atmosphere requires globe projection",
12929
+ path: ["atmosphere"]
12930
+ });
12931
+ }
12861
12932
  if (!Object.hasOwn(map.themes, map.defaultTheme)) {
12862
12933
  context.addIssue({
12863
12934
  code: "custom",
@@ -13272,7 +13343,7 @@ function cloneJson22(value) {
13272
13343
  }
13273
13344
 
13274
13345
  // src/icon-appearance.ts
13275
- import { Color } from "@maplibre/maplibre-gl-style-spec";
13346
+ import { Color as Color3 } from "@maplibre/maplibre-gl-style-spec";
13276
13347
  import { z as z8 } from "zod";
13277
13348
 
13278
13349
  // src/icon-layout.ts
@@ -13346,7 +13417,7 @@ function scaleTileflowIconLayout(layout, scale) {
13346
13417
  }
13347
13418
 
13348
13419
  // src/icon-appearance.ts
13349
- var color2 = z8.string().max(128).refine((value) => Color.parse(value) !== void 0, "Expected a MapLibre color");
13420
+ var color2 = z8.string().max(128).refine((value) => Color3.parse(value) !== void 0, "Expected a MapLibre color");
13350
13421
  var tileflowIconAppearanceSchema = z8.object({
13351
13422
  representation: z8.literal("sdf"),
13352
13423
  defaults: z8.object({
@@ -14888,7 +14959,9 @@ function compileSemanticStyleInternal(input, options, inspect, onReport) {
14888
14959
  layers
14889
14960
  })
14890
14961
  );
14962
+ const atmosphere = resolveTileflowAtmosphere(config.atmosphere);
14891
14963
  const style = {
14964
+ ...atmosphere ? { sky: compileTileflowSky(atmosphere) } : {},
14892
14965
  version: 8,
14893
14966
  name: config.name ?? "Streets",
14894
14967
  ...glyphs ? { glyphs } : {},
@@ -14906,6 +14979,7 @@ function compileSemanticStyleInternal(input, options, inspect, onReport) {
14906
14979
  "tileflow:compilerVersion": tileflowSemanticCompilerIdentity.version,
14907
14980
  ...mapMetadata.lineage && mapMetadata.lineage.length > 1 ? { "tileflow:extends": mapMetadata.lineage.slice(1) } : {}
14908
14981
  } : {},
14982
+ ...atmosphere ? { [tileflowAtmosphereMetadataKey]: { version: 1, ...atmosphere } } : {},
14909
14983
  "tileflow:theme": selected.name,
14910
14984
  "tileflow:colorScheme": resolvedTheme.colorScheme,
14911
14985
  "tileflow:data": data.identity,
@@ -15232,6 +15306,7 @@ var TileflowMapResolutionError = class extends Error {
15232
15306
  }
15233
15307
  };
15234
15308
  var tileflowMapMergeStrategies = {
15309
+ atmosphere: "atomic",
15235
15310
  data: "atomic",
15236
15311
  defaultTheme: "atomic",
15237
15312
  extends: "lineage",
@@ -15727,12 +15802,12 @@ function validateTileflowMap(input) {
15727
15802
  }
15728
15803
 
15729
15804
  // src/icon-preview.ts
15730
- import { Color as Color2 } from "@maplibre/maplibre-gl-style-spec";
15805
+ import { Color as Color4 } from "@maplibre/maplibre-gl-style-spec";
15731
15806
  function resolveTileflowIconPreviewPaint(appearance) {
15732
15807
  return {
15733
15808
  ...appearance.defaults,
15734
- color: Color2.parse(appearance.defaults.color),
15735
- haloColor: Color2.parse(appearance.defaults.haloColor)
15809
+ color: Color4.parse(appearance.defaults.color),
15810
+ haloColor: Color4.parse(appearance.defaults.haloColor)
15736
15811
  };
15737
15812
  }
15738
15813
  function createTileflowIconPreviewRuntime() {
@@ -17894,7 +17969,11 @@ var tileflowRenderedIconIdentitySchema = z12.object({
17894
17969
  }).strict()
17895
17970
  }).strict();
17896
17971
  var tileflowIconCompositionSchema = z12.object({
17897
- format: z12.enum(["tileflow-icon-composition-v1", "tileflow-icon-composition-v2"]),
17972
+ // An explicit map keeps declaration order independent of TypeScript's literal cache.
17973
+ format: z12.enum({
17974
+ "tileflow-icon-composition-v1": "tileflow-icon-composition-v1",
17975
+ "tileflow-icon-composition-v2": "tileflow-icon-composition-v2"
17976
+ }),
17898
17977
  compositionVersion: z12.union([z12.literal(1), z12.literal(2)]),
17899
17978
  packageHash: tileflowIconPackageContentHashSchema,
17900
17979
  contributors: z12.array(
@@ -514,6 +514,7 @@ type TileflowLight = {
514
514
  position?: readonly [number, number, number];
515
515
  };
516
516
  type MapLibreStyle = {
517
+ sky?: Record<string, unknown>;
517
518
  version: 8;
518
519
  name: string;
519
520
  glyphs?: string;
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
- import { T as TileflowRuntimeManifest } from './manifest-types-BdGjIYy-.js';
3
- export { a as TileflowRuntimeColorScheme, b as TileflowRuntimeManifestMapEntry, c as TileflowRuntimeManifestTheme, d as TileflowRuntimeSystemThemes, t as tileflowRuntimeManifestLimits, e as tileflowRuntimeManifestVersion } from './manifest-types-BdGjIYy-.js';
2
+ import { T as TileflowRuntimeManifest } from './manifest-types-BZU4zbmI.js';
3
+ export { a as TileflowRuntimeColorScheme, b as TileflowRuntimeManifestMapEntry, c as TileflowRuntimeManifestTheme, d as TileflowRuntimeSystemThemes, t as tileflowRuntimeManifestLimits, e as tileflowRuntimeManifestVersion } from './manifest-types-BZU4zbmI.js';
4
4
 
5
5
  declare const tileflowRuntimeManifestSchema: z.ZodType<TileflowRuntimeManifest>;
6
6
  declare function parseTileflowRuntimeManifest(input: unknown): TileflowRuntimeManifest;
@@ -34,6 +34,7 @@ type TileflowLight = {
34
34
  position?: readonly [number, number, number];
35
35
  };
36
36
  type MapLibreStyle = {
37
+ sky?: Record<string, unknown>;
37
38
  version: 8;
38
39
  name: string;
39
40
  glyphs?: string;
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, b9 as TileflowThemeSelection, bh as assertValidTileflowRuntimeSource, bi as clearTileflowManifestCache, bk as createTileflowSessionController, bl as createTileflowSessionId, bm as defaultTileflowManifestUrl, bn as defaultTileflowRuntimeView, bp as getTileflowAnalyticsApiUrl, bq as getTileflowStyleFontFaces, br as inferTileflowAnalyticsFromStyleUrl, bs as loadTileflowManifest, bt as mergeTileflowAnalytics, bu as normalizeTileflowRuntimeCenter, bv as normalizeTileflowStaticImageSize, bQ as normalizeTileflowSurfaceId, bw as normalizeTileflowUrl, bx as resolveTileflowAnalyticsRequestUrl, by as resolveTileflowManifestMap, bz as resolveTileflowMapMode, bA as resolveTileflowRuntimeStyle, bB as resolveTileflowRuntimeTheme, bC as resolveTileflowRuntimeView, bD as resolveTileflowStaticImageUrl, bE as shouldLoadTileflowManifest, bF as startTileflowSession, bH as tileflowStyleFontFaceLimits, bI as tileflowStyleFontFacesMetadataKey, bL as validateTileflowRuntimeSource, bM as validateTileflowThemeSelection } from './manifest-types-BdGjIYy-.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, b9 as TileflowThemeSelection, bh as assertValidTileflowRuntimeSource, bi as clearTileflowManifestCache, bk as createTileflowSessionController, bl as createTileflowSessionId, bm as defaultTileflowManifestUrl, bn as defaultTileflowRuntimeView, bp as getTileflowAnalyticsApiUrl, bq as getTileflowStyleFontFaces, br as inferTileflowAnalyticsFromStyleUrl, bs as loadTileflowManifest, bt as mergeTileflowAnalytics, bu as normalizeTileflowRuntimeCenter, bv as normalizeTileflowStaticImageSize, bQ as normalizeTileflowSurfaceId, bw as normalizeTileflowUrl, bx as resolveTileflowAnalyticsRequestUrl, by as resolveTileflowManifestMap, bz as resolveTileflowMapMode, bA as resolveTileflowRuntimeStyle, bB as resolveTileflowRuntimeTheme, bC as resolveTileflowRuntimeView, bD as resolveTileflowStaticImageUrl, bE as shouldLoadTileflowManifest, bF as startTileflowSession, bH as tileflowStyleFontFaceLimits, bI as tileflowStyleFontFacesMetadataKey, bL as validateTileflowRuntimeSource, bM as validateTileflowThemeSelection } from './manifest-types-BZU4zbmI.js';
@@ -125,8 +125,8 @@ export default defineMap({
125
125
 
126
126
  The standalone map above is complete as written. A map always owns its complete text provider; Core does not
127
127
  obtain fonts or sprites from World and never invents a fallback URL. The URL-backed first-party
128
- `streets`, `ferraris`, `harad`, `soundings`, `verdant`, and `sanFrancisto` maps declare their glyph
129
- providers directly. `baedeker`, `civica`, `cyberpunk`, `matrix`, `siegfried`, and `superTileWorld`
128
+ `streets`, `ferraris`, `harad`, `soundings`, and `blueprint` maps declare their glyph
129
+ providers directly. `baedeker`, `civica`, and `siegfried`
130
130
  declare packaged fonts, so ordinary imports and derived maps compile without out-of-band release
131
131
  metadata.
132
132
 
@@ -120,7 +120,7 @@ another. Browser adapters load local faces before MapLibre. Native releases use
120
120
  `glyphs` URL provider instead, which enumerates the exact comma-joined MapLibre request keys in
121
121
  `fontStacks`.
122
122
 
123
- Streets, Ferraris, Härad, Soundings, Verdant, and San Francisto each declare
123
+ Streets, Ferraris, Härad, Soundings, and Blueprint each declare
124
124
  `https://api.tileflow.dev/base/33d4de5e8086d9d629d67d3f39fedb87e23686c4c1ac653c27e2a52aee9d00b3/glyphs/{fontstack}/{range}.pbf`
125
125
  with the exact `Noto Sans Regular` and `Noto Sans Bold` stacks. The full hash identifies one
126
126
  published, immutable glyph collection independent of World data. The older `/fonts/...` endpoint
@@ -332,8 +332,7 @@ source classes into one civic color.
332
332
 
333
333
  World and text assets are independent contracts. `tileflowWorld()` selects `world-v1/current` or an
334
334
  exact `releaseId + descriptorSha256`; a `glyphs` declaration contains its own complete URL. Ordinary
335
- imports of Streets, Baedeker, Cívica, Ferraris, Härad, Siegfried, Soundings, Cyberpunk, Matrix, Verdant,
336
- San Francisto, and Super Tile World
335
+ imports of Streets, Baedeker, Cívica, Ferraris, Härad, Siegfried, Soundings, Cyberpunk, Matrix, Blueprint, and Super Tile World
337
336
  remain usable because each official map owns or inherits a URL or packaged-font provider.
338
337
  URL-backed maps become exact-byte reproducible
339
338
  when the immutable global base-asset set is published and their explicit URL is updated to its
@@ -0,0 +1,83 @@
1
+ # Globe atmosphere
2
+
3
+ Enable atmosphere in the map exported by `tileflow.config.ts`. Install `@tileflow/core` and
4
+ `@tileflow/maps` and use a browser adapter from the same compatible SDK release. The example
5
+ extends the complete Streets map, including its data and text resources.
6
+
7
+ <!-- docs:check -->
8
+
9
+ ```ts
10
+ import {defineMap} from '@tileflow/core';
11
+ import {streets} from '@tileflow/maps';
12
+
13
+ export default defineMap({
14
+ id: 'earth',
15
+ version: 1,
16
+ extends: streets,
17
+ projection: 'globe',
18
+ atmosphere: true,
19
+ view: {center: [2.3522, 48.8566], zoom: 2},
20
+ });
21
+ ```
22
+
23
+ The result has a blue atmospheric rim, a dark space background, and a deterministic star field.
24
+ Stars move slightly with the camera. There is no continuous animation while the camera is still.
25
+ The space background, stars, and supplementary rim fade between zooms 3 and 6; native atmospheric
26
+ scattering fades out by zoom 7. Coordinates are longitude, then latitude.
27
+
28
+ Omit `atmosphere` to inherit it from the base map. A map without inherited atmosphere remains
29
+ unchanged. Set `atmosphere: false` to disable an inherited atmosphere. An enabled atmosphere requires
30
+ `projection: 'globe'`; validation rejects a Mercator or unspecified projection. Atmosphere options
31
+ replace the inherited object atomically rather than merging individual fields.
32
+
33
+ ## Configure appearance
34
+
35
+ Use an object instead of `true` to override defaults:
36
+
37
+ | Option | Default | Meaning |
38
+ | --------------- | --------- | ------------------------------------------------------- |
39
+ | `skyColor` | `#07152b` | Near-space sky color |
40
+ | `horizonColor` | `#83b9f4` | Horizon and supplementary rim color |
41
+ | `fogColor` | `#bad2eb` | Native atmospheric fog color |
42
+ | `spaceColor` | `#030916` | Outer space background color |
43
+ | `starIntensity` | `0.6` | Brightness from 0 to 1; 0 hides stars |
44
+ | `starParallax` | `0.4` | Camera-relative motion from 0 to 1; 0 keeps stars still |
45
+
46
+ Colors follow the usual theme contract: use `token.color(...)`, color operations, or
47
+ `fixed(color, {reason})`. They must resolve to opaque colors. Compilation normalizes them to
48
+ six-digit hexadecimal values in the runtime metadata. Numeric options must be finite and within
49
+ 0–1. Unknown properties are rejected. For example, this fragment belongs inside `defineMap(...)`
50
+ and uses `fixed` imported from `@tileflow/core`:
51
+
52
+ ```ts
53
+ atmosphere: {
54
+ horizonColor: fixed('#83b9f4', {reason: 'Earth atmosphere stays blue across map themes'}),
55
+ starIntensity: 0.5,
56
+ starParallax: 0.25,
57
+ },
58
+ ```
59
+
60
+ The browser's reduced-motion preference overrides parallax while keeping the sky and stars visible.
61
+ No additional image, font, API key, or network request is needed for the effect.
62
+
63
+ ## Browser integration
64
+
65
+ The compiler emits MapLibre `sky` and versioned `metadata['tileflow:atmosphere']` in every concrete
66
+ style. React, Vue, Svelte, and standalone browser capture attach the shared atmosphere runtime.
67
+ Theme changes update the effect from the newly loaded style. Loading a style without atmosphere
68
+ removes the decoration.
69
+
70
+ When constructing a MapLibre map directly, call `attachTileflowAtmosphere(map)` from
71
+ `@tileflow/core/browser` after constructing the map. Keep its returned cleanup function and call it
72
+ before removing the map; the map's `remove` event also disposes it. The helper creates its own
73
+ noninteractive, accessibility-hidden canvas inside the map container. It does not create a map,
74
+ change the camera, or add controls. Preserve the renderer's transparent canvas and standard
75
+ MapLibre CSS so space can show around the globe.
76
+
77
+ Importing the browser entry is safe during server rendering. Call the attachment only in the
78
+ browser, after mounting. Raw MapLibre consumers that do not attach the helper display the compiled
79
+ native atmosphere but do not receive Tileflow's stars or space background.
80
+
81
+ The native artifact profile does not support globe atmosphere and rejects `sky`. This browser
82
+ capability does not establish React Native or hosted Static Maps support. Public availability is
83
+ established by the installed package version, not by this repository's main branch.
@@ -48,21 +48,15 @@ import {
48
48
  baedeker,
49
49
  baedekerFonts,
50
50
  baedekerIcons,
51
+ blueprint,
52
+ blueprintIcons,
51
53
  civica,
52
54
  civicaFonts,
53
55
  civicaIcons,
54
- cyberpunk,
55
- cyberpunkFonts,
56
- cyberpunkIcons,
57
56
  ferraris,
58
57
  ferrarisIcons,
59
58
  harad,
60
59
  haradIcons,
61
- matrix,
62
- matrixFonts,
63
- matrixIcons,
64
- sanFrancisto,
65
- sanFrancistoIcons,
66
60
  siegfried,
67
61
  siegfriedFonts,
68
62
  siegfriedIcons,
@@ -71,11 +65,6 @@ import {
71
65
  streets,
72
66
  streetsIcons,
73
67
  streetsThemes,
74
- superTileWorld,
75
- superTileWorldFonts,
76
- superTileWorldIcons,
77
- verdant,
78
- verdantIcons,
79
68
  } from '@tileflow/maps';
80
69
  ```
81
70
 
@@ -87,11 +76,8 @@ without changing the asset collection. Baedeker declares `[baedekerIcons]`, whos
87
76
  patterns support its travel-atlas design, and `[baedekerFonts]`, its own Cormorant Garamond
88
77
  directory; it derives contours in the browser from unpackaged Mapterhorn terrain tiles. Cívica
89
78
  declares `[civicaIcons]` for its original civic-print patterns and destination artwork and
90
- `[civicaFonts]` for its packaged lettering. Super Tile World declares `[superTileWorldIcons]` and
91
- `[superTileWorldFonts]` for its pixel-art sprites, patterns, and lettering. Cyberpunk
92
- declares `[cyberpunkIcons]` and `[cyberpunkFonts]`; Matrix
93
- independently declares `[matrixIcons]` and `[matrixFonts]`. San Francisto declares
94
- `[sanFrancistoIcons]` for its four technical hatches and schematic POI node, derives contours from
79
+ `[civicaFonts]` for its packaged lettering. Blueprint declares
80
+ `[blueprintIcons]` for its four technical hatches and schematic POI node, derives contours from
95
81
  unpackaged Mapterhorn tiles, and uses the canonical Noto Sans glyph provider. The same asset
96
82
  operation is available to applications:
97
83
 
@@ -117,6 +103,6 @@ explicit locked descriptor, not a generic source registry.
117
103
  and prepares ordinary public artifacts without serializing installation paths. It compiles one
118
104
  deterministic sprite from the final icon composition and validates every literal `icon-image`,
119
105
  `fill-pattern`, and `line-pattern` in the final style against it. It also prepares any declared font
120
- directories generically; `baedekerFonts`, `cyberpunkFonts`, `matrixFonts`, and `siegfriedFonts` are
106
+ directories generically; `baedekerFonts`, `civicaFonts`, and `siegfriedFonts` are
121
107
  ordinary package descriptors rather than pipeline special cases. Calling the pure compiler for a map whose style needs unprepared
122
108
  assets fails instead of emitting broken runtime references.
@@ -76,6 +76,7 @@ Framework adapters import the browser-only lifecycle kernel explicitly:
76
76
 
77
77
  ```ts
78
78
  import {
79
+ attachTileflowAtmosphere,
79
80
  attachTileflowFairUseNotice,
80
81
  attachTileflowMapLifecycle,
81
82
  createTileflowSessionStarter,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tileflow/core",
3
- "version": "0.1.0-alpha.27",
3
+ "version": "0.1.0-alpha.29",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Typed Tileflow config and MapLibre style compiler.",
6
6
  "type": "module",