({
level,
isSelected,
isDragging,
dragHandleProps,
dragHandleRef,
onSelect,
onDuplicate,
onPaste,
onRequestDelete,
}: {
level: LevelNode
isSelected: boolean
isDragging?: boolean
dragHandleProps?: ButtonHTMLAttributes<HTMLButtonElement>
dragHandleRef?: (element: HTMLButtonElement | null) => void
onSelect: () => void
onDuplicate: (preset?: LevelDuplicatePreset) => void
onPaste?: () => void
onRequestDelete: () => void
})
| 123 | // ── Level row with three-dot menu ─────────────────────────────────────────── |
| 124 | |
| 125 | function LevelRow({ |
| 126 | level, |
| 127 | isSelected, |
| 128 | isDragging, |
| 129 | dragHandleProps, |
| 130 | dragHandleRef, |
| 131 | onSelect, |
| 132 | onDuplicate, |
| 133 | onPaste, |
| 134 | onRequestDelete, |
| 135 | }: { |
| 136 | level: LevelNode |
| 137 | isSelected: boolean |
| 138 | isDragging?: boolean |
| 139 | dragHandleProps?: ButtonHTMLAttributes<HTMLButtonElement> |
| 140 | dragHandleRef?: (element: HTMLButtonElement | null) => void |
| 141 | onSelect: () => void |
| 142 | onDuplicate: (preset?: LevelDuplicatePreset) => void |
| 143 | onPaste?: () => void |
| 144 | onRequestDelete: () => void |
| 145 | }) { |
| 146 | const [duplicateDialogOpen, setDuplicateDialogOpen] = useState(false) |
| 147 | const [isEditing, setIsEditing] = useState(false) |
| 148 | |
| 149 | return ( |
| 150 | <div className="group/level"> |
| 151 | {isEditing ? ( |
| 152 | <LevelInlineRename |
| 153 | isEditing={isEditing} |
| 154 | level={level} |
| 155 | onStopEditing={() => setIsEditing(false)} |
| 156 | /> |
| 157 | ) : ( |
| 158 | <div |
| 159 | className={cn( |
| 160 | 'flex items-center rounded-lg transition-colors', |
| 161 | isDragging && 'bg-white/10 text-foreground shadow-lg', |
| 162 | isSelected |
| 163 | ? 'bg-white/10 text-foreground' |
| 164 | : 'text-muted-foreground/70 hover:bg-white/5 hover:text-muted-foreground', |
| 165 | )} |
| 166 | > |
| 167 | <button |
| 168 | {...dragHandleProps} |
| 169 | aria-label={`Reorder ${getLevelDisplayName(level)}`} |
| 170 | className={cn( |
| 171 | 'ml-0.5 flex h-6 w-4 shrink-0 cursor-grab touch-none items-center justify-center rounded-md text-muted-foreground/35 opacity-0 transition-colors hover:bg-white/5 hover:text-foreground focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary/50 group-hover/level:opacity-100', |
| 172 | isDragging && 'cursor-grabbing opacity-100', |
| 173 | )} |
| 174 | onClick={(e) => { |
| 175 | e.stopPropagation() |
| 176 | dragHandleProps?.onClick?.(e) |
| 177 | }} |
| 178 | ref={dragHandleRef} |
| 179 | title="Drag to reorder" |
| 180 | type="button" |
| 181 | > |
| 182 | <GripVertical className="h-3.5 w-3.5" /> |
nothing calls this directly
no test coverage detected
searching dependent graphs…