Thomas G. Lopes commited on
Commit
15cf6e6
·
1 Parent(s): 2028168

improve zooming

Browse files
src/lib/components/inference-playground/generation-config.svelte CHANGED
@@ -1,6 +1,7 @@
1
  <script lang="ts">
 
2
  import type { ConversationClass } from "$lib/state/conversations.svelte.js";
3
- import { settings } from "$lib/state/settings.svelte.js";
4
  import { maxAllowedTokens } from "$lib/utils/business.svelte.js";
5
  import { cn } from "$lib/utils/cn.js";
6
  import { isNumber } from "$lib/utils/is.js";
@@ -10,10 +11,6 @@
10
  import { GENERATION_CONFIG_KEYS, GENERATION_CONFIG_SETTINGS } from "./generation-config-settings.js";
11
  import MCPModal from "./mcp-modal.svelte";
12
  import StructuredOutputModal, { openStructuredOutputModal } from "./structured-output-modal.svelte";
13
- import { mcpServers } from "$lib/state/mcps.svelte.js";
14
- import { isMcpEnabled } from "$lib/constants.js";
15
- import IconMinus from "~icons/carbon/subtract";
16
- import IconPlus from "~icons/carbon/add-large";
17
 
18
  interface Props {
19
  conversation: ConversationClass;
@@ -170,36 +167,6 @@
170
  class="peer relative h-5 w-9 rounded-full bg-gray-200 peer-checked:bg-black peer-focus:outline-hidden after:absolute after:start-[2px] after:top-[2px] after:h-4 after:w-4 after:rounded-full after:border after:border-gray-300 after:bg-white after:transition-all after:content-[''] peer-checked:after:translate-x-full peer-checked:after:border-white dark:border-gray-600 dark:bg-gray-700 dark:peer-checked:bg-blue-600"
171
  ></div>
172
  </label>
173
-
174
- <!-- Text Size Setting -->
175
- <div class="mt-4 flex items-center justify-between">
176
- <span class="text-sm font-medium text-gray-900 dark:text-gray-300">Text Size</span>
177
- <div class="flex items-center gap-2">
178
- <button
179
- type="button"
180
- onclick={() => {
181
- if (settings.textSize > 50) {
182
- settings.textSize = settings.textSize - 10;
183
- }
184
- }}
185
- class="btn-mini aspect-square"
186
- >
187
- <IconMinus />
188
- </button>
189
- <span class="text-sm">{settings.textSize}%</span>
190
- <button
191
- type="button"
192
- onclick={() => {
193
- if (settings.textSize < 200) {
194
- settings.textSize = settings.textSize + 10;
195
- }
196
- }}
197
- class="btn-mini aspect-square"
198
- >
199
- <IconPlus />
200
- </button>
201
- </div>
202
- </div>
203
  </div>
204
 
205
  <StructuredOutputModal {conversation} />
 
1
  <script lang="ts">
2
+ import { isMcpEnabled } from "$lib/constants.js";
3
  import type { ConversationClass } from "$lib/state/conversations.svelte.js";
4
+ import { mcpServers } from "$lib/state/mcps.svelte.js";
5
  import { maxAllowedTokens } from "$lib/utils/business.svelte.js";
6
  import { cn } from "$lib/utils/cn.js";
7
  import { isNumber } from "$lib/utils/is.js";
 
11
  import { GENERATION_CONFIG_KEYS, GENERATION_CONFIG_SETTINGS } from "./generation-config-settings.js";
12
  import MCPModal from "./mcp-modal.svelte";
13
  import StructuredOutputModal, { openStructuredOutputModal } from "./structured-output-modal.svelte";
 
 
 
 
14
 
15
  interface Props {
16
  conversation: ConversationClass;
 
167
  class="peer relative h-5 w-9 rounded-full bg-gray-200 peer-checked:bg-black peer-focus:outline-hidden after:absolute after:start-[2px] after:top-[2px] after:h-4 after:w-4 after:rounded-full after:border after:border-gray-300 after:bg-white after:transition-all after:content-[''] peer-checked:after:translate-x-full peer-checked:after:border-white dark:border-gray-600 dark:bg-gray-700 dark:peer-checked:bg-blue-600"
168
  ></div>
169
  </label>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  </div>
171
 
172
  <StructuredOutputModal {conversation} />
src/lib/components/inference-playground/message-textarea.svelte CHANGED
@@ -4,7 +4,6 @@
4
  import { TextareaAutosize } from "$lib/spells/textarea-autosize.svelte.js";
5
  import { conversations } from "$lib/state/conversations.svelte";
6
  import { images } from "$lib/state/images.svelte";
7
- import { settings } from "$lib/state/settings.svelte.js";
8
  import type { ConversationMessage } from "$lib/types.js";
9
  import { fileToDataURL } from "$lib/utils/file.js";
10
  import { omit } from "$lib/utils/object.svelte";
@@ -15,8 +14,6 @@
15
  import IconMaximize from "~icons/carbon/maximize";
16
  import Tooltip from "../tooltip.svelte";
17
  import { previewImage } from "./img-preview.svelte";
18
- import { watch } from "runed";
19
- import { tick } from "svelte";
20
 
21
  const multiple = $derived(conversations.active.length > 1);
22
  const loading = $derived(conversations.generating);
@@ -95,17 +92,6 @@
95
  });
