import { createEffect, on, 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 = () => ( 1. 2. 3. ); const RuleIcon = () => ( ); export type ExecFn = (cmd: string, val?: string) => void; export function Toolbar(props: { exec: ExecFn; class?: string }) { const e = props.exec; function toggleHeading() { const val = document.queryCommandValue("formatBlock").toLowerCase(); e("formatBlock", val === "h2" ? "p" : "h2"); } return (
); } /* ── Inline editor (Add.tsx, Entry.tsx note view) ── */ interface NoteEditorInlineProps { initialContent: string; onContentChange?: (html: string) => void; onBlur?: (html: string) => void; onReady?: (el: HTMLDivElement) => void; autoFocus?: boolean; /** When this key changes, the editor re-loads initialContent (e.g., switching between vault entries in-place). */ entryKey?: string; } export function NoteEditorInline(props: NoteEditorInlineProps) { let editorRef: HTMLDivElement | undefined; onMount(() => { if (!editorRef) return; editorRef.innerHTML = toHtml(props.initialContent); if (props.autoFocus !== false) editorRef.focus(); props.onReady?.(editorRef); }); createEffect(on(() => props.entryKey, (key, prevKey) => { if (prevKey === undefined || key === prevKey || !editorRef) return; editorRef.innerHTML = toHtml(props.initialContent); props.onReady?.(editorRef); })); function exec(cmd: string, value?: string) { document.execCommand(cmd, false, value); editorRef?.focus(); } function handleKeyDown(e: KeyboardEvent) { const mod = e.metaKey || e.ctrlKey; // Only intercept shortcuts for non-alphanumeric keys to avoid swallowing // letter input. Letter keys (a–z, etc.) must always pass through freely. const isLetterKey = e.key.length === 1; if (isLetterKey) return; 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 ?? "")} onBlur={() => props.onBlur?.(editorRef?.innerHTML ?? "")} aria-multiline="true" aria-label="Note content" />
); }