@tileflow/core 0.1.0-alpha.47 → 0.1.0-alpha.48

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/REFERENCE.md ADDED
@@ -0,0 +1,379 @@
1
+ # Core reference
2
+
3
+ Detailed authoring and runtime contracts for `@tileflow/core`. Start with the
4
+ [README](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/README.md) to install the
5
+ package and preview your first map. For step-by-step guides, see the
6
+ [Tileflow documentation](https://tileflow.dev/docs).
7
+
8
+ This reference ships with the package. Use the copy included in your installed release for
9
+ version-specific behavior; the GitHub `main` branch can contain unreleased changes.
10
+
11
+ Core defines, validates, and compiles the map language. The CLI and build integrations prepare
12
+ assets; browser adapters render prepared maps. Loading a config executes its imports, so treat
13
+ it as trusted code.
14
+
15
+ - [Inheritance](#understand-inheritance)
16
+ - [Team Icon Sets](#team-icon-sets-foundations)
17
+ - [Themes and semantic modules](#style-with-themes-and-semantic-modules)
18
+ - [Compilation and inspection](#compile-and-inspect)
19
+ - [Prepared map sources](#select-a-prepared-map)
20
+ - [Data, terrain, and browser resources](#data-terrain-and-browser-resources)
21
+ - [Generated reference](#reference)
22
+ - [Native icon capabilities](#native-icon-capabilities)
23
+ - [Flat footprints under 3D buildings](#flat-footprints-under-3d-buildings)
24
+
25
+ ## Understand inheritance
26
+
27
+ Omitted fields inherit, but declaring a field does not imply a recursive merge:
28
+
29
+ - `view` deep-merges; nested arrays replace.
30
+ - `modules` merges by domain. Declaring `roads(...)` replaces that domain's inherited request and
31
+ render contributions. Use `refine(...)` to patch it, `disable()` to remove it, and `reset()` for
32
+ an explicit reset inside a supported patch.
33
+ - `themes` replaces the complete collection and clears inherited `systemThemes` and `timeOfDay` mappings.
34
+ `defaultTheme` can select an inherited concrete theme; `systemThemes` replaces its complete mapping.
35
+ - `icons` replaces the ordered contributor list. Omission inherits it; `[]` disables it. Local and
36
+ package directories can be combined with explicit locked `iconSet('@team/set')` descriptors.
37
+ Spread the parent's list explicitly when composing contributors. Later contributors win for an
38
+ exact icon ID.
39
+ - `fonts` and `glyphs` are mutually exclusive text providers. Declaring either replaces the inherited
40
+ provider. `atmosphere`, `data`, `projection`, `sky`, `terrain`, and `marine` are also atomic.
41
+
42
+ Identity (`id`, `name`, `version`) and tooling `scenes` and `shots` belong to the leaf map and do not inherit.
43
+ Module object order does not determine rendering order.
44
+
45
+ ## Team Icon Sets foundations
46
+
47
+ `iconSet('@team/set')` declares a contributor alongside local/package directories, without I/O.
48
+ Maps accept at most 32 contributors; set references must be unique. Explicit array order and
49
+ later-wins icon precedence apply to all contributors.
50
+
51
+ `tileflow.icons.lock.json` pins immutable set revisions and artifacts. Its parser rejects duplicate
52
+ keys, stale references, mixed Teams, invalid IDs, floating versions, unsafe URLs and manifest/hash
53
+ mismatches. Serialization is canonical; hashes are internal integrity details.
54
+
55
+ Shared identity follows published artwork, not source-only SVG edits yielding identical artifacts.
56
+ Git retains original artwork history. Shared packages contain no original-source hash, format or
57
+ filesystem path; local/package originals retain source identity. Shared winners use `rendered-icon`
58
+ identity. Ordered, versioned composition receipts record consumed revisions, including shadowed
59
+ sets and dependency changes preserving rendered pixels.
60
+
61
+ Maps without shared sets retain v1 revision hashing. Shared sets require complete receipts and the
62
+ domain-separated v2 contract, identified by `mapRevisionSchemaVersion: 2`; omission means v1.
63
+ Metadata-free RGBA packages retain `tileflow-icon-package-v1`. SDF appearance or text-fitting
64
+ metadata requires `tileflow-icon-package-v2` and v2 composition receipts, including defaults/layout.
65
+
66
+ `@tileflow/dev` prepares declared contributors; the CLI manages catalogs and exact locks.
67
+ Importing `iconSet` neither resolves revisions nor makes a Team catalog available to deployments.
68
+
69
+ ## Style with themes and semantic modules
70
+
71
+ `roads.pathGround` optionally gives surface paths different colors on mapped green ground and
72
+ elsewhere. It accepts `greenColor`, `groundColor`, optional `widthScale`, and `opacity` (zero
73
+ disables the treatment). The compiler keeps a complete ground-colored path, adds clipped green
74
+ portions from the same HTTP(S) vector source, and places paths below vehicle casings. Grass,
75
+ woods, wetlands, orchards, nurseries, and green recreation polygons supply context; polygon
76
+ holes remain unpainted. Classification follows tile geometry, not imagery or inferred climate.
77
+
78
+ Framework web adapters, CLI preview, capture, and the embedded mobile web runtime register the
79
+ derived-source protocol automatically. Raw MapLibre integrations must call
80
+ `registerTileflowPathGroundProtocol({addProtocol: maplibregl.addProtocol})` from
81
+ `@tileflow/core/browser` before creating the map. The `native-v1` build keeps the complete
82
+ ground-colored paths and disables the green overlay, since native renderers cannot run this
83
+ browser protocol. Its build record explicitly reports `pathGround: 'ground-fallback'`.
84
+
85
+ Themes are complete appearance documents, not loose color overrides. Every theme must supply the
86
+ same token schema. Use `token.color(...)`, `token.number(...)`, `token.image(...)`, and typed font
87
+ roles for theme-dependent values. Use `fixed(value, {reason})` for an intentionally invariant visual
88
+ value. Structural controls, such as visibility and zoom gates, remain ordinary literals.
89
+
90
+ Extend a theme without changing the inherited map structure:
91
+
92
+ <!-- docs:check -->
93
+
94
+ ```ts
95
+ import {defineMap, defineTheme} from '@tileflow/core';
96
+ import {streets, streetsThemes} from '@tileflow/maps';
97
+
98
+ const dark = defineTheme(streetsThemes.dark, {
99
+ id: 'madrid-dark',
100
+ version: 1,
101
+ colorScheme: 'dark',
102
+ tokens: {color: {'surface.land': '#0d1320', 'surface.water': '#081e2e'}},
103
+ });
104
+
105
+ export default defineMap({
106
+ id: 'madrid',
107
+ version: 1,
108
+ extends: streets,
109
+ themes: {light: streetsThemes.light, dark},
110
+ defaultTheme: 'light',
111
+ systemThemes: {light: 'light', dark: 'dark'},
112
+ });
113
+ ```
114
+
115
+ `system` is a runtime selection policy, not a stored theme. Builds, captures, static scenes, and
116
+ receipts must use a concrete theme such as `light` or `dark`.
117
+
118
+ Theme and `timeOfDay` changes animate over 450 ms, respecting reduced motion. Web manifests v3
119
+ add `familyUrl`, a bounded `tileflow-style-family` v1 document sharing structure and parameters;
120
+ flat `styleUrl` exports remain. `createTileflowStyleFamily` (`@tileflow/core/build`) factors styles;
121
+ `parseTileflowStyleFamily` and `materializeTileflowStyleFamily` (`@tileflow/core/runtime`) validate
122
+ and expand them. Controllers cache families. Compatible appearances preserve sources,
123
+ application layers and 3D palettes; structural variants swap styles. Feature-dependent branches
124
+ prepare once; discrete values and RGBA icons switch at the dominant theme without relayout.
125
+ Fades use premultiplied OKLab. Parameter columns are not semantic tokens.
126
+
127
+ `controller.setColors({'surface.water': '#008800'})` overrides named tokens; `{}` restores authored
128
+ colours. Fixed colours and application layers remain. Web builds retain token bindings; direct
129
+ `createStyle` calls opt in with `runtimeColors: true`. `createTileflowAppearanceController().set()`
130
+ selects author-owned `fixed`, `system` or local `clock` behaviour without UI or location requests.
131
+ Profile performance on target devices.
132
+
133
+ Theme controllers also provide module/label emphasis, eased numeric `expr.globalState` values,
134
+ and fixed-size dynamic RGBA images with state refresh and restoration across theme changes.
135
+ `getRouteInks()` supplies route colours; `createTileflowLineProgress` animates drawing routes.
136
+ `createTileflowGroundLayers` places them under 3D buildings, optionally showing occluded stretches
137
+ faintly. Themes declare `lighting.sun` and `lighting.ambient`; `getSun()` returns the displayed
138
+ sun. `setSun()` accepts angles or a date and location. Transitions
139
+ mix 3D directions (angular fallback for opposite vectors) and OKLab light colours.
140
+
141
+ `createTileflowBuildings3D` enables worker-meshed buildings rising at zoom 15–15.3, scene sun,
142
+ cast/contact shadows and 0.8 m rounded corners; effects are independently overridable. Its
143
+ `tileflow-buildings-scene-3d` layer replaces `tileflow-buildings-native-extrusion` only after visible
144
+ building tiles draw. Failure keeps the native fallback; 2D restores authored visibility.
145
+ Street lights default off, including in Streets: enable `roads.streetLights.enabled` and mount
146
+ `createTileflowStreetLights`. `createTileflowVegetation` follows the map's `3d`, `flat` or `auto` policy.
147
+
148
+ POI icons and names place together; `placement.coupleIconAndLabel: false` separates them.
149
+
150
+ The semantic domains are `land`, `water`, `nautical`, `roads`, `buildings`, `boundaries`, `labels`,
151
+ `poi`, `aeroways`, `transit`, `vegetation`, `addresses`, and `landforms`. Style stable geographic
152
+ targets rather than compiler-generated MapLibre layer IDs. Shared primitives cover fills, lines,
153
+ text, icons, circles, and extrusions. `zoom.*` supplies zoom curves; `expr.*` and `field(...)` supply
154
+ the closed data-expression language. `renderPass`, `refineRenderTarget`, and `withRenderStack` add
155
+ owner-local rendering behavior without bypassing the compiler. A pass, or a target its module moves,
156
+ is placed at a band edge such as `'above-relief'` or `'below-labels'`, or `{above}` / `{below}` one
157
+ semantic target.
158
+
159
+ ## Compile and inspect
160
+
161
+ `validateTileflowMap(input)` returns `{valid, messages}`. `parseTileflowMap(map)` resolves and
162
+ validates the authoring input and throws on failure. `createStyle(map, options)` returns a style or
163
+ throws; `createStyleResult(map, options)` returns structured diagnostics and a compilation report.
164
+ Only a successful result contains `style`.
165
+
166
+ Compilation compacts redundant expressions and shares repeated predicates and values with
167
+ MapLibre `let` bindings. Themes still produce standalone Style JSON, with the same layer order,
168
+ appearance and assets. Inspect semantic targets rather than depending on the emitted expression
169
+ shape; it may change when the compiler removes repetition.
170
+
171
+ Maps with package/local icon or font directories need the CLI, a build plugin, or
172
+ [`@tileflow/dev/artifacts`](https://github.com/tileflow/tileflow-sdk/blob/main/packages/dev/README.md)
173
+ to prepare assets. Browser components consume the resulting manifest.
174
+
175
+ Discover the language and inspect a prepared map:
176
+
177
+ ```sh
178
+ npx tileflow describe themes --json
179
+ npx tileflow language manifest --json
180
+ npx tileflow language schema --json
181
+ npx tileflow inspect --json
182
+ npx tileflow explain --theme dark --json
183
+ npx tileflow semantic-diff --from-config before/tileflow.config.ts --to-config after/tileflow.config.ts --json
184
+ ```
185
+
186
+ The language manifest is also exported as `tileflowAuthoringManifest`, with
187
+ `tileflowAuthoringManifestSchemaVersion`. The generated schema distinguishes authoring input from
188
+ resolved compiler input. `diffTileflowMaps(before, after)` returns deterministic semantic changes
189
+ at JSON Pointer paths. Physical inspection IDs and indexes are diagnostic observations, not stable
190
+ application targets.
191
+
192
+ ## Select a prepared map
193
+
194
+ React, Vue and Svelte accept a required `source` object, `{map, manifestUrl?}`. `map` is the portable
195
+ name in the manifest, not a Hosted `map_...` identifier. An omitted web `manifestUrl` means exactly
196
+ `/tileflow/manifest.json`; custom paths and external hosts must be explicit. The native Core and
197
+ React Native type contracts use `{map, manifestUrl}` with an explicit absolute URL. They do not
198
+ infer an application origin, Metro host or manifest location.
199
+
200
+ <!-- docs:check -->
201
+
202
+ ```ts
203
+ import type {TileflowNativeSource} from '@tileflow/core/native';
204
+ import type {TileflowRuntimeSource} from '@tileflow/core/runtime';
205
+
206
+ const webSource = {map: 'madrid'} satisfies TileflowRuntimeSource;
207
+ const nativeSource = {
208
+ map: 'madrid',
209
+ manifestUrl: 'https://maps.example.com/tileflow/native/manifest.json',
210
+ } satisfies TileflowNativeSource;
211
+ ```
212
+
213
+ These objects select existing prepared maps; they do not compile or render one. Every Tileflow
214
+ framework Map is manifest-backed, without a renderer discriminator or direct-style mode. The
215
+ obsolete source fields `kind` and `style` are rejected. Completely unmanaged maps use upstream
216
+ MapLibre directly. Omitted themes use the manifest default, concrete themes select exact names,
217
+ and `system` requires the manifest's explicit light/dark mapping and a supplied runtime color scheme.
218
+ The pre-release React Native
219
+ package uses this contract for its mounted Map; it is not yet published.
220
+
221
+ ## Data, terrain, and browser resources
222
+
223
+ Tileflow World is the hosted primary source, with an open (CC0)
224
+ [schema](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/reference/tileflow-world-v1.json);
225
+ detail layers load only when drawn. `vectorTiles()` takes that schema or OpenMapTiles
226
+ (`openMapTiles()`). `hostedTileset()`, `geojsonSource()`, `boundaryAreas` and overlays add named
227
+ sources.
228
+
229
+ `geojsonSource()` declares GeoJSON in `sources`, and `clusterOverlay()` and `heatmapOverlay()` return
230
+ ordinary overlays that keep `placement`, `remove()`, and `tileflow validate`:
231
+
232
+ <!-- docs:check -->
233
+
234
+ ```ts
235
+ import {clusterOverlay, defineMap, geojsonSource, heatmapOverlay} from '@tileflow/core';
236
+ import {streets} from '@tileflow/maps';
237
+
238
+ export default defineMap({
239
+ id: 'store-locator',
240
+ version: 1,
241
+ extends: streets,
242
+ sources: {
243
+ stores: geojsonSource({
244
+ attribution: 'Stores © Example',
245
+ cluster: true,
246
+ clusterMaxZoom: 14,
247
+ clusterRadius: 50,
248
+ }),
249
+ },
250
+ overlays: {
251
+ density: heatmapOverlay({
252
+ id: 'density',
253
+ maxZoom: 9,
254
+ placement: 'below-labels',
255
+ source: 'stores',
256
+ }),
257
+ stores: clusterOverlay({id: 'stores', placement: 'above-labels', source: 'stores'}),
258
+ },
259
+ });
260
+ ```
261
+
262
+ Omit `data` to fill the source at runtime through a framework adapter's `dataSources`. Inline `data`
263
+ is limited to 512,000 bytes; larger files use an absolute `https://` URL. Clustering options keep
264
+ their MapLibre and Mapbox names. A cluster overlay over a source without `cluster: true` fails
265
+ validation with `TF_OVERLAY_CLUSTER_SOURCE_INVALID`, and a map with no label font and no `font` option
266
+ fails with `TF_OVERLAY_FONT_UNAVAILABLE`. Web helpers are also exported from
267
+ `@tileflow/core/runtime`. `heatmapOverlay()` also accepts `sourceLayer` for hosted vector tilesets,
268
+ which cannot cluster. See the
269
+ [interactions reference](https://github.com/tileflow/tileflow-sdk/blob/main/packages/interactions/REFERENCE.md)
270
+ for runtime data, click-to-expand, and React Native support.
271
+
272
+ `bathymetry({vectorLayers: {...}})` declares contour/name layers. `marine: 'nautical'` adds
273
+ navigation marks, flashing lights, and a "Not for navigation" notice.
274
+
275
+ `circular_feature` optionally retains `network` (a normalized road-network string; coverage is
276
+ partial) and `official` (a numeric path-status indicator). For paths, footways, cycleways and
277
+ bridleways, `official=0` means OSM marks the way `informal=yes`; `official=1` means `informal=no`
278
+ or a recorded operator, unless `informal=yes`. Absence means unknown or not applicable.
279
+ This indicator does not establish legal recognition or public access.
280
+
281
+ World attribution credits Tileflow and OpenStreetMap; other vector data keeps its owner's
282
+ attribution.
283
+
284
+ `projection` accepts `mercator` or `globe`. Terrain supports `none`, `hillshade`, `3d`, and an object
285
+ form for explicit hillshade and contour configuration. Browser-derived contours require a DEM tile
286
+ template, zoom limits, thresholds, and the Tileflow contour protocol. Framework adapters and local
287
+ tooling prepare browser resources; direct MapLibre integrations must register required protocols
288
+ before loading a style.
289
+
290
+ ### Load a portable style in MapLibre
291
+
292
+ Await `loadTileflowRuntimeStyle` before giving MapLibre a runtime style. React, Vue and Svelte do
293
+ this automatically. The loader prepares flat styles or shared families, resolving sprites, glyphs,
294
+ fonts, sources and model/landmark URLs against their declaring documents. HTTP TileJSON loads once
295
+ per preparation; explicit source options win. Artifacts and input objects remain unchanged.
296
+
297
+ <!-- docs:check -->
298
+
299
+ ```ts
300
+ import {loadTileflowRuntimeStyle, loadTileflowStyleFonts} from '@tileflow/core/browser';
301
+ import type {TileflowRuntimeStyle} from '@tileflow/core/runtime';
302
+
303
+ export async function prepareMapStyle(runtime: TileflowRuntimeStyle, signal?: AbortSignal) {
304
+ const prepared = await loadTileflowRuntimeStyle(runtime, {signal});
305
+ await loadTileflowStyleFonts(prepared.style, {fontFaces: prepared.fontFaces});
306
+ return prepared.style; // Use as new maplibregl.Map({container, style}).
307
+ }
308
+ ```
309
+
310
+ Resolve the runtime with `resolveTileflowRuntimeStyle`. For inline styles, `baseUrl` supplies the
311
+ document URL (default: `document.baseURI`). Absolute URLs, signatures, template tokens and
312
+ application data retain their meaning. Custom source protocols remain with MapLibre's handlers.
313
+
314
+ `fetch`, `signal` and `transformRequest(url, 'Style' | 'Source')` control document requests, including
315
+ families. Defaults use same-origin credentials and reject redirects. Invalid documents, failed
316
+ requests and size limits (style/family: 16 MiB; TileJSON: 1 MiB) reject preparation.
317
+
318
+ For theme changes, pass `initial: prepared` and `styleLoadOptions` to `createTileflowThemeController`.
319
+ With flat styles, `initialStyle: prepared.style` can instead preserve the original `initial` and
320
+ `getCurrent()` identity. Inline themes and `loadStyle` overrides must already be prepared. Disposal
321
+ aborts pending loads; blends and rollback reuse prepared resources.
322
+
323
+ With `projection: 'globe'`, `atmosphere: true` adds a halo and stars; an object configures colors, star count and size.
324
+ `sky` follows the sun at street level. Frameworks and capture attach both; direct
325
+ MapLibre consumers call `attachTileflowAtmosphere(map)` from `@tileflow/core/browser`.
326
+
327
+ Applications that need the map's data themselves, such as streets to route over or the place
328
+ under the camera, read chosen layers of a vector source for an area at a fixed zoom with
329
+ `createTileflowTileReader` from `@tileflow/core/browser`, which also runs in a module worker.
330
+
331
+ Browser 3D scenes resolve `camera.adaptivePerspective` from caller override, map default, then
332
+ `false`; Streets enables it. Buildings occlude depth markers. `camera.pitchLimit: {maxZoom, maxPitch}`
333
+ caps inclination through `maxZoom`, respecting stricter application caps. Closer views and disposal
334
+ restore the application's maximum.
335
+ 3D layers prioritize visible ground from viewport bottom toward the horizon. Buildings fade across
336
+ the far boundary, followed by haze. Coverage follows resize and projection within each layer's
337
+ `maxTiles` budget (default 25), prioritizing nearest ground.
338
+ Model roles use `modelLighting` for colours/materials and `colorScale` (0–1, default 1) for darkening
339
+ recoloured assets. Ordinary facades use soft daylight and a gradient through their lower 85%, leaving
340
+ roofs and upper edges light. Map-shaded models retain a short base gradient; physical roles retain
341
+ their lighting. Model corners belong to the asset; ordinary buildings use `edgeRadius`.
342
+ `buildings.threeDimensional.entrance: false` shows buildings/models at full height and opacity at
343
+ entrance zooms, without zoom/arrival growth or fading. Equal endpoints such as
344
+ `entrance: {buildings: [14.25, 14.25], models: [14.25, 14.25]}` switch immediately at that zoom.
345
+
346
+ Text requires exactly one provider. Soundings and Blueprint use URL glyphs; Streets packages DINish
347
+ and Noto Sans; Baedeker, 1777 and Siegfried package Cormorant; Cívica packages its lettering. Hosted
348
+ rejects packaged/local fonts: self-host or replace them with compatible public glyphs. Tile and font
349
+ URLs do not grant redistribution rights.
350
+
351
+ ## Reference
352
+
353
+ Use the [generated language schema](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/reference/modules-api-reference.json),
354
+ and [public exports](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/src/index.ts)
355
+ for exact options. Prefer the installed CLI's generated contracts when using a published release;
356
+ `main` can contain unreleased changes. Report defects in the
357
+ [issue tracker](https://github.com/tileflow/tileflow-sdk/issues).
358
+
359
+ ## Native icon capabilities
360
+
361
+ Prepared icon metadata identifies SDF assets and their default fill and halo. Core rejects any
362
+ symbol layer that can select both SDF and RGBA, including fallbacks and effective local overrides,
363
+ with `TF_ICON_REPRESENTATION_MIXED`. It preserves layers, collisions and interaction IDs. Omitted
364
+ SDF paint follows the resolved image selection; supplied map paint stays independent from asset
365
+ defaults. See [Author recolorable and adaptable icons](https://github.com/tileflow/tileflow-sdk/blob/main/packages/dev/README.md).
366
+
367
+ Land may supply a georeferenced `globalLandcoverUnderlay` image with `url`, four
368
+ `coordinates` (northwest, northeast, southeast, southwest), `attribution`, zoom bounds
369
+ and themed `opacity`. It is drawn below global cover and omitted when land is disabled.
370
+ Tree forms may use `sizeAnchor` and `crownAnchor` (metres) with `sizeCompression`
371
+ from 0 to 1 to reduce size variation while preserving each tree’s proportions.
372
+
373
+ ## Flat footprints under 3D buildings
374
+
375
+ `modules.buildings.threeDimensional.flatFootprints` defaults to `true`. Set it to `false`
376
+ to suspend duplicate flat building fills, outlines and flat shadows in the shared 3D scene,
377
+ after its building entrance zoom. Roads then remain visible beneath open landmark structures.
378
+ Returning to 2D or disposing the scene restores their previous visibility; without WebGL2 the
379
+ flat fallback remains. Streets selects this option; other maps keep their authored treatment.