AkurAI Build
Menu

Public repository / 439f0dcabf5cdf2b120c7724be895cf1df30507f

AkurAI-Framework / site/frontend/ai/components/media/image.js

Latest change 36f53e8d189d0609aaabc65e705cf9db9d497d14 - Port Media components as vanilla ES modules by Ólafur Búi Ólafsson

// Image component — renders a responsive image card with optional caption.

export const def = {
  name: "image",
  category: "Media",
  title: "Image",

  match(payload) {
    return typeof payload?.src === "string";
  },

  render(payload, ctx) {
    const { src, alt = "", caption = "" } = payload;

    // XSS safety: only set src/alt from payload, never innerHTML
    const img = document.createElement("img");
    img.src = src;
    img.alt = alt;
    img.loading = "lazy";
    img.style.width = "100%";
    img.style.height = "auto";
    img.style.borderRadius = "10px";
    img.style.display = "block";

    if (!caption) {
      // No caption — just the image in a card
      const card = document.createElement("div");
      card.className = "card";
      card.style.padding = "0";
      card.style.overflow = "hidden";
      card.appendChild(img);
      return card;
    }

    // With caption
    const card = document.createElement("div");
    card.className = "card";

    const imgWrapper = document.createElement("div");
    imgWrapper.style.marginBottom = "12px";
    imgWrapper.style.overflow = "hidden";
    imgWrapper.style.borderRadius = "8px";
    imgWrapper.appendChild(img);

    const captionEl = document.createElement("p");
    captionEl.style.margin = "0";
    captionEl.style.fontSize = "13px";
    captionEl.style.color = "var(--muted)";
    captionEl.style.lineHeight = "1.5";
    captionEl.textContent = caption;

    card.appendChild(imgWrapper);
    card.appendChild(captionEl);

    return card;
  },

  example: {
    src: "https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=800&h=600&fit=crop",
    alt: "Mountain landscape",
    caption: "A serene mountain landscape at sunset"
  }
};