Thomas G. Lopes commited on
Commit
09f13ea
1 Parent(s): 5ee41c6

fix visual overflow errors & update workflow

Browse files
.github/workflows/deploy-to-spaces.yml CHANGED
@@ -7,7 +7,37 @@ on:
7
  workflow_dispatch:
8
 
9
  jobs:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  sync-to-hub:
 
11
  runs-on: ubuntu-latest
12
  steps:
13
  - uses: actions/checkout@v3
 
7
  workflow_dispatch:
8
 
9
  jobs:
10
+ test-build:
11
+ runs-on: ubuntu-latest
12
+ timeout-minutes: 10
13
+ steps:
14
+ - uses: actions/checkout@v3
15
+ - uses: actions/setup-node@v3
16
+ with:
17
+ node-version: "20"
18
+ - name: Install pnpm
19
+ uses: pnpm/action-setup@v2
20
+ with:
21
+ version: latest
22
+ run_install: false
23
+ - name: Get pnpm store directory
24
+ id: pnpm-cache
25
+ shell: bash
26
+ run: |
27
+ echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
28
+ - uses: actions/cache@v3
29
+ with:
30
+ path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
31
+ key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
32
+ restore-keys: |
33
+ ${{ runner.os }}-pnpm-store-
34
+ - name: Install dependencies
35
+ run: pnpm install --frozen-lockfile
36
+ - name: "Build"
37
+ run: |
38
+ pnpm run build
39
  sync-to-hub:
40
+ needs: test-build
41
  runs-on: ubuntu-latest
42
  steps:
43
  - uses: actions/checkout@v3
src/lib/actions/observe.svelte.ts ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { Action } from "svelte/action";
2
+
3
+ export enum ObservedElements {
4
+ BottomActions = "bottom-actions",
5
+ TokenCountEnd = "token-count-end",
6
+ TokenCountStart = "token-count-start",
7
+ // Add other elements here as needed
8
+ }
9
+
10
+ type ObservedData = {
11
+ rect: {
12
+ width: number;
13
+ height: number;
14
+ top: number;
15
+ left: number;
16
+ right: number;
17
+ bottom: number;
18
+ };
19
+ offset: {
20
+ width: number;
21
+ height: number;
22
+ top: number;
23
+ left: number;
24
+ right: number;
25
+ bottom: number;
26
+ };
27
+ };
28
+
29
+ export const observed: Record<ObservedElements, ObservedData> = $state(
30
+ Object.values(ObservedElements).reduce(
31
+ (acc, key) => {
32
+ acc[key] = {
33
+ rect: {
34
+ width: 0,
35
+ height: 0,
36
+ top: 0,
37
+ left: 0,
38
+ right: 0,
39
+ bottom: 0,
40
+ },
41
+ offset: {
42
+ width: 0,
43
+ height: 0,
44
+ top: 0,
45
+ left: 0,
46
+ right: 0,
47
+ bottom: 0,
48
+ },
49
+ };
50
+ return acc;
51
+ },
52
+ {} as Record<ObservedElements, ObservedData>
53
+ )
54
+ );
55
+
56
+ type ObserveArgs = {
57
+ name: ObservedElements;
58
+ };
59
+
60
+ function getOffsetPosition(el: HTMLElement) {
61
+ let top = 0;
62
+ let left = 0;
63
+ const width = el.offsetWidth;
64
+ const height = el.offsetHeight;
65
+
66
+ while (el) {
67
+ top += el.offsetTop;
68
+ left += el.offsetLeft;
69
+ el = el.offsetParent as HTMLElement;
70
+ }
71
+
72
+ return { top, left, width, height, right: left + width, bottom: top + height };
73
+ }
74
+
75
+ export const observe: Action<HTMLElement, ObserveArgs> = (node, args) => {
76
+ let resizeObserver: ResizeObserver;
77
+
78
+ function setVars(name: ObservedElements) {
79
+ // 1. Standard rect (includes transforms)
80
+ const rect = node.getBoundingClientRect();
81
+ document.documentElement.style.setProperty(`--${name}-width`, `${rect.width}px`);
82
+ document.documentElement.style.setProperty(`--${name}-height`, `${rect.height}px`);
83
+ document.documentElement.style.setProperty(`--${name}-top`, `${rect.top}px`);
84
+ document.documentElement.style.setProperty(`--${name}-left`, `${rect.left}px`);
85
+ document.documentElement.style.setProperty(`--${name}-right`, `${rect.right}px`);
86
+ document.documentElement.style.setProperty(`--${name}-bottom`, `${rect.bottom}px`);
87
+
88
+ // 2. Offset position (ignores transforms)
89
+ const offset = getOffsetPosition(node);
90
+ document.documentElement.style.setProperty(`--${name}-width-offset`, `${offset.width}px`);
91
+ document.documentElement.style.setProperty(`--${name}-height-offset`, `${offset.height}px`);
92
+ document.documentElement.style.setProperty(`--${name}-top-offset`, `${offset.top}px`);
93
+ document.documentElement.style.setProperty(`--${name}-left-offset`, `${offset.left}px`);
94
+ document.documentElement.style.setProperty(`--${name}-right-offset`, `${offset.right}px`);
95
+ document.documentElement.style.setProperty(`--${name}-bottom-offset`, `${offset.bottom}px`);
96
+
97
+ observed[name] = {
98
+ rect,
99
+ offset,
100
+ };
101
+ }
102
+
103
+ function update(args: ObserveArgs) {
104
+ if (resizeObserver) {
105
+ resizeObserver.disconnect();
106
+ }
107
+
108
+ resizeObserver = new ResizeObserver(() => {
109
+ setVars(args.name);
110
+ });
111
+ resizeObserver.observe(node);
112
+
113
+ // Listen for scroll and resize events
114
+ window.addEventListener("scroll", onWindowChange, true);
115
+ window.addEventListener("resize", onWindowChange, true);
116
+
117
+ setVars(args.name); // Initial set after observing
118
+ }
119
+
120
+ function onWindowChange() {
121
+ setVars(args.name);
122
+ }
123
+
124
+ update(args); // Initial setup
125
+
126
+ function destroy() {
127
+ resizeObserver.disconnect();
128
+ window.removeEventListener("scroll", onWindowChange, true);
129
+ window.removeEventListener("resize", onWindowChange, true);
130
+ }
131
+
132
+ return {
133
+ update,
134
+ destroy,
135
+ };
136
+ };
src/lib/components/inference-playground/playground.svelte CHANGED
@@ -1,12 +1,10 @@
1
  <script lang="ts">
