1<script lang="ts">
2 import { Edit, Copy, RefreshCw, Trash2, ArrowRight } from '@lucide/svelte';
3 import {
4 ActionButton,
5 ChatMessageBranchingControls,
6 DialogConfirmation
7 } from '$lib/components/app';
8
9 interface Props {
10 role: 'user' | 'assistant';
11 justify: 'start' | 'end';
12 actionsPosition: 'left' | 'right';
13 siblingInfo?: ChatMessageSiblingInfo | null;
14 showDeleteDialog: boolean;
15 deletionInfo: {
16 totalCount: number;
17 userMessages: number;
18 assistantMessages: number;
19 messageTypes: string[];
20 } | null;
21 onCopy: () => void;
22 onEdit?: () => void;
23 onRegenerate?: () => void;
24 onContinue?: () => void;
25 onDelete: () => void;
26 onConfirmDelete: () => void;
27 onNavigateToSibling?: (siblingId: string) => void;
28 onShowDeleteDialogChange: (show: boolean) => void;
29 }
30
31 let {
32 actionsPosition,
33 deletionInfo,
34 justify,
35 onCopy,
36 onEdit,
37 onConfirmDelete,
38 onContinue,
39 onDelete,
40 onNavigateToSibling,
41 onShowDeleteDialogChange,
42 onRegenerate,
43 role,
44 siblingInfo = null,
45 showDeleteDialog
46 }: Props = $props();
47
48 function handleConfirmDelete() {
49 onConfirmDelete();
50 onShowDeleteDialogChange(false);
51 }
52</script>
53
54<div class="relative {justify === 'start' ? 'mt-2' : ''} flex h-6 items-center justify-{justify}">
55 <div
56 class="absolute top-0 {actionsPosition === 'left'
57 ? 'left-0'
58 : 'right-0'} flex items-center gap-2 opacity-100 transition-opacity"
59 >
60 {#if siblingInfo && siblingInfo.totalSiblings > 1}
61 <ChatMessageBranchingControls {siblingInfo} {onNavigateToSibling} />
62 {/if}
63
64 <div
65 class="pointer-events-auto inset-0 flex items-center gap-1 opacity-100 transition-all duration-150"
66 >
67 <ActionButton icon={Copy} tooltip="Copy" onclick={onCopy} />
68
69 {#if onEdit}
70 <ActionButton icon={Edit} tooltip="Edit" onclick={onEdit} />
71 {/if}
72
73 {#if role === 'assistant' && onRegenerate}
74 <ActionButton icon={RefreshCw} tooltip="Regenerate" onclick={() => onRegenerate()} />
75 {/if}
76
77 {#if role === 'assistant' && onContinue}
78 <ActionButton icon={ArrowRight} tooltip="Continue" onclick={onContinue} />
79 {/if}
80
81 <ActionButton icon={Trash2} tooltip="Delete" onclick={onDelete} />
82 </div>
83 </div>
84</div>
85
86<DialogConfirmation
87 bind:open={showDeleteDialog}
88 title="Delete Message"
89 description={deletionInfo && deletionInfo.totalCount > 1
90 ? `This will delete ${deletionInfo.totalCount} messages including: ${deletionInfo.userMessages} user message${deletionInfo.userMessages > 1 ? 's' : ''} and ${deletionInfo.assistantMessages} assistant response${deletionInfo.assistantMessages > 1 ? 's' : ''}. All messages in this branch and their responses will be permanently removed. This action cannot be undone.`
91 : 'Are you sure you want to delete this message? This action cannot be undone.'}
92 confirmText={deletionInfo && deletionInfo.totalCount > 1
93 ? `Delete ${deletionInfo.totalCount} Messages`
94 : 'Delete'}
95 cancelText="Cancel"
96 variant="destructive"
97 icon={Trash2}
98 onConfirm={handleConfirmDelete}
99 onCancel={() => onShowDeleteDialogChange(false)}
100/>