You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.tsx 4.0KB

5 maanden geleden
5 maanden geleden
3 maanden geleden
3 maanden geleden
3 maanden geleden
5 maanden geleden
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import {
  2. memo,
  3. useCallback,
  4. useRef,
  5. } from 'react'
  6. import { useTranslation } from 'react-i18next'
  7. import { useClickAway } from 'ahooks'
  8. import type { NodeProps } from 'reactflow'
  9. import NodeResizer from '../nodes/_base/components/node-resizer'
  10. import { useWorkflowHistoryStore } from '../workflow-history-store'
  11. import {
  12. useNodeDataUpdate,
  13. useNodesInteractions,
  14. } from '../hooks'
  15. import { useStore } from '../store'
  16. import {
  17. NoteEditor,
  18. NoteEditorContextProvider,
  19. NoteEditorToolbar,
  20. } from './note-editor'
  21. import { THEME_MAP } from './constants'
  22. import { useNote } from './hooks'
  23. import type { NoteNodeType } from './types'
  24. import cn from '@/utils/classnames'
  25. const Icon = () => {
  26. return (
  27. <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" fill="none">
  28. <path fillRule="evenodd" clipRule="evenodd" d="M12 9.75V6H13.5V9.75C13.5 11.8211 11.8211 13.5 9.75 13.5H6V12H9.75C10.9926 12 12 10.9926 12 9.75Z" fill="black" fillOpacity="0.16" />
  29. </svg>
  30. )
  31. }
  32. const NoteNode = ({
  33. id,
  34. data,
  35. }: NodeProps<NoteNodeType>) => {
  36. const { t } = useTranslation()
  37. const controlPromptEditorRerenderKey = useStore(s => s.controlPromptEditorRerenderKey)
  38. const ref = useRef<HTMLDivElement | null>(null)
  39. const theme = data.theme
  40. const {
  41. handleThemeChange,
  42. handleEditorChange,
  43. handleShowAuthorChange,
  44. } = useNote(id)
  45. const {
  46. handleNodesCopy,
  47. handleNodesDuplicate,
  48. handleNodeDelete,
  49. } = useNodesInteractions()
  50. const { handleNodeDataUpdateWithSyncDraft } = useNodeDataUpdate()
  51. const handleDeleteNode = useCallback(() => {
  52. handleNodeDelete(id)
  53. }, [id, handleNodeDelete])
  54. useClickAway(() => {
  55. handleNodeDataUpdateWithSyncDraft({ id, data: { selected: false } })
  56. }, ref)
  57. const { setShortcutsEnabled } = useWorkflowHistoryStore()
  58. return (
  59. <div
  60. className={cn(
  61. 'relative flex flex-col rounded-md border shadow-xs hover:shadow-md',
  62. THEME_MAP[theme].bg,
  63. data.selected ? THEME_MAP[theme].border : 'border-black/5',
  64. )}
  65. style={{
  66. width: data.width,
  67. height: data.height,
  68. }}
  69. ref={ref}
  70. >
  71. <NoteEditorContextProvider
  72. key={controlPromptEditorRerenderKey}
  73. value={data.text}
  74. editable={!data._isTempNode}
  75. >
  76. <>
  77. {
  78. !data._isTempNode && (
  79. <NodeResizer
  80. nodeId={id}
  81. nodeData={data}
  82. icon={<Icon />}
  83. minWidth={240}
  84. minHeight={88}
  85. />
  86. )
  87. }
  88. <div
  89. className={cn(
  90. 'h-2 shrink-0 rounded-t-md opacity-50',
  91. THEME_MAP[theme].title,
  92. )}></div>
  93. {
  94. data.selected && !data._isTempNode && (
  95. <div className='absolute left-1/2 top-[-41px] -translate-x-1/2'>
  96. <NoteEditorToolbar
  97. theme={theme}
  98. onThemeChange={handleThemeChange}
  99. onCopy={handleNodesCopy}
  100. onDuplicate={handleNodesDuplicate}
  101. onDelete={handleDeleteNode}
  102. showAuthor={data.showAuthor}
  103. onShowAuthorChange={handleShowAuthorChange}
  104. />
  105. </div>
  106. )
  107. }
  108. <div className='grow overflow-y-auto px-3 py-2.5'>
  109. <div className={cn(
  110. data.selected && 'nodrag nopan nowheel cursor-text',
  111. )}>
  112. <NoteEditor
  113. containerElement={ref.current}
  114. placeholder={t('workflow.nodes.note.editor.placeholder') || ''}
  115. onChange={handleEditorChange}
  116. setShortcutsEnabled={setShortcutsEnabled}
  117. />
  118. </div>
  119. </div>
  120. {
  121. data.showAuthor && (
  122. <div className='p-3 pt-0 text-xs text-text-tertiary'>
  123. {data.author}
  124. </div>
  125. )
  126. }
  127. </>
  128. </NoteEditorContextProvider>
  129. </div>
  130. )
  131. }
  132. export default memo(NoteNode)