@gradio/core 1.0.0-dev.0 → 1.0.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.
Files changed (109) hide show
  1. package/CHANGELOG.md +110 -0
  2. package/dist/index.d.ts +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/src/Blocks.svelte +534 -1001
  5. package/dist/src/Blocks.svelte.d.ts +32 -45
  6. package/dist/src/Embed.svelte +82 -55
  7. package/dist/src/Embed.svelte.d.ts +39 -30
  8. package/dist/src/Login.svelte +33 -29
  9. package/dist/src/Login.svelte.d.ts +21 -19
  10. package/dist/src/MountComponents.svelte +19 -25
  11. package/dist/src/MountComponents.svelte.d.ts +5 -28
  12. package/dist/src/{init.d.ts → _init.d.ts} +5 -4
  13. package/dist/src/{init.js → _init.js} +31 -108
  14. package/dist/src/api_docs/ApiBanner.svelte +12 -8
  15. package/dist/src/api_docs/ApiBanner.svelte.d.ts +22 -20
  16. package/dist/src/api_docs/ApiDocs.svelte +356 -247
  17. package/dist/src/api_docs/ApiDocs.svelte.d.ts +27 -24
  18. package/dist/src/api_docs/ApiRecorder.svelte +6 -3
  19. package/dist/src/api_docs/ApiRecorder.svelte.d.ts +19 -17
  20. package/dist/src/api_docs/CodeSnippet.svelte +122 -48
  21. package/dist/src/api_docs/CodeSnippet.svelte.d.ts +29 -25
  22. package/dist/src/api_docs/CopyButton.svelte +69 -13
  23. package/dist/src/api_docs/CopyButton.svelte.d.ts +18 -16
  24. package/dist/src/api_docs/CopyMarkdown.svelte +734 -0
  25. package/dist/src/api_docs/CopyMarkdown.svelte.d.ts +37 -0
  26. package/dist/src/api_docs/EndpointDetail.svelte +81 -23
  27. package/dist/src/api_docs/EndpointDetail.svelte.d.ts +23 -18
  28. package/dist/src/api_docs/IconArrowUpRight.svelte +34 -0
  29. package/dist/src/api_docs/IconArrowUpRight.svelte.d.ts +20 -0
  30. package/dist/src/api_docs/IconCaret.svelte +39 -0
  31. package/dist/src/api_docs/IconCaret.svelte.d.ts +20 -0
  32. package/dist/src/api_docs/IconHuggingChat.svelte +62 -0
  33. package/dist/src/api_docs/IconHuggingChat.svelte.d.ts +20 -0
  34. package/dist/src/api_docs/InputPayload.svelte +17 -11
  35. package/dist/src/api_docs/InputPayload.svelte.d.ts +25 -23
  36. package/dist/src/api_docs/InstallSnippet.svelte +9 -6
  37. package/dist/src/api_docs/InstallSnippet.svelte.d.ts +18 -16
  38. package/dist/src/api_docs/MCPSnippet.svelte +139 -126
  39. package/dist/src/api_docs/MCPSnippet.svelte.d.ts +60 -58
  40. package/dist/src/api_docs/NoApi.svelte +7 -4
  41. package/dist/src/api_docs/NoApi.svelte.d.ts +20 -18
  42. package/dist/src/api_docs/ParametersSnippet.svelte +8 -6
  43. package/dist/src/api_docs/ParametersSnippet.svelte.d.ts +21 -19
  44. package/dist/src/api_docs/PercentileChart.svelte +125 -0
  45. package/dist/src/api_docs/PercentileChart.svelte.d.ts +22 -0
  46. package/dist/src/api_docs/RecordingSnippet.svelte +124 -110
  47. package/dist/src/api_docs/RecordingSnippet.svelte.d.ts +24 -22
  48. package/dist/src/api_docs/ResponseSnippet.svelte +7 -5
  49. package/dist/src/api_docs/ResponseSnippet.svelte.d.ts +21 -19
  50. package/dist/src/api_docs/Settings.svelte +73 -62
  51. package/dist/src/api_docs/Settings.svelte.d.ts +25 -23
  52. package/dist/src/api_docs/SettingsBanner.svelte +11 -8
  53. package/dist/src/api_docs/SettingsBanner.svelte.d.ts +20 -18
  54. package/dist/src/api_docs/TryButton.svelte +5 -3
  55. package/dist/src/api_docs/TryButton.svelte.d.ts +19 -17
  56. package/dist/src/api_docs/img/IconCheck.svelte +33 -0
  57. package/dist/src/api_docs/img/IconCheck.svelte.d.ts +26 -0
  58. package/dist/src/api_docs/img/IconCopy.svelte +40 -0
  59. package/dist/src/api_docs/img/IconCopy.svelte.d.ts +26 -0
  60. package/dist/src/api_docs/img/clear.svelte.d.ts +22 -21
  61. package/dist/src/dependency.d.ts +145 -0
  62. package/dist/src/dependency.js +668 -0
  63. package/dist/src/init.svelte.d.ts +78 -0
  64. package/dist/src/init.svelte.js +469 -0
  65. package/dist/src/init_utils.d.ts +32 -0
  66. package/dist/src/init_utils.js +73 -0
  67. package/dist/src/lang/en.json +10 -1
  68. package/dist/src/lang/get_lang_names.js +0 -3
  69. package/dist/src/lang/ru.json +10 -1
  70. package/dist/src/stores.d.ts +0 -21
  71. package/dist/src/stories/I18nMultiLanguageTestComponent.svelte +5 -3
  72. package/dist/src/stories/I18nMultiLanguageTestComponent.svelte.d.ts +16 -14
  73. package/dist/src/stories/I18nTestSetup.svelte +14 -10
  74. package/dist/src/stories/I18nTestSetup.svelte.d.ts +18 -16
  75. package/dist/src/types.d.ts +31 -26
  76. package/index.ts +1 -1
  77. package/package.json +62 -63
  78. package/src/Blocks.svelte +360 -1063
  79. package/src/MountComponents.svelte +17 -27
  80. package/src/{init.ts → _init.ts} +49 -126
  81. package/src/api_docs/ApiDocs.svelte +84 -62
  82. package/src/api_docs/CodeSnippet.svelte +83 -24
  83. package/src/api_docs/CopyButton.svelte +61 -7
  84. package/src/api_docs/CopyMarkdown.svelte +734 -0
  85. package/src/api_docs/EndpointDetail.svelte +73 -17
  86. package/src/api_docs/IconArrowUpRight.svelte +34 -0
  87. package/src/api_docs/IconCaret.svelte +39 -0
  88. package/src/api_docs/IconHuggingChat.svelte +62 -0
  89. package/src/api_docs/MCPSnippet.svelte +44 -73
  90. package/src/api_docs/ParametersSnippet.svelte +1 -1
  91. package/src/api_docs/PercentileChart.svelte +125 -0
  92. package/src/api_docs/ResponseSnippet.svelte +1 -1
  93. package/src/api_docs/Settings.svelte +11 -11
  94. package/src/api_docs/img/IconCheck.svelte +33 -0
  95. package/src/api_docs/img/IconCopy.svelte +40 -0
  96. package/src/dependency.ts +909 -0
  97. package/src/init.svelte.ts +717 -0
  98. package/src/init_utils.ts +99 -0
  99. package/src/lang/en.json +10 -1
  100. package/src/lang/get_lang_names.js +0 -3
  101. package/src/lang/ru.json +10 -1
  102. package/src/stores.ts +22 -22
  103. package/src/types.ts +55 -43
  104. package/dist/src/Render.svelte +0 -105
  105. package/dist/src/Render.svelte.d.ts +0 -31
  106. package/dist/src/RenderComponent.svelte +0 -72
  107. package/dist/src/RenderComponent.svelte.d.ts +0 -33
  108. package/src/Render.svelte +0 -126
  109. package/src/RenderComponent.svelte +0 -91