96
 
97
  const autosized = new TextareaAutosize();
98
-
99
- // Watch for text size changes and trigger resize
100
- watch(
101
- () => settings.textSize,
102
- () => {
103
- // Trigger resize on next tick to ensure styles are applied
104
- tick().then(() => {
105
- autosized.triggerResize();
106
- });
107
- },
108
- );
109
  </script>
110
 
111
  <svelte:window onkeydown={onKeydown} />
@@ -132,7 +118,6 @@
132
  bind:value={input}
133
  {@attach autosized.attachment}
134
  {@attach autofocus()}
135
- style="font-size: {settings.textSize}%"
136
  ></textarea>
137
  {#if canUploadImgs}
138
  <Tooltip openDelay={250}>
 
4
  import { TextareaAutosize } from "$lib/spells/textarea-autosize.svelte.js";
5
  import { conversations } from "$lib/state/conversations.svelte";
6
  import { images } from "$lib/state/images.svelte";
 
7
  import type { ConversationMessage } from "$lib/types.js";
8
  import { fileToDataURL } from "$lib/utils/file.js";
9
  import { omit } from "$lib/utils/object.svelte";
 
14
  import IconMaximize from "~icons/carbon/maximize";
15
  import Tooltip from "../tooltip.svelte";
16
  import { previewImage } from "./img-preview.svelte";
 
 
17
 
18
  const multiple = $derived(conversations.active.length > 1);
19
  const loading = $derived(conversations.generating);
 
92
  });
93
 
94
  const autosized = new TextareaAutosize();
 
 
 
 
 
 
 
 
 
 
 
95
  </script>
96
 
97
  <svelte:window onkeydown={onKeydown} />
 
118
  bind:value={input}
119
  {@attach autosized.attachment}
120
  {@attach autofocus()}
 
121
  ></textarea>
