@gradio/core 0.27.2 → 0.28.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,40 @@
1
1
  # @gradio/core
2
2
 
3
+ ## 0.28.0
4
+
5
+ ### Features
6
+
7
+ - [#11814](https://github.com/gradio-app/gradio/pull/11814) [`013784a`](https://github.com/gradio-app/gradio/commit/013784a7086047651e8e661a38bde7d5c7f10db7) - add validation support. Thanks @pngwn!
8
+ - [#11833](https://github.com/gradio-app/gradio/pull/11833) [`a446fcb`](https://github.com/gradio-app/gradio/commit/a446fcba6f3fe59c32194beb7f27fb6f80b61347) - Add gr.Navbar component for multipage apps. Thanks @abidlabs!
9
+ - [#11783](https://github.com/gradio-app/gradio/pull/11783) [`f407daf`](https://github.com/gradio-app/gradio/commit/f407daf8046f37e042ab8b86730ff0ab8d174bcf) - Add Walkthrough and Step compoents to facilitate multi-step workflows. Thanks @pngwn!
10
+
11
+ ### Fixes
12
+
13
+ - [#11815](https://github.com/gradio-app/gradio/pull/11815) [`1a477c5`](https://github.com/gradio-app/gradio/commit/1a477c5202c13097d1089fb70a32a08db22d7660) - Fix i18n string visible during load and i18n not respecting HTML. Thanks @freddyaboulton!
14
+ - [#11749](https://github.com/gradio-app/gradio/pull/11749) [`70f4532`](https://github.com/gradio-app/gradio/commit/70f4532a4dc7576dbdbe1d0a43a05644a0dfcf43) - fix various iFrame related UI issues when deploying to spaces. Thanks @pngwn!
15
+
16
+ ### Dependency updates
17
+
18
+ - @gradio/client@1.18.0
19
+ - @gradio/icons@0.14.0
20
+ - @gradio/atoms@0.17.0
21
+ - @gradio/statustracker@0.11.0
22
+ - @gradio/gallery@0.15.32
23
+ - @gradio/plot@0.9.23
24
+ - @gradio/upload@0.16.17
25
+ - @gradio/file@0.12.29
26
+ - @gradio/image@0.22.18
27
+ - @gradio/video@0.15.1
28
+ - @gradio/tabitem@0.6.0
29
+ - @gradio/tabs@0.5.0
30
+ - @gradio/code@0.14.16
31
+ - @gradio/paramviewer@0.7.16
32
+ - @gradio/column@0.2.1
33
+ - @gradio/textbox@0.11.0
34
+ - @gradio/dropdown@0.10.3
35
+ - @gradio/button@0.5.12
36
+ - @gradio/checkbox@0.4.29
37
+
3
38
  ## 0.27.2
4
39
 
5
40
  ### Features
@@ -193,6 +193,17 @@ async function handle_update(data, fn_index) {
193
193
  }
194
194
  });
195
195
  update_value(updates);
196
+ updates.forEach((update) => {
197
+ const component = components.find((comp) => comp.id === update.id);
198
+ if (component && component.type === "navbar") {
199
+ import("./navbar_store").then(({ navbar_config }) => {
200
+ navbar_config.update((current) => ({
201
+ ...current,
202
+ [update.prop]: update.value
203
+ }));
204
+ });
205
+ }
206
+ });
196
207
  await tick();
197
208
  }
198
209
  let submit_map = /* @__PURE__ */ new Map();
@@ -485,6 +496,40 @@ async function trigger_api_call(dep_index, trigger_id = null, event_data = null)
485
496
  }
486
497
  }