@@ -0,0 +1,717 @@
1
+ import {
2
+ determine_interactivity,
3
+ get_component,
4
+ get_inputs_outputs
5
+ } from "./init_utils";
6
+ import { translate_if_needed } from "./i18n";
7
+ import { tick } from "svelte";
8
+
9
+ import type {
10
+ ComponentMeta,
11
+ ProcessedComponentMeta,
12
+ LayoutNode,
13
+ Dependency,
14
+ LoadingComponent,
15
+ AppConfig,
16
+ ServerFunctions
17
+ } from "./types";
18
+ import type { SharedProps } from "@gradio/utils";
19
+ import { allowed_shared_props } from "@gradio/utils";
20
+ import { Client } from "@gradio/client";
21
+
22
+ type client_return = Awaited<ReturnType<typeof Client.connect>>;
23
+
24
+ type set_data_type = (data: Record<string, unknown>) => void;
25
+ type get_data_type = () => Promise<Record<string, unknown>>;
26
+ type visitor<T> = (node: T) => ProcessedComponentMeta;
27
+
28
+ type Tab = {
29
+ label: string;
30
+ id: string;
31
+ visible: boolean;
32
+ interactive: boolean;
33
+ elem_id: string | undefined;
34
+ scale: number | null;
35
+ order?: number;
36
+ };
37
+
38
+ const type_map = {
39
+ walkthrough: "tabs",
40
+ walkthroughstep: "tabitem"
41
+ };
42
+ export class AppTree {
43
+ /** the raw component structure received from the backend */
44
+ #component_payload: ComponentMeta[];
45
+ /** the raw layout node structure received from the backend */
46
+ #layout_payload: LayoutNode;
47
+ /** the raw dependency structure received from the backend */
48
+ #dependency_payload: Dependency[];
49
+ /** Need this to set i18n in re-render */
50
+ reactive_formatter: (str: string) => string = (str: string) => str;
51
+ /** the config for the app */
52
+ #config: AppConfig;
53
+ client: client_return;
54
+
55
+ /** the root node of the processed layout tree */
56
+ root = $state<ProcessedComponentMeta>();
57
+
58
+ /** a set of all component IDs that are inputs to dependencies */
59
+ #input_ids: Set<number> = new Set();
60
+ /** a set of all component IDs that are outputs of dependencies */
61
+ #output_ids: Set<number> = new Set();
62
+
63
+ /** A list of components that are currently loading */
64
+ #pending_components: Array<LoadingComponent> = [];
65
+
66
+ #get_callbacks = new Map<number, get_data_type>();
67
+ #set_callbacks = new Map<number, set_data_type>();
68
+ component_ids: number[];
69
+ initial_tabs: Record<number, Tab[]> = {};
70
+
71
+ components_to_register: Set<number> = new Set();
72
+ ready: Promise<void>;
73
+ ready_resolve!: () => void;
74
+ resolved: boolean = false;
75
+
76
+ constructor(
77
+ components: ComponentMeta[],
78
+ layout: LayoutNode,
79
+ dependencies: Dependency[],
80
+ config: AppConfig,
81
+ app: client_return,
82
+ reactive_formatter: (str: string) => string
83
+ ) {
84
+ this.ready = new Promise<void>((resolve) => {
85
+ this.ready_resolve = resolve;
86
+ });
87
+ this.reactive_formatter = reactive_formatter;
88
+
89
+ this.#config = config;
90
+ this.#component_payload = components;
91
+ this.#layout_payload = layout;
92
+ this.#dependency_payload = dependencies;
93
+ this.root = this.create_node(
94
+ { id: layout.id, children: [] },
95
+ new Map(),
96
+ true
97
+ );
98
+ for (const comp of components) {
99
+ if (comp.props.visible != false) this.components_to_register.add(comp.id);
100
+ }
101
+
102
+ this.client = app;
103
+
104
+ this.prepare();
105
+
106
+ const component_map = components.reduce((map, comp) => {
107
+ map.set(comp.id, comp);
108
+ return map;
109
+ }, new Map<number, ComponentMeta>());
110
+
111
+ this.root!.children = this.#layout_payload.children.map((node) =>
112
+ this.traverse(node, (node) => {
113
+ const new_node = this.create_node(
114
+ node,
115
+ component_map,
116
+ false,
117
+ this.reactive_formatter
118
+ );
119
+ return new_node;
120
+ })
121
+ );
122
+ this.component_ids = components.map((c) => c.id);
123
+ this.initial_tabs = {};
124
+ gather_initial_tabs(this.root!, this.initial_tabs);
125
+ this.postprocess(this.root!);
126
+ }
127
+
128
+ reload(
129
+ components: ComponentMeta[],
130
+ layout: LayoutNode,
131
+ dependencies: Dependency[],
132
+ config: AppConfig
133
+ ) {
134
+ this.#layout_payload = layout;
135
+ this.#component_payload = components;
136
+ this.#config = config;
137
+ this.#dependency_payload = dependencies;
138
+
139
+ this.root = this.create_node(
140
+ { id: layout.id, children: [] },
141
+ new Map(),
142
+ true
143
+ );
144
+ for (const comp of components) {
145
+ if (comp.props.visible != false) this.components_to_register.add(comp.id);
146
+ }
147
+
148
+ this.prepare();
149
+
150
+ const component_map = components.reduce((map, comp) => {
151
+ map.set(comp.id, comp);
152
+ return map;
153
+ }, new Map<number, ComponentMeta>());
154
+
155
+ this.root!.children = this.#layout_payload.children.map((node) =>
156
+ this.traverse(node, (node) => {
157
+ const new_node = this.create_node(
158
+ node,
159
+ component_map,
160
+ false,
161
+ this.reactive_formatter
162
+ );
163
+ return new_node;
164
+ })
165
+ );
166
+ this.component_ids = components.map((c) => c.id);
167
+ this.initial_tabs = {};
168
+ gather_initial_tabs(this.root!, this.initial_tabs);
169
+ this.postprocess(this.root!);
170
+ }
171
+
172
+ /**
173
+ * Registers a component with its ID and data callbacks
174
+ * @param id the ID of the component
175
+ * @param _set_data the set data callback
176
+ * @param _get_data the get data callback
177
+ */
178
+ register_component(
179
+ id: number,
180
+ _set_data: set_data_type,
181
+ _get_data: get_data_type
182
+ ): void {
183
+ this.#set_callbacks.set(id, _set_data);
184
+ this.#get_callbacks.set(id, _get_data);
185
+ this.components_to_register.delete(id);
186
+ if (this.components_to_register.size === 0 && !this.resolved) {
187
+ this.resolved = true;
188
+ this.ready_resolve();
189
+ }
190
+ }
191
+
192
+ /**
193
+ * Preprocess the payloads to get the correct state read to build the tree
194
+ */
195
+ prepare() {
196
+ const [inputs, outputs] = get_inputs_outputs(this.#dependency_payload);
197
+ this.#input_ids = inputs;
198
+ this.#output_ids = outputs;
199
+ }
200
+
201
+ /** Processes the layout payload into a tree of components */
202
+ process() {}
203
+
204
+ postprocess(tree: ProcessedComponentMeta) {
205
+ this.root = this.traverse(tree, [
206
+ (node) => handle_visibility(node, this.#config.root),
207
+ (node) =>
208
+ untrack_children_of_invisible_parents(
209
+ node,
210
+ this.#config.root,
211
+ this.components_to_register
212
+ ),
213
+ (node) =>
214
+ handle_empty_forms(
215
+ node,
216
+ this.#config.root,
217
+ this.components_to_register
218
+ ),
219
+ (node) => translate_props(node, this.#config.root),
220
+ (node) => apply_initial_tabs(node, this.#config.root, this.initial_tabs),
221
+ (node) => this.find_attached_events(node, this.#dependency_payload)
222
+ ]);
223
+ }
224
+
225
+ find_attached_events(
226
+ node: ProcessedComponentMeta,
227
+ dependencies: Dependency[]
228
+ ): ProcessedComponentMeta {
229
+ const attached_events = dependencies
230
+ .filter((dep) => dep.targets.find(([id]) => id === node.id))
231
+ .map((dep) => {
232
+ const target = dep.targets.find(([id]) => id === node.id);
233
+ return target ? target[1] : null;
234
+ })
235
+ .filter(Boolean) as string[];
236
+
237
+ node.props.shared_props.attached_events = attached_events;
238
+
239
+ return node;
240
+ }
241
+
242
+ /**
243
+ * Traverses the layout tree and applies a callback to each node
244
+ * @param node the current layout node
245
+ * @param visit the callback to apply to each node
246
+ * @returns the return value of the callback, with a `children` property added for any child nodes
247
+ */
248
+
249
+ traverse<T extends LayoutNode | ProcessedComponentMeta>(
250
+ node: T,
251
+ visit: visitor<T> | visitor<T>[]
252
+ ): ProcessedComponentMeta {
253
+ function single_visit<U extends T>(
254
+ node: U,
255
+ visit: visitor<U>,
256
+ traverse_fn: any
257
+ ): ProcessedComponentMeta {
258
+ const result = visit(node);
259
+ if ("children" in node && node.children.length > 0) {
260
+ result.children =
261
+ node.children?.map((child) => traverse_fn(child, visit)) || [];
262
+ }
263
+
264
+ return result;
265
+ }
266
+
267
+ if (Array.isArray(visit)) {
268
+ let result: ProcessedComponentMeta = node as ProcessedComponentMeta;
269
+ for (const v of visit) {
270
+ result = single_visit(result as T, v, this.traverse.bind(this));
271
+ }
272
+
273
+ return result;
274
+ } else {
275
+ return single_visit(node, visit, this.traverse.bind(this));
276
+ }
277
+ }
278
+
279
+ /**
280
+ * Creates a processed component node from a layout node
281
+ * @param opts the layout node options
282
+ * @param root whether this is the root node
283
+ * @returns the processed component node
284
+ */
285
+ create_node(
286
+ opts: LayoutNode,
287
+ component_map: Map<number, ComponentMeta>,
288
+ root = false,
289
+ reactive_formatter?: (str: string) => string
290
+ ): ProcessedComponentMeta {
291
+ let component: ComponentMeta | undefined;
292
+ if (!root) {
293
+ component = component_map.get(opts.id);
294
+ } else {
295
+ component = {
296
+ type: "column",
297
+ id: opts.id,
298
+ // @ts-ignore
299
+ props: {
300
+ visible: true,
301
+ root: "",
302
+ theme_mode: "light"
303
+ },
304
+ component_class_id: "column",
305
+ key: null
306
+ };
307
+ }
308
+
309
+ if (!component) {
310
+ throw new Error(`Component with ID ${opts.id} not found`);
311
+ }
312
+ if (reactive_formatter) {
313
+ component.props.i18n = reactive_formatter;
314
+ }
315
+ const processed_props = gather_props(
316
+ opts.id,
317
+ component.props,
318
+ [this.#input_ids, this.#output_ids],
319
+ this.client,
320
+ { ...this.#config }
321
+ );
322
+
323
+ const type =
324
+ type_map[component.type as keyof typeof type_map] || component.type;
325
+
326
+ const node = {
327
+ id: opts.id,
328
+ type: type,
329
+ props: processed_props,
330
+ children: [],
331
+ show_progress_on: null,
332
+ component_class_id: component.component_class_id || component.type,
333
+ component:
334
+ processed_props.shared_props.visible !== false
335
+ ? get_component(
336
+ component.type,
337
+ component.component_class_id,
338
+ this.#config.root || ""
339
+ )
340
+ : null,
341
+ key: component.key,
342
+ rendered_in: component.rendered_in,
343
+ documentation: component.documentation
344
+ };
345
+
346
+ return node;
347
+ }
348
+
349
+ rerender(components: ComponentMeta[], layout: LayoutNode) {
350
+ const component_map = components.reduce((map, comp) => {
351
+ map.set(comp.id, comp);
352
+ return map;
353
+ }, new Map<number, ComponentMeta>());
354
+ const subtree = this.traverse(layout, (node) => {
355
+ const new_node = this.create_node(
356
+ node,
357
+ component_map,
358
+ false,
359
+ this.reactive_formatter
360
+ );
361
+ return new_node;
362
+ });
363
+
364
+ const n = find_node_by_id(this.root!, subtree.id);
365
+
366
+ if (!n) {
367
+ throw new Error("Rerender failed: root node not found in current tree");
368
+ }
369
+ n.children = subtree.children;
370
+ }
371
+
372
+ /*
373
+ * Updates the state of a component by its ID
374
+ * @param id the ID of the component to update
375
+ * @param new_state the new state to set
376
+ * */
377
+ async update_state(
378
+ id: number,
379
+ new_state: Partial<SharedProps> & Record<string, unknown>,
380
+ check_visibility: boolean = true
381
+ ) {
382
+ // Visibility is tricky 😅
383
+ // If the component is not visible, it has not been rendered
384
+ // and so it has no _set_data callback
385
+ // Therefore, we need to traverse the tree and set the visible prop to true
386
+ // and then render it and its children. After that, we can call the _set_data callback
387
+ const node = find_node_by_id(this.root!, id);
388
+ let already_updated_visibility = false;
389
+ if (check_visibility && !node?.component) {
390
+ await tick();
391
+ this.root = this.traverse(this.root!, [
392
+ //@ts-ignore
393
+ (n) => set_visibility_for_updated_node(n, id, new_state.visible),
394
+ (n) => handle_visibility(n, this.#config.root)
395
+ ]);
396
+ already_updated_visibility = true;
397
+ }
398
+ const _set_data = this.#set_callbacks.get(id);
399
+ if (!_set_data) return;
400
+ _set_data(new_state);
401
+ if (!check_visibility || already_updated_visibility) return;
402
+ // need to let the UI settle before traversing again
403
+ // otherwise there could be
404
+ await tick();
405
+ this.root = this.traverse(this.root!, (n) =>
406
+ handle_visibility(n, this.#config.root)
407
+ );
408
+ }
409
+
410
+ /**
411
+ * Gets the current state of a component by its ID
412
+ * @param id the ID of the component to get the state of
413
+ * @returns the current state of the component, or null if not found
414
+ */
415
+ async get_state(id: number): Promise<Record<string, unknown> | null> {
416
+ const _get_data = this.#get_callbacks.get(id);
417
+ const component = this.#component_payload.find((c) => c.id === id);
418
+ if (!_get_data && !component) return null;
419
+ if (_get_data) return await _get_data();
420
+
421
+ if (component) return Promise.resolve({ value: component.props.value });
422
+
423
+ return null;
424
+ }
425
+ }
426
+
427
+ /**
428
+ * Process the server function names and return a dictionary of functions
429
+ * @param id the component id
430
+ * @param server_fns the server function names
431
+ * @param app the client instance
432
+ * @returns the actual server functions
433
+ */
434
+ export function process_server_fn(
435
+ id: number,
436
+ server_fns: string[] | undefined,
437
+ app: client_return
438
+ ): ServerFunctions {
439
+ if (!server_fns) {
440
+ return {};
441
+ }
442
+ return server_fns.reduce((acc, fn: string) => {
443
+ acc[fn] = async (...args: any[]) => {
444
+ if (args.length === 1) {
445
+ args = args[0];
446
+ }
447
+ const result = await app.component_server(id, fn, args);
448
+ return result;
449
+ };
450
+ return acc;
451
+ }, {} as ServerFunctions);
452
+ }
453
+
454
+ /**
455
+ * Gathers the props for a component
456
+ * @param id the ID of the component
457
+ * @param props the props of the component
458
+ * @param dependencies the component's dependencies
459
+ * @param additional any additional props to include
460
+ * @returns the gathered props as an object with `shared_props` and `props` keys
461
+ */
462
+ function gather_props(
463
+ id: number,
464
+ props: ComponentMeta["props"],
465
+ dependencies: [Set<number>, Set<number>],
466
+ client: client_return,
467
+ additional: Record<string, unknown> = {}
468
+ ): {
469
+ shared_props: SharedProps;
470
+ props: Record<string, unknown>;
471
+ } {
472
+ const _shared_props: Partial<SharedProps> = {};
473
+ const _props: Record<string, unknown> = {};
474
+ for (const key in props) {
475
+ // For Tabs (or any component that already has an id prop)
476
+ // Set the id to the props so that it doesn't get overwritten
477
+ if (key === "id" || key === "autoscroll") {
478
+ _props[key] = props[key];
479
+ } else if (allowed_shared_props.includes(key as keyof SharedProps)) {
480
+ const _key = key as keyof SharedProps;
481
+ _shared_props[_key] = props[key];
482
+ if (_key === "server_fns") {
483
+ _shared_props.server = process_server_fn(id, props.server_fns, client);
484
+ }
485
+ } else {
486
+ _props[key] = props[key];
487
+ }
488
+ }
489
+
490
+ for (const key in additional) {
491
+ if (allowed_shared_props.includes(key as keyof SharedProps)) {
492
+ const _key = key as keyof SharedProps;
493
+ _shared_props[_key] = additional[key];
494
+ } else {
495
+ _props[key] = additional[key];
496
+ }
497
+ }
498
+
499
+ _shared_props.client = client;
500
+ _shared_props.id = id;
501
+ _shared_props.interactive = determine_interactivity(
502
+ id,
503
+ _shared_props.interactive,
504
+ _props.value,
505
+ dependencies
506
+ );
507
+
508
+ _shared_props.load_component = (
509
+ name: string,
510
+ variant: "base" | "component" | "example"
511
+ ) =>
512
+ get_component(
513
+ name,
514
+ "",
515
+ _shared_props.root || "",
516
+ variant
517
+ ) as LoadingComponent;
518
+
519
+ _shared_props.visible =
520
+ _shared_props.visible === undefined ? true : _shared_props.visible;
521
+ _shared_props.loading_status = {};
522
+
523
+ return { shared_props: _shared_props as SharedProps, props: _props };
524
+ }
525
+
526
+ function handle_visibility(
527
+ node: ProcessedComponentMeta,
528
+ root: string
529
+ ): ProcessedComponentMeta {
530
+ // Check if the node is visible
531
+ if (node.props.shared_props.visible && !node.component) {
532
+ const result: ProcessedComponentMeta = {
533
+ ...node,
534
+ component: get_component(node.type, node.component_class_id, root),
535
+ children: []
536
+ };
537
+
538
+ if (node.children) {
539
+ result.children = node.children.map((child) =>
540
+ handle_visibility(child, root)
541
+ );
542
+ }
543
+ return result;
544
+ } else {
545
+ return node;
546
+ }
547
+ }
548
+
549
+ function set_visibility_for_updated_node(
550
+ node: ProcessedComponentMeta,
551
+ id: number,
552
+ visible: boolean
553
+ ): ProcessedComponentMeta {
554
+ if (node.id == id) {
555
+ node.props.shared_props.visible = visible;
556
+ }
557
+ return node;
558
+ }
559
+
560
+ function _untrack(
561
+ node: ProcessedComponentMeta,
562
+ components_to_register: Set<number>
563
+ ): void {
564
+ components_to_register.delete(node.id);
565
+ if (node.children) {
566
+ node.children.forEach((child) => _untrack(child, components_to_register));
567
+ }
568
+ return;
569
+ }
570
+
571
+ function untrack_children_of_invisible_parents(
572
+ node: ProcessedComponentMeta,
573
+ root: string,
574
+ components_to_register: Set<number>
575
+ ): ProcessedComponentMeta {
576
+ // Check if the node is visible
577
+ if (node.props.shared_props.visible !== true) {
578
+ _untrack(node, components_to_register);
579
+ }
580
+ return node;
581
+ }
582
+
583
+ function handle_empty_forms(
584
+ node: ProcessedComponentMeta,
585
+ root: string,
586
+ components_to_register: Set<number>
587
+ ): ProcessedComponentMeta {
588
+ // Check if the node is visible
589
+ if (node.type === "form") {
590
+ const all_children_invisible = node.children.every(
591
+ (child) => child.props.shared_props.visible === false
592
+ );
593
+
594
+ if (all_children_invisible) {
595
+ node.props.shared_props.visible = false;
596
+ components_to_register.delete(node.id);
597
+ return node;
598
+ }
599
+ }
600
+
601
+ return node;
602
+ }
603
+
604
+ function translate_props(
605
+ node: ProcessedComponentMeta,
606
+ root: string
607
+ ): ProcessedComponentMeta {
608
+ const supported_props = [
609
+ "description",
610
+ "info",
611
+ "title",
612
+ "placeholder",
613
+ "value",
614
+ "label"
615
+ ];
616
+ for (const attr of Object.keys(node.props.shared_props)) {
617
+ if (supported_props.includes(attr as string)) {
618
+ // @ts-ignore
619
+ node.props.shared_props[attr] = translate_if_needed(
620
+ node.props.shared_props[attr as keyof SharedProps]
621
+ );
622
+ }
623
+ }
624
+ for (const attr of Object.keys(node.props.props)) {
625
+ if (supported_props.includes(attr as string)) {
626
+ node.props.props[attr] = translate_if_needed(node.props.props[attr]);
627
+ }
628
+ }
629
+ return node;
630
+ }
631
+
632
+ function apply_initial_tabs(
633
+ node: ProcessedComponentMeta,
634
+ root: string,
635
+ initial_tabs: Record<number, Tab[]>
636
+ ): ProcessedComponentMeta {
637
+ if (node.type === "tabs" && node.id in initial_tabs) {
638
+ const tabs = initial_tabs[node.id].sort((a, b) => a.order! - b.order!);
639
+ node.props.props.initial_tabs = tabs;
640
+ }
641
+ return node;
642
+ }
643
+
644
+ function _gather_initial_tabs(
645
+ node: ProcessedComponentMeta,
646
+ initial_tabs: Record<number, Tab[]>,
647
+ parent_tab_id: number | null,
648
+ order: number | null
649
+ ): void {
650
+ if (parent_tab_id !== null && node.type === "tabitem") {
651
+ if (!(parent_tab_id in initial_tabs)) {
652
+ initial_tabs[parent_tab_id] = [];
653
+ }
654
+ if (!("id" in node.props.props)) {
655
+ node.props.props.id = node.id;
656
+ }
657
+ initial_tabs[parent_tab_id].push({
658
+ label: node.props.shared_props.label as string,
659
+ id: node.props.props.id as string,
660
+ elem_id: node.props.shared_props.elem_id,
661
+ visible: node.props.shared_props.visible as boolean,
662
+ interactive: node.props.shared_props.interactive,
663
+ scale: node.props.shared_props.scale || null
664
+ });
665
+ node.props.props.order = order;
666
+ }
667
+ if (node.children) {
668
+ node.children.forEach((child, i) => {
669
+ _gather_initial_tabs(
670
+ child,
671
+ initial_tabs,
672
+ node.type === "tabs" ? node.id : null,
673
+ node.type === "tabs" ? i : null
674
+ );
675
+ });
676
+ }
677
+ return;
678
+ }
679
+
680
+ function gather_initial_tabs(
681
+ node: ProcessedComponentMeta,
682
+ initial_tabs: Record<number, Tab[]>
683
+ ): void {
684
+ function single_visit<U extends ProcessedComponentMeta>(node: U): void {
685
+ if ("children" in node && node.children.length > 0) {
686
+ node.children?.forEach((child) =>
687
+ _gather_initial_tabs(
688
+ child,
689
+ initial_tabs,
690
+ node.type === "tabs" ? node.id : null,
691
+ null
692
+ )
693
+ );
694
+ }
695
+ }
696
+ return single_visit(node);
697
+ }
698
+
699
+ function find_node_by_id(
700
+ tree: ProcessedComponentMeta,
701
+ id: number
702
+ ): ProcessedComponentMeta | null {
703
+ if (tree.id === id) {
704
+ return tree;
705
+ }
706
+
707
+ if (tree.children) {
708
+ for (const child of tree.children) {
709
+ const result = find_node_by_id(child, id);
710
+ if (result) {
711
+ return result;
712
+ }
713
+ }
714
+ }
715
+
716
+ return null;
717
+ }