@react-x11/components 0.4.0 → 0.5.0
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 +125 -4
- package/dist/charts/components.d.ts +3 -1
- package/dist/charts/components.d.ts.map +1 -1
- package/dist/charts/components.js +8 -4
- package/dist/charts/components.js.map +1 -1
- package/dist/charts/node.d.ts +13 -6
- package/dist/charts/node.d.ts.map +1 -1
- package/dist/charts/node.js +75 -24
- package/dist/charts/node.js.map +1 -1
- package/dist/charts/render.d.ts +4 -0
- package/dist/charts/render.d.ts.map +1 -1
- package/dist/charts/render.js +11 -6
- package/dist/charts/render.js.map +1 -1
- package/dist/code-editor/node.d.ts +47 -16
- package/dist/code-editor/node.d.ts.map +1 -1
- package/dist/code-editor/node.js +121 -51
- package/dist/code-editor/node.js.map +1 -1
- package/dist/flow/draw.d.ts +19 -1
- package/dist/flow/draw.d.ts.map +1 -1
- package/dist/flow/draw.js +64 -35
- package/dist/flow/draw.js.map +1 -1
- package/dist/flow/index.d.ts.map +1 -1
- package/dist/flow/index.js +24 -8
- package/dist/flow/index.js.map +1 -1
- package/dist/flow/model.d.ts +4 -2
- package/dist/flow/model.d.ts.map +1 -1
- package/dist/flow/model.js +4 -2
- package/dist/flow/model.js.map +1 -1
- package/dist/flow/node.d.ts +40 -9
- package/dist/flow/node.d.ts.map +1 -1
- package/dist/flow/node.js +142 -53
- package/dist/flow/node.js.map +1 -1
- package/dist/flow/types.d.ts +46 -21
- package/dist/flow/types.d.ts.map +1 -1
- package/dist/formula/index.d.ts +4 -2
- package/dist/formula/index.d.ts.map +1 -1
- package/dist/formula/index.js.map +1 -1
- package/dist/formula/node.d.ts +5 -1
- package/dist/formula/node.d.ts.map +1 -1
- package/dist/formula/node.js +19 -3
- package/dist/formula/node.js.map +1 -1
- package/dist/html/controls.d.ts +4 -1
- package/dist/html/controls.d.ts.map +1 -1
- package/dist/html/controls.js.map +1 -1
- package/dist/html/css/cascade.d.ts +11 -5
- package/dist/html/css/cascade.d.ts.map +1 -1
- package/dist/html/css/cascade.js +18 -8
- package/dist/html/css/cascade.js.map +1 -1
- package/dist/html/css/parse.d.ts +15 -10
- package/dist/html/css/parse.d.ts.map +1 -1
- package/dist/html/css/parse.js +41 -16
- package/dist/html/css/parse.js.map +1 -1
- package/dist/html/css/style.d.ts +3 -0
- package/dist/html/css/style.d.ts.map +1 -1
- package/dist/html/css/style.js +3 -1
- package/dist/html/css/style.js.map +1 -1
- package/dist/html/css/values.d.ts +14 -1
- package/dist/html/css/values.d.ts.map +1 -1
- package/dist/html/css/values.js +11 -8
- package/dist/html/css/values.js.map +1 -1
- package/dist/html/index.d.ts.map +1 -1
- package/dist/html/index.js +1 -0
- package/dist/html/index.js.map +1 -1
- package/dist/html/layout/boxes.d.ts +12 -5
- package/dist/html/layout/boxes.d.ts.map +1 -1
- package/dist/html/layout/boxes.js +7 -4
- package/dist/html/layout/boxes.js.map +1 -1
- package/dist/html/layout/inline.d.ts.map +1 -1
- package/dist/html/layout/inline.js +22 -1
- package/dist/html/layout/inline.js.map +1 -1
- package/dist/html/node.d.ts +22 -8
- package/dist/html/node.d.ts.map +1 -1
- package/dist/html/node.js +97 -15
- package/dist/html/node.js.map +1 -1
- package/dist/html/paint.d.ts +3 -0
- package/dist/html/paint.d.ts.map +1 -1
- package/dist/html/paint.js +2 -2
- package/dist/html/paint.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -1
- package/dist/maps/clip.d.ts +43 -0
- package/dist/maps/clip.d.ts.map +1 -0
- package/dist/maps/clip.js +171 -0
- package/dist/maps/clip.js.map +1 -0
- package/dist/maps/gzip.d.ts +15 -0
- package/dist/maps/gzip.d.ts.map +1 -0
- package/dist/maps/gzip.js +56 -0
- package/dist/maps/gzip.js.map +1 -0
- package/dist/maps/index.d.ts +55 -0
- package/dist/maps/index.d.ts.map +1 -0
- package/dist/maps/index.js +141 -0
- package/dist/maps/index.js.map +1 -0
- package/dist/maps/labels.d.ts +123 -0
- package/dist/maps/labels.d.ts.map +1 -0
- package/dist/maps/labels.js +323 -0
- package/dist/maps/labels.js.map +1 -0
- package/dist/maps/mvt.d.ts +244 -0
- package/dist/maps/mvt.d.ts.map +1 -0
- package/dist/maps/mvt.js +820 -0
- package/dist/maps/mvt.js.map +1 -0
- package/dist/maps/node.d.ts +278 -0
- package/dist/maps/node.d.ts.map +1 -0
- package/dist/maps/node.js +1459 -0
- package/dist/maps/node.js.map +1 -0
- package/dist/maps/overlay.d.ts +157 -0
- package/dist/maps/overlay.d.ts.map +1 -0
- package/dist/maps/overlay.js +472 -0
- package/dist/maps/overlay.js.map +1 -0
- package/dist/maps/paint.d.ts +226 -0
- package/dist/maps/paint.d.ts.map +1 -0
- package/dist/maps/paint.js +705 -0
- package/dist/maps/paint.js.map +1 -0
- package/dist/maps/proj.d.ts +281 -0
- package/dist/maps/proj.d.ts.map +1 -0
- package/dist/maps/proj.js +451 -0
- package/dist/maps/proj.js.map +1 -0
- package/dist/maps/sources.d.ts +256 -0
- package/dist/maps/sources.d.ts.map +1 -0
- package/dist/maps/sources.js +210 -0
- package/dist/maps/sources.js.map +1 -0
- package/dist/maps/style.d.ts +141 -0
- package/dist/maps/style.d.ts.map +1 -0
- package/dist/maps/style.js +147 -0
- package/dist/maps/style.js.map +1 -0
- package/dist/maps/styles.d.ts +82 -0
- package/dist/maps/styles.d.ts.map +1 -0
- package/dist/maps/styles.js +898 -0
- package/dist/maps/styles.js.map +1 -0
- package/dist/maps/tiles.d.ts +283 -0
- package/dist/maps/tiles.d.ts.map +1 -0
- package/dist/maps/tiles.js +469 -0
- package/dist/maps/tiles.js.map +1 -0
- package/dist/maps/types.d.ts +244 -0
- package/dist/maps/types.d.ts.map +1 -0
- package/dist/maps/types.js +2 -0
- package/dist/maps/types.js.map +1 -0
- package/dist/reorder/hx.d.ts +18 -0
- package/dist/reorder/hx.d.ts.map +1 -0
- package/dist/reorder/hx.js +10 -0
- package/dist/reorder/hx.js.map +1 -0
- package/dist/reorder/index.d.ts +314 -0
- package/dist/reorder/index.d.ts.map +1 -0
- package/dist/reorder/index.js +1539 -0
- package/dist/reorder/index.js.map +1 -0
- package/dist/reorder/model.d.ts +107 -0
- package/dist/reorder/model.d.ts.map +1 -0
- package/dist/reorder/model.js +162 -0
- package/dist/reorder/model.js.map +1 -0
- package/dist/richtext/node.d.ts +15 -5
- package/dist/richtext/node.d.ts.map +1 -1
- package/dist/richtext/node.js +40 -11
- package/dist/richtext/node.js.map +1 -1
- package/dist/richtext/runs.d.ts +35 -13
- package/dist/richtext/runs.d.ts.map +1 -1
- package/dist/richtext/runs.js +83 -27
- package/dist/richtext/runs.js.map +1 -1
- package/dist/tabs/index.d.ts +17 -0
- package/dist/tabs/index.d.ts.map +1 -1
- package/dist/tabs/index.js +849 -186
- package/dist/tabs/index.js.map +1 -1
- package/dist/terminal/vt/fonts.d.ts +45 -15
- package/dist/terminal/vt/fonts.d.ts.map +1 -1
- package/dist/terminal/vt/fonts.js +89 -19
- package/dist/terminal/vt/fonts.js.map +1 -1
- package/dist/terminal/vt/node.d.ts +42 -0
- package/dist/terminal/vt/node.d.ts.map +1 -1
- package/dist/terminal/vt/node.js +95 -11
- package/dist/terminal/vt/node.js.map +1 -1
- package/dist/terminal/vt/renderer.d.ts.map +1 -1
- package/dist/terminal/vt/renderer.js +13 -3
- package/dist/terminal/vt/renderer.js.map +1 -1
- package/package.json +13 -3
- package/src/charts/components.ts +14 -7
- package/src/charts/node.ts +81 -26
- package/src/charts/render.ts +16 -6
- package/src/code-editor/node.ts +147 -53
- package/src/flow/draw.ts +104 -35
- package/src/flow/index.ts +33 -13
- package/src/flow/model.ts +4 -2
- package/src/flow/node.ts +158 -59
- package/src/flow/types.ts +46 -21
- package/src/formula/index.ts +4 -2
- package/src/formula/node.ts +24 -5
- package/src/html/controls.ts +4 -1
- package/src/html/css/cascade.ts +18 -7
- package/src/html/css/parse.ts +46 -21
- package/src/html/css/style.ts +6 -1
- package/src/html/css/values.ts +25 -9
- package/src/html/index.ts +1 -0
- package/src/html/layout/boxes.ts +19 -9
- package/src/html/layout/inline.ts +23 -1
- package/src/html/node.ts +110 -17
- package/src/html/paint.ts +17 -2
- package/src/index.ts +98 -0
- package/src/maps/clip.ts +184 -0
- package/src/maps/gzip.ts +66 -0
- package/src/maps/index.ts +316 -0
- package/src/maps/labels.ts +442 -0
- package/src/maps/mvt.ts +857 -0
- package/src/maps/node.ts +1819 -0
- package/src/maps/overlay.ts +639 -0
- package/src/maps/paint.ts +978 -0
- package/src/maps/proj.ts +641 -0
- package/src/maps/sources.ts +425 -0
- package/src/maps/style.ts +309 -0
- package/src/maps/styles.ts +1040 -0
- package/src/maps/tiles.ts +676 -0
- package/src/maps/types.ts +260 -0
- package/src/reorder/hx.ts +31 -0
- package/src/reorder/index.ts +2223 -0
- package/src/reorder/model.ts +232 -0
- package/src/richtext/node.ts +49 -14
- package/src/richtext/runs.ts +115 -30
- package/src/tabs/index.ts +1040 -204
- package/src/terminal/vt/fonts.ts +128 -36
- package/src/terminal/vt/node.ts +105 -12
- package/src/terminal/vt/renderer.ts +13 -3
|
@@ -0,0 +1,1040 @@
|
|
|
1
|
+
// A default style, so that `<Map>` with a source and nothing else looks
|
|
2
|
+
// like a map.
|
|
3
|
+
//
|
|
4
|
+
// Written against **Shortbread 1.1**, the schema OpenStreetMap's own vector
|
|
5
|
+
// tiles are cut in (`vector.openstreetmap.org`) — chosen because it is the
|
|
6
|
+
// one open schema with an open, keyless, canonical server behind it, which
|
|
7
|
+
// is what makes `<Map source={osmVectorSource()} />` a line that works.
|
|
8
|
+
//
|
|
9
|
+
// The cartography is deliberately close to a familiar one (OSM Carto's
|
|
10
|
+
// hues for the light palette, a desaturated dark counterpart), because a
|
|
11
|
+
// map that looks unlike every other map reads as broken rather than as
|
|
12
|
+
// styled. Both palettes are here rather than derived from the theme: a
|
|
13
|
+
// map's colours are a *scheme* — water against land against parkland
|
|
14
|
+
// against six classes of road — and interpolating that out of an
|
|
15
|
+
// application's accent colour produces mud. What the theme does decide is
|
|
16
|
+
// which of the two is used, and the ink and halo of the labels, so labels
|
|
17
|
+
// on a map agree with text beside it.
|
|
18
|
+
//
|
|
19
|
+
// Every layer's `id` is stable, because that is what an application filters
|
|
20
|
+
// on to hide one (`style.layers.filter((l) => l.id !== 'buildings')`) and
|
|
21
|
+
// what a `<Map>` event names.
|
|
22
|
+
import type { MapStyle, MapStyleLayer, Zoomed } from './style.js';
|
|
23
|
+
|
|
24
|
+
/** The tags Shortbread puts a road's class in, grouped as a style wants
|
|
25
|
+
* them rather than as the schema lists them. */
|
|
26
|
+
const MOTORWAY = ['motorway'] as const;
|
|
27
|
+
const TRUNK = ['trunk'] as const;
|
|
28
|
+
const PRIMARY = ['primary'] as const;
|
|
29
|
+
const SECONDARY = ['secondary'] as const;
|
|
30
|
+
const TERTIARY = ['tertiary'] as const;
|
|
31
|
+
const MINOR = [
|
|
32
|
+
'unclassified',
|
|
33
|
+
'residential',
|
|
34
|
+
'living_street',
|
|
35
|
+
'pedestrian',
|
|
36
|
+
'busway',
|
|
37
|
+
] as const;
|
|
38
|
+
const SERVICE = ['service', 'track', 'ford'] as const;
|
|
39
|
+
const PATH = ['path', 'footway', 'cycleway', 'steps', 'bridleway'] as const;
|
|
40
|
+
const RAIL = [
|
|
41
|
+
'rail',
|
|
42
|
+
'narrow_gauge',
|
|
43
|
+
'light_rail',
|
|
44
|
+
'subway',
|
|
45
|
+
'tram',
|
|
46
|
+
'monorail',
|
|
47
|
+
'funicular',
|
|
48
|
+
] as const;
|
|
49
|
+
|
|
50
|
+
/** Landuse kinds that read as green space. */
|
|
51
|
+
const GREEN = [
|
|
52
|
+
'park',
|
|
53
|
+
'garden',
|
|
54
|
+
'grass',
|
|
55
|
+
'meadow',
|
|
56
|
+
'forest',
|
|
57
|
+
'wood',
|
|
58
|
+
'scrub',
|
|
59
|
+
'heath',
|
|
60
|
+
'orchard',
|
|
61
|
+
'vineyard',
|
|
62
|
+
'village_green',
|
|
63
|
+
'recreation_ground',
|
|
64
|
+
'golf_course',
|
|
65
|
+
'cemetery',
|
|
66
|
+
'allotments',
|
|
67
|
+
'farmland',
|
|
68
|
+
'farmyard',
|
|
69
|
+
] as const;
|
|
70
|
+
|
|
71
|
+
/** …and the ones that read as built-up. */
|
|
72
|
+
const BUILT = [
|
|
73
|
+
'residential',
|
|
74
|
+
'commercial',
|
|
75
|
+
'retail',
|
|
76
|
+
'industrial',
|
|
77
|
+
'brownfield',
|
|
78
|
+
'greenfield',
|
|
79
|
+
'railway',
|
|
80
|
+
'garages',
|
|
81
|
+
'quarry',
|
|
82
|
+
'construction',
|
|
83
|
+
'landfill',
|
|
84
|
+
] as const;
|
|
85
|
+
|
|
86
|
+
/** One palette. Every colour a {@link shortbreadStyle} layer uses comes
|
|
87
|
+
* from here, so a third palette is a literal rather than a fork. */
|
|
88
|
+
export interface MapPalette {
|
|
89
|
+
land: string;
|
|
90
|
+
ocean: string;
|
|
91
|
+
water: string;
|
|
92
|
+
green: string;
|
|
93
|
+
built: string;
|
|
94
|
+
site: string;
|
|
95
|
+
building: string;
|
|
96
|
+
buildingEdge: string;
|
|
97
|
+
motorway: string;
|
|
98
|
+
motorwayCasing: string;
|
|
99
|
+
trunk: string;
|
|
100
|
+
primary: string;
|
|
101
|
+
secondary: string;
|
|
102
|
+
minor: string;
|
|
103
|
+
minorCasing: string;
|
|
104
|
+
path: string;
|
|
105
|
+
rail: string;
|
|
106
|
+
boundary: string;
|
|
107
|
+
pier: string;
|
|
108
|
+
text: string;
|
|
109
|
+
textMinor: string;
|
|
110
|
+
halo: string;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** OSM Carto's hues, near enough that a user's eye reads the map as the one
|
|
114
|
+
* they already know. */
|
|
115
|
+
export const LIGHT_PALETTE: MapPalette = {
|
|
116
|
+
land: '#f2efe9',
|
|
117
|
+
ocean: '#aad3df',
|
|
118
|
+
water: '#aad3df',
|
|
119
|
+
green: '#cfe8b4',
|
|
120
|
+
built: '#e8e2dc',
|
|
121
|
+
site: '#f0e7db',
|
|
122
|
+
building: '#dfd7cd',
|
|
123
|
+
buildingEdge: '#cec4b8',
|
|
124
|
+
motorway: '#f9b29c',
|
|
125
|
+
motorwayCasing: '#d97f63',
|
|
126
|
+
trunk: '#fcd6a4',
|
|
127
|
+
primary: '#fcd6a4',
|
|
128
|
+
secondary: '#f7fabf',
|
|
129
|
+
minor: '#ffffff',
|
|
130
|
+
minorCasing: '#cfcdca',
|
|
131
|
+
path: '#d4b8a8',
|
|
132
|
+
rail: '#b0aeab',
|
|
133
|
+
boundary: '#a4a1ae',
|
|
134
|
+
pier: '#f2efe9',
|
|
135
|
+
text: '#33322e',
|
|
136
|
+
textMinor: '#6b6862',
|
|
137
|
+
halo: 'rgba(255,255,255,0.85)',
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
/** The dark counterpart. Desaturated rather than inverted: an inverted map
|
|
141
|
+
* puts white water under dark land, which reads as a negative. */
|
|
142
|
+
export const DARK_PALETTE: MapPalette = {
|
|
143
|
+
land: '#191b1f',
|
|
144
|
+
ocean: '#0f1c28',
|
|
145
|
+
water: '#12222f',
|
|
146
|
+
green: '#1a2620',
|
|
147
|
+
built: '#1f2126',
|
|
148
|
+
site: '#20232a',
|
|
149
|
+
building: '#23262c',
|
|
150
|
+
buildingEdge: '#2b2f36',
|
|
151
|
+
motorway: '#5d4b38',
|
|
152
|
+
motorwayCasing: '#7a6244',
|
|
153
|
+
trunk: '#4c4232',
|
|
154
|
+
primary: '#43403a',
|
|
155
|
+
secondary: '#3b3a35',
|
|
156
|
+
minor: '#33363c',
|
|
157
|
+
minorCasing: '#22242a',
|
|
158
|
+
path: '#3a352f',
|
|
159
|
+
rail: '#33363c',
|
|
160
|
+
boundary: '#4a4757',
|
|
161
|
+
pier: '#22252b',
|
|
162
|
+
text: '#d3d7de',
|
|
163
|
+
textMinor: '#9299a3',
|
|
164
|
+
halo: 'rgba(12,14,18,0.85)',
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
/** How wide a road class is, at each zoom. */
|
|
168
|
+
function width(stops: readonly (readonly [number, number])[]): Zoomed<number> {
|
|
169
|
+
return { stops };
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export interface ShortbreadStyleOptions {
|
|
173
|
+
/** `false` (the default) for the light palette. */
|
|
174
|
+
dark?: boolean;
|
|
175
|
+
/** Swap individual colours without forking the layer list. */
|
|
176
|
+
palette?: Partial<MapPalette>;
|
|
177
|
+
/**
|
|
178
|
+
* Which name tag labels read.
|
|
179
|
+
*
|
|
180
|
+
* Shortbread carries `name` (the local name) plus `name_<lang>` for the
|
|
181
|
+
* languages a feature has one in. `'name'` is the honest default —
|
|
182
|
+
* Tokyo's streets are labelled in Japanese on a Japanese map — and an
|
|
183
|
+
* application that knows its user's locale passes `name_en`, `name_de`
|
|
184
|
+
* and so on. A missing translation falls back to `name`.
|
|
185
|
+
*/
|
|
186
|
+
nameField?: string;
|
|
187
|
+
/** Leave the label layers out — for a map an application labels itself,
|
|
188
|
+
* or a background under a heavy data overlay. */
|
|
189
|
+
labels?: boolean;
|
|
190
|
+
/** Leave building footprints out. They are the densest polygon layer at
|
|
191
|
+
* high zoom and the first thing to drop on a slow machine. */
|
|
192
|
+
buildings?: boolean;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* The default style for Shortbread tiles.
|
|
197
|
+
*
|
|
198
|
+
* Twenty-six layers, in paint order. The order is the cartography: sea,
|
|
199
|
+
* then landuse, then water, then sites and buildings, then road *casings*
|
|
200
|
+
* as one pass and road *fills* as another — which is what makes a junction
|
|
201
|
+
* look like a junction rather than two roads crossing — then rail,
|
|
202
|
+
* boundaries, and labels last.
|
|
203
|
+
*/
|
|
204
|
+
export function shortbreadStyle(
|
|
205
|
+
options: ShortbreadStyleOptions = {},
|
|
206
|
+
): MapStyle {
|
|
207
|
+
const p: MapPalette = {
|
|
208
|
+
...(options.dark ? DARK_PALETTE : LIGHT_PALETTE),
|
|
209
|
+
...options.palette,
|
|
210
|
+
};
|
|
211
|
+
const name = options.nameField ?? 'name';
|
|
212
|
+
const layers: MapStyleLayer[] = [
|
|
213
|
+
{ id: 'ocean', type: 'fill', sourceLayer: 'ocean', color: p.ocean },
|
|
214
|
+
{
|
|
215
|
+
id: 'landuse-green',
|
|
216
|
+
type: 'fill',
|
|
217
|
+
sourceLayer: 'land',
|
|
218
|
+
filter: ['in', 'kind', ...GREEN],
|
|
219
|
+
color: p.green,
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
id: 'landuse-built',
|
|
223
|
+
type: 'fill',
|
|
224
|
+
sourceLayer: 'land',
|
|
225
|
+
filter: ['in', 'kind', ...BUILT],
|
|
226
|
+
color: p.built,
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
id: 'sites',
|
|
230
|
+
type: 'fill',
|
|
231
|
+
sourceLayer: 'sites',
|
|
232
|
+
color: p.site,
|
|
233
|
+
minZoom: 13,
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
id: 'water-polygons',
|
|
237
|
+
type: 'fill',
|
|
238
|
+
sourceLayer: 'water_polygons',
|
|
239
|
+
color: p.water,
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
id: 'water-lines',
|
|
243
|
+
type: 'line',
|
|
244
|
+
sourceLayer: 'water_lines',
|
|
245
|
+
color: p.water,
|
|
246
|
+
width: width([
|
|
247
|
+
[6, 0.5],
|
|
248
|
+
[10, 1.2],
|
|
249
|
+
[14, 3],
|
|
250
|
+
[18, 8],
|
|
251
|
+
]),
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
id: 'dams',
|
|
255
|
+
type: 'fill',
|
|
256
|
+
sourceLayer: 'dam_polygons',
|
|
257
|
+
color: p.built,
|
|
258
|
+
minZoom: 13,
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
id: 'piers',
|
|
262
|
+
type: 'fill',
|
|
263
|
+
sourceLayer: 'pier_polygons',
|
|
264
|
+
color: p.pier,
|
|
265
|
+
minZoom: 13,
|
|
266
|
+
},
|
|
267
|
+
];
|
|
268
|
+
|
|
269
|
+
if (options.buildings !== false) {
|
|
270
|
+
layers.push({
|
|
271
|
+
id: 'buildings',
|
|
272
|
+
type: 'fill',
|
|
273
|
+
sourceLayer: 'buildings',
|
|
274
|
+
minZoom: 14,
|
|
275
|
+
color: p.building,
|
|
276
|
+
// The edge only once a footprint is big enough for it to be an edge
|
|
277
|
+
// rather than a darkening of the whole polygon.
|
|
278
|
+
outlineColor: p.buildingEdge,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Casings first, every class in one pass, so that the fills above them
|
|
283
|
+
// knit together at every junction. This is the one thing that separates a
|
|
284
|
+
// road network from a pile of coloured lines.
|
|
285
|
+
const roadClasses: {
|
|
286
|
+
id: string;
|
|
287
|
+
kinds: readonly string[];
|
|
288
|
+
fill: string;
|
|
289
|
+
casing: string;
|
|
290
|
+
fillWidth: Zoomed<number>;
|
|
291
|
+
minZoom?: number;
|
|
292
|
+
}[] = [
|
|
293
|
+
{
|
|
294
|
+
id: 'motorway',
|
|
295
|
+
kinds: MOTORWAY,
|
|
296
|
+
fill: p.motorway,
|
|
297
|
+
casing: p.motorwayCasing,
|
|
298
|
+
fillWidth: width([
|
|
299
|
+
[5, 0.6],
|
|
300
|
+
[8, 1.4],
|
|
301
|
+
[10, 2.4],
|
|
302
|
+
[13, 5],
|
|
303
|
+
[16, 12],
|
|
304
|
+
[20, 40],
|
|
305
|
+
]),
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
id: 'trunk',
|
|
309
|
+
kinds: TRUNK,
|
|
310
|
+
fill: p.trunk,
|
|
311
|
+
casing: p.motorwayCasing,
|
|
312
|
+
fillWidth: width([
|
|
313
|
+
[6, 0.5],
|
|
314
|
+
[9, 1.2],
|
|
315
|
+
[12, 2.6],
|
|
316
|
+
[16, 9],
|
|
317
|
+
[20, 30],
|
|
318
|
+
]),
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
id: 'primary',
|
|
322
|
+
kinds: PRIMARY,
|
|
323
|
+
fill: p.primary,
|
|
324
|
+
casing: p.minorCasing,
|
|
325
|
+
fillWidth: width([
|
|
326
|
+
[7, 0.5],
|
|
327
|
+
[10, 1.3],
|
|
328
|
+
[13, 3],
|
|
329
|
+
[16, 8],
|
|
330
|
+
[20, 26],
|
|
331
|
+
]),
|
|
332
|
+
minZoom: 7,
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
id: 'secondary',
|
|
336
|
+
kinds: SECONDARY,
|
|
337
|
+
fill: p.secondary,
|
|
338
|
+
casing: p.minorCasing,
|
|
339
|
+
fillWidth: width([
|
|
340
|
+
[9, 0.5],
|
|
341
|
+
[12, 1.6],
|
|
342
|
+
[15, 5],
|
|
343
|
+
[20, 20],
|
|
344
|
+
]),
|
|
345
|
+
minZoom: 9,
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
id: 'tertiary',
|
|
349
|
+
kinds: TERTIARY,
|
|
350
|
+
fill: p.minor,
|
|
351
|
+
casing: p.minorCasing,
|
|
352
|
+
fillWidth: width([
|
|
353
|
+
[11, 0.6],
|
|
354
|
+
[14, 2.4],
|
|
355
|
+
[17, 7],
|
|
356
|
+
[20, 18],
|
|
357
|
+
]),
|
|
358
|
+
minZoom: 11,
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
id: 'minor',
|
|
362
|
+
kinds: MINOR,
|
|
363
|
+
fill: p.minor,
|
|
364
|
+
casing: p.minorCasing,
|
|
365
|
+
fillWidth: width([
|
|
366
|
+
[12, 0.5],
|
|
367
|
+
[14, 1.8],
|
|
368
|
+
[17, 6],
|
|
369
|
+
[20, 16],
|
|
370
|
+
]),
|
|
371
|
+
minZoom: 12,
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
id: 'service',
|
|
375
|
+
kinds: SERVICE,
|
|
376
|
+
fill: p.minor,
|
|
377
|
+
casing: p.minorCasing,
|
|
378
|
+
fillWidth: width([
|
|
379
|
+
[14, 0.8],
|
|
380
|
+
[17, 3],
|
|
381
|
+
[20, 9],
|
|
382
|
+
]),
|
|
383
|
+
minZoom: 14,
|
|
384
|
+
},
|
|
385
|
+
];
|
|
386
|
+
|
|
387
|
+
for (const road of roadClasses) {
|
|
388
|
+
layers.push({
|
|
389
|
+
id: `${road.id}-casing`,
|
|
390
|
+
type: 'line',
|
|
391
|
+
sourceLayer: 'streets',
|
|
392
|
+
minZoom: road.minZoom,
|
|
393
|
+
filter: ['all', ['in', 'kind', ...road.kinds], ['!=', 'rail', true]],
|
|
394
|
+
color: road.casing,
|
|
395
|
+
// A casing is the fill plus two logical pixels, which is what makes
|
|
396
|
+
// the outline a constant width at every zoom rather than a ratio that
|
|
397
|
+
// disappears when the road is thin.
|
|
398
|
+
width: scaleWidth(road.fillWidth, 2),
|
|
399
|
+
cap: 'round',
|
|
400
|
+
join: 'round',
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
for (const road of roadClasses) {
|
|
404
|
+
layers.push({
|
|
405
|
+
id: road.id,
|
|
406
|
+
type: 'line',
|
|
407
|
+
sourceLayer: 'streets',
|
|
408
|
+
minZoom: road.minZoom,
|
|
409
|
+
filter: ['all', ['in', 'kind', ...road.kinds], ['!=', 'rail', true]],
|
|
410
|
+
color: road.fill,
|
|
411
|
+
width: road.fillWidth,
|
|
412
|
+
cap: 'round',
|
|
413
|
+
join: 'round',
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
layers.push(
|
|
418
|
+
{
|
|
419
|
+
id: 'paths',
|
|
420
|
+
type: 'line',
|
|
421
|
+
sourceLayer: 'streets',
|
|
422
|
+
minZoom: 15,
|
|
423
|
+
filter: ['in', 'kind', ...PATH],
|
|
424
|
+
color: p.path,
|
|
425
|
+
width: width([
|
|
426
|
+
[15, 0.8],
|
|
427
|
+
[18, 1.6],
|
|
428
|
+
[20, 3],
|
|
429
|
+
]),
|
|
430
|
+
dash: [3, 2],
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
id: 'rail',
|
|
434
|
+
type: 'line',
|
|
435
|
+
sourceLayer: 'streets',
|
|
436
|
+
minZoom: 9,
|
|
437
|
+
filter: ['in', 'kind', ...RAIL],
|
|
438
|
+
color: p.rail,
|
|
439
|
+
width: width([
|
|
440
|
+
[9, 0.5],
|
|
441
|
+
[13, 1],
|
|
442
|
+
[17, 2],
|
|
443
|
+
[20, 3],
|
|
444
|
+
]),
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
id: 'ferries',
|
|
448
|
+
type: 'line',
|
|
449
|
+
sourceLayer: 'ferries',
|
|
450
|
+
minZoom: 9,
|
|
451
|
+
color: p.boundary,
|
|
452
|
+
width: 1,
|
|
453
|
+
dash: [4, 3],
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
id: 'boundaries-country',
|
|
457
|
+
type: 'line',
|
|
458
|
+
sourceLayer: 'boundaries',
|
|
459
|
+
color: p.boundary,
|
|
460
|
+
filter: ['<=', 'admin_level', 2],
|
|
461
|
+
width: width([
|
|
462
|
+
[2, 0.6],
|
|
463
|
+
[6, 1.1],
|
|
464
|
+
[12, 1.6],
|
|
465
|
+
]),
|
|
466
|
+
dash: [5, 3],
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
// Regional borders only once there is room for them to mean
|
|
470
|
+
// something — at zoom 3 they are noise over the country outlines.
|
|
471
|
+
id: 'boundaries-region',
|
|
472
|
+
type: 'line',
|
|
473
|
+
sourceLayer: 'boundaries',
|
|
474
|
+
minZoom: 6,
|
|
475
|
+
color: p.boundary,
|
|
476
|
+
filter: ['>', 'admin_level', 2],
|
|
477
|
+
width: width([
|
|
478
|
+
[6, 0.5],
|
|
479
|
+
[12, 1],
|
|
480
|
+
]),
|
|
481
|
+
dash: [3, 3],
|
|
482
|
+
},
|
|
483
|
+
);
|
|
484
|
+
|
|
485
|
+
if (options.labels !== false) {
|
|
486
|
+
layers.push(
|
|
487
|
+
// Places, split by kind rather than ranked by a field — see
|
|
488
|
+
// `SymbolLayer.rank` for why. The split is also what lets each class
|
|
489
|
+
// have its own size and its own zoom, which is most of what makes a
|
|
490
|
+
// label layer read as cartography.
|
|
491
|
+
{
|
|
492
|
+
id: 'place-labels-city',
|
|
493
|
+
type: 'symbol',
|
|
494
|
+
sourceLayer: 'place_labels',
|
|
495
|
+
filter: ['in', 'kind', 'capital', 'city'],
|
|
496
|
+
textField: name,
|
|
497
|
+
textColor: p.text,
|
|
498
|
+
textHaloColor: p.halo,
|
|
499
|
+
textHaloWidth: 1.5,
|
|
500
|
+
textSize: {
|
|
501
|
+
stops: [
|
|
502
|
+
[3, 12],
|
|
503
|
+
[8, 15],
|
|
504
|
+
[12, 18],
|
|
505
|
+
[16, 20],
|
|
506
|
+
],
|
|
507
|
+
},
|
|
508
|
+
rank: 100,
|
|
509
|
+
},
|
|
510
|
+
{
|
|
511
|
+
id: 'place-labels-town',
|
|
512
|
+
type: 'symbol',
|
|
513
|
+
sourceLayer: 'place_labels',
|
|
514
|
+
minZoom: 7,
|
|
515
|
+
filter: ['in', 'kind', 'town', 'borough'],
|
|
516
|
+
textField: name,
|
|
517
|
+
textColor: p.text,
|
|
518
|
+
textHaloColor: p.halo,
|
|
519
|
+
textHaloWidth: 1.5,
|
|
520
|
+
textSize: {
|
|
521
|
+
stops: [
|
|
522
|
+
[7, 11],
|
|
523
|
+
[12, 14],
|
|
524
|
+
[16, 16],
|
|
525
|
+
],
|
|
526
|
+
},
|
|
527
|
+
rank: 80,
|
|
528
|
+
},
|
|
529
|
+
{
|
|
530
|
+
id: 'place-labels-suburb',
|
|
531
|
+
type: 'symbol',
|
|
532
|
+
sourceLayer: 'place_labels',
|
|
533
|
+
minZoom: 11,
|
|
534
|
+
filter: ['in', 'kind', 'suburb', 'quarter', 'neighbourhood', 'village'],
|
|
535
|
+
textField: name,
|
|
536
|
+
textColor: p.textMinor,
|
|
537
|
+
textHaloColor: p.halo,
|
|
538
|
+
textHaloWidth: 1.2,
|
|
539
|
+
textSize: {
|
|
540
|
+
stops: [
|
|
541
|
+
[11, 10],
|
|
542
|
+
[15, 13],
|
|
543
|
+
],
|
|
544
|
+
},
|
|
545
|
+
rank: 60,
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
id: 'place-labels-locality',
|
|
549
|
+
type: 'symbol',
|
|
550
|
+
sourceLayer: 'place_labels',
|
|
551
|
+
minZoom: 13,
|
|
552
|
+
filter: [
|
|
553
|
+
'in',
|
|
554
|
+
'kind',
|
|
555
|
+
'hamlet',
|
|
556
|
+
'locality',
|
|
557
|
+
'isolated_dwelling',
|
|
558
|
+
'farm',
|
|
559
|
+
'island',
|
|
560
|
+
'islet',
|
|
561
|
+
],
|
|
562
|
+
textField: name,
|
|
563
|
+
textColor: p.textMinor,
|
|
564
|
+
textHaloColor: p.halo,
|
|
565
|
+
textHaloWidth: 1.2,
|
|
566
|
+
textSize: 10,
|
|
567
|
+
rank: 40,
|
|
568
|
+
},
|
|
569
|
+
{
|
|
570
|
+
id: 'water-labels',
|
|
571
|
+
type: 'symbol',
|
|
572
|
+
sourceLayer: 'water_polygons_labels',
|
|
573
|
+
minZoom: 9,
|
|
574
|
+
textField: name,
|
|
575
|
+
textColor: p.textMinor,
|
|
576
|
+
textHaloColor: p.halo,
|
|
577
|
+
textHaloWidth: 1,
|
|
578
|
+
textSize: 11,
|
|
579
|
+
rank: 30,
|
|
580
|
+
},
|
|
581
|
+
{
|
|
582
|
+
id: 'street-labels',
|
|
583
|
+
type: 'symbol',
|
|
584
|
+
sourceLayer: 'street_labels',
|
|
585
|
+
minZoom: 14,
|
|
586
|
+
filter: ['!in', 'kind', ...RAIL],
|
|
587
|
+
textField: name,
|
|
588
|
+
textColor: p.textMinor,
|
|
589
|
+
textHaloColor: p.halo,
|
|
590
|
+
textHaloWidth: 1,
|
|
591
|
+
textSize: 11,
|
|
592
|
+
// Under every place name: a suburb's name is what orients someone,
|
|
593
|
+
// a street's name is what they read once they are oriented.
|
|
594
|
+
rank: 20,
|
|
595
|
+
},
|
|
596
|
+
{
|
|
597
|
+
id: 'transport-labels',
|
|
598
|
+
type: 'symbol',
|
|
599
|
+
sourceLayer: 'public_transport',
|
|
600
|
+
minZoom: 15,
|
|
601
|
+
textField: name,
|
|
602
|
+
textColor: p.textMinor,
|
|
603
|
+
textHaloColor: p.halo,
|
|
604
|
+
textHaloWidth: 1,
|
|
605
|
+
textSize: 10,
|
|
606
|
+
rank: 10,
|
|
607
|
+
},
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
return { background: p.land, layers };
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/** A width ramp plus a constant — how a casing is derived from its fill so
|
|
615
|
+
* the two cannot drift apart when one of them is retuned. */
|
|
616
|
+
function scaleWidth(base: Zoomed<number>, add: number): Zoomed<number> {
|
|
617
|
+
if (typeof base === 'number') return base + add;
|
|
618
|
+
return { stops: base.stops.map(([z, v]) => [z, v + add] as const) };
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// --- OpenMapTiles -----------------------------------------------------------
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* Road classes as **OpenMapTiles** names them.
|
|
625
|
+
*
|
|
626
|
+
* Not the same words as Shortbread's, which is the whole reason this second
|
|
627
|
+
* style exists: `transportation.class` is `minor` where Shortbread says
|
|
628
|
+
* `residential`, `unclassified` and `living_street`, and rail lives in the
|
|
629
|
+
* same layer under `class: 'rail'` rather than beside the roads. Point
|
|
630
|
+
* {@link shortbreadStyle} at an OpenMapTiles source and it matches nothing
|
|
631
|
+
* and draws an empty map.
|
|
632
|
+
*/
|
|
633
|
+
const OMT_RAIL = ['rail', 'transit'] as const;
|
|
634
|
+
|
|
635
|
+
/** Landcover classes that read as green space. */
|
|
636
|
+
const OMT_GREEN = ['wood', 'grass', 'farmland', 'wetland'] as const;
|
|
637
|
+
|
|
638
|
+
/** Landuse classes that read as built-up. */
|
|
639
|
+
const OMT_BUILT = [
|
|
640
|
+
'residential',
|
|
641
|
+
'commercial',
|
|
642
|
+
'industrial',
|
|
643
|
+
'retail',
|
|
644
|
+
'railway',
|
|
645
|
+
'cemetery',
|
|
646
|
+
'quarry',
|
|
647
|
+
] as const;
|
|
648
|
+
|
|
649
|
+
/** Landuse classes for an institutional site. */
|
|
650
|
+
const OMT_SITES = [
|
|
651
|
+
'hospital',
|
|
652
|
+
'school',
|
|
653
|
+
'university',
|
|
654
|
+
'college',
|
|
655
|
+
'kindergarten',
|
|
656
|
+
'stadium',
|
|
657
|
+
'pitch',
|
|
658
|
+
'playground',
|
|
659
|
+
] as const;
|
|
660
|
+
|
|
661
|
+
export interface OpenMapTilesStyleOptions extends ShortbreadStyleOptions {}
|
|
662
|
+
|
|
663
|
+
/**
|
|
664
|
+
* The same cartography over the **OpenMapTiles** schema.
|
|
665
|
+
*
|
|
666
|
+
* OpenMapTiles is the other open schema, and between them the two cover
|
|
667
|
+
* nearly every provider worth pointing this at: Shortbread is what
|
|
668
|
+
* OpenStreetMap's own server and VersaTiles cut, OpenMapTiles is what
|
|
669
|
+
* MapTiler, Stadia, Geoapify, OpenFreeMap and most self-hosted planets cut.
|
|
670
|
+
*
|
|
671
|
+
* Deliberately the same palette, the same layer ids where they mean the
|
|
672
|
+
* same thing, and the same casing-then-fill ordering, so switching a source
|
|
673
|
+
* between the two schemas changes which style you pass and nothing else
|
|
674
|
+
* about how the map looks.
|
|
675
|
+
*/
|
|
676
|
+
export function openMapTilesStyle(
|
|
677
|
+
options: OpenMapTilesStyleOptions = {},
|
|
678
|
+
): MapStyle {
|
|
679
|
+
const p: MapPalette = {
|
|
680
|
+
...(options.dark ? DARK_PALETTE : LIGHT_PALETTE),
|
|
681
|
+
...options.palette,
|
|
682
|
+
};
|
|
683
|
+
const name = options.nameField ?? 'name';
|
|
684
|
+
const layers: MapStyleLayer[] = [
|
|
685
|
+
// One `water` layer for everything wet, with `class` telling the sea
|
|
686
|
+
// from a lake — where Shortbread has `ocean` and `water_polygons`.
|
|
687
|
+
{ id: 'ocean', type: 'fill', sourceLayer: 'water', color: p.water },
|
|
688
|
+
{
|
|
689
|
+
id: 'landuse-green',
|
|
690
|
+
type: 'fill',
|
|
691
|
+
sourceLayer: 'landcover',
|
|
692
|
+
filter: ['in', 'class', ...OMT_GREEN],
|
|
693
|
+
color: p.green,
|
|
694
|
+
},
|
|
695
|
+
{ id: 'park', type: 'fill', sourceLayer: 'park', color: p.green },
|
|
696
|
+
{
|
|
697
|
+
id: 'landuse-built',
|
|
698
|
+
type: 'fill',
|
|
699
|
+
sourceLayer: 'landuse',
|
|
700
|
+
filter: ['in', 'class', ...OMT_BUILT],
|
|
701
|
+
color: p.built,
|
|
702
|
+
},
|
|
703
|
+
{
|
|
704
|
+
id: 'sites',
|
|
705
|
+
type: 'fill',
|
|
706
|
+
sourceLayer: 'landuse',
|
|
707
|
+
minZoom: 13,
|
|
708
|
+
filter: ['in', 'class', ...OMT_SITES],
|
|
709
|
+
color: p.site,
|
|
710
|
+
},
|
|
711
|
+
{
|
|
712
|
+
id: 'water-lines',
|
|
713
|
+
type: 'line',
|
|
714
|
+
sourceLayer: 'waterway',
|
|
715
|
+
color: p.water,
|
|
716
|
+
width: width([
|
|
717
|
+
[6, 0.5],
|
|
718
|
+
[10, 1.2],
|
|
719
|
+
[14, 3],
|
|
720
|
+
[18, 8],
|
|
721
|
+
]),
|
|
722
|
+
},
|
|
723
|
+
];
|
|
724
|
+
|
|
725
|
+
if (options.buildings !== false) {
|
|
726
|
+
layers.push({
|
|
727
|
+
id: 'buildings',
|
|
728
|
+
type: 'fill',
|
|
729
|
+
sourceLayer: 'building',
|
|
730
|
+
minZoom: 14,
|
|
731
|
+
color: p.building,
|
|
732
|
+
outlineColor: p.buildingEdge,
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
const roads: {
|
|
737
|
+
id: string;
|
|
738
|
+
classes: readonly string[];
|
|
739
|
+
fill: string;
|
|
740
|
+
casing: string;
|
|
741
|
+
fillWidth: Zoomed<number>;
|
|
742
|
+
minZoom?: number;
|
|
743
|
+
}[] = [
|
|
744
|
+
{
|
|
745
|
+
id: 'motorway',
|
|
746
|
+
classes: ['motorway'],
|
|
747
|
+
fill: p.motorway,
|
|
748
|
+
casing: p.motorwayCasing,
|
|
749
|
+
fillWidth: width([
|
|
750
|
+
[5, 0.6],
|
|
751
|
+
[8, 1.4],
|
|
752
|
+
[10, 2.4],
|
|
753
|
+
[13, 5],
|
|
754
|
+
[16, 12],
|
|
755
|
+
[20, 40],
|
|
756
|
+
]),
|
|
757
|
+
},
|
|
758
|
+
{
|
|
759
|
+
id: 'trunk',
|
|
760
|
+
classes: ['trunk'],
|
|
761
|
+
fill: p.trunk,
|
|
762
|
+
casing: p.motorwayCasing,
|
|
763
|
+
fillWidth: width([
|
|
764
|
+
[6, 0.5],
|
|
765
|
+
[9, 1.2],
|
|
766
|
+
[12, 2.6],
|
|
767
|
+
[16, 9],
|
|
768
|
+
[20, 30],
|
|
769
|
+
]),
|
|
770
|
+
},
|
|
771
|
+
{
|
|
772
|
+
id: 'primary',
|
|
773
|
+
classes: ['primary'],
|
|
774
|
+
fill: p.primary,
|
|
775
|
+
casing: p.minorCasing,
|
|
776
|
+
minZoom: 7,
|
|
777
|
+
fillWidth: width([
|
|
778
|
+
[7, 0.5],
|
|
779
|
+
[10, 1.3],
|
|
780
|
+
[13, 3],
|
|
781
|
+
[16, 8],
|
|
782
|
+
[20, 26],
|
|
783
|
+
]),
|
|
784
|
+
},
|
|
785
|
+
{
|
|
786
|
+
id: 'secondary',
|
|
787
|
+
classes: ['secondary'],
|
|
788
|
+
fill: p.secondary,
|
|
789
|
+
casing: p.minorCasing,
|
|
790
|
+
minZoom: 9,
|
|
791
|
+
fillWidth: width([
|
|
792
|
+
[9, 0.5],
|
|
793
|
+
[12, 1.6],
|
|
794
|
+
[15, 5],
|
|
795
|
+
[20, 20],
|
|
796
|
+
]),
|
|
797
|
+
},
|
|
798
|
+
{
|
|
799
|
+
id: 'tertiary',
|
|
800
|
+
classes: ['tertiary'],
|
|
801
|
+
fill: p.minor,
|
|
802
|
+
casing: p.minorCasing,
|
|
803
|
+
minZoom: 11,
|
|
804
|
+
fillWidth: width([
|
|
805
|
+
[11, 0.6],
|
|
806
|
+
[14, 2.4],
|
|
807
|
+
[17, 7],
|
|
808
|
+
[20, 18],
|
|
809
|
+
]),
|
|
810
|
+
},
|
|
811
|
+
{
|
|
812
|
+
// `minor` is OpenMapTiles' one word for residential, unclassified and
|
|
813
|
+
// living_street, which Shortbread keeps apart.
|
|
814
|
+
id: 'minor',
|
|
815
|
+
classes: ['minor'],
|
|
816
|
+
fill: p.minor,
|
|
817
|
+
casing: p.minorCasing,
|
|
818
|
+
minZoom: 12,
|
|
819
|
+
fillWidth: width([
|
|
820
|
+
[12, 0.5],
|
|
821
|
+
[14, 1.8],
|
|
822
|
+
[17, 6],
|
|
823
|
+
[20, 16],
|
|
824
|
+
]),
|
|
825
|
+
},
|
|
826
|
+
{
|
|
827
|
+
id: 'service',
|
|
828
|
+
classes: ['service', 'track'],
|
|
829
|
+
fill: p.minor,
|
|
830
|
+
casing: p.minorCasing,
|
|
831
|
+
minZoom: 14,
|
|
832
|
+
fillWidth: width([
|
|
833
|
+
[14, 0.8],
|
|
834
|
+
[17, 3],
|
|
835
|
+
[20, 9],
|
|
836
|
+
]),
|
|
837
|
+
},
|
|
838
|
+
];
|
|
839
|
+
|
|
840
|
+
for (const road of roads) {
|
|
841
|
+
layers.push({
|
|
842
|
+
id: `${road.id}-casing`,
|
|
843
|
+
type: 'line',
|
|
844
|
+
sourceLayer: 'transportation',
|
|
845
|
+
minZoom: road.minZoom,
|
|
846
|
+
filter: ['in', 'class', ...road.classes],
|
|
847
|
+
color: road.casing,
|
|
848
|
+
width: scaleWidth(road.fillWidth, 2),
|
|
849
|
+
cap: 'round',
|
|
850
|
+
join: 'round',
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
for (const road of roads) {
|
|
854
|
+
layers.push({
|
|
855
|
+
id: road.id,
|
|
856
|
+
type: 'line',
|
|
857
|
+
sourceLayer: 'transportation',
|
|
858
|
+
minZoom: road.minZoom,
|
|
859
|
+
filter: ['in', 'class', ...road.classes],
|
|
860
|
+
color: road.fill,
|
|
861
|
+
width: road.fillWidth,
|
|
862
|
+
cap: 'round',
|
|
863
|
+
join: 'round',
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
layers.push(
|
|
868
|
+
{
|
|
869
|
+
id: 'paths',
|
|
870
|
+
type: 'line',
|
|
871
|
+
sourceLayer: 'transportation',
|
|
872
|
+
minZoom: 15,
|
|
873
|
+
filter: ['in', 'class', 'path', 'pedestrian'],
|
|
874
|
+
color: p.path,
|
|
875
|
+
width: width([
|
|
876
|
+
[15, 0.8],
|
|
877
|
+
[18, 1.6],
|
|
878
|
+
[20, 3],
|
|
879
|
+
]),
|
|
880
|
+
dash: [3, 2],
|
|
881
|
+
},
|
|
882
|
+
{
|
|
883
|
+
id: 'rail',
|
|
884
|
+
type: 'line',
|
|
885
|
+
sourceLayer: 'transportation',
|
|
886
|
+
minZoom: 9,
|
|
887
|
+
filter: ['in', 'class', ...OMT_RAIL],
|
|
888
|
+
color: p.rail,
|
|
889
|
+
width: width([
|
|
890
|
+
[9, 0.5],
|
|
891
|
+
[13, 1],
|
|
892
|
+
[17, 2],
|
|
893
|
+
[20, 3],
|
|
894
|
+
]),
|
|
895
|
+
},
|
|
896
|
+
{
|
|
897
|
+
id: 'ferries',
|
|
898
|
+
type: 'line',
|
|
899
|
+
sourceLayer: 'transportation',
|
|
900
|
+
minZoom: 9,
|
|
901
|
+
filter: ['==', 'class', 'ferry'],
|
|
902
|
+
color: p.boundary,
|
|
903
|
+
width: 1,
|
|
904
|
+
dash: [4, 3],
|
|
905
|
+
},
|
|
906
|
+
{
|
|
907
|
+
id: 'boundaries-country',
|
|
908
|
+
type: 'line',
|
|
909
|
+
sourceLayer: 'boundary',
|
|
910
|
+
filter: ['<=', 'admin_level', 2],
|
|
911
|
+
color: p.boundary,
|
|
912
|
+
width: width([
|
|
913
|
+
[2, 0.6],
|
|
914
|
+
[6, 1.1],
|
|
915
|
+
[12, 1.6],
|
|
916
|
+
]),
|
|
917
|
+
dash: [5, 3],
|
|
918
|
+
},
|
|
919
|
+
{
|
|
920
|
+
id: 'boundaries-region',
|
|
921
|
+
type: 'line',
|
|
922
|
+
sourceLayer: 'boundary',
|
|
923
|
+
minZoom: 6,
|
|
924
|
+
filter: ['>', 'admin_level', 2],
|
|
925
|
+
color: p.boundary,
|
|
926
|
+
width: width([
|
|
927
|
+
[6, 0.5],
|
|
928
|
+
[12, 1],
|
|
929
|
+
]),
|
|
930
|
+
dash: [3, 3],
|
|
931
|
+
},
|
|
932
|
+
);
|
|
933
|
+
|
|
934
|
+
if (options.labels !== false) {
|
|
935
|
+
layers.push(
|
|
936
|
+
{
|
|
937
|
+
id: 'place-labels-city',
|
|
938
|
+
type: 'symbol',
|
|
939
|
+
sourceLayer: 'place',
|
|
940
|
+
filter: ['in', 'class', 'city'],
|
|
941
|
+
textField: name,
|
|
942
|
+
textColor: p.text,
|
|
943
|
+
textHaloColor: p.halo,
|
|
944
|
+
textHaloWidth: 1.5,
|
|
945
|
+
textSize: {
|
|
946
|
+
stops: [
|
|
947
|
+
[3, 12],
|
|
948
|
+
[8, 15],
|
|
949
|
+
[12, 18],
|
|
950
|
+
[16, 20],
|
|
951
|
+
],
|
|
952
|
+
},
|
|
953
|
+
rank: 100,
|
|
954
|
+
},
|
|
955
|
+
{
|
|
956
|
+
id: 'place-labels-town',
|
|
957
|
+
type: 'symbol',
|
|
958
|
+
sourceLayer: 'place',
|
|
959
|
+
minZoom: 7,
|
|
960
|
+
filter: ['in', 'class', 'town'],
|
|
961
|
+
textField: name,
|
|
962
|
+
textColor: p.text,
|
|
963
|
+
textHaloColor: p.halo,
|
|
964
|
+
textHaloWidth: 1.5,
|
|
965
|
+
textSize: {
|
|
966
|
+
stops: [
|
|
967
|
+
[7, 11],
|
|
968
|
+
[12, 14],
|
|
969
|
+
[16, 16],
|
|
970
|
+
],
|
|
971
|
+
},
|
|
972
|
+
rank: 80,
|
|
973
|
+
},
|
|
974
|
+
{
|
|
975
|
+
id: 'place-labels-suburb',
|
|
976
|
+
type: 'symbol',
|
|
977
|
+
sourceLayer: 'place',
|
|
978
|
+
minZoom: 11,
|
|
979
|
+
filter: [
|
|
980
|
+
'in',
|
|
981
|
+
'class',
|
|
982
|
+
'suburb',
|
|
983
|
+
'quarter',
|
|
984
|
+
'neighbourhood',
|
|
985
|
+
'village',
|
|
986
|
+
],
|
|
987
|
+
textField: name,
|
|
988
|
+
textColor: p.textMinor,
|
|
989
|
+
textHaloColor: p.halo,
|
|
990
|
+
textHaloWidth: 1.2,
|
|
991
|
+
textSize: {
|
|
992
|
+
stops: [
|
|
993
|
+
[11, 10],
|
|
994
|
+
[15, 13],
|
|
995
|
+
],
|
|
996
|
+
},
|
|
997
|
+
rank: 60,
|
|
998
|
+
},
|
|
999
|
+
{
|
|
1000
|
+
id: 'place-labels-locality',
|
|
1001
|
+
type: 'symbol',
|
|
1002
|
+
sourceLayer: 'place',
|
|
1003
|
+
minZoom: 13,
|
|
1004
|
+
filter: ['in', 'class', 'hamlet', 'isolated_dwelling', 'island'],
|
|
1005
|
+
textField: name,
|
|
1006
|
+
textColor: p.textMinor,
|
|
1007
|
+
textHaloColor: p.halo,
|
|
1008
|
+
textHaloWidth: 1.2,
|
|
1009
|
+
textSize: 10,
|
|
1010
|
+
rank: 40,
|
|
1011
|
+
},
|
|
1012
|
+
{
|
|
1013
|
+
id: 'water-labels',
|
|
1014
|
+
type: 'symbol',
|
|
1015
|
+
sourceLayer: 'water_name',
|
|
1016
|
+
minZoom: 9,
|
|
1017
|
+
textField: name,
|
|
1018
|
+
textColor: p.textMinor,
|
|
1019
|
+
textHaloColor: p.halo,
|
|
1020
|
+
textHaloWidth: 1,
|
|
1021
|
+
textSize: 11,
|
|
1022
|
+
rank: 30,
|
|
1023
|
+
},
|
|
1024
|
+
{
|
|
1025
|
+
id: 'street-labels',
|
|
1026
|
+
type: 'symbol',
|
|
1027
|
+
sourceLayer: 'transportation_name',
|
|
1028
|
+
minZoom: 14,
|
|
1029
|
+
textField: name,
|
|
1030
|
+
textColor: p.textMinor,
|
|
1031
|
+
textHaloColor: p.halo,
|
|
1032
|
+
textHaloWidth: 1,
|
|
1033
|
+
textSize: 11,
|
|
1034
|
+
rank: 20,
|
|
1035
|
+
},
|
|
1036
|
+
);
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
return { background: p.land, layers };
|
|
1040
|
+
}
|