|
15 | 15 | import WebSearchToggle from "../WebSearchToggle.svelte";
|
16 | 16 | import type { WebSearchMessage } from "$lib/types/WebSearch";
|
17 | 17 | import LoginModal from "../LoginModal.svelte";
|
| 18 | + import FileDropzone from "../FileDropzone.svelte"; |
18 | 19 |
|
19 | 20 | export let messages: Message[] = [];
|
20 | 21 | export let loading = false;
|
|
44 | 45 | dispatch("message", message);
|
45 | 46 | message = "";
|
46 | 47 | };
|
| 48 | +
|
| 49 | + let lastTarget: EventTarget | null = null; |
| 50 | + let onDrag = false; |
| 51 | +
|
| 52 | + const onDragEnter = (e: DragEvent) => { |
| 53 | + lastTarget = e.target; |
| 54 | + onDrag = true; |
| 55 | + }; |
| 56 | +
|
| 57 | + const onDragLeave = (e: DragEvent) => { |
| 58 | + if (e.target === lastTarget) { |
| 59 | + onDrag = false; |
| 60 | + } |
| 61 | + }; |
| 62 | +
|
| 63 | + const onDragOver = (e: DragEvent) => { |
| 64 | + e.preventDefault(); |
| 65 | + }; |
47 | 66 | </script>
|
48 | 67 |
|
49 | 68 | <div class="relative min-h-0 min-w-0">
|
|
69 | 88 | />
|
70 | 89 | <div
|
71 | 90 | class="dark:via-gray-80 pointer-events-none absolute inset-x-0 bottom-0 z-0 mx-auto flex w-full max-w-3xl flex-col items-center justify-center bg-gradient-to-t from-white via-white/80 to-white/0 px-3.5 py-4 dark:border-gray-800 dark:from-gray-900 dark:to-gray-900/0 max-md:border-t max-md:bg-white max-md:dark:bg-gray-900 sm:px-5 md:py-8 xl:max-w-4xl [&>*]:pointer-events-auto"
|
| 91 | + on:dragover={onDragOver} |
| 92 | + on:dragenter={onDragEnter} |
| 93 | + on:dragleave={onDragLeave} |
72 | 94 | >
|
73 |
| - <div class="flex w-full pb-3 max-md:justify-between"> |
74 |
| - {#if settings?.searchEnabled} |
75 |
| - <WebSearchToggle /> |
76 |
| - {/if} |
77 |
| - {#if loading} |
78 |
| - <StopGeneratingBtn |
79 |
| - classNames={settings?.searchEnabled ? "md:-translate-x-1/2 md:mx-auto" : "mx-auto"} |
80 |
| - on:click={() => dispatch("stop")} |
81 |
| - /> |
82 |
| - {/if} |
83 |
| - </div> |
84 |
| - <form |
85 |
| - on:submit|preventDefault={handleSubmit} |
86 |
| - class="relative flex w-full max-w-4xl flex-1 items-center rounded-xl border bg-gray-100 focus-within:border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:focus-within:border-gray-500 |
87 |
| - {isReadOnly ? 'opacity-30' : ''}" |
88 |
| - > |
89 |
| - <div class="flex w-full flex-1 border-none bg-transparent"> |
90 |
| - <ChatInput |
91 |
| - placeholder="Ask anything" |
92 |
| - bind:value={message} |
93 |
| - on:submit={handleSubmit} |
94 |
| - on:keypress={() => { |
95 |
| - if (loginRequired) loginModalOpen = true; |
96 |
| - }} |
97 |
| - maxRows={4} |
98 |
| - disabled={isReadOnly} |
99 |
| - /> |
100 |
| - |
| 95 | + {#if onDrag} |
| 96 | + <FileDropzone bind:value={message} bind:onDrag /> |
| 97 | + {:else} |
| 98 | + <div class="flex w-full pb-3 max-md:justify-between"> |
| 99 | + {#if settings?.searchEnabled} |
| 100 | + <WebSearchToggle /> |
| 101 | + {/if} |
101 | 102 | {#if loading}
|
102 |
| - <button |
103 |
| - class="btn mx-1 my-1 inline-block h-[2.4rem] self-end rounded-lg bg-transparent p-1 px-[0.7rem] text-gray-400 disabled:opacity-60 enabled:hover:text-gray-700 dark:disabled:opacity-40 enabled:dark:hover:text-gray-100 md:hidden" |
| 103 | + <StopGeneratingBtn |
| 104 | + classNames={settings?.searchEnabled ? "md:-translate-x-1/2 md:mx-auto" : "mx-auto"} |
104 | 105 | on:click={() => dispatch("stop")}
|
105 |
| - > |
106 |
| - <CarbonStopFilledAlt /> |
107 |
| - </button> |
108 |
| - <div |
109 |
| - class="mx-1 my-1 hidden h-[2.4rem] items-center p-1 px-[0.7rem] text-gray-400 disabled:opacity-60 enabled:hover:text-gray-700 dark:disabled:opacity-40 enabled:dark:hover:text-gray-100 md:flex" |
110 |
| - > |
111 |
| - <EosIconsLoading /> |
112 |
| - </div> |
113 |
| - {:else} |
| 106 | + /> |
| 107 | + {/if} |
| 108 | + </div> |
| 109 | + <form |
| 110 | + on:submit|preventDefault={handleSubmit} |
| 111 | + class="relative flex w-full max-w-4xl flex-1 items-center rounded-xl border bg-gray-100 focus-within:border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:focus-within:border-gray-500 |
| 112 | + {isReadOnly ? 'opacity-30' : ''}" |
| 113 | + > |
| 114 | + <div class="flex w-full flex-1 border-none bg-transparent"> |
| 115 | + <ChatInput |
| 116 | + placeholder="Ask anything" |
| 117 | + bind:value={message} |
| 118 | + on:submit={handleSubmit} |
| 119 | + on:keypress={() => { |
| 120 | + if (loginRequired) loginModalOpen = true; |
| 121 | + }} |
| 122 | + maxRows={4} |
| 123 | + disabled={isReadOnly} |
| 124 | + /> |
| 125 | + |
| 126 | + {#if loading} |
| 127 | + <button |
| 128 | + class="btn mx-1 my-1 inline-block h-[2.4rem] self-end rounded-lg bg-transparent p-1 px-[0.7rem] text-gray-400 enabled:hover:text-gray-700 disabled:opacity-60 enabled:dark:hover:text-gray-100 dark:disabled:opacity-40 md:hidden" |
| 129 | + on:click={() => dispatch("stop")} |
| 130 | + > |
| 131 | + <CarbonStopFilledAlt /> |
| 132 | + </button> |
| 133 | + <div |
| 134 | + class="mx-1 my-1 hidden h-[2.4rem] items-center p-1 px-[0.7rem] text-gray-400 enabled:hover:text-gray-700 disabled:opacity-60 enabled:dark:hover:text-gray-100 dark:disabled:opacity-40 md:flex" |
| 135 | + > |
| 136 | + <EosIconsLoading /> |
| 137 | + </div> |
| 138 | + {:else} |
| 139 | + <button |
| 140 | + class="btn mx-1 my-1 h-[2.4rem] self-end rounded-lg bg-transparent p-1 px-[0.7rem] text-gray-400 enabled:hover:text-gray-700 disabled:opacity-60 enabled:dark:hover:text-gray-100 dark:disabled:opacity-40" |
| 141 | + disabled={!message || isReadOnly} |
| 142 | + type="submit" |
| 143 | + > |
| 144 | + <CarbonSendAltFilled /> |
| 145 | + </button> |
| 146 | + {/if} |
| 147 | + </div> |
| 148 | + </form> |
| 149 | + <div |
| 150 | + class="mt-2 flex justify-between self-stretch px-1 text-xs text-gray-400/90 max-sm:gap-2" |
| 151 | + > |
| 152 | + <p> |
| 153 | + Model: <a |
| 154 | + href={currentModel.modelUrl || "https://huggingface.co/" + currentModel.name} |
| 155 | + target="_blank" |
| 156 | + rel="noreferrer" |
| 157 | + class="hover:underline">{currentModel.displayName}</a |
| 158 | + > <span class="max-sm:hidden">·</span><br class="sm:hidden" /> Generated content may be inaccurate |
| 159 | + or false. |
| 160 | + </p> |
| 161 | + {#if messages.length} |
114 | 162 | <button
|
115 |
| - class="btn mx-1 my-1 h-[2.4rem] self-end rounded-lg bg-transparent p-1 px-[0.7rem] text-gray-400 disabled:opacity-60 enabled:hover:text-gray-700 dark:disabled:opacity-40 enabled:dark:hover:text-gray-100" |
116 |
| - disabled={!message || isReadOnly} |
117 |
| - type="submit" |
| 163 | + class="flex flex-none items-center hover:text-gray-400 hover:underline max-sm:rounded-lg max-sm:bg-gray-50 max-sm:px-2.5 dark:max-sm:bg-gray-800" |
| 164 | + type="button" |
| 165 | + on:click={() => dispatch("share")} |
118 | 166 | >
|
119 |
| - <CarbonSendAltFilled /> |
| 167 | + <CarbonExport class="text-[.6rem] sm:mr-1.5 sm:text-primary-500" /> |
| 168 | + <div class="max-sm:hidden">Share this conversation</div> |
120 | 169 | </button>
|
121 | 170 | {/if}
|
122 | 171 | </div>
|
123 |
| - </form> |
124 |
| - <div class="mt-2 flex justify-between self-stretch px-1 text-xs text-gray-400/90 max-sm:gap-2"> |
125 |
| - <p> |
126 |
| - Model: <a |
127 |
| - href={currentModel.modelUrl || "https://huggingface.co/" + currentModel.name} |
128 |
| - target="_blank" |
129 |
| - rel="noreferrer" |
130 |
| - class="hover:underline">{currentModel.displayName}</a |
131 |
| - > <span class="max-sm:hidden">·</span><br class="sm:hidden" /> Generated content may be inaccurate |
132 |
| - or false. |
133 |
| - </p> |
134 |
| - {#if messages.length} |
135 |
| - <button |
136 |
| - class="flex flex-none items-center hover:text-gray-400 hover:underline max-sm:rounded-lg max-sm:bg-gray-50 max-sm:px-2.5 dark:max-sm:bg-gray-800" |
137 |
| - type="button" |
138 |
| - on:click={() => dispatch("share")} |
139 |
| - > |
140 |
| - <CarbonExport class="text-[.6rem] sm:mr-1.5 sm:text-primary-500" /> |
141 |
| - <div class="max-sm:hidden">Share this conversation</div> |
142 |
| - </button> |
143 |
| - {/if} |
144 |
| - </div> |
| 172 | + {/if} |
145 | 173 | </div>
|
146 | 174 | </div>
|
0 commit comments