MCPcopy Create free account
hub / github.com/FlowiseAI/Flowise / RichTextEditor

Function RichTextEditor

packages/agentflow/src/atoms/RichTextEditor.tsx:163–238  ·  view source on GitHub ↗
({
    value,
    onChange,
    placeholder,
    disabled = false,
    rows,
    autoFocus = false,
    onEditorReady,
    useMarkdown = true
}: RichTextEditorProps)

Source from the content-addressed store, hash-verified

161 * business logic. Variable/mention support lives in the features layer.
162 */
163export function RichTextEditor({
164 value,
165 onChange,
166 placeholder,
167 disabled = false,
168 rows,
169 autoFocus = false,
170 onEditorReady,
171 useMarkdown = true
172}: RichTextEditorProps) {
173 // Keep a ref to the latest onChange so the TipTap onUpdate callback never goes stale
174 const onChangeRef = useRef(onChange)
175 useEffect(() => {
176 onChangeRef.current = onChange
177 }, [onChange])
178
179 // Track the last value we emitted (or loaded) to avoid re-setting content
180 // when the parent echoes our own onChange value back as the new prop.
181 const lastEmittedRef = useRef<string>(value || '')
182
183 // Capture initial value and useMarkdown for the mount effect below so we can
184 // depend only on `editor` without suppressing the exhaustive-deps rule.
185 const initialValueRef = useRef(value)
186 const useMarkdownRef = useRef(useMarkdown)
187
188 const extensions = useMemo(() => buildExtensions(placeholder, useMarkdown), [placeholder, useMarkdown])
189
190 const editor = useEditor({
191 extensions,
192 content: '',
193 editable: !disabled,
194 autofocus: autoFocus ? 'end' : false,
195 onUpdate: ({ editor: ed }) => {
196 const raw = useMarkdown ? getEditorMarkdown(ed) : ed.getHTML()
197 const emitted = useMarkdown ? unescapeXmlTags(raw) : raw
198 lastEmittedRef.current = emitted
199 onChangeRef.current(emitted)
200 }
201 })
202
203 // Notify parent when the editor instance is ready (used by ExpandTextDialog to flush
204 // the current editor state to markdown when switching to Source mode).
205 useEffect(() => {
206 onEditorReady?.(editor)
207 return () => onEditorReady?.(null)
208 }, [editor, onEditorReady])
209
210 // Load initial content once the editor is ready, detecting legacy HTML vs markdown.
211 // Reads from refs so only `editor` needs to be in the dep array.
212 useEffect(() => {
213 if (!editor || !initialValueRef.current) return
214 loadContent(editor, initialValueRef.current, useMarkdownRef.current)
215 lastEmittedRef.current = initialValueRef.current
216 }, [editor])
217
218 // Sync genuine external value changes (e.g. parent resets the field programmatically).
219 useEffect(() => {
220 if (editor && value !== lastEmittedRef.current) {

Callers

nothing calls this directly

Calls 5

useEditorFunction · 0.90
getEditorMarkdownFunction · 0.90
unescapeXmlTagsFunction · 0.90
buildExtensionsFunction · 0.85
loadContentFunction · 0.70

Tested by

no test coverage detected