@aguacerowx/javascript-sdk 0.0.28 → 0.0.29
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/dist/AguaceroCore.js +794 -207
- package/dist/default-colormaps.js +556 -437
- package/dist/dictionaries.js +2069 -2411
- package/dist/events.js +2 -2
- package/dist/getBundleId.js +9 -20
- package/dist/getBundleId.native.js +18 -0
- package/dist/gridDecodePipeline.js +37 -0
- package/dist/gridDecodeWorker.js +31 -0
- package/dist/index.js +172 -1
- package/dist/nexradTiltCoalesce.js +95 -0
- package/dist/nexradTilts.js +129 -0
- package/dist/nexrad_level3_catalog.js +56 -0
- package/dist/nexrad_support.js +269 -0
- package/dist/satellite_support.js +395 -0
- package/dist/unitConversions.js +10 -10
- package/package.json +99 -99
- package/src/coordinate_configs.js +374 -374
- package/src/default-colormaps.js +3369 -3369
- package/src/dictionaries.js +3857 -3857
- package/src/events.js +31 -31
- package/src/fill-layer-worker.js +26 -26
- package/src/getBundleId.js +8 -8
- package/src/getBundleId.native.js +14 -14
- package/src/gridDecodePipeline.js +32 -32
- package/src/gridDecodeWorker.js +24 -24
- package/src/index.js +48 -48
- package/src/map-styles.js +101 -101
- package/src/nexradTiltCoalesce.js +95 -95
- package/src/nexradTilts.js +138 -128
- package/src/nexrad_level3_catalog.js +26 -26
- package/src/nexrad_support.js +40 -6
- package/src/nws/nwsAlertsFetchSpec.js +93 -93
- package/src/nws/nwsEventColorsDefaults.js +133 -133
- package/src/nws/nwsSdkConstants.js +368 -368
- package/src/satellite_support.js +376 -376
- package/src/spawnGridDecodeWorker.js +5 -5
- package/src/unitConversions.js +102 -102
|
@@ -1,368 +1,368 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* NWS alert styling defaults — palette from `nwsEventColorsDefaults.js` (synced with
|
|
3
|
-
* aguacero-frontend `defaultColormaps`). 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
|
-
/**
|
|
330
|
-
* Literal-only dash pattern for one {@link NwsWatchesWarningsOverlay} line mode (`solid` | `dash` | `dot`).
|
|
331
|
-
* Use where Mapbox RN cannot apply data-driven `line-dasharray` (see {@link buildNwsLineDasharrayExpression}).
|
|
332
|
-
*/
|
|
333
|
-
export function buildNwsLineDasharrayLiteralExpression(mode) {
|
|
334
|
-
return nwsLineDasharrayExprForMode(mode);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
function resolveNwsAlertLineStyleForEventDash(lineStyles, name, defaultMode) {
|
|
338
|
-
return resolveNwsAlertLineStyleForEvent(lineStyles, name)?.lineDash ?? defaultMode;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
export function buildNwsLineDasharrayExpression(lineStyles, defaultMode, eventNames) {
|
|
342
|
-
const names = eventNames ?? collectNwsExpressionEventKeys({ lineStyles });
|
|
343
|
-
const pairs = [];
|
|
344
|
-
for (const name of names) {
|
|
345
|
-
const mode = resolveNwsAlertLineStyleForEventDash(lineStyles, name, defaultMode);
|
|
346
|
-
pairs.push(name, nwsLineDasharrayExprForMode(mode));
|
|
347
|
-
}
|
|
348
|
-
return ['match', ['get', 'event_name'], ...pairs, nwsLineDasharrayExprForMode(defaultMode)];
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
/** @deprecated Mapbox layers no longer use a `disabled` filter; scope is applied to GeoJSON (`alertScope` / `includedAlerts`). */
|
|
352
|
-
export function buildNwsDisabledFilterExpr(disabled) {
|
|
353
|
-
if (!disabled) return undefined;
|
|
354
|
-
const disabledNames = new Set();
|
|
355
|
-
for (const [key, val] of Object.entries(disabled)) {
|
|
356
|
-
if (val === true) disabledNames.add(key);
|
|
357
|
-
}
|
|
358
|
-
for (const subtype of Object.keys(NWS_WARNINGS_SUBTYPE_PARENT)) {
|
|
359
|
-
if (isNwsAlertDisabled(disabled, subtype)) {
|
|
360
|
-
disabledNames.add(subtype);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
if (disabled['Tornado Warning (Reported)'] === true) {
|
|
364
|
-
disabledNames.add('Tornado Warning (Observed)');
|
|
365
|
-
}
|
|
366
|
-
if (disabledNames.size === 0) return undefined;
|
|
367
|
-
return ['!', ['in', ['get', 'event_name'], ['literal', Array.from(disabledNames)]]];
|
|
368
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* NWS alert styling defaults — palette from `nwsEventColorsDefaults.js` (synced with
|
|
3
|
+
* aguacero-frontend `defaultColormaps`). 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
|
+
/**
|
|
330
|
+
* Literal-only dash pattern for one {@link NwsWatchesWarningsOverlay} line mode (`solid` | `dash` | `dot`).
|
|
331
|
+
* Use where Mapbox RN cannot apply data-driven `line-dasharray` (see {@link buildNwsLineDasharrayExpression}).
|
|
332
|
+
*/
|
|
333
|
+
export function buildNwsLineDasharrayLiteralExpression(mode) {
|
|
334
|
+
return nwsLineDasharrayExprForMode(mode);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function resolveNwsAlertLineStyleForEventDash(lineStyles, name, defaultMode) {
|
|
338
|
+
return resolveNwsAlertLineStyleForEvent(lineStyles, name)?.lineDash ?? defaultMode;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export function buildNwsLineDasharrayExpression(lineStyles, defaultMode, eventNames) {
|
|
342
|
+
const names = eventNames ?? collectNwsExpressionEventKeys({ lineStyles });
|
|
343
|
+
const pairs = [];
|
|
344
|
+
for (const name of names) {
|
|
345
|
+
const mode = resolveNwsAlertLineStyleForEventDash(lineStyles, name, defaultMode);
|
|
346
|
+
pairs.push(name, nwsLineDasharrayExprForMode(mode));
|
|
347
|
+
}
|
|
348
|
+
return ['match', ['get', 'event_name'], ...pairs, nwsLineDasharrayExprForMode(defaultMode)];
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/** @deprecated Mapbox layers no longer use a `disabled` filter; scope is applied to GeoJSON (`alertScope` / `includedAlerts`). */
|
|
352
|
+
export function buildNwsDisabledFilterExpr(disabled) {
|
|
353
|
+
if (!disabled) return undefined;
|
|
354
|
+
const disabledNames = new Set();
|
|
355
|
+
for (const [key, val] of Object.entries(disabled)) {
|
|
356
|
+
if (val === true) disabledNames.add(key);
|
|
357
|
+
}
|
|
358
|
+
for (const subtype of Object.keys(NWS_WARNINGS_SUBTYPE_PARENT)) {
|
|
359
|
+
if (isNwsAlertDisabled(disabled, subtype)) {
|
|
360
|
+
disabledNames.add(subtype);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
if (disabled['Tornado Warning (Reported)'] === true) {
|
|
364
|
+
disabledNames.add('Tornado Warning (Observed)');
|
|
365
|
+
}
|
|
366
|
+
if (disabledNames.size === 0) return undefined;
|
|
367
|
+
return ['!', ['in', ['get', 'event_name'], ['literal', Array.from(disabledNames)]]];
|
|
368
|
+
}
|