122
  {#if canUploadImgs}
123
  <Tooltip openDelay={250}>
src/lib/components/inference-playground/message.svelte CHANGED
@@ -1,33 +1,30 @@
1
  <script lang="ts">
 
 
2
  import Tooltip from "$lib/components/tooltip.svelte";
3
  import { TEST_IDS } from "$lib/constants.js";
4
  import { TextareaAutosize } from "$lib/spells/textarea-autosize.svelte.js";
5
  import { type ConversationClass } from "$lib/state/conversations.svelte.js";
6
  import { images } from "$lib/state/images.svelte";
7
- import { settings } from "$lib/state/settings.svelte.js";
8
  import { type ConversationMessage } from "$lib/types.js";
9
  import { copyToClipboard } from "$lib/utils/copy.js";
10
  import { cmdOrCtrl } from "$lib/utils/platform.js";
11
  import { AsyncQueue } from "$lib/utils/queue.js";
12
- import { clickOutside } from "$lib/attachments/click-outside.js";
 
13
  import { FileUpload } from "melt/builders";
14
  import { fade } from "svelte/transition";
15
- import { watch } from "runed";
16
- import { tick } from "svelte";
17
  import IconCopy from "~icons/carbon/copy";
 
18
  import IconImage from "~icons/carbon/image-reference";
19
  import IconMaximize from "~icons/carbon/maximize";
20
- import IconEdit from "~icons/carbon/edit";
21
  import IconCustom from "../icon-custom.svelte";
22
  import LocalToasts from "../local-toasts.svelte";
23
  import { previewImage } from "./img-preview.svelte";
24
- import { marked } from "marked";
25
- import { parseThinkingTokens } from "$lib/utils/thinking.js";
26
- import IconChevronDown from "~icons/carbon/chevron-down";
27
- import IconChevronRight from "~icons/carbon/chevron-right";
28
- import ArrowSplitRounded from "~icons/material-symbols/arrow-split-rounded";
29
- import { addToast } from "$lib/components/toaster.svelte.js";
30
- import { projects } from "$lib/state/projects.svelte";
31
 
32
  type Props = {
33
  conversation: ConversationClass;
@@ -94,18 +91,6 @@
94
  }
95
  return marked(parsedMessage.thinking);
96
  });
97
-
98
- // Watch for text size changes and trigger resize
99
- watch(
100
- () => settings.textSize,
101
- () => {
102
- // Trigger resize on next tick to ensure styles are applied
103
- tick().then(() => {
104
- autosized.triggerResize();
105
- reasoningAutosized.triggerResize();
106
- });
107
- },
108
- );
109
  </script>
110
 
111
  <div
@@ -157,7 +142,6 @@
157
  {#if conversation.data.parseMarkdown && !isEditing}
158
  <div
159
  class="relative w-full max-w-none rounded-lg bg-transparent px-2 py-2.5 ring-gray-100 outline-none group-hover/message:ring-3 hover:bg-white @2xl:px-3 dark:ring-gray-600 dark:hover:bg-gray-900"
160
- style="font-size: {settings.textSize}%"
161
  >
162
  <div class="prose prose-sm dark:prose-invert">
163
  {@html parsedReasoning}
@@ -187,7 +171,6 @@
187
  class="w-full resize-none overflow-hidden rounded-lg bg-transparent px-2 py-2.5 ring-gray-100 outline-none group-hover/message:ring-3 hover:bg-white focus:bg-white focus:ring-3 @2xl:px-3 dark:ring-gray-600 dark:hover:bg-gray-900 dark:focus:bg-gray-900"
188
  rows="1"
189
  {@attach reasoningAutosized.attachment}
190
- style="font-size: {settings.textSize}%"
191
  ></textarea>
192
  {/if}
193
  {/if}
@@ -201,7 +184,6 @@
201
  data-message
202
  data-test-id={TEST_IDS.message}
203
  {@attach clickOutside(() => (isEditing = false))}
204
- style="font-size: {settings.textSize}%"
205
  >
206
  <Tooltip>
207
  {#snippet trigger(tooltip)}
@@ -246,7 +228,6 @@
246
  class="w-full resize-none overflow-hidden border-none bg-transparent outline-none"
247
  rows="1"
248
  {@attach autosized.attachment}
249
- style="font-size: {settings.textSize}%"
250
  ></textarea>
251
  {/if}
252
  </div>
@@ -276,7 +257,6 @@
276
  data-message
277
  data-test-id={TEST_IDS.message}
278
  {@attach autosized.attachment}
279
- style="font-size: {settings.textSize}%"
280
  ></textarea>
281
  {/if}
282
  </div>
 
1
  <script lang="ts">
2
+ import { clickOutside } from "$lib/attachments/click-outside.js";
3
+ import { addToast } from "$lib/components/toaster.svelte.js";
4
  import Tooltip from "$lib/components/tooltip.svelte";
5
  import { TEST_IDS } from "$lib/constants.js";
6
  import { TextareaAutosize } from "$lib/spells/textarea-autosize.svelte.js";
7
  import { type ConversationClass } from "$lib/state/conversations.svelte.js";
8
  import { images } from "$lib/state/images.svelte";
9
+ import { projects } from "$lib/state/projects.svelte";
10
  import { type ConversationMessage } from "$lib/types.js";
11
  import { copyToClipboard } from "$lib/utils/copy.js";
12
  import { cmdOrCtrl } from "$lib/utils/platform.js";
13
  import { AsyncQueue } from "$lib/utils/queue.js";
14
+ import { parseThinkingTokens } from "$lib/utils/thinking.js";
15
+ import { marked } from "marked";
16
  import { FileUpload } from "melt/builders";
17
  import { fade } from "svelte/transition";
18
+ import IconChevronDown from "~icons/carbon/chevron-down";
19
+ import IconChevronRight from "~icons/carbon/chevron-right";
20
  import IconCopy from "~icons/carbon/copy";
21
+ import IconEdit from "~icons/carbon/edit";
22
  import IconImage from "~icons/carbon/image-reference";
23
  import IconMaximize from "~icons/carbon/maximize";
24
+ import ArrowSplitRounded from "~icons/material-symbols/arrow-split-rounded";
25
  import IconCustom from "../icon-custom.svelte";
26
  import LocalToasts from "../local-toasts.svelte";
27
  import { previewImage } from "./img-preview.svelte";
 
 
 
 
 
 
 
28
 
29
  type Props = {
30
  conversation: ConversationClass;
 
91
  }
92
  return marked(parsedMessage.thinking);
93
  });
 
 
 
 
 
 
 
 
 
 
 
 
