@aparte/plugin-cards 0.0.0-stage → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +148 -2
- package/dist/carousel-CPy-0JGN.js +63 -0
- package/dist/carousel-CPy-0JGN.js.map +1 -0
- package/dist/controls-BVX2u7sK.js +62 -0
- package/dist/controls-BVX2u7sK.js.map +1 -0
- package/dist/format-CchcJRum.js +720 -0
- package/dist/format-CchcJRum.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/items/icons.d.ts +12 -0
- package/dist/items/icons.d.ts.map +1 -0
- package/dist/items/index.d.ts +100 -0
- package/dist/items/index.d.ts.map +1 -0
- package/dist/items.js +698 -0
- package/dist/items.js.map +1 -0
- package/dist/kit/carousel.d.ts +17 -0
- package/dist/kit/carousel.d.ts.map +1 -0
- package/dist/kit/controls.d.ts +51 -0
- package/dist/kit/controls.d.ts.map +1 -0
- package/dist/kit/define.d.ts +194 -0
- package/dist/kit/define.d.ts.map +1 -0
- package/dist/kit/dom.d.ts +40 -0
- package/dist/kit/dom.d.ts.map +1 -0
- package/dist/kit/format.d.ts +49 -0
- package/dist/kit/format.d.ts.map +1 -0
- package/dist/kit/rating.d.ts +19 -0
- package/dist/kit/rating.d.ts.map +1 -0
- package/dist/kit/sparkline.d.ts +19 -0
- package/dist/kit/sparkline.d.ts.map +1 -0
- package/dist/kit/strings.d.ts +139 -0
- package/dist/kit/strings.d.ts.map +1 -0
- package/dist/link/icons.d.ts +16 -0
- package/dist/link/icons.d.ts.map +1 -0
- package/dist/link/index.d.ts +98 -0
- package/dist/link/index.d.ts.map +1 -0
- package/dist/link.js +387 -0
- package/dist/link.js.map +1 -0
- package/dist/media/icons.d.ts +28 -0
- package/dist/media/icons.d.ts.map +1 -0
- package/dist/media/index.d.ts +107 -0
- package/dist/media/index.d.ts.map +1 -0
- package/dist/media.js +610 -0
- package/dist/media.js.map +1 -0
- package/dist/order/icons.d.ts +49 -0
- package/dist/order/icons.d.ts.map +1 -0
- package/dist/order/index.d.ts +204 -0
- package/dist/order/index.d.ts.map +1 -0
- package/dist/order.js +1843 -0
- package/dist/order.js.map +1 -0
- package/dist/place/icons.d.ts +18 -0
- package/dist/place/icons.d.ts.map +1 -0
- package/dist/place/index.d.ts +207 -0
- package/dist/place/index.d.ts.map +1 -0
- package/dist/place.js +1456 -0
- package/dist/place.js.map +1 -0
- package/dist/plan/icons.d.ts +25 -0
- package/dist/plan/icons.d.ts.map +1 -0
- package/dist/plan/index.d.ts +153 -0
- package/dist/plan/index.d.ts.map +1 -0
- package/dist/plan.js +1191 -0
- package/dist/plan.js.map +1 -0
- package/dist/product/icons.d.ts +16 -0
- package/dist/product/icons.d.ts.map +1 -0
- package/dist/product/index.d.ts +133 -0
- package/dist/product/index.d.ts.map +1 -0
- package/dist/product.js +1245 -0
- package/dist/product.js.map +1 -0
- package/dist/rating-B8Mdx_b_.js +35 -0
- package/dist/rating-B8Mdx_b_.js.map +1 -0
- package/dist/score/icons.d.ts +35 -0
- package/dist/score/icons.d.ts.map +1 -0
- package/dist/score/index.d.ts +185 -0
- package/dist/score/index.d.ts.map +1 -0
- package/dist/score.js +1843 -0
- package/dist/score.js.map +1 -0
- package/dist/sparkline-C-cA9obz.js +56 -0
- package/dist/sparkline-C-cA9obz.js.map +1 -0
- package/dist/stats/icons.d.ts +19 -0
- package/dist/stats/icons.d.ts.map +1 -0
- package/dist/stats/index.d.ts +137 -0
- package/dist/stats/index.d.ts.map +1 -0
- package/dist/stats.js +1085 -0
- package/dist/stats.js.map +1 -0
- package/dist/stock/chart.d.ts +135 -0
- package/dist/stock/chart.d.ts.map +1 -0
- package/dist/stock/icons.d.ts +15 -0
- package/dist/stock/icons.d.ts.map +1 -0
- package/dist/stock/index.d.ts +195 -0
- package/dist/stock/index.d.ts.map +1 -0
- package/dist/stock.js +1013 -0
- package/dist/stock.js.map +1 -0
- package/dist/weather/conditions.d.ts +25 -0
- package/dist/weather/conditions.d.ts.map +1 -0
- package/dist/weather/icons.d.ts +12 -0
- package/dist/weather/icons.d.ts.map +1 -0
- package/dist/weather/index.d.ts +146 -0
- package/dist/weather/index.d.ts.map +1 -0
- package/dist/weather.js +1162 -0
- package/dist/weather.js.map +1 -0
- package/package.json +137 -3
package/dist/weather.js
ADDED
|
@@ -0,0 +1,1162 @@
|
|
|
1
|
+
import { d as defineCard, o as str, p as word, e as el, n as num, t as toDate, i as formatUnit, k as glyph, f as formatDay, g as formatPercent, b as formatNumber, j as formatWhen, a as formatHour } from "./format-CchcJRum.js";
|
|
2
|
+
import { s as sparkline } from "./sparkline-C-cA9obz.js";
|
|
3
|
+
const WEATHER_CONDITIONS = [
|
|
4
|
+
"clear",
|
|
5
|
+
"partly-cloudy",
|
|
6
|
+
"cloudy",
|
|
7
|
+
"fog",
|
|
8
|
+
"drizzle",
|
|
9
|
+
"rain",
|
|
10
|
+
"heavy-rain",
|
|
11
|
+
"sleet",
|
|
12
|
+
"snow",
|
|
13
|
+
"thunder",
|
|
14
|
+
"wind"
|
|
15
|
+
];
|
|
16
|
+
function conditionFromWmo(code) {
|
|
17
|
+
const c = typeof code === "string" ? Number(code) : code;
|
|
18
|
+
if (typeof c !== "number" || !Number.isFinite(c)) return void 0;
|
|
19
|
+
if (c === 0) return "clear";
|
|
20
|
+
if (c === 1 || c === 2) return "partly-cloudy";
|
|
21
|
+
if (c === 3) return "cloudy";
|
|
22
|
+
if (c === 45 || c === 48) return "fog";
|
|
23
|
+
if (c >= 51 && c <= 55) return "drizzle";
|
|
24
|
+
if (c === 56 || c === 57 || c === 66 || c === 67) return "sleet";
|
|
25
|
+
if (c === 61 || c === 63 || c === 80 || c === 81) return "rain";
|
|
26
|
+
if (c === 65 || c === 82) return "heavy-rain";
|
|
27
|
+
if (c >= 71 && c <= 77 || c === 85 || c === 86) return "snow";
|
|
28
|
+
if (c >= 95 && c <= 99) return "thunder";
|
|
29
|
+
return void 0;
|
|
30
|
+
}
|
|
31
|
+
function conditionFromOpenWeather(id) {
|
|
32
|
+
const c = typeof id === "string" ? Number(id) : id;
|
|
33
|
+
if (typeof c !== "number" || !Number.isFinite(c)) return void 0;
|
|
34
|
+
if (c >= 200 && c < 300) return "thunder";
|
|
35
|
+
if (c >= 300 && c < 400) return "drizzle";
|
|
36
|
+
if (c === 511 || c >= 611 && c <= 616) return "sleet";
|
|
37
|
+
if (c >= 502 && c <= 504) return "heavy-rain";
|
|
38
|
+
if (c === 522 || c === 531) return "heavy-rain";
|
|
39
|
+
if (c >= 500 && c < 600) return "rain";
|
|
40
|
+
if (c >= 600 && c < 700) return "snow";
|
|
41
|
+
if (c === 771 || c === 781) return "wind";
|
|
42
|
+
if (c >= 700 && c < 800) return "fog";
|
|
43
|
+
if (c === 800) return "clear";
|
|
44
|
+
if (c === 801 || c === 802) return "partly-cloudy";
|
|
45
|
+
if (c === 803 || c === 804) return "cloudy";
|
|
46
|
+
return void 0;
|
|
47
|
+
}
|
|
48
|
+
const TEXT_MATCHES = [
|
|
49
|
+
[/thunder|storm|orage|lightning/i, "thunder"],
|
|
50
|
+
[/sleet|freezing|verglas|grésil|hail|grêle/i, "sleet"],
|
|
51
|
+
[/snow|neige|blizzard|flurr/i, "snow"],
|
|
52
|
+
[/heavy rain|downpour|torrential|forte pluie|averse forte|déluge/i, "heavy-rain"],
|
|
53
|
+
[/drizzle|bruine|crachin/i, "drizzle"],
|
|
54
|
+
[/rain|shower|pluie|pluvieux|averse/i, "rain"],
|
|
55
|
+
[/fog|mist|haze|brouillard|brume/i, "fog"],
|
|
56
|
+
[/partly|partial|scattered|few clouds|mostly sunny|éclaircie|partiellement|peu nuageux/i, "partly-cloudy"],
|
|
57
|
+
[/cloud|overcast|couvert|nuageux|gris/i, "cloudy"],
|
|
58
|
+
[/wind|gust|vent|rafale/i, "wind"],
|
|
59
|
+
[/clear|sunny|fair|soleil|ensoleillé|dégagé/i, "clear"]
|
|
60
|
+
];
|
|
61
|
+
function conditionFromText(text) {
|
|
62
|
+
if (typeof text !== "string" || !text.trim()) return void 0;
|
|
63
|
+
const known = text.trim().toLowerCase().replace(/[\s_]+/g, "-");
|
|
64
|
+
if (WEATHER_CONDITIONS.includes(known)) return known;
|
|
65
|
+
for (const [re, condition] of TEXT_MATCHES) if (re.test(text)) return condition;
|
|
66
|
+
return void 0;
|
|
67
|
+
}
|
|
68
|
+
const CONDITION_WORDS = {
|
|
69
|
+
clear: { en: "Clear", fr: "Dégagé", de: "Klar", es: "Despejado", it: "Sereno", ja: "晴れ", ko: "맑음", pt: "Céu limpo", ru: "Ясно", zh: "晴" },
|
|
70
|
+
"partly-cloudy": { en: "Partly cloudy", fr: "Partiellement nuageux", de: "Teilweise bewölkt", es: "Parcialmente nublado", it: "Parzialmente nuvoloso", ja: "晴れ時々曇り", ko: "구름 조금", pt: "Parcialmente nublado", ru: "Переменная облачность", zh: "多云" },
|
|
71
|
+
cloudy: { en: "Cloudy", fr: "Couvert", de: "Bewölkt", es: "Nublado", it: "Nuvoloso", ja: "曇り", ko: "흐림", pt: "Nublado", ru: "Облачно", zh: "阴" },
|
|
72
|
+
fog: { en: "Fog", fr: "Brouillard", de: "Nebel", es: "Niebla", it: "Nebbia", ja: "霧", ko: "안개", pt: "Nevoeiro", ru: "Туман", zh: "雾" },
|
|
73
|
+
drizzle: { en: "Drizzle", fr: "Bruine", de: "Nieselregen", es: "Llovizna", it: "Pioviggine", ja: "霧雨", ko: "이슬비", pt: "Garoa", ru: "Морось", zh: "毛毛雨" },
|
|
74
|
+
rain: { en: "Rain", fr: "Pluie", de: "Regen", es: "Lluvia", it: "Pioggia", ja: "雨", ko: "비", pt: "Chuva", ru: "Дождь", zh: "雨" },
|
|
75
|
+
"heavy-rain": { en: "Heavy rain", fr: "Forte pluie", de: "Starkregen", es: "Lluvia intensa", it: "Pioggia forte", ja: "大雨", ko: "폭우", pt: "Chuva forte", ru: "Сильный дождь", zh: "大雨" },
|
|
76
|
+
sleet: { en: "Sleet", fr: "Pluie verglaçante", de: "Schneeregen", es: "Aguanieve", it: "Nevischio", ja: "みぞれ", ko: "진눈깨비", pt: "Granizo fino", ru: "Мокрый снег", zh: "雨夹雪" },
|
|
77
|
+
snow: { en: "Snow", fr: "Neige", de: "Schnee", es: "Nieve", it: "Neve", ja: "雪", ko: "눈", pt: "Neve", ru: "Снег", zh: "雪" },
|
|
78
|
+
thunder: { en: "Thunderstorm", fr: "Orage", de: "Gewitter", es: "Tormenta", it: "Temporale", ja: "雷雨", ko: "뇌우", pt: "Trovoada", ru: "Гроза", zh: "雷雨" },
|
|
79
|
+
wind: { en: "Windy", fr: "Venteux", de: "Windig", es: "Ventoso", it: "Ventoso", ja: "強風", ko: "바람", pt: "Ventoso", ru: "Ветрено", zh: "有风" }
|
|
80
|
+
};
|
|
81
|
+
const r = (n) => Math.round(n * 100) / 100;
|
|
82
|
+
const RAYS = Array.from({ length: 8 }, (_, i) => {
|
|
83
|
+
const a = i * Math.PI / 4;
|
|
84
|
+
return `M${r(32 + 16 * Math.cos(a))} ${r(32 + 16 * Math.sin(a))}L${r(32 + 22 * Math.cos(a))} ${r(32 + 22 * Math.sin(a))}`;
|
|
85
|
+
}).join("");
|
|
86
|
+
const SUN = `<g class="aparte-wx-sun-g"><path class="aparte-wx-rays" d="${RAYS}"/><circle class="aparte-wx-sun" cx="32" cy="32" r="11"/></g>`;
|
|
87
|
+
const MOON = `<g class="aparte-wx-moon-g"><path class="aparte-wx-moon" d="M38.5 16.5A16 16 0 1 0 47.5 44.5A12.5 12.5 0 0 1 38.5 16.5Z"/><circle class="aparte-wx-star" cx="48" cy="17" r="1.6"/><circle class="aparte-wx-star" cx="54" cy="27" r="1.1"/></g>`;
|
|
88
|
+
const CLOUD_PATH = "M22 46H46A9 9 0 0 0 47 28.06A13 13 0 0 0 22.4 25.1A10.5 10.5 0 0 0 22 46Z";
|
|
89
|
+
const cloud = (cls, transform = "") => `<path class="${cls}"${transform ? ` transform="${transform}"` : ""} d="${CLOUD_PATH}"/>`;
|
|
90
|
+
const behind = (night) => `<g transform="translate(-6.5 -6.5) scale(0.72)" class="aparte-wx-behind">${night ? MOON : SUN}</g>`;
|
|
91
|
+
const drops = (n, cls = "aparte-wx-drop") => {
|
|
92
|
+
const xs = n === 5 ? [19, 26, 33, 40, 47] : n === 4 ? [22, 29, 36, 43] : n === 2 ? [24, 32] : [24, 32, 40];
|
|
93
|
+
return `<g class="aparte-wx-fall">${xs.map((x, i) => `<path class="${cls}" style="--i:${i}" d="M${x} ${46 + i % 2 * 3}l-2.5 6"/>`).join("")}</g>`;
|
|
94
|
+
};
|
|
95
|
+
const dots = (n) => {
|
|
96
|
+
const xs = [22, 29, 36, 43];
|
|
97
|
+
return `<g class="aparte-wx-fall">${xs.map((x, i) => `<circle class="aparte-wx-drip" style="--i:${i}" cx="${x}" cy="${49 + i % 2 * 3}" r="1.8"/>`).join("")}</g>`;
|
|
98
|
+
};
|
|
99
|
+
const flakes = (xs) => `<g class="aparte-wx-drift-down">${xs.map((x, i) => `<g class="aparte-wx-flake" style="--i:${i}" transform="translate(${x} ${50 + i % 2 * 4})"><path d="M0 -3.2V3.2M-2.8 -1.6L2.8 1.6M-2.8 1.6L2.8 -1.6"/></g>`).join("")}</g>`;
|
|
100
|
+
const BOLT = '<path class="aparte-wx-bolt" d="M34.5 40 26 53h6.5l-3 10L41 48.5h-6.5l4.5-8.5z"/>';
|
|
101
|
+
const FOG = '<g class="aparte-wx-fog-g"><path class="aparte-wx-fog" d="M14 49H50M18 55H46M22 61H42"/></g>';
|
|
102
|
+
const WIND = '<g class="aparte-wx-wind-g"><path class="aparte-wx-wind" d="M9 25h26a6 6 0 1 0-6-6"/><path class="aparte-wx-wind" d="M9 33h37a6.5 6.5 0 1 1-6.5 6.5"/><path class="aparte-wx-wind" d="M9 41h18"/></g>';
|
|
103
|
+
function weatherIcon(condition, night = false) {
|
|
104
|
+
const up = "translate(0 -6)";
|
|
105
|
+
let body;
|
|
106
|
+
switch (condition) {
|
|
107
|
+
case "clear":
|
|
108
|
+
body = night ? MOON : SUN;
|
|
109
|
+
break;
|
|
110
|
+
case "partly-cloudy":
|
|
111
|
+
body = `${behind(night)}<g class="aparte-wx-drift">${cloud("aparte-wx-cloud", "translate(4 6)")}</g>`;
|
|
112
|
+
break;
|
|
113
|
+
case "cloudy":
|
|
114
|
+
body = `${cloud("aparte-wx-cloud-back", "translate(8 -5) scale(0.82)")}<g class="aparte-wx-drift">${cloud("aparte-wx-cloud", "translate(-2 4)")}</g>`;
|
|
115
|
+
break;
|
|
116
|
+
case "fog":
|
|
117
|
+
body = `${cloud("aparte-wx-cloud", "translate(0 -8)")}${FOG}`;
|
|
118
|
+
break;
|
|
119
|
+
case "drizzle":
|
|
120
|
+
body = `${cloud("aparte-wx-cloud", up)}${dots()}`;
|
|
121
|
+
break;
|
|
122
|
+
case "rain":
|
|
123
|
+
body = `${cloud("aparte-wx-cloud", up)}${drops(3)}`;
|
|
124
|
+
break;
|
|
125
|
+
case "heavy-rain":
|
|
126
|
+
body = `${cloud("aparte-wx-cloud-back", "translate(9 -12) scale(0.8)")}${cloud("aparte-wx-cloud aparte-wx-cloud--dark", up)}${drops(5)}`;
|
|
127
|
+
break;
|
|
128
|
+
case "sleet":
|
|
129
|
+
body = `${cloud("aparte-wx-cloud", up)}${drops(2)}${flakes([40])}`;
|
|
130
|
+
break;
|
|
131
|
+
case "snow":
|
|
132
|
+
body = `${cloud("aparte-wx-cloud", up)}${flakes([23, 32, 41])}`;
|
|
133
|
+
break;
|
|
134
|
+
case "thunder":
|
|
135
|
+
body = `${cloud("aparte-wx-cloud-back", "translate(9 -12) scale(0.8)")}${cloud("aparte-wx-cloud aparte-wx-cloud--dark", up)}${BOLT}`;
|
|
136
|
+
break;
|
|
137
|
+
case "wind":
|
|
138
|
+
body = WIND;
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
return `<svg viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" class="aparte-wx" data-condition="${condition}"${night ? ' data-night=""' : ""}>${body}</svg>`;
|
|
142
|
+
}
|
|
143
|
+
const weatherStyles = `/* =========================================
|
|
144
|
+
The weather card — @aparte/plugin-cards/weather
|
|
145
|
+
=========================================
|
|
146
|
+
Three variants of one card, chosen by \`data-variant\` on its root:
|
|
147
|
+
hero the sky behind the temperature, the stats, the next hours
|
|
148
|
+
compact one line on the card's surface, the sky as an edge
|
|
149
|
+
forecast a header on the sky, then the days, each with its range
|
|
150
|
+
Every colour is a \`--aparte-weather-*\` token: the glyphs' parts, the eleven skies by
|
|
151
|
+
day and by night. A theme repaints the weather by setting them.
|
|
152
|
+
*/
|
|
153
|
+
|
|
154
|
+
/* Declared with no weight: core adds a renderer's sheet AFTER the app's CSS, so at equal
|
|
155
|
+
weight an app's own \`.aparte-weather-card { --aparte-weather-sky-clear: … }\` would lose. */
|
|
156
|
+
:where(.aparte-weather-card) {
|
|
157
|
+
/* The glyphs on the card's own surface. */
|
|
158
|
+
--aparte-weather-sun: #fbbf24;
|
|
159
|
+
--aparte-weather-sun-rays: #f59e0b;
|
|
160
|
+
--aparte-weather-moon: #c9ad5f;
|
|
161
|
+
--aparte-weather-star: #fde68a;
|
|
162
|
+
--aparte-weather-cloud: #c7d0dc;
|
|
163
|
+
--aparte-weather-cloud-back: #dfe5ed;
|
|
164
|
+
--aparte-weather-cloud-dark: #8794a7;
|
|
165
|
+
--aparte-weather-rain: #3b82f6;
|
|
166
|
+
--aparte-weather-snow: #6aa9ec;
|
|
167
|
+
--aparte-weather-bolt: #f5b80b;
|
|
168
|
+
--aparte-weather-fog: #98a3b3;
|
|
169
|
+
--aparte-weather-wind: #7f93ad;
|
|
170
|
+
|
|
171
|
+
/* The skies, by day. */
|
|
172
|
+
--aparte-weather-sky-clear: linear-gradient(160deg, #2a78dc 0%, #4fa7f0 55%, #7cc6f7 100%);
|
|
173
|
+
--aparte-weather-sky-partly-cloudy: linear-gradient(160deg, #3a7acb 0%, #6aa3dd 60%, #9cc4ea 100%);
|
|
174
|
+
--aparte-weather-sky-cloudy: linear-gradient(160deg, #56657a 0%, #75849a 60%, #8d9bb0 100%);
|
|
175
|
+
--aparte-weather-sky-fog: linear-gradient(160deg, #636e7d 0%, #808a98 60%, #9aa3af 100%);
|
|
176
|
+
--aparte-weather-sky-drizzle: linear-gradient(160deg, #4a6079 0%, #6a7f98 60%, #8396ac 100%);
|
|
177
|
+
--aparte-weather-sky-rain: linear-gradient(160deg, #364860 0%, #55687f 60%, #6c7f95 100%);
|
|
178
|
+
--aparte-weather-sky-heavy-rain: linear-gradient(160deg, #2a374b 0%, #445367 60%, #5a697d 100%);
|
|
179
|
+
--aparte-weather-sky-sleet: linear-gradient(160deg, #495b71 0%, #6a7f96 60%, #8ea2b8 100%);
|
|
180
|
+
--aparte-weather-sky-snow: linear-gradient(160deg, #557495 0%, #7e9cbd 60%, #a5bfd8 100%);
|
|
181
|
+
--aparte-weather-sky-thunder: linear-gradient(160deg, #26223c 0%, #3d375a 60%, #554d74 100%);
|
|
182
|
+
--aparte-weather-sky-wind: linear-gradient(160deg, #46719a 0%, #6b93b9 60%, #93b4d2 100%);
|
|
183
|
+
|
|
184
|
+
/* And by night. */
|
|
185
|
+
--aparte-weather-night-clear: linear-gradient(160deg, #081127 0%, #16224a 55%, #2b3a70 100%);
|
|
186
|
+
--aparte-weather-night-partly-cloudy: linear-gradient(160deg, #0f1834 0%, #1f2b52 60%, #38466f 100%);
|
|
187
|
+
--aparte-weather-night-cloudy: linear-gradient(160deg, #191f2b 0%, #2a3241 60%, #3c4556 100%);
|
|
188
|
+
--aparte-weather-night-fog: linear-gradient(160deg, #1f242d 0%, #333a45 60%, #484f5b 100%);
|
|
189
|
+
--aparte-weather-night-drizzle: linear-gradient(160deg, #18212f 0%, #2a3647 60%, #3c4a5e 100%);
|
|
190
|
+
--aparte-weather-night-rain: linear-gradient(160deg, #131b28 0%, #24303f 60%, #344255 100%);
|
|
191
|
+
--aparte-weather-night-heavy-rain: linear-gradient(160deg, #0e141f 0%, #1c2533 60%, #2b3647 100%);
|
|
192
|
+
--aparte-weather-night-sleet: linear-gradient(160deg, #1a2433 0%, #2d3a4d 60%, #425267 100%);
|
|
193
|
+
--aparte-weather-night-snow: linear-gradient(160deg, #1f2c42 0%, #33476a 60%, #4d6386 100%);
|
|
194
|
+
--aparte-weather-night-thunder: linear-gradient(160deg, #110e23 0%, #221d3d 60%, #352e55 100%);
|
|
195
|
+
--aparte-weather-night-wind: linear-gradient(160deg, #142236 0%, #243a58 60%, #395271 100%);
|
|
196
|
+
|
|
197
|
+
/* Text on a sky. */
|
|
198
|
+
--aparte-weather-on-sky: #ffffff;
|
|
199
|
+
--aparte-weather-on-sky-muted: rgb(255 255 255 / 0.8);
|
|
200
|
+
--aparte-weather-tile: rgb(255 255 255 / 0.14);
|
|
201
|
+
--aparte-weather-tile-border: rgb(255 255 255 / 0.18);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/* The glyphs drawn over a sky: white clouds, pale rain. */
|
|
205
|
+
.aparte-weather-card[data-variant="hero"][data-state="ready"],
|
|
206
|
+
.aparte-weather__forecast-head {
|
|
207
|
+
--aparte-weather-cloud: #ffffff;
|
|
208
|
+
--aparte-weather-moon: #f1e9c8;
|
|
209
|
+
--aparte-weather-cloud-back: rgb(255 255 255 / 0.62);
|
|
210
|
+
--aparte-weather-cloud-dark: #d3dae4;
|
|
211
|
+
--aparte-weather-rain: #bfdbfe;
|
|
212
|
+
--aparte-weather-snow: #ffffff;
|
|
213
|
+
--aparte-weather-fog: rgb(255 255 255 / 0.85);
|
|
214
|
+
--aparte-weather-wind: rgb(255 255 255 / 0.92);
|
|
215
|
+
--aparte-rich-card-spark: rgb(255 255 255 / 0.95);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/* ── The sky ─────────────────────────────────────────────────────────── */
|
|
219
|
+
|
|
220
|
+
.aparte-weather__sky {
|
|
221
|
+
position: absolute;
|
|
222
|
+
inset: 0;
|
|
223
|
+
z-index: -1;
|
|
224
|
+
background: var(--aparte-weather-sky-partly-cloudy);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.aparte-weather__sky::after {
|
|
228
|
+
content: "";
|
|
229
|
+
position: absolute;
|
|
230
|
+
inset: 0;
|
|
231
|
+
background: radial-gradient(120% 80% at 100% 0%, rgb(255 255 255 / 0.22), transparent 60%);
|
|
232
|
+
pointer-events: none;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.aparte-weather__sky[data-condition="clear"]::after {
|
|
236
|
+
background: radial-gradient(90% 70% at 92% 4%, rgb(255 223 130 / 0.45), transparent 62%);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.aparte-weather__sky[data-night]::after {
|
|
240
|
+
background:
|
|
241
|
+
radial-gradient(1.5px 1.5px at 18% 22%, rgb(255 255 255 / 0.8), transparent 100%),
|
|
242
|
+
radial-gradient(1px 1px at 34% 12%, rgb(255 255 255 / 0.7), transparent 100%),
|
|
243
|
+
radial-gradient(1.2px 1.2px at 62% 30%, rgb(255 255 255 / 0.6), transparent 100%),
|
|
244
|
+
radial-gradient(1px 1px at 78% 16%, rgb(255 255 255 / 0.7), transparent 100%),
|
|
245
|
+
radial-gradient(1.4px 1.4px at 48% 8%, rgb(255 255 255 / 0.5), transparent 100%);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.aparte-weather__sky[data-condition="clear"], .aparte-weather__accent[data-condition="clear"] { background: var(--aparte-weather-sky-clear); }
|
|
249
|
+
.aparte-weather__sky[data-condition="partly-cloudy"], .aparte-weather__accent[data-condition="partly-cloudy"] { background: var(--aparte-weather-sky-partly-cloudy); }
|
|
250
|
+
.aparte-weather__sky[data-condition="cloudy"], .aparte-weather__accent[data-condition="cloudy"] { background: var(--aparte-weather-sky-cloudy); }
|
|
251
|
+
.aparte-weather__sky[data-condition="fog"], .aparte-weather__accent[data-condition="fog"] { background: var(--aparte-weather-sky-fog); }
|
|
252
|
+
.aparte-weather__sky[data-condition="drizzle"], .aparte-weather__accent[data-condition="drizzle"] { background: var(--aparte-weather-sky-drizzle); }
|
|
253
|
+
.aparte-weather__sky[data-condition="rain"], .aparte-weather__accent[data-condition="rain"] { background: var(--aparte-weather-sky-rain); }
|
|
254
|
+
.aparte-weather__sky[data-condition="heavy-rain"], .aparte-weather__accent[data-condition="heavy-rain"] { background: var(--aparte-weather-sky-heavy-rain); }
|
|
255
|
+
.aparte-weather__sky[data-condition="sleet"], .aparte-weather__accent[data-condition="sleet"] { background: var(--aparte-weather-sky-sleet); }
|
|
256
|
+
.aparte-weather__sky[data-condition="snow"], .aparte-weather__accent[data-condition="snow"] { background: var(--aparte-weather-sky-snow); }
|
|
257
|
+
.aparte-weather__sky[data-condition="thunder"], .aparte-weather__accent[data-condition="thunder"] { background: var(--aparte-weather-sky-thunder); }
|
|
258
|
+
.aparte-weather__sky[data-condition="wind"], .aparte-weather__accent[data-condition="wind"] { background: var(--aparte-weather-sky-wind); }
|
|
259
|
+
|
|
260
|
+
.aparte-weather__sky[data-night][data-condition="clear"], .aparte-weather__accent[data-night][data-condition="clear"] { background: var(--aparte-weather-night-clear); }
|
|
261
|
+
.aparte-weather__sky[data-night][data-condition="partly-cloudy"], .aparte-weather__accent[data-night][data-condition="partly-cloudy"] { background: var(--aparte-weather-night-partly-cloudy); }
|
|
262
|
+
.aparte-weather__sky[data-night][data-condition="cloudy"], .aparte-weather__accent[data-night][data-condition="cloudy"] { background: var(--aparte-weather-night-cloudy); }
|
|
263
|
+
.aparte-weather__sky[data-night][data-condition="fog"], .aparte-weather__accent[data-night][data-condition="fog"] { background: var(--aparte-weather-night-fog); }
|
|
264
|
+
.aparte-weather__sky[data-night][data-condition="drizzle"], .aparte-weather__accent[data-night][data-condition="drizzle"] { background: var(--aparte-weather-night-drizzle); }
|
|
265
|
+
.aparte-weather__sky[data-night][data-condition="rain"], .aparte-weather__accent[data-night][data-condition="rain"] { background: var(--aparte-weather-night-rain); }
|
|
266
|
+
.aparte-weather__sky[data-night][data-condition="heavy-rain"], .aparte-weather__accent[data-night][data-condition="heavy-rain"] { background: var(--aparte-weather-night-heavy-rain); }
|
|
267
|
+
.aparte-weather__sky[data-night][data-condition="sleet"], .aparte-weather__accent[data-night][data-condition="sleet"] { background: var(--aparte-weather-night-sleet); }
|
|
268
|
+
.aparte-weather__sky[data-night][data-condition="snow"], .aparte-weather__accent[data-night][data-condition="snow"] { background: var(--aparte-weather-night-snow); }
|
|
269
|
+
.aparte-weather__sky[data-night][data-condition="thunder"], .aparte-weather__accent[data-night][data-condition="thunder"] { background: var(--aparte-weather-night-thunder); }
|
|
270
|
+
.aparte-weather__sky[data-night][data-condition="wind"], .aparte-weather__accent[data-night][data-condition="wind"] { background: var(--aparte-weather-night-wind); }
|
|
271
|
+
|
|
272
|
+
/* ── Hero ────────────────────────────────────────────────────────────── */
|
|
273
|
+
|
|
274
|
+
.aparte-weather-card[data-variant="hero"][data-state="ready"] {
|
|
275
|
+
color: var(--aparte-weather-on-sky);
|
|
276
|
+
border-color: rgb(0 0 0 / 0.06);
|
|
277
|
+
background: transparent;
|
|
278
|
+
box-shadow: 0 10px 30px -18px rgb(15 23 42 / 0.55);
|
|
279
|
+
text-shadow: 0 1px 2px rgb(0 0 0 / 0.16);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/* The card narrows on its own width, not the window's: a widget on a wide screen is as
|
|
283
|
+
narrow as a phone. On a drawn card (or its skeleton) only — a one-line state shrinks to
|
|
284
|
+
its words, and a size container cannot. */
|
|
285
|
+
.aparte-weather-card:is([data-state="ready"], [data-state="loading"]) {
|
|
286
|
+
container: aparte-weather / inline-size;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.aparte-weather__body {
|
|
290
|
+
display: grid;
|
|
291
|
+
gap: var(--aparte-space-6);
|
|
292
|
+
padding: var(--aparte-space-7) var(--aparte-space-8) var(--aparte-space-7);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.aparte-weather__head {
|
|
296
|
+
display: flex;
|
|
297
|
+
align-items: flex-start;
|
|
298
|
+
justify-content: space-between;
|
|
299
|
+
gap: var(--aparte-space-4);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.aparte-weather__place {
|
|
303
|
+
display: flex;
|
|
304
|
+
flex-direction: column;
|
|
305
|
+
gap: var(--aparte-space-1);
|
|
306
|
+
min-inline-size: 0;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.aparte-weather__location {
|
|
310
|
+
font-size: var(--aparte-font-size-lg);
|
|
311
|
+
font-weight: var(--aparte-font-weight-semibold);
|
|
312
|
+
letter-spacing: -0.01em;
|
|
313
|
+
overflow: hidden;
|
|
314
|
+
text-overflow: ellipsis;
|
|
315
|
+
white-space: nowrap;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.aparte-weather__when {
|
|
319
|
+
font-size: var(--aparte-font-size-sm);
|
|
320
|
+
color: var(--aparte-weather-on-sky-muted);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
.aparte-weather-card[data-variant="hero"] .aparte-weather__icon {
|
|
324
|
+
--aparte-rich-card-glyph-size: 4.5rem;
|
|
325
|
+
margin-block: calc(var(--aparte-space-2) * -1) calc(var(--aparte-space-6) * -1);
|
|
326
|
+
margin-inline-end: calc(var(--aparte-space-2) * -1);
|
|
327
|
+
filter: drop-shadow(0 6px 10px rgb(0 0 0 / 0.18));
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
.aparte-weather__now {
|
|
331
|
+
display: flex;
|
|
332
|
+
align-items: center;
|
|
333
|
+
gap: var(--aparte-space-7);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
.aparte-weather-card[data-variant="hero"] .aparte-weather__temp {
|
|
337
|
+
font-size: calc(3.75rem * var(--aparte-font-scale));
|
|
338
|
+
font-weight: 300;
|
|
339
|
+
line-height: 0.9;
|
|
340
|
+
letter-spacing: -0.045em;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
.aparte-weather__now-text {
|
|
344
|
+
display: flex;
|
|
345
|
+
flex-direction: column;
|
|
346
|
+
gap: var(--aparte-space-2);
|
|
347
|
+
min-inline-size: 0;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.aparte-weather__summary {
|
|
351
|
+
font-size: var(--aparte-font-size-base);
|
|
352
|
+
font-weight: var(--aparte-font-weight-medium);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
.aparte-weather__line {
|
|
356
|
+
display: flex;
|
|
357
|
+
flex-wrap: wrap;
|
|
358
|
+
column-gap: var(--aparte-space-5);
|
|
359
|
+
row-gap: var(--aparte-space-1);
|
|
360
|
+
font-size: var(--aparte-font-size-sm);
|
|
361
|
+
color: var(--aparte-weather-on-sky-muted);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.aparte-weather__range {
|
|
365
|
+
display: inline-flex;
|
|
366
|
+
gap: var(--aparte-space-4);
|
|
367
|
+
white-space: nowrap;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
.aparte-weather__stats {
|
|
371
|
+
display: grid;
|
|
372
|
+
grid-template-columns: repeat(auto-fit, minmax(5.5rem, 1fr));
|
|
373
|
+
gap: var(--aparte-space-3);
|
|
374
|
+
margin: 0;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.aparte-weather__stat {
|
|
378
|
+
display: flex;
|
|
379
|
+
flex-direction: column;
|
|
380
|
+
gap: var(--aparte-space-1);
|
|
381
|
+
padding: var(--aparte-space-3) var(--aparte-space-4);
|
|
382
|
+
border: var(--aparte-border-width) solid var(--aparte-weather-tile-border);
|
|
383
|
+
border-radius: var(--aparte-radius-lg);
|
|
384
|
+
background: var(--aparte-weather-tile);
|
|
385
|
+
backdrop-filter: blur(6px);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.aparte-weather__stat-label {
|
|
389
|
+
font-size: var(--aparte-font-size-2xs);
|
|
390
|
+
font-weight: var(--aparte-font-weight-semibold);
|
|
391
|
+
letter-spacing: 0.06em;
|
|
392
|
+
text-transform: uppercase;
|
|
393
|
+
color: var(--aparte-weather-on-sky-muted);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
.aparte-weather__stat-value {
|
|
397
|
+
display: flex;
|
|
398
|
+
align-items: center;
|
|
399
|
+
gap: var(--aparte-space-2);
|
|
400
|
+
margin: 0;
|
|
401
|
+
font-size: var(--aparte-font-size-md);
|
|
402
|
+
font-weight: var(--aparte-font-weight-semibold);
|
|
403
|
+
white-space: nowrap;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
.aparte-weather__wind-arrow {
|
|
407
|
+
display: inline-block;
|
|
408
|
+
font-size: var(--aparte-font-size-sm);
|
|
409
|
+
transform: rotate(var(--aparte-weather-wind-angle, 0deg));
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/* Buttons on the sky: glass, not the surface's. */
|
|
413
|
+
.aparte-weather-card[data-variant="hero"][data-state="ready"] .aparte-rich-card__actions {
|
|
414
|
+
padding-inline: var(--aparte-space-8);
|
|
415
|
+
border-block-start-color: var(--aparte-weather-tile-border);
|
|
416
|
+
background: rgb(0 0 0 / 0.1);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
.aparte-weather-card[data-variant="hero"][data-state="ready"] .aparte-rich-card__action {
|
|
420
|
+
border-color: var(--aparte-weather-tile-border);
|
|
421
|
+
background: var(--aparte-weather-tile);
|
|
422
|
+
color: var(--aparte-weather-on-sky);
|
|
423
|
+
text-shadow: none;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
.aparte-weather-card[data-variant="hero"][data-state="ready"] .aparte-rich-card__action:hover {
|
|
427
|
+
background: rgb(255 255 255 / 0.24);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/* The next hours: a row of columns, the temperature's curve drawn above them. */
|
|
431
|
+
.aparte-weather__hourly {
|
|
432
|
+
--aparte-weather-hours: 8;
|
|
433
|
+
display: grid;
|
|
434
|
+
gap: var(--aparte-space-1);
|
|
435
|
+
padding-block-start: var(--aparte-space-5);
|
|
436
|
+
border-block-start: var(--aparte-border-width) solid var(--aparte-weather-tile-border);
|
|
437
|
+
overflow-x: auto;
|
|
438
|
+
scrollbar-width: none;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
.aparte-weather__curve {
|
|
442
|
+
block-size: 1.75rem;
|
|
443
|
+
/* The curve's points sit over the middle of each column. */
|
|
444
|
+
padding-inline: calc(50% / var(--aparte-weather-hours));
|
|
445
|
+
min-inline-size: calc(var(--aparte-weather-hours) * 2.75rem);
|
|
446
|
+
box-sizing: border-box;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
.aparte-weather__hours {
|
|
450
|
+
display: grid;
|
|
451
|
+
grid-auto-flow: column;
|
|
452
|
+
grid-auto-columns: minmax(2.75rem, 1fr);
|
|
453
|
+
margin: 0;
|
|
454
|
+
padding: 0;
|
|
455
|
+
list-style: none;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
.aparte-weather__hour {
|
|
459
|
+
display: flex;
|
|
460
|
+
flex-direction: column;
|
|
461
|
+
align-items: center;
|
|
462
|
+
gap: var(--aparte-space-2);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
.aparte-weather__hour-time {
|
|
466
|
+
font-size: var(--aparte-font-size-xs);
|
|
467
|
+
color: var(--aparte-weather-on-sky-muted);
|
|
468
|
+
white-space: nowrap;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
.aparte-weather__hour-temp {
|
|
472
|
+
font-size: var(--aparte-font-size-md);
|
|
473
|
+
font-weight: var(--aparte-font-weight-semibold);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
.aparte-weather__hour-rain {
|
|
477
|
+
margin-block: calc(var(--aparte-space-2) * -1);
|
|
478
|
+
font-size: var(--aparte-font-size-2xs);
|
|
479
|
+
font-weight: var(--aparte-font-weight-semibold);
|
|
480
|
+
color: #cfe5ff;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
.aparte-weather__mini {
|
|
484
|
+
--aparte-rich-card-glyph-size: 1.6rem;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/* A small drawing stands still: only the big glyph moves. */
|
|
488
|
+
.aparte-weather__mini svg * {
|
|
489
|
+
animation: none !important;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/* ── Compact ─────────────────────────────────────────────────────────── */
|
|
493
|
+
|
|
494
|
+
.aparte-weather-card[data-variant="compact"] {
|
|
495
|
+
max-inline-size: 22rem;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
.aparte-weather__accent {
|
|
499
|
+
position: absolute;
|
|
500
|
+
inset-block: 0;
|
|
501
|
+
inset-inline-start: 0;
|
|
502
|
+
inline-size: 4px;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
.aparte-weather__compact {
|
|
506
|
+
display: flex;
|
|
507
|
+
align-items: center;
|
|
508
|
+
gap: var(--aparte-space-5);
|
|
509
|
+
padding: var(--aparte-space-4) var(--aparte-space-6) var(--aparte-space-4) calc(var(--aparte-space-6) + 4px);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
.aparte-weather__compact .aparte-weather__icon {
|
|
513
|
+
--aparte-rich-card-glyph-size: 2.4rem;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
.aparte-weather__compact .aparte-weather__temp {
|
|
517
|
+
font-size: var(--aparte-font-size-2xl);
|
|
518
|
+
font-weight: var(--aparte-font-weight-semibold);
|
|
519
|
+
letter-spacing: -0.03em;
|
|
520
|
+
line-height: 1;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
.aparte-weather__compact-text {
|
|
524
|
+
display: flex;
|
|
525
|
+
flex-direction: column;
|
|
526
|
+
min-inline-size: 0;
|
|
527
|
+
flex: 1;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
.aparte-weather__compact .aparte-weather__location {
|
|
531
|
+
font-size: var(--aparte-font-size-md);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
.aparte-weather__compact .aparte-weather__summary {
|
|
535
|
+
font-size: var(--aparte-font-size-sm);
|
|
536
|
+
font-weight: var(--aparte-font-weight-normal);
|
|
537
|
+
color: var(--aparte-text-muted);
|
|
538
|
+
overflow: hidden;
|
|
539
|
+
text-overflow: ellipsis;
|
|
540
|
+
white-space: nowrap;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
.aparte-weather__compact .aparte-weather__range {
|
|
544
|
+
flex-direction: column;
|
|
545
|
+
gap: 0;
|
|
546
|
+
font-size: var(--aparte-font-size-sm);
|
|
547
|
+
color: var(--aparte-text-muted);
|
|
548
|
+
text-align: end;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
.aparte-weather__compact .aparte-weather__hi {
|
|
552
|
+
color: var(--aparte-text);
|
|
553
|
+
font-weight: var(--aparte-font-weight-semibold);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/* ── Forecast ────────────────────────────────────────────────────────── */
|
|
557
|
+
|
|
558
|
+
.aparte-weather__forecast-head {
|
|
559
|
+
position: relative;
|
|
560
|
+
isolation: isolate;
|
|
561
|
+
color: var(--aparte-weather-on-sky);
|
|
562
|
+
text-shadow: 0 1px 2px rgb(0 0 0 / 0.16);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
.aparte-weather__forecast-head .aparte-weather__compact {
|
|
566
|
+
padding: var(--aparte-space-6) var(--aparte-space-7);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
.aparte-weather__forecast-head .aparte-weather__icon {
|
|
570
|
+
--aparte-rich-card-glyph-size: 3.25rem;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
.aparte-weather__forecast-head .aparte-weather__temp {
|
|
574
|
+
font-size: calc(2.25rem * var(--aparte-font-scale));
|
|
575
|
+
font-weight: 300;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
.aparte-weather__forecast-head .aparte-weather__summary,
|
|
579
|
+
.aparte-weather__forecast-head .aparte-weather__range {
|
|
580
|
+
color: var(--aparte-weather-on-sky-muted);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
.aparte-weather__forecast-head .aparte-weather__hi {
|
|
584
|
+
color: var(--aparte-weather-on-sky);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
.aparte-weather__days {
|
|
588
|
+
margin: 0;
|
|
589
|
+
padding: var(--aparte-space-2) var(--aparte-space-7) var(--aparte-space-4);
|
|
590
|
+
list-style: none;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
.aparte-weather__day {
|
|
594
|
+
display: grid;
|
|
595
|
+
grid-template-columns: minmax(3.25rem, auto) 1.75rem 2.25rem 2.25rem minmax(3rem, 1fr) 2.25rem;
|
|
596
|
+
align-items: center;
|
|
597
|
+
gap: var(--aparte-space-3);
|
|
598
|
+
padding-block: var(--aparte-space-3);
|
|
599
|
+
font-size: var(--aparte-font-size-md);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
.aparte-weather__day + .aparte-weather__day {
|
|
603
|
+
border-block-start: var(--aparte-border-width) solid var(--aparte-border);
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
.aparte-weather__day-name {
|
|
607
|
+
font-weight: var(--aparte-font-weight-medium);
|
|
608
|
+
white-space: nowrap;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
.aparte-weather__day-rain {
|
|
612
|
+
font-size: var(--aparte-font-size-xs);
|
|
613
|
+
font-weight: var(--aparte-font-weight-semibold);
|
|
614
|
+
color: var(--aparte-weather-rain);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
.aparte-weather__day-low {
|
|
618
|
+
color: var(--aparte-text-muted);
|
|
619
|
+
text-align: end;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
.aparte-weather__day-high {
|
|
623
|
+
font-weight: var(--aparte-font-weight-semibold);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
.aparte-weather__bar {
|
|
627
|
+
position: relative;
|
|
628
|
+
block-size: 6px;
|
|
629
|
+
border-radius: var(--aparte-radius-full);
|
|
630
|
+
background: color-mix(in oklab, var(--aparte-text) 10%, transparent);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
.aparte-weather__bar-fill {
|
|
634
|
+
position: absolute;
|
|
635
|
+
inset-block: 0;
|
|
636
|
+
inset-inline-start: var(--aparte-weather-bar-start, 0%);
|
|
637
|
+
inset-inline-end: calc(100% - var(--aparte-weather-bar-end, 100%));
|
|
638
|
+
border-radius: inherit;
|
|
639
|
+
background: linear-gradient(to right, var(--aparte-weather-bar-cold), var(--aparte-weather-bar-warm));
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
.aparte-weather__bar-fill:dir(rtl) {
|
|
643
|
+
background: linear-gradient(to left, var(--aparte-weather-bar-cold), var(--aparte-weather-bar-warm));
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
.aparte-weather__bar-now {
|
|
647
|
+
position: absolute;
|
|
648
|
+
inset-block-start: 50%;
|
|
649
|
+
inset-inline-start: calc(var(--aparte-weather-bar-at, 0%) - 5px);
|
|
650
|
+
inline-size: 10px;
|
|
651
|
+
block-size: 10px;
|
|
652
|
+
border: 2px solid var(--aparte-surface-1);
|
|
653
|
+
border-radius: var(--aparte-radius-full);
|
|
654
|
+
background: var(--aparte-text);
|
|
655
|
+
transform: translateY(-50%);
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/* ── Loading ─────────────────────────────────────────────────────────── */
|
|
659
|
+
|
|
660
|
+
.aparte-weather-card[data-state="loading"] .aparte-weather__sk-place { inline-size: 7rem; }
|
|
661
|
+
.aparte-weather-card[data-state="loading"] .aparte-weather__sk-icon { inline-size: 3.5rem; block-size: 3.5rem; flex: none; }
|
|
662
|
+
.aparte-weather-card[data-state="loading"] .aparte-weather__sk-temp { inline-size: 5.5rem; block-size: 3.25rem; border-radius: var(--aparte-radius-lg); }
|
|
663
|
+
.aparte-weather-card[data-state="loading"] .aparte-weather__sk-summary { inline-size: 8rem; }
|
|
664
|
+
.aparte-weather-card[data-state="loading"] .aparte-weather__sk-stats {
|
|
665
|
+
display: grid;
|
|
666
|
+
grid-template-columns: repeat(3, 1fr);
|
|
667
|
+
gap: var(--aparte-space-3);
|
|
668
|
+
}
|
|
669
|
+
.aparte-weather-card[data-state="loading"] .aparte-weather__sk-stat { block-size: 3rem; border-radius: var(--aparte-radius-lg); }
|
|
670
|
+
.aparte-weather-card[data-state="loading"] .aparte-weather__compact .aparte-weather__sk-icon { inline-size: 2.6rem; block-size: 2.6rem; }
|
|
671
|
+
.aparte-weather-card[data-state="loading"] .aparte-weather__compact .aparte-weather__sk-temp { inline-size: 3rem; block-size: 1.75rem; }
|
|
672
|
+
|
|
673
|
+
/* ── The glyphs ──────────────────────────────────────────────────────── */
|
|
674
|
+
|
|
675
|
+
.aparte-wx .aparte-wx-sun { fill: var(--aparte-weather-sun); }
|
|
676
|
+
.aparte-wx .aparte-wx-rays {
|
|
677
|
+
fill: none;
|
|
678
|
+
stroke: var(--aparte-weather-sun-rays);
|
|
679
|
+
stroke-width: 3.2;
|
|
680
|
+
stroke-linecap: round;
|
|
681
|
+
transform-box: view-box;
|
|
682
|
+
transform-origin: 32px 32px;
|
|
683
|
+
/* Core's turn: its sheet is on every page a chat is on. */
|
|
684
|
+
animation: aparte-spin 60s linear infinite;
|
|
685
|
+
}
|
|
686
|
+
.aparte-wx .aparte-wx-moon { fill: var(--aparte-weather-moon); }
|
|
687
|
+
.aparte-wx .aparte-wx-star { fill: var(--aparte-weather-star); animation: aparte-weather-twinkle 3.2s ease-in-out infinite; }
|
|
688
|
+
.aparte-wx .aparte-wx-star + .aparte-wx-star { animation-delay: -1.6s; }
|
|
689
|
+
.aparte-wx .aparte-wx-cloud { fill: var(--aparte-weather-cloud); }
|
|
690
|
+
.aparte-wx .aparte-wx-cloud-back { fill: var(--aparte-weather-cloud-back); }
|
|
691
|
+
.aparte-wx .aparte-wx-cloud--dark { fill: var(--aparte-weather-cloud-dark); }
|
|
692
|
+
.aparte-wx .aparte-wx-drift { animation: aparte-weather-drift 7s ease-in-out infinite alternate; }
|
|
693
|
+
.aparte-wx .aparte-wx-drop {
|
|
694
|
+
fill: none;
|
|
695
|
+
stroke: var(--aparte-weather-rain);
|
|
696
|
+
stroke-width: 3;
|
|
697
|
+
stroke-linecap: round;
|
|
698
|
+
animation: aparte-weather-fall 1.3s ease-in infinite;
|
|
699
|
+
animation-delay: calc(var(--i, 0) * -0.45s);
|
|
700
|
+
}
|
|
701
|
+
.aparte-wx .aparte-wx-drip {
|
|
702
|
+
fill: var(--aparte-weather-rain);
|
|
703
|
+
animation: aparte-weather-fall 1.6s ease-in infinite;
|
|
704
|
+
animation-delay: calc(var(--i, 0) * -0.4s);
|
|
705
|
+
}
|
|
706
|
+
.aparte-wx .aparte-wx-flake path {
|
|
707
|
+
fill: none;
|
|
708
|
+
stroke: var(--aparte-weather-snow);
|
|
709
|
+
stroke-width: 1.8;
|
|
710
|
+
stroke-linecap: round;
|
|
711
|
+
animation: aparte-weather-snowfall 3.4s linear infinite;
|
|
712
|
+
}
|
|
713
|
+
.aparte-wx .aparte-wx-flake:nth-child(2) path { animation-delay: -1.1s; }
|
|
714
|
+
.aparte-wx .aparte-wx-flake:nth-child(3) path { animation-delay: -2.2s; }
|
|
715
|
+
.aparte-wx .aparte-wx-bolt { fill: var(--aparte-weather-bolt); animation: aparte-weather-flash 4.5s linear infinite; }
|
|
716
|
+
.aparte-wx .aparte-wx-fog, .aparte-wx .aparte-wx-wind {
|
|
717
|
+
fill: none;
|
|
718
|
+
stroke-width: 3.2;
|
|
719
|
+
stroke-linecap: round;
|
|
720
|
+
}
|
|
721
|
+
.aparte-wx .aparte-wx-fog { stroke: var(--aparte-weather-fog); }
|
|
722
|
+
.aparte-wx .aparte-wx-fog-g { animation: aparte-weather-drift 6s ease-in-out infinite alternate; }
|
|
723
|
+
.aparte-wx .aparte-wx-wind { stroke: var(--aparte-weather-wind); stroke-width: 3.6; animation: aparte-weather-gust 3.2s ease-in-out infinite alternate; }
|
|
724
|
+
.aparte-wx .aparte-wx-wind:nth-child(2) { animation-delay: -1.1s; }
|
|
725
|
+
.aparte-wx .aparte-wx-wind:nth-child(3) { animation-delay: -2.2s; }
|
|
726
|
+
|
|
727
|
+
@keyframes aparte-weather-twinkle { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
|
|
728
|
+
@keyframes aparte-weather-drift { from { transform: translateX(-1.5px); } to { transform: translateX(1.5px); } }
|
|
729
|
+
@keyframes aparte-weather-fall {
|
|
730
|
+
0% { transform: translateY(-3px); opacity: 0; }
|
|
731
|
+
25% { opacity: 1; }
|
|
732
|
+
100% { transform: translateY(6px); opacity: 0; }
|
|
733
|
+
}
|
|
734
|
+
@keyframes aparte-weather-snowfall {
|
|
735
|
+
0% { transform: translate(0, -3px); opacity: 0; }
|
|
736
|
+
20% { opacity: 1; }
|
|
737
|
+
100% { transform: translate(2px, 6px); opacity: 0; }
|
|
738
|
+
}
|
|
739
|
+
@keyframes aparte-weather-flash {
|
|
740
|
+
0%, 86%, 100% { opacity: 1; }
|
|
741
|
+
88% { opacity: 0.25; }
|
|
742
|
+
90% { opacity: 1; }
|
|
743
|
+
92% { opacity: 0.4; }
|
|
744
|
+
}
|
|
745
|
+
@keyframes aparte-weather-gust {
|
|
746
|
+
from { transform: translateX(-2px); }
|
|
747
|
+
to { transform: translateX(2.5px); }
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
@container aparte-weather (max-width: 22rem) {
|
|
751
|
+
.aparte-weather__body { padding: var(--aparte-space-6); }
|
|
752
|
+
.aparte-weather-card[data-variant="hero"] .aparte-weather__temp { font-size: calc(3rem * var(--aparte-font-scale)); }
|
|
753
|
+
.aparte-weather__days { padding-inline: var(--aparte-space-5); }
|
|
754
|
+
.aparte-weather__day { grid-template-columns: minmax(2.75rem, auto) 1.5rem 2rem 2rem minmax(2rem, 1fr) 2rem; }
|
|
755
|
+
}
|
|
756
|
+
`;
|
|
757
|
+
const W = {
|
|
758
|
+
cardsWeatherTitle: { en: "Weather", fr: "Météo", de: "Wetter", es: "Tiempo", it: "Meteo", ja: "天気", ko: "날씨", pt: "Clima", ru: "Погода", zh: "天气" },
|
|
759
|
+
cardsWeatherIn: { en: "Weather in {place}", fr: "Météo à {place}", de: "Wetter in {place}", es: "Tiempo en {place}", it: "Meteo a {place}", ja: "{place}の天気", ko: "{place} 날씨", pt: "Clima em {place}", ru: "Погода: {place}", zh: "{place}天气" },
|
|
760
|
+
cardsWeatherFeelsLike: { en: "Feels like {t}", fr: "Ressenti {t}", de: "Gefühlt {t}", es: "Sensación {t}", it: "Percepita {t}", ja: "体感 {t}", ko: "체감 {t}", pt: "Sensação {t}", ru: "Ощущается как {t}", zh: "体感 {t}" },
|
|
761
|
+
cardsWeatherHigh: { en: "High", fr: "Max.", de: "Höchst", es: "Máx.", it: "Max", ja: "最高", ko: "최고", pt: "Máx.", ru: "Макс.", zh: "最高" },
|
|
762
|
+
cardsWeatherLow: { en: "Low", fr: "Min.", de: "Tiefst", es: "Mín.", it: "Min", ja: "最低", ko: "최저", pt: "Mín.", ru: "Мин.", zh: "最低" },
|
|
763
|
+
cardsWeatherWind: { en: "Wind", fr: "Vent", de: "Wind", es: "Viento", it: "Vento", ja: "風", ko: "바람", pt: "Vento", ru: "Ветер", zh: "风" },
|
|
764
|
+
cardsWeatherHumidity: { en: "Humidity", fr: "Humidité", de: "Feuchte", es: "Humedad", it: "Umidità", ja: "湿度", ko: "습도", pt: "Umidade", ru: "Влажность", zh: "湿度" },
|
|
765
|
+
cardsWeatherRain: { en: "Rain", fr: "Pluie", de: "Regen", es: "Lluvia", it: "Pioggia", ja: "降水", ko: "강수", pt: "Chuva", ru: "Осадки", zh: "降水" },
|
|
766
|
+
cardsWeatherNow: { en: "Now", fr: "Maint.", de: "Jetzt", es: "Ahora", it: "Ora", ja: "今", ko: "지금", pt: "Agora", ru: "Сейчас", zh: "现在" },
|
|
767
|
+
cardsWeatherForecast: { en: "Forecast", fr: "Prévisions", de: "Vorhersage", es: "Pronóstico", it: "Previsioni", ja: "予報", ko: "예보", pt: "Previsão", ru: "Прогноз", zh: "预报" }
|
|
768
|
+
};
|
|
769
|
+
const WIND_INTL = { "km/h": "kilometer-per-hour", mph: "mile-per-hour", "m/s": "meter-per-second", kn: null };
|
|
770
|
+
const HOURS_SHOWN = 8;
|
|
771
|
+
const DAYS_SHOWN = 7;
|
|
772
|
+
function readCondition(value) {
|
|
773
|
+
if (typeof value === "number") return conditionFromWmo(value);
|
|
774
|
+
return conditionFromText(value);
|
|
775
|
+
}
|
|
776
|
+
function readUnit(value) {
|
|
777
|
+
return typeof value === "string" && /^\s*°?\s*f\b|fahrenheit|imperial/i.test(value) ? "F" : "C";
|
|
778
|
+
}
|
|
779
|
+
function readWindUnit(value) {
|
|
780
|
+
if (typeof value !== "string") return "km/h";
|
|
781
|
+
const v = value.toLowerCase().replace(/\s/g, "");
|
|
782
|
+
if (v.includes("mph") || v.includes("mp/h")) return "mph";
|
|
783
|
+
if (v === "m/s" || v === "ms") return "m/s";
|
|
784
|
+
if (v.startsWith("kn") || v === "kt") return "kn";
|
|
785
|
+
return "km/h";
|
|
786
|
+
}
|
|
787
|
+
function percent(value, share = false) {
|
|
788
|
+
const n = num(value);
|
|
789
|
+
if (n === void 0) return void 0;
|
|
790
|
+
const p = n > 0 && n <= 1 && (share || !Number.isInteger(n)) ? n * 100 : n;
|
|
791
|
+
return Math.max(0, Math.min(100, Math.round(p)));
|
|
792
|
+
}
|
|
793
|
+
function writesShares(items) {
|
|
794
|
+
return items.some((item) => {
|
|
795
|
+
const n = num(item?.["precipitation"]);
|
|
796
|
+
return n !== void 0 && n > 0 && n < 1;
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
function chanceOf(item, shares) {
|
|
800
|
+
return percent(item?.["precipitation"], shares) ?? percent(item?.["pop"], true);
|
|
801
|
+
}
|
|
802
|
+
function readWeather(raw) {
|
|
803
|
+
if (!raw || typeof raw !== "object") return null;
|
|
804
|
+
const r2 = raw;
|
|
805
|
+
const temperature = num(r2["temperature"] ?? r2["temp"]);
|
|
806
|
+
const rawDaily = Array.isArray(r2["daily"]) ? r2["daily"] : [];
|
|
807
|
+
const dailyShares = writesShares(rawDaily);
|
|
808
|
+
const daily = rawDaily.map((d) => {
|
|
809
|
+
const date = toDate(d?.date ?? d?.time);
|
|
810
|
+
const high = num(d?.high ?? d?.max);
|
|
811
|
+
const low = num(d?.low ?? d?.min);
|
|
812
|
+
if (!date || high === void 0 || low === void 0) return null;
|
|
813
|
+
return { date, condition: readCondition(d?.condition) ?? "cloudy", high, low, precipitation: chanceOf(d, dailyShares) };
|
|
814
|
+
}).filter((d) => d !== null).slice(0, DAYS_SHOWN);
|
|
815
|
+
if (temperature === void 0 && daily.length === 0) return null;
|
|
816
|
+
const night = r2["night"] === true || r2["isDay"] === false || r2["is_day"] === 0;
|
|
817
|
+
const rawHourly = Array.isArray(r2["hourly"]) ? r2["hourly"] : [];
|
|
818
|
+
const hourlyShares = writesShares(rawHourly);
|
|
819
|
+
const hourly = rawHourly.map((h) => {
|
|
820
|
+
const time = toDate(h?.time);
|
|
821
|
+
const t = num(h?.temperature ?? h?.temp);
|
|
822
|
+
if (!time || t === void 0) return null;
|
|
823
|
+
return { time, temperature: t, condition: readCondition(h?.condition), precipitation: chanceOf(h, hourlyShares), night: h?.night === true };
|
|
824
|
+
}).filter((h) => h !== null).slice(0, HOURS_SHOWN);
|
|
825
|
+
let wind;
|
|
826
|
+
const w = r2["wind"];
|
|
827
|
+
if (typeof w === "number" || typeof w === "string") {
|
|
828
|
+
const speed = num(w);
|
|
829
|
+
if (speed !== void 0) wind = { speed, unit: readWindUnit(r2["windUnit"]), direction: num(r2["windDirection"]) };
|
|
830
|
+
} else if (w && typeof w === "object") {
|
|
831
|
+
const o = w;
|
|
832
|
+
const speed = num(o["speed"]);
|
|
833
|
+
if (speed !== void 0) wind = { speed, unit: readWindUnit(o["unit"]), direction: num(o["direction"]) };
|
|
834
|
+
} else if (num(r2["windSpeed"]) !== void 0) {
|
|
835
|
+
wind = { speed: num(r2["windSpeed"]), unit: readWindUnit(r2["windUnit"]), direction: num(r2["windDirection"]) };
|
|
836
|
+
}
|
|
837
|
+
const condition = readCondition(r2["condition"]) ?? readCondition(r2["summary"]) ?? daily[0]?.condition ?? "cloudy";
|
|
838
|
+
return {
|
|
839
|
+
location: str(r2["location"] ?? r2["city"] ?? r2["place"]),
|
|
840
|
+
condition,
|
|
841
|
+
summary: str(r2["summary"] ?? r2["description"]),
|
|
842
|
+
temperature,
|
|
843
|
+
unit: readUnit(r2["unit"]),
|
|
844
|
+
feelsLike: num(r2["feelsLike"] ?? r2["feels_like"]),
|
|
845
|
+
high: num(r2["high"]) ?? daily[0]?.high,
|
|
846
|
+
low: num(r2["low"]) ?? daily[0]?.low,
|
|
847
|
+
humidity: percent(r2["humidity"]),
|
|
848
|
+
wind,
|
|
849
|
+
precipitation: chanceOf(r2, false),
|
|
850
|
+
night,
|
|
851
|
+
time: toDate(r2["time"]) ?? void 0,
|
|
852
|
+
hourly,
|
|
853
|
+
daily
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
function fromOpenMeteo(response, options = {}) {
|
|
857
|
+
const r2 = response && typeof response === "object" ? response : {};
|
|
858
|
+
const current = r2["current"] ?? r2["current_weather"] ?? {};
|
|
859
|
+
const cu = r2["current_units"] ?? {};
|
|
860
|
+
const cwu = r2["current_weather_units"] ?? {};
|
|
861
|
+
const hu = r2["hourly_units"] ?? {};
|
|
862
|
+
const du = r2["daily_units"] ?? {};
|
|
863
|
+
const unit = readUnit(cu["temperature_2m"] ?? cu["temperature"] ?? cwu["temperature"] ?? du["temperature_2m_max"] ?? du["temperature_2m_min"] ?? hu["temperature_2m"]);
|
|
864
|
+
const windUnit = readWindUnit(cu["wind_speed_10m"] ?? cu["windspeed"] ?? cwu["windspeed"] ?? cwu["wind_speed_10m"] ?? hu["wind_speed_10m"] ?? du["wind_speed_10m_max"]);
|
|
865
|
+
const offset = num(r2["utc_offset_seconds"]);
|
|
866
|
+
const instant = (time) => openMeteoTime(time, offset);
|
|
867
|
+
const nowMs = instant(current["time"])?.getTime() ?? Date.now();
|
|
868
|
+
const hourly = [];
|
|
869
|
+
const h = r2["hourly"];
|
|
870
|
+
if (h && Array.isArray(h["time"])) {
|
|
871
|
+
h["time"].forEach((time, i) => {
|
|
872
|
+
const at = instant(time);
|
|
873
|
+
const t = num(h["temperature_2m"]?.[i]);
|
|
874
|
+
if (!at || t === void 0 || at.getTime() < nowMs - 36e5) return;
|
|
875
|
+
hourly.push({
|
|
876
|
+
time: at,
|
|
877
|
+
temperature: t,
|
|
878
|
+
condition: conditionFromWmo(h["weather_code"]?.[i]),
|
|
879
|
+
precipitation: num(h["precipitation_probability"]?.[i]),
|
|
880
|
+
night: h["is_day"]?.[i] === 0
|
|
881
|
+
});
|
|
882
|
+
});
|
|
883
|
+
}
|
|
884
|
+
const daily = [];
|
|
885
|
+
const d = r2["daily"];
|
|
886
|
+
if (d && Array.isArray(d["time"])) {
|
|
887
|
+
d["time"].forEach((date, i) => {
|
|
888
|
+
const high = num(d["temperature_2m_max"]?.[i]);
|
|
889
|
+
const low = num(d["temperature_2m_min"]?.[i]);
|
|
890
|
+
if (high === void 0 || low === void 0) return;
|
|
891
|
+
daily.push({
|
|
892
|
+
date,
|
|
893
|
+
condition: conditionFromWmo(d["weather_code"]?.[i]),
|
|
894
|
+
high,
|
|
895
|
+
low,
|
|
896
|
+
precipitation: num(d["precipitation_probability_max"]?.[i])
|
|
897
|
+
});
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
return {
|
|
901
|
+
location: options.location,
|
|
902
|
+
condition: conditionFromWmo(current["weather_code"] ?? current["weathercode"]),
|
|
903
|
+
temperature: num(current["temperature_2m"] ?? current["temperature"]),
|
|
904
|
+
unit,
|
|
905
|
+
feelsLike: num(current["apparent_temperature"]),
|
|
906
|
+
humidity: num(current["relative_humidity_2m"]),
|
|
907
|
+
wind: num(current["wind_speed_10m"] ?? current["windspeed"]) !== void 0 ? { speed: num(current["wind_speed_10m"] ?? current["windspeed"]), unit: windUnit, direction: num(current["wind_direction_10m"] ?? current["winddirection"]) } : void 0,
|
|
908
|
+
precipitation: num(hourly[0]?.precipitation),
|
|
909
|
+
night: current["is_day"] === 0,
|
|
910
|
+
time: instant(current["time"]) ?? void 0,
|
|
911
|
+
hourly: hourly.slice(0, HOURS_SHOWN),
|
|
912
|
+
daily: daily.slice(0, DAYS_SHOWN)
|
|
913
|
+
};
|
|
914
|
+
}
|
|
915
|
+
function openMeteoTime(value, offset) {
|
|
916
|
+
const m = typeof value === "string" ? /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?$/.exec(value.trim()) : null;
|
|
917
|
+
if (!m || offset === void 0) return toDate(value);
|
|
918
|
+
const utc = Date.UTC(Number(m[1]), Number(m[2]) - 1, Number(m[3]), Number(m[4]), Number(m[5]), Number(m[6] ?? 0));
|
|
919
|
+
return new Date(utc - offset * 1e3);
|
|
920
|
+
}
|
|
921
|
+
const deg = (config, t) => `${formatNumber(config, Math.round(t))}°`;
|
|
922
|
+
const degFull = (config, t, unit) => formatUnit(config, Math.round(t), unit === "F" ? "fahrenheit" : "celsius");
|
|
923
|
+
function summaryOf(data, config) {
|
|
924
|
+
return data.summary ?? word(config, `cardsWeather_${data.condition}`, CONDITION_WORDS[data.condition]);
|
|
925
|
+
}
|
|
926
|
+
function windText(config, wind) {
|
|
927
|
+
const intl = WIND_INTL[wind.unit];
|
|
928
|
+
return intl ? formatUnit(config, wind.speed, intl) : `${formatNumber(config, Math.round(wind.speed))} kn`;
|
|
929
|
+
}
|
|
930
|
+
function stat(ctx, key, value, extra) {
|
|
931
|
+
const dt = el("dt", { class: "aparte-weather__stat-label" });
|
|
932
|
+
ctx.word(dt, key, W[key]);
|
|
933
|
+
const dd = el("dd", { class: "aparte-weather__stat-value" });
|
|
934
|
+
const text = el("span");
|
|
935
|
+
ctx.bind(text, value);
|
|
936
|
+
dd.append(...extra ? [extra, text] : [text]);
|
|
937
|
+
return el("div", { class: "aparte-weather__stat", attrs: { "data-stat": key.replace("cardsWeather", "").toLowerCase() } }, dt, dd);
|
|
938
|
+
}
|
|
939
|
+
function rangeText(ctx, data) {
|
|
940
|
+
if (data.high === void 0 && data.low === void 0) return null;
|
|
941
|
+
const range = el("span", { class: "aparte-weather__range" });
|
|
942
|
+
if (data.high !== void 0) {
|
|
943
|
+
const hi = el("span", { class: "aparte-weather__hi" });
|
|
944
|
+
ctx.bind(hi, () => `↑ ${deg(ctx.config, data.high)}`);
|
|
945
|
+
ctx.bind(hi, () => `${word(ctx.config, "cardsWeatherHigh", W.cardsWeatherHigh)} ${degFull(ctx.config, data.high, data.unit)}`, "aria-label");
|
|
946
|
+
range.append(hi);
|
|
947
|
+
}
|
|
948
|
+
if (data.low !== void 0) {
|
|
949
|
+
const lo = el("span", { class: "aparte-weather__lo" });
|
|
950
|
+
ctx.bind(lo, () => `↓ ${deg(ctx.config, data.low)}`);
|
|
951
|
+
ctx.bind(lo, () => `${word(ctx.config, "cardsWeatherLow", W.cardsWeatherLow)} ${degFull(ctx.config, data.low, data.unit)}`, "aria-label");
|
|
952
|
+
range.append(lo);
|
|
953
|
+
}
|
|
954
|
+
return range;
|
|
955
|
+
}
|
|
956
|
+
function placeLine(ctx, data) {
|
|
957
|
+
const place = el("div", { class: "aparte-weather__place" });
|
|
958
|
+
const name = el("span", { class: "aparte-weather__location" });
|
|
959
|
+
ctx.bind(name, () => data.location ?? word(ctx.config, "cardsWeatherTitle", W.cardsWeatherTitle));
|
|
960
|
+
place.append(name);
|
|
961
|
+
if (data.time) {
|
|
962
|
+
const when = el("time", { class: "aparte-weather__when", attrs: { datetime: data.time.toISOString() } });
|
|
963
|
+
ctx.bind(when, () => formatWhen(ctx.config, data.time));
|
|
964
|
+
place.append(when);
|
|
965
|
+
}
|
|
966
|
+
return place;
|
|
967
|
+
}
|
|
968
|
+
function sky(data) {
|
|
969
|
+
return el("div", { class: "aparte-weather__sky", attrs: { "data-condition": data.condition, "data-night": data.night, "aria-hidden": "true" } });
|
|
970
|
+
}
|
|
971
|
+
function hours(ctx, data) {
|
|
972
|
+
if (data.hourly.length < 2) return null;
|
|
973
|
+
const temps = data.hourly.map((h) => h.temperature);
|
|
974
|
+
const list = el("ol", { class: "aparte-weather__hours" });
|
|
975
|
+
data.hourly.forEach((h, i) => {
|
|
976
|
+
const time = el("span", { class: "aparte-weather__hour-time" });
|
|
977
|
+
if (i === 0) ctx.word(time, "cardsWeatherNow", W.cardsWeatherNow);
|
|
978
|
+
else ctx.bind(time, () => formatHour(ctx.config, h.time));
|
|
979
|
+
const temp = el("span", { class: "aparte-weather__hour-temp" });
|
|
980
|
+
ctx.bind(temp, () => deg(ctx.config, h.temperature));
|
|
981
|
+
const cond = h.condition ?? data.condition;
|
|
982
|
+
const sky2 = el("span", { class: "aparte-sr-only" });
|
|
983
|
+
ctx.word(sky2, `cardsWeather_${cond}`, CONDITION_WORDS[cond]);
|
|
984
|
+
let rain = null;
|
|
985
|
+
if (h.precipitation !== void 0 && h.precipitation >= 30) {
|
|
986
|
+
rain = el("span", { class: "aparte-weather__hour-rain" });
|
|
987
|
+
ctx.bind(rain, () => formatPercent(ctx.config, h.precipitation / 100));
|
|
988
|
+
}
|
|
989
|
+
list.append(el("li", { class: "aparte-weather__hour" }, time, sky2, glyph(weatherIcon(cond, h.night), "aparte-rich-card__glyph aparte-weather__mini"), rain, temp));
|
|
990
|
+
});
|
|
991
|
+
const strip = el(
|
|
992
|
+
"div",
|
|
993
|
+
{ class: "aparte-weather__hourly" },
|
|
994
|
+
el("div", { class: "aparte-weather__curve" }, sparkline(temps, { area: true, pad: 0.2 })),
|
|
995
|
+
list
|
|
996
|
+
);
|
|
997
|
+
strip.style.setProperty("--aparte-weather-hours", String(data.hourly.length));
|
|
998
|
+
return strip;
|
|
999
|
+
}
|
|
1000
|
+
function renderHero(data, ctx) {
|
|
1001
|
+
const { config } = ctx;
|
|
1002
|
+
const head = el("div", { class: "aparte-weather__head" }, placeLine(ctx, data), glyph(weatherIcon(data.condition, data.night), "aparte-rich-card__glyph aparte-weather__icon"));
|
|
1003
|
+
const now = el("div", { class: "aparte-weather__now" });
|
|
1004
|
+
if (data.temperature !== void 0) {
|
|
1005
|
+
const temp = el("span", { class: "aparte-weather__temp" });
|
|
1006
|
+
ctx.bind(temp, () => deg(config, data.temperature));
|
|
1007
|
+
ctx.bind(temp, () => degFull(config, data.temperature, data.unit), "aria-label");
|
|
1008
|
+
now.append(temp);
|
|
1009
|
+
}
|
|
1010
|
+
const text = el("div", { class: "aparte-weather__now-text" });
|
|
1011
|
+
const summary = el("span", { class: "aparte-weather__summary" });
|
|
1012
|
+
ctx.bind(summary, () => summaryOf(data, config));
|
|
1013
|
+
text.append(summary);
|
|
1014
|
+
const line = el("span", { class: "aparte-weather__line" });
|
|
1015
|
+
const range = rangeText(ctx, data);
|
|
1016
|
+
if (range) line.append(range);
|
|
1017
|
+
if (data.feelsLike !== void 0) {
|
|
1018
|
+
const feels = el("span", { class: "aparte-weather__feels" });
|
|
1019
|
+
ctx.bind(feels, () => word(config, "cardsWeatherFeelsLike", W.cardsWeatherFeelsLike, { t: deg(config, data.feelsLike) }));
|
|
1020
|
+
line.append(feels);
|
|
1021
|
+
}
|
|
1022
|
+
if (line.childNodes.length) text.append(line);
|
|
1023
|
+
now.append(text);
|
|
1024
|
+
const stats = el("dl", { class: "aparte-weather__stats" });
|
|
1025
|
+
if (data.wind) {
|
|
1026
|
+
const arrow = data.wind.direction !== void 0 ? el("span", { class: "aparte-weather__wind-arrow", attrs: { "aria-hidden": "true", style: `--aparte-weather-wind-angle: ${Math.round(data.wind.direction + 180)}deg` }, text: "↑" }) : void 0;
|
|
1027
|
+
stats.append(stat(ctx, "cardsWeatherWind", () => windText(config, data.wind), arrow));
|
|
1028
|
+
}
|
|
1029
|
+
if (data.humidity !== void 0) stats.append(stat(ctx, "cardsWeatherHumidity", () => formatUnit(config, data.humidity, "percent")));
|
|
1030
|
+
if (data.precipitation !== void 0) stats.append(stat(ctx, "cardsWeatherRain", () => formatUnit(config, data.precipitation, "percent")));
|
|
1031
|
+
const body = el("div", { class: "aparte-weather__body" }, head, now);
|
|
1032
|
+
if (stats.childNodes.length) body.append(stats);
|
|
1033
|
+
const hourly = hours(ctx, data);
|
|
1034
|
+
if (hourly) body.append(hourly);
|
|
1035
|
+
return [sky(data), body];
|
|
1036
|
+
}
|
|
1037
|
+
function renderCompact(data, ctx) {
|
|
1038
|
+
const { config } = ctx;
|
|
1039
|
+
const row = el("div", { class: "aparte-weather__compact" });
|
|
1040
|
+
row.append(glyph(weatherIcon(data.condition, data.night), "aparte-rich-card__glyph aparte-weather__icon"));
|
|
1041
|
+
if (data.temperature !== void 0) {
|
|
1042
|
+
const temp = el("span", { class: "aparte-weather__temp" });
|
|
1043
|
+
ctx.bind(temp, () => deg(config, data.temperature));
|
|
1044
|
+
ctx.bind(temp, () => degFull(config, data.temperature, data.unit), "aria-label");
|
|
1045
|
+
row.append(temp);
|
|
1046
|
+
}
|
|
1047
|
+
const text = el("div", { class: "aparte-weather__compact-text" });
|
|
1048
|
+
const name = el("span", { class: "aparte-weather__location" });
|
|
1049
|
+
ctx.bind(name, () => data.location ?? word(config, "cardsWeatherTitle", W.cardsWeatherTitle));
|
|
1050
|
+
const summary = el("span", { class: "aparte-weather__summary" });
|
|
1051
|
+
ctx.bind(summary, () => summaryOf(data, config));
|
|
1052
|
+
text.append(name, summary);
|
|
1053
|
+
row.append(text);
|
|
1054
|
+
const range = rangeText(ctx, data);
|
|
1055
|
+
if (range) row.append(range);
|
|
1056
|
+
return [el("span", { class: "aparte-weather__accent", attrs: { "data-condition": data.condition, "data-night": data.night, "aria-hidden": "true" } }), row];
|
|
1057
|
+
}
|
|
1058
|
+
function heat(celsius) {
|
|
1059
|
+
const stops = [
|
|
1060
|
+
[-10, [129, 140, 248]],
|
|
1061
|
+
[0, [96, 165, 250]],
|
|
1062
|
+
[10, [52, 211, 153]],
|
|
1063
|
+
[18, [250, 204, 21]],
|
|
1064
|
+
[26, [251, 146, 60]],
|
|
1065
|
+
[34, [239, 68, 68]]
|
|
1066
|
+
];
|
|
1067
|
+
if (celsius <= stops[0][0]) return `rgb(${stops[0][1].join(" ")})`;
|
|
1068
|
+
for (let i = 1; i < stops.length; i++) {
|
|
1069
|
+
const [t1, c1] = stops[i];
|
|
1070
|
+
const [t0, c0] = stops[i - 1];
|
|
1071
|
+
if (celsius <= t1) {
|
|
1072
|
+
const k = (celsius - t0) / (t1 - t0);
|
|
1073
|
+
return `rgb(${c0.map((v, j) => Math.round(v + (c1[j] - v) * k)).join(" ")})`;
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
return `rgb(${stops[stops.length - 1][1].join(" ")})`;
|
|
1077
|
+
}
|
|
1078
|
+
function renderForecast(data, ctx) {
|
|
1079
|
+
const { config } = ctx;
|
|
1080
|
+
const header = el("div", { class: "aparte-weather__forecast-head" }, sky(data));
|
|
1081
|
+
header.append(...renderCompact(data, ctx).slice(1));
|
|
1082
|
+
if (data.daily.length === 0) return [header];
|
|
1083
|
+
const toC = (t) => data.unit === "F" ? (t - 32) * 5 / 9 : t;
|
|
1084
|
+
const lo = Math.min(...data.daily.map((d) => d.low));
|
|
1085
|
+
const hi = Math.max(...data.daily.map((d) => d.high));
|
|
1086
|
+
const span = hi - lo || 1;
|
|
1087
|
+
const list = el("ol", { class: "aparte-weather__days" });
|
|
1088
|
+
ctx.bind(list, () => word(config, "cardsWeatherForecast", W.cardsWeatherForecast), "aria-label");
|
|
1089
|
+
data.daily.forEach((d, i) => {
|
|
1090
|
+
const name = el("span", { class: "aparte-weather__day-name" });
|
|
1091
|
+
ctx.bind(name, () => formatDay(config, d.date, "short"));
|
|
1092
|
+
const rain = el("span", { class: "aparte-weather__day-rain" });
|
|
1093
|
+
if (d.precipitation !== void 0 && d.precipitation >= 20) ctx.bind(rain, () => formatPercent(config, d.precipitation / 100));
|
|
1094
|
+
const low = el("span", { class: "aparte-weather__day-low" });
|
|
1095
|
+
ctx.bind(low, () => deg(config, d.low));
|
|
1096
|
+
const high = el("span", { class: "aparte-weather__day-high" });
|
|
1097
|
+
ctx.bind(high, () => deg(config, d.high));
|
|
1098
|
+
const fill = el("span", { class: "aparte-weather__bar-fill" });
|
|
1099
|
+
fill.style.setProperty("--aparte-weather-bar-start", `${(d.low - lo) / span * 100}%`);
|
|
1100
|
+
fill.style.setProperty("--aparte-weather-bar-end", `${(d.high - lo) / span * 100}%`);
|
|
1101
|
+
fill.style.setProperty("--aparte-weather-bar-cold", heat(toC(d.low)));
|
|
1102
|
+
fill.style.setProperty("--aparte-weather-bar-warm", heat(toC(d.high)));
|
|
1103
|
+
const bar = el("span", { class: "aparte-weather__bar", attrs: { "aria-hidden": "true" } }, fill);
|
|
1104
|
+
if (i === 0 && data.temperature !== void 0 && data.temperature >= d.low && data.temperature <= d.high) {
|
|
1105
|
+
const dot = el("span", { class: "aparte-weather__bar-now" });
|
|
1106
|
+
dot.style.setProperty("--aparte-weather-bar-at", `${(data.temperature - lo) / span * 100}%`);
|
|
1107
|
+
bar.append(dot);
|
|
1108
|
+
}
|
|
1109
|
+
const row = el("li", { class: "aparte-weather__day" }, name, glyph(weatherIcon(d.condition), "aparte-rich-card__glyph aparte-weather__mini"), rain, low, bar, high);
|
|
1110
|
+
ctx.bind(row, () => `${formatDay(config, d.date, "long")}: ${word(config, `cardsWeather_${d.condition}`, CONDITION_WORDS[d.condition])}, ${word(config, "cardsWeatherLow", W.cardsWeatherLow)} ${degFull(config, d.low, data.unit)}, ${word(config, "cardsWeatherHigh", W.cardsWeatherHigh)} ${degFull(config, d.high, data.unit)}`, "aria-label");
|
|
1111
|
+
list.append(row);
|
|
1112
|
+
});
|
|
1113
|
+
return [header, list];
|
|
1114
|
+
}
|
|
1115
|
+
function skeleton(partial, ctx) {
|
|
1116
|
+
const block = (cls, kind = "rect") => el("span", { class: `aparte-skeleton aparte-skeleton--${kind} ${cls}`, attrs: { "aria-hidden": "true" } });
|
|
1117
|
+
const place = el("div", { class: "aparte-weather__place" });
|
|
1118
|
+
if (partial?.location) place.append(el("span", { class: "aparte-weather__location", text: partial.location }));
|
|
1119
|
+
else place.append(block("aparte-weather__sk-place", "text"));
|
|
1120
|
+
const head = el("div", { class: "aparte-weather__head" }, place, block("aparte-weather__sk-icon", "circle"));
|
|
1121
|
+
if (ctx.variant === "compact") {
|
|
1122
|
+
return [el("div", { class: "aparte-weather__compact" }, block("aparte-weather__sk-icon", "circle"), block("aparte-weather__sk-temp"), place)];
|
|
1123
|
+
}
|
|
1124
|
+
const stats = el("div", { class: "aparte-weather__sk-stats" }, block("aparte-weather__sk-stat"), block("aparte-weather__sk-stat"), block("aparte-weather__sk-stat"));
|
|
1125
|
+
return [el("div", { class: "aparte-weather__body" }, head, el("div", { class: "aparte-weather__now" }, block("aparte-weather__sk-temp"), block("aparte-weather__sk-summary", "text")), stats)];
|
|
1126
|
+
}
|
|
1127
|
+
const weatherCard = defineCard({
|
|
1128
|
+
name: "weather",
|
|
1129
|
+
variants: ["hero", "compact", "forecast"],
|
|
1130
|
+
styles: weatherStyles,
|
|
1131
|
+
icon: weatherIcon("partly-cloudy"),
|
|
1132
|
+
normalize: readWeather,
|
|
1133
|
+
render: (data, ctx) => ctx.variant === "compact" ? renderCompact(data, ctx) : ctx.variant === "forecast" ? renderForecast(data, ctx) : renderHero(data, ctx),
|
|
1134
|
+
skeleton,
|
|
1135
|
+
label: (data, ctx) => data?.location ? word(ctx.config, "cardsWeatherIn", W.cardsWeatherIn, { place: data.location }) : word(ctx.config, "cardsWeatherTitle", W.cardsWeatherTitle),
|
|
1136
|
+
fallback: (data, ctx) => {
|
|
1137
|
+
const parts = [
|
|
1138
|
+
data.temperature !== void 0 ? degFull(ctx.config, data.temperature, data.unit) : null,
|
|
1139
|
+
summaryOf(data, ctx.config),
|
|
1140
|
+
data.high !== void 0 && data.low !== void 0 ? `${word(ctx.config, "cardsWeatherHigh", W.cardsWeatherHigh)} ${degFull(ctx.config, data.high, data.unit)} / ${word(ctx.config, "cardsWeatherLow", W.cardsWeatherLow)} ${degFull(ctx.config, data.low, data.unit)}` : null
|
|
1141
|
+
].filter(Boolean);
|
|
1142
|
+
return `${data.location ? `${data.location}: ` : ""}${parts.join(", ")}`;
|
|
1143
|
+
},
|
|
1144
|
+
partial: (input) => {
|
|
1145
|
+
const location = str(input["location"] ?? input["city"] ?? input["place"] ?? input["q"] ?? input["query"]);
|
|
1146
|
+
return location ? { location } : null;
|
|
1147
|
+
}
|
|
1148
|
+
});
|
|
1149
|
+
function setupWeatherCard(options = {}) {
|
|
1150
|
+
return weatherCard.setup(options);
|
|
1151
|
+
}
|
|
1152
|
+
export {
|
|
1153
|
+
WEATHER_CONDITIONS,
|
|
1154
|
+
conditionFromOpenWeather,
|
|
1155
|
+
conditionFromText,
|
|
1156
|
+
conditionFromWmo,
|
|
1157
|
+
fromOpenMeteo,
|
|
1158
|
+
readWeather,
|
|
1159
|
+
setupWeatherCard,
|
|
1160
|
+
weatherCard
|
|
1161
|
+
};
|
|
1162
|
+
//# sourceMappingURL=weather.js.map
|