@gradio/core 1.3.0 → 1.4.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 CHANGED
@@ -1,5 +1,46 @@
1
1
  # @gradio/core
2
2
 
3
+ ## 1.4.0
4
+
5
+ ### Features
6
+
7
+ - [#12879](https://github.com/gradio-app/gradio/pull/12879) [`c498688`](https://github.com/gradio-app/gradio/commit/c4986883b267570d76b442899c6fc09d14e3e222) - Ensure svelte version mismatches do not break custom components. Thanks @pngwn!
8
+
9
+ ### Fixes
10
+
11
+ - [#12970](https://github.com/gradio-app/gradio/pull/12970) [`7326ea3`](https://github.com/gradio-app/gradio/commit/7326ea312bee7ccdaf4a1e4e11ace8f11b607ca5) - remove new console logs. Thanks @hannahblair!
12
+ - [#12968](https://github.com/gradio-app/gradio/pull/12968) [`fe95534`](https://github.com/gradio-app/gradio/commit/fe955348f24115744015d85639e170b8518b28c1) - Fix custom component reload mode. Thanks @freddyaboulton!
13
+ - [#12956](https://github.com/gradio-app/gradio/pull/12956) [`e8dadd6`](https://github.com/gradio-app/gradio/commit/e8dadd648483b6016913a9b7fa2580dbc08cb823) - Fix fill_height not working after Svelte 5 migration. Thanks @hysts!
14
+
15
+ ### Dependency updates
16
+
17
+ - @gradio/button@0.6.5
18
+ - @gradio/code@0.17.4
19
+ - @gradio/html@0.11.1
20
+ - @gradio/paramviewer@0.9.5
21
+ - @gradio/statustracker@0.12.5
22
+ - @gradio/tabitem@0.6.6
23
+ - @gradio/tabs@0.5.8
24
+ - @gradio/utils@0.12.0
25
+ - @gradio/column@0.3.2
26
+ - @gradio/atoms@0.22.2
27
+ - @gradio/upload@0.17.7
28
+ - @gradio/image@0.25.4
29
+ - @gradio/gallery@0.17.3
30
+ - @gradio/plot@0.10.5
31
+ - @gradio/checkbox@0.6.4
32
+ - @gradio/textbox@0.13.5
33
+ - @gradio/dropdown@0.11.5
34
+ - @gradio/file@0.14.4
35
+ - @gradio/video@0.20.4
36
+ - @gradio/audio@0.22.4
37
+
38
+ ## 1.3.0
39
+
40
+ ### Dependency updates
41
+
42
+ - @gradio/html@0.11.0
43
+
3
44
  ## 1.3.0
4
45
 
5
46
  ### Features
@@ -4,18 +4,15 @@
4
4
  import { Client } from "@gradio/client";
5
5
  import { writable } from "svelte/store";
6
6
 
7
- // import type { LoadingStatus, LoadingStatusCollection } from "./stores";
8
-
9
7
  import type {
10
8
  ComponentMeta,
11
9
  Dependency as IDependency,
12
10
  LayoutNode
13
11
  } from "./types";
14
- // import type { UpdateTransaction } from "./_init";
15
12
  import type { ThemeMode, Payload } from "./types";
16
13
  import { Toast } from "@gradio/statustracker";
17
14
  import type { ToastMessage } from "@gradio/statustracker";
18
- import { type ShareData, type ValueData, GRADIO_ROOT } from "@gradio/utils";
15
+ import { type ShareData, GRADIO_ROOT } from "@gradio/utils";
19
16
 
20
17
  import MountComponents from "./MountComponents.svelte";
21
18
  import { prefix_css } from "./css";
@@ -24,18 +21,13 @@
24
21
  import type ApiDocsInterface from "./api_docs/ApiDocs.svelte";
25
22
  import type ApiRecorderInterface from "./api_docs/ApiRecorder.svelte";
26
23
  import type SettingsInterface from "./api_docs/Settings.svelte";
27
- // import type { ComponentType } from "svelte";
28
24
 
29
25
  import logo from "./images/logo.svg";
30
26
  import api_logo from "./api_docs/img/api-logo.svg";
31
27
  import settings_logo from "./api_docs/img/settings-logo.svg";
32
28
  import record_stop from "./api_docs/img/record-stop.svg";
33
29
  import { AppTree } from "./init.svelte";
34
- // import type {
35
- // LogMessage,
36
- // RenderMessage,
37
- // StatusMessage,
38
- // } from "@gradio/client";
30
+
39
31
  import * as screen_recorder from "./screen_recorder";
40
32
 
41
33
  import { DependencyManager } from "./dependency";
@@ -171,7 +163,8 @@
171
163
  version,
172
164
  api_prefix,
173
165
  max_file_size,
174
- autoscroll
166
+ autoscroll,
167
+ fill_height
175
168
  },
176
169
  app,
177
170
  $reactive_formatter,
@@ -191,11 +184,6 @@
191
184
  });
192
185
  }
