|
1 | 1 | import { useCallback, useEffect, useMemo, useRef, useState } from 'react' |
2 | | -import { ChevronsUpDown, Plus } from 'lucide-react' |
| 2 | +import { ChevronDown, ChevronsUpDown, ChevronUp, Plus } from 'lucide-react' |
3 | 3 | import { Button, Popover, PopoverContent, PopoverItem, PopoverTrigger } from '@/components/emcn' |
4 | 4 | import { Trash } from '@/components/emcn/icons/trash' |
5 | 5 | import { cn } from '@/lib/utils' |
@@ -164,6 +164,40 @@ export function MessagesInput({ |
164 | 164 | [localMessages, setMessages, isPreview, disabled] |
165 | 165 | ) |
166 | 166 |
|
| 167 | + /** |
| 168 | + * Moves a message up in the list |
| 169 | + */ |
| 170 | + const moveMessageUp = useCallback( |
| 171 | + (index: number) => { |
| 172 | + if (isPreview || disabled || index === 0) return |
| 173 | + |
| 174 | + const newMessages = [...localMessages] |
| 175 | + const temp = newMessages[index] |
| 176 | + newMessages[index] = newMessages[index - 1] |
| 177 | + newMessages[index - 1] = temp |
| 178 | + setLocalMessages(newMessages) |
| 179 | + setMessages(newMessages) |
| 180 | + }, |
| 181 | + [localMessages, setMessages, isPreview, disabled] |
| 182 | + ) |
| 183 | + |
| 184 | + /** |
| 185 | + * Moves a message down in the list |
| 186 | + */ |
| 187 | + const moveMessageDown = useCallback( |
| 188 | + (index: number) => { |
| 189 | + if (isPreview || disabled || index === localMessages.length - 1) return |
| 190 | + |
| 191 | + const newMessages = [...localMessages] |
| 192 | + const temp = newMessages[index] |
| 193 | + newMessages[index] = newMessages[index + 1] |
| 194 | + newMessages[index + 1] = temp |
| 195 | + setLocalMessages(newMessages) |
| 196 | + setMessages(newMessages) |
| 197 | + }, |
| 198 | + [localMessages, setMessages, isPreview, disabled] |
| 199 | + ) |
| 200 | + |
167 | 201 | /** |
168 | 202 | * Capitalizes the first letter of the role |
169 | 203 | */ |
@@ -358,18 +392,44 @@ export function MessagesInput({ |
358 | 392 | {!isPreview && !disabled && ( |
359 | 393 | <div className='flex items-center'> |
360 | 394 | {currentMessages.length > 1 && ( |
361 | | - <Button |
362 | | - variant='ghost' |
363 | | - onClick={(e: React.MouseEvent) => { |
364 | | - e.stopPropagation() |
365 | | - deleteMessage(index) |
366 | | - }} |
367 | | - disabled={disabled} |
368 | | - className='-my-1 -mr-1 h-6 w-6 p-0' |
369 | | - aria-label='Delete message' |
370 | | - > |
371 | | - <Trash className='h-3 w-3' /> |
372 | | - </Button> |
| 395 | + <> |
| 396 | + <Button |
| 397 | + variant='ghost' |
| 398 | + onClick={(e: React.MouseEvent) => { |
| 399 | + e.stopPropagation() |
| 400 | + deleteMessage(index) |
| 401 | + }} |
| 402 | + disabled={disabled} |
| 403 | + className='-my-1 -mr-1 h-6 w-6 p-0' |
| 404 | + aria-label='Delete message' |
| 405 | + > |
| 406 | + <Trash className='h-3 w-3' /> |
| 407 | + </Button> |
| 408 | + <Button |
| 409 | + variant='ghost' |
| 410 | + onClick={(e: React.MouseEvent) => { |
| 411 | + e.stopPropagation() |
| 412 | + moveMessageUp(index) |
| 413 | + }} |
| 414 | + disabled={disabled || index === 0} |
| 415 | + className='-my-1 -mr-1 h-6 w-6 p-0' |
| 416 | + aria-label='Move message up' |
| 417 | + > |
| 418 | + <ChevronUp className='h-3 w-3' /> |
| 419 | + </Button> |
| 420 | + <Button |
| 421 | + variant='ghost' |
| 422 | + onClick={(e: React.MouseEvent) => { |
| 423 | + e.stopPropagation() |
| 424 | + moveMessageDown(index) |
| 425 | + }} |
| 426 | + disabled={disabled || index === currentMessages.length - 1} |
| 427 | + className='-my-1 -mr-1 h-6 w-6 p-0' |
| 428 | + aria-label='Move message down' |
| 429 | + > |
| 430 | + <ChevronDown className='h-3 w-3' /> |
| 431 | + </Button> |
| 432 | + </> |
373 | 433 | )} |
374 | 434 | <Button |
375 | 435 | variant='ghost' |
|
0 commit comments