From ee5c620c4943448d066e4e4fa8124e886eb5aeda Mon Sep 17 00:00:00 2001 From: cade Date: Tue, 20 Aug 2024 12:06:25 -0600 Subject: [PATCH] add link customization to rich textarea --- app/_components/rich-textarea.tsx | 125 ++++++++++++++++++++++++++++-- 1 file changed, 119 insertions(+), 6 deletions(-) diff --git a/app/_components/rich-textarea.tsx b/app/_components/rich-textarea.tsx index 08f3750f..eaf56e64 100644 --- a/app/_components/rich-textarea.tsx +++ b/app/_components/rich-textarea.tsx @@ -1,10 +1,14 @@ 'use client'; +import Button from '@/_components/button'; import DirtyHtml from '@/_components/dirty-html'; import IconButton from '@/_components/icon-button'; +import Input from '@/_components/input'; +import * as Modal from '@/_components/modal'; import Tip from '@/_components/tip'; import BoldIcon from '@heroicons/react/24/outline/BoldIcon'; import ItalicIcon from '@heroicons/react/24/outline/ItalicIcon'; +import LinkIcon from '@heroicons/react/24/outline/LinkIcon'; import ListBulletIcon from '@heroicons/react/24/outline/ListBulletIcon'; import NumberedListIcon from '@heroicons/react/24/outline/NumberedListIcon'; import UnderlineIcon from '@heroicons/react/24/outline/UnderlineIcon'; @@ -83,7 +87,10 @@ const RichTextarea = ( Document, History, Italic, - Link.configure({ HTMLAttributes: { target: '_blank' } }), + Link.configure({ + HTMLAttributes: { target: '_blank' }, + defaultProtocol: 'https', + }).extend({ inclusive: false }), ListItem, OrderedList, Paragraph, @@ -120,6 +127,11 @@ const RichTextarea = ( }, }); + const [setLinkModal, setSetLinkModal] = React.useState<{ + href: string; + text: string; + } | null>(null); + React.useEffect(() => { if (!editor || value === editorRef.current?.getHTML()) return; editor.commands.setContent(value ?? ''); @@ -162,7 +174,7 @@ const RichTextarea = ( > } @@ -171,7 +183,7 @@ const RichTextarea = ( /> } @@ -180,7 +192,7 @@ const RichTextarea = ( /> } @@ -189,7 +201,7 @@ const RichTextarea = ( /> } @@ -198,13 +210,40 @@ const RichTextarea = ( /> } label="Ordered list" onClick={() => editor.chain().focus().toggleOrderedList().run()} /> + } + label="Set link" + onClick={() => + editor + .chain() + .focus() + .extendMarkRange('link') + .command(({ editor, state, tr }) => { + setSetLinkModal({ + href: editor.getAttributes('link').href, + text: + state.doc.textBetween( + tr.selection.$from.pos, + tr.selection.$to.pos, + ' ', + ) ?? '', + }); + + return true; + }) + } + /> @@ -225,6 +264,80 @@ const RichTextarea = ( {right} )} + {!!setLinkModal && !!editor && ( + setSetLinkModal(null)} open> + + + + Set link +
{ + e.preventDefault(); + e.stopPropagation(); + const data = new FormData(e.currentTarget); + const href = data.get('href') as string; + const text = data.get('text') as string; + + editor + .chain() + .focus() + .extendMarkRange('link') + .insertContent(`${text}`) + .run(); + + setSetLinkModal(null); + }} + > + + +
+ + +
+ e.preventDefault()}> + + +
+
+
+
+
+ )} ); };