123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- 'use client'
- import type { FC } from 'react'
- import { useEffect } from 'react'
- import type {
- EditorState,
- } from 'lexical'
- import {
- $getRoot,
- TextNode,
- } from 'lexical'
- import { CodeNode } from '@lexical/code'
- import { LexicalComposer } from '@lexical/react/LexicalComposer'
- import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin'
- import { ContentEditable } from '@lexical/react/LexicalContentEditable'
- import LexicalErrorBoundary from '@lexical/react/LexicalErrorBoundary'
- import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin'
- import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin'
- // import TreeView from './plugins/tree-view'
- import Placeholder from './plugins/placeholder'
- import ComponentPickerBlock from './plugins/component-picker-block'
- import {
- ContextBlock,
- ContextBlockNode,
- ContextBlockReplacementBlock,
- } from './plugins/context-block'
- import {
- QueryBlock,
- QueryBlockNode,
- QueryBlockReplacementBlock,
- } from './plugins/query-block'
- import {
- HistoryBlock,
- HistoryBlockNode,
- HistoryBlockReplacementBlock,
- } from './plugins/history-block'
- import {
- WorkflowVariableBlock,
- WorkflowVariableBlockNode,
- WorkflowVariableBlockReplacementBlock,
- } from './plugins/workflow-variable-block'
- import VariableBlock from './plugins/variable-block'
- import VariableValueBlock from './plugins/variable-value-block'
- 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 { textToEditorState } from './utils'
- import type {
- ContextBlockType,
- ExternalToolBlockType,
- HistoryBlockType,
- QueryBlockType,
- VariableBlockType,
- WorkflowVariableBlockType,
- } from './types'
- import {
- UPDATE_DATASETS_EVENT_EMITTER,
- UPDATE_HISTORY_EVENT_EMITTER,
- } from './constants'
- import { useEventEmitterContextContext } from '@/context/event-emitter'
- import cn from '@/utils/classnames'
- export type PromptEditorProps = {
- instanceId?: string
- compact?: boolean
- className?: string
- placeholder?: string
- placeholderClassName?: string
- style?: React.CSSProperties
- value?: string
- editable?: boolean
- onChange?: (text: string) => void
- onBlur?: () => void
- onFocus?: () => void
- contextBlock?: ContextBlockType
- queryBlock?: QueryBlockType
- historyBlock?: HistoryBlockType
- variableBlock?: VariableBlockType
- externalToolBlock?: ExternalToolBlockType
- workflowVariableBlock?: WorkflowVariableBlockType
- isSupportFileVar?: boolean
- }
- const PromptEditor: FC<PromptEditorProps> = ({
- instanceId,
- compact,
- className,
- placeholder,
- placeholderClassName,
- style,
- value,
- editable = true,
- onChange,
- onBlur,
- onFocus,
- contextBlock,
- queryBlock,
- historyBlock,
- variableBlock,
- externalToolBlock,
- workflowVariableBlock,
- isSupportFileVar,
- }) => {
- const { eventEmitter } = useEventEmitterContextContext()
- const initialConfig = {
- namespace: 'prompt-editor',
- nodes: [
- CodeNode,
- CustomTextNode,
- {
- replace: TextNode,
- with: (node: TextNode) => new CustomTextNode(node.__text),
- },
- ContextBlockNode,
- HistoryBlockNode,
- QueryBlockNode,
- WorkflowVariableBlockNode,
- VariableValueBlockNode,
- ],
- editorState: textToEditorState(value || ''),
- onError: (error: Error) => {
- throw error
- },
- }
- const handleEditorChange = (editorState: EditorState) => {
- const text = editorState.read(() => {
- return $getRoot().getChildren().map(p => p.getTextContent()).join('\n')
- })
- if (onChange)
- onChange(text)
- }
- useEffect(() => {
- eventEmitter?.emit({
- type: UPDATE_DATASETS_EVENT_EMITTER,
- payload: contextBlock?.datasets,
- } as any)
- }, [eventEmitter, contextBlock?.datasets])
- useEffect(() => {
- eventEmitter?.emit({
- type: UPDATE_HISTORY_EVENT_EMITTER,
- payload: historyBlock?.history,
- } as any)
- }, [eventEmitter, historyBlock?.history])
- return (
- <LexicalComposer initialConfig={{ ...initialConfig, editable }}>
- <div className='relative min-h-5'>
- <RichTextPlugin
- 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={cn('truncate', placeholderClassName)} compact={compact} />}
- ErrorBoundary={LexicalErrorBoundary}
- />
- <ComponentPickerBlock
- triggerString='/'
- contextBlock={contextBlock}
- historyBlock={historyBlock}
- queryBlock={queryBlock}
- variableBlock={variableBlock}
- externalToolBlock={externalToolBlock}
- workflowVariableBlock={workflowVariableBlock}
- isSupportFileVar={isSupportFileVar}
- />
- <ComponentPickerBlock
- triggerString='{'
- contextBlock={contextBlock}
- historyBlock={historyBlock}
- queryBlock={queryBlock}
- variableBlock={variableBlock}
- externalToolBlock={externalToolBlock}
- workflowVariableBlock={workflowVariableBlock}
- isSupportFileVar={isSupportFileVar}
- />
- {
- contextBlock?.show && (
- <>
- <ContextBlock {...contextBlock} />
- <ContextBlockReplacementBlock {...contextBlock} />
- </>
- )
- }
- {
- queryBlock?.show && (
- <>
- <QueryBlock {...queryBlock} />
- <QueryBlockReplacementBlock />
- </>
- )
- }
- {
- historyBlock?.show && (
- <>
- <HistoryBlock {...historyBlock} />
- <HistoryBlockReplacementBlock {...historyBlock} />
- </>
- )
- }
- {
- (variableBlock?.show || externalToolBlock?.show) && (
- <>
- <VariableBlock />
- <VariableValueBlock />
- </>
- )
- }
- {
- workflowVariableBlock?.show && (
- <>
- <WorkflowVariableBlock {...workflowVariableBlock} />
- <WorkflowVariableBlockReplacementBlock {...workflowVariableBlock} />
- </>
- )
- }
- <OnChangePlugin onChange={handleEditorChange} />
- <OnBlurBlock onBlur={onBlur} onFocus={onFocus} />
- <UpdateBlock instanceId={instanceId} />
- <HistoryPlugin />
- {/* <TreeView /> */}
- </div>
- </LexicalComposer>
- )
- }
- export default PromptEditor
|