import type { FC } from 'react' import { RiCheckLine, RiFullscreenLine, RiZoomInLine, RiZoomOutLine, } from '@remixicon/react' import { Fragment, memo, useCallback, useState, } from 'react' import { useTranslation } from 'react-i18next' import { useReactFlow, useViewport, } from 'reactflow' import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger, } from '@/app/components/base/portal-to-follow-elem' import { useGlobalPublicStore } from '@/context/global-public-context' import { cn } from '@/utils/classnames' import Divider from '../../base/divider' import { useNodesSyncDraft, useWorkflowReadOnly, } from '../hooks' import ShortcutsName from '../shortcuts-name' import TipPopup from './tip-popup' enum ZoomType { zoomIn = 'zoomIn', zoomOut = 'zoomOut', zoomToFit = 'zoomToFit', zoomTo25 = 'zoomTo25', zoomTo50 = 'zoomTo50', zoomTo75 = 'zoomTo75', zoomTo100 = 'zoomTo100', zoomTo200 = 'zoomTo200', toggleUserComments = 'toggleUserComments', toggleUserCursors = 'toggleUserCursors', toggleMiniMap = 'toggleMiniMap', } type ZoomInOutProps = { showMiniMap?: boolean onToggleMiniMap?: () => void showUserCursors?: boolean onToggleUserCursors?: () => void showUserComments?: boolean onToggleUserComments?: () => void isCommentMode?: boolean } const ZoomInOut: FC = ({ showMiniMap = true, onToggleMiniMap, showUserCursors = true, onToggleUserCursors, showUserComments = true, onToggleUserComments, isCommentMode = false, }) => { const { t } = useTranslation() const { zoomIn, zoomOut, zoomTo, fitView, } = useReactFlow() const { zoom } = useViewport() const { handleSyncWorkflowDraft } = useNodesSyncDraft() const [open, setOpen] = useState(false) const { workflowReadOnly, getWorkflowReadOnly, } = useWorkflowReadOnly() const isCollaborationEnabled = useGlobalPublicStore(s => s.systemFeatures.enable_collaboration_mode) const ZOOM_IN_OUT_OPTIONS = [ [ { key: ZoomType.zoomTo200, text: '200%', }, { key: ZoomType.zoomTo100, text: '100%', }, { key: ZoomType.zoomTo75, text: '75%', }, { key: ZoomType.zoomTo50, text: '50%', }, { key: ZoomType.zoomTo25, text: '25%', }, { key: ZoomType.zoomToFit, text: t('operator.zoomToFit', { ns: 'workflow' }), }, ], isCollaborationEnabled ? [ { key: ZoomType.toggleUserComments, text: t('operator.showUserComments', { ns: 'workflow' }), }, { key: ZoomType.toggleUserCursors, text: t('operator.showUserCursors', { ns: 'workflow' }), }, { key: ZoomType.toggleMiniMap, text: t('operator.showMiniMap', { ns: 'workflow' }), }, ] : [ { key: ZoomType.toggleMiniMap, text: t('operator.showMiniMap', { ns: 'workflow' }), }, ], ] const handleZoom = (type: string) => { if (workflowReadOnly) return if (type === ZoomType.zoomToFit) fitView() if (type === ZoomType.zoomTo25) zoomTo(0.25) if (type === ZoomType.zoomTo50) zoomTo(0.5) if (type === ZoomType.zoomTo75) zoomTo(0.75) if (type === ZoomType.zoomTo100) zoomTo(1) if (type === ZoomType.zoomTo200) zoomTo(2) if (type === ZoomType.toggleUserComments) { if (!isCommentMode) onToggleUserComments?.() return } if (type === ZoomType.toggleUserCursors) { onToggleUserCursors?.() return } if (type === ZoomType.toggleMiniMap) { onToggleMiniMap?.() return } handleSyncWorkflowDraft() } const handleTrigger = useCallback(() => { if (getWorkflowReadOnly()) return setOpen(v => !v) }, [getWorkflowReadOnly]) return (
{ if (zoom <= 0.25) return e.stopPropagation() zoomOut() }} >
{Number.parseFloat(`${zoom * 100}`).toFixed(0)} %
= 2 ? 'cursor-not-allowed' : 'cursor-pointer hover:bg-black/5'}`} onClick={(e) => { if (zoom >= 2) return e.stopPropagation() zoomIn() }} >
{ ZOOM_IN_OUT_OPTIONS.map((options, i) => ( { i !== 0 && ( ) }
{ options.map(option => (
handleZoom(option.key)} >
{option.key === ZoomType.toggleUserComments && showUserComments && ( )} {option.key === ZoomType.toggleUserComments && !showUserComments && (
)} {option.key === ZoomType.toggleUserCursors && showUserCursors && ( )} {option.key === ZoomType.toggleUserCursors && !showUserCursors && (
)} {option.key === ZoomType.toggleMiniMap && showMiniMap && ( )} {option.key === ZoomType.toggleMiniMap && !showMiniMap && (
)} {option.key === ZoomType.zoomToFit && ( )} {option.key !== ZoomType.toggleUserComments && option.key !== ZoomType.toggleUserCursors && option.key !== ZoomType.toggleMiniMap && option.key !== ZoomType.zoomToFit && (
)} {option.text}
{ option.key === ZoomType.zoomToFit && ( ) } { option.key === ZoomType.zoomTo50 && ( ) } { option.key === ZoomType.zoomTo100 && ( ) }
)) }
)) }
) } export default memo(ZoomInOut)