@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/README.md +3 -0
- package/dist/browser.d.ts +629 -1
- package/dist/browser.js +559 -16
- package/dist/build.js +18 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +24 -0
- package/dist/native.d.ts +134 -1
- package/dist/native.js +691 -1
- package/docs/authoring-model.md +15 -0
- package/docs/map-emphasis.md +89 -0
- package/docs/theme-transitions-and-blends.md +59 -3
- package/package.json +1 -1
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
|
-
|
|
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 };
|