1import { R as get_inputs_outputs, T as get_component, U as determine_interactivity } from './i18n-CGlVUOvE.js'; 2export { E as Embed, J as changeLocale, V as get_initial_locale, W as is_translation_metadata, I as language_choices, X as load_translations, A as mount_css, z as prefix_css, Y as process_langs, y as setupi18n } from './i18n-CGlVUOvE.js'; 3import { ab as state, Z as get, $ as set, I as tick } from './index-Bq2njFOY.js'; 4import { d as dequal } from './index-DnoGeqVF.js'; 5import { d as allowed_shared_props } from './utils.svelte-Bi9ASwv9.js'; 6export { I as i18n_marker } from './utils.svelte-Bi9ASwv9.js'; 7 8/* init.svelte.ts generated by Svelte v5.48.0 */ 9 10const type_map = { walkthrough: "tabs", walkthroughstep: "tabitem" }; 11 12class AppTree { 13 /** the raw component structure received from the backend */ 14 #component_payload; 15 16 /** the raw layout node structure received from the backend */ 17 #layout_payload; 18 19 /** the raw dependency structure received from the backend */ 20 #dependency_payload; 21 22 /** Need this to set i18n in re-render */ 23 reactive_formatter = (str) => str; 24 25 /** the config for the app */ 26 #config; 27 28 client; 29 30 #root = /** the root node of the processed layout tree */ 31 state(); 32 33 get root() { 34 return get(this.#root); 35 } 36 37 set root(value) { 38 set(this.#root, value, true); 39 } 40 41 root_untracked; 42 #input_ids = new Set(); 43 #output_ids = new Set(); 44 #pending_components = []; 45 #get_callbacks = new Map(); 46 #set_callbacks = new Map(); 47 #pending_updates = new Map(); 48 #event_dispatcher; 49 component_ids; 50 initial_tabs = {}; 51 components_to_register = new Set(); 52 ready; 53 ready_resolve; 54 resolved = false; 55 #hidden_on_startup = new Set(); 56 57 constructor( 58 components, 59 layout, 60 dependencies, 61 config, 62 app, 63 reactive_formatter, 64 event_dispatcher 65 ) { 66 this.ready = new Promise((resolve) => { 67 this.ready_resolve = resolve; 68 }); 69 70 this.reactive_formatter = reactive_formatter; 71 72 this.#config = { 73 ...config, 74 api_url: new URL(config.api_prefix, config.root).toString() 75 }; 76 77 this.#component_payload = components; 78 this.#layout_payload = layout; 79 this.#dependency_payload = dependencies; 80 this.#event_dispatcher = event_dispatcher; 81 this.root = this.create_node({ id: layout.id, children: [] }, /* @__PURE__ */ new Map(), true); 82 83 for (const comp of components) { 84 if (comp.props.visible != false) this.components_to_register.add(comp.id); 85 } 86 87 this.client = app; 88 this.prepare(); 89 90 const component_map = components.reduce( 91 (map, comp) => { 92 map.set(comp.id, comp); 93 94 return map; 95 }, /* @__PURE__ */ 96 new Map() 97 ); 98 99 this.root.children = this.#layout_payload.children.map((node) => this.traverse(node, (node2) => { 100 const new_node = this.create_node(node2, component_map, false, this.reactive_formatter); 101 102 return new_node; 103 })); 104 105 this.component_ids = components.map((c) => c.id); 106 this.initial_tabs = {}; 107 gather_initial_tabs(this.root, this.initial_tabs); 108 this.postprocess(this.root); 109 this.root_untracked = this.root; 110 } 111 112 reload(components, layout, dependencies, config) { 113 this.#layout_payload = layout; 114 this.#component_payload = components; 115 116 this.#config = { 117 ...config, 118 api_url: new URL(config.api_prefix, config.root).toString() 119 }; 120 121 this.#dependency_payload = dependencies; 122 this.root = this.create_node({ id: layout.id, children: [] }, /* @__PURE__ */ new Map(), true); 123 124 for (const comp of components) { 125 if (comp.props.visible != false) this.components_to_register.add(comp.id); 126 } 127 128 this.prepare(); 129 130 const component_map = components.reduce( 131 (map, comp) => { 132 map.set(comp.id, comp); 133 134 return map; 135 }, /* @__PURE__ */ 136 new Map() 137 ); 138 139 this.root.children = this.#layout_payload.children.map((node) => this.traverse(node, (node2) => { 140 const new_node = this.create_node(node2, component_map, false, this.reactive_formatter); 141 142 return new_node; 143 })); 144 145 this.component_ids = components.map((c) => c.id); 146 this.initial_tabs = {}; 147 gather_initial_tabs(this.root, this.initial_tabs); 148 this.postprocess(this.root); 149 } 150 151 /** 152 * Registers a component with its ID and data callbacks 153 * @param id the ID of the component 154 * @param _set_data the set data callback 155 * @param _get_data the get data callback 156 */ 157 register_component(id, _set_data, _get_data) { 158 this.#set_callbacks.set(id, _set_data); 159 this.#get_callbacks.set(id, _get_data); 160 this.components_to_register.delete(id); 161 162 const pending = this.#pending_updates.get(id); 163 164 if (pending) { 165 this.#pending_updates.delete(id); 166 167 tick().then(() => { 168 const _set = this.#set_callbacks.get(id); 169 170 if (_set) _set(pending); 171 }); 172 } 173 174 if (this.components_to_register.size === 0 && !this.resolved) { 175 this.resolved = true; 176 this.ready_resolve(); 177 } 178 } 179
180 /** 181 * Preprocess the payloads to get the correct state read to build the tree 182 */ 183 prepare() { 184 const [inputs, outputs] = get_inputs_outputs(this.#dependency_payload); 185 186 this.#input_ids = inputs; 187 this.#output_ids = outputs; 188 } 189 190 /** Processes the layout payload into a tree of components */ 191 process() {} 192 193 postprocess(tree) { 194 this.root = this.traverse(tree, [ 195 (node) => handle_visibility(node, this.#config.api_url), 196 (node) => untrack_children_of_invisible_parents(node, this.components_to_register), 197 (node) => apply_initial_tabs(node, this.initial_tabs), 198 (node) => this.find_attached_events(node, this.#dependency_payload), 199 (node) => untrack_children_of_closed_accordions_or_inactive_tabs(node, this.components_to_register, this.#hidden_on_startup) 200 ]); 201 } 202 203 find_attached_events(node, dependencies) { 204 const attached_events = dependencies.filter((dep) => dep.targets.find(([id]) => id === node.id)).map((dep) => { 205 const target = dep.targets.find(([id]) => id === node.id); 206 207 return target ? target[1] : null; 208 }).filter(Boolean); 209 210 node.props.shared_props.attached_events = attached_events; 211 212 return node; 213 } 214 215 /** 216 * Traverses the layout tree and applies a callback to each node 217 * @param node the current layout node 218 * @param visit the callback to apply to each node 219 * @returns the return value of the callback, with a `children` property added for any child nodes 220 */ 221 traverse(node, visit) { 222 function single_visit(node2, visit2, traverse_fn) { 223 const result = visit2(node2); 224 225 if ("children" in node2 && node2.children.length > 0) { 226 result.children = node2.children?.map((child) => traverse_fn(child, visit2)) || []; 227 } 228 229 return result; 230 } 231 232 if (Array.isArray(visit)) { 233 let result = node; 234 235 for (const v of visit) { 236 result = single_visit(result, v, this.traverse.bind(this)); 237 } 238 239 return result; 240 } else { 241 return single_visit(node, visit, this.traverse.bind(this)); 242 } 243 } 244 245 /** 246 * Creates a processed component node from a layout node 247 * @param opts the layout node options 248 * @param root whether this is the root node 249 * @returns the processed component node 250 */ 251 create_node(opts, component_map, root = false, reactive_formatter) { 252 let component; 253 254 if (!root) { 255 component = component_map.get(opts.id); 256 } else { 257 component = { 258 type: "column", 259 id: opts.id, 260 // @ts-ignore 261 props: { 262 visible: true, 263 root: "", 264 theme_mode: "light", 265 scale: this.#config.fill_height ? 1 : null 266 }, 267 component_class_id: "column", 268 key: null 269 }; 270 } 271 272 if (!component) { 273 throw new Error(`Component with ID ${opts.id} not found`); 274 } 275 276 if (reactive_formatter) { 277 component.props.i18n = reactive_formatter; 278 } 279 280 const processed_props = gather_props(opts.id, component.props, [this.#input_ids, this.#output_ids], this.client, this.#config.api_url, { 281 ...this.#config, 282 register_component: this.register_component.bind(this), 283 dispatcher: this.#event_dispatcher.bind(this) 284 }); 285 286 const type = type_map[component.type] || component.type; 287 288 const loading_component = processed_props.shared_props.visible !== false 289 ? get_component(component.type, component.component_class_id, this.#config.api_url || "") 290 : null; 291 292 const node = { 293 id: opts.id, 294 type, 295 props: processed_props, 296 children: [], 297 show_progress_on: null, 298 component_class_id: component.component_class_id || component.type, 299 component: processed_props.shared_props.visible !== false ? loading_component?.component || null : null, 300 runtime: loading_component?.runtime || false, 301 key: component.key, 302 rendered_in: component.rendered_in, 303 documentation: component.documentation, 304 original_visibility: processed_props.shared_props.visible 305 }; 306 307 return node; 308 } 309 310 rerender(components, layout) { 311 const component_map = components.reduce( 312 (map, comp) => { 313 map.set(comp.id, comp); 314 315 return map; 316 }, /* @__PURE__ */ 317 new Map() 318 ); 319 320 const _subtree = this.traverse(layout, (node) => { 321 const new_node = this.create_node(node, component_map, false, this.reactive_formatter); 322 323 return new_node; 324 }); 325 326 gather_initial_tabs(_subtree, this.initial_tabs); 327 328 const subtree = this.traverse(_subtree, (node) =>
328 apply_initial_tabs(node, this.initial_tabs)); 329 const n = find_node_by_id(this.root, subtree.id); 330 331 if (!n) { 332 throw new Error("Rerender failed: root node not found in current tree"); 333 } 334 335 n.children = subtree.children; 336 } 337 338 /* 339 * Updates the state of a component by its ID 340 * @param id the ID of the component to update 341 * @param new_state the new state to set 342 * */ 343 async update_state(id, new_state, check_visibility = true) { 344 const node = find_node_by_id(this.root, id); 345 let already_updated_visibility = false; 346 347 if (check_visibility && !node?.component) { 348 await tick(); 349 350 this.root = this.traverse(this.root, [ 351 //@ts-ignore 352 (n) => set_visibility_for_updated_node(n, id, new_state.visible), 353 354 //@ts-ignore 355 (n) => handle_visibility(n, this.#config.api_url) 356 ]); 357 358 await tick(); 359 already_updated_visibility = true; 360 } 361 362 const _set_data = this.#set_callbacks.get(id); 363 364 if (!_set_data) { 365 const old_value = node?.props.props.value; 366 const new_props = create_props_shared_props(new_state); 367 368 for (const key in new_props.shared_props) { 369 node.props.shared_props[key] = new_props.shared_props[key]; 370 } 371 372 for (const key in new_props.props) { 373 node.props.props[key] = new_props.props[key]; 374 } 375 376 const existing = this.#pending_updates.get(id) || {}; 377 378 this.#pending_updates.set(id, { ...existing, ...new_state }); 379 380 if ("value" in new_state && !dequal(old_value, new_state.value)) { 381 this.#event_dispatcher(id, "change", null); 382 } 383 } else if (_set_data) { 384 _set_data(new_state); 385 } 386 387 if (!check_visibility || already_updated_visibility) return; 388 389 await tick(); 390 await this.update_visibility(node, new_state); 391 } 392 393 async update_visibility(node, new_state) { 394 node.children.forEach((child) => { 395 const _set_data = this.#set_callbacks.get(child.id); 396 397 if (_set_data) { 398 _set_data(new_state); 399 } 400 401 this.update_visibility(child, new_state); 402 }); 403 } 404 405 /** 406 * Gets the current state of a component by its ID 407 * @param id the ID of the component to get the state of 408 * @returns the current state of the component, or null if not found 409 */ 410 async get_state(id) { 411 const _get_data = this.#get_callbacks.get(id); 412 const component = find_node_by_id(this.root, id); 413 414 if (!_get_data && !component) return null; 415 if (_get_data) return await _get_data(); 416 if (component) return Promise.resolve({ value: component.props.props.value }); 417 418 return null; 419 } 420 421 async render_previously_invisible_children(id) { 422 const node = find_node_by_id(this.root, id); 423 424 if (!node) return; 425 426 if (!this.#hidden_on_startup.has(node.id) && !has_hidden_descendants(node, this.#hidden_on_startup)) { 427 return; 428 } 429 430 make_visible_if_not_rendered(node, this.#hidden_on_startup, true); 431 load_components(node, this.#config.api_url); 432 } 433} 434 435function make_visible_if_not_rendered(node, hidden_on_startup, is_target_node = false) { 436 node.props.shared_props.visible = hidden_on_startup.has(node.id) ? true : node.props.shared_props.visible; 437 438 if (node.type === "tabs") { 439 const selectedId = node.props.props.selected ?? node.props.props.initial_tabs?.[0]?.id; 440 441 node.children.forEach((child) => { 442 if (child.type === "tabitem" && (child.props.props.id === selectedId || child.id === selectedId)) { 443 make_visible_if_not_rendered(child, hidden_on_startup, false); 444 } 445 }); 446 } else if (node.type === "accordion" && node.props.props.open === false && !is_target_node) ; else { 447 node.children.forEach((child) => { 448 make_visible_if_not_rendered(child, hidden_on_startup, false); 449 }); 450 } 451} 452 453function has_hidden_descendants(node, hidden_on_startup) { 454 for (const child of node.children) { 455 if (hidden_on_startup.has(child.id)) return true; 456 if (has_hidden_descendants(child, hidden_on_startup)) return true; 457 } 458 459 return false; 460} 461 462function load_components(node, api_url) { 463 if (node.props.shared_props.visible && !node.component) { 464 node.component = get_component(node.type, node.component_class_id, api_url); 465 } 466 467 node.children.forEach((child) => load_components(child, api_url)); 468} 469 470function process_server_fn(id, server_fns, app) { 471 if (!server_fns) { 472 return {}; 473 } 474 475 return server_fns.reduce( 476 (acc, fn) => { 477 acc[fn] = async (...args) => { 478 if (args.length === 1) { 479 args = args[0]; 480 } 481 482 const result = await app.component_server(id, fn, args); 483 484 return result; 485 }; 486 487 return acc; 488 }, 489 {} 490 ); 491} 492 493function create_props_shared_props(props) { 494 const _shared_props = {}; 495 const _props = {}; 496 497 for (const key in props) { 498 if (key === "id" || key === "autoscroll") { 499 _props[key] = props[key]; 500 } else if (allowed_shared_props.includes(key)) { 501 const _key = key; 502 503 _shared_props[_key] = props[key]; 504 } else { 505 _props[key] = props[key]; 506 } 507 } 508 509 return { shared_props: _shared_props, props: _props }; 510} 511 512function gather_props(id, props, dependencies, client, api_url, additional = {}) { 513 const { shared_props: _shared_props, props: _props } = create_props_shared_props(props); 514 515 _shared_props.server = process_server_fn(id, props.server_fns, client); 516 517 for (const key in additional) { 518 if (allowed_shared_props.includes(key)) { 519 const _key = key; 520 521 _shared_props[_key] = additional[key]; 522 } else { 523 _props[key] = additional[key]; 524 } 525 } 526 527 _shared_props.client = client; 528 _shared_props.id = id; 529 _shared_props.interactive = determine_interactivity(id, _shared_props.interactive, _props.value, dependencies); 530 _shared_props.load_component = (name, variant) => get_component(name, "", api_url, variant).component; 531 _shared_props.visible = _shared_props.visible === void 0 ? true : _shared_props.visible; 532 _shared_props.loading_status = {}; 533 534 return { shared_props: _shared_props, props: _props }; 535} 536 537function handle_visibility(node, api_url) { 538 if (node.props.shared_props.visible && !node.component) { 539 const loading_component = get_component(node.type, node.component_class_id, api_url); 540 541 const result = { 542 ...node, 543 component: loading_component.component, 544 children: [] 545 }; 546 547 if (node.children) { 548 result.children = node.children.map((child) => handle_visibility(child, api_url)); 549 } 550 551 return result; 552 } else { 553 return node; 554 } 555} 556 557function set_visibility_for_updated_node(node, id, visible) { 558 if (node.id == id) { 559 node.props.shared_props.visible = visible; 560 } 561 562 return node; 563} 564 565function _untrack(node, components_to_register) { 566 components_to_register.delete(node.id); 567 568 if (node.children) {
569 node.children.forEach((child) => _untrack(child, components_to_register)); 570 } 571 572 return; 573} 574 575function untrack_children_of_invisible_parents(node, components_to_register) { 576 if (node.props.shared_props.visible !== true) { 577 _untrack(node, components_to_register); 578 } 579 580 return node; 581} 582 583function mark_component_invisible_if_visible(node, hidden_on_startup) { 584 if (node.props.shared_props.visible === true) { 585 hidden_on_startup.add(node.id); 586 node.props.shared_props.visible = false; 587 } 588 589 node.children.forEach((child) => { 590 mark_component_invisible_if_visible(child, hidden_on_startup); 591 }); 592 593 return node; 594} 595 596function untrack_children_of_closed_accordions_or_inactive_tabs(node, components_to_register, hidden_on_startup) { 597 if (node.type === "accordion" && node.props.props.open === false) { 598 _untrack(node, components_to_register); 599 600 if (node.children) { 601 node.children.forEach((child) => { 602 mark_component_invisible_if_visible(child, hidden_on_startup); 603 }); 604 } 605 } 606 607 if (node.type === "tabs") { 608 node.children.forEach((child) => { 609 if (child.type === "tabitem" && child.props.props.id !== (//@ts-ignore 610 node.props.props.selected || node.props.props.initial_tabs[0].id)) { 611 _untrack(child, components_to_register); 612 mark_component_invisible_if_visible(child, hidden_on_startup); 613 } 614 }); 615 } 616 617 return node; 618} 619 620function apply_initial_tabs(node, initial_tabs) { 621 if (node.type === "tabs" && node.id in initial_tabs) { 622 const tabs = initial_tabs[node.id].sort((a, b) => a.order - b.order); 623 624 node.props.props.initial_tabs = tabs; 625 } else if (node.type === "tabitem") { 626 node.props.props.component_id = node.id; 627 } 628 629 return node; 630} 631 632function _gather_initial_tabs(node, initial_tabs, parent_tab_id, order) { 633 if (parent_tab_id !== null && node.type === "tabitem") { 634 if (!(parent_tab_id in initial_tabs)) { 635 initial_tabs[parent_tab_id] = []; 636 } 637 638 if (!("id" in node.props.props)) { 639 node.props.props.id = node.id; 640 } 641 642 const i18n = node.props.props.i18n; 643 const raw_label = node.props.shared_props.label; 644 645 initial_tabs[parent_tab_id].push({ 646 label: i18n ? i18n(raw_label) : raw_label, 647 id: node.props.props.id, 648 elem_id: node.props.shared_props.elem_id, 649 visible: node.props.shared_props.visible, 650 interactive: node.props.shared_props.interactive, 651 scale: node.props.shared_props.scale || null, 652 component_id: node.id 653 }); 654 655 node.props.props.order = order; 656 } 657 658 if (node.children) { 659 node.children.forEach((child, i) => { 660 _gather_initial_tabs(child, initial_tabs, node.type === "tabs" ? node.id : null, node.type === "tabs" ? i : null); 661 }); 662 } 663 664 return; 665} 666 667function gather_initial_tabs(node, initial_tabs) { 668 function single_visit(node2) { 669 if ("children" in node2 && node2.children.length > 0) { 670 node2.children?.forEach((child) => _gather_initial_tabs(child, initial_tabs, node2.type === "tabs" ? node2.id : null, null)); 671 } 672 } 673 674 return single_visit(node); 675} 676 677function find_node_by_id(tree, id) { 678 if (tree.id === id) { 679 return tree; 680 } 681 682 if (tree.children) { 683 for (const child of tree.children) { 684 const result = find_node_by_id(child, id); 685 686 if (result) { 687 return result; 688 } 689 } 690 } 691 692 return null; 693} 694 695export { AppTree }; 696//# sourceMappingURL=index-CjLnGHRW.js.map
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.