@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/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 = $_("blocks.long_requests_queue");
326
- const MOBILE_QUEUE_WARNING = $_("blocks.connection_can_break");
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 = $_("blocks.waiting_for_inputs");
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
- {#if footer_links.length > 0}
430
- <footer bind:clientHeight={footer_height}>
431
- {#if footer_links.includes("api")}
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
- screen_recording();
462
+ set_api_docs_visible(!api_docs_visible);
466
463
  }}
467
- class="record"
464
+ on:mouseenter={() => {
465
+ loadApiDocs();
466
+ loadApiRecorder();
467
+ }}
468
+ class="show-api"
468
469
  >
469
- {$_("common.stop_recording")}
470
- <img src={record_stop} alt={$_("common.stop_recording")} />
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
- <div class="divider">·</div>
473
- {#if footer_links.includes("settings")}
474
- <div class="divider" class:hidden={!$is_screen_recording}>·</div>
475
- <button
476
- on:click={() => {
477
- set_settings_visible(!settings_visible);
478
- }}
479
- on:mouseenter={() => {
480
- loadSettings();
481
- }}
482
- class="settings"
483
- >
484
- {$_("common.settings")}
485
- <img src={settings_logo} alt={$_("common.settings")} />
486
- </button>
487
- {/if}
488
- </footer>
489
- {/if}
490
- </div>
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
- on:close={() => {
588
+ onclose={() => {
556
589
  set_settings_visible(false);
557
590
  }}
558
- on:start_recording={() => {
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(e: CustomEvent): void {
63
- const new_locale = e.detail;
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 on:close {root} />
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>{$_("common.display_theme")}</h2>
83
- <p class="padded theme-buttons">
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>☀︎ &nbsp;Light</button>
91
+ <button on:click={() => setTheme("light")}>☀︎ &nbsp;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>⏾ &nbsp; Dark</button>
98
+ <button on:click={() => setTheme("dark")}>⏾ &nbsp; 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>🖥︎ &nbsp;System</button>
105
+ <button on:click={() => setTheme("system")}>🖥︎ &nbsp;System</button>
107
106
  </li>
108
- </p>
107
+ </ul>
109
108
  </div>
110
109
  {/if}
111
110
  <div class="banner-wrap">
112
- <h2>{$_("common.language")}</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
- on:change={handleLanguageChange}
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>{$_("common.pwa")}</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>{$_("common.screen_studio")} <span class="beta-tag">beta</span></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
- dispatch("close");
168
- dispatch("start_recording");
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
- export let root: string;
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={() => dispatch("close")}>
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(this.id, _data_payload, event_data, target_id)
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
  }