@tileflow/core 0.1.0-alpha.38 → 0.1.0-alpha.39

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.
@@ -1,10 +1,12 @@
1
1
  # Nautical marks
2
2
 
3
3
  The `nautical` module draws navigation marks from a `nautical-v1` vector source: buoys, beacons,
4
- lighthouses, lights, rocks and other hazards, wrecks, reefs, navigation areas, routes, cables,
5
- harbours, ports, and a restrained indication of where a provider publishes marks. It is reference
6
- cartography for general-purpose maps. It is not a nautical chart, and a map that draws it always
7
- shows a "Not for navigation" notice.
4
+ lighthouses, lights that flash in their rhythm, rocks and other hazards, wrecks, reefs, navigation
5
+ areas, routes, submarine and overhead cables, bridges with their clearances, harbours, marinas,
6
+ berths, small-craft facilities, inland notice boards, waterway distance marks, ports, and a
7
+ restrained indication of where a provider publishes marks. It is reference cartography for
8
+ general-purpose maps. It is not a nautical chart, and a map that draws it always shows a "Not for
9
+ navigation" notice.
8
10
 
9
11
  ## Enable Nautical on a map
10
12
 
@@ -100,19 +102,25 @@ displayed.
100
102
  Every feature carries `provider`, `provenance`, `edition`, `coverage`, `licence`, and `min_zoom`,
101
103
  the first zoom at which the feature appears. `rank` (1 is the most important feature of its layer)
102
104
  and `name` are optional. Colours are S-57 colour names, and multi-valued colours and categories are
103
- comma-separated in source order, for example `black,yellow`. `tileflowNauticalV1Schema` lists the
104
- field names, layers, and geometry types.
105
-
106
- | Source layer | Geometry | Fields the module reads |
107
- | ----------------- | -------------------------- | -------------------------------------------------------- |
108
- | `aid` | Point | `class`, `subclass`, `category`, `color`, `rank`, `name` |
109
- | `light` | Point | `class` (`major` or `minor`), `color`, `label`, `rank` |
110
- | `hazard` | Point, LineString, Polygon | `class`, `water_level`, `name` |
111
- | `wreck` | Point, Polygon | `class`, `name` |
112
- | `reef` | Polygon | `name` |
113
- | `navigation_area` | Point, LineString, Polygon | `class`, `size`, `rank`, `name` |
114
- | `coverage` | Polygon | `families` |
115
- | `sounding` | Point | `depth` |
105
+ comma-separated in source order, for example `black,yellow`. Clearances, depths, and heights are in
106
+ metres. `tileflowNauticalV1Schema` lists the field names, layers, geometry types, and known
107
+ providers: `openstreetmap` (coverage class `community`), `nga-list-of-lights` (`list`), and the
108
+ `chart` providers `noaa-office-of-coast-survey` and `usace-ienc` (U.S. Army Corps of Engineers
109
+ Inland ENCs). The source's TileJSON owns every provider credit.
110
+
111
+ | Source layer | Geometry | Fields the module reads |
112
+ | ----------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------ |
113
+ | `aid` | Point | `class`, `subclass`, `category`, `color`, `rank`, `name`, `information`, `distance`, `distance_unit` |
114
+ | `light` | Point | `class` (`major` or `minor`), `color`, `label`, `rank`, `character`, `group`, `period_s`, `sequence` |
115
+ | `hazard` | Point, LineString, Polygon | `class`, `water_level`, `name` |
116
+ | `wreck` | Point, Polygon | `class`, `name` |
117
+ | `reef` | Polygon | `name` |
118
+ | `navigation_area` | Point, LineString, Polygon | `class`, `subclass`, `size`, `rank`, `name`, `vertical_clearance` and its `_closed`, `_open`, and `_safe` variants |
119
+ | `coverage` | Polygon | `families` |
120
+ | `sounding` | Point | `depth` |
121
+
122
+ The Nautical source promotes each light's `provenance` as its feature ID
123
+ (`promoteId: {light: 'provenance'}`), so lights can be animated with MapLibre feature state.
116
124
 
117
125
  Every layer filters on `min_zoom`, so a compatible source that keeps features in lower-zoom tiles
118
126
  still shows each one from its own first zoom. Point groups place a lower `rank` first.
