@aguacerowx/mapsgl 0.0.54 → 0.0.56
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/index.js +5 -6
- package/package.json +3 -3
- package/src/NexradWeatherController.js +11 -1
- package/src/WeatherLayerManager.js +3 -5
- package/src/nexrad/loadNexradSites.ts +85 -7
- package/src/nexrad/nexradArchiveDiag.ts +26 -0
- package/src/nexrad/nexradMapboxFrameOpts.bundled.js +3 -2
- package/src/nexrad/nexradMapboxFrameOpts.ts +3 -2
- package/src/nexrad/nexradSitesDefault.json +1700 -0
- package/src/nexrad/radarArchiveCore.bundled.js +2724 -37
- package/src/nexrad/radarArchiveCore.ts +149 -30
- package/src/nexrad/radarDecode.worker.bundled.js +130 -126
- package/src/nexrad/radarDecode.worker.ts +13 -215
- package/src/nexrad/radarDecodeSlot.ts +195 -0
- package/src/NwsWatchesWarningsOverlay.js +0 -973
- package/src/nwsAlertsFetchSpec.js +0 -114
- package/src/nwsAlertsSupport.js +0 -1337
- package/src/nwsEventColorsDefaults.js +0 -133
- package/src/nwsSdkConstants.js +0 -360
- package/src/nwsWarningCustomizationKey.gen.js +0 -493
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Default NWS/IPAWS alert fill colors — kept in sync with
|
|
3
|
-
* `aguacero-frontend/src/lib/defaultColormaps.ts` (`NWS_EVENT_COLORS`).
|
|
4
|
-
* Update both when the palette changes.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export const NWS_EVENT_COLORS = {
|
|
8
|
-
'Tsunami Warning': '#FD6347',
|
|
9
|
-
'Tsunami Advisory': '#D2691E',
|
|
10
|
-
'Tsunami Watch': '#FF00FF',
|
|
11
|
-
'Tornado Warning': '#FF0000',
|
|
12
|
-
'Tornado Warning (Observed)': '#FF0000',
|
|
13
|
-
'Tornado Warning (PDS)': '#FF0000',
|
|
14
|
-
'Tornado Warning (Emergency)': '#FF0000',
|
|
15
|
-
'Tornado Watch': '#FFFF00',
|
|
16
|
-
'Severe Thunderstorm Warning': '#FFA500',
|
|
17
|
-
'Severe Thunderstorm Warning (Considerable)': '#FFA500',
|
|
18
|
-
'Severe Thunderstorm Warning (Destructive)': '#FFA500',
|
|
19
|
-
'Severe Thunderstorm Watch': '#DB7093',
|
|
20
|
-
'Severe Weather Statement': '#00FFFF',
|
|
21
|
-
'Extreme Wind Warning': '#FF8C00',
|
|
22
|
-
'High Wind Warning': '#DAA520',
|
|
23
|
-
'High Wind Watch': '#B8860B',
|
|
24
|
-
'Wind Advisory': '#D2B48C',
|
|
25
|
-
'Lake Wind Advisory': '#D2B48C',
|
|
26
|
-
'Flash Flood Warning': '#8B0000',
|
|
27
|
-
'Flash Flood Warning (Considerable)': '#8B0000',
|
|
28
|
-
'Flash Flood Warning (Emergency)': '#8B0000',
|
|
29
|
-
'Flash Flood Statement': '#8B0000',
|
|
30
|
-
'Flash Flood Watch': '#2E8B57',
|
|
31
|
-
'Flood Warning': '#00FF00',
|
|
32
|
-
'Flood Statement': '#00FF00',
|
|
33
|
-
'Flood Watch': '#2E8B57',
|
|
34
|
-
'Flood Advisory': '#00FF7F',
|
|
35
|
-
'Coastal Flood Warning': '#228B22',
|
|
36
|
-
'Coastal Flood Watch': '#66CDAA',
|
|
37
|
-
'Coastal Flood Advisory': '#7CFC00',
|
|
38
|
-
'Coastal Flood Statement': '#6B8E23',
|
|
39
|
-
'Lakeshore Flood Warning': '#228B22',
|
|
40
|
-
'Lakeshore Flood Watch': '#66CDAA',
|
|
41
|
-
'Lakeshore Flood Advisory': '#7CFC00',
|
|
42
|
-
'Lakeshore Flood Statement': '#6B8E23',
|
|
43
|
-
'Hydrologic Outlook': '#90EE90',
|
|
44
|
-
'Shelter In Place Warning': '#FA8072',
|
|
45
|
-
'Evacuation Immediate': '#7FFF00',
|
|
46
|
-
'Civil Danger Warning': '#FFB6C1',
|
|
47
|
-
'Civil Emergency Message': '#FFB6C1',
|
|
48
|
-
'Law Enforcement Warning': '#C0C0C0',
|
|
49
|
-
'Local Area Emergency': '#C0C0C0',
|
|
50
|
-
'911 Telephone Outage': '#C0C0C0',
|
|
51
|
-
'Nuclear Power Plant Warning': '#4B0082',
|
|
52
|
-
'Radiological Hazard Warning': '#4B0082',
|
|
53
|
-
'Hazardous Materials Warning': '#4B0082',
|
|
54
|
-
'Fire Warning': '#A0522D',
|
|
55
|
-
'Red Flag Warning': '#FF1493',
|
|
56
|
-
'Fire Weather Watch': '#FFDEAD',
|
|
57
|
-
'Extreme Fire Danger': '#E9967A',
|
|
58
|
-
'Storm Surge Warning': '#B524F7',
|
|
59
|
-
'Storm Surge Watch': '#DB7FF7',
|
|
60
|
-
'Hurricane Force Wind Warning': '#CD5C5C',
|
|
61
|
-
'Hurricane Force Wind Watch': '#9932CC',
|
|
62
|
-
'Hurricane Warning': '#DC143C',
|
|
63
|
-
'Hurricane Watch': '#FF00FF',
|
|
64
|
-
'Typhoon Warning': '#DC143C',
|
|
65
|
-
'Typhoon Watch': '#FF00FF',
|
|
66
|
-
'Tropical Storm Warning': '#B22222',
|
|
67
|
-
'Tropical Storm Watch': '#F08080',
|
|
68
|
-
'Tropical Cyclone Local Statement': '#FFE4B5',
|
|
69
|
-
'Special Marine Warning': '#FFA500',
|
|
70
|
-
'Gale Warning': '#DDA0DD',
|
|
71
|
-
'Gale Watch': '#FFC0CB',
|
|
72
|
-
'Storm Warning': '#9400D3',
|
|
73
|
-
'Storm Watch': '#FFE4B5',
|
|
74
|
-
'Small Craft Advisory': '#D8BFD8',
|
|
75
|
-
'Brisk Wind Advisory': '#D8BFD8',
|
|
76
|
-
'Hazardous Seas Warning': '#D8BFD8',
|
|
77
|
-
'Hazardous Seas Watch': '#483D8B',
|
|
78
|
-
'Heavy Freezing Spray Warning': '#00BFFF',
|
|
79
|
-
'Heavy Freezing Spray Watch': '#BC8F8F',
|
|
80
|
-
'Marine Weather Statement': '#FFDAB9',
|
|
81
|
-
'Low Water Advisory': '#A52A2A',
|
|
82
|
-
'High Surf Warning': '#228B22',
|
|
83
|
-
'High Surf Advisory': '#BA55D3',
|
|
84
|
-
'Beach Hazards Statement': '#40E0D0',
|
|
85
|
-
'Rip Current Statement': '#40E0D0',
|
|
86
|
-
'Blizzard Warning': '#FF4500',
|
|
87
|
-
'Snow Squall Warning': '#C71585',
|
|
88
|
-
'Ice Storm Warning': '#8B008B',
|
|
89
|
-
'Winter Storm Warning': '#FF69B4',
|
|
90
|
-
'Lake Effect Snow Warning': '#008B8B',
|
|
91
|
-
'Winter Storm Watch': '#4682B4',
|
|
92
|
-
'Winter Weather Advisory': '#7B68EE',
|
|
93
|
-
'Freeze Warning': '#483D8B',
|
|
94
|
-
'Freeze Watch': '#00FFFF',
|
|
95
|
-
'Frost Advisory': '#6495ED',
|
|
96
|
-
'Freezing Fog Advisory': '#008080',
|
|
97
|
-
'Freezing Spray Advisory': '#00BFFF',
|
|
98
|
-
'Freezing Rain Advisory': '#DA70D6',
|
|
99
|
-
'Wind Chill Warning': '#B0C4DE',
|
|
100
|
-
'Cold Weather Advisory': '#AFEEEE',
|
|
101
|
-
'Extreme Heat Warning': '#C71585',
|
|
102
|
-
'Extreme Heat Watch': '#800000',
|
|
103
|
-
'Heat Advisory': '#FF7F50',
|
|
104
|
-
'Extreme Cold Warning': '#0000FF',
|
|
105
|
-
'Extreme Cold Watch': '#5F9EA0',
|
|
106
|
-
'Dust Storm Warning': '#FFE4C4',
|
|
107
|
-
'Blowing Dust Warning': '#FFE4C4',
|
|
108
|
-
'Dust Advisory': '#BDB76B',
|
|
109
|
-
'Blowing Dust Advisory': '#BDB76B',
|
|
110
|
-
'Ashfall Warning': '#A9A9A9',
|
|
111
|
-
'Ashfall Advisory': '#696969',
|
|
112
|
-
'Avalanche Warning': '#1E90FF',
|
|
113
|
-
'Avalanche Watch': '#F4A460',
|
|
114
|
-
'Avalanche Advisory': '#CD853F',
|
|
115
|
-
'Earthquake Warning': '#8B4513',
|
|
116
|
-
'Volcano Warning': '#2F4F4F',
|
|
117
|
-
'Dense Fog Advisory': '#708090',
|
|
118
|
-
'Dense Smoke Advisory': '#F0E68C',
|
|
119
|
-
'Air Quality Alert': '#808080',
|
|
120
|
-
'Air Stagnation Advisory': '#808080',
|
|
121
|
-
'Special Weather Statement': '#FFE4B5',
|
|
122
|
-
'Hazardous Weather Outlook': '#EEE8AA',
|
|
123
|
-
'Short Term Forecast': '#98FB98',
|
|
124
|
-
'Administrative Message': '#C0C0C0',
|
|
125
|
-
'Test': '#F0FFFF',
|
|
126
|
-
'Child Abduction Emergency': '#FFFFFF',
|
|
127
|
-
'Blue Alert': '#FFFFFF',
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
/** Same ordering as frontend `NWS_ALERT_EVENT_NAMES`. */
|
|
131
|
-
export const NWS_ALERT_EVENT_NAMES = Object.keys(NWS_EVENT_COLORS).sort((a, b) =>
|
|
132
|
-
a.localeCompare(b, undefined, { sensitivity: 'base' })
|
|
133
|
-
);
|
package/src/nwsSdkConstants.js
DELETED
|
@@ -1,360 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* NWS alert styling defaults — palette from `nwsEventColorsDefaults.js` (synced with
|
|
3
|
-
* aguacero-frontend `src/lib/defaultColormaps.ts`). Unknown CAP event names still fall back to
|
|
4
|
-
* {@link WARNING_DEFAULT_COLOR}.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { NWS_ALERT_EVENT_NAMES, NWS_EVENT_COLORS } from './nwsEventColorsDefaults.js';
|
|
8
|
-
|
|
9
|
-
export { NWS_ALERT_EVENT_NAMES, NWS_EVENT_COLORS };
|
|
10
|
-
|
|
11
|
-
/** @deprecated Use {@link NWS_EVENT_COLORS}. */
|
|
12
|
-
export const NWS_SDK_EVENT_COLOR = NWS_EVENT_COLORS;
|
|
13
|
-
|
|
14
|
-
/** @deprecated Use {@link NWS_ALERT_EVENT_NAMES}. */
|
|
15
|
-
export const NWS_SDK_EVENT_NAMES = NWS_ALERT_EVENT_NAMES;
|
|
16
|
-
|
|
17
|
-
export const NWS_DEFAULT_FILL_OPACITY = 0.5;
|
|
18
|
-
|
|
19
|
-
/** Warnings outline-only by default for convective + flash-flood warnings — same as aguacero-frontend. */
|
|
20
|
-
export const NWS_DEFAULT_FILL_HIDDEN = Object.fromEntries(
|
|
21
|
-
[
|
|
22
|
-
'Tornado Warning',
|
|
23
|
-
'Tornado Warning (Observed)',
|
|
24
|
-
'Tornado Warning (PDS)',
|
|
25
|
-
'Tornado Warning (Emergency)',
|
|
26
|
-
'Severe Thunderstorm Warning',
|
|
27
|
-
'Severe Thunderstorm Warning (Considerable)',
|
|
28
|
-
'Severe Thunderstorm Warning (Destructive)',
|
|
29
|
-
'Flash Flood Warning',
|
|
30
|
-
'Flash Flood Warning (Considerable)',
|
|
31
|
-
'Flash Flood Warning (Emergency)',
|
|
32
|
-
'Flash Flood Statement',
|
|
33
|
-
].map((name) => [name, true])
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
export const NWS_WARNINGS_SUBTYPE_PARENT = {
|
|
37
|
-
'Tornado Warning (Observed)': 'Tornado Warning',
|
|
38
|
-
'Tornado Warning (PDS)': 'Tornado Warning',
|
|
39
|
-
'Tornado Warning (Emergency)': 'Tornado Warning',
|
|
40
|
-
'Severe Thunderstorm Warning (Considerable)': 'Severe Thunderstorm Warning',
|
|
41
|
-
'Severe Thunderstorm Warning (Destructive)': 'Severe Thunderstorm Warning',
|
|
42
|
-
'Flash Flood Warning (Considerable)': 'Flash Flood Warning',
|
|
43
|
-
'Flash Flood Warning (Emergency)': 'Flash Flood Warning',
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export const NWS_ALERT_END_TIME_PROP_KEYS = ['ends', 'expires', 'expires_at'];
|
|
47
|
-
|
|
48
|
-
export function resolveNwsAlertUserColor(userColors, eventName) {
|
|
49
|
-
const uc = userColors ?? {};
|
|
50
|
-
const own = uc[eventName];
|
|
51
|
-
if (own != null && String(own).trim() !== '') return own;
|
|
52
|
-
if (eventName === 'Tornado Warning (Observed)') {
|
|
53
|
-
const legacy = uc['Tornado Warning (Reported)'];
|
|
54
|
-
if (legacy != null && String(legacy).trim() !== '') return legacy;
|
|
55
|
-
}
|
|
56
|
-
const parent = NWS_WARNINGS_SUBTYPE_PARENT[eventName];
|
|
57
|
-
if (parent) {
|
|
58
|
-
const p = uc[parent];
|
|
59
|
-
if (p != null && String(p).trim() !== '') return p;
|
|
60
|
-
}
|
|
61
|
-
return undefined;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export function isNwsAlertDisabled(disabled, eventName) {
|
|
65
|
-
const d = disabled ?? {};
|
|
66
|
-
if (d[eventName] === true) return true;
|
|
67
|
-
if (eventName === 'Tornado Warning (Observed)' && d['Tornado Warning (Reported)'] === true) {
|
|
68
|
-
return true;
|
|
69
|
-
}
|
|
70
|
-
const parent = NWS_WARNINGS_SUBTYPE_PARENT[eventName];
|
|
71
|
-
return parent != null && d[parent] === true;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export function isNwsPerEventToggleHidden(hiddenMap, eventName) {
|
|
75
|
-
const h = hiddenMap ?? {};
|
|
76
|
-
if (typeof h[eventName] === 'boolean') return h[eventName] === true;
|
|
77
|
-
const parent = NWS_WARNINGS_SUBTYPE_PARENT[eventName];
|
|
78
|
-
return parent != null && h[parent] === true;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export function resolveNwsAlertUserFillOpacity(fillOpacity, eventName) {
|
|
82
|
-
const fo = fillOpacity ?? {};
|
|
83
|
-
const own = fo[eventName];
|
|
84
|
-
if (typeof own === 'number' && Number.isFinite(own)) return own;
|
|
85
|
-
const parent = NWS_WARNINGS_SUBTYPE_PARENT[eventName];
|
|
86
|
-
if (parent) {
|
|
87
|
-
const p = fo[parent];
|
|
88
|
-
if (typeof p === 'number' && Number.isFinite(p)) return p;
|
|
89
|
-
}
|
|
90
|
-
return undefined;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export function resolveNwsAlertLineStyleForEvent(lineStyles, eventName) {
|
|
94
|
-
return (lineStyles ?? {})[eventName];
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export function resolveNwsAlertLineWidths(override, baseWidth) {
|
|
98
|
-
const o = override ?? {};
|
|
99
|
-
const innerW =
|
|
100
|
-
typeof o.innerWidth === 'number' && Number.isFinite(o.innerWidth) && o.innerWidth > 0
|
|
101
|
-
? o.innerWidth
|
|
102
|
-
: baseWidth;
|
|
103
|
-
let outerW = innerW;
|
|
104
|
-
if (typeof o.casingRatio === 'number' && Number.isFinite(o.casingRatio) && o.casingRatio >= 1) {
|
|
105
|
-
outerW = innerW * o.casingRatio;
|
|
106
|
-
} else if (typeof o.outerWidth === 'number' && Number.isFinite(o.outerWidth) && o.outerWidth > 0) {
|
|
107
|
-
outerW = Math.max(innerW, o.outerWidth);
|
|
108
|
-
}
|
|
109
|
-
return { innerW, outerW };
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function mergeNwsLineStyleDefinedKeys(builtin, user) {
|
|
113
|
-
const b = { ...(builtin ?? {}) };
|
|
114
|
-
const u = user ?? {};
|
|
115
|
-
for (const k of ['innerColor', 'outerColor', 'innerWidth', 'outerWidth', 'casingRatio', 'lineDash']) {
|
|
116
|
-
if (u[k] !== undefined) b[k] = u[k];
|
|
117
|
-
}
|
|
118
|
-
return b;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export function getNwsBuiltinLineStyleForEvent(eventName, fillHex) {
|
|
122
|
-
switch (eventName) {
|
|
123
|
-
case 'Tornado Warning (PDS)':
|
|
124
|
-
case 'Severe Thunderstorm Warning (Considerable)':
|
|
125
|
-
case 'Flash Flood Warning (Considerable)':
|
|
126
|
-
return {
|
|
127
|
-
outerColor: '#000000',
|
|
128
|
-
innerColor: fillHex,
|
|
129
|
-
casingRatio: 1.5,
|
|
130
|
-
};
|
|
131
|
-
case 'Tornado Warning (Emergency)':
|
|
132
|
-
case 'Severe Thunderstorm Warning (Destructive)':
|
|
133
|
-
case 'Flash Flood Warning (Emergency)':
|
|
134
|
-
return {
|
|
135
|
-
innerColor: '#FFFFFF',
|
|
136
|
-
outerColor: fillHex,
|
|
137
|
-
casingRatio: 1.6,
|
|
138
|
-
};
|
|
139
|
-
default:
|
|
140
|
-
break;
|
|
141
|
-
}
|
|
142
|
-
if (NWS_DEFAULT_FILL_HIDDEN[eventName] === true) {
|
|
143
|
-
return {
|
|
144
|
-
outerColor: '#000000',
|
|
145
|
-
innerWidth: 3,
|
|
146
|
-
casingRatio: 1.4,
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
return undefined;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export function resolveNwsAlertLineStyleWithBuiltin(lineStyles, eventName, fillHex) {
|
|
153
|
-
const user = resolveNwsAlertLineStyleForEvent(lineStyles ?? {}, eventName);
|
|
154
|
-
const builtin = getNwsBuiltinLineStyleForEvent(eventName, fillHex);
|
|
155
|
-
return mergeNwsLineStyleDefinedKeys(builtin, user);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export function darkenHex(hex, factor = 0.75) {
|
|
159
|
-
const m = hex.match(/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i) ?? hex.match(/^#?([a-f\d])([a-f\d])([a-f\d])$/i);
|
|
160
|
-
if (!m) return hex;
|
|
161
|
-
const toNum = (s) => parseInt(s.length === 1 ? s + s : s, 16);
|
|
162
|
-
const r = Math.round(toNum(m[1]) * factor);
|
|
163
|
-
const g = Math.round(toNum(m[2]) * factor);
|
|
164
|
-
const b = Math.round(toNum(m[3]) * factor);
|
|
165
|
-
return `#${[r, g, b]
|
|
166
|
-
.map((x) => Math.max(0, Math.min(255, x)).toString(16).padStart(2, '0'))
|
|
167
|
-
.join('')}`;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const WARNING_DEFAULT_COLOR = { fill: '#f59e0b', stroke: '#d97706' };
|
|
171
|
-
|
|
172
|
-
export function getWarningColorsForEvent(eventName, userSettings) {
|
|
173
|
-
if (!eventName || typeof eventName !== 'string') return WARNING_DEFAULT_COLOR;
|
|
174
|
-
const key = eventName.trim();
|
|
175
|
-
const fill = resolveNwsAlertUserColor(userSettings?.colors ?? {}, key) ?? NWS_EVENT_COLORS[key];
|
|
176
|
-
if (!fill) return WARNING_DEFAULT_COLOR;
|
|
177
|
-
return { fill, stroke: darkenHex(fill) };
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const NWS_EMPHASIS_OUTLINE_MIN_INNER_PX = 3.5;
|
|
181
|
-
|
|
182
|
-
function nwsEventIsEmphasisOutline(eventName) {
|
|
183
|
-
return (
|
|
184
|
-
eventName.startsWith('Tornado ') ||
|
|
185
|
-
eventName.startsWith('Severe Thunderstorm ') ||
|
|
186
|
-
eventName.startsWith('Flash Flood ')
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Union of built-in convective names plus any keys referenced in user settings (so Mapbox `match`
|
|
192
|
-
* expressions include per-event colors/toggles for arbitrary alert types).
|
|
193
|
-
* @param {object} [settings]
|
|
194
|
-
* @returns {string[]}
|
|
195
|
-
*/
|
|
196
|
-
export function collectNwsExpressionEventKeys(settings) {
|
|
197
|
-
const s = new Set(NWS_ALERT_EVENT_NAMES);
|
|
198
|
-
const addObj = (o) => {
|
|
199
|
-
if (!o || typeof o !== 'object') return;
|
|
200
|
-
for (const k of Object.keys(o)) {
|
|
201
|
-
if (k) s.add(k);
|
|
202
|
-
}
|
|
203
|
-
};
|
|
204
|
-
if (settings && typeof settings === 'object') {
|
|
205
|
-
addObj(settings.colors);
|
|
206
|
-
if (Array.isArray(settings.includedAlerts)) {
|
|
207
|
-
for (const name of settings.includedAlerts) {
|
|
208
|
-
if (name != null && String(name).trim() !== '') {
|
|
209
|
-
s.add(String(name).trim());
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
addObj(settings.fillHidden);
|
|
214
|
-
addObj(settings.lineHidden);
|
|
215
|
-
addObj(settings.fillOpacity);
|
|
216
|
-
addObj(settings.lineStyles);
|
|
217
|
-
addObj(settings.flashStyles);
|
|
218
|
-
}
|
|
219
|
-
return [...s].sort((a, b) => a.localeCompare(b));
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
export function buildNwsDualLinePaint(userColors, lineStyles, baseWidth, eventNames) {
|
|
223
|
-
const names = eventNames ?? collectNwsExpressionEventKeys({ colors: userColors, lineStyles });
|
|
224
|
-
const casingColorPairs = [];
|
|
225
|
-
const coreColorPairs = [];
|
|
226
|
-
const casingWidthParts = [];
|
|
227
|
-
const coreWidthParts = [];
|
|
228
|
-
|
|
229
|
-
for (const name of names) {
|
|
230
|
-
const fill =
|
|
231
|
-
resolveNwsAlertUserColor(userColors, name) ?? NWS_EVENT_COLORS[name] ?? WARNING_DEFAULT_COLOR.fill;
|
|
232
|
-
const strokeDefault = darkenHex(fill);
|
|
233
|
-
const o = resolveNwsAlertLineStyleWithBuiltin(lineStyles, name, fill);
|
|
234
|
-
let { innerW, outerW } = resolveNwsAlertLineWidths(o, baseWidth);
|
|
235
|
-
const userLineOnly = resolveNwsAlertLineStyleForEvent(lineStyles ?? {}, name);
|
|
236
|
-
const u = userLineOnly;
|
|
237
|
-
const userCustomLineWidth =
|
|
238
|
-
(typeof u?.innerWidth === 'number' && Number.isFinite(u.innerWidth) && u.innerWidth > 0) ||
|
|
239
|
-
(typeof u?.outerWidth === 'number' && Number.isFinite(u.outerWidth) && u.outerWidth > 0) ||
|
|
240
|
-
(typeof u?.casingRatio === 'number' && Number.isFinite(u.casingRatio) && u.casingRatio >= 1);
|
|
241
|
-
if (nwsEventIsEmphasisOutline(name) && !userCustomLineWidth && innerW < NWS_EMPHASIS_OUTLINE_MIN_INNER_PX) {
|
|
242
|
-
const scale = NWS_EMPHASIS_OUTLINE_MIN_INNER_PX / innerW;
|
|
243
|
-
innerW = NWS_EMPHASIS_OUTLINE_MIN_INNER_PX;
|
|
244
|
-
outerW = Math.max(outerW * scale, innerW * 1.12);
|
|
245
|
-
}
|
|
246
|
-
const innerC =
|
|
247
|
-
typeof o?.innerColor === 'string' && o.innerColor.trim() !== '' ? o.innerColor : strokeDefault;
|
|
248
|
-
let outerC = typeof o?.outerColor === 'string' && o.outerColor.trim() !== '' ? o.outerColor : innerC;
|
|
249
|
-
if (outerW <= innerW) {
|
|
250
|
-
outerC = innerC;
|
|
251
|
-
}
|
|
252
|
-
casingColorPairs.push(name, outerC);
|
|
253
|
-
coreColorPairs.push(name, innerC);
|
|
254
|
-
casingWidthParts.push(name, outerW);
|
|
255
|
-
coreWidthParts.push(name, innerW);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
return {
|
|
259
|
-
casingColor: ['match', ['get', 'event_name'], ...casingColorPairs, WARNING_DEFAULT_COLOR.stroke],
|
|
260
|
-
coreColor: ['match', ['get', 'event_name'], ...coreColorPairs, WARNING_DEFAULT_COLOR.stroke],
|
|
261
|
-
casingWidth: ['match', ['get', 'event_name'], ...casingWidthParts, baseWidth],
|
|
262
|
-
coreWidth: ['match', ['get', 'event_name'], ...coreWidthParts, baseWidth],
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
export function buildNwsFillColorExpression(userColors, eventNames) {
|
|
267
|
-
const names = eventNames ?? collectNwsExpressionEventKeys({ colors: userColors });
|
|
268
|
-
const pairs = [];
|
|
269
|
-
for (const name of names) {
|
|
270
|
-
pairs.push(
|
|
271
|
-
name,
|
|
272
|
-
resolveNwsAlertUserColor(userColors, name) ?? NWS_EVENT_COLORS[name] ?? WARNING_DEFAULT_COLOR.fill
|
|
273
|
-
);
|
|
274
|
-
}
|
|
275
|
-
return ['match', ['get', 'event_name'], ...pairs, WARNING_DEFAULT_COLOR.fill];
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
function buildNwsPerEventFillFactorExpr(fillHidden, fillOpacityByEvent, eventNames) {
|
|
279
|
-
const fh = fillHidden ?? {};
|
|
280
|
-
const fo = fillOpacityByEvent ?? {};
|
|
281
|
-
const pairs = [];
|
|
282
|
-
const names = eventNames ?? collectNwsExpressionEventKeys({ fillHidden: fh, fillOpacity: fo });
|
|
283
|
-
for (const name of names) {
|
|
284
|
-
const hidden = isNwsPerEventToggleHidden(fh, name);
|
|
285
|
-
const raw = resolveNwsAlertUserFillOpacity(fo, name);
|
|
286
|
-
const scale =
|
|
287
|
-
typeof raw === 'number' && Number.isFinite(raw) ? Math.max(0, Math.min(1, raw)) : NWS_DEFAULT_FILL_OPACITY;
|
|
288
|
-
pairs.push(name, hidden ? 0 : scale);
|
|
289
|
-
}
|
|
290
|
-
return ['match', ['get', 'event_name'], ...pairs, NWS_DEFAULT_FILL_OPACITY];
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
function buildNwsPerEventLineFactorExpr(lineHidden, eventNames) {
|
|
294
|
-
const lh = lineHidden ?? {};
|
|
295
|
-
const pairs = [];
|
|
296
|
-
const names = eventNames ?? collectNwsExpressionEventKeys({ lineHidden: lh });
|
|
297
|
-
for (const name of names) {
|
|
298
|
-
pairs.push(name, isNwsPerEventToggleHidden(lh, name) ? 0 : 1);
|
|
299
|
-
}
|
|
300
|
-
return ['match', ['get', 'event_name'], ...pairs, 1];
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
export function buildWarningsFillOpacityExpr(visible, fillOpacity, fillHidden, fillOpacityByEvent, eventNames) {
|
|
304
|
-
const factor = buildNwsPerEventFillFactorExpr(fillHidden, fillOpacityByEvent, eventNames);
|
|
305
|
-
const base = visible ? fillOpacity : 0;
|
|
306
|
-
return ['*', base, factor];
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
export function buildWarningsLineOpacityExpr(visible, lineOpacity, lineHidden, eventNames) {
|
|
310
|
-
const factor = buildNwsPerEventLineFactorExpr(lineHidden, eventNames);
|
|
311
|
-
const base = visible ? lineOpacity : 0;
|
|
312
|
-
return ['*', base, factor];
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
function nwsWarningsLineDashLiteral(mode) {
|
|
316
|
-
if (!mode || mode === 'solid') return null;
|
|
317
|
-
if (mode === 'dash') return [3, 2];
|
|
318
|
-
return [0.5, 2];
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
function nwsLineDasharrayExprForMode(mode) {
|
|
322
|
-
const lit = nwsWarningsLineDashLiteral(mode);
|
|
323
|
-
if (lit == null) {
|
|
324
|
-
return ['literal', [1, 0]];
|
|
325
|
-
}
|
|
326
|
-
return ['literal', lit];
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
function resolveNwsAlertLineStyleForEventDash(lineStyles, name, defaultMode) {
|
|
330
|
-
return resolveNwsAlertLineStyleForEvent(lineStyles, name)?.lineDash ?? defaultMode;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
export function buildNwsLineDasharrayExpression(lineStyles, defaultMode, eventNames) {
|
|
334
|
-
const names = eventNames ?? collectNwsExpressionEventKeys({ lineStyles });
|
|
335
|
-
const pairs = [];
|
|
336
|
-
for (const name of names) {
|
|
337
|
-
const mode = resolveNwsAlertLineStyleForEventDash(lineStyles, name, defaultMode);
|
|
338
|
-
pairs.push(name, nwsLineDasharrayExprForMode(mode));
|
|
339
|
-
}
|
|
340
|
-
return ['match', ['get', 'event_name'], ...pairs, nwsLineDasharrayExprForMode(defaultMode)];
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
/** @deprecated Mapbox layers no longer use a `disabled` filter; scope is applied to GeoJSON (`alertScope` / `includedAlerts`). */
|
|
344
|
-
export function buildNwsDisabledFilterExpr(disabled) {
|
|
345
|
-
if (!disabled) return undefined;
|
|
346
|
-
const disabledNames = new Set();
|
|
347
|
-
for (const [key, val] of Object.entries(disabled)) {
|
|
348
|
-
if (val === true) disabledNames.add(key);
|
|
349
|
-
}
|
|
350
|
-
for (const subtype of Object.keys(NWS_WARNINGS_SUBTYPE_PARENT)) {
|
|
351
|
-
if (isNwsAlertDisabled(disabled, subtype)) {
|
|
352
|
-
disabledNames.add(subtype);
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
if (disabled['Tornado Warning (Reported)'] === true) {
|
|
356
|
-
disabledNames.add('Tornado Warning (Observed)');
|
|
357
|
-
}
|
|
358
|
-
if (disabledNames.size === 0) return undefined;
|
|
359
|
-
return ['!', ['in', ['get', 'event_name'], ['literal', Array.from(disabledNames)]]];
|
|
360
|
-
}
|