tiptap: show modal when create iframe

This commit is contained in:
fantasticit 2022-06-10 22:32:27 +08:00
parent 8cadda82c2
commit 82446482c7
3 changed files with 38 additions and 7 deletions

View File

@ -1,12 +1,21 @@
import { IUser } from '@think/domains';
import { mergeAttributes, Node } from '@tiptap/core'; import { mergeAttributes, Node } from '@tiptap/core';
import { ReactNodeViewRenderer } from '@tiptap/react'; import { ReactNodeViewRenderer } from '@tiptap/react';
import { IframeWrapper } from 'tiptap/core/wrappers/iframe'; import { IframeWrapper } from 'tiptap/core/wrappers/iframe';
import { getDatasetAttribute } from 'tiptap/prose-utils'; import { getDatasetAttribute } from 'tiptap/prose-utils';
export interface IIframeAttrs {
width?: number | string;
height?: number;
url?: string;
defaultShowPicker?: boolean;
createUser?: IUser['id'];
}
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands<ReturnType> { interface Commands<ReturnType> {
iframe: { iframe: {
setIframe: (attrs) => ReturnType; setIframe: (attrs: IIframeAttrs) => ReturnType;
}; };
} }
} }
@ -41,6 +50,12 @@ export const Iframe = Node.create({
default: null, default: null,
parseHTML: getDatasetAttribute('url'), parseHTML: getDatasetAttribute('url'),
}, },
defaultShowPicker: {
default: false,
},
createUser: {
default: null,
},
}; };
}, },
@ -66,7 +81,7 @@ export const Iframe = Node.create({
return commands.updateAttributes(this.name, options); return commands.updateAttributes(this.name, options);
} }
const { url } = options || { url: '' }; const attrs = options || { url: '' };
const { selection } = editor.state; const { selection } = editor.state;
const pos = selection.$head; const pos = selection.$head;
@ -74,7 +89,7 @@ export const Iframe = Node.create({
.insertContentAt(pos.before(), [ .insertContentAt(pos.before(), [
{ {
type: this.name, type: this.name,
attrs: { url }, attrs,
}, },
]) ])
.run(); .run();

View File

@ -106,7 +106,8 @@ export const COMMANDS: ICommand[] = [
{ {
icon: <IconLink />, icon: <IconLink />,
label: '外链', label: '外链',
action: (editor) => editor.chain().focus().setIframe({ url: '' }).run(), action: (editor, user) =>
editor.chain().focus().setIframe({ url: '', defaultShowPicker: true, createUser: user.id }).run(),
}, },
{ {
title: '卡片', title: '卡片',

View File

@ -4,10 +4,11 @@ import { FormApi } from '@douyinfe/semi-ui/lib/es/form';
import { Divider } from 'components/divider'; import { Divider } from 'components/divider';
import { SizeSetter } from 'components/size-setter'; import { SizeSetter } from 'components/size-setter';
import { Tooltip } from 'components/tooltip'; import { Tooltip } from 'components/tooltip';
import { useUser } from 'data/user';
import { useToggle } from 'hooks/use-toggle'; import { useToggle } from 'hooks/use-toggle';
import { useCallback, useRef } from 'react'; import { useCallback, useEffect, useRef } from 'react';
import { BubbleMenu } from 'tiptap/core/bubble-menu'; import { BubbleMenu } from 'tiptap/core/bubble-menu';
import { Iframe } from 'tiptap/core/extensions/iframe'; import { Iframe, IIframeAttrs } from 'tiptap/core/extensions/iframe';
import { useAttributes } from 'tiptap/core/hooks/use-attributes'; import { useAttributes } from 'tiptap/core/hooks/use-attributes';
import { copyNode, deleteNode } from 'tiptap/prose-utils'; import { copyNode, deleteNode } from 'tiptap/prose-utils';
@ -17,8 +18,15 @@ const EXAMPLE_LINK =
'https://proxy.tencentsuite.com/openapi/proxy/v2/addon?uid=144115212008575217&creator=144115212008575217&redirect=https%3A%2F%2Fi.y.qq.com%2Fn2%2Fm%2Foutchain%2Fplayer%2Findex.html%3Fsongid%3D5408217&docType=1&docID=300000000$RwqOunTcpXjs&addonID=0b69e1b9517e44a4aee35d33ee021b55&packageID=817&nonce=m3rqxn'; 'https://proxy.tencentsuite.com/openapi/proxy/v2/addon?uid=144115212008575217&creator=144115212008575217&redirect=https%3A%2F%2Fi.y.qq.com%2Fn2%2Fm%2Foutchain%2Fplayer%2Findex.html%3Fsongid%3D5408217&docType=1&docID=300000000$RwqOunTcpXjs&addonID=0b69e1b9517e44a4aee35d33ee021b55&packageID=817&nonce=m3rqxn';
export const IframeBubbleMenu = ({ editor }) => { export const IframeBubbleMenu = ({ editor }) => {
const { width, height, url } = useAttributes(editor, Iframe.name, { width: 0, height: 0, url: '' }); const { width, height, url, defaultShowPicker, createUser } = useAttributes<IIframeAttrs>(editor, Iframe.name, {
width: 0,
height: 0,
url: '',
defaultShowPicker: false,
createUser: null,
});
const $form = useRef<FormApi>(); const $form = useRef<FormApi>();
const { user } = useUser();
const [visible, toggleVisible] = useToggle(false); const [visible, toggleVisible] = useToggle(false);
const useExample = useCallback(() => { const useExample = useCallback(() => {
@ -61,6 +69,13 @@ export const IframeBubbleMenu = ({ editor }) => {
const copyMe = useCallback(() => copyNode(Iframe.name, editor), [editor]); const copyMe = useCallback(() => copyNode(Iframe.name, editor), [editor]);
const deleteMe = useCallback(() => deleteNode(Iframe.name, editor), [editor]); const deleteMe = useCallback(() => deleteNode(Iframe.name, editor), [editor]);
useEffect(() => {
if (defaultShowPicker && user && createUser === user.id) {
toggleVisible(true);
editor.chain().updateAttributes(Iframe.name, { defaultShowPicker: false }).focus().run();
}
}, [createUser, defaultShowPicker, editor, toggleVisible, user]);
return ( return (
<BubbleMenu <BubbleMenu
className={'bubble-menu'} className={'bubble-menu'}