Thomas G. Lopes
commited on
Commit
·
a5619c2
1
Parent(s):
2087f3e
add quota modal
Browse files- src/lib/actions/autofocus.ts +5 -1
- src/lib/components/debug-menu.svelte +7 -0
- src/lib/components/inference-playground/conversation.svelte +0 -2
- src/lib/components/prompts.svelte +9 -14
- src/lib/components/quota-modal.svelte +172 -0
- src/lib/components/toaster.svelte.ts +1 -1
- src/routes/+layout.svelte +3 -1
src/lib/actions/autofocus.ts
CHANGED
@@ -1,3 +1,7 @@
|
|
|
|
|
|
1 |
export function autofocus(node: HTMLElement) {
|
2 |
-
|
|
|
|
|
3 |
}
|
|
|
1 |
+
import { tick } from "svelte";
|
2 |
+
|
3 |
export function autofocus(node: HTMLElement) {
|
4 |
+
tick().then(() => {
|
5 |
+
node.focus();
|
6 |
+
});
|
7 |
}
|
src/lib/components/debug-menu.svelte
CHANGED
@@ -7,6 +7,7 @@
|
|
7 |
import { compareStr } from "$lib/utils/compare.js";
|
8 |
import type { ToastData } from "./toaster.svelte.js";
|
9 |
import { addToast } from "./toaster.svelte.js";
|
|
|
10 |
|
11 |
let innerWidth = $state<number>();
|
12 |
let innerHeight = $state<number>();
|
@@ -38,6 +39,12 @@
|
|
38 |
console.log(await prompt("Test prompt"));
|
39 |
},
|
40 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
{
|
42 |
label: "Show token modal",
|
43 |
cb: () => {
|
|
|
7 |
import { compareStr } from "$lib/utils/compare.js";
|
8 |
import type { ToastData } from "./toaster.svelte.js";
|
9 |
import { addToast } from "./toaster.svelte.js";
|
10 |
+
import { showQuotaModal } from "./quota-modal.svelte";
|
11 |
|
12 |
let innerWidth = $state<number>();
|
13 |
let innerHeight = $state<number>();
|
|
|
39 |
console.log(await prompt("Test prompt"));
|
40 |
},
|
41 |
},
|
42 |
+
{
|
43 |
+
label: "Show quota modal",
|
44 |
+
cb: () => {
|
45 |
+
showQuotaModal();
|
46 |
+
},
|
47 |
+
},
|
48 |
{
|
49 |
label: "Show token modal",
|
50 |
cb: () => {
|
src/lib/components/inference-playground/conversation.svelte
CHANGED
@@ -1,5 +1,3 @@
|
|
1 |
-
<!-- @migration-task Error while migrating Svelte code: Can only bind to an Identifier or MemberExpression or a `{get, set}` pair
|
2 |
-
https://svelte.dev/e/bind_invalid_expression -->
|
3 |
<script lang="ts">
|
4 |
import { run } from "svelte/legacy";
|
5 |
|
|
|
|
|
|
|
1 |
<script lang="ts">
|
2 |
import { run } from "svelte/legacy";
|
3 |
|
src/lib/components/prompts.svelte
CHANGED
@@ -1,8 +1,7 @@
|
|
1 |
<script lang="ts" module>
|
|
|
2 |
import { clickOutside } from "$lib/actions/click-outside.js";
|
3 |
-
import { writable } from "svelte/store";
|
4 |
import IconCross from "~icons/carbon/close";
|
5 |
-
import { autofocus } from "$lib/actions/autofocus.js";
|
6 |
|
7 |
type Prompt = {
|
8 |
label: string;
|
@@ -11,30 +10,26 @@
|
|
11 |
callback: (value: string) => void;
|
12 |
};
|
13 |
|
14 |
-
|
|
|
15 |
|
16 |
export function resolvePrompt() {
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
});
|
21 |
}
|
22 |
|
23 |
-
export async function prompt(label: string,
|
24 |
return new Promise(res => {
|
25 |
-
prompts.
|
26 |
});
|
27 |
}
|
28 |
</script>
|
29 |
|
30 |
<script lang="ts">
|
31 |
-
import { run } from "svelte/legacy";
|
32 |
-
|
33 |
-
let current = $derived($prompts?.[0]);
|
34 |
-
|
35 |
let dialog: HTMLDialogElement | undefined = $state();
|
36 |
|
37 |
-
|
38 |
if (current) {
|
39 |
dialog?.showModal();
|
40 |
} else {
|
|
|
1 |
<script lang="ts" module>
|
2 |
+
import { autofocus } from "$lib/actions/autofocus.js";
|
3 |
import { clickOutside } from "$lib/actions/click-outside.js";
|
|
|
4 |
import IconCross from "~icons/carbon/close";
|
|
|
5 |
|
6 |
type Prompt = {
|
7 |
label: string;
|
|
|
10 |
callback: (value: string) => void;
|
11 |
};
|
12 |
|
13 |
+
let prompts = $state<Prompt[]>([]);
|
14 |
+
const current = $derived(prompts[0]);
|
15 |
|
16 |
export function resolvePrompt() {
|
17 |
+
if (!current) return;
|
18 |
+
current.callback(current.value ?? "");
|
19 |
+
prompts.splice(0, 1);
|
|
|
20 |
}
|
21 |
|
22 |
+
export async function prompt(label: string, defaultValue?: string): Promise<string> {
|
23 |
return new Promise(res => {
|
24 |
+
prompts.push({ label, value: defaultValue, callback: res });
|
25 |
});
|
26 |
}
|
27 |
</script>
|
28 |
|
29 |
<script lang="ts">
|
|
|
|
|
|
|
|
|
30 |
let dialog: HTMLDialogElement | undefined = $state();
|
31 |
|
32 |
+
$effect(() => {
|
33 |
if (current) {
|
34 |
dialog?.showModal();
|
35 |
} else {
|
src/lib/components/quota-modal.svelte
ADDED
@@ -0,0 +1,172 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<script lang="ts" module>
|
2 |
+
let open = $state(true);
|
3 |
+
|
4 |
+
export function showQuotaModal() {
|
5 |
+
open = true;
|
6 |
+
}
|
7 |
+
</script>
|
8 |
+
|
9 |
+
<script lang="ts">
|
10 |
+
import { clickOutside } from "$lib/actions/click-outside.js";
|
11 |
+
import IconCross from "~icons/carbon/close";
|
12 |
+
import IconCheck from "~icons/carbon/checkmark";
|
13 |
+
import IconExternal from "~icons/carbon/arrow-up-right";
|
14 |
+
let dialog: HTMLDialogElement | undefined = $state();
|
15 |
+
|
16 |
+
$effect(() => {
|
17 |
+
if (open) {
|
18 |
+
dialog?.showModal();
|
19 |
+
} else {
|
20 |
+
dialog?.close();
|
21 |
+
}
|
22 |
+
});
|
23 |
+
</script>
|
24 |
+
|
25 |
+
{#snippet pro()}
|
26 |
+
<span
|
27 |
+
class="inline-block -skew-x-12 rounded-md border border-gray-200 bg-linear-to-br from-pink-300 via-green-200 to-yellow-200 px-1.5 py-0 text-sm font-bold text-black shadow-lg shadow-green-500/10 dark:border-gray-800 dark:from-pink-500 dark:via-green-500 dark:to-yellow-500 dark:text-black dark:shadow-green-500/20"
|
28 |
+
>
|
29 |
+
PRO
|
30 |
+
</span>
|
31 |
+
{/snippet}
|
32 |
+
|
33 |
+
<dialog bind:this={dialog} onclose={() => (open = false)}>
|
34 |
+
{#if open}
|
35 |
+
<div class="fixed inset-0 z-50 flex items-center justify-center overflow-hidden bg-black/85">
|
36 |
+
<div
|
37 |
+
class="relative w-3xl rounded-lg bg-white shadow-sm dark:bg-gray-900"
|
38 |
+
use:clickOutside={() => (open = false)}
|
39 |
+
>
|
40 |
+
<div class="flex items-center justify-between rounded-t border-b p-4 md:px-5 md:py-4 dark:border-gray-800">
|
41 |
+
<h3 class="flex items-center gap-2.5 text-lg font-semibold text-gray-900 dark:text-white">
|
42 |
+
<img
|
43 |
+
alt="Hugging Face's logo"
|
44 |
+
class="w-7"
|
45 |
+
src="https://huggingface.co/front/assets/huggingface_logo-noborder.svg"
|
46 |
+
/> Increase your usage limits
|
47 |
+
</h3>
|
48 |
+
<button
|
49 |
+
type="button"
|
50 |
+
class="ms-auto 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"
|
51 |
+
onclick={() => (open = false)}
|
52 |
+
>
|
53 |
+
<div class="text-xl">
|
54 |
+
<IconCross />
|
55 |
+
</div>
|
56 |
+
<span class="sr-only">Close modal</span>
|
57 |
+
</button>
|
58 |
+
</div>
|
59 |
+
<!-- Modal body -->
|
60 |
+
<div class="flex flex-col gap-2 p-4 text-white md:p-5">
|
61 |
+
<p>
|
62 |
+
It seems you have reached your usage limits. If you want to continue using the playground, please consider
|
63 |
+
creating a {@render pro()} account!
|
64 |
+
</p>
|
65 |
+
<p>You'll also gain access to:</p>
|
66 |
+
<ul
|
67 |
+
class="grid grid-cols-1 flex-col gap-2 text-base text-gray-500 md:col-span-3 md:grid-cols-2 md:flex-row dark:text-gray-400"
|
68 |
+
>
|
69 |
+
<li class="flex items-start">
|
70 |
+
<IconCheck class="text-md shrink-0 pt-2" />
|
71 |
+
<p>
|
72 |
+
<a
|
73 |
+
href="/spaces/enzostvs/zero-gpu-spaces"
|
74 |
+
class="font-semibold whitespace-nowrap text-gray-700 underline decoration-gray-400 hover:text-gray-900 hover:decoration-gray-600 dark:text-gray-200 dark:hover:text-gray-200 dark:hover:decoration-gray-300"
|
75 |
+
target="_blank">ZeroGPU</a
|
76 |
+
>: Get 5x usage quota and highest GPU queue priority
|
77 |
+
</p>
|
78 |
+
</li>
|
79 |
+
<li class="flex items-start">
|
80 |
+
<IconCheck class="text-md shrink-0 pt-2" />
|
81 |
+
<p>
|
82 |
+
<a
|
83 |
+
href="/docs/hub/spaces-zerogpu"
|
84 |
+
class="font-semibold whitespace-nowrap text-gray-700 underline decoration-gray-400 hover:text-gray-900 hover:decoration-gray-600 dark:text-gray-200 dark:hover:text-gray-200 dark:hover:decoration-gray-300"
|
85 |
+
target="_blank">Spaces Hosting</a
|
86 |
+
>: Create ZeroGPU Spaces with A100 hardware
|
87 |
+
</p>
|
88 |
+
</li>
|
89 |
+
<li class="flex items-start">
|
90 |
+
<IconCheck class="text-md shrink-0 pt-2" />
|
91 |
+
<p>
|
92 |
+
<a
|
93 |
+
href="/docs/hub/spaces-dev-mode"
|
94 |
+
class="font-semibold whitespace-nowrap text-gray-700 underline decoration-gray-400 hover:text-gray-900 hover:decoration-gray-600 dark:text-gray-200 dark:hover:text-gray-200 dark:hover:decoration-gray-300"
|
95 |
+
target="_blank">Spaces Dev Mode</a
|
96 |
+
>: Fast iterations via SSH/VS Code for Spaces
|
97 |
+
</p>
|
98 |
+
</li>
|
99 |
+
|
100 |
+
<li class="flex items-start">
|
101 |
+
<IconCheck class="text-md shrink-0 pt-2" />
|
102 |
+
<p>
|
103 |
+
<a
|
104 |
+
href="https://huggingface.co/blog/inference-providers"
|
105 |
+
class="font-semibold whitespace-nowrap text-gray-700 underline decoration-gray-400 hover:text-gray-900 hover:decoration-gray-600 dark:text-gray-200 dark:hover:text-gray-200 dark:hover:decoration-gray-300"
|
106 |
+
target="_blank">Inference Providers</a
|
107 |
+
>: Get $2 included credits across all Inference Providers
|
108 |
+
</p>
|
109 |
+
</li>
|
110 |
+
<li class="flex items-start">
|
111 |
+
<IconCheck class="text-md shrink-0 pt-2" />
|
112 |
+
<p>
|
113 |
+
<a
|
114 |
+
href="/docs/hub/datasets-viewer"
|
115 |
+
class="font-semibold whitespace-nowrap text-gray-700 underline decoration-gray-400 hover:text-gray-900 hover:decoration-gray-600 dark:text-gray-200 dark:hover:text-gray-200 dark:hover:decoration-gray-300"
|
116 |
+
target="_blank">Dataset Viewer</a
|
117 |
+
>: Activate it on private datasets
|
118 |
+
</p>
|
119 |
+
</li>
|
120 |
+
<li class="flex items-start">
|
121 |
+
<IconCheck class="text-md shrink-0 pt-2" />
|
122 |
+
<p>
|
123 |
+
<a
|
124 |
+
href="/blog"
|
125 |
+
class="font-semibold whitespace-nowrap text-gray-700 underline decoration-gray-400 hover:text-gray-900 hover:decoration-gray-600 dark:text-gray-200 dark:hover:text-gray-200 dark:hover:decoration-gray-300"
|
126 |
+
target="_blank">Blog Articles</a
|
127 |
+
>: Publish articles to the Hugging Face blog
|
128 |
+
</p>
|
129 |
+
</li>
|
130 |
+
<li class="flex items-start">
|
131 |
+
<IconCheck class="text-md shrink-0 pt-2" />
|
132 |
+
<p>
|
133 |
+
<a
|
134 |
+
href="/posts"
|
135 |
+
class="font-semibold whitespace-nowrap text-gray-700 underline decoration-gray-400 hover:text-gray-900 hover:decoration-gray-600 dark:text-gray-200 dark:hover:text-gray-200 dark:hover:decoration-gray-300"
|
136 |
+
target="_blank">Social Posts</a
|
137 |
+
>: Share short updates with the community
|
138 |
+
</p>
|
139 |
+
</li>
|
140 |
+
|
141 |
+
<li class="flex items-start">
|
142 |
+
<IconCheck class="text-md shrink-0 pt-2" />
|
143 |
+
<p>
|
144 |
+
<span class="font-semibold text-gray-700 dark:text-gray-200">Features Preview</span>: Get early access
|
145 |
+
to upcoming features
|
146 |
+
</p>
|
147 |
+
</li>
|
148 |
+
<li class="flex items-start">
|
149 |
+
<IconCheck class="text-md shrink-0 pt-2" />
|
150 |
+
<p>
|
151 |
+
{@render pro()}<span class="ml-1.5 font-semibold text-gray-700 dark:text-gray-200">Badge</span>: Show
|
152 |
+
your support on your profile
|
153 |
+
</p>
|
154 |
+
</li>
|
155 |
+
</ul>
|
156 |
+
</div>
|
157 |
+
|
158 |
+
<!-- Modal footer -->
|
159 |
+
<div class="flex rounded-b border-t border-gray-200 p-4 md:p-5 dark:border-gray-800">
|
160 |
+
<a
|
161 |
+
class="ml-auto flex items-center gap-1.5 rounded-lg bg-black px-4 py-2.5 pl-3 text-sm font-medium text-white hover:bg-gray-900 focus:ring-4 focus:ring-gray-300 focus:outline-hidden dark:border-gray-700 dark:bg-gray-800 dark:hover:bg-gray-700 dark:focus:ring-gray-700"
|
162 |
+
href="https://huggingface.co/settings/billing/subscription#subscribe"
|
163 |
+
target="_blank"
|
164 |
+
>
|
165 |
+
<IconExternal />
|
166 |
+
Get Pro ($9/month)
|
167 |
+
</a>
|
168 |
+
</div>
|
169 |
+
</div>
|
170 |
+
</div>
|
171 |
+
{/if}
|
172 |
+
</dialog>
|
src/lib/components/toaster.svelte.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
import { Toaster
|
2 |
|
3 |
export type ToastData = {
|
4 |
title: string;
|
|
|
1 |
+
import { Toaster } from "melt/builders";
|
2 |
|
3 |
export type ToastData = {
|
4 |
title: string;
|
src/routes/+layout.svelte
CHANGED
@@ -3,8 +3,9 @@
|
|
3 |
import DebugMenu from "$lib/components/debug-menu.svelte";
|
4 |
import Prompts from "$lib/components/prompts.svelte";
|
5 |
import Toaster from "$lib/components/toaster.svelte";
|
|
|
6 |
interface Props {
|
7 |
-
children?: import(
|
8 |
}
|
9 |
|
10 |
let { children }: Props = $props();
|
@@ -14,3 +15,4 @@
|
|
14 |
<DebugMenu />
|
15 |
<Prompts />
|
16 |
<Toaster />
|
|
|
|
3 |
import DebugMenu from "$lib/components/debug-menu.svelte";
|
4 |
import Prompts from "$lib/components/prompts.svelte";
|
5 |
import Toaster from "$lib/components/toaster.svelte";
|
6 |
+
import QuotaModal from "$lib/components/quota-modal.svelte";
|
7 |
interface Props {
|
8 |
+
children?: import("svelte").Snippet;
|
9 |
}
|
10 |
|
11 |
let { children }: Props = $props();
|
|
|
15 |
<DebugMenu />
|
16 |
<Prompts />
|
17 |
<Toaster />
|
18 |
+
<QuotaModal />
|