94
  </script>
95
 
96
  <div
 
142
  {#if conversation.data.parseMarkdown && !isEditing}
143
  <div
144
  class="relative w-full max-w-none rounded-lg bg-transparent px-2 py-2.5 ring-gray-100 outline-none group-hover/message:ring-3 hover:bg-white @2xl:px-3 dark:ring-gray-600 dark:hover:bg-gray-900"
 
145
  >
146
  <div class="prose prose-sm dark:prose-invert">
147
  {@html parsedReasoning}
 
171
  class="w-full resize-none overflow-hidden rounded-lg bg-transparent px-2 py-2.5 ring-gray-100 outline-none group-hover/message:ring-3 hover:bg-white focus:bg-white focus:ring-3 @2xl:px-3 dark:ring-gray-600 dark:hover:bg-gray-900 dark:focus:bg-gray-900"
172
  rows="1"
173
  {@attach reasoningAutosized.attachment}
 
174
  ></textarea>
175
  {/if}
176
  {/if}
 
184
  data-message
185
  data-test-id={TEST_IDS.message}
186
  {@attach clickOutside(() => (isEditing = false))}
 
187
  >
188
  <Tooltip>
189
  {#snippet trigger(tooltip)}
 
228
  class="w-full resize-none overflow-hidden border-none bg-transparent outline-none"
229
  rows="1"
230
  {@attach autosized.attachment}
 
231
  ></textarea>
232
  {/if}
233
  </div>
 
257
  data-message
258
  data-test-id={TEST_IDS.message}
259
  {@attach autosized.attachment}
 
260
  ></textarea>
261
  {/if}
262
  </div>
src/lib/components/inference-playground/playground.svelte CHANGED
@@ -1,36 +1,35 @@
1
  <script lang="ts">
2
  import { observe, observed, ObservedElements } from "$lib/attachments/observe.svelte.js";
 
3
  import { conversations } from "$lib/state/conversations.svelte";
4
  import { projects } from "$lib/state/projects.svelte";
5
- import { settings } from "$lib/state/settings.svelte.js";
6
  import { token } from "$lib/state/token.svelte.js";
7
  import { isHFModel } from "$lib/types.js";
8
  import { iterate } from "$lib/utils/array.js";
9
  import { isSystemPromptSupported } from "$lib/utils/business.svelte.js";
 
10
  import IconExternal from "~icons/carbon/arrow-up-right";
11
  import IconWaterfall from "~icons/carbon/chart-waterfall";
 
12
  import IconCode from "~icons/carbon/code";
13
  import IconCompare from "~icons/carbon/compare";
14
  import IconInfo from "~icons/carbon/information";
15
  import IconSettings from "~icons/carbon/settings";
16
  import IconShare from "~icons/carbon/share";
17
  import { default as IconDelete } from "~icons/carbon/trash-can";
 
18
  import { showShareModal } from "../share-modal.svelte";
19
  import Toaster from "../toaster.svelte";
20
  import Tooltip from "../tooltip.svelte";
 
21
  import PlaygroundConversationHeader from "./conversation-header.svelte";
22
  import PlaygroundConversation from "./conversation.svelte";
23
  import GenerationConfig from "./generation-config.svelte";
24
  import HFTokenModal from "./hf-token-modal.svelte";
 
25
  import ModelSelectorModal from "./model-selector-modal.svelte";
26
  import ModelSelector from "./model-selector.svelte";
27
  import ProjectSelect from "./project-select.svelte";
28
- import BillingModal from "./billing-modal.svelte";
29
- import BillingIndicator from "../billing-indicator.svelte";
30
- import { TEST_IDS } from "$lib/constants.js";
31
- import MessageTextarea from "./message-textarea.svelte";
32
- import { atLeastNDecimals } from "$lib/utils/number.js";
33
- import IconClose from "~icons/carbon/close";
34
 
35
  let viewCode = $state(false);
36
  let viewSettings = $state(false);
@@ -97,7 +96,6 @@
97
  projects.update({ ...projects.current, systemMessage: e.currentTarget.value });
98
  }}
