canvas/dist/nodes/index.mjs.map
2026-03-11 18:42:08 -07:00

1 line
No EOL
9.3 KiB
Text

{"version":3,"sources":["../../src/nodes/NoteNode/NoteNode.tsx","../../src/utils/debug.ts"],"sourcesContent":["/**\n * NoteNode Component\n *\n * A rich text note editor node using BlockNote.\n * Storage-agnostic - accepts a storage adapter for any backend.\n */\n\n'use client';\n\nimport React, { useEffect, useRef } from 'react';\nimport { useCreateBlockNote, useEditorChange } from '@blocknote/react';\nimport { BlockNoteView } from '@blocknote/shadcn';\nimport { en } from '@blocknote/core/locales';\nimport { createDebug } from '../../utils/debug';\nconst debug = createDebug('note-node');\n\n// CSS imports - consumers must ensure these are available\nimport '@blocknote/core/fonts/inter.css';\nimport '@blocknote/shadcn/style.css';\n\n/**\n * NoteNode - A rich text editor node for canvas.\n *\n * Uses BlockNote for the editor and accepts a storage adapter\n * for persistence. This allows it to work with any backend:\n * Jazz, Supabase, local state, etc.\n *\n * @example\n * ```tsx\n * // With Jazz storage\n * <NoteNode\n * nodeData={nodeData}\n * storage={useJazzNoteStorage(nodeData.id)}\n * />\n *\n * // With local state\n * const [content, setContent] = useState('');\n * <NoteNode\n * nodeData={nodeData}\n * storage={{ content, onChange: setContent }}\n * />\n * ```\n */\nimport { jsx as _jsx } from \"react/jsx-runtime\";\nexport function NoteNode({\n nodeData,\n storage,\n theme = 'light',\n placeholder = 'Start typing...',\n isResizing\n}) {\n // Refs to prevent sync loops between editor and storage\n const isSyncingFromStorage = useRef(false);\n const isSyncingToStorage = useRef(false);\n const lastStorageContent = useRef('');\n\n // Create BlockNote editor\n const editor = useCreateBlockNote({\n initialContent: [{\n id: crypto.randomUUID(),\n type: 'paragraph',\n content: ''\n }],\n dictionary: {\n ...en,\n placeholders: {\n ...en.placeholders,\n emptyDocument: placeholder,\n default: placeholder,\n heading: 'Enter a heading'\n }\n }\n }, []);\n\n // Sync editor changes → storage\n useEditorChange(() => {\n if (isSyncingFromStorage.current) {\n return;\n }\n try {\n isSyncingToStorage.current = true;\n const html = editor.blocksToFullHTML(editor.document);\n if (html !== lastStorageContent.current) {\n lastStorageContent.current = html;\n storage.onChange(html);\n }\n } catch (err) {\n debug.error('Failed to sync to storage: %O', err);\n } finally {\n isSyncingToStorage.current = false;\n }\n }, editor);\n\n // Sync storage changes → editor (for real-time sync)\n useEffect(() => {\n if (!editor) return;\n const handleStorageChange = newContent => {\n if (isSyncingToStorage.current) {\n return;\n }\n\n // Throttle to next microtask to avoid invalid intermediate states\n queueMicrotask(() => {\n if (newContent === lastStorageContent.current) return;\n lastStorageContent.current = newContent;\n if (newContent && newContent.trim()) {\n try {\n isSyncingFromStorage.current = true;\n const blocks = editor.tryParseHTMLToBlocks(newContent);\n editor.replaceBlocks(editor.document, blocks);\n } catch (err_0) {\n debug.error('Failed to parse HTML from storage: %O', err_0);\n } finally {\n isSyncingFromStorage.current = false;\n }\n }\n });\n };\n\n // Subscribe to external changes if available\n const unsubscribe = storage.subscribe?.(handleStorageChange);\n\n // Initial sync from storage\n if (storage.content && storage.content !== lastStorageContent.current) {\n handleStorageChange(storage.content);\n }\n return () => {\n unsubscribe?.();\n };\n }, [editor, storage]);\n\n // Show loading state if storage is loading\n if (storage.isLoading) {\n return /*#__PURE__*/_jsx(\"div\", {\n className: \"note-node note-node--loading\",\n style: styles.loading,\n children: \"Loading...\"\n });\n }\n return /*#__PURE__*/_jsx(\"div\", {\n className: \"note-node\",\n style: styles.container,\n \"data-no-drag\": \"true\",\n onClick: e => {\n e.stopPropagation();\n },\n children: /*#__PURE__*/_jsx(BlockNoteView, {\n editor: editor,\n theme: theme\n })\n });\n}\nconst styles = {\n container: {\n height: '100%',\n width: '100%',\n overflow: 'auto',\n touchAction: 'auto'\n },\n loading: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n height: '100%',\n color: '#666'\n }\n};\nexport default NoteNode;","/**\n * Debug utility for @blinksgg/canvas\n *\n * Uses the `debug` package with `canvas:*` namespaces.\n * Enable in browser: `localStorage.debug = 'canvas:*'`\n * Enable in Node: `DEBUG=canvas:* node ...`\n *\n * Log levels:\n * debug('message') — verbose trace (blue)\n * debug.warn('message') — warnings (yellow, always stderr)\n * debug.error('message') — errors (red, always stderr)\n */\n\nimport debugFactory from 'debug';\nconst NAMESPACE = 'canvas';\n/**\n * Create a debug logger for a specific module.\n *\n * @example\n * ```ts\n * const debug = createDebug('graph');\n * debug('loaded %d nodes', count); // canvas:graph\n * debug.warn('node %s not found', id); // canvas:graph:warn\n * debug.error('sync failed: %O', err); // canvas:graph:error\n * ```\n */\nexport function createDebug(module) {\n const base = debugFactory(`${NAMESPACE}:${module}`);\n const warn = debugFactory(`${NAMESPACE}:${module}:warn`);\n const error = debugFactory(`${NAMESPACE}:${module}:error`);\n\n // Warnings and errors always log (even without DEBUG=canvas:*)\n warn.enabled = true;\n error.enabled = true;\n\n // Color hints: warn = yellow, error = red\n warn.log = console.warn.bind(console);\n error.log = console.error.bind(console);\n\n // Build the debugger with warn/error sub-loggers\n const debugFn = Object.assign(base, {\n warn,\n error\n });\n return debugFn;\n}\n\n// Pre-configured debug loggers\nexport const debug = {\n graph: {\n node: createDebug('graph:node'),\n edge: createDebug('graph:edge'),\n sync: createDebug('graph:sync')\n },\n ui: {\n selection: createDebug('ui:selection'),\n drag: createDebug('ui:drag'),\n resize: createDebug('ui:resize')\n },\n sync: {\n status: createDebug('sync:status'),\n mutations: createDebug('sync:mutations'),\n queue: createDebug('sync:queue')\n },\n viewport: createDebug('viewport')\n};"],"mappings":"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","names":["debug"]}