@bereasoftware/nexa 1.5.0 → 1.7.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/nexa.es.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! Nexa v1.5.0 | (c) 2026 Berea-Soft | MIT License | https://github.com/Berea-Soft/Nexa */
1
+ /*! Nexa v1.7.0 | (c) 2026 Berea-Soft | MIT License | https://github.com/Berea-Soft/Nexa */
2
2
  //#region src/types/index.ts
3
3
  var e = (e) => ({
4
4
  ok: !0,
@@ -1499,7 +1499,9 @@ var q = class {
1499
1499
  devOnly: e.devOnly ?? !0,
1500
1500
  floatingButtonSize: e.floatingButtonSize ?? 48,
1501
1501
  floatingButtonOffset: e.floatingButtonOffset ?? 24,
1502
- floatingButtonTheme: e.floatingButtonTheme ?? "inherit"
1502
+ floatingButtonTheme: e.floatingButtonTheme ?? "inherit",
1503
+ branding: e.branding ?? "Nexa DevTools",
1504
+ icon: e.icon ?? "https://raw.githubusercontent.com/Berea-Soft/nexa/refs/heads/main/src/assets/faviconNew.png"
1503
1505
  };
1504
1506
  }
1505
1507
  track(e) {
@@ -1560,7 +1562,9 @@ var q = class {
1560
1562
  clear: "<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 6h18M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2\"/></svg>",
1561
1563
  search: "<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"11\" cy=\"11\" r=\"8\"/><path d=\"M21 21l-4.35-4.35\"/></svg>",
1562
1564
  clock: "<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M12 6v6l4 2\"/></svg>",
1563
- zap: "<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><polygon points=\"13 2 3 14 12 14 11 22 21 10 12 10 13 2\"/></svg>"
1565
+ zap: "<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><polygon points=\"13 2 3 14 12 14 11 22 21 10 12 10 13 2\"/></svg>",
1566
+ download: "<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v4\"/><polyline points=\"7 10 12 15 17 10\"/><line x1=\"12\" y1=\"15\" x2=\"12\" y2=\"3\"/></svg>",
1567
+ copy: "<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\"/><path d=\"M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1\"/></svg>"
1564
1568
  }, Y = {
1565
1569
  bg: "#0b1120",
1566
1570
  bgElevated: "#111827",
@@ -1709,6 +1713,34 @@ var q = class {
1709
1713
  box-shadow: 0 0 0 3px ${Y.accentSoft};
1710
1714
  }
1711
1715
  #nexa-dev-overlay .nexa-search-input::placeholder { color: ${Y.textDim}; }
1716
+ #nexa-dev-overlay .nexa-filters {
1717
+ display: flex;
1718
+ gap: 6px;
1719
+ padding: 12px 16px 12px 16px;
1720
+ border-bottom: 1px solid ${Y.border};
1721
+ overflow-x: auto;
1722
+ scrollbar-width: none;
1723
+ min-height: 50px;
1724
+ }
1725
+ #nexa-dev-overlay .nexa-filters::-webkit-scrollbar { display: none; }
1726
+ #nexa-dev-overlay .nexa-filter-chip {
1727
+ padding: 4px 10px;
1728
+ background: ${Y.bgSurface};
1729
+ border: 1px solid ${Y.border};
1730
+ border-radius: 20px;
1731
+ color: ${Y.textDim};
1732
+ font-size: 11px;
1733
+ font-weight: 600;
1734
+ white-space: nowrap;
1735
+ cursor: pointer;
1736
+ transition: all 0.15s;
1737
+ }
1738
+ #nexa-dev-overlay .nexa-filter-chip:hover { border-color: ${Y.borderFocus}; color: ${Y.textMuted}; }
1739
+ #nexa-dev-overlay .nexa-filter-chip-active {
1740
+ background: ${Y.accentSoft};
1741
+ border-color: ${Y.accent};
1742
+ color: ${Y.accent};
1743
+ }
1712
1744
  #nexa-dev-overlay .nexa-tabs {
1713
1745
  display: flex;
1714
1746
  gap: 4px;
@@ -1849,6 +1881,10 @@ var q = class {
1849
1881
  justify-content: space-between;
1850
1882
  margin-bottom: 16px;
1851
1883
  }
