bc-deeplib 1.1.2 → 1.2.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/dist/deeplib.js CHANGED
@@ -361,6 +361,12 @@ var BaseSubscreen = class _BaseSubscreen {
361
361
  get currentPage() {
362
362
  return this.pageStructure[Math.min(_BaseSubscreen.currentPage - 1, this.pageStructure.length - 1)];
363
363
  }
364
+ getPageLabel() {
365
+ return CommonStringPartitionReplace(getText("settings.page.label"), {
366
+ $currentPage$: `${_BaseSubscreen.currentPage}`,
367
+ $totalPages$: `${this.pageStructure.length}`
368
+ }).join("");
369
+ }
364
370
  /**
365
371
  * Changes the visible page in a multi-page subscreen.
366
372
  * Automatically wraps around when going past the first or last page.
@@ -371,7 +377,7 @@ var BaseSubscreen = class _BaseSubscreen {
371
377
  if (page < 1) page = totalPages;
372
378
  _BaseSubscreen.currentPage = page;
373
379
  this.managePageElementsVisibility();
374
- setLabel(`${_BaseSubscreen.currentPage} of ${this.pageStructure.length}`);
380
+ setLabel(this.getPageLabel());
375
381
  }
376
382
  /**
377
383
  * Updates the DOM to show only elements belonging to the current page.
@@ -419,7 +425,7 @@ var BaseSubscreen = class _BaseSubscreen {
419
425
  initialNextTooltip: getText("settings.button.next_button_hint"),
420
426
  back: /* @__PURE__ */ __name(({ setLabel }) => this.changePage(_BaseSubscreen.currentPage - 1, setLabel), "back"),
421
427
  initialPrevTooltip: getText("settings.button.prev_button_hint"),
422
- initialLabel: `${_BaseSubscreen.currentPage} of ${this.pageStructure.length}`
428
+ initialLabel: this.getPageLabel()
423
429
  });
424
430
  ElementMenu.PrependItem(menu, backNext);
425
431
  }
@@ -432,11 +438,13 @@ var BaseSubscreen = class _BaseSubscreen {
432
438
  const exitButton = advElement.createButton({
433
439
  id: "deeplib-exit",
434
440
  size: [90, 90],
435
- image: `${PUBLIC_URL}/dl_images/exit.svg`,
436
441
  onClick: /* @__PURE__ */ __name(() => {
437
442
  this.exit();
438
443
  }, "onClick"),
439
- tooltip: getText("settings.button.back_button_hint")
444
+ options: {
445
+ image: `${PUBLIC_URL}/dl_images/exit.svg`,
446
+ tooltip: getText("settings.button.back_button_hint")
447
+ }
440
448
  });
441
449
  ElementMenu.AppendButton(menu, exitButton);
442
450
  }
