dishui 0.0.71 → 0.0.73

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 (93) 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 +69 -33
  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 +136 -73
  54. package/dist/components/pro/RichTextEditor/SlashMenu.js.map +1 -1
  55. package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.d.ts +1 -1
  56. package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js +346 -313
  57. package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js.map +1 -1
  58. package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js +114 -146
  59. package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js.map +1 -1
  60. package/dist/components/pro/RichTextEditor/extensions/CommentMark.js +2 -2
  61. package/dist/components/pro/RichTextEditor/extensions/CommentMark.js.map +1 -1
  62. package/dist/components/pro/RichTextEditor/extensions/FloatingDialog.js +178 -163
  63. package/dist/components/pro/RichTextEditor/extensions/FloatingDialog.js.map +1 -1
  64. package/dist/components/pro/RichTextEditor/extensions/FontSize.js +8 -5
  65. package/dist/components/pro/RichTextEditor/extensions/FontSize.js.map +1 -1
  66. package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.d.ts +6 -0
  67. package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js +85 -74
  68. package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js.map +1 -1
  69. package/dist/components/pro/RichTextEditor/searchUtils.d.ts +23 -0
  70. package/dist/contexts/AppContext.js +47 -45
  71. package/dist/contexts/AppContext.js.map +1 -1
  72. package/dist/dishui.css +1 -1
  73. package/dist/index-nostyled.d.ts +11 -1
  74. package/dist/index.d.ts +11 -1
  75. package/dist/index.js +119 -114
  76. package/dist/layouts/MainLayout.js +9 -10
  77. package/dist/layouts/MainLayout.js.map +1 -1
  78. package/dist/layouts/Sidebar.d.ts +9 -0
  79. package/dist/layouts/Sidebar.js +99 -80
  80. package/dist/layouts/Sidebar.js.map +1 -1
  81. package/dist/layouts/headbar/Headbar.d.ts +1 -1
  82. package/dist/layouts/headbar/Headbar.js +2 -2
  83. package/dist/layouts/headbar/Headbar.js.map +1 -1
  84. package/dist/lite.d.ts +19 -1
  85. package/dist/lite.js +17 -8
  86. package/dist/styles/themeStyles.js +6 -6
  87. package/dist/styles/themeStyles.js.map +1 -1
  88. package/dist/utils/i18n.d.ts +3 -0
  89. package/dist/utils/i18n.js +78 -0
  90. package/dist/utils/i18n.js.map +1 -1
  91. package/dist/utils/menu.js +23 -6
  92. package/dist/utils/menu.js.map +1 -1
  93. package/package.json +8 -2