1884
+ #nexa-dev-overlay .nexa-btn-group {
1885
+ display: flex;
1886
+ gap: 8px;
1887
+ }
1852
1888
  #nexa-dev-overlay .nexa-btn {
1853
1889
  display: flex;
1854
1890
  align-items: center;
@@ -1866,6 +1902,8 @@ var q = class {
1866
1902
  #nexa-dev-overlay .nexa-btn:hover { background: rgba(53, 80, 122, 0.24); color: ${Y.text}; }
1867
1903
  #nexa-dev-overlay .nexa-btn-retry { background: ${Y.successBg}; border-color: transparent; color: ${Y.success}; }
1868
1904
  #nexa-dev-overlay .nexa-btn-retry:hover { background: ${Y.success}; color: #052e26; }
1905
+ #nexa-dev-overlay .nexa-btn-copy { background: ${Y.accentSoft}; border-color: transparent; color: ${Y.accent}; }
1906
+ #nexa-dev-overlay .nexa-btn-copy:hover { background: ${Y.accent}; color: #ffffff; }
1869
1907
  #nexa-dev-overlay .nexa-card {
1870
1908
  background: ${Y.bgSurface};
1871
1909
  border: 1px solid ${Y.border};
@@ -1881,6 +1919,28 @@ var q = class {
1881
1919
  letter-spacing: 0.05em;
1882
1920
  margin-bottom: 12px;
1883
1921
  }
1922
+ #nexa-dev-overlay .nexa-notification {
1923
+ position: absolute;
1924
+ bottom: 24px;
1925
+ left: 50%;
1926
+ transform: translateX(-50%) translateY(20px);
1927
+ background: ${Y.bgElevated};
1928
+ color: ${Y.text};
1929
+ padding: 10px 18px;
1930
+ border-radius: 12px;
1931
+ border: 1px solid ${Y.borderFocus};
1932
+ font-size: 13px;
1933
+ font-weight: 500;
1934
+ box-shadow: 0 12px 32px rgba(0,0,0,0.4);
1935
+ z-index: 2147483651;
1936
+ opacity: 0;
1937
+ pointer-events: none;
1938
+ transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
1939
+ }
1940
+ #nexa-dev-overlay .nexa-notification-show {
1941
+ opacity: 1;
1942
+ transform: translateX(-50%) translateY(0);
1943
+ }
1884
1944
  #nexa-dev-overlay .nexa-row {
1885
1945
  display: flex;
1886
1946
  justify-content: space-between;
@@ -1917,7 +1977,6 @@ var q = class {
1917
1977
  flex-direction: column;
1918
1978
  gap: 12px;
1919
1979
  }
1920
- /* Settings modal (overlays the content area without shifting layout) */
1921
1980
  #nexa-dev-overlay .nexa-settings-panel {
1922
1981
  position: absolute;
1923
1982
  top: 72px;
@@ -1957,7 +2016,8 @@ var q = class {
1957
2016
  #nexa-dev-overlay.nexa-theme-light .nexa-request-item,
1958
2017
  #nexa-dev-overlay.nexa-theme-light .nexa-btn,
1959
2018
  #nexa-dev-overlay.nexa-theme-light .nexa-card,
1960
- #nexa-dev-overlay.nexa-theme-light .nexa-settings-panel {
2019
+ #nexa-dev-overlay.nexa-theme-light .nexa-settings-panel,
2020
+ #nexa-dev-overlay.nexa-theme-light .nexa-notification {
1961
2021
  background: #ffffff;
1962
2022
  border-color: #d8e4f2;
1963
2023
  }
@@ -1977,9 +2037,14 @@ var q = class {
1977
2037
  #nexa-dev-overlay.nexa-theme-light .nexa-empty,
1978
2038
  #nexa-dev-overlay.nexa-theme-light .nexa-empty span,
1979
2039
  #nexa-dev-overlay.nexa-theme-light .nexa-row span,
1980
- #nexa-dev-overlay.nexa-theme-light .nexa-settings-row label {
2040
+ #nexa-dev-overlay.nexa-theme-light .nexa-settings-row label,
2041
+ #nexa-dev-overlay.nexa-theme-light .nexa-notification {
1981
2042
  color: #64748b;
1982
2043
  }