@@ -122,26 +130,42 @@ still shows each one from its own first zoom. Point groups place a lower `rank`
122
130
  Each group is a style option of `nautical(...)`, with the same marker, symbol, area, and line style
123
131
  objects as other modules.
124
132
 
125
- | Option | Draws | Default symbology |
126
- | ----------------- | ------------------------------------------------------------------------------- | --------------------------------------------------------- |
127
- | `buoys` | `aid` buoys, light floats, and light vessels | Circle in the first colour, ringed with the second |
128
- | `beacons` | `aid` beacons and daymarks | Small circle in the first colour |
129
- | `lighthouses` | `aid` lighthouses | Ink circle and name |
130
- | `aids` | Other `aid` classes, such as moorings, fog signals, and racons | Small hollow circle |
131
- | `lights` | `light` points, one per sector | Flare in the light's first colour and its chart `label` |
132
- | `hazards` | `hazard` points | `+` for rocks, `*` for rocks that show; circled obstacles |
133
- | `hazardAreas` | `hazard` polygons; the outline also strokes linear hazards | Accent wash with a dotted outline |
134
- | `wrecks` | `wreck` points | `Wk`, in the accent colour when dangerous |
135
- | `wreckAreas` | `wreck` polygons | Ink wash with a dashed outline |
136
- | `reefs` | `reef` polygons | Sand wash with a dotted outline |
137
- | `navigationAreas` | `navigation_area` polygons | Dashed outlines; accent for operational areas |
138
- | `routes` | `navigation_area` lines of class `route` and `traffic-separation` | Dashed line; accent for traffic separation |
139
- | `cables` | `navigation_area` lines of class `cable`, `pipeline`, and their area classes | Fine dashed accent line |
140
- | `harbours` | `navigation_area` points of class `harbour` | Ink circle and name |
141
- | `ports` | `navigation_area` points of class `port` | Ink circle and name sized by `size`, from low zooms |
142
- | `coverage` | `coverage` polygons that cover every family | Faint tint at low zooms only |
143
- | `soundings` | `sounding` points | Depth figure |
144
- | `labels` | Names inside hazard, navigation-area, reef, and wreck polygons; coverage opt-in | Collision-aware text |
133
+ | Option | Draws | Default symbology |
134
+ | ----------------- | ---------------------------------------------------------------------------- | --------------------------------------------------------- |
135
+ | `buoys` | `aid` buoys, light floats, and light vessels | Circle in the first colour, ringed with the second |
136
+ | `beacons` | `aid` beacons and daymarks | Small circle in the first colour |
137
+ | `lighthouses` | `aid` lighthouses | Ink circle and name |
138
+ | `aids` | Other `aid` classes, such as moorings, fog signals, and racons | Small hollow circle |
139
+ | `lights` | `light` points, one per sector | Flare in the light's first colour and its chart `label` |
140
+ | `hazards` | `hazard` points | `+` for rocks, `*` for rocks that show; circled obstacles |
141
+ | `hazardAreas` | `hazard` polygons; the outline also strokes linear hazards | Accent wash with a dotted outline |
142
+ | `wrecks` | `wreck` points | `Wk`, in the accent colour when dangerous |
143
+ | `wreckAreas` | `wreck` polygons | Ink wash with a dashed outline |
144
+ | `reefs` | `reef` polygons | Sand wash with a dotted outline |
145
+ | `navigationAreas` | `navigation_area` polygons | Dashed outlines; accent for operational areas |
146
+ | `routes` | `navigation_area` lines of class `route` and `traffic-separation` | Dashed line; accent for traffic separation |
147
+ | `cables` | `navigation_area` lines of class `cable`, `pipeline`, and their area classes | Fine dashed accent line |
148
+ | `overheadCables` | `navigation_area` lines of class `overhead-cable` | Dash-dot accent line |
149
+ | `bridges` | `navigation_area` bridge polygons; the outline also strokes bridge lines | Land-coloured deck with an ink outline |
150
+ | `berths` | `navigation_area` berth polygons; the outline also strokes berth lines | Thin ink outline, wider and darker for `guest` berths |
151
+ | `harbourAreas` | `navigation_area` harbour and marina polygons | Faint ink wash with a solid outline |
152
+ | `harbours` | `navigation_area` harbour points, and a symbol inside harbour polygons | Ink circle and name; the marina token for marinas |
153
+ | `facilities` | `navigation_area` facility points, polygons, and line centres, from zoom 13 | Hollow circle; facility icons from the theme |
154
+ | `notices` | `aid` notice boards, from zoom 12 | Circle in the board's function colour and `information` |
155
+ | `distanceMarks` | `aid` distance marks, from zoom 11 | Ink dot and distance with its unit, fainter if not posted |
156
+ | `ports` | `navigation_area` points of class `port` | Ink circle and name sized by `size`, from low zooms |
157
+ | `coverage` | `coverage` polygons that cover every family | Faint tint at low zooms only |
158
+ | `soundings` | `sounding` points | Depth figure |
159
+ | `labels` | Names inside polygons, bridge and overhead-cable clearances; coverage opt-in | Collision-aware text |
160
+
161
+ Bridge, berth, facility, and harbour polygons are drawn by their own groups rather than as
162
+ navigation areas. `labels.bridges` shows `clearance 4.5 m`, or `closed 3.6 m · open 12 m` for an
163
+ opening bridge, at bridge points, inside bridge polygons, and at the centre of bridge lines, from
164
+ zoom 13. `labels.overheadCables` shows `safe clearance 28.5 m`, or the plain clearance, at cable
165
+ points and along cable lines. Distance marks read `12 km`, `5 hm`, `300 m`, `12 mi`, or `4.5 NM`
166
+ from zoom 13. Notice boards follow the CEVNI colours: red for prohibitions, regulations, and
167
+ restrictions, green for recommendations, and blue for information; their `information`, such as a
168
+ speed limit, appears from zoom 14. Board orientation and impact are not drawn.
145
169
 