@@ -519,9 +527,10 @@ var BaseSubscreen = class _BaseSubscreen {
519
527
  ElementSetPosition(advElement.getTooltip() || "", 250, 850);
520
528
  ElementSetSize(advElement.getTooltip() || "", 1500, 70);
521
529
  _BaseSubscreen.currentElements.forEach((item) => {
530
+ const element = item[0];
522
531
  const options = item[1];
523
- domUtil.autoSetPosition(options.id, options.position);
524
- domUtil.autoSetSize(options.id, options.size);
532
+ domUtil.autoSetPosition(options.id ?? element.id, options.position);
533
+ domUtil.autoSetSize(options.id ?? element.id, options.size);
525
534
  });
526
535
  if (settingsDiv) {
527
536
  if (domUtil.hasOverflow(settingsDiv)?.vertical) {
@@ -548,6 +557,7 @@ var styles_default = `.deeplib-subscreen,
548
557
  --deeplib-background-color: var(--tmd-main, white);
549
558
  --deeplib-element-color: var(--tmd-element, white);
550
559
  --deeplib-element-hover-color: var(--tmd-element-hover, cyan);
560
+ --deeplib-accent-color: var(--tmd-accent, #FFFF88);
551
561
  --deeplib-blocked-color: var(--tmd-blocked, red);
552
562
  --deeplib-text-color: var(--tmd-text, black);
553
563
  --deeplib-icon-color: var(--tmd-accent, black);
@@ -690,6 +700,25 @@ var styles_default = `.deeplib-subscreen,
690
700
  gap: min(2dvh, 1dvw);
691
701
  }
692
702
 
703
+ #deeplib-storage-meter {
704
+ position: absolute;
705
+ top: 0px;
706
+ left: 0px;
707
+ width: 100%;
708
+ height: 100%;
709
+ overflow: hidden;
710
+ background-color: var(--deeplib-element-color);
711
+ border: var(--deeplib-border-width) solid var(--deeplib-border-color);
712
+ border-radius: var(--deeplib-border-radius);
713
+ z-index: -1;
714
+ }
715
+
716
+ #deeplib-storage-bar {
717
+ height: 100%;
718
+ width: 0%;
719
+ background: var(--deeplib-accent-color);
720
+ }
721
+
693
722
  .deeplib-checkbox-container {
694
723
  display: flex;
695
724
  flex-direction: row;
@@ -829,6 +858,12 @@ input[type=number] {
829
858
  .deeplib-modal .deeplib-modal-button-container .deeplib-button .button-label {
830
859
  display: contents;
831
860
  }
861
+ .deeplib-modal .deeplib-modal-prompt-container {
862
+ display: flex;
863
+ flex-direction: column;
864
+ justify-content: center;
865
+ align-items: center;
866
+ }
832
867
 
833
868
  .deeplib-modal-blocker {
834
869
  z-index: 1000;
@@ -839,12 +874,13 @@ input[type=number] {
839
874
  height: 100dvh;
840
875
  background-color: rgba(0, 0, 0, 0.5);
841
876
  }
842
- /*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VSb290IjoiL21lZGlhL05WTUUvU3R1ZmYvQ29kZS9CQy9CQy1EZWVwTGliL3NyYy9zdHlsZXMiLCJzb3VyY2VzIjpbInZhcnMuc2NzcyIsImJ1dHRvbnMuc2NzcyIsImVsZW1lbnRzLnNjc3MiLCJpbnB1dHMuc2NzcyIsIm1lc3NhZ2VzLnNjc3MiLCJtb2RhbC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FBQUE7RUFFRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7OztBQ2JGO0VBQ0U7RUFDQTtFQUNBOzs7QUFHRjtBQUFBO0VBRUU7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUVBO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7OztBQzNDRjtFQUNFO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBOzs7QUFHRjtFQUNFOzs7QUFHRjtFQUNFO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBOzs7QUFHRjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOzs7QUFHRjtFQUNFOzs7QUFHRjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7QUFFQTtFQU1FO0VBQ0E7O0FBTkE7RUFDRTtFQUNBOztBQU9KO0VBQ0U7OztBQUlKO0VBQ0U7RUFDQTtFQUNBOzs7QUN0RkY7RUFDRTtFQUNBO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOzs7QUFJRjtFQUNFO0VBQ0E7RUFDQTtFQUNBOzs7QUFHRjtFQUNFO0VBQ0E7OztBQUdGO0FBQUE7RUFFRTtFQUNBOzs7QUFHRjtFQUNFO0VBQ0E7OztBQzdERjtFQUNFO0VBQ0E7OztBQUdGO0FBQUE7RUFFRTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOzs7QUFHRjtBQUFBO0VBRUU7OztBQUdGO0VBQ0U7RUFDQTtFQUNBOzs7QUM3QkY7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOztBQUVBO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7O0FBR0Y7RUFDRTs7QUFHRjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTtFQUNBO0VBQ0E7RUFDQTs7QUFFQTtFQUNFOzs7QUFNUjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBIiwic291cmNlc0NvbnRlbnQiOlsiLmRlZXBsaWItc3Vic2NyZWVuLFxuLmRlZXBsaWItbW9kYWwge1xuICAtLWRlZXBsaWItYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tdG1kLW1haW4sIHdoaXRlKTtcbiAgLS1kZWVwbGliLWVsZW1lbnQtY29sb3I6IHZhcigtLXRtZC1lbGVtZW50LCB3aGl0ZSk7XG4gIC0tZGVlcGxpYi1lbGVtZW50LWhvdmVyLWNvbG9yOiB2YXIoLS10bWQtZWxlbWVudC1ob3ZlciwgY3lhbik7XG4gIC0tZGVlcGxpYi1ibG9ja2VkLWNvbG9yOiB2YXIoLS10bWQtYmxvY2tlZCwgcmVkKTtcbiAgLS1kZWVwbGliLXRleHQtY29sb3I6IHZhcigtLXRtZC10ZXh0LCBibGFjayk7XG4gIC0tZGVlcGxpYi1pY29uLWNvbG9yOiB2YXIoLS10bWQtYWNjZW50LCBibGFjayk7XG4gIC0tZGVlcGxpYi1pY29uLWhvdmVyLWNvbG9yOiB2YXIoLS10bWQtYWNjZW50LWhvdmVyLCBibGFjayk7XG4gIC0tZGVlcGxpYi1ib3JkZXItY29sb3I6IHZhcigtLXRtZC1hY2NlbnQsIGJsYWNrKTtcbiAgLS1kZWVwbGliLWJvcmRlci13aWR0aDogbWluKDAuMnZoLCAwLjF2dyk7XG4gIC0tZGVlcGxpYi1ib3JkZXItd2lkdGg6IG1pbigwLjJkdmgsIDAuMWR2dyk7XG4gIC0tZGVlcGxpYi1ib3JkZXItcmFkaXVzOiBtaW4oMXZoLCAwLjV2dyk7XG4gIC0tZGVlcGxpYi1ib3JkZXItcmFkaXVzOiBtaW4oMWR2aCwgMC41ZHZ3KTtcbn1cbiIsIi5kZWVwbGliLWJ1dHRvbiB7XG4gIGNvbG9yOiB2YXIoLS1kZWVwbGliLXRleHQtY29sb3IpO1xuICB3aWR0aDogMTAwJTtcbiAgaGVpZ2h0OiAxMDAlO1xufVxuXG4uZGVlcGxpYi1idXR0b24uYnV0dG9uLXN0eWxpbmcsXG4uZGVlcGxpYi1idXR0b24uYnV0dG9uLXN0eWxpbmc6OmJlZm9yZSB7XG4gIGJvcmRlci1yYWRpdXM6IG1pbigxLjBkdmgsIDAuNWR2dyk7XG59XG5cbi5kZWVwbGliLWJ1dHRvbiBpbWcge1xuICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gIHRvcDogMCU7XG4gIGxlZnQ6IDAlO1xuICB3aWR0aDogMTAwJTtcbiAgaGVpZ2h0OiAxMDAlO1xuICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiBsZWZ0O1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1kZWVwbGliLWljb24tY29sb3IpO1xuICBiYWNrZ3JvdW5kLWJsZW5kLW1vZGU6IG11bHRpcGx5O1xuICBiYWNrZ3JvdW5kLXNpemU6IGNvbnRhaW47XG4gIG1hc2stcG9zaXRpb246IGxlZnQ7XG4gIG1hc2stc2l6ZTogY29udGFpbjtcbiAgYmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDtcbiAgbWFzay1yZXBlYXQ6IG5vLXJlcGVhdDtcbiAgY29sb3I6IHRyYW5zcGFyZW50O1xuXG4gIGJhY2tncm91bmQtaW1hZ2U6IHZhcigtLWltYWdlKTtcbiAgbWFzay1pbWFnZTogdmFyKC0taW1hZ2UpO1xuICBwb2ludGVyLWV2ZW50czogbm9uZTtcbn1cblxuLmRlZXBsaWItYnV0dG9uOmhvdmVyIGltZyB7XG4gIGJhY2tncm91bmQtY29sb3I6IHZhcigtLWRlZXBsaWItaWNvbi1ob3Zlci1jb2xvcik7XG59XG5cbi5kZWVwbGliLWJ1dHRvbiAuYnV0dG9uLWxhYmVsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQgIWltcG9ydGFudDtcbiAgY29sb3I6IHZhcigtLWRlZXBsaWItdGV4dC1jb2xvcik7XG4gIGZvbnQtc2l6ZTogbWluKDMuNmR2aCwgMS44ZHZ3KTtcbn1cblxuLmRlZXBsaWItYnV0dG9uIC5idXR0b24tdG9vbHRpcCB7XG4gIGJvcmRlci1yYWRpdXM6IG1pbigxLjBkdmgsIDAuNWR2dyk7XG59XG4iLCIjZGVlcGxpYi1wYWdlLWxhYmVsIHtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG59XG5cbiNkZWVwbGliLXN1YnNjcmVlbi10aXRsZSB7XG4gIHRleHQtYWxpZ246IGxlZnQ7XG4gIGNvbG9yOiB2YXIoLS1kZWVwbGliLXRleHQtY29sb3IpO1xufVxuXG4uZGVlcGxpYi10ZXh0IHtcbiAgY29sb3I6IHZhcigtLWRlZXBsaWItdGV4dC1jb2xvcik7XG59XG5cbi5kZWVwbGliLXN1YnNjcmVlbiB7XG4gIHBhZGRpbmc6IDA7XG4gIG1hcmdpbjogMDtcbiAgcG9pbnRlci1ldmVudHM6IG5vbmU7XG59XG5cbi5kZWVwbGliLXN1YnNjcmVlbiAqIHtcbiAgYm94LXNpemluZzogYm9yZGVyLWJveDtcbiAgcG9pbnRlci1ldmVudHM6IGFsbDtcbn1cblxuLmRlZXBsaWItc2V0dGluZ3Mge1xuICBkaXNwbGF5OiBncmlkO1xuICBncmlkLWF1dG8tcm93czogbWluLWNvbnRlbnQ7XG4gIHBhZGRpbmc6IG1pbigxLjBkdmgsIDAuNWR2dyk7XG4gIGdhcDogMC4zZW07XG4gIG92ZXJmbG93LXk6IHNjcm9sbDtcbn1cblxuLmRlZXBsaWItbWlzYyB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW4tcmV2ZXJzZTtcbiAgZ2FwOiBtaW4oMXZoLCAwLjV2dyk7XG59XG5cbi5kZWVwbGliLXRvb2x0aXAge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1kZWVwbGliLWVsZW1lbnQtY29sb3IpO1xuICBjb2xvcjogdmFyKC0tZGVlcGxpYi10ZXh0LWNvbG9yKTtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG4gIGJvcmRlci1yYWRpdXM6IG1pbigxLjBkdmgsIDAuNWR2dyk7XG4gIHBhZGRpbmc6IG1pbigxdmgsIDAuNXZ3KTtcbiAgZm9udC1zaXplOiAwLjhlbTtcbiAgYm9yZGVyOiBtaW4oMC4ydmgsIDAuMXZ3KSBzb2xpZCB2YXIoLS1kZWVwbGliLWJvcmRlci1jb2xvcik7XG59XG5cbi5kZWVwbGliLW92ZXJmbG93LWJveCB7XG4gIGJvcmRlcjogdmFyKC0tZGVlcGxpYi1ib3JkZXItY29sb3IpIHNvbGlkIHZhcigtLWRlZXBsaWItYm9yZGVyLXdpZHRoKTtcbn1cblxuLmRlZXBsaWItcHJldi1uZXh0IHtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xuICBmbGV4LWRpcmVjdGlvbjogcm93O1xuICBnYXA6IG1pbigyZHZoLCAxZHZ3KTtcbiAgYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tZGVlcGxpYi1lbGVtZW50LWNvbG9yKTtcbiAgY29sb3I6IHZhcigtLWRlZXBsaWItdGV4dC1jb2xvcik7XG4gIGJvcmRlci1yYWRpdXM6IG1pbigxLjBkdmgsIDAuNWR2dyk7XG4gIGJvcmRlcjogbWluKDAuMnZoLCAwLjF2dykgc29saWQgdmFyKC0tZGVlcGxpYi1ib3JkZXItY29sb3IpO1xuXG4gIC5kZWVwbGliLXByZXYtbmV4dC1idXR0b24ge1xuICAgICY6aG92ZXIge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tZGVlcGxpYi1lbGVtZW50LWhvdmVyLWNvbG9yKTtcbiAgICAgIGJvcmRlci1yYWRpdXM6IHZhcigtLWRlZXBsaWItYm9yZGVyLXJhZGl1cyk7XG4gICAgfVxuICAgIFxuICAgIGhlaWdodDogMTAwJTtcbiAgICBhc3BlY3QtcmF0aW86IDE7XG4gIH1cblxuICAuZGVlcGxpYi1wcmV2LW5leHQtbGFiZWwge1xuICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7XG4gIH1cbn1cblxuI2RlZXBsaWItbmF2LW1lbnUge1xuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LWRpcmVjdGlvbjogcm93O1xuICBnYXA6IG1pbigyZHZoLCAxZHZ3KTtcbn0iLCIuZGVlcGxpYi1jaGVja2JveC1jb250YWluZXIge1xuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LWRpcmVjdGlvbjogcm93O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBnYXA6IDAuM2VtO1xufVxuXG4uZGVlcGxpYi1jaGVja2JveC1jb250YWluZXIgaW5wdXQuZGVlcGxpYi1pbnB1dCB7XG4gIHdpZHRoOiBtaW4oNXZoLCAyLjV2dyk7XG4gIGhlaWdodDogbWluKDV2aCwgMi41dncpO1xuICBib3JkZXItcmFkaXVzOiBtaW4oMS4wZHZoLCAwLjVkdncpO1xufVxuXG4uZGVlcGxpYi1jaGVja2JveC1jb250YWluZXIgaW5wdXQuZGVlcGxpYi1pbnB1dFt0eXBlPVwiY2hlY2tib3hcIl06Y2hlY2tlZDo6YmVmb3JlIHtcbiAgd2lkdGg6IDgwJTtcbiAgaGVpZ2h0OiA4MCU7XG59XG5cbi5kZWVwbGliLWlucHV0LWNvbnRhaW5lciB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiByb3c7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGdhcDogMC4zZW07XG59XG5cbi5kZWVwbGliLWlucHV0LWNvbnRhaW5lcjpoYXMobGFiZWwuZGVlcGxpYi10ZXh0KSB7XG4gIG1hcmdpbi10b3A6IG1pbigxdmgsIDAuNXZ3KTtcbn1cblxuLmRlZXBsaWItaW5wdXQtY29udGFpbmVyIGlucHV0LmRlZXBsaWItaW5wdXQge1xuICBmb250LXNpemU6IDAuNmVtO1xuICBwYWRkaW5nOiA1cHggMDtcbiAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7XG4gIG91dGxpbmU6IG5vbmU7XG4gIHBhZGRpbmctbGVmdDogbWluKDF2aCwgMC41dncpO1xuICBwYWRkaW5nLXJpZ2h0OiBtaW4oMXZoLCAwLjV2dyk7XG4gIG1pbi1oZWlnaHQ6IG1pbig1ZHZoLCAyLjVkdncpO1xuICBib3JkZXItcmFkaXVzOiBtaW4oMS4wZHZoLCAwLjVkdncpO1xufVxuXG5cbi5kZWVwbGliLWlucHV0LWNvbnRhaW5lciBpbnB1dC5kZWVwbGliLWlucHV0W3R5cGU9XCJjb2xvclwiXSB7XG4gIHBhZGRpbmc6IDBweDtcbiAgd2lkdGg6IG1pbig1dmgsIDIuNXZ3KTtcbiAgaGVpZ2h0OiBtaW4oNXZoLCAyLjV2dyk7XG4gIGJvcmRlci1yYWRpdXM6IDBweDtcbn1cblxuLmRlZXBsaWItaW5wdXQtY29udGFpbmVyIGlucHV0LmRlZXBsaWItaW5wdXRbdHlwZT1cImNvbG9yXCJdOmRpc2FibGVkIHtcbiAgYm9yZGVyOiB2YXIoLS1kZWVwbGliLWJsb2NrZWQtY29sb3IpIHNvbGlkIHZhcigtLWRlZXBsaWItYm9yZGVyLXdpZHRoKTtcbiAgY3Vyc29yOiBub3QtYWxsb3dlZDtcbn1cblxuaW5wdXQ6Oi13ZWJraXQtb3V0ZXItc3Bpbi1idXR0b24sXG5pbnB1dDo6LXdlYmtpdC1pbm5lci1zcGluLWJ1dHRvbiB7XG4gIC13ZWJraXQtYXBwZWFyYW5jZTogbm9uZTtcbiAgbWFyZ2luOiAwO1xufVxuXG5pbnB1dFt0eXBlPW51bWJlcl0ge1xuICBhcHBlYXJhbmNlOiB0ZXh0ZmllbGQ7XG4gIC1tb3otYXBwZWFyYW5jZTogdGV4dGZpZWxkO1xufVxuIiwiLmRlZXBsaWItaGlnaGxpZ2h0LXRleHQge1xuICBmb250LXdlaWdodDogYm9sZDtcbiAgY29sb3I6IHJnYigyMDMsIDE4NSwgMjMpO1xufVxuXG4jVGV4dEFyZWFDaGF0TG9nW2RhdGEtY29sb3J0aGVtZT0nZGFyayddIGRpdi5DaGF0TWVzc2FnZS5kZWVwbGliLW1lc3NhZ2UsXG4jVGV4dEFyZWFDaGF0TG9nW2RhdGEtY29sb3J0aGVtZT0nZGFyazInXSBkaXYuQ2hhdE1lc3NhZ2UuZGVlcGxpYi1tZXNzYWdlIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tZGVlcGxpYi1lbGVtZW50LWNvbG9yKTtcbiAgYm9yZGVyOiBtaW4oMC4yZHZoLCAwLjFkdncpIHNvbGlkIHZhcigtLWRlZXBsaWItYm9yZGVyLWNvbG9yKTtcbiAgY29sb3I6IHZhcigtLWRlZXBsaWItdGV4dC1jb2xvcik7XG59XG5cbiNUZXh0QXJlYUNoYXRMb2cgZGl2LkNoYXRNZXNzYWdlLmRlZXBsaWItbWVzc2FnZSB7XG4gIGJhY2tncm91bmQtY29sb3I6ICNlZWU7XG4gIGJvcmRlcjogbWluKDAuMmR2aCwgMC4xZHZ3KSBzb2xpZCAjNDQwMTcxO1xuICBjb2xvcjogIzExMTtcbiAgcGFkZGluZy1sZWZ0OiBtaW4oMC42ZHZoLCAwLjNkdncpO1xuICBkaXNwbGF5OiBibG9jaztcbiAgd2hpdGUtc3BhY2U6IG5vcm1hbDtcbn1cblxuI1RleHRBcmVhQ2hhdExvZ1tkYXRhLWNvbG9ydGhlbWU9J2RhcmsnXSBkaXYuQ2hhdE1lc3NhZ2UuZGVlcGxpYi1tZXNzYWdlIGEsXG4jVGV4dEFyZWFDaGF0TG9nW2RhdGEtY29sb3J0aGVtZT0nZGFyazInXSBkaXYuQ2hhdE1lc3NhZ2UuZGVlcGxpYi1tZXNzYWdlIGEge1xuICBjb2xvcjogdmFyKC0tZGVlcGxpYi10ZXh0LWNvbG9yKTtcbn1cblxuI1RleHRBcmVhQ2hhdExvZyBkaXYuQ2hhdE1lc3NhZ2UuZGVlcGxpYi1tZXNzYWdlIGEge1xuICBjdXJzb3I6IHBvaW50ZXI7XG4gIGZvbnQtd2VpZ2h0OiBib2xkO1xuICBjb2xvcjogIzExMTtcbn1cbiIsIi5kZWVwbGliLW1vZGFsIHtcbiAgcG9zaXRpb246IGZpeGVkO1xuICB0b3A6IDEwJTtcbiAgbGVmdDogNTAlO1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoLTUwJSk7XG4gIHotaW5kZXg6IDEwMDE7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBnYXA6IDAuNWVtO1xuICB3aWR0aDogbWF4KDUwZHZ3LCAyNWR2aCk7XG4gIGZvbnQtc2l6ZTogbWluKDRkdmgsIDJkdncpO1xuICBwYWRkaW5nOiBtaW4oMmR2aCwgMWR2dyk7XG4gIGJhY2tncm91bmQtY29sb3I6IHZhcigtLWRlZXBsaWItZWxlbWVudC1jb2xvcik7XG4gIGJvcmRlci1yYWRpdXM6IG1pbigxLjJkdmgsIDAuNmR2dyk7XG4gIGJvcmRlcjogbWluKDAuMmR2aCwgMC4xZHZ3KSBzb2xpZCB2YXIoLS1kZWVwbGliLWJvcmRlci1jb2xvcik7XG4gIGNvbG9yOiB2YXIoLS1kZWVwbGliLXRleHQtY29sb3IpO1xuXG4gIC5kZWVwbGliLW1vZGFsLWlucHV0IHtcbiAgICB3aWR0aDogMTAwJTtcbiAgICBmb250LXNpemU6IG1pbigyLjZkdmgsIDEuOGR2dyk7XG4gICAgYm9yZGVyLXJhZGl1czogbWluKDEuMGR2aCwgMC41ZHZ3KTtcbiAgICBwYWRkaW5nOiBtaW4oMWR2aCwgMC41ZHZ3KTtcbiAgfVxuXG4gIGlucHV0LmRlZXBsaWItbW9kYWwtaW5wdXQge1xuICAgIG1heC13aWR0aDogbWF4KDUwZHZoLCAyNWR2dyk7XG4gIH1cblxuICAuZGVlcGxpYi1tb2RhbC1idXR0b24tY29udGFpbmVyIHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGZsZXgtZGlyZWN0aW9uOiByb3c7XG4gICAganVzdGlmeS1jb250ZW50OiBmbGV4LWVuZDtcbiAgICBnYXA6IDAuNWVtO1xuICAgIHdpZHRoOiAxMDAlO1xuXG4gICAgLmRlZXBsaWItYnV0dG9uIHtcbiAgICAgIGZvbnQtc2l6ZTogMC44ZW07XG4gICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgd2lkdGg6IGF1dG87XG4gICAgICBwYWRkaW5nOiBtaW4oMC40dmgsIDAuMnZ3KSBtaW4oMnZoLCAxdncpO1xuXG4gICAgICAuYnV0dG9uLWxhYmVsIHtcbiAgICAgICAgZGlzcGxheTogY29udGVudHM7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi5kZWVwbGliLW1vZGFsLWJsb2NrZXIge1xuICB6LWluZGV4OiAxMDAwO1xuICBwb3NpdGlvbjogZml4ZWQ7XG4gIHRvcDogMDtcbiAgbGVmdDogMDtcbiAgd2lkdGg6IDEwMGR2dztcbiAgaGVpZ2h0OiAxMDBkdmg7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMCwgMCwgMCwgMC41KTtcbn1cbiJdfQ== */`;
877
+ /*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VSb290IjoiL21lZGlhL05WTUUvU3R1ZmYvQ29kZS9CQy9CQy1EZWVwTGliL3NyYy9zdHlsZXMiLCJzb3VyY2VzIjpbInZhcnMuc2NzcyIsImJ1dHRvbnMuc2NzcyIsImVsZW1lbnRzLnNjc3MiLCJpbnB1dHMuc2NzcyIsIm1lc3NhZ2VzLnNjc3MiLCJtb2RhbC5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FBQUE7RUFFRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7O0FDZEY7RUFDRTtFQUNBO0VBQ0E7OztBQUdGO0FBQUE7RUFFRTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBRUE7RUFDQTtFQUNBOzs7QUFHRjtFQUNFOzs7QUFHRjtFQUNFO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTs7O0FDM0NGO0VBQ0U7RUFDQTtFQUNBOzs7QUFHRjtFQUNFO0VBQ0E7OztBQUdGO0VBQ0U7OztBQUdGO0VBQ0U7RUFDQTtFQUNBOzs7QUFHRjtFQUNFO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOztBQUVBO0VBTUU7RUFDQTs7QUFOQTtFQUNFO0VBQ0E7O0FBT0o7RUFDRTs7O0FBSUo7RUFDRTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBOzs7QUN6R0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTs7O0FBR0Y7RUFDRTs7O0FBR0Y7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOzs7QUFJRjtFQUNFO0VBQ0E7RUFDQTtFQUNBOzs7QUFHRjtFQUNFO0VBQ0E7OztBQUdGO0FBQUE7RUFFRTtFQUNBOzs7QUFHRjtFQUNFO0VBQ0E7OztBQzdERjtFQUNFO0VBQ0E7OztBQUdGO0FBQUE7RUFFRTtFQUNBO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOzs7QUFHRjtBQUFBO0VBRUU7OztBQUdGO0VBQ0U7RUFDQTtFQUNBOzs7QUM3QkY7RUFDRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOztBQUVBO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7O0FBR0Y7RUFDRTs7QUFHRjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7O0FBRUE7RUFDRTtFQUNBO0VBQ0E7RUFDQTs7QUFFQTtFQUNFOztBQUtOO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7OztBQUlKO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0EiLCJzb3VyY2VzQ29udGVudCI6WyIuZGVlcGxpYi1zdWJzY3JlZW4sXG4uZGVlcGxpYi1tb2RhbCB7XG4gIC0tZGVlcGxpYi1iYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS10bWQtbWFpbiwgd2hpdGUpO1xuICAtLWRlZXBsaWItZWxlbWVudC1jb2xvcjogdmFyKC0tdG1kLWVsZW1lbnQsIHdoaXRlKTtcbiAgLS1kZWVwbGliLWVsZW1lbnQtaG92ZXItY29sb3I6IHZhcigtLXRtZC1lbGVtZW50LWhvdmVyLCBjeWFuKTtcbiAgLS1kZWVwbGliLWFjY2VudC1jb2xvcjogdmFyKC0tdG1kLWFjY2VudCwgI0ZGRkY4OCk7XG4gIC0tZGVlcGxpYi1ibG9ja2VkLWNvbG9yOiB2YXIoLS10bWQtYmxvY2tlZCwgcmVkKTtcbiAgLS1kZWVwbGliLXRleHQtY29sb3I6IHZhcigtLXRtZC10ZXh0LCBibGFjayk7XG4gIC0tZGVlcGxpYi1pY29uLWNvbG9yOiB2YXIoLS10bWQtYWNjZW50LCBibGFjayk7XG4gIC0tZGVlcGxpYi1pY29uLWhvdmVyLWNvbG9yOiB2YXIoLS10bWQtYWNjZW50LWhvdmVyLCBibGFjayk7XG4gIC0tZGVlcGxpYi1ib3JkZXItY29sb3I6IHZhcigtLXRtZC1hY2NlbnQsIGJsYWNrKTtcbiAgLS1kZWVwbGliLWJvcmRlci13aWR0aDogbWluKDAuMnZoLCAwLjF2dyk7XG4gIC0tZGVlcGxpYi1ib3JkZXItd2lkdGg6IG1pbigwLjJkdmgsIDAuMWR2dyk7XG4gIC0tZGVlcGxpYi1ib3JkZXItcmFkaXVzOiBtaW4oMXZoLCAwLjV2dyk7XG4gIC0tZGVlcGxpYi1ib3JkZXItcmFkaXVzOiBtaW4oMWR2aCwgMC41ZHZ3KTtcbn1cbiIsIi5kZWVwbGliLWJ1dHRvbiB7XG4gIGNvbG9yOiB2YXIoLS1kZWVwbGliLXRleHQtY29sb3IpO1xuICB3aWR0aDogMTAwJTtcbiAgaGVpZ2h0OiAxMDAlO1xufVxuXG4uZGVlcGxpYi1idXR0b24uYnV0dG9uLXN0eWxpbmcsXG4uZGVlcGxpYi1idXR0b24uYnV0dG9uLXN0eWxpbmc6OmJlZm9yZSB7XG4gIGJvcmRlci1yYWRpdXM6IG1pbigxLjBkdmgsIDAuNWR2dyk7XG59XG5cbi5kZWVwbGliLWJ1dHRvbiBpbWcge1xuICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gIHRvcDogMCU7XG4gIGxlZnQ6IDAlO1xuICB3aWR0aDogMTAwJTtcbiAgaGVpZ2h0OiAxMDAlO1xuICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiBsZWZ0O1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1kZWVwbGliLWljb24tY29sb3IpO1xuICBiYWNrZ3JvdW5kLWJsZW5kLW1vZGU6IG11bHRpcGx5O1xuICBiYWNrZ3JvdW5kLXNpemU6IGNvbnRhaW47XG4gIG1hc2stcG9zaXRpb246IGxlZnQ7XG4gIG1hc2stc2l6ZTogY29udGFpbjtcbiAgYmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDtcbiAgbWFzay1yZXBlYXQ6IG5vLXJlcGVhdDtcbiAgY29sb3I6IHRyYW5zcGFyZW50O1xuXG4gIGJhY2tncm91bmQtaW1hZ2U6IHZhcigtLWltYWdlKTtcbiAgbWFzay1pbWFnZTogdmFyKC0taW1hZ2UpO1xuICBwb2ludGVyLWV2ZW50czogbm9uZTtcbn1cblxuLmRlZXBsaWItYnV0dG9uOmhvdmVyIGltZyB7XG4gIGJhY2tncm91bmQtY29sb3I6IHZhcigtLWRlZXBsaWItaWNvbi1ob3Zlci1jb2xvcik7XG59XG5cbi5kZWVwbGliLWJ1dHRvbiAuYnV0dG9uLWxhYmVsIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQgIWltcG9ydGFudDtcbiAgY29sb3I6IHZhcigtLWRlZXBsaWItdGV4dC1jb2xvcik7XG4gIGZvbnQtc2l6ZTogbWluKDMuNmR2aCwgMS44ZHZ3KTtcbn1cblxuLmRlZXBsaWItYnV0dG9uIC5idXR0b24tdG9vbHRpcCB7XG4gIGJvcmRlci1yYWRpdXM6IG1pbigxLjBkdmgsIDAuNWR2dyk7XG59XG4iLCIjZGVlcGxpYi1wYWdlLWxhYmVsIHtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG59XG5cbiNkZWVwbGliLXN1YnNjcmVlbi10aXRsZSB7XG4gIHRleHQtYWxpZ246IGxlZnQ7XG4gIGNvbG9yOiB2YXIoLS1kZWVwbGliLXRleHQtY29sb3IpO1xufVxuXG4uZGVlcGxpYi10ZXh0IHtcbiAgY29sb3I6IHZhcigtLWRlZXBsaWItdGV4dC1jb2xvcik7XG59XG5cbi5kZWVwbGliLXN1YnNjcmVlbiB7XG4gIHBhZGRpbmc6IDA7XG4gIG1hcmdpbjogMDtcbiAgcG9pbnRlci1ldmVudHM6IG5vbmU7XG59XG5cbi5kZWVwbGliLXN1YnNjcmVlbiAqIHtcbiAgYm94LXNpemluZzogYm9yZGVyLWJveDtcbiAgcG9pbnRlci1ldmVudHM6IGFsbDtcbn1cblxuLmRlZXBsaWItc2V0dGluZ3Mge1xuICBkaXNwbGF5OiBncmlkO1xuICBncmlkLWF1dG8tcm93czogbWluLWNvbnRlbnQ7XG4gIHBhZGRpbmc6IG1pbigxLjBkdmgsIDAuNWR2dyk7XG4gIGdhcDogMC4zZW07XG4gIG92ZXJmbG93LXk6IHNjcm9sbDtcbn1cblxuLmRlZXBsaWItbWlzYyB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW4tcmV2ZXJzZTtcbiAgZ2FwOiBtaW4oMXZoLCAwLjV2dyk7XG59XG5cbi5kZWVwbGliLXRvb2x0aXAge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1kZWVwbGliLWVsZW1lbnQtY29sb3IpO1xuICBjb2xvcjogdmFyKC0tZGVlcGxpYi10ZXh0LWNvbG9yKTtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG4gIGJvcmRlci1yYWRpdXM6IG1pbigxLjBkdmgsIDAuNWR2dyk7XG4gIHBhZGRpbmc6IG1pbigxdmgsIDAuNXZ3KTtcbiAgZm9udC1zaXplOiAwLjhlbTtcbiAgYm9yZGVyOiBtaW4oMC4ydmgsIDAuMXZ3KSBzb2xpZCB2YXIoLS1kZWVwbGliLWJvcmRlci1jb2xvcik7XG59XG5cbi5kZWVwbGliLW92ZXJmbG93LWJveCB7XG4gIGJvcmRlcjogdmFyKC0tZGVlcGxpYi1ib3JkZXItY29sb3IpIHNvbGlkIHZhcigtLWRlZXBsaWItYm9yZGVyLXdpZHRoKTtcbn1cblxuLmRlZXBsaWItcHJldi1uZXh0IHtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xuICBmbGV4LWRpcmVjdGlvbjogcm93O1xuICBnYXA6IG1pbigyZHZoLCAxZHZ3KTtcbiAgYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tZGVlcGxpYi1lbGVtZW50LWNvbG9yKTtcbiAgY29sb3I6IHZhcigtLWRlZXBsaWItdGV4dC1jb2xvcik7XG4gIGJvcmRlci1yYWRpdXM6IG1pbigxLjBkdmgsIDAuNWR2dyk7XG4gIGJvcmRlcjogbWluKDAuMnZoLCAwLjF2dykgc29saWQgdmFyKC0tZGVlcGxpYi1ib3JkZXItY29sb3IpO1xuXG4gIC5kZWVwbGliLXByZXYtbmV4dC1idXR0b24ge1xuICAgICY6aG92ZXIge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tZGVlcGxpYi1lbGVtZW50LWhvdmVyLWNvbG9yKTtcbiAgICAgIGJvcmRlci1yYWRpdXM6IHZhcigtLWRlZXBsaWItYm9yZGVyLXJhZGl1cyk7XG4gICAgfVxuICAgIFxuICAgIGhlaWdodDogMTAwJTtcbiAgICBhc3BlY3QtcmF0aW86IDE7XG4gIH1cblxuICAuZGVlcGxpYi1wcmV2LW5leHQtbGFiZWwge1xuICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7XG4gIH1cbn1cblxuI2RlZXBsaWItbmF2LW1lbnUge1xuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LWRpcmVjdGlvbjogcm93O1xuICBnYXA6IG1pbigyZHZoLCAxZHZ3KTtcbn1cblxuI2RlZXBsaWItc3RvcmFnZS1tZXRlciB7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgdG9wOiAwcHg7XG4gIGxlZnQ6IDBweDtcbiAgd2lkdGg6IDEwMCU7XG4gIGhlaWdodDogMTAwJTtcbiAgb3ZlcmZsb3c6IGhpZGRlbjtcbiAgYmFja2dyb3VuZC1jb2xvcjogdmFyKC0tZGVlcGxpYi1lbGVtZW50LWNvbG9yKTtcbiAgYm9yZGVyOiB2YXIoLS1kZWVwbGliLWJvcmRlci13aWR0aCkgc29saWQgdmFyKC0tZGVlcGxpYi1ib3JkZXItY29sb3IpO1xuICBib3JkZXItcmFkaXVzOiB2YXIoLS1kZWVwbGliLWJvcmRlci1yYWRpdXMpO1xuICB6LWluZGV4OiAtMTtcbn1cblxuI2RlZXBsaWItc3RvcmFnZS1iYXIge1xuICBoZWlnaHQ6IDEwMCU7XG4gIHdpZHRoOiAwJTtcbiAgYmFja2dyb3VuZDogdmFyKC0tZGVlcGxpYi1hY2NlbnQtY29sb3IpO1xufVxuIiwiLmRlZXBsaWItY2hlY2tib3gtY29udGFpbmVyIHtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC1kaXJlY3Rpb246IHJvdztcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgZ2FwOiAwLjNlbTtcbn1cblxuLmRlZXBsaWItY2hlY2tib3gtY29udGFpbmVyIGlucHV0LmRlZXBsaWItaW5wdXQge1xuICB3aWR0aDogbWluKDV2aCwgMi41dncpO1xuICBoZWlnaHQ6IG1pbig1dmgsIDIuNXZ3KTtcbiAgYm9yZGVyLXJhZGl1czogbWluKDEuMGR2aCwgMC41ZHZ3KTtcbn1cblxuLmRlZXBsaWItY2hlY2tib3gtY29udGFpbmVyIGlucHV0LmRlZXBsaWItaW5wdXRbdHlwZT1cImNoZWNrYm94XCJdOmNoZWNrZWQ6OmJlZm9yZSB7XG4gIHdpZHRoOiA4MCU7XG4gIGhlaWdodDogODAlO1xufVxuXG4uZGVlcGxpYi1pbnB1dC1jb250YWluZXIge1xuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LWRpcmVjdGlvbjogcm93O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBnYXA6IDAuM2VtO1xufVxuXG4uZGVlcGxpYi1pbnB1dC1jb250YWluZXI6aGFzKGxhYmVsLmRlZXBsaWItdGV4dCkge1xuICBtYXJnaW4tdG9wOiBtaW4oMXZoLCAwLjV2dyk7XG59XG5cbi5kZWVwbGliLWlucHV0LWNvbnRhaW5lciBpbnB1dC5kZWVwbGliLWlucHV0IHtcbiAgZm9udC1zaXplOiAwLjZlbTtcbiAgcGFkZGluZzogNXB4IDA7XG4gIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xuICBvdXRsaW5lOiBub25lO1xuICBwYWRkaW5nLWxlZnQ6IG1pbigxdmgsIDAuNXZ3KTtcbiAgcGFkZGluZy1yaWdodDogbWluKDF2aCwgMC41dncpO1xuICBtaW4taGVpZ2h0OiBtaW4oNWR2aCwgMi41ZHZ3KTtcbiAgYm9yZGVyLXJhZGl1czogbWluKDEuMGR2aCwgMC41ZHZ3KTtcbn1cblxuXG4uZGVlcGxpYi1pbnB1dC1jb250YWluZXIgaW5wdXQuZGVlcGxpYi1pbnB1dFt0eXBlPVwiY29sb3JcIl0ge1xuICBwYWRkaW5nOiAwcHg7XG4gIHdpZHRoOiBtaW4oNXZoLCAyLjV2dyk7XG4gIGhlaWdodDogbWluKDV2aCwgMi41dncpO1xuICBib3JkZXItcmFkaXVzOiAwcHg7XG59XG5cbi5kZWVwbGliLWlucHV0LWNvbnRhaW5lciBpbnB1dC5kZWVwbGliLWlucHV0W3R5cGU9XCJjb2xvclwiXTpkaXNhYmxlZCB7XG4gIGJvcmRlcjogdmFyKC0tZGVlcGxpYi1ibG9ja2VkLWNvbG9yKSBzb2xpZCB2YXIoLS1kZWVwbGliLWJvcmRlci13aWR0aCk7XG4gIGN1cnNvcjogbm90LWFsbG93ZWQ7XG59XG5cbmlucHV0Ojotd2Via2l0LW91dGVyLXNwaW4tYnV0dG9uLFxuaW5wdXQ6Oi13ZWJraXQtaW5uZXItc3Bpbi1idXR0b24ge1xuICAtd2Via2l0LWFwcGVhcmFuY2U6IG5vbmU7XG4gIG1hcmdpbjogMDtcbn1cblxuaW5wdXRbdHlwZT1udW1iZXJdIHtcbiAgYXBwZWFyYW5jZTogdGV4dGZpZWxkO1xuICAtbW96LWFwcGVhcmFuY2U6IHRleHRmaWVsZDtcbn1cbiIsIi5kZWVwbGliLWhpZ2hsaWdodC10ZXh0IHtcbiAgZm9udC13ZWlnaHQ6IGJvbGQ7XG4gIGNvbG9yOiByZ2IoMjAzLCAxODUsIDIzKTtcbn1cblxuI1RleHRBcmVhQ2hhdExvZ1tkYXRhLWNvbG9ydGhlbWU9J2RhcmsnXSBkaXYuQ2hhdE1lc3NhZ2UuZGVlcGxpYi1tZXNzYWdlLFxuI1RleHRBcmVhQ2hhdExvZ1tkYXRhLWNvbG9ydGhlbWU9J2RhcmsyJ10gZGl2LkNoYXRNZXNzYWdlLmRlZXBsaWItbWVzc2FnZSB7XG4gIGJhY2tncm91bmQtY29sb3I6IHZhcigtLWRlZXBsaWItZWxlbWVudC1jb2xvcik7XG4gIGJvcmRlcjogbWluKDAuMmR2aCwgMC4xZHZ3KSBzb2xpZCB2YXIoLS1kZWVwbGliLWJvcmRlci1jb2xvcik7XG4gIGNvbG9yOiB2YXIoLS1kZWVwbGliLXRleHQtY29sb3IpO1xufVxuXG4jVGV4dEFyZWFDaGF0TG9nIGRpdi5DaGF0TWVzc2FnZS5kZWVwbGliLW1lc3NhZ2Uge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZWVlO1xuICBib3JkZXI6IG1pbigwLjJkdmgsIDAuMWR2dykgc29saWQgIzQ0MDE3MTtcbiAgY29sb3I6ICMxMTE7XG4gIHBhZGRpbmctbGVmdDogbWluKDAuNmR2aCwgMC4zZHZ3KTtcbiAgZGlzcGxheTogYmxvY2s7XG4gIHdoaXRlLXNwYWNlOiBub3JtYWw7XG59XG5cbiNUZXh0QXJlYUNoYXRMb2dbZGF0YS1jb2xvcnRoZW1lPSdkYXJrJ10gZGl2LkNoYXRNZXNzYWdlLmRlZXBsaWItbWVzc2FnZSBhLFxuI1RleHRBcmVhQ2hhdExvZ1tkYXRhLWNvbG9ydGhlbWU9J2RhcmsyJ10gZGl2LkNoYXRNZXNzYWdlLmRlZXBsaWItbWVzc2FnZSBhIHtcbiAgY29sb3I6IHZhcigtLWRlZXBsaWItdGV4dC1jb2xvcik7XG59XG5cbiNUZXh0QXJlYUNoYXRMb2cgZGl2LkNoYXRNZXNzYWdlLmRlZXBsaWItbWVzc2FnZSBhIHtcbiAgY3Vyc29yOiBwb2ludGVyO1xuICBmb250LXdlaWdodDogYm9sZDtcbiAgY29sb3I6ICMxMTE7XG59XG4iLCIuZGVlcGxpYi1tb2RhbCB7XG4gIHBvc2l0aW9uOiBmaXhlZDtcbiAgdG9wOiAxMCU7XG4gIGxlZnQ6IDUwJTtcbiAgdHJhbnNmb3JtOiB0cmFuc2xhdGVYKC01MCUpO1xuICB6LWluZGV4OiAxMDAxO1xuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgZ2FwOiAwLjVlbTtcbiAgd2lkdGg6IG1heCg1MGR2dywgMjVkdmgpO1xuICBmb250LXNpemU6IG1pbig0ZHZoLCAyZHZ3KTtcbiAgcGFkZGluZzogbWluKDJkdmgsIDFkdncpO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1kZWVwbGliLWVsZW1lbnQtY29sb3IpO1xuICBib3JkZXItcmFkaXVzOiBtaW4oMS4yZHZoLCAwLjZkdncpO1xuICBib3JkZXI6IG1pbigwLjJkdmgsIDAuMWR2dykgc29saWQgdmFyKC0tZGVlcGxpYi1ib3JkZXItY29sb3IpO1xuICBjb2xvcjogdmFyKC0tZGVlcGxpYi10ZXh0LWNvbG9yKTtcblxuICAuZGVlcGxpYi1tb2RhbC1pbnB1dCB7XG4gICAgd2lkdGg6IDEwMCU7XG4gICAgZm9udC1zaXplOiBtaW4oMi42ZHZoLCAxLjhkdncpO1xuICAgIGJvcmRlci1yYWRpdXM6IG1pbigxLjBkdmgsIDAuNWR2dyk7XG4gICAgcGFkZGluZzogbWluKDFkdmgsIDAuNWR2dyk7XG4gIH1cblxuICBpbnB1dC5kZWVwbGliLW1vZGFsLWlucHV0IHtcbiAgICBtYXgtd2lkdGg6IG1heCg1MGR2aCwgMjVkdncpO1xuICB9XG5cbiAgLmRlZXBsaWItbW9kYWwtYnV0dG9uLWNvbnRhaW5lciB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBmbGV4LWRpcmVjdGlvbjogcm93O1xuICAgIGp1c3RpZnktY29udGVudDogZmxleC1lbmQ7XG4gICAgZ2FwOiAwLjVlbTtcbiAgICB3aWR0aDogMTAwJTtcblxuICAgIC5kZWVwbGliLWJ1dHRvbiB7XG4gICAgICBmb250LXNpemU6IDAuOGVtO1xuICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgIHdpZHRoOiBhdXRvO1xuICAgICAgcGFkZGluZzogbWluKDAuNHZoLCAwLjJ2dykgbWluKDJ2aCwgMXZ3KTtcblxuICAgICAgLmJ1dHRvbi1sYWJlbCB7XG4gICAgICAgIGRpc3BsYXk6IGNvbnRlbnRzO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC5kZWVwbGliLW1vZGFsLXByb21wdC1jb250YWluZXIge1xuICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICB9XG59XG5cbi5kZWVwbGliLW1vZGFsLWJsb2NrZXIge1xuICB6LWluZGV4OiAxMDAwO1xuICBwb3NpdGlvbjogZml4ZWQ7XG4gIHRvcDogMDtcbiAgbGVmdDogMDtcbiAgd2lkdGg6IDEwMGR2dztcbiAgaGVpZ2h0OiAxMDBkdmg7XG4gIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMCwgMCwgMCwgMC41KTtcbn1cbiJdfQ== */`;
843
878
 
844
879
  // src/base/initialization.ts
845
880
  var modStorage;
881
+ var sdk;
846
882
  function initMod(options) {
847
- const sdk = new ModSdkManager(options.modInfo.info, options.modInfo.options);
883
+ sdk = new ModSdkManager(options.modInfo.info, options.modInfo.options);
848
884
  const MOD_NAME = ModSdkManager.ModInfo.name;
849
885
  modStorage = new ModStorage(ModSdkManager.ModInfo.name);
850
886
  Style.injectInline("deeplib-style", styles_default);
@@ -865,7 +901,6 @@ function initMod(options) {
865
901
  deepLibLogger.debug(`Already logged in, initing ${MOD_NAME}`);
866
902
  init(options);
867
903
  }
868
- return { sdk };
869
904
  }
870
905
  __name(initMod, "initMod");
871
906
  async function init(options) {
@@ -958,20 +993,34 @@ var GUI = class _GUI extends BaseModule {
958
993
  static {
959
994
  __name(this, "GUI");
960
995
  }
996
+ /** The singleton instance of the GUI controller. */
961
997
  static instance = null;
998
+ /** All subscreens managed by this GUI, including the main menu and module settings screens. */
962
999
  _subscreens;
1000
+ /** The mod's main menu screen. */
963
1001
  _mainMenu;
1002
+ /** The currently active subscreen, or `null` if none is active. */
964
1003
  _currentSubscreen = null;
1004
+ /** Options defining how the mod's settings button is displayed and behaves. */
965
1005
  _modButtonOptions;
1006
+ /** Returns all registered subscreens. */
966
1007
  get subscreens() {
967
1008
  return this._subscreens;
968
1009
  }
1010
+ /** Returns the main menu subscreen instance. */
969
1011
  get mainMenu() {
970
1012
  return this._mainMenu;
971
1013
  }
1014
+ /** Returns the currently active subscreen. */
972
1015
  get currentSubscreen() {
973
1016
  return this._currentSubscreen;
974
1017
  }
1018
+ /**
1019
+ * Sets the current subscreen.
1020
+ * Accepts either a `BaseSubscreen` instance or the `name` of a subscreen.
1021
+ *
1022
+ * @throws If a string is provided but no subscreen with that name exists.
1023
+ */
975
1024
  set currentSubscreen(subscreen) {
976
1025
  if (this._currentSubscreen) {
977
1026
  this._currentSubscreen.unload();
@@ -988,7 +1037,11 @@ var GUI = class _GUI extends BaseModule {
988
1037
  this._currentSubscreen.resize(true);
989
1038
  }
990
1039
  }
991
- /** Creates the GUI instance and initializes the main menu. */
1040
+ /**
1041
+ * Creates the GUI instance and initializes the main menu.
1042
+ *
1043
+ * @throws If another `GUI` instance already exists.
1044
+ */
992
1045
  constructor(modButtonOptions) {
993
1046
  super();
994
1047
  if (_GUI.instance) {
@@ -1002,9 +1055,13 @@ var GUI = class _GUI extends BaseModule {
1002
1055
  this._modButtonOptions = modButtonOptions;
1003
1056
  _GUI.instance = this;
1004
1057
  }
1005
- get defaultSettings() {
1006
- return null;
1007
- }
1058
+ /**
1059
+ * Loads the GUI and registers the mod's settings button in the extensions menu.
1060
+ *
1061
+ * - Creates subscreens for each module's settings screen.
1062
+ * - Registers lifecycle callbacks for subscreens events.
1063
+ * - Sets up the main menu and its subscreens.
1064
+ */
1008
1065
  load() {
1009
1066
  for (const module of modules()) {
1010
1067
  if (!module.settingsScreen) continue;
@@ -1015,36 +1072,34 @@ var GUI = class _GUI extends BaseModule {
1015
1072
  Identifier: this._modButtonOptions.Identifier,
1016
1073
  ButtonText: this._modButtonOptions.ButtonText,
1017
1074
  Image: this._modButtonOptions.Image,
1018
- load: this._modButtonOptions.load || (() => {
1075
+ load: /* @__PURE__ */ __name(() => {
1019
1076
  setSubscreen(new MainMenu(this));
1020
- }),
1021
- run: this._modButtonOptions.run || (() => {
1077
+ }, "load"),
1078
+ run: /* @__PURE__ */ __name(() => {
1022
1079
  if (this._currentSubscreen) {
1023
- MainCanvas.textAlign = "left";
1024
1080
  this._currentSubscreen.run();
1025
- MainCanvas.textAlign = "center";
1026
1081
  const newCanvasPosition = [MainCanvas.canvas.offsetLeft, MainCanvas.canvas.offsetTop, MainCanvas.canvas.clientWidth, MainCanvas.canvas.clientHeight];
1027
1082
  if (!CommonArraysEqual(newCanvasPosition, DrawCanvasPosition)) {
1028
1083
  DrawCanvasPosition = newCanvasPosition;
1029
1084
  this._currentSubscreen.resize(false);
1030
1085
  }
1031
1086
  }
1032
- }),
1033
- click: this._modButtonOptions.click || (() => {
1087
+ }, "run"),
1088
+ click: /* @__PURE__ */ __name(() => {
1034
1089
  if (this._currentSubscreen) {
1035
1090
  this._currentSubscreen.click();
1036
1091
  }
1037
- }),
1038
- exit: this._modButtonOptions.exit || (() => {
1092
+ }, "click"),
1093
+ exit: /* @__PURE__ */ __name(() => {
1039
1094
  if (this._currentSubscreen) {
1040
1095
  this._currentSubscreen.exit();
1041
1096
  }
1042
- }),
1043
- unload: this._modButtonOptions.unload || (() => {
1097
+ }, "exit"),
1098
+ unload: /* @__PURE__ */ __name(() => {
1044
1099
  if (this._currentSubscreen) {
1045
1100
  this._currentSubscreen.unload();
1046
1101
  }
1047
- })
1102
+ }, "unload")
1048
1103
  });
1049
1104
  }
1050
1105
  };
@@ -1054,10 +1109,19 @@ var VersionModule = class _VersionModule extends BaseModule {
1054
1109
  static {
1055
1110
  __name(this, "VersionModule");
1056
1111
  }
1112
+ /** Whether the current session is running a new version compared to stored data */
1057
1113
  static isItNewVersion = false;
1114
+ /** The current mod version (retrieved from `ModSdkManager.ModInfo.version`) */
1058
1115
  static Version;
1116
+ /** Message to display when a new version is detected */
1059
1117
  static NewVersionMessage = "";
1118
+ /** List of registered migration handlers, sorted by version */
1060
1119
  static Migrators = [];
1120
+ /**
1121
+ * Initializes the module on load:
1122
+ * - Stores the current mod version.
1123
+ * - Hooks into `ChatRoomSync` to show a "new version" message when applicable.
1124
+ */
1061
1125
  load() {
1062
1126
  _VersionModule.Version = ModSdkManager.ModInfo.version;
1063
1127
  ModSdkManager.prototype.hookFunction(
@@ -1072,6 +1136,14 @@ var VersionModule = class _VersionModule extends BaseModule {
1072
1136
  "VersionModule"
1073
1137
  );
1074
1138
  }
1139
+ /**
1140
+ * Checks if the stored version differs from the current version.
1141
+ * If a new version is detected:
1142
+ * - Flags the session as updated.
1143
+ * - Runs applicable migrations.
1144
+ * - Updates stored version in player data.
1145
+ * - Saves `modStorage`.
1146
+ */
1075
1147
  static checkVersionUpdate() {
1076
1148
  const PreviousVersion = _VersionModule.loadVersion();
1077
1149
  const CurrentVersion = _VersionModule.Version;
@@ -1082,6 +1154,10 @@ var VersionModule = class _VersionModule extends BaseModule {
1082
1154
  }
1083
1155
  modStorage.save();
1084
1156
  }
1157
+ /**
1158
+ * Executes migrations for all registered migrators whose `MigrationVersion`
1159
+ * is newer than the previously stored version.
1160
+ */
1085
1161
  static checkVersionMigration() {
1086
1162
  const PreviousVersion = _VersionModule.loadVersion();
1087
1163
  for (const migrator of _VersionModule.Migrators) {
@@ -1091,16 +1167,27 @@ var VersionModule = class _VersionModule extends BaseModule {
1091
1167
  }
1092
1168
  }
1093
1169
  }
1170
+ /**
1171
+ * Registers a new migrator for handling version-specific changes.
1172
+ * Migrators are sorted by their `MigrationVersion` in ascending order.
1173
+ */
1094
1174
  static registerMigrator(migrator) {
1095
1175
  _VersionModule.Migrators.push(migrator);
1096
1176
  _VersionModule.Migrators.sort((a, b) => a.MigrationVersion.localeCompare(b.MigrationVersion));
1097
1177
  }
1178
+ /** Sets the message that will be displayed when a new version is detected. */
1098
1179
  static setNewVersionMessage(newVersionMessage) {
1099
1180
  _VersionModule.NewVersionMessage = newVersionMessage;
1100
1181
  }
1182
+ /** Sends the currently configured "new version" message to the local player. */
1101
1183
  static sendNewVersionMessage() {
1102
1184
  sendLocalMessage("deeplib-new-version", _VersionModule.NewVersionMessage);
1103
1185
  }
1186
+ /**
1187
+ * Determines if a given `candidate` version is newer than the `current` version.
1188
+ *
1189
+ * Version strings are expected in `MAJOR.MINOR.PATCH` format.
1190
+ */
1104
1191
  static isNewVersion(current, candidate) {
1105
1192
  if (current !== void 0) {
1106
1193
  const CURRENT_ = current.split("."), CANDIDATE_ = candidate.split(".");
@@ -1116,11 +1203,13 @@ var VersionModule = class _VersionModule extends BaseModule {
1116
1203
  }
1117
1204
  return false;
1118
1205
  }
1206
+ /** Saves the current mod version into persistent player storage. */
1119
1207
  static saveVersion() {
1120
1208
  if (modStorage.playerStorage) {
1121
1209
  Player[ModSdkManager.ModInfo.name].Version = _VersionModule.Version;
1122
1210
  }
1123
1211
  }
1212
+ /** Loads the stored mod version from persistent player storage. */
1124
1213
  static loadVersion() {
1125
1214
  return modStorage.playerStorage?.Version;
1126
1215
  }
@@ -1342,6 +1431,7 @@ function hasSetter(obj, prop) {
1342
1431
  return false;
1343
1432
  }
1344
1433
  __name(hasSetter, "hasSetter");
1434
+ var byteToKB = /* @__PURE__ */ __name((nByte) => Math.round(nByte / 100) / 10, "byteToKB");
1345
1435
 
1346
1436
  // src/utilities/elements/elements.ts
1347
1437
  var advElement = {
@@ -1356,19 +1446,23 @@ var advElement = {
1356
1446
  createBackNext: elementPrevNext
1357
1447
  };
1358
1448
  function elementCreateButton(options) {
1449
+ options.id ??= ElementGenerateID();
1359
1450
  const elem = document.getElementById(options.id);
1360
1451
  if (elem) return elem;
1361
1452
  options.type = "button";
1453
+ let image = void 0;
1454
+ if (options.options?.image) {
1455
+ image = options.options.image;
1456
+ options.options.image = void 0;
1457
+ }
1362
1458
  const disabled = typeof options?.disabled === "function" ? options?.disabled() : options?.disabled;
1363
1459
  const button = ElementButton.Create(
1364
- options.htmlOptions?.id ?? options.id,
1365
- options.htmlOptions?.onClick ?? options?.onClick ?? (() => {
1460
+ options.id,
1461
+ options?.onClick ?? (() => {
1366
1462
  }),
1367
1463
  deepMerge({
1368
- tooltip: options.tooltip,
1369
- label: options.label,
1370
1464
  labelPosition: "center"
1371
- }, options.htmlOptions?.options),
1465
+ }, options.options),
1372
1466
  deepMerge({
1373
1467
  button: {
1374
1468
  classList: ["deeplib-button"],
@@ -1376,7 +1470,7 @@ function elementCreateButton(options) {
1376
1470
  disabled
1377
1471
  },
1378
1472
  children: [
1379
- options.image ? {
1473
+ image ? {
1380
1474
  tag: "img",
1381
1475
  attributes: {
1382
1476
  id: `${options.id}-image`,
@@ -1387,12 +1481,12 @@ function elementCreateButton(options) {
1387
1481
  // 1x1 transparent image to get rid of broken image
1388
1482
  },
1389
1483
  style: {
1390
- "--image": `url("${options.image}")`
1484
+ "--image": `url("${image}")`
1391
1485
  }
1392
1486
  } : void 0
1393
1487
  ]
1394
1488
  }
1395
- }, options.htmlOptions?.htmlOptions ?? {})
1489
+ }, options.htmlOptions ?? {})
1396
1490
  );
1397
1491
  BaseSubscreen.currentElements.push([button, options]);
1398
1492
  return button;
@@ -1585,7 +1679,6 @@ function elementPrevNext(options) {
1585
1679
  children: [
1586
1680
  advElement.createButton({
1587
1681
  id: `deeplib-prev-next-${options.id}-prev-button`,
1588
- image: `${PUBLIC_URL}/dl_images/arrow_left.svg`,
1589
1682
  onClick: /* @__PURE__ */ __name(() => {
1590
1683
  options.back({
1591
1684
  setLabel,
@@ -1593,16 +1686,15 @@ function elementPrevNext(options) {
1593
1686
  setNextTooltip
1594
1687
  });
1595
1688
  }, "onClick"),
1596
- tooltip: options.initialPrevTooltip,
1597
1689
  htmlOptions: {
1598
- htmlOptions: {
1599
- button: {
1600
- classList: ["deeplib-prev-next-button"]
1601
- }
1602
- },
1603
- options: {
1604
- noStyling: true
1690
+ button: {
1691
+ classList: ["deeplib-prev-next-button"]
1605
1692
  }
1693
+ },
1694
+ options: {
1695
+ noStyling: true,
1696
+ image: `${PUBLIC_URL}/dl_images/arrow_left.svg`,
1697
+ tooltip: options.initialPrevTooltip
1606
1698
  }
1607
1699
  }),
1608
1700
  advElement.createLabel({
@@ -1614,7 +1706,6 @@ function elementPrevNext(options) {
1614
1706
  }),
1615
1707
  advElement.createButton({
1616
1708
  id: `deeplib-prev-next-${options.id}-next-button`,
1617
- image: `${PUBLIC_URL}/dl_images/arrow_right.svg`,
1618
1709
  onClick: /* @__PURE__ */ __name(() => {
1619
1710
  options.next({
1620
1711
  setLabel,
@@ -1622,16 +1713,15 @@ function elementPrevNext(options) {
1622
1713
  setNextTooltip
1623
1714
  });
1624
1715
  }, "onClick"),
1625
- tooltip: options.initialNextTooltip,
1626
1716
  htmlOptions: {
1627
- htmlOptions: {
1628
- button: {
1629
- classList: ["deeplib-prev-next-button"]
1630
- }
1631
- },
1632
- options: {
1633
- noStyling: true
1717
+ button: {
1718
+ classList: ["deeplib-prev-next-button"]
1634
1719
  }
1720
+ },
1721
+ options: {
1722
+ noStyling: true,
1723
+ image: `${PUBLIC_URL}/dl_images/arrow_right.svg`,
1724
+ tooltip: options.initialNextTooltip
1635
1725
  }
1636
1726
  })
1637
1727
  ]
@@ -1645,6 +1735,7 @@ var Modal = class _Modal {
1645
1735
  opts ??= {};
1646
1736
  opts.closeOnBackdrop ??= true;
1647
1737
  const promptId = `modal-prompt-${Date.now()}`;
1738
+ const prompt = (CommonIsArray(opts.prompt) ? opts.prompt : [opts.prompt]).filter((i) => i != null) ?? [""];
1648
1739
  this.dialog = ElementCreate({
1649
1740
  tag: "dialog",
1650
1741
  classList: ["deeplib-modal"],
@@ -1657,7 +1748,13 @@ var Modal = class _Modal {
1657
1748
  fontFamily: CommonGetFontName()
1658
1749
  },
1659
1750
  children: [
1660
- opts.prompt,
1751
+ {
1752
+ tag: "div",
1753
+ classList: ["deeplib-modal-prompt-container"],
1754
+ children: [
1755
+ ...prompt
1756
+ ]
1757
+ },
1661
1758
  {
1662
1759
  tag: "div",
1663
1760
  classList: ["deeplib-modal-prompt"],
@@ -1686,22 +1783,56 @@ var Modal = class _Modal {
1686
1783
  blocker;
1687
1784
  inputEl;
1688
1785
  timeoutId;
1786
+ /** Static modal queue. */
1689
1787
  static queue = [];
1788
+ /** Flag to indicate if a modal is currently being shown. */
1690
1789
  static processing = false;
1790
+ /**
1791
+ * Displays the modal and resolves with the chosen action and input value.
1792
+ */
1691
1793
  show() {
1692
1794
  return _Modal.enqueue(this);
1693
1795
  }
1796
+ /**
1797
+ * Shows a simple alert modal with a single "OK" button.
1798
+ */
1694
1799
  static async alert(msg, timeoutMs) {
1695
- await new _Modal({ prompt: msg, buttons: [{ action: "close", text: "OK" }], timeoutMs }).show();
1800
+ await new _Modal({
1801
+ prompt: msg,
1802
+ buttons: [{ action: "close", text: getText("modal.button.ok") }],
1803
+ timeoutMs,
1804
+ escapeAction: "close"
1805
+ }).show();
1696
1806
  }
1807
+ /**
1808
+ * Shows a confirmation modal with "Cancel" and "OK" buttons.
1809
+ * Returns true if "OK" is clicked.
1810
+ */
1697
1811
  static async confirm(msg) {
1698
- const [action] = await new _Modal({ prompt: msg, buttons: [{ text: "Cancel", action: "cancel" }, { text: "OK", action: "ok" }] }).show();
1699
- return action === "ok";
1812
+ const [action] = await new _Modal({
1813
+ prompt: msg,
1814
+ buttons: [{ text: getText("modal.button.decline"), action: "decline" }, { text: getText("modal.button.confirm"), action: "confirm" }],
1815
+ escapeAction: "decline",
1816
+ enterAction: "confirm"
1817
+ }).show();
1818
+ return action === "confirm";
1700
1819
  }
1820
+ /**
1821
+ * Shows a prompt modal with an input field and "Submit"/"Cancel" buttons.
1822
+ * Returns the input value if submitted, otherwise null.
1823
+ */
1701
1824
  static async prompt(msg, defaultValue = "") {
1702
- const [action, value] = await new _Modal({ prompt: msg, timeoutMs: 0, input: { type: "input", defaultValue }, buttons: [{ text: "Cancel", action: "cancel" }, { text: "Submit", action: "submit" }] }).show();
1825
+ const [action, value] = await new _Modal({
1826
+ prompt: msg,
1827
+ timeoutMs: 0,
1828
+ input: { type: "input", defaultValue },
1829
+ buttons: [{ text: getText("modal.button.cancel"), action: "cancel" }, { text: getText("modal.button.submit"), action: "submit" }],
1830
+ escapeAction: "cancel",
1831
+ enterAction: "submit"
1832
+ }).show();
1703
1833
  return action === "submit" ? value : null;
1704
1834
  }
1835
+ /** Creates the input element for the modal, applying configuration and validation. */
1705
1836
  renderInput(cfg) {
1706
1837
  const el = document.createElement(cfg.type);
1707
1838
  el.classList.add("deeplib-modal-input");
@@ -1716,21 +1847,25 @@ var Modal = class _Modal {
1716
1847
  this.inputEl = el;
1717
1848
  return el;
1718
1849
  }
1850
+ /** Creates modal action buttons from configuration. */
1719
1851
  renderButtons() {
1720
1852
  const container = document.createElement("div");
1721
1853
  container.classList.add("deeplib-modal-button-container");
1722
1854
  const btns = this.opts.buttons ? [...this.opts.buttons] : [];
1723
1855
  btns.forEach((b) => {
1724
1856
  const btn = advElement.createButton({
1725
- label: b.text,
1726
1857
  id: `deeplib-modal-${b.action}`,
1727
- disabled: b.disabled,
1728
- onClick: /* @__PURE__ */ __name(() => this.close(b.action), "onClick")
1858
+ onClick: /* @__PURE__ */ __name(() => this.close(b.action), "onClick"),
1859
+ options: {
1860
+ disabled: b.disabled,
1861
+ label: b.text
1862
+ }
1729
1863
  });
1730
1864
  container.append(btn);
1731
1865
  });
1732
1866
  return container;
1733
1867
  }
1868
+ /** Creates the modal backdrop blocker with optional click-to-close behavior. */
1734
1869
  createBlocker() {
1735
1870
  const blocker = document.createElement("div");
1736
1871
  blocker.classList.add("deeplib-modal-blocker");
@@ -1739,6 +1874,7 @@ var Modal = class _Modal {
1739
1874
  blocker.addEventListener("click", () => this.close("close"));
1740
1875
  return blocker;
1741
1876
  }
1877
+ /** Implements a focus trap to keep keyboard navigation inside the modal. */
1742
1878
  setupFocusTrap() {
1743
1879
  const focusable = 'button, [href], input, textarea, select, [tabindex]:not([tabindex="-1"])';
1744
1880
  const elements = Array.from(this.dialog.querySelectorAll(focusable));
@@ -1763,13 +1899,19 @@ var Modal = class _Modal {
1763
1899
  }
1764
1900
  } else if (e.key === "Escape") {
1765
1901
  e.stopPropagation();
1766
- this.close("close");
1902
+ this.close(this.opts.escapeAction ?? "close");
1903
+ } else if (e.key === "Enter") {
1904
+ if (elements.some((el) => el === document.activeElement) && document.activeElement !== this.inputEl) return;
1905
+ e.preventDefault();
1906
+ e.stopPropagation();
1907
+ this.close(this.opts.enterAction ?? "submit");
1767
1908
  }
1768
1909
  });
1769
1910
  window.requestAnimationFrame(() => {
1770
1911
  (this.inputEl || first)?.focus();
1771
1912
  });
1772
1913
  }
1914
+ /** Closes the modal, cleans up DOM, resolves promise, and shows next queued modal. */
1773
1915
  close(action) {
1774
1916
  if (this.timeoutId) clearTimeout(this.timeoutId);
1775
1917
  this.dialog.close();
@@ -1802,7 +1944,6 @@ var Modal = class _Modal {
1802
1944
  }
1803
1945
  }
1804
1946
  };
1805
- window.Modal = Modal;
1806
1947
 
1807
1948
  // src/screens/main_menu.ts
1808
1949
  var MainMenu = class _MainMenu extends BaseSubscreen {
@@ -1827,11 +1968,13 @@ var MainMenu = class _MainMenu extends BaseSubscreen {
1827
1968
  const exitButton = advElement.createButton({
1828
1969
  id: "exit",
1829
1970
  size: [90, 90],
1830
- image: `${PUBLIC_URL}/dl_images/exit.svg`,
1831
1971
  onClick: /* @__PURE__ */ __name(() => {
1832
1972
  this.exit();
1833
1973
  }, "onClick"),
1834
- tooltip: getText("settings.button.back_button_hint")
1974
+ options: {
1975
+ image: `${PUBLIC_URL}/dl_images/exit.svg`,
1976
+ tooltip: getText("settings.button.back_button_hint")
1977
+ }
1835
1978
  });
1836
1979
  const menu = document.getElementById("deeplib-nav-menu");
1837
1980
  if (menu) {
@@ -1841,12 +1984,14 @@ var MainMenu = class _MainMenu extends BaseSubscreen {
1841
1984
  if (screen.name == "mainmenu") continue;
1842
1985
  const button = advElement.createButton({
1843
1986
  id: `${screen.name}-button`,
1844
- image: screen.icon,
1845
- label: getText(`mainmenu.button.${screen.name}`),
1846
1987
  onClick: /* @__PURE__ */ __name(() => {
1847
1988
  this.setSubscreen(screen);
1848
1989
  }, "onClick"),
1849
- size: [null, 90]
1990
+ size: [null, 90],
1991
+ options: {
1992
+ image: screen.icon,
1993
+ label: getText(`mainmenu.button.${screen.name}`)
1994
+ }
1850
1995
  });
1851
1996
  layout.appendToSettingsDiv(button);
1852
1997
  }
@@ -1855,59 +2000,107 @@ var MainMenu = class _MainMenu extends BaseSubscreen {
1855
2000
  if (_MainMenu.options.wikiLink) {
1856
2001
  const wikiButton = advElement.createButton({
1857
2002
  id: "deeplib-wiki-button",
1858
- image: `${PUBLIC_URL}/dl_images/notebook.svg`,
1859
- label: getText("mainmenu.button.wiki"),
1860
2003
  onClick: /* @__PURE__ */ __name(() => {
1861
2004
  window.open(_MainMenu.options.wikiLink, "_blank");
1862
2005
  }, "onClick"),
1863
- size: [null, 80]
2006
+ size: [null, 80],
2007
+ options: {
2008
+ image: `${PUBLIC_URL}/dl_images/notebook.svg`,
2009
+ label: getText("mainmenu.button.wiki")
2010
+ }
1864
2011
  });
1865
2012
  layout.appendToMiscDiv(wikiButton);
1866
2013
  }
1867
2014
  if (_MainMenu.options.repoLink) {
1868
2015
  const repoButton = advElement.createButton({
1869
2016
  id: "deeplib-repo-button",
1870
- image: `${PUBLIC_URL}/dl_images/git.svg`,
1871
- label: getText("mainmenu.button.repo"),
1872
2017
  onClick: /* @__PURE__ */ __name(() => {
1873
2018
  window.open(_MainMenu.options.repoLink, "_blank");
1874
2019
  }, "onClick"),
1875
- size: [null, 80]
2020
+ size: [null, 80],
2021
+ options: {
2022
+ image: `${PUBLIC_URL}/dl_images/git.svg`,
2023
+ label: getText("mainmenu.button.repo")
2024
+ }
1876
2025
  });
1877
2026
  layout.appendToMiscDiv(repoButton);
1878
2027
  }
1879
2028
  if (_MainMenu.options.resetSubscreen) {
1880
2029
  const resetButton = advElement.createButton({
1881
2030
  id: "deeplib-reset-button",
1882
- image: `${PUBLIC_URL}/dl_images/trash_bin.svg`,
1883
- label: getText("mainmenu.button.reset"),
1884
2031
  onClick: /* @__PURE__ */ __name(() => {
1885
2032
  this.setSubscreen(_MainMenu.options.resetSubscreen);
1886
2033
  }, "onClick"),
1887
- size: [null, 80]
2034
+ size: [null, 80],
2035
+ options: {
2036
+ image: `${PUBLIC_URL}/dl_images/trash_bin.svg`,
2037
+ label: getText("mainmenu.button.reset")
2038
+ }
1888
2039
  });
1889
2040
  layout.appendToMiscDiv(resetButton);
1890
2041
  }
1891
2042
  if (_MainMenu.options.importExportSubscreen) {
1892
2043
  const importExportButton = advElement.createButton({
1893
2044
  id: "deeplib-import-export-button",
1894
- image: `${PUBLIC_URL}/dl_images/transfer.svg`,
1895
- label: getText("mainmenu.button.import_export"),
1896
2045
  onClick: /* @__PURE__ */ __name(() => {
1897
2046
  this.setSubscreen(_MainMenu.options.importExportSubscreen);
1898
2047
  }, "onClick"),
1899
- size: [null, 80]
2048
+ size: [null, 80],
2049
+ options: {
2050
+ image: `${PUBLIC_URL}/dl_images/transfer.svg`,
2051
+ label: getText("mainmenu.button.import_export")
2052
+ }
1900
2053
  });
1901
2054
  layout.appendToMiscDiv(importExportButton);
1902
2055
  }
2056
+ if (_MainMenu.options.storageFullnessIndicator) {
2057
+ const maxStorageCapacityKB = 180;
2058
+ const currentStorageCapacityKB = byteToKB(ModStorage.measureSize(Player.OnlineSettings));
2059
+ const fullness = (currentStorageCapacityKB / maxStorageCapacityKB * 100).toFixed(1);
2060
+ const storageFullnessWrapper = advElement.createButton({
2061
+ id: CommonGenerateUniqueID(),
2062
+ size: [null, 80],
2063
+ options: {
2064
+ tooltipPosition: "left",
2065
+ noStyling: true,
2066
+ tooltip: CommonStringPartitionReplace(getText("mainmenu.meter.storage_hint"), {
2067
+ $percentage$: `${fullness}`
2068
+ }).join(""),
2069
+ label: CommonStringPartitionReplace(getText("mainmenu.meter.storage_label"), {
2070
+ $currentCapacity$: `${currentStorageCapacityKB}`,
2071
+ $maxCapacity$: `${maxStorageCapacityKB}`
2072
+ }).join("")
2073
+ },
2074
+ htmlOptions: {
2075
+ button: {
2076
+ children: [
2077
+ {
2078
+ tag: "div",
2079
+ attributes: { id: "deeplib-storage-meter" },
2080
+ children: [
2081
+ {
2082
+ tag: "div",
2083
+ attributes: { id: "deeplib-storage-bar" },
2084
+ style: { width: `${fullness}%` }
2085
+ }
2086
+ ]
2087
+ }
2088
+ ]
2089
+ }
2090
+ }
2091
+ });
2092
+ layout.appendToMiscDiv(storageFullnessWrapper);
2093
+ }
1903
2094
  if (IS_DEBUG) {
1904
2095
  const debugButton = advElement.createButton({
1905
2096
  id: "deeplib-debug-button",
1906
- image: `${PUBLIC_URL}/dl_images/bug.svg`,
1907
2097
  onClick: /* @__PURE__ */ __name(() => {
1908
2098
  this.setSubscreen(new GuiDebug());
1909
2099
  }, "onClick"),
1910
- size: [90, 90]
2100
+ size: [90, 90],
2101
+ options: {
2102
+ image: `${PUBLIC_URL}/dl_images/bug.svg`
2103
+ }
1911
2104
  });
1912
2105
  if (menu) {
1913
2106
  ElementMenu.PrependItem(menu, debugButton);
@@ -1953,47 +2146,56 @@ var GuiImportExport = class extends BaseSubscreen {
1953
2146
  const importFromFileButton = advElement.createButton({
1954
2147
  id: "deeplib-import-file-button",
1955
2148
  size: [600, 90],
1956
- image: `${PUBLIC_URL}/dl_images/file_import.svg`,
1957
2149
  onClick: /* @__PURE__ */ __name(() => {
1958
2150
  this.dataImport("file");
1959
2151
  }, "onClick"),
1960
- label: getText("import-export.button.import_file")
2152
+ options: {
2153
+ image: `${PUBLIC_URL}/dl_images/file_import.svg`,
2154
+ label: getText("import-export.button.import_file")
2155
+ }
1961
2156
  });
1962
2157
  layout.appendToSettingsDiv(importFromFileButton);
1963
2158
  const exportToFileButton = advElement.createButton({
1964
2159
  id: "deeplib-export-file-button",
1965
2160
  size: [600, 90],
1966
- image: `${PUBLIC_URL}/dl_images/file_export.svg`,
1967
2161
  onClick: /* @__PURE__ */ __name(() => {
1968
2162
  this.dataExport("file");
1969
2163
  }, "onClick"),
1970
- label: getText("import-export.button.export_file")
2164
+ options: {
2165
+ image: `${PUBLIC_URL}/dl_images/file_export.svg`,
2166
+ label: getText("import-export.button.export_file")
2167
+ }
1971
2168
  });
1972
2169
  layout.appendToSettingsDiv(exportToFileButton);
1973
2170
  const importFromClipboardButton = advElement.createButton({
1974
2171
  id: "deeplib-import-clipboard-button",
1975
2172
  size: [600, 90],
1976
- image: `${PUBLIC_URL}/dl_images/clipboard_import.svg`,
1977
2173
  onClick: /* @__PURE__ */ __name(() => {
1978
2174
  this.dataImport("clipboard");
1979
2175
  }, "onClick"),
1980
- label: getText("import-export.button.import_clipboard")
2176
+ options: {
2177
+ image: `${PUBLIC_URL}/dl_images/clipboard_import.svg`,
2178
+ label: getText("import-export.button.import_clipboard")
2179
+ }
1981
2180
  });
1982
2181
  layout.appendToSettingsDiv(importFromClipboardButton);
1983
2182
  const exportToClipboardButton = advElement.createButton({
1984
2183
  id: "deeplib-export-clipboard-button",
1985
2184
  size: [600, 90],
1986
- image: `${PUBLIC_URL}/dl_images/clipboard_export.svg`,
1987
2185
  onClick: /* @__PURE__ */ __name(() => {
1988
2186
  this.dataExport("clipboard");
1989
2187
  }, "onClick"),
1990
- label: getText("import-export.button.export_clipboard")
2188
+ options: {
2189
+ image: `${PUBLIC_URL}/dl_images/clipboard_export.svg`,
2190
+ label: getText("import-export.button.export_clipboard")
2191
+ }
1991
2192
  });
1992
2193
  layout.appendToSettingsDiv(exportToClipboardButton);
1993
2194
  }
1994
2195
  resize() {
1995
2196
  super.resize();
1996
2197
  }
2198
+ /** Exports the mod data using the specified method. */
1997
2199
  async dataExport(transferMethod) {
1998
2200
  try {
1999
2201
  const data = LZString.compressToBase64(JSON.stringify(modStorage.playerStorage));
@@ -2009,6 +2211,7 @@ var GuiImportExport = class extends BaseSubscreen {
2009
2211
  deepLibLogger.error(`Data export failed for ${ModSdkManager.ModInfo.name}.`, error);
2010
2212
  }
2011
2213
  }
2214
+ /** Imports mod data using the specified method. */
2012
2215
  async dataImport(transferMethod) {
2013
2216
  try {
2014
2217
  let importedData = "";
@@ -2032,6 +2235,7 @@ var GuiImportExport = class extends BaseSubscreen {
2032
2235
  deepLibLogger.error(`Data import failed for ${ModSdkManager.ModInfo.name}.`, error);
2033
2236
  }
2034
2237
  }
2238
+ /** Saves data to a file using the browser's save dialog. */
2035
2239
  async exportToFile(data, defaultFileName) {
2036
2240
  const CUSTOM_EXTENSION = this.importExportOptions.customFileExtension.startsWith(".") ? this.importExportOptions.customFileExtension : "." + this.importExportOptions.customFileExtension;
2037
2241
  const suggestedName = defaultFileName.endsWith(CUSTOM_EXTENSION) ? defaultFileName : defaultFileName + CUSTOM_EXTENSION;
@@ -2071,6 +2275,7 @@ var GuiImportExport = class extends BaseSubscreen {
2071
2275
  URL.revokeObjectURL(link.href);
2072
2276
  }
2073
2277
  }
2278
+ /** Opens a file picker and reads the selected file's contents, importing the data. */
2074
2279
  async importFromFile() {
2075
2280
  const CUSTOM_EXTENSION = this.importExportOptions.customFileExtension.startsWith(".") ? this.importExportOptions.customFileExtension : "." + this.importExportOptions.customFileExtension;
2076
2281
  async function importFromFileInternal(file) {
@@ -2123,11 +2328,13 @@ var GuiImportExport = class extends BaseSubscreen {
2123
2328
  });
2124
2329
  }
2125
2330
  }
2331
+ /** Copies the given data to the clipboard. */
2126
2332
  async exportToClipboard(data) {
2127
2333
  return navigator.clipboard.writeText(data).catch((error) => {
2128
2334
  throw new Error("Failed to copy data to clipboard." + error);
2129
2335
  });
2130
2336
  }
2337
+ /** Prompts the user to enter data and returns it. */
2131
2338
  async importFromClipboard() {
2132
2339
  return Modal.prompt("Enter data to import").catch((error) => {
2133
2340
  throw new Error("Failed to read data from clipboard." + error);
@@ -2140,7 +2347,9 @@ var ModStorage = class _ModStorage {
2140
2347
  static {
2141
2348
  __name(this, "ModStorage");
2142
2349
  }
2350
+ /** Singleton instance of ModStorage */
2143
2351
  static _instance = null;
2352
+ /** The unique mod identifier used as key prefix in storage */
2144
2353
  modName;
2145
2354
  constructor(modName) {
2146
2355
  if (!_ModStorage._instance) {
@@ -2202,14 +2411,51 @@ var ModStorage = class _ModStorage {
2202
2411
  static dataCompress(object) {
2203
2412
  return LZString.compressToBase64(JSON.stringify(object));
2204
2413
  }
2414
+ static measureSize(data) {
2415
+ try {
2416
+ if (typeof data !== "string") {
2417
+ data = JSON.stringify(data) || "";
2418
+ }
2419
+ if (typeof data === "string") {
2420
+ return new TextEncoder().encode(data).byteLength;
2421
+ }
2422
+ throw new Error();
2423
+ } catch {
2424
+ return NaN;
2425
+ }
2426
+ }
2205
2427
  };
2206
2428
 
2207
2429
  // src/utilities/elements/helpers.ts
2208
2430
  var domUtil = {
2431
+ /**
2432
+ * Automatically sets the position of the element based on the given position.
2433
+ * The position can be either a [x, y] tuple or a function returning such a tuple.
2434
+ * If both x and y are defined, the element's position is updated accordingly.
2435
+ */
2209
2436
  autoSetPosition,
2437
+ /**
2438
+ * Automatically sets the size of the element based on the given size.
2439
+ * The size can be either a [width, height] tuple or a function returning such a tuple.
2440
+ * If both width and height are defined, the element's size is updated accordingly.
2441
+ */
2210
2442
  autoSetSize,
2443
+ /**
2444
+ * Hides the element by setting its CSS display property to 'none'.
2445
+ * If the element cannot be found, the function does nothing.
2446
+ */
2211
2447
  hide,
2448
+ /**
2449
+ * Unhides the element by clearing its CSS display property (sets it to '').
2450
+ * If the element cannot be found, the function does nothing.
2451
+ */
2212
2452
  unhide,
2453
+ /**
2454
+ * Checks if the element has overflow content.
2455
+ * Returns an object indicating if there is any overflow,
2456
+ * and specifically if there is vertical or horizontal overflow.
2457
+ * Returns null if the element is not found.
2458
+ */
2213
2459
  hasOverflow
2214
2460
  };
2215
2461
  function autoSetPosition(_, position) {
@@ -2487,10 +2733,12 @@ var ModSdkManager = class _ModSdkManager {
2487
2733
  static SDK;
2488
2734
  static patchedFunctions = /* @__PURE__ */ new Map();
2489
2735
  static ModInfo;
2736
+ /** Registers a mod with the SDK and stores mod information. */
2490
2737
  constructor(info, options) {
2491
2738
  _ModSdkManager.SDK = bcModSdkRef.registerMod(info, options);
2492
2739
  _ModSdkManager.ModInfo = info;
2493
2740
  }
2741
+ /** Retrieves or initializes patch data for a given target function. */
2494
2742
  initPatchableFunction(target) {
2495
2743
  let result = _ModSdkManager.patchedFunctions.get(target);
2496
2744
  if (!result) {
@@ -2502,6 +2750,11 @@ var ModSdkManager = class _ModSdkManager {
2502
2750
  }
2503
2751
  return result;
2504
2752
  }
2753
+ /**
2754
+ * Hooks a function with a callback at a given priority.
2755
+ *
2756
+ * Prevents duplicate hooks.
2757
+ */
2505
2758
  hookFunction(target, priority, hook, module = null) {
2506
2759
  const data = this.initPatchableFunction(target);
2507
2760
  if (data.hooks.some((h) => h.hook === hook)) {
@@ -2517,12 +2770,23 @@ var ModSdkManager = class _ModSdkManager {
2517
2770
  data.hooks.sort((a, b) => b.priority - a.priority);
2518
2771
  return removeCallback;
2519
2772
  }
2773
+ /**
2774
+ * Applies patches to a target function.
2775
+ *
2776
+ * **This method is DANGEROUS** to use and has high potential to conflict with other mods.
2777
+ */
2520
2778
  patchFunction(target, patches) {
2521
2779
  _ModSdkManager.SDK?.patchFunction(target, patches);
2522
2780
  }
2781
+ /**
2782
+ * Removes all patches from a target function.
2783
+ */
2523
2784
  unpatchFunction(target) {
2524
2785
  _ModSdkManager.SDK?.removePatches(target);
2525
2786
  }
2787
+ /**
2788
+ * Removes all hooks associated with a specific module from a target function.
2789
+ */
2526
2790
  removeHookByModule(target, module) {
2527
2791
  const data = this.initPatchableFunction(target);
2528
2792
  for (let i = data.hooks.length - 1; i >= 0; i--) {
@@ -2533,6 +2797,9 @@ var ModSdkManager = class _ModSdkManager {
2533
2797
  }
2534
2798
  return true;
2535
2799
  }
2800
+ /**
2801
+ * Removes all hooks associated with a specific module across all patched functions.
2802
+ */
2536
2803
  removeAllHooksByModule(module) {
2537
2804
  for (const data of _ModSdkManager.patchedFunctions.values()) {
2538
2805
  for (let i = data.hooks.length - 1; i >= 0; i--) {
@@ -2548,6 +2815,10 @@ var ModSdkManager = class _ModSdkManager {
2548
2815
 
2549
2816
  // src/utilities/style.ts
2550
2817
  var Style = {
2818
+ /**
2819
+ * Injects a CSS style block directly into the document head using a <style> tag.
2820
+ * If a style element with the same `styleId` already exists, it won't inject again.
2821
+ */
2551
2822
  injectInline(styleId, styleSource) {
2552
2823
  const isStyleLoaded = document.getElementById(styleId);
2553
2824
  if (isStyleLoaded) return;
@@ -2556,6 +2827,10 @@ var Style = {
2556
2827
  styleElement.appendChild(document.createTextNode(styleSource));
2557
2828
  document.head.appendChild(styleElement);
2558
2829
  },
2830
+ /**
2831
+ * Injects a CSS stylesheet link into the document head using a <link> tag.
2832
+ * If a link element with the same `styleId` already exists, it won't inject again.
2833
+ */
2559
2834
  injectEmbed(styleId, styleLink) {
2560
2835
  const isStyleLoaded = document.getElementById(styleId);
2561
2836
  if (isStyleLoaded) return;
@@ -2565,15 +2840,24 @@ var Style = {
2565
2840
  styleElement.href = styleLink;
2566
2841
  document.head.appendChild(styleElement);
2567
2842
  },
2843
+ /**
2844
+ * Removes a style element from the document head by its ID.
2845
+ * Does nothing if the element is not found.
2846
+ */
2568
2847
  eject(id) {
2569
2848
  const style = document.getElementById(id);
2570
2849
  if (!style) return;
2571
2850
  style.remove();
2572
2851
  },
2852
+ /**
2853
+ * Reloads an inline style by removing the existing style element (if any)
2854
+ * and injecting the new styles inline again.
2855
+ */
2573
2856
  reload(styleId, styleSource) {
2574
2857
  Style.eject(styleId);
2575
2858
  Style.injectInline(styleId, styleSource);
2576
2859
  },
2860
+ /** Fetches the text content of a stylesheet or any resource at the given link. */
2577
2861
  async fetch(link) {
2578
2862
  return fetch(link).then((res) => res.text());
2579
2863
  }
@@ -2589,7 +2873,9 @@ var Localization = class _Localization {
2589
2873
  static PathToModTranslation;
2590
2874
  static PathToLibTranslation = `${PUBLIC_URL}/dl_translations/`;
2591
2875
  static DefaultLanguage = "en";
2876
+ /** Flag to prevent re-initialization */
2592
2877
  static initialized = false;
2878
+ /** Initialize the localization system by loading translation files. */
2593
2879
  static async init(initOptions) {
2594
2880
  if (_Localization.initialized) return;
2595
2881
  _Localization.initialized = true;
@@ -2615,12 +2901,18 @@ var Localization = class _Localization {
2615
2901
  _Localization.ModTranslation = { ...fallbackTranslation, ...modTranslation };
2616
2902
  }
2617
2903
  }
2904
+ /** Get a translated string from mod translations by source tag. */
2618
2905
  static getTextMod(srcTag) {
2619
2906
  return _Localization.ModTranslation?.[srcTag] || void 0;
2620
2907
  }
2908
+ /** Get a translated string from library translations by source tag. */
2621
2909
  static getTextLib(srcTag) {
2622
2910
  return _Localization.LibTranslation?.[srcTag] || void 0;
2623
2911
  }
2912
+ /**
2913
+ * Fetch and parse a language file from the given base URL and language code.
2914
+ * Falls back to default language if the requested language file is unavailable.
2915
+ */
2624
2916
  static async fetchLanguageFile(baseUrl, lang) {
2625
2917
  const response = await fetch(`${baseUrl}${lang}.lang`);
2626
2918
  if (lang !== _Localization.DefaultLanguage && !response.ok) {
@@ -2632,6 +2924,10 @@ var Localization = class _Localization {
2632
2924
  const langFileContent = await response.text();
2633
2925
  return this.parseLanguageFile(langFileContent);
2634
2926
  }
2927
+ /**
2928
+ * Parse the raw content of a language file into a TranslationDict.
2929
+ * Ignores empty lines and comments starting with '#'.
2930
+ */
2635
2931
  static parseLanguageFile(content) {
2636
2932
  const translations = {};
2637
2933
  const lines = content.split("\n");
@@ -2647,10 +2943,71 @@ var Localization = class _Localization {
2647
2943
  var getText = /* @__PURE__ */ __name((srcTag) => {
2648
2944
  return Localization.getTextMod(srcTag) || Localization.getTextLib(srcTag) || srcTag;
2649
2945
  }, "getText");
2946
+
2947
+ // src/utilities/event_channel.ts
2948
+ var EventChannel = class {
2949
+ constructor(channelName) {
2950
+ this.channelName = channelName;
2951
+ ModSdkManager.prototype.hookFunction("ChatRoomMessageProcessHidden", 0, (args, next) => {
2952
+ if (!this.isChannelMessage(args[0])) {
2953
+ return next(args);
2954
+ }
2955
+ const [message, sender] = args;
2956
+ const { type, data } = message.Dictionary[0];
2957
+ const listeners = this.listeners[type];
2958
+ if (listeners) {
2959
+ listeners.forEach((listener) => listener(data, sender));
2960
+ }
2961
+ return next(args);
2962
+ }, `EventChannel-${channelName}`);
2963
+ }
2964
+ static {
2965
+ __name(this, "EventChannel");
2966
+ }
2967
+ listeners = {};
2968
+ unload() {
2969
+ Object.keys(this.listeners).forEach((key) => delete this.listeners[key]);
2970
+ ModSdkManager.prototype.removeHookByModule("ChatRoomMessageProcessHidden", `EventChannel-${this.channelName}`);
2971
+ }
2972
+ sendEvent(type, data, target = null) {
2973
+ const packet = {
2974
+ Type: "Hidden",
2975
+ Content: this.channelName,
2976
+ Sender: Player.MemberNumber,
2977
+ ...target ? { Target: target } : {},
2978
+ Dictionary: [
2979
+ {
2980
+ type,
2981
+ data
2982
+ }
2983
+ ]
2984
+ };
2985
+ ServerSend("ChatRoomChat", packet);
2986
+ }
2987
+ registerListener(event, listener) {
2988
+ const listeners = this.listeners[event] ?? [];
2989
+ listeners.push(listener);
2990
+ this.listeners[event] = listeners;
2991
+ return () => this.unregisterListener(event, listener);
2992
+ }
2993
+ unregisterListener(event, listener) {
2994
+ const listeners = this.listeners[event];
2995
+ if (listeners) {
2996
+ const index = listeners.indexOf(listener);
2997
+ if (index !== -1) {
2998
+ listeners.splice(index, 1);
2999
+ }
3000
+ }
3001
+ }
3002
+ isChannelMessage(message) {
3003
+ return message && message.Type === "Hidden" && message.Content === this.channelName && message.Sender && message.Sender !== Player.MemberNumber && message.Dictionary && !!message.Dictionary[0]?.data && !!message.Dictionary[0]?.type || false;
3004
+ }
3005
+ };
2650
3006
  export {
2651
3007
  BaseMigrator2 as BaseMigrator,
2652
3008
  BaseModule,
2653
3009
  BaseSubscreen,
3010
+ EventChannel,
2654
3011
  GUI,
2655
3012
  GuiDebug,
2656
3013
  GuiImportExport,
@@ -2664,6 +3021,7 @@ export {
2664
3021
  Style,
2665
3022
  VersionModule,
2666
3023
  advElement,
3024
+ byteToKB,
2667
3025
  deepLibLogger,
2668
3026
  deepMerge,
2669
3027
  deepMergeMatchingProperties,
@@ -2680,6 +3038,7 @@ export {
2680
3038
  modules,
2681
3039
  modulesMap,
2682
3040
  registerModule,
3041
+ sdk,
2683
3042
  sendActionMessage,
2684
3043
  sendLocalMessage,
2685
3044
  setSubscreen,