2044
+ #nexa-dev-overlay.nexa-theme-light .nexa-notification {
2045
+ box-shadow: 0 12px 32px rgba(15,23,42,0.12);
2046
+ border-color: #e2e8f0;
2047
+ }
1983
2048
  #nexa-dev-overlay.nexa-theme-light .nexa-url,
1984
2049
  #nexa-dev-overlay.nexa-theme-light .nexa-empty p,
1985
2050
  #nexa-dev-overlay.nexa-theme-light .nexa-icon-btn,
@@ -2022,6 +2087,13 @@ var q = class {
2022
2087
  align-items: center;
2023
2088
  gap: 8px;
2024
2089
  }
2090
+ #nexa-dev-overlay.nexa-view-detail .nexa-metrics-bar,
2091
+ #nexa-dev-overlay.nexa-view-detail .nexa-search,
2092
+ #nexa-dev-overlay.nexa-view-detail .nexa-filters,
2093
+ #nexa-dev-overlay.nexa-view-detail .nexa-tabs,
2094
+ #nexa-dev-overlay.nexa-view-detail .nexa-body {
2095
+ display: none !important;
2096
+ }
2025
2097
  `;
2026
2098
  function X() {
2027
2099
  try {
@@ -2046,6 +2118,7 @@ var we = class {
2046
2118
  selectedRequest = null;
2047
2119
  config;
2048
2120
  searchQuery = "";
2121
+ filterType = "all";
2049
2122
  removeTrackerListener = null;
2050
2123
  keyboardShortcutHandler = null;
2051
2124
  globalKeyboardHandler = null;
@@ -2088,7 +2161,7 @@ var we = class {
2088
2161
  e && e.remove();
2089
2162
  } catch {}
2090
2163
  this.panel = document.createElement("div"), this.panel.id = "nexa-dev-overlay";
2091
- let e = this.config.position, t = e.includes("bottom"), n = e.includes("right"), r = `${this.config.floatingButtonOffset ?? 24}px`;
2164
+ let e = this.config.position, t = e.includes("bottom"), n = e.includes("right"), r = `${this.config.floatingButtonOffset ?? 24}px`, i = this.config.branding || "Nexa DevTools", a = this.config.icon || "https://raw.githubusercontent.com/Berea-Soft/nexa/refs/heads/main/src/assets/faviconNew.png";
2092
2165
  this.panel.style.cssText = `
2093
2166
  position: fixed;
2094
2167
  ${t ? `bottom: ${r};` : `top: ${r};`}
