@gradio/core 0.23.0 → 0.23.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/CHANGELOG.md +21 -0
- package/dist/src/Blocks.svelte +13 -2
- package/dist/src/RenderComponent.svelte +1 -0
- package/dist/src/api_docs/ApiDocs.svelte +27 -1
- package/dist/src/i18n.js +6 -0
- package/dist/src/init.d.ts +8 -1
- package/dist/src/init.js +26 -9
- package/dist/src/lang/get_lang_names.js +5 -0
- package/dist/src/lang/loading.d.ts +33 -0
- package/dist/src/lang/loading.js +33 -0
- package/package.json +22 -19
- package/src/Blocks.svelte +15 -2
- package/src/RenderComponent.svelte +1 -0
- package/src/api_docs/ApiDocs.svelte +31 -1
- package/src/i18n.test.ts +4 -1
- package/src/i18n.ts +7 -0
- package/src/init.ts +40 -11
- package/src/lang/get_lang_names.js +5 -0
- package/src/lang/loading.ts +33 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @gradio/core
|
|
2
2
|
|
|
3
|
+
## 0.23.2
|
|
4
|
+
|
|
5
|
+
### Fixes
|
|
6
|
+
|
|
7
|
+
- [#11632](https://github.com/gradio-app/gradio/pull/11632) [`8f19bff`](https://github.com/gradio-app/gradio/commit/8f19bffd04a73d4fc1080f5854caa0361516f3af) - ensure i18n is initialised before displaying localised loading text. Thanks @pngwn!
|
|
8
|
+
|
|
9
|
+
### Dependency updates
|
|
10
|
+
|
|
11
|
+
- @gradio/textbox@0.10.18
|
|
12
|
+
|
|
13
|
+
## 0.23.1
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
- [#11619](https://github.com/gradio-app/gradio/pull/11619) [`33c5d2b`](https://github.com/gradio-app/gradio/commit/33c5d2bb8214c0d7a90daca0f1eaf96411a52e79) - Add a query param for the selected language & make MCP the default option when `mcp_server` is enabled. Thanks @abidlabs!
|
|
18
|
+
- [#11615](https://github.com/gradio-app/gradio/pull/11615) [`e2b66d7`](https://github.com/gradio-app/gradio/commit/e2b66d718f3a8f57b6ee224502849ee737b1b120) - fix change events for hidden components. Thanks @pngwn!
|
|
19
|
+
|
|
20
|
+
### Fixes
|
|
21
|
+
|
|
22
|
+
- [#11599](https://github.com/gradio-app/gradio/pull/11599) [`c39d373`](https://github.com/gradio-app/gradio/commit/c39d3739bf2494ad13556174757cdd56060f033e) - Ensure component visibility is correctly propagated to all components. Thanks @copilot-swe-agent!
|
|
23
|
+
|
|
3
24
|
## 0.23.0
|
|
4
25
|
|
|
5
26
|
### Features
|
package/dist/src/Blocks.svelte
CHANGED
|
@@ -47,8 +47,11 @@ let {
|
|
|
47
47
|
loading_status,
|
|
48
48
|
scheduled_updates,
|
|
49
49
|
create_layout,
|
|
50
|
-
rerender_layout
|
|
51
|
-
|
|
50
|
+
rerender_layout,
|
|
51
|
+
value_change
|
|
52
|
+
} = create_components({
|
|
53
|
+
initial_layout
|
|
54
|
+
});
|
|
52
55
|
$:
|
|
53
56
|
components, layout, dependencies, root, app, fill_height, target, run();
|
|
54
57
|
$: {
|
|
@@ -674,6 +677,14 @@ async function handle_mount() {
|
|
|
674
677
|
});
|
|
675
678
|
render_complete = true;
|
|
676
679
|
}
|
|
680
|
+
value_change((id, value) => {
|
|
681
|
+
const deps = $targets[id]?.["change"];
|
|
682
|
+
deps?.forEach((dep_id) => {
|
|
683
|
+
requestAnimationFrame(() => {
|
|
684
|
+
wait_then_trigger_api_call(dep_id, id, value);
|
|
685
|
+
});
|
|
686
|
+
});
|
|
687
|
+
});
|
|
677
688
|
const handle_load_triggers = () => {
|
|
678
689
|
dependencies.forEach((dep) => {
|
|
679
690
|
if (dep.targets.some((dep2) => dep2[1] === "load")) {
|
|
@@ -35,6 +35,18 @@ if (!root.endsWith("/")) {
|
|
|
35
35
|
}
|
|
36
36
|
export let api_calls = [];
|
|
37
37
|
let current_language = "python";
|
|
38
|
+
function set_query_param(key, value) {
|
|
39
|
+
const url = new URL(window.location.href);
|
|
40
|
+
url.searchParams.set(key, value);
|
|
41
|
+
history.replaceState(null, "", url.toString());
|
|
42
|
+
}
|
|
43
|
+
function get_query_param(key) {
|
|
44
|
+
const url = new URL(window.location.href);
|
|
45
|
+
return url.searchParams.get(key);
|
|
46
|
+
}
|
|
47
|
+
function is_valid_language(lang) {
|
|
48
|
+
return ["python", "javascript", "bash", "mcp"].includes(lang ?? "");
|
|
49
|
+
}
|
|
38
50
|
const langs = [
|
|
39
51
|
["python", "Python", python],
|
|
40
52
|
["javascript", "JavaScript", javascript],
|
|
@@ -152,10 +164,21 @@ onMount(() => {
|
|
|
152
164
|
if ("parentIFrame" in window) {
|
|
153
165
|
window.parentIFrame?.scrollTo(0, 0);
|
|
154
166
|
}
|
|
167
|
+
const lang_param = get_query_param("lang");
|
|
168
|
+
if (is_valid_language(lang_param)) {
|
|
169
|
+
current_language = lang_param;
|
|
170
|
+
}
|
|
155
171
|
fetch(mcp_server_url).then((response) => {
|
|
156
172
|
mcp_server_active = response.ok;
|
|
157
173
|
if (mcp_server_active) {
|
|
158
174
|
fetchMcpTools();
|
|
175
|
+
if (!is_valid_language(lang_param)) {
|
|
176
|
+
current_language = "mcp";
|
|
177
|
+
}
|
|
178
|
+
} else {
|
|
179
|
+
if (!is_valid_language(lang_param)) {
|
|
180
|
+
current_language = "python";
|
|
181
|
+
}
|
|
159
182
|
}
|
|
160
183
|
}).catch(() => {
|
|
161
184
|
mcp_server_active = false;
|
|
@@ -189,7 +212,10 @@ onMount(() => {
|
|
|
189
212
|
<li
|
|
190
213
|
class="snippet
|
|
191
214
|
{current_language === language ? 'current-lang' : 'inactive-lang'}"
|
|
192
|
-
on:click={() =>
|
|
215
|
+
on:click={() => {
|
|
216
|
+
current_language = language;
|
|
217
|
+
set_query_param("lang", language);
|
|
218
|
+
}}
|
|
193
219
|
>
|
|
194
220
|
<img src={img} alt="" />
|
|
195
221
|
{display_name}
|
package/dist/src/i18n.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { addMessages, init, getLocaleFromNavigator, locale, register, waitLocale } from "svelte-i18n";
|
|
2
2
|
import { formatter } from "./gradio_helper";
|
|
3
|
+
import { loading } from "./lang/loading";
|
|
3
4
|
const lang_map = {
|
|
4
5
|
ar: "العربية",
|
|
5
6
|
ca: "Català",
|
|
@@ -166,4 +167,9 @@ export function load_translations(translations) {
|
|
|
166
167
|
catch (e) {
|
|
167
168
|
console.error("Error loading translations:", e);
|
|
168
169
|
}
|
|
170
|
+
for (const lang in loading) {
|
|
171
|
+
addMessages(lang, {
|
|
172
|
+
common: { loading: loading[lang] }
|
|
173
|
+
});
|
|
174
|
+
}
|
|
169
175
|
}
|
package/dist/src/init.d.ts
CHANGED
|
@@ -7,7 +7,13 @@ export interface UpdateTransaction {
|
|
|
7
7
|
value: any;
|
|
8
8
|
prop: string;
|
|
9
9
|
}
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Create a store with the layout and a map of targets
|
|
12
|
+
* @returns A store with the layout and a map of targets
|
|
13
|
+
*/
|
|
14
|
+
export declare function create_components({ initial_layout }?: {
|
|
15
|
+
initial_layout: ComponentMeta | undefined;
|
|
16
|
+
}): {
|
|
11
17
|
layout: Writable<ComponentMeta>;
|
|
12
18
|
targets: Writable<TargetMap>;
|
|
13
19
|
update_value: (updates: UpdateTransaction[]) => void;
|
|
@@ -34,6 +40,7 @@ export declare function create_components(initial_layout: ComponentMeta | undefi
|
|
|
34
40
|
root: string;
|
|
35
41
|
dependencies: Dependency[];
|
|
36
42
|
}) => void;
|
|
43
|
+
value_change: (cb: (id: number, value: any) => void) => void;
|
|
37
44
|
};
|
|
38
45
|
/** An async version of 'new Function' */
|
|
39
46
|
export declare const AsyncFunction: new (...args: string[]) => (...args: any[]) => Promise<any>;
|
package/dist/src/init.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { writable, get } from "svelte/store";
|
|
2
|
+
import { dequal } from "dequal";
|
|
2
3
|
import { load_component } from "virtual:component-loader";
|
|
3
4
|
import { create_loading_status_store } from "./stores";
|
|
4
5
|
import { _ } from "svelte-i18n";
|
|
@@ -11,8 +12,9 @@ const raf = is_browser
|
|
|
11
12
|
* Create a store with the layout and a map of targets
|
|
12
13
|
* @returns A store with the layout and a map of targets
|
|
13
14
|
*/
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
export function create_components({ initial_layout = undefined } = {
|
|
16
|
+
initial_layout: undefined
|
|
17
|
+
}) {
|
|
16
18
|
let _component_map;
|
|
17
19
|
let target_map = writable({});
|
|
18
20
|
let _target_map = {};
|
|
@@ -26,6 +28,10 @@ export function create_components(initial_layout) {
|
|
|
26
28
|
let app;
|
|
27
29
|
let keys_per_render_id = {};
|
|
28
30
|
let _rootNode;
|
|
31
|
+
let value_change_cb = null;
|
|
32
|
+
function value_change(cb) {
|
|
33
|
+
value_change_cb = cb;
|
|
34
|
+
}
|
|
29
35
|
// Store current layout and root for dynamic visibility recalculation
|
|
30
36
|
let current_layout;
|
|
31
37
|
let current_root;
|
|
@@ -182,17 +188,11 @@ export function create_components(initial_layout) {
|
|
|
182
188
|
if (!instance.component) {
|
|
183
189
|
const constructor_key = instance.component_class_id || instance.type;
|
|
184
190
|
let component_constructor = constructor_map.get(constructor_key);
|
|
185
|
-
// Only load component if it was preloaded (i.e., it's visible)
|
|
186
191
|
if (component_constructor) {
|
|
187
192
|
instance.component = (await component_constructor)?.default;
|
|
188
193
|
}
|
|
189
|
-
// If component wasn't preloaded, leave it unloaded for now
|
|
190
|
-
// It will be loaded later when/if it becomes visible
|
|
191
194
|
}
|
|
192
195
|
instance.parent = parent;
|
|
193
|
-
// if (instance.type === "timer") {
|
|
194
|
-
// console.log("timer", instance, constructor_map);
|
|
195
|
-
// }
|
|
196
196
|
if (instance.type === "dataset") {
|
|
197
197
|
instance.props.component_map = get_component(instance.type, instance.component_class_id, root, components, instance.props.components).example_components;
|
|
198
198
|
}
|
|
@@ -304,6 +304,7 @@ export function create_components(initial_layout) {
|
|
|
304
304
|
if (!instance)
|
|
305
305
|
continue;
|
|
306
306
|
let new_value;
|
|
307
|
+
const old_value = instance.props[update.prop];
|
|
307
308
|
if (update.value instanceof Map)
|
|
308
309
|
new_value = new Map(update.value);
|
|
309
310
|
else if (update.value instanceof Set)
|
|
@@ -317,6 +318,11 @@ export function create_components(initial_layout) {
|
|
|
317
318
|
else
|
|
318
319
|
new_value = update.value;
|
|
319
320
|
instance.props[update.prop] = new_value;
|
|
321
|
+
if (update.prop === "value" &&
|
|
322
|
+
!is_visible(instance) &&
|
|
323
|
+
!dequal(old_value, new_value)) {
|
|
324
|
+
value_change_cb?.(update.id, new_value);
|
|
325
|
+
}
|
|
320
326
|
}
|
|
321
327
|
}
|
|
322
328
|
return layout;
|
|
@@ -411,7 +417,8 @@ export function create_components(initial_layout) {
|
|
|
411
417
|
loading_status,
|
|
412
418
|
scheduled_updates: update_scheduled_store,
|
|
413
419
|
create_layout: create_layout,
|
|
414
|
-
rerender_layout
|
|
420
|
+
rerender_layout,
|
|
421
|
+
value_change
|
|
415
422
|
};
|
|
416
423
|
}
|
|
417
424
|
/** An async version of 'new Function' */
|
|
@@ -725,3 +732,13 @@ export function preload_all_components(components, root) {
|
|
|
725
732
|
});
|
|
726
733
|
return constructor_map;
|
|
727
734
|
}
|
|
735
|
+
function is_visible(component) {
|
|
736
|
+
if (typeof component.props.visible === "boolean" &&
|
|
737
|
+
component.props.visible === false) {
|
|
738
|
+
return false;
|
|
739
|
+
}
|
|
740
|
+
else if (component.parent) {
|
|
741
|
+
return is_visible(component.parent);
|
|
742
|
+
}
|
|
743
|
+
return true;
|
|
744
|
+
}
|
|
@@ -9,6 +9,8 @@ const __dirname = path.dirname(__filename);
|
|
|
9
9
|
const langs = fs.readdirSync(path.join(__dirname, "..", "lang"));
|
|
10
10
|
|
|
11
11
|
let lang_names = {};
|
|
12
|
+
let lang_loading = {};
|
|
13
|
+
|
|
12
14
|
for (const lang of langs) {
|
|
13
15
|
if (lang.endsWith(".json")) {
|
|
14
16
|
const lang_text = fs.readFileSync(
|
|
@@ -17,7 +19,10 @@ for (const lang of langs) {
|
|
|
17
19
|
);
|
|
18
20
|
const lang_data = JSON.parse(lang_text.trim());
|
|
19
21
|
lang_names[lang.split(".")[0]] = lang_data._name;
|
|
22
|
+
lang_loading[lang.split(".")[0]] =
|
|
23
|
+
lang_data?.common?.loading || "Loading...";
|
|
20
24
|
}
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
console.log(lang_names);
|
|
28
|
+
console.log(lang_loading);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export declare const loading: {
|
|
2
|
+
ar: string;
|
|
3
|
+
ca: string;
|
|
4
|
+
ckb: string;
|
|
5
|
+
de: string;
|
|
6
|
+
en: string;
|
|
7
|
+
es: string;
|
|
8
|
+
eu: string;
|
|
9
|
+
fa: string;
|
|
10
|
+
fi: string;
|
|
11
|
+
fr: string;
|
|
12
|
+
he: string;
|
|
13
|
+
hi: string;
|
|
14
|
+
ja: string;
|
|
15
|
+
ko: string;
|
|
16
|
+
lt: string;
|
|
17
|
+
nb: string;
|
|
18
|
+
nl: string;
|
|
19
|
+
pl: string;
|
|
20
|
+
"pt-BR": string;
|
|
21
|
+
pt: string;
|
|
22
|
+
ro: string;
|
|
23
|
+
ru: string;
|
|
24
|
+
sv: string;
|
|
25
|
+
ta: string;
|
|
26
|
+
th: string;
|
|
27
|
+
tr: string;
|
|
28
|
+
uk: string;
|
|
29
|
+
ur: string;
|
|
30
|
+
uz: string;
|
|
31
|
+
"zh-CN": string;
|
|
32
|
+
"zh-TW": string;
|
|
33
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export const loading = {
|
|
2
|
+
ar: "جاري التحميل",
|
|
3
|
+
ca: "S'està carregant",
|
|
4
|
+
ckb: "بارکردن",
|
|
5
|
+
de: "Laden",
|
|
6
|
+
en: "Loading",
|
|
7
|
+
es: "Cargando",
|
|
8
|
+
eu: "Kargatzen",
|
|
9
|
+
fa: "در حال بارگذاری",
|
|
10
|
+
fi: "Ladataan",
|
|
11
|
+
fr: "Chargement",
|
|
12
|
+
he: "טוען",
|
|
13
|
+
hi: "लोड हो रहा है",
|
|
14
|
+
ja: "読み込み中",
|
|
15
|
+
ko: "로딩 중",
|
|
16
|
+
lt: "Kraunama",
|
|
17
|
+
nb: "Laster",
|
|
18
|
+
nl: "Laden",
|
|
19
|
+
pl: "Ładowanie",
|
|
20
|
+
"pt-BR": "Carregando",
|
|
21
|
+
pt: "A carregar",
|
|
22
|
+
ro: "Se încarcă",
|
|
23
|
+
ru: "Загрузка",
|
|
24
|
+
sv: "Laddar",
|
|
25
|
+
ta: "ஏற்றுகிறது",
|
|
26
|
+
th: "กำลังโหลด",
|
|
27
|
+
tr: "Yükleniyor",
|
|
28
|
+
uk: "Завантаження",
|
|
29
|
+
ur: "لوڈ ہو رہا ہے",
|
|
30
|
+
uz: "Yuklanmoqda",
|
|
31
|
+
"zh-CN": "加载中",
|
|
32
|
+
"zh-TW": "載入中"
|
|
33
|
+
};
|
package/package.json
CHANGED
|
@@ -1,61 +1,61 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gradio/core",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"devDependencies": {
|
|
6
6
|
"@gradio/atoms": "^0.16.3",
|
|
7
|
-
"@gradio/audio": "^0.17.21",
|
|
8
7
|
"@gradio/accordion": "^0.5.20",
|
|
9
8
|
"@gradio/annotatedimage": "^0.9.25",
|
|
9
|
+
"@gradio/audio": "^0.17.21",
|
|
10
10
|
"@gradio/box": "^0.2.21",
|
|
11
11
|
"@gradio/button": "^0.5.7",
|
|
12
|
+
"@gradio/browserstate": "^0.3.2",
|
|
12
13
|
"@gradio/chatbot": "^0.26.18",
|
|
13
14
|
"@gradio/checkbox": "^0.4.26",
|
|
14
15
|
"@gradio/checkboxgroup": "^0.6.25",
|
|
15
16
|
"@gradio/client": "^1.15.6",
|
|
16
17
|
"@gradio/code": "^0.14.11",
|
|
17
|
-
"@gradio/
|
|
18
|
-
"@gradio/dataset": "^0.4.27",
|
|
19
|
-
"@gradio/datetime": "^0.3.18",
|
|
20
|
-
"@gradio/column": "^0.2.1",
|
|
18
|
+
"@gradio/dataset": "^0.4.28",
|
|
21
19
|
"@gradio/dataframe": "^0.18.3",
|
|
20
|
+
"@gradio/datetime": "^0.3.18",
|
|
21
|
+
"@gradio/colorpicker": "^0.4.25",
|
|
22
22
|
"@gradio/downloadbutton": "^0.4.7",
|
|
23
23
|
"@gradio/dropdown": "^0.9.25",
|
|
24
|
-
"@gradio/
|
|
24
|
+
"@gradio/column": "^0.2.1",
|
|
25
25
|
"@gradio/file": "^0.12.24",
|
|
26
|
+
"@gradio/fallback": "^0.4.25",
|
|
26
27
|
"@gradio/fileexplorer": "^0.5.35",
|
|
27
28
|
"@gradio/form": "^0.2.21",
|
|
28
|
-
"@gradio/group": "^0.2.0",
|
|
29
29
|
"@gradio/gallery": "^0.15.27",
|
|
30
|
+
"@gradio/group": "^0.2.0",
|
|
30
31
|
"@gradio/highlightedtext": "^0.9.8",
|
|
31
32
|
"@gradio/html": "^0.6.17",
|
|
32
33
|
"@gradio/icons": "^0.12.0",
|
|
33
34
|
"@gradio/image": "^0.22.13",
|
|
34
|
-
"@gradio/imageeditor": "^0.16.1",
|
|
35
35
|
"@gradio/imageslider": "^0.2.9",
|
|
36
|
+
"@gradio/imageeditor": "^0.16.1",
|
|
36
37
|
"@gradio/json": "^0.5.27",
|
|
37
|
-
"@gradio/browserstate": "^0.3.2",
|
|
38
|
-
"@gradio/model3d": "^0.14.20",
|
|
39
|
-
"@gradio/markdown": "^0.13.18",
|
|
40
38
|
"@gradio/label": "^0.5.17",
|
|
39
|
+
"@gradio/markdown": "^0.13.18",
|
|
40
|
+
"@gradio/model3d": "^0.14.21",
|
|
41
|
+
"@gradio/multimodaltextbox": "^0.10.13",
|
|
41
42
|
"@gradio/nativeplot": "^0.7.2",
|
|
42
43
|
"@gradio/number": "^0.6.2",
|
|
43
44
|
"@gradio/paramviewer": "^0.7.13",
|
|
44
|
-
"@gradio/multimodaltextbox": "^0.10.13",
|
|
45
|
-
"@gradio/plot": "^0.9.20",
|
|
46
45
|
"@gradio/radio": "^0.7.8",
|
|
47
|
-
"@gradio/
|
|
46
|
+
"@gradio/plot": "^0.9.20",
|
|
47
|
+
"@gradio/simpledropdown": "^0.3.25",
|
|
48
48
|
"@gradio/sidebar": "^0.1.18",
|
|
49
49
|
"@gradio/simpletextbox": "^0.3.26",
|
|
50
|
+
"@gradio/row": "^0.2.1",
|
|
50
51
|
"@gradio/simpleimage": "^0.8.35",
|
|
51
52
|
"@gradio/sketchbox": "^0.6.13",
|
|
53
|
+
"@gradio/statustracker": "^0.10.15",
|
|
52
54
|
"@gradio/slider": "^0.6.14",
|
|
53
|
-
"@gradio/simpledropdown": "^0.3.25",
|
|
54
55
|
"@gradio/state": "^0.1.2",
|
|
55
|
-
"@gradio/statustracker": "^0.10.15",
|
|
56
|
-
"@gradio/tabs": "^0.4.5",
|
|
57
|
-
"@gradio/textbox": "^0.10.17",
|
|
58
56
|
"@gradio/tabitem": "^0.5.0",
|
|
57
|
+
"@gradio/tabs": "^0.4.5",
|
|
58
|
+
"@gradio/textbox": "^0.10.18",
|
|
59
59
|
"@gradio/theme": "^0.4.0",
|
|
60
60
|
"@gradio/timer": "^0.4.5",
|
|
61
61
|
"@gradio/upload": "^0.16.11",
|
|
@@ -94,5 +94,8 @@
|
|
|
94
94
|
"type": "git",
|
|
95
95
|
"url": "git+https://github.com/gradio-app/gradio.git",
|
|
96
96
|
"directory": "js/core"
|
|
97
|
+
},
|
|
98
|
+
"dependencies": {
|
|
99
|
+
"dequal": "^2.0.2"
|
|
97
100
|
}
|
|
98
101
|
}
|
package/src/Blocks.svelte
CHANGED
|
@@ -69,8 +69,11 @@
|
|
|
69
69
|
loading_status,
|
|
70
70
|
scheduled_updates,
|
|
71
71
|
create_layout,
|
|
72
|
-
rerender_layout
|
|
73
|
-
|
|
72
|
+
rerender_layout,
|
|
73
|
+
value_change
|
|
74
|
+
} = create_components({
|
|
75
|
+
initial_layout
|
|
76
|
+
});
|
|
74
77
|
|
|
75
78
|
$: components, layout, dependencies, root, app, fill_height, target, run();
|
|
76
79
|
|
|
@@ -845,6 +848,16 @@
|
|
|
845
848
|
render_complete = true;
|
|
846
849
|
}
|
|
847
850
|
|
|
851
|
+
value_change((id, value) => {
|
|
852
|
+
const deps = $targets[id]?.["change"];
|
|
853
|
+
|
|
854
|
+
deps?.forEach((dep_id) => {
|
|
855
|
+
requestAnimationFrame(() => {
|
|
856
|
+
wait_then_trigger_api_call(dep_id, id, value);
|
|
857
|
+
});
|
|
858
|
+
});
|
|
859
|
+
});
|
|
860
|
+
|
|
848
861
|
const handle_load_triggers = (): void => {
|
|
849
862
|
dependencies.forEach((dep) => {
|
|
850
863
|
if (dep.targets.some((dep) => dep[1] === "load")) {
|
|
@@ -52,6 +52,21 @@
|
|
|
52
52
|
export let api_calls: Payload[] = [];
|
|
53
53
|
let current_language: "python" | "javascript" | "bash" | "mcp" = "python";
|
|
54
54
|
|
|
55
|
+
function set_query_param(key: string, value: string) {
|
|
56
|
+
const url = new URL(window.location.href);
|
|
57
|
+
url.searchParams.set(key, value);
|
|
58
|
+
history.replaceState(null, "", url.toString());
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function get_query_param(key: string): string | null {
|
|
62
|
+
const url = new URL(window.location.href);
|
|
63
|
+
return url.searchParams.get(key);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function is_valid_language(lang: string | null): boolean {
|
|
67
|
+
return ["python", "javascript", "bash", "mcp"].includes(lang ?? "");
|
|
68
|
+
}
|
|
69
|
+
|
|
55
70
|
const langs = [
|
|
56
71
|
["python", "Python", python],
|
|
57
72
|
["javascript", "JavaScript", javascript],
|
|
@@ -211,12 +226,24 @@
|
|
|
211
226
|
window.parentIFrame?.scrollTo(0, 0);
|
|
212
227
|
}
|
|
213
228
|
|
|
229
|
+
const lang_param = get_query_param("lang");
|
|
230
|
+
if (is_valid_language(lang_param)) {
|
|
231
|
+
current_language = lang_param as "python" | "javascript" | "bash" | "mcp";
|
|
232
|
+
}
|
|
233
|
+
|
|
214
234
|
// Check MCP server status and fetch tools if active
|
|
215
235
|
fetch(mcp_server_url)
|
|
216
236
|
.then((response) => {
|
|
217
237
|
mcp_server_active = response.ok;
|
|
218
238
|
if (mcp_server_active) {
|
|
219
239
|
fetchMcpTools();
|
|
240
|
+
if (!is_valid_language(lang_param)) {
|
|
241
|
+
current_language = "mcp";
|
|
242
|
+
}
|
|
243
|
+
} else {
|
|
244
|
+
if (!is_valid_language(lang_param)) {
|
|
245
|
+
current_language = "python";
|
|
246
|
+
}
|
|
220
247
|
}
|
|
221
248
|
})
|
|
222
249
|
.catch(() => {
|
|
@@ -252,7 +279,10 @@
|
|
|
252
279
|
<li
|
|
253
280
|
class="snippet
|
|
254
281
|
{current_language === language ? 'current-lang' : 'inactive-lang'}"
|
|
255
|
-
on:click={() =>
|
|
282
|
+
on:click={() => {
|
|
283
|
+
current_language = language;
|
|
284
|
+
set_query_param("lang", language);
|
|
285
|
+
}}
|
|
256
286
|
>
|
|
257
287
|
<img src={img} alt="" />
|
|
258
288
|
{display_name}
|
package/src/i18n.test.ts
CHANGED
|
@@ -17,6 +17,9 @@ import {
|
|
|
17
17
|
changeLocale,
|
|
18
18
|
is_translation_metadata
|
|
19
19
|
} from "./i18n";
|
|
20
|
+
import { loading } from "./lang/loading";
|
|
21
|
+
|
|
22
|
+
const loading_count = Object.keys(loading).length;
|
|
20
23
|
|
|
21
24
|
vi.mock("svelte-i18n", () => ({
|
|
22
25
|
locale: { set: vi.fn() },
|
|
@@ -117,7 +120,7 @@ describe("i18n", () => {
|
|
|
117
120
|
|
|
118
121
|
load_translations({ processed_langs: {}, custom_translations });
|
|
119
122
|
|
|
120
|
-
expect(mockAddMessages).toHaveBeenCalledTimes(2);
|
|
123
|
+
expect(mockAddMessages).toHaveBeenCalledTimes(loading_count + 2);
|
|
121
124
|
expect(mockAddMessages).toHaveBeenCalledWith(
|
|
122
125
|
"en",
|
|
123
126
|
custom_translations.en
|
package/src/i18n.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
waitLocale
|
|
8
8
|
} from "svelte-i18n";
|
|
9
9
|
import { formatter } from "./gradio_helper";
|
|
10
|
+
import { loading } from "./lang/loading";
|
|
10
11
|
|
|
11
12
|
const lang_map = {
|
|
12
13
|
ar: "العربية",
|
|
@@ -237,4 +238,10 @@ export function load_translations(translations: {
|
|
|
237
238
|
} catch (e) {
|
|
238
239
|
console.error("Error loading translations:", e);
|
|
239
240
|
}
|
|
241
|
+
|
|
242
|
+
for (const lang in loading) {
|
|
243
|
+
addMessages(lang, {
|
|
244
|
+
common: { loading: loading[lang as keyof typeof loading] }
|
|
245
|
+
});
|
|
246
|
+
}
|
|
240
247
|
}
|
package/src/init.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { writable, type Writable, get } from "svelte/store";
|
|
2
|
+
import { dequal } from "dequal";
|
|
2
3
|
|
|
3
4
|
import type {
|
|
4
5
|
ComponentMeta,
|
|
@@ -28,8 +29,15 @@ const raf = is_browser
|
|
|
28
29
|
* Create a store with the layout and a map of targets
|
|
29
30
|
* @returns A store with the layout and a map of targets
|
|
30
31
|
*/
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
export function create_components(
|
|
33
|
+
{
|
|
34
|
+
initial_layout = undefined
|
|
35
|
+
}: {
|
|
36
|
+
initial_layout: ComponentMeta | undefined;
|
|
37
|
+
} = {
|
|
38
|
+
initial_layout: undefined
|
|
39
|
+
}
|
|
40
|
+
): {
|
|
33
41
|
layout: Writable<ComponentMeta>;
|
|
34
42
|
targets: Writable<TargetMap>;
|
|
35
43
|
update_value: (updates: UpdateTransaction[]) => void;
|
|
@@ -56,6 +64,7 @@ export function create_components(initial_layout: ComponentMeta | undefined): {
|
|
|
56
64
|
root: string;
|
|
57
65
|
dependencies: Dependency[];
|
|
58
66
|
}) => void;
|
|
67
|
+
value_change: (cb: (id: number, value: any) => void) => void;
|
|
59
68
|
} {
|
|
60
69
|
let _component_map: Map<number, ComponentMeta>;
|
|
61
70
|
|
|
@@ -73,6 +82,12 @@ export function create_components(initial_layout: ComponentMeta | undefined): {
|
|
|
73
82
|
let keys_per_render_id: Record<number, (string | number)[]> = {};
|
|
74
83
|
let _rootNode: ComponentMeta;
|
|
75
84
|
|
|
85
|
+
let value_change_cb: ((id: number, value: any) => void) | null = null;
|
|
86
|
+
|
|
87
|
+
function value_change(cb: (id: number, value: any) => void): void {
|
|
88
|
+
value_change_cb = cb;
|
|
89
|
+
}
|
|
90
|
+
|
|
76
91
|
// Store current layout and root for dynamic visibility recalculation
|
|
77
92
|
let current_layout: LayoutNode;
|
|
78
93
|
let current_root: string;
|
|
@@ -132,7 +147,6 @@ export function create_components(initial_layout: ComponentMeta | undefined): {
|
|
|
132
147
|
pending_updates = [];
|
|
133
148
|
constructor_map = new Map();
|
|
134
149
|
_component_map = new Map();
|
|
135
|
-
|
|
136
150
|
instance_map = {};
|
|
137
151
|
|
|
138
152
|
// Store current layout and root for dynamic visibility recalculation
|
|
@@ -327,19 +341,12 @@ export function create_components(initial_layout: ComponentMeta | undefined): {
|
|
|
327
341
|
const constructor_key = instance.component_class_id || instance.type;
|
|
328
342
|
let component_constructor = constructor_map.get(constructor_key);
|
|
329
343
|
|
|
330
|
-
// Only load component if it was preloaded (i.e., it's visible)
|
|
331
344
|
if (component_constructor) {
|
|
332
345
|
instance.component = (await component_constructor)?.default;
|
|
333
346
|
}
|
|
334
|
-
// If component wasn't preloaded, leave it unloaded for now
|
|
335
|
-
// It will be loaded later when/if it becomes visible
|
|
336
347
|
}
|
|
337
348
|
instance.parent = parent;
|
|
338
349
|
|
|
339
|
-
// if (instance.type === "timer") {
|
|
340
|
-
// console.log("timer", instance, constructor_map);
|
|
341
|
-
// }
|
|
342
|
-
|
|
343
350
|
if (instance.type === "dataset") {
|
|
344
351
|
instance.props.component_map = get_component(
|
|
345
352
|
instance.type,
|
|
@@ -506,6 +513,7 @@ export function create_components(initial_layout: ComponentMeta | undefined): {
|
|
|
506
513
|
const instance = instance_map[update.id];
|
|
507
514
|
if (!instance) continue;
|
|
508
515
|
let new_value;
|
|
516
|
+
const old_value = instance.props[update.prop];
|
|
509
517
|
if (update.value instanceof Map) new_value = new Map(update.value);
|
|
510
518
|
else if (update.value instanceof Set)
|
|
511
519
|
new_value = new Set(update.value);
|
|
@@ -515,6 +523,14 @@ export function create_components(initial_layout: ComponentMeta | undefined): {
|
|
|
515
523
|
new_value = { ...update.value };
|
|
516
524
|
else new_value = update.value;
|
|
517
525
|
instance.props[update.prop] = new_value;
|
|
526
|
+
|
|
527
|
+
if (
|
|
528
|
+
update.prop === "value" &&
|
|
529
|
+
!is_visible(instance) &&
|
|
530
|
+
!dequal(old_value, new_value)
|
|
531
|
+
) {
|
|
532
|
+
value_change_cb?.(update.id, new_value);
|
|
533
|
+
}
|
|
518
534
|
}
|
|
519
535
|
}
|
|
520
536
|
return layout;
|
|
@@ -631,7 +647,8 @@ export function create_components(initial_layout: ComponentMeta | undefined): {
|
|
|
631
647
|
loading_status,
|
|
632
648
|
scheduled_updates: update_scheduled_store,
|
|
633
649
|
create_layout: create_layout,
|
|
634
|
-
rerender_layout
|
|
650
|
+
rerender_layout,
|
|
651
|
+
value_change
|
|
635
652
|
};
|
|
636
653
|
}
|
|
637
654
|
|
|
@@ -1094,3 +1111,15 @@ export function preload_all_components(
|
|
|
1094
1111
|
|
|
1095
1112
|
return constructor_map;
|
|
1096
1113
|
}
|
|
1114
|
+
|
|
1115
|
+
function is_visible(component: ComponentMeta): boolean {
|
|
1116
|
+
if (
|
|
1117
|
+
typeof component.props.visible === "boolean" &&
|
|
1118
|
+
component.props.visible === false
|
|
1119
|
+
) {
|
|
1120
|
+
return false;
|
|
1121
|
+
} else if (component.parent) {
|
|
1122
|
+
return is_visible(component.parent);
|
|
1123
|
+
}
|
|
1124
|
+
return true;
|
|
1125
|
+
}
|
|
@@ -9,6 +9,8 @@ const __dirname = path.dirname(__filename);
|
|
|
9
9
|
const langs = fs.readdirSync(path.join(__dirname, "..", "lang"));
|
|
10
10
|
|
|
11
11
|
let lang_names = {};
|
|
12
|
+
let lang_loading = {};
|
|
13
|
+
|
|
12
14
|
for (const lang of langs) {
|
|
13
15
|
if (lang.endsWith(".json")) {
|
|
14
16
|
const lang_text = fs.readFileSync(
|
|
@@ -17,7 +19,10 @@ for (const lang of langs) {
|
|
|
17
19
|
);
|
|
18
20
|
const lang_data = JSON.parse(lang_text.trim());
|
|
19
21
|
lang_names[lang.split(".")[0]] = lang_data._name;
|
|
22
|
+
lang_loading[lang.split(".")[0]] =
|
|
23
|
+
lang_data?.common?.loading || "Loading...";
|
|
20
24
|
}
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
console.log(lang_names);
|
|
28
|
+
console.log(lang_loading);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export const loading = {
|
|
2
|
+
ar: "جاري التحميل",
|
|
3
|
+
ca: "S'està carregant",
|
|
4
|
+
ckb: "بارکردن",
|
|
5
|
+
de: "Laden",
|
|
6
|
+
en: "Loading",
|
|
7
|
+
es: "Cargando",
|
|
8
|
+
eu: "Kargatzen",
|
|
9
|
+
fa: "در حال بارگذاری",
|
|
10
|
+
fi: "Ladataan",
|
|
11
|
+
fr: "Chargement",
|
|
12
|
+
he: "טוען",
|
|
13
|
+
hi: "लोड हो रहा है",
|
|
14
|
+
ja: "読み込み中",
|
|
15
|
+
ko: "로딩 중",
|
|
16
|
+
lt: "Kraunama",
|
|
17
|
+
nb: "Laster",
|
|
18
|
+
nl: "Laden",
|
|
19
|
+
pl: "Ładowanie",
|
|
20
|
+
"pt-BR": "Carregando",
|
|
21
|
+
pt: "A carregar",
|
|
22
|
+
ro: "Se încarcă",
|
|
23
|
+
ru: "Загрузка",
|
|
24
|
+
sv: "Laddar",
|
|
25
|
+
ta: "ஏற்றுகிறது",
|
|
26
|
+
th: "กำลังโหลด",
|
|
27
|
+
tr: "Yükleniyor",
|
|
28
|
+
uk: "Завантаження",
|
|
29
|
+
ur: "لوڈ ہو رہا ہے",
|
|
30
|
+
uz: "Yuklanmoqda",
|
|
31
|
+
"zh-CN": "加载中",
|
|
32
|
+
"zh-TW": "載入中"
|
|
33
|
+
};
|