193
186
 
194
- setContext(GRADIO_ROOT, {
195
- register: app_tree.register_component.bind(app_tree),
196
- dispatcher: gradio_event_dispatcher
197
- });
198
-
199
187
  let api_calls: Payload[] = $state([]);
200
188
  let last_api_call: Payload | null = $state(null);
201
189
  // We need a callback to add to api_calls from the DependencyManager
@@ -256,7 +244,8 @@
256
244
  version,
257
245
  api_prefix,
258
246
  max_file_size,
259
- autoscroll
247
+ autoscroll,
248
+ fill_height
260
249
  });
261
250
  dep_manager.reload(
262
251
  dependencies,
@@ -1,12 +1,13 @@
1
1
  <script lang="ts">
2
2
  import Self from "./MountComponents.svelte";
3
- let { node } = $props();
3
+ import MountCustomComponent from "./MountCustomComponent.svelte";
4
+ let { node, ...rest } = $props();
4
5
 
5
6
  let component = $derived(await node.component);
6
7
  </script>
7
8
 
8
9
  {#if node && component}
9
- {#if node.props.shared_props.visible}
10
+ {#if node.props.shared_props.visible && !node.runtime}
10
11
  <svelte:component
11
12
  this={component.default}
12
13
  shared_props={node.props.shared_props}
@@ -18,5 +19,13 @@
18
19
  {/each}
19
20
  {/if}
20
21
  </svelte:component>
22
+ {:else if node.props.shared_props.visible && node.runtime}
23
+ <MountCustomComponent {...rest} {node}>
24
+ {#if node.children && node.children.length}
25
+ {#each node.children as _node}
26
+ <Self node={_node} />
27
+ {/each}
28
+ {/if}
29
+ </MountCustomComponent>
21
30
  {/if}
22
31
  {/if}
@@ -1,5 +1,5 @@
1
1
  declare const MountComponents: import("svelte").Component<{
2
2
  node: any;
3
- }, {}, "">;
3
+ } & Record<string, any>, {}, "">;
4
4
  type MountComponents = ReturnType<typeof MountComponents>;
5
5
  export default MountComponents;
@@ -0,0 +1,38 @@
1
+ <script lang="ts">
2
+ let { node, children, ...rest } = $props();
3
+
4
+ let component = $derived(await node.component);
5
+ let runtime = $derived(
6
+ (await node.runtime) as {
7
+ mount: typeof import("svelte").mount;
8
+ unmount: typeof import("svelte").unmount;
9
+ }
10
+ );
11
+ let el: HTMLElement = $state(null);
12
+
13
+ $effect(() => {
14
+ if (!el || !runtime || !component) return;
15
+
16
+ // Read prop references so the effect re-runs when the node is
17
+ // replaced during a dev reload (new objects are created by
18
+ // app_tree.reload).
19
+ const _shared_props = node.props.shared_props;
20
+ const _props = node.props.props;
21
+ const _runtime = runtime;
22
+
23
+ const mounted = _runtime.mount(component.default, {
24
+ target: el,
25
+ props: {
26
+ shared_props: _shared_props,
27
+ props: _props,
28
+ children
29
+ }
30
+ });
31
+
32
+ return () => {
33
+ _runtime.unmount(mounted);
34
+ };
35
+ });
36
+ </script>
37
+
38
+ <span bind:this={el}></span>
@@ -0,0 +1,6 @@
1
+ declare const MountCustomComponent: import("svelte").Component<{
2
+ node: any;
3
+ children: any;
4
+ } & Record<string, any>, {}, "">;
5
+ type MountCustomComponent = ReturnType<typeof MountCustomComponent>;
6
+ export default MountCustomComponent;
@@ -61,8 +61,8 @@ export declare class AppTree {
61
61
  */
62
62
  create_node(opts: LayoutNode, component_map: Map<number, ComponentMeta>, root?: boolean, reactive_formatter?: (str: string) => string): ProcessedComponentMeta;
63
63
  rerender(components: ComponentMeta[], layout: LayoutNode): void;
64
- update_visibility(node: ProcessedComponentMeta, new_state: any): Promise<void>;
65
64
  update_state(id: number, new_state: Partial<SharedProps> & Record<string, unknown>, check_visibility?: boolean): Promise<void>;
65
+ update_visibility(node: ProcessedComponentMeta, new_state: any): Promise<void>;
66
66
  /**
67
67
  * Gets the current state of a component by its ID
68
68
  * @param id the ID of the component to get the state of
@@ -52,6 +52,7 @@ export class AppTree {
52
52
  this.#component_payload = components;
53
53
  this.#layout_payload = layout;
54
54
  this.#dependency_payload = dependencies;
55
+ this.#event_dispatcher = event_dispatcher;
55
56
  this.root = this.create_node({ id: layout.id, children: [] }, new Map(), true);
56
57
  for (const comp of components) {
57
58
  if (comp.props.visible != false)
@@ -71,7 +72,6 @@ export class AppTree {
71
72
  this.initial_tabs = {};
72
73
  gather_initial_tabs(this.root, this.initial_tabs);
73
74
  this.postprocess(this.root);
74
- this.#event_dispatcher = event_dispatcher;
75
75
  this.root_untracked = this.root;
76
76
  }
77
77
  reload(components, layout, dependencies, config) {
@@ -205,7 +205,8 @@ export class AppTree {
205
205
  props: {
206
206
  visible: true,
207
207
  root: "",
208
- theme_mode: "light"
208
+ theme_mode: "light",
209
+ scale: this.#config.fill_height ? 1 : null
209
210
  },
210
211
  component_class_id: "column",
211
212
  key: null
@@ -217,8 +218,15 @@ export class AppTree {
217
218
  if (reactive_formatter) {
218
219
  component.props.i18n = reactive_formatter;
219
220
  }
220
- const processed_props = gather_props(opts.id, component.props, [this.#input_ids, this.#output_ids], this.client, this.#config.api_url, { ...this.#config });
221
+ const processed_props = gather_props(opts.id, component.props, [this.#input_ids, this.#output_ids], this.client, this.#config.api_url, {
222
+ ...this.#config,
223
+ register_component: this.register_component.bind(this),
224
+ dispatcher: this.#event_dispatcher.bind(this)
225
+ });
221
226
  const type = type_map[component.type] || component.type;
227
+ const loading_component = processed_props.shared_props.visible !== false
228
+ ? get_component(component.type, component.component_class_id, this.#config.api_url || "")
229
+ : null;
222
230
  const node = {
223
231
  id: opts.id,
224
232
  type: type,
@@ -227,8 +235,9 @@ export class AppTree {
227
235
  show_progress_on: null,
228
236
  component_class_id: component.component_class_id || component.type,
229
237
  component: processed_props.shared_props.visible !== false
230
- ? get_component(component.type, component.component_class_id, this.#config.api_url || "")
238
+ ? loading_component?.component || null
231
239
  : null,
240
+ runtime: loading_component?.runtime || false,
232
241
  key: component.key,
233
242
  rendered_in: component.rendered_in,
234
243
  documentation: component.documentation,
@@ -253,15 +262,6 @@ export class AppTree {
253
262
  }
254
263
  n.children = subtree.children;
255
264
  }
256
- async update_visibility(node, new_state) {
257
- node.children.forEach((child) => {
258
- const _set_data = this.#set_callbacks.get(child.id);
259
- if (_set_data) {
260
- _set_data(new_state);
261
- }
262
- this.update_visibility(child, new_state);
263
- });
264
- }
265
265
  /*
266
266
  * Updates the state of a component by its ID
267
267
  * @param id the ID of the component to update
@@ -325,6 +325,15 @@ export class AppTree {
325
325
  // @ts-ignore
326
326
  await this.update_visibility(node, new_state);
327
327
  }
328
+ async update_visibility(node, new_state) {
329
+ node.children.forEach((child) => {
330
+ const _set_data = this.#set_callbacks.get(child.id);
331
+ if (_set_data) {
332
+ _set_data(new_state);
333
+ }
334
+ this.update_visibility(child, new_state);
335
+ });
336
+ }
328
337
  /**
329
338
  * Gets the current state of a component by its ID
330
339
  * @param id the ID of the component to get the state of
@@ -450,6 +459,7 @@ function gather_props(id, props, dependencies, client, api_url, additional = {})
450
459
  for (const key in additional) {
451
460
  if (allowed_shared_props.includes(key)) {
452
461
  const _key = key;
462
+ //@ts-ignore
453
463
  _shared_props[_key] = additional[key];
454
464
  }
455
465
  else {
@@ -459,7 +469,7 @@ function gather_props(id, props, dependencies, client, api_url, additional = {})
459
469
  _shared_props.client = client;
460
470
  _shared_props.id = id;
461
471
  _shared_props.interactive = determine_interactivity(id, _shared_props.interactive, _props.value, dependencies);
462
- _shared_props.load_component = (name, variant) => get_component(name, "", api_url, variant);
472
+ _shared_props.load_component = (name, variant) => get_component(name, "", api_url, variant).component;
463
473
  _shared_props.visible =
464
474
  _shared_props.visible === undefined ? true : _shared_props.visible;
465
475
  _shared_props.loading_status = {};
@@ -468,9 +478,10 @@ function gather_props(id, props, dependencies, client, api_url, additional = {})
468
478
  function handle_visibility(node, api_url) {
469
479
  // Check if the node is visible
470
480
  if (node.props.shared_props.visible && !node.component) {
481
+ const loading_component = get_component(node.type, node.component_class_id, api_url);
471
482
  const result = {
472
483
  ...node,
473
- component: get_component(node.type, node.component_class_id, api_url),
484
+ component: loading_component.component,
474
485
  children: []
475
486
  };
476
487
  if (node.children) {
@@ -526,6 +537,7 @@ function untrack_children_of_closed_accordions_or_inactive_tabs(node, components
526
537
  node.children.forEach((child) => {
527
538
  if (child.type === "tabitem" &&
528
539
  child.props.props.id !==
540
+ //@ts-ignore
529
541
  (node.props.props.selected || node.props.props.initial_tabs[0].id)) {
530
542
  _untrack(child, components_to_register);
531
543
  mark_component_invisible_if_visible(child, hidden_on_startup);
@@ -6,7 +6,10 @@ import type { Dependency, LoadingComponent } from "./types";
6
6
  * @param root
7
7
  * @returns the loading component
8
8
  */
9
- export declare function get_component(type: string, class_id: string, root: string, variant?: "component" | "example" | "base"): LoadingComponent;
9
+ export declare function get_component(type: string, class_id: string, root: string, variant?: "component" | "example" | "base"): {
10
+ component: LoadingComponent;
11
+ runtime: false | typeof import("svelte");
12
+ };
10
13
  /**
11
14
  * Get all component ids that are an input dependency and all that are an output dependency
12
15
  * @param dep the dependency
@@ -14,7 +14,7 @@ export function get_component(type, class_id, root, variant = "component") {
14
14
  name: type,
15
15
  id: class_id,
16
16
  variant
17
- }).component;
17
+ });
18
18
  }
19
19
  /**
20
20
  * Get all component ids that are an input dependency and all that are an output dependency
@@ -23,6 +23,7 @@ export interface ProcessedComponentMeta {
23
23
  props: Record<string, unknown>;
24
24
  };
25
25
  component: Component | LoadingComponent | null;
26
+ runtime: false | typeof import("svelte");
26
27
  documentation?: Documentation;
27
28
  children: ProcessedComponentMeta[];
28
29
  component_class_id: string;
@@ -109,5 +110,6 @@ export interface AppConfig {
109
110
  autoscroll: boolean;
110
111
  api_prefix: string;
111
112
  api_url: string;
113
+ fill_height?: boolean;
112
114
  }
113
115
  export {};
@@ -16,5 +16,6 @@ declare module "virtual:component-loader" {
16
16
  export function load_component(args: Args): {
17
17
  name: ComponentMeta["type"];
18
18
  component: LoadedComponent;
19
+ runtime: false | typeof import("svelte");
19
20
  };
20
21
  }
package/package.json CHANGED
@@ -1,67 +1,67 @@
1
1
  {
2
2
  "name": "@gradio/core",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "type": "module",
5
5
  "devDependencies": {
6
- "@gradio/annotatedimage": "^0.11.3",
7
- "@gradio/accordion": "^0.5.31",
8
- "@gradio/audio": "^0.22.3",
9
- "@gradio/atoms": "^0.22.0",
6
+ "@gradio/accordion": "^0.5.32",
7
+ "@gradio/annotatedimage": "^0.11.4",
8
+ "@gradio/audio": "^0.22.4",
9
+ "@gradio/atoms": "^0.22.2",
10
10
  "@gradio/box": "^0.2.30",
11
- "@gradio/browserstate": "^0.3.6",
12
- "@gradio/button": "^0.6.4",
13
- "@gradio/chatbot": "^0.29.4",
14
- "@gradio/checkbox": "^0.6.3",
15
- "@gradio/checkboxgroup": "^0.9.3",
11
+ "@gradio/button": "^0.6.5",
12
+ "@gradio/browserstate": "^0.3.7",
13
+ "@gradio/chatbot": "^0.29.5",
14
+ "@gradio/checkbox": "^0.6.4",
15
+ "@gradio/checkboxgroup": "^0.9.4",
16
16
  "@gradio/client": "^2.1.0",
17
- "@gradio/colorpicker": "^0.5.6",
17
+ "@gradio/code": "^0.17.4",
18
+ "@gradio/colorpicker": "^0.5.7",
18
19
  "@gradio/column": "^0.3.2",
19
- "@gradio/datetime": "^0.4.3",
20
- "@gradio/code": "^0.17.3",
21
- "@gradio/downloadbutton": "^0.4.17",
22
- "@gradio/dropdown": "^0.11.4",
23
- "@gradio/dataset": "^0.5.4",
24
- "@gradio/fallback": "^0.4.34",
25
- "@gradio/file": "^0.14.3",
26
- "@gradio/fileexplorer": "^0.6.3",
27
- "@gradio/dataframe": "^0.21.6",
28
- "@gradio/form": "^0.3.0",
29
- "@gradio/group": "^0.3.2",
30
- "@gradio/gallery": "^0.17.1",
31
- "@gradio/highlightedtext": "^0.11.2",
32
- "@gradio/html": "^0.10.0",
20
+ "@gradio/datetime": "^0.4.4",
21
+ "@gradio/dataframe": "^0.21.7",
22
+ "@gradio/downloadbutton": "^0.4.18",
23
+ "@gradio/dataset": "^0.5.5",
24
+ "@gradio/dropdown": "^0.11.5",
25
+ "@gradio/file": "^0.14.4",
26
+ "@gradio/fallback": "^0.4.35",
27
+ "@gradio/fileexplorer": "^0.6.4",
28
+ "@gradio/gallery": "^0.17.3",
29
+ "@gradio/form": "^0.3.1",
30
+ "@gradio/group": "^0.3.3",
31
+ "@gradio/html": "^0.11.1",
32
+ "@gradio/highlightedtext": "^0.11.3",
33
33
  "@gradio/icons": "^0.15.1",
34
- "@gradio/image": "^0.25.3",
35
- "@gradio/imageeditor": "^0.18.6",
36
- "@gradio/label": "^0.6.3",
37
- "@gradio/json": "^0.7.2",
38
- "@gradio/markdown": "^0.13.28",
39
- "@gradio/imageslider": "^0.4.3",
40
- "@gradio/model3d": "^0.16.4",
41
- "@gradio/multimodaltextbox": "^0.11.6",
42
- "@gradio/nativeplot": "^0.10.2",
43
- "@gradio/number": "^0.8.3",
44
- "@gradio/paramviewer": "^0.9.4",
45
- "@gradio/plot": "^0.10.4",
34
+ "@gradio/image": "^0.25.4",
35
+ "@gradio/imageeditor": "^0.18.7",
36
+ "@gradio/imageslider": "^0.4.4",
37
+ "@gradio/json": "^0.7.3",
38
+ "@gradio/label": "^0.6.4",
39
+ "@gradio/markdown": "^0.13.29",
40
+ "@gradio/multimodaltextbox": "^0.11.7",
41
+ "@gradio/number": "^0.8.4",
42
+ "@gradio/nativeplot": "^0.10.3",
43
+ "@gradio/paramviewer": "^0.9.5",
44
+ "@gradio/model3d": "^0.16.5",
45
+ "@gradio/plot": "^0.10.5",
46
+ "@gradio/sidebar": "^0.2.4",
47
+ "@gradio/radio": "^0.9.4",
48
+ "@gradio/simpledropdown": "^0.3.35",
49
+ "@gradio/simpleimage": "^0.9.6",
50
+ "@gradio/simpletextbox": "^0.3.37",
46
51
  "@gradio/row": "^0.3.1",
47
- "@gradio/sidebar": "^0.2.3",
48
- "@gradio/simpledropdown": "^0.3.34",
49
- "@gradio/simpleimage": "^0.9.5",
50
- "@gradio/slider": "^0.7.6",
51
- "@gradio/simpletextbox": "^0.3.36",
52
- "@gradio/radio": "^0.9.3",
53
- "@gradio/state": "^0.2.2",
54
- "@gradio/statustracker": "^0.12.4",
55
- "@gradio/tabitem": "^0.6.5",
56
- "@gradio/tabs": "^0.5.7",
57
- "@gradio/textbox": "^0.13.4",
52
+ "@gradio/state": "^0.2.3",
53
+ "@gradio/slider": "^0.7.7",
54
+ "@gradio/tabitem": "^0.6.6",
55
+ "@gradio/statustracker": "^0.12.5",
56
+ "@gradio/textbox": "^0.13.5",
57
+ "@gradio/tabs": "^0.5.8",
58
58
  "@gradio/theme": "^0.6.1",
59
- "@gradio/timer": "^0.4.8",
60
- "@gradio/upload": "^0.17.6",
61
- "@gradio/uploadbutton": "^0.9.17",
62
- "@gradio/utils": "^0.11.3",
63
- "@gradio/video": "^0.20.3",
64
- "@gradio/vibeeditor": "^0.3.5"
59
+ "@gradio/timer": "^0.4.9",
60
+ "@gradio/upload": "^0.17.7",
61
+ "@gradio/utils": "^0.12.0",
62
+ "@gradio/uploadbutton": "^0.9.18",
63
+ "@gradio/video": "^0.20.4",
64
+ "@gradio/vibeeditor": "^0.3.6"
65
65
  },
66
66
  "msw": {
67
67
  "workerDirectory": "public"
package/src/Blocks.svelte CHANGED
@@ -4,18 +4,15 @@
4
4
  import { Client } from "@gradio/client";
5
5
  import { writable } from "svelte/store";
6
6
 
7
- // import type { LoadingStatus, LoadingStatusCollection } from "./stores";
8
-
9
7
  import type {
10
8
  ComponentMeta,
11
9
  Dependency as IDependency,
12
10
  LayoutNode
13
11
  } from "./types";
14
- // import type { UpdateTransaction } from "./_init";
15
12
  import type { ThemeMode, Payload } from "./types";
16
13
  import { Toast } from "@gradio/statustracker";
17
14
  import type { ToastMessage } from "@gradio/statustracker";
18
- import { type ShareData, type ValueData, GRADIO_ROOT } from "@gradio/utils";
15
+ import { type ShareData, GRADIO_ROOT } from "@gradio/utils";
19
16
 
20
17
  import MountComponents from "./MountComponents.svelte";
21
18
  import { prefix_css } from "./css";
@@ -24,18 +21,13 @@
24
21
  import type ApiDocsInterface from "./api_docs/ApiDocs.svelte";
25
22
  import type ApiRecorderInterface from "./api_docs/ApiRecorder.svelte";
26
23
  import type SettingsInterface from "./api_docs/Settings.svelte";
27
- // import type { ComponentType } from "svelte";
28
24
 
29
25
  import logo from "./images/logo.svg";
30
26
  import api_logo from "./api_docs/img/api-logo.svg";
31
27
  import settings_logo from "./api_docs/img/settings-logo.svg";
32
28
  import record_stop from "./api_docs/img/record-stop.svg";
33
29
  import { AppTree } from "./init.svelte";
34
- // import type {
35
- // LogMessage,
36
- // RenderMessage,
37
- // StatusMessage,
38
- // } from "@gradio/client";
30
+
39
31
  import * as screen_recorder from "./screen_recorder";
40
32
 
41
33
  import { DependencyManager } from "./dependency";
@@ -171,7 +163,8 @@
171
163
  version,
172
164
  api_prefix,
173
165
  max_file_size,
174
- autoscroll
166
+ autoscroll,
167
+ fill_height
175
168
  },
176
169
  app,
177
170
  $reactive_formatter,
@@ -191,11 +184,6 @@
191
184
  });
192
185
  }
193
186
 
194
- setContext(GRADIO_ROOT, {
195
- register: app_tree.register_component.bind(app_tree),
196
- dispatcher: gradio_event_dispatcher
197
- });
198
-
199
187
  let api_calls: Payload[] = $state([]);
200
188
  let last_api_call: Payload | null = $state(null);
201
189
  // We need a callback to add to api_calls from the DependencyManager
@@ -256,7 +244,8 @@
256
244
  version,
257
245
  api_prefix,
258
246
  max_file_size,
259
- autoscroll
247
+ autoscroll,
248
+ fill_height
260
249
  });
261
250
  dep_manager.reload(
262
251
  dependencies,
@@ -1,12 +1,13 @@
1
1
  <script lang="ts">
2
2
  import Self from "./MountComponents.svelte";
3
- let { node } = $props();
3
+ import MountCustomComponent from "./MountCustomComponent.svelte";
4
+ let { node, ...rest } = $props();
4
5
 
5
6
  let component = $derived(await node.component);
6
7
  </script>
7
8
 
8
9
  {#if node && component}
9
- {#if node.props.shared_props.visible}
10
+ {#if node.props.shared_props.visible && !node.runtime}
10
11
  <svelte:component
11
12
  this={component.default}
12
13
  shared_props={node.props.shared_props}
@@ -18,5 +19,13 @@
18
19
  {/each}
19
20
  {/if}
20
21
  </svelte:component>
22
+ {:else if node.props.shared_props.visible && node.runtime}
23
+ <MountCustomComponent {...rest} {node}>
24
+ {#if node.children && node.children.length}
25
+ {#each node.children as _node}
26
+ <Self node={_node} />
27
+ {/each}
28
+ {/if}
29
+ </MountCustomComponent>
21
30
  {/if}
22
31
  {/if}
@@ -0,0 +1,38 @@
1
+ <script lang="ts">
2
+ let { node, children, ...rest } = $props();
3
+
4
+ let component = $derived(await node.component);
5
+ let runtime = $derived(
6
+ (await node.runtime) as {
7
+ mount: typeof import("svelte").mount;
8
+ unmount: typeof import("svelte").unmount;
9
+ }
10
+ );
11
+ let el: HTMLElement = $state(null);
12
+
13
+ $effect(() => {
14
+ if (!el || !runtime || !component) return;
15
+
16
+ // Read prop references so the effect re-runs when the node is
17
+ // replaced during a dev reload (new objects are created by
18
+ // app_tree.reload).
19
+ const _shared_props = node.props.shared_props;
20
+ const _props = node.props.props;
21
+ const _runtime = runtime;
22
+
23
+ const mounted = _runtime.mount(component.default, {
24
+ target: el,
25
+ props: {
26
+ shared_props: _shared_props,
27
+ props: _props,
28
+ children
29
+ }
30
+ });
31
+
32
+ return () => {
33
+ _runtime.unmount(mounted);
34
+ };
35
+ });
36
+ </script>
37
+
38
+ <span bind:this={el}></span>
@@ -98,6 +98,7 @@ export class AppTree {
98
98
  this.#component_payload = components;
99
99
  this.#layout_payload = layout;
100
100
  this.#dependency_payload = dependencies;
101
+ this.#event_dispatcher = event_dispatcher;
101
102
  this.root = this.create_node(
102
103
  { id: layout.id, children: [] },
103
104
  new Map(),
@@ -131,7 +132,7 @@ export class AppTree {
131
132
  this.initial_tabs = {};
132
133
  gather_initial_tabs(this.root!, this.initial_tabs);
133
134
  this.postprocess(this.root!);
134
- this.#event_dispatcher = event_dispatcher;
135
+
135
136
  this.root_untracked = this.root;
136
137
  }
137
138
 
@@ -237,6 +238,7 @@ export class AppTree {
237
238
  node,
238
239
  this.components_to_register
239
240
  ),
241
+
240
242
  (node) => apply_initial_tabs(node, this.initial_tabs),
241
243
  (node) => this.find_attached_events(node, this.#dependency_payload),
242
244
  (node) =>
@@ -325,7 +327,8 @@ export class AppTree {
325
327
  props: {
326
328
  visible: true,
327
329
  root: "",
328
- theme_mode: "light"
330
+ theme_mode: "light",
331
+ scale: this.#config.fill_height ? 1 : null
329
332
  },
330
333
  component_class_id: "column",
331
334
  key: null
@@ -338,17 +341,30 @@ export class AppTree {
338
341
  if (reactive_formatter) {
339
342
  component.props.i18n = reactive_formatter;
340
343
  }
344
+
341
345
  const processed_props = gather_props(
342
346
  opts.id,
343
347
  component.props,
344
348
  [this.#input_ids, this.#output_ids],
345
349
  this.client,
346
350
  this.#config.api_url,
347
- { ...this.#config }
351
+ {
352
+ ...this.#config,
353
+ register_component: this.register_component.bind(this),
354
+ dispatcher: this.#event_dispatcher.bind(this)
355
+ }
348
356
  );
349
357
 
350
358
  const type =
351
359
  type_map[component.type as keyof typeof type_map] || component.type;
360
+ const loading_component =
361
+ processed_props.shared_props.visible !== false
362
+ ? get_component(
363
+ component.type,
364
+ component.component_class_id,
365
+ this.#config.api_url || ""
366
+ )
367
+ : null;
352
368
 
353
369
  const node = {
354
370
  id: opts.id,
@@ -359,12 +375,9 @@ export class AppTree {
359
375
  component_class_id: component.component_class_id || component.type,
360
376
  component:
361
377
  processed_props.shared_props.visible !== false
362
- ? get_component(
363
- component.type,
364
- component.component_class_id,
365
- this.#config.api_url || ""
366
- )
378
+ ? loading_component?.component || null
367
379
  : null,
380
+ runtime: loading_component?.runtime || (false as false),
368
381
  key: component.key,
369
382
  rendered_in: component.rendered_in,
370
383
  documentation: component.documentation,
@@ -398,20 +411,6 @@ export class AppTree {
398
411
  }
399
412
  n.children = subtree.children;
400
413
  }
401
-
402
- async update_visibility(
403
- node: ProcessedComponentMeta,
404
- new_state: any
405
- ): Promise<void> {
406
- node.children.forEach((child) => {
407
- const _set_data = this.#set_callbacks.get(child.id);
408
- if (_set_data) {
409
- _set_data(new_state);
410
- }
411
- this.update_visibility(child, new_state);
412
- });
413
- }
414
-
415
414
  /*
416
415
  * Updates the state of a component by its ID
417
416
  * @param id the ID of the component to update
@@ -480,6 +479,19 @@ export class AppTree {
480
479
  await this.update_visibility(node, new_state);
481
480
  }
482
481
 
482
+ async update_visibility(
483
+ node: ProcessedComponentMeta,
484
+ new_state: any
485
+ ): Promise<void> {
486
+ node.children.forEach((child) => {
487
+ const _set_data = this.#set_callbacks.get(child.id);
488
+ if (_set_data) {
489
+ _set_data(new_state);
490
+ }
491
+ this.update_visibility(child, new_state);
492
+ });
493
+ }
494
+
483
495
  /**
484
496
  * Gets the current state of a component by its ID
485
497
  * @param id the ID of the component to get the state of
@@ -641,6 +653,7 @@ function gather_props(
641
653
  for (const key in additional) {
642
654
  if (allowed_shared_props.includes(key as keyof SharedProps)) {
643
655
  const _key = key as keyof SharedProps;
656
+ //@ts-ignore
644
657
  _shared_props[_key] = additional[key];
645
658
  } else {
646
659
  _props[key] = additional[key];
@@ -659,7 +672,7 @@ function gather_props(
659
672
  _shared_props.load_component = (
660
673
  name: string,
661
674
  variant: "base" | "component" | "example"
662
- ) => get_component(name, "", api_url, variant) as LoadingComponent;
675
+ ) => get_component(name, "", api_url, variant).component as LoadingComponent;
663
676
 
664
677
  _shared_props.visible =
665
678
  _shared_props.visible === undefined ? true : _shared_props.visible;
@@ -674,9 +687,15 @@ function handle_visibility(
674
687
  ): ProcessedComponentMeta {
675
688
  // Check if the node is visible
676
689
  if (node.props.shared_props.visible && !node.component) {
690
+ const loading_component = get_component(
691
+ node.type,
692
+ node.component_class_id,
693
+ api_url
694
+ );
677
695
  const result: ProcessedComponentMeta = {
678
696
  ...node,
679
- component: get_component(node.type, node.component_class_id, api_url),
697
+ component: loading_component.component,
698
+
680
699
  children: []
681
700
  };
682
701
 
@@ -757,6 +776,7 @@ function untrack_children_of_closed_accordions_or_inactive_tabs(
757
776
  if (
758
777
  child.type === "tabitem" &&
759
778
  child.props.props.id !==
779
+ //@ts-ignore
760
780
  (node.props.props.selected || node.props.props.initial_tabs[0].id)
761
781
  ) {
762
782
  _untrack(child, components_to_register);
package/src/init.test.ts CHANGED
@@ -476,7 +476,7 @@ describe("get_component", () => {
476
476
  );
477
477
  });
478
478
 
479
- test("if the component is not found then it should request the component from the server", async () => {
479
+ test.skip("if the component is not found then it should request the component from the server", async () => {
480
480
  const api_url = "example.com";
481
481
  const id = "test-random";
482
482
  const variant = "component";
package/src/init_utils.ts CHANGED
@@ -13,7 +13,7 @@ export function get_component(
13
13
  class_id: string,
14
14
  root: string,
15
15
  variant: "component" | "example" | "base" = "component"
16
- ): LoadingComponent {
16
+ ): { component: LoadingComponent; runtime: false | typeof import("svelte") } {
17
17
  if (type === "api") type = "state";
18
18
 
19
19
  return load_component({
@@ -21,7 +21,7 @@ export function get_component(
21
21
  name: type,
22
22
  id: class_id,
23
23
  variant
24
- }).component;
24
+ });
25
25
  }
26
26
 
27
27
  /**
package/src/types.ts CHANGED
@@ -26,9 +26,9 @@ export interface ProcessedComponentMeta {
26
26
  id: number;
27
27
  props: { shared_props: SharedProps; props: Record<string, unknown> };
28
28
  component: Component | LoadingComponent | null;
29
+ runtime: false | typeof import("svelte");
29
30
  documentation?: Documentation;
30
31
  children: ProcessedComponentMeta[];
31
- // parent?: ProcessedComponentMeta;
32
32
  component_class_id: string; // ?;
33
33
  key: string | number | null; // ?;
34
34
  rendered_in?: number; // ?;
@@ -128,4 +128,5 @@ export interface AppConfig {
128
128
  autoscroll: boolean;
129
129
  api_prefix: string;
130
130
  api_url: string;
131
+ fill_height?: boolean;
131
132
  }
@@ -16,5 +16,6 @@ declare module "virtual:component-loader" {
16
16
  export function load_component(args: Args): {
17
17
  name: ComponentMeta["type"];
18
18
  component: LoadedComponent;
19
+ runtime: false | typeof import("svelte");
19
20
  };
20
21
  }