@@ -2104,17 +2177,20 @@ var we = class {
2104
2177
  <div class="nexa-header">
2105
2178
  <div class="nexa-header-left">
2106
2179
  <div class="nexa-logo">
2107
- <img src="https://raw.githubusercontent.com/Berea-Soft/nexa/refs/heads/main/src/assets/faviconNew.png" alt="Nexa" style="width:100%;height:auto;object-fit:cover;border-radius:8px;display:block;" />
2180
+ <img src="${a}" alt="${i}" style="width:100%;height:auto;object-fit:cover;border-radius:8px;display:block;" />
2108
2181
  </div>
2109
- <span class="nexa-title">Nexa DevTools</span>
2182
+ <span class="nexa-title">${i}</span>
2110
2183
  </div>
2111
2184
  <div class="nexa-header-actions">
2112
- <button class="nexa-icon-btn nexa-btn-settings" title="Settings">${J.gear}</button>
2185
+ <button class="nexa-icon-btn nexa-btn-export" title="Export history (JSON)">${J.download}</button>
2186
+ <button class="nexa-icon-btn nexa-btn-settings" title="Settings">${J.gear}</button>
2113
2187
  <button class="nexa-icon-btn nexa-btn-clear" title="Clear history">${J.clear}</button>
2114
2188
  <button class="nexa-icon-btn nexa-btn-close" title="Close (Esc)">${J.close}</button>
2115
2189
  </div>
2116
2190
  </div>
2117
2191
 
2192
+ <div class="nexa-notification"></div>
2193
+
2118
2194
  <div class="nexa-settings-panel" style="display:none">
2119
2195
  <div class="nexa-settings-row">
2120
2196
  <label for="nexa-pos">Position</label>
@@ -2151,6 +2227,13 @@ var we = class {
2151
2227
  <input type="text" class="nexa-search-input" placeholder="Filter by URL, method, or status..." />
2152
2228
  </div>
2153
2229
 
2230
+ <div class="nexa-filters">
2231
+ <div class="nexa-filter-chip nexa-filter-chip-active" data-filter="all">All</div>
2232
+ <div class="nexa-filter-chip" data-filter="err">Errors</div>
2233
+ <div class="nexa-filter-chip" data-filter="xhr">JSON</div>
2234
+ <div class="nexa-filter-chip" data-filter="slow">Slow</div>
2235
+ </div>
2236
+
2154
2237
  <div class="nexa-tabs">
2155
2238
  <button class="nexa-tab nexa-tab-active" data-tab="requests"><span>Requests</span><span class="nexa-tab-count" data-count="requests">0</span></button>
2156
2239
  <button class="nexa-tab" data-tab="metrics"><span>Metrics</span></button>
@@ -2164,13 +2247,16 @@ var we = class {
2164
2247
  <div class="nexa-detail" style="display:none">
2165
2248
  <div class="nexa-detail-header">
2166
2249
  <button class="nexa-btn nexa-btn-back">${J.back} Back</button>
2167
- <button class="nexa-btn nexa-btn-retry">${J.retry} Retry</button>
2250
+ <div class="nexa-btn-group">
2251
+ <button class="nexa-btn nexa-btn-copy">${J.copy} Copy as fetch</button>
2252
+ <button class="nexa-btn nexa-btn-retry">${J.retry} Retry</button>
2253
+ </div>
2168
2254
  </div>
2169
2255
  <div class="nexa-detail-body"></div>
2170
2256
  </div>
2171
2257
  `, document.body.appendChild(this.panel), this.config.theme === "light" ? this.panel.classList.add("nexa-theme-light") : this.panel.classList.remove("nexa-theme-light"), this.bindEvents(), this.removeTrackerListener = this.tracker.onChange(() => this.render());
2172
- let i = !this.config.devOnly || X();
2173
- this.config.enabled && i && this.createFloatingIcon(), this.hide(), this.globalKeyboardHandler = (e) => {
2258
+ let o = !this.config.devOnly || X();
2259
+ this.config.enabled && o && this.createFloatingIcon(), this.updateHeaderActionsVisibility(), this.hide(), this.globalKeyboardHandler = (e) => {
2174
2260
  if (e.key === "Escape" && this.visible) {
2175
2261
  this.hide();
2176
2262
  return;
@@ -2183,10 +2269,14 @@ var we = class {
2183
2269
  }, document.addEventListener("keydown", this.globalKeyboardHandler);
2184
2270
  }
2185
2271
  bindEvents() {
2186
- this.panel && (this.panel.querySelector(".nexa-btn-close")?.addEventListener("click", () => this.hide()), this.panel.querySelector(".nexa-btn-clear")?.addEventListener("click", () => {
2272
+ this.panel && (this.panel.querySelector(".nexa-btn-close")?.addEventListener("click", () => this.hide()), this.panel.querySelector(".nexa-btn-export")?.addEventListener("click", () => this.exportHistory()), this.panel.querySelector(".nexa-btn-copy")?.addEventListener("click", () => this.copyAsFetch()), this.panel.querySelector(".nexa-btn-clear")?.addEventListener("click", () => {
2187
2273
  this.tracker.clear(), this.render();
2188
2274
  }), this.panel.querySelector(".nexa-btn-back")?.addEventListener("click", () => this.showMainView()), this.panel.querySelector(".nexa-btn-retry")?.addEventListener("click", () => this.retrySelected()), this.panel.querySelector(".nexa-search-input")?.addEventListener("input", (e) => {
2189
2275
  this.searchQuery = e.target.value.toLowerCase(), this.renderRequestList();
2276
+ }), this.panel.querySelectorAll(".nexa-filter-chip").forEach((e) => {
2277
+ e.addEventListener("click", () => {
2278
+ this.panel.querySelectorAll(".nexa-filter-chip").forEach((e) => e.classList.remove("nexa-filter-chip-active")), e.classList.add("nexa-filter-chip-active"), this.filterType = e.dataset.filter, this.renderRequestList();
2279
+ });
2190
2280
  }), this.panel.querySelectorAll(".nexa-tab").forEach((e) => {
2191
2281
  e.addEventListener("click", () => {
2192
2282
  this.panel.querySelectorAll(".nexa-tab").forEach((e) => e.classList.remove("nexa-tab-active")), this.panel.querySelectorAll(".nexa-panel").forEach((e) => e.classList.remove("nexa-panel-active")), e.classList.add("nexa-tab-active"), this.panel.querySelector(`[data-panel="${e.dataset.tab}"]`)?.classList.add("nexa-panel-active"), e.dataset.tab === "metrics" && this.renderMetrics();
@@ -2213,13 +2303,17 @@ var we = class {
2213
2303
  }
2214
2304
  renderMetricsBar() {
2215
2305
  let e = this.tracker.getMetrics(), t = this.panel;
2216
- t && (t.querySelector("[data-metric=\"total\"]").textContent = String(e.totalRequests), t.querySelector("[data-metric=\"avg\"]").textContent = `${e.avgDuration.toFixed(0)}ms`, t.querySelector("[data-metric=\"rate\"]").textContent = `${e.requestsPerSecond.toFixed(1)}`, t.querySelector("[data-metric=\"success\"]").textContent = String(e.successfulRequests), t.querySelector("[data-metric=\"fail\"]").textContent = String(e.failedRequests), t.querySelector("[data-count=\"requests\"]").textContent = String(e.totalRequests));
2306
+ t && (t.querySelector("[data-metric=\"total\"]").textContent = String(e.totalRequests), t.querySelector("[data-metric=\"avg\"]").textContent = `${e.avgDuration.toFixed(0)}ms`, t.querySelector("[data-metric=\"rate\"]").textContent = `${e.requestsPerSecond.toFixed(1)}`, t.querySelector("[data-metric=\"success\"]").textContent = String(e.successfulRequests), t.querySelector("[data-metric=\"fail\"]").textContent = String(e.failedRequests), t.querySelector("[data-count=\"requests\"]").textContent = String(e.totalRequests), this.updateHeaderActionsVisibility());
2307
+ }
2308
+ updateHeaderActionsVisibility() {
2309
+ let e = this.tracker.getHistory().length > 0, t = this.panel?.querySelector(".nexa-btn-export"), n = this.panel?.querySelector(".nexa-btn-clear");
2310
+ t && (t.style.display = e ? "flex" : "none"), n && (n.style.display = e ? "flex" : "none");
2217
2311
  }
2218
2312
  renderRequestList() {
2219
2313
  let e = this.panel?.querySelector(".nexa-request-list");
2220
2314
  if (!e) return;
2221
2315
  let t = this.tracker.getHistory();
2222
- if (this.searchQuery && (t = t.filter((e) => e.url.toLowerCase().includes(this.searchQuery) || e.method.toLowerCase().includes(this.searchQuery) || String(e.status).includes(this.searchQuery))), t.length === 0) {
2316
+ if (this.filterType === "err" ? t = t.filter((e) => !e.ok) : this.filterType === "xhr" ? t = t.filter((e) => e.headers["content-type"] && e.headers["content-type"].includes("json") || e.responseHeaders && e.responseHeaders["content-type"] && e.responseHeaders["content-type"].includes("json")) : this.filterType === "slow" && (t = t.filter((e) => e.duration > 500)), this.searchQuery && (t = t.filter((e) => e.url.toLowerCase().includes(this.searchQuery) || e.method.toLowerCase().includes(this.searchQuery) || String(e.status).includes(this.searchQuery))), t.length === 0) {
2223
2317
  e.innerHTML = `
2224
2318
  <div class="nexa-empty">
2225
2319
  <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
@@ -2284,9 +2378,9 @@ var we = class {
2284
2378
  ` : ""}`;
2285
2379
  }
2286
2380
  showDetail(e) {
2287
- this.selectedRequest = e;
2288
- let t = this.panel?.querySelector(".nexa-body"), n = this.panel?.querySelector(".nexa-detail"), r = this.panel?.querySelector(".nexa-detail-body");
2289
- !t || !n || !r || (t.style.display = "none", n.style.display = "flex", r.innerHTML = `
2381
+ if (this.selectedRequest = e, !this.panel) return;
2382
+ let t = this.panel.querySelector(".nexa-body"), n = this.panel.querySelector(".nexa-detail"), r = this.panel.querySelector(".nexa-detail-body");
2383
+ !t || !n || !r || (this.panel.classList.add("nexa-view-detail"), t.style.display = "none", n.style.display = "flex", r.innerHTML = `
2290
2384
  <div class="nexa-card">
2291
2385
  <h3>Request</h3>
2292
2386
  <div class="nexa-row"><span>Method</span><strong style="color:${e.method === "GET" ? Y.get : e.method === "POST" ? Y.post : e.method === "DELETE" ? Y.delete : Y.warning}">${e.method}</strong></div>
@@ -2311,6 +2405,7 @@ var we = class {
2311
2405
  ` : ""}`);
2312
2406
  }
2313
2407
  showMainView() {
2408
+ this.panel && this.panel.classList.remove("nexa-view-detail");
2314
2409
  let e = this.panel?.querySelector(".nexa-body"), t = this.panel?.querySelector(".nexa-detail");
2315
2410
  e && (e.style.display = "flex"), t && (t.style.display = "none"), this.selectedRequest = null;
2316
2411
  }
@@ -2331,6 +2426,27 @@ var we = class {
2331
2426
  }, this.showDetail(this.selectedRequest));
2332
2427
  }).catch(() => {});
2333
2428
  }
