@gradio/core 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +54 -0
- package/dist/src/Blocks.svelte +117 -83
- package/dist/src/api_docs/Settings.svelte +21 -22
- package/dist/src/api_docs/Settings.svelte.d.ts +6 -21
- package/dist/src/api_docs/SettingsBanner.svelte +2 -4
- package/dist/src/api_docs/SettingsBanner.svelte.d.ts +5 -20
- package/dist/src/dependency.js +9 -1
- package/dist/src/init.svelte.d.ts +6 -2
- package/dist/src/init.svelte.js +156 -22
- package/dist/src/types.d.ts +1 -0
- package/package.json +56 -56
- package/src/Blocks.svelte +117 -83
- package/src/api_docs/Settings.svelte +21 -22
- package/src/api_docs/SettingsBanner.svelte +2 -4
- package/src/dependency.ts +16 -2
- package/src/init.svelte.ts +202 -30
- package/src/init.test.ts +1 -1
- package/src/types.ts +1 -0
package/src/Blocks.svelte
CHANGED
|
@@ -104,27 +104,6 @@
|
|
|
104
104
|
}
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
-
let app_tree = new AppTree(
|
|
108
|
-
components,
|
|
109
|
-
layout,
|
|
110
|
-
dependencies,
|
|
111
|
-
{
|
|
112
|
-
root,
|
|
113
|
-
theme: theme_mode,
|
|
114
|
-
version,
|
|
115
|
-
api_prefix,
|
|
116
|
-
max_file_size,
|
|
117
|
-
autoscroll
|
|
118
|
-
},
|
|
119
|
-
app,
|
|
120
|
-
$reactive_formatter
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
setContext(GRADIO_ROOT, {
|
|
124
|
-
register: app_tree.register_component.bind(app_tree),
|
|
125
|
-
dispatcher: gradio_event_dispatcher
|
|
126
|
-
});
|
|
127
|
-
|
|
128
107
|
let messages: (ToastMessage & { fn_index: number })[] = $state([]);
|
|
129
108
|
|
|
130
109
|
function gradio_event_dispatcher(
|
|
@@ -142,6 +121,12 @@
|
|
|
142
121
|
new_message("Warning", data as string, -1, event, 10, true);
|
|
143
122
|
} else if (event === "info") {
|
|
144
123
|
new_message("Info", data as string, -1, event, 10, true);
|
|
124
|
+
} else if (event === "gradio_expand" || event === "gradio_tab_select") {
|
|
125
|
+
const id_ =
|
|
126
|
+
event === "gradio_expand"
|
|
127
|
+
? id
|
|
128
|
+
: (data as { component_id: number }).component_id;
|
|
129
|
+
app_tree.render_previously_invisible_children(id_);
|
|
145
130
|
} else if (event == "clear_status") {
|
|
146
131
|
app_tree.update_state(
|
|
147
132
|
id,
|
|
@@ -155,6 +140,9 @@
|
|
|
155
140
|
// update_status(id, "complete", data);
|
|
156
141
|
} else if (event == "close_stream") {
|
|
157
142
|
dep_manager.close_stream(id);
|
|
143
|
+
} else if (event === "custom_button_click") {
|
|
144
|
+
const button_id = (data as { id: number }).id;
|
|
145
|
+
dispatch_to_target(button_id, "click", null);
|
|
158
146
|
} else {
|
|
159
147
|
// Tabs are a bit weird. The Tabs component dispatches 'select' events
|
|
160
148
|
// but the target id corresponds to the child Tab component that was selected.
|
|
@@ -173,6 +161,41 @@
|
|
|
173
161
|
}
|
|
174
162
|
}
|
|
175
163
|
|
|
164
|
+
let app_tree = new AppTree(
|
|
165
|
+
components,
|
|
166
|
+
layout,
|
|
167
|
+
dependencies,
|
|
168
|
+
{
|
|
169
|
+
root,
|
|
170
|
+
theme: theme_mode,
|
|
171
|
+
version,
|
|
172
|
+
api_prefix,
|
|
173
|
+
max_file_size,
|
|
174
|
+
autoscroll
|
|
175
|
+
},
|
|
176
|
+
app,
|
|
177
|
+
$reactive_formatter,
|
|
178
|
+
gradio_event_dispatcher
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
function dispatch_to_target(
|
|
182
|
+
target_id: number,
|
|
183
|
+
event: string,
|
|
184
|
+
data: unknown
|
|
185
|
+
): void {
|
|
186
|
+
dep_manager.dispatch({
|
|
187
|
+
type: "event",
|
|
188
|
+
event_name: event,
|
|
189
|
+
target_id: target_id,
|
|
190
|
+
event_data: data
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
setContext(GRADIO_ROOT, {
|
|
195
|
+
register: app_tree.register_component.bind(app_tree),
|
|
196
|
+
dispatcher: gradio_event_dispatcher
|
|
197
|
+
});
|
|
198
|
+
|
|
176
199
|
let api_calls: Payload[] = $state([]);
|
|
177
200
|
let last_api_call: Payload | null = $state(null);
|
|
178
201
|
// We need a callback to add to api_calls from the DependencyManager
|
|
@@ -322,8 +345,10 @@
|
|
|
322
345
|
|
|
323
346
|
const MESSAGE_QUOTE_RE = /^'([^]+)'$/;
|
|
324
347
|
|
|
325
|
-
const DUPLICATE_MESSAGE = $
|
|
326
|
-
const MOBILE_QUEUE_WARNING = $
|
|
348
|
+
const DUPLICATE_MESSAGE = $reactive_formatter("blocks.long_requests_queue");
|
|
349
|
+
const MOBILE_QUEUE_WARNING = $reactive_formatter(
|
|
350
|
+
"blocks.connection_can_break"
|
|
351
|
+
);
|
|
327
352
|
const LOST_CONNECTION_MESSAGE =
|
|
328
353
|
"Connection to the server was lost. Attempting reconnection...";
|
|
329
354
|
const CHANGED_CONNECTION_MESSAGE =
|
|
@@ -331,7 +356,9 @@
|
|
|
331
356
|
const RECONNECTION_MESSAGE = "Connection re-established.";
|
|
332
357
|
const SESSION_NOT_FOUND_MESSAGE =
|
|
333
358
|
"Session not found - this is likely because the machine you were connected to has changed. <a href=''>Refresh the page</a> to continue.";
|
|
334
|
-
const WAITING_FOR_INPUTS_MESSAGE = $
|
|
359
|
+
const WAITING_FOR_INPUTS_MESSAGE = $reactive_formatter(
|
|
360
|
+
"blocks.waiting_for_inputs"
|
|
361
|
+
);
|
|
335
362
|
const SHOW_DUPLICATE_MESSAGE_ON_ETA = 15;
|
|
336
363
|
const SHOW_MOBILE_QUEUE_WARNING_ON_ETA = 10;
|
|
337
364
|
let is_mobile_device = false;
|
|
@@ -425,69 +452,75 @@
|
|
|
425
452
|
style:margin-right={vibe_mode ? `${vibe_editor_width}px` : "0"}
|
|
426
453
|
>
|
|
427
454
|
<MountComponents node={app_tree.root} />
|
|
455
|
+
</div>
|
|
428
456
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
<button
|
|
433
|
-
on:click={() => {
|
|
434
|
-
set_api_docs_visible(!api_docs_visible);
|
|
435
|
-
}}
|
|
436
|
-
on:mouseenter={() => {
|
|
437
|
-
loadApiDocs();
|
|
438
|
-
loadApiRecorder();
|
|
439
|
-
}}
|
|
440
|
-
class="show-api"
|
|
441
|
-
>
|
|
442
|
-
{#if app.config?.mcp_server}
|
|
443
|
-
{$_("errors.use_via_api_or_mcp")}
|
|
444
|
-
{:else}
|
|
445
|
-
{$_("errors.use_via_api")}
|
|
446
|
-
{/if}
|
|
447
|
-
<img src={api_logo} alt={$_("common.logo")} />
|
|
448
|
-
</button>
|
|
449
|
-
{/if}
|
|
450
|
-
{#if footer_links.includes("gradio")}
|
|
451
|
-
<div class="divider show-api-divider">·</div>
|
|
452
|
-
<a
|
|
453
|
-
href="https://gradio.app"
|
|
454
|
-
class="built-with"
|
|
455
|
-
target="_blank"
|
|
456
|
-
rel="noreferrer"
|
|
457
|
-
>
|
|
458
|
-
{$_("common.built_with_gradio")}
|
|
459
|
-
<img src={logo} alt={$_("common.logo")} />
|
|
460
|
-
</a>
|
|
461
|
-
{/if}
|
|
457
|
+
{#if footer_links.length > 0}
|
|
458
|
+
<footer bind:clientHeight={footer_height}>
|
|
459
|
+
{#if footer_links.includes("api")}
|
|
462
460
|
<button
|
|
463
|
-
class:hidden={!$is_screen_recording}
|
|
464
461
|
on:click={() => {
|
|
465
|
-
|
|
462
|
+
set_api_docs_visible(!api_docs_visible);
|
|
466
463
|
}}
|
|
467
|
-
|
|
464
|
+
on:mouseenter={() => {
|
|
465
|
+
loadApiDocs();
|
|
466
|
+
loadApiRecorder();
|
|
467
|
+
}}
|
|
468
|
+
class="show-api"
|
|
468
469
|
>
|
|
469
|
-
{
|
|
470
|
-
|
|
470
|
+
{#if app.config?.mcp_server}
|
|
471
|
+
{$reactive_formatter("errors.use_via_api_or_mcp")}
|
|
472
|
+
{:else}
|
|
473
|
+
{$reactive_formatter("errors.use_via_api")}
|
|
474
|
+
{/if}
|
|
475
|
+
<img src={api_logo} alt={$reactive_formatter("common.logo")} />
|
|
471
476
|
</button>
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
{
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
477
|
+
{/if}
|
|
478
|
+
{#if footer_links.includes("gradio")}
|
|
479
|
+
<div class="divider show-api-divider">·</div>
|
|
480
|
+
<a
|
|
481
|
+
href="https://gradio.app"
|
|
482
|
+
class="built-with"
|
|
483
|
+
target="_blank"
|
|
484
|
+
rel="noreferrer"
|
|
485
|
+
>
|
|
486
|
+
{$reactive_formatter("common.built_with_gradio")}
|
|
487
|
+
<img src={logo} alt={$reactive_formatter("common.logo")} />
|
|
488
|
+
</a>
|
|
489
|
+
{/if}
|
|
490
|
+
<button
|
|
491
|
+
class:hidden={!$is_screen_recording}
|
|
492
|
+
on:click={() => {
|
|
493
|
+
screen_recording();
|
|
494
|
+
}}
|
|
495
|
+
class="record"
|
|
496
|
+
>
|
|
497
|
+
{$reactive_formatter("common.stop_recording")}
|
|
498
|
+
<img
|
|
499
|
+
src={record_stop}
|
|
500
|
+
alt={$reactive_formatter("common.stop_recording")}
|
|
501
|
+
/>
|
|
502
|
+
</button>
|
|
503
|
+
<div class="divider">·</div>
|
|
504
|
+
{#if footer_links.includes("settings")}
|
|
505
|
+
<div class="divider" class:hidden={!$is_screen_recording}>·</div>
|
|
506
|
+
<button
|
|
507
|
+
on:click={() => {
|
|
508
|
+
set_settings_visible(!settings_visible);
|
|
509
|
+
}}
|
|
510
|
+
on:mouseenter={() => {
|
|
511
|
+
loadSettings();
|
|
512
|
+
}}
|
|
513
|
+
class="settings"
|
|
514
|
+
>
|
|
515
|
+
{$reactive_formatter("common.settings")}
|
|
516
|
+
<img
|
|
517
|
+
src={settings_logo}
|
|
518
|
+
alt={$reactive_formatter("common.settings")}
|
|
519
|
+
/>
|
|
520
|
+
</button>
|
|
521
|
+
{/if}
|
|
522
|
+
</footer>
|
|
523
|
+
{/if}
|
|
491
524
|
{#if api_recorder_visible && ApiRecorder}
|
|
492
525
|
<!-- TODO: fix -->
|
|
493
526
|
<!-- svelte-ignore a11y-click-events-have-key-events-->
|
|
@@ -552,15 +585,16 @@
|
|
|
552
585
|
this={Settings}
|
|
553
586
|
bind:allow_zoom
|
|
554
587
|
bind:allow_video_trim
|
|
555
|
-
|
|
588
|
+
onclose={() => {
|
|
556
589
|
set_settings_visible(false);
|
|
557
590
|
}}
|
|
558
|
-
|
|
591
|
+
start_recording={() => {
|
|
559
592
|
screen_recording();
|
|
560
593
|
}}
|
|
561
594
|
pwa_enabled={app.config.pwa}
|
|
562
595
|
{root}
|
|
563
596
|
{space_id}
|
|
597
|
+
i18n={$reactive_formatter}
|
|
564
598
|
/>
|
|
565
599
|
</div>
|
|
566
600
|
</div>
|
|
@@ -7,17 +7,18 @@
|
|
|
7
7
|
import { language_choices, changeLocale } from "../i18n";
|
|
8
8
|
import { locale, _ } from "svelte-i18n";
|
|
9
9
|
import record from "./img/record.svg";
|
|
10
|
-
import { createEventDispatcher } from "svelte";
|
|
11
10
|
|
|
12
11
|
let {
|
|
13
12
|
root,
|
|
14
13
|
space_id,
|
|
15
14
|
pwa_enabled,
|
|
16
15
|
allow_zoom = $bindable(),
|
|
17
|
-
allow_video_trim = $bindable()
|
|
16
|
+
allow_video_trim = $bindable(),
|
|
17
|
+
onclose,
|
|
18
|
+
start_recording,
|
|
19
|
+
i18n
|
|
18
20
|
} = $props();
|
|
19
21
|
|
|
20
|
-
const dispatch = createEventDispatcher();
|
|
21
22
|
if (root === "") {
|
|
22
23
|
root = location.protocol + "//" + location.host + location.pathname;
|
|
23
24
|
}
|
|
@@ -34,6 +35,7 @@
|
|
|
34
35
|
url.searchParams.set("__theme", theme);
|
|
35
36
|
current_theme = theme;
|
|
36
37
|
}
|
|
38
|
+
url.searchParams.delete("view");
|
|
37
39
|
window.location.href = url.toString();
|
|
38
40
|
}
|
|
39
41
|
|
|
@@ -59,8 +61,8 @@
|
|
|
59
61
|
}
|
|
60
62
|
});
|
|
61
63
|
|
|
62
|
-
function handleLanguageChange(
|
|
63
|
-
const new_locale =
|
|
64
|
+
function handleLanguageChange(value: string): void {
|
|
65
|
+
const new_locale = value;
|
|
64
66
|
changeLocale(new_locale);
|
|
65
67
|
}
|
|
66
68
|
|
|
@@ -74,54 +76,51 @@
|
|
|
74
76
|
</script>
|
|
75
77
|
|
|
76
78
|
<div class="banner-wrap">
|
|
77
|
-
<SettingsBanner
|
|
79
|
+
<SettingsBanner onclose={() => onclose()} {root} />
|
|
78
80
|
</div>
|
|
79
81
|
{#if space_id === null}
|
|
80
82
|
<!-- on Spaces, the theme is set in HF settings -->
|
|
81
83
|
<div class="banner-wrap">
|
|
82
|
-
<h2>{
|
|
83
|
-
<
|
|
84
|
+
<h2>{i18n("common.display_theme")}</h2>
|
|
85
|
+
<ul class="padded theme-buttons">
|
|
84
86
|
<li
|
|
85
87
|
class="theme-button {current_theme === 'light'
|
|
86
88
|
? 'current-theme'
|
|
87
89
|
: 'inactive-theme'}"
|
|
88
|
-
on:click={() => setTheme("light")}
|
|
89
90
|
>
|
|
90
|
-
<button>☀︎ Light</button>
|
|
91
|
+
<button on:click={() => setTheme("light")}>☀︎ Light</button>
|
|
91
92
|
</li>
|
|
92
93
|
<li
|
|
93
94
|
class="theme-button {current_theme === 'dark'
|
|
94
95
|
? 'current-theme'
|
|
95
96
|
: 'inactive-theme'}"
|
|
96
|
-
on:click={() => setTheme("dark")}
|
|
97
97
|
>
|
|
98
|
-
<button>⏾ Dark</button>
|
|
98
|
+
<button on:click={() => setTheme("dark")}>⏾ Dark</button>
|
|
99
99
|
</li>
|
|
100
100
|
<li
|
|
101
101
|
class="theme-button {current_theme === 'system'
|
|
102
102
|
? 'current-theme'
|
|
103
103
|
: 'inactive-theme'}"
|
|
104
|
-
on:click={() => setTheme("system")}
|
|
105
104
|
>
|
|
106
|
-
<button>🖥︎ System</button>
|
|
105
|
+
<button on:click={() => setTheme("system")}>🖥︎ System</button>
|
|
107
106
|
</li>
|
|
108
|
-
</
|
|
107
|
+
</ul>
|
|
109
108
|
</div>
|
|
110
109
|
{/if}
|
|
111
110
|
<div class="banner-wrap">
|
|
112
|
-
<h2>{
|
|
111
|
+
<h2>{i18n("common.language")}</h2>
|
|
113
112
|
<p class="padded">
|
|
114
113
|
<Dropdown
|
|
115
114
|
label="Language"
|
|
116
115
|
choices={language_choices}
|
|
117
116
|
show_label={false}
|
|
118
|
-
value={current_locale}
|
|
119
|
-
|
|
117
|
+
bind:value={current_locale}
|
|
118
|
+
on_change={() => handleLanguageChange(current_locale)}
|
|
120
119
|
/>
|
|
121
120
|
</p>
|
|
122
121
|
</div>
|
|
123
122
|
<div class="banner-wrap">
|
|
124
|
-
<h2>{
|
|
123
|
+
<h2>{i18n("common.pwa")}</h2>
|
|
125
124
|
<p class="padded">
|
|
126
125
|
{#if pwa_enabled}
|
|
127
126
|
You can install this app as a Progressive Web App on your device. Visit <a
|
|
@@ -135,7 +134,7 @@
|
|
|
135
134
|
</p>
|
|
136
135
|
</div>
|
|
137
136
|
<div class="banner-wrap">
|
|
138
|
-
<h2>{
|
|
137
|
+
<h2>{i18n("common.screen_studio")} <span class="beta-tag">beta</span></h2>
|
|
139
138
|
<p class="padded">
|
|
140
139
|
Screen Studio allows you to record your screen and generates a video of your
|
|
141
140
|
app with automatically adding zoom in and zoom out effects as well as
|
|
@@ -164,8 +163,8 @@
|
|
|
164
163
|
<button
|
|
165
164
|
class="record-button"
|
|
166
165
|
on:click={() => {
|
|
167
|
-
|
|
168
|
-
|
|
166
|
+
onclose?.();
|
|
167
|
+
start_recording?.();
|
|
169
168
|
}}
|
|
170
169
|
>
|
|
171
170
|
<img src={record} alt="Start Recording" />
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { createEventDispatcher } from "svelte";
|
|
3
2
|
import { _ } from "svelte-i18n";
|
|
4
3
|
import settings_logo from "./img/settings-logo.svg";
|
|
5
4
|
import Clear from "./img/clear.svelte";
|
|
6
5
|
import { setupi18n } from "../i18n";
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
let { root, onclose }: { root: string; onclose?: () => void } = $props();
|
|
9
8
|
|
|
10
|
-
const dispatch = createEventDispatcher();
|
|
11
9
|
setupi18n();
|
|
12
10
|
</script>
|
|
13
11
|
|
|
@@ -21,7 +19,7 @@
|
|
|
21
19
|
</div>
|
|
22
20
|
</h2>
|
|
23
21
|
|
|
24
|
-
<button on:click={() =>
|
|
22
|
+
<button on:click={() => onclose?.()}>
|
|
25
23
|
<Clear />
|
|
26
24
|
</button>
|
|
27
25
|
|
package/src/dependency.ts
CHANGED
|
@@ -113,7 +113,14 @@ export class Dependency {
|
|
|
113
113
|
if (this.functions.backend) {
|
|
114
114
|
return {
|
|
115
115
|
type: "submit",
|
|
116
|
-
data: client.submit(
|
|
116
|
+
data: client.submit(
|
|
117
|
+
this.id,
|
|
118
|
+
_data_payload,
|
|
119
|
+
event_data,
|
|
120
|
+
target_id,
|
|
121
|
+
undefined,
|
|
122
|
+
{ "x-gradio-user": "app" }
|
|
123
|
+
)
|
|
117
124
|
};
|
|
118
125
|
} else if (this.functions.frontend) {
|
|
119
126
|
return { type: "data", data: _data_payload };
|
|
@@ -320,7 +327,6 @@ export class DependencyManager {
|
|
|
320
327
|
`${event_meta.event_name}-${event_meta.target_id}`
|
|
321
328
|
);
|
|
322
329
|
}
|
|
323
|
-
|
|
324
330
|
for (let i = 0; i < (deps?.length || 0); i++) {
|
|
325
331
|
const dep = deps ? deps[i] : undefined;
|
|
326
332
|
if (dep) {
|
|
@@ -791,6 +797,14 @@ export class DependencyManager {
|
|
|
791
797
|
const submission = this.submissions.get(id);
|
|
792
798
|
if (submission) {
|
|
793
799
|
await submission.cancel();
|
|
800
|
+
this.loading_stati.update({
|
|
801
|
+
status: "complete",
|
|
802
|
+
fn_index: id,
|
|
803
|
+
eta: 0,
|
|
804
|
+
queue: false,
|
|
805
|
+
stream_state: null
|
|
806
|
+
});
|
|
807
|
+
this.update_loading_stati_state();
|
|
794
808
|
this.submissions.delete(id);
|
|
795
809
|
}
|
|
796
810
|
}
|