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

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/build.js CHANGED
@@ -7953,6 +7953,9 @@ function compareCodeUnits3(left, right) {
7953
7953
  return left < right ? -1 : left > right ? 1 : 0;
7954
7954
  }
7955
7955
 
7956
+ // src/layer-domain.ts
7957
+ var tileflowLayerDomainMetadataKey = "tileflow:domain";
7958
+
7956
7959
  // src/cartography/domains.ts
7957
7960
  var tileflowLayerDomains = Object.freeze([
7958
7961
  ...tileflowSemanticModuleNames,
@@ -8326,6 +8329,11 @@ function featureState(name) {
8326
8329
  if (!key) throw new Error("expr.featureState requires a non-empty state key.");
8327
8330
  return make(["feature-state", key]);
8328
8331
  }
8332
+ function globalState(name) {
8333
+ const key = name.trim();
8334
+ if (!key) throw new Error("expr.globalState requires a non-empty state key.");
8335
+ return make(["global-state", key]);
8336
+ }
8329
8337
  function variable(name) {
8330
8338
  const key = name.trim();
8331
8339
  if (!key) throw new Error("expr.var requires a non-empty variable name.");
@@ -8568,6 +8576,12 @@ function visitExpression(value, path, variables, issues) {
8568
8576
  }
8569
8577
  return;
8570
8578
  }
8579
+ case "global-state": {
8580
+ if (exact(2) && !isNonEmptyString(value[1])) {
8581
+ addExpressionIssue(issues, [...path, 1], "Global-state keys must be non-empty strings.");
8582
+ }
8583
+ return;
8584
+ }
8571
8585
  case "var": {
8572
8586
  if (exact(2)) {
8573
8587
  if (!isNonEmptyString(value[1])) {
@@ -8834,6 +8848,7 @@ var expr = Object.freeze({
8834
8848
  has,
8835
8849
  id,
8836
8850
  featureState,
8851
+ globalState,
8837
8852
  interpolate: interpolate2,
8838
8853
  let: letValue,
8839
8854
  literal,
@@ -14091,8 +14106,11 @@ function finalizeTileflowLayers(input) {
14091
14106
  }
14092
14107
  const metadata = isRecord8(layer.metadata) ? { ...layer.metadata } : void 0;
14093
14108
  if (metadata) {
14109
+ const owner = metadata[tileflowCompilerMetadataKeys.owner];
14094
14110
  delete metadata[tileflowCompilerProvenanceMetadataKey];
14095
14111
  for (const key of Object.values(tileflowCompilerMetadataKeys)) delete metadata[key];
14112
+ if (tileflowLayerDomains.includes(owner))
14113
+ metadata[tileflowLayerDomainMetadataKey] = owner;
14096
14114
  }
14097
14115
  return {
14098
14116
  ...layer,
package/dist/index.d.ts CHANGED
@@ -169,6 +169,7 @@ declare function toNumber(value: TileflowDataExpressionInput<unknown>, fallback?
169
169
  declare function toBoolean(value: TileflowDataExpressionInput<unknown>, fallback?: TileflowDataExpressionInput<boolean>): TileflowExpression<boolean>;
170
170
  declare function toString(value: TileflowDataExpressionInput<unknown>): TileflowExpression<string>;
171
171
  declare function featureState(name: string): TileflowExpression<unknown>;
172
+ declare function globalState(name: string): TileflowExpression<unknown>;
172
173
  declare function variable<T>(name: string): TileflowExpression<T>;
173
174
  declare function letValue<TBinding, TResult>(name: string, value: TileflowDataExpressionInput<TBinding>, body: TileflowDataExpressionInput<TResult>): TileflowExpression<TileflowDataExpressionResult<TResult>>;
174
175
  declare function abs(value: TileflowDataExpressionInput<number>): TileflowExpression<number>;
@@ -211,6 +212,7 @@ declare const expr: Readonly<{
211
212
  has: typeof has;
212
213
  id: typeof id;
213
214
  featureState: typeof featureState;
215
+ globalState: typeof globalState;
214
216
  interpolate: typeof interpolate;
215
217
  let: typeof letValue;
216
218
  literal: typeof literal;
package/dist/index.js CHANGED
@@ -9316,6 +9316,9 @@ function compareCodeUnits3(left, right) {
9316
9316
  return left < right ? -1 : left > right ? 1 : 0;
9317
9317
  }
9318
9318
 
9319
+ // src/layer-domain.ts
9320
+ var tileflowLayerDomainMetadataKey = "tileflow:domain";
9321
+
9319
9322
  // src/cartography/domains.ts
9320
9323
  var tileflowLayerDomains = Object.freeze([
9321
9324
  ...tileflowSemanticModuleNames,
@@ -9677,6 +9680,11 @@ function featureState(name) {
9677
9680
  if (!key) throw new Error("expr.featureState requires a non-empty state key.");
9678
9681
  return make(["feature-state", key]);
9679
9682
  }
9683
+ function globalState(name) {
9684
+ const key = name.trim();
9685
+ if (!key) throw new Error("expr.globalState requires a non-empty state key.");
9686
+ return make(["global-state", key]);
9687
+ }
9680
9688
  function variable(name) {
9681
9689
  const key = name.trim();
9682
9690
  if (!key) throw new Error("expr.var requires a non-empty variable name.");
@@ -9919,6 +9927,12 @@ function visitExpression(value, path, variables, issues) {
9919
9927
  }
9920
9928
  return;
9921
9929
  }
9930
+ case "global-state": {
9931
+ if (exact(2) && !isNonEmptyString(value[1])) {
9932
+ addExpressionIssue(issues, [...path, 1], "Global-state keys must be non-empty strings.");
9933
+ }
9934
+ return;
9935
+ }
9922
9936
  case "var": {
9923
9937
  if (exact(2)) {
9924
9938
  if (!isNonEmptyString(value[1])) {
@@ -10185,6 +10199,7 @@ var expr = Object.freeze({
10185
10199
  has,
10186
10200
  id,
10187
10201
  featureState,
10202
+ globalState,
10188
10203
  interpolate: interpolate2,
10189
10204
  let: letValue,
10190
10205
  literal,
@@ -15578,8 +15593,11 @@ function finalizeTileflowLayers(input) {
15578
15593
  }
15579
15594
  const metadata = isRecord8(layer.metadata) ? { ...layer.metadata } : void 0;
15580
15595
  if (metadata) {
15596
+ const owner = metadata[tileflowCompilerMetadataKeys.owner];
15581
15597
  delete metadata[tileflowCompilerProvenanceMetadataKey];
15582
15598
  for (const key of Object.values(tileflowCompilerMetadataKeys)) delete metadata[key];
15599
+ if (tileflowLayerDomains.includes(owner))
15600
+ metadata[tileflowLayerDomainMetadataKey] = owner;
15583
15601
  }
15584
15602
  return {
15585
15603
  ...layer,
@@ -16618,6 +16636,12 @@ var expressionBuilders = [
16618
16636
  returns: "registered field value",
16619
16637
  serializedOperator: "get"
16620
16638
  },
16639
+ {
16640
+ arguments: ["name: nonempty string"],
16641
+ name: "globalState",
16642
+ returns: "unknown",
16643
+ serializedOperator: "global-state"
16644
+ },
16621
16645
  {
16622
16646
  arguments: ["left: T", "right: T"],
16623
16647
  name: "gt",
package/dist/native.d.ts CHANGED
@@ -26,12 +26,39 @@ declare function resolveTileflowNativeManifestUrl(value: unknown, options?: Tile
26
26
  /** Resolve a resource against its owner without fetching it or authorizing requests. */
27
27
  declare function resolveTileflowNativeResourceUrl(value: unknown, options: TileflowNativeResourceUrlOptions): string;
28
28
 
29
+ type TileflowColor = `#${string}`;
29
30
  type TileflowViewConfig = {
30
31
  bearing?: number;
31
32
  center?: readonly [number, number];
32
33
  pitch?: number;
33
34
  zoom?: number;
34
35
  };
36
+ type MapLibreSprite = string | Array<{
37
+ id: string;
38
+ url: string;
39
+ }>;
40
+ type TileflowProjection = 'globe' | 'mercator';
41
+ type TileflowLight = {
42
+ anchor?: 'map' | 'viewport';
43
+ color?: TileflowColor;
44
+ intensity?: number;
45
+ position?: readonly [number, number, number];
46
+ };
47
+ type MapLibreStyle = {
48
+ sky?: Record<string, unknown>;
49
+ version: 8;
50
+ name: string;
51
+ glyphs?: string;
52
+ light?: TileflowLight;
53
+ projection?: {
54
+ type: TileflowProjection;
55
+ };
56
+ sprite?: MapLibreSprite;
57
+ sources: Record<string, Record<string, unknown>>;
58
+ layers: Array<Record<string, unknown>>;
59
+ terrain?: Record<string, unknown>;
60
+ metadata?: Record<string, unknown>;
61
+ };
35
62
 
36
63
  /** Runtime-ready logical map with all relative theme resources already resolved. */
37
64
  type TileflowRuntimeManifestMap = TileflowRuntimeManifestMapEntry & {
@@ -47,6 +74,24 @@ type TileflowStyleFontFace = {
47
74
  style?: 'italic' | 'normal' | 'oblique';
48
75
  weight?: '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';
49
76
  };
77
+ /**
78
+ * A continuous blend of named themes of one Tileflow map. `position` places the map between
79
+ * neighbouring themes: 0 is the first, 1 the second, and 1.25 a quarter of the way from the second
80
+ * to the third.
81
+ */
82
+ type TileflowThemeBlendSelection = Readonly<{
83
+ /** From 0 to `themes.length - 1`. */
84
+ position: number;
85
+ /** Two to eight concrete theme names of the map, in blend order. */
86
+ themes: readonly string[];
87
+ }>;
88
+ declare const tileflowThemeBlendLimits: Readonly<{
89
+ maximumThemes: 8;
90
+ minimumThemes: 2;
91
+ }>;
92
+ declare function validateTileflowThemeBlendSelection(value: unknown): value is TileflowThemeBlendSelection;
93
+ /** The theme nearest to a blend position, which a blend shows when it cannot blend. */
94
+ declare function nearestTileflowBlendTheme(blend: TileflowThemeBlendSelection): string;
50
95
 
51
96
  /** The first and only public multi-theme runtime manifest contract. */
52
97
  declare const tileflowRuntimeManifestVersion: 1;
@@ -219,4 +264,92 @@ type TileflowNativeInitialViewOptions = {
219
264
  /** Resolve once or repeatedly without changing source generations, themes or acquisition. */
220
265
  declare function resolveTileflowNativeInitialView(options?: TileflowNativeInitialViewOptions): TileflowNativeInitialView;
221
266
 
222
- export { type TileflowNativeAbortSignal, type TileflowNativeInitialView, type TileflowNativeInitialViewOptions, type TileflowNativeManifestAcquire, type TileflowNativeManifestLoadOptions, type TileflowNativeManifestOperation, type TileflowNativeManifestReader, type TileflowNativeManifestResponse, type TileflowNativeManifestResult, type TileflowNativeNetworkOptions, type TileflowNativeResourceUrlOptions, type TileflowNativeSource, type TileflowNativeSourceController, TileflowNativeSourceError, type TileflowNativeSourceErrorCode, type TileflowNativeSourceErrorField, type TileflowNativeSourceOptions, type TileflowNativeSourceState, TileflowNativeUrlError, type TileflowNativeUrlErrorCode, type TileflowNativeUrlField, createTileflowNativeSourceController, loadTileflowNativeManifest, resolveTileflowNativeInitialView, resolveTileflowNativeManifestUrl, resolveTileflowNativeResourceUrl, tileflowNativeManifestLimits, tileflowNativeUrlLimits };
267
+ /**
268
+ * Theme blending plans one MapLibre style that can show any point between the themes of one map.
269
+ *
270
+ * The themes of a Tileflow map compile to the same sources, layers, filters, and expressions; they
271
+ * differ only in token values: colours, numbers, and image names. A plan keeps the first theme's
272
+ * structure and records every value that differs as a template the browser fills in for a blend
273
+ * position: 0 is the first theme, 1 the second, and 1.25 a quarter of the way from the second to
274
+ * the third. Filling a template needs no expression parsing in the browser, so the renderer only
275
+ * receives plain values.
276
+ *
277
+ * Values that MapLibre evaluates per feature (data-driven values, such as a fill colour chosen by
278
+ * land-use class) are baked into tiles, and changing them re-lays the whole source out. A plan
279
+ * splits such a layer into one layer per branch that a feature can take through the value's
280
+ * decisions on feature data, each filtered to the features that take it, so each value depends
281
+ * only on zoom and the blend position. A value that reads feature data continuously is drawn once
282
+ * per theme instead, and the copies cross-fade by opacity. Images are mixed in their pixels.
283
+ * Values that read feature state cannot be split, because filters cannot read state; they switch
284
+ * when the dominant theme changes.
285
+ */
286
+ /** A paint value that the browser sets as the blend moves. */
287
+ type TileflowThemeBlendPaint = Readonly<{
288
+ layer: string;
289
+ property: string;
290
+ template: unknown;
291
+ /** Ground values follow the blend position; symbol values follow the label cross-fade. */
292
+ follows: TileflowThemeBlendClock;
293
+ }>;
294
+ /** Image names whose artwork differs between themes and is mixed in pixels. */
295
+ type TileflowThemeBlendImage = Readonly<{
296
+ names: readonly string[];
297
+ follows: TileflowThemeBlendClock;
298
+ }>;
299
+ /** A value that can only change all at once, when the dominant theme changes. */
300
+ type TileflowThemeBlendSwitch = Readonly<{
301
+ layer: string;
302
+ group: 'layout' | 'paint';
303
+ property: string;
304
+ values: readonly unknown[];
305
+ }>;
306
+ /**
307
+ * `position` values follow the blend; `dominant` values follow a short cross-fade that starts when
308
+ * the nearest theme changes. Labels use it because light lettering on a dark plate and dark
309
+ * lettering on a light plate meet in the same grey halfway.
310
+ */
311
+ type TileflowThemeBlendClock = 'dominant' | 'position';
312
+ type TileflowThemeBlendPlan = Readonly<{
313
+ /** Number of themes; blend positions run from 0 to `themes - 1`. */
314
+ themes: number;
315
+ paints: readonly TileflowThemeBlendPaint[];
316
+ images: readonly TileflowThemeBlendImage[];
317
+ switches: readonly TileflowThemeBlendSwitch[];
318
+ /** Root sky and light, when they differ between themes. */
319
+ sky?: unknown;
320
+ light?: unknown;
321
+ summary: Readonly<{
322
+ splitLayers: number;
323
+ copiedLayers: number;
324
+ /** Per-theme layers of which only the nearest theme's copy is shown. */
325
+ switchedLayers: number;
326
+ switchedValues: number;
327
+ }>;
328
+ /** The style at a blend position: every template filled, every switch at the nearest theme. */
329
+ styleAt(position: number): MapLibreStyle;
330
+ }>;
331
+ type TileflowThemeBlendOptions = Readonly<{
332
+ /**
333
+ * How icon images that differ between themes change. `mix` (the default) mixes their artwork in
334
+ * pixels under the first theme's image names. `switch` changes the image names when the nearest
335
+ * theme changes, for renderers that cannot replace an image's pixels while keeping its stretch
336
+ * and content metadata.
337
+ */
338
+ iconImages?: 'mix' | 'switch';
339
+ /**
340
+ * How values that read feature data change when they can be neither split nor cross-faded.
341
+ * `values` (the default) sets each value when the nearest theme changes. `layers` draws such a
342
+ * layer once per theme and shows only the nearest theme's copy, for renderers that cannot set
343
+ * data-driven values at run time reliably.
344
+ */
345
+ featureSwitches?: 'layers' | 'values';
346
+ }>;
347
+ declare class TileflowThemeBlendError extends Error {
348
+ name: string;
349
+ }
350
+ /** Plans a blend of two or more compiled themes of one map, in blend order. */
351
+ declare function planTileflowThemeBlend(styles: readonly MapLibreStyle[], options?: TileflowThemeBlendOptions): TileflowThemeBlendPlan;
352
+ /** Fills one blend template for a position. Plain values pass through unchanged. */
353
+ declare function fillTileflowThemeBlendTemplate(template: unknown, position: number): unknown;
354
+
355
+ export { type TileflowNativeAbortSignal, type TileflowNativeInitialView, type TileflowNativeInitialViewOptions, type TileflowNativeManifestAcquire, type TileflowNativeManifestLoadOptions, type TileflowNativeManifestOperation, type TileflowNativeManifestReader, type TileflowNativeManifestResponse, type TileflowNativeManifestResult, type TileflowNativeNetworkOptions, type TileflowNativeResourceUrlOptions, type TileflowNativeSource, type TileflowNativeSourceController, TileflowNativeSourceError, type TileflowNativeSourceErrorCode, type TileflowNativeSourceErrorField, type TileflowNativeSourceOptions, type TileflowNativeSourceState, TileflowNativeUrlError, type TileflowNativeUrlErrorCode, type TileflowNativeUrlField, type TileflowThemeBlendClock, TileflowThemeBlendError, type TileflowThemeBlendImage, type TileflowThemeBlendOptions, type TileflowThemeBlendPaint, type TileflowThemeBlendPlan, type TileflowThemeBlendSelection, type TileflowThemeBlendSwitch, createTileflowNativeSourceController, fillTileflowThemeBlendTemplate, loadTileflowNativeManifest, nearestTileflowBlendTheme, planTileflowThemeBlend, resolveTileflowNativeInitialView, resolveTileflowNativeManifestUrl, resolveTileflowNativeResourceUrl, tileflowNativeManifestLimits, tileflowNativeUrlLimits, tileflowThemeBlendLimits, validateTileflowThemeBlendSelection };