2429
+ exportHistory() {
2430
+ let e = this.tracker.getHistory(), t = JSON.stringify(e, null, 2), n = new Blob([t], { type: "application/json" }), r = URL.createObjectURL(n), i = document.createElement("a");
2431
+ i.href = r, i.download = `nexa-history-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace(/[:]/g, "-")}.json`, document.body.appendChild(i), i.click(), document.body.removeChild(i), URL.revokeObjectURL(r), this.showNotification("History exported as JSON");
2432
+ }
2433
+ copyAsFetch() {
2434
+ if (!this.selectedRequest) return;
2435
+ let e = this.selectedRequest, t = { ...e.headers };
2436
+ delete t.host;
2437
+ let n = `fetch("${e.url}", {\n`;
2438
+ n += ` "method": "${e.method}",\n`, Object.keys(t).length > 0 && (n += ` "headers": ${JSON.stringify(t, null, 4).replace(/\n/g, "\n ")},\n`), e.body && (n += ` "body": ${JSON.stringify(e.body, null, 4).replace(/\n/g, "\n ")},\n`), n += "});", navigator.clipboard.writeText(n).then(() => {
2439
+ this.showNotification("Copied as fetch to clipboard");
2440
+ }).catch(() => {
2441
+ this.showNotification("Failed to copy to clipboard");
2442
+ });
2443
+ }
2444
+ showNotification(e) {
2445
+ let t = this.panel?.querySelector(".nexa-notification");
2446
+ t && (t.textContent = e, t.classList.add("nexa-notification-show"), setTimeout(() => {
2447
+ t.classList.remove("nexa-notification-show");
2448
+ }, 2500));
2449
+ }
2334
2450
  truncateUrl(e, t = 35) {
2335
2451
  try {
2336
2452
  let t = new URL(e);
@@ -2359,7 +2475,9 @@ var we = class {
2359
2475
  let e = document.createElement("button");
2360
2476
  e.id = "nexa-dev-overlay-floating", e.title = "Toggle Nexa DevTools";
2361
2477
  let t = this.config.floatingButtonSize ?? 48, n = this.config.floatingButtonOffset ?? 24, r = this.config.position || "bottom-right", i = r.includes("bottom"), a = r.includes("right"), o = `${i ? `bottom: ${n}px;` : `top: ${n}px;`} ${a ? `right: ${n}px;` : `left: ${n}px;`}`, s = this.config.floatingButtonTheme === "inherit" ? this.config.theme : this.config.floatingButtonTheme, c = "linear-gradient(135deg,#0ea5e9,#8b5cf6)", l = "#ffffff", u = "0 16px 36px rgba(2,6,23,0.34)", d = "none";
2362
- s === "light" && (c = "linear-gradient(135deg,#f8fbff,#e0f2fe)", l = "#0f172a", u = "0 14px 30px rgba(15,23,42,0.16)", d = "1px solid #d8e4f2"), e.style.cssText = `
2478
+ s === "light" && (c = "linear-gradient(135deg,#f8fbff,#e0f2fe)", l = "#0f172a", u = "0 14px 30px rgba(15,23,42,0.16)", d = "1px solid #d8e4f2");
2479
+ let f = this.config.branding || "Nexa DevTools", p = this.config.icon || "https://raw.githubusercontent.com/Berea-Soft/nexa/refs/heads/main/src/assets/faviconNew.png";
2480
+ e.style.cssText = `
2363
2481
  position: fixed;
2364
2482
  ${o}
2365
2483
  width: ${t}px;
@@ -2376,7 +2494,7 @@ var we = class {
2376
2494
  color: ${l};
2377
2495
  font-weight: 700;
2378
2496
  font-size: ${Math.max(12, Math.floor(t / 3))}px;
2379
- `, e.innerHTML = `<img src="https://raw.githubusercontent.com/Berea-Soft/nexa/refs/heads/main/src/assets/faviconNew.png" alt="Nexa" style="width:${t - 10}px;height:auto;object-fit:cover;border-radius:999px;display:block;" />`, e.addEventListener("click", (e) => {
2497
+ `, e.innerHTML = `<img src="${p}" alt="${f}" style="width:${t - 10}px;height:auto;object-fit:cover;border-radius:999px;display:block;" />`, e.addEventListener("click", (e) => {
2380
2498
  e.stopPropagation(), this.toggle();
2381
2499
  }), e.addEventListener("mousedown", (e) => e.preventDefault()), document.body.appendChild(e), e.style.display = this.visible ? "none" : "flex", this.floatingIcon = e;
2382
2500
  }
@@ -2393,7 +2511,12 @@ var we = class {
2393
2511
  applyConfigToUI(e) {
2394
2512
  this.config = e ?? this.tracker.getConfig();
2395
2513
  let t = this.config.position, n = t.includes("bottom"), r = t.includes("right"), i = `${this.config.floatingButtonOffset ?? 24}px`;
2396
- this.panel && (this.panel.style.bottom = n ? i : "", this.panel.style.top = n ? "" : i, this.panel.style.right = r ? i : "", this.panel.style.left = r ? "" : i, this.config.theme === "light" ? this.panel.classList.add("nexa-theme-light") : this.panel.classList.remove("nexa-theme-light")), this.floatingIcon &&= (this.floatingIcon.remove(), null), this.config.enabled && (!this.config.devOnly || X()) && this.createFloatingIcon();
2514
+ if (this.panel) {
2515
+ this.panel.style.bottom = n ? i : "", this.panel.style.top = n ? "" : i, this.panel.style.right = r ? i : "", this.panel.style.left = r ? "" : i, this.config.theme === "light" ? this.panel.classList.add("nexa-theme-light") : this.panel.classList.remove("nexa-theme-light");
2516
+ let e = this.panel.querySelector(".nexa-logo img"), t = this.panel.querySelector(".nexa-title"), a = this.config.branding || "Nexa DevTools", o = this.config.icon || "https://raw.githubusercontent.com/Berea-Soft/nexa/refs/heads/main/src/assets/faviconNew.png";
2517
+ e && (e.src = o, e.alt = a), t && (t.textContent = a);
2518
+ }
2519
+ this.floatingIcon &&= (this.floatingIcon.remove(), null), this.config.enabled && (!this.config.devOnly || X()) && this.createFloatingIcon();
2397
2520
  }
2398
2521
  refreshConfig(e) {
2399
2522
  this.applyConfigToUI(e);
@@ -2407,7 +2530,9 @@ var we = class {
2407
2530
  devOnly: !0,
2408
2531
  floatingButtonSize: 48,
2409
2532
  floatingButtonOffset: 24,
2410
- floatingButtonTheme: "inherit"
2533
+ floatingButtonTheme: "inherit",
2534
+ branding: "Nexa DevTools",
2535
+ icon: "https://raw.githubusercontent.com/Berea-Soft/nexa/refs/heads/main/src/assets/faviconNew.png"
2411
2536
  };
2412
2537
  function Te(e = {}) {
2413
2538
  if (Z && Q) {