@tileflow/core 0.1.0-alpha.42 → 0.1.0-alpha.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +56 -69
  2. package/THIRD_PARTY_NOTICES.md +3 -3
  3. package/dist/{3d-CzLTD0RK.d.ts → 3d-CW5Ls0An.d.ts} +32 -2
  4. package/dist/3d.d.ts +1 -1
  5. package/dist/3d.js +425 -50
  6. package/dist/browser.d.ts +95 -5
  7. package/dist/browser.js +866 -101
  8. package/dist/build.d.ts +8 -4
  9. package/dist/build.js +250 -3
  10. package/dist/config-reference.json +3395 -2140
  11. package/dist/{icon-composition-B1A2udKb.d.ts → icon-composition-Bbw9umUA.d.ts} +37 -2
  12. package/dist/index.d.ts +13 -4
  13. package/dist/index.js +193 -3
  14. package/dist/{manifest-types-B0lQjabX.d.ts → manifest-types-CwjHd4qc.d.ts} +8 -0
  15. package/dist/manifest.d.ts +2 -2
  16. package/dist/native-profile.d.ts +4 -0
  17. package/dist/native-profile.js +2 -0
  18. package/dist/native.js +789 -462
  19. package/dist/runtime.d.ts +1 -1
  20. package/dist/worker/camera-tile-worker.global.js +2 -2
  21. package/package.json +5 -6
  22. package/docs/application-tile-reading.md +0 -86
  23. package/docs/authoring-model.md +0 -269
  24. package/docs/boundary-areas-and-choropleths.md +0 -230
  25. package/docs/buildings-3d.md +0 -624
  26. package/docs/camera-moves-and-tile-cache.md +0 -112
  27. package/docs/capture-scenes.md +0 -40
  28. package/docs/capture-shots.md +0 -173
  29. package/docs/cartographic-defaults.md +0 -214
  30. package/docs/compiled-style-performance.md +0 -286
  31. package/docs/data-is-separate-from-design.md +0 -610
  32. package/docs/depth-markers.md +0 -65
  33. package/docs/dynamic-style-images.md +0 -100
  34. package/docs/globe-atmosphere.md +0 -113
  35. package/docs/hosted-session-authorization.md +0 -106
  36. package/docs/map-and-terrain-examples.md +0 -156
  37. package/docs/map-emphasis.md +0 -89
  38. package/docs/native-artifact-profile.md +0 -152
  39. package/docs/native-resource-urls.md +0 -369
  40. package/docs/nautical-marks.md +0 -308
  41. package/docs/public-api-and-browser-subpath.md +0 -101
  42. package/docs/route-drawing.md +0 -191
  43. package/docs/shared-visual-primitives.md +0 -101
  44. package/docs/street-lights.md +0 -127
  45. package/docs/street-sky.md +0 -156
  46. package/docs/style-states.md +0 -73
  47. package/docs/sun-and-light.md +0 -167
  48. package/docs/theme-transitions-and-blends.md +0 -317
  49. package/docs/themes-and-module-styles.md +0 -156
  50. package/docs/trees-3d.md +0 -295