@@ -1 +1 @@
1
- {"version":3,"file":"CommentPopover.js","names":[],"sources":["../../../../src/components/pro/RichTextEditor/CommentPopover.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback } from 'react';\nimport type { Editor } from '@tiptap/react';\nimport type { CommentThread, CommentItem } from './extensions/CommentMark';\n\nfunction generateId() {\n return `c_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;\n}\n\nfunction timeAgo(ts: number): string {\n const diff = Date.now() - ts;\n const sec = Math.floor(diff / 1000);\n if (sec < 60) return 'just now';\n const min = Math.floor(sec / 60);\n if (min < 60) return `${min}m ago`;\n const hr = Math.floor(min / 60);\n if (hr < 24) return `${hr}h ago`;\n const d = Math.floor(hr / 24);\n return `${d}d ago`;\n}\n\ninterface CommentPopoverProps {\n editor: Editor;\n threads: CommentThread[];\n onThreadsChange: (threads: CommentThread[]) => void;\n showPanel: boolean;\n onOpenPanel: () => void;\n onScrollToThread: (id: string) => void;\n currentUser?: string;\n}\n\nconst CommentPopover: React.FC<CommentPopoverProps> = ({\n editor,\n threads,\n onThreadsChange,\n showPanel,\n onOpenPanel,\n onScrollToThread,\n currentUser = 'User',\n}) => {\n const [activeThread, setActiveThread] = useState<CommentThread | null>(null);\n const [pos, setPos] = useState({ x: 0, y: 0 });\n const [replyText, setReplyText] = useState('');\n const popRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n const dom = editor.view.dom;\n const handleClick = (e: Event) => {\n const target = e.target as HTMLElement;\n const commentEl = target.closest('.rte-comment-mark') as HTMLElement | null;\n if (!commentEl) { setActiveThread(null); return; }\n\n const commentId = commentEl.getAttribute('data-comment-id');\n if (!commentId) return;\n\n const thread = threads.find((t) => t.id === commentId);\n if (!thread || thread.resolved) return;\n\n if (showPanel) {\n onScrollToThread(commentId);\n setActiveThread(null);\n return;\n }\n\n const wrapperEl = dom.closest('.rte-editor-wrapper');\n if (!wrapperEl) return;\n const wRect = wrapperEl.getBoundingClientRect();\n const elRect = commentEl.getBoundingClientRect();\n\n setPos({\n x: elRect.left - wRect.left + elRect.width / 2,\n y: elRect.bottom - wRect.top + 6,\n });\n setActiveThread(thread);\n setReplyText('');\n };\n\n dom.addEventListener('click', handleClick);\n return () => dom.removeEventListener('click', handleClick);\n }, [editor, threads, showPanel, onScrollToThread]);\n\n useEffect(() => {\n if (!activeThread) return;\n const handler = (e: MouseEvent) => {\n if (popRef.current && !popRef.current.contains(e.target as Node)) {\n setActiveThread(null);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [activeThread]);\n\n useEffect(() => {\n if (activeThread && inputRef.current) inputRef.current.focus();\n }, [activeThread]);\n\n const toggleResolve = useCallback(() => {\n if (!activeThread) return;\n const updated = threads.map((t) => {\n if (t.id !== activeThread.id) return t;\n editor.state.doc.descendants((node, pos) => {\n node.marks.forEach((mark) => {\n if (mark.type.name === 'comment' && mark.attrs.commentId === activeThread.id) {\n editor.view.dispatch(\n editor.state.tr\n .removeMark(pos, pos + node.nodeSize, mark)\n .addMark(pos, pos + node.nodeSize, mark.type.create({ ...mark.attrs, resolved: true }))\n );\n }\n });\n });\n return { ...t, resolved: true };\n });\n onThreadsChange(updated);\n setActiveThread(null);\n }, [activeThread, editor, threads, onThreadsChange]);\n\n const addReply = useCallback(() => {\n if (!activeThread || !replyText.trim()) return;\n const reply: CommentItem = {\n id: generateId(),\n author: currentUser,\n text: replyText.trim(),\n createdAt: Date.now(),\n };\n const updated = threads.map((t) =>\n t.id === activeThread.id ? { ...t, comments: [...t.comments, reply] } : t\n );\n onThreadsChange(updated);\n setActiveThread(updated.find((t) => t.id === activeThread.id) || null);\n setReplyText('');\n }, [activeThread, replyText, threads, onThreadsChange, currentUser]);\n\n if (!activeThread) return null;\n\n return (\n <div ref={popRef} className=\"rte-comment-popover\" style={{ left: pos.x, top: pos.y }}>\n <div className=\"rte-comment-popover__header\">\n <span className=\"rte-comment-popover__status\">Open</span>\n <div className=\"rte-comment-popover__actions\">\n <button type=\"button\" className=\"rte-comments__icon-btn\" onClick={toggleResolve} title=\"Resolve\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><polyline points=\"20 6 9 17 4 12\" /></svg>\n </button>\n <button type=\"button\" className=\"rte-comments__icon-btn\" onClick={() => { onOpenPanel(); setActiveThread(null); }} title=\"Open panel\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><polyline points=\"15 3 21 3 21 9\" /><polyline points=\"9 21 3 21 3 15\" /><line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\" /><line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" /></svg>\n </button>\n <button type=\"button\" className=\"rte-comments__icon-btn\" onClick={() => setActiveThread(null)} title=\"Close\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" /><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" /></svg>\n </button>\n </div>\n </div>\n\n {activeThread.comments.map((c) => (\n <div key={c.id} className=\"rte-comment-popover__comment\">\n <div className=\"rte-comments__comment-meta\">\n <span className=\"rte-comments__author\">{c.author}</span>\n <span className=\"rte-comments__time\">{timeAgo(c.createdAt)}</span>\n </div>\n <div className=\"rte-comments__comment-text\">{c.text}</div>\n </div>\n ))}\n\n <div className=\"rte-comment-popover__reply\">\n <input\n ref={inputRef}\n className=\"rte-comments__reply-input\"\n value={replyText}\n onChange={(e) => setReplyText(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') addReply();\n if (e.key === 'Escape') setActiveThread(null);\n }}\n placeholder=\"Reply...\"\n />\n <button type=\"button\" className=\"rte-comments__reply-send\" onClick={addReply} disabled={!replyText.trim()}>\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\" /><polygon points=\"22 2 15 22 11 13 2 9 22 2\" /></svg>\n </button>\n </div>\n </div>\n );\n};\n\nexport default CommentPopover;\n"],"mappings":"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"}
1
+ {"version":3,"file":"CommentPopover.js","names":[],"sources":["../../../../src/components/pro/RichTextEditor/CommentPopover.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback } from 'react';\nimport { useEditorState, type Editor } from '@tiptap/react';\nimport type { CommentThread, CommentItem } from './extensions/CommentMark';\n\nfunction generateId() {\n return `c_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;\n}\n\nfunction timeAgo(ts: number): string {\n const diff = Date.now() - ts;\n const sec = Math.floor(diff / 1000);\n if (sec < 60) return 'just now';\n const min = Math.floor(sec / 60);\n if (min < 60) return `${min}m ago`;\n const hr = Math.floor(min / 60);\n if (hr < 24) return `${hr}h ago`;\n const d = Math.floor(hr / 24);\n return `${d}d ago`;\n}\n\ninterface CommentPopoverProps {\n editor: Editor;\n threads: CommentThread[];\n onThreadsChange: (threads: CommentThread[]) => void;\n showPanel: boolean;\n onOpenPanel: () => void;\n onScrollToThread: (id: string) => void;\n currentUser?: string;\n editable?: boolean;\n}\n\nconst CommentPopover: React.FC<CommentPopoverProps> = ({\n editor,\n threads,\n onThreadsChange,\n showPanel,\n onOpenPanel,\n onScrollToThread,\n currentUser = 'User',\n editable = true,\n}) => {\n const [activeThreadId, setActiveThreadId] = useState<string | null>(null);\n const activeThread = threads.find((t) => t.id === activeThreadId && !t.resolved);\n const latest = useRef({ editable, threads, activeThreadId });\n latest.current = { editable, threads, activeThreadId };\n const editorEditable = useEditorState({ editor, selector: ({ editor }) => editor.isEditable });\n const canEdit = editable && editorEditable;\n const [pos, setPos] = useState({ x: 0, y: 0 });\n const [replyText, setReplyText] = useState('');\n const popRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n const dom = editor.view.dom;\n const handleClick = (e: Event) => {\n const target = e.target as HTMLElement;\n const commentEl = target.closest('.rte-comment-mark') as HTMLElement | null;\n if (!commentEl) { setActiveThreadId(null); return; }\n\n const commentId = commentEl.getAttribute('data-comment-id');\n const thread = latest.current.threads.find((t) => t.id === commentId);\n if (!commentId || !thread || thread.resolved) { setActiveThreadId(null); return; }\n\n if (showPanel) {\n onScrollToThread(commentId);\n setActiveThreadId(null);\n return;\n }\n\n const wrapperEl = dom.closest('.rte-editor-wrapper');\n if (!wrapperEl) return;\n const wRect = wrapperEl.getBoundingClientRect();\n const elRect = commentEl.getBoundingClientRect();\n\n setPos({\n x: elRect.left - wRect.left + elRect.width / 2,\n y: elRect.bottom - wRect.top + 6,\n });\n setActiveThreadId(thread.id);\n setReplyText('');\n };\n\n dom.addEventListener('click', handleClick);\n return () => dom.removeEventListener('click', handleClick);\n }, [editor, threads, showPanel, onScrollToThread]);\n\n useEffect(() => {\n if (!activeThread) return;\n const handler = (e: MouseEvent) => {\n if (popRef.current && !popRef.current.contains(e.target as Node)) {\n setActiveThreadId(null);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [activeThread]);\n\n useEffect(() => {\n if (activeThreadId && inputRef.current) inputRef.current.focus();\n }, [activeThreadId, canEdit]);\n\n useEffect(() => {\n if (!activeThread || showPanel) {\n setActiveThreadId(null);\n setReplyText('');\n }\n }, [activeThread, showPanel]);\n\n const toggleResolve = useCallback(() => {\n if (!latest.current.editable || !editor.isEditable) return;\n const thread = latest.current.threads.find((t) => t.id === latest.current.activeThreadId && !t.resolved);\n if (!thread) return;\n const tr = editor.state.tr;\n editor.state.doc.descendants((node, pos) => {\n node.marks.forEach((mark) => {\n if (mark.type.name === 'comment' && mark.attrs.commentId === thread.id) {\n tr.removeMark(pos, pos + node.nodeSize, mark)\n .addMark(pos, pos + node.nodeSize, mark.type.create({ ...mark.attrs, resolved: true }));\n }\n });\n });\n if (tr.docChanged) editor.view.dispatch(tr);\n onThreadsChange(latest.current.threads.map((t) => t.id === thread.id ? { ...t, resolved: true } : t));\n setActiveThreadId(null);\n }, [activeThread, editor, threads, onThreadsChange]);\n\n const addReply = useCallback(() => {\n if (!latest.current.editable || !editor.isEditable || !replyText.trim()) return;\n const thread = latest.current.threads.find((t) => t.id === latest.current.activeThreadId && !t.resolved);\n if (!thread) return;\n const reply: CommentItem = {\n id: generateId(),\n author: currentUser,\n text: replyText.trim(),\n createdAt: Date.now(),\n };\n const updated = latest.current.threads.map((t) =>\n t.id === thread.id ? { ...t, comments: [...t.comments, reply] } : t\n );\n onThreadsChange(updated);\n setReplyText('');\n }, [editor, activeThread, replyText, threads, onThreadsChange, currentUser]);\n\n if (!activeThread || showPanel) return null;\n\n return (\n <div ref={popRef} className=\"rte-comment-popover\" style={{ left: pos.x, top: pos.y }}>\n <div className=\"rte-comment-popover__header\">\n <span className=\"rte-comment-popover__status\">Open</span>\n <div className=\"rte-comment-popover__actions\">\n {canEdit && <button type=\"button\" className=\"rte-comments__icon-btn\" onClick={toggleResolve} title=\"Resolve\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><polyline points=\"20 6 9 17 4 12\" /></svg>\n </button>}\n <button type=\"button\" className=\"rte-comments__icon-btn\" onClick={() => { onOpenPanel(); setActiveThreadId(null); }} title=\"Open panel\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><polyline points=\"15 3 21 3 21 9\" /><polyline points=\"9 21 3 21 3 15\" /><line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\" /><line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" /></svg>\n </button>\n <button type=\"button\" className=\"rte-comments__icon-btn\" onClick={() => setActiveThreadId(null)} title=\"Close\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" /><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" /></svg>\n </button>\n </div>\n </div>\n\n {activeThread.comments.map((c) => (\n <div key={c.id} className=\"rte-comment-popover__comment\">\n <div className=\"rte-comments__comment-meta\">\n <span className=\"rte-comments__author\">{c.author}</span>\n <span className=\"rte-comments__time\">{timeAgo(c.createdAt)}</span>\n </div>\n <div className=\"rte-comments__comment-text\">{c.text}</div>\n </div>\n ))}\n\n {canEdit && <div className=\"rte-comment-popover__reply\">\n <input\n ref={inputRef}\n className=\"rte-comments__reply-input\"\n value={replyText}\n onChange={(e) => setReplyText(e.target.value)}\n onKeyDown={(e) => {\n if (e.nativeEvent.isComposing || e.nativeEvent.keyCode === 229) return;\n if (e.key === 'Enter') { e.preventDefault(); addReply(); }\n if (e.key === 'Escape') setActiveThreadId(null);\n }}\n placeholder=\"Reply...\"\n />\n <button type=\"button\" className=\"rte-comments__reply-send\" onClick={addReply} disabled={!replyText.trim()}>\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\" /><polygon points=\"22 2 15 22 11 13 2 9 22 2\" /></svg>\n </button>\n </div>}\n </div>\n );\n};\n\nexport default CommentPopover;\n"],"mappings":"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"}
@@ -1,15 +1,15 @@
1
1
  import { cn as e } from "../../../utils/cn.js";
