dishui 0.0.64 → 0.0.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Badge/index.js +12 -9
- package/dist/components/Badge/index.js.map +1 -1
- package/dist/components/Button/index.js +43 -40
- package/dist/components/Button/index.js.map +1 -1
- package/dist/components/Card/index.d.ts +11 -0
- package/dist/components/Card/index.js +62 -37
- package/dist/components/Card/index.js.map +1 -1
- package/dist/components/Chart/Chart.js.map +1 -1
- package/dist/components/Checkbox/index.js +32 -30
- package/dist/components/Checkbox/index.js.map +1 -1
- package/dist/components/Demo/index.js.map +1 -1
- package/dist/components/EmptyState/index.d.ts +4 -1
- package/dist/components/EmptyState/index.js +3 -3
- package/dist/components/EmptyState/index.js.map +1 -1
- package/dist/components/FileUploader/DropZone.js.map +1 -1
- package/dist/components/FileUploader/FileItem.js.map +1 -1
- package/dist/components/FileUploader/FileUploader.js.map +1 -1
- package/dist/components/FileUploader/UploadQueue.js.map +1 -1
- package/dist/components/Input/index.js +30 -30
- package/dist/components/Input/index.js.map +1 -1
- package/dist/components/Label/index.js +41 -40
- package/dist/components/Label/index.js.map +1 -1
- package/dist/components/List/index.js +47 -32
- package/dist/components/List/index.js.map +1 -1
- package/dist/components/Markdown/Markdown.js +61 -57
- package/dist/components/Markdown/Markdown.js.map +1 -1
- package/dist/components/Markdown/markdownComponents.js +49 -49
- package/dist/components/Markdown/markdownComponents.js.map +1 -1
- package/dist/components/Modal/index.d.ts +7 -3
- package/dist/components/Modal/index.js +77 -65
- package/dist/components/Modal/index.js.map +1 -1
- package/dist/components/Page/index.d.ts +58 -0
- package/dist/components/Page/index.js +74 -0
- package/dist/components/Page/index.js.map +1 -0
- package/dist/components/PageHeader/index.js.map +1 -1
- package/dist/components/Select/index.js +0 -3
- package/dist/components/Select/index.js.map +1 -1
- package/dist/components/SidebarToggleButton/index.js.map +1 -1
- package/dist/components/StatCard/index.d.ts +3 -1
- package/dist/components/StatCard/index.js +39 -11
- package/dist/components/StatCard/index.js.map +1 -1
- package/dist/components/Table/index.js +103 -85
- package/dist/components/Table/index.js.map +1 -1
- package/dist/components/Tabs/index.d.ts +19 -5
- package/dist/components/Tabs/index.js +32 -13
- package/dist/components/Tabs/index.js.map +1 -1
- package/dist/components/Tree/Tree.js.map +1 -1
- package/dist/components/pro/ArticleContextMenu/index.js.map +1 -1
- package/dist/components/pro/ArticleControl/ArticleControl2.js.map +1 -1
- package/dist/components/pro/CodeEditor/editors/CodeEditor.js +141 -134
- package/dist/components/pro/CodeEditor/editors/CodeEditor.js.map +1 -1
- package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js +81 -78
- package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/FootnotePanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/HistoryPanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/OutlinePanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/TableOfContentsPanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/panels/VariablePanel.js.map +1 -1
- package/dist/components/pro/CodeEditor/themes.js +59 -59
- package/dist/components/pro/CodeEditor/themes.js.map +1 -1
- package/dist/components/pro/DataTable/DataTable.js +49 -48
- package/dist/components/pro/DataTable/DataTable.js.map +1 -1
- package/dist/components/pro/DataTable/Filters.js +42 -42
- package/dist/components/pro/DataTable/Filters.js.map +1 -1
- package/dist/components/pro/DataTable/PivotPanel.js.map +1 -1
- package/dist/components/pro/DataTable/PivotView.js +35 -32
- package/dist/components/pro/DataTable/PivotView.js.map +1 -1
- package/dist/components/pro/DataTable/components/BulkActions.js.map +1 -1
- package/dist/components/pro/DataTable/components/ColumnSelector.js.map +1 -1
- package/dist/components/pro/DataTable/components/FilterBar.js.map +1 -1
- package/dist/components/pro/DataTable/components/TableBody.js.map +1 -1
- package/dist/components/pro/DataTable/components/TableHeader.js.map +1 -1
- package/dist/components/pro/DataTable/components/TablePagination.js.map +1 -1
- package/dist/components/pro/DataTable/components/TableToolbar.js.map +1 -1
- package/dist/components/pro/DataTable/pivotExtension.js.map +1 -1
- package/dist/components/pro/DataTable/rowDetailExtension.js.map +1 -1
- package/dist/components/pro/DataTable/tanstack-table.js +37 -37
- package/dist/components/pro/DataTable/tanstack-table.js.map +1 -1
- package/dist/components/pro/FileExplorer/Breadcrumb.js +53 -53
- package/dist/components/pro/FileExplorer/Breadcrumb.js.map +1 -1
- package/dist/components/pro/FileExplorer/CreateDialog.js.map +1 -1
- package/dist/components/pro/FileExplorer/FileExplorer.js.map +1 -1
- package/dist/components/pro/FileExplorer/FileIcon.js +22 -22
- package/dist/components/pro/FileExplorer/FileIcon.js.map +1 -1
- package/dist/components/pro/FileExplorer/GridView.js.map +1 -1
- package/dist/components/pro/FileExplorer/ListView.js.map +1 -1
- package/dist/components/pro/FileExplorer/Toolbar.js.map +1 -1
- package/dist/components/pro/Flow/Flow.js +496 -494
- package/dist/components/pro/Flow/Flow.js.map +1 -1
- package/dist/components/pro/Flow/FlowCanvas.js +916 -917
- package/dist/components/pro/Flow/FlowCanvas.js.map +1 -1
- package/dist/components/pro/Flow/context/FlowUIContext.js.map +1 -1
- package/dist/components/pro/Flow/edges/EdgeRenderer.js +59 -59
- package/dist/components/pro/Flow/edges/EdgeRenderer.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useClipboard.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useDeleteSelection.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useEdgeMutations.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useLayoutActions.js +9 -11
- package/dist/components/pro/Flow/hooks/useLayoutActions.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useLineMutations.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useMindMap.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useNodeMutations.js.map +1 -1
- package/dist/components/pro/Flow/lines/FreehandTool.js +9 -9
- package/dist/components/pro/Flow/lines/FreehandTool.js.map +1 -1
- package/dist/components/pro/Flow/lines/LineRenderer.js +5 -5
- package/dist/components/pro/Flow/lines/LineRenderer.js.map +1 -1
- package/dist/components/pro/Flow/nodes/DataNodeView.js +113 -93
- package/dist/components/pro/Flow/nodes/DataNodeView.js.map +1 -1
- package/dist/components/pro/Flow/nodes/MediaContent.js.map +1 -1
- package/dist/components/pro/Flow/nodes/MediaOverlay.js.map +1 -1
- package/dist/components/pro/Flow/nodes/Model3DView.js +1 -1
- package/dist/components/pro/Flow/nodes/Model3DView.js.map +1 -1
- package/dist/components/pro/Flow/nodes/NodeRenderer.js +118 -118
- package/dist/components/pro/Flow/nodes/NodeRenderer.js.map +1 -1
- package/dist/components/pro/Flow/nodes/dataUtils.js.map +1 -1
- package/dist/components/pro/Flow/nodes/shapes.js +1 -3
- package/dist/components/pro/Flow/nodes/shapes.js.map +1 -1
- package/dist/components/pro/Flow/panels/AIPanel.js.map +1 -1
- package/dist/components/pro/Flow/panels/Breadcrumb.js.map +1 -1
- package/dist/components/pro/Flow/panels/ContextMenu.js.map +1 -1
- package/dist/components/pro/Flow/panels/DataInspectorSection.js.map +1 -1
- package/dist/components/pro/Flow/panels/ExpandableTextarea.js.map +1 -1
- package/dist/components/pro/Flow/panels/FlowPanelGroup.js.map +1 -1
- package/dist/components/pro/Flow/panels/FlowToolbar.js +97 -97
- package/dist/components/pro/Flow/panels/FlowToolbar.js.map +1 -1
- package/dist/components/pro/Flow/panels/InspectorPanel.js +57 -57
- package/dist/components/pro/Flow/panels/InspectorPanel.js.map +1 -1
- package/dist/components/pro/Flow/panels/OutlinePanel.js +26 -22
- package/dist/components/pro/Flow/panels/OutlinePanel.js.map +1 -1
- package/dist/components/pro/Flow/panels/PresentationMode.js +18 -16
- package/dist/components/pro/Flow/panels/PresentationMode.js.map +1 -1
- package/dist/components/pro/Flow/panels/ProjectTitle.js.map +1 -1
- package/dist/components/pro/Flow/panels/ShapePalette.js +109 -104
- package/dist/components/pro/Flow/panels/ShapePalette.js.map +1 -1
- package/dist/components/pro/Flow/panels/toolbarIcons.js.map +1 -1
- package/dist/components/pro/RichTextEditor/AIRewrite.js.map +1 -1
- package/dist/components/pro/RichTextEditor/BlockHandle.js.map +1 -1
- package/dist/components/pro/RichTextEditor/BubbleToolbar.js.map +1 -1
- package/dist/components/pro/RichTextEditor/CommentDialog.js.map +1 -1
- package/dist/components/pro/RichTextEditor/CommentPanel.js.map +1 -1
- package/dist/components/pro/RichTextEditor/CommentPopover.js.map +1 -1
- package/dist/components/pro/RichTextEditor/ContextMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/RichTextEditor.js.map +1 -1
- package/dist/components/pro/RichTextEditor/SlashMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/SelectDropdown.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/TableOpsMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/FloatingDialog.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js.map +1 -1
- package/dist/contexts/AppContext.js.map +1 -1
- package/dist/dishui.css +1 -1
- package/dist/hooks/useTableColumns.js +7 -8
- package/dist/hooks/useTableColumns.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +227 -221
- package/dist/layouts/MainLayout.js +22 -22
- package/dist/layouts/MainLayout.js.map +1 -1
- package/dist/layouts/Navbar.js.map +1 -1
- package/dist/layouts/Sidebar.js +94 -73
- package/dist/layouts/Sidebar.js.map +1 -1
- package/dist/layouts/headbar/Headbar.js.map +1 -1
- package/dist/layouts/headbar/HeadbarLangSwitcher.js.map +1 -1
- package/dist/layouts/headbar/HeadbarSearch.js.map +1 -1
- package/dist/layouts/headbar/HeadbarThemeSwitcher.js +11 -11
- package/dist/layouts/headbar/HeadbarThemeSwitcher.js.map +1 -1
- package/dist/layouts/headbar/HeadbarTitle.js.map +1 -1
- package/dist/utils/i18n.js +10 -10
- package/dist/utils/i18n.js.map +1 -1
- package/dist/utils/menu.js.map +1 -1
- package/dist/utils/routerBuilder.js +17 -15
- package/dist/utils/routerBuilder.js.map +1 -1
- package/dist/utils/themes.js.map +1 -1
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContextMenu.js","names":[],"sources":["../../../../src/components/pro/RichTextEditor/ContextMenu.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback } from 'react';\nimport type { Editor } from '@tiptap/react';\nimport type { RichTextEditorLabels } from './types';\nimport { defaultLabels } from './types';\nimport { getNextFloatZIndex } from './extensions/FloatingDialog';\n\ninterface ContextMenuProps {\n editor: Editor;\n labels?: RichTextEditorLabels;\n onAIClick?: () => void;\n}\n\ninterface MenuItem {\n label: string;\n icon?: string;\n action: () => void;\n disabled?: boolean;\n divider?: boolean;\n shortcut?: string;\n}\n\nconst ContextMenu: React.FC<ContextMenuProps> = ({ editor, labels: propsLabels, onAIClick }) => {\n const labels = { ...defaultLabels, ...propsLabels };\n const [visible, setVisible] = useState(false);\n const [pos, setPos] = useState({ x: 0, y: 0 });\n const menuRef = useRef<HTMLDivElement>(null);\n\n const close = useCallback(() => setVisible(false), []);\n\n useEffect(() => {\n const editorEl = editor.view.dom;\n\n const handleContextMenu = (e: Event) => {\n const me = e as MouseEvent;\n me.preventDefault();\n\n const wrapperEl = editorEl.closest('.rte-editor-wrapper');\n if (!wrapperEl) return;\n const rect = wrapperEl.getBoundingClientRect();\n\n setPos({\n x: me.clientX - rect.left,\n y: me.clientY - rect.top,\n });\n setVisible(true);\n };\n\n editorEl.addEventListener('contextmenu', handleContextMenu);\n document.addEventListener('mousedown', (e) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) {\n close();\n }\n });\n document.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') close();\n });\n\n return () => {\n editorEl.removeEventListener('contextmenu', handleContextMenu);\n };\n }, [editor, close]);\n\n useEffect(() => {\n if (!visible || !menuRef.current) return;\n const menu = menuRef.current;\n const wrapper = menu.parentElement;\n if (!wrapper) return;\n\n const wRect = wrapper.getBoundingClientRect();\n const mRect = menu.getBoundingClientRect();\n\n let { x, y } = pos;\n if (x + mRect.width > wRect.width) x = Math.max(0, wRect.width - mRect.width - 4);\n if (y + mRect.height > wRect.height) y = Math.max(0, y - mRect.height);\n if (x !== pos.x || y !== pos.y) setPos({ x, y });\n }, [visible]);\n\n if (!visible) return null;\n\n const hasSelection = editor.state.selection.from !== editor.state.selection.to;\n const isInTable = editor.isActive('table');\n\n const items: (MenuItem | 'divider')[] = [\n { label: 'Cut', shortcut: '⌘X', action: () => { document.execCommand('cut'); close(); }, disabled: !hasSelection },\n { label: 'Copy', shortcut: '⌘C', action: () => { document.execCommand('copy'); close(); }, disabled: !hasSelection },\n { label: 'Paste', shortcut: '⌘V', action: () => { document.execCommand('paste'); close(); } },\n { label: 'Select All', shortcut: '⌘A', action: () => { editor.chain().focus().selectAll().run(); close(); } },\n 'divider',\n { label: labels.bold || 'Bold', shortcut: '⌘B', action: () => { editor.chain().focus().toggleBold().run(); close(); } },\n { label: labels.italic || 'Italic', shortcut: '⌘I', action: () => { editor.chain().focus().toggleItalic().run(); close(); } },\n { label: labels.underline || 'Underline', shortcut: '⌘U', action: () => { editor.chain().focus().toggleUnderline().run(); close(); } },\n { label: labels.strikethrough || 'Strikethrough', action: () => { editor.chain().focus().toggleStrike().run(); close(); } },\n 'divider',\n { label: labels.link || 'Insert Link', action: () => {\n const url = window.prompt(labels.insertLinkUrl || 'Enter URL');\n if (url) editor.chain().focus().setLink({ href: url }).run();\n close();\n }},\n { label: labels.image || 'Insert Image', action: () => {\n const url = window.prompt(labels.insertImageUrl || 'Enter image URL');\n if (url) editor.chain().focus().setImage({ src: url }).run();\n close();\n }},\n { label: labels.codeBlock || 'Code Block', action: () => { editor.chain().focus().toggleNode('codeBlock', 'paragraph').run(); close(); } },\n { label: labels.blockquote || 'Blockquote', action: () => { editor.chain().focus().toggleBlockquote().run(); close(); } },\n { label: labels.horizontalRule || 'Horizontal Rule', action: () => { editor.chain().focus().setHorizontalRule().run(); close(); } },\n { label: `${labels.floatingDialog || 'Floating Dialog'} — ${labels.layoutBlock || 'Block'}`, action: () => {\n editor.chain().focus().insertContent({ type: 'floatingDialog', attrs: { title: 'Note', layout: 'block' }, content: [{ type: 'paragraph' }] }).run();\n close();\n }},\n { label: `${labels.floatingDialog || 'Floating Dialog'} — ${labels.layoutWrapLeft || 'Wrap Left'}`, action: () => {\n editor.chain().focus().insertContent({ type: 'floatingDialog', attrs: { title: 'Note', layout: 'wrap-left', width: 240 }, content: [{ type: 'paragraph' }] }).run();\n close();\n }},\n { label: `${labels.floatingDialog || 'Floating Dialog'} — ${labels.layoutWrapRight || 'Wrap Right'}`, action: () => {\n editor.chain().focus().insertContent({ type: 'floatingDialog', attrs: { title: 'Note', layout: 'wrap-right', width: 240 }, content: [{ type: 'paragraph' }] }).run();\n close();\n }},\n { label: `${labels.floatingDialog || 'Floating Dialog'} — ${labels.layoutFloat || 'Float'}`, action: () => {\n editor.chain().focus().insertContent({ type: 'floatingDialog', attrs: { title: 'Note', layout: 'float', x: 40, y: 40, zIndex: getNextFloatZIndex(editor) }, content: [{ type: 'paragraph' }] }).run();\n close();\n }},\n ];\n\n if (isInTable) {\n items.push('divider');\n items.push({ label: labels.tableAddRowAfter || 'Add Row After', action: () => { editor.chain().focus().addRowAfter().run(); close(); } });\n items.push({ label: labels.tableAddColumnAfter || 'Add Column After', action: () => { editor.chain().focus().addColumnAfter().run(); close(); } });\n items.push({ label: labels.tableDeleteRow || 'Delete Row', action: () => { editor.chain().focus().deleteRow().run(); close(); } });\n items.push({ label: labels.tableDeleteColumn || 'Delete Column', action: () => { editor.chain().focus().deleteColumn().run(); close(); } });\n items.push({ label: labels.tableMergeCells || 'Merge Cells', action: () => { editor.chain().focus().mergeCells().run(); close(); } });\n items.push({ label: labels.tableSplitCell || 'Split Cell', action: () => { editor.chain().focus().splitCell().run(); close(); } });\n }\n\n if (onAIClick) {\n items.push('divider');\n items.push({ label: `✨ ${labels.ai || 'AI Assistant'}`, action: () => { onAIClick(); close(); }, disabled: !hasSelection });\n }\n\n return (\n <div\n ref={menuRef}\n className=\"rte-context-menu\"\n style={{ left: pos.x, top: pos.y }}\n >\n {items.map((item, i) =>\n item === 'divider' ? (\n <div key={`d-${i}`} className=\"rte-context-menu__divider\" />\n ) : (\n <button\n key={i}\n type=\"button\"\n className=\"rte-context-menu__item\"\n onClick={item.action}\n disabled={item.disabled}\n >\n <span className=\"rte-context-menu__label\">{item.label}</span>\n {item.shortcut && <span className=\"rte-context-menu__shortcut\">{item.shortcut}</span>}\n </button>\n )\n )}\n </div>\n );\n};\n\nexport default ContextMenu;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ContextMenu.js","names":[],"sources":["../../../../src/components/pro/RichTextEditor/ContextMenu.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback } from 'react';\nimport type { Editor } from '@tiptap/react';\nimport type { RichTextEditorLabels } from './types';\nimport { defaultLabels } from './types';\nimport { getNextFloatZIndex } from './extensions/FloatingDialog';\n\ninterface ContextMenuProps {\n editor: Editor;\n labels?: RichTextEditorLabels;\n onAIClick?: () => void;\n}\n\ninterface MenuItem {\n label: string;\n icon?: string;\n action: () => void;\n disabled?: boolean;\n divider?: boolean;\n shortcut?: string;\n}\n\nconst ContextMenu: React.FC<ContextMenuProps> = ({ editor, labels: propsLabels, onAIClick }) => {\n const labels = { ...defaultLabels, ...propsLabels };\n const [visible, setVisible] = useState(false);\n const [pos, setPos] = useState({ x: 0, y: 0 });\n const menuRef = useRef<HTMLDivElement>(null);\n\n const close = useCallback(() => setVisible(false), []);\n\n useEffect(() => {\n const editorEl = editor.view.dom;\n\n const handleContextMenu = (e: Event) => {\n const me = e as MouseEvent;\n me.preventDefault();\n\n const wrapperEl = editorEl.closest('.rte-editor-wrapper');\n if (!wrapperEl) return;\n const rect = wrapperEl.getBoundingClientRect();\n\n setPos({\n x: me.clientX - rect.left,\n y: me.clientY - rect.top,\n });\n setVisible(true);\n };\n\n editorEl.addEventListener('contextmenu', handleContextMenu);\n document.addEventListener('mousedown', (e) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) {\n close();\n }\n });\n document.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') close();\n });\n\n return () => {\n editorEl.removeEventListener('contextmenu', handleContextMenu);\n };\n }, [editor, close]);\n\n useEffect(() => {\n if (!visible || !menuRef.current) return;\n const menu = menuRef.current;\n const wrapper = menu.parentElement;\n if (!wrapper) return;\n\n const wRect = wrapper.getBoundingClientRect();\n const mRect = menu.getBoundingClientRect();\n\n let { x, y } = pos;\n if (x + mRect.width > wRect.width) x = Math.max(0, wRect.width - mRect.width - 4);\n if (y + mRect.height > wRect.height) y = Math.max(0, y - mRect.height);\n if (x !== pos.x || y !== pos.y) setPos({ x, y });\n }, [visible]);\n\n if (!visible) return null;\n\n const hasSelection = editor.state.selection.from !== editor.state.selection.to;\n const isInTable = editor.isActive('table');\n\n const items: (MenuItem | 'divider')[] = [\n { label: 'Cut', shortcut: '⌘X', action: () => { document.execCommand('cut'); close(); }, disabled: !hasSelection },\n { label: 'Copy', shortcut: '⌘C', action: () => { document.execCommand('copy'); close(); }, disabled: !hasSelection },\n { label: 'Paste', shortcut: '⌘V', action: () => { document.execCommand('paste'); close(); } },\n { label: 'Select All', shortcut: '⌘A', action: () => { editor.chain().focus().selectAll().run(); close(); } },\n 'divider',\n { label: labels.bold || 'Bold', shortcut: '⌘B', action: () => { editor.chain().focus().toggleBold().run(); close(); } },\n { label: labels.italic || 'Italic', shortcut: '⌘I', action: () => { editor.chain().focus().toggleItalic().run(); close(); } },\n { label: labels.underline || 'Underline', shortcut: '⌘U', action: () => { editor.chain().focus().toggleUnderline().run(); close(); } },\n { label: labels.strikethrough || 'Strikethrough', action: () => { editor.chain().focus().toggleStrike().run(); close(); } },\n 'divider',\n { label: labels.link || 'Insert Link', action: () => {\n const url = window.prompt(labels.insertLinkUrl || 'Enter URL');\n if (url) editor.chain().focus().setLink({ href: url }).run();\n close();\n }},\n { label: labels.image || 'Insert Image', action: () => {\n const url = window.prompt(labels.insertImageUrl || 'Enter image URL');\n if (url) editor.chain().focus().setImage({ src: url }).run();\n close();\n }},\n { label: labels.codeBlock || 'Code Block', action: () => { editor.chain().focus().toggleNode('codeBlock', 'paragraph').run(); close(); } },\n { label: labels.blockquote || 'Blockquote', action: () => { editor.chain().focus().toggleBlockquote().run(); close(); } },\n { label: labels.horizontalRule || 'Horizontal Rule', action: () => { editor.chain().focus().setHorizontalRule().run(); close(); } },\n { label: `${labels.floatingDialog || 'Floating Dialog'} — ${labels.layoutBlock || 'Block'}`, action: () => {\n editor.chain().focus().insertContent({ type: 'floatingDialog', attrs: { title: 'Note', layout: 'block' }, content: [{ type: 'paragraph' }] }).run();\n close();\n }},\n { label: `${labels.floatingDialog || 'Floating Dialog'} — ${labels.layoutWrapLeft || 'Wrap Left'}`, action: () => {\n editor.chain().focus().insertContent({ type: 'floatingDialog', attrs: { title: 'Note', layout: 'wrap-left', width: 240 }, content: [{ type: 'paragraph' }] }).run();\n close();\n }},\n { label: `${labels.floatingDialog || 'Floating Dialog'} — ${labels.layoutWrapRight || 'Wrap Right'}`, action: () => {\n editor.chain().focus().insertContent({ type: 'floatingDialog', attrs: { title: 'Note', layout: 'wrap-right', width: 240 }, content: [{ type: 'paragraph' }] }).run();\n close();\n }},\n { label: `${labels.floatingDialog || 'Floating Dialog'} — ${labels.layoutFloat || 'Float'}`, action: () => {\n editor.chain().focus().insertContent({ type: 'floatingDialog', attrs: { title: 'Note', layout: 'float', x: 40, y: 40, zIndex: getNextFloatZIndex(editor) }, content: [{ type: 'paragraph' }] }).run();\n close();\n }},\n ];\n\n if (isInTable) {\n items.push('divider');\n items.push({ label: labels.tableAddRowAfter || 'Add Row After', action: () => { editor.chain().focus().addRowAfter().run(); close(); } });\n items.push({ label: labels.tableAddColumnAfter || 'Add Column After', action: () => { editor.chain().focus().addColumnAfter().run(); close(); } });\n items.push({ label: labels.tableDeleteRow || 'Delete Row', action: () => { editor.chain().focus().deleteRow().run(); close(); } });\n items.push({ label: labels.tableDeleteColumn || 'Delete Column', action: () => { editor.chain().focus().deleteColumn().run(); close(); } });\n items.push({ label: labels.tableMergeCells || 'Merge Cells', action: () => { editor.chain().focus().mergeCells().run(); close(); } });\n items.push({ label: labels.tableSplitCell || 'Split Cell', action: () => { editor.chain().focus().splitCell().run(); close(); } });\n }\n\n if (onAIClick) {\n items.push('divider');\n items.push({ label: `✨ ${labels.ai || 'AI Assistant'}`, action: () => { onAIClick(); close(); }, disabled: !hasSelection });\n }\n\n return (\n <div\n ref={menuRef}\n className=\"rte-context-menu\"\n style={{ left: pos.x, top: pos.y }}\n >\n {items.map((item, i) =>\n item === 'divider' ? (\n <div key={`d-${i}`} className=\"rte-context-menu__divider\" />\n ) : (\n <button\n key={i}\n type=\"button\"\n className=\"rte-context-menu__item\"\n onClick={item.action}\n disabled={item.disabled}\n >\n <span className=\"rte-context-menu__label\">{item.label}</span>\n {item.shortcut && <span className=\"rte-context-menu__shortcut\">{item.shortcut}</span>}\n </button>\n )\n )}\n </div>\n );\n};\n\nexport default ContextMenu;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RichTextEditor.js","names":[],"sources":["../../../../src/components/pro/RichTextEditor/RichTextEditor.tsx"],"sourcesContent":["import React, { useEffect, useCallback, useState, useRef } from 'react';\nimport { useEditor, EditorContent } from '@tiptap/react';\nimport StarterKit from '@tiptap/starter-kit';\nimport Underline from '@tiptap/extension-underline';\nimport { TextStyle } from '@tiptap/extension-text-style';\nimport Color from '@tiptap/extension-color';\nimport Highlight from '@tiptap/extension-highlight';\nimport TextAlign from '@tiptap/extension-text-align';\nimport Link from '@tiptap/extension-link';\nimport Image from '@tiptap/extension-image';\nimport { Table } from '@tiptap/extension-table';\nimport TableRow from '@tiptap/extension-table-row';\nimport TableCell from '@tiptap/extension-table-cell';\nimport TableHeader from '@tiptap/extension-table-header';\nimport Placeholder from '@tiptap/extension-placeholder';\nimport TaskList from '@tiptap/extension-task-list';\nimport TaskItem from '@tiptap/extension-task-item';\nimport Subscript from '@tiptap/extension-subscript';\nimport Superscript from '@tiptap/extension-superscript';\nimport Typography from '@tiptap/extension-typography';\nimport FontFamily from '@tiptap/extension-font-family';\n\nimport Toolbar from './Toolbar';\nimport AIRewrite from './AIRewrite';\nimport ContextMenu from './ContextMenu';\nimport CommentPanel from './CommentPanel';\nimport type { CommentPanelHandle } from './CommentPanel';\nimport CommentDialog from './CommentDialog';\nimport CommentPopover from './CommentPopover';\nimport SlashMenu from './SlashMenu';\nimport BubbleToolbar from './BubbleToolbar';\nimport BlockHandle from './BlockHandle';\nimport { MarkdownBlockExtension } from './extensions/MarkdownBlock';\nimport { CodeBlockExtension } from './extensions/CodeBlockView';\nimport FontSize from './extensions/FontSize';\nimport { FloatingDialogExtension } from './extensions/FloatingDialog';\nimport { CommentMark } from './extensions/CommentMark';\nimport type { CommentThread } from './extensions/CommentMark';\nimport type { RichTextEditorProps } from './types';\nimport './styles.css';\n\nfunction generateId() {\n return `c_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;\n}\n\nconst RichTextEditor: React.FC<RichTextEditorProps> = ({\n content,\n value,\n onChange,\n onChangeJSON,\n placeholder = 'Start writing...',\n editable = true,\n aiConfig,\n toolbarConfig,\n minHeight = '200px',\n maxHeight,\n className = '',\n autofocus = false,\n labels,\n editorRef,\n notionMode: initialNotionMode = false,\n showComments: initialShowComments = false,\n commentThreads: externalThreads,\n onCommentThreadsChange,\n currentUser,\n}) => {\n const [formatPainterActive, setFormatPainterActive] = useState(false);\n const [showAIPanel, setShowAIPanel] = useState(false);\n const [aiSelection, setAiSelection] = useState('');\n const [aiSelectionRange, setAiSelectionRange] = useState({ from: 0, to: 0 });\n const [notionMode, setNotionMode] = useState(initialNotionMode);\n const [showComments, setShowComments] = useState(initialShowComments);\n const [internalThreads, setInternalThreads] = useState<CommentThread[]>([]);\n const [commentDialogOpen, setCommentDialogOpen] = useState(false);\n const [commentSelectionRange, setCommentSelectionRange] = useState({ from: 0, to: 0 });\n const commentPanelRef = useRef<CommentPanelHandle>(null);\n\n const threads = externalThreads ?? internalThreads;\n const setThreads = onCommentThreadsChange ?? setInternalThreads;\n\n const editor = useEditor({\n extensions: [\n StarterKit.configure({\n codeBlock: false,\n heading: { levels: [1, 2, 3, 4, 5, 6] },\n }),\n Underline,\n TextStyle,\n Color,\n Highlight.configure({ multicolor: true }),\n TextAlign.configure({\n types: ['heading', 'paragraph'],\n }),\n Link.configure({\n openOnClick: false,\n autolink: true,\n HTMLAttributes: { class: 'rte-link' },\n }),\n Image.configure({ inline: false, allowBase64: true }),\n Table.configure({ resizable: true }),\n TableRow,\n TableCell,\n TableHeader,\n Placeholder.configure({ placeholder }),\n CodeBlockExtension,\n TaskList,\n TaskItem.configure({ nested: true }),\n Subscript,\n Superscript,\n Typography,\n FontFamily,\n FontSize,\n FloatingDialogExtension,\n MarkdownBlockExtension,\n CommentMark,\n ],\n content: value || content || '',\n editable,\n autofocus: autofocus ? 'end' : false,\n onUpdate: ({ editor: e }) => {\n onChange?.(e.getHTML());\n onChangeJSON?.(e.getJSON() as Record<string, unknown>);\n },\n });\n\n useEffect(() => {\n if (editorRef && editor) {\n editorRef.current = editor;\n }\n }, [editor, editorRef]);\n\n useEffect(() => {\n if (editor && value !== undefined) {\n const currentHTML = editor.getHTML();\n if (value !== currentHTML) {\n editor.commands.setContent(value, { emitUpdate: false });\n }\n }\n }, [editor, value]);\n\n useEffect(() => {\n if (editor) {\n editor.setEditable(editable);\n }\n }, [editor, editable]);\n\n const handleAIClick = useCallback(() => {\n if (!editor) return;\n const { from, to } = editor.state.selection;\n const text = from !== to\n ? editor.state.doc.textBetween(from, to, ' ')\n : '';\n setAiSelection(text);\n setAiSelectionRange({ from, to });\n setShowAIPanel(true);\n }, [editor]);\n\n const requestAddComment = useCallback(() => {\n if (!editor) return;\n const { from, to } = editor.state.selection;\n if (from === to) return;\n setCommentSelectionRange({ from, to });\n setCommentDialogOpen(true);\n }, [editor]);\n\n const handleCommentSubmit = useCallback((text: string) => {\n if (!editor) return;\n const id = generateId();\n const thread: CommentThread = {\n id,\n resolved: false,\n comments: [{\n id: generateId(),\n author: currentUser || 'User',\n text,\n createdAt: Date.now(),\n }],\n createdAt: Date.now(),\n };\n editor.chain()\n .focus()\n .setTextSelection(commentSelectionRange)\n .setComment(id)\n .run();\n setThreads([...threads, thread]);\n setCommentDialogOpen(false);\n }, [editor, commentSelectionRange, threads, setThreads, currentUser]);\n\n const handleScrollToThread = useCallback((id: string) => {\n commentPanelRef.current?.scrollToThread(id);\n }, []);\n\n if (!editor) return null;\n\n const minH = typeof minHeight === 'number' ? `${minHeight}px` : minHeight;\n const maxH = maxHeight ? (typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight) : undefined;\n\n const containerClass = [\n 'rte-container',\n formatPainterActive ? 'rte-container--format-painter' : '',\n notionMode ? 'rte-container--notion' : '',\n className,\n ].filter(Boolean).join(' ');\n\n const activeCommentCount = threads.filter((t) => !t.resolved).length;\n\n const modeToggle = (\n <div className=\"rte-mode-toggle\">\n <button\n type=\"button\"\n className={`rte-mode-toggle__btn ${!notionMode ? 'rte-mode-toggle__btn--active' : ''}`}\n onClick={() => setNotionMode(false)}\n title=\"Classic mode\"\n >\n Classic\n </button>\n <button\n type=\"button\"\n className={`rte-mode-toggle__btn ${notionMode ? 'rte-mode-toggle__btn--active' : ''}`}\n onClick={() => setNotionMode(true)}\n title=\"Notion-style mode\"\n >\n Notion\n </button>\n <div className=\"rte-toolbar__divider\" style={{ height: 20, margin: '0 4px' }} />\n <button\n type=\"button\"\n className={`rte-toolbar__btn rte-toolbar__comment-btn ${showComments ? 'rte-toolbar__btn--active' : ''}`}\n onClick={() => setShowComments(!showComments)}\n title=\"Toggle comments\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z\" />\n </svg>\n {activeCommentCount > 0 && <span className=\"rte-toolbar__comment-badge\" />}\n </button>\n </div>\n );\n\n return (\n <div className={containerClass} style={{ minHeight: minH, maxHeight: maxH }}>\n {editable && !notionMode && (\n <Toolbar\n editor={editor}\n config={toolbarConfig}\n labels={labels}\n hasAI={!!aiConfig}\n onAIClick={handleAIClick}\n onFormatPainterChange={setFormatPainterActive}\n >\n {modeToggle}\n </Toolbar>\n )}\n\n {editable && notionMode && (\n <div className=\"rte-notion-topbar\">\n {modeToggle}\n </div>\n )}\n\n <div style={{ display: 'flex', flex: 1, overflow: 'hidden' }}>\n <div className=\"rte-editor-wrapper\" style={{ flex: 1 }}>\n <EditorContent editor={editor} className=\"rte-editor-content\" />\n {editable && <ContextMenu editor={editor} labels={labels} onAIClick={aiConfig ? handleAIClick : undefined} />}\n {editable && <SlashMenu editor={editor} />}\n {editable && notionMode && <BubbleToolbar editor={editor} onAddComment={requestAddComment} />}\n {editable && notionMode && <BlockHandle editor={editor} />}\n <CommentPopover\n editor={editor}\n threads={threads}\n onThreadsChange={setThreads}\n showPanel={showComments}\n onOpenPanel={() => setShowComments(true)}\n onScrollToThread={handleScrollToThread}\n currentUser={currentUser}\n />\n </div>\n\n {showComments && (\n <CommentPanel\n ref={commentPanelRef}\n editor={editor}\n threads={threads}\n onThreadsChange={setThreads}\n onRequestAddComment={requestAddComment}\n currentUser={currentUser}\n />\n )}\n </div>\n\n {aiConfig && showAIPanel && (\n <AIRewrite\n editor={editor}\n aiConfig={aiConfig}\n labels={labels}\n initialSelection={aiSelection}\n selectionRange={aiSelectionRange}\n onClose={() => setShowAIPanel(false)}\n />\n )}\n\n <CommentDialog\n open={commentDialogOpen}\n onSubmit={handleCommentSubmit}\n onClose={() => setCommentDialogOpen(false)}\n />\n </div>\n );\n};\n\nexport default RichTextEditor;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RichTextEditor.js","names":[],"sources":["../../../../src/components/pro/RichTextEditor/RichTextEditor.tsx"],"sourcesContent":["import React, { useEffect, useCallback, useState, useRef } from 'react';\nimport { useEditor, EditorContent } from '@tiptap/react';\nimport StarterKit from '@tiptap/starter-kit';\nimport Underline from '@tiptap/extension-underline';\nimport { TextStyle } from '@tiptap/extension-text-style';\nimport Color from '@tiptap/extension-color';\nimport Highlight from '@tiptap/extension-highlight';\nimport TextAlign from '@tiptap/extension-text-align';\nimport Link from '@tiptap/extension-link';\nimport Image from '@tiptap/extension-image';\nimport { Table } from '@tiptap/extension-table';\nimport TableRow from '@tiptap/extension-table-row';\nimport TableCell from '@tiptap/extension-table-cell';\nimport TableHeader from '@tiptap/extension-table-header';\nimport Placeholder from '@tiptap/extension-placeholder';\nimport TaskList from '@tiptap/extension-task-list';\nimport TaskItem from '@tiptap/extension-task-item';\nimport Subscript from '@tiptap/extension-subscript';\nimport Superscript from '@tiptap/extension-superscript';\nimport Typography from '@tiptap/extension-typography';\nimport FontFamily from '@tiptap/extension-font-family';\n\nimport Toolbar from './Toolbar';\nimport AIRewrite from './AIRewrite';\nimport ContextMenu from './ContextMenu';\nimport CommentPanel from './CommentPanel';\nimport type { CommentPanelHandle } from './CommentPanel';\nimport CommentDialog from './CommentDialog';\nimport CommentPopover from './CommentPopover';\nimport SlashMenu from './SlashMenu';\nimport BubbleToolbar from './BubbleToolbar';\nimport BlockHandle from './BlockHandle';\nimport { MarkdownBlockExtension } from './extensions/MarkdownBlock';\nimport { CodeBlockExtension } from './extensions/CodeBlockView';\nimport FontSize from './extensions/FontSize';\nimport { FloatingDialogExtension } from './extensions/FloatingDialog';\nimport { CommentMark } from './extensions/CommentMark';\nimport type { CommentThread } from './extensions/CommentMark';\nimport type { RichTextEditorProps } from './types';\nimport './styles.css';\n\nfunction generateId() {\n return `c_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;\n}\n\nconst RichTextEditor: React.FC<RichTextEditorProps> = ({\n content,\n value,\n onChange,\n onChangeJSON,\n placeholder = 'Start writing...',\n editable = true,\n aiConfig,\n toolbarConfig,\n minHeight = '200px',\n maxHeight,\n className = '',\n autofocus = false,\n labels,\n editorRef,\n notionMode: initialNotionMode = false,\n showComments: initialShowComments = false,\n commentThreads: externalThreads,\n onCommentThreadsChange,\n currentUser,\n}) => {\n const [formatPainterActive, setFormatPainterActive] = useState(false);\n const [showAIPanel, setShowAIPanel] = useState(false);\n const [aiSelection, setAiSelection] = useState('');\n const [aiSelectionRange, setAiSelectionRange] = useState({ from: 0, to: 0 });\n const [notionMode, setNotionMode] = useState(initialNotionMode);\n const [showComments, setShowComments] = useState(initialShowComments);\n const [internalThreads, setInternalThreads] = useState<CommentThread[]>([]);\n const [commentDialogOpen, setCommentDialogOpen] = useState(false);\n const [commentSelectionRange, setCommentSelectionRange] = useState({ from: 0, to: 0 });\n const commentPanelRef = useRef<CommentPanelHandle>(null);\n\n const threads = externalThreads ?? internalThreads;\n const setThreads = onCommentThreadsChange ?? setInternalThreads;\n\n const editor = useEditor({\n extensions: [\n StarterKit.configure({\n codeBlock: false,\n heading: { levels: [1, 2, 3, 4, 5, 6] },\n }),\n Underline,\n TextStyle,\n Color,\n Highlight.configure({ multicolor: true }),\n TextAlign.configure({\n types: ['heading', 'paragraph'],\n }),\n Link.configure({\n openOnClick: false,\n autolink: true,\n HTMLAttributes: { class: 'rte-link' },\n }),\n Image.configure({ inline: false, allowBase64: true }),\n Table.configure({ resizable: true }),\n TableRow,\n TableCell,\n TableHeader,\n Placeholder.configure({ placeholder }),\n CodeBlockExtension,\n TaskList,\n TaskItem.configure({ nested: true }),\n Subscript,\n Superscript,\n Typography,\n FontFamily,\n FontSize,\n FloatingDialogExtension,\n MarkdownBlockExtension,\n CommentMark,\n ],\n content: value || content || '',\n editable,\n autofocus: autofocus ? 'end' : false,\n onUpdate: ({ editor: e }) => {\n onChange?.(e.getHTML());\n onChangeJSON?.(e.getJSON() as Record<string, unknown>);\n },\n });\n\n useEffect(() => {\n if (editorRef && editor) {\n editorRef.current = editor;\n }\n }, [editor, editorRef]);\n\n useEffect(() => {\n if (editor && value !== undefined) {\n const currentHTML = editor.getHTML();\n if (value !== currentHTML) {\n editor.commands.setContent(value, { emitUpdate: false });\n }\n }\n }, [editor, value]);\n\n useEffect(() => {\n if (editor) {\n editor.setEditable(editable);\n }\n }, [editor, editable]);\n\n const handleAIClick = useCallback(() => {\n if (!editor) return;\n const { from, to } = editor.state.selection;\n const text = from !== to\n ? editor.state.doc.textBetween(from, to, ' ')\n : '';\n setAiSelection(text);\n setAiSelectionRange({ from, to });\n setShowAIPanel(true);\n }, [editor]);\n\n const requestAddComment = useCallback(() => {\n if (!editor) return;\n const { from, to } = editor.state.selection;\n if (from === to) return;\n setCommentSelectionRange({ from, to });\n setCommentDialogOpen(true);\n }, [editor]);\n\n const handleCommentSubmit = useCallback((text: string) => {\n if (!editor) return;\n const id = generateId();\n const thread: CommentThread = {\n id,\n resolved: false,\n comments: [{\n id: generateId(),\n author: currentUser || 'User',\n text,\n createdAt: Date.now(),\n }],\n createdAt: Date.now(),\n };\n editor.chain()\n .focus()\n .setTextSelection(commentSelectionRange)\n .setComment(id)\n .run();\n setThreads([...threads, thread]);\n setCommentDialogOpen(false);\n }, [editor, commentSelectionRange, threads, setThreads, currentUser]);\n\n const handleScrollToThread = useCallback((id: string) => {\n commentPanelRef.current?.scrollToThread(id);\n }, []);\n\n if (!editor) return null;\n\n const minH = typeof minHeight === 'number' ? `${minHeight}px` : minHeight;\n const maxH = maxHeight ? (typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight) : undefined;\n\n const containerClass = [\n 'rte-container',\n formatPainterActive ? 'rte-container--format-painter' : '',\n notionMode ? 'rte-container--notion' : '',\n className,\n ].filter(Boolean).join(' ');\n\n const activeCommentCount = threads.filter((t) => !t.resolved).length;\n\n const modeToggle = (\n <div className=\"rte-mode-toggle\">\n <button\n type=\"button\"\n className={`rte-mode-toggle__btn ${!notionMode ? 'rte-mode-toggle__btn--active' : ''}`}\n onClick={() => setNotionMode(false)}\n title=\"Classic mode\"\n >\n Classic\n </button>\n <button\n type=\"button\"\n className={`rte-mode-toggle__btn ${notionMode ? 'rte-mode-toggle__btn--active' : ''}`}\n onClick={() => setNotionMode(true)}\n title=\"Notion-style mode\"\n >\n Notion\n </button>\n <div className=\"rte-toolbar__divider\" style={{ height: 20, margin: '0 4px' }} />\n <button\n type=\"button\"\n className={`rte-toolbar__btn rte-toolbar__comment-btn ${showComments ? 'rte-toolbar__btn--active' : ''}`}\n onClick={() => setShowComments(!showComments)}\n title=\"Toggle comments\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z\" />\n </svg>\n {activeCommentCount > 0 && <span className=\"rte-toolbar__comment-badge\" />}\n </button>\n </div>\n );\n\n return (\n <div className={containerClass} style={{ minHeight: minH, maxHeight: maxH }}>\n {editable && !notionMode && (\n <Toolbar\n editor={editor}\n config={toolbarConfig}\n labels={labels}\n hasAI={!!aiConfig}\n onAIClick={handleAIClick}\n onFormatPainterChange={setFormatPainterActive}\n >\n {modeToggle}\n </Toolbar>\n )}\n\n {editable && notionMode && (\n <div className=\"rte-notion-topbar\">\n {modeToggle}\n </div>\n )}\n\n <div style={{ display: 'flex', flex: 1, overflow: 'hidden' }}>\n <div className=\"rte-editor-wrapper\" style={{ flex: 1 }}>\n <EditorContent editor={editor} className=\"rte-editor-content\" />\n {editable && <ContextMenu editor={editor} labels={labels} onAIClick={aiConfig ? handleAIClick : undefined} />}\n {editable && <SlashMenu editor={editor} />}\n {editable && notionMode && <BubbleToolbar editor={editor} onAddComment={requestAddComment} />}\n {editable && notionMode && <BlockHandle editor={editor} />}\n <CommentPopover\n editor={editor}\n threads={threads}\n onThreadsChange={setThreads}\n showPanel={showComments}\n onOpenPanel={() => setShowComments(true)}\n onScrollToThread={handleScrollToThread}\n currentUser={currentUser}\n />\n </div>\n\n {showComments && (\n <CommentPanel\n ref={commentPanelRef}\n editor={editor}\n threads={threads}\n onThreadsChange={setThreads}\n onRequestAddComment={requestAddComment}\n currentUser={currentUser}\n />\n )}\n </div>\n\n {aiConfig && showAIPanel && (\n <AIRewrite\n editor={editor}\n aiConfig={aiConfig}\n labels={labels}\n initialSelection={aiSelection}\n selectionRange={aiSelectionRange}\n onClose={() => setShowAIPanel(false)}\n />\n )}\n\n <CommentDialog\n open={commentDialogOpen}\n onSubmit={handleCommentSubmit}\n onClose={() => setCommentDialogOpen(false)}\n />\n </div>\n );\n};\n\nexport default RichTextEditor;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SlashMenu.js","names":[],"sources":["../../../../src/components/pro/RichTextEditor/SlashMenu.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback } from 'react';\nimport type { Editor } from '@tiptap/react';\n\ninterface SlashMenuItem {\n label: string;\n icon: string;\n description: string;\n action: (editor: Editor) => void;\n keywords?: string[];\n}\n\nconst SLASH_ITEMS: SlashMenuItem[] = [\n { label: 'Text', icon: 'Aa', description: 'Plain text', keywords: ['paragraph', 'text', 'plain'],\n action: (e) => e.chain().focus().setParagraph().run() },\n { label: 'Heading 1', icon: 'H1', description: 'Large heading', keywords: ['h1', 'title'],\n action: (e) => e.chain().focus().toggleHeading({ level: 1 }).run() },\n { label: 'Heading 2', icon: 'H2', description: 'Medium heading', keywords: ['h2', 'subtitle'],\n action: (e) => e.chain().focus().toggleHeading({ level: 2 }).run() },\n { label: 'Heading 3', icon: 'H3', description: 'Small heading', keywords: ['h3'],\n action: (e) => e.chain().focus().toggleHeading({ level: 3 }).run() },\n { label: 'Bullet List', icon: '•', description: 'Unordered list', keywords: ['ul', 'bullet', 'unordered'],\n action: (e) => e.chain().focus().toggleBulletList().run() },\n { label: 'Numbered List', icon: '1.', description: 'Ordered list', keywords: ['ol', 'ordered', 'number'],\n action: (e) => e.chain().focus().toggleOrderedList().run() },\n { label: 'Task List', icon: '☑', description: 'To-do list', keywords: ['todo', 'checkbox', 'task'],\n action: (e) => e.chain().focus().toggleTaskList().run() },\n { label: 'Blockquote', icon: '\"', description: 'Quote block', keywords: ['quote', 'blockquote'],\n action: (e) => e.chain().focus().toggleBlockquote().run() },\n { label: 'Code Block', icon: '</>', description: 'Code snippet', keywords: ['code', 'pre', 'snippet'],\n action: (e) => e.chain().focus().toggleNode('codeBlock', 'paragraph').run() },\n { label: 'Divider', icon: '—', description: 'Horizontal rule', keywords: ['hr', 'divider', 'separator', 'line'],\n action: (e) => e.chain().focus().setHorizontalRule().run() },\n { label: 'Table', icon: '⊞', description: 'Insert 3×3 table', keywords: ['table', 'grid'],\n action: (e) => e.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run() },\n { label: 'Image', icon: '🖼', description: 'Insert image by URL', keywords: ['image', 'picture', 'photo'],\n action: (e) => {\n const url = window.prompt('Image URL:');\n if (url) e.chain().focus().setImage({ src: url }).run();\n }},\n];\n\ninterface SlashMenuProps {\n editor: Editor;\n}\n\nconst SlashMenu: React.FC<SlashMenuProps> = ({ editor }) => {\n const [visible, setVisible] = useState(false);\n const [query, setQuery] = useState('');\n const [pos, setPos] = useState({ x: 0, y: 0 });\n const [selected, setSelected] = useState(0);\n const [slashPos, setSlashPos] = useState<number | null>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n\n const filtered = query\n ? SLASH_ITEMS.filter((item) => {\n const q = query.toLowerCase();\n return item.label.toLowerCase().includes(q)\n || item.description.toLowerCase().includes(q)\n || item.keywords?.some((k) => k.includes(q));\n })\n : SLASH_ITEMS;\n\n const close = useCallback(() => {\n setVisible(false);\n setQuery('');\n setSlashPos(null);\n setSelected(0);\n }, []);\n\n const executeItem = useCallback((item: SlashMenuItem) => {\n if (slashPos !== null) {\n const { from } = editor.state.selection;\n editor.chain().focus().deleteRange({ from: slashPos, to: from }).run();\n }\n item.action(editor);\n close();\n }, [editor, slashPos, close]);\n\n useEffect(() => {\n const handleUpdate = () => {\n const { $from } = editor.state.selection;\n const textBefore = $from.parent.textContent.slice(0, $from.parentOffset);\n const slashMatch = /\\/([a-zA-Z0-9]*)$/.exec(textBefore);\n\n if (slashMatch) {\n const start = $from.start() + slashMatch.index;\n setSlashPos(start);\n setQuery(slashMatch[1]);\n setSelected(0);\n\n const coords = editor.view.coordsAtPos($from.pos);\n const editorRect = editor.view.dom.closest('.rte-editor-wrapper')?.getBoundingClientRect();\n if (editorRect) {\n setPos({\n x: coords.left - editorRect.left,\n y: coords.bottom - editorRect.top + 4,\n });\n }\n setVisible(true);\n } else {\n if (visible) close();\n }\n };\n\n editor.on('selectionUpdate', handleUpdate);\n editor.on('update', handleUpdate);\n return () => {\n editor.off('selectionUpdate', handleUpdate);\n editor.off('update', handleUpdate);\n };\n }, [editor, visible, close]);\n\n useEffect(() => {\n if (!visible) return;\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setSelected((s) => (s + 1) % filtered.length);\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n setSelected((s) => (s - 1 + filtered.length) % filtered.length);\n } else if (e.key === 'Enter') {\n e.preventDefault();\n if (filtered[selected]) executeItem(filtered[selected]);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n close();\n }\n };\n document.addEventListener('keydown', handleKeyDown, true);\n return () => document.removeEventListener('keydown', handleKeyDown, true);\n }, [visible, filtered, selected, executeItem, close]);\n\n useEffect(() => {\n if (!visible) return;\n const handler = (e: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) close();\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [visible, close]);\n\n if (!visible || filtered.length === 0) return null;\n\n return (\n <div ref={menuRef} className=\"rte-slash-menu\" style={{ left: pos.x, top: pos.y }}>\n {filtered.map((item, i) => (\n <button\n key={item.label}\n type=\"button\"\n className={`rte-slash-menu__item ${i === selected ? 'rte-slash-menu__item--active' : ''}`}\n onClick={() => executeItem(item)}\n onMouseEnter={() => setSelected(i)}\n >\n <span className=\"rte-slash-menu__icon\">{item.icon}</span>\n <div className=\"rte-slash-menu__text\">\n <span className=\"rte-slash-menu__label\">{item.label}</span>\n <span className=\"rte-slash-menu__desc\">{item.description}</span>\n </div>\n </button>\n ))}\n </div>\n );\n};\n\nexport default SlashMenu;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SlashMenu.js","names":[],"sources":["../../../../src/components/pro/RichTextEditor/SlashMenu.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback } from 'react';\nimport type { Editor } from '@tiptap/react';\n\ninterface SlashMenuItem {\n label: string;\n icon: string;\n description: string;\n action: (editor: Editor) => void;\n keywords?: string[];\n}\n\nconst SLASH_ITEMS: SlashMenuItem[] = [\n { label: 'Text', icon: 'Aa', description: 'Plain text', keywords: ['paragraph', 'text', 'plain'],\n action: (e) => e.chain().focus().setParagraph().run() },\n { label: 'Heading 1', icon: 'H1', description: 'Large heading', keywords: ['h1', 'title'],\n action: (e) => e.chain().focus().toggleHeading({ level: 1 }).run() },\n { label: 'Heading 2', icon: 'H2', description: 'Medium heading', keywords: ['h2', 'subtitle'],\n action: (e) => e.chain().focus().toggleHeading({ level: 2 }).run() },\n { label: 'Heading 3', icon: 'H3', description: 'Small heading', keywords: ['h3'],\n action: (e) => e.chain().focus().toggleHeading({ level: 3 }).run() },\n { label: 'Bullet List', icon: '•', description: 'Unordered list', keywords: ['ul', 'bullet', 'unordered'],\n action: (e) => e.chain().focus().toggleBulletList().run() },\n { label: 'Numbered List', icon: '1.', description: 'Ordered list', keywords: ['ol', 'ordered', 'number'],\n action: (e) => e.chain().focus().toggleOrderedList().run() },\n { label: 'Task List', icon: '☑', description: 'To-do list', keywords: ['todo', 'checkbox', 'task'],\n action: (e) => e.chain().focus().toggleTaskList().run() },\n { label: 'Blockquote', icon: '\"', description: 'Quote block', keywords: ['quote', 'blockquote'],\n action: (e) => e.chain().focus().toggleBlockquote().run() },\n { label: 'Code Block', icon: '</>', description: 'Code snippet', keywords: ['code', 'pre', 'snippet'],\n action: (e) => e.chain().focus().toggleNode('codeBlock', 'paragraph').run() },\n { label: 'Divider', icon: '—', description: 'Horizontal rule', keywords: ['hr', 'divider', 'separator', 'line'],\n action: (e) => e.chain().focus().setHorizontalRule().run() },\n { label: 'Table', icon: '⊞', description: 'Insert 3×3 table', keywords: ['table', 'grid'],\n action: (e) => e.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run() },\n { label: 'Image', icon: '🖼', description: 'Insert image by URL', keywords: ['image', 'picture', 'photo'],\n action: (e) => {\n const url = window.prompt('Image URL:');\n if (url) e.chain().focus().setImage({ src: url }).run();\n }},\n];\n\ninterface SlashMenuProps {\n editor: Editor;\n}\n\nconst SlashMenu: React.FC<SlashMenuProps> = ({ editor }) => {\n const [visible, setVisible] = useState(false);\n const [query, setQuery] = useState('');\n const [pos, setPos] = useState({ x: 0, y: 0 });\n const [selected, setSelected] = useState(0);\n const [slashPos, setSlashPos] = useState<number | null>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n\n const filtered = query\n ? SLASH_ITEMS.filter((item) => {\n const q = query.toLowerCase();\n return item.label.toLowerCase().includes(q)\n || item.description.toLowerCase().includes(q)\n || item.keywords?.some((k) => k.includes(q));\n })\n : SLASH_ITEMS;\n\n const close = useCallback(() => {\n setVisible(false);\n setQuery('');\n setSlashPos(null);\n setSelected(0);\n }, []);\n\n const executeItem = useCallback((item: SlashMenuItem) => {\n if (slashPos !== null) {\n const { from } = editor.state.selection;\n editor.chain().focus().deleteRange({ from: slashPos, to: from }).run();\n }\n item.action(editor);\n close();\n }, [editor, slashPos, close]);\n\n useEffect(() => {\n const handleUpdate = () => {\n const { $from } = editor.state.selection;\n const textBefore = $from.parent.textContent.slice(0, $from.parentOffset);\n const slashMatch = /\\/([a-zA-Z0-9]*)$/.exec(textBefore);\n\n if (slashMatch) {\n const start = $from.start() + slashMatch.index;\n setSlashPos(start);\n setQuery(slashMatch[1]);\n setSelected(0);\n\n const coords = editor.view.coordsAtPos($from.pos);\n const editorRect = editor.view.dom.closest('.rte-editor-wrapper')?.getBoundingClientRect();\n if (editorRect) {\n setPos({\n x: coords.left - editorRect.left,\n y: coords.bottom - editorRect.top + 4,\n });\n }\n setVisible(true);\n } else {\n if (visible) close();\n }\n };\n\n editor.on('selectionUpdate', handleUpdate);\n editor.on('update', handleUpdate);\n return () => {\n editor.off('selectionUpdate', handleUpdate);\n editor.off('update', handleUpdate);\n };\n }, [editor, visible, close]);\n\n useEffect(() => {\n if (!visible) return;\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setSelected((s) => (s + 1) % filtered.length);\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n setSelected((s) => (s - 1 + filtered.length) % filtered.length);\n } else if (e.key === 'Enter') {\n e.preventDefault();\n if (filtered[selected]) executeItem(filtered[selected]);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n close();\n }\n };\n document.addEventListener('keydown', handleKeyDown, true);\n return () => document.removeEventListener('keydown', handleKeyDown, true);\n }, [visible, filtered, selected, executeItem, close]);\n\n useEffect(() => {\n if (!visible) return;\n const handler = (e: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) close();\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [visible, close]);\n\n if (!visible || filtered.length === 0) return null;\n\n return (\n <div ref={menuRef} className=\"rte-slash-menu\" style={{ left: pos.x, top: pos.y }}>\n {filtered.map((item, i) => (\n <button\n key={item.label}\n type=\"button\"\n className={`rte-slash-menu__item ${i === selected ? 'rte-slash-menu__item--active' : ''}`}\n onClick={() => executeItem(item)}\n onMouseEnter={() => setSelected(i)}\n >\n <span className=\"rte-slash-menu__icon\">{item.icon}</span>\n <div className=\"rte-slash-menu__text\">\n <span className=\"rte-slash-menu__label\">{item.label}</span>\n <span className=\"rte-slash-menu__desc\">{item.description}</span>\n </div>\n </button>\n ))}\n </div>\n );\n};\n\nexport default SlashMenu;\n"],"mappings":";;AAWA,IAAM,IAA+B;AAAA,EACnC;AAAA,IAAE,OAAO;AAAA,IAAQ,MAAM;AAAA,IAAM,aAAa;AAAA,IAAc,UAAU;AAAA,MAAC;AAAA,MAAa;AAAA,MAAQ;AAAA,IAAO;AAAA,IAC7F,QAAA,CAAS,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI;AAAA,EAAE;AAAA,EACxD;AAAA,IAAE,OAAO;AAAA,IAAa,MAAM;AAAA,IAAM,aAAa;AAAA,IAAiB,UAAU,CAAC,MAAM,OAAO;AAAA,IACtF,QAAA,CAAS,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI;AAAA,EAAE;AAAA,EACrE;AAAA,IAAE,OAAO;AAAA,IAAa,MAAM;AAAA,IAAM,aAAa;AAAA,IAAkB,UAAU,CAAC,MAAM,UAAU;AAAA,IAC1F,QAAA,CAAS,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI;AAAA,EAAE;AAAA,EACrE;AAAA,IAAE,OAAO;AAAA,IAAa,MAAM;AAAA,IAAM,aAAa;AAAA,IAAiB,UAAU,CAAC,IAAI;AAAA,IAC7E,QAAA,CAAS,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI;AAAA,EAAE;AAAA,EACrE;AAAA,IAAE,OAAO;AAAA,IAAe,MAAM;AAAA,IAAK,aAAa;AAAA,IAAkB,UAAU;AAAA,MAAC;AAAA,MAAM;AAAA,MAAU;AAAA,IAAW;AAAA,IACtG,QAAA,CAAS,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,IAAI;AAAA,EAAE;AAAA,EAC5D;AAAA,IAAE,OAAO;AAAA,IAAiB,MAAM;AAAA,IAAM,aAAa;AAAA,IAAgB,UAAU;AAAA,MAAC;AAAA,MAAM;AAAA,MAAW;AAAA,IAAQ;AAAA,IACrG,QAAA,CAAS,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,EAAE,IAAI;AAAA,EAAE;AAAA,EAC7D;AAAA,IAAE,OAAO;AAAA,IAAa,MAAM;AAAA,IAAK,aAAa;AAAA,IAAc,UAAU;AAAA,MAAC;AAAA,MAAQ;AAAA,MAAY;AAAA,IAAM;AAAA,IAC/F,QAAA,CAAS,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,IAAI;AAAA,EAAE;AAAA,EAC1D;AAAA,IAAE,OAAO;AAAA,IAAc,MAAM;AAAA,IAAK,aAAa;AAAA,IAAe,UAAU,CAAC,SAAS,YAAY;AAAA,IAC5F,QAAA,CAAS,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,IAAI;AAAA,EAAE;AAAA,EAC5D;AAAA,IAAE,OAAO;AAAA,IAAc,MAAM;AAAA,IAAO,aAAa;AAAA,IAAgB,UAAU;AAAA,MAAC;AAAA,MAAQ;AAAA,MAAO;AAAA,IAAS;AAAA,IAClG,QAAA,CAAS,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,aAAa,WAAW,EAAE,IAAI;AAAA,EAAE;AAAA,EAC9E;AAAA,IAAE,OAAO;AAAA,IAAW,MAAM;AAAA,IAAK,aAAa;AAAA,IAAmB,UAAU;AAAA,MAAC;AAAA,MAAM;AAAA,MAAW;AAAA,MAAa;AAAA,IAAM;AAAA,IAC5G,QAAA,CAAS,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,EAAE,IAAI;AAAA,EAAE;AAAA,EAC7D;AAAA,IAAE,OAAO;AAAA,IAAS,MAAM;AAAA,IAAK,aAAa;AAAA,IAAoB,UAAU,CAAC,SAAS,MAAM;AAAA,IACtF,QAAA,CAAS,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY;AAAA,MAAE,MAAM;AAAA,MAAG,MAAM;AAAA,MAAG,eAAe;AAAA,IAAK,CAAC,EAAE,IAAI;AAAA,EAAE;AAAA,EAChG;AAAA,IAAE,OAAO;AAAA,IAAS,MAAM;AAAA,IAAM,aAAa;AAAA,IAAuB,UAAU;AAAA,MAAC;AAAA,MAAS;AAAA,MAAW;AAAA,IAAO;AAAA,IACtG,QAAA,CAAS,MAAM;AACb,YAAM,IAAM,OAAO,OAAO,YAAY;AACtC,MAAI,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAI,CAAC,EAAE,IAAI;AAAA,IACxD;AAAA,EAAC;AACL,GAMM,IAAA,CAAuC,EAAE,QAAA,EAAA,MAAa;AAC1D,QAAM,CAAC,GAAS,CAAA,IAAc,EAAS,EAAK,GACtC,CAAC,GAAO,CAAA,IAAY,EAAS,EAAE,GAC/B,CAAC,GAAK,CAAA,IAAU,EAAS;AAAA,IAAE,GAAG;AAAA,IAAG,GAAG;AAAA,EAAE,CAAC,GACvC,CAAC,GAAU,CAAA,IAAe,EAAS,CAAC,GACpC,CAAC,GAAU,CAAA,IAAe,EAAwB,IAAI,GACtD,IAAU,EAAuB,IAAI,GAErC,IAAW,IACb,EAAY,OAAA,CAAQ,MAAS;AAC3B,UAAM,IAAI,EAAM,YAAY;AAC5B,WAAO,EAAK,MAAM,YAAY,EAAE,SAAS,CAAC,KACrC,EAAK,YAAY,YAAY,EAAE,SAAS,CAAC,KACzC,EAAK,UAAU,KAAA,CAAM,MAAM,EAAE,SAAS,CAAC,CAAC;AAAA,EAC/C,CAAC,IACD,GAEE,IAAQ,EAAA,MAAkB;AAC9B,IAAA,EAAW,EAAK,GAChB,EAAS,EAAE,GACX,EAAY,IAAI,GAChB,EAAY,CAAC;AAAA,EACf,GAAG,CAAC,CAAC,GAEC,IAAc,EAAA,CAAa,MAAwB;AACvD,QAAI,MAAa,MAAM;AACrB,YAAM,EAAE,MAAA,EAAA,IAAS,EAAO,MAAM;AAC9B,MAAA,EAAO,MAAM,EAAE,MAAM,EAAE,YAAY;AAAA,QAAE,MAAM;AAAA,QAAU,IAAI;AAAA,MAAK,CAAC,EAAE,IAAI;AAAA,IACvE;AACA,IAAA,EAAK,OAAO,CAAM,GAClB,EAAM;AAAA,EACR,GAAG;AAAA,IAAC;AAAA,IAAQ;AAAA,IAAU;AAAA,EAAK,CAAC;AAkE5B,SAhEA,EAAA,MAAgB;AACd,UAAM,IAAA,MAAqB;AACzB,YAAM,EAAE,OAAA,EAAA,IAAU,EAAO,MAAM,WACzB,IAAa,EAAM,OAAO,YAAY,MAAM,GAAG,EAAM,YAAY,GACjE,IAAa,oBAAoB,KAAK,CAAU;AAEtD,UAAI,GAAY;AACd,cAAM,IAAQ,EAAM,MAAM,IAAI,EAAW;AACzC,QAAA,EAAY,CAAK,GACjB,EAAS,EAAW,CAAA,CAAE,GACtB,EAAY,CAAC;AAEb,cAAM,IAAS,EAAO,KAAK,YAAY,EAAM,GAAG,GAC1C,IAAa,EAAO,KAAK,IAAI,QAAQ,qBAAqB,GAAG,sBAAsB;AACzF,QAAI,KACF,EAAO;AAAA,UACL,GAAG,EAAO,OAAO,EAAW;AAAA,UAC5B,GAAG,EAAO,SAAS,EAAW,MAAM;AAAA,QACtC,CAAC,GAEH,EAAW,EAAI;AAAA,MACjB,MACE,CAAI,KAAS,EAAM;AAAA,IAEvB;AAEA,WAAA,EAAO,GAAG,mBAAmB,CAAY,GACzC,EAAO,GAAG,UAAU,CAAY,GAChC,MAAa;AACX,MAAA,EAAO,IAAI,mBAAmB,CAAY,GAC1C,EAAO,IAAI,UAAU,CAAY;AAAA,IACnC;AAAA,EACF,GAAG;AAAA,IAAC;AAAA,IAAQ;AAAA,IAAS;AAAA,EAAK,CAAC,GAE3B,EAAA,MAAgB;AACd,QAAI,CAAC,EAAS;AACd,UAAM,IAAA,CAAiB,MAAqB;AAC1C,MAAI,EAAE,QAAQ,eACZ,EAAE,eAAe,GACjB,EAAA,CAAa,OAAO,IAAI,KAAK,EAAS,MAAM,KACnC,EAAE,QAAQ,aACnB,EAAE,eAAe,GACjB,EAAA,CAAa,OAAO,IAAI,IAAI,EAAS,UAAU,EAAS,MAAM,KACrD,EAAE,QAAQ,WACnB,EAAE,eAAe,GACb,EAAS,CAAA,KAAW,EAAY,EAAS,CAAA,CAAS,KAC7C,EAAE,QAAQ,aACnB,EAAE,eAAe,GACjB,EAAM;AAAA,IAEV;AACA,oBAAS,iBAAiB,WAAW,GAAe,EAAI,GACxD,MAAa,SAAS,oBAAoB,WAAW,GAAe,EAAI;AAAA,EAC1E,GAAG;AAAA,IAAC;AAAA,IAAS;AAAA,IAAU;AAAA,IAAU;AAAA,IAAa;AAAA,EAAK,CAAC,GAEpD,EAAA,MAAgB;AACd,QAAI,CAAC,EAAS;AACd,UAAM,IAAA,CAAW,MAAkB;AACjC,MAAI,EAAQ,WAAW,CAAC,EAAQ,QAAQ,SAAS,EAAE,MAAc,KAAG,EAAM;AAAA,IAC5E;AACA,oBAAS,iBAAiB,aAAa,CAAO,GAC9C,MAAa,SAAS,oBAAoB,aAAa,CAAO;AAAA,EAChE,GAAG,CAAC,GAAS,CAAK,CAAC,GAEf,CAAC,KAAW,EAAS,WAAW,IAAU,OAG5C,gBAAA,EAAC,OAAD;AAAA,IAAK,KAAK;AAAA,IAAS,WAAU;AAAA,IAAiB,OAAO;AAAA,MAAE,MAAM,EAAI;AAAA,MAAG,KAAK,EAAI;AAAA,IAAE;AAAA,IAC5E,UAAA,EAAS,IAAA,CAAK,GAAM,MACnB,gBAAA,EAAC,UAAD;AAAA,MAEE,MAAK;AAAA,MACL,WAAW,wBAAwB,MAAM,IAAW,iCAAiC,EAAA;AAAA,MACrF,SAAA,MAAe,EAAY,CAAI;AAAA,MAC/B,cAAA,MAAoB,EAAY,CAAC;AAAA,MALnC,UAAA,CAOE,gBAAA,EAAC,QAAD;AAAA,QAAM,WAAU;AAAA,QAAwB,UAAA,EAAK;AAAA,MAAW,CAAA,GACxD,gBAAA,EAAC,OAAD;AAAA,QAAK,WAAU;AAAA,QAAf,UAAA,CACE,gBAAA,EAAC,QAAD;AAAA,UAAM,WAAU;AAAA,UAAyB,UAAA,EAAK;AAAA,QAAY,CAAA,GAC1D,gBAAA,EAAC,QAAD;AAAA,UAAM,WAAU;AAAA,UAAwB,UAAA,EAAK;AAAA,QAAkB,CAAA,CAC5D;AAAA,MACC,CAAA,CAAA;AAAA,IAXD,GAAA,EAAK,KAWJ,CACT;AAAA,EACE,CAAA;AAET"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ColorPicker.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/Toolbar/ColorPicker.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from 'react';\n\ninterface ColorPickerProps {\n value: string;\n onChange: (color: string) => void;\n title?: string;\n icon: React.ReactNode;\n}\n\nconst COLORS = [\n '#000000', '#434343', '#666666', '#999999', '#cccccc', '#eeeeee', '#ffffff',\n '#ff0000', '#ff4500', '#ff8c00', '#ffd700', '#32cd32', '#00bfff', '#8a2be2',\n '#ff69b4', '#dc143c', '#ff6347', '#ffa500', '#9acd32', '#20b2aa', '#4169e1',\n '#9370db', '#db7093', '#b22222', '#d2691e', '#daa520', '#228b22', '#008b8b',\n '#191970', '#4b0082',\n];\n\nexport const ColorPicker: React.FC<ColorPickerProps> = ({ value, onChange, title, icon }) => {\n const [isOpen, setIsOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, []);\n\n return (\n <div ref={ref} className=\"rte-toolbar__color-picker\">\n <button\n type=\"button\"\n className=\"rte-toolbar__btn\"\n onClick={() => setIsOpen(!isOpen)}\n title={title}\n >\n {icon}\n <span\n className=\"rte-toolbar__color-indicator\"\n style={{ backgroundColor: value || '#000' }}\n />\n </button>\n {isOpen && (\n <div className=\"rte-toolbar__color-dropdown\">\n {COLORS.map((c) => (\n <button\n key={c}\n type=\"button\"\n className={`rte-toolbar__color-swatch ${c === value ? 'rte-toolbar__color-swatch--active' : ''}`}\n style={{ backgroundColor: c }}\n onClick={() => { onChange(c); setIsOpen(false); }}\n title={c}\n />\n ))}\n <button\n type=\"button\"\n className=\"rte-toolbar__color-clear\"\n onClick={() => { onChange(''); setIsOpen(false); }}\n >\n Clear\n </button>\n </div>\n )}\n </div>\n );\n};\n"],"mappings":";;AASA,IAAM,IAAS;AAAA,EACb;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAClE;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAClE;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAClE;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAClE;AAAA,EAAW;AACb,GAEa,IAAA,CAA2C,EAAE,OAAA,GAAO,UAAA,GAAU,OAAA,GAAO,MAAA,EAAA,MAAW;AAC3F,QAAM,CAAC,GAAQ,CAAA,IAAa,EAAS,EAAK,GACpC,IAAM,EAAuB,IAAI;AAEvC,SAAA,EAAA,MAAgB;AACd,UAAM,IAAA,CAAW,MAAkB;AACjC,MAAI,EAAI,WAAW,CAAC,EAAI,QAAQ,SAAS,EAAE,MAAc,KACvD,EAAU,EAAK;AAAA,IAEnB;AACA,oBAAS,iBAAiB,aAAa,CAAO,GAC9C,MAAa,SAAS,oBAAoB,aAAa,CAAO;AAAA,EAChE,GAAG,CAAC,CAAC,GAGH,gBAAA,EAAC,OAAD;AAAA,IAAU,KAAA;AAAA,IAAK,WAAU;AAAA,
|
|
1
|
+
{"version":3,"file":"ColorPicker.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/Toolbar/ColorPicker.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from 'react';\n\ninterface ColorPickerProps {\n value: string;\n onChange: (color: string) => void;\n title?: string;\n icon: React.ReactNode;\n}\n\nconst COLORS = [\n '#000000', '#434343', '#666666', '#999999', '#cccccc', '#eeeeee', '#ffffff',\n '#ff0000', '#ff4500', '#ff8c00', '#ffd700', '#32cd32', '#00bfff', '#8a2be2',\n '#ff69b4', '#dc143c', '#ff6347', '#ffa500', '#9acd32', '#20b2aa', '#4169e1',\n '#9370db', '#db7093', '#b22222', '#d2691e', '#daa520', '#228b22', '#008b8b',\n '#191970', '#4b0082',\n];\n\nexport const ColorPicker: React.FC<ColorPickerProps> = ({ value, onChange, title, icon }) => {\n const [isOpen, setIsOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, []);\n\n return (\n <div ref={ref} className=\"rte-toolbar__color-picker\">\n <button\n type=\"button\"\n className=\"rte-toolbar__btn\"\n onClick={() => setIsOpen(!isOpen)}\n title={title}\n >\n {icon}\n <span\n className=\"rte-toolbar__color-indicator\"\n style={{ backgroundColor: value || '#000' }}\n />\n </button>\n {isOpen && (\n <div className=\"rte-toolbar__color-dropdown\">\n {COLORS.map((c) => (\n <button\n key={c}\n type=\"button\"\n className={`rte-toolbar__color-swatch ${c === value ? 'rte-toolbar__color-swatch--active' : ''}`}\n style={{ backgroundColor: c }}\n onClick={() => { onChange(c); setIsOpen(false); }}\n title={c}\n />\n ))}\n <button\n type=\"button\"\n className=\"rte-toolbar__color-clear\"\n onClick={() => { onChange(''); setIsOpen(false); }}\n >\n Clear\n </button>\n </div>\n )}\n </div>\n );\n};\n"],"mappings":";;AASA,IAAM,IAAS;AAAA,EACb;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAClE;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAClE;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAClE;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EAClE;AAAA,EAAW;AACb,GAEa,IAAA,CAA2C,EAAE,OAAA,GAAO,UAAA,GAAU,OAAA,GAAO,MAAA,EAAA,MAAW;AAC3F,QAAM,CAAC,GAAQ,CAAA,IAAa,EAAS,EAAK,GACpC,IAAM,EAAuB,IAAI;AAEvC,SAAA,EAAA,MAAgB;AACd,UAAM,IAAA,CAAW,MAAkB;AACjC,MAAI,EAAI,WAAW,CAAC,EAAI,QAAQ,SAAS,EAAE,MAAc,KACvD,EAAU,EAAK;AAAA,IAEnB;AACA,oBAAS,iBAAiB,aAAa,CAAO,GAC9C,MAAa,SAAS,oBAAoB,aAAa,CAAO;AAAA,EAChE,GAAG,CAAC,CAAC,GAGH,gBAAA,EAAC,OAAD;AAAA,IAAU,KAAA;AAAA,IAAK,WAAU;AAAA,IAAzB,UAAA,CACE,gBAAA,EAAC,UAAD;AAAA,MACE,MAAK;AAAA,MACL,WAAU;AAAA,MACV,SAAA,MAAe,EAAU,CAAC,CAAM;AAAA,MACzB,OAAA;AAAA,MAJT,UAAA,CAMG,GACD,gBAAA,EAAC,QAAD;AAAA,QACE,WAAU;AAAA,QACV,OAAO,EAAE,iBAAiB,KAAS,OAAO;AAAA,MAC3C,CAAA,CACK;AAAA,IACP,CAAA,GAAA,KACC,gBAAA,EAAC,OAAD;AAAA,MAAK,WAAU;AAAA,MAAf,UAAA,CACG,EAAO,IAAA,CAAK,MACX,gBAAA,EAAC,UAAD;AAAA,QAEE,MAAK;AAAA,QACL,WAAW,6BAA6B,MAAM,IAAQ,sCAAsC,EAAA;AAAA,QAC5F,OAAO,EAAE,iBAAiB,EAAE;AAAA,QAC5B,SAAA,MAAe;AAAE,UAAA,EAAS,CAAC,GAAG,EAAU,EAAK;AAAA,QAAG;AAAA,QAChD,OAAO;AAAA,MACR,GANM,CAMN,CACF,GACD,gBAAA,EAAC,UAAD;AAAA,QACE,MAAK;AAAA,QACL,WAAU;AAAA,QACV,SAAA,MAAe;AAAE,UAAA,EAAS,EAAE,GAAG,EAAU,EAAK;AAAA,QAAG;AAAA,QAClD,UAAA;AAAA,MAEO,CAAA,CACL;AAAA,IAEJ,CAAA,CAAA;AAAA;AAET"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FloatingDialogMenu.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from 'react';\nimport type { RichTextEditorLabels } from '../types';\n\ninterface FloatingDialogMenuProps {\n labels: RichTextEditorLabels;\n onInsert: (layout: 'block' | 'wrap-left' | 'wrap-right' | 'float') => void;\n}\n\nconst DIALOG_LAYOUT_OPTIONS: { key: 'block' | 'wrap-left' | 'wrap-right' | 'float'; labelKey: keyof RichTextEditorLabels; icon: React.ReactNode }[] = [\n {\n key: 'block', labelKey: 'layoutBlock',\n icon: <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\" /><line x1=\"3\" y1=\"3\" x2=\"21\" y2=\"3\" /><line x1=\"3\" y1=\"21\" x2=\"21\" y2=\"21\" /></svg>,\n },\n {\n key: 'wrap-left', labelKey: 'layoutWrapLeft',\n icon: <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><rect x=\"2\" y=\"4\" width=\"10\" height=\"8\" rx=\"1\" /><line x1=\"15\" y1=\"5\" x2=\"22\" y2=\"5\" /><line x1=\"15\" y1=\"8\" x2=\"22\" y2=\"8\" /><line x1=\"15\" y1=\"11\" x2=\"22\" y2=\"11\" /><line x1=\"2\" y1=\"15\" x2=\"22\" y2=\"15\" /><line x1=\"2\" y1=\"18\" x2=\"22\" y2=\"18\" /></svg>,\n },\n {\n key: 'wrap-right', labelKey: 'layoutWrapRight',\n icon: <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><rect x=\"12\" y=\"4\" width=\"10\" height=\"8\" rx=\"1\" /><line x1=\"2\" y1=\"5\" x2=\"9\" y2=\"5\" /><line x1=\"2\" y1=\"8\" x2=\"9\" y2=\"8\" /><line x1=\"2\" y1=\"11\" x2=\"9\" y2=\"11\" /><line x1=\"2\" y1=\"15\" x2=\"22\" y2=\"15\" /><line x1=\"2\" y1=\"18\" x2=\"22\" y2=\"18\" /></svg>,\n },\n {\n key: 'float', labelKey: 'layoutFloat',\n icon: <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"2\" /><path d=\"M2 2h4M18 2h4M2 22h4M18 22h4\" strokeDasharray=\"2 2\" /><line x1=\"2\" y1=\"12\" x2=\"6\" y2=\"12\" strokeDasharray=\"2 2\" /><line x1=\"18\" y1=\"12\" x2=\"22\" y2=\"12\" strokeDasharray=\"2 2\" /></svg>,\n },\n];\n\nexport const FloatingDialogMenu: React.FC<FloatingDialogMenuProps> = ({ labels, onInsert }) => {\n const [isOpen, setIsOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) setIsOpen(false);\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, []);\n\n return (\n <div ref={ref} className=\"rte-toolbar__template-menu\">\n <button\n type=\"button\"\n className={`rte-toolbar__btn ${isOpen ? 'rte-toolbar__btn--active' : ''}`}\n onClick={() => setIsOpen(!isOpen)}\n title={labels.floatingDialog || 'Floating Dialog'}\n style={{ width: 'auto', padding: '0 6px', gap: '2px', display: 'inline-flex', alignItems: 'center' }}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"2\" y=\"3\" width=\"20\" height=\"18\" rx=\"2\" />\n <line x1=\"2\" y1=\"8\" x2=\"22\" y2=\"8\" />\n <line x1=\"8\" y1=\"3\" x2=\"8\" y2=\"8\" />\n </svg>\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n {isOpen && (\n <div className=\"rte-toolbar__template-dropdown\" style={{ minWidth: 140 }}>\n {DIALOG_LAYOUT_OPTIONS.map((opt) => (\n <button\n key={opt.key}\n type=\"button\"\n className=\"rte-toolbar__template-item\"\n onClick={() => { onInsert(opt.key); setIsOpen(false); }}\n >\n <span className=\"rte-toolbar__template-icon\" style={{ display: 'flex', alignItems: 'center' }}>{opt.icon}</span>\n <span>{labels[opt.labelKey] || opt.labelKey}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n};\n"],"mappings":";;AAQA,IAAM,IAAgJ;AAAA,EACpJ;AAAA,IACE,KAAK;AAAA,IAAS,UAAU;AAAA,IACxB,MAAM,gBAAA,EAAC,OAAD;AAAA,MAAK,OAAM;AAAA,MAAK,QAAO;AAAA,MAAK,SAAQ;AAAA,MAAY,MAAK;AAAA,MAAO,QAAO;AAAA,MAAe,aAAY;AAAA,
|
|
1
|
+
{"version":3,"file":"FloatingDialogMenu.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from 'react';\nimport type { RichTextEditorLabels } from '../types';\n\ninterface FloatingDialogMenuProps {\n labels: RichTextEditorLabels;\n onInsert: (layout: 'block' | 'wrap-left' | 'wrap-right' | 'float') => void;\n}\n\nconst DIALOG_LAYOUT_OPTIONS: { key: 'block' | 'wrap-left' | 'wrap-right' | 'float'; labelKey: keyof RichTextEditorLabels; icon: React.ReactNode }[] = [\n {\n key: 'block', labelKey: 'layoutBlock',\n icon: <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\" /><line x1=\"3\" y1=\"3\" x2=\"21\" y2=\"3\" /><line x1=\"3\" y1=\"21\" x2=\"21\" y2=\"21\" /></svg>,\n },\n {\n key: 'wrap-left', labelKey: 'layoutWrapLeft',\n icon: <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><rect x=\"2\" y=\"4\" width=\"10\" height=\"8\" rx=\"1\" /><line x1=\"15\" y1=\"5\" x2=\"22\" y2=\"5\" /><line x1=\"15\" y1=\"8\" x2=\"22\" y2=\"8\" /><line x1=\"15\" y1=\"11\" x2=\"22\" y2=\"11\" /><line x1=\"2\" y1=\"15\" x2=\"22\" y2=\"15\" /><line x1=\"2\" y1=\"18\" x2=\"22\" y2=\"18\" /></svg>,\n },\n {\n key: 'wrap-right', labelKey: 'layoutWrapRight',\n icon: <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><rect x=\"12\" y=\"4\" width=\"10\" height=\"8\" rx=\"1\" /><line x1=\"2\" y1=\"5\" x2=\"9\" y2=\"5\" /><line x1=\"2\" y1=\"8\" x2=\"9\" y2=\"8\" /><line x1=\"2\" y1=\"11\" x2=\"9\" y2=\"11\" /><line x1=\"2\" y1=\"15\" x2=\"22\" y2=\"15\" /><line x1=\"2\" y1=\"18\" x2=\"22\" y2=\"18\" /></svg>,\n },\n {\n key: 'float', labelKey: 'layoutFloat',\n icon: <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"2\" /><path d=\"M2 2h4M18 2h4M2 22h4M18 22h4\" strokeDasharray=\"2 2\" /><line x1=\"2\" y1=\"12\" x2=\"6\" y2=\"12\" strokeDasharray=\"2 2\" /><line x1=\"18\" y1=\"12\" x2=\"22\" y2=\"12\" strokeDasharray=\"2 2\" /></svg>,\n },\n];\n\nexport const FloatingDialogMenu: React.FC<FloatingDialogMenuProps> = ({ labels, onInsert }) => {\n const [isOpen, setIsOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) setIsOpen(false);\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, []);\n\n return (\n <div ref={ref} className=\"rte-toolbar__template-menu\">\n <button\n type=\"button\"\n className={`rte-toolbar__btn ${isOpen ? 'rte-toolbar__btn--active' : ''}`}\n onClick={() => setIsOpen(!isOpen)}\n title={labels.floatingDialog || 'Floating Dialog'}\n style={{ width: 'auto', padding: '0 6px', gap: '2px', display: 'inline-flex', alignItems: 'center' }}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"2\" y=\"3\" width=\"20\" height=\"18\" rx=\"2\" />\n <line x1=\"2\" y1=\"8\" x2=\"22\" y2=\"8\" />\n <line x1=\"8\" y1=\"3\" x2=\"8\" y2=\"8\" />\n </svg>\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n {isOpen && (\n <div className=\"rte-toolbar__template-dropdown\" style={{ minWidth: 140 }}>\n {DIALOG_LAYOUT_OPTIONS.map((opt) => (\n <button\n key={opt.key}\n type=\"button\"\n className=\"rte-toolbar__template-item\"\n onClick={() => { onInsert(opt.key); setIsOpen(false); }}\n >\n <span className=\"rte-toolbar__template-icon\" style={{ display: 'flex', alignItems: 'center' }}>{opt.icon}</span>\n <span>{labels[opt.labelKey] || opt.labelKey}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarkdownTemplates.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from 'react';\nimport type { RichTextEditorLabels } from '../types';\n\nexport const MD_TEMPLATES: { key: string; labelKey: keyof RichTextEditorLabels; icon: string; content: string }[] = [\n {\n key: 'flowchart', labelKey: 'mdTplFlowchart', icon: '🔀',\n content: `## Flowchart\n\n\\`\\`\\`mermaid\ngraph TD\n A[Start] --> B{Is it valid?}\n B -->|Yes| C[Process Data]\n B -->|No| D[Show Error]\n C --> E[Save to DB]\n E --> F[Send Response]\n D --> G[Log Warning]\n G --> A\n F --> H[End]\n\\`\\`\\`\n`,\n },\n {\n key: 'sequence', labelKey: 'mdTplSequence', icon: '🔄',\n content: `## Sequence Diagram\n\n\\`\\`\\`mermaid\nsequenceDiagram\n participant Browser\n participant Server\n participant Database\n participant Cache\n\n Browser->>Server: POST /api/login\n Server->>Database: Query user\n Database-->>Server: User record\n Server->>Cache: Store session\n Cache-->>Server: OK\n Server-->>Browser: 200 JWT Token\n Browser->>Server: GET /api/data (Bearer token)\n Server->>Cache: Validate session\n Cache-->>Server: Valid\n Server->>Database: Fetch data\n Database-->>Server: Result set\n Server-->>Browser: 200 JSON data\n\\`\\`\\`\n`,\n },\n {\n key: 'pie', labelKey: 'mdTplPieChart', icon: '🥧',\n content: `## Pie Chart\n\n\\`\\`\\`mermaid\npie title Tech Stack Usage 2025\n \"TypeScript\" : 35\n \"Python\" : 25\n \"Rust\" : 15\n \"Go\" : 12\n \"Java\" : 8\n \"Others\" : 5\n\\`\\`\\`\n`,\n },\n {\n key: 'gantt', labelKey: 'mdTplGantt', icon: '📊',\n content: `## Gantt Chart\n\n\\`\\`\\`mermaid\ngantt\n title Project Development Timeline\n dateFormat YYYY-MM-DD\n section Design\n UI/UX Design :a1, 2025-01-01, 20d\n API Design :a2, after a1, 10d\n section Frontend\n Component Library :b1, after a2, 25d\n Page Integration :b2, after b1, 15d\n Testing & Bug Fix :b3, after b2, 10d\n section Backend\n Core API Development :c1, after a2, 30d\n Database Optimization :c2, after c1, 10d\n section Deployment\n Staging Deploy :d1, after b3, 5d\n Production Release :milestone, after d1, 0d\n\\`\\`\\`\n`,\n },\n {\n key: 'xychart', labelKey: 'mdTplBarChart', icon: '📈',\n content: `## Bar Chart (xychart)\n\n\\`\\`\\`mermaid\nxychart-beta\n title \"Monthly Revenue (in thousands)\"\n x-axis [Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec]\n y-axis \"Revenue (USD)\" 0 --> 120\n bar [52, 48, 61, 55, 72, 68, 85, 90, 78, 95, 102, 110]\n line [52, 48, 61, 55, 72, 68, 85, 90, 78, 95, 102, 110]\n\\`\\`\\`\n`,\n },\n {\n key: 'python', labelKey: 'mdTplPython', icon: '🐍',\n content: `## Python Example\n\n\\`\\`\\`python\nimport asyncio\nfrom dataclasses import dataclass, field\nfrom typing import AsyncIterator\n\n\n@dataclass\nclass DataPipeline:\n \"\"\"Async data processing pipeline.\"\"\"\n name: str\n buffer_size: int = 100\n _queue: asyncio.Queue = field(init=False)\n\n def __post_init__(self):\n self._queue = asyncio.Queue(maxsize=self.buffer_size)\n\n async def produce(self, items: list[int]) -> None:\n for item in items:\n transformed = item ** 2 + 2 * item + 1\n await self._queue.put(transformed)\n await self._queue.put(None) # sentinel\n\n async def consume(self) -> AsyncIterator[int]:\n while True:\n item = await self._queue.get()\n if item is None:\n break\n yield item\n\n async def run(self, data: list[int]) -> list[int]:\n results: list[int] = []\n producer = asyncio.create_task(self.produce(data))\n async for value in self.consume():\n results.append(value)\n await producer\n return results\n\n\nasync def main():\n pipeline = DataPipeline(name=\"squares\", buffer_size=50)\n data = list(range(1, 21))\n results = await pipeline.run(data)\n print(f\"Processed {len(results)} items: {results[:5]}...\")\n\n\nif __name__ == \"__main__\":\n asyncio.run(main())\n\\`\\`\\`\n`,\n },\n {\n key: 'typescript', labelKey: 'mdTplTypeScript', icon: '🟦',\n content: `## TypeScript Example\n\n\\`\\`\\`typescript\ninterface APIResponse<T> {\n data: T;\n status: number;\n message: string;\n timestamp: Date;\n}\n\ntype HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';\n\nclass TypedFetcher {\n private baseUrl: string;\n private headers: Record<string, string>;\n\n constructor(baseUrl: string, token?: string) {\n this.baseUrl = baseUrl;\n this.headers = {\n 'Content-Type': 'application/json',\n ...(token ? { Authorization: \\\\\\`Bearer \\\\\\${token}\\\\\\` } : {}),\n };\n }\n\n async request<T>(\n method: HttpMethod,\n path: string,\n body?: unknown,\n ): Promise<APIResponse<T>> {\n const response = await fetch(\\\\\\`\\\\\\${this.baseUrl}\\\\\\${path}\\\\\\`, {\n method,\n headers: this.headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n throw new Error(\\\\\\`HTTP \\\\\\${response.status}: \\\\\\${response.statusText}\\\\\\`);\n }\n\n return response.json() as Promise<APIResponse<T>>;\n }\n\n get<T>(path: string) { return this.request<T>('GET', path); }\n post<T>(path: string, body: unknown) { return this.request<T>('POST', path, body); }\n put<T>(path: string, body: unknown) { return this.request<T>('PUT', path, body); }\n delete<T>(path: string) { return this.request<T>('DELETE', path); }\n}\n\n// Usage\ninterface User {\n id: number;\n name: string;\n email: string;\n}\n\nconst api = new TypedFetcher('https://api.example.com', 'my-token');\nconst users = await api.get<User[]>('/users');\nconsole.log(users.data);\n\\`\\`\\`\n`,\n },\n {\n key: 'rust', labelKey: 'mdTplRust', icon: '🦀',\n content: `## Rust Example\n\n\\`\\`\\`rust\nuse std::collections::HashMap;\nuse std::sync::Arc;\nuse tokio::sync::RwLock;\n\n#[derive(Debug, Clone)]\nstruct CacheEntry<V: Clone> {\n value: V,\n expires_at: std::time::Instant,\n}\n\n#[derive(Clone)]\nstruct AsyncCache<V: Clone + Send + Sync + 'static> {\n store: Arc<RwLock<HashMap<String, CacheEntry<V>>>>,\n ttl: std::time::Duration,\n}\n\nimpl<V: Clone + Send + Sync + 'static> AsyncCache<V> {\n fn new(ttl_secs: u64) -> Self {\n Self {\n store: Arc::new(RwLock::new(HashMap::new())),\n ttl: std::time::Duration::from_secs(ttl_secs),\n }\n }\n\n async fn get(&self, key: &str) -> Option<V> {\n let store = self.store.read().await;\n store.get(key).and_then(|entry| {\n if entry.expires_at > std::time::Instant::now() {\n Some(entry.value.clone())\n } else {\n None\n }\n })\n }\n\n async fn set(&self, key: String, value: V) {\n let mut store = self.store.write().await;\n store.insert(key, CacheEntry {\n value,\n expires_at: std::time::Instant::now() + self.ttl,\n });\n }\n\n async fn cleanup(&self) -> usize {\n let mut store = self.store.write().await;\n let now = std::time::Instant::now();\n let before = store.len();\n store.retain(|_, entry| entry.expires_at > now);\n before - store.len()\n }\n}\n\n#[tokio::main]\nasync fn main() {\n let cache = AsyncCache::<String>::new(60);\n cache.set(\"hello\".into(), \"world\".into()).await;\n\n if let Some(val) = cache.get(\"hello\").await {\n println!(\"Got: {val}\");\n }\n}\n\\`\\`\\`\n`,\n },\n {\n key: 'math', labelKey: 'mdTplMath', icon: '🔢',\n content: `## Math Formulas (TeX)\n\n### Euler's Identity\n\n$$\ne^{i\\\\pi} + 1 = 0\n$$\n\n### Quadratic Formula\n\n$$\nx = \\\\frac{-b \\\\pm \\\\sqrt{b^2 - 4ac}}{2a}\n$$\n\n### Gaussian Integral\n\n$$\n\\\\int_{-\\\\infty}^{\\\\infty} e^{-x^2} \\\\, dx = \\\\sqrt{\\\\pi}\n$$\n\n### Maxwell's Equations\n\n$$\n\\\\nabla \\\\cdot \\\\mathbf{E} = \\\\frac{\\\\rho}{\\\\epsilon_0}\n$$\n\n$$\n\\\\nabla \\\\cdot \\\\mathbf{B} = 0\n$$\n\n$$\n\\\\nabla \\\\times \\\\mathbf{E} = -\\\\frac{\\\\partial \\\\mathbf{B}}{\\\\partial t}\n$$\n\n$$\n\\\\nabla \\\\times \\\\mathbf{B} = \\\\mu_0 \\\\mathbf{J} + \\\\mu_0 \\\\epsilon_0 \\\\frac{\\\\partial \\\\mathbf{E}}{\\\\partial t}\n$$\n\n### Taylor Series Expansion\n\n$$\nf(x) = \\\\sum_{n=0}^{\\\\infty} \\\\frac{f^{(n)}(a)}{n!}(x-a)^n\n$$\n\n### Matrix Notation\n\n$$\n\\\\mathbf{A} = \\\\begin{pmatrix} a_{11} & a_{12} & \\\\cdots & a_{1n} \\\\\\\\ a_{21} & a_{22} & \\\\cdots & a_{2n} \\\\\\\\ \\\\vdots & \\\\vdots & \\\\ddots & \\\\vdots \\\\\\\\ a_{m1} & a_{m2} & \\\\cdots & a_{mn} \\\\end{pmatrix}\n$$\n\n### Inline math: The identity $e^{i\\\\theta} = \\\\cos\\\\theta + i\\\\sin\\\\theta$ is known as Euler's formula.\n`,\n },\n {\n key: 'mixed', labelKey: 'mdTplMixed', icon: '🎨',\n content: `## Mixed Content Example\n\n### Architecture Overview\n\n\\`\\`\\`mermaid\ngraph LR\n Client[Client App] --> Gateway[API Gateway]\n Gateway --> Auth[Auth Service]\n Gateway --> Core[Core Service]\n Core --> DB[(PostgreSQL)]\n Core --> Cache[(Redis)]\n Auth --> DB\n\\`\\`\\`\n\n### Performance Formula\n\nThe response time $T$ is calculated as:\n\n$$\nT = T_{network} + T_{processing} + T_{db}\n$$\n\nwhere $T_{db} = O(\\\\log n)$ with proper indexing.\n\n### Implementation\n\n\\`\\`\\`python\nfrom fastapi import FastAPI, Depends\nfrom functools import lru_cache\n\napp = FastAPI()\n\n@lru_cache(maxsize=256)\ndef compute_heavy(n: int) -> float:\n \"\"\"Cached computation: O(log n) amortized.\"\"\"\n return sum(1.0 / i for i in range(1, n + 1))\n\n@app.get(\"/api/harmonic/{n}\")\nasync def harmonic(n: int):\n result = compute_heavy(n)\n return {\"n\": n, \"H_n\": round(result, 6)}\n\\`\\`\\`\n\n### Project Status\n\n\\`\\`\\`mermaid\npie title Sprint Progress\n \"Completed\" : 65\n \"In Progress\" : 20\n \"Blocked\" : 10\n \"Not Started\" : 5\n\\`\\`\\`\n`,\n },\n];\n\ninterface MarkdownTemplateMenuProps {\n labels: RichTextEditorLabels;\n onSelect: (content: string) => void;\n}\n\nexport const MarkdownTemplateMenu: React.FC<MarkdownTemplateMenuProps> = ({ labels, onSelect }) => {\n const [isOpen, setIsOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, []);\n\n return (\n <div ref={ref} className=\"rte-toolbar__template-menu\">\n <button\n type=\"button\"\n className={`rte-toolbar__btn ${isOpen ? 'rte-toolbar__btn--active' : ''}`}\n onClick={() => setIsOpen(!isOpen)}\n title={labels.mdTemplates || 'Markdown Templates'}\n style={{ width: 'auto', padding: '0 6px', gap: '2px', display: 'inline-flex', alignItems: 'center' }}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M2 3h20v18H2z\" />\n <path d=\"M5 15V9l3 3.5L11 9v6\" />\n <path d=\"M17 9l-2.5 3H17v3\" />\n </svg>\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n {isOpen && (\n <div className=\"rte-toolbar__template-dropdown\">\n <div className=\"rte-toolbar__template-group-label\">Mermaid</div>\n {MD_TEMPLATES.filter(t => ['flowchart', 'sequence', 'pie', 'gantt', 'xychart'].includes(t.key)).map(t => (\n <button\n key={t.key}\n type=\"button\"\n className=\"rte-toolbar__template-item\"\n onClick={() => { onSelect(t.content); setIsOpen(false); }}\n >\n <span className=\"rte-toolbar__template-icon\">{t.icon}</span>\n <span>{labels[t.labelKey] || t.labelKey}</span>\n </button>\n ))}\n <div className=\"rte-toolbar__template-group-label\">Code</div>\n {MD_TEMPLATES.filter(t => ['python', 'typescript', 'rust'].includes(t.key)).map(t => (\n <button\n key={t.key}\n type=\"button\"\n className=\"rte-toolbar__template-item\"\n onClick={() => { onSelect(t.content); setIsOpen(false); }}\n >\n <span className=\"rte-toolbar__template-icon\">{t.icon}</span>\n <span>{labels[t.labelKey] || t.labelKey}</span>\n </button>\n ))}\n <div className=\"rte-toolbar__template-group-label\">Math / Mixed</div>\n {MD_TEMPLATES.filter(t => ['math', 'mixed'].includes(t.key)).map(t => (\n <button\n key={t.key}\n type=\"button\"\n className=\"rte-toolbar__template-item\"\n onClick={() => { onSelect(t.content); setIsOpen(false); }}\n >\n <span className=\"rte-toolbar__template-icon\">{t.icon}</span>\n <span>{labels[t.labelKey] || t.labelKey}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MarkdownTemplates.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from 'react';\nimport type { RichTextEditorLabels } from '../types';\n\nexport const MD_TEMPLATES: { key: string; labelKey: keyof RichTextEditorLabels; icon: string; content: string }[] = [\n {\n key: 'flowchart', labelKey: 'mdTplFlowchart', icon: '🔀',\n content: `## Flowchart\n\n\\`\\`\\`mermaid\ngraph TD\n A[Start] --> B{Is it valid?}\n B -->|Yes| C[Process Data]\n B -->|No| D[Show Error]\n C --> E[Save to DB]\n E --> F[Send Response]\n D --> G[Log Warning]\n G --> A\n F --> H[End]\n\\`\\`\\`\n`,\n },\n {\n key: 'sequence', labelKey: 'mdTplSequence', icon: '🔄',\n content: `## Sequence Diagram\n\n\\`\\`\\`mermaid\nsequenceDiagram\n participant Browser\n participant Server\n participant Database\n participant Cache\n\n Browser->>Server: POST /api/login\n Server->>Database: Query user\n Database-->>Server: User record\n Server->>Cache: Store session\n Cache-->>Server: OK\n Server-->>Browser: 200 JWT Token\n Browser->>Server: GET /api/data (Bearer token)\n Server->>Cache: Validate session\n Cache-->>Server: Valid\n Server->>Database: Fetch data\n Database-->>Server: Result set\n Server-->>Browser: 200 JSON data\n\\`\\`\\`\n`,\n },\n {\n key: 'pie', labelKey: 'mdTplPieChart', icon: '🥧',\n content: `## Pie Chart\n\n\\`\\`\\`mermaid\npie title Tech Stack Usage 2025\n \"TypeScript\" : 35\n \"Python\" : 25\n \"Rust\" : 15\n \"Go\" : 12\n \"Java\" : 8\n \"Others\" : 5\n\\`\\`\\`\n`,\n },\n {\n key: 'gantt', labelKey: 'mdTplGantt', icon: '📊',\n content: `## Gantt Chart\n\n\\`\\`\\`mermaid\ngantt\n title Project Development Timeline\n dateFormat YYYY-MM-DD\n section Design\n UI/UX Design :a1, 2025-01-01, 20d\n API Design :a2, after a1, 10d\n section Frontend\n Component Library :b1, after a2, 25d\n Page Integration :b2, after b1, 15d\n Testing & Bug Fix :b3, after b2, 10d\n section Backend\n Core API Development :c1, after a2, 30d\n Database Optimization :c2, after c1, 10d\n section Deployment\n Staging Deploy :d1, after b3, 5d\n Production Release :milestone, after d1, 0d\n\\`\\`\\`\n`,\n },\n {\n key: 'xychart', labelKey: 'mdTplBarChart', icon: '📈',\n content: `## Bar Chart (xychart)\n\n\\`\\`\\`mermaid\nxychart-beta\n title \"Monthly Revenue (in thousands)\"\n x-axis [Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec]\n y-axis \"Revenue (USD)\" 0 --> 120\n bar [52, 48, 61, 55, 72, 68, 85, 90, 78, 95, 102, 110]\n line [52, 48, 61, 55, 72, 68, 85, 90, 78, 95, 102, 110]\n\\`\\`\\`\n`,\n },\n {\n key: 'python', labelKey: 'mdTplPython', icon: '🐍',\n content: `## Python Example\n\n\\`\\`\\`python\nimport asyncio\nfrom dataclasses import dataclass, field\nfrom typing import AsyncIterator\n\n\n@dataclass\nclass DataPipeline:\n \"\"\"Async data processing pipeline.\"\"\"\n name: str\n buffer_size: int = 100\n _queue: asyncio.Queue = field(init=False)\n\n def __post_init__(self):\n self._queue = asyncio.Queue(maxsize=self.buffer_size)\n\n async def produce(self, items: list[int]) -> None:\n for item in items:\n transformed = item ** 2 + 2 * item + 1\n await self._queue.put(transformed)\n await self._queue.put(None) # sentinel\n\n async def consume(self) -> AsyncIterator[int]:\n while True:\n item = await self._queue.get()\n if item is None:\n break\n yield item\n\n async def run(self, data: list[int]) -> list[int]:\n results: list[int] = []\n producer = asyncio.create_task(self.produce(data))\n async for value in self.consume():\n results.append(value)\n await producer\n return results\n\n\nasync def main():\n pipeline = DataPipeline(name=\"squares\", buffer_size=50)\n data = list(range(1, 21))\n results = await pipeline.run(data)\n print(f\"Processed {len(results)} items: {results[:5]}...\")\n\n\nif __name__ == \"__main__\":\n asyncio.run(main())\n\\`\\`\\`\n`,\n },\n {\n key: 'typescript', labelKey: 'mdTplTypeScript', icon: '🟦',\n content: `## TypeScript Example\n\n\\`\\`\\`typescript\ninterface APIResponse<T> {\n data: T;\n status: number;\n message: string;\n timestamp: Date;\n}\n\ntype HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';\n\nclass TypedFetcher {\n private baseUrl: string;\n private headers: Record<string, string>;\n\n constructor(baseUrl: string, token?: string) {\n this.baseUrl = baseUrl;\n this.headers = {\n 'Content-Type': 'application/json',\n ...(token ? { Authorization: \\\\\\`Bearer \\\\\\${token}\\\\\\` } : {}),\n };\n }\n\n async request<T>(\n method: HttpMethod,\n path: string,\n body?: unknown,\n ): Promise<APIResponse<T>> {\n const response = await fetch(\\\\\\`\\\\\\${this.baseUrl}\\\\\\${path}\\\\\\`, {\n method,\n headers: this.headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n throw new Error(\\\\\\`HTTP \\\\\\${response.status}: \\\\\\${response.statusText}\\\\\\`);\n }\n\n return response.json() as Promise<APIResponse<T>>;\n }\n\n get<T>(path: string) { return this.request<T>('GET', path); }\n post<T>(path: string, body: unknown) { return this.request<T>('POST', path, body); }\n put<T>(path: string, body: unknown) { return this.request<T>('PUT', path, body); }\n delete<T>(path: string) { return this.request<T>('DELETE', path); }\n}\n\n// Usage\ninterface User {\n id: number;\n name: string;\n email: string;\n}\n\nconst api = new TypedFetcher('https://api.example.com', 'my-token');\nconst users = await api.get<User[]>('/users');\nconsole.log(users.data);\n\\`\\`\\`\n`,\n },\n {\n key: 'rust', labelKey: 'mdTplRust', icon: '🦀',\n content: `## Rust Example\n\n\\`\\`\\`rust\nuse std::collections::HashMap;\nuse std::sync::Arc;\nuse tokio::sync::RwLock;\n\n#[derive(Debug, Clone)]\nstruct CacheEntry<V: Clone> {\n value: V,\n expires_at: std::time::Instant,\n}\n\n#[derive(Clone)]\nstruct AsyncCache<V: Clone + Send + Sync + 'static> {\n store: Arc<RwLock<HashMap<String, CacheEntry<V>>>>,\n ttl: std::time::Duration,\n}\n\nimpl<V: Clone + Send + Sync + 'static> AsyncCache<V> {\n fn new(ttl_secs: u64) -> Self {\n Self {\n store: Arc::new(RwLock::new(HashMap::new())),\n ttl: std::time::Duration::from_secs(ttl_secs),\n }\n }\n\n async fn get(&self, key: &str) -> Option<V> {\n let store = self.store.read().await;\n store.get(key).and_then(|entry| {\n if entry.expires_at > std::time::Instant::now() {\n Some(entry.value.clone())\n } else {\n None\n }\n })\n }\n\n async fn set(&self, key: String, value: V) {\n let mut store = self.store.write().await;\n store.insert(key, CacheEntry {\n value,\n expires_at: std::time::Instant::now() + self.ttl,\n });\n }\n\n async fn cleanup(&self) -> usize {\n let mut store = self.store.write().await;\n let now = std::time::Instant::now();\n let before = store.len();\n store.retain(|_, entry| entry.expires_at > now);\n before - store.len()\n }\n}\n\n#[tokio::main]\nasync fn main() {\n let cache = AsyncCache::<String>::new(60);\n cache.set(\"hello\".into(), \"world\".into()).await;\n\n if let Some(val) = cache.get(\"hello\").await {\n println!(\"Got: {val}\");\n }\n}\n\\`\\`\\`\n`,\n },\n {\n key: 'math', labelKey: 'mdTplMath', icon: '🔢',\n content: `## Math Formulas (TeX)\n\n### Euler's Identity\n\n$$\ne^{i\\\\pi} + 1 = 0\n$$\n\n### Quadratic Formula\n\n$$\nx = \\\\frac{-b \\\\pm \\\\sqrt{b^2 - 4ac}}{2a}\n$$\n\n### Gaussian Integral\n\n$$\n\\\\int_{-\\\\infty}^{\\\\infty} e^{-x^2} \\\\, dx = \\\\sqrt{\\\\pi}\n$$\n\n### Maxwell's Equations\n\n$$\n\\\\nabla \\\\cdot \\\\mathbf{E} = \\\\frac{\\\\rho}{\\\\epsilon_0}\n$$\n\n$$\n\\\\nabla \\\\cdot \\\\mathbf{B} = 0\n$$\n\n$$\n\\\\nabla \\\\times \\\\mathbf{E} = -\\\\frac{\\\\partial \\\\mathbf{B}}{\\\\partial t}\n$$\n\n$$\n\\\\nabla \\\\times \\\\mathbf{B} = \\\\mu_0 \\\\mathbf{J} + \\\\mu_0 \\\\epsilon_0 \\\\frac{\\\\partial \\\\mathbf{E}}{\\\\partial t}\n$$\n\n### Taylor Series Expansion\n\n$$\nf(x) = \\\\sum_{n=0}^{\\\\infty} \\\\frac{f^{(n)}(a)}{n!}(x-a)^n\n$$\n\n### Matrix Notation\n\n$$\n\\\\mathbf{A} = \\\\begin{pmatrix} a_{11} & a_{12} & \\\\cdots & a_{1n} \\\\\\\\ a_{21} & a_{22} & \\\\cdots & a_{2n} \\\\\\\\ \\\\vdots & \\\\vdots & \\\\ddots & \\\\vdots \\\\\\\\ a_{m1} & a_{m2} & \\\\cdots & a_{mn} \\\\end{pmatrix}\n$$\n\n### Inline math: The identity $e^{i\\\\theta} = \\\\cos\\\\theta + i\\\\sin\\\\theta$ is known as Euler's formula.\n`,\n },\n {\n key: 'mixed', labelKey: 'mdTplMixed', icon: '🎨',\n content: `## Mixed Content Example\n\n### Architecture Overview\n\n\\`\\`\\`mermaid\ngraph LR\n Client[Client App] --> Gateway[API Gateway]\n Gateway --> Auth[Auth Service]\n Gateway --> Core[Core Service]\n Core --> DB[(PostgreSQL)]\n Core --> Cache[(Redis)]\n Auth --> DB\n\\`\\`\\`\n\n### Performance Formula\n\nThe response time $T$ is calculated as:\n\n$$\nT = T_{network} + T_{processing} + T_{db}\n$$\n\nwhere $T_{db} = O(\\\\log n)$ with proper indexing.\n\n### Implementation\n\n\\`\\`\\`python\nfrom fastapi import FastAPI, Depends\nfrom functools import lru_cache\n\napp = FastAPI()\n\n@lru_cache(maxsize=256)\ndef compute_heavy(n: int) -> float:\n \"\"\"Cached computation: O(log n) amortized.\"\"\"\n return sum(1.0 / i for i in range(1, n + 1))\n\n@app.get(\"/api/harmonic/{n}\")\nasync def harmonic(n: int):\n result = compute_heavy(n)\n return {\"n\": n, \"H_n\": round(result, 6)}\n\\`\\`\\`\n\n### Project Status\n\n\\`\\`\\`mermaid\npie title Sprint Progress\n \"Completed\" : 65\n \"In Progress\" : 20\n \"Blocked\" : 10\n \"Not Started\" : 5\n\\`\\`\\`\n`,\n },\n];\n\ninterface MarkdownTemplateMenuProps {\n labels: RichTextEditorLabels;\n onSelect: (content: string) => void;\n}\n\nexport const MarkdownTemplateMenu: React.FC<MarkdownTemplateMenuProps> = ({ labels, onSelect }) => {\n const [isOpen, setIsOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, []);\n\n return (\n <div ref={ref} className=\"rte-toolbar__template-menu\">\n <button\n type=\"button\"\n className={`rte-toolbar__btn ${isOpen ? 'rte-toolbar__btn--active' : ''}`}\n onClick={() => setIsOpen(!isOpen)}\n title={labels.mdTemplates || 'Markdown Templates'}\n style={{ width: 'auto', padding: '0 6px', gap: '2px', display: 'inline-flex', alignItems: 'center' }}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M2 3h20v18H2z\" />\n <path d=\"M5 15V9l3 3.5L11 9v6\" />\n <path d=\"M17 9l-2.5 3H17v3\" />\n </svg>\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n {isOpen && (\n <div className=\"rte-toolbar__template-dropdown\">\n <div className=\"rte-toolbar__template-group-label\">Mermaid</div>\n {MD_TEMPLATES.filter(t => ['flowchart', 'sequence', 'pie', 'gantt', 'xychart'].includes(t.key)).map(t => (\n <button\n key={t.key}\n type=\"button\"\n className=\"rte-toolbar__template-item\"\n onClick={() => { onSelect(t.content); setIsOpen(false); }}\n >\n <span className=\"rte-toolbar__template-icon\">{t.icon}</span>\n <span>{labels[t.labelKey] || t.labelKey}</span>\n </button>\n ))}\n <div className=\"rte-toolbar__template-group-label\">Code</div>\n {MD_TEMPLATES.filter(t => ['python', 'typescript', 'rust'].includes(t.key)).map(t => (\n <button\n key={t.key}\n type=\"button\"\n className=\"rte-toolbar__template-item\"\n onClick={() => { onSelect(t.content); setIsOpen(false); }}\n >\n <span className=\"rte-toolbar__template-icon\">{t.icon}</span>\n <span>{labels[t.labelKey] || t.labelKey}</span>\n </button>\n ))}\n <div className=\"rte-toolbar__template-group-label\">Math / Mixed</div>\n {MD_TEMPLATES.filter(t => ['math', 'mixed'].includes(t.key)).map(t => (\n <button\n key={t.key}\n type=\"button\"\n className=\"rte-toolbar__template-item\"\n onClick={() => { onSelect(t.content); setIsOpen(false); }}\n >\n <span className=\"rte-toolbar__template-icon\">{t.icon}</span>\n <span>{labels[t.labelKey] || t.labelKey}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectDropdown.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/Toolbar/SelectDropdown.tsx"],"sourcesContent":["import React from 'react';\n\nexport const FONT_FAMILIES = [\n { label: 'Default', value: '' },\n { label: 'Arial', value: 'Arial, sans-serif' },\n { label: 'Helvetica', value: 'Helvetica, sans-serif' },\n { label: 'Georgia', value: 'Georgia, serif' },\n { label: 'Times New Roman', value: 'Times New Roman, serif' },\n { label: 'Courier New', value: 'Courier New, monospace' },\n { label: 'Verdana', value: 'Verdana, sans-serif' },\n { label: 'Trebuchet MS', value: 'Trebuchet MS, sans-serif' },\n { label: 'Impact', value: 'Impact, sans-serif' },\n { label: 'Comic Sans MS', value: 'Comic Sans MS, cursive' },\n];\n\nexport const FONT_SIZES = [\n { label: 'Default', value: '' },\n { label: '10px', value: '10px' },\n { label: '12px', value: '12px' },\n { label: '14px', value: '14px' },\n { label: '16px', value: '16px' },\n { label: '18px', value: '18px' },\n { label: '20px', value: '20px' },\n { label: '24px', value: '24px' },\n { label: '28px', value: '28px' },\n { label: '32px', value: '32px' },\n { label: '36px', value: '36px' },\n { label: '48px', value: '48px' },\n { label: '64px', value: '64px' },\n { label: '72px', value: '72px' },\n];\n\ninterface SelectDropdownProps {\n value: string;\n options: { label: string; value: string }[];\n onChange: (value: string) => void;\n title?: string;\n width?: number;\n}\n\nexport const SelectDropdown: React.FC<SelectDropdownProps> = ({ value, options, onChange, title, width = 110 }) => (\n <select\n className=\"rte-toolbar__select\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n title={title}\n style={{ width }}\n >\n {options.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n);\n"],"mappings":";;AAEA,IAAa,IAAgB;AAAA,EAC3B;AAAA,IAAE,OAAO;AAAA,IAAW,OAAO;AAAA,EAAG;AAAA,EAC9B;AAAA,IAAE,OAAO;AAAA,IAAS,OAAO;AAAA,EAAoB;AAAA,EAC7C;AAAA,IAAE,OAAO;AAAA,IAAa,OAAO;AAAA,EAAwB;AAAA,EACrD;AAAA,IAAE,OAAO;AAAA,IAAW,OAAO;AAAA,EAAiB;AAAA,EAC5C;AAAA,IAAE,OAAO;AAAA,IAAmB,OAAO;AAAA,EAAyB;AAAA,EAC5D;AAAA,IAAE,OAAO;AAAA,IAAe,OAAO;AAAA,EAAyB;AAAA,EACxD;AAAA,IAAE,OAAO;AAAA,IAAW,OAAO;AAAA,EAAsB;AAAA,EACjD;AAAA,IAAE,OAAO;AAAA,IAAgB,OAAO;AAAA,EAA2B;AAAA,EAC3D;AAAA,IAAE,OAAO;AAAA,IAAU,OAAO;AAAA,EAAqB;AAAA,EAC/C;AAAA,IAAE,OAAO;AAAA,IAAiB,OAAO;AAAA,EAAyB;AAC5D,GAEa,IAAa;AAAA,EACxB;AAAA,IAAE,OAAO;AAAA,IAAW,OAAO;AAAA,EAAG;AAAA,EAC9B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AACjC,GAUa,IAAA,CAAiD,EAAE,OAAA,GAAO,SAAA,GAAS,UAAA,GAAU,OAAA,GAAO,OAAA,IAAQ,IAAA,MACvG,gBAAA,EAAC,UAAD;AAAA,EACE,WAAU;AAAA,EACH,OAAA;AAAA,EACP,UAAA,CAAW,MAAM,EAAS,EAAE,OAAO,KAAK;AAAA,EACjC,OAAA;AAAA,EACP,OAAO,EAAE,OAAA,EAAM;AAAA,
|
|
1
|
+
{"version":3,"file":"SelectDropdown.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/Toolbar/SelectDropdown.tsx"],"sourcesContent":["import React from 'react';\n\nexport const FONT_FAMILIES = [\n { label: 'Default', value: '' },\n { label: 'Arial', value: 'Arial, sans-serif' },\n { label: 'Helvetica', value: 'Helvetica, sans-serif' },\n { label: 'Georgia', value: 'Georgia, serif' },\n { label: 'Times New Roman', value: 'Times New Roman, serif' },\n { label: 'Courier New', value: 'Courier New, monospace' },\n { label: 'Verdana', value: 'Verdana, sans-serif' },\n { label: 'Trebuchet MS', value: 'Trebuchet MS, sans-serif' },\n { label: 'Impact', value: 'Impact, sans-serif' },\n { label: 'Comic Sans MS', value: 'Comic Sans MS, cursive' },\n];\n\nexport const FONT_SIZES = [\n { label: 'Default', value: '' },\n { label: '10px', value: '10px' },\n { label: '12px', value: '12px' },\n { label: '14px', value: '14px' },\n { label: '16px', value: '16px' },\n { label: '18px', value: '18px' },\n { label: '20px', value: '20px' },\n { label: '24px', value: '24px' },\n { label: '28px', value: '28px' },\n { label: '32px', value: '32px' },\n { label: '36px', value: '36px' },\n { label: '48px', value: '48px' },\n { label: '64px', value: '64px' },\n { label: '72px', value: '72px' },\n];\n\ninterface SelectDropdownProps {\n value: string;\n options: { label: string; value: string }[];\n onChange: (value: string) => void;\n title?: string;\n width?: number;\n}\n\nexport const SelectDropdown: React.FC<SelectDropdownProps> = ({ value, options, onChange, title, width = 110 }) => (\n <select\n className=\"rte-toolbar__select\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n title={title}\n style={{ width }}\n >\n {options.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n);\n"],"mappings":";;AAEA,IAAa,IAAgB;AAAA,EAC3B;AAAA,IAAE,OAAO;AAAA,IAAW,OAAO;AAAA,EAAG;AAAA,EAC9B;AAAA,IAAE,OAAO;AAAA,IAAS,OAAO;AAAA,EAAoB;AAAA,EAC7C;AAAA,IAAE,OAAO;AAAA,IAAa,OAAO;AAAA,EAAwB;AAAA,EACrD;AAAA,IAAE,OAAO;AAAA,IAAW,OAAO;AAAA,EAAiB;AAAA,EAC5C;AAAA,IAAE,OAAO;AAAA,IAAmB,OAAO;AAAA,EAAyB;AAAA,EAC5D;AAAA,IAAE,OAAO;AAAA,IAAe,OAAO;AAAA,EAAyB;AAAA,EACxD;AAAA,IAAE,OAAO;AAAA,IAAW,OAAO;AAAA,EAAsB;AAAA,EACjD;AAAA,IAAE,OAAO;AAAA,IAAgB,OAAO;AAAA,EAA2B;AAAA,EAC3D;AAAA,IAAE,OAAO;AAAA,IAAU,OAAO;AAAA,EAAqB;AAAA,EAC/C;AAAA,IAAE,OAAO;AAAA,IAAiB,OAAO;AAAA,EAAyB;AAC5D,GAEa,IAAa;AAAA,EACxB;AAAA,IAAE,OAAO;AAAA,IAAW,OAAO;AAAA,EAAG;AAAA,EAC9B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AAAA,EAC/B;AAAA,IAAE,OAAO;AAAA,IAAQ,OAAO;AAAA,EAAO;AACjC,GAUa,IAAA,CAAiD,EAAE,OAAA,GAAO,SAAA,GAAS,UAAA,GAAU,OAAA,GAAO,OAAA,IAAQ,IAAA,MACvG,gBAAA,EAAC,UAAD;AAAA,EACE,WAAU;AAAA,EACH,OAAA;AAAA,EACP,UAAA,CAAW,MAAM,EAAS,EAAE,OAAO,KAAK;AAAA,EACjC,OAAA;AAAA,EACP,OAAO,EAAE,OAAA,EAAM;AAAA,EAEd,UAAA,EAAQ,IAAA,CAAK,MACZ,gBAAA,EAAC,UAAD;AAAA,IAAwB,OAAO,EAAI;AAAA,IAAQ,UAAA,EAAI;AAAA,EAAc,GAAhD,EAAI,KAA4C,CAC9D;AACK,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableOpsMenu.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/Toolbar/TableOpsMenu.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from 'react';\nimport type { Editor } from '@tiptap/react';\nimport type { RichTextEditorLabels } from '../types';\n\ninterface TableOpsMenuProps {\n editor: Editor;\n labels: RichTextEditorLabels;\n}\n\nexport const TableOpsMenu: React.FC<TableOpsMenuProps> = ({ editor, labels }) => {\n const [isOpen, setIsOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, []);\n\n const isInTable = editor.isActive('table');\n\n const actions: { label: string; action: () => void; icon: string }[] = [\n { label: labels.tableAddColumnBefore || 'Add Column Before', action: () => editor.chain().focus().addColumnBefore().run(), icon: '⇤+' },\n { label: labels.tableAddColumnAfter || 'Add Column After', action: () => editor.chain().focus().addColumnAfter().run(), icon: '+⇥' },\n { label: labels.tableDeleteColumn || 'Delete Column', action: () => editor.chain().focus().deleteColumn().run(), icon: '−⫼' },\n { label: labels.tableAddRowBefore || 'Add Row Before', action: () => editor.chain().focus().addRowBefore().run(), icon: '↑+' },\n { label: labels.tableAddRowAfter || 'Add Row After', action: () => editor.chain().focus().addRowAfter().run(), icon: '+↓' },\n { label: labels.tableDeleteRow || 'Delete Row', action: () => editor.chain().focus().deleteRow().run(), icon: '−═' },\n { label: labels.tableMergeCells || 'Merge Cells', action: () => editor.chain().focus().mergeCells().run(), icon: '⊞' },\n { label: labels.tableSplitCell || 'Split Cell', action: () => editor.chain().focus().splitCell().run(), icon: '⊟' },\n { label: labels.tableDelete || 'Delete Table', action: () => editor.chain().focus().deleteTable().run(), icon: '🗑' },\n ];\n\n return (\n <div ref={ref} className=\"rte-toolbar__template-menu\">\n <button\n type=\"button\"\n className={`rte-toolbar__btn ${isOpen ? 'rte-toolbar__btn--active' : ''}`}\n onClick={() => setIsOpen(!isOpen)}\n disabled={!isInTable}\n title={labels.tableOps || 'Table Operations'}\n style={{ width: 'auto', padding: '0 6px', gap: '2px', display: 'inline-flex', alignItems: 'center', opacity: isInTable ? 1 : 0.4 }}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" />\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\" /><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\" />\n <line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\" /><line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\" />\n </svg>\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n {isOpen && isInTable && (\n <div className=\"rte-toolbar__template-dropdown\">\n <div className=\"rte-toolbar__template-group-label\">Columns</div>\n {actions.slice(0, 3).map((a, i) => (\n <button key={i} type=\"button\" className=\"rte-toolbar__template-item\" onClick={() => { a.action(); setIsOpen(false); }}>\n <span className=\"rte-toolbar__template-icon\">{a.icon}</span>\n <span>{a.label}</span>\n </button>\n ))}\n <div className=\"rte-toolbar__template-group-label\">Rows</div>\n {actions.slice(3, 6).map((a, i) => (\n <button key={i} type=\"button\" className=\"rte-toolbar__template-item\" onClick={() => { a.action(); setIsOpen(false); }}>\n <span className=\"rte-toolbar__template-icon\">{a.icon}</span>\n <span>{a.label}</span>\n </button>\n ))}\n <div className=\"rte-toolbar__template-group-label\">Merge / Split</div>\n {actions.slice(6, 8).map((a, i) => (\n <button key={i} type=\"button\" className=\"rte-toolbar__template-item\" onClick={() => { a.action(); setIsOpen(false); }}>\n <span className=\"rte-toolbar__template-icon\">{a.icon}</span>\n <span>{a.label}</span>\n </button>\n ))}\n <div className=\"rte-toolbar__template-group-label\">Table</div>\n {actions.slice(8).map((a, i) => (\n <button key={i} type=\"button\" className=\"rte-toolbar__template-item rte-toolbar__template-item--danger\" onClick={() => { a.action(); setIsOpen(false); }}>\n <span className=\"rte-toolbar__template-icon\">{a.icon}</span>\n <span>{a.label}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n};\n"],"mappings":";;AASA,IAAa,IAAA,CAA6C,EAAE,QAAA,GAAQ,QAAA,EAAA,MAAa;AAC/E,QAAM,CAAC,GAAQ,CAAA,IAAa,EAAS,EAAK,GACpC,IAAM,EAAuB,IAAI;AAEvC,EAAA,EAAA,MAAgB;AACd,UAAM,IAAA,CAAW,MAAkB;AACjC,MAAI,EAAI,WAAW,CAAC,EAAI,QAAQ,SAAS,EAAE,MAAc,KACvD,EAAU,EAAK;AAAA,IAEnB;AACA,oBAAS,iBAAiB,aAAa,CAAO,GAC9C,MAAa,SAAS,oBAAoB,aAAa,CAAO;AAAA,EAChE,GAAG,CAAC,CAAC;AAEL,QAAM,IAAY,EAAO,SAAS,OAAO,GAEnC,IAAiE;AAAA,IACrE;AAAA,MAAE,OAAO,EAAO,wBAAwB;AAAA,MAAqB,QAAA,MAAc,EAAO,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,IAAI;AAAA,MAAG,MAAM;AAAA,IAAK;AAAA,IACtI;AAAA,MAAE,OAAO,EAAO,uBAAuB;AAAA,MAAoB,QAAA,MAAc,EAAO,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,IAAI;AAAA,MAAG,MAAM;AAAA,IAAK;AAAA,IACnI;AAAA,MAAE,OAAO,EAAO,qBAAqB;AAAA,MAAiB,QAAA,MAAc,EAAO,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI;AAAA,MAAG,MAAM;AAAA,IAAK;AAAA,IAC5H;AAAA,MAAE,OAAO,EAAO,qBAAqB;AAAA,MAAkB,QAAA,MAAc,EAAO,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI;AAAA,MAAG,MAAM;AAAA,IAAK;AAAA,IAC7H;AAAA,MAAE,OAAO,EAAO,oBAAoB;AAAA,MAAiB,QAAA,MAAc,EAAO,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI;AAAA,MAAG,MAAM;AAAA,IAAK;AAAA,IAC1H;AAAA,MAAE,OAAO,EAAO,kBAAkB;AAAA,MAAc,QAAA,MAAc,EAAO,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI;AAAA,MAAG,MAAM;AAAA,IAAK;AAAA,IACnH;AAAA,MAAE,OAAO,EAAO,mBAAmB;AAAA,MAAe,QAAA,MAAc,EAAO,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI;AAAA,MAAG,MAAM;AAAA,IAAI;AAAA,IACrH;AAAA,MAAE,OAAO,EAAO,kBAAkB;AAAA,MAAc,QAAA,MAAc,EAAO,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI;AAAA,MAAG,MAAM;AAAA,IAAI;AAAA,IAClH;AAAA,MAAE,OAAO,EAAO,eAAe;AAAA,MAAgB,QAAA,MAAc,EAAO,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI;AAAA,MAAG,MAAM;AAAA,IAAK;AAAA,EACtH;AAEA,SACE,gBAAA,EAAC,OAAD;AAAA,IAAU,KAAA;AAAA,IAAK,WAAU;AAAA,
|
|
1
|
+
{"version":3,"file":"TableOpsMenu.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/Toolbar/TableOpsMenu.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from 'react';\nimport type { Editor } from '@tiptap/react';\nimport type { RichTextEditorLabels } from '../types';\n\ninterface TableOpsMenuProps {\n editor: Editor;\n labels: RichTextEditorLabels;\n}\n\nexport const TableOpsMenu: React.FC<TableOpsMenuProps> = ({ editor, labels }) => {\n const [isOpen, setIsOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, []);\n\n const isInTable = editor.isActive('table');\n\n const actions: { label: string; action: () => void; icon: string }[] = [\n { label: labels.tableAddColumnBefore || 'Add Column Before', action: () => editor.chain().focus().addColumnBefore().run(), icon: '⇤+' },\n { label: labels.tableAddColumnAfter || 'Add Column After', action: () => editor.chain().focus().addColumnAfter().run(), icon: '+⇥' },\n { label: labels.tableDeleteColumn || 'Delete Column', action: () => editor.chain().focus().deleteColumn().run(), icon: '−⫼' },\n { label: labels.tableAddRowBefore || 'Add Row Before', action: () => editor.chain().focus().addRowBefore().run(), icon: '↑+' },\n { label: labels.tableAddRowAfter || 'Add Row After', action: () => editor.chain().focus().addRowAfter().run(), icon: '+↓' },\n { label: labels.tableDeleteRow || 'Delete Row', action: () => editor.chain().focus().deleteRow().run(), icon: '−═' },\n { label: labels.tableMergeCells || 'Merge Cells', action: () => editor.chain().focus().mergeCells().run(), icon: '⊞' },\n { label: labels.tableSplitCell || 'Split Cell', action: () => editor.chain().focus().splitCell().run(), icon: '⊟' },\n { label: labels.tableDelete || 'Delete Table', action: () => editor.chain().focus().deleteTable().run(), icon: '🗑' },\n ];\n\n return (\n <div ref={ref} className=\"rte-toolbar__template-menu\">\n <button\n type=\"button\"\n className={`rte-toolbar__btn ${isOpen ? 'rte-toolbar__btn--active' : ''}`}\n onClick={() => setIsOpen(!isOpen)}\n disabled={!isInTable}\n title={labels.tableOps || 'Table Operations'}\n style={{ width: 'auto', padding: '0 6px', gap: '2px', display: 'inline-flex', alignItems: 'center', opacity: isInTable ? 1 : 0.4 }}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" />\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\" /><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\" />\n <line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\" /><line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\" />\n </svg>\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </button>\n {isOpen && isInTable && (\n <div className=\"rte-toolbar__template-dropdown\">\n <div className=\"rte-toolbar__template-group-label\">Columns</div>\n {actions.slice(0, 3).map((a, i) => (\n <button key={i} type=\"button\" className=\"rte-toolbar__template-item\" onClick={() => { a.action(); setIsOpen(false); }}>\n <span className=\"rte-toolbar__template-icon\">{a.icon}</span>\n <span>{a.label}</span>\n </button>\n ))}\n <div className=\"rte-toolbar__template-group-label\">Rows</div>\n {actions.slice(3, 6).map((a, i) => (\n <button key={i} type=\"button\" className=\"rte-toolbar__template-item\" onClick={() => { a.action(); setIsOpen(false); }}>\n <span className=\"rte-toolbar__template-icon\">{a.icon}</span>\n <span>{a.label}</span>\n </button>\n ))}\n <div className=\"rte-toolbar__template-group-label\">Merge / Split</div>\n {actions.slice(6, 8).map((a, i) => (\n <button key={i} type=\"button\" className=\"rte-toolbar__template-item\" onClick={() => { a.action(); setIsOpen(false); }}>\n <span className=\"rte-toolbar__template-icon\">{a.icon}</span>\n <span>{a.label}</span>\n </button>\n ))}\n <div className=\"rte-toolbar__template-group-label\">Table</div>\n {actions.slice(8).map((a, i) => (\n <button key={i} type=\"button\" className=\"rte-toolbar__template-item rte-toolbar__template-item--danger\" onClick={() => { a.action(); setIsOpen(false); }}>\n <span className=\"rte-toolbar__template-icon\">{a.icon}</span>\n <span>{a.label}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n};\n"],"mappings":"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"}
|