99
  class="absolute inset-x-0 bottom-0 h-full resize-none bg-transparent px-3 pt-10 text-sm outline-hidden"
100
- style="font-size: {settings.textSize}%"
101
  ></textarea>
102
  </div>
103
  </div>
@@ -191,7 +189,7 @@
191
  {#if !compareActive}
192
  <div
193
  class={[
194
- "z-50 flex h-full flex-col p-3 max-md:fixed max-md:inset-0 max-md:backdrop-blur-lg ",
195
  !viewSettings && "max-md:hidden",
196
  ]}
197
  >
@@ -239,7 +237,7 @@
239
  <div class="flex items-center justify-end">
240
  <BillingIndicator showModal={() => (billingModalOpen = true)} />
241
  </div>
242
- <div class="flex items-center justify-end gap-4 whitespace-nowrap">
243
  <button
244
  onclick={() => projects.current && showShareModal(projects.current)}
245
  class="flex items-center gap-1 text-sm text-gray-500 underline decoration-gray-300 hover:text-gray-800 dark:text-gray-400 dark:decoration-gray-600 dark:hover:text-gray-200"
 
1
  <script lang="ts">
2
  import { observe, observed, ObservedElements } from "$lib/attachments/observe.svelte.js";
3
+ import { TEST_IDS } from "$lib/constants.js";
4
  import { conversations } from "$lib/state/conversations.svelte";
5
  import { projects } from "$lib/state/projects.svelte";
 
6
  import { token } from "$lib/state/token.svelte.js";
7
  import { isHFModel } from "$lib/types.js";
8
  import { iterate } from "$lib/utils/array.js";
9
  import { isSystemPromptSupported } from "$lib/utils/business.svelte.js";
10
+ import { atLeastNDecimals } from "$lib/utils/number.js";
11
  import IconExternal from "~icons/carbon/arrow-up-right";
12
  import IconWaterfall from "~icons/carbon/chart-waterfall";
13
+ import IconClose from "~icons/carbon/close";
14
  import IconCode from "~icons/carbon/code";
15
  import IconCompare from "~icons/carbon/compare";
16
  import IconInfo from "~icons/carbon/information";
17
  import IconSettings from "~icons/carbon/settings";
18
  import IconShare from "~icons/carbon/share";
19
  import { default as IconDelete } from "~icons/carbon/trash-can";
20
+ import BillingIndicator from "../billing-indicator.svelte";
21
  import { showShareModal } from "../share-modal.svelte";
22
  import Toaster from "../toaster.svelte";
23
  import Tooltip from "../tooltip.svelte";
24
+ import BillingModal from "./billing-modal.svelte";
25
  import PlaygroundConversationHeader from "./conversation-header.svelte";
26
  import PlaygroundConversation from "./conversation.svelte";
27
  import GenerationConfig from "./generation-config.svelte";
28
  import HFTokenModal from "./hf-token-modal.svelte";
29
+ import MessageTextarea from "./message-textarea.svelte";
30
  import ModelSelectorModal from "./model-selector-modal.svelte";
31
  import ModelSelector from "./model-selector.svelte";
32
  import ProjectSelect from "./project-select.svelte";
 
 
 
 
 
 
33
 
34
  let viewCode = $state(false);
35
  let viewSettings = $state(false);
 
96
  projects.update({ ...projects.current, systemMessage: e.currentTarget.value });
97
  }}