2
- import { FloatingDialogExtension as t } from "./extensions/FloatingDialog.js";
3
- import n from "./Toolbar/Toolbar.js";
4
- import ee from "./AIRewrite.js";
5
- import r from "./ContextMenu.js";
6
- import i from "./CommentPanel.js";
7
- import a from "./CommentDialog.js";
8
- import o from "./CommentPopover.js";
9
- import s from "./SlashMenu.js";
10
- import c from "./BubbleToolbar.js";
11
- import te from "./BlockHandle.js";
12
- import { MarkdownBlockExtension as ne } from "./extensions/MarkdownBlock.js";
2
+ import { MarkdownBlockExtension as t } from "./extensions/MarkdownBlock.js";
3
+ import { FloatingDialogExtension as n } from "./extensions/FloatingDialog.js";
4
+ import ee from "./Toolbar/Toolbar.js";
5
+ import r from "./AIRewrite.js";
6
+ import i from "./ContextMenu.js";
7
+ import a from "./CommentPanel.js";
8
+ import o from "./CommentDialog.js";
9
+ import s from "./CommentPopover.js";
10
+ import c from "./SlashMenu.js";
11
+ import te from "./BubbleToolbar.js";
12
+ import ne from "./BlockHandle.js";
13
13
  import { CodeBlockExtension as re } from "./extensions/CodeBlockView.js";