2
- import { type ConversationMessage, type Model, type Project } from "$lib/types.js";
3
-
4
- import { getTokens, handleNonStreamingResponse, handleStreamingResponse, isSystemPromptSupported } from "./utils.js";
5
-
6
  import { AbortManager } from "$lib/spells/abort-manager.svelte.js";
7
  import { models } from "$lib/state/models.svelte.js";
8
  import { session } from "$lib/state/session.svelte.js";
9
  import { token } from "$lib/state/token.svelte.js";
 
10
  import { isMac } from "$lib/utils/platform.js";
11
  import { watch } from "runed";
12
  import typia from "typia";
@@ -29,6 +27,7 @@
29
  import ModelSelectorModal from "./model-selector-modal.svelte";
30
  import ModelSelector from "./model-selector.svelte";
31
  import ProjectSelect from "./project-select.svelte";
 
32
 
33
  const startMessageUser: ConversationMessage = { role: "user", content: "" };
34
 
@@ -307,12 +306,24 @@
307
  <div
308
  class="pointer-events-none absolute inset-0 flex flex-1 shrink-0 items-center justify-around gap-x-8 text-center text-sm text-gray-500 max-xl:hidden"
309
  >
310
- {#each generationStats as { latency, generatedTokensCount }}
311
- <span>{generatedTokensCount} tokens Latency {latency}ms</span>
 
 
 
 
 
 
 
312
  {/each}
313
  </div>
314
  <div class="flex flex-1 justify-end gap-x-2">
315
- <button type="button" onclick={() => (viewCode = !viewCode)} class="btn">
 
 
 
 
 
316
  <IconCode />
317
  {!viewCode ? "View Code" : "Hide Code"}
318
  </button>
 
1
  <script lang="ts">
2
+ import { observe, observed, ObservedElements } from "$lib/actions/observe.svelte.js";
 
 
 
3
  import { AbortManager } from "$lib/spells/abort-manager.svelte.js";
4
  import { models } from "$lib/state/models.svelte.js";
5
  import { session } from "$lib/state/session.svelte.js";
6
  import { token } from "$lib/state/token.svelte.js";
7
+ import { type ConversationMessage, type Model, type Project } from "$lib/types.js";
8
  import { isMac } from "$lib/utils/platform.js";
9
  import { watch } from "runed";
10
  import typia from "typia";
 
27
  import ModelSelectorModal from "./model-selector-modal.svelte";
28
  import ModelSelector from "./model-selector.svelte";
29
  import ProjectSelect from "./project-select.svelte";
30
+ import { getTokens, handleNonStreamingResponse, handleStreamingResponse, isSystemPromptSupported } from "./utils.js";
31
 
32
  const startMessageUser: ConversationMessage = { role: "user", content: "" };
33
 
 
306
  <div
307
  class="pointer-events-none absolute inset-0 flex flex-1 shrink-0 items-center justify-around gap-x-8 text-center text-sm text-gray-500 max-xl:hidden"
308
  >
309
+ {#each generationStats as { latency, generatedTokensCount }, index}
310
+ {@const isLast = index === generationStats.length - 1}
311
+ {@const baLeft = observed["bottom-actions"].rect.left}
312
+ {@const tceRight = observed["token-count-end"].offset.right}
313
+ <span
314
+ style:translate={isLast ? (baLeft - 12 < tceRight ? baLeft - tceRight - 12 + "px" : "") : undefined}
315
+ use:observe={{ name: isLast ? ObservedElements.TokenCountEnd : ObservedElements.TokenCountStart }}
316
+ >{generatedTokensCount} tokens 路 Latency {latency}ms</span
317
+ >
318
  {/each}
319
  </div>
320
  <div class="flex flex-1 justify-end gap-x-2">
321
+ <button
322
+ type="button"
323
+ onclick={() => (viewCode = !viewCode)}
324
+ class="btn"
325
+ use:observe={{ name: ObservedElements.BottomActions }}
326
+ >
327
  <IconCode />
328
  {!viewCode ? "View Code" : "Hide Code"}
329
  </button>