146
170
  Operational areas are restricted, military, anchorage, anchor-berth, dumping-ground, and
147
171
  traffic-separation areas. Marks keep their conventional colours in every theme; a white light is
@@ -173,6 +197,77 @@ export default defineMap({
173
197
  });
174
198
  ```
175
199
 
200
+ ## Flashing lights
201
+
202
+ In React, Vue, Svelte, and the development preview, every light with a rhythm flashes: its flare or
203
+ circle draws at its styled opacity while the light shines and at 15 % of it during an eclipse.
204
+ Fixed lights, lights without a usable characteristic, reduced motion, capture, native renderers, and
205
+ static images show every light steadily, exactly as it is styled. Set `animateLights: false` to keep
206
+ a map's lights steady everywhere:
207
+
208
+ <!-- docs:check -->
209
+
210
+ ```ts
211
+ import {defineMap, nautical} from '@tileflow/core';
212
+ import {streets} from '@tileflow/maps';
213
+
214
+ export default defineMap({
215
+ id: 'harbour-guide',
216
+ version: 1,
217
+ extends: streets,
218
+ marine: 'nautical',
219
+ modules: {nautical: nautical({animateLights: false})},
220
+ });
221
+ ```
222
+
223
+ A light flashes by its published `sequence` when it has one: light and eclipse durations in
224
+ seconds, eclipses in parentheses, for example `0.5+(1.5)+0.5+(4.5)`. Otherwise
225
+ `tileflowLightRhythm(properties)` derives a conventional rhythm from `character`, `group`, and
226
+ `period_s`; `tileflowLightRhythmConventions` holds the values below.
227
+
228
+ | Character | Rhythm |
229
+ | ------------------------------------- | ------------------------------------------------------------------------------------------------------ |
230
+ | `Fl` | Flashes of `min(1 s, 0.3 × period ÷ flashes)`; gaps within a group at most twice the flash |
231
+ | `Fl` with a group such as `2+1` | Groups separated by twice the inner gap; the rest of the period is the final eclipse |
232
+ | `LFl` | The same layout with 2 s flashes, shorter only when the period cannot hold them |
233
+ | `Q`, `VQ`, `UQ` | 60, 120, and 240 flashes a minute, lit for 30 % of each; a group of `n` flashes then eclipses |
234
+ | `IQ`, `IVQ`, `IUQ` | Quick flashes for 60 % of the period, then an eclipse |
235
+ | `Iso` | Equal light and eclipse |
236
+ | `Oc` | Eclipses totalling 25 % of the period, laid out like `Fl`, so the light is always longer |
237
+ | `Mo` | The Morse letter in `group`: 0.5 s dots, three-unit dashes, one-unit gaps, then the rest of the period |
238
+ | `FFl`, `F+LFl` | A fixed light at half intensity with full flashes, or long flashes |
239
+ | `Q+LFl`, `VQ+LFl`, `UQ+LFl`, `Fl+LFl` | The group (six quick flashes by default), one 2 s long flash, then the eclipse |
240
+ | `Oc+Fl` | Its occulting part |
241
+ | `Al.<character>`, `Al` | Each lit phase shows the next colour of `color`; `Al` alone shows each colour for an equal share |
242
+ | `F`, unknown, or missing period | Steady; grouped `Q` and `VQ` cardinal marks without a period use the IALA periods |
243
+
244
+ `tileflowLightStateAt(rhythm, seconds)` returns the intensity, colour index, and time to the next
245
+ change at any moment. Lights with the same rhythm flash together.
246
+
247
+ React, Vue, Svelte, the development preview, and standalone capture call
248
+ `attachTileflowNauticalLights(map)` from `@tileflow/core/browser`. It reads the light layers the
249
+ style declares in `metadata['tileflow:nautical-lights']`, and writes each rendered light's
250
+ `tileflowLightIntensity` and `tileflowLightColour` feature state only when its phase changes. It runs
251
+ one timer for the next change, and none while the page is hidden, while no light layer is visible at
252
+ the current zoom, or under reduced motion. A direct MapLibre integration attaches it after
253
+ constructing the map:
254
+
255
+ ```ts
256
+ import maplibregl from 'maplibre-gl';
257
+ import {attachTileflowNauticalLights, attachTileflowNotices} from '@tileflow/core/browser';
258
+
259
+ const map = new maplibregl.Map({
260
+ container: 'map',
261
+ style: '/tileflow/styles/harbour-guide/light.json',
262
+ });
263
+ attachTileflowNotices(map);
264
+ const detach = attachTileflowNauticalLights(map);
265
+ // Call detach() to return every light to steady; removing the map also detaches it.
266
+ ```
267
+
268
+ `steadyTileflowNauticalLights(style)` returns a copy that draws every light steadily without feature
269
+ state; native artifact preparation applies it automatically.
270
+
176
271
  ## Chart symbols from the theme
177
272
 
178
273
  A theme that declares the image tokens below replaces a point group's circle marker with that icon.
@@ -190,11 +285,24 @@ Buoy variants fall back to `nautical.buoy`. `tileflowNauticalImageRoles` lists t
190
285
  | `nautical.aid` | `aids` |
191
286
  | `nautical.wreck` | `wrecks` |
192
287
  | `nautical.harbour` | `harbours` |
288
+ | `nautical.marina` | Harbours whose `subclass` lists a marina |
193
289
  | `nautical.port` | `ports` |
290
+ | `nautical.notice` | `notices` |
291
+ | `nautical.notice.<role>` | Notices of that function |
292
+ | `nautical.distance-mark` | `distanceMarks` |
293
+ | `nautical.facility` | `facilities` |
294
+ | `nautical.facility.<cat>` | Facilities listing that category |
295
+
296
+ Notice roles are `prohibition`, `regulation`, `restriction`, `recommendation`, and `information`.
297
+ Facility categories are `fuel-station`, `slipway`, `boat-hoist`, `pump-out`, `water-tap`,
298
+ `visitor-berth` (also used for `visitors-mooring`), and `boatyard`: a facility listing several shows
299
+ the first in that order (`tileflowNauticalFacilityIcons`), and the others show `nautical.facility`.
300
+ Every icon expression selects among the declared image names only.
194
301
 
195
302
  Buoys, beacons, other aids, and lights colour their icon with the mark's own colour, so declare
196
303
  them as [SDF icons](https://github.com/tileflow/tileflow-sdk/blob/main/packages/dev/docs/native-icons.md)
197
304
  that share one representation within each group. The defaults size icons for the SDF profile,
198
- whose drawing occupies the central 12 of 24 pixels; set `icon.size` for other artwork. Soundings
199
- declares these tokens with its own buoy, light, lighthouse, wreck, and harbour symbols and keeps
305
+ whose drawing occupies the central 12 of 24 pixels; set `icon.size` for other artwork. Notice
306
+ boards take their function colour. Soundings declares these tokens with its own buoy, light,
307
+ lighthouse, wreck, harbour, marina, notice-board, distance-mark, and facility symbols and keeps
200
308
  beacons as coloured dots.
@@ -79,6 +79,7 @@ import {
79
79
  attachTileflowAtmosphere,
80
80
  attachTileflowFairUseNotice,
81
81
  attachTileflowMapLifecycle,
82
+ attachTileflowNauticalLights,
82
83
  attachTileflowNotices,
83
84
  createTileflowSessionStarter,
84
85
  createTileflowTransformRequest,
@@ -91,8 +92,8 @@ application can load them with a dynamic import when a style declares a 3D scene
91
92
  [3D buildings](buildings-3d.md#the-maps-3d-scene). The browser entry exports the same function.
92
93
 
93
94
  `attachTileflowNotices(map)` renders the notices a compiled style declares, such as Nautical's
94
- "Not for navigation", as a compact map control; see
95
- [Nautical marks](nautical-marks.md). The browser entry is not re-exported from the root. It is SSR-safe to import, has no MapLibre
95
+ "Not for navigation", as a compact map control, and `attachTileflowNauticalLights(map)` flashes
96
+ Nautical lights in their rhythm; see [Nautical marks](nautical-marks.md). The browser entry is not re-exported from the root. It is SSR-safe to import, has no MapLibre
96
97
  runtime dependency, and reads no browser global during module evaluation. See the
97
98
  [framework browser runtime contract](https://github.com/tileflow/tileflow-sdk/blob/main/docs/contracts/framework-browser-runtime.md) and the
98
99
  [cartographic authoring contract](https://github.com/tileflow/tileflow-sdk/blob/main/docs/contracts/cartographic-authoring.md). Exact field
@@ -0,0 +1,153 @@
1
+ # Street sky
2
+
3
+ A map's `sky` paints the sky above the horizon when the camera tilts up the street, in either
4
+ projection: blue by day, warm at dusk, dark with stars at night. Install `@tileflow/core` and
5
+ `@tileflow/maps` and use a browser adapter from the same compatible SDK release. Streets declares a
6
+ sky in every theme; the example extends it and keeps its sky.
7
+
8
+ <!-- docs:check -->
9
+
10
+ ```ts
11
+ import {defineMap} from '@tileflow/core';
12
+ import {streets} from '@tileflow/maps';
13
+
14
+ export default defineMap({
15
+ id: 'street-level',
16
+ version: 1,
17
+ extends: streets,
18
+ view: {center: [-3.6904, 40.4493], zoom: 17, bearing: 8, pitch: 80},
19
+ });
20
+ ```
21
+
22
+ The view looks north along Paseo de la Castellana in Madrid, with the sky above the skyline.
23
+ Coordinates are longitude, then latitude.
24
+
25
+ ## Camera pitch
26
+
27
+ React, Vue, Svelte, the Dev preview, and browser capture create maps with a maximum pitch of 85
28
+ degrees, `tileflowMaxPitch`, instead of MapLibre's default of 60. Every portable view already admits
29
+ pitch 0–85. Pass `mapOptions: {maxPitch}` to lower the limit for one map. A map constructed directly
30
+ with MapLibre keeps MapLibre's default unless it sets `maxPitch: tileflowMaxPitch` itself.
31
+
32
+ The React Native surface still uses the native engines' 60-degree limit.
33
+
34
+ ## Configure the sky
35
+
36
+ `sky: true` uses the defaults. An options object replaces an inherited sky atomically, and
37
+ `sky: false` removes it.
38
+
39
+ | Option | Default | Meaning |
40
+ | --------------- | --------- | ----------------------------------------------------------------- |
41
+ | `color` | `#5c9ce6` | The sky overhead |
42
+ | `horizonColor` | `#dcebf7` | The pale band along the horizon, also 3D terrain's distance fog |
43
+ | `horizonBlend` | `0.6` | How far up the band reaches, as a share of half the view's height |
44
+ | `glowColor` | `#ffc68a` | The light round a low sun, which glows on the horizon towards it |
45
+ | `starIntensity` | `0.6` | The brightest the stars shine, from 0 (none) to 1 |
46
+
47
+ Colors take `token.color(...)`, color operations, or `fixed(color, {reason})`, and must resolve to
48
+ opaque colors. Numbers take `token.number(...)`, `fixed(number, {reason})`, or a number, and must
49
+ resolve to 0–1. Unknown properties are rejected. Because tokens resolve per theme, one declaration
50
+ gives each theme its own sky. Streets uses its themes' `sky.color`, `sky.horizon`,
51
+ `sky.horizonBlend`, and `sky.glow` tokens:
52
+
53
+ ```ts
54
+ sky: {
55
+ color: token.color('sky.color'),
56
+ horizonColor: token.color('sky.horizon'),
57
+ horizonBlend: token.number('sky.horizonBlend'),
58
+ glowColor: token.color('sky.glow'),
59
+ starIntensity: 0.6,
60
+ },
61
+ ```
62
+
63
+ A map that replaces Streets' themes supplies those tokens or declares its own `sky`.
64
+
65
+ ## A sky that follows the sun
66
+
67
+ When an application places the sun with the theme controller's `setSun`, by direction or by the
68
+ real sun of a date and place, the sky follows its height continuously instead of staying on the
69
+ theme's preset. Above about 14 degrees the sky is the day theme's; it warms into the dawn or dusk
70
+ theme's sky as the sun nears the horizon, using dawn while the sun stands in the eastern half of
71
+ the sky and dusk in the western half; it holds that sky within two degrees of sunrise or sunset,
72
+ and it darkens into the night theme's sky as twilight ends, about ten degrees below the horizon.
73
+ The themes come from the map's `timeOfDay` family of the theme on screen, and every colour is
74
+ resolved from that theme's own tokens, so a Monochrome family stays grey and a client's own
75
+ family keeps its palette. A family with only one twilight uses it at both ends of the day; a theme
76
+ outside a family, or a family without a day and a night theme, keeps its own sky.
77
+ `setSun(undefined)` returns the sky to the themes. The map's colours on the ground stay those of
78
+ the theme or blend on screen; pair `setSun` with `setBlend` to move them too. See
79
+ [sun and light](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/docs/sun-and-light.md).
80
+
81
+ <!-- docs:check -->
82
+
83
+ ```ts
84
+ import type {TileflowThemeController} from '@tileflow/core/browser';
85
+
86
+ export function sunsetOverMadrid(controller: TileflowThemeController) {
87
+ // 19:15 in Madrid on 21 October 2026: the sun stands 1.5 degrees above the western horizon.
88
+ return controller.setSun({date: Date.UTC(2026, 9, 21, 17, 15), location: [-3.69, 40.45]});
89
+ }
90
+ ```
91
+
92
+ ## Glow, sun and stars
93
+
94
+ A low sun glows on the horizon towards it, in the theme's `glowColor` or, for a sun an application
95
+ placed, in the glow of its hour. The glow is strongest as the sun touches the horizon, fades by
96
+ mid-morning, and is gone once the sun is about nine degrees below. While the sun is low and above
97
+ the horizon, its disc shows too. The sun is the one the theme controller shows, so its
98
+ disc stands where the 3D scene's shadows say it is; without a controller, the theme's own sun.
99
+
100
+ Stars come out as the sky darkens: a night sky shows them, a day or dusk sky does not, and a
101
+ time-of-day blend or a placed sun moving into night brings them in with the dark. They sit on a
102
+ fixed dome, so they turn with the camera's bearing and pitch but not with its position.
103
+
104
+ The glow, the sun, and the stars draw beneath every map layer and only where nothing else has
105
+ drawn, so buildings and trees stand in front of them. With 3D terrain enabled, they are not
106
+ drawn.
107
+
108
+ ## Distance haze
109
+
110
+ Above 45 degrees of pitch, the far city fades into the sky's horizon color, so streets meet the sky
111
+ instead of ending in a sharp edge. The haze starts at the camera's distance to the map's center and
112
+ is complete where MapLibre stops drawing the ground, about 6.7 times farther, where the sky starts in
113
+ the same color. It comes in between 45 and 60 degrees, follows the current sky (theme blends
114
+ and a sky that follows the sun included), and leaves the globe alone. Place and POI labels above the
115
+ 3D layers stay clear.
116
+
117
+ Tileflow's 3D buildings stand on the tiles round the camera, up to a limit of 25 by default, which
118
+ end well before the horizon. Where that ring ends nearer than the horizon, the haze fits itself to
119
+ it: it is nine-tenths complete at the nearest point where the ring's far side shows across the view,
120
+ and complete soon after, never nearer than three camera distances for the nine-tenths, so a renderer
121
+ held to few tiles does not pull the haze in. Buildings on the ring's far side sink into the ground
122
+ over its last fifth, and nothing past the ring or past the complete haze is drawn. Buildings on the
123
+ near side of a ring held short by the tile limit keep standing.
124
+
125
+ The haze is drawn twice, from one model: Tileflow's 3D buildings, trees, and placed models haze
126
+ each pixel by its depth, and a band over the flat map, just under the first 3D layer, hazes the
127
+ flat ground by the depth its screen row has. Road names and one-way arrows that a style draws on the
128
+ ground before its 3D layers fade with the ground, and so do distant 3D shadows, contact shade, and
129
+ night floodlight. A style without a sky, or whose sky has no opaque horizon color, has no haze.
130
+
131
+ ## Browser integration
132
+
133
+ The compiler emits MapLibre `sky` in every concrete style and versioned `metadata['tileflow:sky']`
134
+ with the star brightness, the glow, and, for a theme in a time-of-day family, the family's skies;
135
+ `readTileflowSky` reads it and `tileflowSkyAtSun` mixes the sky of a sun's height. MapLibre draws the sky itself, so raw MapLibre consumers see it. On a
136
+ globe, the sky blends into MapLibre's atmosphere at world zooms; when a map also declares
137
+ `atmosphere`, the sky's colors replace the atmosphere's sky colors while its space background and
138
+ globe stars stay.
139
+
140
+ React, Vue, Svelte, and standalone browser capture draw the glow, the sun, the stars, and the flat
141
+ map's haze through `attachTileflowAtmosphere(map)`. A direct MapLibre integration calls that
142
+ function, or `attachTileflowSky(map)` or `attachTileflowSkyHaze(map)` from `@tileflow/core/browser`
143
+ for one of them alone, after constructing the map; each returns a cleanup function. The sky is the
144
+ custom layer `tileflow-sky` at the bottom of the layer stack, and the haze the custom layer
145
+ `tileflow-sky-haze` under the first 3D layer, or the first label layer without one. Tileflow's 3D
146
+ layers haze themselves. A sky that follows the sun needs the theme controller, which writes the
147
+ sky's colours; raw MapLibre consumers see each theme's own sky.
148
+
149
+ MapLibre applies its own fog only to 3D terrain; with 3D terrain enabled, the flat haze band is not
150
+ drawn and the terrain's fog takes its place. Other layers drawn by an application, such as
151
+ `fill-extrusion` layers, stay sharp. Native artifacts remove the sky during preparation and record
152
+ the removal; see the
153
+ [native artifact profile](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/docs/native-artifact-profile.md).
@@ -106,8 +106,10 @@ custom layer draws; the map redraws whenever the sun changes.
106
106
 
107
107
  `setSun` places the sun by direction, or by the real sun of a date over a place given as
108
108
  `[longitude, latitude]`, the map's centre when it is left out. The themes keep the sun's colours,
109
- strengths and shadow strength; only its direction changes. `setSun(undefined)` returns it to the
110
- themes. This example assumes an existing MapLibre map and a controller for it:
109
+ strengths and shadow strength; only its direction changes. A map with a
110
+ [street sky](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/docs/street-sky.md)
111
+ also takes the sky of the sun's hour from its time-of-day themes. `setSun(undefined)` returns both
112
+ to the themes. This example assumes an existing MapLibre map and a controller for it:
111
113
 
112
114
  <!-- docs:check -->
113
115
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tileflow/core",
3
- "version": "0.1.0-alpha.38",
3
+ "version": "0.1.0-alpha.39",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Typed Tileflow config and MapLibre style compiler.",
6
6
  "type": "module",