notes upgrade

This commit is contained in:
nmemmert
2026-06-18 13:43:17 -04:00
parent e0ed798741
commit dd43d0c3ea
9 changed files with 1591 additions and 155 deletions
+96
View File
@@ -0,0 +1,96 @@
import { useEditor, EditorContent } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import { useEffect } from 'react'
interface NoteCardProps {
anchorLabel: string
html: string
autoSaveMsg?: string
onChange: (html: string) => void
onClose: () => void
}
export function NoteCard({ anchorLabel, html, autoSaveMsg, onChange, onClose }: NoteCardProps) {
const editor = useEditor({
extensions: [StarterKit],
content: html || '<p></p>',
onUpdate({ editor }) {
const next = editor.getHTML()
onChange(next === '<p></p>' ? '' : next)
},
})
useEffect(() => {
if (!editor || editor.isDestroyed) return
if (editor.getHTML() !== html) {
editor.commands.setContent(html || '<p></p>', false)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [html])
useEffect(() => () => { editor?.destroy() }, [editor])
if (!editor) return null
return (
<div className="note-card">
<div className="note-card-header">
<span className="note-card-label"> {anchorLabel}</span>
<div style={{ display: 'flex', alignItems: 'center', gap: '0.75rem' }}>
{autoSaveMsg && <span className="note-card-autosave">{autoSaveMsg}</span>}
<button type="button" className="note-card-close" onClick={onClose} aria-label="Close note">×</button>
</div>
</div>
<div className="note-card-toolbar" role="toolbar" aria-label="Text formatting">
<button
type="button"
className={`note-tool${editor.isActive('bold') ? ' note-tool--active' : ''}`}
onMouseDown={e => { e.preventDefault(); editor.chain().focus().toggleBold().run() }}
aria-label="Bold"
title="Bold (Ctrl+B)"
><strong>B</strong></button>
<button
type="button"
className={`note-tool${editor.isActive('italic') ? ' note-tool--active' : ''}`}
onMouseDown={e => { e.preventDefault(); editor.chain().focus().toggleItalic().run() }}
aria-label="Italic"
title="Italic (Ctrl+I)"
><em>I</em></button>
<button
type="button"
className={`note-tool${editor.isActive('bulletList') ? ' note-tool--active' : ''}`}
onMouseDown={e => { e.preventDefault(); editor.chain().focus().toggleBulletList().run() }}
aria-label="Bullet list"
title="Bullet list"
></button>
<button
type="button"
className={`note-tool${editor.isActive('orderedList') ? ' note-tool--active' : ''}`}
onMouseDown={e => { e.preventDefault(); editor.chain().focus().toggleOrderedList().run() }}
aria-label="Numbered list"
title="Numbered list"
>1.</button>
<div className="note-tool-divider" />
<button
type="button"
className="note-tool"
onMouseDown={e => { e.preventDefault(); editor.chain().focus().undo().run() }}
disabled={!editor.can().undo()}
aria-label="Undo"
title="Undo (Ctrl+Z)"
></button>
<button
type="button"
className="note-tool"
onMouseDown={e => { e.preventDefault(); editor.chain().focus().redo().run() }}
disabled={!editor.can().redo()}
aria-label="Redo"
title="Redo (Ctrl+Y)"
></button>
</div>
<EditorContent editor={editor} className="note-card-editor" />
</div>
)
}