history-block-replacement-block.tsx 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. import {
  2. useCallback,
  3. useEffect,
  4. } from 'react'
  5. import { $applyNodeReplacement } from 'lexical'
  6. import { mergeRegister } from '@lexical/utils'
  7. import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
  8. import { decoratorTransform } from '../../utils'
  9. import { HISTORY_PLACEHOLDER_TEXT } from '../../constants'
  10. import type { HistoryBlockType } from '../../types'
  11. import {
  12. $createHistoryBlockNode,
  13. HistoryBlockNode,
  14. } from '../history-block/node'
  15. import { CustomTextNode } from '../custom-text/node'
  16. const REGEX = new RegExp(HISTORY_PLACEHOLDER_TEXT)
  17. const HistoryBlockReplacementBlock = ({
  18. history = { user: '', assistant: '' },
  19. onEditRole = () => {},
  20. onInsert,
  21. }: HistoryBlockType) => {
  22. const [editor] = useLexicalComposerContext()
  23. useEffect(() => {
  24. if (!editor.hasNodes([HistoryBlockNode]))
  25. throw new Error('HistoryBlockNodePlugin: HistoryBlockNode not registered on editor')
  26. }, [editor])
  27. const createHistoryBlockNode = useCallback((): HistoryBlockNode => {
  28. if (onInsert)
  29. onInsert()
  30. return $applyNodeReplacement($createHistoryBlockNode(history, onEditRole))
  31. }, [history, onEditRole, onInsert])
  32. const getMatch = useCallback((text: string) => {
  33. const matchArr = REGEX.exec(text)
  34. if (matchArr === null)
  35. return null
  36. const startOffset = matchArr.index
  37. const endOffset = startOffset + HISTORY_PLACEHOLDER_TEXT.length
  38. return {
  39. end: endOffset,
  40. start: startOffset,
  41. }
  42. }, [])
  43. useEffect(() => {
  44. REGEX.lastIndex = 0
  45. return mergeRegister(
  46. editor.registerNodeTransform(CustomTextNode, textNode => decoratorTransform(textNode, getMatch, createHistoryBlockNode)),
  47. )
  48. }, [])
  49. return null
  50. }
  51. export default HistoryBlockReplacementBlock