Thomas G. Lopes commited on
Commit
6b57de3
·
1 Parent(s): c1646a5

img preview

Browse files
src/lib/components/inference-playground/img-preview.svelte ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import { clickOutside } from "$lib/actions/click-outside.js";
3
+ import { fade, scale } from "svelte/transition";
4
+ import IconCross from "~icons/carbon/close";
5
+
6
+ interface Props {
7
+ img?: string;
8
+ }
9
+
10
+ let { img = $bindable() }: Props = $props();
11
+
12
+ let dialog: HTMLDialogElement | undefined = $state();
13
+
14
+ $effect(() => {
15
+ if (img) {
16
+ dialog?.showModal();
17
+ } else {
18
+ setTimeout(() => dialog?.close(), 250);
19
+ }
20
+ });
21
+ </script>
22
+
23
+ <dialog
24
+ class="backdrop:bg-transparent"
25
+ bind:this={dialog}
26
+ onclose={e => {
27
+ e.preventDefault();
28
+ img = undefined;
29
+ }}
30
+ >
31
+ {#if img}
32
+ <!-- Backdrop -->
33
+ <div
34
+ class="fixed inset-0 z-50 flex items-center justify-center overflow-hidden bg-black/50 backdrop-blur-sm"
35
+ transition:fade={{ duration: 150 }}
36
+ >
37
+ <!-- Content -->
38
+ <div
39
+ class="relative w-lg rounded-xl bg-white shadow-sm dark:bg-gray-900"
40
+ use:clickOutside={() => (img = undefined)}
41
+ transition:scale={{ start: 0.975, duration: 250 }}
42
+ >
43
+ <img src={img} alt="" />
44
+ </div>
45
+
46
+ <button
47
+ type="button"
48
+ class="absolute top-3 right-3 inline-flex h-8 w-8 items-center justify-center rounded-lg bg-transparent text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900 dark:hover:bg-gray-600 dark:hover:text-white"
49
+ onclick={() => (img = undefined)}
50
+ aria-label="Close modal"
51
+ >
52
+ <div class="text-xl">
53
+ <IconCross />
54
+ </div>
55
+ </button>
56
+ </div>
57
+ {/if}
58
+ </dialog>
src/lib/components/inference-playground/message.svelte CHANGED
@@ -6,6 +6,8 @@
6
  import { FileUpload } from "melt/builders";
7
  import { fade } from "svelte/transition";
8
  import IconImage from "~icons/carbon/image-reference";
 
 
9
 
10
  type Props = {
11
  conversation: Conversation;
@@ -41,6 +43,8 @@
41
  },
42
  disabled: () => !canUploadImgs,
43
  });
 
 
44
  </script>
45
 
46
  <div
@@ -119,16 +123,28 @@
119
  </Tooltip>
120
  </div>
121
  </div>
 
122
  {#if message.images?.length}
123
  <div class="mt-2">
124
  <div class="flex items-center gap-2">
125
  {#each message.images as img (img)}
126
  <div class="group/img relative">
 
 
 
 
 
 
 
127
  <img src={img} alt="uploaded" class="size-12 rounded-lg object-cover" />
128
  <button
 
129
  type="button"
130
- onclick={() => (message.images = message.images?.filter(i => i !== img))}
131
- class="invisible absolute -top-1 -right-1 grid size-5 place-items-center rounded-full bg-gray-800 text-xs text-white group-hover/img:visible hover:bg-gray-700"
 
 
 
132
  >
133
 
134
  </button>
@@ -138,3 +154,5 @@
138
  </div>
139
  {/if}
140
  </div>
 
 
 
6
  import { FileUpload } from "melt/builders";
7
  import { fade } from "svelte/transition";
8
  import IconImage from "~icons/carbon/image-reference";
9
+ import IconMaximize from "~icons/carbon/maximize";
10
+ import ImgPreview from "./img-preview.svelte";
11
 
12
  type Props = {
13
  conversation: Conversation;
 
43
  },
44
  disabled: () => !canUploadImgs,
45
  });
46
+
47
+ let previewImg = $state<string>();
48
  </script>
49
 
50
  <div
 
123
  </Tooltip>
124
  </div>
125
  </div>
126
+
127
  {#if message.images?.length}
128
  <div class="mt-2">
129
  <div class="flex items-center gap-2">
130
  {#each message.images as img (img)}
131
  <div class="group/img relative">
132
+ <button
133
+ aria-label="expand"
134
+ class="absolute inset-0 z-10 grid place-items-center bg-gray-800/70 opacity-0 group-hover/img:opacity-100"
135
+ onclick={() => (previewImg = img)}
136
+ >
137
+ <IconMaximize />
138
+ </button>
139
  <img src={img} alt="uploaded" class="size-12 rounded-lg object-cover" />
140
  <button
141
+ aria-label="remove"
142
  type="button"
143
+ onclick={e => {
144
+ e.stopPropagation();
145
+ message.images = message.images?.filter(i => i !== img);
146
+ }}
147
+ class="invisible absolute -top-1 -right-1 z-20 grid size-5 place-items-center rounded-full bg-gray-800 text-xs text-white group-hover/img:visible hover:bg-gray-700"
148
  >
149
 
150
  </button>
 
154
  </div>
155
  {/if}
156
  </div>
157
+
158
+ <ImgPreview bind:img={previewImg} />