@mushi-mushi/web 1.7.7 → 1.8.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/README.md +39 -1
- package/dist/index.cjs +248 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +248 -28
- package/dist/index.js.map +1 -1
- package/package.json +15 -15
package/README.md
CHANGED
|
@@ -263,6 +263,44 @@ on every hide path.
|
|
|
263
263
|
> sit at a certain z-index. Use `hideOnSelector` or `Mushi.hide()` for the safest
|
|
264
264
|
> experience in native shells.
|
|
265
265
|
|
|
266
|
+
### Rich banner layout (1.8+)
|
|
267
|
+
|
|
268
|
+
With `trigger: 'banner'`, setting `bannerConfig.message` switches the strip from
|
|
269
|
+
button-only CTAs to the rich layout used by the Mushi admin console's beta
|
|
270
|
+
banner — a pill label, body copy, and flat text actions:
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
Mushi.init({
|
|
274
|
+
projectId: 'proj_xxx',
|
|
275
|
+
apiKey: 'mushi_xxx',
|
|
276
|
+
widget: {
|
|
277
|
+
trigger: 'banner',
|
|
278
|
+
bannerConfig: {
|
|
279
|
+
variant: 'brand', // 'neon' | 'brand' | 'subtle'
|
|
280
|
+
position: 'top', // 'top' | 'bottom'
|
|
281
|
+
message: 'Mushi is in beta — spotted something off? Tell us.',
|
|
282
|
+
label: 'Beta', // pill before the message; `false` hides it
|
|
283
|
+
bugCta: '🐛 Report a bug',
|
|
284
|
+
featureCta: true,
|
|
285
|
+
links: [
|
|
286
|
+
{ label: 'My submissions', href: 'https://app.example.com/feedback' },
|
|
287
|
+
{ label: 'Request a feature', featureRequest: true }, // opens widget in feature mode
|
|
288
|
+
],
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
});
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
- All banner text renders via `textContent` — never HTML — so server- or
|
|
295
|
+
CMS-sourced copy can't inject markup.
|
|
296
|
+
- `links[].href` opens in a new tab with `rel="noopener noreferrer"`; omit
|
|
297
|
+
`href` and set `featureRequest: true` to open the widget instead.
|
|
298
|
+
- `message` and `label` can also be driven remotely per-project from the
|
|
299
|
+
dashboard runtime config (`bannerMessage` / `bannerLabel`), so you can change
|
|
300
|
+
the copy without a deploy. `links` are local-config only.
|
|
301
|
+
- Without `message`, the banner keeps the original compact button-only layout —
|
|
302
|
+
existing integrations are unchanged.
|
|
303
|
+
|
|
266
304
|
### Presets and widget anchor
|
|
267
305
|
|
|
268
306
|
```typescript
|
|
@@ -462,4 +500,4 @@ MIT
|
|
|
462
500
|
<!-- mushi-readme-stats-footer -->
|
|
463
501
|
---
|
|
464
502
|
|
|
465
|
-
<sub>Monorepo scale (June 2026): 43 edge functions ·
|
|
503
|
+
<sub>Monorepo scale (June 2026): 43 edge functions · 234 SQL migrations · 13 outbound plugins · 11 inbound adapters. Canonical counts: <a href="https://github.com/kensaurus/mushi-mushi/blob/master/docs/stats.md">docs/stats.md</a> · <code>pnpm docs-stats</code></sub>
|
package/dist/index.cjs
CHANGED
|
@@ -1512,6 +1512,106 @@ function getWidgetStyles(theme) {
|
|
|
1512
1512
|
text-overflow: ellipsis;
|
|
1513
1513
|
}
|
|
1514
1514
|
|
|
1515
|
+
/* Rich layout \u2014 pill + message + flat text actions (admin BetaBanner parity) */
|
|
1516
|
+
.mushi-banner--rich {
|
|
1517
|
+
justify-content: space-between;
|
|
1518
|
+
gap: 12px;
|
|
1519
|
+
min-height: 36px;
|
|
1520
|
+
height: auto;
|
|
1521
|
+
padding: 4px 12px 4px 16px;
|
|
1522
|
+
white-space: normal;
|
|
1523
|
+
}
|
|
1524
|
+
.mushi-banner-body {
|
|
1525
|
+
display: flex;
|
|
1526
|
+
align-items: center;
|
|
1527
|
+
gap: 8px;
|
|
1528
|
+
flex: 1;
|
|
1529
|
+
min-width: 0;
|
|
1530
|
+
overflow: hidden;
|
|
1531
|
+
}
|
|
1532
|
+
.mushi-banner-pill {
|
|
1533
|
+
display: inline-flex;
|
|
1534
|
+
flex-shrink: 0;
|
|
1535
|
+
align-items: center;
|
|
1536
|
+
padding: 1px 6px;
|
|
1537
|
+
border-radius: 3px;
|
|
1538
|
+
border: 1px solid currentColor;
|
|
1539
|
+
font-size: 10px;
|
|
1540
|
+
font-weight: 700;
|
|
1541
|
+
letter-spacing: 0.18em;
|
|
1542
|
+
text-transform: uppercase;
|
|
1543
|
+
opacity: 0.92;
|
|
1544
|
+
}
|
|
1545
|
+
.mushi-banner.neon .mushi-banner-pill {
|
|
1546
|
+
border-color: rgba(10,26,10,0.45);
|
|
1547
|
+
background: rgba(10,26,10,0.12);
|
|
1548
|
+
}
|
|
1549
|
+
.mushi-banner.brand .mushi-banner-pill {
|
|
1550
|
+
border-color: rgba(255,255,255,0.45);
|
|
1551
|
+
background: rgba(255,255,255,0.14);
|
|
1552
|
+
}
|
|
1553
|
+
.mushi-banner.subtle .mushi-banner-pill {
|
|
1554
|
+
border-color: ${ruleStrong};
|
|
1555
|
+
background: ${isDark ? "rgba(242,235,221,0.08)" : "rgba(14,13,11,0.06)"};
|
|
1556
|
+
}
|
|
1557
|
+
.mushi-banner-message {
|
|
1558
|
+
min-width: 0;
|
|
1559
|
+
overflow: hidden;
|
|
1560
|
+
text-overflow: ellipsis;
|
|
1561
|
+
white-space: nowrap;
|
|
1562
|
+
font-size: 11.5px;
|
|
1563
|
+
font-weight: 500;
|
|
1564
|
+
line-height: 1.3;
|
|
1565
|
+
opacity: 0.9;
|
|
1566
|
+
}
|
|
1567
|
+
.mushi-banner-actions {
|
|
1568
|
+
display: inline-flex;
|
|
1569
|
+
align-items: center;
|
|
1570
|
+
gap: 0;
|
|
1571
|
+
/* Shrinkable + swipe-scrollable so a long action row can never push
|
|
1572
|
+
past the viewport edge (dismiss sits outside this nav). */
|
|
1573
|
+
flex-shrink: 1;
|
|
1574
|
+
min-width: 0;
|
|
1575
|
+
overflow-x: auto;
|
|
1576
|
+
scrollbar-width: none;
|
|
1577
|
+
font-size: 11px;
|
|
1578
|
+
}
|
|
1579
|
+
.mushi-banner-actions::-webkit-scrollbar { display: none; }
|
|
1580
|
+
@media (max-width: 480px) {
|
|
1581
|
+
/* Phones: keep only the primary bug CTA (+ dismiss outside the nav). */
|
|
1582
|
+
.mushi-banner-actions .mushi-banner-extra { display: none; }
|
|
1583
|
+
}
|
|
1584
|
+
.mushi-banner-link {
|
|
1585
|
+
display: inline-flex;
|
|
1586
|
+
align-items: center;
|
|
1587
|
+
padding: 2px 8px;
|
|
1588
|
+
border: none;
|
|
1589
|
+
background: transparent;
|
|
1590
|
+
color: inherit;
|
|
1591
|
+
cursor: pointer;
|
|
1592
|
+
font: inherit;
|
|
1593
|
+
letter-spacing: inherit;
|
|
1594
|
+
text-decoration: none;
|
|
1595
|
+
opacity: 0.88;
|
|
1596
|
+
transition: opacity 0.15s ease;
|
|
1597
|
+
flex-shrink: 0;
|
|
1598
|
+
}
|
|
1599
|
+
.mushi-banner-link:hover { opacity: 1; }
|
|
1600
|
+
.mushi-banner-link:focus-visible {
|
|
1601
|
+
outline: 2px solid ${widgetAccent};
|
|
1602
|
+
outline-offset: 2px;
|
|
1603
|
+
border-radius: 2px;
|
|
1604
|
+
}
|
|
1605
|
+
.mushi-banner-divider {
|
|
1606
|
+
opacity: 0.28;
|
|
1607
|
+
padding: 0 1px;
|
|
1608
|
+
user-select: none;
|
|
1609
|
+
flex-shrink: 0;
|
|
1610
|
+
}
|
|
1611
|
+
.mushi-banner--rich .mushi-banner-dismiss {
|
|
1612
|
+
margin-left: 4px;
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1515
1615
|
.mushi-banner-btn {
|
|
1516
1616
|
display: inline-flex;
|
|
1517
1617
|
align-items: center;
|
|
@@ -1754,7 +1854,12 @@ var MushiWidget = class _MushiWidget {
|
|
|
1754
1854
|
...config.responseSlaLabel !== void 0 ? { responseSlaLabel: config.responseSlaLabel } : {},
|
|
1755
1855
|
...config.featureRequestCard !== void 0 ? { featureRequestCard: config.featureRequestCard } : {},
|
|
1756
1856
|
...config.featureRequestLabel !== void 0 ? { featureRequestLabel: config.featureRequestLabel } : {},
|
|
1757
|
-
...config.featureRequestDescription !== void 0 ? { featureRequestDescription: config.featureRequestDescription } : {}
|
|
1857
|
+
...config.featureRequestDescription !== void 0 ? { featureRequestDescription: config.featureRequestDescription } : {},
|
|
1858
|
+
// Runtime/dashboard config delivers bannerMessage/bannerLabel via
|
|
1859
|
+
// mergeRuntimeConfig → bannerConfig. The widget is constructed before
|
|
1860
|
+
// that fetch resolves, so this pass-through is what makes server-driven
|
|
1861
|
+
// banner copy actually render.
|
|
1862
|
+
...config.bannerConfig !== void 0 ? { bannerConfig: config.bannerConfig } : {}
|
|
1758
1863
|
};
|
|
1759
1864
|
this.locale = getLocale(this.config.locale === "auto" ? void 0 : this.config.locale);
|
|
1760
1865
|
if (this.host.isConnected) this.syncHostChromeState();
|
|
@@ -2139,18 +2244,16 @@ var MushiWidget = class _MushiWidget {
|
|
|
2139
2244
|
const bc = this.config.bannerConfig ?? {};
|
|
2140
2245
|
const variant = bc.variant ?? "brand";
|
|
2141
2246
|
const position = bc.position ?? "top";
|
|
2247
|
+
const message = bc.message?.trim() ?? "";
|
|
2248
|
+
const richLayout = message.length > 0;
|
|
2142
2249
|
const bugLabel = bc.bugCta ?? "\u{1F41B} Report a bug";
|
|
2143
2250
|
const showFeat = bc.featureCta !== false;
|
|
2144
2251
|
const featLabel = bc.featureCtaLabel ?? "\u2728 Request feature";
|
|
2145
2252
|
const zIdx = bc.zIndex ?? (this.config.zIndex ?? 99999) - 1;
|
|
2146
2253
|
const banner = document.createElement("div");
|
|
2147
|
-
banner.className = `mushi-banner ${variant} ${position}`;
|
|
2254
|
+
banner.className = `mushi-banner ${variant} ${position}${richLayout ? " mushi-banner--rich" : ""}`;
|
|
2148
2255
|
banner.style.setProperty("--mushi-banner-z", String(zIdx));
|
|
2149
2256
|
banner.setAttribute("role", "banner");
|
|
2150
|
-
const bugBtn = document.createElement("button");
|
|
2151
|
-
bugBtn.className = "mushi-banner-btn";
|
|
2152
|
-
bugBtn.textContent = bugLabel;
|
|
2153
|
-
bugBtn.addEventListener("click", () => this.open());
|
|
2154
2257
|
const dismissBtn = document.createElement("button");
|
|
2155
2258
|
dismissBtn.className = "mushi-banner-dismiss";
|
|
2156
2259
|
dismissBtn.textContent = "\u2715";
|
|
@@ -2160,15 +2263,81 @@ var MushiWidget = class _MushiWidget {
|
|
|
2160
2263
|
this.removeBodyNudge();
|
|
2161
2264
|
this.render();
|
|
2162
2265
|
});
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2266
|
+
if (richLayout) {
|
|
2267
|
+
const body = document.createElement("div");
|
|
2268
|
+
body.className = "mushi-banner-body";
|
|
2269
|
+
const labelText = bc.label === false ? null : bc.label ?? "Beta";
|
|
2270
|
+
if (labelText) {
|
|
2271
|
+
const pill = document.createElement("span");
|
|
2272
|
+
pill.className = "mushi-banner-pill";
|
|
2273
|
+
pill.textContent = labelText;
|
|
2274
|
+
body.appendChild(pill);
|
|
2275
|
+
}
|
|
2276
|
+
const msg = document.createElement("span");
|
|
2277
|
+
msg.className = "mushi-banner-message";
|
|
2278
|
+
msg.textContent = message;
|
|
2279
|
+
body.appendChild(msg);
|
|
2280
|
+
banner.appendChild(body);
|
|
2281
|
+
const nav = document.createElement("nav");
|
|
2282
|
+
nav.className = "mushi-banner-actions";
|
|
2283
|
+
nav.setAttribute("aria-label", "Feedback banner actions");
|
|
2284
|
+
const appendDivider = (extra = false) => {
|
|
2285
|
+
const sep = document.createElement("span");
|
|
2286
|
+
sep.className = `mushi-banner-divider${extra ? " mushi-banner-extra" : ""}`;
|
|
2287
|
+
sep.setAttribute("aria-hidden", "true");
|
|
2288
|
+
sep.textContent = "|";
|
|
2289
|
+
nav.appendChild(sep);
|
|
2290
|
+
};
|
|
2291
|
+
const appendAction = (label, onClick, extra = false) => {
|
|
2292
|
+
const btn = document.createElement("button");
|
|
2293
|
+
btn.type = "button";
|
|
2294
|
+
btn.className = `mushi-banner-link${extra ? " mushi-banner-extra" : ""}`;
|
|
2295
|
+
btn.textContent = label;
|
|
2296
|
+
btn.addEventListener("click", onClick);
|
|
2297
|
+
nav.appendChild(btn);
|
|
2298
|
+
};
|
|
2299
|
+
appendAction(bugLabel, () => this.open());
|
|
2300
|
+
if (showFeat) {
|
|
2301
|
+
appendDivider(true);
|
|
2302
|
+
appendAction(featLabel, () => this.open({ featureRequest: true }), true);
|
|
2303
|
+
}
|
|
2304
|
+
for (const link of bc.links ?? []) {
|
|
2305
|
+
const linkLabel = link.label?.trim();
|
|
2306
|
+
if (!linkLabel) continue;
|
|
2307
|
+
const href = link.href && (/^https?:\/\//i.test(link.href) || link.href.startsWith("/")) ? link.href : void 0;
|
|
2308
|
+
appendDivider(true);
|
|
2309
|
+
if (href) {
|
|
2310
|
+
const anchor = document.createElement("a");
|
|
2311
|
+
anchor.className = "mushi-banner-link mushi-banner-extra";
|
|
2312
|
+
anchor.href = href;
|
|
2313
|
+
anchor.textContent = linkLabel;
|
|
2314
|
+
anchor.target = "_blank";
|
|
2315
|
+
anchor.rel = "noopener noreferrer";
|
|
2316
|
+
nav.appendChild(anchor);
|
|
2317
|
+
} else {
|
|
2318
|
+
appendAction(linkLabel, () => {
|
|
2319
|
+
if (link.featureRequest) this.open({ featureRequest: true });
|
|
2320
|
+
else this.open();
|
|
2321
|
+
}, true);
|
|
2322
|
+
}
|
|
2323
|
+
}
|
|
2324
|
+
banner.appendChild(nav);
|
|
2325
|
+
banner.appendChild(dismissBtn);
|
|
2326
|
+
} else {
|
|
2327
|
+
const bugBtn = document.createElement("button");
|
|
2328
|
+
bugBtn.className = "mushi-banner-btn";
|
|
2329
|
+
bugBtn.textContent = bugLabel;
|
|
2330
|
+
bugBtn.addEventListener("click", () => this.open());
|
|
2331
|
+
banner.appendChild(bugBtn);
|
|
2332
|
+
if (showFeat) {
|
|
2333
|
+
const featBtn = document.createElement("button");
|
|
2334
|
+
featBtn.className = "mushi-banner-btn";
|
|
2335
|
+
featBtn.textContent = featLabel;
|
|
2336
|
+
featBtn.addEventListener("click", () => this.open({ featureRequest: true }));
|
|
2337
|
+
banner.appendChild(featBtn);
|
|
2338
|
+
}
|
|
2339
|
+
banner.appendChild(dismissBtn);
|
|
2340
|
+
}
|
|
2172
2341
|
this.shadow.appendChild(banner);
|
|
2173
2342
|
this.applyBodyNudge(position);
|
|
2174
2343
|
}
|
|
@@ -3660,18 +3829,18 @@ function createScreenshotCapture(options = {}) {
|
|
|
3660
3829
|
const url = URL.createObjectURL(blob);
|
|
3661
3830
|
return new Promise((resolve) => {
|
|
3662
3831
|
img.onload = () => {
|
|
3663
|
-
ctx.drawImage(img, 0, 0, width, height);
|
|
3664
|
-
URL.revokeObjectURL(url);
|
|
3665
3832
|
try {
|
|
3666
|
-
|
|
3667
|
-
|
|
3833
|
+
ctx.drawImage(img, 0, 0, width, height);
|
|
3834
|
+
URL.revokeObjectURL(url);
|
|
3835
|
+
resolve(canvas.toDataURL("image/jpeg", 0.7));
|
|
3668
3836
|
} catch {
|
|
3669
|
-
|
|
3837
|
+
URL.revokeObjectURL(url);
|
|
3838
|
+
resolve(buildDegradedScreenshot(width, height));
|
|
3670
3839
|
}
|
|
3671
3840
|
};
|
|
3672
3841
|
img.onerror = () => {
|
|
3673
3842
|
URL.revokeObjectURL(url);
|
|
3674
|
-
resolve(
|
|
3843
|
+
resolve(buildDegradedScreenshot(width, height));
|
|
3675
3844
|
};
|
|
3676
3845
|
img.src = url;
|
|
3677
3846
|
});
|
|
@@ -3693,6 +3862,7 @@ var DEFAULT_REDACT_SELECTORS = [
|
|
|
3693
3862
|
function buildPrivacySafeDocument(privacy) {
|
|
3694
3863
|
const clone = document.documentElement.cloneNode(true);
|
|
3695
3864
|
clone.querySelector("#mushi-mushi-widget")?.remove();
|
|
3865
|
+
stripTaintSources(clone);
|
|
3696
3866
|
const redactSelectors = privacy?.redactSelectors !== void 0 ? privacy.redactSelectors : DEFAULT_REDACT_SELECTORS;
|
|
3697
3867
|
for (const selector of redactSelectors) {
|
|
3698
3868
|
for (const el of safeQueryAll(clone, selector)) {
|
|
@@ -3731,6 +3901,46 @@ function redactElement(el) {
|
|
|
3731
3901
|
el.setAttribute("data-mushi-redacted", "true");
|
|
3732
3902
|
while (el.firstChild) el.removeChild(el.firstChild);
|
|
3733
3903
|
}
|
|
3904
|
+
function stripTaintSources(root) {
|
|
3905
|
+
const pageOrigin = typeof location !== "undefined" ? location.origin : "";
|
|
3906
|
+
for (const el of root.querySelectorAll("img, video, iframe, object, embed, picture")) {
|
|
3907
|
+
el.remove();
|
|
3908
|
+
}
|
|
3909
|
+
for (const link of root.querySelectorAll('link[rel="stylesheet"], link[as="style"]')) {
|
|
3910
|
+
const href = link.getAttribute("href");
|
|
3911
|
+
if (!href || isCrossOriginUrl(href, pageOrigin)) link.remove();
|
|
3912
|
+
}
|
|
3913
|
+
for (const script of root.querySelectorAll("script")) {
|
|
3914
|
+
script.remove();
|
|
3915
|
+
}
|
|
3916
|
+
}
|
|
3917
|
+
function isCrossOriginUrl(raw, pageOrigin) {
|
|
3918
|
+
if (!raw || raw.startsWith("data:") || raw.startsWith("blob:")) return false;
|
|
3919
|
+
try {
|
|
3920
|
+
const resolved = new URL(raw, typeof location !== "undefined" ? location.href : "http://localhost/");
|
|
3921
|
+
return Boolean(pageOrigin) && resolved.origin !== pageOrigin;
|
|
3922
|
+
} catch {
|
|
3923
|
+
return true;
|
|
3924
|
+
}
|
|
3925
|
+
}
|
|
3926
|
+
function buildDegradedScreenshot(width, height) {
|
|
3927
|
+
const canvas = document.createElement("canvas");
|
|
3928
|
+
const ctx = canvas.getContext("2d");
|
|
3929
|
+
if (!ctx) return null;
|
|
3930
|
+
canvas.width = width;
|
|
3931
|
+
canvas.height = height;
|
|
3932
|
+
ctx.fillStyle = "#111827";
|
|
3933
|
+
ctx.fillRect(0, 0, width, height);
|
|
3934
|
+
ctx.fillStyle = "#e5e7eb";
|
|
3935
|
+
ctx.font = "13px system-ui, sans-serif";
|
|
3936
|
+
ctx.fillText("Screenshot: layout captured (external media stripped)", 16, 28);
|
|
3937
|
+
ctx.fillText(`${width}\xD7${height}px`, 16, 48);
|
|
3938
|
+
try {
|
|
3939
|
+
return canvas.toDataURL("image/jpeg", 0.7);
|
|
3940
|
+
} catch {
|
|
3941
|
+
return null;
|
|
3942
|
+
}
|
|
3943
|
+
}
|
|
3734
3944
|
function maskElement(el) {
|
|
3735
3945
|
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
|
|
3736
3946
|
el.value = "";
|
|
@@ -4782,7 +4992,7 @@ function createProactiveManager(config = {}) {
|
|
|
4782
4992
|
|
|
4783
4993
|
// src/version.ts
|
|
4784
4994
|
var MUSHI_SDK_PACKAGE = "@mushi-mushi/web";
|
|
4785
|
-
var MUSHI_SDK_VERSION = "1.
|
|
4995
|
+
var MUSHI_SDK_VERSION = "1.8.0" ;
|
|
4786
4996
|
|
|
4787
4997
|
// src/mushi.ts
|
|
4788
4998
|
var instance = null;
|
|
@@ -4963,8 +5173,10 @@ function createInstance(config) {
|
|
|
4963
5173
|
});
|
|
4964
5174
|
let detachAutoBreadcrumbs = null;
|
|
4965
5175
|
detachAutoBreadcrumbs = installAutoBreadcrumbs(breadcrumbs);
|
|
5176
|
+
let screenshotCaptureInFlight = false;
|
|
4966
5177
|
async function takeScreenshotWithoutChrome() {
|
|
4967
|
-
if (!screenshotCap) return null;
|
|
5178
|
+
if (!screenshotCap || screenshotCaptureInFlight) return null;
|
|
5179
|
+
screenshotCaptureInFlight = true;
|
|
4968
5180
|
const panelWasVisible = widget.getIsOpen();
|
|
4969
5181
|
if (panelWasVisible) widget.hidePanel();
|
|
4970
5182
|
const host = document.getElementById("mushi-mushi-widget");
|
|
@@ -4976,6 +5188,7 @@ function createInstance(config) {
|
|
|
4976
5188
|
try {
|
|
4977
5189
|
return await screenshotCap.take();
|
|
4978
5190
|
} finally {
|
|
5191
|
+
screenshotCaptureInFlight = false;
|
|
4979
5192
|
if (host) host.style.visibility = prevVisibility;
|
|
4980
5193
|
if (panelWasVisible) widget.showPanel();
|
|
4981
5194
|
}
|
|
@@ -5649,14 +5862,21 @@ function mergeRuntimeConfig(config, runtime) {
|
|
|
5649
5862
|
const nativeTrigger = runtime.native?.triggerMode;
|
|
5650
5863
|
const runtimeLauncher = runtime.widget?.launcher;
|
|
5651
5864
|
const widgetTrigger = runtimeLauncher ?? runtime.widget?.trigger ?? (nativeTrigger === "none" || nativeTrigger === "shake" ? "manual" : void 0);
|
|
5652
|
-
const
|
|
5653
|
-
const
|
|
5654
|
-
const
|
|
5655
|
-
const
|
|
5656
|
-
const
|
|
5865
|
+
const runtimeWidget = runtime.widget;
|
|
5866
|
+
const runtimeBannerVariant = runtimeWidget?.bannerVariant;
|
|
5867
|
+
const runtimeBannerPosition = runtimeWidget?.bannerPosition;
|
|
5868
|
+
const runtimeBannerMessage = runtimeWidget?.bannerMessage;
|
|
5869
|
+
const runtimeBannerLabel = runtimeWidget?.bannerLabel;
|
|
5870
|
+
const runtimeBannerBugCta = runtimeWidget?.bannerBugCta;
|
|
5871
|
+
const runtimeBannerFeatureCta = runtimeWidget?.bannerFeatureCta;
|
|
5872
|
+
const derivedBannerConfig = runtimeBannerVariant || runtimeBannerPosition || runtimeBannerMessage != null || runtimeBannerLabel != null || runtimeBannerBugCta != null || runtimeBannerFeatureCta != null ? {
|
|
5657
5873
|
...config.widget?.bannerConfig ?? {},
|
|
5658
5874
|
...runtimeBannerVariant ? { variant: runtimeBannerVariant } : {},
|
|
5659
5875
|
...runtimeBannerPosition ? { position: runtimeBannerPosition } : {},
|
|
5876
|
+
...runtimeBannerMessage != null ? { message: runtimeBannerMessage } : {},
|
|
5877
|
+
// Dashboard sends an empty string to hide the pill (the runtime
|
|
5878
|
+
// payload has no way to express the local-config `label: false`).
|
|
5879
|
+
...runtimeBannerLabel != null ? { label: runtimeBannerLabel === "" ? false : runtimeBannerLabel } : {},
|
|
5660
5880
|
...runtimeBannerBugCta != null ? { bugCta: runtimeBannerBugCta ?? void 0 } : {},
|
|
5661
5881
|
...runtimeBannerFeatureCta != null ? { featureCta: runtimeBannerFeatureCta } : {}
|
|
5662
5882
|
} : void 0;
|