@gradio/core 1.0.0 → 1.0.2

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
@@ -40,7 +40,6 @@
40
40
  import * as screen_recorder from "./screen_recorder";
41
41
 
42
42
  import { DependencyManager } from "./dependency";
43
-
44
43
  let {
45
44
  root,
46
45
  components,
@@ -105,27 +104,6 @@
105
104
  }
106
105
  });
107
106
 
108
- let app_tree = new AppTree(
109
- components,
110
- layout,
111
- dependencies,
112
- {
113
- root,
114
- theme: theme_mode,
115
- version,
116
- api_prefix,
117
- max_file_size,
118
- autoscroll
119
- },
120
- app,
121
- $reactive_formatter
122
- );
123
-
124
- setContext(GRADIO_ROOT, {
125
- register: app_tree.register_component.bind(app_tree),
126
- dispatcher: gradio_event_dispatcher
127
- });
128
-
129
107
  let messages: (ToastMessage & { fn_index: number })[] = $state([]);
130
108
 
131
109
  function gradio_event_dispatcher(
@@ -138,11 +116,17 @@
138
116
  // trigger_share(title, description);
139
117
  // TODO: lets combine all of the into a log type with levels
140
118
  } else if (event === "error") {
141
- new_message("Error", data, -1, event, 10, true);
119
+ new_message("Error", data as string, -1, event, 10, true);
142
120
  } else if (event === "warning") {
143
- new_message("Warning", data, -1, event, 10, true);
121
+ new_message("Warning", data as string, -1, event, 10, true);
144
122
  } else if (event === "info") {
145
- new_message("Info", data, -1, event, 10, true);
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_);
146
130
  } else if (event == "clear_status") {
147
131
  app_tree.update_state(
148
132
  id,
@@ -163,7 +147,7 @@
163
147
  // so we need to pull out the correct id here.
164
148
  if (event === "select" && id in app_tree.initial_tabs) {
165
149
  // this is the id of the selected tab
166
- id = data.id;
150
+ id = (data as { id: number }).id;
167
151
  }
168
152
  dep_manager.dispatch({
169
153
  type: "event",
@@ -174,6 +158,28 @@
174
158
  }
175
159
  }
176
160
 
161
+ let app_tree = new AppTree(
162
+ components,
163
+ layout,
164
+ dependencies,
165
+ {
166
+ root,
167
+ theme: theme_mode,
168
+ version,
169
+ api_prefix,
170
+ max_file_size,
171
+ autoscroll
172
+ },
173
+ app,
174
+ $reactive_formatter,
175
+ gradio_event_dispatcher
176
+ );
177
+
178
+ setContext(GRADIO_ROOT, {
179
+ register: app_tree.register_component.bind(app_tree),
180
+ dispatcher: gradio_event_dispatcher
181
+ });
182
+
177
183
  let api_calls: Payload[] = $state([]);
178
184
  let last_api_call: Payload | null = $state(null);
179
185
  // We need a callback to add to api_calls from the DependencyManager
@@ -239,8 +245,8 @@
239
245
  if (!ApiDocs || !ApiRecorder) {
240
246
  const api_docs_module = await import("./api_docs/ApiDocs.svelte");
241
247
  const api_recorder_module = await import("./api_docs/ApiRecorder.svelte");
242
- if (!ApiDocs) ApiDocs = api_docs_module.default;
243
- if (!ApiRecorder) ApiRecorder = api_recorder_module.default;
248
+ if (!ApiDocs) ApiDocs = api_docs_module?.default;
249
+ if (!ApiRecorder) ApiRecorder = api_recorder_module?.default;
244
250
  }
245
251
  }
246
252
 
@@ -323,8 +329,10 @@
323
329
 
324
330
  const MESSAGE_QUOTE_RE = /^'([^]+)'$/;
325
331
 
326
- const DUPLICATE_MESSAGE = $_("blocks.long_requests_queue");
327
- const MOBILE_QUEUE_WARNING = $_("blocks.connection_can_break");
332
+ const DUPLICATE_MESSAGE = $reactive_formatter("blocks.long_requests_queue");
333
+ const MOBILE_QUEUE_WARNING = $reactive_formatter(
334
+ "blocks.connection_can_break"
335
+ );
328
336
  const LOST_CONNECTION_MESSAGE =
329
337
  "Connection to the server was lost. Attempting reconnection...";
330
338
  const CHANGED_CONNECTION_MESSAGE =
@@ -332,7 +340,9 @@
332
340
  const RECONNECTION_MESSAGE = "Connection re-established.";
333
341
  const SESSION_NOT_FOUND_MESSAGE =
334
342
  "Session not found - this is likely because the machine you were connected to has changed. <a href=''>Refresh the page</a> to continue.";
335
- const WAITING_FOR_INPUTS_MESSAGE = $_("blocks.waiting_for_inputs");
343
+ const WAITING_FOR_INPUTS_MESSAGE = $reactive_formatter(
344
+ "blocks.waiting_for_inputs"
345
+ );
336
346
  const SHOW_DUPLICATE_MESSAGE_ON_ETA = 15;
337
347
  const SHOW_MOBILE_QUEUE_WARNING_ON_ETA = 10;
338
348
  let is_mobile_device = false;
@@ -441,11 +451,11 @@
441
451
  class="show-api"
442
452
  >
443
453
  {#if app.config?.mcp_server}
444
- {$_("errors.use_via_api_or_mcp")}
454
+ {$reactive_formatter("errors.use_via_api_or_mcp")}
445
455
  {:else}
446
- {$_("errors.use_via_api")}
456
+ {$reactive_formatter("errors.use_via_api")}
447
457
  {/if}
448
- <img src={api_logo} alt={$_("common.logo")} />
458
+ <img src={api_logo} alt={$reactive_formatter("common.logo")} />
449
459
  </button>
450
460
  {/if}
451
461
  {#if footer_links.includes("gradio")}
@@ -456,8 +466,8 @@
456
466
  target="_blank"
457
467
  rel="noreferrer"
458
468
  >
459
- {$_("common.built_with_gradio")}
460
- <img src={logo} alt={$_("common.logo")} />
469
+ {$reactive_formatter("common.built_with_gradio")}
470
+ <img src={logo} alt={$reactive_formatter("common.logo")} />
461
471
  </a>
462
472
  {/if}
463
473
  <button
@@ -467,8 +477,11 @@
467
477
  }}
468
478
  class="record"
469
479
  >
470
- {$_("common.stop_recording")}
471
- <img src={record_stop} alt={$_("common.stop_recording")} />
480
+ {$reactive_formatter("common.stop_recording")}
481
+ <img
482
+ src={record_stop}
483
+ alt={$reactive_formatter("common.stop_recording")}
484
+ />
472
485
  </button>
473
486
  <div class="divider">·</div>
474
487
  {#if footer_links.includes("settings")}
@@ -482,8 +495,11 @@
482
495
  }}
