/** * Changelog UI — renders an app's CHANGELOG.md as an in-app "What's new" * surface. Core owns all of this; a template just passes its own * `CHANGELOG.md?raw` content in (Vite inlines it at build time, so this works * on every host with no runtime file access or server route). * * Surfaces: * - a self-contained modal listing every release. * - a settings-page card with the latest updates. * - useChangelogSeen() tracks the last release a user has seen (so the * command menu can show an "unseen" dot). * * The command menu's built-in `changelog` prop (see CommandMenu.tsx) wires the * dialog automatically — most templates never touch these directly. */ import { IconX, IconHistory } from "@tabler/icons-react"; import React, { useEffect, useMemo, useState } from "react"; import { parseChangelog, type ChangelogEntry } from "../../changelog/parse.js"; import { markdownModule, remarkGfmFn, useMarkdownReady, markdownUrlTransform, } from "../chat/markdown-renderer.js"; import { DEFAULT_LOCALE, useOptionalLocale, type LocaleCode } from "../i18n.js"; import { cn } from "../utils.js"; // ─── Date formatting ────────────────────────────────────────────────────────── function formatEntryHeading(entry: ChangelogEntry, locale: LocaleCode): string { if (entry.date) { // Parse as a plain calendar date (avoid TZ shifting YYYY-MM-DD back a day). const [y, m, d] = entry.date.split("-").map(Number); if (y && m && d) { const formatted = new Date(y, m - 1, d).toLocaleDateString(locale, { year: "numeric", month: "long", day: "numeric", }); return entry.version ? `${entry.version} · ${formatted}` : formatted; } } return entry.title; } // ─── Markdown body ──────────────────────────────────────────────────────────── // A small, self-contained renderer for a release body. Avoids depending on the // typography plugin (`prose`) being generated in the host template by applying // explicit utility classes that Tailwind scans from core's compiled output. const changelogMarkdownComponents = { h3: (props: React.HTMLAttributes) => (

), ul: (props: React.HTMLAttributes) => (