From 672328463b13f59acd665d2985664f63d5c05761 Mon Sep 17 00:00:00 2001 From: Phodal Huang Date: Tue, 21 Nov 2023 20:27:23 +0800 Subject: [PATCH] refactor: reorg ui menu --- components/editor/action/custom-commands.jsx | 6 +- .../editor/intelli/ai-quick-command.jsx | 77 ++++++++++++++++++- .../editor/intelli/ai-slash-commands.jsx | 6 +- ...{ai-bubble-menu.jsx => ui-bubble-menu.jsx} | 4 +- .../{ai-menu-bar.jsx => ui-menubar.jsx} | 2 +- .../editor/intelli/ui-quick-command.jsx | 9 +++ .../{ai-slash-menu.jsx => ui-slash-menu.jsx} | 4 +- components/editor/live-editor.jsx | 6 +- components/editor/menu-bar.jsx | 4 +- 9 files changed, 99 insertions(+), 19 deletions(-) rename components/editor/intelli/{ai-bubble-menu.jsx => ui-bubble-menu.jsx} (84%) rename components/editor/intelli/{ai-menu-bar.jsx => ui-menubar.jsx} (96%) create mode 100644 components/editor/intelli/ui-quick-command.jsx rename components/editor/intelli/{ai-slash-menu.jsx => ui-slash-menu.jsx} (97%) diff --git a/components/editor/action/custom-commands.jsx b/components/editor/action/custom-commands.jsx index 512361b..da70202 100644 --- a/components/editor/action/custom-commands.jsx +++ b/components/editor/action/custom-commands.jsx @@ -8,11 +8,11 @@ export const CustomCommands = Extension.create({ console.log('variable', variableName, variableValue) }, getSelectedText: () => ({ editor }) => { + if (!editor.state) return null + const { from, to, empty } = editor.state.selection - if (empty) { - return null - } + if (empty) return null return editor.state.doc.textBetween(from, to, ' ') }, diff --git a/components/editor/intelli/ai-quick-command.jsx b/components/editor/intelli/ai-quick-command.jsx index 7bb7c45..5e2f537 100644 --- a/components/editor/intelli/ai-quick-command.jsx +++ b/components/editor/intelli/ai-quick-command.jsx @@ -1,13 +1,86 @@ -import { Extension } from '@tiptap/react' +import { Extension, ReactRenderer } from '@tiptap/react' +import { Suggestion } from '@tiptap/suggestion' +import tippy from 'tippy.js' +import { UiQuickCommand } from './ui-quick-command' + +const extensionName = 'quick-command' export const AiQuickCommand = Extension.create({ name: 'quick-command', - + addOptions () { + return { + char: 'Mod-/', + pluginKey: 'quick-command', + } + }, addKeyboardShortcuts () { return { 'Mod-/': () => { console.log('Mod-/ pressed') }, } + }, + addProseMirrorPlugins () { + return [ + Suggestion({ + editor: this.editor, + char: this.options.char, + pluginKey: this.options.pluginKey, + + render: () => { + let component + let popup + let isEditable + + return { + onStart: (props) => { + isEditable = props.editor.isEditable + if (!isEditable) return + + component = new ReactRenderer(UiQuickCommand, { + props, + editor: props.editor, + }) + + popup = tippy('body', { + getReferenceClientRect: props.clientRect || (() => props.editor.storage[extensionName].rect), + appendTo: () => document.body, + content: component.element, + showOnCreate: true, + interactive: true, + trigger: 'manual', + placement: 'bottom-start', + }) + }, + + onUpdate (props) { + if (!isEditable) return + + component.updateProps(props) + props.editor.storage[extensionName].rect = props.clientRect() + popup[0].setProps({ + getReferenceClientRect: props.clientRect, + }) + }, + + onKeyDown (props) { + if (!isEditable) return + + if (props.event.key === 'Escape') { + popup[0].hide() + return true + } + return component.ref?.onKeyDown(props) + }, + + onExit () { + if (!isEditable) return + popup && popup[0].destroy() + component.destroy() + }, + } + } + }) + ] } }) \ No newline at end of file diff --git a/components/editor/intelli/ai-slash-commands.jsx b/components/editor/intelli/ai-slash-commands.jsx index 95e5294..bca7e34 100644 --- a/components/editor/intelli/ai-slash-commands.jsx +++ b/components/editor/intelli/ai-slash-commands.jsx @@ -2,7 +2,7 @@ import { ReactRenderer } from '@tiptap/react' import { Node } from '@tiptap/core' import { Suggestion } from '@tiptap/suggestion' import tippy from 'tippy.js' -import AiSlashMenu from './ai-slash-menu' +import UiSlashMenu from './ui-slash-menu' // or try SlashCommands: https://github.com/ueberdosis/tiptap/issues/1508 const extensionName = `ai-insert` @@ -53,13 +53,11 @@ export const createSlashCommand = (name, options) => { isEditable = props.editor.isEditable if (!isEditable) return - component = new ReactRenderer(AiSlashMenu, { + component = new ReactRenderer(UiSlashMenu, { props, editor: props.editor, }) - console.log(component.element) - popup = tippy('body', { getReferenceClientRect: props.clientRect || (() => props.editor.storage[extensionName].rect), appendTo: () => document.body, diff --git a/components/editor/intelli/ai-bubble-menu.jsx b/components/editor/intelli/ui-bubble-menu.jsx similarity index 84% rename from components/editor/intelli/ai-bubble-menu.jsx rename to components/editor/intelli/ui-bubble-menu.jsx index e7bb6c2..7bca171 100644 --- a/components/editor/intelli/ai-bubble-menu.jsx +++ b/components/editor/intelli/ui-bubble-menu.jsx @@ -1,8 +1,8 @@ import { BubbleMenu } from '@tiptap/react' import React from 'react' -export const AiBubbleMenu = ({ editor }) => { - const selection = editor.commands.getSelectedText() +export const UiBubbleMenu = ({ editor }) => { + const selection = editor.commands?.getSelectedText() let selectLength = selection?.length ? selection.length : 0 // 根据长度优化 diff --git a/components/editor/intelli/ai-menu-bar.jsx b/components/editor/intelli/ui-menubar.jsx similarity index 96% rename from components/editor/intelli/ai-menu-bar.jsx rename to components/editor/intelli/ui-menubar.jsx index 927af03..ffa1ce0 100644 --- a/components/editor/intelli/ai-menu-bar.jsx +++ b/components/editor/intelli/ui-menubar.jsx @@ -2,7 +2,7 @@ import * as DropdownMenu from '@radix-ui/react-dropdown-menu' import { CookieIcon } from '@radix-ui/react-icons' import React from 'react' // spike: https://ai-demo.tiptap.dev/kmLmpqbFJW -export const AiMenubar = ({ editor }) => { +export const UiMenubar = ({ editor }) => { return