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.

control.tsx 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import type { MouseEvent } from 'react'
  2. import {
  3. memo,
  4. } from 'react'
  5. import { useTranslation } from 'react-i18next'
  6. import {
  7. RiAspectRatioFill,
  8. RiAspectRatioLine,
  9. RiCursorLine,
  10. RiFunctionAddLine,
  11. RiHand,
  12. RiStickyNoteAddLine,
  13. } from '@remixicon/react'
  14. import {
  15. useNodesReadOnly,
  16. useWorkflowCanvasMaximize,
  17. useWorkflowMoveMode,
  18. useWorkflowOrganize,
  19. } from '../hooks'
  20. import {
  21. ControlMode,
  22. } from '../types'
  23. import { useStore } from '../store'
  24. import Divider from '../../base/divider'
  25. import AddBlock from './add-block'
  26. import TipPopup from './tip-popup'
  27. import ExportImage from './export-image'
  28. import { useOperator } from './hooks'
  29. import cn from '@/utils/classnames'
  30. const Control = () => {
  31. const { t } = useTranslation()
  32. const controlMode = useStore(s => s.controlMode)
  33. const maximizeCanvas = useStore(s => s.maximizeCanvas)
  34. const { handleModePointer, handleModeHand } = useWorkflowMoveMode()
  35. const { handleLayout } = useWorkflowOrganize()
  36. const { handleAddNote } = useOperator()
  37. const {
  38. nodesReadOnly,
  39. getNodesReadOnly,
  40. } = useNodesReadOnly()
  41. const { handleToggleMaximizeCanvas } = useWorkflowCanvasMaximize()
  42. const addNote = (e: MouseEvent<HTMLDivElement>) => {
  43. if (getNodesReadOnly())
  44. return
  45. e.stopPropagation()
  46. handleAddNote()
  47. }
  48. return (
  49. <div className='flex flex-col items-center rounded-lg border-[0.5px] border-components-actionbar-border bg-components-actionbar-bg p-0.5 text-text-tertiary shadow-lg'>
  50. <AddBlock />
  51. <TipPopup title={t('workflow.nodes.note.addNote')}>
  52. <div
  53. className={cn(
  54. 'ml-[1px] flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg hover:bg-state-base-hover hover:text-text-secondary',
  55. `${nodesReadOnly && 'cursor-not-allowed text-text-disabled hover:bg-transparent hover:text-text-disabled'}`,
  56. )}
  57. onClick={addNote}
  58. >
  59. <RiStickyNoteAddLine className='h-4 w-4' />
  60. </div>
  61. </TipPopup>
  62. <Divider className='my-1 w-3.5' />
  63. <TipPopup title={t('workflow.common.pointerMode')} shortcuts={['v']}>
  64. <div
  65. className={cn(
  66. 'mr-[1px] flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg',
  67. controlMode === ControlMode.Pointer ? 'bg-state-accent-active text-text-accent' : 'hover:bg-state-base-hover hover:text-text-secondary',
  68. `${nodesReadOnly && 'cursor-not-allowed text-text-disabled hover:bg-transparent hover:text-text-disabled'}`,
  69. )}
  70. onClick={handleModePointer}
  71. >
  72. <RiCursorLine className='h-4 w-4' />
  73. </div>
  74. </TipPopup>
  75. <TipPopup title={t('workflow.common.handMode')} shortcuts={['h']}>
  76. <div
  77. className={cn(
  78. 'flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg',
  79. controlMode === ControlMode.Hand ? 'bg-state-accent-active text-text-accent' : 'hover:bg-state-base-hover hover:text-text-secondary',
  80. `${nodesReadOnly && 'cursor-not-allowed text-text-disabled hover:bg-transparent hover:text-text-disabled'}`,
  81. )}
  82. onClick={handleModeHand}
  83. >
  84. <RiHand className='h-4 w-4' />
  85. </div>
  86. </TipPopup>
  87. <Divider className='my-1 w-3.5' />
  88. <ExportImage />
  89. <TipPopup title={t('workflow.panel.organizeBlocks')} shortcuts={['ctrl', 'o']}>
  90. <div
  91. className={cn(
  92. 'flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg hover:bg-state-base-hover hover:text-text-secondary',
  93. `${nodesReadOnly && 'cursor-not-allowed text-text-disabled hover:bg-transparent hover:text-text-disabled'}`,
  94. )}
  95. onClick={handleLayout}
  96. >
  97. <RiFunctionAddLine className='h-4 w-4' />
  98. </div>
  99. </TipPopup>
  100. <TipPopup title={maximizeCanvas ? t('workflow.panel.minimize') : t('workflow.panel.maximize')} shortcuts={['f']}>
  101. <div
  102. className={cn(
  103. 'flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg hover:bg-state-base-hover hover:text-text-secondary',
  104. maximizeCanvas ? 'bg-state-accent-active text-text-accent hover:text-text-accent' : 'hover:bg-state-base-hover hover:text-text-secondary',
  105. `${nodesReadOnly && 'cursor-not-allowed text-text-disabled hover:bg-transparent hover:text-text-disabled'}`,
  106. )}
  107. onClick={handleToggleMaximizeCanvas}
  108. >
  109. {maximizeCanvas && <RiAspectRatioFill className='h-4 w-4' />}
  110. {!maximizeCanvas && <RiAspectRatioLine className='h-4 w-4' />}
  111. </div>
  112. </TipPopup>
  113. </div>
  114. )
  115. }
  116. export default memo(Control)