rspace-online/modules/rmaps/applets.ts

84 lines
2.9 KiB
TypeScript

/**
* rMaps applet definitions — Location Pin + Route Summary.
*/
import type { AppletDefinition, AppletLiveData } from "../../shared/applet-types";
const locationPin: AppletDefinition = {
id: "location-pin",
label: "Location Pin",
icon: "📍",
accentColor: "#1d4ed8",
ports: [
{ name: "location-in", type: "json", direction: "input" },
{ name: "coords-out", type: "json", direction: "output" },
],
renderCompact(data: AppletLiveData): string {
const { snapshot } = data;
const label = (snapshot.label as string) || "Location";
const lat = (snapshot.lat as number) || 0;
const lng = (snapshot.lng as number) || 0;
const hasCoords = lat !== 0 || lng !== 0;
return `
<div style="text-align:center">
<div style="font-size:28px;margin-bottom:4px">📍</div>
<div style="font-size:13px;font-weight:600;margin-bottom:4px">${label}</div>
${hasCoords
? `<div style="font-size:10px;color:#94a3b8;font-family:monospace">${lat.toFixed(4)}, ${lng.toFixed(4)}</div>`
: `<div style="font-size:10px;color:#94a3b8;font-style:italic">No coordinates</div>`
}
</div>
`;
},
onInputReceived(portName, value, ctx) {
if (portName === "location-in" && value && typeof value === "object") {
const loc = value as Record<string, unknown>;
ctx.emitOutput("coords-out", { lat: loc.lat, lng: loc.lng });
}
},
};
const routeSummary: AppletDefinition = {
id: "route-summary",
label: "Route Summary",
icon: "🗺️",
accentColor: "#1d4ed8",
ports: [
{ name: "route-in", type: "json", direction: "input" },
{ name: "distance-out", type: "number", direction: "output" },
],
renderCompact(data: AppletLiveData): string {
const { snapshot } = data;
const from = (snapshot.from as string) || "Start";
const to = (snapshot.to as string) || "End";
const distance = (snapshot.distance as string) || "—";
const duration = (snapshot.duration as string) || "—";
return `
<div>
<div style="display:flex;align-items:center;gap:6px;margin-bottom:8px">
<span style="font-size:11px;color:#94a3b8">From</span>
<span style="font-size:12px;font-weight:600;color:#e2e8f0">${from}</span>
</div>
<div style="display:flex;align-items:center;gap:6px;margin-bottom:8px">
<span style="font-size:11px;color:#94a3b8">To</span>
<span style="font-size:12px;font-weight:600;color:#e2e8f0">${to}</span>
</div>
<div style="display:flex;justify-content:space-between;border-top:1px solid #334155;padding-top:6px">
<span style="font-size:11px;color:#60a5fa">${distance}</span>
<span style="font-size:11px;color:#94a3b8">${duration}</span>
</div>
</div>
`;
},
onInputReceived(portName, value, ctx) {
if (portName === "route-in" && value && typeof value === "object") {
const route = value as Record<string, unknown>;
ctx.emitOutput("distance-out", Number(route.distanceKm) || 0);
}
},
};
export const mapsApplets: AppletDefinition[] = [locationPin, routeSummary];