use-weather-forecast 0.1.2 → 0.1.3
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/index.cjs +109 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -2
- package/dist/index.d.ts +13 -2
- package/dist/index.js +109 -22
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -134,7 +134,7 @@ async function getWeatherForecast(options = {}) {
|
|
|
134
134
|
throw new Error("Invalid weather response");
|
|
135
135
|
}
|
|
136
136
|
return {
|
|
137
|
-
location,
|
|
137
|
+
location: { ...location, timezone: data.timezone || location.timezone },
|
|
138
138
|
current: {
|
|
139
139
|
time: data.current.time,
|
|
140
140
|
temperature: Math.round(data.current.temperature_2m),
|
|
@@ -262,6 +262,7 @@ function WeatherIcon({ condition, ...props }) {
|
|
|
262
262
|
}
|
|
263
263
|
|
|
264
264
|
// src/components/WeatherForecast.tsx
|
|
265
|
+
var import_react2 = require("react");
|
|
265
266
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
266
267
|
var WIND_SPEED_UNIT_LABELS = {
|
|
267
268
|
kmh: "km/h",
|
|
@@ -276,6 +277,13 @@ function closestHour(hourly, targetTime) {
|
|
|
276
277
|
return diff < closestDiff ? hour : closest;
|
|
277
278
|
}, void 0);
|
|
278
279
|
}
|
|
280
|
+
function formatInZone(instant, timezone, options) {
|
|
281
|
+
try {
|
|
282
|
+
return new Intl.DateTimeFormat([], { ...options, timeZone: timezone || void 0 }).format(instant);
|
|
283
|
+
} catch {
|
|
284
|
+
return new Intl.DateTimeFormat([], options).format(instant);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
279
287
|
var styles = {
|
|
280
288
|
root: {
|
|
281
289
|
fontFamily: "system-ui, sans-serif",
|
|
@@ -295,37 +303,81 @@ var styles = {
|
|
|
295
303
|
compactHeaderText: { display: "flex", alignItems: "baseline", gap: 8, flexWrap: "wrap" },
|
|
296
304
|
compactDateTime: { fontSize: 11, opacity: 0.7 },
|
|
297
305
|
compactStats: { display: "flex", flexWrap: "wrap", gap: 12, fontSize: 12, opacity: 0.9 },
|
|
298
|
-
compactStat: { display: "flex", alignItems: "center", gap: 4, whiteSpace: "nowrap" }
|
|
306
|
+
compactStat: { display: "flex", alignItems: "center", gap: 4, whiteSpace: "nowrap" },
|
|
307
|
+
unitSwitch: { display: "inline-flex", alignItems: "center", cursor: "pointer", userSelect: "none" },
|
|
308
|
+
rain: { color: "#2563eb", whiteSpace: "nowrap" },
|
|
309
|
+
tz: { fontSize: 12, opacity: 0.7, marginTop: 2 },
|
|
310
|
+
list: { display: "flex", flexDirection: "column" }
|
|
299
311
|
};
|
|
300
|
-
function
|
|
301
|
-
|
|
302
|
-
|
|
312
|
+
function RainBadge({ probability, compact }) {
|
|
313
|
+
if (probability === void 0 || probability === null || probability <= 0) return null;
|
|
314
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: styles.rain, children: compact ? ` \xB7 ${probability}%` : ` \xB7 ${probability}% rain` });
|
|
315
|
+
}
|
|
316
|
+
function SingleWeatherForecast(props) {
|
|
317
|
+
const [unit, setUnit] = (0, import_react2.useState)(props.temperatureUnit ?? "fahrenheit");
|
|
318
|
+
(0, import_react2.useEffect)(() => {
|
|
319
|
+
setUnit(props.temperatureUnit ?? "fahrenheit");
|
|
320
|
+
}, [props.temperatureUnit]);
|
|
321
|
+
const { data, loading, error } = useWeatherForecast({ ...props, temperatureUnit: unit });
|
|
322
|
+
const [now, setNow] = (0, import_react2.useState)(() => /* @__PURE__ */ new Date());
|
|
323
|
+
(0, import_react2.useEffect)(() => {
|
|
324
|
+
const id = setInterval(() => setNow(/* @__PURE__ */ new Date()), 1e3);
|
|
325
|
+
return () => clearInterval(id);
|
|
326
|
+
}, []);
|
|
327
|
+
const toggleUnit = () => setUnit((u) => u === "celsius" ? "fahrenheit" : "celsius");
|
|
328
|
+
const renderUnitSwitch = (fontSize) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
329
|
+
"span",
|
|
330
|
+
{
|
|
331
|
+
role: "button",
|
|
332
|
+
tabIndex: 0,
|
|
333
|
+
onClick: (e) => {
|
|
334
|
+
e.stopPropagation();
|
|
335
|
+
toggleUnit();
|
|
336
|
+
},
|
|
337
|
+
onKeyDown: (e) => {
|
|
338
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
339
|
+
e.preventDefault();
|
|
340
|
+
toggleUnit();
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
title: "Switch temperature units",
|
|
344
|
+
"aria-label": `Switch temperature units, currently ${unit === "celsius" ? "Celsius" : "Fahrenheit"}`,
|
|
345
|
+
style: { ...styles.unitSwitch, fontSize },
|
|
346
|
+
children: [
|
|
347
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { fontWeight: unit === "fahrenheit" ? 700 : 400, opacity: unit === "fahrenheit" ? 1 : 0.45 }, children: "\xB0F" }),
|
|
348
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { opacity: 0.4, margin: "0 3px" }, children: "|" }),
|
|
349
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { fontWeight: unit === "celsius" ? 700 : 400, opacity: unit === "celsius" ? 1 : 0.45 }, children: "\xB0C" })
|
|
350
|
+
]
|
|
351
|
+
}
|
|
352
|
+
);
|
|
353
|
+
if (loading && !data) return null;
|
|
303
354
|
if (error) return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: props.className, style: props.style, children: [
|
|
304
355
|
"Error: ",
|
|
305
356
|
error.message
|
|
306
357
|
] });
|
|
307
358
|
if (!data) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: props.className, style: props.style, children: "No forecast available." });
|
|
359
|
+
const timezone = data.location?.timezone;
|
|
360
|
+
const currentDate = formatInZone(now, timezone, { weekday: "short", month: "short", day: "numeric" });
|
|
361
|
+
const currentTime = formatInZone(now, timezone, { hour: "numeric", minute: "2-digit", second: "2-digit", timeZoneName: "short" });
|
|
308
362
|
if (props.compact) {
|
|
309
|
-
const
|
|
363
|
+
const forecastBase = new Date(data.current.time);
|
|
310
364
|
const today = data.daily[0];
|
|
311
365
|
const tomorrow = data.daily[1];
|
|
312
|
-
const in6Hours = closestHour(data.hourly, new Date(
|
|
366
|
+
const in6Hours = closestHour(data.hourly, new Date(forecastBase.getTime() + 6 * 60 * 60 * 1e3));
|
|
313
367
|
const windSpeedUnitLabel = WIND_SPEED_UNIT_LABELS[props.windSpeedUnit ?? "mph"];
|
|
314
368
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: props.className, style: { ...styles.compactRoot, ...props.style }, children: [
|
|
315
369
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles.compactHeader, children: [
|
|
316
370
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(WeatherIcon, { condition: data.current.icon, width: 24, height: 24, title: "Current weather" }),
|
|
317
371
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
|
|
318
372
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles.compactHeaderText, children: [
|
|
319
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.
|
|
320
|
-
|
|
321
|
-
"\xB0"
|
|
322
|
-
] }),
|
|
373
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { style: { fontSize: 16 }, children: data.current.temperature }),
|
|
374
|
+
renderUnitSwitch(12),
|
|
323
375
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { fontSize: 14, opacity: 0.8 }, children: data.location?.city || "Current location" })
|
|
324
376
|
] }),
|
|
325
377
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles.compactDateTime, children: [
|
|
326
|
-
|
|
378
|
+
currentDate,
|
|
327
379
|
" \xB7 ",
|
|
328
|
-
|
|
380
|
+
currentTime
|
|
329
381
|
] })
|
|
330
382
|
] })
|
|
331
383
|
] }),
|
|
@@ -335,13 +387,17 @@ function WeatherForecast(props) {
|
|
|
335
387
|
today.max,
|
|
336
388
|
"\xB0 / ",
|
|
337
389
|
today.min,
|
|
338
|
-
"\xB0"
|
|
390
|
+
"\xB0",
|
|
391
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RainBadge, { probability: today.precipitationProbabilityMax, compact: true })
|
|
339
392
|
] }),
|
|
340
393
|
tomorrow && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { style: styles.compactStat, children: [
|
|
341
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(WeatherIcon, { condition: tomorrow.icon, width: 16, height: 16, title: "Tomorrow" }),
|
|
394
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(WeatherIcon, { condition: tomorrow.icon, width: 16, height: 16, title: "Tomorrow's high and low" }),
|
|
342
395
|
"Tomorrow ",
|
|
343
396
|
tomorrow.max,
|
|
344
|
-
"\xB0"
|
|
397
|
+
"\xB0 / ",
|
|
398
|
+
tomorrow.min,
|
|
399
|
+
"\xB0",
|
|
400
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RainBadge, { probability: tomorrow.precipitationProbabilityMax, compact: true })
|
|
345
401
|
] }),
|
|
346
402
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { style: styles.compactStat, children: [
|
|
347
403
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(WindIcon, { width: 16, height: 16, title: "Wind speed" }),
|
|
@@ -350,7 +406,8 @@ function WeatherForecast(props) {
|
|
|
350
406
|
in6Hours && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { style: styles.compactStat, children: [
|
|
351
407
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(WeatherIcon, { condition: in6Hours.icon, width: 16, height: 16, title: "In 6 hours" }),
|
|
352
408
|
in6Hours.temperature,
|
|
353
|
-
"\xB0 in 6h"
|
|
409
|
+
"\xB0 in 6h",
|
|
410
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RainBadge, { probability: in6Hours.precipitationProbability, compact: true })
|
|
354
411
|
] })
|
|
355
412
|
] })
|
|
356
413
|
] });
|
|
@@ -361,12 +418,16 @@ function WeatherForecast(props) {
|
|
|
361
418
|
data.location?.city || "Current location",
|
|
362
419
|
data.location?.region ? `, ${data.location.region}` : ""
|
|
363
420
|
] }),
|
|
421
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: styles.tz, children: [
|
|
422
|
+
currentDate,
|
|
423
|
+
" \xB7 ",
|
|
424
|
+
currentTime,
|
|
425
|
+
timezone ? ` \xB7 ${timezone}` : ""
|
|
426
|
+
] }),
|
|
364
427
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { ...styles.row, marginTop: 8 }, children: [
|
|
365
428
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(WeatherIcon, { condition: data.current.icon, width: 28, height: 28, title: "Current weather" }),
|
|
366
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.
|
|
367
|
-
|
|
368
|
-
"\xB0"
|
|
369
|
-
] })
|
|
429
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { style: { fontSize: 28 }, children: data.current.temperature }),
|
|
430
|
+
renderUnitSwitch(14)
|
|
370
431
|
] })
|
|
371
432
|
] }),
|
|
372
433
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { marginTop: 20 }, children: [
|
|
@@ -377,6 +438,10 @@ function WeatherForecast(props) {
|
|
|
377
438
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
|
|
378
439
|
hour.temperature,
|
|
379
440
|
"\xB0"
|
|
441
|
+
] }),
|
|
442
|
+
hour.precipitationProbability !== void 0 && hour.precipitationProbability > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { ...styles.rain, fontSize: 12 }, children: [
|
|
443
|
+
hour.precipitationProbability,
|
|
444
|
+
"%"
|
|
380
445
|
] })
|
|
381
446
|
] }, hour.time)) })
|
|
382
447
|
] }),
|
|
@@ -389,12 +454,34 @@ function WeatherForecast(props) {
|
|
|
389
454
|
day.min,
|
|
390
455
|
"\xB0 / ",
|
|
391
456
|
day.max,
|
|
392
|
-
"\xB0"
|
|
457
|
+
"\xB0",
|
|
458
|
+
day.precipitationProbabilityMax !== void 0 && day.precipitationProbabilityMax > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { style: styles.rain, children: [
|
|
459
|
+
" \xB7 ",
|
|
460
|
+
day.precipitationProbabilityMax,
|
|
461
|
+
"%"
|
|
462
|
+
] })
|
|
393
463
|
] })
|
|
394
464
|
] }, day.date)) })
|
|
395
465
|
] })
|
|
396
466
|
] });
|
|
397
467
|
}
|
|
468
|
+
function WeatherForecast(props) {
|
|
469
|
+
const { locations, ...rest } = props;
|
|
470
|
+
if (locations && locations.length > 0) {
|
|
471
|
+
const gap = props.compact ? 8 : 16;
|
|
472
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { ...styles.list, gap }, children: locations.map((loc, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
473
|
+
SingleWeatherForecast,
|
|
474
|
+
{
|
|
475
|
+
...rest,
|
|
476
|
+
latitude: typeof loc.latitude === "number" ? loc.latitude : void 0,
|
|
477
|
+
longitude: typeof loc.longitude === "number" ? loc.longitude : void 0,
|
|
478
|
+
location: { city: loc.label, timezone: loc.timezone }
|
|
479
|
+
},
|
|
480
|
+
`${loc.label ?? ""}:${loc.latitude ?? ""}:${loc.longitude ?? ""}:${index}`
|
|
481
|
+
)) });
|
|
482
|
+
}
|
|
483
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SingleWeatherForecast, { ...rest });
|
|
484
|
+
}
|
|
398
485
|
// Annotate the CommonJS export names for ESM import in node:
|
|
399
486
|
0 && (module.exports = {
|
|
400
487
|
WeatherForecast,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/weatherCodes.ts","../src/api/geolocation.ts","../src/api/forecast.ts","../src/hooks/useWeatherForecast.ts","../src/icons/BaseIcon.tsx","../src/icons/weather-icons.tsx","../src/icons/WeatherIcon.tsx","../src/components/WeatherForecast.tsx"],"sourcesContent":["export * from './types';\nexport * from './weatherCodes';\nexport * from './api/geolocation';\nexport * from './api/forecast';\nexport * from './hooks/useWeatherForecast';\nexport * from './icons/WeatherIcon';\nexport * from './components/WeatherForecast';\n","import type { WeatherCondition } from './types';\n\nexport function getWeatherIcon(code: number, isDay = 1): WeatherCondition {\n if (code === 0) return 'sun';\n if ([1, 2].includes(code)) return isDay ? 'cloud-sun' : 'clouds';\n if (code === 3) return 'clouds';\n if ([45, 48].includes(code)) return 'cloud-fog';\n if ([51, 53, 55, 56, 57].includes(code)) return 'cloud-drizzle';\n if ([61, 63].includes(code)) return 'cloud-showers';\n if ([65, 66, 67, 80, 81, 82].includes(code)) return 'cloud-showers-heavy';\n if ([71, 73, 75, 77, 85, 86].includes(code)) return 'cloud-snow';\n if (code === 95) return 'cloud-bolt';\n if ([96, 99].includes(code)) return 'cloud-hail';\n return 'clouds';\n}\n","import type { WeatherLocation } from '../types';\n\nconst DEFAULT_IP_API_URL = 'https://ipapi.co';\n\ntype IpApiResponse = {\n city?: string;\n region?: string;\n country_name?: string;\n timezone?: string;\n latitude?: number;\n longitude?: number;\n error?: boolean;\n reason?: string;\n};\n\ntype GeoWorkerResponse = {\n city?: string;\n region?: string;\n country?: string;\n timezone?: string;\n latitude?: number | string;\n longitude?: number | string;\n};\n\nexport async function getClientLocation(geoEndpoint?: string, ip?: string): Promise<WeatherLocation> {\n if (geoEndpoint) {\n const url = ip ? `${geoEndpoint}?ip=${encodeURIComponent(ip)}` : geoEndpoint;\n const res = await fetch(url);\n if (!res.ok) throw new Error(`Geolocation worker lookup failed: ${res.status}`);\n const data: GeoWorkerResponse = await res.json();\n\n return {\n city: data.city,\n region: data.region,\n country: data.country,\n timezone: data.timezone,\n latitude: Number(data.latitude),\n longitude: Number(data.longitude),\n };\n }\n\n const res = await fetch(`${DEFAULT_IP_API_URL}/${ip ? `${encodeURIComponent(ip)}/` : ''}json/`);\n if (!res.ok) throw new Error(`ipapi.co lookup failed: ${res.status}`);\n const data: IpApiResponse = await res.json();\n\n if (data.error) {\n throw new Error(`ipapi.co lookup failed: ${data.reason ?? 'unknown error'}`);\n }\n\n return {\n city: data.city,\n region: data.region,\n country: data.country_name,\n timezone: data.timezone,\n latitude: Number(data.latitude),\n longitude: Number(data.longitude),\n };\n}\n","import type { WeatherForecastData, WeatherForecastOptions, WeatherLocation } from '../types';\nimport { getWeatherIcon } from '../weatherCodes';\nimport { getClientLocation } from './geolocation';\n\nfunction buildUrl(latitude: number, longitude: number, options: WeatherForecastOptions) {\n const params = new URLSearchParams({\n latitude: String(latitude),\n longitude: String(longitude),\n timezone: options.location?.timezone || 'auto',\n temperature_unit: options.temperatureUnit || 'fahrenheit',\n wind_speed_unit: options.windSpeedUnit || 'mph',\n forecast_days: String(options.forecastDays ?? 5),\n forecast_hours: String(options.forecastHours ?? 24),\n current: [\n 'temperature_2m',\n 'weather_code',\n 'is_day',\n 'rain',\n 'showers',\n 'snowfall',\n 'wind_speed_10m',\n ].join(','),\n hourly: [\n 'temperature_2m',\n 'weather_code',\n 'precipitation_probability',\n 'rain',\n 'showers',\n 'snowfall',\n ].join(','),\n daily: [\n 'temperature_2m_max',\n 'temperature_2m_min',\n 'weather_code',\n 'precipitation_probability_max',\n ].join(','),\n });\n\n return `https://api.open-meteo.com/v1/forecast?${params.toString()}`;\n}\n\nexport async function getWeatherForecast(\n options: WeatherForecastOptions = {}\n): Promise<WeatherForecastData> {\n let location: WeatherLocation;\n\n if (typeof options.latitude === 'number' && typeof options.longitude === 'number') {\n location = {\n ...options.location,\n latitude: options.latitude,\n longitude: options.longitude,\n };\n } else {\n location = await getClientLocation(options.geoEndpoint, options.ip);\n }\n\n const url = buildUrl(location.latitude, location.longitude, { ...options, location });\n const response = await fetch(url, { headers: { 'Content-Type': 'application/json' } });\n\n if (!response.ok) {\n throw new Error(`Weather request failed: ${response.status} ${response.statusText}`);\n }\n\n const data = await response.json();\n\n if (!data?.current || !data?.hourly || !data?.daily) {\n throw new Error('Invalid weather response');\n }\n\n return {\n location,\n current: {\n time: data.current.time,\n temperature: Math.round(data.current.temperature_2m),\n weatherCode: data.current.weather_code,\n icon: getWeatherIcon(data.current.weather_code, data.current.is_day),\n isDay: data.current.is_day,\n rain: data.current.rain,\n showers: data.current.showers,\n snowfall: data.current.snowfall,\n windSpeed: data.current.wind_speed_10m,\n },\n hourly: data.hourly.time.map((time: string, index: number) => ({\n time,\n temperature: Math.round(data.hourly.temperature_2m[index]),\n weatherCode: data.hourly.weather_code[index],\n precipitationProbability: data.hourly.precipitation_probability?.[index],\n rain: data.hourly.rain?.[index],\n showers: data.hourly.showers?.[index],\n snowfall: data.hourly.snowfall?.[index],\n icon: getWeatherIcon(data.hourly.weather_code[index]),\n })),\n daily: data.daily.time.map((date: string, index: number) => ({\n date,\n min: Math.round(data.daily.temperature_2m_min[index]),\n max: Math.round(data.daily.temperature_2m_max[index]),\n weatherCode: data.daily.weather_code[index],\n precipitationProbabilityMax: data.daily.precipitation_probability_max?.[index],\n icon: getWeatherIcon(data.daily.weather_code[index]),\n })),\n };\n}\n","import { useEffect, useState } from 'react';\nimport type { WeatherForecastData, WeatherForecastOptions } from '../types';\nimport { getWeatherForecast } from '../api/forecast';\n\nexport function useWeatherForecast(options: WeatherForecastOptions = {}) {\n const [data, setData] = useState<WeatherForecastData | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n let active = true;\n setLoading(true);\n setError(null);\n\n getWeatherForecast(options)\n .then((result) => { if (active) setData(result); })\n .catch((err) => { if (active) setError(err instanceof Error ? err : new Error('Unknown error')); })\n .finally(() => { if (active) setLoading(false); });\n\n return () => { active = false; };\n }, [\n options.latitude,\n options.longitude,\n options.geoEndpoint,\n options.ip,\n options.forecastDays,\n options.forecastHours,\n options.temperatureUnit,\n options.windSpeedUnit,\n options.location?.timezone,\n ]);\n\n return { data, error, loading };\n}\n","import React from 'react';\nimport type { IconProps } from '../types';\n\nexport function BaseIcon({ title, children, ...props }: IconProps & { children: React.ReactNode }) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n role={title ? 'img' : 'presentation'}\n aria-hidden={title ? undefined : true}\n aria-label={title}\n {...props}\n >\n {title ? <title>{title}</title> : null}\n {children}\n </svg>\n );\n}\n","import React from 'react';\nimport type { IconProps } from '../types';\nimport { BaseIcon } from './BaseIcon';\n\nexport const CloudBoltIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M7 18a4.815 4.815 0 0 1-3.327-1.318A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 0 7h-1m-4.75-5L11 17.5h3.375l-2.25 4.5\" /></BaseIcon>\n);\nexport const CloudDrizzleIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M12 18v1m-3-4v1m6-1v1m2 3v1M7 19v1m-3-3.034a4.63 4.63 0 0 1-.327-.284A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 1.5 6.662\" /></BaseIcon>\n);\nexport const CloudFogIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M4 16.966a4.63 4.63 0 0 1-.327-.284A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 1.5 6.662M5 21h7m4 0h3M8 17h8\" /></BaseIcon>\n);\nexport const CloudHailIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M8 17.45v.1m-1.5 3.9v.1m10.5-4.1v.1m-1.5 3.9v.1m-3-4.1v.1m-1.5 3.9v.1m10.475-4.575A3.5 3.5 0 0 0 19 11h-1c.146-.65.148-1.32.006-1.97a4.784 4.784 0 0 0-.831-1.823 5.36 5.36 0 0 0-1.544-1.398 5.964 5.964 0 0 0-2.02-.759 6.224 6.224 0 0 0-2.19-.006 5.971 5.971 0 0 0-2.024.749C8.157 6.533 7.295 7.687 7 9a4.815 4.815 0 0 0-3.327 1.318A4.403 4.403 0 0 0 2.295 13.5c0 1.194.496 2.338 1.378 3.182.105.1.214.195.327.284m4.5.534a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Zm-1.5 4a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Zm10.5-4a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Zm-1.5 4a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Zm-3-4a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Zm-1.5 4a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Z\" /></BaseIcon>\n);\nexport const CloudShowersIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M4 16.966a4.63 4.63 0 0 1-.327-.284A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 1.5 6.662M12 13v2m0 3v2m4-5v2m0 3v2m-8-7v2m0 3v2\" /></BaseIcon>\n);\nexport const CloudShowersHeavyIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M4 16.966a4.63 4.63 0 0 1-.327-.284A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 1.5 6.662M16 15v6m-8-6v6m4-8v6\" /></BaseIcon>\n);\nexport const CloudSleetIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M13.5 17.45a1 1 0 1 0-2 0h2Zm-2 .1a1 1 0 1 0 2 0h-2Zm.5 3.9a1 1 0 1 0-2 0h2Zm-2 .1a1 1 0 1 0 2 0h-2Zm-6.327-4.868.692-.723-.692.723ZM7 9v1a1 1 0 0 0 .976-.781L7 9Zm2.397-3.207.512.858-.512-.858ZM18 11l-.976-.219A1 1 0 0 0 18 12v-1Zm2.768 5.268a1 1 0 0 0 1.414 1.414l-.707-.707-.707-.707ZM3.379 17.75a1 1 0 0 0 1.242-1.567L4 16.966l-.62.784Zm5.55-.379a1 1 0 0 0-1.857-.742L8 17l.928.371ZM5.071 21.63a1 1 0 0 0 1.856.742L6 22l-.928-.371Zm13.857-4.258a1 1 0 0 0-1.857-.742L18 17l.928.371Zm-3.857 4.258a1 1 0 0 0 1.857.742L16 22l-.928-.371ZM13 17.5h-1a.5.5 0 0 1 .5-.5v2a1.5 1.5 0 0 0 1.5-1.5h-1Zm-.5.5v-1a.5.5 0 0 1 .5.5h-2a1.5 1.5 0 0 0 1.5 1.5v-1Zm-.5-.5h1a.5.5 0 0 1-.5.5v-2a1.5 1.5 0 0 0-1.5 1.5h1Zm.5-.5v1a.5.5 0 0 1-.5-.5h2a1.5 1.5 0 0 0-1.5-1.5v1Zm0 .45h-1v.1h2v-.1h-1Zm-1 4.05h-1a.5.5 0 0 1 .5-.5v2a1.5 1.5 0 0 0 1.5-1.5h-1Zm-.5.5v-1a.5.5 0 0 1 .5.5h-2A1.5 1.5 0 0 0 11 23v-1Zm-.5-.5h1a.5.5 0 0 1-.5.5v-2a1.5 1.5 0 0 0-1.5 1.5h1Zm.5-.5v1a.5.5 0 0 1-.5-.5h2A1.5 1.5 0 0 0 11 20v1Zm0 .45h-1v.1h2v-.1h-1Zm-7.327-4.768.692-.723a3.403 3.403 0 0 1-1.07-2.459h-2c0 1.473.613 2.877 1.687 3.905l.691-.723ZM2.295 13.5h1c0-.914.38-1.8 1.07-2.46l-.692-.722-.69-.723A5.403 5.403 0 0 0 1.294 13.5h1Zm1.378-3.182.692.723A3.815 3.815 0 0 1 7 10V8c-1.499 0-2.945.57-4.018 1.595l.691.723ZM7 9l.976.219c.23-1.024.91-1.956 1.933-2.568l-.512-.858-.513-.859c-1.456.87-2.5 2.245-2.86 3.847L7 9Zm2.397-3.207.512.858a4.972 4.972 0 0 1 1.686-.622l-.173-.985-.174-.985a6.971 6.971 0 0 0-2.364.875l.513.859Zm2.025-.749.173.985a5.223 5.223 0 0 1 1.837.005l.18-.984.178-.984a7.223 7.223 0 0 0-2.542-.007l.174.985Zm2.19.006-.18.984c.606.11 1.177.326 1.681.631l.518-.856.518-.855a6.963 6.963 0 0 0-2.359-.888l-.179.984Zm2.02.76-.519.855c.505.305.93.693 1.257 1.136l.805-.594.805-.594a6.361 6.361 0 0 0-1.831-1.659l-.518.855Zm1.543 1.397-.805.594c.326.442.549.932.66 1.441l.976-.212.978-.213a5.786 5.786 0 0 0-1.005-2.204l-.804.594Zm.831 1.823-.977.212c.111.509.11 1.031-.005 1.539L18 11l.976.219c.178-.792.18-1.609.008-2.402l-.978.213ZM18 11v1h1v-2h-1v1Zm1 0v1a2.5 2.5 0 0 1 1.768.732l.707-.707.707-.707A4.5 4.5 0 0 0 19 10v1Zm2.475 1.025-.707.707A2.5 2.5 0 0 1 21.5 14.5h2a4.5 4.5 0 0 0-1.318-3.182l-.707.707ZM22.5 14.5h-1a2.5 2.5 0 0 1-.732 1.768l.707.707.707.707A4.5 4.5 0 0 0 23.5 14.5h-1ZM4 16.966l.62-.784a3.684 3.684 0 0 1-.255-.223l-.692.723-.69.723c.126.121.259.237.396.345L4 16.966ZM8 17l-.928-.371-2 5L6 22l.928.371 2-5L8 17Zm10 0-.928-.371-2 5L16 22l.928.371 2-5L18 17Z\" /></BaseIcon>\n);\nexport const CloudSnowIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M8 15h2m-1-1v2m5-1h2m-1-1v2M5 21h2m-1-1v2m5-2h2m-1-1v2m5 0h2m-1-1v2M4 16.966a4.63 4.63 0 0 1-.327-.284A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 1.5 6.662\" /></BaseIcon>\n);\nexport const CloudSunIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M10.201 19.997c-1.977 0-3.58-1.544-3.58-3.448 0-1.903 1.603-3.446 3.58-3.446.303-1.355 1.38-2.461 2.827-2.902 1.445-.44 3.042-.148 4.186.77 1.144.915 1.663 2.312 1.361 3.667h.761c1.472 0 2.664 1.2 2.664 2.68A2.672 2.672 0 0 1 19.336 20h-9.134m2.66-12.934a4.166 4.166 0 0 0-2.677-1.732m2.677 1.732 2.744-1.892m-2.744 1.892c.55.796.802 1.754.723 2.709m-3.4-4.44a4.167 4.167 0 0 0-3.118.667m3.118-.668.602-3.278m-3.72 3.946A4.167 4.167 0 0 0 5.334 8.68m1.733-2.678L5.174 3.26m.16 5.42c-.2 1.088.041 2.21.669 3.12m-.669-3.12-3.278-.601m3.947 3.72-2.744 1.893m2.744-1.893a4.167 4.167 0 0 0 2.174 1.607\" /></BaseIcon>\n);\nexport const CloudsIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M8.958 21.05C6.772 21.05 5 19.344 5 17.24s1.772-3.81 3.958-3.81c.335-1.498 1.525-2.72 3.124-3.207 1.598-.487 3.363-.164 4.628.85 1.264 1.011 1.837 2.556 1.504 4.053h.842A2.953 2.953 0 0 1 22 18.09a2.954 2.954 0 0 1-2.945 2.964H8.958M18 8c-.5-2.5-3.532-3.401-5.5-2.5a3.117 3.117 0 0 0-2.11-2.312c-1.352-.411-2.845-.138-3.915.72-1.07.855-1.554 2.161-1.273 3.428h-.711A2.498 2.498 0 0 0 2 9.843c0 1.094.695 2.023 1.666 2.366\" /></BaseIcon>\n);\nexport const SnowflakeIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"m9.25 4-1 2H6m-2.25 4L5 12m0 0-1.25 2M5 12h3m-3 0H2.5m17.75-2L19 12l1.25 2M6 18h2.25l1 2M14 9h-4m4 0 3-5m-3 5 2 3m-6-3L7 4m3 5-2 3m0 0 2 3m0 0-3 5m3-5h4m2-3-2 3m2-3h5.5M14 15l3 5M14.75 4l1 2H18m0 12h-2.25l-1 2\" /></BaseIcon>\n);\nexport const SunIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M12 4V2m0 20v-2m10-8h-2M4 12H2m15.657-5.657 1.414-1.414M4.93 19.07l1.414-1.414m12.728 1.414-1.414-1.414M6.343 6.343 4.93 4.929M7 12a5 5 0 1 0 10 0 5 5 0 0 0-10 0Z\" /></BaseIcon>\n);\nexport const WindIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M9.59 4.59A2 2 0 1 1 11 8H2m10.59 11.41A2 2 0 1 0 14 16H2m15.73-8.27A2.5 2.5 0 1 1 19.5 12H2\" /></BaseIcon>\n);\n","import React from 'react';\nimport type { IconProps, WeatherCondition } from '../types';\nimport {\n CloudBoltIcon,\n CloudDrizzleIcon,\n CloudFogIcon,\n CloudHailIcon,\n CloudShowersHeavyIcon,\n CloudShowersIcon,\n CloudSleetIcon,\n CloudSnowIcon,\n CloudSunIcon,\n CloudsIcon,\n SnowflakeIcon,\n SunIcon,\n} from './weather-icons';\n\nconst iconMap: Record<WeatherCondition, React.ComponentType<IconProps>> = {\n sun: SunIcon,\n 'cloud-sun': CloudSunIcon,\n clouds: CloudsIcon,\n 'cloud-fog': CloudFogIcon,\n 'cloud-drizzle': CloudDrizzleIcon,\n 'cloud-showers': CloudShowersIcon,\n 'cloud-showers-heavy': CloudShowersHeavyIcon,\n 'cloud-sleet': CloudSleetIcon,\n 'cloud-snow': CloudSnowIcon,\n snowflake: SnowflakeIcon,\n 'cloud-bolt': CloudBoltIcon,\n 'cloud-hail': CloudHailIcon,\n};\n\nexport function WeatherIcon({ condition, ...props }: IconProps & { condition: WeatherCondition }) {\n const Icon = iconMap[condition] || CloudsIcon;\n return <Icon {...props} />;\n}\n","import React from 'react';\nimport { useWeatherForecast } from '../hooks/useWeatherForecast';\nimport type { HourlyWeather, WeatherForecastOptions, WindSpeedUnit } from '../types';\nimport { WeatherIcon } from '../icons/WeatherIcon';\nimport { WindIcon } from '../icons/weather-icons';\n\ntype Props = WeatherForecastOptions & {\n className?: string;\n style?: React.CSSProperties;\n compact?: boolean;\n};\n\nconst WIND_SPEED_UNIT_LABELS: Record<WindSpeedUnit, string> = {\n kmh: 'km/h',\n mph: 'mph',\n ms: 'm/s',\n kn: 'kn',\n};\n\nfunction closestHour(hourly: HourlyWeather[], targetTime: Date): HourlyWeather | undefined {\n return hourly.reduce<HourlyWeather | undefined>((closest, hour) => {\n const diff = Math.abs(new Date(hour.time).getTime() - targetTime.getTime());\n const closestDiff = closest ? Math.abs(new Date(closest.time).getTime() - targetTime.getTime()) : Infinity;\n return diff < closestDiff ? hour : closest;\n }, undefined);\n}\n\nconst styles = {\n root: {\n fontFamily: 'system-ui, sans-serif',\n border: '1px solid #e5e7eb',\n borderRadius: 12,\n padding: 16,\n background: '#fff',\n color: '#111827',\n maxWidth: 640,\n } as React.CSSProperties,\n row: { display: 'flex', alignItems: 'center', gap: 8 } as React.CSSProperties,\n hours: { display: 'flex', gap: 12, overflowX: 'auto', paddingBottom: 4 } as React.CSSProperties,\n hourCard: { minWidth: 72, textAlign: 'center' as const, padding: 8, borderRadius: 8, background: '#f9fafb' },\n dayRow: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, padding: '8px 0', borderBottom: '1px solid #f3f4f6' } as React.CSSProperties,\n compactRoot: { fontFamily: 'system-ui, sans-serif', display: 'flex', flexDirection: 'column', gap: 8, padding: '10px 14px', borderRadius: 8 } as React.CSSProperties,\n compactHeader: { display: 'flex', alignItems: 'center', gap: 10 } as React.CSSProperties,\n compactHeaderText: { display: 'flex', alignItems: 'baseline', gap: 8, flexWrap: 'wrap' } as React.CSSProperties,\n compactDateTime: { fontSize: 11, opacity: 0.7 } as React.CSSProperties,\n compactStats: { display: 'flex', flexWrap: 'wrap', gap: 12, fontSize: 12, opacity: 0.9 } as React.CSSProperties,\n compactStat: { display: 'flex', alignItems: 'center', gap: 4, whiteSpace: 'nowrap' } as React.CSSProperties,\n};\n\nexport function WeatherForecast(props: Props) {\n const { data, loading, error } = useWeatherForecast(props);\n\n if (loading) return null;\n if (error) return <div className={props.className} style={props.style}>Error: {error.message}</div>;\n if (!data) return <div className={props.className} style={props.style}>No forecast available.</div>;\n\n if (props.compact) {\n const now = new Date(data.current.time);\n const today = data.daily[0];\n const tomorrow = data.daily[1];\n const in6Hours = closestHour(data.hourly, new Date(now.getTime() + 6 * 60 * 60 * 1000));\n const windSpeedUnitLabel = WIND_SPEED_UNIT_LABELS[props.windSpeedUnit ?? 'mph'];\n\n return (\n <div className={props.className} style={{ ...styles.compactRoot, ...props.style }}>\n <div style={styles.compactHeader}>\n <WeatherIcon condition={data.current.icon} width={24} height={24} title=\"Current weather\" />\n <div>\n <div style={styles.compactHeaderText}>\n <strong style={{ fontSize: 16 }}>{data.current.temperature}°</strong>\n <span style={{ fontSize: 14, opacity: 0.8 }}>\n {data.location?.city || 'Current location'}\n </span>\n </div>\n <div style={styles.compactDateTime}>\n {now.toLocaleDateString([], { weekday: 'short', month: 'short', day: 'numeric' })}\n {' · '}\n {now.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' })}\n </div>\n </div>\n </div>\n\n <div style={styles.compactStats}>\n {today && (\n <span style={styles.compactStat}>\n <WeatherIcon condition={today.icon} width={16} height={16} title=\"Today's high and low\" />\n {today.max}° / {today.min}°\n </span>\n )}\n {tomorrow && (\n <span style={styles.compactStat}>\n <WeatherIcon condition={tomorrow.icon} width={16} height={16} title=\"Tomorrow\" />\n Tomorrow {tomorrow.max}°\n </span>\n )}\n <span style={styles.compactStat}>\n <WindIcon width={16} height={16} title=\"Wind speed\" />\n {data.current.windSpeed !== undefined ? `${Math.round(data.current.windSpeed)} ${windSpeedUnitLabel}` : '—'}\n </span>\n {in6Hours && (\n <span style={styles.compactStat}>\n <WeatherIcon condition={in6Hours.icon} width={16} height={16} title=\"In 6 hours\" />\n {in6Hours.temperature}° in 6h\n </span>\n )}\n </div>\n </div>\n );\n }\n\n return (\n <div className={props.className} style={{ ...styles.root, ...props.style }}>\n <div>\n <h3 style={{ margin: 0, fontSize: 20 }}>\n {data.location?.city || 'Current location'}\n {data.location?.region ? `, ${data.location.region}` : ''}\n </h3>\n <div style={{ ...styles.row, marginTop: 8 }}>\n <WeatherIcon condition={data.current.icon} width={28} height={28} title=\"Current weather\" />\n <strong style={{ fontSize: 28 }}>{data.current.temperature}°</strong>\n </div>\n </div>\n\n <div style={{ marginTop: 20 }}>\n <h4 style={{ margin: '0 0 10px 0' }}>Next hours</h4>\n <div style={styles.hours}>\n {data.hourly.slice(0, props.forecastHours ?? 12).map((hour) => (\n <div key={hour.time} style={styles.hourCard}>\n <div style={{ fontSize: 12 }}>{new Date(hour.time).toLocaleTimeString([], { hour: 'numeric' })}</div>\n <WeatherIcon condition={hour.icon} width={20} height={20} style={{ margin: '6px auto' }} />\n <div>{hour.temperature}°</div>\n </div>\n ))}\n </div>\n </div>\n\n <div style={{ marginTop: 20 }}>\n <h4 style={{ margin: '0 0 10px 0' }}>Next days</h4>\n <div>\n {data.daily.map((day) => (\n <div key={day.date} style={styles.dayRow}>\n <div style={{ width: 120 }}>{new Date(day.date).toLocaleDateString([], { weekday: 'short', month: 'short', day: 'numeric' })}</div>\n <WeatherIcon condition={day.icon} width={20} height={20} />\n <div>{day.min}° / {day.max}°</div>\n </div>\n ))}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["res","data","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/weatherCodes.ts","../src/api/geolocation.ts","../src/api/forecast.ts","../src/hooks/useWeatherForecast.ts","../src/icons/BaseIcon.tsx","../src/icons/weather-icons.tsx","../src/icons/WeatherIcon.tsx","../src/components/WeatherForecast.tsx"],"sourcesContent":["export * from './types';\nexport * from './weatherCodes';\nexport * from './api/geolocation';\nexport * from './api/forecast';\nexport * from './hooks/useWeatherForecast';\nexport * from './icons/WeatherIcon';\nexport * from './components/WeatherForecast';\n","import type { WeatherCondition } from './types';\n\nexport function getWeatherIcon(code: number, isDay = 1): WeatherCondition {\n if (code === 0) return 'sun';\n if ([1, 2].includes(code)) return isDay ? 'cloud-sun' : 'clouds';\n if (code === 3) return 'clouds';\n if ([45, 48].includes(code)) return 'cloud-fog';\n if ([51, 53, 55, 56, 57].includes(code)) return 'cloud-drizzle';\n if ([61, 63].includes(code)) return 'cloud-showers';\n if ([65, 66, 67, 80, 81, 82].includes(code)) return 'cloud-showers-heavy';\n if ([71, 73, 75, 77, 85, 86].includes(code)) return 'cloud-snow';\n if (code === 95) return 'cloud-bolt';\n if ([96, 99].includes(code)) return 'cloud-hail';\n return 'clouds';\n}\n","import type { WeatherLocation } from '../types';\n\nconst DEFAULT_IP_API_URL = 'https://ipapi.co';\n\ntype IpApiResponse = {\n city?: string;\n region?: string;\n country_name?: string;\n timezone?: string;\n latitude?: number;\n longitude?: number;\n error?: boolean;\n reason?: string;\n};\n\ntype GeoWorkerResponse = {\n city?: string;\n region?: string;\n country?: string;\n timezone?: string;\n latitude?: number | string;\n longitude?: number | string;\n};\n\nexport async function getClientLocation(geoEndpoint?: string, ip?: string): Promise<WeatherLocation> {\n if (geoEndpoint) {\n const url = ip ? `${geoEndpoint}?ip=${encodeURIComponent(ip)}` : geoEndpoint;\n const res = await fetch(url);\n if (!res.ok) throw new Error(`Geolocation worker lookup failed: ${res.status}`);\n const data: GeoWorkerResponse = await res.json();\n\n return {\n city: data.city,\n region: data.region,\n country: data.country,\n timezone: data.timezone,\n latitude: Number(data.latitude),\n longitude: Number(data.longitude),\n };\n }\n\n const res = await fetch(`${DEFAULT_IP_API_URL}/${ip ? `${encodeURIComponent(ip)}/` : ''}json/`);\n if (!res.ok) throw new Error(`ipapi.co lookup failed: ${res.status}`);\n const data: IpApiResponse = await res.json();\n\n if (data.error) {\n throw new Error(`ipapi.co lookup failed: ${data.reason ?? 'unknown error'}`);\n }\n\n return {\n city: data.city,\n region: data.region,\n country: data.country_name,\n timezone: data.timezone,\n latitude: Number(data.latitude),\n longitude: Number(data.longitude),\n };\n}\n","import type { WeatherForecastData, WeatherForecastOptions, WeatherLocation } from '../types';\nimport { getWeatherIcon } from '../weatherCodes';\nimport { getClientLocation } from './geolocation';\n\nfunction buildUrl(latitude: number, longitude: number, options: WeatherForecastOptions) {\n const params = new URLSearchParams({\n latitude: String(latitude),\n longitude: String(longitude),\n timezone: options.location?.timezone || 'auto',\n temperature_unit: options.temperatureUnit || 'fahrenheit',\n wind_speed_unit: options.windSpeedUnit || 'mph',\n forecast_days: String(options.forecastDays ?? 5),\n forecast_hours: String(options.forecastHours ?? 24),\n current: [\n 'temperature_2m',\n 'weather_code',\n 'is_day',\n 'rain',\n 'showers',\n 'snowfall',\n 'wind_speed_10m',\n ].join(','),\n hourly: [\n 'temperature_2m',\n 'weather_code',\n 'precipitation_probability',\n 'rain',\n 'showers',\n 'snowfall',\n ].join(','),\n daily: [\n 'temperature_2m_max',\n 'temperature_2m_min',\n 'weather_code',\n 'precipitation_probability_max',\n ].join(','),\n });\n\n return `https://api.open-meteo.com/v1/forecast?${params.toString()}`;\n}\n\nexport async function getWeatherForecast(\n options: WeatherForecastOptions = {}\n): Promise<WeatherForecastData> {\n let location: WeatherLocation;\n\n if (typeof options.latitude === 'number' && typeof options.longitude === 'number') {\n location = {\n ...options.location,\n latitude: options.latitude,\n longitude: options.longitude,\n };\n } else {\n location = await getClientLocation(options.geoEndpoint, options.ip);\n }\n\n const url = buildUrl(location.latitude, location.longitude, { ...options, location });\n const response = await fetch(url, { headers: { 'Content-Type': 'application/json' } });\n\n if (!response.ok) {\n throw new Error(`Weather request failed: ${response.status} ${response.statusText}`);\n }\n\n const data = await response.json();\n\n if (!data?.current || !data?.hourly || !data?.daily) {\n throw new Error('Invalid weather response');\n }\n\n return {\n location: { ...location, timezone: data.timezone || location.timezone },\n current: {\n time: data.current.time,\n temperature: Math.round(data.current.temperature_2m),\n weatherCode: data.current.weather_code,\n icon: getWeatherIcon(data.current.weather_code, data.current.is_day),\n isDay: data.current.is_day,\n rain: data.current.rain,\n showers: data.current.showers,\n snowfall: data.current.snowfall,\n windSpeed: data.current.wind_speed_10m,\n },\n hourly: data.hourly.time.map((time: string, index: number) => ({\n time,\n temperature: Math.round(data.hourly.temperature_2m[index]),\n weatherCode: data.hourly.weather_code[index],\n precipitationProbability: data.hourly.precipitation_probability?.[index],\n rain: data.hourly.rain?.[index],\n showers: data.hourly.showers?.[index],\n snowfall: data.hourly.snowfall?.[index],\n icon: getWeatherIcon(data.hourly.weather_code[index]),\n })),\n daily: data.daily.time.map((date: string, index: number) => ({\n date,\n min: Math.round(data.daily.temperature_2m_min[index]),\n max: Math.round(data.daily.temperature_2m_max[index]),\n weatherCode: data.daily.weather_code[index],\n precipitationProbabilityMax: data.daily.precipitation_probability_max?.[index],\n icon: getWeatherIcon(data.daily.weather_code[index]),\n })),\n };\n}\n","import { useEffect, useState } from 'react';\nimport type { WeatherForecastData, WeatherForecastOptions } from '../types';\nimport { getWeatherForecast } from '../api/forecast';\n\nexport function useWeatherForecast(options: WeatherForecastOptions = {}) {\n const [data, setData] = useState<WeatherForecastData | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n let active = true;\n setLoading(true);\n setError(null);\n\n getWeatherForecast(options)\n .then((result) => { if (active) setData(result); })\n .catch((err) => { if (active) setError(err instanceof Error ? err : new Error('Unknown error')); })\n .finally(() => { if (active) setLoading(false); });\n\n return () => { active = false; };\n }, [\n options.latitude,\n options.longitude,\n options.geoEndpoint,\n options.ip,\n options.forecastDays,\n options.forecastHours,\n options.temperatureUnit,\n options.windSpeedUnit,\n options.location?.timezone,\n ]);\n\n return { data, error, loading };\n}\n","import React from 'react';\nimport type { IconProps } from '../types';\n\nexport function BaseIcon({ title, children, ...props }: IconProps & { children: React.ReactNode }) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n role={title ? 'img' : 'presentation'}\n aria-hidden={title ? undefined : true}\n aria-label={title}\n {...props}\n >\n {title ? <title>{title}</title> : null}\n {children}\n </svg>\n );\n}\n","import React from 'react';\nimport type { IconProps } from '../types';\nimport { BaseIcon } from './BaseIcon';\n\nexport const CloudBoltIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M7 18a4.815 4.815 0 0 1-3.327-1.318A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 0 7h-1m-4.75-5L11 17.5h3.375l-2.25 4.5\" /></BaseIcon>\n);\nexport const CloudDrizzleIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M12 18v1m-3-4v1m6-1v1m2 3v1M7 19v1m-3-3.034a4.63 4.63 0 0 1-.327-.284A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 1.5 6.662\" /></BaseIcon>\n);\nexport const CloudFogIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M4 16.966a4.63 4.63 0 0 1-.327-.284A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 1.5 6.662M5 21h7m4 0h3M8 17h8\" /></BaseIcon>\n);\nexport const CloudHailIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M8 17.45v.1m-1.5 3.9v.1m10.5-4.1v.1m-1.5 3.9v.1m-3-4.1v.1m-1.5 3.9v.1m10.475-4.575A3.5 3.5 0 0 0 19 11h-1c.146-.65.148-1.32.006-1.97a4.784 4.784 0 0 0-.831-1.823 5.36 5.36 0 0 0-1.544-1.398 5.964 5.964 0 0 0-2.02-.759 6.224 6.224 0 0 0-2.19-.006 5.971 5.971 0 0 0-2.024.749C8.157 6.533 7.295 7.687 7 9a4.815 4.815 0 0 0-3.327 1.318A4.403 4.403 0 0 0 2.295 13.5c0 1.194.496 2.338 1.378 3.182.105.1.214.195.327.284m4.5.534a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Zm-1.5 4a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Zm10.5-4a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Zm-1.5 4a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Zm-3-4a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Zm-1.5 4a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Z\" /></BaseIcon>\n);\nexport const CloudShowersIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M4 16.966a4.63 4.63 0 0 1-.327-.284A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 1.5 6.662M12 13v2m0 3v2m4-5v2m0 3v2m-8-7v2m0 3v2\" /></BaseIcon>\n);\nexport const CloudShowersHeavyIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M4 16.966a4.63 4.63 0 0 1-.327-.284A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 1.5 6.662M16 15v6m-8-6v6m4-8v6\" /></BaseIcon>\n);\nexport const CloudSleetIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M13.5 17.45a1 1 0 1 0-2 0h2Zm-2 .1a1 1 0 1 0 2 0h-2Zm.5 3.9a1 1 0 1 0-2 0h2Zm-2 .1a1 1 0 1 0 2 0h-2Zm-6.327-4.868.692-.723-.692.723ZM7 9v1a1 1 0 0 0 .976-.781L7 9Zm2.397-3.207.512.858-.512-.858ZM18 11l-.976-.219A1 1 0 0 0 18 12v-1Zm2.768 5.268a1 1 0 0 0 1.414 1.414l-.707-.707-.707-.707ZM3.379 17.75a1 1 0 0 0 1.242-1.567L4 16.966l-.62.784Zm5.55-.379a1 1 0 0 0-1.857-.742L8 17l.928.371ZM5.071 21.63a1 1 0 0 0 1.856.742L6 22l-.928-.371Zm13.857-4.258a1 1 0 0 0-1.857-.742L18 17l.928.371Zm-3.857 4.258a1 1 0 0 0 1.857.742L16 22l-.928-.371ZM13 17.5h-1a.5.5 0 0 1 .5-.5v2a1.5 1.5 0 0 0 1.5-1.5h-1Zm-.5.5v-1a.5.5 0 0 1 .5.5h-2a1.5 1.5 0 0 0 1.5 1.5v-1Zm-.5-.5h1a.5.5 0 0 1-.5.5v-2a1.5 1.5 0 0 0-1.5 1.5h1Zm.5-.5v1a.5.5 0 0 1-.5-.5h2a1.5 1.5 0 0 0-1.5-1.5v1Zm0 .45h-1v.1h2v-.1h-1Zm-1 4.05h-1a.5.5 0 0 1 .5-.5v2a1.5 1.5 0 0 0 1.5-1.5h-1Zm-.5.5v-1a.5.5 0 0 1 .5.5h-2A1.5 1.5 0 0 0 11 23v-1Zm-.5-.5h1a.5.5 0 0 1-.5.5v-2a1.5 1.5 0 0 0-1.5 1.5h1Zm.5-.5v1a.5.5 0 0 1-.5-.5h2A1.5 1.5 0 0 0 11 20v1Zm0 .45h-1v.1h2v-.1h-1Zm-7.327-4.768.692-.723a3.403 3.403 0 0 1-1.07-2.459h-2c0 1.473.613 2.877 1.687 3.905l.691-.723ZM2.295 13.5h1c0-.914.38-1.8 1.07-2.46l-.692-.722-.69-.723A5.403 5.403 0 0 0 1.294 13.5h1Zm1.378-3.182.692.723A3.815 3.815 0 0 1 7 10V8c-1.499 0-2.945.57-4.018 1.595l.691.723ZM7 9l.976.219c.23-1.024.91-1.956 1.933-2.568l-.512-.858-.513-.859c-1.456.87-2.5 2.245-2.86 3.847L7 9Zm2.397-3.207.512.858a4.972 4.972 0 0 1 1.686-.622l-.173-.985-.174-.985a6.971 6.971 0 0 0-2.364.875l.513.859Zm2.025-.749.173.985a5.223 5.223 0 0 1 1.837.005l.18-.984.178-.984a7.223 7.223 0 0 0-2.542-.007l.174.985Zm2.19.006-.18.984c.606.11 1.177.326 1.681.631l.518-.856.518-.855a6.963 6.963 0 0 0-2.359-.888l-.179.984Zm2.02.76-.519.855c.505.305.93.693 1.257 1.136l.805-.594.805-.594a6.361 6.361 0 0 0-1.831-1.659l-.518.855Zm1.543 1.397-.805.594c.326.442.549.932.66 1.441l.976-.212.978-.213a5.786 5.786 0 0 0-1.005-2.204l-.804.594Zm.831 1.823-.977.212c.111.509.11 1.031-.005 1.539L18 11l.976.219c.178-.792.18-1.609.008-2.402l-.978.213ZM18 11v1h1v-2h-1v1Zm1 0v1a2.5 2.5 0 0 1 1.768.732l.707-.707.707-.707A4.5 4.5 0 0 0 19 10v1Zm2.475 1.025-.707.707A2.5 2.5 0 0 1 21.5 14.5h2a4.5 4.5 0 0 0-1.318-3.182l-.707.707ZM22.5 14.5h-1a2.5 2.5 0 0 1-.732 1.768l.707.707.707.707A4.5 4.5 0 0 0 23.5 14.5h-1ZM4 16.966l.62-.784a3.684 3.684 0 0 1-.255-.223l-.692.723-.69.723c.126.121.259.237.396.345L4 16.966ZM8 17l-.928-.371-2 5L6 22l.928.371 2-5L8 17Zm10 0-.928-.371-2 5L16 22l.928.371 2-5L18 17Z\" /></BaseIcon>\n);\nexport const CloudSnowIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M8 15h2m-1-1v2m5-1h2m-1-1v2M5 21h2m-1-1v2m5-2h2m-1-1v2m5 0h2m-1-1v2M4 16.966a4.63 4.63 0 0 1-.327-.284A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 1.5 6.662\" /></BaseIcon>\n);\nexport const CloudSunIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M10.201 19.997c-1.977 0-3.58-1.544-3.58-3.448 0-1.903 1.603-3.446 3.58-3.446.303-1.355 1.38-2.461 2.827-2.902 1.445-.44 3.042-.148 4.186.77 1.144.915 1.663 2.312 1.361 3.667h.761c1.472 0 2.664 1.2 2.664 2.68A2.672 2.672 0 0 1 19.336 20h-9.134m2.66-12.934a4.166 4.166 0 0 0-2.677-1.732m2.677 1.732 2.744-1.892m-2.744 1.892c.55.796.802 1.754.723 2.709m-3.4-4.44a4.167 4.167 0 0 0-3.118.667m3.118-.668.602-3.278m-3.72 3.946A4.167 4.167 0 0 0 5.334 8.68m1.733-2.678L5.174 3.26m.16 5.42c-.2 1.088.041 2.21.669 3.12m-.669-3.12-3.278-.601m3.947 3.72-2.744 1.893m2.744-1.893a4.167 4.167 0 0 0 2.174 1.607\" /></BaseIcon>\n);\nexport const CloudsIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M8.958 21.05C6.772 21.05 5 19.344 5 17.24s1.772-3.81 3.958-3.81c.335-1.498 1.525-2.72 3.124-3.207 1.598-.487 3.363-.164 4.628.85 1.264 1.011 1.837 2.556 1.504 4.053h.842A2.953 2.953 0 0 1 22 18.09a2.954 2.954 0 0 1-2.945 2.964H8.958M18 8c-.5-2.5-3.532-3.401-5.5-2.5a3.117 3.117 0 0 0-2.11-2.312c-1.352-.411-2.845-.138-3.915.72-1.07.855-1.554 2.161-1.273 3.428h-.711A2.498 2.498 0 0 0 2 9.843c0 1.094.695 2.023 1.666 2.366\" /></BaseIcon>\n);\nexport const SnowflakeIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"m9.25 4-1 2H6m-2.25 4L5 12m0 0-1.25 2M5 12h3m-3 0H2.5m17.75-2L19 12l1.25 2M6 18h2.25l1 2M14 9h-4m4 0 3-5m-3 5 2 3m-6-3L7 4m3 5-2 3m0 0 2 3m0 0-3 5m3-5h4m2-3-2 3m2-3h5.5M14 15l3 5M14.75 4l1 2H18m0 12h-2.25l-1 2\" /></BaseIcon>\n);\nexport const SunIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M12 4V2m0 20v-2m10-8h-2M4 12H2m15.657-5.657 1.414-1.414M4.93 19.07l1.414-1.414m12.728 1.414-1.414-1.414M6.343 6.343 4.93 4.929M7 12a5 5 0 1 0 10 0 5 5 0 0 0-10 0Z\" /></BaseIcon>\n);\nexport const WindIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M9.59 4.59A2 2 0 1 1 11 8H2m10.59 11.41A2 2 0 1 0 14 16H2m15.73-8.27A2.5 2.5 0 1 1 19.5 12H2\" /></BaseIcon>\n);\n","import React from 'react';\nimport type { IconProps, WeatherCondition } from '../types';\nimport {\n CloudBoltIcon,\n CloudDrizzleIcon,\n CloudFogIcon,\n CloudHailIcon,\n CloudShowersHeavyIcon,\n CloudShowersIcon,\n CloudSleetIcon,\n CloudSnowIcon,\n CloudSunIcon,\n CloudsIcon,\n SnowflakeIcon,\n SunIcon,\n} from './weather-icons';\n\nconst iconMap: Record<WeatherCondition, React.ComponentType<IconProps>> = {\n sun: SunIcon,\n 'cloud-sun': CloudSunIcon,\n clouds: CloudsIcon,\n 'cloud-fog': CloudFogIcon,\n 'cloud-drizzle': CloudDrizzleIcon,\n 'cloud-showers': CloudShowersIcon,\n 'cloud-showers-heavy': CloudShowersHeavyIcon,\n 'cloud-sleet': CloudSleetIcon,\n 'cloud-snow': CloudSnowIcon,\n snowflake: SnowflakeIcon,\n 'cloud-bolt': CloudBoltIcon,\n 'cloud-hail': CloudHailIcon,\n};\n\nexport function WeatherIcon({ condition, ...props }: IconProps & { condition: WeatherCondition }) {\n const Icon = iconMap[condition] || CloudsIcon;\n return <Icon {...props} />;\n}\n","import React, { useEffect, useState } from 'react';\nimport { useWeatherForecast } from '../hooks/useWeatherForecast';\nimport type { HourlyWeather, TemperatureUnit, WeatherForecastOptions, WindSpeedUnit } from '../types';\nimport { WeatherIcon } from '../icons/WeatherIcon';\nimport { WindIcon } from '../icons/weather-icons';\n\ntype Props = WeatherForecastOptions & {\n className?: string;\n style?: React.CSSProperties;\n compact?: boolean;\n};\n\nconst WIND_SPEED_UNIT_LABELS: Record<WindSpeedUnit, string> = {\n kmh: 'km/h',\n mph: 'mph',\n ms: 'm/s',\n kn: 'kn',\n};\n\nfunction closestHour(hourly: HourlyWeather[], targetTime: Date): HourlyWeather | undefined {\n return hourly.reduce<HourlyWeather | undefined>((closest, hour) => {\n const diff = Math.abs(new Date(hour.time).getTime() - targetTime.getTime());\n const closestDiff = closest ? Math.abs(new Date(closest.time).getTime() - targetTime.getTime()) : Infinity;\n return diff < closestDiff ? hour : closest;\n }, undefined);\n}\n\n// Format a real instant in a specific IANA timezone, falling back to the\n// browser's local zone if the timezone string is missing or invalid.\nfunction formatInZone(instant: Date, timezone: string | undefined, options: Intl.DateTimeFormatOptions): string {\n try {\n return new Intl.DateTimeFormat([], { ...options, timeZone: timezone || undefined }).format(instant);\n } catch {\n return new Intl.DateTimeFormat([], options).format(instant);\n }\n}\n\nconst styles = {\n root: {\n fontFamily: 'system-ui, sans-serif',\n border: '1px solid #e5e7eb',\n borderRadius: 12,\n padding: 16,\n background: '#fff',\n color: '#111827',\n maxWidth: 640,\n } as React.CSSProperties,\n row: { display: 'flex', alignItems: 'center', gap: 8 } as React.CSSProperties,\n hours: { display: 'flex', gap: 12, overflowX: 'auto', paddingBottom: 4 } as React.CSSProperties,\n hourCard: { minWidth: 72, textAlign: 'center' as const, padding: 8, borderRadius: 8, background: '#f9fafb' },\n dayRow: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, padding: '8px 0', borderBottom: '1px solid #f3f4f6' } as React.CSSProperties,\n compactRoot: { fontFamily: 'system-ui, sans-serif', display: 'flex', flexDirection: 'column', gap: 8, padding: '10px 14px', borderRadius: 8 } as React.CSSProperties,\n compactHeader: { display: 'flex', alignItems: 'center', gap: 10 } as React.CSSProperties,\n compactHeaderText: { display: 'flex', alignItems: 'baseline', gap: 8, flexWrap: 'wrap' } as React.CSSProperties,\n compactDateTime: { fontSize: 11, opacity: 0.7 } as React.CSSProperties,\n compactStats: { display: 'flex', flexWrap: 'wrap', gap: 12, fontSize: 12, opacity: 0.9 } as React.CSSProperties,\n compactStat: { display: 'flex', alignItems: 'center', gap: 4, whiteSpace: 'nowrap' } as React.CSSProperties,\n unitSwitch: { display: 'inline-flex', alignItems: 'center', cursor: 'pointer', userSelect: 'none' } as React.CSSProperties,\n rain: { color: '#2563eb', whiteSpace: 'nowrap' } as React.CSSProperties,\n tz: { fontSize: 12, opacity: 0.7, marginTop: 2 } as React.CSSProperties,\n list: { display: 'flex', flexDirection: 'column' } as React.CSSProperties,\n};\n\n// Precipitation chance is only surfaced when there is a non-zero chance of it.\nfunction RainBadge({ probability, compact }: { probability?: number; compact?: boolean }) {\n if (probability === undefined || probability === null || probability <= 0) return null;\n return <span style={styles.rain}>{compact ? ` · ${probability}%` : ` · ${probability}% rain`}</span>;\n}\n\n/**\n * Renders one location's forecast: a live current time (ticking, in the\n * location's own timezone), a clickable degF / degC unit switch, high/low and\n * precipitation for the next hours and days.\n */\nfunction SingleWeatherForecast(props: Props) {\n // Temperature unit is local state so the degF / degC switch can toggle it;\n // it is seeded from (and re-synced to) the temperatureUnit prop.\n const [unit, setUnit] = useState<TemperatureUnit>(props.temperatureUnit ?? 'fahrenheit');\n useEffect(() => {\n setUnit(props.temperatureUnit ?? 'fahrenheit');\n }, [props.temperatureUnit]);\n\n const { data, loading, error } = useWeatherForecast({ ...props, temperatureUnit: unit });\n\n // A ticking clock so the displayed current time stays accurate to the second.\n const [now, setNow] = useState(() => new Date());\n useEffect(() => {\n const id = setInterval(() => setNow(new Date()), 1000);\n return () => clearInterval(id);\n }, []);\n\n const toggleUnit = () => setUnit((u) => (u === 'celsius' ? 'fahrenheit' : 'celsius'));\n\n const renderUnitSwitch = (fontSize: number) => (\n <span\n role=\"button\"\n tabIndex={0}\n onClick={(e) => {\n e.stopPropagation();\n toggleUnit();\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n toggleUnit();\n }\n }}\n title=\"Switch temperature units\"\n aria-label={`Switch temperature units, currently ${unit === 'celsius' ? 'Celsius' : 'Fahrenheit'}`}\n style={{ ...styles.unitSwitch, fontSize }}\n >\n <span style={{ fontWeight: unit === 'fahrenheit' ? 700 : 400, opacity: unit === 'fahrenheit' ? 1 : 0.45 }}>°F</span>\n <span style={{ opacity: 0.4, margin: '0 3px' }}>|</span>\n <span style={{ fontWeight: unit === 'celsius' ? 700 : 400, opacity: unit === 'celsius' ? 1 : 0.45 }}>°C</span>\n </span>\n );\n\n // Keep showing the last forecast while a unit switch refetches in the\n // background; only suppress output on the very first load.\n if (loading && !data) return null;\n if (error) return <div className={props.className} style={props.style}>Error: {error.message}</div>;\n if (!data) return <div className={props.className} style={props.style}>No forecast available.</div>;\n\n const timezone = data.location?.timezone;\n const currentDate = formatInZone(now, timezone, { weekday: 'short', month: 'short', day: 'numeric' });\n const currentTime = formatInZone(now, timezone, { hour: 'numeric', minute: '2-digit', second: '2-digit', timeZoneName: 'short' });\n\n if (props.compact) {\n const forecastBase = new Date(data.current.time);\n const today = data.daily[0];\n const tomorrow = data.daily[1];\n const in6Hours = closestHour(data.hourly, new Date(forecastBase.getTime() + 6 * 60 * 60 * 1000));\n const windSpeedUnitLabel = WIND_SPEED_UNIT_LABELS[props.windSpeedUnit ?? 'mph'];\n\n return (\n <div className={props.className} style={{ ...styles.compactRoot, ...props.style }}>\n <div style={styles.compactHeader}>\n <WeatherIcon condition={data.current.icon} width={24} height={24} title=\"Current weather\" />\n <div>\n <div style={styles.compactHeaderText}>\n <strong style={{ fontSize: 16 }}>{data.current.temperature}</strong>\n {renderUnitSwitch(12)}\n <span style={{ fontSize: 14, opacity: 0.8 }}>\n {data.location?.city || 'Current location'}\n </span>\n </div>\n <div style={styles.compactDateTime}>\n {currentDate}\n {' · '}\n {currentTime}\n </div>\n </div>\n </div>\n\n <div style={styles.compactStats}>\n {today && (\n <span style={styles.compactStat}>\n <WeatherIcon condition={today.icon} width={16} height={16} title=\"Today's high and low\" />\n {today.max}° / {today.min}°\n <RainBadge probability={today.precipitationProbabilityMax} compact />\n </span>\n )}\n {tomorrow && (\n <span style={styles.compactStat}>\n <WeatherIcon condition={tomorrow.icon} width={16} height={16} title=\"Tomorrow's high and low\" />\n Tomorrow {tomorrow.max}° / {tomorrow.min}°\n <RainBadge probability={tomorrow.precipitationProbabilityMax} compact />\n </span>\n )}\n <span style={styles.compactStat}>\n <WindIcon width={16} height={16} title=\"Wind speed\" />\n {data.current.windSpeed !== undefined ? `${Math.round(data.current.windSpeed)} ${windSpeedUnitLabel}` : '—'}\n </span>\n {in6Hours && (\n <span style={styles.compactStat}>\n <WeatherIcon condition={in6Hours.icon} width={16} height={16} title=\"In 6 hours\" />\n {in6Hours.temperature}° in 6h\n <RainBadge probability={in6Hours.precipitationProbability} compact />\n </span>\n )}\n </div>\n </div>\n );\n }\n\n return (\n <div className={props.className} style={{ ...styles.root, ...props.style }}>\n <div>\n <h3 style={{ margin: 0, fontSize: 20 }}>\n {data.location?.city || 'Current location'}\n {data.location?.region ? `, ${data.location.region}` : ''}\n </h3>\n <div style={styles.tz}>\n {currentDate} · {currentTime}\n {timezone ? ` · ${timezone}` : ''}\n </div>\n <div style={{ ...styles.row, marginTop: 8 }}>\n <WeatherIcon condition={data.current.icon} width={28} height={28} title=\"Current weather\" />\n <strong style={{ fontSize: 28 }}>{data.current.temperature}</strong>\n {renderUnitSwitch(14)}\n </div>\n </div>\n\n <div style={{ marginTop: 20 }}>\n <h4 style={{ margin: '0 0 10px 0' }}>Next hours</h4>\n <div style={styles.hours}>\n {data.hourly.slice(0, props.forecastHours ?? 12).map((hour) => (\n <div key={hour.time} style={styles.hourCard}>\n <div style={{ fontSize: 12 }}>{new Date(hour.time).toLocaleTimeString([], { hour: 'numeric' })}</div>\n <WeatherIcon condition={hour.icon} width={20} height={20} style={{ margin: '6px auto' }} />\n <div>{hour.temperature}°</div>\n {hour.precipitationProbability !== undefined && hour.precipitationProbability > 0 && (\n <div style={{ ...styles.rain, fontSize: 12 }}>{hour.precipitationProbability}%</div>\n )}\n </div>\n ))}\n </div>\n </div>\n\n <div style={{ marginTop: 20 }}>\n <h4 style={{ margin: '0 0 10px 0' }}>Next days</h4>\n <div>\n {data.daily.map((day) => (\n <div key={day.date} style={styles.dayRow}>\n <div style={{ width: 120 }}>{new Date(day.date).toLocaleDateString([], { weekday: 'short', month: 'short', day: 'numeric' })}</div>\n <WeatherIcon condition={day.icon} width={20} height={20} />\n <div>\n {day.min}° / {day.max}°\n {day.precipitationProbabilityMax !== undefined && day.precipitationProbabilityMax > 0 && (\n <span style={styles.rain}> · {day.precipitationProbabilityMax}%</span>\n )}\n </div>\n </div>\n ))}\n </div>\n </div>\n </div>\n );\n}\n\n/**\n * Weather forecast widget. When `locations` is provided, one forecast is\n * rendered per location; otherwise a single auto-detected forecast is shown.\n */\nexport function WeatherForecast(props: Props) {\n const { locations, ...rest } = props;\n\n if (locations && locations.length > 0) {\n const gap = props.compact ? 8 : 16;\n return (\n <div style={{ ...styles.list, gap }}>\n {locations.map((loc, index) => (\n <SingleWeatherForecast\n key={`${loc.label ?? ''}:${loc.latitude ?? ''}:${loc.longitude ?? ''}:${index}`}\n {...rest}\n latitude={typeof loc.latitude === 'number' ? loc.latitude : undefined}\n longitude={typeof loc.longitude === 'number' ? loc.longitude : undefined}\n location={{ city: loc.label, timezone: loc.timezone }}\n />\n ))}\n </div>\n );\n }\n\n return <SingleWeatherForecast {...rest} />;\n}\n"],"mappings":"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","names":["res","data","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -10,6 +10,12 @@ type WeatherLocation = {
|
|
|
10
10
|
latitude: number;
|
|
11
11
|
longitude: number;
|
|
12
12
|
};
|
|
13
|
+
type WeatherLocationInput = {
|
|
14
|
+
label?: string;
|
|
15
|
+
latitude?: number;
|
|
16
|
+
longitude?: number;
|
|
17
|
+
timezone?: string;
|
|
18
|
+
};
|
|
13
19
|
type WeatherCondition = 'sun' | 'cloud-sun' | 'clouds' | 'cloud-fog' | 'cloud-drizzle' | 'cloud-showers' | 'cloud-showers-heavy' | 'cloud-sleet' | 'cloud-snow' | 'snowflake' | 'cloud-bolt' | 'cloud-hail';
|
|
14
20
|
type CurrentWeather = {
|
|
15
21
|
time: string;
|
|
@@ -50,6 +56,7 @@ type WeatherForecastOptions = {
|
|
|
50
56
|
latitude?: number;
|
|
51
57
|
longitude?: number;
|
|
52
58
|
location?: Partial<WeatherLocation>;
|
|
59
|
+
locations?: WeatherLocationInput[];
|
|
53
60
|
geoEndpoint?: string;
|
|
54
61
|
ip?: string;
|
|
55
62
|
forecastDays?: number;
|
|
@@ -82,6 +89,10 @@ type Props = WeatherForecastOptions & {
|
|
|
82
89
|
style?: React.CSSProperties;
|
|
83
90
|
compact?: boolean;
|
|
84
91
|
};
|
|
85
|
-
|
|
92
|
+
/**
|
|
93
|
+
* Weather forecast widget. When `locations` is provided, one forecast is
|
|
94
|
+
* rendered per location; otherwise a single auto-detected forecast is shown.
|
|
95
|
+
*/
|
|
96
|
+
declare function WeatherForecast(props: Props): React.JSX.Element;
|
|
86
97
|
|
|
87
|
-
export { type CurrentWeather, type DailyWeather, type HourlyWeather, type IconProps, type TemperatureUnit, type WeatherCondition, WeatherForecast, type WeatherForecastData, type WeatherForecastOptions, WeatherIcon, type WeatherLocation, type WindSpeedUnit, getClientLocation, getWeatherForecast, getWeatherIcon, useWeatherForecast };
|
|
98
|
+
export { type CurrentWeather, type DailyWeather, type HourlyWeather, type IconProps, type TemperatureUnit, type WeatherCondition, WeatherForecast, type WeatherForecastData, type WeatherForecastOptions, WeatherIcon, type WeatherLocation, type WeatherLocationInput, type WindSpeedUnit, getClientLocation, getWeatherForecast, getWeatherIcon, useWeatherForecast };
|
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,12 @@ type WeatherLocation = {
|
|
|
10
10
|
latitude: number;
|
|
11
11
|
longitude: number;
|
|
12
12
|
};
|
|
13
|
+
type WeatherLocationInput = {
|
|
14
|
+
label?: string;
|
|
15
|
+
latitude?: number;
|
|
16
|
+
longitude?: number;
|
|
17
|
+
timezone?: string;
|
|
18
|
+
};
|
|
13
19
|
type WeatherCondition = 'sun' | 'cloud-sun' | 'clouds' | 'cloud-fog' | 'cloud-drizzle' | 'cloud-showers' | 'cloud-showers-heavy' | 'cloud-sleet' | 'cloud-snow' | 'snowflake' | 'cloud-bolt' | 'cloud-hail';
|
|
14
20
|
type CurrentWeather = {
|
|
15
21
|
time: string;
|
|
@@ -50,6 +56,7 @@ type WeatherForecastOptions = {
|
|
|
50
56
|
latitude?: number;
|
|
51
57
|
longitude?: number;
|
|
52
58
|
location?: Partial<WeatherLocation>;
|
|
59
|
+
locations?: WeatherLocationInput[];
|
|
53
60
|
geoEndpoint?: string;
|
|
54
61
|
ip?: string;
|
|
55
62
|
forecastDays?: number;
|
|
@@ -82,6 +89,10 @@ type Props = WeatherForecastOptions & {
|
|
|
82
89
|
style?: React.CSSProperties;
|
|
83
90
|
compact?: boolean;
|
|
84
91
|
};
|
|
85
|
-
|
|
92
|
+
/**
|
|
93
|
+
* Weather forecast widget. When `locations` is provided, one forecast is
|
|
94
|
+
* rendered per location; otherwise a single auto-detected forecast is shown.
|
|
95
|
+
*/
|
|
96
|
+
declare function WeatherForecast(props: Props): React.JSX.Element;
|
|
86
97
|
|
|
87
|
-
export { type CurrentWeather, type DailyWeather, type HourlyWeather, type IconProps, type TemperatureUnit, type WeatherCondition, WeatherForecast, type WeatherForecastData, type WeatherForecastOptions, WeatherIcon, type WeatherLocation, type WindSpeedUnit, getClientLocation, getWeatherForecast, getWeatherIcon, useWeatherForecast };
|
|
98
|
+
export { type CurrentWeather, type DailyWeather, type HourlyWeather, type IconProps, type TemperatureUnit, type WeatherCondition, WeatherForecast, type WeatherForecastData, type WeatherForecastOptions, WeatherIcon, type WeatherLocation, type WeatherLocationInput, type WindSpeedUnit, getClientLocation, getWeatherForecast, getWeatherIcon, useWeatherForecast };
|
package/dist/index.js
CHANGED
|
@@ -103,7 +103,7 @@ async function getWeatherForecast(options = {}) {
|
|
|
103
103
|
throw new Error("Invalid weather response");
|
|
104
104
|
}
|
|
105
105
|
return {
|
|
106
|
-
location,
|
|
106
|
+
location: { ...location, timezone: data.timezone || location.timezone },
|
|
107
107
|
current: {
|
|
108
108
|
time: data.current.time,
|
|
109
109
|
temperature: Math.round(data.current.temperature_2m),
|
|
@@ -231,6 +231,7 @@ function WeatherIcon({ condition, ...props }) {
|
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
// src/components/WeatherForecast.tsx
|
|
234
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
234
235
|
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
235
236
|
var WIND_SPEED_UNIT_LABELS = {
|
|
236
237
|
kmh: "km/h",
|
|
@@ -245,6 +246,13 @@ function closestHour(hourly, targetTime) {
|
|
|
245
246
|
return diff < closestDiff ? hour : closest;
|
|
246
247
|
}, void 0);
|
|
247
248
|
}
|
|
249
|
+
function formatInZone(instant, timezone, options) {
|
|
250
|
+
try {
|
|
251
|
+
return new Intl.DateTimeFormat([], { ...options, timeZone: timezone || void 0 }).format(instant);
|
|
252
|
+
} catch {
|
|
253
|
+
return new Intl.DateTimeFormat([], options).format(instant);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
248
256
|
var styles = {
|
|
249
257
|
root: {
|
|
250
258
|
fontFamily: "system-ui, sans-serif",
|
|
@@ -264,37 +272,81 @@ var styles = {
|
|
|
264
272
|
compactHeaderText: { display: "flex", alignItems: "baseline", gap: 8, flexWrap: "wrap" },
|
|
265
273
|
compactDateTime: { fontSize: 11, opacity: 0.7 },
|
|
266
274
|
compactStats: { display: "flex", flexWrap: "wrap", gap: 12, fontSize: 12, opacity: 0.9 },
|
|
267
|
-
compactStat: { display: "flex", alignItems: "center", gap: 4, whiteSpace: "nowrap" }
|
|
275
|
+
compactStat: { display: "flex", alignItems: "center", gap: 4, whiteSpace: "nowrap" },
|
|
276
|
+
unitSwitch: { display: "inline-flex", alignItems: "center", cursor: "pointer", userSelect: "none" },
|
|
277
|
+
rain: { color: "#2563eb", whiteSpace: "nowrap" },
|
|
278
|
+
tz: { fontSize: 12, opacity: 0.7, marginTop: 2 },
|
|
279
|
+
list: { display: "flex", flexDirection: "column" }
|
|
268
280
|
};
|
|
269
|
-
function
|
|
270
|
-
|
|
271
|
-
|
|
281
|
+
function RainBadge({ probability, compact }) {
|
|
282
|
+
if (probability === void 0 || probability === null || probability <= 0) return null;
|
|
283
|
+
return /* @__PURE__ */ jsx4("span", { style: styles.rain, children: compact ? ` \xB7 ${probability}%` : ` \xB7 ${probability}% rain` });
|
|
284
|
+
}
|
|
285
|
+
function SingleWeatherForecast(props) {
|
|
286
|
+
const [unit, setUnit] = useState2(props.temperatureUnit ?? "fahrenheit");
|
|
287
|
+
useEffect2(() => {
|
|
288
|
+
setUnit(props.temperatureUnit ?? "fahrenheit");
|
|
289
|
+
}, [props.temperatureUnit]);
|
|
290
|
+
const { data, loading, error } = useWeatherForecast({ ...props, temperatureUnit: unit });
|
|
291
|
+
const [now, setNow] = useState2(() => /* @__PURE__ */ new Date());
|
|
292
|
+
useEffect2(() => {
|
|
293
|
+
const id = setInterval(() => setNow(/* @__PURE__ */ new Date()), 1e3);
|
|
294
|
+
return () => clearInterval(id);
|
|
295
|
+
}, []);
|
|
296
|
+
const toggleUnit = () => setUnit((u) => u === "celsius" ? "fahrenheit" : "celsius");
|
|
297
|
+
const renderUnitSwitch = (fontSize) => /* @__PURE__ */ jsxs2(
|
|
298
|
+
"span",
|
|
299
|
+
{
|
|
300
|
+
role: "button",
|
|
301
|
+
tabIndex: 0,
|
|
302
|
+
onClick: (e) => {
|
|
303
|
+
e.stopPropagation();
|
|
304
|
+
toggleUnit();
|
|
305
|
+
},
|
|
306
|
+
onKeyDown: (e) => {
|
|
307
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
308
|
+
e.preventDefault();
|
|
309
|
+
toggleUnit();
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
title: "Switch temperature units",
|
|
313
|
+
"aria-label": `Switch temperature units, currently ${unit === "celsius" ? "Celsius" : "Fahrenheit"}`,
|
|
314
|
+
style: { ...styles.unitSwitch, fontSize },
|
|
315
|
+
children: [
|
|
316
|
+
/* @__PURE__ */ jsx4("span", { style: { fontWeight: unit === "fahrenheit" ? 700 : 400, opacity: unit === "fahrenheit" ? 1 : 0.45 }, children: "\xB0F" }),
|
|
317
|
+
/* @__PURE__ */ jsx4("span", { style: { opacity: 0.4, margin: "0 3px" }, children: "|" }),
|
|
318
|
+
/* @__PURE__ */ jsx4("span", { style: { fontWeight: unit === "celsius" ? 700 : 400, opacity: unit === "celsius" ? 1 : 0.45 }, children: "\xB0C" })
|
|
319
|
+
]
|
|
320
|
+
}
|
|
321
|
+
);
|
|
322
|
+
if (loading && !data) return null;
|
|
272
323
|
if (error) return /* @__PURE__ */ jsxs2("div", { className: props.className, style: props.style, children: [
|
|
273
324
|
"Error: ",
|
|
274
325
|
error.message
|
|
275
326
|
] });
|
|
276
327
|
if (!data) return /* @__PURE__ */ jsx4("div", { className: props.className, style: props.style, children: "No forecast available." });
|
|
328
|
+
const timezone = data.location?.timezone;
|
|
329
|
+
const currentDate = formatInZone(now, timezone, { weekday: "short", month: "short", day: "numeric" });
|
|
330
|
+
const currentTime = formatInZone(now, timezone, { hour: "numeric", minute: "2-digit", second: "2-digit", timeZoneName: "short" });
|
|
277
331
|
if (props.compact) {
|
|
278
|
-
const
|
|
332
|
+
const forecastBase = new Date(data.current.time);
|
|
279
333
|
const today = data.daily[0];
|
|
280
334
|
const tomorrow = data.daily[1];
|
|
281
|
-
const in6Hours = closestHour(data.hourly, new Date(
|
|
335
|
+
const in6Hours = closestHour(data.hourly, new Date(forecastBase.getTime() + 6 * 60 * 60 * 1e3));
|
|
282
336
|
const windSpeedUnitLabel = WIND_SPEED_UNIT_LABELS[props.windSpeedUnit ?? "mph"];
|
|
283
337
|
return /* @__PURE__ */ jsxs2("div", { className: props.className, style: { ...styles.compactRoot, ...props.style }, children: [
|
|
284
338
|
/* @__PURE__ */ jsxs2("div", { style: styles.compactHeader, children: [
|
|
285
339
|
/* @__PURE__ */ jsx4(WeatherIcon, { condition: data.current.icon, width: 24, height: 24, title: "Current weather" }),
|
|
286
340
|
/* @__PURE__ */ jsxs2("div", { children: [
|
|
287
341
|
/* @__PURE__ */ jsxs2("div", { style: styles.compactHeaderText, children: [
|
|
288
|
-
/* @__PURE__ */
|
|
289
|
-
|
|
290
|
-
"\xB0"
|
|
291
|
-
] }),
|
|
342
|
+
/* @__PURE__ */ jsx4("strong", { style: { fontSize: 16 }, children: data.current.temperature }),
|
|
343
|
+
renderUnitSwitch(12),
|
|
292
344
|
/* @__PURE__ */ jsx4("span", { style: { fontSize: 14, opacity: 0.8 }, children: data.location?.city || "Current location" })
|
|
293
345
|
] }),
|
|
294
346
|
/* @__PURE__ */ jsxs2("div", { style: styles.compactDateTime, children: [
|
|
295
|
-
|
|
347
|
+
currentDate,
|
|
296
348
|
" \xB7 ",
|
|
297
|
-
|
|
349
|
+
currentTime
|
|
298
350
|
] })
|
|
299
351
|
] })
|
|
300
352
|
] }),
|
|
@@ -304,13 +356,17 @@ function WeatherForecast(props) {
|
|
|
304
356
|
today.max,
|
|
305
357
|
"\xB0 / ",
|
|
306
358
|
today.min,
|
|
307
|
-
"\xB0"
|
|
359
|
+
"\xB0",
|
|
360
|
+
/* @__PURE__ */ jsx4(RainBadge, { probability: today.precipitationProbabilityMax, compact: true })
|
|
308
361
|
] }),
|
|
309
362
|
tomorrow && /* @__PURE__ */ jsxs2("span", { style: styles.compactStat, children: [
|
|
310
|
-
/* @__PURE__ */ jsx4(WeatherIcon, { condition: tomorrow.icon, width: 16, height: 16, title: "Tomorrow" }),
|
|
363
|
+
/* @__PURE__ */ jsx4(WeatherIcon, { condition: tomorrow.icon, width: 16, height: 16, title: "Tomorrow's high and low" }),
|
|
311
364
|
"Tomorrow ",
|
|
312
365
|
tomorrow.max,
|
|
313
|
-
"\xB0"
|
|
366
|
+
"\xB0 / ",
|
|
367
|
+
tomorrow.min,
|
|
368
|
+
"\xB0",
|
|
369
|
+
/* @__PURE__ */ jsx4(RainBadge, { probability: tomorrow.precipitationProbabilityMax, compact: true })
|
|
314
370
|
] }),
|
|
315
371
|
/* @__PURE__ */ jsxs2("span", { style: styles.compactStat, children: [
|
|
316
372
|
/* @__PURE__ */ jsx4(WindIcon, { width: 16, height: 16, title: "Wind speed" }),
|
|
@@ -319,7 +375,8 @@ function WeatherForecast(props) {
|
|
|
319
375
|
in6Hours && /* @__PURE__ */ jsxs2("span", { style: styles.compactStat, children: [
|
|
320
376
|
/* @__PURE__ */ jsx4(WeatherIcon, { condition: in6Hours.icon, width: 16, height: 16, title: "In 6 hours" }),
|
|
321
377
|
in6Hours.temperature,
|
|
322
|
-
"\xB0 in 6h"
|
|
378
|
+
"\xB0 in 6h",
|
|
379
|
+
/* @__PURE__ */ jsx4(RainBadge, { probability: in6Hours.precipitationProbability, compact: true })
|
|
323
380
|
] })
|
|
324
381
|
] })
|
|
325
382
|
] });
|
|
@@ -330,12 +387,16 @@ function WeatherForecast(props) {
|
|
|
330
387
|
data.location?.city || "Current location",
|
|
331
388
|
data.location?.region ? `, ${data.location.region}` : ""
|
|
332
389
|
] }),
|
|
390
|
+
/* @__PURE__ */ jsxs2("div", { style: styles.tz, children: [
|
|
391
|
+
currentDate,
|
|
392
|
+
" \xB7 ",
|
|
393
|
+
currentTime,
|
|
394
|
+
timezone ? ` \xB7 ${timezone}` : ""
|
|
395
|
+
] }),
|
|
333
396
|
/* @__PURE__ */ jsxs2("div", { style: { ...styles.row, marginTop: 8 }, children: [
|
|
334
397
|
/* @__PURE__ */ jsx4(WeatherIcon, { condition: data.current.icon, width: 28, height: 28, title: "Current weather" }),
|
|
335
|
-
/* @__PURE__ */
|
|
336
|
-
|
|
337
|
-
"\xB0"
|
|
338
|
-
] })
|
|
398
|
+
/* @__PURE__ */ jsx4("strong", { style: { fontSize: 28 }, children: data.current.temperature }),
|
|
399
|
+
renderUnitSwitch(14)
|
|
339
400
|
] })
|
|
340
401
|
] }),
|
|
341
402
|
/* @__PURE__ */ jsxs2("div", { style: { marginTop: 20 }, children: [
|
|
@@ -346,6 +407,10 @@ function WeatherForecast(props) {
|
|
|
346
407
|
/* @__PURE__ */ jsxs2("div", { children: [
|
|
347
408
|
hour.temperature,
|
|
348
409
|
"\xB0"
|
|
410
|
+
] }),
|
|
411
|
+
hour.precipitationProbability !== void 0 && hour.precipitationProbability > 0 && /* @__PURE__ */ jsxs2("div", { style: { ...styles.rain, fontSize: 12 }, children: [
|
|
412
|
+
hour.precipitationProbability,
|
|
413
|
+
"%"
|
|
349
414
|
] })
|
|
350
415
|
] }, hour.time)) })
|
|
351
416
|
] }),
|
|
@@ -358,12 +423,34 @@ function WeatherForecast(props) {
|
|
|
358
423
|
day.min,
|
|
359
424
|
"\xB0 / ",
|
|
360
425
|
day.max,
|
|
361
|
-
"\xB0"
|
|
426
|
+
"\xB0",
|
|
427
|
+
day.precipitationProbabilityMax !== void 0 && day.precipitationProbabilityMax > 0 && /* @__PURE__ */ jsxs2("span", { style: styles.rain, children: [
|
|
428
|
+
" \xB7 ",
|
|
429
|
+
day.precipitationProbabilityMax,
|
|
430
|
+
"%"
|
|
431
|
+
] })
|
|
362
432
|
] })
|
|
363
433
|
] }, day.date)) })
|
|
364
434
|
] })
|
|
365
435
|
] });
|
|
366
436
|
}
|
|
437
|
+
function WeatherForecast(props) {
|
|
438
|
+
const { locations, ...rest } = props;
|
|
439
|
+
if (locations && locations.length > 0) {
|
|
440
|
+
const gap = props.compact ? 8 : 16;
|
|
441
|
+
return /* @__PURE__ */ jsx4("div", { style: { ...styles.list, gap }, children: locations.map((loc, index) => /* @__PURE__ */ jsx4(
|
|
442
|
+
SingleWeatherForecast,
|
|
443
|
+
{
|
|
444
|
+
...rest,
|
|
445
|
+
latitude: typeof loc.latitude === "number" ? loc.latitude : void 0,
|
|
446
|
+
longitude: typeof loc.longitude === "number" ? loc.longitude : void 0,
|
|
447
|
+
location: { city: loc.label, timezone: loc.timezone }
|
|
448
|
+
},
|
|
449
|
+
`${loc.label ?? ""}:${loc.latitude ?? ""}:${loc.longitude ?? ""}:${index}`
|
|
450
|
+
)) });
|
|
451
|
+
}
|
|
452
|
+
return /* @__PURE__ */ jsx4(SingleWeatherForecast, { ...rest });
|
|
453
|
+
}
|
|
367
454
|
export {
|
|
368
455
|
WeatherForecast,
|
|
369
456
|
WeatherIcon,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/weatherCodes.ts","../src/api/geolocation.ts","../src/api/forecast.ts","../src/hooks/useWeatherForecast.ts","../src/icons/BaseIcon.tsx","../src/icons/weather-icons.tsx","../src/icons/WeatherIcon.tsx","../src/components/WeatherForecast.tsx"],"sourcesContent":["import type { WeatherCondition } from './types';\n\nexport function getWeatherIcon(code: number, isDay = 1): WeatherCondition {\n if (code === 0) return 'sun';\n if ([1, 2].includes(code)) return isDay ? 'cloud-sun' : 'clouds';\n if (code === 3) return 'clouds';\n if ([45, 48].includes(code)) return 'cloud-fog';\n if ([51, 53, 55, 56, 57].includes(code)) return 'cloud-drizzle';\n if ([61, 63].includes(code)) return 'cloud-showers';\n if ([65, 66, 67, 80, 81, 82].includes(code)) return 'cloud-showers-heavy';\n if ([71, 73, 75, 77, 85, 86].includes(code)) return 'cloud-snow';\n if (code === 95) return 'cloud-bolt';\n if ([96, 99].includes(code)) return 'cloud-hail';\n return 'clouds';\n}\n","import type { WeatherLocation } from '../types';\n\nconst DEFAULT_IP_API_URL = 'https://ipapi.co';\n\ntype IpApiResponse = {\n city?: string;\n region?: string;\n country_name?: string;\n timezone?: string;\n latitude?: number;\n longitude?: number;\n error?: boolean;\n reason?: string;\n};\n\ntype GeoWorkerResponse = {\n city?: string;\n region?: string;\n country?: string;\n timezone?: string;\n latitude?: number | string;\n longitude?: number | string;\n};\n\nexport async function getClientLocation(geoEndpoint?: string, ip?: string): Promise<WeatherLocation> {\n if (geoEndpoint) {\n const url = ip ? `${geoEndpoint}?ip=${encodeURIComponent(ip)}` : geoEndpoint;\n const res = await fetch(url);\n if (!res.ok) throw new Error(`Geolocation worker lookup failed: ${res.status}`);\n const data: GeoWorkerResponse = await res.json();\n\n return {\n city: data.city,\n region: data.region,\n country: data.country,\n timezone: data.timezone,\n latitude: Number(data.latitude),\n longitude: Number(data.longitude),\n };\n }\n\n const res = await fetch(`${DEFAULT_IP_API_URL}/${ip ? `${encodeURIComponent(ip)}/` : ''}json/`);\n if (!res.ok) throw new Error(`ipapi.co lookup failed: ${res.status}`);\n const data: IpApiResponse = await res.json();\n\n if (data.error) {\n throw new Error(`ipapi.co lookup failed: ${data.reason ?? 'unknown error'}`);\n }\n\n return {\n city: data.city,\n region: data.region,\n country: data.country_name,\n timezone: data.timezone,\n latitude: Number(data.latitude),\n longitude: Number(data.longitude),\n };\n}\n","import type { WeatherForecastData, WeatherForecastOptions, WeatherLocation } from '../types';\nimport { getWeatherIcon } from '../weatherCodes';\nimport { getClientLocation } from './geolocation';\n\nfunction buildUrl(latitude: number, longitude: number, options: WeatherForecastOptions) {\n const params = new URLSearchParams({\n latitude: String(latitude),\n longitude: String(longitude),\n timezone: options.location?.timezone || 'auto',\n temperature_unit: options.temperatureUnit || 'fahrenheit',\n wind_speed_unit: options.windSpeedUnit || 'mph',\n forecast_days: String(options.forecastDays ?? 5),\n forecast_hours: String(options.forecastHours ?? 24),\n current: [\n 'temperature_2m',\n 'weather_code',\n 'is_day',\n 'rain',\n 'showers',\n 'snowfall',\n 'wind_speed_10m',\n ].join(','),\n hourly: [\n 'temperature_2m',\n 'weather_code',\n 'precipitation_probability',\n 'rain',\n 'showers',\n 'snowfall',\n ].join(','),\n daily: [\n 'temperature_2m_max',\n 'temperature_2m_min',\n 'weather_code',\n 'precipitation_probability_max',\n ].join(','),\n });\n\n return `https://api.open-meteo.com/v1/forecast?${params.toString()}`;\n}\n\nexport async function getWeatherForecast(\n options: WeatherForecastOptions = {}\n): Promise<WeatherForecastData> {\n let location: WeatherLocation;\n\n if (typeof options.latitude === 'number' && typeof options.longitude === 'number') {\n location = {\n ...options.location,\n latitude: options.latitude,\n longitude: options.longitude,\n };\n } else {\n location = await getClientLocation(options.geoEndpoint, options.ip);\n }\n\n const url = buildUrl(location.latitude, location.longitude, { ...options, location });\n const response = await fetch(url, { headers: { 'Content-Type': 'application/json' } });\n\n if (!response.ok) {\n throw new Error(`Weather request failed: ${response.status} ${response.statusText}`);\n }\n\n const data = await response.json();\n\n if (!data?.current || !data?.hourly || !data?.daily) {\n throw new Error('Invalid weather response');\n }\n\n return {\n location,\n current: {\n time: data.current.time,\n temperature: Math.round(data.current.temperature_2m),\n weatherCode: data.current.weather_code,\n icon: getWeatherIcon(data.current.weather_code, data.current.is_day),\n isDay: data.current.is_day,\n rain: data.current.rain,\n showers: data.current.showers,\n snowfall: data.current.snowfall,\n windSpeed: data.current.wind_speed_10m,\n },\n hourly: data.hourly.time.map((time: string, index: number) => ({\n time,\n temperature: Math.round(data.hourly.temperature_2m[index]),\n weatherCode: data.hourly.weather_code[index],\n precipitationProbability: data.hourly.precipitation_probability?.[index],\n rain: data.hourly.rain?.[index],\n showers: data.hourly.showers?.[index],\n snowfall: data.hourly.snowfall?.[index],\n icon: getWeatherIcon(data.hourly.weather_code[index]),\n })),\n daily: data.daily.time.map((date: string, index: number) => ({\n date,\n min: Math.round(data.daily.temperature_2m_min[index]),\n max: Math.round(data.daily.temperature_2m_max[index]),\n weatherCode: data.daily.weather_code[index],\n precipitationProbabilityMax: data.daily.precipitation_probability_max?.[index],\n icon: getWeatherIcon(data.daily.weather_code[index]),\n })),\n };\n}\n","import { useEffect, useState } from 'react';\nimport type { WeatherForecastData, WeatherForecastOptions } from '../types';\nimport { getWeatherForecast } from '../api/forecast';\n\nexport function useWeatherForecast(options: WeatherForecastOptions = {}) {\n const [data, setData] = useState<WeatherForecastData | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n let active = true;\n setLoading(true);\n setError(null);\n\n getWeatherForecast(options)\n .then((result) => { if (active) setData(result); })\n .catch((err) => { if (active) setError(err instanceof Error ? err : new Error('Unknown error')); })\n .finally(() => { if (active) setLoading(false); });\n\n return () => { active = false; };\n }, [\n options.latitude,\n options.longitude,\n options.geoEndpoint,\n options.ip,\n options.forecastDays,\n options.forecastHours,\n options.temperatureUnit,\n options.windSpeedUnit,\n options.location?.timezone,\n ]);\n\n return { data, error, loading };\n}\n","import React from 'react';\nimport type { IconProps } from '../types';\n\nexport function BaseIcon({ title, children, ...props }: IconProps & { children: React.ReactNode }) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n role={title ? 'img' : 'presentation'}\n aria-hidden={title ? undefined : true}\n aria-label={title}\n {...props}\n >\n {title ? <title>{title}</title> : null}\n {children}\n </svg>\n );\n}\n","import React from 'react';\nimport type { IconProps } from '../types';\nimport { BaseIcon } from './BaseIcon';\n\nexport const CloudBoltIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M7 18a4.815 4.815 0 0 1-3.327-1.318A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 0 7h-1m-4.75-5L11 17.5h3.375l-2.25 4.5\" /></BaseIcon>\n);\nexport const CloudDrizzleIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M12 18v1m-3-4v1m6-1v1m2 3v1M7 19v1m-3-3.034a4.63 4.63 0 0 1-.327-.284A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 1.5 6.662\" /></BaseIcon>\n);\nexport const CloudFogIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M4 16.966a4.63 4.63 0 0 1-.327-.284A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 1.5 6.662M5 21h7m4 0h3M8 17h8\" /></BaseIcon>\n);\nexport const CloudHailIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M8 17.45v.1m-1.5 3.9v.1m10.5-4.1v.1m-1.5 3.9v.1m-3-4.1v.1m-1.5 3.9v.1m10.475-4.575A3.5 3.5 0 0 0 19 11h-1c.146-.65.148-1.32.006-1.97a4.784 4.784 0 0 0-.831-1.823 5.36 5.36 0 0 0-1.544-1.398 5.964 5.964 0 0 0-2.02-.759 6.224 6.224 0 0 0-2.19-.006 5.971 5.971 0 0 0-2.024.749C8.157 6.533 7.295 7.687 7 9a4.815 4.815 0 0 0-3.327 1.318A4.403 4.403 0 0 0 2.295 13.5c0 1.194.496 2.338 1.378 3.182.105.1.214.195.327.284m4.5.534a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Zm-1.5 4a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Zm10.5-4a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Zm-1.5 4a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Zm-3-4a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Zm-1.5 4a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Z\" /></BaseIcon>\n);\nexport const CloudShowersIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M4 16.966a4.63 4.63 0 0 1-.327-.284A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 1.5 6.662M12 13v2m0 3v2m4-5v2m0 3v2m-8-7v2m0 3v2\" /></BaseIcon>\n);\nexport const CloudShowersHeavyIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M4 16.966a4.63 4.63 0 0 1-.327-.284A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 1.5 6.662M16 15v6m-8-6v6m4-8v6\" /></BaseIcon>\n);\nexport const CloudSleetIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M13.5 17.45a1 1 0 1 0-2 0h2Zm-2 .1a1 1 0 1 0 2 0h-2Zm.5 3.9a1 1 0 1 0-2 0h2Zm-2 .1a1 1 0 1 0 2 0h-2Zm-6.327-4.868.692-.723-.692.723ZM7 9v1a1 1 0 0 0 .976-.781L7 9Zm2.397-3.207.512.858-.512-.858ZM18 11l-.976-.219A1 1 0 0 0 18 12v-1Zm2.768 5.268a1 1 0 0 0 1.414 1.414l-.707-.707-.707-.707ZM3.379 17.75a1 1 0 0 0 1.242-1.567L4 16.966l-.62.784Zm5.55-.379a1 1 0 0 0-1.857-.742L8 17l.928.371ZM5.071 21.63a1 1 0 0 0 1.856.742L6 22l-.928-.371Zm13.857-4.258a1 1 0 0 0-1.857-.742L18 17l.928.371Zm-3.857 4.258a1 1 0 0 0 1.857.742L16 22l-.928-.371ZM13 17.5h-1a.5.5 0 0 1 .5-.5v2a1.5 1.5 0 0 0 1.5-1.5h-1Zm-.5.5v-1a.5.5 0 0 1 .5.5h-2a1.5 1.5 0 0 0 1.5 1.5v-1Zm-.5-.5h1a.5.5 0 0 1-.5.5v-2a1.5 1.5 0 0 0-1.5 1.5h1Zm.5-.5v1a.5.5 0 0 1-.5-.5h2a1.5 1.5 0 0 0-1.5-1.5v1Zm0 .45h-1v.1h2v-.1h-1Zm-1 4.05h-1a.5.5 0 0 1 .5-.5v2a1.5 1.5 0 0 0 1.5-1.5h-1Zm-.5.5v-1a.5.5 0 0 1 .5.5h-2A1.5 1.5 0 0 0 11 23v-1Zm-.5-.5h1a.5.5 0 0 1-.5.5v-2a1.5 1.5 0 0 0-1.5 1.5h1Zm.5-.5v1a.5.5 0 0 1-.5-.5h2A1.5 1.5 0 0 0 11 20v1Zm0 .45h-1v.1h2v-.1h-1Zm-7.327-4.768.692-.723a3.403 3.403 0 0 1-1.07-2.459h-2c0 1.473.613 2.877 1.687 3.905l.691-.723ZM2.295 13.5h1c0-.914.38-1.8 1.07-2.46l-.692-.722-.69-.723A5.403 5.403 0 0 0 1.294 13.5h1Zm1.378-3.182.692.723A3.815 3.815 0 0 1 7 10V8c-1.499 0-2.945.57-4.018 1.595l.691.723ZM7 9l.976.219c.23-1.024.91-1.956 1.933-2.568l-.512-.858-.513-.859c-1.456.87-2.5 2.245-2.86 3.847L7 9Zm2.397-3.207.512.858a4.972 4.972 0 0 1 1.686-.622l-.173-.985-.174-.985a6.971 6.971 0 0 0-2.364.875l.513.859Zm2.025-.749.173.985a5.223 5.223 0 0 1 1.837.005l.18-.984.178-.984a7.223 7.223 0 0 0-2.542-.007l.174.985Zm2.19.006-.18.984c.606.11 1.177.326 1.681.631l.518-.856.518-.855a6.963 6.963 0 0 0-2.359-.888l-.179.984Zm2.02.76-.519.855c.505.305.93.693 1.257 1.136l.805-.594.805-.594a6.361 6.361 0 0 0-1.831-1.659l-.518.855Zm1.543 1.397-.805.594c.326.442.549.932.66 1.441l.976-.212.978-.213a5.786 5.786 0 0 0-1.005-2.204l-.804.594Zm.831 1.823-.977.212c.111.509.11 1.031-.005 1.539L18 11l.976.219c.178-.792.18-1.609.008-2.402l-.978.213ZM18 11v1h1v-2h-1v1Zm1 0v1a2.5 2.5 0 0 1 1.768.732l.707-.707.707-.707A4.5 4.5 0 0 0 19 10v1Zm2.475 1.025-.707.707A2.5 2.5 0 0 1 21.5 14.5h2a4.5 4.5 0 0 0-1.318-3.182l-.707.707ZM22.5 14.5h-1a2.5 2.5 0 0 1-.732 1.768l.707.707.707.707A4.5 4.5 0 0 0 23.5 14.5h-1ZM4 16.966l.62-.784a3.684 3.684 0 0 1-.255-.223l-.692.723-.69.723c.126.121.259.237.396.345L4 16.966ZM8 17l-.928-.371-2 5L6 22l.928.371 2-5L8 17Zm10 0-.928-.371-2 5L16 22l.928.371 2-5L18 17Z\" /></BaseIcon>\n);\nexport const CloudSnowIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M8 15h2m-1-1v2m5-1h2m-1-1v2M5 21h2m-1-1v2m5-2h2m-1-1v2m5 0h2m-1-1v2M4 16.966a4.63 4.63 0 0 1-.327-.284A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 1.5 6.662\" /></BaseIcon>\n);\nexport const CloudSunIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M10.201 19.997c-1.977 0-3.58-1.544-3.58-3.448 0-1.903 1.603-3.446 3.58-3.446.303-1.355 1.38-2.461 2.827-2.902 1.445-.44 3.042-.148 4.186.77 1.144.915 1.663 2.312 1.361 3.667h.761c1.472 0 2.664 1.2 2.664 2.68A2.672 2.672 0 0 1 19.336 20h-9.134m2.66-12.934a4.166 4.166 0 0 0-2.677-1.732m2.677 1.732 2.744-1.892m-2.744 1.892c.55.796.802 1.754.723 2.709m-3.4-4.44a4.167 4.167 0 0 0-3.118.667m3.118-.668.602-3.278m-3.72 3.946A4.167 4.167 0 0 0 5.334 8.68m1.733-2.678L5.174 3.26m.16 5.42c-.2 1.088.041 2.21.669 3.12m-.669-3.12-3.278-.601m3.947 3.72-2.744 1.893m2.744-1.893a4.167 4.167 0 0 0 2.174 1.607\" /></BaseIcon>\n);\nexport const CloudsIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M8.958 21.05C6.772 21.05 5 19.344 5 17.24s1.772-3.81 3.958-3.81c.335-1.498 1.525-2.72 3.124-3.207 1.598-.487 3.363-.164 4.628.85 1.264 1.011 1.837 2.556 1.504 4.053h.842A2.953 2.953 0 0 1 22 18.09a2.954 2.954 0 0 1-2.945 2.964H8.958M18 8c-.5-2.5-3.532-3.401-5.5-2.5a3.117 3.117 0 0 0-2.11-2.312c-1.352-.411-2.845-.138-3.915.72-1.07.855-1.554 2.161-1.273 3.428h-.711A2.498 2.498 0 0 0 2 9.843c0 1.094.695 2.023 1.666 2.366\" /></BaseIcon>\n);\nexport const SnowflakeIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"m9.25 4-1 2H6m-2.25 4L5 12m0 0-1.25 2M5 12h3m-3 0H2.5m17.75-2L19 12l1.25 2M6 18h2.25l1 2M14 9h-4m4 0 3-5m-3 5 2 3m-6-3L7 4m3 5-2 3m0 0 2 3m0 0-3 5m3-5h4m2-3-2 3m2-3h5.5M14 15l3 5M14.75 4l1 2H18m0 12h-2.25l-1 2\" /></BaseIcon>\n);\nexport const SunIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M12 4V2m0 20v-2m10-8h-2M4 12H2m15.657-5.657 1.414-1.414M4.93 19.07l1.414-1.414m12.728 1.414-1.414-1.414M6.343 6.343 4.93 4.929M7 12a5 5 0 1 0 10 0 5 5 0 0 0-10 0Z\" /></BaseIcon>\n);\nexport const WindIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M9.59 4.59A2 2 0 1 1 11 8H2m10.59 11.41A2 2 0 1 0 14 16H2m15.73-8.27A2.5 2.5 0 1 1 19.5 12H2\" /></BaseIcon>\n);\n","import React from 'react';\nimport type { IconProps, WeatherCondition } from '../types';\nimport {\n CloudBoltIcon,\n CloudDrizzleIcon,\n CloudFogIcon,\n CloudHailIcon,\n CloudShowersHeavyIcon,\n CloudShowersIcon,\n CloudSleetIcon,\n CloudSnowIcon,\n CloudSunIcon,\n CloudsIcon,\n SnowflakeIcon,\n SunIcon,\n} from './weather-icons';\n\nconst iconMap: Record<WeatherCondition, React.ComponentType<IconProps>> = {\n sun: SunIcon,\n 'cloud-sun': CloudSunIcon,\n clouds: CloudsIcon,\n 'cloud-fog': CloudFogIcon,\n 'cloud-drizzle': CloudDrizzleIcon,\n 'cloud-showers': CloudShowersIcon,\n 'cloud-showers-heavy': CloudShowersHeavyIcon,\n 'cloud-sleet': CloudSleetIcon,\n 'cloud-snow': CloudSnowIcon,\n snowflake: SnowflakeIcon,\n 'cloud-bolt': CloudBoltIcon,\n 'cloud-hail': CloudHailIcon,\n};\n\nexport function WeatherIcon({ condition, ...props }: IconProps & { condition: WeatherCondition }) {\n const Icon = iconMap[condition] || CloudsIcon;\n return <Icon {...props} />;\n}\n","import React from 'react';\nimport { useWeatherForecast } from '../hooks/useWeatherForecast';\nimport type { HourlyWeather, WeatherForecastOptions, WindSpeedUnit } from '../types';\nimport { WeatherIcon } from '../icons/WeatherIcon';\nimport { WindIcon } from '../icons/weather-icons';\n\ntype Props = WeatherForecastOptions & {\n className?: string;\n style?: React.CSSProperties;\n compact?: boolean;\n};\n\nconst WIND_SPEED_UNIT_LABELS: Record<WindSpeedUnit, string> = {\n kmh: 'km/h',\n mph: 'mph',\n ms: 'm/s',\n kn: 'kn',\n};\n\nfunction closestHour(hourly: HourlyWeather[], targetTime: Date): HourlyWeather | undefined {\n return hourly.reduce<HourlyWeather | undefined>((closest, hour) => {\n const diff = Math.abs(new Date(hour.time).getTime() - targetTime.getTime());\n const closestDiff = closest ? Math.abs(new Date(closest.time).getTime() - targetTime.getTime()) : Infinity;\n return diff < closestDiff ? hour : closest;\n }, undefined);\n}\n\nconst styles = {\n root: {\n fontFamily: 'system-ui, sans-serif',\n border: '1px solid #e5e7eb',\n borderRadius: 12,\n padding: 16,\n background: '#fff',\n color: '#111827',\n maxWidth: 640,\n } as React.CSSProperties,\n row: { display: 'flex', alignItems: 'center', gap: 8 } as React.CSSProperties,\n hours: { display: 'flex', gap: 12, overflowX: 'auto', paddingBottom: 4 } as React.CSSProperties,\n hourCard: { minWidth: 72, textAlign: 'center' as const, padding: 8, borderRadius: 8, background: '#f9fafb' },\n dayRow: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, padding: '8px 0', borderBottom: '1px solid #f3f4f6' } as React.CSSProperties,\n compactRoot: { fontFamily: 'system-ui, sans-serif', display: 'flex', flexDirection: 'column', gap: 8, padding: '10px 14px', borderRadius: 8 } as React.CSSProperties,\n compactHeader: { display: 'flex', alignItems: 'center', gap: 10 } as React.CSSProperties,\n compactHeaderText: { display: 'flex', alignItems: 'baseline', gap: 8, flexWrap: 'wrap' } as React.CSSProperties,\n compactDateTime: { fontSize: 11, opacity: 0.7 } as React.CSSProperties,\n compactStats: { display: 'flex', flexWrap: 'wrap', gap: 12, fontSize: 12, opacity: 0.9 } as React.CSSProperties,\n compactStat: { display: 'flex', alignItems: 'center', gap: 4, whiteSpace: 'nowrap' } as React.CSSProperties,\n};\n\nexport function WeatherForecast(props: Props) {\n const { data, loading, error } = useWeatherForecast(props);\n\n if (loading) return null;\n if (error) return <div className={props.className} style={props.style}>Error: {error.message}</div>;\n if (!data) return <div className={props.className} style={props.style}>No forecast available.</div>;\n\n if (props.compact) {\n const now = new Date(data.current.time);\n const today = data.daily[0];\n const tomorrow = data.daily[1];\n const in6Hours = closestHour(data.hourly, new Date(now.getTime() + 6 * 60 * 60 * 1000));\n const windSpeedUnitLabel = WIND_SPEED_UNIT_LABELS[props.windSpeedUnit ?? 'mph'];\n\n return (\n <div className={props.className} style={{ ...styles.compactRoot, ...props.style }}>\n <div style={styles.compactHeader}>\n <WeatherIcon condition={data.current.icon} width={24} height={24} title=\"Current weather\" />\n <div>\n <div style={styles.compactHeaderText}>\n <strong style={{ fontSize: 16 }}>{data.current.temperature}°</strong>\n <span style={{ fontSize: 14, opacity: 0.8 }}>\n {data.location?.city || 'Current location'}\n </span>\n </div>\n <div style={styles.compactDateTime}>\n {now.toLocaleDateString([], { weekday: 'short', month: 'short', day: 'numeric' })}\n {' · '}\n {now.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' })}\n </div>\n </div>\n </div>\n\n <div style={styles.compactStats}>\n {today && (\n <span style={styles.compactStat}>\n <WeatherIcon condition={today.icon} width={16} height={16} title=\"Today's high and low\" />\n {today.max}° / {today.min}°\n </span>\n )}\n {tomorrow && (\n <span style={styles.compactStat}>\n <WeatherIcon condition={tomorrow.icon} width={16} height={16} title=\"Tomorrow\" />\n Tomorrow {tomorrow.max}°\n </span>\n )}\n <span style={styles.compactStat}>\n <WindIcon width={16} height={16} title=\"Wind speed\" />\n {data.current.windSpeed !== undefined ? `${Math.round(data.current.windSpeed)} ${windSpeedUnitLabel}` : '—'}\n </span>\n {in6Hours && (\n <span style={styles.compactStat}>\n <WeatherIcon condition={in6Hours.icon} width={16} height={16} title=\"In 6 hours\" />\n {in6Hours.temperature}° in 6h\n </span>\n )}\n </div>\n </div>\n );\n }\n\n return (\n <div className={props.className} style={{ ...styles.root, ...props.style }}>\n <div>\n <h3 style={{ margin: 0, fontSize: 20 }}>\n {data.location?.city || 'Current location'}\n {data.location?.region ? `, ${data.location.region}` : ''}\n </h3>\n <div style={{ ...styles.row, marginTop: 8 }}>\n <WeatherIcon condition={data.current.icon} width={28} height={28} title=\"Current weather\" />\n <strong style={{ fontSize: 28 }}>{data.current.temperature}°</strong>\n </div>\n </div>\n\n <div style={{ marginTop: 20 }}>\n <h4 style={{ margin: '0 0 10px 0' }}>Next hours</h4>\n <div style={styles.hours}>\n {data.hourly.slice(0, props.forecastHours ?? 12).map((hour) => (\n <div key={hour.time} style={styles.hourCard}>\n <div style={{ fontSize: 12 }}>{new Date(hour.time).toLocaleTimeString([], { hour: 'numeric' })}</div>\n <WeatherIcon condition={hour.icon} width={20} height={20} style={{ margin: '6px auto' }} />\n <div>{hour.temperature}°</div>\n </div>\n ))}\n </div>\n </div>\n\n <div style={{ marginTop: 20 }}>\n <h4 style={{ margin: '0 0 10px 0' }}>Next days</h4>\n <div>\n {data.daily.map((day) => (\n <div key={day.date} style={styles.dayRow}>\n <div style={{ width: 120 }}>{new Date(day.date).toLocaleDateString([], { weekday: 'short', month: 'short', day: 'numeric' })}</div>\n <WeatherIcon condition={day.icon} width={20} height={20} />\n <div>{day.min}° / {day.max}°</div>\n </div>\n ))}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["res","data","jsx","jsx","jsx","jsxs"]}
|
|
1
|
+
{"version":3,"sources":["../src/weatherCodes.ts","../src/api/geolocation.ts","../src/api/forecast.ts","../src/hooks/useWeatherForecast.ts","../src/icons/BaseIcon.tsx","../src/icons/weather-icons.tsx","../src/icons/WeatherIcon.tsx","../src/components/WeatherForecast.tsx"],"sourcesContent":["import type { WeatherCondition } from './types';\n\nexport function getWeatherIcon(code: number, isDay = 1): WeatherCondition {\n if (code === 0) return 'sun';\n if ([1, 2].includes(code)) return isDay ? 'cloud-sun' : 'clouds';\n if (code === 3) return 'clouds';\n if ([45, 48].includes(code)) return 'cloud-fog';\n if ([51, 53, 55, 56, 57].includes(code)) return 'cloud-drizzle';\n if ([61, 63].includes(code)) return 'cloud-showers';\n if ([65, 66, 67, 80, 81, 82].includes(code)) return 'cloud-showers-heavy';\n if ([71, 73, 75, 77, 85, 86].includes(code)) return 'cloud-snow';\n if (code === 95) return 'cloud-bolt';\n if ([96, 99].includes(code)) return 'cloud-hail';\n return 'clouds';\n}\n","import type { WeatherLocation } from '../types';\n\nconst DEFAULT_IP_API_URL = 'https://ipapi.co';\n\ntype IpApiResponse = {\n city?: string;\n region?: string;\n country_name?: string;\n timezone?: string;\n latitude?: number;\n longitude?: number;\n error?: boolean;\n reason?: string;\n};\n\ntype GeoWorkerResponse = {\n city?: string;\n region?: string;\n country?: string;\n timezone?: string;\n latitude?: number | string;\n longitude?: number | string;\n};\n\nexport async function getClientLocation(geoEndpoint?: string, ip?: string): Promise<WeatherLocation> {\n if (geoEndpoint) {\n const url = ip ? `${geoEndpoint}?ip=${encodeURIComponent(ip)}` : geoEndpoint;\n const res = await fetch(url);\n if (!res.ok) throw new Error(`Geolocation worker lookup failed: ${res.status}`);\n const data: GeoWorkerResponse = await res.json();\n\n return {\n city: data.city,\n region: data.region,\n country: data.country,\n timezone: data.timezone,\n latitude: Number(data.latitude),\n longitude: Number(data.longitude),\n };\n }\n\n const res = await fetch(`${DEFAULT_IP_API_URL}/${ip ? `${encodeURIComponent(ip)}/` : ''}json/`);\n if (!res.ok) throw new Error(`ipapi.co lookup failed: ${res.status}`);\n const data: IpApiResponse = await res.json();\n\n if (data.error) {\n throw new Error(`ipapi.co lookup failed: ${data.reason ?? 'unknown error'}`);\n }\n\n return {\n city: data.city,\n region: data.region,\n country: data.country_name,\n timezone: data.timezone,\n latitude: Number(data.latitude),\n longitude: Number(data.longitude),\n };\n}\n","import type { WeatherForecastData, WeatherForecastOptions, WeatherLocation } from '../types';\nimport { getWeatherIcon } from '../weatherCodes';\nimport { getClientLocation } from './geolocation';\n\nfunction buildUrl(latitude: number, longitude: number, options: WeatherForecastOptions) {\n const params = new URLSearchParams({\n latitude: String(latitude),\n longitude: String(longitude),\n timezone: options.location?.timezone || 'auto',\n temperature_unit: options.temperatureUnit || 'fahrenheit',\n wind_speed_unit: options.windSpeedUnit || 'mph',\n forecast_days: String(options.forecastDays ?? 5),\n forecast_hours: String(options.forecastHours ?? 24),\n current: [\n 'temperature_2m',\n 'weather_code',\n 'is_day',\n 'rain',\n 'showers',\n 'snowfall',\n 'wind_speed_10m',\n ].join(','),\n hourly: [\n 'temperature_2m',\n 'weather_code',\n 'precipitation_probability',\n 'rain',\n 'showers',\n 'snowfall',\n ].join(','),\n daily: [\n 'temperature_2m_max',\n 'temperature_2m_min',\n 'weather_code',\n 'precipitation_probability_max',\n ].join(','),\n });\n\n return `https://api.open-meteo.com/v1/forecast?${params.toString()}`;\n}\n\nexport async function getWeatherForecast(\n options: WeatherForecastOptions = {}\n): Promise<WeatherForecastData> {\n let location: WeatherLocation;\n\n if (typeof options.latitude === 'number' && typeof options.longitude === 'number') {\n location = {\n ...options.location,\n latitude: options.latitude,\n longitude: options.longitude,\n };\n } else {\n location = await getClientLocation(options.geoEndpoint, options.ip);\n }\n\n const url = buildUrl(location.latitude, location.longitude, { ...options, location });\n const response = await fetch(url, { headers: { 'Content-Type': 'application/json' } });\n\n if (!response.ok) {\n throw new Error(`Weather request failed: ${response.status} ${response.statusText}`);\n }\n\n const data = await response.json();\n\n if (!data?.current || !data?.hourly || !data?.daily) {\n throw new Error('Invalid weather response');\n }\n\n return {\n location: { ...location, timezone: data.timezone || location.timezone },\n current: {\n time: data.current.time,\n temperature: Math.round(data.current.temperature_2m),\n weatherCode: data.current.weather_code,\n icon: getWeatherIcon(data.current.weather_code, data.current.is_day),\n isDay: data.current.is_day,\n rain: data.current.rain,\n showers: data.current.showers,\n snowfall: data.current.snowfall,\n windSpeed: data.current.wind_speed_10m,\n },\n hourly: data.hourly.time.map((time: string, index: number) => ({\n time,\n temperature: Math.round(data.hourly.temperature_2m[index]),\n weatherCode: data.hourly.weather_code[index],\n precipitationProbability: data.hourly.precipitation_probability?.[index],\n rain: data.hourly.rain?.[index],\n showers: data.hourly.showers?.[index],\n snowfall: data.hourly.snowfall?.[index],\n icon: getWeatherIcon(data.hourly.weather_code[index]),\n })),\n daily: data.daily.time.map((date: string, index: number) => ({\n date,\n min: Math.round(data.daily.temperature_2m_min[index]),\n max: Math.round(data.daily.temperature_2m_max[index]),\n weatherCode: data.daily.weather_code[index],\n precipitationProbabilityMax: data.daily.precipitation_probability_max?.[index],\n icon: getWeatherIcon(data.daily.weather_code[index]),\n })),\n };\n}\n","import { useEffect, useState } from 'react';\nimport type { WeatherForecastData, WeatherForecastOptions } from '../types';\nimport { getWeatherForecast } from '../api/forecast';\n\nexport function useWeatherForecast(options: WeatherForecastOptions = {}) {\n const [data, setData] = useState<WeatherForecastData | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n let active = true;\n setLoading(true);\n setError(null);\n\n getWeatherForecast(options)\n .then((result) => { if (active) setData(result); })\n .catch((err) => { if (active) setError(err instanceof Error ? err : new Error('Unknown error')); })\n .finally(() => { if (active) setLoading(false); });\n\n return () => { active = false; };\n }, [\n options.latitude,\n options.longitude,\n options.geoEndpoint,\n options.ip,\n options.forecastDays,\n options.forecastHours,\n options.temperatureUnit,\n options.windSpeedUnit,\n options.location?.timezone,\n ]);\n\n return { data, error, loading };\n}\n","import React from 'react';\nimport type { IconProps } from '../types';\n\nexport function BaseIcon({ title, children, ...props }: IconProps & { children: React.ReactNode }) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n role={title ? 'img' : 'presentation'}\n aria-hidden={title ? undefined : true}\n aria-label={title}\n {...props}\n >\n {title ? <title>{title}</title> : null}\n {children}\n </svg>\n );\n}\n","import React from 'react';\nimport type { IconProps } from '../types';\nimport { BaseIcon } from './BaseIcon';\n\nexport const CloudBoltIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M7 18a4.815 4.815 0 0 1-3.327-1.318A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 0 7h-1m-4.75-5L11 17.5h3.375l-2.25 4.5\" /></BaseIcon>\n);\nexport const CloudDrizzleIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M12 18v1m-3-4v1m6-1v1m2 3v1M7 19v1m-3-3.034a4.63 4.63 0 0 1-.327-.284A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 1.5 6.662\" /></BaseIcon>\n);\nexport const CloudFogIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M4 16.966a4.63 4.63 0 0 1-.327-.284A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 1.5 6.662M5 21h7m4 0h3M8 17h8\" /></BaseIcon>\n);\nexport const CloudHailIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M8 17.45v.1m-1.5 3.9v.1m10.5-4.1v.1m-1.5 3.9v.1m-3-4.1v.1m-1.5 3.9v.1m10.475-4.575A3.5 3.5 0 0 0 19 11h-1c.146-.65.148-1.32.006-1.97a4.784 4.784 0 0 0-.831-1.823 5.36 5.36 0 0 0-1.544-1.398 5.964 5.964 0 0 0-2.02-.759 6.224 6.224 0 0 0-2.19-.006 5.971 5.971 0 0 0-2.024.749C8.157 6.533 7.295 7.687 7 9a4.815 4.815 0 0 0-3.327 1.318A4.403 4.403 0 0 0 2.295 13.5c0 1.194.496 2.338 1.378 3.182.105.1.214.195.327.284m4.5.534a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Zm-1.5 4a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Zm10.5-4a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Zm-1.5 4a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Zm-3-4a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Zm-1.5 4a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0Z\" /></BaseIcon>\n);\nexport const CloudShowersIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M4 16.966a4.63 4.63 0 0 1-.327-.284A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 1.5 6.662M12 13v2m0 3v2m4-5v2m0 3v2m-8-7v2m0 3v2\" /></BaseIcon>\n);\nexport const CloudShowersHeavyIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M4 16.966a4.63 4.63 0 0 1-.327-.284A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 1.5 6.662M16 15v6m-8-6v6m4-8v6\" /></BaseIcon>\n);\nexport const CloudSleetIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M13.5 17.45a1 1 0 1 0-2 0h2Zm-2 .1a1 1 0 1 0 2 0h-2Zm.5 3.9a1 1 0 1 0-2 0h2Zm-2 .1a1 1 0 1 0 2 0h-2Zm-6.327-4.868.692-.723-.692.723ZM7 9v1a1 1 0 0 0 .976-.781L7 9Zm2.397-3.207.512.858-.512-.858ZM18 11l-.976-.219A1 1 0 0 0 18 12v-1Zm2.768 5.268a1 1 0 0 0 1.414 1.414l-.707-.707-.707-.707ZM3.379 17.75a1 1 0 0 0 1.242-1.567L4 16.966l-.62.784Zm5.55-.379a1 1 0 0 0-1.857-.742L8 17l.928.371ZM5.071 21.63a1 1 0 0 0 1.856.742L6 22l-.928-.371Zm13.857-4.258a1 1 0 0 0-1.857-.742L18 17l.928.371Zm-3.857 4.258a1 1 0 0 0 1.857.742L16 22l-.928-.371ZM13 17.5h-1a.5.5 0 0 1 .5-.5v2a1.5 1.5 0 0 0 1.5-1.5h-1Zm-.5.5v-1a.5.5 0 0 1 .5.5h-2a1.5 1.5 0 0 0 1.5 1.5v-1Zm-.5-.5h1a.5.5 0 0 1-.5.5v-2a1.5 1.5 0 0 0-1.5 1.5h1Zm.5-.5v1a.5.5 0 0 1-.5-.5h2a1.5 1.5 0 0 0-1.5-1.5v1Zm0 .45h-1v.1h2v-.1h-1Zm-1 4.05h-1a.5.5 0 0 1 .5-.5v2a1.5 1.5 0 0 0 1.5-1.5h-1Zm-.5.5v-1a.5.5 0 0 1 .5.5h-2A1.5 1.5 0 0 0 11 23v-1Zm-.5-.5h1a.5.5 0 0 1-.5.5v-2a1.5 1.5 0 0 0-1.5 1.5h1Zm.5-.5v1a.5.5 0 0 1-.5-.5h2A1.5 1.5 0 0 0 11 20v1Zm0 .45h-1v.1h2v-.1h-1Zm-7.327-4.768.692-.723a3.403 3.403 0 0 1-1.07-2.459h-2c0 1.473.613 2.877 1.687 3.905l.691-.723ZM2.295 13.5h1c0-.914.38-1.8 1.07-2.46l-.692-.722-.69-.723A5.403 5.403 0 0 0 1.294 13.5h1Zm1.378-3.182.692.723A3.815 3.815 0 0 1 7 10V8c-1.499 0-2.945.57-4.018 1.595l.691.723ZM7 9l.976.219c.23-1.024.91-1.956 1.933-2.568l-.512-.858-.513-.859c-1.456.87-2.5 2.245-2.86 3.847L7 9Zm2.397-3.207.512.858a4.972 4.972 0 0 1 1.686-.622l-.173-.985-.174-.985a6.971 6.971 0 0 0-2.364.875l.513.859Zm2.025-.749.173.985a5.223 5.223 0 0 1 1.837.005l.18-.984.178-.984a7.223 7.223 0 0 0-2.542-.007l.174.985Zm2.19.006-.18.984c.606.11 1.177.326 1.681.631l.518-.856.518-.855a6.963 6.963 0 0 0-2.359-.888l-.179.984Zm2.02.76-.519.855c.505.305.93.693 1.257 1.136l.805-.594.805-.594a6.361 6.361 0 0 0-1.831-1.659l-.518.855Zm1.543 1.397-.805.594c.326.442.549.932.66 1.441l.976-.212.978-.213a5.786 5.786 0 0 0-1.005-2.204l-.804.594Zm.831 1.823-.977.212c.111.509.11 1.031-.005 1.539L18 11l.976.219c.178-.792.18-1.609.008-2.402l-.978.213ZM18 11v1h1v-2h-1v1Zm1 0v1a2.5 2.5 0 0 1 1.768.732l.707-.707.707-.707A4.5 4.5 0 0 0 19 10v1Zm2.475 1.025-.707.707A2.5 2.5 0 0 1 21.5 14.5h2a4.5 4.5 0 0 0-1.318-3.182l-.707.707ZM22.5 14.5h-1a2.5 2.5 0 0 1-.732 1.768l.707.707.707.707A4.5 4.5 0 0 0 23.5 14.5h-1ZM4 16.966l.62-.784a3.684 3.684 0 0 1-.255-.223l-.692.723-.69.723c.126.121.259.237.396.345L4 16.966ZM8 17l-.928-.371-2 5L6 22l.928.371 2-5L8 17Zm10 0-.928-.371-2 5L16 22l.928.371 2-5L18 17Z\" /></BaseIcon>\n);\nexport const CloudSnowIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M8 15h2m-1-1v2m5-1h2m-1-1v2M5 21h2m-1-1v2m5-2h2m-1-1v2m5 0h2m-1-1v2M4 16.966a4.63 4.63 0 0 1-.327-.284A4.403 4.403 0 0 1 2.295 13.5c0-1.194.496-2.338 1.378-3.182A4.815 4.815 0 0 1 7 9c.295-1.313 1.157-2.466 2.397-3.207a5.971 5.971 0 0 1 2.025-.749 6.224 6.224 0 0 1 2.19.006c.721.131 1.408.39 2.02.76a5.36 5.36 0 0 1 1.543 1.397c.407.552.69 1.172.831 1.823.142.65.14 1.32-.006 1.97h1a3.5 3.5 0 0 1 1.5 6.662\" /></BaseIcon>\n);\nexport const CloudSunIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M10.201 19.997c-1.977 0-3.58-1.544-3.58-3.448 0-1.903 1.603-3.446 3.58-3.446.303-1.355 1.38-2.461 2.827-2.902 1.445-.44 3.042-.148 4.186.77 1.144.915 1.663 2.312 1.361 3.667h.761c1.472 0 2.664 1.2 2.664 2.68A2.672 2.672 0 0 1 19.336 20h-9.134m2.66-12.934a4.166 4.166 0 0 0-2.677-1.732m2.677 1.732 2.744-1.892m-2.744 1.892c.55.796.802 1.754.723 2.709m-3.4-4.44a4.167 4.167 0 0 0-3.118.667m3.118-.668.602-3.278m-3.72 3.946A4.167 4.167 0 0 0 5.334 8.68m1.733-2.678L5.174 3.26m.16 5.42c-.2 1.088.041 2.21.669 3.12m-.669-3.12-3.278-.601m3.947 3.72-2.744 1.893m2.744-1.893a4.167 4.167 0 0 0 2.174 1.607\" /></BaseIcon>\n);\nexport const CloudsIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M8.958 21.05C6.772 21.05 5 19.344 5 17.24s1.772-3.81 3.958-3.81c.335-1.498 1.525-2.72 3.124-3.207 1.598-.487 3.363-.164 4.628.85 1.264 1.011 1.837 2.556 1.504 4.053h.842A2.953 2.953 0 0 1 22 18.09a2.954 2.954 0 0 1-2.945 2.964H8.958M18 8c-.5-2.5-3.532-3.401-5.5-2.5a3.117 3.117 0 0 0-2.11-2.312c-1.352-.411-2.845-.138-3.915.72-1.07.855-1.554 2.161-1.273 3.428h-.711A2.498 2.498 0 0 0 2 9.843c0 1.094.695 2.023 1.666 2.366\" /></BaseIcon>\n);\nexport const SnowflakeIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"m9.25 4-1 2H6m-2.25 4L5 12m0 0-1.25 2M5 12h3m-3 0H2.5m17.75-2L19 12l1.25 2M6 18h2.25l1 2M14 9h-4m4 0 3-5m-3 5 2 3m-6-3L7 4m3 5-2 3m0 0 2 3m0 0-3 5m3-5h4m2-3-2 3m2-3h5.5M14 15l3 5M14.75 4l1 2H18m0 12h-2.25l-1 2\" /></BaseIcon>\n);\nexport const SunIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M12 4V2m0 20v-2m10-8h-2M4 12H2m15.657-5.657 1.414-1.414M4.93 19.07l1.414-1.414m12.728 1.414-1.414-1.414M6.343 6.343 4.93 4.929M7 12a5 5 0 1 0 10 0 5 5 0 0 0-10 0Z\" /></BaseIcon>\n);\nexport const WindIcon = (props: IconProps) => (\n <BaseIcon {...props}><path d=\"M9.59 4.59A2 2 0 1 1 11 8H2m10.59 11.41A2 2 0 1 0 14 16H2m15.73-8.27A2.5 2.5 0 1 1 19.5 12H2\" /></BaseIcon>\n);\n","import React from 'react';\nimport type { IconProps, WeatherCondition } from '../types';\nimport {\n CloudBoltIcon,\n CloudDrizzleIcon,\n CloudFogIcon,\n CloudHailIcon,\n CloudShowersHeavyIcon,\n CloudShowersIcon,\n CloudSleetIcon,\n CloudSnowIcon,\n CloudSunIcon,\n CloudsIcon,\n SnowflakeIcon,\n SunIcon,\n} from './weather-icons';\n\nconst iconMap: Record<WeatherCondition, React.ComponentType<IconProps>> = {\n sun: SunIcon,\n 'cloud-sun': CloudSunIcon,\n clouds: CloudsIcon,\n 'cloud-fog': CloudFogIcon,\n 'cloud-drizzle': CloudDrizzleIcon,\n 'cloud-showers': CloudShowersIcon,\n 'cloud-showers-heavy': CloudShowersHeavyIcon,\n 'cloud-sleet': CloudSleetIcon,\n 'cloud-snow': CloudSnowIcon,\n snowflake: SnowflakeIcon,\n 'cloud-bolt': CloudBoltIcon,\n 'cloud-hail': CloudHailIcon,\n};\n\nexport function WeatherIcon({ condition, ...props }: IconProps & { condition: WeatherCondition }) {\n const Icon = iconMap[condition] || CloudsIcon;\n return <Icon {...props} />;\n}\n","import React, { useEffect, useState } from 'react';\nimport { useWeatherForecast } from '../hooks/useWeatherForecast';\nimport type { HourlyWeather, TemperatureUnit, WeatherForecastOptions, WindSpeedUnit } from '../types';\nimport { WeatherIcon } from '../icons/WeatherIcon';\nimport { WindIcon } from '../icons/weather-icons';\n\ntype Props = WeatherForecastOptions & {\n className?: string;\n style?: React.CSSProperties;\n compact?: boolean;\n};\n\nconst WIND_SPEED_UNIT_LABELS: Record<WindSpeedUnit, string> = {\n kmh: 'km/h',\n mph: 'mph',\n ms: 'm/s',\n kn: 'kn',\n};\n\nfunction closestHour(hourly: HourlyWeather[], targetTime: Date): HourlyWeather | undefined {\n return hourly.reduce<HourlyWeather | undefined>((closest, hour) => {\n const diff = Math.abs(new Date(hour.time).getTime() - targetTime.getTime());\n const closestDiff = closest ? Math.abs(new Date(closest.time).getTime() - targetTime.getTime()) : Infinity;\n return diff < closestDiff ? hour : closest;\n }, undefined);\n}\n\n// Format a real instant in a specific IANA timezone, falling back to the\n// browser's local zone if the timezone string is missing or invalid.\nfunction formatInZone(instant: Date, timezone: string | undefined, options: Intl.DateTimeFormatOptions): string {\n try {\n return new Intl.DateTimeFormat([], { ...options, timeZone: timezone || undefined }).format(instant);\n } catch {\n return new Intl.DateTimeFormat([], options).format(instant);\n }\n}\n\nconst styles = {\n root: {\n fontFamily: 'system-ui, sans-serif',\n border: '1px solid #e5e7eb',\n borderRadius: 12,\n padding: 16,\n background: '#fff',\n color: '#111827',\n maxWidth: 640,\n } as React.CSSProperties,\n row: { display: 'flex', alignItems: 'center', gap: 8 } as React.CSSProperties,\n hours: { display: 'flex', gap: 12, overflowX: 'auto', paddingBottom: 4 } as React.CSSProperties,\n hourCard: { minWidth: 72, textAlign: 'center' as const, padding: 8, borderRadius: 8, background: '#f9fafb' },\n dayRow: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, padding: '8px 0', borderBottom: '1px solid #f3f4f6' } as React.CSSProperties,\n compactRoot: { fontFamily: 'system-ui, sans-serif', display: 'flex', flexDirection: 'column', gap: 8, padding: '10px 14px', borderRadius: 8 } as React.CSSProperties,\n compactHeader: { display: 'flex', alignItems: 'center', gap: 10 } as React.CSSProperties,\n compactHeaderText: { display: 'flex', alignItems: 'baseline', gap: 8, flexWrap: 'wrap' } as React.CSSProperties,\n compactDateTime: { fontSize: 11, opacity: 0.7 } as React.CSSProperties,\n compactStats: { display: 'flex', flexWrap: 'wrap', gap: 12, fontSize: 12, opacity: 0.9 } as React.CSSProperties,\n compactStat: { display: 'flex', alignItems: 'center', gap: 4, whiteSpace: 'nowrap' } as React.CSSProperties,\n unitSwitch: { display: 'inline-flex', alignItems: 'center', cursor: 'pointer', userSelect: 'none' } as React.CSSProperties,\n rain: { color: '#2563eb', whiteSpace: 'nowrap' } as React.CSSProperties,\n tz: { fontSize: 12, opacity: 0.7, marginTop: 2 } as React.CSSProperties,\n list: { display: 'flex', flexDirection: 'column' } as React.CSSProperties,\n};\n\n// Precipitation chance is only surfaced when there is a non-zero chance of it.\nfunction RainBadge({ probability, compact }: { probability?: number; compact?: boolean }) {\n if (probability === undefined || probability === null || probability <= 0) return null;\n return <span style={styles.rain}>{compact ? ` · ${probability}%` : ` · ${probability}% rain`}</span>;\n}\n\n/**\n * Renders one location's forecast: a live current time (ticking, in the\n * location's own timezone), a clickable degF / degC unit switch, high/low and\n * precipitation for the next hours and days.\n */\nfunction SingleWeatherForecast(props: Props) {\n // Temperature unit is local state so the degF / degC switch can toggle it;\n // it is seeded from (and re-synced to) the temperatureUnit prop.\n const [unit, setUnit] = useState<TemperatureUnit>(props.temperatureUnit ?? 'fahrenheit');\n useEffect(() => {\n setUnit(props.temperatureUnit ?? 'fahrenheit');\n }, [props.temperatureUnit]);\n\n const { data, loading, error } = useWeatherForecast({ ...props, temperatureUnit: unit });\n\n // A ticking clock so the displayed current time stays accurate to the second.\n const [now, setNow] = useState(() => new Date());\n useEffect(() => {\n const id = setInterval(() => setNow(new Date()), 1000);\n return () => clearInterval(id);\n }, []);\n\n const toggleUnit = () => setUnit((u) => (u === 'celsius' ? 'fahrenheit' : 'celsius'));\n\n const renderUnitSwitch = (fontSize: number) => (\n <span\n role=\"button\"\n tabIndex={0}\n onClick={(e) => {\n e.stopPropagation();\n toggleUnit();\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n toggleUnit();\n }\n }}\n title=\"Switch temperature units\"\n aria-label={`Switch temperature units, currently ${unit === 'celsius' ? 'Celsius' : 'Fahrenheit'}`}\n style={{ ...styles.unitSwitch, fontSize }}\n >\n <span style={{ fontWeight: unit === 'fahrenheit' ? 700 : 400, opacity: unit === 'fahrenheit' ? 1 : 0.45 }}>°F</span>\n <span style={{ opacity: 0.4, margin: '0 3px' }}>|</span>\n <span style={{ fontWeight: unit === 'celsius' ? 700 : 400, opacity: unit === 'celsius' ? 1 : 0.45 }}>°C</span>\n </span>\n );\n\n // Keep showing the last forecast while a unit switch refetches in the\n // background; only suppress output on the very first load.\n if (loading && !data) return null;\n if (error) return <div className={props.className} style={props.style}>Error: {error.message}</div>;\n if (!data) return <div className={props.className} style={props.style}>No forecast available.</div>;\n\n const timezone = data.location?.timezone;\n const currentDate = formatInZone(now, timezone, { weekday: 'short', month: 'short', day: 'numeric' });\n const currentTime = formatInZone(now, timezone, { hour: 'numeric', minute: '2-digit', second: '2-digit', timeZoneName: 'short' });\n\n if (props.compact) {\n const forecastBase = new Date(data.current.time);\n const today = data.daily[0];\n const tomorrow = data.daily[1];\n const in6Hours = closestHour(data.hourly, new Date(forecastBase.getTime() + 6 * 60 * 60 * 1000));\n const windSpeedUnitLabel = WIND_SPEED_UNIT_LABELS[props.windSpeedUnit ?? 'mph'];\n\n return (\n <div className={props.className} style={{ ...styles.compactRoot, ...props.style }}>\n <div style={styles.compactHeader}>\n <WeatherIcon condition={data.current.icon} width={24} height={24} title=\"Current weather\" />\n <div>\n <div style={styles.compactHeaderText}>\n <strong style={{ fontSize: 16 }}>{data.current.temperature}</strong>\n {renderUnitSwitch(12)}\n <span style={{ fontSize: 14, opacity: 0.8 }}>\n {data.location?.city || 'Current location'}\n </span>\n </div>\n <div style={styles.compactDateTime}>\n {currentDate}\n {' · '}\n {currentTime}\n </div>\n </div>\n </div>\n\n <div style={styles.compactStats}>\n {today && (\n <span style={styles.compactStat}>\n <WeatherIcon condition={today.icon} width={16} height={16} title=\"Today's high and low\" />\n {today.max}° / {today.min}°\n <RainBadge probability={today.precipitationProbabilityMax} compact />\n </span>\n )}\n {tomorrow && (\n <span style={styles.compactStat}>\n <WeatherIcon condition={tomorrow.icon} width={16} height={16} title=\"Tomorrow's high and low\" />\n Tomorrow {tomorrow.max}° / {tomorrow.min}°\n <RainBadge probability={tomorrow.precipitationProbabilityMax} compact />\n </span>\n )}\n <span style={styles.compactStat}>\n <WindIcon width={16} height={16} title=\"Wind speed\" />\n {data.current.windSpeed !== undefined ? `${Math.round(data.current.windSpeed)} ${windSpeedUnitLabel}` : '—'}\n </span>\n {in6Hours && (\n <span style={styles.compactStat}>\n <WeatherIcon condition={in6Hours.icon} width={16} height={16} title=\"In 6 hours\" />\n {in6Hours.temperature}° in 6h\n <RainBadge probability={in6Hours.precipitationProbability} compact />\n </span>\n )}\n </div>\n </div>\n );\n }\n\n return (\n <div className={props.className} style={{ ...styles.root, ...props.style }}>\n <div>\n <h3 style={{ margin: 0, fontSize: 20 }}>\n {data.location?.city || 'Current location'}\n {data.location?.region ? `, ${data.location.region}` : ''}\n </h3>\n <div style={styles.tz}>\n {currentDate} · {currentTime}\n {timezone ? ` · ${timezone}` : ''}\n </div>\n <div style={{ ...styles.row, marginTop: 8 }}>\n <WeatherIcon condition={data.current.icon} width={28} height={28} title=\"Current weather\" />\n <strong style={{ fontSize: 28 }}>{data.current.temperature}</strong>\n {renderUnitSwitch(14)}\n </div>\n </div>\n\n <div style={{ marginTop: 20 }}>\n <h4 style={{ margin: '0 0 10px 0' }}>Next hours</h4>\n <div style={styles.hours}>\n {data.hourly.slice(0, props.forecastHours ?? 12).map((hour) => (\n <div key={hour.time} style={styles.hourCard}>\n <div style={{ fontSize: 12 }}>{new Date(hour.time).toLocaleTimeString([], { hour: 'numeric' })}</div>\n <WeatherIcon condition={hour.icon} width={20} height={20} style={{ margin: '6px auto' }} />\n <div>{hour.temperature}°</div>\n {hour.precipitationProbability !== undefined && hour.precipitationProbability > 0 && (\n <div style={{ ...styles.rain, fontSize: 12 }}>{hour.precipitationProbability}%</div>\n )}\n </div>\n ))}\n </div>\n </div>\n\n <div style={{ marginTop: 20 }}>\n <h4 style={{ margin: '0 0 10px 0' }}>Next days</h4>\n <div>\n {data.daily.map((day) => (\n <div key={day.date} style={styles.dayRow}>\n <div style={{ width: 120 }}>{new Date(day.date).toLocaleDateString([], { weekday: 'short', month: 'short', day: 'numeric' })}</div>\n <WeatherIcon condition={day.icon} width={20} height={20} />\n <div>\n {day.min}° / {day.max}°\n {day.precipitationProbabilityMax !== undefined && day.precipitationProbabilityMax > 0 && (\n <span style={styles.rain}> · {day.precipitationProbabilityMax}%</span>\n )}\n </div>\n </div>\n ))}\n </div>\n </div>\n </div>\n );\n}\n\n/**\n * Weather forecast widget. When `locations` is provided, one forecast is\n * rendered per location; otherwise a single auto-detected forecast is shown.\n */\nexport function WeatherForecast(props: Props) {\n const { locations, ...rest } = props;\n\n if (locations && locations.length > 0) {\n const gap = props.compact ? 8 : 16;\n return (\n <div style={{ ...styles.list, gap }}>\n {locations.map((loc, index) => (\n <SingleWeatherForecast\n key={`${loc.label ?? ''}:${loc.latitude ?? ''}:${loc.longitude ?? ''}:${index}`}\n {...rest}\n latitude={typeof loc.latitude === 'number' ? loc.latitude : undefined}\n longitude={typeof loc.longitude === 'number' ? loc.longitude : undefined}\n location={{ city: loc.label, timezone: loc.timezone }}\n />\n ))}\n </div>\n );\n }\n\n return <SingleWeatherForecast {...rest} />;\n}\n"],"mappings":"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","names":["res","data","jsx","jsx","useEffect","useState","jsx","jsxs","useState","useEffect"]}
|