iterative/vscode-dvc

View on GitHub
webview/src/plots/components/templatePlots/AddedSection.tsx

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
import React, { DragEvent } from 'react'
import { useSelector } from 'react-redux'
import cx from 'classnames'
import { TemplatePlotGroup } from 'dvc/src/plots/webview/contract'
import { PlotGroup } from './templatePlotsSlice'
import styles from '../styles.module.scss'
import { PlotsState } from '../../store'
import { getIDWithoutIndex } from '../../../util/ids'
import { Icon } from '../../../shared/components/Icon'
import { GraphLine } from '../../../shared/components/icons'
import { useDeferredDragLeave } from '../../../shared/hooks/useDeferredDragLeave'

interface AddedSectionProps {
  id: string
  hoveredSection: string
  setHoveredSection: (section: string) => void
  onDrop: (e: DragEvent<HTMLElement>) => void
  closestSection: PlotGroup
  acceptedGroups: string[]
}

export const AddedSection: React.FC<AddedSectionProps> = ({
  id,
  onDrop,
  hoveredSection,
  setHoveredSection,
  closestSection,
  acceptedGroups
}) => {
  const { draggedRef } = useSelector((state: PlotsState) => state.dragAndDrop)
  const { immediateDragEnter, deferredDragLeave } = useDeferredDragLeave()

  const isHovered = hoveredSection === id

  const handleDragLeave = () => {
    deferredDragLeave(() => setHoveredSection(''))
  }

  const handleDragEnter = () => {
    const draggedGroup = getIDWithoutIndex(draggedRef?.group) || ''
    if (
      acceptedGroups.includes(draggedGroup) &&
      (draggedGroup as TemplatePlotGroup) !== closestSection.group
    ) {
      setHoveredSection(id)
      immediateDragEnter()
    }
  }

  const handleDragOver = (e: DragEvent<HTMLElement>) => {
    e.preventDefault()
    immediateDragEnter()
  }

  return (
    <div
      id={id}
      data-testid={id}
      onDragEnter={handleDragEnter}
      onDragLeave={handleDragLeave}
      onDragOver={handleDragOver}
      onDrop={onDrop}
      draggable
      className={cx(
        styles.singleViewPlotsGrid,
        styles.noBigGrid,
        styles.dropSectionWrapper
      )}
    >
      <div
        className={cx(styles.dropSection, {
          [styles.dropSectionMaximized]: isHovered,
          [styles.plot]: isHovered
        })}
      >
        {isHovered && (
          <Icon
            data-testid={`${id}_drop-icon`}
            icon={GraphLine}
            className={styles.dropIcon}
            width={50}
            height={50}
          />
        )}
      </div>
    </div>
  )
}