Menu
Public repository / 439f0dcabf5cdf2b120c7724be895cf1df30507f
AkurAI-Framework / site/frontend/ai/components/display/weather_widget.js
Latest change 88d669a6b3c5464f8a947a66be0437a90424470f - feat(ai): add Display components — citation, link_preview, stats_display, terminal, weather_widget by Ólafur Búi Ólafsson
/**
* Weather Widget — location, temp, condition, hi/lo, optional hourly array.
* Payload: {
* location: string,
* temp: number,
* unit?: "C" | "F",
* condition: string,
* hi: number,
* lo: number,
* hourly?: Array<{ time: string, temp: number, condition: string }>
* }
* Condition icon: native SVG. No libs.
*/
function el(tag, cls) {
const node = document.createElement(tag);
if (cls) node.className = cls;
return node;
}
// Map a condition string to an emoji (no lib, no images)
function conditionEmoji(condition) {
const c = String(condition).toLowerCase();
if (c.includes("thunder") || c.includes("storm")) return "⛈️";
if (c.includes("snow") || c.includes("blizzard")) return "❄️";
if (c.includes("sleet") || c.includes("hail")) return "🌨️";
if (c.includes("rain") || c.includes("drizzle") || c.includes("shower")) return "🌧️";
if (c.includes("fog") || c.includes("mist") || c.includes("haze")) return "🌫️";
if (c.includes("cloud") || c.includes("overcast")) return "☁️";
if (c.includes("partly") || c.includes("partial")) return "⛅";
if (c.includes("clear") || c.includes("sunny")) return "☀️";
if (c.includes("wind") || c.includes("breezy")) return "💨";
return "🌡️";
}
export const def = {
name: "weather_widget",
category: "Display",
title: "Weather Widget",
match(payload) {
return (
payload !== null &&
typeof payload === "object" &&
typeof payload.location === "string" &&
typeof payload.temp === "number" &&
typeof payload.condition === "string" &&
typeof payload.hi === "number" &&
typeof payload.lo === "number"
);
},
render(payload) {
const { location, temp, unit = "C", condition, hi, lo, hourly } = payload;
const deg = (n) => String(Math.round(n)) + "°" + unit;
const card = el("div", "card tc-display-weather");
// Top row: location + icon
const top = el("div", "tc-display-weather__top");
const locEl = el("div", "tc-display-weather__location muted small");
locEl.textContent = location;
top.appendChild(locEl);
const icon = el("span", "tc-display-weather__icon");
icon.textContent = conditionEmoji(condition);
icon.setAttribute("aria-label", condition);
top.appendChild(icon);
card.appendChild(top);
// Main temp
const tempEl = el("div", "tc-display-weather__temp");
tempEl.textContent = deg(temp);
card.appendChild(tempEl);
// Condition label
const condEl = el("div", "tc-display-weather__condition muted");
condEl.textContent = condition;
card.appendChild(condEl);
// Hi / Lo row
const range = el("div", "tc-display-weather__range");
const hiEl = el("span", "tc-display-weather__hi");
hiEl.textContent = "H " + deg(hi);
const sep = el("span", "muted");
sep.textContent = " · ";
const loEl = el("span", "tc-display-weather__lo muted");
loEl.textContent = "L " + deg(lo);
range.appendChild(hiEl);
range.appendChild(sep);
range.appendChild(loEl);
card.appendChild(range);
// Optional hourly strip
if (Array.isArray(hourly) && hourly.length > 0) {
const strip = el("div", "tc-display-weather__hourly");
for (const h of hourly.slice(0, 8)) {
const slot = el("div", "tc-display-weather__slot");
const slotTime = el("div", "tc-display-weather__slot-time muted small");
slotTime.textContent = String(h.time ?? "");
slot.appendChild(slotTime);
const slotIcon = el("div", "tc-display-weather__slot-icon");
slotIcon.textContent = conditionEmoji(h.condition ?? "");
slotIcon.setAttribute("aria-label", h.condition ?? "");
slot.appendChild(slotIcon);
const slotTemp = el("div", "tc-display-weather__slot-temp");
slotTemp.textContent = deg(h.temp);
slot.appendChild(slotTemp);
strip.appendChild(slot);
}
card.appendChild(strip);
}
return card;
},
example: {
location: "Akureyri, Iceland",
temp: 9,
unit: "C",
condition: "Partly cloudy",
hi: 12,
lo: 5,
hourly: [
{ time: "Now", temp: 9, condition: "Partly cloudy" },
{ time: "13:00", temp: 10, condition: "Partly cloudy" },
{ time: "14:00", temp: 11, condition: "Sunny" },
{ time: "15:00", temp: 12, condition: "Sunny" },
{ time: "16:00", temp: 11, condition: "Cloudy" },
{ time: "17:00", temp: 10, condition: "Rain" },
{ time: "18:00", temp: 8, condition: "Rain" },
{ time: "19:00", temp: 7, condition: "Cloudy" },
],
},
};