diff --git a/web/app/components/base/prompt-editor/__tests__/index.spec.tsx b/web/app/components/base/prompt-editor/__tests__/index.spec.tsx
index 31e25ab19e1..4faf88f0595 100644
--- a/web/app/components/base/prompt-editor/__tests__/index.spec.tsx
+++ b/web/app/components/base/prompt-editor/__tests__/index.spec.tsx
@@ -36,6 +36,7 @@ const mocks = vi.hoisted(() => {
})),
parseEditorState: vi.fn(() => ({ state: 'parsed' })),
setEditorState: vi.fn(),
+ setEditable: vi.fn(),
focus: vi.fn(),
update: vi.fn((fn: () => void) => fn()),
},
@@ -328,6 +329,20 @@ describe('PromptEditor', () => {
expect(screen.getByTestId('lexical-composer')).toBeInTheDocument()
})
+ it('should update lexical editable state when editable prop changes', () => {
+ const { rerender } = render()
+
+ expect(mocks.editor.setEditable).toHaveBeenLastCalledWith(true)
+
+ rerender()
+
+ expect(mocks.editor.setEditable).toHaveBeenLastCalledWith(false)
+
+ rerender()
+
+ expect(mocks.editor.setEditable).toHaveBeenLastCalledWith(true)
+ })
+
it('should render with isSupportFileVar=true', () => {
render()
expect(screen.getByTestId('lexical-composer')).toBeInTheDocument()
diff --git a/web/app/components/base/prompt-editor/index.tsx b/web/app/components/base/prompt-editor/index.tsx
index 29d0d717157..eab61f4729e 100644
--- a/web/app/components/base/prompt-editor/index.tsx
+++ b/web/app/components/base/prompt-editor/index.tsx
@@ -20,6 +20,7 @@ import type {
VariableBlockType,
WorkflowVariableBlockType,
} from './types'
+import type { EventEmitterValue } from '@/context/event-emitter'
import { cn } from '@langgenius/dify-ui/cn'
import { CodeNode } from '@lexical/code'
import { LexicalComposer } from '@lexical/react/LexicalComposer'
@@ -97,6 +98,16 @@ const ValueSyncPlugin: FC<{ value?: string }> = ({ value }) => {
return null
}
+const EditableSyncPlugin: FC<{ editable: boolean }> = ({ editable }) => {
+ const [editor] = useLexicalComposerContext()
+
+ useEffect(() => {
+ editor.setEditable(editable)
+ }, [editable, editor])
+
+ return null
+}
+
export type PromptEditorProps = {
instanceId?: string
compact?: boolean
@@ -122,7 +133,7 @@ export type PromptEditorProps = {
errorMessageBlock?: ErrorMessageBlockType
lastRunBlock?: LastRunBlockType
isSupportFileVar?: boolean
- shortcutPopups?: Array<{ hotkey: Hotkey, Popup: React.ComponentType<{ onClose: () => void, onInsert: (command: LexicalCommand, params: any[]) => void }> }>
+ shortcutPopups?: Array<{ hotkey: Hotkey, Popup: React.ComponentType<{ onClose: () => void, onInsert: (command: LexicalCommand, params: unknown[]) => void }> }>
}
const PromptEditor: FC = ({
@@ -191,16 +202,18 @@ const PromptEditor: FC = ({
}
useEffect(() => {
- eventEmitter?.emit({
+ const event: EventEmitterValue = {
type: UPDATE_DATASETS_EVENT_EMITTER,
payload: contextBlock?.datasets,
- } as any)
+ }
+ eventEmitter?.emit(event)
}, [eventEmitter, contextBlock?.datasets])
useEffect(() => {
- eventEmitter?.emit({
+ const event: EventEmitterValue = {
type: UPDATE_HISTORY_EVENT_EMITTER,
payload: historyBlock?.history,
- } as any)
+ }
+ eventEmitter?.emit(event)
}, [eventEmitter, historyBlock?.history])
const [floatingAnchorElem, setFloatingAnchorElem] = useState(null)
@@ -243,6 +256,7 @@ const PromptEditor: FC = ({
onEditorChange={handleEditorChange}
/>
+
)