hotwire-native-dev-tools 0.1.0 → 0.3.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.
@@ -1,11 +1,4 @@
1
- var $ = Object.defineProperty;
2
- var L = (i) => {
3
- throw TypeError(i);
4
- };
5
- var I = (i, t, e) => t in i ? $(i, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : i[t] = e;
6
- var l = (i, t, e) => I(i, typeof t != "symbol" ? t + "" : t, e), F = (i, t, e) => t.has(i) || L("Cannot " + e);
7
- var b = (i, t, e) => (F(i, t, "read from private field"), e ? e.call(i) : t.get(i)), g = (i, t, e) => t.has(i) ? L("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(i) : t.set(i, e);
8
- const M = () => `
1
+ const E = () => `
9
2
  :host {
10
3
  all: initial;
11
4
  font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !important;
@@ -65,6 +58,13 @@ const M = () => `
65
58
  fill: white;
66
59
  }
67
60
 
61
+ .icon--black svg {
62
+ fill: black;
63
+ }
64
+ .icon--muted svg {
65
+ fill: #6c6c6c;
66
+ }
67
+
68
68
  /* Dropdown */
69
69
  .dropdown-content {
70
70
  display: none;
@@ -103,10 +103,20 @@ const M = () => `
103
103
  align-items: center;
104
104
  }
105
105
 
106
- .dropdown-content button:not(:first-child) {
106
+ .dropdown-content .dropdown-btn-full-width:not(:first-child),
107
+ .dropdown-content .dropdown-entry:not(:first-child) {
107
108
  border-top: 1px solid #cecdcd;
108
109
  }
109
110
 
111
+ .dropdown--right .dropdown-content {
112
+ right: 1em;
113
+ }
114
+
115
+ .dropdown--scrollable .dropdown-content {
116
+ overflow-y: auto;
117
+ max-height: 100%;
118
+ }
119
+
110
120
  .settings-dropdown {
111
121
  right: 0;
112
122
  top: 2rem;
@@ -223,6 +233,8 @@ const M = () => `
223
233
  }
224
234
 
225
235
  .bottom-sheet .content {
236
+ display: flex;
237
+ flex-direction: column;
226
238
  width: 100%;
227
239
  height: 40vh;
228
240
  position: relative;
@@ -336,8 +348,8 @@ const M = () => `
336
348
  height: 100%;
337
349
  overflow: scroll;
338
350
  background-color: hsl(0deg 0% 0% / 80%);
339
- backdrop-filter: blur(3px) saturate(100%);
340
- -webkit-backdrop-filter: blur(3px) saturate(100%);
351
+ backdrop-filter: blur(30px) saturate(250%);
352
+ -webkit-backdrop-filter: blur(30px) saturate(250%);
341
353
  padding-bottom: 7em;
342
354
  }
343
355
  .outer-tab-content.active {
@@ -352,6 +364,25 @@ const M = () => `
352
364
  white-space: normal;
353
365
  }
354
366
 
367
+ .info-card {
368
+ border-radius: 5px;
369
+ background: hsl(0deg 0% 0% / 20%);
370
+ padding: 1em;
371
+ margin-bottom: 1em;
372
+ }
373
+
374
+ .info-card-title {
375
+ font-size: 1em;
376
+ font-weight: 700;
377
+ margin-bottom: 1em;
378
+ display: flex;
379
+ justify-content: space-between;
380
+ }
381
+
382
+ .info-card-hint {
383
+ font-size: 0.8em;
384
+ }
385
+
355
386
  .tab-empty-content {
356
387
  display: flex;
357
388
  justify-content: center;
@@ -583,6 +614,10 @@ const M = () => `
583
614
  text-align: center;
584
615
  }
585
616
 
617
+ .text-muted {
618
+ color: #6c6c6c;
619
+ }
620
+
586
621
  .text-ellipsis {
587
622
  text-overflow: ellipsis;
588
623
  white-space: nowrap;
@@ -634,6 +669,10 @@ const M = () => `
634
669
  overflow: auto;
635
670
  }
636
671
 
672
+ .m-0 {
673
+ margin: 0;
674
+ }
675
+
637
676
  .mt-1 {
638
677
  margin-top: 0.25rem;
639
678
  }
@@ -682,73 +721,73 @@ const M = () => `
682
721
  width: 100%;
683
722
  }
684
723
 
724
+ .w-auto {
725
+ width: auto !important;
726
+ }
727
+
685
728
  .w-80 {
686
729
  width: 80%;
687
730
  }
688
731
  `;
689
- var m, u, v;
690
- class H {
732
+ class T {
691
733
  constructor() {
692
- l(this, "printWarning", (t, e = !0, ...o) => {
693
- e && this.printedWarnings.includes(t) || (console.warn(`DevTools: ${t}`, ...o), this.printedWarnings.push(t));
694
- });
695
- l(this, "checkForWarnings", () => {
696
- b(this, m).call(this), b(this, u).call(this), b(this, v).call(this);
697
- });
698
- g(this, m, () => {
699
- var t;
700
- window.Turbo ? ((t = window.Turbo) == null ? void 0 : t.session.drive) === !1 && setTimeout(() => {
701
- var e;
702
- ((e = window.Turbo) == null ? void 0 : e.session.drive) === !1 && this.printWarning("Turbo Drive is disabled. Hotwire Native will not work correctly without Turbo Drive");
703
- }, 1e3) : setTimeout(() => {
704
- window.Turbo || this.printWarning("Turbo is not detected. Hotwire Native will not work correctly without Turbo");
705
- }, 1e3);
706
- });
707
- g(this, u, () => {
708
- const t = this.turboFrameIds;
709
- t.filter((o, s) => t.indexOf(o) !== s).forEach((o) => {
710
- this.printWarning(`Multiple Turbo Frames with the same ID '${o}' detected. This can cause unexpected behavior. Ensure that each Turbo Frame has a unique ID.`);
711
- });
712
- });
713
- g(this, v, () => {
714
- const t = document.querySelectorAll("[data-turbo-permanent]");
715
- t.length !== 0 && t.forEach((e) => {
716
- const o = e.id;
717
- if (o === "" && this.printWarning("Turbo Permanent Element detected without an ID. Turbo Permanent Elements must have a unique ID to work correctly.", !0, e), o && document.querySelectorAll(`#${o}`).length > 1) {
718
- const n = `Turbo Permanent Element with ID '${o}' doesn't have a unique ID. Turbo Permanent Elements must have a unique ID to work correctly.`;
719
- this.printWarning(n, !0, e);
720
- }
721
- });
722
- });
723
734
  this.printedWarnings = [];
724
735
  }
736
+ printWarning = (t, e = !0, ...o) => {
737
+ e && this.printedWarnings.includes(t) || (console.warn(`DevTools: ${t}`, ...o), this.printedWarnings.push(t));
738
+ };
739
+ checkForWarnings = () => {
740
+ this.#t(), this.#e();
741
+ };
742
+ #t = () => {
743
+ const t = this.turboFrameIds;
744
+ t.filter((o, s) => t.indexOf(o) !== s).forEach((o) => {
745
+ this.printWarning(`Multiple Turbo Frames with the same ID '${o}' detected. This can cause unexpected behavior. Ensure that each Turbo Frame has a unique ID.`);
746
+ });
747
+ };
748
+ #e = () => {
749
+ const t = document.querySelectorAll("[data-turbo-permanent]");
750
+ t.length !== 0 && t.forEach((e) => {
751
+ const o = e.id;
752
+ if (o === "" && this.printWarning("Turbo Permanent Element detected without an ID. Turbo Permanent Elements must have a unique ID to work correctly.", !0, e), o && document.querySelectorAll(`#${o}`).length > 1) {
753
+ const n = `Turbo Permanent Element with ID '${o}' doesn't have a unique ID. Turbo Permanent Elements must have a unique ID to work correctly.`;
754
+ this.printWarning(n, !0, e);
755
+ }
756
+ });
757
+ };
725
758
  get turboFrameIds() {
726
759
  return Array.from(document.querySelectorAll("turbo-frame")).map((t) => t.id);
727
760
  }
728
761
  }