487
498
  function handle_status_update(message) {
499
+ if (message.code === "validation_error") {
500
+ const dep2 = dependencies.find((dep3) => dep3.id === message.fn_index);
501
+ if (dep2 === void 0 || message.message === void 0 || typeof message.message === "string") {
502
+ return;
503
+ }
504
+ const validation_error_data = [];
505
+ message.message.forEach((message2, i) => {
506
+ if (message2.is_valid) {
507
+ return;
508
+ }
509
+ validation_error_data.push({
510
+ id: dep2.inputs[i],
511
+ prop: "validation_error",
512
+ value: message2.message
513
+ });
514
+ validation_error_data.push({
515
+ id: dep2.inputs[i],
516
+ prop: "loading_status",
517
+ value: { validation_error: message2.message }
518
+ });
519
+ });
520
+ if (validation_error_data.length > 0) {
521
+ update_value(validation_error_data);
522
+ loading_status.update({
523
+ status: "complete",
524
+ fn_index: message.fn_index,
525
+ eta: 0,
526
+ queue: false,
527
+ queue_position: null
528
+ });
529
+ set_status($loading_status);
530
+ return;
531
+ }
532
+ }
488
533
  if (message.broken && !broken_connection) {
489
534
  messages = [
490
535
  new_message(
@@ -567,7 +612,7 @@ async function trigger_api_call(dep_index, trigger_id = null, event_data = null)
567
612
  submit_map.delete(dep_index);
568
613
  }
569
614
  if (status.stage === "error" && !broken_connection && !message.session_not_found) {
570
- if (status.message) {
615
+ if (status.message && typeof status.message === "string") {
571
616
  const _message = status.message.replace(
572
617
  MESSAGE_QUOTE_RE,
573
618
  (_2, b) => b
@@ -636,6 +681,11 @@ async function handle_mount() {
636
681
  target.addEventListener("prop_change", (e) => {
637
682
  if (!isCustomEvent(e)) throw new Error("not a custom event");
638
683
  const { id, prop, value } = e.detail;
684
+ if (prop === "value") {
685
+ update_value([
686
+ { id, prop: "loading_status", value: { validation_error: void 0 } }
687
+ ]);
688
+ }
639
689
  update_value([{ id, prop, value }]);
640
690
  if (prop === "input_ready" && value === false) {
641
691
  inputs_waiting.push(id);
@@ -780,6 +830,33 @@ function screen_recording() {
780
830
  screen_recorder.startRecording();
781
831
  }
782
832
  }
833
+ let footer_height = 0;
834
+ let root_container;
835
+ $: root_node = $_layout && get_root_node(root_container);
836
+ function get_root_node(container) {
837
+ if (!container) return null;
838
+ return container.children[container.children.length - 1];
839
+ }
840
+ onMount(() => {
841
+ if ("parentIFrame" in window) {
842
+ window.parentIFrame?.autoResize(false);
843
+ }
844
+ const mut = new MutationObserver((mutations) => {
845
+ if ("parentIFrame" in window) {
846
+ const box = root_node?.getBoundingClientRect();
847
+ if (!box) return;
848
+ window.parentIFrame?.size(box.bottom + footer_height + 32);
849
+ }
850
+ });
851
+ mut.observe(root_container, {
852
+ childList: true,
853
+ subtree: true,
854
+ attributes: true
855
+ });
856
+ return () => {
857
+ mut.disconnect();
858
+ };
859
+ });
783
860
  </script>
784
861
 
785
862
  <svelte:head>
@@ -795,6 +872,7 @@ function screen_recording() {
795
872
  <div
796
873
  class="contain"
797
874
  style:flex-grow={app_mode ? "1" : "auto"}
875
+ bind:this={root_container}
798
876
  style:margin-right={vibe_mode ? `${vibe_editor_width}px` : "0"}
799
877
  >
800
878
  {#if $_layout && app.config}
@@ -813,7 +891,7 @@ function screen_recording() {
813
891
  </div>
814
892
 
815
893
  {#if show_footer}
816
- <footer>
894
+ <footer bind:clientHeight={footer_height}>
817
895
  {#if show_api}
818
896
  <button
819
897
  on:click={() => {
@@ -1,6 +1,7 @@
1
- <script>import { getContext } from "svelte";
1
+ <script>import { getContext, onMount } from "svelte";
2
2
  import space_logo from "./images/spaces.svg";
3
3
  import { _ } from "svelte-i18n";
4
+ import { navbar_config } from "./navbar_store";
4
5
  export let wrapper;
5
6
  export let version;
6
7
  export let initial_height;
@@ -14,7 +15,38 @@ export let loaded;
14
15
  export let pages = [];
15
16
  export let current_page = "";
16
17
  export let root;
18
+ export let components = [];
17
19
  const set_page = getContext("set_lite_page");
20
+ let navbar_component = components.find((c) => c.type === "navbar");
21
+ let navbar = navbar_component ? {
22
+ visible: navbar_component.props.visible,
23
+ main_page_name: navbar_component.props.main_page_name,
24
+ value: navbar_component.props.value
25
+ } : null;
26
+ if (navbar) {
27
+ navbar_config.set(navbar);
28
+ }
29
+ $: if ($navbar_config) {
30
+ navbar = {
31
+ visible: $navbar_config.visible ?? true,
32
+ main_page_name: $navbar_config.main_page_name ?? "Home",
33
+ value: $navbar_config.value ?? null
34
+ };
35
+ }
36
+ $: show_navbar = pages.length > 1 && (navbar === null || navbar.visible !== false);
37
+ $: effective_pages = (() => {
38
+ let base_pages = navbar && navbar.main_page_name !== false && navbar.main_page_name !== "Home" ? pages.map(
39
+ ([route, label], index) => index === 0 && route === "" && label === "Home" ? [route, navbar.main_page_name] : [route, label]
40
+ ) : pages;
41
+ if (navbar?.value && navbar.value.length > 0) {
42
+ const existing_routes = new Set(base_pages.map(([route]) => route));
43
+ const additional_pages = navbar.value.map(
44
+ ([page_name, page_path]) => [page_path, page_name]
45
+ ).filter(([route]) => !existing_routes.has(route));
46
+ return [...base_pages, ...additional_pages];
47
+ }
48
+ return base_pages;
49
+ })();
18
50
  </script>
19
51
 
20
52
  <div
@@ -27,10 +59,10 @@ const set_page = getContext("set_lite_page");
27
59
  style:flex-grow={!display ? "1" : "auto"}
28
60
  data-iframe-height
29
61
  >
30
- {#if pages.length > 1}
62
+ {#if show_navbar}
31
63
  <div class="nav-holder">
32
64
  <nav class="fillable" class:fill_width>
33
- {#each pages as [route, label], i}
65
+ {#each effective_pages as [route, label], i}
34
66
  {#if is_lite}
35
67
  <button
36
68
  class:active={route === current_page}
@@ -42,9 +74,18 @@ const set_page = getContext("set_lite_page");
42
74
  </button>
43
75
  {:else}
44
76
  <a
45
- href={`${root}/${route}`}
77
+ href={route.startsWith("http://") || route.startsWith("https://")
78
+ ? route
79
+ : `${root}/${route}`}
46
80
  class:active={route === current_page}
47
81
  data-sveltekit-reload
82
+ target={route.startsWith("http://") ||
83
+ route.startsWith("https://")
84
+ ? "_blank"
85
+ : "_self"}
86
+ rel={route.startsWith("http://") || route.startsWith("https://")
87
+ ? "noopener noreferrer"
88
+ : ""}
48
89
  >{label}
49
90
  </a>
50
91
  {/if}
@@ -14,6 +14,7 @@ declare const __propDef: {
14
14
  pages?: [string, string][];
15
15
  current_page?: string;
16
16
  root: string;
17
+ components?: any[];
17
18
  };
18
19
  events: {
19
20
  [evt: string]: CustomEvent<any>;
@@ -15,11 +15,12 @@ export interface LangsRecord {
15
15
  };
16
16
  }
17
17
  export declare function is_translation_metadata(obj: any): obj is I18nData;
18
+ export declare const i18n_marker = "__i18n__";
18
19
  export declare function translate_if_needed(value: any): string;
19
20
  export declare function process_langs(): LangsRecord;
20
21
  export declare const language_choices: [string, string][];
21
22
  export declare let all_common_keys: Set<string>;
22
- export declare function setupi18n(custom_translations?: Record<string, Record<string, string>>): Promise<void>;
23
+ export declare function setupi18n(custom_translations?: Record<string, Record<string, string>>, preferred_locale?: string): Promise<void>;
23
24
  export declare function changeLocale(new_locale: string): void;
24
25
  export declare function get_initial_locale(browser_locale: string | null, available_locales: string[], fallback_locale?: string): string;
25
26
  export declare function load_translations(translations: {
package/dist/src/i18n.js CHANGED
@@ -43,12 +43,12 @@ export function is_translation_metadata(obj) {
43
43
  typeof obj.key === "string";
44
44
  return result;
45
45
  }
46
+ export const i18n_marker = "__i18n__";
46
47
  // handles strings with embedded JSON metadata of shape "__i18n__{"key": "some.key"}"
47
48
  export function translate_if_needed(value) {
48
49
  if (typeof value !== "string") {
49
50
  return value;
50
51
  }
51
- const i18n_marker = "__i18n__";
52
52
  const marker_index = value.indexOf(i18n_marker);
53
53
  if (marker_index === -1) {
54
54
  return value;
@@ -108,7 +108,7 @@ export const language_choices = Object.entries(processed_langs).map(([code]) =>
108
108
  export let all_common_keys = new Set();
109
109
  let i18n_initialized = false;
110
110
  let previous_translations;
111
- export async function setupi18n(custom_translations) {
111
+ export async function setupi18n(custom_translations, preferred_locale) {
112
112
  const should_reinitialize = i18n_initialized && custom_translations !== previous_translations;
113
113
  if (i18n_initialized && !should_reinitialize) {
114
114
  return;
@@ -118,7 +118,7 @@ export async function setupi18n(custom_translations) {
118
118
  processed_langs,
119
119
  custom_translations: custom_translations ?? {}
120
120
  });
121
- const browser_locale = getLocaleFromNavigator();
121
+ const browser_locale = preferred_locale ?? getLocaleFromNavigator();
122
122
  let initial_locale = browser_locale && available_locales.includes(browser_locale)
123
123
  ? browser_locale
124
124
  : null;
package/dist/src/init.js CHANGED
@@ -3,6 +3,7 @@ import { dequal } from "dequal";
3
3
  import { load_component } from "virtual:component-loader";
4
4
  import { create_loading_status_store } from "./stores";
5
5
  import { _ } from "svelte-i18n";
6
+ import { i18n_marker } from "./i18n";
6
7
  let pending_updates = [];
7
8
  const is_browser = typeof window !== "undefined";
8
9
  const raf = is_browser
@@ -38,7 +39,7 @@ export function create_components({ initial_layout = undefined } = {
38
39
  function set_event_specific_args(dependencies) {
39
40
  dependencies.forEach((dep) => {
40
41
  dep.targets.forEach((target) => {
41
- const instance = instance_map[target[0]];
42
+ const instance = instance_map?.[target[0]];
42
43
  if (instance && dep.event_specific_args?.length > 0) {
43
44
  dep.event_specific_args?.forEach((arg) => {
44
45
  instance.props[arg] = dep[arg];
@@ -133,7 +134,7 @@ export function create_components({ initial_layout = undefined } = {
133
134
  get_inputs_outputs(dep, inputs, outputs);
134
135
  });
135
136
  target_map.set(_target_map);
136
- let current_element = instance_map[layout.id];
137
+ let current_element = instance_map?.[layout.id];
137
138
  let all_current_children = [];
138
139
  const add_to_current_children = (component) => {
139
140
  all_current_children.push(component);
@@ -149,7 +150,7 @@ export function create_components({ initial_layout = undefined } = {
149
150
  if (component.rendered_in === render_id) {
150
151
  let replacement_component = replacement_components.find((c) => c.key === component.key);
151
152
  if (component.key != null && replacement_component !== undefined) {
152
- const instance = instance_map[component.id];
153
+ const instance = instance_map?.[component.id];
153
154
  for (const prop in replacement_component.props) {
154
155
  if (!replacement_component.props.preserved_by_key?.includes(prop)) {
155
156
  instance.props[prop] = replacement_component.props[prop];
@@ -157,20 +158,21 @@ export function create_components({ initial_layout = undefined } = {
157
158
  }
158
159
  }
159
160
  else {
160
- delete instance_map[_id];
161
+ if (instance_map)
162
+ delete instance_map[_id];
161
163
  if (_component_map.has(_id)) {
162
164
  _component_map.delete(_id);
163
165
  }
164
166
  }
165
167
  }
166
168
  });
167
- const components_to_add = new_components.concat(replacement_components.filter((c) => !instance_map[c.id]));
169
+ const components_to_add = new_components.concat(replacement_components.filter((c) => !instance_map?.[c.id]));
168
170
  components_to_add.forEach((c) => {
169
171
  instance_map[c.id] = c;
170
172
  _component_map.set(c.id, c);
171
173
  });
172
174
  if (current_element.parent) {
173
- current_element.parent.children[current_element.parent.children.indexOf(current_element)] = instance_map[layout.id];
175
+ current_element.parent.children[current_element.parent.children.indexOf(current_element)] = instance_map?.[layout.id];
174
176
  }
175
177
  walk_layout(layout, root, _components.concat(components), current_element.parent).then(() => {
176
178
  layout_store.set(_rootNode);
@@ -181,7 +183,7 @@ export function create_components({ initial_layout = undefined } = {
181
183
  set_event_specific_args(dependencies);
182
184
  }
183
185
  async function walk_layout(node, root, components, parent) {
184
- const instance = instance_map[node.id];
186
+ const instance = instance_map?.[node.id];
185
187
  if (!instance.component) {
186
188
  const constructor_key = instance.component_class_id || instance.type;
187
189
  let component_constructor = constructor_map.get(constructor_key);
@@ -202,9 +204,10 @@ export function create_components({ initial_layout = undefined } = {
202
204
  if (node.children) {
203
205
  instance.children = await Promise.all(node.children.map((v) => walk_layout(v, root, components, instance)));
204
206
  }
205
- if (instance.type === "tabs" && !instance.props.initial_tabs) {
207
+ if ((instance.type === "tabs" && !instance.props.initial_tabs) ||
208
+ (instance.type === "walkthrough" && !instance.props.initial_tabs)) {
206
209
  const tab_items_props = node.children?.map((c, i) => {
207
- const instance = instance_map[c.id];
210
+ const instance = instance_map?.[c.id];
208
211
  instance.props.id ??= c.id;
209
212
  return {
210
213
  type: instance.type,
@@ -215,18 +218,19 @@ export function create_components({ initial_layout = undefined } = {
215
218
  }
216
219
  };
217
220
  }) || [];
218
- const child_tab_items = tab_items_props.filter((child) => child.type === "tabitem");
221
+ const _type = instance.type === "walkthrough" ? "walkthroughstep" : "tabitem";
222
+ const child_tab_items = tab_items_props.filter((child) => child.type === _type);
219
223
  instance.props.initial_tabs = child_tab_items?.map((child) => ({
220
- label: child.props.label,
224
+ label: child.props.label.includes(i18n_marker) ? "" : child.props.label,
221
225
  id: child.props.id,
222
226
  visible: typeof child.props.visible === "boolean" ? child.props.visible : true,
223
227
  interactive: child.props.interactive,
224
228
  order: child.props.order
225
229
  }));
226
230
  }
227
- if (instance.type === "tabs") {
231
+ if (instance.type === "tabs" || instance.type === "walkthrough") {
228
232
  node.children?.forEach((c, i) => {
229
- const child = instance_map[c.id];
233
+ const child = instance_map?.[c.id];
230
234
  child.props.order = i;
231
235
  });
232
236
  }
@@ -272,7 +276,7 @@ export function create_components({ initial_layout = undefined } = {
272
276
  */
273
277
  function has_visibility_changes(updates) {
274
278
  return updates.some((update_batch) => update_batch.some((update) => {
275
- const instance = instance_map[update.id];
279
+ const instance = instance_map?.[update.id];
276
280
  if (!instance)
277
281
  return false;
278
282
  // Check for visibility property changes
@@ -300,7 +304,7 @@ export function create_components({ initial_layout = undefined } = {
300
304
  const update = pending_updates[i][j];
301
305
  if (!update)
302
306
  continue;
303
- const instance = instance_map[update.id];
307
+ const instance = instance_map?.[update.id];
304
308
  if (!instance)
305
309
  continue;
306
310
  let new_value;
@@ -0,0 +1,154 @@
1
+ {
2
+ "_name": "Bahasa Indonesia",
3
+ "3D_model": {
4
+ "3d_model": "Model 3D",
5
+ "drop_to_upload": "Letakkan file model 3D (.obj, .glb, .stl, .gltf, .splat, atau .ply) di sini untuk mengunggah"
6
+ },
7
+ "annotated_image": {
8
+ "annotated_image": "Gambar Beranotasi"
9
+ },
10
+ "audio": {
11
+ "allow_recording_access": "Mohon izinkan akses ke mikrofon untuk merekam.",
12
+ "audio": "Audio",
13
+ "record_from_microphone": "Rekam dari mikrofon",
14
+ "stop_recording": "Hentikan rekaman",
15
+ "no_device_support": "Perangkat media tidak dapat diakses. Pastikan Anda menjalankan dari sumber yang aman (https) atau localhost (atau Anda telah meneruskan sertifikat SSL yang valid ke ssl_verify), dan Anda telah mengizinkan akses browser ke perangkat Anda.",
16
+ "stop": "Berhenti",
17
+ "resume": "Lanjutkan",
18
+ "record": "Rekam",
19
+ "no_microphone": "Tidak ada mikrofon yang ditemukan",
20
+ "pause": "Jeda",
21
+ "play": "Putar",
22
+ "waiting": "Menunggu",
23
+ "drop_to_upload": "Letakkan file audio di sini untuk mengunggah"
24
+ },
25
+ "blocks": {
26
+ "connection_can_break": "Di perangkat seluler, koneksi dapat terputus jika tab ini tidak dalam fokus atau perangkat dalam mode tidur, sehingga Anda kehilangan posisi dalam antrian.",
27
+ "long_requests_queue": "Ada antrian panjang dari permintaan yang tertunda. Gandakan Ruang ini untuk melompati antrian.",
28
+ "lost_connection": "Koneksi terputus karena meninggalkan halaman. Bergabung kembali ke antrian...",
29
+ "waiting_for_inputs": "Menunggu file selesai diunggah, mohon coba lagi."
30
+ },
31
+ "checkbox": {
32
+ "checkbox": "Kotak centang",
33
+ "checkbox_group": "Grup kotak centang"
34
+ },
35
+ "code": {
36
+ "code": "Kode"
37
+ },
38
+ "color_picker": {
39
+ "color_picker": "Pemilih Warna"
40
+ },
41
+ "common": {
42
+ "built_with": "dibuat dengan",
43
+ "built_with_gradio": "Dibuat dengan Gradio",
44
+ "clear": "Bersihkan",
45
+ "download": "Unduh",
46
+ "edit": "Edit",
47
+ "empty": "Kosong",
48
+ "error": "Error",
49
+ "hosted_on": "Di-hosting di",
50
+ "loading": "Memuat",
51
+ "logo": "logo",
52
+ "or": "atau",
53
+ "remove": "Hapus",
54
+ "settings": "Pengaturan",
55
+ "share": "Bagikan",
56
+ "submit": "Kirim",
57
+ "undo": "Urungkan",
58
+ "no_devices": "Tidak ada perangkat yang ditemukan",
59
+ "language": "Bahasa",
60
+ "display_theme": "Tema Tampilan",
61
+ "pwa": "Aplikasi Web Progresif"
62
+ },
63
+ "dataframe": {
64
+ "incorrect_format": "Format salah, hanya file CSV dan TSV yang didukung",
65
+ "new_column": "Tambah kolom",
66
+ "new_row": "Baris baru",
67
+ "add_row_above": "Tambah baris di atas",
68
+ "add_row_below": "Tambah baris di bawah",
69
+ "add_column_left": "Tambah kolom ke kiri",
70
+ "add_column_right": "Tambah kolom ke kanan",
71
+ "delete_row": "Hapus baris",
72
+ "delete_column": "Hapus kolom",
73
+ "sort_column": "Urutkan kolom",
74
+ "sort_ascending": "Urutkan menaik",
75
+ "sort_descending": "Urutkan menurun",
76
+ "drop_to_upload": "Letakkan file CSV atau TSV di sini untuk mengimpor data ke dataframe",
77
+ "clear_sort": "Bersihkan pengurutan"
78
+ },
79
+ "dropdown": {
80
+ "dropdown": "Dropdown"
81
+ },
82
+ "errors": {
83
+ "build_error": "ada error saat membangun",
84
+ "config_error": "ada error konfigurasi",
85
+ "contact_page_author": "Mohon hubungi penulis halaman untuk memberitahu mereka.",
86
+ "no_app_file": "tidak ada file aplikasi",
87
+ "runtime_error": "ada error runtime",
88
+ "space_not_working": "\"Ruang tidak berfungsi karena\" {0}",
89
+ "space_paused": "ruang sedang dijeda",
90
+ "use_via_api": "Gunakan melalui API"
91
+ },
92
+ "file": {
93
+ "uploading": "Mengunggah..."
94
+ },
95
+ "highlighted_text": {
96
+ "highlighted_text": "Teks yang Disorot"
97
+ },
98
+ "image": {
99
+ "allow_webcam_access": "Mohon izinkan akses ke webcam untuk merekam.",
100
+ "brush_color": "Warna kuas",
101
+ "brush_radius": "Radius kuas",
102
+ "image": "Gambar",
103
+ "remove_image": "Hapus Gambar",
104
+ "select_brush_color": "Pilih warna kuas",
105
+ "start_drawing": "Mulai menggambar",
106
+ "use_brush": "Gunakan kuas",
107
+ "drop_to_upload": "Letakkan file gambar di sini untuk mengunggah"
108
+ },
109
+ "label": {
110
+ "label": "Label"
111
+ },
112
+ "login": {
113
+ "enable_cookies": "Jika Anda mengunjungi Ruang HuggingFace dalam mode Penyamaran, Anda harus mengaktifkan cookie pihak ketiga.",
114
+ "incorrect_credentials": "Kredensial salah",
115
+ "username": "nama pengguna",
116
+ "password": "kata sandi",
117
+ "login": "Masuk"
118
+ },
119
+ "number": {
120
+ "number": "Nomor"
121
+ },
122
+ "plot": {
123
+ "plot": "Plot"
124
+ },
125
+ "radio": {
126
+ "radio": "Tombol Radio"
127
+ },
128
+ "slider": {
129
+ "slider": "Penggeser"
130
+ },
131
+ "upload_text": {
132
+ "click_to_upload": "Klik untuk Mengunggah",
133
+ "drop_audio": "Letakkan Audio di Sini",
134
+ "drop_csv": "Letakkan CSV di Sini",
135
+ "drop_file": "Letakkan File di Sini",
136
+ "drop_image": "Letakkan Gambar di Sini",
137
+ "drop_video": "Letakkan Video di Sini",
138
+ "drop_gallery": "Letakkan Media di Sini",
139
+ "paste_clipboard": "Tempel dari Papan Klip"
140
+ },
141
+ "video": {
142
+ "drop_to_upload": "Letakkan file video di sini untuk mengunggah"
143
+ },
144
+ "chatbot": {
145
+ "edit": "Edit",
146
+ "retry": "Coba lagi",
147
+ "undo": "Urungkan",
148
+ "submit": "Kirim",
149
+ "cancel": "Batal",
150
+ "like": "Suka",
151
+ "dislike": "Tidak Suka",
152
+ "clear": "Bersihkan obrolan"
153
+ }
154
+ }
@@ -0,0 +1,6 @@
1
+ export interface NavbarConfig {
2
+ visible?: boolean;
3
+ main_page_name?: string | false;
4
+ value?: [string, string][] | null;
5
+ }
6
+ export declare const navbar_config: import("svelte/store").Writable<NavbarConfig | null>;
@@ -0,0 +1,2 @@
1
+ import { writable } from "svelte/store";
2
+ export const navbar_config = writable(null);
@@ -17,6 +17,7 @@ export interface LoadingStatus {
17
17
  unit: string | null;
18
18
  desc: string | null;
19
19
  }[];
20
+ validation_error?: string | null;
20
21
  }
21
22
  export type LoadingStatusCollection = Record<number, LoadingStatus>;
22
23
  interface LoadingStatusStore {
@@ -25,6 +26,7 @@ interface LoadingStatusStore {
25
26
  register: (index: number, inputs: number[], outputs: number[]) => void;
26
27
  get_status_for_fn: (i: number) => LoadingStatus["status"];
27
28
  get_inputs_to_update: () => Map<number, string>;
29
+ update_component_status: (index: number, status: Partial<LoadingStatus>) => void;
28
30
  }
29
31
  export declare function create_loading_status_store(): LoadingStatusStore;
30
32
  export type LoadingStatusType = ReturnType<typeof create_loading_status_store>;
@@ -79,8 +79,18 @@ export function create_loading_status_store() {
79
79
  fn_inputs[index] = inputs;
80
80
  fn_outputs[index] = outputs;
81
81
  }
82
+ function update_component_status(index, status) {
83
+ store.update((outputs) => {
84
+ outputs[index] = {
85
+ ...outputs[index],
86
+ ...status
87
+ };
88
+ return outputs;
89
+ });
90
+ }
82
91
  return {
83
92
  update,
93
+ update_component_status,
84
94
  register,
85
95
  subscribe: store.subscribe,
86
96
  get_status_for_fn(i) {
@@ -1,7 +1,6 @@
1
1
  import type { StoryObj } from "@storybook/svelte";
2
2
  import I18nMultiLanguageTestComponent from "./I18nMultiLanguageTestComponent.svelte";
3
3
  declare const meta: {
4
- title: string;
5
4
  component: typeof I18nMultiLanguageTestComponent;
6
5
  parameters: {
7
6
  layout: string;
@@ -1,6 +1,6 @@
1
1
  import I18nMultiLanguageTestComponent from "./I18nMultiLanguageTestComponent.svelte";
2
2
  const meta = {
3
- title: "Core/I18n Multi-Language Test",
3
+ // title: "Core/I18n Multi-Language Test",
4
4
  component: I18nMultiLanguageTestComponent,
5
5
  parameters: {
6
6
  layout: "centered"