14
14
  import ie from "./extensions/FontSize.js";
15
15
  import { CommentMark as ae } from "./extensions/CommentMark.js";
@@ -58,7 +58,9 @@ var w = ({ content: w, value: T, onChange: E, onChangeJSON: D, placeholder: O =
58
58
  4,
59
59
  5,
60
60
  6
61
- ] }
61
+ ] },
62
+ link: !1,
63
+ underline: !1
62
64
  }),
63
65
  le,
64
66
  ue,
@@ -87,8 +89,8 @@ var w = ({ content: w, value: T, onChange: E, onChangeJSON: D, placeholder: O =
87
89
  x,
88
90
  S,
89
91
  ie,
92
+ n,
90
93
  t,
91
- ne,
92
94
  ae
93
95
  ],
94
96
  content: T || w || "",
@@ -193,7 +195,7 @@ var w = ({ content: w, value: T, onChange: E, onChangeJSON: D, placeholder: O =
193
195
  maxHeight: Ie
194
196
  },
195
197
  children: [
196
- k && !V && /* @__PURE__ */ f(n, {
198
+ k && !V && /* @__PURE__ */ f(ee, {
197
199
  editor: X,
198
200
  config: j,
199
201
  labels: I,
@@ -220,18 +222,18 @@ var w = ({ content: w, value: T, onChange: E, onChangeJSON: D, placeholder: O =
220
222
  editor: X,
221
223
  className: "rte-editor-content"
222
224
  }),
223
- k && /* @__PURE__ */ f(r, {
225
+ k && /* @__PURE__ */ f(i, {
224
226
  editor: X,
225
227
  labels: I,
226
228
  onAIClick: A ? Z : void 0
227
229
  }),
228
- k && /* @__PURE__ */ f(s, { editor: X }),
229
- k && V && /* @__PURE__ */ f(c, {
230
+ k && /* @__PURE__ */ f(c, { editor: X }),
231
+ k && V && /* @__PURE__ */ f(te, {
230
232
  editor: X,
231
233
  onAddComment: Q
232
234
  }),
233
- k && V && /* @__PURE__ */ f(te, { editor: X }),
234
- /* @__PURE__ */ f(o, {
235
+ k && V && /* @__PURE__ */ f(ne, { editor: X }),
236
+ /* @__PURE__ */ f(s, {
235
237
  editor: X,
236
238
  threads: J,
237
239
  onThreadsChange: Y,
@@ -241,7 +243,7 @@ var w = ({ content: w, value: T, onChange: E, onChangeJSON: D, placeholder: O =
241
243
  currentUser: z
242
244
  })
243
245
  ]
244
- }), U && /* @__PURE__ */ f(i, {
246
+ }), U && /* @__PURE__ */ f(a, {
245
247
  ref: q,
246
248
  editor: X,
247
249
  threads: J,
@@ -250,7 +252,7 @@ var w = ({ content: w, value: T, onChange: E, onChangeJSON: D, placeholder: O =
250
252
  currentUser: z
251
253
  })]
252
254
  }),
253
- A && we && /* @__PURE__ */ f(ee, {
255
+ A && we && /* @__PURE__ */ f(r, {
254
256
  editor: X,
255
257
  aiConfig: A,
256
258
  labels: I,
@@ -258,7 +260,7 @@ var w = ({ content: w, value: T, onChange: E, onChangeJSON: D, placeholder: O =
258
260
  selectionRange: De,
259
261
  onClose: () => B(!1)
260
262
  }),
261
- /* @__PURE__ */ f(a, {
263
+ /* @__PURE__ */ f(o, {
262
264
  open: je,
263
265
  onSubmit: Ne,
264
266
  onClose: () => G(!1)
@@ -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 { cn } from '../../../utils/cn';\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 = cn(\n 'rte-container',\n formatPainterActive && 'rte-container--format-painter',\n notionMode && 'rte-container--notion',\n className,\n );\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 { cn } from '../../../utils/cn';\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 // v3 StarterKit bundles these; explicit extensions below stay in charge.\n link: false,\n underline: false,\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 = cn(\n 'rte-container',\n formatPainterActive && 'rte-container--format-painter',\n notionMode && 'rte-container--notion',\n className,\n );\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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"}
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import type { Editor } from '@tiptap/core';
3
+ export interface SearchReplaceProps {
4
+ editor: Editor;
5
+ }
6
+ export declare function SearchReplace({ editor }: SearchReplaceProps): React.JSX.Element;
7
+ export default SearchReplace;
@@ -1,7 +1,8 @@
1
- import { useCallback as e, useEffect as t, useRef as n, useState as r } from "react";
2
- import { jsx as i, jsxs as a } from "react/jsx-runtime";
1
+ import { useCallback as e, useEffect as t, useLayoutEffect as n, useRef as r, useState as i } from "react";
2
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
3
+ import { TextSelection as s } from "@tiptap/pm/state";
3
4
  //#region src/components/pro/RichTextEditor/SlashMenu.tsx
4
- var o = [
5
+ var c = [
5
6
  {
6
7
  label: "Text",
7
8
  icon: "Aa",
@@ -11,28 +12,28 @@ var o = [
11
12
  "text",
12
13
  "plain"
13
14
  ],
14
- action: (e) => e.chain().focus().setParagraph().run()
15
+ action: (e) => e.setParagraph()
15
16
  },
16
17
  {
17
18
  label: "Heading 1",
18
19
  icon: "H1",
19
20
  description: "Large heading",
20
21
  keywords: ["h1", "title"],
21
- action: (e) => e.chain().focus().toggleHeading({ level: 1 }).run()
22
+ action: (e) => e.setHeading({ level: 1 })
22
23
  },
23
24
  {
24
25
  label: "Heading 2",
25
26
  icon: "H2",
26
27
  description: "Medium heading",
27
28
  keywords: ["h2", "subtitle"],
28
- action: (e) => e.chain().focus().toggleHeading({ level: 2 }).run()
29
+ action: (e) => e.setHeading({ level: 2 })
29
30
  },
30
31
  {
31
32
  label: "Heading 3",
32
33
  icon: "H3",
33
34
  description: "Small heading",
34
35
  keywords: ["h3"],
35
- action: (e) => e.chain().focus().toggleHeading({ level: 3 }).run()
36
+ action: (e) => e.setHeading({ level: 3 })
36
37
  },
37
38
  {
38
39
  label: "Bullet List",
@@ -43,7 +44,7 @@ var o = [
43
44
  "bullet",
44
45
  "unordered"
45
46
  ],
46
- action: (e) => e.chain().focus().toggleBulletList().run()
47
+ action: (e) => e.toggleBulletList()
47
48
  },
48
49
  {
49
50
  label: "Numbered List",
@@ -54,7 +55,7 @@ var o = [
54
55
  "ordered",
55
56
  "number"
56
57
  ],
57
- action: (e) => e.chain().focus().toggleOrderedList().run()
58
+ action: (e) => e.toggleOrderedList()
58
59
  },
59
60
  {
60
61
  label: "Task List",
@@ -65,14 +66,14 @@ var o = [
65
66
  "checkbox",
66
67
  "task"
67
68
  ],
68
- action: (e) => e.chain().focus().toggleTaskList().run()
69
+ action: (e) => e.toggleTaskList()
69
70
  },
70
71
  {
71
72
  label: "Blockquote",
72
73
  icon: "\"",
73
74
  description: "Quote block",
74
75
  keywords: ["quote", "blockquote"],
75
- action: (e) => e.chain().focus().toggleBlockquote().run()
76
+ action: (e) => e.toggleBlockquote()
76
77
  },
77
78
  {
78
79
  label: "Code Block",
@@ -83,7 +84,7 @@ var o = [
83
84
  "pre",
84
85
  "snippet"
85
86
  ],
86
- action: (e) => e.chain().focus().toggleNode("codeBlock", "paragraph").run()
87
+ action: (e) => e.setNode("codeBlock")
87
88
  },
88
89
  {
89
90
  label: "Divider",
@@ -95,18 +96,18 @@ var o = [
95
96
  "separator",
96
97
  "line"
97
98
  ],
98
- action: (e) => e.chain().focus().setHorizontalRule().run()
99
+ action: (e) => e.setHorizontalRule()
99
100
  },
100
101
  {
101
102
  label: "Table",
102
103
  icon: "⊞",
103
104
  description: "Insert 3×3 table",
104
105
  keywords: ["table", "grid"],
105
- action: (e) => e.chain().focus().insertTable({
106
+ action: (e) => e.insertTable({
106
107
  rows: 3,
107
108
  cols: 3,
108
109
  withHeaderRow: !0
109
- }).run()
110
+ })
110
111
  },
111
112
  {
112
113
  label: "Image",
@@ -117,93 +118,155 @@ var o = [
117
118
  "picture",
118
119
  "photo"
119
120
  ],
120
- action: (e) => {
121
- let t = window.prompt("Image URL:");
122
- t && e.chain().focus().setImage({ src: t }).run();
123
- }
121
+ action: (e) => e
124
122
  }
125
- ], s = ({ editor: s }) => {
126
- let [c, l] = r(!1), [u, d] = r(""), [f, p] = r({
123
+ ], l = ({ editor: l }) => {
124
+ let [u, d] = i(!1), [f, p] = i(""), [m, h] = i({
127
125
  x: 0,
128
126
  y: 0
129
- }), [m, h] = r(0), [g, _] = r(null), v = n(null), y = u ? o.filter((e) => {
130
- let t = u.toLowerCase();
127
+ }), [g, _] = i(0), v = r(null), y = r(null), b = r(null), x = r(!1), S = e(() => {
128
+ if (l.isDestroyed || !l.isEditable || l.view.composing || x.current) return null;
129
+ let e = l.state.selection;
130
+ if (!(e instanceof s) || !e.empty || e.$from.parent.type.spec.code || e.$from.marks().some((e) => e.type.spec.code)) return null;
131
+ let { $from: t } = e, n = t.parent.textBetween(0, t.parentOffset, "\n", (e) => e.type.name === "hardBreak" ? "\n" : ""), r = /(?:^|\s)\/([^\s/]*)$/.exec(n);
132
+ return r ? {
133
+ from: t.pos - r[1].length - 1,
134
+ to: t.pos,
135
+ query: r[1]
136
+ } : null;
137
+ }, [l]), C = f ? c.filter((e) => {
138
+ let t = f.toLowerCase();
131
139
  return e.label.toLowerCase().includes(t) || e.description.toLowerCase().includes(t) || e.keywords?.some((e) => e.includes(t));
132
- }) : o, b = e(() => {
133
- l(!1), d(""), _(null), h(0);
134
- }, []), x = e((e) => {
135
- if (g !== null) {
136
- let { from: e } = s.state.selection;
137
- s.chain().focus().deleteRange({
138
- from: g,
139
- to: e
140
- }).run();
140
+ }) : c, w = e(() => {
141
+ d(!1), p("");
142
+ let e = y.current;
143
+ e && (b.current = `${e.from}:${e.to}:${e.query}`), y.current = null, _(0);
144
+ }, []), T = e((e) => {
145
+ let t = S(), n = y.current;
146
+ if (!t || !n || t.from !== n.from || t.to !== n.to || t.query !== n.query) {
147
+ w();
148
+ return;
149
+ }
150
+ let r = e.label === "Image" ? window.prompt("Image URL:")?.trim() : void 0;
151
+ if (e.label === "Image" && !r) {
152
+ w();
153
+ return;
141
154
  }
142
- e.action(s), b();
155
+ w();
156
+ let i = l.chain().focus().deleteRange(t);
157
+ (r ? i.setImage({ src: r }) : e.action(i)).run();
143
158
  }, [
144
- s,
145
- g,
146
- b
159
+ l,
160
+ S,
161
+ w
147
162
  ]);
148
163
  return t(() => {
149
- let e = () => {
150
- let { $from: e } = s.state.selection, t = e.parent.textContent.slice(0, e.parentOffset), n = /\/([a-zA-Z0-9]*)$/.exec(t);
151
- if (n) {
152
- let t = e.start() + n.index;
153
- _(t), d(n[1]), h(0);
154
- let r = s.view.coordsAtPos(e.pos), i = s.view.dom.closest(".rte-editor-wrapper")?.getBoundingClientRect();
155
- i && p({
156
- x: r.left - i.left,
157
- y: r.bottom - i.top + 4
158
- }), l(!0);
159
- } else c && b();
164
+ let e, t = () => {
165
+ let e = l.isFocused ? S() : null;
166
+ if (!e) {
167
+ y.current = null, b.current = null, d(!1);
168
+ return;
169
+ }
170
+ b.current !== `${e.from}:${e.to}:${e.query}` && ((y.current?.query !== e.query || y.current?.from !== e.from) && _(0), y.current = e, p(e.query), d(!0));
171
+ }, n = () => {
172
+ x.current = !0, w();
173
+ }, r = () => {
174
+ x.current = !1, b.current = null, e = setTimeout(t, 0);
175
+ }, i = l.view.dom;
176
+ return l.on("transaction", t), l.on("blur", w), i.addEventListener("compositionstart", n), i.addEventListener("compositionend", r), () => {
177
+ clearTimeout(e), l.off("transaction", t), l.off("blur", w), i.removeEventListener("compositionstart", n), i.removeEventListener("compositionend", r);
160
178
  };
161
- return s.on("selectionUpdate", e), s.on("update", e), () => {
162
- s.off("selectionUpdate", e), s.off("update", e);
179
+ }, [
180
+ l,
181
+ S,
182
+ w
183
+ ]), n(() => {
184
+ if (!u || !C.length) return;
185
+ let e = l.view.dom.closest(".rte-editor-wrapper"), t = v.current;
186
+ if (!e || !t) return;
187
+ let n = () => {
188
+ let n = S();
189
+ if (!n) {
190
+ w();
191
+ return;
192
+ }
193
+ let r = l.view.coordsAtPos(n.to), i = e.getBoundingClientRect(), a = Math.max(8, i.left + e.clientLeft), o = Math.min(window.innerWidth - 8, i.right), s = Math.max(8, i.top + e.clientTop), c = Math.min(window.innerHeight - 8, i.bottom);
194
+ if (r.bottom < s || r.top > c) {
195
+ w();
196
+ return;
197
+ }
198
+ t.style.minWidth = "0", t.style.width = `${Math.max(0, Math.min(280, o - a))}px`;
199
+ let u = c - r.bottom - 4, d = r.top - s - 4, f = u < Math.min(300, t.scrollHeight) && d > u;
200
+ t.style.maxHeight = `${Math.max(0, Math.min(300, f ? d : u))}px`;
201
+ let p = Math.max(a, Math.min(r.left, o - t.offsetWidth)), m = f ? r.top - t.offsetHeight - 4 : r.bottom + 4;
202
+ h({
203
+ x: p - i.left - e.clientLeft + e.scrollLeft,
204
+ y: m - i.top - e.clientTop + e.scrollTop
205
+ });
206
+ };
207
+ return n(), window.addEventListener("scroll", n, !0), window.addEventListener("resize", n), l.on("transaction", n), () => {
208
+ window.removeEventListener("scroll", n, !0), window.removeEventListener("resize", n), l.off("transaction", n);
163
209
  };
164
210
  }, [
165
- s,
166
- c,
167
- b
211
+ l,
212
+ u,
213
+ C.length,
214
+ S,
215
+ w
168
216
  ]), t(() => {
169
- if (!c) return;
217
+ if (!u) return;
218
+ let e = v.current, t = e?.children[g];
219
+ e && t && (t.offsetTop < e.scrollTop ? e.scrollTop = t.offsetTop : t.offsetTop + t.offsetHeight > e.scrollTop + e.clientHeight && (e.scrollTop = t.offsetTop + t.offsetHeight - e.clientHeight));
220
+ }, [g, u]), t(() => {
221
+ if (!u) return;
170
222
  let e = (e) => {
171
- e.key === "ArrowDown" ? (e.preventDefault(), h((e) => (e + 1) % y.length)) : e.key === "ArrowUp" ? (e.preventDefault(), h((e) => (e - 1 + y.length) % y.length)) : e.key === "Enter" ? (e.preventDefault(), y[m] && x(y[m])) : e.key === "Escape" && (e.preventDefault(), b());
223
+ !l.view.dom.contains(e.target) || !l.isFocused || e.isComposing || e.keyCode === 229 || l.view.composing || x.current || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey || (C.length || e.key === "Escape") && ([
224
+ "ArrowDown",
225
+ "ArrowUp",
226
+ "Enter",
227
+ "Escape"
228
+ ].includes(e.key) && e.stopImmediatePropagation(), e.key === "ArrowDown" ? (e.preventDefault(), _((e) => (e + 1) % C.length)) : e.key === "ArrowUp" ? (e.preventDefault(), _((e) => (e - 1 + C.length) % C.length)) : e.key === "Enter" ? (e.preventDefault(), C[g] && T(C[g])) : e.key === "Escape" && (e.preventDefault(), w()));
172
229
  };
173
230
  return document.addEventListener("keydown", e, !0), () => document.removeEventListener("keydown", e, !0);
174
231
  }, [
175
- c,
176
- y,
177
- m,
178
- x,
179
- b
232
+ l,
233
+ u,
234
+ C,
235
+ g,
236
+ T,
237
+ w
180
238
  ]), t(() => {
181
- if (!c) return;
239
+ if (!u) return;
182
240
  let e = (e) => {
183
- v.current && !v.current.contains(e.target) && b();
241
+ v.current && !v.current.contains(e.target) && w();
184
242
  };
185
243
  return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
186
- }, [c, b]), !c || y.length === 0 ? null : /* @__PURE__ */ i("div", {
244
+ }, [u, w]), !u || C.length === 0 ? null : /* @__PURE__ */ a("div", {
187
245
  ref: v,
188
246
  className: "rte-slash-menu",
247
+ role: "menu",
248
+ "aria-label": "Insert block",
189
249
  style: {
190
- left: f.x,
191
- top: f.y
250
+ left: m.x,
251
+ top: m.y
192
252
  },
193
- children: y.map((e, t) => /* @__PURE__ */ a("button", {
253
+ onMouseDown: (e) => e.preventDefault(),
254
+ children: C.map((e, t) => /* @__PURE__ */ o("button", {
194
255
  type: "button",
195
- className: `rte-slash-menu__item ${t === m ? "rte-slash-menu__item--active" : ""}`,
196
- onClick: () => x(e),
197
- onMouseEnter: () => h(t),
198
- children: [/* @__PURE__ */ i("span", {
256
+ role: "menuitem",
257
+ tabIndex: -1,
258
+ className: `rte-slash-menu__item ${t === g ? "rte-slash-menu__item--active" : ""}`,
259
+ onClick: () => T(e),
260
+ onMouseEnter: () => _(t),
261
+ children: [/* @__PURE__ */ a("span", {
199
262
  className: "rte-slash-menu__icon",
200
263
  children: e.icon
201
- }), /* @__PURE__ */ a("div", {
264
+ }), /* @__PURE__ */ o("div", {
202
265
  className: "rte-slash-menu__text",
203
- children: [/* @__PURE__ */ i("span", {
266
+ children: [/* @__PURE__ */ a("span", {
204
267
  className: "rte-slash-menu__label",
205
268
  children: e.label
206
- }), /* @__PURE__ */ i("span", {
269
+ }), /* @__PURE__ */ a("span", {
207
270
  className: "rte-slash-menu__desc",
208
271
  children: e.description
209
272
  })]
@@ -212,6 +275,6 @@ var o = [
212
275
  });
213
276
  };
214
277
  //#endregion
215
- export { s as default };
278
+ export { l as default };
216
279
 
217
280
  //# sourceMappingURL=SlashMenu.js.map