feat: add YouTube video embed support for TipTap editor (#294)
* feat: add YouTube video embed support for TipTap editor - Paste YouTube URLs to auto-embed videos with metadata - Edit video title and URL through dropdown menu - Convert embed back to plain URL link - Fetch video titles automatically via YouTube oEmbed API * fix: - reverted NewCardForm CSS properties back to max-h-48. - Added boolean prop to TipTap Edtior for YouTube embed. - Disabled YouTube embed feature for NewCardForm Editor * chore: lint * chore: translations * chore: update translations --------- Co-authored-by: Henry <henry_ball@hotmail.co.uk>
This commit is contained in:
committed by
GitHub
parent
a5432c60b7
commit
89c8961176
@@ -1,3 +1,4 @@
|
||||
import type { Range as TiptapRange } from "@tiptap/core";
|
||||
import type { Editor as TiptapEditor } from "@tiptap/react";
|
||||
import type {
|
||||
SuggestionKeyDownProps,
|
||||
@@ -44,6 +45,7 @@ import { Markdown } from "tiptap-markdown";
|
||||
|
||||
import { getAvatarUrl } from "~/utils/helpers";
|
||||
import Avatar from "./Avatar";
|
||||
import { YouTubeNode } from "./YouTubeEmbed/YouTubeNode";
|
||||
|
||||
declare module "@tiptap/core" {
|
||||
interface Commands<ReturnType> {
|
||||
@@ -56,7 +58,7 @@ declare module "@tiptap/core" {
|
||||
export interface SlashCommandItem {
|
||||
title: string;
|
||||
icon?: React.ReactNode;
|
||||
command?: (props: { editor: TiptapEditor; range: Range }) => void;
|
||||
command?: (props: { editor: TiptapEditor; range: TiptapRange }) => void;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
@@ -431,12 +433,14 @@ export default function Editor({
|
||||
onBlur,
|
||||
readOnly = false,
|
||||
workspaceMembers,
|
||||
enableYouTubeEmbed = true,
|
||||
}: {
|
||||
content: string | null;
|
||||
onChange?: (value: string) => void;
|
||||
onBlur?: () => void;
|
||||
readOnly?: boolean;
|
||||
workspaceMembers: WorkspaceMember[];
|
||||
enableYouTubeEmbed?: boolean;
|
||||
}) {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
@@ -484,10 +488,17 @@ export default function Editor({
|
||||
}),
|
||||
);
|
||||
const q = query.toLowerCase();
|
||||
return all.filter((u) => u.label.toLowerCase().includes(q));
|
||||
return all.filter(
|
||||
(u) =>
|
||||
u.label &&
|
||||
typeof u.label === "string" &&
|
||||
u.label.toLowerCase().includes(q),
|
||||
);
|
||||
},
|
||||
command: ({ editor, range, props }: any) => {
|
||||
const mentionHTML = `<span data-type="mention" data-id="${props.id}" data-label="${props.label}">@${props.label}</span> `;
|
||||
command: ({ editor, range, props }) => {
|
||||
const id = props.id ?? "";
|
||||
const label = props.label ?? "";
|
||||
const mentionHTML = `<span data-type="mention" data-id="${id}" data-label="${label}">@${label}</span> `;
|
||||
|
||||
editor
|
||||
.chain()
|
||||
@@ -503,6 +514,7 @@ export default function Editor({
|
||||
return `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`;
|
||||
},
|
||||
}),
|
||||
...(enableYouTubeEmbed ? [YouTubeNode] : []),
|
||||
],
|
||||
content,
|
||||
onUpdate: ({ editor }) => onChange?.(editor.getHTML()),
|
||||
@@ -559,6 +571,9 @@ export default function Editor({
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
}
|
||||
.tiptap [data-youtube] {
|
||||
margin: 1rem 0;
|
||||
}
|
||||
`}</style>
|
||||
{!readOnly && editor && <EditorBubbleMenu editor={editor} />}
|
||||
<EditorContent
|
||||
|
||||
Reference in New Issue
Block a user