import { onMount } from "solid-js";
export function toHtml(raw: string): string {
if (/<\/?[a-z]/i.test(raw)) return raw;
return raw
.replace(/&/g, "&")
.replace(//g, ">")
.replace(/\n/g, "
");
}
const BoldIcon = () => B;
const ItalicIcon = () => I;
const UnderlineIcon = () => U;
const StrikeIcon = () => S;
const HeadingIcon = () => H;
const BulletIcon = () => (
);
const NumberedIcon = () => (
);
const RuleIcon = () => (
);
type ExecFn = (cmd: string, val?: string) => void;
function Toolbar(props: { exec: ExecFn }) {
const e = props.exec;
function toggleHeading() {
const val = document.queryCommandValue("formatBlock").toLowerCase();
e("formatBlock", val === "h2" ? "p" : "h2");
}
return (
);
}
/* ── Full-popup overlay editor (Entry.tsx) ── */
interface NoteEditorProps {
initialContent: string;
saving: boolean;
onSave: (html: string) => Promise;
onCancel: () => void;
}
export function NoteEditor(props: NoteEditorProps) {
let editorRef: HTMLDivElement | undefined;
onMount(() => {
if (!editorRef) return;
editorRef.innerHTML = toHtml(props.initialContent);
editorRef.focus();
const sel = window.getSelection();
if (sel) {
const range = document.createRange();
range.selectNodeContents(editorRef);
range.collapse(false);
sel.removeAllRanges();
sel.addRange(range);
}
});
function exec(cmd: string, value?: string) {
document.execCommand(cmd, false, value);
editorRef?.focus();
}
function handleKeyDown(e: KeyboardEvent) {
const mod = e.metaKey || e.ctrlKey;
if (mod && e.key === "b") { e.preventDefault(); exec("bold"); return; }
if (mod && e.key === "i") { e.preventDefault(); exec("italic"); return; }
if (mod && e.key === "u") { e.preventDefault(); exec("underline"); return; }
if (e.key === "Escape") { e.preventDefault(); props.onCancel(); }
}
return (
);
}
/* ── Inline editor (Add.tsx) ── */
interface NoteEditorInlineProps {
initialContent: string;
onContentChange: (html: string) => void;
}
export function NoteEditorInline(props: NoteEditorInlineProps) {
let editorRef: HTMLDivElement | undefined;
onMount(() => {
if (!editorRef) return;
editorRef.innerHTML = toHtml(props.initialContent);
editorRef.focus();
});
function exec(cmd: string, value?: string) {
document.execCommand(cmd, false, value);
editorRef?.focus();
}
function handleKeyDown(e: KeyboardEvent) {
const mod = e.metaKey || e.ctrlKey;
if (mod && e.key === "b") { e.preventDefault(); exec("bold"); }
if (mod && e.key === "i") { e.preventDefault(); exec("italic"); }
if (mod && e.key === "u") { e.preventDefault(); exec("underline"); }
}
return (
props.onContentChange(editorRef?.innerHTML ?? "")}
aria-multiline="true"
aria-label="Note content"
/>
);
}