/**
* rCal applet definitions — Next Event, Timeline View.
*/
import type { AppletDefinition, AppletLiveData } from "../../shared/applet-types";
import { projectSpace } from "../../shared/markwhen";
const nextEvent: AppletDefinition = {
id: "next-event",
label: "Next Event",
icon: "📅",
accentColor: "#2563eb",
ports: [
{ name: "events-in", type: "json", direction: "input" },
{ name: "event-out", type: "json", direction: "output" },
],
renderCompact(data: AppletLiveData): string {
const { snapshot } = data;
const title = (snapshot.title as string) || "No upcoming events";
const time = (snapshot.time as string) || "";
const location = (snapshot.location as string) || "";
return `
${title}
${time ? `
🕐 ${time}
` : ""}
${location ? `
📍 ${location}
` : ""}
${!time && !location ? `
Connect a calendar feed
` : ""}
`;
},
onInputReceived(portName, value, ctx) {
if (portName === "events-in" && Array.isArray(value) && value.length > 0) {
ctx.emitOutput("event-out", value[0]);
}
},
};
const timelineView: AppletDefinition = {
id: "timeline-view",
label: "Timeline",
icon: "🕒",
accentColor: "#2563eb",
ports: [
{ name: "range-in", type: "json", direction: "input" },
{ name: "mw-out", type: "json", direction: "output" },
],
renderCompact(data: AppletLiveData): string {
const count = Number(data.snapshot.count ?? 0);
const preview = (data.snapshot.preview as string) || "";
return `
${count} event(s)
${preview || "Open to render timeline"}
`;
},
async fetchLiveData(space: string) {
const projection = await projectSpace(space, { modules: ["rcal"] });
const first = projection.events[0];
return {
count: projection.count,
preview: first ? first.title : "",
mw: projection.text,
};
},
onInputReceived(portName, value, ctx) {
if (portName === "range-in" && value && typeof value === "object") {
const range = value as { from?: number; to?: number };
projectSpace(ctx.space, { modules: ["rcal"], from: range.from, to: range.to })
.then(p => ctx.emitOutput("mw-out", p.text));
}
},
};
export const calApplets: AppletDefinition[] = [nextEvent, timelineView];