dishui 0.0.72 → 0.0.74

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.
Files changed (100) hide show
  1. package/dist/components/Button/index.d.ts +4 -4
  2. package/dist/components/Button/index.js +18 -17
  3. package/dist/components/Button/index.js.map +1 -1
  4. package/dist/components/Card/Metric.d.ts +17 -0
  5. package/dist/components/Card/Metric2.js +50 -0
  6. package/dist/components/Card/Metric2.js.map +1 -0
  7. package/dist/components/Card/index.d.ts +3 -0
  8. package/dist/components/Card/index.js +118 -117
  9. package/dist/components/Card/index.js.map +1 -1
  10. package/dist/components/Group/index.d.ts +2 -0
  11. package/dist/components/GroupButton/index.d.ts +16 -0
  12. package/dist/components/GroupButton/index.js +41 -0
  13. package/dist/components/GroupButton/index.js.map +1 -0
  14. package/dist/components/GroupedTable/index.d.ts +38 -0
  15. package/dist/components/GroupedTable/index.js +92 -0
  16. package/dist/components/GroupedTable/index.js.map +1 -0
  17. package/dist/components/Layout/index.d.ts +4 -2
  18. package/dist/components/Layout/index.js +1 -1
  19. package/dist/components/Layout/index.js.map +1 -1
  20. package/dist/components/NavigationList/index.d.ts +17 -0
  21. package/dist/components/NavigationList/index.js +48 -0
  22. package/dist/components/NavigationList/index.js.map +1 -0
  23. package/dist/components/Section/index.d.ts +28 -0
  24. package/dist/components/Section/index.js +58 -0
  25. package/dist/components/Section/index.js.map +1 -0
  26. package/dist/components/Select/index.d.ts +2 -0
  27. package/dist/components/Select/index.js +83 -82
  28. package/dist/components/Select/index.js.map +1 -1
  29. package/dist/components/SidebarToggleButton/index.d.ts +16 -1
  30. package/dist/components/SidebarToggleButton/index.js +90 -30
  31. package/dist/components/SidebarToggleButton/index.js.map +1 -1
  32. package/dist/components/Skeleton/index.d.ts +7 -0
  33. package/dist/components/Skeleton/index.js +21 -0
  34. package/dist/components/Skeleton/index.js.map +1 -0
  35. package/dist/components/Tree/Tree.js +5 -2
  36. package/dist/components/Tree/Tree.js.map +1 -1
  37. package/dist/components/pro/RichTextEditor/AIRewrite.js +114 -72
  38. package/dist/components/pro/RichTextEditor/AIRewrite.js.map +1 -1
  39. package/dist/components/pro/RichTextEditor/BlockHandle.js +315 -196
  40. package/dist/components/pro/RichTextEditor/BlockHandle.js.map +1 -1
  41. package/dist/components/pro/RichTextEditor/BubbleToolbar.d.ts +1 -1
  42. package/dist/components/pro/RichTextEditor/BubbleToolbar.js +156 -39
  43. package/dist/components/pro/RichTextEditor/BubbleToolbar.js.map +1 -1
  44. package/dist/components/pro/RichTextEditor/CommentPanel.d.ts +2 -1
  45. package/dist/components/pro/RichTextEditor/CommentPanel.js +100 -81
  46. package/dist/components/pro/RichTextEditor/CommentPanel.js.map +1 -1
  47. package/dist/components/pro/RichTextEditor/CommentPopover.d.ts +2 -1
  48. package/dist/components/pro/RichTextEditor/CommentPopover.js +92 -68
  49. package/dist/components/pro/RichTextEditor/CommentPopover.js.map +1 -1
  50. package/dist/components/pro/RichTextEditor/RichTextEditor.js +24 -22
  51. package/dist/components/pro/RichTextEditor/RichTextEditor.js.map +1 -1
  52. package/dist/components/pro/RichTextEditor/SearchReplace.d.ts +7 -0
  53. package/dist/components/pro/RichTextEditor/SlashMenu.js +132 -73
  54. package/dist/components/pro/RichTextEditor/SlashMenu.js.map +1 -1
  55. package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.d.ts +2 -0
  56. package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js +9 -9
  57. package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js.map +1 -1
  58. package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js +8 -13
  59. package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js.map +1 -1
  60. package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js +22 -3
  61. package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js.map +1 -1
  62. package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.d.ts +1 -1
  63. package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js +346 -313
  64. package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js.map +1 -1
  65. package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js +120 -146
  66. package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js.map +1 -1
  67. package/dist/components/pro/RichTextEditor/extensions/CommentMark.js +2 -2
  68. package/dist/components/pro/RichTextEditor/extensions/CommentMark.js.map +1 -1
  69. package/dist/components/pro/RichTextEditor/extensions/FloatingDialog.js +178 -163
  70. package/dist/components/pro/RichTextEditor/extensions/FloatingDialog.js.map +1 -1
  71. package/dist/components/pro/RichTextEditor/extensions/FontSize.js +8 -5
  72. package/dist/components/pro/RichTextEditor/extensions/FontSize.js.map +1 -1
  73. package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.d.ts +6 -0
  74. package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js +85 -74
  75. package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js.map +1 -1
  76. package/dist/components/pro/RichTextEditor/searchUtils.d.ts +23 -0
  77. package/dist/contexts/AppContext.js +47 -45
  78. package/dist/contexts/AppContext.js.map +1 -1
  79. package/dist/dishui.css +1 -1
  80. package/dist/index-nostyled.d.ts +11 -1
  81. package/dist/index.d.ts +11 -1
  82. package/dist/index.js +119 -114
  83. package/dist/layouts/MainLayout.js +9 -10
  84. package/dist/layouts/MainLayout.js.map +1 -1
  85. package/dist/layouts/Sidebar.d.ts +9 -0
  86. package/dist/layouts/Sidebar.js +99 -80
  87. package/dist/layouts/Sidebar.js.map +1 -1
  88. package/dist/layouts/headbar/Headbar.d.ts +1 -1
  89. package/dist/layouts/headbar/Headbar.js +2 -2
  90. package/dist/layouts/headbar/Headbar.js.map +1 -1
  91. package/dist/lite.d.ts +19 -1
  92. package/dist/lite.js +17 -8
  93. package/dist/styles/themeStyles.js +6 -6
  94. package/dist/styles/themeStyles.js.map +1 -1
  95. package/dist/utils/i18n.d.ts +3 -0
  96. package/dist/utils/i18n.js +78 -0
  97. package/dist/utils/i18n.js.map +1 -1
  98. package/dist/utils/menu.js +23 -6
  99. package/dist/utils/menu.js.map +1 -1
  100. package/package.json +8 -2
