fix prompt editor

This commit is contained in:
StyleZhang
2024-04-01 19:03:08 +08:00
parent e08d871837
commit 45d5d259a4
11 changed files with 83 additions and 15 deletions

View File

@ -9,7 +9,10 @@ import {
$getRoot,
TextNode,
} from 'lexical'
import { CodeNode } from '@lexical/code'
import {
CodeHighlightNode,
CodeNode,
} from '@lexical/code'
import { LexicalComposer } from '@lexical/react/LexicalComposer'
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin'
import { ContentEditable } from '@lexical/react/LexicalContentEditable'
@ -44,6 +47,7 @@ import { VariableValueBlockNode } from './plugins/variable-value-block/node'
import { CustomTextNode } from './plugins/custom-text/node'
import OnBlurBlock from './plugins/on-blur-or-focus-block'
import UpdateBlock from './plugins/update-block'
import CodeHighlightBlock from './plugins/code-highlight-block'
import { textToEditorState } from './utils'
import type {
ContextBlockType,
@ -61,6 +65,7 @@ import { useEventEmitterContextContext } from '@/context/event-emitter'
export type PromptEditorProps = {
instanceId?: string
compact?: boolean
className?: string
placeholder?: string
placeholderClassName?: string
@ -80,6 +85,7 @@ export type PromptEditorProps = {
const PromptEditor: FC<PromptEditorProps> = ({
instanceId,
compact,
className,
placeholder,
placeholderClassName,
@ -101,6 +107,7 @@ const PromptEditor: FC<PromptEditorProps> = ({
namespace: 'prompt-editor',
nodes: [
CodeNode,
CodeHighlightNode,
CustomTextNode,
{
replace: TextNode,
@ -141,8 +148,8 @@ const PromptEditor: FC<PromptEditorProps> = ({
<LexicalComposer initialConfig={{ ...initialConfig, editable }}>
<div className='relative'>
<RichTextPlugin
contentEditable={<ContentEditable className={`${className} outline-none text-sm text-gray-700 leading-6`} style={style || {}} />}
placeholder={<Placeholder value={placeholder} className={placeholderClassName} />}
contentEditable={<ContentEditable className={`${className} outline-none ${compact ? 'leading-5 text-[13px]' : 'leading-6 text-sm'} text-gray-700`} style={style || {}} />}
placeholder={<Placeholder value={placeholder} className={placeholderClassName} compact={compact} />}
ErrorBoundary={LexicalErrorBoundary}
/>
<ComponentPickerBlock
@ -207,6 +214,7 @@ const PromptEditor: FC<PromptEditorProps> = ({
<OnChangePlugin onChange={handleEditorChange} />
<OnBlurBlock onBlur={onBlur} onFocus={onFocus} />
<UpdateBlock instanceId={instanceId} />
<CodeHighlightBlock />
{/* <TreeView /> */}
</div>
</LexicalComposer>

View File

@ -0,0 +1,13 @@
import { useEffect } from 'react'
import { registerCodeHighlighting } from '@lexical/code'
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
export default function CodeHighlightPlugin() {
const [editor] = useLexicalComposerContext()
useEffect(() => {
return registerCodeHighlighting(editor)
}, [editor])
return null
}

View File

@ -195,7 +195,7 @@ export const useOptions = (
variableOptions,
externalToolOptions,
workflowVariableOptions,
allOptions: [...promptOptions, ...variableOptions, ...externalToolOptions, ...workflowVariableOptions],
allOptions: [...promptOptions, ...variableOptions, ...externalToolOptions],
}
}, [promptOptions, variableOptions, externalToolOptions, workflowVariableOptions])
}

View File

@ -82,11 +82,12 @@ const ComponentPicker = ({
matchingString: string,
) => {
editor.update(() => {
if (nodeToRemove)
if (nodeToRemove && selectedOption?.key)
nodeToRemove.remove()
if (selectedOption?.onSelect)
selectedOption.onSelect(matchingString)
closeMenu()
})
},
@ -104,9 +105,9 @@ const ComponentPicker = ({
anchorElementRef,
{ selectedIndex, selectOptionAndCleanUp, setHighlightedIndex },
) => {
if (anchorElementRef.current && allOptions.length) {
if (anchorElementRef.current && (allOptions.length || workflowVariableOptions.length)) {
return ReactDOM.createPortal(
<div className='mt-[25px] w-[260px] bg-white rounded-lg border-[0.5px] border-gray-200 shadow-lg'>
<div className='w-[260px] bg-white rounded-lg border-[0.5px] border-gray-200 shadow-lg'>
{
!!promptOptions.length && (
<>
@ -196,8 +197,7 @@ const ComponentPicker = ({
<VarReferenceVars
hideSearch
vars={workflowVariableOptions}
onChange={(variables: string[], item: any) => {
selectOptionAndCleanUp(item)
onChange={(variables: string[]) => {
handleSelectWorkflowVariable(variables)
}}
/>

View File

@ -1,20 +1,27 @@
import { memo } from 'react'
import { useTranslation } from 'react-i18next'
import cn from 'classnames'
const Placeholder = ({
compact,
value,
className,
}: {
compact?: boolean
value?: string
className?: string
}) => {
const { t } = useTranslation()
return (
<div className={cn(className, 'absolute top-0 left-0 h-full w-full text-sm text-gray-300 select-none pointer-events-none leading-6')}>
<div className={cn(
className,
'absolute top-0 left-0 h-full w-full text-sm text-gray-300 select-none pointer-events-none',
compact ? 'leading-5 text-[13px]' : 'leading-6 text-sm',
)}>
{value || t('common.promptEditor.placeholder')}
</div>
)
}
export default Placeholder
export default memo(Placeholder)

View File

@ -1,8 +1,11 @@
import { $insertNodes } from 'lexical'
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
import { textToEditorState } from '../utils'
import { CustomTextNode } from './custom-text/node'
import { useEventEmitterContextContext } from '@/context/event-emitter'
export const PROMPT_EDITOR_UPDATE_VALUE_BY_EVENT_EMITTER = 'PROMPT_EDITOR_UPDATE_VALUE_BY_EVENT_EMITTER'
export const PROMPT_EDITOR_INSERT_QUICKLY = 'PROMPT_EDITOR_INSERT_QUICKLY'
type UpdateBlockProps = {
instanceId?: string
@ -20,6 +23,16 @@ const UpdateBlock = ({
}
})
eventEmitter?.useSubscription((v: any) => {
if (v.type === PROMPT_EDITOR_INSERT_QUICKLY && v.instanceId === instanceId) {
editor.focus()
editor.update(() => {
const textNode = new CustomTextNode('/')
$insertNodes([textNode])
})
}
})
return null
}

View File

@ -27,7 +27,7 @@ const WorkflowVariableBlockComponent: FC<WorkflowVariableBlockComponentProps> =
return (
<div
className={`
mr-[2px] relative group/wrap flex items-center h-[20px] pl-0.5 pr-[3px] rounded-[5px] border
mx-0.5 relative group/wrap flex items-center h-[18px] pl-0.5 pr-[3px] rounded-[5px] border
${isSelected ? ' border-[#84ADFF] bg-[#F5F8FF]' : ' border-black/5 bg-white'}
`}
ref={ref}

View File

@ -3,6 +3,8 @@ import {
useEffect,
} from 'react'
import {
$getNodeByKey,
$getPreviousSelection,
$insertNodes,
COMMAND_PRIORITY_EDITOR,
createCommand,
@ -39,9 +41,16 @@ const WorkflowVariableBlock = memo(({
editor.registerCommand(
INSERT_WORKFLOW_VARIABLE_BLOCK_COMMAND,
(variables: string[]) => {
const contextBlockNode = $createWorkflowVariableBlockNode(variables, getWorkflowNode)
const workflowVariableBlockNode = $createWorkflowVariableBlockNode(variables, getWorkflowNode)
const prevNodeKey = ($getPreviousSelection() as any)?.anchor?.key
$insertNodes([contextBlockNode])
if (prevNodeKey) {
const prevNode = $getNodeByKey(prevNodeKey)
prevNode?.remove()
}
$insertNodes([workflowVariableBlockNode])
if (onInsert)
onInsert()