98
  class="absolute inset-x-0 bottom-0 h-full resize-none bg-transparent px-3 pt-10 text-sm outline-hidden"
 
99
  ></textarea>
100
  </div>
101
  </div>
 
189
  {#if !compareActive}
190
  <div
191
  class={[
192
+ "z-50 flex h-full flex-col overflow-y-auto p-3 max-md:fixed max-md:inset-0 max-md:backdrop-blur-lg ",
193
  !viewSettings && "max-md:hidden",
194
  ]}
195
  >
 
237
  <div class="flex items-center justify-end">
238
  <BillingIndicator showModal={() => (billingModalOpen = true)} />
239
  </div>
240
+ <div class="flex flex-wrap items-center justify-end gap-4 whitespace-nowrap">
241
  <button
242
  onclick={() => projects.current && showShareModal(projects.current)}
243
  class="flex items-center gap-1 text-sm text-gray-500 underline decoration-gray-300 hover:text-gray-800 dark:text-gray-400 dark:decoration-gray-600 dark:hover:text-gray-200"
src/lib/components/inference-playground/project-select.svelte CHANGED
@@ -31,6 +31,9 @@
31
  if (v) projects.activeId = v;
32
  },
33
  sameWidth: true,
 
 
 
34
  });
35
 
36
  type SaveDialogState = {
 
31
  if (v) projects.activeId = v;
32
  },
33
  sameWidth: true,
34
+ onOpenChange(open) {
35
+ console.log("open", open);
36
+ },
37
  });
38
 
39
  type SaveDialogState = {
src/lib/state/settings.svelte.ts DELETED
@@ -1,27 +0,0 @@
1
- const TEXT_SIZE_KEY = "textSize";
2
-
3
- class Settings {
4
- #textSize = $state(100);
5
-
6
- constructor() {
7
- const storedTextSize = localStorage.getItem(TEXT_SIZE_KEY);
8
- const parsed = storedTextSize ? parseInt(storedTextSize, 10) : null;
9
- this.textSize = parsed && !isNaN(parsed) ? parsed : 100;
10
- }
11
-
12
- get textSize() {
13
- return this.#textSize;
14
- }
15
-
16
- set textSize(size: number) {
17
- localStorage.setItem(TEXT_SIZE_KEY, JSON.stringify(size));
18
- this.#textSize = size;
19
- }
20
-
21
- // Reset to default
22
- resetTextSize = () => {
23
- this.textSize = 100;
24
- };
25
- }
26
-
27
- export const settings = new Settings();