import type { Edge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge'; import type { Instruction } from '@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item'; import { cssVar } from '@toeverything/theme'; import { assignInlineVars } from '@vanilla-extract/dynamic'; import clsx from 'clsx'; import { type ReactElement } from 'react'; import * as styles from './drop-indicator.css'; export type DropIndicatorProps = { instruction?: Instruction | null; edge?: Edge | null; }; function getTreeElement({ instruction, isBlocked, }: { instruction: Exclude; isBlocked: boolean; }): ReactElement | null { const style = { [styles.horizontalIndent]: `${instruction.currentLevel * instruction.indentPerLevel}px`, [styles.indicatorColor]: !isBlocked ? cssVar('--affine-primary-color') : cssVar('--affine-warning-color'), }; if (instruction.type === 'reorder-above') { return (
); } if (instruction.type === 'reorder-below') { return (
); } if (instruction.type === 'make-child') { return (
); } if (instruction.type === 'reparent') { style[styles.horizontalIndent] = `${ instruction.desiredLevel * instruction.indentPerLevel }px`; return (
); } return null; } type Orientation = 'horizontal' | 'vertical'; const edgeToOrientationMap: Record = { top: 'horizontal', bottom: 'horizontal', left: 'vertical', right: 'vertical', }; const orientationStyles: Record = { horizontal: styles.horizontal, vertical: styles.vertical, }; const edgeStyles: Record = { top: styles.top, bottom: styles.bottom, left: styles.left, right: styles.right, }; function getEdgeElement(edge: Edge, gap: number = 0) { const lineOffset = `calc(-0.5 * (${gap}px + 2px))`; const orientation = edgeToOrientationMap[edge]; return (
); } export function DropIndicator({ instruction, edge }: DropIndicatorProps) { if (edge) { return getEdgeElement(edge, 0); } if (instruction) { if (instruction.type === 'instruction-blocked') { return getTreeElement({ instruction: instruction.desired, isBlocked: true, }); } return getTreeElement({ instruction, isBlocked: false }); } return; }