AkurAI Build
Menu

Public repository / 439f0dcabf5cdf2b120c7724be895cf1df30507f

AkurAI-Framework / site/frontend/ai/components/content/x_post.js

Latest change 67a966d4abf972b300e8c6c214a30a0279103337 - feat(ai): Artifacts content components + geo map + item carousel (AB3-C) by Ólafur Búi Ólafsson

/**
 * X Post — Artifacts / content component.
 * Payload: { handle: string, name: string, avatar?: string, text: string, stats?: { likes?: number, reposts?: number, replies?: number } }
 * Renders an X/Twitter-style post card.
 */

function esc(str) {
  return String(str ?? "")
    .replace(/&/g, "&")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;");
}

function fmt(n) {
  if (n == null) return "0";
  if (n >= 1_000_000) return (n / 1_000_000).toFixed(1) + "M";
  if (n >= 1_000) return (n / 1_000).toFixed(1) + "K";
  return String(n);
}

function avatarEl(avatar, name) {
  if (avatar) {
    return `<img class="tc-content-xpost__avatar" src="${esc(avatar)}" alt="${esc(name)}" width="40" height="40" loading="lazy">`;
  }
  const initials = esc((name || "?").slice(0, 2).toUpperCase());
  return `<div class="tc-content-xpost__avatar tc-content-xpost__avatar--placeholder" aria-label="${esc(name)}">${initials}</div>`;
}

export const def = {
  name: "x_post",
  category: "Artifacts",
  title: "X Post",

  match(payload) {
    return (
      payload !== null &&
      typeof payload === "object" &&
      typeof payload.handle === "string" &&
      typeof payload.text === "string"
    );
  },

  render(payload) {
    const { handle, name = handle, avatar, text, stats = {} } = payload;
    const { likes = 0, reposts = 0, replies = 0 } = stats;

    const card = document.createElement("div");
    card.className = "tc-content-xpost";
    card.setAttribute("role", "article");
    card.setAttribute("aria-label", `Post by ${name}`);

    card.innerHTML = `
<div class="tc-content-xpost__header">
  ${avatarEl(avatar, name)}
  <div class="tc-content-xpost__meta">
    <span class="tc-content-xpost__name">${esc(name)}</span>
    <span class="tc-content-xpost__handle">@${esc(handle)}</span>
  </div>
  <svg class="tc-content-xpost__logo" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" width="18" height="18">
    <path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.746l7.73-8.835L1.254 2.25H8.08l4.253 5.622L18.244 2.25zm-1.161 17.52h1.833L7.084 4.126H5.117L17.083 19.77z"/>
  </svg>
</div>
<div class="tc-content-xpost__text">${esc(text)}</div>
<div class="tc-content-xpost__stats">
  <span class="tc-content-xpost__stat">
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" width="16" height="16" aria-hidden="true"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
    ${fmt(replies)}
  </span>
  <span class="tc-content-xpost__stat">
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" width="16" height="16" aria-hidden="true"><path d="M17 1l4 4-4 4M3 11V9a4 4 0 0 1 4-4h14M7 23l-4-4 4-4M21 13v2a4 4 0 0 1-4 4H3"/></svg>
    ${fmt(reposts)}
  </span>
  <span class="tc-content-xpost__stat tc-content-xpost__stat--likes">
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" width="16" height="16" aria-hidden="true"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg>
    ${fmt(likes)}
  </span>
</div>
`;
    return card;
  },

  example: {
    handle: "olibuijr",
    name: "Ólafur Búi",
    text: "Just shipped the AI component library for AkurAI Framework — native ESM, zero deps, streaming generative UI. No React, no bundler. 🚀",
    stats: { likes: 142, reposts: 38, replies: 17 },
  },
};