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