@gradio/core 0.16.1 → 0.18.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 +43 -0
- package/dist/src/Blocks.svelte +75 -4
- package/dist/src/Render.svelte +2 -2
- package/dist/src/RenderComponent.svelte +21 -1
- package/dist/src/api_docs/ApiDocs.svelte +6 -1
- package/dist/src/api_docs/Settings.svelte +74 -1
- package/dist/src/api_docs/Settings.svelte.d.ts +3 -0
- package/dist/src/api_docs/img/record-stop.svg +1 -0
- package/dist/src/api_docs/img/record.svg +1 -0
- package/dist/src/gradio_helper.d.ts +1 -11
- package/dist/src/gradio_helper.js +3 -19
- package/dist/src/i18n.d.ts +12 -5
- package/dist/src/i18n.js +93 -12
- package/dist/src/init.js +40 -20
- package/dist/src/lang/en.json +6 -1
- package/dist/src/lang/es.json +2 -1
- package/dist/src/lang/fr.json +2 -1
- package/dist/src/lang/ja.json +2 -1
- package/dist/src/lang/ko.json +2 -1
- package/dist/src/lang/lt.json +2 -1
- package/dist/src/lang/nb.json +2 -1
- package/dist/src/lang/nl.json +2 -1
- package/dist/src/lang/pl.json +2 -1
- package/dist/src/lang/pt-BR.json +1 -0
- package/dist/src/lang/pt.json +2 -1
- package/dist/src/lang/ro.json +2 -1
- package/dist/src/lang/ru.json +2 -1
- package/dist/src/lang/sv.json +2 -1
- package/dist/src/lang/ta.json +2 -1
- package/dist/src/lang/th.json +2 -1
- package/dist/src/lang/tr.json +2 -1
- package/dist/src/lang/uk.json +2 -1
- package/dist/src/lang/ur.json +2 -1
- package/dist/src/lang/uz.json +2 -1
- package/dist/src/lang/zh-CN.json +2 -1
- package/dist/src/lang/zh-TW.json +2 -1
- package/dist/src/screen_recorder.d.ts +16 -0
- package/dist/src/screen_recorder.js +255 -0
- package/package.json +53 -53
- package/src/Blocks.svelte +86 -6
- package/src/Render.svelte +2 -2
- package/src/RenderComponent.svelte +21 -1
- package/src/api_docs/ApiDocs.svelte +7 -1
- package/src/api_docs/Settings.svelte +77 -1
- package/src/api_docs/img/record-stop.svg +1 -0
- package/src/api_docs/img/record.svg +1 -0
- package/src/gradio_helper.ts +5 -21
- package/src/i18n.test.ts +120 -1
- package/src/i18n.ts +126 -24
- package/src/init.ts +48 -26
- package/src/lang/en.json +6 -1
- package/src/lang/es.json +2 -1
- package/src/lang/fr.json +2 -1
- package/src/lang/ja.json +2 -1
- package/src/lang/ko.json +2 -1
- package/src/lang/lt.json +2 -1
- package/src/lang/nb.json +2 -1
- package/src/lang/nl.json +2 -1
- package/src/lang/pl.json +2 -1
- package/src/lang/pt-BR.json +1 -0
- package/src/lang/pt.json +2 -1
- package/src/lang/ro.json +2 -1
- package/src/lang/ru.json +2 -1
- package/src/lang/sv.json +2 -1
- package/src/lang/ta.json +2 -1
- package/src/lang/th.json +2 -1
- package/src/lang/tr.json +2 -1
- package/src/lang/uk.json +2 -1
- package/src/lang/ur.json +2 -1
- package/src/lang/uz.json +2 -1
- package/src/lang/zh-CN.json +2 -1
- package/src/lang/zh-TW.json +2 -1
- package/src/screen_recorder.ts +361 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,48 @@
|
|
|
1
1
|
# @gradio/core
|
|
2
2
|
|
|
3
|
+
## 0.18.0
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- [#11224](https://github.com/gradio-app/gradio/pull/11224) [`834e92c`](https://github.com/gradio-app/gradio/commit/834e92c187f200665c78c344f0b38f5adede807b) - Fix re-rendering with key when setting a value to None. Thanks @aliabid94!
|
|
8
|
+
- [#10832](https://github.com/gradio-app/gradio/pull/10832) [`d457438`](https://github.com/gradio-app/gradio/commit/d4574381bdd12709183c3affe740fada82b8baea) - Screen recording. Thanks @dawoodkhan82!
|
|
9
|
+
|
|
10
|
+
## 0.17.0
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
- [#11155](https://github.com/gradio-app/gradio/pull/11155) [`30a1d9e`](https://github.com/gradio-app/gradio/commit/30a1d9e2ac3013d9c844b236410010bce97ffaf5) - Improvements to MCP page. Thanks @abidlabs!
|
|
15
|
+
- [#11047](https://github.com/gradio-app/gradio/pull/11047) [`6d4b8a7`](https://github.com/gradio-app/gradio/commit/6d4b8a7f10daefc9c79aa224635da23fbaeebb76) - Implement custom i18n. Thanks @hannahblair!
|
|
16
|
+
|
|
17
|
+
### Fixes
|
|
18
|
+
|
|
19
|
+
- [#11206](https://github.com/gradio-app/gradio/pull/11206) [`c196ac2`](https://github.com/gradio-app/gradio/commit/c196ac25b7744e9dcfa788b1ac8edf6551eec1ff) - Render key fixes. Thanks @aliabid94!
|
|
20
|
+
|
|
21
|
+
### Dependency updates
|
|
22
|
+
|
|
23
|
+
- @gradio/code@0.14.4
|
|
24
|
+
- @gradio/paramviewer@0.7.9
|
|
25
|
+
- @gradio/statustracker@0.10.11
|
|
26
|
+
- @gradio/atoms@0.16.1
|
|
27
|
+
- @gradio/client@1.15.0
|
|
28
|
+
- @gradio/upload@0.16.5
|
|
29
|
+
- @gradio/button@0.5.0
|
|
30
|
+
- @gradio/image@0.22.6
|
|
31
|
+
- @gradio/video@0.14.14
|
|
32
|
+
- @gradio/file@0.12.18
|
|
33
|
+
- @gradio/column@0.2.0
|
|
34
|
+
- @gradio/gallery@0.15.19
|
|
35
|
+
- @gradio/plot@0.9.16
|
|
36
|
+
- @gradio/textbox@0.10.11
|
|
37
|
+
- @gradio/checkbox@0.4.21
|
|
38
|
+
|
|
39
|
+
## 0.16.1
|
|
40
|
+
|
|
41
|
+
### Dependency updates
|
|
42
|
+
|
|
43
|
+
- @gradio/tabs@0.4.4
|
|
44
|
+
- @gradio/tabitem@0.4.4
|
|
45
|
+
|
|
3
46
|
## 0.16.1
|
|
4
47
|
|
|
5
48
|
### Fixes
|
package/dist/src/Blocks.svelte
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script>import { tick, onMount } from "svelte";
|
|
2
2
|
import { _ } from "svelte-i18n";
|
|
3
3
|
import { Client } from "@gradio/client";
|
|
4
|
+
import { writable } from "svelte/store";
|
|
4
5
|
import { setupi18n } from "./i18n";
|
|
5
6
|
import { ApiDocs, ApiRecorder, Settings } from "./api_docs/";
|
|
6
7
|
import { Toast } from "@gradio/statustracker";
|
|
@@ -9,8 +10,9 @@ import { prefix_css } from "./css";
|
|
|
9
10
|
import logo from "./images/logo.svg";
|
|
10
11
|
import api_logo from "./api_docs/img/api-logo.svg";
|
|
11
12
|
import settings_logo from "./api_docs/img/settings-logo.svg";
|
|
13
|
+
import record_stop from "./api_docs/img/record-stop.svg";
|
|
12
14
|
import { create_components, AsyncFunction } from "./init";
|
|
13
|
-
|
|
15
|
+
import * as screen_recorder from "./screen_recorder";
|
|
14
16
|
export let root;
|
|
15
17
|
export let components;
|
|
16
18
|
export let layout;
|
|
@@ -34,6 +36,7 @@ export let api_prefix = "";
|
|
|
34
36
|
export let max_file_size = void 0;
|
|
35
37
|
export let initial_layout = void 0;
|
|
36
38
|
export let css = null;
|
|
39
|
+
setupi18n(app.config?.i18n_translations ?? void 0);
|
|
37
40
|
let {
|
|
38
41
|
layout: _layout,
|
|
39
42
|
targets,
|
|
@@ -74,6 +77,8 @@ export let search_params;
|
|
|
74
77
|
let api_docs_visible = search_params.get("view") === "api" && show_api;
|
|
75
78
|
let settings_visible = search_params.get("view") === "settings";
|
|
76
79
|
let api_recorder_visible = search_params.get("view") === "api-recorder" && show_api;
|
|
80
|
+
let allow_zoom = true;
|
|
81
|
+
let allow_video_trim = true;
|
|
77
82
|
function set_api_docs_visible(visible) {
|
|
78
83
|
api_recorder_visible = false;
|
|
79
84
|
api_docs_visible = visible;
|
|
@@ -99,6 +104,17 @@ let api_calls = [];
|
|
|
99
104
|
export let render_complete = false;
|
|
100
105
|
async function handle_update(data, fn_index) {
|
|
101
106
|
const dep = dependencies.find((dep2) => dep2.id === fn_index);
|
|
107
|
+
const input_type = components.find(
|
|
108
|
+
(comp) => comp.id === dep?.inputs[0]
|
|
109
|
+
)?.type;
|
|
110
|
+
if (allow_zoom && dep && input_type !== "dataset") {
|
|
111
|
+
if (dep && dep.inputs && dep.inputs.length > 0 && $is_screen_recording) {
|
|
112
|
+
screen_recorder.zoom(true, dep.inputs, 1);
|
|
113
|
+
}
|
|
114
|
+
if (dep && dep.outputs && dep.outputs.length > 0 && $is_screen_recording) {
|
|
115
|
+
screen_recorder.zoom(false, dep.outputs, 2);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
102
118
|
if (!dep) {
|
|
103
119
|
return;
|
|
104
120
|
}
|
|
@@ -285,6 +301,9 @@ async function trigger_api_call(dep_index, trigger_id = null, event_data = null)
|
|
|
285
301
|
}
|
|
286
302
|
}
|
|
287
303
|
async function make_prediction(payload2, streaming = false) {
|
|
304
|
+
if (allow_video_trim) {
|
|
305
|
+
screen_recorder.markRemoveSegmentStart();
|
|
306
|
+
}
|
|
288
307
|
if (api_recorder_visible) {
|
|
289
308
|
api_calls = [...api_calls, JSON.parse(JSON.stringify(payload2))];
|
|
290
309
|
}
|
|
@@ -472,6 +491,9 @@ async function trigger_api_call(dep_index, trigger_id = null, event_data = null)
|
|
|
472
491
|
});
|
|
473
492
|
}
|
|
474
493
|
}
|
|
494
|
+
if (allow_video_trim) {
|
|
495
|
+
screen_recorder.markRemoveSegmentEnd();
|
|
496
|
+
}
|
|
475
497
|
}
|
|
476
498
|
}
|
|
477
499
|
function trigger_share(title2, description) {
|
|
@@ -612,6 +634,7 @@ function set_status(statuses) {
|
|
|
612
634
|
function isCustomEvent(event) {
|
|
613
635
|
return "detail" in event;
|
|
614
636
|
}
|
|
637
|
+
let is_screen_recording = writable(false);
|
|
615
638
|
onMount(() => {
|
|
616
639
|
document.addEventListener("visibilitychange", function() {
|
|
617
640
|
if (document.visibilityState === "hidden") {
|
|
@@ -621,7 +644,23 @@ onMount(() => {
|
|
|
621
644
|
is_mobile_device = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
|
|
622
645
|
navigator.userAgent
|
|
623
646
|
);
|
|
647
|
+
screen_recorder.initialize(
|
|
648
|
+
root,
|
|
649
|
+
(title2, message, type) => {
|
|
650
|
+
add_new_message(title2, message, type);
|
|
651
|
+
},
|
|
652
|
+
(isRecording) => {
|
|
653
|
+
$is_screen_recording = isRecording;
|
|
654
|
+
}
|
|
655
|
+
);
|
|
624
656
|
});
|
|
657
|
+
function screen_recording() {
|
|
658
|
+
if ($is_screen_recording) {
|
|
659
|
+
screen_recorder.stopRecording();
|
|
660
|
+
} else {
|
|
661
|
+
screen_recorder.startRecording();
|
|
662
|
+
}
|
|
663
|
+
}
|
|
625
664
|
</script>
|
|
626
665
|
|
|
627
666
|
<svelte:head>
|
|
@@ -659,7 +698,11 @@ onMount(() => {
|
|
|
659
698
|
}}
|
|
660
699
|
class="show-api"
|
|
661
700
|
>
|
|
662
|
-
{
|
|
701
|
+
{#if app.config?.mcp_server}
|
|
702
|
+
{$_("errors.use_via_api_or_mcp")}
|
|
703
|
+
{:else}
|
|
704
|
+
{$_("errors.use_via_api")}
|
|
705
|
+
{/if}
|
|
663
706
|
<img src={api_logo} alt={$_("common.logo")} />
|
|
664
707
|
</button>
|
|
665
708
|
<div class="divider show-api-divider">·</div>
|
|
@@ -673,6 +716,17 @@ onMount(() => {
|
|
|
673
716
|
{$_("common.built_with_gradio")}
|
|
674
717
|
<img src={logo} alt={$_("common.logo")} />
|
|
675
718
|
</a>
|
|
719
|
+
<div class="divider" class:hidden={!$is_screen_recording}>·</div>
|
|
720
|
+
<button
|
|
721
|
+
class:hidden={!$is_screen_recording}
|
|
722
|
+
on:click={() => {
|
|
723
|
+
screen_recording();
|
|
724
|
+
}}
|
|
725
|
+
class="record"
|
|
726
|
+
>
|
|
727
|
+
{$_("common.stop_recording")}
|
|
728
|
+
<img src={record_stop} alt={$_("common.stop_recording")} />
|
|
729
|
+
</button>
|
|
676
730
|
<div class="divider">·</div>
|
|
677
731
|
<button
|
|
678
732
|
on:click={() => {
|
|
@@ -745,9 +799,14 @@ onMount(() => {
|
|
|
745
799
|
/>
|
|
746
800
|
<div class="api-docs-wrap">
|
|
747
801
|
<Settings
|
|
802
|
+
bind:allow_zoom
|
|
803
|
+
bind:allow_video_trim
|
|
748
804
|
on:close={(event) => {
|
|
749
805
|
set_settings_visible(false);
|
|
750
806
|
}}
|
|
807
|
+
on:start_recording={(event) => {
|
|
808
|
+
screen_recording();
|
|
809
|
+
}}
|
|
751
810
|
pwa_enabled={app.config.pwa}
|
|
752
811
|
{root}
|
|
753
812
|
{space_id}
|
|
@@ -787,7 +846,8 @@ onMount(() => {
|
|
|
787
846
|
}
|
|
788
847
|
|
|
789
848
|
.show-api,
|
|
790
|
-
.settings
|
|
849
|
+
.settings,
|
|
850
|
+
.record {
|
|
791
851
|
display: flex;
|
|
792
852
|
align-items: center;
|
|
793
853
|
}
|
|
@@ -807,13 +867,20 @@ onMount(() => {
|
|
|
807
867
|
width: var(--size-4);
|
|
808
868
|
}
|
|
809
869
|
|
|
870
|
+
.record img {
|
|
871
|
+
margin-right: var(--size-1);
|
|
872
|
+
margin-left: var(--size-1);
|
|
873
|
+
width: var(--size-3);
|
|
874
|
+
}
|
|
875
|
+
|
|
810
876
|
.built-with {
|
|
811
877
|
display: flex;
|
|
812
878
|
align-items: center;
|
|
813
879
|
}
|
|
814
880
|
|
|
815
881
|
.built-with:hover,
|
|
816
|
-
.settings:hover
|
|
882
|
+
.settings:hover,
|
|
883
|
+
.record:hover {
|
|
817
884
|
color: var(--body-text-color);
|
|
818
885
|
}
|
|
819
886
|
|
|
@@ -884,4 +951,8 @@ onMount(() => {
|
|
|
884
951
|
.show-api:hover {
|
|
885
952
|
color: var(--body-text-color);
|
|
886
953
|
}
|
|
954
|
+
|
|
955
|
+
.hidden {
|
|
956
|
+
display: none;
|
|
957
|
+
}
|
|
887
958
|
</style>
|
package/dist/src/Render.svelte
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script>import { Gradio,
|
|
1
|
+
<script>import { Gradio, reactive_formatter } from "./gradio_helper";
|
|
2
2
|
import { onMount, createEventDispatcher, setContext } from "svelte";
|
|
3
3
|
import RenderComponent from "./RenderComponent.svelte";
|
|
4
4
|
import { load_component } from "virtual:component-loader";
|
|
@@ -55,7 +55,7 @@ $:
|
|
|
55
55
|
root,
|
|
56
56
|
autoscroll,
|
|
57
57
|
max_file_size,
|
|
58
|
-
|
|
58
|
+
$reactive_formatter,
|
|
59
59
|
client,
|
|
60
60
|
load_component
|
|
61
61
|
);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<svelte:options immutable={true} />
|
|
2
2
|
|
|
3
|
-
<script>import {
|
|
3
|
+
<script>import { translate_if_needed } from "./i18n";
|
|
4
|
+
import { bind, binding_callbacks } from "svelte/internal";
|
|
4
5
|
export let root;
|
|
5
6
|
export let component;
|
|
6
7
|
export let target;
|
|
@@ -34,6 +35,25 @@ function wrap(component2) {
|
|
|
34
35
|
return ProxiedMyClass;
|
|
35
36
|
}
|
|
36
37
|
const _component = wrap(component);
|
|
38
|
+
const supported_props = [
|
|
39
|
+
"description",
|
|
40
|
+
"info",
|
|
41
|
+
"title",
|
|
42
|
+
"placeholder",
|
|
43
|
+
"value",
|
|
44
|
+
"label"
|
|
45
|
+
];
|
|
46
|
+
function translate_prop(obj) {
|
|
47
|
+
for (const key in obj) {
|
|
48
|
+
if (supported_props.includes(key)) {
|
|
49
|
+
obj[key] = translate_if_needed(obj[key]);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
$:
|
|
54
|
+
translate_prop($$restProps);
|
|
55
|
+
$:
|
|
56
|
+
value = translate_if_needed(value);
|
|
37
57
|
</script>
|
|
38
58
|
|
|
39
59
|
<!-- {#if visible} -->
|
|
@@ -23,6 +23,7 @@ const js_docs = "https://www.gradio.app/guides/getting-started-with-the-js-clien
|
|
|
23
23
|
const py_docs = "https://www.gradio.app/guides/getting-started-with-the-python-client";
|
|
24
24
|
const bash_docs = "https://www.gradio.app/guides/querying-gradio-apps-with-curl";
|
|
25
25
|
const spaces_docs_suffix = "#connecting-to-a-hugging-face-space";
|
|
26
|
+
const mcp_docs = "https://www.gradio.app/guides/building-mcp-server-with-gradio";
|
|
26
27
|
let api_count = dependencies.filter(
|
|
27
28
|
(dependency) => dependency.show_api
|
|
28
29
|
).length;
|
|
@@ -326,7 +327,11 @@ onMount(() => {
|
|
|
326
327
|
</code>
|
|
327
328
|
</Block>
|
|
328
329
|
<p> </p>
|
|
329
|
-
<p
|
|
330
|
+
<p>
|
|
331
|
+
<a href={mcp_docs} target="_blank">
|
|
332
|
+
Read more about MCP in the Gradio docs
|
|
333
|
+
</a>
|
|
334
|
+
</p>
|
|
330
335
|
{:else}
|
|
331
336
|
This Gradio app can also serve as an MCP server, with an MCP
|
|
332
337
|
tool corresponding to each API endpoint. To enable this, launch
|
|
@@ -4,9 +4,13 @@ export let root;
|
|
|
4
4
|
export let space_id;
|
|
5
5
|
export let pwa_enabled;
|
|
6
6
|
import { BaseDropdown as Dropdown } from "@gradio/dropdown";
|
|
7
|
+
import { BaseCheckbox as Checkbox } from "@gradio/checkbox";
|
|
7
8
|
import { language_choices, changeLocale } from "../i18n";
|
|
8
9
|
import { locale, _ } from "svelte-i18n";
|
|
9
10
|
import { setupi18n } from "../i18n";
|
|
11
|
+
import record from "./img/record.svg";
|
|
12
|
+
import { createEventDispatcher } from "svelte";
|
|
13
|
+
const dispatch = createEventDispatcher();
|
|
10
14
|
if (root === "") {
|
|
11
15
|
root = location.protocol + "//" + location.host + location.pathname;
|
|
12
16
|
}
|
|
@@ -38,6 +42,8 @@ onMount(() => {
|
|
|
38
42
|
});
|
|
39
43
|
let current_locale;
|
|
40
44
|
let current_theme = "system";
|
|
45
|
+
export let allow_zoom = true;
|
|
46
|
+
export let allow_video_trim = true;
|
|
41
47
|
locale.subscribe((value) => {
|
|
42
48
|
if (value) {
|
|
43
49
|
current_locale = value;
|
|
@@ -47,6 +53,12 @@ function handleLanguageChange(e) {
|
|
|
47
53
|
const new_locale = e.detail;
|
|
48
54
|
changeLocale(new_locale);
|
|
49
55
|
}
|
|
56
|
+
function handleZoomChange(e) {
|
|
57
|
+
allow_zoom = e.detail;
|
|
58
|
+
}
|
|
59
|
+
function handleVideoTrimChange(e) {
|
|
60
|
+
allow_video_trim = e.detail;
|
|
61
|
+
}
|
|
50
62
|
setupi18n();
|
|
51
63
|
</script>
|
|
52
64
|
|
|
@@ -112,6 +124,44 @@ setupi18n();
|
|
|
112
124
|
{/if}
|
|
113
125
|
</p>
|
|
114
126
|
</div>
|
|
127
|
+
<div class="banner-wrap">
|
|
128
|
+
<h2>{$_("common.screen_studio")} <span class="beta-tag">beta</span></h2>
|
|
129
|
+
<p class="padded">
|
|
130
|
+
Screen Studio allows you to record your screen and generates a video of your
|
|
131
|
+
app with automatically adding zoom in and zoom out effects as well as
|
|
132
|
+
trimming the video to remove the prediction time.
|
|
133
|
+
<br /><br />
|
|
134
|
+
Start recording by clicking the <i>Start Recording</i> button below and then
|
|
135
|
+
sharing the current browser tab of your Gradio demo. Use your app as you
|
|
136
|
+
would normally to generate a prediction.
|
|
137
|
+
<br />
|
|
138
|
+
Stop recording by clicking the <i>Stop Recording</i> button in the footer of
|
|
139
|
+
the demo.
|
|
140
|
+
<br /><br />
|
|
141
|
+
<Checkbox
|
|
142
|
+
label="Include automatic zoom in/out"
|
|
143
|
+
interactive={true}
|
|
144
|
+
value={allow_zoom}
|
|
145
|
+
on:change={handleZoomChange}
|
|
146
|
+
/>
|
|
147
|
+
<Checkbox
|
|
148
|
+
label="Include automatic video trimming"
|
|
149
|
+
interactive={true}
|
|
150
|
+
value={allow_video_trim}
|
|
151
|
+
on:change={handleVideoTrimChange}
|
|
152
|
+
/>
|
|
153
|
+
</p>
|
|
154
|
+
<button
|
|
155
|
+
class="record-button"
|
|
156
|
+
on:click={() => {
|
|
157
|
+
dispatch("close");
|
|
158
|
+
dispatch("start_recording");
|
|
159
|
+
}}
|
|
160
|
+
>
|
|
161
|
+
<img src={record} alt="Start Recording" />
|
|
162
|
+
Start Recording
|
|
163
|
+
</button>
|
|
164
|
+
</div>
|
|
115
165
|
|
|
116
166
|
<style>
|
|
117
167
|
.banner-wrap {
|
|
@@ -142,7 +192,8 @@ setupi18n();
|
|
|
142
192
|
margin-left: var(--size-2);
|
|
143
193
|
}
|
|
144
194
|
|
|
145
|
-
.theme-button
|
|
195
|
+
.theme-button,
|
|
196
|
+
.record-button {
|
|
146
197
|
display: flex;
|
|
147
198
|
align-items: center;
|
|
148
199
|
border: 1px solid var(--border-color-primary);
|
|
@@ -154,6 +205,15 @@ setupi18n();
|
|
|
154
205
|
cursor: pointer;
|
|
155
206
|
}
|
|
156
207
|
|
|
208
|
+
.record-button img {
|
|
209
|
+
margin-right: var(--size-1);
|
|
210
|
+
margin-left: var(--size-1);
|
|
211
|
+
width: var(--size-3);
|
|
212
|
+
}
|
|
213
|
+
.record-button:hover {
|
|
214
|
+
border-color: red;
|
|
215
|
+
}
|
|
216
|
+
|
|
157
217
|
.current-theme {
|
|
158
218
|
border: 1px solid var(--body-text-color-subdued);
|
|
159
219
|
color: var(--body-text-color);
|
|
@@ -173,4 +233,17 @@ setupi18n();
|
|
|
173
233
|
all: unset;
|
|
174
234
|
cursor: pointer;
|
|
175
235
|
}
|
|
236
|
+
|
|
237
|
+
.beta-tag {
|
|
238
|
+
position: relative;
|
|
239
|
+
top: -5px;
|
|
240
|
+
font-size: var(--text-xs);
|
|
241
|
+
background-color: var(--color-accent);
|
|
242
|
+
color: white;
|
|
243
|
+
padding: 2px 6px;
|
|
244
|
+
border-radius: 10px;
|
|
245
|
+
margin-left: 5px;
|
|
246
|
+
font-weight: normal;
|
|
247
|
+
text-transform: uppercase;
|
|
248
|
+
}
|
|
176
249
|
</style>
|
|
@@ -4,9 +4,12 @@ declare const __propDef: {
|
|
|
4
4
|
root: string;
|
|
5
5
|
space_id: string | null;
|
|
6
6
|
pwa_enabled: boolean | undefined;
|
|
7
|
+
allow_zoom?: boolean | undefined;
|
|
8
|
+
allow_video_trim?: boolean | undefined;
|
|
7
9
|
};
|
|
8
10
|
events: {
|
|
9
11
|
close: CustomEvent<any>;
|
|
12
|
+
start_recording: CustomEvent<any>;
|
|
10
13
|
} & {
|
|
11
14
|
[evt: string]: CustomEvent<any>;
|
|
12
15
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#000000"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <title>record [#982]</title> <desc>Created with Sketch.</desc> <defs> </defs> <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="Dribbble-Light-Preview" transform="translate(-380.000000, -3839.000000)" fill="#FF0000"> <g id="icons" transform="translate(56.000000, 160.000000)"> <path d="M338,3689 C338,3691.209 336.209,3693 334,3693 C331.791,3693 330,3691.209 330,3689 C330,3686.791 331.791,3685 334,3685 C336.209,3685 338,3686.791 338,3689 M334,3697 C329.589,3697 326,3693.411 326,3689 C326,3684.589 329.589,3681 334,3681 C338.411,3681 342,3684.589 342,3689 C342,3693.411 338.411,3697 334,3697 M334,3679 C328.477,3679 324,3683.477 324,3689 C324,3694.523 328.477,3699 334,3699 C339.523,3699 344,3694.523 344,3689 C344,3683.477 339.523,3679 334,3679" id="record-[#982]"> </path> </g> </g> </g> </g></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#000000"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <title>record [#982]</title> <desc>Created with Sketch.</desc> <defs> </defs> <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="Dribbble-Light-Preview" transform="translate(-380.000000, -3839.000000)" fill="#808080"> <g id="icons" transform="translate(56.000000, 160.000000)"> <path d="M338,3689 C338,3691.209 336.209,3693 334,3693 C331.791,3693 330,3691.209 330,3689 C330,3686.791 331.791,3685 334,3685 C336.209,3685 338,3686.791 338,3689 M334,3697 C329.589,3697 326,3693.411 326,3689 C326,3684.589 329.589,3681 334,3681 C338.411,3681 342,3684.589 342,3689 C342,3693.411 338.411,3697 334,3697 M334,3679 C328.477,3679 324,3683.477 324,3689 C324,3694.523 328.477,3699 334,3699 C339.523,3699 344,3694.523 344,3689 C344,3683.477 339.523,3679 334,3679" id="record-[#982]"> </path> </g> </g> </g> </g></svg>
|
|
@@ -1,14 +1,4 @@
|
|
|
1
1
|
export { Gradio } from "@gradio/utils";
|
|
2
2
|
export type I18nFormatter = typeof formatter;
|
|
3
|
-
/**
|
|
4
|
-
* i18n formatter with fallback to svelte-i18n's format function.
|
|
5
|
-
*
|
|
6
|
-
* @param value - The string to translate or format
|
|
7
|
-
* @returns The translated string
|
|
8
|
-
*
|
|
9
|
-
* This formatter attempts translation in the following order:
|
|
10
|
-
* 1. Direct translation of the input string
|
|
11
|
-
* 2. Checks if input matches any common key names
|
|
12
|
-
* 3. Falls back to svelte-i18n's format function
|
|
13
|
-
*/
|
|
14
3
|
export declare function formatter(value: string | null | undefined): string;
|
|
4
|
+
export declare const reactive_formatter: import("svelte/store").Readable<typeof formatter>;
|
|
@@ -1,25 +1,13 @@
|
|
|
1
|
-
import { format, _ } from "svelte-i18n";
|
|
2
|
-
import { get } from "svelte/store";
|
|
3
1
|
import { all_common_keys } from "./i18n";
|
|
2
|
+
import { _ } from "svelte-i18n";
|
|
3
|
+
import { get, derived } from "svelte/store";
|
|
4
4
|
export { Gradio } from "@gradio/utils";
|
|
5
|
-
/**
|
|
6
|
-
* i18n formatter with fallback to svelte-i18n's format function.
|
|
7
|
-
*
|
|
8
|
-
* @param value - The string to translate or format
|
|
9
|
-
* @returns The translated string
|
|
10
|
-
*
|
|
11
|
-
* This formatter attempts translation in the following order:
|
|
12
|
-
* 1. Direct translation of the input string
|
|
13
|
-
* 2. Checks if input matches any common key names
|
|
14
|
-
* 3. Falls back to svelte-i18n's format function
|
|
15
|
-
*/
|
|
16
5
|
export function formatter(value) {
|
|
17
6
|
if (value == null) {
|
|
18
7
|
return "";
|
|
19
8
|
}
|
|
20
9
|
const string_value = String(value);
|
|
21
10
|
const translate = get(_);
|
|
22
|
-
const initial_formatter = get(format);
|
|
23
11
|
let direct_translation = translate(string_value);
|
|
24
12
|
if (direct_translation !== string_value) {
|
|
25
13
|
return direct_translation;
|
|
@@ -35,10 +23,6 @@ export function formatter(value) {
|
|
|
35
23
|
break;
|
|
36
24
|
}
|
|
37
25
|
}
|
|
38
|
-
// fall back to the svelte-i18n formatter to maintain compatibility
|
|
39
|
-
const formatted = initial_formatter(string_value);
|
|
40
|
-
if (formatted !== string_value) {
|
|
41
|
-
return formatted;
|
|
42
|
-
}
|
|
43
26
|
return string_value;
|
|
44
27
|
}
|
|
28
|
+
export const reactive_formatter = derived(_, () => formatter);
|
package/dist/src/i18n.d.ts
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export interface I18nData {
|
|
2
|
+
__type__: "translation_metadata";
|
|
3
|
+
key: string;
|
|
4
|
+
}
|
|
5
|
+
export interface LangsRecord {
|
|
6
|
+
[lang: string]: any;
|
|
7
|
+
}
|
|
8
|
+
export declare function is_translation_metadata(obj: any): obj is I18nData;
|
|
9
|
+
export declare function translate_if_needed(value: any): string;
|
|
4
10
|
export declare function process_langs(): LangsRecord;
|
|
5
11
|
export declare const language_choices: [string, string][];
|
|
6
12
|
export declare let all_common_keys: Set<string>;
|
|
7
|
-
export declare function setupi18n(): Promise<void>;
|
|
13
|
+
export declare function setupi18n(custom_translations?: Record<string, Record<string, string>>): Promise<void>;
|
|
8
14
|
export declare function changeLocale(new_locale: string): void;
|
|
9
|
-
export
|
|
15
|
+
export declare function get_initial_locale(browser_locale: string | null, available_locales: string[], fallback_locale?: string): string;
|
|
16
|
+
export declare function load_translations(translations: LangsRecord | null | undefined): void;
|
package/dist/src/i18n.js
CHANGED
|
@@ -1,27 +1,87 @@
|
|
|
1
|
-
import { addMessages, init, getLocaleFromNavigator, locale
|
|
1
|
+
import { addMessages, init, getLocaleFromNavigator, locale } from "svelte-i18n";
|
|
2
|
+
import { formatter } from "./gradio_helper";
|
|
2
3
|
const langs = import.meta.glob("./lang/*.json", {
|
|
3
4
|
eager: true
|
|
4
5
|
});
|
|
5
|
-
export function
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
export function is_translation_metadata(obj) {
|
|
7
|
+
console.log(obj);
|
|
8
|
+
const result = obj &&
|
|
9
|
+
typeof obj === "object" &&
|
|
10
|
+
obj.__type__ === "translation_metadata" &&
|
|
11
|
+
typeof obj.key === "string";
|
|
12
|
+
return result;
|
|
13
|
+
}
|
|
14
|
+
// handles strings with embedded JSON metadata of shape "__i18n__{"key": "some.key"}"
|
|
15
|
+
export function translate_if_needed(value) {
|
|
16
|
+
if (typeof value !== "string") {
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
const i18n_marker = "__i18n__";
|
|
20
|
+
const marker_index = value.indexOf(i18n_marker);
|
|
21
|
+
if (marker_index === -1) {
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const before_marker = marker_index > 0 ? value.substring(0, marker_index) : "";
|
|
26
|
+
const after_marker_index = marker_index + i18n_marker.length;
|
|
27
|
+
const json_start = value.indexOf("{", after_marker_index);
|
|
28
|
+
let json_end = -1;
|
|
29
|
+
let bracket_count = 0;
|
|
30
|
+
for (let i = json_start; i < value.length; i++) {
|
|
31
|
+
if (value[i] === "{")
|
|
32
|
+
bracket_count++;
|
|
33
|
+
if (value[i] === "}")
|
|
34
|
+
bracket_count--;
|
|
35
|
+
if (bracket_count === 0) {
|
|
36
|
+
json_end = i + 1;
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (json_end === -1) {
|
|
41
|
+
console.error("Could not find end of JSON in i18n string");
|
|
42
|
+
return value;
|
|
43
|
+
}
|
|
44
|
+
const metadata_json = value.substring(json_start, json_end);
|
|
45
|
+
const after_json = json_end < value.length ? value.substring(json_end) : "";
|
|
46
|
+
try {
|
|
47
|
+
const metadata = JSON.parse(metadata_json);
|
|
48
|
+
if (metadata && metadata.key) {
|
|
49
|
+
const translated = formatter(metadata.key);
|
|
50
|
+
return before_marker + translated + after_json;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch (jsonError) {
|
|
54
|
+
console.error("Error parsing i18n JSON:", jsonError);
|
|
55
|
+
}
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
catch (e) {
|
|
59
|
+
console.error("Error processing translation:", e);
|
|
60
|
+
return value;
|
|
10
61
|
}
|
|
11
|
-
|
|
62
|
+
}
|
|
63
|
+
export function process_langs() {
|
|
64
|
+
return Object.fromEntries(Object.entries(langs).map(([path, module]) => [
|
|
65
|
+
path.split("/").pop().split(".")[0],
|
|
66
|
+
module.default
|
|
67
|
+
]));
|
|
12
68
|
}
|
|
13
69
|
const processed_langs = process_langs();
|
|
14
70
|
const available_locales = Object.keys(processed_langs);
|
|
15
71
|
export const language_choices = Object.entries(processed_langs).map(([code, data]) => [data._name || code, code]);
|
|
16
72
|
export let all_common_keys = new Set();
|
|
17
|
-
for (const lang in processed_langs) {
|
|
18
|
-
addMessages(lang, processed_langs[lang]);
|
|
19
|
-
}
|
|
20
73
|
let i18n_initialized = false;
|
|
21
|
-
|
|
22
|
-
|
|
74
|
+
let previous_translations;
|
|
75
|
+
export async function setupi18n(custom_translations) {
|
|
76
|
+
const should_reinitialize = i18n_initialized && custom_translations !== previous_translations;
|
|
77
|
+
if (i18n_initialized && !should_reinitialize) {
|
|
23
78
|
return;
|
|
24
79
|
}
|
|
80
|
+
previous_translations = custom_translations;
|
|
81
|
+
load_translations({
|
|
82
|
+
...processed_langs,
|
|
83
|
+
...(custom_translations ?? {})
|
|
84
|
+
});
|
|
25
85
|
const browser_locale = getLocaleFromNavigator();
|
|
26
86
|
let initial_locale = browser_locale && available_locales.includes(browser_locale)
|
|
27
87
|
? browser_locale
|
|
@@ -53,3 +113,24 @@ export async function setupi18n() {
|
|
|
53
113
|
export function changeLocale(new_locale) {
|
|
54
114
|
locale.set(new_locale);
|
|
55
115
|
}
|
|
116
|
+
export function get_initial_locale(browser_locale, available_locales, fallback_locale = "en") {
|
|
117
|
+
if (!browser_locale)
|
|
118
|
+
return fallback_locale;
|
|
119
|
+
if (available_locales.includes(browser_locale)) {
|
|
120
|
+
return browser_locale;
|
|
121
|
+
}
|
|
122
|
+
return fallback_locale;
|
|
123
|
+
}
|
|
124
|
+
export function load_translations(translations) {
|
|
125
|
+
if (!translations) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
for (const lang in translations) {
|
|
130
|
+
addMessages(lang, translations[lang]);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch (e) {
|
|
134
|
+
console.error("Error loading translations:", e);
|
|
135
|
+
}
|
|
136
|
+
}
|