@@ -1 +1 @@
1
- {"version":3,"file":"BlockHandle.js","names":[],"sources":["../../../../src/components/pro/RichTextEditor/BlockHandle.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback } from 'react';\nimport type { Editor } from '@tiptap/react';\n\ninterface BlockHandleProps {\n editor: Editor;\n}\n\ninterface BlockInfo {\n pos: number;\n size: number;\n domTop: number;\n domBottom: number;\n}\n\nconst BlockHandle: React.FC<BlockHandleProps> = ({ editor }) => {\n const [visible, setVisible] = useState(false);\n const [handleTop, setHandleTop] = useState(0);\n const [showMenu, setShowMenu] = useState(false);\n const [currentBlockIndex, setCurrentBlockIndex] = useState(-1);\n const [isDragging, setIsDragging] = useState(false);\n const [dropIndicator, setDropIndicator] = useState<{ top: number } | null>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n const handleRef = useRef<HTMLDivElement>(null);\n const hideTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const hoveringHandle = useRef(false);\n\n const cancelHide = useCallback(() => {\n if (hideTimer.current) {\n clearTimeout(hideTimer.current);\n hideTimer.current = null;\n }\n }, []);\n\n const scheduleHide = useCallback(() => {\n cancelHide();\n hideTimer.current = setTimeout(() => {\n if (!hoveringHandle.current && !showMenu && !isDragging) {\n setVisible(false);\n }\n }, 200);\n }, [cancelHide, showMenu, isDragging]);\n\n const getBlocks = useCallback((): BlockInfo[] => {\n const wrapperEl = editor.view.dom.closest('.rte-editor-wrapper') as HTMLElement | null;\n if (!wrapperEl) return [];\n const wrapperRect = wrapperEl.getBoundingClientRect();\n const scrollTop = wrapperEl.scrollTop;\n const blocks: BlockInfo[] = [];\n\n editor.state.doc.forEach((node, offset) => {\n const domNode = editor.view.nodeDOM(offset) as HTMLElement | null;\n if (domNode) {\n const rect = domNode.getBoundingClientRect();\n blocks.push({\n pos: offset,\n size: node.nodeSize,\n domTop: rect.top - wrapperRect.top + scrollTop,\n domBottom: rect.bottom - wrapperRect.top + scrollTop,\n });\n }\n });\n return blocks;\n }, [editor]);\n\n const findBlockByClientY = useCallback((clientY: number): number => {\n const wrapperEl = editor.view.dom.closest('.rte-editor-wrapper') as HTMLElement | null;\n if (!wrapperEl) return -1;\n const wrapperRect = wrapperEl.getBoundingClientRect();\n const y = clientY - wrapperRect.top + wrapperEl.scrollTop;\n\n const blocks = getBlocks();\n for (let i = 0; i < blocks.length; i++) {\n const mid = (blocks[i].domTop + blocks[i].domBottom) / 2;\n if (y < mid) return i;\n }\n return blocks.length - 1;\n }, [editor, getBlocks]);\n\n const findDropSlot = useCallback((clientY: number): { slotIndex: number; indicatorTop: number } | null => {\n const wrapperEl = editor.view.dom.closest('.rte-editor-wrapper') as HTMLElement | null;\n if (!wrapperEl) return null;\n const wrapperRect = wrapperEl.getBoundingClientRect();\n const y = clientY - wrapperRect.top + wrapperEl.scrollTop;\n\n const blocks = getBlocks();\n if (blocks.length === 0) return null;\n\n let bestSlot = 0;\n let bestDist = Infinity;\n let bestTop = blocks[0].domTop;\n\n for (let i = 0; i <= blocks.length; i++) {\n const edgeY = i < blocks.length ? blocks[i].domTop : blocks[blocks.length - 1].domBottom;\n const dist = Math.abs(y - edgeY);\n if (dist < bestDist) {\n bestDist = dist;\n bestSlot = i;\n bestTop = edgeY;\n }\n }\n\n return { slotIndex: bestSlot, indicatorTop: bestTop };\n }, [getBlocks]);\n\n useEffect(() => {\n const wrapperEl = editor.view.dom.closest('.rte-editor-wrapper') as HTMLElement | null;\n if (!wrapperEl) return;\n\n const handleMouseMove = (e: MouseEvent) => {\n if (isDragging) return;\n\n const idx = findBlockByClientY(e.clientY);\n if (idx < 0) return;\n\n const blocks = getBlocks();\n if (idx >= blocks.length) return;\n\n setHandleTop(blocks[idx].domTop);\n setCurrentBlockIndex(idx);\n cancelHide();\n setVisible(true);\n };\n\n const handleMouseLeave = () => {\n if (!isDragging) scheduleHide();\n };\n\n wrapperEl.addEventListener('mousemove', handleMouseMove);\n wrapperEl.addEventListener('mouseleave', handleMouseLeave);\n return () => {\n wrapperEl.removeEventListener('mousemove', handleMouseMove);\n wrapperEl.removeEventListener('mouseleave', handleMouseLeave);\n cancelHide();\n };\n }, [editor, cancelHide, scheduleHide, isDragging, findBlockByClientY, getBlocks]);\n\n useEffect(() => {\n if (!showMenu) return;\n const handler = (e: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) {\n setShowMenu(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [showMenu]);\n\n const addBlockBelow = useCallback(() => {\n const blocks = getBlocks();\n if (currentBlockIndex < 0 || currentBlockIndex >= blocks.length) return;\n const block = blocks[currentBlockIndex];\n const insertPos = block.pos + block.size;\n try {\n editor.chain().focus().insertContentAt(insertPos, { type: 'paragraph' }).run();\n editor.commands.focus(insertPos + 1);\n } catch { /* noop */ }\n setShowMenu(false);\n }, [editor, currentBlockIndex, getBlocks]);\n\n const handleDragStart = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n const dragIdx = currentBlockIndex;\n const blocks = getBlocks();\n if (dragIdx < 0 || dragIdx >= blocks.length) return;\n\n setIsDragging(true);\n\n const handleDragMove = (ev: MouseEvent) => {\n const slot = findDropSlot(ev.clientY);\n if (slot) {\n setDropIndicator({ top: slot.indicatorTop });\n }\n };\n\n const handleDragEnd = (ev: MouseEvent) => {\n document.removeEventListener('mousemove', handleDragMove);\n document.removeEventListener('mouseup', handleDragEnd);\n setIsDragging(false);\n setDropIndicator(null);\n\n const freshBlocks = getBlocks();\n if (dragIdx >= freshBlocks.length) return;\n\n const slot = findDropSlot(ev.clientY);\n if (!slot) return;\n\n let targetSlot = slot.slotIndex;\n\n // No-op: dropping at the same position or one below (no actual move)\n if (targetSlot === dragIdx || targetSlot === dragIdx + 1) return;\n\n const sourceBlock = freshBlocks[dragIdx];\n const sourceNode = editor.state.doc.nodeAt(sourceBlock.pos);\n if (!sourceNode) return;\n\n // Compute the insert position (before which block, or at end)\n let insertBefore: number;\n if (targetSlot < freshBlocks.length) {\n insertBefore = freshBlocks[targetSlot].pos;\n } else {\n const last = freshBlocks[freshBlocks.length - 1];\n insertBefore = last.pos + last.size;\n }\n\n const sourceFrom = sourceBlock.pos;\n const sourceTo = sourceBlock.pos + sourceBlock.size;\n const content = editor.state.doc.slice(sourceFrom, sourceTo).content;\n\n const { tr } = editor.state;\n\n if (targetSlot <= dragIdx) {\n // Moving up: delete source first (it's after target), then insert\n tr.delete(sourceFrom, sourceTo);\n const mapped = tr.mapping.map(insertBefore);\n tr.insert(mapped, content);\n } else {\n // Moving down: insert first (target is after source), then delete\n tr.insert(insertBefore, content);\n tr.delete(\n tr.mapping.map(sourceFrom),\n tr.mapping.map(sourceTo)\n );\n }\n\n editor.view.dispatch(tr);\n };\n\n document.addEventListener('mousemove', handleDragMove);\n document.addEventListener('mouseup', handleDragEnd);\n }, [editor, currentBlockIndex, getBlocks, findDropSlot]);\n\n const menuItems = [\n { label: 'Text', action: () => { addBlockBelow(); } },\n { label: 'Heading 1', action: () => { addBlockBelow(); editor.chain().focus().toggleHeading({ level: 1 }).run(); } },\n { label: 'Heading 2', action: () => { addBlockBelow(); editor.chain().focus().toggleHeading({ level: 2 }).run(); } },\n { label: 'Heading 3', action: () => { addBlockBelow(); editor.chain().focus().toggleHeading({ level: 3 }).run(); } },\n { label: 'Bullet List', action: () => { addBlockBelow(); editor.chain().focus().toggleBulletList().run(); } },\n { label: 'Numbered List', action: () => { addBlockBelow(); editor.chain().focus().toggleOrderedList().run(); } },\n { label: 'Task List', action: () => { addBlockBelow(); editor.chain().focus().toggleTaskList().run(); } },\n { label: 'Blockquote', action: () => { addBlockBelow(); editor.chain().focus().toggleBlockquote().run(); } },\n { label: 'Code Block', action: () => { addBlockBelow(); editor.chain().focus().toggleNode('codeBlock', 'paragraph').run(); } },\n { label: 'Divider', action: () => { addBlockBelow(); editor.chain().focus().setHorizontalRule().run(); } },\n { label: 'Table 3×3', action: () => { addBlockBelow(); editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run(); } },\n ];\n\n if (!visible && !showMenu && !isDragging) return null;\n\n return (\n <>\n <div\n ref={handleRef}\n className=\"rte-block-handle\"\n style={{ top: handleTop }}\n onMouseEnter={() => { hoveringHandle.current = true; cancelHide(); }}\n onMouseLeave={() => { hoveringHandle.current = false; if (!isDragging) scheduleHide(); }}\n onMouseDown={(e) => { e.stopPropagation(); e.preventDefault(); }}\n >\n <button\n type=\"button\"\n className=\"rte-block-handle__btn rte-block-handle__btn--add\"\n onMouseDown={(e) => { e.stopPropagation(); e.preventDefault(); }}\n onClick={(e) => { e.stopPropagation(); setShowMenu(!showMenu); }}\n title=\"Add block\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" /><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" /></svg>\n </button>\n <button\n type=\"button\"\n className={`rte-block-handle__btn rte-block-handle__btn--drag ${isDragging ? 'rte-block-handle__btn--dragging' : ''}`}\n title=\"Drag to reorder\"\n onMouseDown={handleDragStart}\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <circle cx=\"9\" cy=\"6\" r=\"1.5\" /><circle cx=\"15\" cy=\"6\" r=\"1.5\" />\n <circle cx=\"9\" cy=\"12\" r=\"1.5\" /><circle cx=\"15\" cy=\"12\" r=\"1.5\" />\n <circle cx=\"9\" cy=\"18\" r=\"1.5\" /><circle cx=\"15\" cy=\"18\" r=\"1.5\" />\n </svg>\n </button>\n </div>\n\n {showMenu && (\n <div\n ref={menuRef}\n className=\"rte-block-handle__menu\"\n style={{ top: handleTop + 28 }}\n onMouseDown={(e) => e.stopPropagation()}\n >\n {menuItems.map((item) => (\n <button\n key={item.label}\n type=\"button\"\n className=\"rte-block-handle__menu-item\"\n onMouseDown={(e) => e.stopPropagation()}\n onClick={(e) => { e.stopPropagation(); item.action(); setShowMenu(false); }}\n >\n {item.label}\n </button>\n ))}\n </div>\n )}\n\n {isDragging && dropIndicator && (\n <div className=\"rte-block-handle__drop-indicator\" style={{ top: dropIndicator.top }} />\n )}\n </>\n );\n};\n\nexport default BlockHandle;\n"],"mappings":"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"}
1
+ {"version":3,"file":"BlockHandle.js","names":[],"sources":["../../../../src/components/pro/RichTextEditor/BlockHandle.tsx"],"sourcesContent":["import React, { useState, useEffect, useLayoutEffect, useRef, useCallback } from 'react';\nimport type { Editor } from '@tiptap/react';\nimport type { JSONContent } from '@tiptap/core';\nimport type { Node as ProseMirrorNode } from '@tiptap/pm/model';\nimport { NodeSelection, Selection } from '@tiptap/pm/state';\n\ninterface BlockHandleProps {\n editor: Editor;\n}\n\ninterface BlockInfo {\n pos: number;\n size: number;\n domTop: number;\n domBottom: number;\n}\n\nconst BlockHandle: React.FC<BlockHandleProps> = ({ editor }) => {\n const [visible, setVisible] = useState(false);\n const [handleTop, setHandleTop] = useState(0);\n const [showMenu, setShowMenu] = useState(false);\n const [menuMode, setMenuMode] = useState<'add' | 'actions'>('add');\n const [menuPos, setMenuPos] = useState({ left: 4, top: 0 });\n const target = useRef<{ pos: number; node: ProseMirrorNode } | null>(null);\n const dragCleanup = useRef<(() => void) | null>(null);\n const suppressClick = useRef(false);\n const [currentBlockIndex, setCurrentBlockIndex] = useState(-1);\n const [isDragging, setIsDragging] = useState(false);\n const [dropIndicator, setDropIndicator] = useState<{ top: number } | null>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n const handleRef = useRef<HTMLDivElement>(null);\n const hideTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const hoveringHandle = useRef(false);\n\n const cancelHide = useCallback(() => {\n if (hideTimer.current) {\n clearTimeout(hideTimer.current);\n hideTimer.current = null;\n }\n }, []);\n\n const scheduleHide = useCallback(() => {\n cancelHide();\n hideTimer.current = setTimeout(() => {\n if (!hoveringHandle.current && !showMenu && !isDragging && !handleRef.current?.contains(document.activeElement) && !menuRef.current?.contains(document.activeElement)) {\n setVisible(false);\n }\n }, 200);\n }, [cancelHide, showMenu, isDragging]);\n\n const getBlocks = useCallback((): BlockInfo[] => {\n if (editor.isDestroyed) return [];\n const wrapperEl = editor.view.dom.closest('.rte-editor-wrapper') as HTMLElement | null;\n if (!wrapperEl) return [];\n const wrapperRect = wrapperEl.getBoundingClientRect();\n const scrollTop = wrapperEl.scrollTop;\n const blocks: BlockInfo[] = [];\n\n editor.state.doc.forEach((node, offset) => {\n const domNode = editor.view.nodeDOM(offset) as HTMLElement | null;\n if (domNode instanceof HTMLElement) {\n const rect = domNode.getBoundingClientRect();\n blocks.push({\n pos: offset,\n size: node.nodeSize,\n domTop: rect.top - wrapperRect.top - wrapperEl.clientTop + scrollTop,\n domBottom: rect.bottom - wrapperRect.top - wrapperEl.clientTop + scrollTop,\n });\n }\n });\n return blocks;\n }, [editor]);\n\n const findBlockByClientY = useCallback((clientY: number): number => {\n const wrapperEl = editor.view.dom.closest('.rte-editor-wrapper') as HTMLElement | null;\n if (!wrapperEl) return -1;\n const wrapperRect = wrapperEl.getBoundingClientRect();\n const y = clientY - wrapperRect.top - wrapperEl.clientTop + wrapperEl.scrollTop;\n return getBlocks().findIndex((block) => y >= block.domTop && y <= block.domBottom);\n }, [editor, getBlocks]);\n\n const findDropSlot = useCallback((clientY: number): { slotIndex: number; indicatorTop: number } | null => {\n const wrapperEl = editor.view.dom.closest('.rte-editor-wrapper') as HTMLElement | null;\n if (!wrapperEl) return null;\n const wrapperRect = wrapperEl.getBoundingClientRect();\n const y = clientY - wrapperRect.top - wrapperEl.clientTop + wrapperEl.scrollTop;\n\n const blocks = getBlocks();\n if (blocks.length === 0) return null;\n\n let bestSlot = 0;\n let bestDist = Infinity;\n let bestTop = blocks[0].domTop;\n\n for (let i = 0; i <= blocks.length; i++) {\n const edgeY = i < blocks.length ? blocks[i].domTop : blocks[blocks.length - 1].domBottom;\n const dist = Math.abs(y - edgeY);\n if (dist < bestDist) {\n bestDist = dist;\n bestSlot = i;\n bestTop = edgeY;\n }\n }\n\n return { slotIndex: bestSlot, indicatorTop: bestTop };\n }, [editor, getBlocks]);\n\n useEffect(() => {\n const wrapperEl = editor.view.dom.closest('.rte-editor-wrapper') as HTMLElement | null;\n if (!wrapperEl) return;\n\n const handleMouseMove = (e: MouseEvent) => {\n if (isDragging || dragCleanup.current || showMenu || hoveringHandle.current || !editor.isEditable || editor.view.composing) return;\n if (handleRef.current?.contains(e.target as Node) || menuRef.current?.contains(e.target as Node)) return;\n\n const idx = findBlockByClientY(e.clientY);\n if (idx < 0) { scheduleHide(); return; }\n\n const blocks = getBlocks();\n if (idx >= blocks.length) return;\n\n // Keep the handle reachable when the top of a long block has scrolled away.\n const viewportTop = Math.max(0, -wrapperEl.getBoundingClientRect().top);\n setHandleTop(Math.max(blocks[idx].domTop, wrapperEl.scrollTop + viewportTop + 4));\n setCurrentBlockIndex(idx);\n const node = editor.state.doc.nodeAt(blocks[idx].pos);\n target.current = node ? { pos: blocks[idx].pos, node } : null;\n cancelHide();\n setVisible(true);\n };\n\n const handleMouseLeave = () => {\n if (!isDragging) scheduleHide();\n };\n\n wrapperEl.addEventListener('mousemove', handleMouseMove);\n wrapperEl.addEventListener('mouseleave', handleMouseLeave);\n return () => {\n wrapperEl.removeEventListener('mousemove', handleMouseMove);\n wrapperEl.removeEventListener('mouseleave', handleMouseLeave);\n cancelHide();\n };\n }, [editor, cancelHide, scheduleHide, isDragging, showMenu, findBlockByClientY, getBlocks]);\n\n useEffect(() => {\n if (!showMenu) return;\n const handler = (e: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node) && !handleRef.current?.contains(e.target as Node)) {\n hoveringHandle.current = false;\n setShowMenu(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [showMenu]);\n\n const getTarget = useCallback(() => {\n const block = target.current;\n if (editor.isDestroyed || !editor.isEditable || editor.view.composing || !block || editor.state.doc.nodeAt(block.pos) !== block.node) return null;\n return block;\n }, [editor]);\n\n const addBlockBelow = useCallback((content: JSONContent) => {\n const block = getTarget();\n if (!block) return;\n const insertPos = block.pos + block.node.nodeSize;\n editor.chain().focus().insertContentAt(insertPos, content).command(({ tr }) => {\n tr.setSelection(Selection.near(tr.doc.resolve(insertPos + 1)));\n return true;\n }).run();\n setShowMenu(false);\n }, [editor, getTarget]);\n\n const moveBlock = useCallback((slotIndex: number) => {\n const block = getTarget();\n const blocks = getBlocks();\n if (!block || slotIndex < 0 || slotIndex > blocks.length) return;\n const index = blocks.findIndex((item) => item.pos === block.pos);\n if (index < 0 || slotIndex === index || slotIndex === index + 1) return;\n const insertBefore = blocks[slotIndex]?.pos ?? editor.state.doc.content.size;\n const tr = editor.state.tr.delete(block.pos, block.pos + block.node.nodeSize);\n const destination = tr.mapping.map(insertBefore);\n tr.insert(destination, block.node);\n tr.setSelection(NodeSelection.isSelectable(block.node)\n ? NodeSelection.create(tr.doc, destination)\n : Selection.near(tr.doc.resolve(destination)));\n editor.view.dispatch(tr.scrollIntoView());\n editor.view.focus();\n }, [editor, getTarget, getBlocks]);\n\n useEffect(() => {\n // Invalidate instead of trusting an index after external edits, undo or collaboration.\n const reset = () => {\n dragCleanup.current?.();\n target.current = null;\n hoveringHandle.current = false;\n setVisible(false);\n setShowMenu(false);\n cancelHide();\n };\n const transaction = ({ transaction: tr }: { transaction: import('@tiptap/pm/state').Transaction }) => {\n if (tr.docChanged || !editor.isEditable) reset();\n };\n const scroll = (event: Event) => {\n if (!(event.target instanceof Node) || !menuRef.current?.contains(event.target)) reset();\n };\n editor.on('transaction', transaction);\n const dom = editor.view.dom;\n dom.addEventListener('compositionstart', reset);\n window.addEventListener('scroll', scroll, true);\n window.addEventListener('resize', reset);\n window.addEventListener('blur', reset);\n return () => {\n editor.off('transaction', transaction);\n dom.removeEventListener('compositionstart', reset);\n window.removeEventListener('scroll', scroll, true);\n window.removeEventListener('resize', reset);\n window.removeEventListener('blur', reset);\n dragCleanup.current?.();\n cancelHide();\n };\n }, [editor, cancelHide]);\n\n useLayoutEffect(() => {\n if (!showMenu) return;\n const menu = menuRef.current;\n const handle = handleRef.current;\n const wrapper = editor.view.dom.closest('.rte-editor-wrapper') as HTMLElement | null;\n if (!menu || !handle || !wrapper) return;\n const rect = wrapper.getBoundingClientRect();\n const anchor = handle.getBoundingClientRect();\n const left = Math.max(8, rect.left + wrapper.clientLeft);\n const right = Math.min(window.innerWidth - 8, rect.right);\n const top = Math.max(8, rect.top + wrapper.clientTop);\n const bottom = Math.min(window.innerHeight - 8, rect.bottom);\n const below = bottom - anchor.bottom - 4;\n const above = anchor.top - top - 4;\n const flip = below < menu.scrollHeight && above > below;\n menu.style.maxHeight = `${Math.max(0, Math.min(320, flip ? above : below))}px`;\n menu.style.minWidth = '0';\n menu.style.width = `${Math.max(0, Math.min(220, right - left))}px`;\n setMenuPos({\n left: Math.max(left, Math.min(anchor.left, right - menu.offsetWidth)) - rect.left - wrapper.clientLeft + wrapper.scrollLeft,\n top: (flip ? anchor.top - menu.offsetHeight - 4 : anchor.bottom + 4) - rect.top - wrapper.clientTop + wrapper.scrollTop,\n });\n const firstItem = menuMode === 'actions' ? 'button:not(:disabled)' : 'button';\n menu.querySelector<HTMLButtonElement>(firstItem)?.focus({ preventScroll: true });\n }, [editor, showMenu, menuMode]);\n\n const handleDragStart = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.button !== 0 || !getTarget()) return;\n dragCleanup.current?.();\n suppressClick.current = false;\n const startX = e.clientX;\n const startY = e.clientY;\n let moved = false;\n\n const handleDragMove = (ev: MouseEvent) => {\n if (!moved && Math.hypot(ev.clientX - startX, ev.clientY - startY) < 5) return;\n moved = true;\n suppressClick.current = true;\n setShowMenu(false);\n setIsDragging(true);\n const slot = findDropSlot(ev.clientY);\n if (slot) {\n setDropIndicator({ top: slot.indicatorTop });\n }\n };\n\n const cleanup = () => {\n document.removeEventListener('mousemove', handleDragMove);\n document.removeEventListener('mouseup', handleDragEnd);\n document.removeEventListener('keydown', cancel, true);\n dragCleanup.current = null;\n setIsDragging(false);\n setDropIndicator(null);\n };\n const cancel = (event: KeyboardEvent) => {\n if (event.key !== 'Escape') return;\n event.preventDefault();\n event.stopImmediatePropagation();\n suppressClick.current = true;\n cleanup();\n };\n const handleDragEnd = (ev: MouseEvent) => {\n cleanup();\n if (!moved) return;\n const rect = editor.view.dom.closest('.rte-editor-wrapper')?.getBoundingClientRect();\n if (!rect || ev.clientX < rect.left || ev.clientX > rect.right || ev.clientY < rect.top || ev.clientY > rect.bottom) return;\n const slot = findDropSlot(ev.clientY);\n if (slot) moveBlock(slot.slotIndex);\n };\n\n dragCleanup.current = cleanup;\n document.addEventListener('mousemove', handleDragMove);\n document.addEventListener('mouseup', handleDragEnd);\n document.addEventListener('keydown', cancel, true);\n }, [editor, getTarget, moveBlock, findDropSlot]);\n\n const paragraph = { type: 'paragraph' };\n const addItems: { label: string; content: JSONContent }[] = [\n { label: 'Text', content: paragraph },\n ...([1, 2, 3] as const).map((level) => ({ label: `Heading ${level}`, content: { type: 'heading', attrs: { level } } })),\n { label: 'Bullet List', content: { type: 'bulletList', content: [{ type: 'listItem', content: [paragraph] }] } },\n { label: 'Numbered List', content: { type: 'orderedList', content: [{ type: 'listItem', content: [paragraph] }] } },\n { label: 'Task List', content: { type: 'taskList', content: [{ type: 'taskItem', attrs: { checked: false }, content: [paragraph] }] } },\n { label: 'Blockquote', content: { type: 'blockquote', content: [paragraph] } },\n { label: 'Code Block', content: { type: 'codeBlock' } },\n { label: 'Divider', content: { type: 'horizontalRule' } },\n { label: 'Table 3×3', content: { type: 'table', content: Array.from({ length: 3 }, (_, row) => ({\n type: 'tableRow', content: Array.from({ length: 3 }, () => ({ type: row === 0 ? 'tableHeader' : 'tableCell', content: [paragraph] })),\n })) } },\n ];\n const menuItems: { label: string; content?: JSONContent; disabled?: boolean }[] = menuMode === 'add'\n ? addItems.filter((item) => editor.schema.nodes[item.content.type!])\n : [\n { label: 'Duplicate' },\n { label: 'Delete' },\n { label: 'Move up', disabled: currentBlockIndex <= 0 },\n { label: 'Move down', disabled: currentBlockIndex >= editor.state.doc.childCount - 1 },\n ];\n\n const executeMenuItem = (item: typeof menuItems[number]) => {\n if (item.disabled) return;\n const block = getTarget();\n if (!block) return;\n if (item.content) addBlockBelow(item.content);\n else if (item.label === 'Duplicate') {\n const pos = block.pos + block.node.nodeSize;\n const tr = editor.state.tr.insert(pos, block.node);\n tr.setSelection(Selection.near(tr.doc.resolve(pos + 1)));\n editor.view.dispatch(tr.scrollIntoView());\n editor.view.focus();\n } else if (item.label === 'Delete') {\n editor.chain().focus().deleteRange({ from: block.pos, to: block.pos + block.node.nodeSize }).run();\n } else if (item.label === 'Move up') moveBlock(currentBlockIndex - 1);\n else if (item.label === 'Move down') moveBlock(currentBlockIndex + 2);\n };\n\n if (!visible && !showMenu && !isDragging) return null;\n\n return (\n <>\n <div\n ref={handleRef}\n className=\"rte-block-handle\"\n style={{ top: handleTop }}\n onFocus={cancelHide}\n onBlur={scheduleHide}\n onMouseEnter={() => { hoveringHandle.current = true; cancelHide(); }}\n onMouseLeave={() => { hoveringHandle.current = false; if (!isDragging) scheduleHide(); }}\n onMouseDown={(e) => { e.stopPropagation(); e.preventDefault(); }}\n >\n <button\n type=\"button\"\n className=\"rte-block-handle__btn rte-block-handle__btn--add\"\n onMouseDown={(e) => { e.stopPropagation(); e.preventDefault(); }}\n onClick={(e) => { e.stopPropagation(); if (getTarget()) { setMenuMode('add'); setShowMenu(!showMenu || menuMode !== 'add'); } }}\n aria-label=\"Add block\"\n aria-haspopup=\"menu\"\n aria-expanded={showMenu && menuMode === 'add'}\n title=\"Add block\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" /><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" /></svg>\n </button>\n <button\n type=\"button\"\n className={`rte-block-handle__btn rte-block-handle__btn--drag ${isDragging ? 'rte-block-handle__btn--dragging' : ''}`}\n title=\"Drag to reorder or click for block actions\"\n aria-label=\"Block actions\"\n aria-haspopup=\"menu\"\n aria-expanded={showMenu && menuMode === 'actions'}\n onMouseDown={handleDragStart}\n onClick={(e) => {\n e.stopPropagation();\n if (suppressClick.current) { suppressClick.current = false; return; }\n if (getTarget()) { setMenuMode('actions'); setShowMenu(!showMenu || menuMode !== 'actions'); }\n }}\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <circle cx=\"9\" cy=\"6\" r=\"1.5\" /><circle cx=\"15\" cy=\"6\" r=\"1.5\" />\n <circle cx=\"9\" cy=\"12\" r=\"1.5\" /><circle cx=\"15\" cy=\"12\" r=\"1.5\" />\n <circle cx=\"9\" cy=\"18\" r=\"1.5\" /><circle cx=\"15\" cy=\"18\" r=\"1.5\" />\n </svg>\n </button>\n </div>\n\n {showMenu && (\n <div\n ref={menuRef}\n className=\"rte-block-handle__menu\"\n role=\"menu\"\n aria-label={menuMode === 'add' ? 'Add block' : 'Block actions'}\n style={{ ...menuPos, overflowY: 'auto' }}\n onMouseEnter={() => { hoveringHandle.current = true; cancelHide(); }}\n onMouseLeave={() => { hoveringHandle.current = false; }}\n onMouseDown={(e) => { e.stopPropagation(); e.preventDefault(); }}\n onKeyDown={(e) => {\n if (e.nativeEvent.isComposing || e.keyCode === 229) return;\n if (e.key === 'Escape' || e.key === 'Tab') {\n if (e.key === 'Escape') e.preventDefault();\n e.stopPropagation();\n hoveringHandle.current = false;\n setShowMenu(false);\n handleRef.current?.querySelector<HTMLButtonElement>(menuMode === 'add' ? '.rte-block-handle__btn--add' : '.rte-block-handle__btn--drag')?.focus({ preventScroll: true });\n return;\n }\n if (!['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(e.key)) return;\n e.preventDefault();\n e.stopPropagation();\n const buttons = Array.from(e.currentTarget.querySelectorAll<HTMLButtonElement>('button:not(:disabled)'));\n const index = buttons.indexOf(document.activeElement as HTMLButtonElement);\n const next = e.key === 'Home' ? 0 : e.key === 'End' ? buttons.length - 1 : (index + (e.key === 'ArrowDown' ? 1 : -1) + buttons.length) % buttons.length;\n buttons[next]?.focus({ preventScroll: true });\n const item = buttons[next];\n if (item && item.offsetTop < e.currentTarget.scrollTop) e.currentTarget.scrollTop = item.offsetTop;\n else if (item && item.offsetTop + item.offsetHeight > e.currentTarget.scrollTop + e.currentTarget.clientHeight) {\n e.currentTarget.scrollTop = item.offsetTop + item.offsetHeight - e.currentTarget.clientHeight;\n }\n }}\n >\n {menuItems.map((item) => (\n <button\n key={item.label}\n type=\"button\"\n role=\"menuitem\"\n disabled={item.disabled}\n style={item.disabled ? { opacity: 0.45, cursor: 'default' } : undefined}\n className=\"rte-block-handle__menu-item\"\n onMouseDown={(e) => e.stopPropagation()}\n onClick={(e) => { e.stopPropagation(); executeMenuItem(item); setShowMenu(false); hoveringHandle.current = false; }}\n >\n {item.label}\n </button>\n ))}\n </div>\n )}\n\n {isDragging && dropIndicator && (\n <div className=\"rte-block-handle__drop-indicator\" style={{ top: dropIndicator.top }} />\n )}\n </>\n );\n};\n\nexport default BlockHandle;\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { Editor } from '@tiptap/react';
2
+ import { type Editor } from '@tiptap/react';
3
3
  interface BubbleToolbarProps {
4
4
  editor: Editor;
5
5
  onAddComment?: () => void;
@@ -1,100 +1,217 @@
1
- import { useEffect as e, useRef as t, useState as n } from "react";
2
- import { Fragment as r, jsx as i, jsxs as a } from "react/jsx-runtime";
1
+ import { ColorPicker as e } from "./Toolbar/ColorPicker.js";
2
+ import { FONT_FAMILIES as t, FONT_SIZES as n } from "./Toolbar/SelectDropdown.js";
3
+ import { useEffect as r, useLayoutEffect as i, useRef as a, useState as o } from "react";
4
+ import { Fragment as s, jsx as c, jsxs as l } from "react/jsx-runtime";
5
+ import { useEditorState as u } from "@tiptap/react";
6
+ import { TextSelection as d } from "@tiptap/pm/state";
3
7
  //#region src/components/pro/RichTextEditor/BubbleToolbar.tsx
4
- var o = ({ editor: o, onAddComment: s }) => {
5
- let [c, l] = n(!1), [u, d] = n({
8
+ var f = ({ editor: f, onAddComment: p }) => {
9
+ u({
10
+ editor: f,
11
+ selector: ({ transactionNumber: e }) => e
12
+ });
13
+ let [m, h] = o(!1), [g, _] = o({
6
14
  x: 0,
7
15
  y: 0
8
- }), f = t(null);
9
- if (e(() => {
10
- let e = () => {
11
- let { from: e, to: t } = o.state.selection;
12
- if (e === t || !o.isFocused) {
13
- l(!1);
16
+ }), v = a(null);
17
+ if (r(() => {
18
+ if (f.isDestroyed) return;
19
+ let e = f.view.dom.ownerDocument, t = e.defaultView;
20
+ if (!t) return;
21
+ let n = null, r = () => {
22
+ n !== null && t.cancelAnimationFrame(n), n = null, h(!1);
23
+ }, i = () => {
24
+ if (n = null, f.isDestroyed) {
25
+ r();
26
+ return;
27
+ }
28
+ let { from: t, to: i } = f.state.selection;
29
+ if (!f.isEditable || !(f.state.selection instanceof d) || t === i || !f.isFocused && !v.current?.contains(e.activeElement)) {
30
+ h(!1);
14
31
  return;
15
32
  }
16
- let n = o.view.coordsAtPos(e), r = o.view.coordsAtPos(t), i = o.view.dom.closest(".rte-editor-wrapper");
17
- if (!i) return;
18
- let a = i.getBoundingClientRect(), s = (n.left + r.left) / 2 - a.left, c = Math.min(n.top, r.top) - a.top - 44;
19
- d({
20
- x: s,
21
- y: c
22
- }), l(!0);
33
+ let a = f.view.coordsAtPos(t), o = f.view.coordsAtPos(i), s = f.view.dom.closest(".rte-editor-wrapper");
34
+ if (!s) {
35
+ r();
36
+ return;
37
+ }
38
+ let c = s.getBoundingClientRect(), l = (a.left + o.left) / 2 - c.left - s.clientLeft + s.scrollLeft, u = Math.min(a.top, o.top) - c.top - s.clientTop + s.scrollTop - 44;
39
+ _({
40
+ x: l,
41
+ y: u
42
+ }), h(!0);
43
+ }, a = () => {
44
+ n !== null && t.cancelAnimationFrame(n), n = t.requestAnimationFrame(i);
45
+ }, o = ({ event: e }) => {
46
+ e.relatedTarget instanceof Node && v.current?.contains(e.relatedTarget) || r();
23
47
  };
24
- return o.on("selectionUpdate", e), o.on("blur", () => l(!1)), () => {
25
- o.off("selectionUpdate", e);
48
+ return f.on("transaction", a), f.on("selectionUpdate", a), f.on("focus", a), f.on("blur", o), f.on("destroy", r), e.addEventListener("scroll", a, !0), t.addEventListener("resize", a), i(), () => {
49
+ n !== null && t.cancelAnimationFrame(n), f.off("transaction", a), f.off("selectionUpdate", a), f.off("focus", a), f.off("blur", o), f.off("destroy", r), e.removeEventListener("scroll", a, !0), t.removeEventListener("resize", a);
26
50
  };
27
- }, [o]), !c) return null;
28
- let p = (e, t, n, r) => /* @__PURE__ */ i("button", {
51
+ }, [f]), i(() => {
52
+ if (!m || !v.current) return;
53
+ let e = v.current, t = e.parentElement;
54
+ if (!t) return;
55
+ let n = t.clientWidth, r = e.offsetWidth / 2, i = Math.min(r + 4, n / 2), a = Math.max(n - r - 4, n / 2), o = Math.min(Math.max(g.x, i), a);
56
+ o !== g.x && _((e) => ({
57
+ ...e,
58
+ x: o
59
+ }));
60
+ }, [m, g.x]), !m || f.isDestroyed || !f.isEditable) return null;
61
+ let y = (e, t, n, r) => /* @__PURE__ */ c("button", {
29
62
  type: "button",
30
63
  className: `rte-bubble__btn ${n ? "rte-bubble__btn--active" : ""}`,
31
- onClick: e,
64
+ onClick: () => {
65
+ !f.isDestroyed && f.isEditable && e();
66
+ },
32
67
  title: t,
68
+ "aria-label": t,
69
+ "aria-pressed": n,
33
70
  onMouseDown: (e) => e.preventDefault(),
34
71
  children: r
35
72
  });
36
- return /* @__PURE__ */ a("div", {
37
- ref: f,
73
+ return /* @__PURE__ */ l("div", {
74
+ ref: v,
38
75
  className: "rte-bubble",
76
+ role: "group",
77
+ "aria-label": "Selection formatting",
78
+ onBlur: (e) => {
79
+ !e.currentTarget.contains(e.relatedTarget) && !f.isFocused && h(!1);
80
+ },
81
+ onKeyDown: (e) => {
82
+ e.key === "Escape" && (e.preventDefault(), f.commands.focus(), h(!1));
83
+ },
39
84
  style: {
40
- left: u.x,
41
- top: u.y
85
+ left: g.x,
86
+ top: g.y
42
87
  },
43
88
  children: [
44
- p(() => o.chain().focus().toggleBold().run(), "Bold", o.isActive("bold"), /* @__PURE__ */ i("strong", {
89
+ y(() => f.chain().focus().toggleBold().run(), "Bold", f.isActive("bold"), /* @__PURE__ */ c("strong", {
45
90
  style: { fontSize: 13 },
46
91
  children: "B"
47
92
  })),
48
- p(() => o.chain().focus().toggleItalic().run(), "Italic", o.isActive("italic"), /* @__PURE__ */ i("em", {
93
+ y(() => f.chain().focus().toggleItalic().run(), "Italic", f.isActive("italic"), /* @__PURE__ */ c("em", {
49
94
  style: { fontSize: 13 },
50
95
  children: "I"
51
96
  })),
52
- p(() => o.chain().focus().toggleUnderline().run(), "Underline", o.isActive("underline"), /* @__PURE__ */ i("span", {
97
+ y(() => f.chain().focus().toggleUnderline().run(), "Underline", f.isActive("underline"), /* @__PURE__ */ c("span", {
53
98
  style: {
54
99
  fontSize: 13,
55
100
  textDecoration: "underline"
56
101
  },
57
102
  children: "U"
58
103
  })),
59
- p(() => o.chain().focus().toggleStrike().run(), "Strike", o.isActive("strike"), /* @__PURE__ */ i("span", {
104
+ y(() => f.chain().focus().toggleStrike().run(), "Strike", f.isActive("strike"), /* @__PURE__ */ c("span", {
60
105
  style: {
61
106
  fontSize: 13,
62
107
  textDecoration: "line-through"
63
108
  },
64
109
  children: "S"
65
110
  })),
66
- p(() => o.chain().focus().toggleCode().run(), "Code", o.isActive("code"), /* @__PURE__ */ i("span", {
111
+ y(() => f.chain().focus().toggleCode().run(), "Code", f.isActive("code"), /* @__PURE__ */ c("span", {
67
112
  style: {
68
113
  fontSize: 11,
69
114
  fontFamily: "monospace"
70
115
  },
71
116
  children: "</>"
72
117
  })),
73
- p(() => {
74
- let e = window.prompt("URL:");
75
- e && o.chain().focus().setLink({ href: e }).run();
76
- }, "Link", o.isActive("link"), /* @__PURE__ */ a("svg", {
118
+ y(() => {
119
+ let e = window.prompt("URL:", f.getAttributes("link").href || "");
120
+ if (e === null || f.isDestroyed || !f.isEditable) return;
121
+ let t = f.chain().focus().extendMarkRange("link");
122
+ e.trim() === "" ? t.unsetLink().run() : t.setLink({ href: e.trim() }).run();
123
+ }, "Link", f.isActive("link"), /* @__PURE__ */ l("svg", {
77
124
  width: "14",
78
125
  height: "14",
79
126
  viewBox: "0 0 24 24",
80
127
  fill: "none",
81
128
  stroke: "currentColor",
82
129
  strokeWidth: "2",
83
- children: [/* @__PURE__ */ i("path", { d: "M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71" }), /* @__PURE__ */ i("path", { d: "M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71" })]
130
+ children: [/* @__PURE__ */ c("path", { d: "M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71" }), /* @__PURE__ */ c("path", { d: "M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71" })]
84
131
  })),
85
- s && /* @__PURE__ */ a(r, { children: [/* @__PURE__ */ i("div", { className: "rte-bubble__divider" }), p(s, "Comment", !1, /* @__PURE__ */ i("svg", {
132
+ /* @__PURE__ */ c("div", { className: "rte-bubble__divider" }),
133
+ /* @__PURE__ */ c(e, {
134
+ value: f.getAttributes("textStyle").color || "",
135
+ onChange: (e) => {
136
+ !f.isDestroyed && f.isEditable && (e ? f.chain().focus().setColor(e).run() : f.chain().focus().unsetColor().run());
137
+ },
138
+ title: "Text color",
139
+ buttonClassName: "rte-bubble__btn",
140
+ icon: /* @__PURE__ */ l("svg", {
141
+ width: "14",
142
+ height: "14",
143
+ viewBox: "0 0 24 24",
144
+ fill: "none",
145
+ stroke: "currentColor",
146
+ strokeWidth: "2",
147
+ strokeLinecap: "round",
148
+ strokeLinejoin: "round",
149
+ children: [
150
+ /* @__PURE__ */ c("path", { d: "M4 20h16" }),
151
+ /* @__PURE__ */ c("path", { d: "M6 16l4.5-12h1L16 16" }),
152
+ /* @__PURE__ */ c("path", { d: "M7.8 12h6.4" })
153
+ ]
154
+ })
155
+ }),
156
+ /* @__PURE__ */ c(e, {
157
+ value: f.getAttributes("highlight").color || "",
158
+ onChange: (e) => {
159
+ !f.isDestroyed && f.isEditable && (e ? f.chain().focus().toggleHighlight({ color: e }).run() : f.chain().focus().unsetHighlight().run());
160
+ },
161
+ title: "Highlight color",
162
+ buttonClassName: "rte-bubble__btn",
163
+ icon: /* @__PURE__ */ l("svg", {
164
+ width: "14",
165
+ height: "14",
166
+ viewBox: "0 0 24 24",
167
+ fill: "none",
168
+ stroke: "currentColor",
169
+ strokeWidth: "2",
170
+ strokeLinecap: "round",
171
+ strokeLinejoin: "round",
172
+ children: [/* @__PURE__ */ c("path", { d: "M12 20h9" }), /* @__PURE__ */ c("path", { d: "M16.5 3.5a2.121 2.121 0 013 3L7 19l-4 1 1-4L16.5 3.5z" })]
173
+ })
174
+ }),
175
+ /* @__PURE__ */ c("div", { className: "rte-bubble__divider" }),
176
+ /* @__PURE__ */ c("select", {
177
+ className: "rte-bubble__select",
178
+ value: f.getAttributes("textStyle").fontFamily || "",
179
+ onChange: (e) => {
180
+ !f.isDestroyed && f.isEditable && (e.target.value ? f.chain().focus().setFontFamily(e.target.value).run() : f.chain().focus().unsetFontFamily().run());
181
+ },
182
+ title: "Font family",
183
+ "aria-label": "Font family",
184
+ children: t.map((e) => /* @__PURE__ */ c("option", {
185
+ value: e.value,
186
+ children: e.label
187
+ }, e.value))
188
+ }),
189
+ /* @__PURE__ */ c("select", {
190
+ className: "rte-bubble__select rte-bubble__select--size",
191
+ value: f.getAttributes("textStyle").fontSize || "",
192
+ onChange: (e) => {
193
+ !f.isDestroyed && f.isEditable && (e.target.value ? f.chain().focus().setFontSize(e.target.value).run() : f.chain().focus().unsetFontSize().run());
194
+ },
195
+ title: "Font size",
196
+ "aria-label": "Font size",
197
+ children: n.map((e) => /* @__PURE__ */ c("option", {
198
+ value: e.value,
199
+ children: e.label
200
+ }, e.value))
201
+ }),
202
+ p && /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ c("div", { className: "rte-bubble__divider" }), y(p, "Comment", void 0, /* @__PURE__ */ c("svg", {
86
203
  width: "14",
87
204
  height: "14",
88
205
  viewBox: "0 0 24 24",
89
206
  fill: "none",
90
207
  stroke: "currentColor",
91
208
  strokeWidth: "2",
92
- children: /* @__PURE__ */ i("path", { d: "M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z" })
209
+ children: /* @__PURE__ */ c("path", { d: "M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z" })
93
210
  }))] })
94
211
  ]
95
212
  });
96
213
  };
97
214
  //#endregion
98
- export { o as default };
215
+ export { f as default };
99
216
 
100
217
  //# sourceMappingURL=BubbleToolbar.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"BubbleToolbar.js","names":[],"sources":["../../../../src/components/pro/RichTextEditor/BubbleToolbar.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\nimport type { Editor } from '@tiptap/react';\n\ninterface BubbleToolbarProps {\n editor: Editor;\n onAddComment?: () => void;\n}\n\nconst BubbleToolbar: React.FC<BubbleToolbarProps> = ({ editor, onAddComment }) => {\n const [visible, setVisible] = useState(false);\n const [pos, setPos] = useState({ x: 0, y: 0 });\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const update = () => {\n const { from, to } = editor.state.selection;\n if (from === to || !editor.isFocused) {\n setVisible(false);\n return;\n }\n const coords = editor.view.coordsAtPos(from);\n const endCoords = editor.view.coordsAtPos(to);\n const wrapperEl = editor.view.dom.closest('.rte-editor-wrapper');\n if (!wrapperEl) return;\n const rect = wrapperEl.getBoundingClientRect();\n\n const centerX = (coords.left + endCoords.left) / 2 - rect.left;\n const topY = Math.min(coords.top, endCoords.top) - rect.top - 44;\n\n setPos({ x: centerX, y: topY });\n setVisible(true);\n };\n\n editor.on('selectionUpdate', update);\n editor.on('blur', () => setVisible(false));\n return () => {\n editor.off('selectionUpdate', update);\n };\n }, [editor]);\n\n if (!visible) return null;\n\n const btn = (onClick: () => void, title: string, isActive: boolean, children: React.ReactNode) => (\n <button\n type=\"button\"\n className={`rte-bubble__btn ${isActive ? 'rte-bubble__btn--active' : ''}`}\n onClick={onClick}\n title={title}\n onMouseDown={(e) => e.preventDefault()}\n >\n {children}\n </button>\n );\n\n return (\n <div ref={ref} className=\"rte-bubble\" style={{ left: pos.x, top: pos.y }}>\n {btn(() => editor.chain().focus().toggleBold().run(), 'Bold', editor.isActive('bold'),\n <strong style={{ fontSize: 13 }}>B</strong>)}\n {btn(() => editor.chain().focus().toggleItalic().run(), 'Italic', editor.isActive('italic'),\n <em style={{ fontSize: 13 }}>I</em>)}\n {btn(() => editor.chain().focus().toggleUnderline().run(), 'Underline', editor.isActive('underline'),\n <span style={{ fontSize: 13, textDecoration: 'underline' }}>U</span>)}\n {btn(() => editor.chain().focus().toggleStrike().run(), 'Strike', editor.isActive('strike'),\n <span style={{ fontSize: 13, textDecoration: 'line-through' }}>S</span>)}\n {btn(() => editor.chain().focus().toggleCode().run(), 'Code', editor.isActive('code'),\n <span style={{ fontSize: 11, fontFamily: 'monospace' }}>&lt;/&gt;</span>)}\n {btn(() => {\n const url = window.prompt('URL:');\n if (url) editor.chain().focus().setLink({ href: url }).run();\n }, 'Link', editor.isActive('link'),\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71\" /><path d=\"M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71\" /></svg>)}\n {onAddComment && (\n <>\n <div className=\"rte-bubble__divider\" />\n {btn(onAddComment, 'Comment', false,\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z\" /></svg>)}\n </>\n )}\n </div>\n );\n};\n\nexport default BubbleToolbar;\n"],"mappings":"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"}
1
+ {"version":3,"file":"BubbleToolbar.js","names":[],"sources":["../../../../src/components/pro/RichTextEditor/BubbleToolbar.tsx"],"sourcesContent":["import React, { useState, useEffect, useLayoutEffect, useRef } from 'react';\nimport { useEditorState, type Editor } from '@tiptap/react';\nimport { TextSelection } from '@tiptap/pm/state';\nimport { ColorPicker } from './Toolbar/ColorPicker';\nimport { FONT_FAMILIES, FONT_SIZES } from './Toolbar/SelectDropdown';\n\ninterface BubbleToolbarProps {\n editor: Editor;\n onAddComment?: () => void;\n}\n\nconst BubbleToolbar: React.FC<BubbleToolbarProps> = ({ editor, onAddComment }) => {\n useEditorState({ editor, selector: ({ transactionNumber }) => transactionNumber });\n const [visible, setVisible] = useState(false);\n const [pos, setPos] = useState({ x: 0, y: 0 });\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (editor.isDestroyed) return;\n const doc = editor.view.dom.ownerDocument;\n const win = doc.defaultView;\n if (!win) return;\n let frame: number | null = null;\n const hide = () => {\n if (frame !== null) win.cancelAnimationFrame(frame);\n frame = null;\n setVisible(false);\n };\n const update = () => {\n frame = null;\n if (editor.isDestroyed) { hide(); return; }\n const { from, to } = editor.state.selection;\n if (!editor.isEditable || !(editor.state.selection instanceof TextSelection) || from === to || (!editor.isFocused && !ref.current?.contains(doc.activeElement))) {\n setVisible(false);\n return;\n }\n const coords = editor.view.coordsAtPos(from);\n const endCoords = editor.view.coordsAtPos(to);\n const wrapperEl = editor.view.dom.closest<HTMLElement>('.rte-editor-wrapper');\n if (!wrapperEl) { hide(); return; }\n const rect = wrapperEl.getBoundingClientRect();\n\n const centerX = (coords.left + endCoords.left) / 2 - rect.left - wrapperEl.clientLeft + wrapperEl.scrollLeft;\n const topY = Math.min(coords.top, endCoords.top) - rect.top - wrapperEl.clientTop + wrapperEl.scrollTop - 44;\n\n setPos({ x: centerX, y: topY });\n setVisible(true);\n };\n\n const scheduleUpdate = () => {\n if (frame !== null) win.cancelAnimationFrame(frame);\n frame = win.requestAnimationFrame(update);\n };\n const onBlur = ({ event }: { event: FocusEvent }) => {\n if (event.relatedTarget instanceof Node && ref.current?.contains(event.relatedTarget)) return;\n hide();\n };\n editor.on('transaction', scheduleUpdate);\n editor.on('selectionUpdate', scheduleUpdate);\n editor.on('focus', scheduleUpdate);\n editor.on('blur', onBlur);\n editor.on('destroy', hide);\n doc.addEventListener('scroll', scheduleUpdate, true);\n win.addEventListener('resize', scheduleUpdate);\n update();\n return () => {\n if (frame !== null) win.cancelAnimationFrame(frame);\n editor.off('transaction', scheduleUpdate);\n editor.off('selectionUpdate', scheduleUpdate);\n editor.off('focus', scheduleUpdate);\n editor.off('blur', onBlur);\n editor.off('destroy', hide);\n doc.removeEventListener('scroll', scheduleUpdate, true);\n win.removeEventListener('resize', scheduleUpdate);\n };\n }, [editor]);\n\n // Keep the bubble inside the wrapper horizontally: with the extra color /\n // font controls it can be wider than a phone-size editor, and transform:\n // translateX(-50%) would otherwise clip it at either edge.\n useLayoutEffect(() => {\n if (!visible || !ref.current) return;\n const el = ref.current;\n const wrapper = el.parentElement;\n if (!wrapper) return;\n const w = wrapper.clientWidth;\n const half = el.offsetWidth / 2;\n const min = Math.min(half + 4, w / 2);\n const max = Math.max(w - half - 4, w / 2);\n const clamped = Math.min(Math.max(pos.x, min), max);\n if (clamped !== pos.x) setPos((p) => ({ ...p, x: clamped }));\n }, [visible, pos.x]);\n\n if (!visible || editor.isDestroyed || !editor.isEditable) return null;\n\n const btn = (onClick: () => void, title: string, isActive: boolean | undefined, children: React.ReactNode) => (\n <button\n type=\"button\"\n className={`rte-bubble__btn ${isActive ? 'rte-bubble__btn--active' : ''}`}\n onClick={() => { if (!editor.isDestroyed && editor.isEditable) onClick(); }}\n title={title}\n aria-label={title}\n aria-pressed={isActive}\n onMouseDown={(e) => e.preventDefault()}\n >\n {children}\n </button>\n );\n\n return (\n <div ref={ref} className=\"rte-bubble\" role=\"group\" aria-label=\"Selection formatting\"\n onBlur={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget) && !editor.isFocused) setVisible(false);\n }}\n onKeyDown={(event) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n editor.commands.focus();\n setVisible(false);\n }\n }}\n style={{ left: pos.x, top: pos.y }}>\n {btn(() => editor.chain().focus().toggleBold().run(), 'Bold', editor.isActive('bold'),\n <strong style={{ fontSize: 13 }}>B</strong>)}\n {btn(() => editor.chain().focus().toggleItalic().run(), 'Italic', editor.isActive('italic'),\n <em style={{ fontSize: 13 }}>I</em>)}\n {btn(() => editor.chain().focus().toggleUnderline().run(), 'Underline', editor.isActive('underline'),\n <span style={{ fontSize: 13, textDecoration: 'underline' }}>U</span>)}\n {btn(() => editor.chain().focus().toggleStrike().run(), 'Strike', editor.isActive('strike'),\n <span style={{ fontSize: 13, textDecoration: 'line-through' }}>S</span>)}\n {btn(() => editor.chain().focus().toggleCode().run(), 'Code', editor.isActive('code'),\n <span style={{ fontSize: 11, fontFamily: 'monospace' }}>&lt;/&gt;</span>)}\n {btn(() => {\n const url = window.prompt('URL:', editor.getAttributes('link').href || '');\n if (url === null || editor.isDestroyed || !editor.isEditable) return;\n const chain = editor.chain().focus().extendMarkRange('link');\n if (url.trim() === '') chain.unsetLink().run();\n else chain.setLink({ href: url.trim() }).run();\n }, 'Link', editor.isActive('link'),\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71\" /><path d=\"M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71\" /></svg>)}\n <div className=\"rte-bubble__divider\" />\n <ColorPicker\n value={editor.getAttributes('textStyle').color || ''}\n onChange={(color) => {\n if (editor.isDestroyed || !editor.isEditable) return;\n if (color) editor.chain().focus().setColor(color).run();\n else editor.chain().focus().unsetColor().run();\n }}\n title=\"Text color\"\n buttonClassName=\"rte-bubble__btn\"\n icon={\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M4 20h16\" /><path d=\"M6 16l4.5-12h1L16 16\" /><path d=\"M7.8 12h6.4\" />\n </svg>\n }\n />\n <ColorPicker\n value={editor.getAttributes('highlight').color || ''}\n onChange={(color) => {\n if (editor.isDestroyed || !editor.isEditable) return;\n if (color) editor.chain().focus().toggleHighlight({ color }).run();\n else editor.chain().focus().unsetHighlight().run();\n }}\n title=\"Highlight color\"\n buttonClassName=\"rte-bubble__btn\"\n icon={\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M12 20h9\" /><path d=\"M16.5 3.5a2.121 2.121 0 013 3L7 19l-4 1 1-4L16.5 3.5z\" />\n </svg>\n }\n />\n <div className=\"rte-bubble__divider\" />\n <select\n className=\"rte-bubble__select\"\n value={editor.getAttributes('textStyle').fontFamily || ''}\n onChange={(e) => {\n if (editor.isDestroyed || !editor.isEditable) return;\n if (e.target.value) editor.chain().focus().setFontFamily(e.target.value).run();\n else editor.chain().focus().unsetFontFamily().run();\n }}\n title=\"Font family\"\n aria-label=\"Font family\"\n >\n {FONT_FAMILIES.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n <select\n className=\"rte-bubble__select rte-bubble__select--size\"\n value={editor.getAttributes('textStyle').fontSize || ''}\n onChange={(e) => {\n if (editor.isDestroyed || !editor.isEditable) return;\n if (e.target.value) (editor.chain().focus() as any).setFontSize(e.target.value).run();\n else (editor.chain().focus() as any).unsetFontSize().run();\n }}\n title=\"Font size\"\n aria-label=\"Font size\"\n >\n {FONT_SIZES.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n {onAddComment && (\n <>\n <div className=\"rte-bubble__divider\" />\n {btn(onAddComment, 'Comment', undefined,\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z\" /></svg>)}\n </>\n )}\n </div>\n );\n};\n\nexport default BubbleToolbar;\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { Editor } from '@tiptap/react';
2
+ import { type Editor } from '@tiptap/react';
3
3
  import type { CommentThread } from './extensions/CommentMark';
4
4
  export interface CommentPanelHandle {
5
5
  scrollToThread: (id: string) => void;
@@ -10,6 +10,7 @@ interface CommentPanelProps {
10
10
  onThreadsChange: (threads: CommentThread[]) => void;
11
11
  onRequestAddComment: () => void;
12
12
  currentUser?: string;
13
+ editable?: boolean;
13
14
  }
14
15
  declare const CommentPanel: React.ForwardRefExoticComponent<CommentPanelProps & React.RefAttributes<CommentPanelHandle>>;
15
16
  export default CommentPanel;