483
496
  class="settings"
484
497
  >
485
- {$_("common.settings")}
486
- <img src={settings_logo} alt={$_("common.settings")} />
498
+ {$reactive_formatter("common.settings")}
499
+ <img
500
+ src={settings_logo}
501
+ alt={$reactive_formatter("common.settings")}
502
+ />
487
503
  </button>
488
504
  {/if}
489
505
  </footer>
@@ -553,15 +569,16 @@
553
569
  this={Settings}
554
570
  bind:allow_zoom
555
571
  bind:allow_video_trim
556
- on:close={() => {
572
+ onclose={() => {
557
573
  set_settings_visible(false);
558
574
  }}
559
- on:start_recording={() => {
575
+ start_recording={() => {
560
576
  screen_recording();
561
577
  }}
562
578
  pwa_enabled={app.config.pwa}
563
579
  {root}
564
580
  {space_id}
581
+ i18n={$reactive_formatter}
565
582
  />
566
583
  </div>
567
584
  </div>
package/src/Login.svelte CHANGED
@@ -1,14 +1,14 @@
1
1
  <script lang="ts">
2
- import Form from "@gradio/form";
2
+ import { BaseForm } from "@gradio/form";
3
3
  import { BaseTextbox as Textbox } from "@gradio/textbox";
4
4
  import { BaseButton } from "@gradio/button";
5
- import Column from "@gradio/column";
5
+ import { BaseColumn } from "@gradio/column";
6
6
  import { Block } from "@gradio/atoms";
7
- import { _ } from "svelte-i18n";
8
7
  export let root: string;
9
8
  export let auth_message: string | null;
10
9
  export let app_mode: boolean;
11
10
  export let space_id: string | null;
11
+ export let i18n: (s: string) => string;
12
12
 
13
13
  let username = "";
14
14
  let password = "";
@@ -34,23 +34,23 @@
34
34
  </script>
35
35
 
36
36
  <div class="wrap" class:min-h-screen={app_mode}>
37
- <Column variant="panel" min_width={480}>
38
- <h2>{$_("login.login")}</h2>
37
+ <BaseColumn variant="panel" min_width={480}>
38
+ <h2>{i18n("login.login")}</h2>
39
39
  {#if auth_message}
40
40
  <p class="auth">{@html auth_message}</p>
41
41
  {/if}
42
42
  {#if space_id}
43
43
  <p class="auth">
44
- {$_("login.enable_cookies")}
44
+ {i18n("login.enable_cookies")}
45
45
  </p>
46
46
  {/if}
47
47
  {#if incorrect_credentials}
48
- <p class="creds">{$_("login.incorrect_credentials")}</p>
48
+ <p class="creds">{i18n("login.incorrect_credentials")}</p>
49
49
  {/if}
50
- <Form>
50
+ <BaseForm>
51
51
  <Block>
52
52
  <Textbox
53
- label={$_("login.username")}
53
+ label={i18n("login.username")}
54
54
  lines={1}
55
55
  show_label={true}
56
56
  max_lines={1}
@@ -61,7 +61,7 @@
61
61
 
62
62
  <Block>
63
63
  <Textbox
64
- label={$_("login.password")}
64
+ label={i18n("login.password")}
65
65
  lines={1}
66
66
  show_label={true}
67
67
  max_lines={1}
@@ -70,12 +70,12 @@
70
70
  bind:value={password}
71
71
  />
72
72
  </Block>
73
- </Form>
73
+ </BaseForm>
74
74
 
75
75
  <BaseButton size="lg" variant="primary" on:click={submit}
76
- >{$_("login.login")}</BaseButton
76
+ >{i18n("login.login")}</BaseButton
77
77
  >
78
- </Column>
78
+ </BaseColumn>
79
79
  </div>
80
80
 
81
81
  <style>
@@ -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
@@ -9,7 +9,11 @@ import { AsyncFunction } from "./init_utils";
9
9
  import { Client, type client_return } from "@gradio/client";
10
10
  import { LoadingStatus, type LoadingStatusArgs } from "@gradio/statustracker";
11
11
  import type { ToastMessage } from "@gradio/statustracker";
12
- import type { StatusMessage, ValidationError } from "@gradio/client";
12
+ import type {
13
+ StatusMessage,
14
+ ValidationError,
15
+ LogMessage
16
+ } from "@gradio/client";
13
17
  const MESSAGE_QUOTE_RE = /^'([^]+)'$/;
14
18
 
15
19
  const NOVALUE = Symbol("NOVALUE");
@@ -150,6 +154,25 @@ interface DispatchEvent {
150
154
  event_data: unknown;
151
155
  }
152
156
 
157
+ type UpdateStateCallback = (
158
+ id: number,
159
+ state: Record<string, unknown>,
160
+ check_visibility?: boolean
161
+ ) => Promise<void>;
162
+ type GetStateCallback = (id: number) => Promise<Record<string, unknown> | null>;
163
+ type RerenderCallback = (
164
+ components: ComponentMeta[],
165
+ layout: LayoutNode
166
+ ) => void;
167
+ type LogCallback = (
168
+ title: string,
169
+ message: string,
170
+ fn_index: number,
171
+ type: ToastMessage["type"],
172
+ duration?: number | null,
173
+ visible?: boolean
174
+ ) => void;
175
+
153
176
  /**
154
177
  * Manages all dependencies for an app acting as a bridge between app state and Dependencies
155
178
  * Responsible for registering dependencies and dispatching events to them
@@ -171,21 +194,11 @@ export class DependencyManager {
171
194
  queue: Set<number> = new Set();
172
195
  add_to_api_calls: (payload: Payload) => void;
173
196
 
174
- update_state_cb: (
175
- id: number,
176
- state: Record<string, unknown>,
177
- check_visibility?: boolean
178
- ) => Promise<void>;
179
- get_state_cb: (id: number) => Promise<Record<string, unknown> | null>;
180
- rerender_cb: (components: ComponentMeta[], layout: LayoutNode) => void;
181
- log_cb: (
182
- title: string,
183
- message: string,
184
- fn_index: number,
185
- type: ToastMessage["type"],
186
- duration?: number | null,
187
- visible?: boolean
188
- ) => void;
197
+ update_state_cb: UpdateStateCallback;
198
+ get_state_cb: GetStateCallback;
199
+ rerender_cb: RerenderCallback;
200
+ log_cb: LogCallback;
201
+
189
202
  loading_stati = new LoadingStatus();
190
203
 
191
204
  constructor(
@@ -213,6 +226,7 @@ export class DependencyManager {
213
226
  this.update_state_cb = update_state_cb;
214
227
  this.get_state_cb = get_state_cb;
215
228
  this.rerender_cb = rerender_cb;
229
+ this.client = client;
216
230
  this.reload(
217
231
  dependencies,
218
232
  update_state_cb,
@@ -224,10 +238,10 @@ export class DependencyManager {
224
238
 
225
239
  reload(
226
240
  dependencies: IDependency[],
227
- update_state,
228
- get_state,
229
- rerender,
230
- client
241
+ update_state: UpdateStateCallback,
242
+ get_state: GetStateCallback,
243
+ rerender: RerenderCallback,
244
+ client: Client
231
245
  ) {
232
246
  const { by_id, by_event } = this.create(dependencies);
233
247
  this.dependencies_by_event = by_event;
@@ -306,7 +320,6 @@ export class DependencyManager {
306
320
  `${event_meta.event_name}-${event_meta.target_id}`
307
321
  );
308
322
  }
309
-
310
323
  for (let i = 0; i < (deps?.length || 0); i++) {
311
324
  const dep = deps ? deps[i] : undefined;
312
325
  if (dep) {
@@ -367,7 +380,7 @@ export class DependencyManager {
367
380
  data: data_payload,
368
381
  event_data: event_meta.event_data
369
382
  };
370
- submission!.send_chunk(payload);
383
+ submission!.send_chunk(payload as any);
371
384
  unset_args.forEach((fn) => fn());
372
385
  continue;
373
386
  }
@@ -508,8 +521,9 @@ export class DependencyManager {
508
521
  (_, b) => b
509
522
  );
510
523
  this.log_cb(
511
- result._title ?? "Error",
512
- _message,
524
+ //@ts-ignore
525
+ result?._title ?? "Error",
526
+ _message || "",
513
527
  fn_index,
514
528
  "error",
515
529
  status.duration,
@@ -776,6 +790,14 @@ export class DependencyManager {
776
790
  const submission = this.submissions.get(id);
777
791
  if (submission) {
778
792
  await submission.cancel();
793
+ this.loading_stati.update({
794
+ status: "complete",
795
+ fn_index: id,
796
+ eta: 0,
797
+ queue: false,
798
+ stream_state: null
799
+ });
800
+ this.update_loading_stati_state();
779
801
  this.submissions.delete(id);
780
802
  }
781
803
  }