import { useMemo, useState, useEffect, useCallback } from "react"; import { KoenigComposer, KoenigEditor, CardMenuPlugin } from "@tryghost/koenig-lexical"; import "koenig-styles"; import makeFileUploader from "./useFileUpload"; export default function Editor({ initialState, onChange, csrfToken, uploadUrls, oembedUrl, unsplashApiKey, snippetsUrl }) { const fileUploader = useMemo(() => makeFileUploader(csrfToken, uploadUrls), [csrfToken, uploadUrls]); const [snippets, setSnippets] = useState([]); useEffect(() => { if (!snippetsUrl) return; fetch(snippetsUrl, { headers: { "X-CSRFToken": csrfToken || "" } }) .then((r) => r.ok ? r.json() : []) .then(setSnippets) .catch(() => {}); }, [snippetsUrl, csrfToken]); const createSnippet = useCallback(async ({ name, value }) => { if (!snippetsUrl) return; const resp = await fetch(snippetsUrl, { method: "POST", headers: { "Content-Type": "application/json", "X-CSRFToken": csrfToken || "", }, body: JSON.stringify({ name, value: JSON.stringify(value) }), }); if (!resp.ok) return; const created = await resp.json(); setSnippets((prev) => { const idx = prev.findIndex((s) => s.name === created.name); if (idx >= 0) { const next = [...prev]; next[idx] = created; return next; } return [...prev, created].sort((a, b) => a.name.localeCompare(b.name)); }); }, [snippetsUrl, csrfToken]); const cardConfig = useMemo(() => ({ fetchEmbed: async (url, { type } = {}) => { const params = new URLSearchParams({ url }); if (type) params.set("type", type); const resp = await fetch(`${oembedUrl}?${params}`, { headers: { "X-CSRFToken": csrfToken || "" }, }); if (!resp.ok) return {}; return resp.json(); }, unsplash: unsplashApiKey ? { defaultHeaders: { Authorization: `Client-ID ${unsplashApiKey}` } } : false, membersEnabled: true, snippets: snippets.map((s) => ({ id: s.id, name: s.name, value: typeof s.value === "string" ? JSON.parse(s.value) : s.value, })), createSnippet, }), [oembedUrl, csrfToken, unsplashApiKey, snippets, createSnippet]); return ( { if (onChange) { onChange(JSON.stringify(serializedState)); } }} > ); }