| 1 | /** |
| 2 | * PublishDialogDragSource - 发布弹框左栏拖拽源包装组件 |
| 3 | * 仅在发布弹框内启用,避免普通草稿页缺少 DndProvider 时触发 react-dnd 上下文错误。 |
| 4 | */ |
| 5 | |
| 6 | 'use client' |
| 7 | |
| 8 | import type { HTMLAttributes, ReactNode } from 'react' |
| 9 | import type { DragSourceMonitor } from 'react-dnd' |
| 10 | import type { PublishDialogDragItem } from '@/components/PublishDialog/PublishDialog.util' |
| 11 | import { memo, useEffect } from 'react' |
| 12 | import { useDrag } from 'react-dnd' |
| 13 | import { getEmptyImage } from 'react-dnd-html5-backend' |
| 14 | import { PUBLISH_DIALOG_DND_TYPE } from '@/components/PublishDialog/PublishDialog.util' |
| 15 | import { cn } from '@/utils/className' |
| 16 | |
| 17 | interface PublishDialogDragSourceProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> { |
| 18 | dragItem: PublishDialogDragItem |
| 19 | children: ReactNode |
| 20 | } |
| 21 | |
| 22 | export const PublishDialogDragSource = memo(({ dragItem, className, children, ...props }: PublishDialogDragSourceProps) => { |
| 23 | const [{ isDragging }, drag, preview] = useDrag( |
| 24 | () => ({ |
| 25 | type: PUBLISH_DIALOG_DND_TYPE, |
| 26 | item: dragItem, |
| 27 | collect: (monitor: DragSourceMonitor) => ({ |
| 28 | isDragging: monitor.isDragging(), |
| 29 | }), |
| 30 | }), |
| 31 | [dragItem], |
| 32 | ) |
| 33 | |
| 34 | useEffect(() => { |
| 35 | preview(getEmptyImage(), { captureDraggingState: true }) |
| 36 | }, [preview]) |
| 37 | |
| 38 | return ( |
| 39 | <div |
| 40 | ref={(node) => { |
| 41 | drag(node) |
| 42 | }} |
| 43 | className={cn(className, 'cursor-grab active:cursor-grabbing', isDragging && 'opacity-50')} |
| 44 | {...props} |
| 45 | > |
| 46 | {children} |
| 47 | </div> |
| 48 | ) |
| 49 | }) |
| 50 | |
| 51 | PublishDialogDragSource.displayName = 'PublishDialogDragSource' |
| 52 |