import { useState, useCallback } from "react";
import { FileText } from "lucide-react";
import { registerWidget } from "./WidgetRegistry";
import type { MarkdownNotesConfig, WidgetComponentProps } from "../types.js";
import { GRID_SIZE } from "../types.js";
import { updateHomepageItem } from "../api.js";
import { WidgetTitle } from "@termix/plugin-sdk/ui";
function renderMarkdown(src: string): string {
return src
.split("\n")
.map((line) => {
if (/^### /.test(line))
return `
${esc(line.slice(4))}
`;
if (/^## /.test(line))
return `${esc(line.slice(3))}
`;
if (/^# /.test(line))
return `${esc(line.slice(2))}
`;
if (/^- /.test(line))
return `${inlineFormat(line.slice(2))}`;
if (/^\d+\. /.test(line))
return `${inlineFormat(line.replace(/^\d+\. /, ""))}`;
if (line.trim() === "") return "
";
return `${inlineFormat(line)}
`;
})
.join("");
}
function esc(s: string): string {
return s.replace(/&/g, "&").replace(//g, ">");
}
function inlineFormat(s: string): string {
return esc(s)
.replace(/\*\*(.+?)\*\*/g, "$1")
.replace(/\*(.+?)\*/g, "$1")
.replace(
/`(.+?)`/g,
'$1',
);
}
function MarkdownNotesWidget({
widget,
config,
isReadOnly,
onConfigUpdate,
}: WidgetComponentProps) {
const { content, backgroundColor, renderMarkdown: doRender } = config;
const [editing, setEditing] = useState(false);
const [draft, setDraft] = useState(content);
const commitEdit = useCallback(async () => {
setEditing(false);
if (draft === content) return;
try {
await updateHomepageItem(widget.id, {
config: { ...config, content: draft } as unknown as Record<
string,
unknown
>,
});
onConfigUpdate?.({ ...config, content: draft } as unknown as Record<
string,
unknown
>);
} catch {
/* ignore */
}
}, [draft, content, widget.id, config, onConfigUpdate]);
return (
} />
);
}
registerWidget
({
id: "markdown_notes",
name: "Markdown Notes",
description: "Notes with optional Markdown rendering and inline editing",
category: "info",
icon: ,
defaultConfig: { content: "", renderMarkdown: true },
defaultSize: { w: GRID_SIZE * 10, h: GRID_SIZE * 8 },
minSize: { w: GRID_SIZE * 3, h: GRID_SIZE * 3 },
component: MarkdownNotesWidget,
});
export { MarkdownNotesWidget };