@@ -1,100 +0,0 @@
1
- # Dynamic style images
2
-
3
- Use `registerImage` on an existing `TileflowThemeController` from `@tileflow/core/browser` when an
4
- application draws RGBA pixels that depend on a theme or style state. The controller owns the image's
5
- registration, refresh and restoration. The application owns its drawing and prepares asynchronous
6
- assets before registration. This browser API is tested with MapLibre GL JS 6.13; it is not a Native
7
- or Static Maps image contract.
8
-
9
- Start with the [Core guide](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/README.md)
10
- and [theme controller setup](theme-transitions-and-blends.md#use-the-core-controller).
11
- The map's symbol layer must already refer to the same image ID in every theme. Register before its
12
- first placement. Choose an ID that does not exist in the sprite or belong to another application
13
- resource. Registering an image does not create a layer or add points to a source.
14
-
15
- ## Draw an alert from state
16
-
17
- This helper runs after browser mounting, with the controller for the existing map. The image is
18
- 64 physical pixels at pixel ratio 2, so it occupies 32 logical pixels before the layer's icon scale.
19
-
20
- <!-- docs:check -->
21
-
22
- ```ts
23
- import type {TileflowThemeController} from '@tileflow/core/browser';
24
-
25
- export function registerAlert(controller: TileflowThemeController) {
26
- const canvas = document.createElement('canvas');
27
- canvas.width = canvas.height = 64;
28
- const context = canvas.getContext('2d', {willReadFrequently: true});
29
- if (!context) throw new Error('Canvas 2D is unavailable.');
30
-
31
- return controller.registerImage('live-alert', {
32
- width: 64,
33
- height: 64,
34
- pixelRatio: 2,
35
- states: ['alert'],
36
- render({theme, states}) {
37
- context.clearRect(0, 0, 64, 64);
38
- context.beginPath();
39
- context.arc(32, 32, 24, 0, Math.PI * 2);
40
- context.fillStyle = states.alert ? '#ee624e' : '#edbd53';
41
- context.fill();
42
- context.strokeStyle = theme === 'night' ? '#ffffff' : '#253b42';
43
- context.lineWidth = 4;
44
- context.stroke();
45
- return context.getImageData(0, 0, 64, 64).data;
46
- },
47
- onError(error) {
48
- console.error('Alert image could not refresh:', error);
49
- },
50
- });
51
- }
52
-
53
- export async function activateAlert(controller: TileflowThemeController) {
54
- await controller.setState('alert', true);
55
- }
56
- ```
57
-
58
- The resource receives the states listed in `states`, including intermediate values during numeric
59
- state transitions. `theme` is the committed theme, or the nearest theme of a blend. `blend` exposes
60
- its position and ordered theme names for continuous artwork interpolation. States not set through
61
- this controller remain undefined; an explicit null is distinct from an unset state.
62
-
63
- ## Update and release
64
-
65
- Theme changes and changes to declared states schedule a refresh. Identical inputs do no work;
66
- several changes before the next animation frame coalesce. The `setState` promise describes the
67
- state transition, not completion of the next image frame. There is no independent animation clock.
68
- For camera values, new application data or another external input, call the returned handle's
69
- `refresh()`. Read those values inside `render`, and return `undefined` when the existing pixels are
70
- still correct. Undefined output on the first render creates a transparent image.
71
-
72
- `render` is synchronous and returns exactly `width * height * 4` RGBA bytes as a `Uint8Array` or
73
- `Uint8ClampedArray`. The controller copies the buffer. Width and height must be integers from 1
74
- through 2048; pixel ratio must be positive and finite. All three remain fixed until disposal.
75
- Changing pixel ratio while keeping physical size would change logical size and collision geometry,
76
- so choose it at registration rather than following device pixel ratio changes automatically.
77
-
78
- A style reload restores the last valid image before placement. WebGL context loss suspends image
79
- work; restoration replays pixels and processes pending inputs. `handle.dispose()` removes only
80
- that resource's image and cancels its pending work. `controller.dispose()` releases all of its
81
- images. Map removal cancels work and releases listeners. Disposal is idempotent.
82
-
83
- Invalid registration throws before claiming a resource. Later render failures keep the last valid
84
- pixels and call `onError`, or `console.error` when omitted. A later refresh can retry. Another image
85
- owner is never silently overwritten. The application must not call `addImage`, `updateImage` or
86
- `removeImage` for a registered ID. Dynamic IDs must stay identical across blended themes; mixing
87
- them with theme-specific atlas artwork is rejected before the blend replaces the style.
88
-
89
- ## Placement and scope
90
-
91
- This API changes image pixels only. It does not resize icons, split layers, change padding,
92
- anchors, sort order, overlap, filters or source features. Native symbol placement and collisions
93
- remain governed by the authored style. Transparent pixels still occupy the image's existing
94
- geometry: this API does not define separate visual and collision bounds.
95
-
96
- All features using an ID share its pixels and state. Independent per-feature animation, SDF
97
- generation, image loading, GPU composition and automatic framework props are outside this API.
98
- Keep every selectable icon in the same symbol layer RGBA, including fallbacks; mixing these images
99
- with SDF icons does not become supported through registration.
100
- Profile the application's drawing cost and visible symbol rendering on its target devices.
@@ -1,113 +0,0 @@
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 pale white rim with a soft blue halo, a muted blue-gray space background, and a
24
- deterministic field of 1,100 stars per repeating 1,600 × 1,000 CSS-pixel area. The halo follows the
25
- globe's contour without brightening its surface or adding glow to labels. Stars have a minimum
26
- radius of 0.6 CSS pixels so the fainter stars remain visible on high-density screens.
27
- Stars move slightly with the camera. There is no continuous animation while the camera is still.
28
- The space background, stars, and rim fade between zooms 3 and 6. Native sun scattering is disabled
29
- when `atmosphere` is enabled, including maps that also declare `sky`. Coordinates are longitude,
30
- then latitude.
31
-
32
- Omit `atmosphere` to inherit it from the base map. A map without inherited atmosphere remains
33
- unchanged. Set `atmosphere: false` to disable an inherited atmosphere. An enabled atmosphere requires
34
- `projection: 'globe'`; validation rejects a Mercator or unspecified projection. Atmosphere options
35
- replace the inherited object atomically rather than merging individual fields.
36
-
37
- ## Configure appearance
38
-
39
- Use an object instead of `true` to override defaults:
40
-
41
- | Option | Default | Meaning |
42
- | --------------- | --------- | -------------------------------------------------------------- |
43
- | `skyColor` | `#263b50` | Near-space sky color |
44
- | `horizonColor` | `#b6cfe2` | Horizon and outer halo color |
45
- | `fogColor` | `#d4e1ec` | Native atmospheric fog color |
46
- | `spaceColor` | `#142233` | Outer space background color |
47
- | `starColor` | `#e0ebff` | Star color |
48
- | `starCount` | `1100` | Stars per repeating 1600 × 1000 CSS-pixel area; integer 0–4096 |
49
- | `starSize` | `1` | Radius multiplier from 0 to 4; 0 hides stars |
50
- | `starIntensity` | `0.6` | Brightness from 0 to 1; 0 hides stars |
51
- | `starParallax` | `0.4` | Camera-relative motion from 0 to 1; 0 keeps stars still |
52
-
53
- Colors follow the usual theme contract: use `token.color(...)`, color operations, or
54
- `fixed(color, {reason})`. They must resolve to opaque colors. Compilation normalizes them to
55
- six-digit hexadecimal values in the runtime metadata. Numeric options must be finite and within
56
- the ranges above. `starCount` controls density rather than the total visible count: the field
57
- repeats on larger viewports. `starSize` scales both the stars and their glow; changing density
58
- preserves the positions of existing stars. Unknown properties are rejected. For example, this fragment belongs inside `defineMap(...)`
59
- and uses `fixed` imported from `@tileflow/core`:
60
-
61
- ```ts
62
- atmosphere: {
63
- horizonColor: fixed('#b6cfe2', {reason: 'Earth atmosphere stays blue across map themes'}),
64
- starCount: 650,
65
- starSize: 0.8,
66
- starColor: fixed('#e0ebff', {reason: 'Cool stars across map themes'}),
67
- starIntensity: 0.5,
68
- starParallax: 0.25,
69
- },
70
- ```
71
-
72
- The browser's reduced-motion preference overrides parallax while keeping the sky and stars visible.
73
- No additional image, font, API key, or network request is needed for the effect.
74
-
75
- ## Browser integration
76
-
77
- The compiler emits MapLibre `sky` and versioned `metadata['tileflow:atmosphere']` in every concrete
78
- style. React, Vue, Svelte, Inspector, and standalone browser capture attach the shared atmosphere
79
- runtime. Metadata version 2 includes star appearance; the runtime also reads version 1 with
80
- the established star defaults. Use matching compiler and browser packages for new styles.
81
- Theme changes update the effect from the newly loaded style. Loading a style without atmosphere
82
- removes the decoration.
83
-
84
- When constructing a MapLibre map directly, call `attachTileflowAtmosphere(map)` from
85
- `@tileflow/core/browser` after constructing the map. Keep its returned cleanup function and call it
86
- before removing the map; the map's `remove` event also disposes it. The helper creates its own
87
- noninteractive, accessibility-hidden canvases for the stars and halo behind the map. A custom layer
88
- reads the globe projection; the halo stays outside theme snapshots, preserving its appearance
89
- through time-of-day transitions. It does not create a map, change the camera, filter the map canvas,
90
- or add controls.
91
- Preserve the renderer's transparent canvas and standard
92
- MapLibre CSS so space can show around the globe.
93
-
94
- For a camera-driven presentation, the optional second argument can adjust star speed and direction:
95
- `attachTileflowAtmosphere(map, {starParallaxScale: -5})` moves stars five times as fast in the
96
- opposite direction. The multiplier must be finite; it defaults to `1`, and `0` freezes the stars.
97
- This runtime option does not change the compiled style or animate a stationary map. Reduced motion
98
- still disables star movement, and stopping the camera also stops the stars.
99
- Use the map's `starParallax` for its authored appearance; reserve `starParallaxScale` for the
100
- embedding application's camera presentation. The effective motion multiplies both values, so a
101
- map declaring `starParallax: 0` remains stationary under any runtime multiplier. Inspector preview
102
- uses the shared atmosphere helper with its default multiplier, just like the framework adapters.
103
-
104
- Importing the browser entry is safe during server rendering. Call the attachment only in the
105
- browser, after mounting. Raw MapLibre consumers must attach the helper to display the globe halo,
106
- stars, and space background. The compiled sky alone does not include these effects.
107
-
108
- A map that also declares a [street sky](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/docs/street-sky.md)
109
- uses the sky's colors for MapLibre's `sky`; the atmosphere keeps its halo, space background and stars.
110
-
111
- The native artifact profile does not support globe atmosphere and rejects `sky`. This browser
112
- capability does not establish React Native or hosted Static Maps support. Public availability is
113
- established by the installed package version, not by this repository's main branch.
@@ -1,106 +0,0 @@
1
- # Hosted session authorization
2
-
3
- Start with the [@tileflow/core guide](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/README.md) for installation and a complete first example.
4
-
5
- The framework adapters use `createTileflowSessionController` to obtain one short-lived session
6
- grant before eligible hosted style, tile, font, or sprite requests. Concurrent resources share the
7
- same preflight, grants are attached only to reviewed HTTP(S) origins, and an expired unused session
8
- rotates once when the server requests it. A controller also rotates after six hours or 10,000
9
- eligible requests. The preflight has a 10-second client timeout by default; direct controller users
10
- can set `grantTimeoutMs` from 1 to 120,000 milliseconds.
11
-
12
- `analytics.enabled: false` disables only the optional analytics beacon. It does not disable this
13
- server-owned commercial authorization. User `transformRequest` callbacks still run first; Tileflow
14
- then decorates only the resulting eligible URL and preserves the other request options.
15
-
16
- Set `analytics.surfaceId` to a stable product location when the same Map appears in several places:
17
-
18
- ```ts
19
- const analytics = {surfaceId: 'store-locator'};
20
- ```
21
-
22
- A Surface ID is 1–64 lowercase ASCII letters, digits, `.`, `_`, or `-`; it starts and ends with a
23
- letter or digit. Missing or invalid values become `default`. Use a durable integration name such as
24
- `checkout` or `dealer-search`, not a URL, branch, preview, random component instance, or user ID.
25
- Surface labels do not change authorization, entitlement, or Session identity.
26
-
27
- For exact Tileflow World release tiles, framework adapters also use the browser request bridge to
28
- observe the response's safe fair-use state without adding identity, query parameters, credentials,
29
- or user headers to the public World URL. The bridge requires the immutable release path and exactly
30
- one lowercase descriptor digest; the retired mutable World template is never intercepted. Early
31
- `GRACE` stays silent; signed late `GRACE` creates a compact
32
- accessible owner-action pill, and `MANAGED_REQUIRED` creates a stronger in-map banner. A missing
33
- header, absent tile, MapLibre error, or failed response cannot erase an existing manage action; a
34
- later successful `OPEN` response can clear it. Shaped empty tiles remain render-safe while the owner
35
- action stays available. Successful World tile bodies are streamed with a 16 MiB maximum: an
36
- oversized `Content-Length` is rejected before reading, and chunked responses are cancelled as soon
37
- as their accumulated bytes cross the same bound. Abort signals cancel an active reader; errors do
38
- not include the remote response body.
39
-
40
- Other subpaths under `src/`, `themes/`, `templates/`, and `modules/` are internal implementation
41
- details and can change during alpha releases.
42
-
43
- Official map definitions and the source assets they own ship together in `@tileflow/maps`, not in
44
- Core. That package exports the maps and their reusable directory descriptors:
45
-
46
- ```ts
47
- import {
48
- baedeker,
49
- baedekerFonts,
50
- baedekerIcons,
51
- blueprint,
52
- blueprintIcons,
53
- civica,
54
- civicaFonts,
55
- civicaIcons,
56
- map1777,
57
- map1777Icons,
58
- siegfried,
59
- siegfriedFonts,
60
- siegfriedIcons,
61
- soundings,
62
- soundingsIcons,
63
- streets,
64
- streetsIcons,
65
- streetsThemes,
66
- } from '@tileflow/maps';
67
- ```
68
-
69
- All official maps are complete standalone maps. The sole semantic compiler is implicit; none
70
- imports or extends another official map, and each declares its own icon directory.
71
- Streets declares `[streetsIcons]` and exposes its complete coordinated appearances as
72
- `streetsThemes.light` and `streetsThemes.dark`; image tokens select the matching sidewalk pattern
73
- without changing the asset collection. Baedeker declares `[baedekerIcons]`, whose eight original
74
- patterns support its travel-atlas design, and `[baedekerFonts]`, its own Cormorant Garamond
75
- directory; it derives contours in the browser from unpackaged Mapterhorn terrain tiles. Cívica
76
- declares `[civicaIcons]` for its original civic-print patterns and destination artwork and
77
- `[civicaFonts]` for its packaged lettering. Blueprint declares
78
- `[blueprintIcons]` for its four technical hatches and schematic POI node, derives contours from
79
- unpackaged Mapterhorn tiles, and uses the canonical Noto Sans glyph provider. The same asset
80
- operation is available to applications:
81
-
82
- ```ts
83
- export default defineMap({
84
- id: 'brand-map',
85
- version: 1,
86
- extends: streets,
87
- icons: [...streets.icons, './icons'],
88
- });
89
- ```
90
-
91
- `icons` is a `readonly TileflowIconSource[]`. Omission inherits the parent's exact array,
92
- declaration replaces it atomically, and `[]` means no icons. Local and package directories, plus
93
- explicit locked `iconSet('@team/set')` descriptors, apply left to right.
94
- `<id>.<ext>` publishes an icon as `<id>`; `<id>.pattern.<ext>` publishes an intrinsic-size pattern
95
- as `<id>`. The published ID must already be canonical lower-kebab; a later exact ID wins and a
96
- case-only collision fails. There is no built-in selector, mutable external sprite selector, icon
97
- mapping, icon-specific inheritance, additive command, or compatibility alias. An Icon Set is an
98
- explicit locked descriptor, not a generic source registry.
99
-
100
- `@tileflow/dev` resolves local and package directory descriptors, verifies real-path containment,
101
- and prepares ordinary public artifacts without serializing installation paths. It compiles one
102
- deterministic sprite from the final icon composition and validates every literal `icon-image`,
103
- `fill-pattern`, and `line-pattern` in the final style against it. It also prepares any declared font
104
- directories generically; `baedekerFonts`, `civicaFonts`, and `siegfriedFonts` are
105
- ordinary package descriptors rather than pipeline special cases. Calling the pure compiler for a map whose style needs unprepared
106
- assets fails instead of emitting broken runtime references.
@@ -1,156 +0,0 @@
1
- # Map and terrain examples
2
-
3
- Start with the [@tileflow/core guide](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/README.md) for installation and a complete first example.
4
-
5
- Typed Tileflow map contracts, semantic modules, and deterministic MapLibre style compilation.
6
-
7
- Every public `tileflow.config.ts` exports one map. Most maps import an existing map and override only
8
- the design fields they own:
9
-
10
- ```ts
11
- import {
12
- defineMap,
13
- defineTheme,
14
- fixed,
15
- labels,
16
- poi,
17
- roads,
18
- token,
19
- water,
20
- zoom,
21
- } from '@tileflow/core';
22
- import {streets, streetsThemes} from '@tileflow/maps';
23
-
24
- const madridDark = defineTheme(streetsThemes.dark, {
25
- id: 'madrid-dark',
26
- version: 1,
27
- colorScheme: 'dark',
28
- tokens: {color: {'surface.land': '#0d1320', 'surface.water': '#081e2e'}},
29
- });
30
-
31
- export default defineMap({
32
- id: 'madrid',
33
- name: 'Madrid',
34
- version: 1,
35
- extends: streets,
36
- themes: {light: streetsThemes.light, dark: madridDark},
37
- defaultTheme: 'light',
38
- systemThemes: {light: 'light', dark: 'dark'},
39
- projection: 'globe',
40
- modules: {
41
- water: water({
42
- bodies: {
43
- fill: {
44
- opacity: fixed(0.95, {reason: 'Madrid keeps this water density in every theme'}),
45
- },
46
- },
47
- }),
48
- roads: roads({
49
- detail: 'streets',
50
- hierarchy: 'strong',
51
- classes: {
52
- primary: {
53
- surface: {
54
- fill: {
55
- color: fixed('#E4A85B', {reason: 'Madrid brand roads stay warm in every theme'}),
56
- width: zoom.linear([
57
- [7, fixed(0.6, {reason: 'Madrid keeps its primary-road hierarchy across themes'})],
58
- [16, fixed(8, {reason: 'Madrid keeps its primary-road hierarchy across themes'})],
59
- ]),
60
- },
61
- },
62
- },
63
- secondary: {surface: {fill: {color: token.color('roads.secondary')}}},
64
- },
65
- }),
66
- labels: labels({
67
- language: 'local',
68
- places: 'all',
69
- roads: 'streets',
70
- styles: {
71
- places: {
72
- city: {
73
- text: {
74
- size: fixed(18, {reason: 'Madrid keeps its city-label scale across themes'}),
75
- haloWidth: fixed(1.5, {reason: 'Madrid keeps its city-label halo across themes'}),
76
- },
77
- },
78
- },
79
- },
80
- }),
81
- poi: poi({categories: ['food-drink', 'arts-entertainment', 'transport'], color: 'category'}),
82
- },
83
- view: {center: [-3.7038, 40.4168], pitch: 35, zoom: 12},
84
- });
85
- ```
86
-
87
- Map identity and scenes belong to the leaf and do not inherit. Hosted browser policy is configured
88
- in Tileflow and does not enter cartographic authoring or compilation.
89
-
90
- Set `projection: 'globe'` for MapLibre's adaptive globe preset. Global zooms render as a sphere,
91
- then transition to Mercator between zoom 10 and 12 so detailed streets remain planar. Omit the
92
- property, or set it to `'mercator'`, for a consistently flat map.
93
-
94
- Terrain keeps the original `'none' | 'hillshade' | '3d'` shorthand. The object form can style every
95
- MapLibre hillshade paint control. Raster terrain accepts either a TileJSON `url` or explicit `tiles`
96
- templates, with optional `tileSize` (256 or 512) and native `minZoom`/`maxZoom` limits. The templates
97
- must contain `{z}`, `{x}` and `{y}` and use HTTPS (HTTP is allowed for loopback development).
98
- These source limits control DEM requests independently of `hillshade.minZoom`/`maxZoom` visibility;
99
- the renderer reuses the highest available native resolution for closer views. Select resolution
100
- limits supported by the provider and retain its required attribution.
101
-
102
- Contours generate vector lines in the browser from their own explicit DEM tile template. They
103
- require `demUrl`, `demMaxZoom`, and zoom-indexed `[minor, index]` `thresholds`; these are separate
104
- from the raster source's `url` or `tiles`. Set `mode: 'none'` to compile
105
- contours without adding a raster source, hillshade, or 3D terrain:
106
-
107
- ```ts
108
- terrain: {
109
- mode: 'none',
110
- encoding: 'terrarium',
111
- contours: {
112
- demUrl: 'https://terrain.example.test/{z}/{x}/{y}.webp',
113
- demMaxZoom: 13,
114
- maxZoom: 15,
115
- overzoom: 2,
116
- thresholds: {
117
- 9: [100, 500],
118
- 11: [50, 250],
119
- 13: [20, 100],
120
- 15: [10, 50],
121
- },
122
- minor: {
123
- color: token.color('terrain.contour.minor'),
124
- width: token.number('terrain.contour.minor-width'),
125
- },
126
- index: {
127
- color: token.color('terrain.contour.index'),
128
- width: token.number('terrain.contour.index-width'),
129
- },
130
- labels: {
131
- color: token.color('terrain.contour.label'),
132
- haloColor: token.color('terrain.contour.halo'),
133
- },
134
- },
135
- }
136
- ```
137
-
138
- Declare those `terrain.*` color and number roles with the same keys in every map theme. The
139
- compiled source is ordinary MapLibre vector data with source layer `contours`; its tile URL
140
- contains the safely encoded DEM template and complete generation parameters. Register the generic
141
- protocol before MapLibre reads the style. It lazily initializes the pinned, locally bundled
142
- `maplibre-contour@0.1.0` browser module on the first contour tile; no public CDN runtime is needed.
143
- `overzoom` may not exceed the lowest threshold zoom, so generated DEM requests never use a negative
144
- zoom. Every index interval must be a whole multiple of its minor interval. Contour labels emit the
145
- scaled numeric elevation without assuming a display unit. Source and layer visibility cannot begin
146
- before the first configured threshold zoom. To bound main-thread work, effective minor intervals
147
- must be at least 250 units at z0–4, 100 at z5–7, 50 at z8–10, 20 at z11–12, and 10 from z13 onward.
148
- Use a trusted, size-bounded DEM tile service; the protocol intentionally accepts author-supplied
149
- HTTP(S) templates rather than proxying or republishing terrain data.
150
-
151
- ```ts
152
- import maplibregl from 'maplibre-gl';
153
- import {registerTileflowContourProtocol} from '@tileflow/core/browser';
154
-
155
- registerTileflowContourProtocol({addProtocol: maplibregl.addProtocol});
156
- ```
@@ -1,89 +0,0 @@
1
- # Map emphasis
2
-
3
- Start with the [@tileflow/core guide](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/README.md) for installation and a complete first example.
4
-
5
- An application that draws its own content over a Tileflow map, such as a route, a selected place, or
6
- search results, often needs the map to step back so that content reads first. Map emphasis does
7
- that on the map's own MapLibre instance: chosen modules recede towards the map's ground colour, and
8
- the map's labels and icons fade, except inside an area the application keeps at full strength. The
9
- change eases in and out, stays when the theme changes, and follows a theme blend.
10
-
11
- Emphasis needs a browser document and MapLibre GL JS. It changes only the layers a Tileflow map
12
- compiled, so an application's own layers, such as the route it draws, keep their appearance.
13
-
14
- ## Show an emphasis
15
-
16
- Create the theme controller for the map, then ask for an emphasis. This example assumes an existing
17
- MapLibre map named `map` that shows the `dark` theme of a published Tileflow map, and a route the
18
- application has already drawn:
19
-
20
- ```ts
21
- import type {Map as MapLibreMap} from 'maplibre-gl';
22
- import {createTileflowThemeController} from '@tileflow/core/browser';
23
-
24
- export function focusOnRoute(map: MapLibreMap, styleUrl: string) {
25
- const controller = createTileflowThemeController({
26
- initial: {style: styleUrl, theme: 'dark'},
27
- map,
28
- });
29
- void controller.setEmphasis(
30
- {
31
- labels: 0.6,
32
- recede: {boundaries: 0.55, roads: 0.5, transit: 0.5},
33
- },
34
- {transition: {duration: 560}},
35
- );
36
- return () => controller.setEmphasis(undefined, {transition: {duration: 560}});
37
- }
38
- ```
39
-
40
- Roads, transit, and boundaries move halfway or a little more towards the ground colour, labels and
41
- icons keep 60 % of their opacity, and the change eases in over 560 milliseconds. Calling
42
- `setEmphasis(undefined)` eases the map back to its design. Each call supersedes the previous one;
43
- the promise of a superseded call resolves with `status: 'superseded'`.
44
-
45
- ## Choose what steps back
46
-
47
- - `recede` maps module names to an amount from 0 (as designed) to 1 (the ground colour itself). The
48
- modules are the semantic domains a map compiles, such as `roads`, `transit`, `boundaries`,
49
- `water`, `land`, `buildings`, and `vegetation`. Every colour of a receding layer moves towards the
50
- ground colour, including the colours inside zoom curves and data cases. Artwork that cannot be
51
- recoloured, such as a pattern, fades by the same amount instead.
52
- - `labels` is the share of their opacity that the map's labels and icons keep, from 0 to 1.
53
- - `keep` is a GeoJSON `Polygon` or `MultiPolygon`. Labels and icons whose features fall inside it
54
- keep their full strength. It can hold up to 4,096 positions. A corridor round a route is a
55
- typical keep area.
56
-
57
- The ground colour is the map's background colour. During a blend it is the blended background, so
58
- receding colours follow the hour as the blend moves.
59
-
60
- ## How it changes over time
61
-
62
- Values that depend only on the camera, such as a colour or an opacity with a zoom curve, ease every
63
- frame. A value that MapLibre evaluates per feature, such as a road colour chosen by class or any
64
- label opacity once a keep area is given, would make MapLibre lay its source out again on every
65
- change. Such values change once, at the start of the change, under a snapshot of the map that fades
66
- out as the transition runs. When the browser asks for reduced motion, every change happens at once.
67
-
68
- An emphasis stays through `setTheme` and `setBlend`: after a new style is applied, the emphasis is
69
- written again under the same cross-fade, and each blend position recomputes the receded colours.
70
-
71
- ## How it finds modules
72
-
73
- Every compiled layer names its semantic module in its metadata:
74
-
75
- ```json
76
- {"id": "tileflow-road-major-fill", "metadata": {"tileflow:domain": "roads"}}
77
- ```
78
-
79
- Layers that a theme blend splits or copies keep the same entry. Applications can read the key from
80
- `tileflowLayerDomainMetadataKey` in `@tileflow/core/browser`. Physical layer IDs remain diagnostic;
81
- use the module name instead. Styles compiled before this metadata existed have no module names, so
82
- an emphasis leaves them unchanged.
83
-
84
- ## Cost
85
-
86
- Each eased frame writes only the values that changed, with `setPaintProperty` and without
87
- validation. For a detailed city map with roads, transit, and boundaries receding, that is about 150
88
- values a frame on a desktop computer. Writing values directly is faster than reading a MapLibre
89
- global state from every value, because a global state change re-evaluates every layer that reads it.