729
- m = new WeakMap(), u = new WeakMap(), v = new WeakMap();
730
- const c = (i) => JSON.parse(localStorage.getItem("hotwire-native-dev-tools") || "{}")[i], d = (i, t) => {
762
+ const a = (i) => JSON.parse(localStorage.getItem("hotwire-native-dev-tools") || "{}")[i], l = (i, t) => {
731
763
  let e = JSON.parse(localStorage.getItem("hotwire-native-dev-tools") || "{}");
732
764
  e[i] = t, localStorage.setItem("hotwire-native-dev-tools", JSON.stringify(e));
733
- }, q = () => {
765
+ }, B = () => {
734
766
  localStorage.removeItem("hotwire-native-dev-tools");
735
- }, y = () => c("consoleFilterLevels") || {
767
+ }, u = () => a("consoleFilterLevels") || {
736
768
  warn: !0,
737
769
  error: !0,
738
770
  debug: !0,
739
771
  info: !0,
740
772
  log: !0
741
- }, z = (i, t) => {
742
- const e = y();
743
- return e[i] = t, d("consoleFilterLevels", e), e;
744
- }, p = (i, t) => {
773
+ }, $ = (i, t) => {
774
+ const e = u();
775
+ return e[i] = t, l("consoleFilterLevels", e), e;
776
+ }, m = () => a("consoleLogBlacklist") || [], I = (i) => {
777
+ i = i.trim();
778
+ const t = a("consoleLogBlacklist") || [];
779
+ return t.includes(i) || (t.push(i), l("consoleLogBlacklist", t)), t;
780
+ }, F = (i) => {
781
+ let t = a("consoleLogBlacklist") || [];
782
+ return t = t.filter((e) => e !== i), l("consoleLogBlacklist", t), t;
783
+ }, h = (i, t) => {
745
784
  let e = null;
746
785
  return (...o) => {
747
786
  const s = () => i.apply(void 0, o);
748
787
  clearTimeout(e), e = setTimeout(s, t);
749
788
  };
750
- }, { userAgent: E } = window.navigator, A = /iOS/.test(E), N = /Android/.test(E), S = () => A ? "ios" : N ? "android" : "unknown", D = () => {
751
- switch (S()) {
789
+ }, { userAgent: S } = window.navigator, k = /iOS/.test(S), q = /Android/.test(S), f = () => k ? "ios" : q ? "android" : "unknown", A = () => {
790
+ switch (f()) {
752
791
  case "android":
753
792
  return "Android";
754
793
  case "ios":
@@ -756,7 +795,10 @@ const c = (i) => JSON.parse(localStorage.getItem("hotwire-native-dev-tools") ||
756
795
  default:
757
796
  return "<unknown>";
758
797
  }
759
- }, P = `
798
+ }, M = (i) => document.querySelector(`meta[name="${i}"]`), v = (i) => {
799
+ const t = M(i);
800
+ return t && t.content;
801
+ }, H = `
760
802
  <svg width="100%" height="100%" viewBox="0 0 294 320">
761
803
  <g transform="matrix(1,0,0,1,-28.38,-15.268)">
762
804
  <g transform="matrix(1,0,0,1,-462.157,-144.417)">
@@ -764,95 +806,76 @@ const c = (i) => JSON.parse(localStorage.getItem("hotwire-native-dev-tools") ||
764
806
  </g>
765
807
  </g>
766
808
  </svg>
767
- `, R = `
809
+ `, z = `
768
810
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
769
811
  <!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
770
812
  <path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM385 215c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-71-71L280 392c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-214.1-71 71c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9L239 103c9.4-9.4 24.6-9.4 33.9 0L385 215z"/>
771
813
  </svg>
772
- `, j = `
814
+ `, N = `
773
815
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
774
816
  <!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
775
817
  <path d="M256 0a256 256 0 1 0 0 512A256 256 0 1 0 256 0zM127 297c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l71 71L232 120c0-13.3 10.7-24 24-24s24 10.7 24 24l0 214.1 71-71c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9L273 409c-9.4 9.4-24.6 9.4-33.9 0L127 297z"/>
776
818
  </svg>
777
- `, C = `
819
+ `, b = `
778
820
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
779
821
  <!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
780
822
  <path d="M9.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l160 160c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.2 288 416 288c17.7 0 32-14.3 32-32s-14.3-32-32-32l-306.7 0L214.6 118.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-160 160z"/>
781
823
  </svg>
782
- `, f = `
824
+ `, p = `
783
825
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
784
826
  <!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
785
827
  <path d="M135.2 17.7L128 32 32 32C14.3 32 0 46.3 0 64S14.3 96 32 96l384 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-96 0-7.2-14.3C307.4 6.8 296.3 0 284.2 0L163.8 0c-12.1 0-23.2 6.8-28.6 17.7zM416 128L32 128 53.2 467c1.6 25.3 22.6 45 47.9 45l245.8 0c25.3 0 46.3-19.7 47.9-45L416 128z"/>
786
828
  </svg>
787
- `, O = `
829
+ `, P = `
788
830
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
789
831
  <!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
790
832
  <path d="M142.9 142.9c-17.5 17.5-30.1 38-37.8 59.8c-5.9 16.7-24.2 25.4-40.8 19.5s-25.4-24.2-19.5-40.8C55.6 150.7 73.2 122 97.6 97.6c87.2-87.2 228.3-87.5 315.8-1L455 55c6.9-6.9 17.2-8.9 26.2-5.2s14.8 12.5 14.8 22.2l0 128c0 13.3-10.7 24-24 24l-8.4 0c0 0 0 0 0 0L344 224c-9.7 0-18.5-5.8-22.2-14.8s-1.7-19.3 5.2-26.2l41.1-41.1c-62.6-61.5-163.1-61.2-225.3 1zM16 312c0-13.3 10.7-24 24-24l7.6 0 .7 0L168 288c9.7 0 18.5 5.8 22.2 14.8s1.7 19.3-5.2 26.2l-41.1 41.1c62.6 61.5 163.1 61.2 225.3-1c17.5-17.5 30.1-38 37.8-59.8c5.9-16.7 24.2-25.4 40.8-19.5s25.4 24.2 19.5 40.8c-10.8 30.6-28.4 59.3-52.9 83.8c-87.2 87.2-228.3 87.5-315.8 1L57 457c-6.9 6.9-17.2 8.9-26.2 5.2S16 449.7 16 440l0-119.6 0-.7 0-7.6z"/>
791
833
  </svg>
792
- `, V = `
834
+ `, D = `
793
835
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
794
836
  <!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
795
837
  <path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM169.8 165.3c7.9-22.3 29.1-37.3 52.8-37.3l58.3 0c34.9 0 63.1 28.3 63.1 63.1c0 22.6-12.1 43.5-31.7 54.8L280 264.4c-.2 13-10.9 23.6-24 23.6c-13.3 0-24-10.7-24-24l0-13.5c0-8.6 4.6-16.5 12.1-20.8l44.3-25.4c4.7-2.7 7.6-7.7 7.6-13.1c0-8.4-6.8-15.1-15.1-15.1l-58.3 0c-3.4 0-6.4 2.1-7.5 5.3l-.4 1.2c-4.4 12.5-18.2 19-30.6 14.6s-19-18.2-14.6-30.6l.4-1.2zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"/>
796
838
  </svg>
797
- `, Y = `
839
+ `, O = `
798
840
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
799
841
  <!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
800
842
  <path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z"/>
801
843
  </svg>
802
- `, W = `
844
+ `, j = `
803
845
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
804
846
  <!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
805
847
  <path d="M3.9 54.9C10.5 40.9 24.5 32 40 32l432 0c15.5 0 29.5 8.9 36.1 22.9s4.6 30.5-5.2 42.5L320 320.9 320 448c0 12.1-6.8 23.2-17.7 28.6s-23.8 4.3-33.5-3l-64-48c-8.1-6-12.8-15.5-12.8-25.6l0-79.1L9 97.3C-.7 85.4-2.8 68.8 3.9 54.9z"/>
806
848
  </svg>
807
- `, X = `
849
+ `, y = `
808
850
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 512">
809
851
  <!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
810
852
  <path d="M64 360a56 56 0 1 0 0 112 56 56 0 1 0 0-112zm0-160a56 56 0 1 0 0 112 56 56 0 1 0 0-112zM120 96A56 56 0 1 0 8 96a56 56 0 1 0 112 0z"/>
811
853
  </svg>
854
+ `, R = `
855
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640">
856
+ <!--!Font Awesome Free 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
857
+ <path d="M431.2 476.5L163.5 208.8C141.1 240.2 128 278.6 128 320C128 426 214 512 320 512C361.5 512 399.9 498.9 431.2 476.5zM476.5 431.2C498.9 399.8 512 361.4 512 320C512 214 426 128 320 128C278.5 128 240.1 141.1 208.8 163.5L476.5 431.2zM64 320C64 178.6 178.6 64 320 64C461.4 64 576 178.6 576 320C576 461.4 461.4 576 320 576C178.6 576 64 461.4 64 320z"/>
858
+ </svg>
812
859
  `;
813
- class U {
860
+ class V {
814
861
  constructor(t) {
815
- l(this, "render", p(() => {
816
- this.setPosition(), this.createDragItem(), this.setTranslate(this.initialX, this.initialY, this.dragItem), this.addEventListeners();
817
- }, 50));
818
- l(this, "animateErrorBorder", p(() => {
819
- if (!this.dragItem || c("errorAnimationEnabled") === !1) return;
820
- let t = this.dragItem.querySelector(".error-border"), e = this.dragItem.querySelector(".error-border circle");
821
- t && t.remove();
822
- const o = document.createElement("div");
823
- o.className = "animation-container", o.innerHTML = `
824
- <svg viewBox="0 0 180 180" xmlns="http://www.w3.org/2000/svg" class="error-border">
825
- <defs>
826
- <linearGradient id="errorGradient" gradientTransform="rotate(45)">
827
- <stop offset="0%" stop-color="#e4241a" />
828
- <stop offset="50%" stop-color="#dd1f15" />
829
- <stop offset="100%" stop-color="#f6160a" />
830
- </linearGradient>
831
- </defs>
832
- <circle cx="90" cy="90" r="90" fill="none" stroke="url(#errorGradient)" stroke-width="21"
833
- stroke-dasharray="565" stroke-dashoffset="565" stroke-linecap="round" />
834
- </svg>
835
- `, this.dragItem.appendChild(o), e = this.dragItem.querySelector(".error-border circle"), e.classList.add("animate"), setTimeout(() => {
836
- o.classList.add("fade-out");
837
- }, 1300), setTimeout(() => {
838
- o && o.parentNode && o.remove();
839
- }, 1800);
840
- }, 100));
841
862
  this.devTools = t, this.bubbleSize = 4.75 * 16 + 0.3 * 16, this.minVisible = this.bubbleSize * 0.5, this.currentlyDragging = !1;
842
863
  }
864
+ render = h(() => {
865
+ this.setPosition(), this.createDragItem(), this.setTranslate(this.initialX, this.initialY, this.dragItem), this.addEventListeners();
866
+ }, 50);
843
867
  setPosition() {
844
868
  this.settingKey = window.innerWidth < window.innerHeight ? "bubblePosPortrait" : "bubblePosLandscape";
845
- const t = { x: window.innerWidth - 100, y: window.innerHeight - 100 }, { x: e, y: o } = c(this.settingKey) || t;
869
+ const t = { x: window.innerWidth - 100, y: window.innerHeight - 100 }, { x: e, y: o } = a(this.settingKey) || t;
846
870
  this.currentX = this.initialX = this.xOffset = e, this.currentY = this.initialY = this.yOffset = o;
847
871
  }
848
872
  createDragItem() {
849
- var e;
850
- const t = (e = this.devTools.shadowRoot) == null ? void 0 : e.getElementById("floating-bubble");
873
+ const t = this.devTools.shadowRoot?.getElementById("floating-bubble");
851
874
  if (t) {
852
875
  this.dragItem = t;
853
876
  return;
854
877
  }
855
- this.dragItem = document.createElement("div"), this.dragItem.id = "floating-bubble", this.dragItem.innerHTML = P, this.devTools.shadowRoot.appendChild(this.dragItem);
878
+ this.dragItem = document.createElement("div"), this.dragItem.id = "floating-bubble", this.dragItem.innerHTML = H, this.devTools.shadowRoot.appendChild(this.dragItem);
856
879
  }
857
880
  addEventListeners() {
858
881
  this.dragItem.hasEventListeners || (this.dragItem.addEventListener("click", this.click.bind(this), { passive: !0 }), this.dragItem.addEventListener("touchstart", this.dragStart.bind(this), { passive: !0 }), this.dragItem.addEventListener("touchend", this.dragEnd.bind(this), { passive: !0 }), this.dragItem.addEventListener("touchmove", this.drag.bind(this), { passive: !0 }), this.dragItem.hasEventListeners = !0);
@@ -860,6 +883,29 @@ class U {
860
883
  click(t) {
861
884
  this.clickCallback && this.clickCallback(t);
862
885
  }
886
+ animateErrorBorder = h(() => {
887
+ if (!this.dragItem || a("errorAnimationEnabled") === !1) return;
888
+ let t = this.dragItem.querySelector(".error-border"), e = this.dragItem.querySelector(".error-border circle");
889
+ t && t.remove();
890
+ const o = document.createElement("div");
891
+ o.className = "animation-container", o.innerHTML = `
892
+ <svg viewBox="0 0 180 180" xmlns="http://www.w3.org/2000/svg" class="error-border">
893
+ <defs>
894
+ <linearGradient id="errorGradient" gradientTransform="rotate(45)">
895
+ <stop offset="0%" stop-color="#e4241a" />
896
+ <stop offset="50%" stop-color="#dd1f15" />
897
+ <stop offset="100%" stop-color="#f6160a" />
898
+ </linearGradient>
899
+ </defs>
900
+ <circle cx="90" cy="90" r="90" fill="none" stroke="url(#errorGradient)" stroke-width="21"
901
+ stroke-dasharray="565" stroke-dashoffset="565" stroke-linecap="round" />
902
+ </svg>
903
+ `, this.dragItem.appendChild(o), e = this.dragItem.querySelector(".error-border circle"), e.classList.add("animate"), setTimeout(() => {
904
+ o.classList.add("fade-out");
905
+ }, 1300), setTimeout(() => {
906
+ o && o.parentNode && o.remove();
907
+ }, 1800);
908
+ }, 100);
863
909
  onClick(t) {
864
910
  this.clickCallback = t;
865
911
  }
@@ -867,7 +913,7 @@ class U {
867
913
  t.target.closest("#floating-bubble") && (this.currentlyDragging = !0, this.initialX = t.touches[0].clientX - this.xOffset, this.initialY = t.touches[0].clientY - this.yOffset);
868
914
  }
869
915
  dragEnd() {
870
- this.initialX = this.currentX, this.initialY = this.currentY, this.currentlyDragging = !1, d(this.settingKey, { x: this.currentX, y: this.currentY });
916
+ this.initialX = this.currentX, this.initialY = this.currentY, this.currentlyDragging = !1, l(this.settingKey, { x: this.currentX, y: this.currentY });
871
917
  }
872
918
  drag(t) {
873
919
  if (!this.currentlyDragging) return;
@@ -880,32 +926,43 @@ class U {
880
926
  o.style.transform = `translate3d(${t}px, ${e}px, 0)`;
881
927
  }
882
928
  }
883
- class J {
929
+ class Y {
884
930
  constructor(t) {
885
- l(this, "handleTabClick", (t) => {
886
- const e = t.target.closest(".tablink");
887
- if (!e) return;
888
- const o = e.dataset.tabId;
889
- this.devTools.state.setActiveTab(o), this.updateTabView(o);
890
- });
891
- this.devTools = t, this.state = t.state.state, this.sheetHeight = parseInt(c("bottomSheetHeight")) || 55;
931
+ this.devTools = t, this.state = t.state.state, this.sheetHeight = parseInt(a("bottomSheetHeight")) || 55;
892
932
  }
893
933
  render() {
894
934
  this.createBottomSheet(), this.sheetContent = this.bottomSheet.querySelector(".content"), this.sheetOverlay = this.bottomSheet.querySelector(".sheet-overlay"), this.addEventListeners();
895
935
  }
936
+ // Called when the in-memory state changes,
937
+ // such as when a new console or bridge log is captured.
896
938
  update(t) {
897
- this.state = t, this.checkNativeFeatures(), this.renderConsoleLogs(), this.renderBridgeComponents(), this.renderBridgeLogs(), this.renderEvents(), this.renderNativeStack();
939
+ this.state = t, this.checkNativeFeatures(), this.renderConsoleLogs(), this.renderBridgeComponents(), this.renderBridgeLogs(), this.renderEvents(), this.renderNativeStack(), this.scrollToLatestLog(this.state.activeTab), this.state.shouldScrollToLatestLog = !0;
940
+ }
941
+ // Called when another native tab of the mobile app
942
+ // updates devtools-related local storage.
943
+ applySettingsFromStorage() {
944
+ [
945
+ { key: "bottomSheetHeight", setter: (o) => this.updateSheetHeight(o) },
946
+ { key: "activeTab", setter: (o) => this.updateTabView(o) },
947
+ { key: "fontSize", setter: (o) => this.updateFontSize(o) },
948
+ { key: "errorAnimationEnabled", setter: (o) => this.updateErrorAnimation(o) },
949
+ { key: "autoOpen", setter: (o) => this.updateAutoOpen(o) }
950
+ ].forEach(({ key: o, setter: s }) => {
951
+ const n = a(o);
952
+ n !== void 0 && s(n);
953
+ });
954
+ const e = u();
955
+ e && this.updateConsoleFilter(e);
898
956
  }
899
957
  createBottomSheet() {
900
- var n;
901
- const t = (n = this.devTools.shadowRoot) == null ? void 0 : n.querySelector(".bottom-sheet");
958
+ const t = this.devTools.shadowRoot?.querySelector(".bottom-sheet");
902
959
  if (t) {
903
960
  this.bottomSheet = t;
904
961
  return;
905
962
  }
906
- const e = this.state.activeTab, o = y(), s = this.state.consoleSearch;
963
+ const e = this.state.activeTab, o = u(), s = this.state.consoleSearch;
907
964
  this.bottomSheet = document.createElement("div"), this.bottomSheet.classList.add("bottom-sheet"), this.bottomSheet.innerHTML = `
908
- <div class="sheet-overlay ${c("bottomSheetPinned") === !0 ? "" : "active"}"></div>
965
+ <div class="sheet-overlay ${a("bottomSheetPinned") === !0 ? "" : "active"}"></div>
909
966
  <div class="content">
910
967
  <div class="top-part">
911
968
  <div class="tablist">
@@ -914,23 +971,25 @@ class J {
914
971
  <button class="tablink ${e === "tab-event-logs" ? "active" : ""}" data-tab-id="tab-event-logs">Events</button>
915
972
  <button class="tablink ${e === "tab-native-stack" ? "active" : ""} d-none" data-tab-id="tab-native-stack">Stack</button>
916
973
  <div class="tablink-settings dropdown d-flex">
917
- <button class="dropdown-trigger tablink-dropdown">${X}</button>
974
+ <button class="dropdown-trigger tablink-dropdown">${y}</button>
918
975
  <div class="dropdown-content settings-dropdown">
919
- <button class="btn-switch-to-single-tab-sheet" data-tab-id="single-tab-settings">Settings</button>
920
- <button class="pin-bottom-sheet">Pin Bottom Sheet</button>
976
+ <button class="dropdown-btn-full-width btn-switch-to-single-tab-sheet" data-tab-id="single-tab-settings">Settings</button>
977
+ <button class="dropdown-btn-full-width btn-switch-to-single-tab-sheet" data-tab-id="single-tab-info">Info</button>
978
+ <button class="dropdown-btn-full-width btn-switch-to-single-tab-sheet d-none" data-tab-id="single-tab-path-configuration-check">PathConfiguration Check</button>
979
+ <button class="dropdown-btn-full-width pin-bottom-sheet">Pin Bottom Sheet</button>
921
980
  </div>
922
981
  </div>
923
982
  </div>
924
983
 
925
984
  <div class="tab-action-bars">
926
985
  <div class="tab-action-bar tab-bridge-components ${e === "tab-bridge-components" ? "active" : ""}">
927
- <button class="btn-icon btn-clear-tab btn-clear-bridge-logs">${f}</button>
986
+ <button class="btn-icon btn-clear-tab btn-clear-bridge-logs">${p}</button>
928
987
  </div>
929
988
  <div class="tab-action-bar d-flex flex-column tab-console-logs ${e === "tab-console-logs" ? "active" : ""}">
930
989
  <div class="d-flex">
931
- <button class="btn-icon btn-search-console">${Y}</button>
990
+ <button class="btn-icon btn-search-console">${O}</button>
932
991
  <div class="dropdown">
933
- <button class="dropdown-trigger btn-icon">${W}</button>
992
+ <button class="dropdown-trigger btn-icon">${j}</button>
934
993
  <div class="dropdown-content console-filter-levels">
935
994
  <label><input type="checkbox" ${o.warn ? "checked" : ""} data-console-filter="warn" /> Warnings</label>
936
995
  <label><input type="checkbox" ${o.error ? "checked" : ""} data-console-filter="error" /> Errors</label>
@@ -939,7 +998,12 @@ class J {
939
998
  <label><input type="checkbox" ${o.log ? "checked" : ""} data-console-filter="log" /> Logs</label>
940
999
  </div>
941
1000
  </div>
942
- <button class="btn-icon btn-clear-tab btn-clear-console-logs">${f}</button>
1001
+ <div class="dropdown dropdown--scrollable">
1002
+ <button class="dropdown-trigger btn-icon">${R}</button>
1003
+ <div class="dropdown-content console-log-blacklist">
1004
+ </div>
1005
+ </div>
1006
+ <button class="btn-icon btn-clear-tab btn-clear-console-logs">${p}</button>
943
1007
  </div>
944
1008
 
945
1009
  <div class="console-search mt-2 ${s ? "" : "d-none"}">
@@ -947,10 +1011,10 @@ class J {
947
1011
  </div>
948
1012
  </div>
949
1013
  <div class="tab-action-bar tab-event-logs ${e === "tab-event-logs" ? "active" : ""}">
950
- <button class="btn-icon btn-clear-tab btn-clear-events">${f}</button>
1014
+ <button class="btn-icon btn-clear-tab btn-clear-events">${p}</button>
951
1015
  </div>
952
1016
  <div class="tab-action-bar tab-native-stack ${e === "tab-native-stack" ? "active" : ""}">
953
- <button class="btn-icon btn-reload-tab btn-reload-stack">${O}</button>
1017
+ <button class="btn-icon btn-reload-tab btn-reload-stack">${P}</button>
954
1018
  </div>
955
1019
  </div>
956
1020
  </div>
@@ -964,7 +1028,7 @@ class J {
964
1028
  <div id="bridge-components-collapse" class="collapse-target">
965
1029
  <div class="d-flex justify-content-between border-bottom">
966
1030
  <div class="tab-content-bridge-components flex-grow-1"></div>
967
- <button class="btn-icon btn-help btn-switch-to-single-tab-sheet mt-1" data-tab-id="single-tab-bridge-component-help">${V}</button>
1031
+ <button class="btn-icon btn-help btn-switch-to-single-tab-sheet mt-1" data-tab-id="single-tab-bridge-component-help">${D}</button>
968
1032
  </div>
969
1033
  </div>
970
1034
 
@@ -991,10 +1055,10 @@ class J {
991
1055
  <div id="single-tab-bridge-component-help" class="single-tab-content outer-tab-content">
992
1056
  <div class="inner-tab-content">
993
1057
  <div class="d-flex align-items-center mb-3">
994
- <button class="btn-icon btn-close-single-mode">${C}</button>
1058
+ <button class="btn-icon btn-close-single-mode">${b}</button>
995
1059
  <h3 class="ms-1">Bridge Components</h3>
996
1060
  </div>
997
- <p>This list shows all the bridge components that the ${D()} app supports. Components that are active on this page are marked with a green dot.</p>
1061
+ <p>This list shows all the bridge components that the ${A()} app supports. Components that are active on this page are marked with a green dot.</p>
998
1062
  <h3 class="mt-4">Why is my bridge component not on the list?</h3>
999
1063
  <p class="mt-2">Bridge components are automatically detected when they are registered in the native code. If your component is not on the list, make sure it is registered correctly.</p>
1000
1064
  ${this.registerBridgeComponentExample()}
@@ -1006,7 +1070,7 @@ class J {
1006
1070
  <div id="single-tab-settings" class="single-tab-content outer-tab-content">
1007
1071
  <div class="inner-tab-content">
1008
1072
  <div class="d-flex align-items-center mb-3">
1009
- <button class="btn-icon btn-close-single-mode">${C}</button>
1073
+ <button class="btn-icon btn-close-single-mode">${b}</button>
1010
1074
  <h3 class="ms-1">Settings</h3>
1011
1075
  </div>
1012
1076
  <div class="mb-3">
@@ -1018,25 +1082,80 @@ class J {
1018
1082
  </div>
1019
1083
  <div class="mb-4">
1020
1084
  <label for="font-size-setting"> Font Size</label>
1021
- <input type="range" id="font-size-setting" class="w-100" min="8" max="24" value="${c("fontSize") || 16}" step="1" list="font-size-setting-markers" />
1085
+ <input type="range" id="font-size-setting" class="w-100" min="8" max="24" value="${a("fontSize") || 16}" step="1" list="font-size-setting-markers" />
1022
1086
  <datalist id="font-size-setting-markers">
1023
1087
  <option value="16"></option>
1024
1088
  </datalist>
1025
1089
  </div>
1026
1090
  <div class="mb-3">
1027
1091
  <label class="toggle">
1028
- <input class="toggle-checkbox" type="checkbox" id="console-error-animation-setting" ${c("errorAnimationEnabled") !== !1 ? "checked" : ""} />
1092
+ <input class="toggle-checkbox" type="checkbox" id="console-error-animation-setting" ${a("errorAnimationEnabled") !== !1 ? "checked" : ""} />
1029
1093
  <div class="toggle-switch"></div>
1030
1094
  <span class="toggle-label">Console Error Animation</span>
1031
1095
  </label>
1032
1096
  </div>
1033
1097
  <div class="mb-3">
1034
1098
  <label class="toggle">
1035
- <input class="toggle-checkbox" type="checkbox" id="auto-open-setting" ${c("autoOpen") === !0 ? "checked" : ""} />
1099
+ <input class="toggle-checkbox" type="checkbox" id="auto-open-setting" ${a("autoOpen") === !0 ? "checked" : ""} />
1036
1100
  <div class="toggle-switch"></div>
1037
1101
  <span class="toggle-label">Auto Open</span>
1038
1102
  </label>
1039
1103
  </div>
1104
+ <div class="mb-3">
1105
+ <label class="toggle">
1106
+ <input class="toggle-checkbox" type="checkbox" id="scroll-to-latest-log-setting" ${a("scrollToLatestLog") === !0 ? "checked" : ""} />
1107
+ <div class="toggle-switch"></div>
1108
+ <span class="toggle-label">Automatically Scroll to New Logs</span>
1109
+ </label>
1110
+ </div>
1111
+ </div>
1112
+ </div>
1113
+
1114
+ <div id="single-tab-path-configuration-check" class="single-tab-content outer-tab-content">
1115
+ <div class="inner-tab-content">
1116
+ <div class="d-flex align-items-center mb-3">
1117
+ <button class="btn-icon btn-close-single-mode">${b}</button>
1118
+ <h3 class="ms-1">PathConfiguration Check</h3>
1119
+ </div>
1120
+ <div class="mb-3">
1121
+ <label for="path-configuration-check-url">URL</label>
1122
+ <input id="path-configuration-check-url" class="w-100" value="/" />
1123
+ </div>
1124
+ <div id="path-configuration-check-properties-output" class="overflow-auto">
1125
+ </div>
1126
+ </div>
1127
+ </div>
1128
+
1129
+ <div id="single-tab-info" class="single-tab-content outer-tab-content">
1130
+ <div class="inner-tab-content">
1131
+ <div class="d-flex align-items-center mb-3">
1132
+ <button class="btn-icon btn-close-single-mode">${b}</button>
1133
+ <h3 class="ms-1">Info</h3>
1134
+ </div>
1135
+ <div class="info-card">
1136
+ <div class="info-card-title">Current URL</div>
1137
+ <div class="current-url">${this.currentUrl}</div>
1138
+ </div>
1139
+ <div class="info-card">
1140
+ <div class="info-card-title">User Agent</div>
1141
+ <div class="user-agent">${navigator.userAgent}</div>
1142
+ </div>
1143
+ <div class="info-card">
1144
+ <div class="info-card-title"><pre class="m-0">turbo-cache-control:</pre> <span>${v("turbo-cache-control") || "-"}</span></div>
1145
+ <div class="info-card-hint"><strong>no-cache:</strong> always fetched from the network, even on restore</div>
1146
+ <div class="info-card-hint"><strong>no-preview:</strong> skipped in preview, used only on restore</div>
1147
+ <div class="info-card-hint"><strong>unset:</strong> shows cached preview if the cache is valid</div>
1148
+ </div>
1149
+ <div class="info-card">
1150
+ <div class="info-card-title"><pre class="m-0">turbo-refresh-method:</pre> <span>${v("turbo-refresh-method") || "-"}</span></div>
1151
+ <div class="info-card-hint"><strong>replace (default):</strong> replaces the entire &lt;body&gt; on revisit</div>
1152
+ <div class="info-card-hint"><strong>morph:</strong> updates only changed DOM elements, preserving state</div>
1153
+ </div>
1154
+ <div class="info-card">
1155
+ <div class="info-card-title"><pre class="m-0">turbo-visit-control:</pre> <span>${v("turbo-visit-control") || "-"}</span></div>
1156
+ <div class="info-card-hint"><strong>reload:</strong> forces a full page reload</div>
1157
+ <div class="info-card-hint"><strong>unset:</strong> allows Turbo to handle the visit normally</div>
1158
+ </div>
1040
1159
  </div>
1041
1160
  </div>
1042
1161
  </div>
@@ -1044,8 +1163,19 @@ class J {
1044
1163
  `, this.devTools.shadowRoot.appendChild(this.bottomSheet);
1045
1164
  }
1046
1165
  renderConsoleLogs() {
1047
- const t = this.bottomSheet.querySelector(".tab-content-console-logs"), e = y(), o = this.state.consoleSearch;
1048
- t.innerHTML = this.state.consoleLogs.length ? this.state.consoleLogs.filter((s) => e[s.type]).filter((s) => o ? s.message.toLowerCase().includes(o.toLowerCase()) : !0).map((s) => this.consoleLogHTML(s.type, s.message, s.time)).join("") : '<div class="tab-empty-content"><span>No console logs yet</span></div>';
1166
+ const t = this.bottomSheet.querySelector(".tab-content-console-logs"), e = u(), o = m(), s = this.state.consoleSearch;
1167
+ t.innerHTML = this.state.consoleLogs.length ? this.state.consoleLogs.filter((n) => e[n.type]).filter((n) => s ? n.message.toLowerCase().includes(s.toLowerCase()) : !0).filter((n) => !o.includes(n.message.trim())).map((n) => this.consoleLogHTML(n.type, n.message, n.time)).join("") : '<div class="tab-empty-content"><span>No console logs yet</span></div>', this.renderConsoleBlacklist();
1168
+ }
1169
+ renderConsoleBlacklist() {
1170
+ this.bottomSheet.querySelector(".console-log-blacklist").innerHTML = m().length ? `
1171
+ ${m().map(
1172
+ (t) => `
1173
+ <div class="d-flex justify-content-between align-items-center dropdown-entry">
1174
+ <label class="console-log-blacklist-entry-text">${t}</label>
1175
+ <button class="btn-icon btn-remove-console-log-blacklist-entry icon--muted dropdown-content-action w-auto" data-entry="${t}">${p}</button>
1176
+ </div>
1177
+ `
1178
+ ).join("")}` : '<div class="text-center text-muted">No blacklisted logs</div>';
1049
1179
  }
1050
1180
  renderBridgeComponents() {
1051
1181
  const t = this.state.supportedBridgeComponents.length;
@@ -1065,11 +1195,26 @@ class J {
1065
1195
  const t = this.bottomSheet.querySelector(".tab-content-native-stack");
1066
1196
  t.innerHTML = '<div class="native-stack-wrapper">' + (this.state.nativeStack.length ? this.state.nativeStack.map((e) => this.nativeViewStackHTML(e)).join("") : '<div class="tab-empty-content"><span>No native stack captured yet</span></div>') + "</div>";
1067
1197
  }
1198
+ renderPathConfigurationCheck = h((t) => {
1199
+ const e = k ? t : `${window.location.origin}${t}`;
1200
+ this.devTools.nativeBridge.send("propertiesForUrl", { url: e }, (o) => {
1201
+ this.bottomSheet.querySelector("#path-configuration-check-properties-output").style.opacity = 1;
1202
+ const s = (() => {
1203
+ try {
1204
+ const c = o.data.properties;
1205
+ return JSON.stringify(typeof c == "string" ? JSON.parse(c) : c, null, 2);
1206
+ } catch {
1207
+ return o.data.properties;
1208
+ }
1209
+ })(), n = s ? `<pre class="view-path-configuration">${s}</pre>` : "", r = this.bottomSheet.querySelector("#path-configuration-check-properties-output");
1210
+ r.innerHTML = n;
1211
+ });
1212
+ }, 500);
1068
1213
  bridgeLogHTML(t, e, o, s, n) {
1069
1214
  return `
1070
1215
  <div class="log-entry d-flex gap-3 pt-2 pb-2">
1071
1216
  <div class="log-entry-icon d-flex justify-content-center align-items-center">
1072
- ${t === "send" ? j : R}
1217
+ ${t === "send" ? N : z}
1073
1218
  </div>
1074
1219
  <div class="w-100 overflow-auto">
1075
1220
  <div class="d-flex justify-content-between">
@@ -1077,9 +1222,9 @@ class J {
1077
1222
  <small>${n}</small>
1078
1223
  </div>
1079
1224
  <div class="overflow-auto">
1080
- ${Object.entries(s).map(([r, a]) => {
1081
- const w = typeof a == "object" && a !== null ? JSON.stringify(a) : a;
1082
- return `<div class="white-space-collapse">${r}: ${w}</div>`;
1225
+ ${Object.entries(s).map(([r, c]) => {
1226
+ const g = typeof c == "object" && c !== null ? JSON.stringify(c) : c;
1227
+ return `<div class="white-space-collapse">${r}: ${g}</div>`;
1083
1228
  }).join("")}
1084
1229
  </div>
1085
1230
  </div>
@@ -1093,8 +1238,17 @@ class J {
1093
1238
  <div class="d-flex justify-content-end">
1094
1239
  <small>${o}</small>
1095
1240
  </div>
1096
- <div class="log-entry-message ${t}">
1097
- ${e}
1241
+ <div class="d-flex justify-content-between">
1242
+ <div class="log-entry-message ${t}">
1243
+ ${e}
1244
+ </div>
1245
+ <div class="dropdown dropdown--right">
1246
+ <button class="dropdown-trigger btn-icon">${y}</button>
1247
+ <div class="dropdown-content">
1248
+ <button class="dropdown-btn-full-width dropdown-content-action console-log-action-hide-console-log">Ignore this log</button>
1249
+ <button class="dropdown-btn-full-width dropdown-content-action console-log-action-copy-console-log">Copy log message</button>
1250
+ </div>
1251
+ </div>
1098
1252
  </div>
1099
1253
  </div>
1100
1254
  </div>
@@ -1115,8 +1269,7 @@ class J {
1115
1269
  `;
1116
1270
  }
1117
1271
  nativeViewStackHTML(t) {
1118
- var x;
1119
- const e = ["UINavigationController", "NavigatorHost"].includes(t.type), o = t.type === "UITabBarController", s = ["VisitableViewController", "HotwireWebFragment", "BackStackEntry"].includes(t.type), r = `viewstack-card ${t.url === this.currentUrl ? "current-view" : ""} ${e ? "main-view" : s ? "hotwire-view" : o ? "tab-container" : "non-identified-view"}`, a = "viewstack-" + Math.random().toString(16).slice(2), w = t.url ? `<div class="view-url">
1272
+ const e = (d) => d?.replace(/\/+$/, ""), o = ["UINavigationController", "NavigatorHost"].includes(t.type), s = t.type === "UITabBarController", n = ["VisitableViewController", "HotwireWebFragment", "BackStackEntry"].includes(t.type), c = `viewstack-card ${e(t.url) === e(this.currentUrl) ? "current-view" : ""} ${o ? "main-view" : n ? "hotwire-view" : s ? "tab-container" : "non-identified-view"}`, g = "viewstack-" + Math.random().toString(16).slice(2), L = t.url ? `<div class="view-url">
1120
1273
  ${(() => {
1121
1274
  try {
1122
1275
  return new URL(t.url).pathname;
@@ -1124,31 +1277,31 @@ class J {
1124
1277
  return t.url;
1125
1278
  }
1126
1279
  })()}
1127
- </div>` : "", k = (() => {
1280
+ </div>` : "", w = (() => {
1128
1281
  try {
1129
- const h = t.pathConfigurationProperties;
1130
- return JSON.stringify(typeof h == "string" ? JSON.parse(h) : h, null, 2);
1282
+ const d = t.pathConfigurationProperties;
1283
+ return JSON.stringify(typeof d == "string" ? JSON.parse(d) : d, null, 2);
1131
1284
  } catch {
1132
1285
  return t.pathConfigurationProperties;
1133
1286
  }
1134
- })(), T = k ? `<pre class="view-path-configuration">${k}</pre>` : "", B = (x = t.children) != null && x.length ? `<div class="child-container">
1135
- ${t.children.map((h) => this.nativeViewStackHTML(h)).join("")}
1287
+ })(), x = w ? `<pre class="view-path-configuration">${w}</pre>` : "", C = t.children?.length ? `<div class="child-container">
1288
+ ${t.children.map((d) => this.nativeViewStackHTML(d)).join("")}
1136
1289
  </div>` : "";
1137
1290
  return `
1138
1291
  <div>
1139
- <div class="${r} collapse no-chevron" data-collapse-target="path-configuration-properties-${a}">
1292
+ <div class="${c} collapse no-chevron" data-collapse-target="path-configuration-properties-${g}">
1140
1293
  <div>
1141
1294
  <div class="view-title">
1142
1295
  ${t.title == "null" ? "" : t.title}
1143
1296
  <div class="view-title-details">${t.type}</div>
1144
1297
  </div>
1145
- ${w}
1298
+ ${L}
1146
1299
  </div>
1147
- <div id="path-configuration-properties-${a}" class="collapse-target">
1148
- ${T}
1300
+ <div id="path-configuration-properties-${g}" class="collapse-target">
1301
+ ${x}
1149
1302
  </div>
1150
1303
  </div>
1151
- ${B}
1304
+ ${C}
1152
1305
  </div>
1153
1306
  `;
1154
1307
  }
@@ -1161,7 +1314,7 @@ class J {
1161
1314
  });
1162
1315
  }
1163
1316
  registerBridgeComponentExample() {
1164
- switch (S()) {
1317
+ switch (f()) {
1165
1318
  case "android":
1166
1319
  return `
1167
1320
  <pre class="overflow-auto">
@@ -1182,7 +1335,7 @@ class J {
1182
1335
  }
1183
1336
  }
1184
1337
  registerBridgeComponentHelpURL() {
1185
- switch (S()) {
1338
+ switch (f()) {
1186
1339
  case "android":
1187
1340
  return "https://native.hotwired.dev/android/bridge-components";
1188
1341
  case "ios":
@@ -1192,7 +1345,7 @@ class J {
1192
1345
  }
1193
1346
  }
1194
1347
  checkNativeFeatures() {
1195
- this.state.supportsNativeStackView && this.bottomSheet.querySelector(".tablink[data-tab-id='tab-native-stack']").classList.remove("d-none");
1348
+ this.state.supportsNativeStackView && (this.bottomSheet.querySelector(".tablink[data-tab-id='tab-native-stack']").classList.remove("d-none"), this.bottomSheet.querySelector(".btn-switch-to-single-tab-sheet[data-tab-id='single-tab-path-configuration-check']").classList.remove("d-none"));
1196
1349
  }
1197
1350
  addEventListeners() {
1198
1351
  this.bottomSheet.hasEventListeners || (this.sheetOverlay.addEventListener("click", () => {
@@ -1208,7 +1361,7 @@ class J {
1208
1361
  }), this.bottomSheet.querySelectorAll(".btn-switch-to-single-tab-sheet").forEach((t) => {
1209
1362
  t.addEventListener("click", (e) => {
1210
1363
  const o = e.target.closest("[data-tab-id]").dataset.tabId;
1211
- o && this.switchToSingleTabSheet(o);
1364
+ o && (o === "single-tab-path-configuration-check" && this.bottomSheet.querySelector("#path-configuration-check-url").value === "/" && this.renderPathConfigurationCheck("/"), this.switchToSingleTabSheet(o));
1212
1365
  });
1213
1366
  }), this.bottomSheet.querySelectorAll(".btn-close-single-mode").forEach((t) => {
1214
1367
  t.addEventListener("click", () => {
@@ -1218,7 +1371,7 @@ class J {
1218
1371
  const e = t.closest("input[type='checkbox']");
1219
1372
  if (!e) return;
1220
1373
  const o = e.dataset.consoleFilter, s = e.checked;
1221
- z(o, s), this.renderConsoleLogs();
1374
+ $(o, s), this.renderConsoleLogs();
1222
1375
  }), this.bottomSheet.querySelector(".btn-search-console").addEventListener("click", () => {
1223
1376
  const t = this.bottomSheet.querySelector(".console-search");
1224
1377
  t.classList.toggle("d-none"), t.querySelector("input").focus();
@@ -1226,24 +1379,28 @@ class J {
1226
1379
  this.devTools.state.setConsoleSearchValue(t.target.value.toLowerCase()), this.renderConsoleLogs();
1227
1380
  }), this.bottomSheet.querySelector("#bottom-sheet-height-setting").addEventListener("change", (t) => {
1228
1381
  const e = t.target.value;
1229
- this.sheetHeight = parseInt(e), d("bottomSheetHeight", e), this.updateSheetHeight(e);
1382
+ this.sheetHeight = parseInt(e), l("bottomSheetHeight", e), this.updateSheetHeight(e);
1230
1383
  }), this.bottomSheet.querySelector("#console-error-animation-setting").addEventListener("change", (t) => {
1231
- d("errorAnimationEnabled", t.target.checked);
1384
+ l("errorAnimationEnabled", t.target.checked);
1232
1385
  }), this.bottomSheet.querySelector("#font-size-setting").addEventListener("change", (t) => {
1233
1386
  let e = t.target.value;
1234
- e = Math.max(8, Math.min(24, e)), d("fontSize", e), this.devTools.setCSSProperty("--font-size", `${e}px`);
1387
+ e = Math.max(8, Math.min(24, e)), l("fontSize", e), this.devTools.setCSSProperty("--font-size", `${e}px`);
1235
1388
  }), this.bottomSheet.querySelector("#auto-open-setting").addEventListener("change", (t) => {
1236
- d("autoOpen", t.target.checked);
1389
+ l("autoOpen", t.target.checked);
1390
+ }), this.bottomSheet.querySelector("#scroll-to-latest-log-setting").addEventListener("change", (t) => {
1391
+ l("scrollToLatestLog", t.target.checked);
1237
1392
  }), this.bottomSheet.querySelector(".pin-bottom-sheet").addEventListener("click", () => {
1238
- const t = c("bottomSheetPinned") === !0;
1239
- d("bottomSheetPinned", !t), this.sheetOverlay.classList.toggle("active"), this.bottomSheet.querySelector(".settings-dropdown").classList.remove("dropdown-open");
1393
+ const t = a("bottomSheetPinned") === !0;
1394
+ l("bottomSheetPinned", !t), this.sheetOverlay.classList.toggle("active"), this.bottomSheet.querySelector(".settings-dropdown").classList.remove("dropdown-open");
1395
+ }), this.bottomSheet.querySelector("#path-configuration-check-url").addEventListener("input", (t) => {
1396
+ this.bottomSheet.querySelector("#path-configuration-check-properties-output").style.opacity = 0.5, this.renderPathConfigurationCheck(t.target.value);
1240
1397
  }), this.bottomSheet.addEventListener("click", (t) => {
1241
1398
  const e = t.target.closest(".collapse");
1242
1399
  if (e && this.bottomSheet.contains(e)) {
1243
1400
  const n = e.getAttribute("data-collapse-target"), r = this.bottomSheet.querySelector(`#${n}`);
1244
1401
  if (r) {
1245
- const a = e.classList.toggle("active");
1246
- r.classList.toggle("active", a);
1402
+ const c = e.classList.toggle("active");
1403
+ r.classList.toggle("active", c);
1247
1404
  }
1248
1405
  return;
1249
1406
  }
@@ -1252,26 +1409,59 @@ class J {
1252
1409
  t.preventDefault(), this.toggleDropdown(o);
1253
1410
  return;
1254
1411
  }
1255
- this.bottomSheet.querySelectorAll(".dropdown-content.dropdown-open").forEach((n) => {
1256
- n.closest(".dropdown").contains(t.target) || n.classList.remove("dropdown-open");
1257
- });
1412
+ if (t.target.closest(".dropdown-content-action")) {
1413
+ this.handleDropdownActionClick(t);
1414
+ return;
1415
+ }
1416
+ this.closeAllDropdowns(t);
1258
1417
  }), this.bottomSheet.hasEventListeners = !0);
1259
1418
  }
1419
+ closeAllDropdowns(t) {
1420
+ this.bottomSheet.querySelectorAll(".dropdown-content.dropdown-open").forEach((o) => {
1421
+ o.closest(".dropdown").contains(t.target) || o.classList.remove("dropdown-open");
1422
+ });
1423
+ }
1424
+ updateConsoleFilter(t) {
1425
+ this.bottomSheet.querySelectorAll(".console-filter-levels input[type='checkbox']").forEach((e) => {
1426
+ const o = e.dataset.consoleFilter, s = t[o];
1427
+ e.checked = s;
1428
+ });
1429
+ }
1260
1430
  toggleDropdown(t) {
1261
1431
  const e = t.nextElementSibling || t.closest(".dropdown").querySelector(".dropdown-content");
1262
1432
  this.bottomSheet.querySelectorAll(".dropdown-content.dropdown-open").forEach((o) => {
1263
1433
  o !== e && o.classList.remove("dropdown-open");
1264
1434
  }), e.classList.toggle("dropdown-open");
1265
1435
  }
1436
+ handleTabClick = (t) => {
1437
+ const e = t.target.closest(".tablink");
1438
+ if (!e) return;
1439
+ const o = e.dataset.tabId;
1440
+ this.devTools.state.setActiveTab(o), this.updateTabView(o);
1441
+ };
1442
+ handleDropdownActionClick = (t) => {
1443
+ const e = t.target.closest(".dropdown-content-action");
1444
+ if (e)
1445
+ if (e.classList.contains("console-log-action-hide-console-log"))
1446
+ I(e.closest(".log-entry").querySelector(".log-entry-message").textContent), this.renderConsoleLogs();
1447
+ else if (e.classList.contains("console-log-action-copy-console-log")) {
1448
+ const s = e.closest(".log-entry").querySelector(".log-entry-message").textContent;
1449
+ navigator.clipboard.writeText(s).then(() => {
1450
+ this.closeAllDropdowns(t);
1451
+ });
1452
+ } else e.classList.contains("btn-remove-console-log-blacklist-entry") && (F(e.dataset.entry.trim()), this.renderConsoleLogs());
1453
+ };
1266
1454
  updateTabView(t) {
1267
- this.devTools.shadowRoot.querySelectorAll(".tablink, .outer-tab-content").forEach((e) => e.classList.remove("active")), this.devTools.shadowRoot.querySelectorAll(".tab-action-bar").forEach((e) => e.classList.remove("active")), this.devTools.shadowRoot.querySelector(`[data-tab-id="${t}"]`).classList.add("active"), this.devTools.shadowRoot.getElementById(t).classList.add("active"), this.devTools.shadowRoot.querySelector(`.tab-action-bar.${t}`).classList.add("active");
1455
+ this.devTools.shadowRoot.querySelectorAll(".tablink, .outer-tab-content").forEach((e) => e.classList.remove("active")), this.devTools.shadowRoot.querySelectorAll(".tab-action-bar").forEach((e) => e.classList.remove("active")), this.devTools.shadowRoot.querySelector(`[data-tab-id="${t}"]`).classList.add("active"), this.devTools.shadowRoot.getElementById(t).classList.add("active"), this.devTools.shadowRoot.querySelector(`.tab-action-bar.${t}`).classList.add("active"), this.state.shouldScrollToLatestLog && (this.scrollToLatestLog(t), this.state.shouldScrollToLatestLog = !1);
1456
+ }
1457
+ scrollToLatestLog(t) {
1458
+ a("scrollToLatestLog") == !0 && requestAnimationFrame(() => {
1459
+ this.devTools.shadowRoot.getElementById(t)?.querySelector(".log-entry:last-child")?.scrollIntoView({ behavior: "instant", block: "center" });
1460
+ });
1268
1461
  }
1269
1462
  showBottomSheet() {
1270
1463
  this.bottomSheet.classList.contains("show") || (this.bottomSheet.classList.add("show"), this.originalOverflow = document.body.style.overflow, document.body.style.overflow = "hidden", this.updateSheetHeight(this.sheetHeight));
1271
1464
  }
1272
- updateSheetHeight(t) {
1273
- this.sheetContent.style.height = `${t}vh`;
1274
- }
1275
1465
  hideBottomSheet() {
1276
1466
  this.bottomSheet.classList.remove("show"), document.body.style.overflow = this.originalOverflow;
1277
1467
  }
@@ -1279,13 +1469,11 @@ class J {
1279
1469
  this.sheetContent.style.height = `${t}vh`, this.bottomSheet.classList.toggle("fullscreen", t === 100);
1280
1470
  }
1281
1471
  dragStart(t) {
1282
- var e;
1283
- this.isDragging = !0, this.startY = t.pageY || ((e = t.touches) == null ? void 0 : e[0].pageY), this.startHeight = parseInt(this.sheetContent.style.height), this.bottomSheet.classList.add("dragging");
1472
+ this.isDragging = !0, this.startY = t.pageY || t.touches?.[0].pageY, this.startHeight = parseInt(this.sheetContent.style.height), this.bottomSheet.classList.add("dragging");
1284
1473
  }
1285
1474
  dragging(t) {
1286
- var s;
1287
1475
  if (!this.isDragging) return;
1288
- const e = this.startY - (t.pageY || ((s = t.touches) == null ? void 0 : s[0].pageY)), o = this.startHeight + e / window.innerHeight * 100;
1476
+ const e = this.startY - (t.pageY || t.touches?.[0].pageY), o = this.startHeight + e / window.innerHeight * 100;
1289
1477
  this.updateSheetHeight(o);
1290
1478
  }
1291
1479
  dragStop() {
@@ -1293,6 +1481,15 @@ class J {
1293
1481
  const t = 10, e = parseInt(this.sheetContent.style.height), o = Math.max(0, this.sheetHeight - t), s = Math.min(100, this.sheetHeight + t);
1294
1482
  e < o ? this.hideBottomSheet() : e > s ? this.updateSheetHeight(100) : this.updateSheetHeight(this.sheetHeight);
1295
1483
  }
1484
+ updateFontSize(t) {
1485
+ this.devTools.setCSSProperty("--font-size", `${t}px`), this.bottomSheet.querySelector("#font-size-setting").value = t;
1486
+ }
1487
+ updateErrorAnimation(t) {
1488
+ this.bottomSheet.querySelector("#console-error-animation-setting").checked = t;
1489
+ }
1490
+ updateAutoOpen(t) {
1491
+ this.bottomSheet.querySelector("#auto-open-setting").checked = t;
1492
+ }
1296
1493
  // Helper function to log messages, without causing a rerender of the bottom sheet
1297
1494
  // (Messages with a `HotwireDevTools` prefix will not be logged in the bottom sheet)
1298
1495
  log(t) {
@@ -1300,14 +1497,13 @@ class J {
1300
1497
  }
1301
1498
  // Get all the `static component = "..."` from the bridge components
1302
1499
  get bridgeComponentIdentifiers() {
1303
- var t;
1304
- return ((t = window.Stimulus) == null ? void 0 : t.controllers.map((e) => e.component).filter((e) => e !== void 0)) || [];
1500
+ return window.Stimulus?.controllers.map((t) => t.component).filter((t) => t !== void 0) || [];
1305
1501
  }
1306
1502
  get currentUrl() {
1307
1503
  return window.location.href;
1308
1504
  }
1309
1505
  }
1310
- class G {
1506
+ class U {
1311
1507
  constructor() {
1312
1508
  this.state = {
1313
1509
  consoleLogs: [],
@@ -1318,7 +1514,7 @@ class G {
1318
1514
  bridgeIsConnected: !1,
1319
1515
  supportsNativeStackView: !1,
1320
1516
  consoleSearch: "",
1321
- activeTab: c("activeTab") || "tab-bridge-components"
1517
+ activeTab: this.storedActiveTab
1322
1518
  }, this.listeners = [];
1323
1519
  }
1324
1520
  subscribe(t) {
@@ -1361,19 +1557,24 @@ class G {
1361
1557
  this.state.eventLogs = [], this.notify();
1362
1558
  }
1363
1559
  setActiveTab(t) {
1364
- this.state.activeTab = t, d("activeTab", t);
1560
+ this.state.activeTab = t, l("activeTab", t);
1365
1561
  }
1366
1562
  setConsoleSearchValue(t) {
1367
1563
  this.state.consoleSearch = t;
1368
1564
  }
1565
+ updateLocalStorageSettings() {
1566
+ this.state.activeTab = this.storedActiveTab;
1567
+ }
1369
1568
  get currentTime() {
1370
1569
  return (/* @__PURE__ */ new Date()).toLocaleTimeString();
1371
1570
  }
1571
+ get storedActiveTab() {
1572
+ return a("activeTab") || "tab-bridge-components";
1573
+ }
1372
1574
  }
1373
- class K {
1575
+ class W {
1374
1576
  bridgeIsConnected() {
1375
- var t, e;
1376
- return !!((t = window.HotwireNative) != null && t.web || (e = window.Strada) != null && e.web);
1577
+ return !!(window.HotwireNative?.web || window.Strada?.web);
1377
1578
  }
1378
1579
  // Send a message to the native side
1379
1580
  send(t, e = {}, o = null) {
@@ -1396,38 +1597,19 @@ class K {
1396
1597
  return this.bridgeIsConnected() ? this.bridge.supportsComponent(t) : !1;
1397
1598
  }
1398
1599
  getSupportedComponents() {
1399
- var t;
1400
- return ((t = document.documentElement.dataset.bridgeComponents) == null ? void 0 : t.split(" ")) || [];
1600
+ return document.documentElement.dataset.bridgeComponents?.split(" ") || [];
1401
1601
  }
1402
1602
  get bridge() {
1403
- var t, e;
1404
- return ((t = window.HotwireNative) == null ? void 0 : t.web) || ((e = window.Strada) == null ? void 0 : e.web);
1603
+ return window.HotwireNative?.web || window.Strada?.web;
1405
1604
  }
1406
1605
  }
1407
- class Z {
1606
+ class X {
1408
1607
  constructor(t = {}) {
1409
- l(this, "update", p((t) => {
1410
- this.bottomSheet.update(t);
1411
- }, 200));
1412
- // Fetch the current stack from the native side
1413
- // The debounce on this function is intentionally high,
1414
- // to ensure the native side has enough time to set the ViewController / Fragment titles.
1415
- // With a lower debounce, the view controller / fragment title would often be empty.
1416
- l(this, "fetchNativeStack", p(() => {
1417
- this.nativeBridge.send("currentStackInfo", {}, (t) => {
1418
- this.state.setSupportsNativeStack(!0), this.state.setNativeStack(t.data.stack);
1419
- });
1420
- }, 1e3));
1421
- l(this, "injectCSSToShadowRoot", async () => {
1422
- if (this.shadowRoot.querySelector("style")) return;
1423
- const t = document.createElement("style");
1424
- t.textContent = M(), this.shadowRoot.appendChild(t);
1425
- });
1426
1608
  this.options = {
1427
1609
  enabled: !0,
1428
1610
  reset: !1,
1429
1611
  ...t
1430
- }, this.options.enabled && (this.options.reset && q(), this.state = new G(), this.bubble = new U(this), this.bottomSheet = new J(this), this.nativeBridge = new K(this), this.diagnosticsChecker = new H(), this.state.subscribe(this.update.bind(this)), this.listenForTurboEvents());
1612
+ }, this.options.enabled && (this.options.reset && B(), this.state = new U(), this.bubble = new V(this), this.bottomSheet = new Y(this), this.nativeBridge = new W(this), this.diagnosticsChecker = new T(), this.state.subscribe(this.update.bind(this)), this.listenForTurboEvents());
1431
1613
  }
1432
1614
  // Setup gets called initially and on every turbo:load event, eg. when navigating to a new page
1433
1615
  setup() {
@@ -1435,23 +1617,25 @@ class Z {
1435
1617
  this.nativeBridgeGotConnected();
1436
1618
  }), this.addEventListeners(), this.diagnosticsChecker.checkForWarnings(), this.bubble.onClick(() => {
1437
1619
  this.bottomSheet.showBottomSheet(), this.nativeBridge.send("vibrate");
1438
- }), c("autoOpen") === !0 && this.bottomSheet.showBottomSheet());
1620
+ }), a("autoOpen") === !0 && this.bottomSheet.showBottomSheet());
1439
1621
  }
1440
1622
  nativeBridgeGotConnected() {
1441
- var t, e;
1442
- this.originalBridge || (this.originalBridge = ((t = window.HotwireNative) == null ? void 0 : t.web) || ((e = window.Strada) == null ? void 0 : e.web), this.addBridgeProxy(), this.state.setBridgeIsConnected(!0), this.callNativeBridgeComponent(), this.updateSupportedBridgeComponents(), this.startBridgeComponentObserver());
1623
+ this.originalBridge || (this.originalBridge = window.HotwireNative?.web || window.Strada?.web, this.addBridgeProxy(), this.state.setBridgeIsConnected(!0), this.callNativeBridgeComponent(), this.updateSupportedBridgeComponents(), this.startBridgeComponentObserver());
1443
1624
  }
1444
1625
  callNativeBridgeComponent() {
1445
1626
  this.nativeBridge.bridgeIsConnected() && this.nativeBridge.send("connect", {}, (t) => {
1446
1627
  this.fetchNativeStack();
1447
1628
  });
1448
1629
  }
1630
+ update = h((t) => {
1631
+ this.bottomSheet.update(t);
1632
+ }, 200);
1449
1633
  setupShadowRoot() {
1450
1634
  if (this.shadowContainer.shadowRoot) {
1451
1635
  this.shadowRoot = this.shadowContainer.shadowRoot, this.injectCSSToShadowRoot();
1452
1636
  return;
1453
1637
  }
1454
- this.shadowRoot = this.shadowContainer.attachShadow({ mode: "open" }), this.setCSSProperty("--font-size", `${c("fontSize") || 16}px`), this.injectCSSToShadowRoot();
1638
+ this.shadowRoot = this.shadowContainer.attachShadow({ mode: "open" }), this.setCSSProperty("--font-size", `${a("fontSize") || 16}px`), this.injectCSSToShadowRoot();
1455
1639
  }
1456
1640
  addBridgeProxy() {
1457
1641
  const t = () => ({
@@ -1466,20 +1650,20 @@ class Z {
1466
1650
  window.console = new Proxy(this.originalConsole, {
1467
1651
  get: (t, e, o) => {
1468
1652
  const s = Reflect.get(t, e, o);
1469
- return (...n) => (this.interceptedConsoleMessage(e, n), s == null ? void 0 : s.apply(t, n));
1653
+ return (...n) => (this.interceptedConsoleMessage(e, n), s?.apply(t, n));
1470
1654
  }
1471
1655
  });
1472
1656
  }
1473
1657
  interceptedBridgeMessage(t, e) {
1474
1658
  e.forEach((o) => {
1475
- const s = o.component, n = o.event, { metadata: r, ...a } = o.data;
1476
- s !== "dev-tools" && this.state.addBridgeLog(t, s, n, a);
1659
+ const s = o.component, n = o.event, { metadata: r, ...c } = o.data;
1660
+ s !== "dev-tools" && this.state.addBridgeLog(t, s, n, c);
1477
1661
  });
1478
1662
  }
1479
1663
  interceptedConsoleMessage(t, e) {
1480
1664
  const o = e.map((s) => {
1481
1665
  if (s instanceof Element) {
1482
- const r = Array.from(s.attributes).map((a) => `${a.name}="${a.value}"`).join(" ");
1666
+ const r = Array.from(s.attributes).map((c) => `${c.name}="${c.value}"`).join(" ");
1483
1667
  return `&lt;${s.tagName.toLowerCase()}${r ? " " + r : ""}&gt;&lt;/${s.tagName.toLowerCase()}&gt;`;
1484
1668
  }
1485
1669
  if (typeof s == "object")
@@ -1490,27 +1674,42 @@ class Z {
1490
1674
  }
1491
1675
  return s.toString().replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
1492
1676
  }).join(" ");
1493
- o.includes("hotwire-native-dev-tools") || o.includes("HotwireDevTools") || (this.state.addConsoleLog(t, o), t === "error" && this.bubble.animateErrorBorder());
1677
+ o.includes("hotwire-native-dev-tools") || o.includes("HotwireDevTools") || (this.state.addConsoleLog(t, o), t === "error" && (m().includes(o) || this.bubble.animateErrorBorder()));
1494
1678
  }
1679
+ // Fetch the current stack from the native side
1680
+ // The debounce on this function is intentionally high,
1681
+ // to ensure the native side has enough time to set the ViewController / Fragment titles.
1682
+ // With a lower debounce, the view controller / fragment title would often be empty.
1683
+ fetchNativeStack = h(() => {
1684
+ this.nativeBridge.send("currentStackInfo", {}, (t) => {
1685
+ this.state.setSupportsNativeStack(!0), this.state.setNativeStack(t.data.stack);
1686
+ });
1687
+ }, 1e3);
1495
1688
  refetchNativeStack() {
1496
1689
  this.nativeBridge.send("currentStackInfo", {}, (t) => {
1497
1690
  this.state.setNativeStack(t.data.stack);
1498
1691
  });
1499
1692
  }
1693
+ injectCSSToShadowRoot = async () => {
1694
+ if (this.shadowRoot.querySelector("style")) return;
1695
+ const t = document.createElement("style");
1696
+ t.textContent = E(), this.shadowRoot.appendChild(t);
1697
+ };
1500
1698
  addEventListeners() {
1501
1699
  this.hasEventListeners || (window.addEventListener("error", (t) => {
1502
1700
  const { message: e, filename: o, lineno: s, colno: n } = t, r = `${e} at ${o}:${s}:${n}`;
1503
1701
  this.interceptedConsoleMessage("error", [r]);
1504
1702
  }), window.addEventListener("unhandledrejection", (t) => {
1505
- var e;
1506
- this.interceptedConsoleMessage("error", [(e = t.reason) == null ? void 0 : e.message]);
1703
+ this.interceptedConsoleMessage("error", [t.reason?.message]);
1507
1704
  }), window.addEventListener(
1508
1705
  "resize",
1509
1706
  () => {
1510
1707
  this.bubble.render();
1511
1708
  },
1512
1709
  { passive: !0 }
1513
- ), this.hasEventListeners = !0);
1710
+ ), window.addEventListener("storage", (t) => {
1711
+ t.key === "hotwire-native-dev-tools" && (this.state.updateLocalStorageSettings(), this.bubble.render(), this.bottomSheet.update(this.state.state), this.bottomSheet.applySettingsFromStorage());
1712
+ }), this.hasEventListeners = !0);
1514
1713
  }
1515
1714
  listenForTurboEvents() {
1516
1715
  if (this.eventsRegistered) return;
@@ -1576,8 +1775,8 @@ class Z {
1576
1775
  return (/* @__PURE__ */ new Date()).toLocaleTimeString();
1577
1776
  }
1578
1777
  }
1579
- const _ = (i = {}) => {
1580
- const t = new Z(i);
1778
+ const J = (i = {}) => {
1779
+ const t = new X(i);
1581
1780
  t.options.enabled && (t.setup(), document.addEventListener(
1582
1781
  "turbo:load",
1583
1782
  () => {
@@ -1587,6 +1786,6 @@ const _ = (i = {}) => {
1587
1786
  ));
1588
1787
  };
1589
1788
  export {
1590
- _ as setupDevTools
1789
+ J as setupDevTools
1591
1790
  };
1592
1791
  //# sourceMappingURL=hotwire-native-dev-tools.es.js.map