From 17952718f7b9cff031f1b0350e7a76a37048b0a3 Mon Sep 17 00:00:00 2001 From: Tim Wilson Date: Thu, 6 Nov 2025 13:05:32 -0500 Subject: [PATCH 1/6] Big `RichTextArea` refactor --- .../[campaignId]/campaign-editor.tsx | 11 +- packages/ui/src/rich-text-area/index.tsx | 224 ++---------------- .../src/rich-text-area/rich-text-provider.tsx | 214 +++++++++++++++++ .../src/rich-text-area/rich-text-toolbar.tsx | 20 +- 4 files changed, 260 insertions(+), 209 deletions(-) create mode 100644 packages/ui/src/rich-text-area/rich-text-provider.tsx diff --git a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/[campaignId]/campaign-editor.tsx b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/[campaignId]/campaign-editor.tsx index 75db9c2424d..ab1493e601a 100644 --- a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/[campaignId]/campaign-editor.tsx +++ b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/[campaignId]/campaign-editor.tsx @@ -15,6 +15,8 @@ import { Lock, PaperPlane, RichTextArea, + RichTextProvider, + RichTextToolbar, SmartDateTimePicker, StatusBadge, Tooltip, @@ -506,7 +508,7 @@ export function CampaignEditor({ campaign }: { campaign: Campaign }) { control={control} name="bodyJson" render={({ field }) => ( - + > +
+ + +
+ )} /> diff --git a/packages/ui/src/rich-text-area/index.tsx b/packages/ui/src/rich-text-area/index.tsx index f66507de6b8..4a33cb58fba 100644 --- a/packages/ui/src/rich-text-area/index.tsx +++ b/packages/ui/src/rich-text-area/index.tsx @@ -1,201 +1,29 @@ import { cn } from "@dub/utils"; -import FileHandler from "@tiptap/extension-file-handler"; -import Image from "@tiptap/extension-image"; -import Mention from "@tiptap/extension-mention"; -import { Placeholder } from "@tiptap/extensions"; -import { Editor, EditorContent, EditorContext, useEditor } from "@tiptap/react"; -import StarterKit from "@tiptap/starter-kit"; -import { forwardRef, useImperativeHandle, useMemo, useState } from "react"; +import { EditorContent } from "@tiptap/react"; import { LoadingSpinner } from "../icons"; -import { RichTextToolbar } from "./rich-text-toolbar"; -import { suggestions } from "./variables"; - -export const richTextAreaExtensions = [ - StarterKit.configure({ - heading: { - levels: [1, 2], - }, - }), -]; - -interface RichTextAreaProps { - initialValue?: any; - onChange?: (editor: Editor) => void; - placeholder?: string; - className?: string; - editorClassName?: string; - uploadImage?: (file: File) => Promise; - variables?: string[]; - editable?: boolean; -} - -export interface RichTextAreaRef { - setContent: (content: any) => void; -} - -export const RichTextArea = forwardRef( - function RichTextArea( - { - initialValue, - onChange, - placeholder = "Start typing...", - className, - editorClassName, - uploadImage, - variables, - editable = true, - }, - ref, - ) { - const [isUploading, setIsUploading] = useState(false); - - const handleImageUpload = async ( - file: File, - currentEditor: Editor, - pos: number, - ) => { - setIsUploading(true); - - const src = await uploadImage?.(file); - if (!src) { - setIsUploading(false); - return; - } - - currentEditor - .chain() - .insertContentAt(pos, { - type: "image", - attrs: { - src, - }, - }) - .focus() - .run(); - - setIsUploading(false); - }; - - const editor = useEditor({ - editable, - extensions: [ - ...richTextAreaExtensions, - Placeholder.configure({ - placeholder, - emptyEditorClass: - "before:content-[attr(data-placeholder)] before:float-left before:text-content-muted before:h-0 before:pointer-events-none", - }), - - // Images - ...(uploadImage - ? [ - Image.configure({ - inline: false, - HTMLAttributes: { - class: "rounded-lg max-w-full h-auto", - }, - }), - FileHandler.configure({ - allowedMimeTypes: [ - "image/png", - "image/jpeg", - "image/gif", - "image/webp", - ], - onDrop: (currentEditor, files, pos) => { - files.forEach((file) => - handleImageUpload(file, currentEditor, pos), - ); - }, - onPaste: (currentEditor, files, htmlContent) => { - if (htmlContent) return false; - files.forEach((file) => - handleImageUpload( - file, - currentEditor, - currentEditor.state.selection.anchor, - ), - ); - }, - }), - ] - : []), - ...(variables - ? [ - Mention.extend({ - renderHTML({ node }: { node: any }) { - return [ - "span", - { - class: - "px-1 py-0.5 bg-blue-100 text-blue-700 rounded font-semibold", - "data-type": "mention", - "data-id": node.attrs.id, - }, - `{{${node.attrs.id}}}`, - ]; - }, - renderText({ node }: { node: any }) { - return `{{${node.attrs.id}}}`; - }, - }).configure({ - suggestion: suggestions(variables), - }), - ] - : []), - ], - editorProps: { - attributes: { - class: cn( - "prose prose-sm prose-neutral max-w-none focus:outline-none", - "[&_.ProseMirror-selectednode]:outline [&_.ProseMirror-selectednode]:outline-2 [&_.ProseMirror-selectednode]:outline-blue-500 [&_.ProseMirror-selectednode]:outline-offset-2", - editorClassName, - ), - }, - }, - content: initialValue, - onUpdate: ({ editor }) => onChange?.(editor), - immediatelyRender: false, - }); - - useImperativeHandle(ref, () => ({ - setContent: (content: any) => { - editor?.commands.setContent(content); - }, - })); - - const providerValue = useMemo(() => ({ editor }), [editor]); - - return ( - -
- - handleImageUpload( - file, - editor, - editor.state.selection.anchor, - ) - : undefined - } - /> - - - {isUploading && ( -
- -
- )} +import { useRichTextContext } from "./rich-text-provider"; + +export * from "./rich-text-provider"; +export * from "./rich-text-toolbar"; + +export function RichTextArea({ className }: { className?: string }) { + const { editor, isUploading, handleImageUpload } = useRichTextContext(); + + return ( +
+ + + {isUploading && ( +
+
- - ); - }, -); + )} +
+ ); +} diff --git a/packages/ui/src/rich-text-area/rich-text-provider.tsx b/packages/ui/src/rich-text-area/rich-text-provider.tsx new file mode 100644 index 00000000000..c1d2f5c4f1c --- /dev/null +++ b/packages/ui/src/rich-text-area/rich-text-provider.tsx @@ -0,0 +1,214 @@ +import { cn } from "@dub/utils"; +import FileHandler from "@tiptap/extension-file-handler"; +import Image from "@tiptap/extension-image"; +import Mention from "@tiptap/extension-mention"; +import { Placeholder } from "@tiptap/extensions"; +import { Editor, useEditor } from "@tiptap/react"; +import StarterKit from "@tiptap/starter-kit"; +import { + PropsWithChildren, + createContext, + forwardRef, + useContext, + useImperativeHandle, + useMemo, + useState, +} from "react"; +import { suggestions } from "./variables"; + +type RichTextProviderProps = PropsWithChildren<{ + placeholder?: string; + initialValue?: any; + onChange?: (editor: Editor) => void; + uploadImage?: (file: File) => Promise; + variables?: string[]; + editable?: boolean; + editorClassName?: string; +}>; + +export const RichTextContext = createContext< + | (RichTextProviderProps & { + editor: Editor | null; + isUploading: boolean; + handleImageUpload: + | ((file: File, currentEditor: Editor, pos: number) => Promise) + | null; + }) + | null +>(null); + +export type RichTextAreaProviderRef = { + setContent: (content: any) => void; +}; + +export const RichTextProvider = forwardRef< + RichTextAreaProviderRef, + RichTextProviderProps +>( + ( + { + children, + placeholder = "Start typing...", + uploadImage, + editable, + editorClassName, + variables, + initialValue, + onChange, + }: RichTextProviderProps, + ref, + ) => { + const [isUploading, setIsUploading] = useState(false); + + const handleImageUpload = useMemo( + () => + uploadImage + ? async (file: File, currentEditor: Editor, pos: number) => { + setIsUploading(true); + + const src = await uploadImage?.(file); + if (!src) { + setIsUploading(false); + return; + } + + currentEditor + .chain() + .insertContentAt(pos, { + type: "image", + attrs: { + src, + }, + }) + .focus() + .run(); + + setIsUploading(false); + } + : null, + [uploadImage], + ); + + const editor = useEditor({ + editable: editable, + extensions: [ + StarterKit.configure({ + heading: { + levels: [1, 2], + }, + }), + Placeholder.configure({ + placeholder, + emptyEditorClass: + "before:content-[attr(data-placeholder)] before:float-left before:text-content-muted before:h-0 before:pointer-events-none", + }), + + // Images + ...(handleImageUpload + ? [ + Image.configure({ + inline: false, + HTMLAttributes: { + class: "rounded-lg max-w-full h-auto", + }, + }), + FileHandler.configure({ + allowedMimeTypes: [ + "image/png", + "image/jpeg", + "image/gif", + "image/webp", + ], + onDrop: (currentEditor, files, pos) => { + files.forEach((file) => + handleImageUpload(file, currentEditor, pos), + ); + }, + onPaste: (currentEditor, files, htmlContent) => { + if (htmlContent) return false; + files.forEach((file) => + handleImageUpload( + file, + currentEditor, + currentEditor.state.selection.anchor, + ), + ); + }, + }), + ] + : []), + ...(variables + ? [ + Mention.extend({ + renderHTML({ node }: { node: any }) { + return [ + "span", + { + class: + "px-1 py-0.5 bg-blue-100 text-blue-700 rounded font-semibold", + "data-type": "mention", + "data-id": node.attrs.id, + }, + `{{${node.attrs.id}}}`, + ]; + }, + renderText({ node }: { node: any }) { + return `{{${node.attrs.id}}}`; + }, + }).configure({ + suggestion: suggestions(variables), + }), + ] + : []), + ], + editorProps: { + attributes: { + class: cn( + "prose prose-sm prose-neutral max-w-none focus:outline-none", + "[&_.ProseMirror-selectednode]:outline [&_.ProseMirror-selectednode]:outline-2 [&_.ProseMirror-selectednode]:outline-blue-500 [&_.ProseMirror-selectednode]:outline-offset-2", + editorClassName, + ), + }, + }, + content: initialValue, + onUpdate: ({ editor }) => onChange?.(editor), + immediatelyRender: false, + }); + + useImperativeHandle(ref, () => ({ + setContent: (content: any) => { + editor?.commands.setContent(content); + }, + })); + + return ( + + {children} + + ); + }, +); + +export function useRichTextContext() { + const context = useContext(RichTextContext); + + if (!context) + throw new Error( + "useRichTextContext must be used within a RichTextProvider", + ); + + return context; +} diff --git a/packages/ui/src/rich-text-area/rich-text-toolbar.tsx b/packages/ui/src/rich-text-area/rich-text-toolbar.tsx index fbb069d11ae..dd9f5dbbd84 100644 --- a/packages/ui/src/rich-text-area/rich-text-toolbar.tsx +++ b/packages/ui/src/rich-text-area/rich-text-toolbar.tsx @@ -11,13 +11,10 @@ import { TextBold, TextItalic, } from "../icons"; +import { useRichTextContext } from "./rich-text-provider"; -export function RichTextToolbar({ - onImageUpload, -}: { - onImageUpload?: (file: File) => void; -}) { - const { editor } = useCurrentEditor(); +export function RichTextToolbar() { + const { editor, handleImageUpload, isUploading } = useRichTextContext(); const editorState = useEditorState({ editor, @@ -33,7 +30,12 @@ export function RichTextToolbar({ const inputImageRef = useRef(null); return ( -
+
- {onImageUpload && ( + {handleImageUpload && editor && ( <> From 50feeaf31213a705cb49ff1765e2820022862526 Mon Sep 17 00:00:00 2001 From: Tim Wilson Date: Thu, 6 Nov 2025 15:05:14 -0500 Subject: [PATCH 2/6] Add features --- .../src/rich-text-area/rich-text-provider.tsx | 27 ++++- .../src/rich-text-area/rich-text-toolbar.tsx | 98 ++++++++++--------- 2 files changed, 76 insertions(+), 49 deletions(-) diff --git a/packages/ui/src/rich-text-area/rich-text-provider.tsx b/packages/ui/src/rich-text-area/rich-text-provider.tsx index c1d2f5c4f1c..128991be605 100644 --- a/packages/ui/src/rich-text-area/rich-text-provider.tsx +++ b/packages/ui/src/rich-text-area/rich-text-provider.tsx @@ -16,9 +16,19 @@ import { } from "react"; import { suggestions } from "./variables"; +const FEATURES = [ + "images", + "variables", + "links", + "headings", + "bold", + "italic", +] as const; + type RichTextProviderProps = PropsWithChildren<{ placeholder?: string; initialValue?: any; + features?: (typeof FEATURES)[number][]; onChange?: (editor: Editor) => void; uploadImage?: (file: File) => Promise; variables?: string[]; @@ -48,6 +58,7 @@ export const RichTextProvider = forwardRef< ( { children, + features = FEATURES as any, placeholder = "Start typing...", uploadImage, editable, @@ -93,9 +104,14 @@ export const RichTextProvider = forwardRef< editable: editable, extensions: [ StarterKit.configure({ - heading: { - levels: [1, 2], - }, + heading: features.includes("headings") + ? { + levels: [1, 2], + } + : false, + bold: features.includes("bold") ? undefined : false, + italic: features.includes("italic") ? undefined : false, + link: features.includes("links") ? undefined : false, }), Placeholder.configure({ placeholder, @@ -104,7 +120,7 @@ export const RichTextProvider = forwardRef< }), // Images - ...(handleImageUpload + ...(features.includes("images") && handleImageUpload ? [ Image.configure({ inline: false, @@ -137,7 +153,7 @@ export const RichTextProvider = forwardRef< }), ] : []), - ...(variables + ...(features.includes("variables") && variables ? [ Mention.extend({ renderHTML({ node }: { node: any }) { @@ -184,6 +200,7 @@ export const RichTextProvider = forwardRef< return ( - editor?.chain().focus().toggleBold().run()} - /> - editor?.chain().focus().toggleItalic().run()} - /> - - editor?.chain().focus().toggleHeading({ level: 1 }).run() - } - /> - - editor?.chain().focus().toggleHeading({ level: 2 }).run() - } - /> - - - { - if (editor?.state.selection.$from.nodeBefore?.text?.endsWith("@")) { - editor?.commands.focus(); - return; - } - editor?.chain().focus().insertContent("@").run(); - }} - /> + {features?.includes("bold") && ( + editor?.chain().focus().toggleBold().run()} + /> + )} + {features?.includes("italic") && ( + editor?.chain().focus().toggleItalic().run()} + /> + )} + {features?.includes("headings") && ( + <> + + editor?.chain().focus().toggleHeading({ level: 1 }).run() + } + /> + + editor?.chain().focus().toggleHeading({ level: 2 }).run() + } + /> + + )} + {features?.includes("links") && } + {features?.includes("variables") && ( + { + if (editor?.state.selection.$from.nodeBefore?.text?.endsWith("@")) { + editor?.commands.focus(); + return; + } + editor?.chain().focus().insertContent("@").run(); + }} + /> + )} - {handleImageUpload && editor && ( + {features?.includes("images") && handleImageUpload && editor && ( <> Date: Thu, 6 Nov 2025 16:35:15 -0500 Subject: [PATCH 3/6] Hook up `MessageInput` --- apps/web/ui/partners/partner-comments.tsx | 11 +- apps/web/ui/shared/emoji-picker.tsx | 23 +- apps/web/ui/shared/message-input.tsx | 142 +++--- packages/ui/package.json | 15 +- packages/ui/src/rich-text-area/index.tsx | 11 +- .../src/rich-text-area/rich-text-provider.tsx | 25 +- .../src/rich-text-area/rich-text-toolbar.tsx | 47 +- pnpm-lock.yaml | 421 ++++++++++++++++-- 8 files changed, 536 insertions(+), 159 deletions(-) diff --git a/apps/web/ui/partners/partner-comments.tsx b/apps/web/ui/partners/partner-comments.tsx index a13421328c7..6c98677532b 100644 --- a/apps/web/ui/partners/partner-comments.tsx +++ b/apps/web/ui/partners/partner-comments.tsx @@ -347,16 +347,7 @@ function CommentCard({ toast.error("Failed to update comment"); }); }} - onMount={({ textarea }) => { - if (!textarea) return; - - // Programmatically focus and move cursor to the end, since React's autoFocus is putting the cursor at the start - textarea.focus(); - textarea.setSelectionRange( - textarea.value.length, - textarea.value.length, - ); - }} + autoFocus className="animate-fade-in" placeholder="Edit comment" sendButtonText="Save" diff --git a/apps/web/ui/shared/emoji-picker.tsx b/apps/web/ui/shared/emoji-picker.tsx index 26c31dd8809..464d853b3b0 100644 --- a/apps/web/ui/shared/emoji-picker.tsx +++ b/apps/web/ui/shared/emoji-picker.tsx @@ -1,15 +1,14 @@ -"use client"; - import { Button, Popover } from "@dub/ui"; import { FaceSmile } from "@dub/ui/icons"; import { EmojiPicker as EmojiPickerBase } from "frimousse"; -import { useState } from "react"; +import { PropsWithChildren, useState } from "react"; export function EmojiPicker({ onSelect, -}: { + children, +}: PropsWithChildren<{ onSelect: (emoji: string) => void; -}) { +}>) { const [isOpen, setIsOpen] = useState(false); return ( @@ -65,12 +64,14 @@ export function EmojiPicker({ } > -
-
+ ); } + +function MessageInputToolbar() { + const { editor } = useRichTextContext(); + + return ( + { + if (!editor) return; + editor.chain().focus().insertContent(emoji).run(); + }} + > + + + } + /> + ); +} diff --git a/packages/ui/package.json b/packages/ui/package.json index 18cbb050fc4..48652f9875f 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -72,13 +72,14 @@ "@react-aria/datepicker": "^3.10.0", "@react-stately/datepicker": "^3.9.3", "@tanstack/react-table": "^8.17.3", - "@tiptap/extension-file-handler": "^3.0.9", - "@tiptap/extension-image": "^3.0.9", - "@tiptap/extension-mention": "^3.0.9", - "@tiptap/extensions": "^3.0.9", - "@tiptap/pm": "^3.0.9", - "@tiptap/react": "^3.0.9", - "@tiptap/starter-kit": "^3.0.9", + "@tiptap/extension-file-handler": "^3.10.2", + "@tiptap/extension-image": "^3.10.2", + "@tiptap/extension-mention": "^3.10.2", + "@tiptap/extensions": "^3.10.2", + "@tiptap/markdown": "^3.10.2", + "@tiptap/pm": "^3.10.2", + "@tiptap/react": "^3.10.2", + "@tiptap/starter-kit": "^3.10.2", "@visx/axis": "^2.14.0", "@visx/clip-path": "^3.3.0", "@visx/curve": "^3.3.0", diff --git a/packages/ui/src/rich-text-area/index.tsx b/packages/ui/src/rich-text-area/index.tsx index 4a33cb58fba..25f7619623d 100644 --- a/packages/ui/src/rich-text-area/index.tsx +++ b/packages/ui/src/rich-text-area/index.tsx @@ -1,13 +1,16 @@ import { cn } from "@dub/utils"; -import { EditorContent } from "@tiptap/react"; +import { EditorContent, EditorContentProps } from "@tiptap/react"; import { LoadingSpinner } from "../icons"; import { useRichTextContext } from "./rich-text-provider"; export * from "./rich-text-provider"; export * from "./rich-text-toolbar"; -export function RichTextArea({ className }: { className?: string }) { - const { editor, isUploading, handleImageUpload } = useRichTextContext(); +export function RichTextArea({ + className, + ...rest +}: Omit) { + const { editor, isUploading } = useRichTextContext(); return (
- + {isUploading && (
diff --git a/packages/ui/src/rich-text-area/rich-text-provider.tsx b/packages/ui/src/rich-text-area/rich-text-provider.tsx index 128991be605..e647ae80304 100644 --- a/packages/ui/src/rich-text-area/rich-text-provider.tsx +++ b/packages/ui/src/rich-text-area/rich-text-provider.tsx @@ -3,6 +3,7 @@ import FileHandler from "@tiptap/extension-file-handler"; import Image from "@tiptap/extension-image"; import Mention from "@tiptap/extension-mention"; import { Placeholder } from "@tiptap/extensions"; +import { Markdown } from "@tiptap/markdown"; import { Editor, useEditor } from "@tiptap/react"; import StarterKit from "@tiptap/starter-kit"; import { @@ -29,15 +30,22 @@ type RichTextProviderProps = PropsWithChildren<{ placeholder?: string; initialValue?: any; features?: (typeof FEATURES)[number][]; + markdown?: boolean; onChange?: (editor: Editor) => void; uploadImage?: (file: File) => Promise; variables?: string[]; editable?: boolean; + autoFocus?: boolean; + + editorProps?: Parameters[0]["editorProps"]; editorClassName?: string; }>; export const RichTextContext = createContext< - | (RichTextProviderProps & { + | (Pick< + RichTextProviderProps, + "features" | "markdown" | "variables" | "editable" + > & { editor: Editor | null; isUploading: boolean; handleImageUpload: @@ -59,13 +67,16 @@ export const RichTextProvider = forwardRef< { children, features = FEATURES as any, + markdown = false, placeholder = "Start typing...", uploadImage, editable, - editorClassName, + autoFocus, variables, initialValue, onChange, + editorProps, + editorClassName, }: RichTextProviderProps, ref, ) => { @@ -102,7 +113,9 @@ export const RichTextProvider = forwardRef< const editor = useEditor({ editable: editable, + autofocus: autoFocus ? "end" : false, extensions: [ + ...(markdown ? [Markdown] : []), StarterKit.configure({ heading: features.includes("headings") ? { @@ -179,12 +192,14 @@ export const RichTextProvider = forwardRef< ], editorProps: { attributes: { + ...editorProps?.attributes, class: cn( "prose prose-sm prose-neutral max-w-none focus:outline-none", "[&_.ProseMirror-selectednode]:outline [&_.ProseMirror-selectednode]:outline-2 [&_.ProseMirror-selectednode]:outline-blue-500 [&_.ProseMirror-selectednode]:outline-offset-2", editorClassName, ), }, + ...editorProps, }, content: initialValue, onUpdate: ({ editor }) => onChange?.(editor), @@ -201,13 +216,9 @@ export const RichTextProvider = forwardRef< + {toolsStart} + {features?.includes("bold") && ( - )} {features?.includes("italic") && ( - - - } {features?.includes("variables") && ( - - )} + + {toolsEnd}
); } function LinkButton() { - const { editor } = useCurrentEditor(); + const { editor } = useRichTextContext(); const editorState = useEditorState({ editor, @@ -126,7 +136,7 @@ function LinkButton() { }); return ( - { @@ -152,7 +162,7 @@ function LinkButton() { ); } -type ToolbarButtonProps = { +type RichTextToolbarButtonProps = { icon: Icon; label?: string; isActive?: boolean; @@ -160,9 +170,18 @@ type ToolbarButtonProps = { disabled?: boolean; }; -const ToolbarButton = forwardRef( +export const RichTextToolbarButton = forwardRef< + HTMLButtonElement, + RichTextToolbarButtonProps +>( ( - { icon: Icon, label, isActive, onClick, disabled }: ToolbarButtonProps, + { + icon: Icon, + label, + isActive, + onClick, + disabled, + }: RichTextToolbarButtonProps, ref, ) => { return ( diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 85b5d44b652..c0c57fc0bf1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -758,26 +758,29 @@ importers: specifier: ^8.17.3 version: 8.17.3(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@tiptap/extension-file-handler': - specifier: ^3.0.9 - version: 3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/extension-text-style@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9)))(@tiptap/pm@3.0.9) + specifier: ^3.10.2 + version: 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/extension-text-style@3.0.9(@tiptap/core@3.10.2(@tiptap/pm@3.10.2)))(@tiptap/pm@3.10.2) '@tiptap/extension-image': - specifier: ^3.0.9 - version: 3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9)) + specifier: ^3.10.2 + version: 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2)) '@tiptap/extension-mention': - specifier: ^3.0.9 - version: 3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9)(@tiptap/suggestion@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9)) + specifier: ^3.10.2 + version: 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2)(@tiptap/suggestion@3.0.9(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2)) '@tiptap/extensions': - specifier: ^3.0.9 - version: 3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9) + specifier: ^3.10.2 + version: 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2) + '@tiptap/markdown': + specifier: ^3.10.2 + version: 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2) '@tiptap/pm': - specifier: ^3.0.9 - version: 3.0.9 + specifier: ^3.10.2 + version: 3.10.2 '@tiptap/react': - specifier: ^3.0.9 - version: 3.0.9(@floating-ui/dom@1.6.12)(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + specifier: ^3.10.2 + version: 3.10.2(@floating-ui/dom@1.6.12)(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2)(@types/react-dom@19.1.9(@types/react@19.1.14))(@types/react@19.1.14)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@tiptap/starter-kit': - specifier: ^3.0.9 - version: 3.0.9 + specifier: ^3.10.2 + version: 3.10.2 '@visx/axis': specifier: ^2.14.0 version: 2.14.0(react@19.1.1) @@ -5631,93 +5634,171 @@ packages: peerDependencies: '@tiptap/pm': ^3.0.9 + '@tiptap/core@3.10.2': + resolution: {integrity: sha512-rWgo/9g5lSWT3/00wPvG+3EEuPqDxegYMp0v7YkSuURi43Btf+SG4yGtQ5Si9ICF0NJjeZoHLusrjeVltcrsSw==} + peerDependencies: + '@tiptap/pm': ^3.10.2 + '@tiptap/extension-blockquote@3.0.9': resolution: {integrity: sha512-dGhMWb6GIjgIUuLQDhSlHT6yB4YvnYqe01nHzEvcbSii75KOcLwboVnqxw4p+gsDZLvZRGv/6bZBJh7GKZa8OQ==} peerDependencies: '@tiptap/core': ^3.0.9 + '@tiptap/extension-blockquote@3.10.2': + resolution: {integrity: sha512-hmGnb5SYTXOeeP4+ZriOELewTMEITW6Xj2KJ8UpvCfSlOU33/SGeIlBsGvXsN3M4CU66HrK6K1LQVM8LiyEITA==} + peerDependencies: + '@tiptap/core': ^3.10.2 + '@tiptap/extension-bold@3.0.9': resolution: {integrity: sha512-rVULIFt9ZO+fO5ty9zuC3HwY3knxUw7q9JBztpKPfQQCuIJ+iQnOfB8NtI3L8hxVSxhIR1pqr8B3S/8vlpXbVg==} peerDependencies: '@tiptap/core': ^3.0.9 - '@tiptap/extension-bubble-menu@3.0.9': - resolution: {integrity: sha512-fZQfdSbKJl3J+Yi+s8NrcLBgXHOaGVD4g+vn+orTPUlZdG9FWvEoon8DexOdK9OvYnW6QMM7kS8whOgpogVyUQ==} + '@tiptap/extension-bold@3.10.2': + resolution: {integrity: sha512-lgUpWuBhlZwf+/pVKfqVUpHfA5PDECDyobcXmMrRSpreM+58psZtWDZMZ21K94SmJukRidW7vdNWoTSRSEiY4Q==} peerDependencies: - '@tiptap/core': ^3.0.9 - '@tiptap/pm': ^3.0.9 + '@tiptap/core': ^3.10.2 + + '@tiptap/extension-bubble-menu@3.10.2': + resolution: {integrity: sha512-gT4PMDXWdUAdijPH35LDUsPv+YIIhEHUuvqPFBGRudrycQ2TlWMmRZ2jYNg1PGBh+/UHVR2l8TNuZ5QSr88ISQ==} + peerDependencies: + '@tiptap/core': ^3.10.2 + '@tiptap/pm': ^3.10.2 '@tiptap/extension-bullet-list@3.0.9': resolution: {integrity: sha512-Aob5TVfrtoEzfTm3wl7lognmWia6EEilOxLihSGISCvI4FTndJg+mwhumduQeYCLWkF9i/DR87m2/3EbjR3R4Q==} peerDependencies: '@tiptap/extension-list': ^3.0.9 + '@tiptap/extension-bullet-list@3.10.2': + resolution: {integrity: sha512-WVUklxiqWHpJnkGGNL3mygDKRDUuhh5HhmKUrBrNlvb+yQgglau+S94F4bobvtiwYBSHWS4HdGTXTQhdX9QfwQ==} + peerDependencies: + '@tiptap/extension-list': ^3.10.2 + '@tiptap/extension-code-block@3.0.9': resolution: {integrity: sha512-H692k9sHIE3rR3S+BIknQXsLb8HSojk+7gQ5DV0hYajSzpJ02OUL4AnNlpMuSgZuaq+ljpN4sT8kCIzIE1kQxw==} peerDependencies: '@tiptap/core': ^3.0.9 '@tiptap/pm': ^3.0.9 + '@tiptap/extension-code-block@3.10.2': + resolution: {integrity: sha512-1EmR8NYBEvIHOQml98XqzGj7pnosm4w/pSwZMPskhDn/3S737lo22vxoTOMmTL+HVdhDuwY66RBF8rELLVioHA==} + peerDependencies: + '@tiptap/core': ^3.10.2 + '@tiptap/pm': ^3.10.2 + '@tiptap/extension-code@3.0.9': resolution: {integrity: sha512-jMo7crwLIefwy13WI2FzxlyJN9AbLNsESFbJuv/KPzjpN7uzPKYsE33Uy2IZD5hPoHtA5UmAUfbz0HzWtWy5Yw==} peerDependencies: '@tiptap/core': ^3.0.9 + '@tiptap/extension-code@3.10.2': + resolution: {integrity: sha512-+oA2fuQPQDzZb3q0pQeObPrhWXPh9JxybnAAGFoGenZsMsoUdN8x/KdtrXGWDMoB9XIg7XwE1xO6EZAH+eLe8Q==} + peerDependencies: + '@tiptap/core': ^3.10.2 + '@tiptap/extension-document@3.0.9': resolution: {integrity: sha512-DB/R5e6QvuGhY8EhCkfNjR2xQfz/TOWoxfQGhDuy5U+oK3WBwCcHq9t5+nbSCMHtKfi/i49aHKDvv7TQCpuP0w==} peerDependencies: '@tiptap/core': ^3.0.9 + '@tiptap/extension-document@3.10.2': + resolution: {integrity: sha512-+H+H/8OMgTK59QSQeWRqiBB2nufh4rglVCP/RW+iZ8GTH5P5w3dObXVp2OBLdtUG2BRKIVmGcuCxLBI2jer+Tg==} + peerDependencies: + '@tiptap/core': ^3.10.2 + '@tiptap/extension-dropcursor@3.0.9': resolution: {integrity: sha512-+P+1nfeCtPLj3OHNiATOL3UyM2omZ8+ac6MKm+FxunRAZZsHzbEFUYYdLF7prEmaf0z0c1k4LKSWpbrIX92pKA==} peerDependencies: '@tiptap/extensions': ^3.0.9 - '@tiptap/extension-file-handler@3.0.9': - resolution: {integrity: sha512-hm7KeLT/HC4q/tSYmZABnSn4PN9RKL33wMevueEnSwXWIuDmrM1ACVg7Zp52ncNcLSn4f9fDxjzKz0IG2+Egag==} + '@tiptap/extension-dropcursor@3.10.2': + resolution: {integrity: sha512-fwb4beHPRdUhnLjdwNfcLa90NAYMzWfE4zwR6hdCHWbamAuAgb0g2O1bU89PcCVeYcFeKPC+TquOG8q8cxeE7A==} peerDependencies: - '@tiptap/core': ^3.0.9 - '@tiptap/extension-text-style': ^3.0.9 - '@tiptap/pm': ^3.0.9 + '@tiptap/extensions': ^3.10.2 + + '@tiptap/extension-file-handler@3.10.2': + resolution: {integrity: sha512-SpbqdKyOcJKk5qZnSkPBSSNg/8VIewUFfnYh0Md6tg0TNWaXTZF8qxfoFAhoYFP2JVdoUHlRZi8CoEnuKQWYhw==} + peerDependencies: + '@tiptap/core': ^3.10.2 + '@tiptap/extension-text-style': ^3.10.2 + '@tiptap/pm': ^3.10.2 - '@tiptap/extension-floating-menu@3.0.9': - resolution: {integrity: sha512-WYQ3mW6G0zxoni6TegpQ46a1Qe1zj8Ev5sBH79H4Mbf0qsc7MOq07jLjipv9M0EJJPUi0cfkQlwfV41nH1ue/g==} + '@tiptap/extension-floating-menu@3.10.2': + resolution: {integrity: sha512-B14/MFffhyowF4/OIive8Z/pL0LWxZxehVBMm4eGG09O01s9/oTc2pDkhMUxbR/1ip81Se1/i+KlTbxogcuduA==} peerDependencies: '@floating-ui/dom': ^1.0.0 - '@tiptap/core': ^3.0.9 - '@tiptap/pm': ^3.0.9 + '@tiptap/core': ^3.10.2 + '@tiptap/pm': ^3.10.2 '@tiptap/extension-gapcursor@3.0.9': resolution: {integrity: sha512-+jy7Z/V6nOtvWin+zJYYoRwEYDOHDlF34Ey1T7A8aRcJlPeAQhoB1Ek7R3Rd3nsuByz70IfQapDvkbhY1nkNvQ==} peerDependencies: '@tiptap/extensions': ^3.0.9 + '@tiptap/extension-gapcursor@3.10.2': + resolution: {integrity: sha512-sBCu8enXm3W3BjnvvGBrzAiSuQSVZyhbQAgaFKjHJKBQRbek55EEbRA0ETUmHcSQbYf0D8hmDt2++HAyEASEsQ==} + peerDependencies: + '@tiptap/extensions': ^3.10.2 + '@tiptap/extension-hard-break@3.0.9': resolution: {integrity: sha512-PWNYsUwVsMWt/R5/OWjfGb+7DQT0DvH+1owBimRq0pWZepg8qkz1jdPGgsRmUFyERRsXeEpgj3VaQfrgbyUfrA==} peerDependencies: '@tiptap/core': ^3.0.9 + '@tiptap/extension-hard-break@3.10.2': + resolution: {integrity: sha512-gQdfzTcDb43JNxqpj83v/XAzIRlgsX2oSf5WPPtSoHj9xpgSbFv87W2PnVxUbzlTYH6Cb44iED+jwI1Sexn6LA==} + peerDependencies: + '@tiptap/core': ^3.10.2 + '@tiptap/extension-heading@3.0.9': resolution: {integrity: sha512-LRLCIt87fvDZ5CdkinzhkCwRz5ax6FlsjJzG32MJ3wXyvVslqeLXBvH28JFUZEyzgcd/SnYmYxnef5+yvAX61g==} peerDependencies: '@tiptap/core': ^3.0.9 + '@tiptap/extension-heading@3.10.2': + resolution: {integrity: sha512-f4NaJHYejn88IN8Q7yeGT2sdS+jb5fLUhj5zKiqC4fWqVeXa4Sh4TpA8Be13Un8KBRY4KSrVLBjcuF121hEYCw==} + peerDependencies: + '@tiptap/core': ^3.10.2 + '@tiptap/extension-horizontal-rule@3.0.9': resolution: {integrity: sha512-jPNCOte0y9R3Y4PiEA/CRGgRk8WoL700Mnn8NPVHa4juUjvMl1qxL8hdnW/k8cxhrBA8tV0qcq82+/Vqq6jSfA==} peerDependencies: '@tiptap/core': ^3.0.9 '@tiptap/pm': ^3.0.9 + '@tiptap/extension-horizontal-rule@3.10.2': + resolution: {integrity: sha512-EkVomzUGfhTp6LF/6jKXKAHiR3bDnZRBVbegocGn5mAZB+5nItxafa7s37zzcPdPI+prnw/C9DRGsZf6pVb4dQ==} + peerDependencies: + '@tiptap/core': ^3.10.2 + '@tiptap/pm': ^3.10.2 + '@tiptap/extension-image@3.0.9': resolution: {integrity: sha512-/2igN/oIF58zqX5fcg00bf6qGLcQyXHysl5I8GiurkvO95d+SQTlYbJneSRUpt6CgrUKbhRnMBPVubmapgg+Zw==} peerDependencies: '@tiptap/core': ^3.0.9 + '@tiptap/extension-image@3.10.2': + resolution: {integrity: sha512-+EeEOwUCQ4K7wFw0xkVPCwrzRMj5lEW7VdtRj+0zVtAMI+HxO4B6/+ZXyuDybBjtGBgZKdg5DP3pOz0XUCA+vw==} + peerDependencies: + '@tiptap/core': ^3.10.2 + '@tiptap/extension-italic@3.0.9': resolution: {integrity: sha512-Gt4FbMtZerzKpit8+FvIjIQ3CBD559/FFC+kOT9y8JHlINeqWyh/bgHuaA/9/XtHphOQiA7NDwOiuPh4KIKpqA==} peerDependencies: '@tiptap/core': ^3.0.9 + '@tiptap/extension-italic@3.10.2': + resolution: {integrity: sha512-MnRbTSNtjLE56E7k0CFprIIfr2yaT0Yd0dwYH7pvWePmSYeVFQDwu9CcVOzF58iv5BasyXc3sO2yhWlXRTY7Ig==} + peerDependencies: + '@tiptap/core': ^3.10.2 + + '@tiptap/extension-link@3.10.2': + resolution: {integrity: sha512-c7ZvinwECBEn3IVI9XpUJKEwvrLtZDiEaYNAjBQgShF1EUCf7JVcNK9wcrFm/oDw9es1cq0yrKqsbBh/bvGO2Q==} + peerDependencies: + '@tiptap/core': ^3.10.2 + '@tiptap/pm': ^3.10.2 + '@tiptap/extension-link@3.6.6': resolution: {integrity: sha512-Uq41J6WpbZkyZinbikVxLNqu2WfwUJcErTmNkPdel1gvYoQajkXZkHz2NzQ2jS9DicHHPV1cJel5f/YvX7nm5w==} peerDependencies: @@ -5729,17 +5810,33 @@ packages: peerDependencies: '@tiptap/extension-list': ^3.0.9 + '@tiptap/extension-list-item@3.10.2': + resolution: {integrity: sha512-lG3qyk49BEYWiwoqc/7Cy0A+T13rgld3e//X3YYb7AFygn9oDKK13QlzoGdurgk7JGF0e5bYUHwh/D7eK9xg3g==} + peerDependencies: + '@tiptap/extension-list': ^3.10.2 + '@tiptap/extension-list-keymap@3.0.9': resolution: {integrity: sha512-naz4+EFzLN695f53GATiglPOc5SOLBm1DNhhUHZNlrUVfDtKmrdbo8t9a/NhAE6Ne/pfg5tbuS+OKuvbJaJcAg==} peerDependencies: '@tiptap/extension-list': ^3.0.9 + '@tiptap/extension-list-keymap@3.10.2': + resolution: {integrity: sha512-tD9OdW1YhvIjFEyarDfoFd1gm0gRMo2FEI3B50VLg45LTb9IzDQwBMDVeqU2hft+Ve4VVZFUEJN+ovHjG6UueA==} + peerDependencies: + '@tiptap/extension-list': ^3.10.2 + '@tiptap/extension-list@3.0.9': resolution: {integrity: sha512-y5JQoFmVR+6FhDdEz2oFIMkURSRSDhCtsrlNWdUpSTGnTAa2WZT7nEhHcIMSGvYU3t0fkfLQ9yTMSaQZFa5GLA==} peerDependencies: '@tiptap/core': ^3.0.9 '@tiptap/pm': ^3.0.9 + '@tiptap/extension-list@3.10.2': + resolution: {integrity: sha512-4IGOQRcy/REuaskha5z29Vb5Hn3l5jTgfT7+aUO5cwAGZFOlEzSgOGBCq2sH4gVSfBqzdG5mGSH4+LEdwfpW8g==} + peerDependencies: + '@tiptap/core': ^3.10.2 + '@tiptap/pm': ^3.10.2 + '@tiptap/extension-mention@3.0.9': resolution: {integrity: sha512-DTQNAQkHZ+7Enlt3KvjqN6eECINlqPpET4Drzwj8Mmz9kMILc87cz3G2cwEKRrS9A1Xn3H3VpWvElWE2Wq9JHw==} peerDependencies: @@ -5747,21 +5844,43 @@ packages: '@tiptap/pm': ^3.0.9 '@tiptap/suggestion': ^3.0.9 + '@tiptap/extension-mention@3.10.2': + resolution: {integrity: sha512-/gyUIMNKBoXOIy0SvjNYJ7G/yiYsnwwbnBo2hQgDza4p53KgnpTzg623/6GHDZSk7zy2S3O+5yWlzEmtrUva3A==} + peerDependencies: + '@tiptap/core': ^3.10.2 + '@tiptap/pm': ^3.10.2 + '@tiptap/suggestion': ^3.10.2 + '@tiptap/extension-ordered-list@3.0.9': resolution: {integrity: sha512-ACubdGc/y/rKPEgHTO7hDSg547wRRA+Es7c/rQgjrkpI///LBJQfixyUvNg2UNNPttNsavF/CUwhshCeo9MeBA==} peerDependencies: '@tiptap/extension-list': ^3.0.9 + '@tiptap/extension-ordered-list@3.10.2': + resolution: {integrity: sha512-zs8wK1GNVedGENZPJOYUMtiLLPPASvJtabS2HTLPQGnpVeXfF0toftdVYDhGRGoQBBDLDjNyyW5ARzJwwXbTzQ==} + peerDependencies: + '@tiptap/extension-list': ^3.10.2 + '@tiptap/extension-paragraph@3.0.9': resolution: {integrity: sha512-K5zGg4zLxxqAG0BgtRpLvKclYSGoSSuU1Fza0M5MwUgrFA0S2q4JnLB1czQ77S4pfb3hpScIe50fwJzZmIUEQw==} peerDependencies: '@tiptap/core': ^3.0.9 + '@tiptap/extension-paragraph@3.10.2': + resolution: {integrity: sha512-k84BMUxpeFTEIoUil4tnXF5viY4oUHXq4wz4JkO/LMEW6lAkO/PhJnJMMrcEJu0sox4aoNppcnS236RNXCiPpg==} + peerDependencies: + '@tiptap/core': ^3.10.2 + '@tiptap/extension-strike@3.0.9': resolution: {integrity: sha512-2TBQ9P/FGe+/34ckfwP+eCdb4vbxDVZ5qD0piDIR9Ws5QI5IdtW90pNO4roxiPeRdVFrhTbFPEIuL0tg4NQRmg==} peerDependencies: '@tiptap/core': ^3.0.9 + '@tiptap/extension-strike@3.10.2': + resolution: {integrity: sha512-e6+WaEhWlsbV3mw8kSMwgq7Tty8BWoRGFGQj5B6Tg7bZUg3qgdE0Kp2s6MGNNikpuDchOebbIZxOk/qfVqgUbw==} + peerDependencies: + '@tiptap/core': ^3.10.2 + '@tiptap/extension-text-style@3.0.9': resolution: {integrity: sha512-x7SZLS537c7w789n8re0IktmkBZqz98dux/hwpFAcC4oL06YPjFG7Dy9mAiKcsKqKWI0eAyTQvMybz+TJusBbw==} peerDependencies: @@ -5772,17 +5891,33 @@ packages: peerDependencies: '@tiptap/core': ^3.0.9 + '@tiptap/extension-text@3.10.2': + resolution: {integrity: sha512-5gHtEh7eIjFYtwIYvjJp1Sg7qlS1ObOLIkYGOm763t0JJbePXnkA5EnyfxAq3g+wfPajK7qgs3uqArCjlHA33w==} + peerDependencies: + '@tiptap/core': ^3.10.2 + '@tiptap/extension-underline@3.0.9': resolution: {integrity: sha512-xLR5NbnxlEJmvfb4Aj8wCbTmh/ycnPsSDeP8+TAsdAYxypSA6BP6G0t4d4NWreqAq+tq6QV6Eh0+YDN0G1VZxw==} peerDependencies: '@tiptap/core': ^3.0.9 + '@tiptap/extension-underline@3.10.2': + resolution: {integrity: sha512-/n/+YXYYGmOOQl8zPZiyZFRtOmsnTe1TfEjNcsJcIUGW4X5teddp4lVTcvGO3aaufH48FcYnSVJya7A9dw3ABg==} + peerDependencies: + '@tiptap/core': ^3.10.2 + '@tiptap/extensions@3.0.9': resolution: {integrity: sha512-IyTcPnZXUf0nxDkC+CCWh10vzn81Kq50euV/ivk8IyPr15hxPiT3Zk1LmCI10Pqf4Bwgz38XUIWtToDfIeEgpg==} peerDependencies: '@tiptap/core': ^3.0.9 '@tiptap/pm': ^3.0.9 + '@tiptap/extensions@3.10.2': + resolution: {integrity: sha512-XyvMn6B6PCPsgV6VMLiS1QXI1OKarBAYwXmqsE+gCzzYyXxYX4sLUlQ8JKysREyIGMHxSg5vgOajsgXgFMrvyA==} + peerDependencies: + '@tiptap/core': ^3.10.2 + '@tiptap/pm': ^3.10.2 + '@tiptap/html@3.6.5': resolution: {integrity: sha512-w37vPb5o/sKFbmnSGS2YE8yfWh2CAtmXnVFVg/tO1UYIVifVsfVVjOkfcbAQNZcHve+7NSwcIeI6oDh7FeYyIw==} peerDependencies: @@ -5790,20 +5925,34 @@ packages: '@tiptap/pm': ^3.6.5 happy-dom: ^18.0.1 + '@tiptap/markdown@3.10.2': + resolution: {integrity: sha512-PsAdNAvd3z3VSMX8efkcr3qhCb2gAa0ohUn9/uzuZ+/CZ6YRkGfT74F5mRk5ttUMtA+5WSaqQYy59iORHuXaXw==} + peerDependencies: + '@tiptap/core': ^3.10.2 + '@tiptap/pm': ^3.10.2 + '@tiptap/pm@3.0.9': resolution: {integrity: sha512-cJdnpGyirRxwi6M4IkyapEK/jhcjFXdfX3uhJp/4uVH1dynNXalV0gE/YnH/yt55kzwvG9OUrwOQt+t1iXgNog==} - '@tiptap/react@3.0.9': - resolution: {integrity: sha512-BbvWPSgYGvd9m8fPXKI81gf9KP+1SMCPpscbtbbhPyxiW2ziY+jwo+i7MwVI73P89hWAJCy/43UnOde438HmOA==} + '@tiptap/pm@3.10.2': + resolution: {integrity: sha512-qXsp7guPLoir49Fh6IOzg6IAJA3tYYy/1316vv7DhJwmdF9GebkwgFcei2XGk6vKlwv18jWV+BlqDv9iwQ5Alg==} + + '@tiptap/react@3.10.2': + resolution: {integrity: sha512-3pvtpG0Wuy4iozYnCFrf3y0PPxOZ1oe/T2DNNTLelui4CiphS3sQoBtuVrzx+2QePGkFM5uU5Bj+ET3NmUbwWA==} peerDependencies: - '@tiptap/core': ^3.0.9 - '@tiptap/pm': ^3.0.9 + '@tiptap/core': ^3.10.2 + '@tiptap/pm': ^3.10.2 + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + '@types/react-dom': ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 '@tiptap/starter-kit@3.0.9': resolution: {integrity: sha512-CYg6tV5fYOvkP1gyATkJJj+nFYmwjDKLipQc/r0D/tHKypxefENrm4G7mf4B78zsB/izfk5mW3iujvyeod6EcQ==} + '@tiptap/starter-kit@3.10.2': + resolution: {integrity: sha512-8eCl+kBkOiXH+k3AVU1F1l3GK7+/Y3hdu/FSfpgTm+jJ14e5VNUQaDPvqKDmCo1dlTzF1OCJPi91hhUeqcJLvw==} + '@tiptap/static-renderer@3.6.6': resolution: {integrity: sha512-m0A18LFuGnWxUdg5miDclouwvA7KyUtiSaGds6EWKGFSSErJZEcaRq1ZdSvuFJtT/rVXc1MhG0Wu2g6mGX6eTw==} peerDependencies: @@ -10074,6 +10223,11 @@ packages: markdown-table@3.0.3: resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} + marked@16.4.1: + resolution: {integrity: sha512-ntROs7RaN3EvWfy3EZi14H4YxmT6A5YvywfhO+0pm+cH/dnSQRmdAmoFIc3B9aiwTehyk7pESH4ofyBY+V5hZg==} + engines: {node: '>= 20'} + hasBin: true + marked@7.0.4: resolution: {integrity: sha512-t8eP0dXRJMtMvBojtkcsA7n48BkauktUKzfkPSCq85ZMTJ0v76Rke4DYz01omYpPTUh4p/f7HePgRo3ebG8+QQ==} engines: {node: '>= 16'} @@ -19753,80 +19907,144 @@ snapshots: dependencies: '@tiptap/pm': 3.0.9 + '@tiptap/core@3.10.2(@tiptap/pm@3.10.2)': + dependencies: + '@tiptap/pm': 3.10.2 + '@tiptap/extension-blockquote@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))': dependencies: '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) + '@tiptap/extension-blockquote@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/extension-bold@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))': dependencies: '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) - '@tiptap/extension-bubble-menu@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9)': + '@tiptap/extension-bold@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + + '@tiptap/extension-bubble-menu@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2)': dependencies: '@floating-ui/dom': 1.6.12 - '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) - '@tiptap/pm': 3.0.9 + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/pm': 3.10.2 optional: true '@tiptap/extension-bullet-list@3.0.9(@tiptap/extension-list@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9))': dependencies: '@tiptap/extension-list': 3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9) + '@tiptap/extension-bullet-list@3.10.2(@tiptap/extension-list@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2))': + dependencies: + '@tiptap/extension-list': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2) + '@tiptap/extension-code-block@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9)': dependencies: '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) '@tiptap/pm': 3.0.9 + '@tiptap/extension-code-block@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2)': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/pm': 3.10.2 + '@tiptap/extension-code@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))': dependencies: '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) + '@tiptap/extension-code@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/extension-document@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))': dependencies: '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) + '@tiptap/extension-document@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/extension-dropcursor@3.0.9(@tiptap/extensions@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9))': dependencies: '@tiptap/extensions': 3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9) - '@tiptap/extension-file-handler@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/extension-text-style@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9)))(@tiptap/pm@3.0.9)': + '@tiptap/extension-dropcursor@3.10.2(@tiptap/extensions@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2))': dependencies: - '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) - '@tiptap/extension-text-style': 3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9)) - '@tiptap/pm': 3.0.9 + '@tiptap/extensions': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2) - '@tiptap/extension-floating-menu@3.0.9(@floating-ui/dom@1.6.12)(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9)': + '@tiptap/extension-file-handler@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/extension-text-style@3.0.9(@tiptap/core@3.10.2(@tiptap/pm@3.10.2)))(@tiptap/pm@3.10.2)': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/extension-text-style': 3.0.9(@tiptap/core@3.10.2(@tiptap/pm@3.10.2)) + '@tiptap/pm': 3.10.2 + + '@tiptap/extension-floating-menu@3.10.2(@floating-ui/dom@1.6.12)(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2)': dependencies: '@floating-ui/dom': 1.6.12 - '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) - '@tiptap/pm': 3.0.9 + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/pm': 3.10.2 optional: true '@tiptap/extension-gapcursor@3.0.9(@tiptap/extensions@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9))': dependencies: '@tiptap/extensions': 3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9) + '@tiptap/extension-gapcursor@3.10.2(@tiptap/extensions@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2))': + dependencies: + '@tiptap/extensions': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2) + '@tiptap/extension-hard-break@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))': dependencies: '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) + '@tiptap/extension-hard-break@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/extension-heading@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))': dependencies: '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) + '@tiptap/extension-heading@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/extension-horizontal-rule@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9)': dependencies: '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) '@tiptap/pm': 3.0.9 + '@tiptap/extension-horizontal-rule@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2)': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/pm': 3.10.2 + '@tiptap/extension-image@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))': dependencies: '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) + '@tiptap/extension-image@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/extension-italic@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))': dependencies: '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) + '@tiptap/extension-italic@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + + '@tiptap/extension-link@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2)': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/pm': 3.10.2 + linkifyjs: 4.3.2 + '@tiptap/extension-link@3.6.6(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9)': dependencies: '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) @@ -19837,56 +20055,106 @@ snapshots: dependencies: '@tiptap/extension-list': 3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9) + '@tiptap/extension-list-item@3.10.2(@tiptap/extension-list@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2))': + dependencies: + '@tiptap/extension-list': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2) + '@tiptap/extension-list-keymap@3.0.9(@tiptap/extension-list@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9))': dependencies: '@tiptap/extension-list': 3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9) + '@tiptap/extension-list-keymap@3.10.2(@tiptap/extension-list@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2))': + dependencies: + '@tiptap/extension-list': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2) + '@tiptap/extension-list@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9)': dependencies: '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) '@tiptap/pm': 3.0.9 + '@tiptap/extension-list@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2)': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/pm': 3.10.2 + '@tiptap/extension-mention@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9)(@tiptap/suggestion@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9))': dependencies: '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) '@tiptap/pm': 3.0.9 '@tiptap/suggestion': 3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9) + '@tiptap/extension-mention@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2)(@tiptap/suggestion@3.0.9(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2))': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/pm': 3.10.2 + '@tiptap/suggestion': 3.0.9(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2) + '@tiptap/extension-ordered-list@3.0.9(@tiptap/extension-list@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9))': dependencies: '@tiptap/extension-list': 3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9) + '@tiptap/extension-ordered-list@3.10.2(@tiptap/extension-list@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2))': + dependencies: + '@tiptap/extension-list': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2) + '@tiptap/extension-paragraph@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))': dependencies: '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) + '@tiptap/extension-paragraph@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/extension-strike@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))': dependencies: '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) - '@tiptap/extension-text-style@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))': + '@tiptap/extension-strike@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))': dependencies: - '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + + '@tiptap/extension-text-style@3.0.9(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) '@tiptap/extension-text@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))': dependencies: '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) + '@tiptap/extension-text@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/extension-underline@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))': dependencies: '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) + '@tiptap/extension-underline@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/extensions@3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9)': dependencies: '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) '@tiptap/pm': 3.0.9 + '@tiptap/extensions@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2)': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/pm': 3.10.2 + '@tiptap/html@3.6.5(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9)(happy-dom@18.0.1)': dependencies: '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) '@tiptap/pm': 3.0.9 happy-dom: 18.0.1 + '@tiptap/markdown@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2)': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/pm': 3.10.2 + marked: 16.4.1 + '@tiptap/pm@3.0.9': dependencies: prosemirror-changeset: 2.3.1 @@ -19908,18 +20176,41 @@ snapshots: prosemirror-transform: 1.10.4 prosemirror-view: 1.40.1 - '@tiptap/react@3.0.9(@floating-ui/dom@1.6.12)(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@tiptap/pm@3.10.2': dependencies: - '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) - '@tiptap/pm': 3.0.9 + prosemirror-changeset: 2.3.1 + prosemirror-collab: 1.3.1 + prosemirror-commands: 1.7.1 + prosemirror-dropcursor: 1.8.2 + prosemirror-gapcursor: 1.3.2 + prosemirror-history: 1.4.1 + prosemirror-inputrules: 1.5.0 + prosemirror-keymap: 1.2.3 + prosemirror-markdown: 1.13.2 + prosemirror-menu: 1.2.5 + prosemirror-model: 1.25.2 + prosemirror-schema-basic: 1.2.4 + prosemirror-schema-list: 1.5.1 + prosemirror-state: 1.4.3 + prosemirror-tables: 1.7.1 + prosemirror-trailing-node: 3.0.0(prosemirror-model@1.25.2)(prosemirror-state@1.4.3)(prosemirror-view@1.40.1) + prosemirror-transform: 1.10.4 + prosemirror-view: 1.40.1 + + '@tiptap/react@3.10.2(@floating-ui/dom@1.6.12)(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2)(@types/react-dom@19.1.9(@types/react@19.1.14))(@types/react@19.1.14)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/pm': 3.10.2 + '@types/react': 19.1.14 + '@types/react-dom': 19.1.9(@types/react@19.1.14) '@types/use-sync-external-store': 0.0.6 fast-deep-equal: 3.1.3 react: 19.1.1 react-dom: 19.1.1(react@19.1.1) use-sync-external-store: 1.5.0(react@19.1.1) optionalDependencies: - '@tiptap/extension-bubble-menu': 3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9) - '@tiptap/extension-floating-menu': 3.0.9(@floating-ui/dom@1.6.12)(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9) + '@tiptap/extension-bubble-menu': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2) + '@tiptap/extension-floating-menu': 3.10.2(@floating-ui/dom@1.6.12)(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2) transitivePeerDependencies: - '@floating-ui/dom' @@ -19950,6 +20241,33 @@ snapshots: '@tiptap/extensions': 3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9) '@tiptap/pm': 3.0.9 + '@tiptap/starter-kit@3.10.2': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/extension-blockquote': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2)) + '@tiptap/extension-bold': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2)) + '@tiptap/extension-bullet-list': 3.10.2(@tiptap/extension-list@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2)) + '@tiptap/extension-code': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2)) + '@tiptap/extension-code-block': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2) + '@tiptap/extension-document': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2)) + '@tiptap/extension-dropcursor': 3.10.2(@tiptap/extensions@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2)) + '@tiptap/extension-gapcursor': 3.10.2(@tiptap/extensions@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2)) + '@tiptap/extension-hard-break': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2)) + '@tiptap/extension-heading': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2)) + '@tiptap/extension-horizontal-rule': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2) + '@tiptap/extension-italic': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2)) + '@tiptap/extension-link': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2) + '@tiptap/extension-list': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2) + '@tiptap/extension-list-item': 3.10.2(@tiptap/extension-list@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2)) + '@tiptap/extension-list-keymap': 3.10.2(@tiptap/extension-list@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2)) + '@tiptap/extension-ordered-list': 3.10.2(@tiptap/extension-list@3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2)) + '@tiptap/extension-paragraph': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2)) + '@tiptap/extension-strike': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2)) + '@tiptap/extension-text': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2)) + '@tiptap/extension-underline': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2)) + '@tiptap/extensions': 3.10.2(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2) + '@tiptap/pm': 3.10.2 + '@tiptap/static-renderer@3.6.6(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) @@ -19962,6 +20280,11 @@ snapshots: '@tiptap/core': 3.0.9(@tiptap/pm@3.0.9) '@tiptap/pm': 3.0.9 + '@tiptap/suggestion@3.0.9(@tiptap/core@3.10.2(@tiptap/pm@3.10.2))(@tiptap/pm@3.10.2)': + dependencies: + '@tiptap/core': 3.10.2(@tiptap/pm@3.10.2) + '@tiptap/pm': 3.10.2 + '@tokenizer/inflate@0.2.7': dependencies: debug: 4.4.0 @@ -25281,6 +25604,8 @@ snapshots: markdown-table@3.0.3: {} + marked@16.4.1: {} + marked@7.0.4: {} math-expression-evaluator@1.4.0: {} From bcbddc3f80f8c451e23e0e975901672d0895344e Mon Sep 17 00:00:00 2001 From: Tim Wilson Date: Thu, 6 Nov 2025 16:45:23 -0500 Subject: [PATCH 4/6] Render message markdown --- apps/web/ui/messages/messages-panel.tsx | 37 +++++++++++++++++++------ apps/web/ui/shared/message-input.tsx | 7 +---- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/apps/web/ui/messages/messages-panel.tsx b/apps/web/ui/messages/messages-panel.tsx index 8d13b3c5c44..a996db9495c 100644 --- a/apps/web/ui/messages/messages-panel.tsx +++ b/apps/web/ui/messages/messages-panel.tsx @@ -8,9 +8,10 @@ import { useMediaQuery, } from "@dub/ui"; import { OG_AVATAR_URL, cn, formatDate } from "@dub/utils"; -import Linkify from "linkify-react"; import { ChevronRight } from "lucide-react"; import { Fragment, useMemo, useRef, useState } from "react"; +import ReactMarkdown from "react-markdown"; +import remarkGfm from "remark-gfm"; import { MessageInput } from "../shared/message-input"; import { MessageMarkdown } from "./message-markdown"; @@ -176,22 +177,40 @@ export function MessagesPanel({ {/* Message box */}
diff --git a/apps/web/ui/shared/message-input.tsx b/apps/web/ui/shared/message-input.tsx index 3281ff83b2f..ba1053a1d64 100644 --- a/apps/web/ui/shared/message-input.tsx +++ b/apps/web/ui/shared/message-input.tsx @@ -10,7 +10,7 @@ import { useRichTextContext, } from "@dub/ui"; import { cn } from "@dub/utils"; -import { useEffect, useRef, useState } from "react"; +import { useRef, useState } from "react"; import { EmojiPicker } from "../shared/emoji-picker"; export function MessageInput({ @@ -21,7 +21,6 @@ export function MessageInput({ placeholder = "Type a message...", sendButtonText = "Send", className, - onMount, }: { onSendMessage: (message: string) => void | false; defaultValue?: string; @@ -30,10 +29,8 @@ export function MessageInput({ placeholder?: string; sendButtonText?: string; className?: string; - onMount?: (props: { textarea: HTMLTextAreaElement | null }) => void; }) { const richTextRef = useRef<{ setContent: (content: any) => void }>(null); - const textAreaRef = useRef(null); const [typedMessage, setTypedMessage] = useState(defaultValue); const sendMessage = () => { @@ -46,8 +43,6 @@ export function MessageInput({ } }; - useEffect(() => onMount?.({ textarea: textAreaRef.current }), [onMount]); - return (
Date: Fri, 7 Nov 2025 16:51:31 -0500 Subject: [PATCH 5/6] More MD handling --- .../bounties/add-edit-bounty-sheet.tsx | 51 ++++++++++++------- .../partners/bounties/claim-bounty-modal.tsx | 10 ++-- .../src/templates/new-bounty-available.tsx | 14 ++--- .../templates/new-message-from-partner.tsx | 18 +++++-- .../templates/new-message-from-program.tsx | 18 +++++-- .../src/rich-text-area/rich-text-provider.tsx | 1 + .../src/rich-text-area/rich-text-toolbar.tsx | 3 ++ 7 files changed, 79 insertions(+), 36 deletions(-) diff --git a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/add-edit-bounty-sheet.tsx b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/add-edit-bounty-sheet.tsx index 2ddae65358e..896d23e5367 100644 --- a/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/add-edit-bounty-sheet.tsx +++ b/apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/add-edit-bounty-sheet.tsx @@ -24,6 +24,9 @@ import { CardSelector, CardSelectorOption, NumberStepper, + RichTextArea, + RichTextProvider, + RichTextToolbar, Sheet, SmartDateTimePicker, Switch, @@ -803,31 +806,45 @@ function BountySheetContent({ setIsOpen, bounty }: BountySheetProps) { )}
-