// One widget, alone, for an iframe in someone else's dashboard (Glance, Home Assistant…): // /embed/widget?type=gauge&sensor=cpu.usage&token= // &machine=grid &title=… &theme=dark|light|cyberpunk|retro &every= &bare=1 // It stays live over the sensor stream. The token must be a read-only sensor token; a // full-control token is refused in a URL by design. import { useSensorStream, Source } from './sensors' import { Widget, WidgetData, WidgetSpec, WidgetType, WIDGET_TYPES } from './widgets' import { applyTheme } from './themes' const p = new URLSearchParams(location.search) if (p.get('theme')) applyTheme(p.get('theme')!) if (p.get('bare') === '1') document.body.style.background = 'transparent' // sit on the host dashboard's own card export default function Embed() { const sensor = p.get('sensor') ?? '' const asked = p.get('type') as WidgetType | null const type: WidgetType = /[*?[]/.test(sensor) ? 'list' : asked && WIDGET_TYPES.some((t) => t.id === asked && !t.many) ? asked : 'stat' const spec: WidgetSpec = { id: 'w', type, sensor, title: p.get('title') ?? undefined } const src: Source = { machine: p.get('machine') || null, token: p.get('token') ?? undefined } const every = Number(p.get('every')) || undefined const live = useSensorStream<{ w: WidgetData }>(sensor ? { w: sensor } : null, { src, everyMs: every }) return (
{!sensor ?
embed needs ?sensor=
: (
{live.error && !live.data &&
{src.token ? live.error : 'no token in the URL (&token=…)'}
}
)}
) }