@mushi-mushi/web 1.2.1 → 1.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.
- package/CONTRIBUTING.md +11 -0
- package/dist/index.cjs +490 -84
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -1
- package/dist/index.d.ts +40 -1
- package/dist/index.js +490 -84
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -47,10 +47,20 @@ var en = {
|
|
|
47
47
|
heading: "Tell us more",
|
|
48
48
|
descriptionPlaceholder: "Describe what happened\u2026",
|
|
49
49
|
screenshotButton: "Attach Screenshot",
|
|
50
|
-
screenshotAttached: "Screenshot attached",
|
|
50
|
+
screenshotAttached: "Screenshot attached \u2713",
|
|
51
|
+
screenshotCapturing: "Taking screenshot\u2026",
|
|
52
|
+
screenshotFailed: "Couldn't capture \u2014 describe it instead",
|
|
51
53
|
elementButton: "Select Element",
|
|
52
|
-
elementSelected: "Element selected",
|
|
53
|
-
|
|
54
|
+
elementSelected: "Element selected \u2713",
|
|
55
|
+
elementCapturing: "Click anything on the page\u2026",
|
|
56
|
+
elementSelectorHint: "Click any element \xB7 Esc to cancel",
|
|
57
|
+
optional: "(optional)",
|
|
58
|
+
tooShort: "A bit more detail helps us fix it faster",
|
|
59
|
+
examplePrompts: [
|
|
60
|
+
"The save button does nothing",
|
|
61
|
+
"Page froze for 10 seconds",
|
|
62
|
+
"Layout looks broken here"
|
|
63
|
+
]
|
|
54
64
|
}
|
|
55
65
|
};
|
|
56
66
|
|
|
@@ -97,10 +107,20 @@ var ja = {
|
|
|
97
107
|
heading: "\u8A73\u7D30\u3092\u6559\u3048\u3066\u304F\u3060\u3055\u3044",
|
|
98
108
|
descriptionPlaceholder: "\u4F55\u304C\u8D77\u304D\u305F\u304B\u8AAC\u660E\u3057\u3066\u304F\u3060\u3055\u3044\u2026",
|
|
99
109
|
screenshotButton: "\u30B9\u30AF\u30EA\u30FC\u30F3\u30B7\u30E7\u30C3\u30C8\u6DFB\u4ED8",
|
|
100
|
-
screenshotAttached: "\u30B9\u30AF\u30EA\u30FC\u30F3\u30B7\u30E7\u30C3\u30C8\u6DFB\u4ED8\u6E08\u307F",
|
|
110
|
+
screenshotAttached: "\u30B9\u30AF\u30EA\u30FC\u30F3\u30B7\u30E7\u30C3\u30C8\u6DFB\u4ED8\u6E08\u307F \u2713",
|
|
111
|
+
screenshotCapturing: "\u30B9\u30AF\u30EA\u30FC\u30F3\u30B7\u30E7\u30C3\u30C8\u64AE\u5F71\u4E2D\u2026",
|
|
112
|
+
screenshotFailed: "\u53D6\u5F97\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F \u2014 \u6587\u5B57\u3067\u6559\u3048\u3066\u304F\u3060\u3055\u3044",
|
|
101
113
|
elementButton: "\u8981\u7D20\u3092\u9078\u629E",
|
|
102
|
-
elementSelected: "\u8981\u7D20\u9078\u629E\u6E08\u307F",
|
|
103
|
-
|
|
114
|
+
elementSelected: "\u8981\u7D20\u9078\u629E\u6E08\u307F \u2713",
|
|
115
|
+
elementCapturing: "\u30DA\u30FC\u30B8\u4E0A\u306E\u8981\u7D20\u3092\u30AF\u30EA\u30C3\u30AF\u2026",
|
|
116
|
+
elementSelectorHint: "\u8981\u7D20\u3092\u30AF\u30EA\u30C3\u30AF \xB7 Esc \u3067\u30AD\u30E3\u30F3\u30BB\u30EB",
|
|
117
|
+
optional: "\uFF08\u4EFB\u610F\uFF09",
|
|
118
|
+
tooShort: "\u3082\u3046\u5C11\u3057\u8A73\u3057\u304F\u6559\u3048\u3066\u304F\u3060\u3055\u3044",
|
|
119
|
+
examplePrompts: [
|
|
120
|
+
"\u4FDD\u5B58\u30DC\u30BF\u30F3\u304C\u53CD\u5FDC\u3057\u306A\u3044",
|
|
121
|
+
"\u30DA\u30FC\u30B8\u304C10\u79D2\u56FA\u307E\u3063\u305F",
|
|
122
|
+
"\u30EC\u30A4\u30A2\u30A6\u30C8\u304C\u5D29\u308C\u3066\u3044\u308B"
|
|
123
|
+
]
|
|
104
124
|
}
|
|
105
125
|
};
|
|
106
126
|
|
|
@@ -147,10 +167,20 @@ var th = {
|
|
|
147
167
|
heading: "\u0E1A\u0E2D\u0E01\u0E40\u0E23\u0E32\u0E40\u0E1E\u0E34\u0E48\u0E21\u0E40\u0E15\u0E34\u0E21",
|
|
148
168
|
descriptionPlaceholder: "\u0E2D\u0E18\u0E34\u0E1A\u0E32\u0E22\u0E2A\u0E34\u0E48\u0E07\u0E17\u0E35\u0E48\u0E40\u0E01\u0E34\u0E14\u0E02\u0E36\u0E49\u0E19\u2026",
|
|
149
169
|
screenshotButton: "\u0E41\u0E19\u0E1A\u0E2A\u0E01\u0E23\u0E35\u0E19\u0E0A\u0E47\u0E2D\u0E15",
|
|
150
|
-
screenshotAttached: "\u0E41\u0E19\u0E1A\u0E2A\u0E01\u0E23\u0E35\u0E19\u0E0A\u0E47\u0E2D\u0E15\u0E41\u0E25\u0E49\u0E27",
|
|
170
|
+
screenshotAttached: "\u0E41\u0E19\u0E1A\u0E2A\u0E01\u0E23\u0E35\u0E19\u0E0A\u0E47\u0E2D\u0E15\u0E41\u0E25\u0E49\u0E27 \u2713",
|
|
171
|
+
screenshotCapturing: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E16\u0E48\u0E32\u0E22\u0E2A\u0E01\u0E23\u0E35\u0E19\u0E0A\u0E47\u0E2D\u0E15\u2026",
|
|
172
|
+
screenshotFailed: "\u0E44\u0E21\u0E48\u0E2A\u0E32\u0E21\u0E32\u0E23\u0E16\u0E16\u0E48\u0E32\u0E22\u0E20\u0E32\u0E1E\u0E44\u0E14\u0E49 \u2014 \u0E42\u0E1B\u0E23\u0E14\u0E2D\u0E18\u0E34\u0E1A\u0E32\u0E22\u0E41\u0E17\u0E19",
|
|
151
173
|
elementButton: "\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E2D\u0E07\u0E04\u0E4C\u0E1B\u0E23\u0E30\u0E01\u0E2D\u0E1A",
|
|
152
|
-
elementSelected: "\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E2D\u0E07\u0E04\u0E4C\u0E1B\u0E23\u0E30\u0E01\u0E2D\u0E1A\u0E41\u0E25\u0E49\u0E27",
|
|
153
|
-
|
|
174
|
+
elementSelected: "\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E2D\u0E07\u0E04\u0E4C\u0E1B\u0E23\u0E30\u0E01\u0E2D\u0E1A\u0E41\u0E25\u0E49\u0E27 \u2713",
|
|
175
|
+
elementCapturing: "\u0E04\u0E25\u0E34\u0E01\u0E2D\u0E07\u0E04\u0E4C\u0E1B\u0E23\u0E30\u0E01\u0E2D\u0E1A\u0E1A\u0E19\u0E2B\u0E19\u0E49\u0E32\u2026",
|
|
176
|
+
elementSelectorHint: "\u0E04\u0E25\u0E34\u0E01\u0E2D\u0E07\u0E04\u0E4C\u0E1B\u0E23\u0E30\u0E01\u0E2D\u0E1A\u0E43\u0E14\u0E01\u0E47\u0E44\u0E14\u0E49 \xB7 Esc \u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E22\u0E01\u0E40\u0E25\u0E34\u0E01",
|
|
177
|
+
optional: "(\u0E44\u0E21\u0E48\u0E1A\u0E31\u0E07\u0E04\u0E31\u0E1A)",
|
|
178
|
+
tooShort: "\u0E01\u0E23\u0E38\u0E13\u0E32\u0E43\u0E2B\u0E49\u0E23\u0E32\u0E22\u0E25\u0E30\u0E40\u0E2D\u0E35\u0E22\u0E14\u0E40\u0E1E\u0E34\u0E48\u0E21\u0E40\u0E15\u0E34\u0E21",
|
|
179
|
+
examplePrompts: [
|
|
180
|
+
"\u0E1B\u0E38\u0E48\u0E21\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E44\u0E21\u0E48\u0E17\u0E33\u0E07\u0E32\u0E19",
|
|
181
|
+
"\u0E2B\u0E19\u0E49\u0E32\u0E04\u0E49\u0E32\u0E07\u0E19\u0E32\u0E19 10 \u0E27\u0E34\u0E19\u0E32\u0E17\u0E35",
|
|
182
|
+
"\u0E40\u0E25\u0E22\u0E4C\u0E40\u0E2D\u0E32\u0E15\u0E4C\u0E1E\u0E31\u0E07"
|
|
183
|
+
]
|
|
154
184
|
}
|
|
155
185
|
};
|
|
156
186
|
|
|
@@ -197,18 +227,29 @@ var es = {
|
|
|
197
227
|
heading: "Cu\xE9ntanos m\xE1s",
|
|
198
228
|
descriptionPlaceholder: "Describe lo que pas\xF3\u2026",
|
|
199
229
|
screenshotButton: "Adjuntar captura",
|
|
200
|
-
screenshotAttached: "Captura adjunta",
|
|
230
|
+
screenshotAttached: "Captura adjunta \u2713",
|
|
231
|
+
screenshotCapturing: "Tomando captura\u2026",
|
|
232
|
+
screenshotFailed: "No se pudo capturar \u2014 descr\xEDbelo en su lugar",
|
|
201
233
|
elementButton: "Seleccionar elemento",
|
|
202
|
-
elementSelected: "Elemento seleccionado",
|
|
203
|
-
|
|
234
|
+
elementSelected: "Elemento seleccionado \u2713",
|
|
235
|
+
elementCapturing: "Haz clic en cualquier elemento\u2026",
|
|
236
|
+
elementSelectorHint: "Clic en cualquier elemento \xB7 Esc para cancelar",
|
|
237
|
+
optional: "(opcional)",
|
|
238
|
+
tooShort: "Un poco m\xE1s de detalle nos ayuda a resolverlo",
|
|
239
|
+
examplePrompts: [
|
|
240
|
+
"El bot\xF3n guardar no responde",
|
|
241
|
+
"La p\xE1gina se congel\xF3 10 segundos",
|
|
242
|
+
"El dise\xF1o se ve roto aqu\xED"
|
|
243
|
+
]
|
|
204
244
|
}
|
|
205
245
|
};
|
|
206
246
|
|
|
207
247
|
// src/i18n/index.ts
|
|
208
248
|
var locales = { en, ja, th, es };
|
|
209
249
|
function getLocale(code) {
|
|
210
|
-
|
|
211
|
-
|
|
250
|
+
const resolved = code && code !== "auto" ? code : typeof navigator !== "undefined" ? navigator.language ?? navigator.languages?.[0] : void 0;
|
|
251
|
+
if (!resolved) return en;
|
|
252
|
+
const base = resolved.split("-")[0].toLowerCase();
|
|
212
253
|
return locales[base] ?? en;
|
|
213
254
|
}
|
|
214
255
|
function getAvailableLocales() {
|
|
@@ -241,6 +282,7 @@ function getWidgetStyles(theme) {
|
|
|
241
282
|
-webkit-font-smoothing: antialiased;
|
|
242
283
|
-moz-osx-font-smoothing: grayscale;
|
|
243
284
|
font-feature-settings: 'ss01', 'cv11'; /* nicer system-ui glyphs where supported */
|
|
285
|
+
--mushi-ok: ${isDark ? "#4ade80" : "#16a34a"};
|
|
244
286
|
}
|
|
245
287
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
246
288
|
button { font-family: inherit; }
|
|
@@ -693,6 +735,51 @@ function getWidgetStyles(theme) {
|
|
|
693
735
|
box-shadow: inset 2px 0 0 ${vermillion};
|
|
694
736
|
}
|
|
695
737
|
|
|
738
|
+
/* Example starter chips \u2014 reduce first-report activation energy */
|
|
739
|
+
.mushi-example-chips {
|
|
740
|
+
display: flex;
|
|
741
|
+
flex-wrap: wrap;
|
|
742
|
+
gap: 6px;
|
|
743
|
+
margin-bottom: 10px;
|
|
744
|
+
}
|
|
745
|
+
.mushi-example-chip {
|
|
746
|
+
padding: 4px 10px;
|
|
747
|
+
border: 1px solid ${rule};
|
|
748
|
+
border-radius: 12px;
|
|
749
|
+
background: transparent;
|
|
750
|
+
color: ${inkMuted};
|
|
751
|
+
font-family: ${fontBody};
|
|
752
|
+
font-size: 11px;
|
|
753
|
+
cursor: pointer;
|
|
754
|
+
transition: color 150ms ${easeStamp}, border-color 150ms ${easeStamp}, background 150ms ${easeStamp};
|
|
755
|
+
white-space: nowrap;
|
|
756
|
+
}
|
|
757
|
+
.mushi-example-chip:hover {
|
|
758
|
+
color: ${ink};
|
|
759
|
+
border-color: ${inkMuted};
|
|
760
|
+
background: ${isDark ? "rgba(242,235,221,0.06)" : "rgba(14,13,11,0.04)"};
|
|
761
|
+
}
|
|
762
|
+
.mushi-example-chip:focus-visible {
|
|
763
|
+
outline: 2px solid ${vermillion};
|
|
764
|
+
outline-offset: 2px;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
/* Textarea wrapper to position char counter */
|
|
768
|
+
.mushi-textarea-wrap {
|
|
769
|
+
position: relative;
|
|
770
|
+
}
|
|
771
|
+
.mushi-char-counter {
|
|
772
|
+
position: absolute;
|
|
773
|
+
bottom: 4px;
|
|
774
|
+
right: 0;
|
|
775
|
+
font-family: ${fontMono};
|
|
776
|
+
font-size: 10px;
|
|
777
|
+
letter-spacing: 0.04em;
|
|
778
|
+
color: ${inkFaint};
|
|
779
|
+
pointer-events: none;
|
|
780
|
+
transition: color 200ms ${easeStamp};
|
|
781
|
+
}
|
|
782
|
+
|
|
696
783
|
.mushi-textarea {
|
|
697
784
|
width: 100%;
|
|
698
785
|
min-height: 96px;
|
|
@@ -755,10 +842,34 @@ function getWidgetStyles(theme) {
|
|
|
755
842
|
border-color: ${vermillion};
|
|
756
843
|
background: ${vermillionWash};
|
|
757
844
|
}
|
|
845
|
+
.mushi-attach-btn.loading {
|
|
846
|
+
opacity: 0.7;
|
|
847
|
+
cursor: wait;
|
|
848
|
+
}
|
|
849
|
+
.mushi-attach-btn.error {
|
|
850
|
+
color: ${vermillion};
|
|
851
|
+
border-color: ${vermillionWash};
|
|
852
|
+
}
|
|
758
853
|
.mushi-attach-btn:focus-visible {
|
|
759
854
|
outline: 2px solid ${vermillion};
|
|
760
855
|
outline-offset: 2px;
|
|
761
856
|
}
|
|
857
|
+
@keyframes mushi-spin {
|
|
858
|
+
to { transform: rotate(360deg); }
|
|
859
|
+
}
|
|
860
|
+
@keyframes mushi-fade-in {
|
|
861
|
+
from { opacity: 0; transform: translateY(4px); }
|
|
862
|
+
to { opacity: 1; transform: translateY(0); }
|
|
863
|
+
}
|
|
864
|
+
.mushi-spinner {
|
|
865
|
+
display: inline-block;
|
|
866
|
+
width: 10px;
|
|
867
|
+
height: 10px;
|
|
868
|
+
border: 1.5px solid currentColor;
|
|
869
|
+
border-top-color: transparent;
|
|
870
|
+
border-radius: 50%;
|
|
871
|
+
animation: mushi-spin 0.7s linear infinite;
|
|
872
|
+
}
|
|
762
873
|
|
|
763
874
|
.mushi-footer {
|
|
764
875
|
padding: 14px 22px 16px;
|
|
@@ -1232,7 +1343,8 @@ var MushiWidget = class {
|
|
|
1232
1343
|
draggable: config.draggable ?? false,
|
|
1233
1344
|
brandFooter: config.brandFooter ?? true,
|
|
1234
1345
|
outdatedBanner: config.outdatedBanner ?? "auto",
|
|
1235
|
-
betaMode: config.betaMode ?? {}
|
|
1346
|
+
betaMode: config.betaMode ?? {},
|
|
1347
|
+
minDescriptionLength: config.minDescriptionLength ?? 20
|
|
1236
1348
|
};
|
|
1237
1349
|
this.callbacks = callbacks;
|
|
1238
1350
|
this.locale = getLocale(this.config.locale === "auto" ? void 0 : this.config.locale);
|
|
@@ -1251,12 +1363,22 @@ var MushiWidget = class {
|
|
|
1251
1363
|
selectedCategory = null;
|
|
1252
1364
|
selectedIntent = null;
|
|
1253
1365
|
screenshotAttached = false;
|
|
1366
|
+
screenshotCapturing = false;
|
|
1367
|
+
screenshotError = false;
|
|
1254
1368
|
allowScreenshotRemove = true;
|
|
1255
1369
|
elementSelected = false;
|
|
1370
|
+
elementCapturing = false;
|
|
1256
1371
|
submitting = false;
|
|
1372
|
+
/** Hint element injected outside the shadow DOM during element selection. */
|
|
1373
|
+
selectorHint = null;
|
|
1257
1374
|
triggerVisible = true;
|
|
1258
1375
|
triggerShrunk = false;
|
|
1259
1376
|
triggerHiddenByScroll = false;
|
|
1377
|
+
/** Milliseconds since mount — used for the 30s first-time nudge gate. */
|
|
1378
|
+
mountedAt = null;
|
|
1379
|
+
nudgeShown = false;
|
|
1380
|
+
nudgeEl = null;
|
|
1381
|
+
nudgeTimer = null;
|
|
1260
1382
|
sdkFreshness = null;
|
|
1261
1383
|
reporterReports = [];
|
|
1262
1384
|
reporterComments = [];
|
|
@@ -1283,6 +1405,7 @@ var MushiWidget = class {
|
|
|
1283
1405
|
this.syncAttachedLaunchers();
|
|
1284
1406
|
this.syncSmartHide();
|
|
1285
1407
|
this.render();
|
|
1408
|
+
this.mountedAt = Date.now();
|
|
1286
1409
|
}
|
|
1287
1410
|
getIsMounted() {
|
|
1288
1411
|
return this.host.isConnected;
|
|
@@ -1309,7 +1432,8 @@ var MushiWidget = class {
|
|
|
1309
1432
|
...config.draggable !== void 0 ? { draggable: config.draggable } : {},
|
|
1310
1433
|
...config.brandFooter !== void 0 ? { brandFooter: config.brandFooter } : {},
|
|
1311
1434
|
...config.outdatedBanner !== void 0 ? { outdatedBanner: config.outdatedBanner } : {},
|
|
1312
|
-
...config.betaMode !== void 0 ? { betaMode: config.betaMode } : {}
|
|
1435
|
+
...config.betaMode !== void 0 ? { betaMode: config.betaMode } : {},
|
|
1436
|
+
...config.minDescriptionLength !== void 0 ? { minDescriptionLength: config.minDescriptionLength } : {}
|
|
1313
1437
|
};
|
|
1314
1438
|
this.locale = getLocale(this.config.locale === "auto" ? void 0 : this.config.locale);
|
|
1315
1439
|
this.syncAttachedLaunchers();
|
|
@@ -1320,9 +1444,13 @@ var MushiWidget = class {
|
|
|
1320
1444
|
if (this.isOpen) return;
|
|
1321
1445
|
this.isOpen = true;
|
|
1322
1446
|
this.screenshotAttached = false;
|
|
1447
|
+
this.screenshotCapturing = false;
|
|
1448
|
+
this.screenshotError = false;
|
|
1323
1449
|
this.elementSelected = false;
|
|
1450
|
+
this.elementCapturing = false;
|
|
1324
1451
|
this.submitting = false;
|
|
1325
1452
|
this.submittedAt = null;
|
|
1453
|
+
this.removeSelectorHint();
|
|
1326
1454
|
if (options?.category) {
|
|
1327
1455
|
this.selectedCategory = options.category;
|
|
1328
1456
|
this.selectedIntent = null;
|
|
@@ -1378,8 +1506,114 @@ var MushiWidget = class {
|
|
|
1378
1506
|
}
|
|
1379
1507
|
setElementSelected(selected) {
|
|
1380
1508
|
this.elementSelected = selected;
|
|
1509
|
+
this.elementCapturing = false;
|
|
1510
|
+
this.removeSelectorHint();
|
|
1511
|
+
if (this.isOpen) this.render();
|
|
1512
|
+
}
|
|
1513
|
+
setScreenshotCapturing(capturing) {
|
|
1514
|
+
this.screenshotCapturing = capturing;
|
|
1515
|
+
this.screenshotError = false;
|
|
1516
|
+
if (this.isOpen) this.render();
|
|
1517
|
+
}
|
|
1518
|
+
setScreenshotError(failed) {
|
|
1519
|
+
this.screenshotError = failed;
|
|
1520
|
+
this.screenshotCapturing = false;
|
|
1381
1521
|
if (this.isOpen) this.render();
|
|
1382
1522
|
}
|
|
1523
|
+
setElementCapturing(capturing) {
|
|
1524
|
+
this.elementCapturing = capturing;
|
|
1525
|
+
if (capturing) {
|
|
1526
|
+
this.showSelectorHint();
|
|
1527
|
+
} else {
|
|
1528
|
+
this.removeSelectorHint();
|
|
1529
|
+
}
|
|
1530
|
+
if (this.isOpen) this.render();
|
|
1531
|
+
}
|
|
1532
|
+
/** Hide the widget panel (but keep the host element) during element selection
|
|
1533
|
+
* so the user can click any element on the page without the panel
|
|
1534
|
+
* intercepting the event. */
|
|
1535
|
+
hidePanel() {
|
|
1536
|
+
const panel = this.shadow.querySelector(".mushi-panel");
|
|
1537
|
+
if (panel) panel.style.display = "none";
|
|
1538
|
+
}
|
|
1539
|
+
showPanel() {
|
|
1540
|
+
const panel = this.shadow.querySelector(".mushi-panel");
|
|
1541
|
+
if (panel) panel.style.display = "";
|
|
1542
|
+
}
|
|
1543
|
+
showSelectorHint() {
|
|
1544
|
+
this.removeSelectorHint();
|
|
1545
|
+
const hint = document.createElement("div");
|
|
1546
|
+
hint.id = "mushi-selector-hint";
|
|
1547
|
+
hint.setAttribute("role", "status");
|
|
1548
|
+
hint.setAttribute("aria-live", "polite");
|
|
1549
|
+
hint.style.cssText = `
|
|
1550
|
+
position: fixed;
|
|
1551
|
+
bottom: 24px;
|
|
1552
|
+
left: 50%;
|
|
1553
|
+
transform: translateX(-50%);
|
|
1554
|
+
z-index: 2147483646;
|
|
1555
|
+
background: rgba(17,17,17,0.92);
|
|
1556
|
+
color: #fff;
|
|
1557
|
+
font-family: ui-monospace, SFMono-Regular, monospace;
|
|
1558
|
+
font-size: 12px;
|
|
1559
|
+
letter-spacing: 0.04em;
|
|
1560
|
+
padding: 8px 16px;
|
|
1561
|
+
border-radius: 20px;
|
|
1562
|
+
pointer-events: none;
|
|
1563
|
+
white-space: nowrap;
|
|
1564
|
+
backdrop-filter: blur(4px);
|
|
1565
|
+
box-shadow: 0 2px 12px rgba(0,0,0,0.35);
|
|
1566
|
+
`;
|
|
1567
|
+
hint.textContent = this.locale.step3.elementSelectorHint;
|
|
1568
|
+
document.body.appendChild(hint);
|
|
1569
|
+
this.selectorHint = hint;
|
|
1570
|
+
}
|
|
1571
|
+
removeSelectorHint() {
|
|
1572
|
+
this.selectorHint?.remove();
|
|
1573
|
+
this.selectorHint = null;
|
|
1574
|
+
document.getElementById("mushi-selector-hint")?.remove();
|
|
1575
|
+
}
|
|
1576
|
+
showNudge() {
|
|
1577
|
+
if (this.nudgeShown || this.nudgeEl) return;
|
|
1578
|
+
this.nudgeShown = true;
|
|
1579
|
+
const trigger = this.shadow.querySelector(".mushi-trigger");
|
|
1580
|
+
const rect = trigger?.getBoundingClientRect();
|
|
1581
|
+
const nudge = document.createElement("div");
|
|
1582
|
+
nudge.id = "mushi-nudge-bubble";
|
|
1583
|
+
nudge.setAttribute("role", "tooltip");
|
|
1584
|
+
const isRight = this.config.position.includes("right");
|
|
1585
|
+
nudge.style.cssText = `
|
|
1586
|
+
position: fixed;
|
|
1587
|
+
z-index: 2147483645;
|
|
1588
|
+
${rect ? `bottom: ${window.innerHeight - rect.top + 8}px; ${isRight ? `right: ${window.innerWidth - rect.right}px;` : `left: ${rect.left}px;`}` : "bottom: 80px; right: 24px;"}
|
|
1589
|
+
background: rgba(17,17,17,0.92);
|
|
1590
|
+
color: #fff;
|
|
1591
|
+
font-family: ui-sans-serif, system-ui, sans-serif;
|
|
1592
|
+
font-size: 12px;
|
|
1593
|
+
line-height: 1.4;
|
|
1594
|
+
padding: 8px 12px;
|
|
1595
|
+
border-radius: 8px;
|
|
1596
|
+
max-width: 200px;
|
|
1597
|
+
pointer-events: none;
|
|
1598
|
+
backdrop-filter: blur(4px);
|
|
1599
|
+
box-shadow: 0 2px 12px rgba(0,0,0,0.35);
|
|
1600
|
+
animation: mushi-fade-in 0.15s ease forwards;
|
|
1601
|
+
`;
|
|
1602
|
+
nudge.textContent = this.locale.step3.tooShort.startsWith("A bit") ? "Found a bug? One sentence is enough \u{1F41B}" : "\u30D0\u30B0\u3092\u898B\u3064\u3051\u305F\uFF1F\u4E00\u884C\u3067\u5927\u4E08\u592B\u3067\u3059 \u{1F41B}";
|
|
1603
|
+
document.body.appendChild(nudge);
|
|
1604
|
+
this.nudgeEl = nudge;
|
|
1605
|
+
if (this.nudgeTimer !== null) clearTimeout(this.nudgeTimer);
|
|
1606
|
+
this.nudgeTimer = setTimeout(() => this.removeNudge(), 5e3);
|
|
1607
|
+
}
|
|
1608
|
+
removeNudge() {
|
|
1609
|
+
if (this.nudgeTimer !== null) {
|
|
1610
|
+
clearTimeout(this.nudgeTimer);
|
|
1611
|
+
this.nudgeTimer = null;
|
|
1612
|
+
}
|
|
1613
|
+
this.nudgeEl?.remove();
|
|
1614
|
+
this.nudgeEl = null;
|
|
1615
|
+
document.getElementById("mushi-nudge-bubble")?.remove();
|
|
1616
|
+
}
|
|
1383
1617
|
setSdkFreshness(info) {
|
|
1384
1618
|
this.sdkFreshness = info;
|
|
1385
1619
|
if (this.isOpen) this.render();
|
|
@@ -1405,6 +1639,8 @@ var MushiWidget = class {
|
|
|
1405
1639
|
this.smartHideCleanup = null;
|
|
1406
1640
|
this.attachedLaunchers.forEach((cleanup) => cleanup());
|
|
1407
1641
|
this.attachedLaunchers = [];
|
|
1642
|
+
this.removeSelectorHint();
|
|
1643
|
+
this.removeNudge();
|
|
1408
1644
|
this.host.remove();
|
|
1409
1645
|
}
|
|
1410
1646
|
syncAttachedLaunchers() {
|
|
@@ -1500,9 +1736,22 @@ var MushiWidget = class {
|
|
|
1500
1736
|
trigger.style.zIndex = String(this.config.zIndex);
|
|
1501
1737
|
this.applyInsetVars(trigger);
|
|
1502
1738
|
trigger.addEventListener("click", () => {
|
|
1739
|
+
this.removeNudge();
|
|
1503
1740
|
if (this.isOpen) this.close();
|
|
1504
1741
|
else this.open();
|
|
1505
1742
|
});
|
|
1743
|
+
trigger.addEventListener("mouseenter", () => {
|
|
1744
|
+
const onPageMs = this.mountedAt ? Date.now() - this.mountedAt : 0;
|
|
1745
|
+
if (!this.nudgeShown && !this.isOpen && onPageMs >= 3e4) {
|
|
1746
|
+
this.showNudge();
|
|
1747
|
+
}
|
|
1748
|
+
});
|
|
1749
|
+
trigger.addEventListener("mouseleave", () => {
|
|
1750
|
+
if (this.nudgeEl) {
|
|
1751
|
+
if (this.nudgeTimer !== null) clearTimeout(this.nudgeTimer);
|
|
1752
|
+
this.nudgeTimer = setTimeout(() => this.removeNudge(), 2e3);
|
|
1753
|
+
}
|
|
1754
|
+
});
|
|
1506
1755
|
this.shadow.appendChild(trigger);
|
|
1507
1756
|
}
|
|
1508
1757
|
const panel = document.createElement("div");
|
|
@@ -1754,25 +2003,62 @@ var MushiWidget = class {
|
|
|
1754
2003
|
${this.renderStepIndicator(STEP_NUMBER.intent)}
|
|
1755
2004
|
`;
|
|
1756
2005
|
}
|
|
2006
|
+
effectiveMinLength() {
|
|
2007
|
+
const base = this.config.minDescriptionLength ?? 20;
|
|
2008
|
+
const lang = this.config.locale === "auto" ? typeof navigator !== "undefined" ? navigator.language ?? "" : "" : this.config.locale ?? "";
|
|
2009
|
+
const isCjk = /^(ja|zh|ko)/i.test(lang);
|
|
2010
|
+
return isCjk ? Math.max(4, Math.floor(base / 2)) : base;
|
|
2011
|
+
}
|
|
1757
2012
|
renderDetailsStep() {
|
|
1758
2013
|
const t = this.locale;
|
|
2014
|
+
const minLen = this.effectiveMinLength();
|
|
2015
|
+
const screenshotLabel = this.screenshotCapturing ? t.step3.screenshotCapturing : this.screenshotError ? t.step3.screenshotFailed : this.screenshotAttached ? t.step3.screenshotAttached : t.step3.screenshotButton;
|
|
2016
|
+
const screenshotClass = [
|
|
2017
|
+
"mushi-attach-btn",
|
|
2018
|
+
this.screenshotAttached ? "active" : "",
|
|
2019
|
+
this.screenshotError ? "error" : "",
|
|
2020
|
+
this.screenshotCapturing ? "loading" : ""
|
|
2021
|
+
].filter(Boolean).join(" ");
|
|
2022
|
+
const elementLabel = this.elementCapturing ? t.step3.elementCapturing : this.elementSelected ? t.step3.elementSelected : t.step3.elementButton;
|
|
2023
|
+
const elementClass = [
|
|
2024
|
+
"mushi-attach-btn",
|
|
2025
|
+
this.elementSelected ? "active" : "",
|
|
2026
|
+
this.elementCapturing ? "loading" : ""
|
|
2027
|
+
].filter(Boolean).join(" ");
|
|
2028
|
+
const exampleChips = t.step3.examplePrompts.map((p) => `<button type="button" class="mushi-example-chip" data-example="${escapeHtml(p)}">${escapeHtml(p)}</button>`).join("");
|
|
1759
2029
|
return `
|
|
1760
2030
|
${this.renderHeader({ title: t.step3.heading, showBack: true, step: STEP_NUMBER.details })}
|
|
1761
2031
|
<div class="mushi-body">
|
|
1762
|
-
<
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
2032
|
+
<div class="mushi-example-chips" aria-label="Example prompts">${exampleChips}</div>
|
|
2033
|
+
<div class="mushi-textarea-wrap">
|
|
2034
|
+
<textarea
|
|
2035
|
+
class="mushi-textarea"
|
|
2036
|
+
placeholder="${t.step3.descriptionPlaceholder}"
|
|
2037
|
+
rows="4"
|
|
2038
|
+
aria-label="${t.step3.heading}"
|
|
2039
|
+
autofocus
|
|
2040
|
+
></textarea>
|
|
2041
|
+
<div class="mushi-char-counter" data-role="char-counter" aria-hidden="true">
|
|
2042
|
+
<span data-role="char-current">0</span>/<span data-role="char-min">${minLen}</span>
|
|
2043
|
+
</div>
|
|
2044
|
+
</div>
|
|
1769
2045
|
<div class="mushi-attachments">
|
|
1770
|
-
<button type="button" class="
|
|
1771
|
-
|
|
2046
|
+
<button type="button" class="${screenshotClass}"
|
|
2047
|
+
data-action="screenshot"
|
|
2048
|
+
${this.screenshotCapturing ? "disabled" : ""}
|
|
2049
|
+
aria-label="${escapeHtml(screenshotLabel)}"
|
|
2050
|
+
>
|
|
2051
|
+
${this.screenshotCapturing ? '<span class="mushi-spinner" aria-hidden="true"></span>' : "\u{1F4F8}"}
|
|
2052
|
+
${escapeHtml(screenshotLabel)}
|
|
1772
2053
|
</button>
|
|
1773
|
-
${this.screenshotAttached && this.allowScreenshotRemove ? '<button type="button" class="mushi-attach-btn danger" data-action="remove-screenshot">\u2715 Remove
|
|
1774
|
-
<button type="button" class="
|
|
1775
|
-
|
|
2054
|
+
${this.screenshotAttached && this.allowScreenshotRemove ? '<button type="button" class="mushi-attach-btn danger" data-action="remove-screenshot" aria-label="Remove screenshot">\u2715 Remove</button>' : ""}
|
|
2055
|
+
<button type="button" class="${elementClass}"
|
|
2056
|
+
data-action="element"
|
|
2057
|
+
${this.elementCapturing ? "disabled" : ""}
|
|
2058
|
+
aria-label="${escapeHtml(elementLabel)}"
|
|
2059
|
+
>
|
|
2060
|
+
${this.elementCapturing ? '<span class="mushi-spinner" aria-hidden="true"></span>' : "\u{1F3AF}"}
|
|
2061
|
+
${escapeHtml(elementLabel)}
|
|
1776
2062
|
</button>
|
|
1777
2063
|
</div>
|
|
1778
2064
|
<div class="mushi-error" style="display:none" role="alert"></div>
|
|
@@ -1942,6 +2228,30 @@ var MushiWidget = class {
|
|
|
1942
2228
|
this.render();
|
|
1943
2229
|
});
|
|
1944
2230
|
});
|
|
2231
|
+
const textarea = panel.querySelector(".mushi-textarea");
|
|
2232
|
+
const charCurrentEl = panel.querySelector('[data-role="char-current"]');
|
|
2233
|
+
if (textarea && charCurrentEl) {
|
|
2234
|
+
const minLen = this.effectiveMinLength();
|
|
2235
|
+
const updateCounter = () => {
|
|
2236
|
+
const len = textarea.value.trim().length;
|
|
2237
|
+
charCurrentEl.textContent = String(len);
|
|
2238
|
+
const counterEl = panel.querySelector('[data-role="char-counter"]');
|
|
2239
|
+
if (counterEl) {
|
|
2240
|
+
counterEl.style.color = len >= minLen ? "var(--mushi-ok, #22c55e)" : "";
|
|
2241
|
+
}
|
|
2242
|
+
};
|
|
2243
|
+
textarea.addEventListener("input", updateCounter);
|
|
2244
|
+
}
|
|
2245
|
+
panel.querySelectorAll("[data-example]").forEach((chip) => {
|
|
2246
|
+
chip.addEventListener("click", () => {
|
|
2247
|
+
const example = chip.dataset.example ?? "";
|
|
2248
|
+
if (textarea) {
|
|
2249
|
+
textarea.value = example;
|
|
2250
|
+
textarea.focus();
|
|
2251
|
+
textarea.dispatchEvent(new Event("input"));
|
|
2252
|
+
}
|
|
2253
|
+
});
|
|
2254
|
+
});
|
|
1945
2255
|
panel.querySelector('[data-action="screenshot"]')?.addEventListener("click", () => {
|
|
1946
2256
|
this.callbacks.onScreenshotRequest();
|
|
1947
2257
|
});
|
|
@@ -1952,14 +2262,16 @@ var MushiWidget = class {
|
|
|
1952
2262
|
this.callbacks.onElementSelectorRequest?.();
|
|
1953
2263
|
});
|
|
1954
2264
|
const submitReport = () => {
|
|
1955
|
-
const
|
|
1956
|
-
const description =
|
|
2265
|
+
const textarea2 = panel.querySelector(".mushi-textarea");
|
|
2266
|
+
const description = textarea2?.value?.trim() ?? "";
|
|
1957
2267
|
const errorEl = panel.querySelector(".mushi-error");
|
|
1958
|
-
const
|
|
1959
|
-
if (description.length <
|
|
2268
|
+
const minLen = this.effectiveMinLength();
|
|
2269
|
+
if (description.length < minLen) {
|
|
1960
2270
|
if (errorEl) {
|
|
1961
|
-
|
|
2271
|
+
const msg = `${t.step3.tooShort} (${description.length}/${minLen})`;
|
|
2272
|
+
errorEl.textContent = msg;
|
|
1962
2273
|
errorEl.style.display = "block";
|
|
2274
|
+
textarea2?.focus();
|
|
1963
2275
|
}
|
|
1964
2276
|
return;
|
|
1965
2277
|
}
|
|
@@ -2622,50 +2934,16 @@ function truncateUrl(url) {
|
|
|
2622
2934
|
function createScreenshotCapture(options = {}) {
|
|
2623
2935
|
let activeOptions = options;
|
|
2624
2936
|
async function take() {
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
const canvas = document.createElement("canvas");
|
|
2628
|
-
const ctx = canvas.getContext("2d");
|
|
2629
|
-
if (!ctx) return null;
|
|
2630
|
-
const width = window.innerWidth;
|
|
2631
|
-
const height = window.innerHeight;
|
|
2632
|
-
const dpr = Math.min(window.devicePixelRatio || 1, 2);
|
|
2633
|
-
canvas.width = width * dpr;
|
|
2634
|
-
canvas.height = height * dpr;
|
|
2635
|
-
ctx.scale(dpr, dpr);
|
|
2636
|
-
const safeDocument = buildPrivacySafeDocument(activeOptions.privacy);
|
|
2637
|
-
const svgData = `
|
|
2638
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}">
|
|
2639
|
-
<foreignObject width="100%" height="100%">
|
|
2640
|
-
<div xmlns="http://www.w3.org/1999/xhtml">
|
|
2641
|
-
${new XMLSerializer().serializeToString(safeDocument)}
|
|
2642
|
-
</div>
|
|
2643
|
-
</foreignObject>
|
|
2644
|
-
</svg>
|
|
2645
|
-
`;
|
|
2646
|
-
const img = new Image();
|
|
2647
|
-
const blob = new Blob([svgData], { type: "image/svg+xml;charset=utf-8" });
|
|
2648
|
-
const url = URL.createObjectURL(blob);
|
|
2649
|
-
return new Promise((resolve) => {
|
|
2650
|
-
img.onload = () => {
|
|
2651
|
-
ctx.drawImage(img, 0, 0, width, height);
|
|
2652
|
-
URL.revokeObjectURL(url);
|
|
2653
|
-
try {
|
|
2654
|
-
const dataUrl = canvas.toDataURL("image/jpeg", 0.7);
|
|
2655
|
-
resolve(dataUrl);
|
|
2656
|
-
} catch {
|
|
2657
|
-
resolve(null);
|
|
2658
|
-
}
|
|
2659
|
-
};
|
|
2660
|
-
img.onerror = () => {
|
|
2661
|
-
URL.revokeObjectURL(url);
|
|
2662
|
-
resolve(null);
|
|
2663
|
-
};
|
|
2664
|
-
img.src = url;
|
|
2665
|
-
});
|
|
2666
|
-
} catch {
|
|
2667
|
-
return null;
|
|
2937
|
+
if (typeof document === "undefined") {
|
|
2938
|
+
return { ok: false, reason: "unsupported", message: "Not in a browser context" };
|
|
2668
2939
|
}
|
|
2940
|
+
const svgResult = await trySvgCapture(activeOptions.privacy);
|
|
2941
|
+
if (svgResult.ok) return svgResult;
|
|
2942
|
+
if (svgResult.reason !== "unsupported") {
|
|
2943
|
+
const mediaResult = await tryDisplayMediaCapture();
|
|
2944
|
+
if (mediaResult.ok) return mediaResult;
|
|
2945
|
+
}
|
|
2946
|
+
return svgResult;
|
|
2669
2947
|
}
|
|
2670
2948
|
return {
|
|
2671
2949
|
take,
|
|
@@ -2674,8 +2952,110 @@ function createScreenshotCapture(options = {}) {
|
|
|
2674
2952
|
}
|
|
2675
2953
|
};
|
|
2676
2954
|
}
|
|
2955
|
+
async function trySvgCapture(privacy) {
|
|
2956
|
+
try {
|
|
2957
|
+
const canvas = document.createElement("canvas");
|
|
2958
|
+
const ctx = canvas.getContext("2d");
|
|
2959
|
+
if (!ctx) return { ok: false, reason: "unsupported", message: "Canvas 2d context unavailable" };
|
|
2960
|
+
const width = window.innerWidth;
|
|
2961
|
+
const height = window.innerHeight;
|
|
2962
|
+
const dpr = Math.min(window.devicePixelRatio || 1, 2);
|
|
2963
|
+
canvas.width = width * dpr;
|
|
2964
|
+
canvas.height = height * dpr;
|
|
2965
|
+
ctx.scale(dpr, dpr);
|
|
2966
|
+
const safeDocument = buildPrivacySafeDocument(privacy);
|
|
2967
|
+
const svgData = `
|
|
2968
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}">
|
|
2969
|
+
<foreignObject width="100%" height="100%">
|
|
2970
|
+
<div xmlns="http://www.w3.org/1999/xhtml">
|
|
2971
|
+
${new XMLSerializer().serializeToString(safeDocument)}
|
|
2972
|
+
</div>
|
|
2973
|
+
</foreignObject>
|
|
2974
|
+
</svg>
|
|
2975
|
+
`;
|
|
2976
|
+
const img = new Image();
|
|
2977
|
+
const blob = new Blob([svgData], { type: "image/svg+xml;charset=utf-8" });
|
|
2978
|
+
const url = URL.createObjectURL(blob);
|
|
2979
|
+
const loadResult = await new Promise((resolve) => {
|
|
2980
|
+
img.onload = () => resolve("loaded");
|
|
2981
|
+
img.onerror = () => resolve("error");
|
|
2982
|
+
const timeout = setTimeout(() => resolve("error"), 5e3);
|
|
2983
|
+
img.onload = () => {
|
|
2984
|
+
clearTimeout(timeout);
|
|
2985
|
+
resolve("loaded");
|
|
2986
|
+
};
|
|
2987
|
+
});
|
|
2988
|
+
URL.revokeObjectURL(url);
|
|
2989
|
+
if (loadResult === "error") {
|
|
2990
|
+
return { ok: false, reason: "load-error", message: "SVG image load failed" };
|
|
2991
|
+
}
|
|
2992
|
+
ctx.drawImage(img, 0, 0, width, height);
|
|
2993
|
+
try {
|
|
2994
|
+
const dataUrl = canvas.toDataURL("image/jpeg", 0.75);
|
|
2995
|
+
return { ok: true, dataUrl };
|
|
2996
|
+
} catch (err) {
|
|
2997
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2998
|
+
return { ok: false, reason: "tainted", message };
|
|
2999
|
+
}
|
|
3000
|
+
} catch (err) {
|
|
3001
|
+
return { ok: false, reason: "error", message: err instanceof Error ? err.message : String(err) };
|
|
3002
|
+
}
|
|
3003
|
+
}
|
|
3004
|
+
async function tryDisplayMediaCapture() {
|
|
3005
|
+
if (typeof navigator === "undefined" || !("mediaDevices" in navigator)) {
|
|
3006
|
+
return { ok: false, reason: "unsupported", message: "mediaDevices not available" };
|
|
3007
|
+
}
|
|
3008
|
+
const mediaDevices = navigator.mediaDevices;
|
|
3009
|
+
if (typeof mediaDevices.getDisplayMedia !== "function") {
|
|
3010
|
+
return { ok: false, reason: "unsupported", message: "getDisplayMedia not available" };
|
|
3011
|
+
}
|
|
3012
|
+
let stream = null;
|
|
3013
|
+
try {
|
|
3014
|
+
stream = await mediaDevices.getDisplayMedia({
|
|
3015
|
+
video: { displaySurface: "browser" },
|
|
3016
|
+
audio: false
|
|
3017
|
+
});
|
|
3018
|
+
const track = stream.getVideoTracks()[0];
|
|
3019
|
+
if (!track) return { ok: false, reason: "error", message: "No video track" };
|
|
3020
|
+
const imageCapture = new window.ImageCapture(track);
|
|
3021
|
+
const bitmap = await imageCapture.grabFrame();
|
|
3022
|
+
const canvas = document.createElement("canvas");
|
|
3023
|
+
canvas.width = bitmap.width;
|
|
3024
|
+
canvas.height = bitmap.height;
|
|
3025
|
+
const ctx = canvas.getContext("2d");
|
|
3026
|
+
ctx.drawImage(bitmap, 0, 0);
|
|
3027
|
+
bitmap.close();
|
|
3028
|
+
const dataUrl = canvas.toDataURL("image/jpeg", 0.85);
|
|
3029
|
+
return { ok: true, dataUrl };
|
|
3030
|
+
} catch (err) {
|
|
3031
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3032
|
+
if (err instanceof Error && err.name === "NotAllowedError") {
|
|
3033
|
+
return { ok: false, reason: "cancelled", message };
|
|
3034
|
+
}
|
|
3035
|
+
return { ok: false, reason: "error", message };
|
|
3036
|
+
} finally {
|
|
3037
|
+
stream?.getTracks().forEach((t) => t.stop());
|
|
3038
|
+
}
|
|
3039
|
+
}
|
|
2677
3040
|
function buildPrivacySafeDocument(privacy) {
|
|
2678
3041
|
const clone = document.documentElement.cloneNode(true);
|
|
3042
|
+
for (const img of Array.from(clone.querySelectorAll("img[src]"))) {
|
|
3043
|
+
const src = img.getAttribute("src") ?? "";
|
|
3044
|
+
try {
|
|
3045
|
+
const url = new URL(src, window.location.href);
|
|
3046
|
+
if (url.origin !== window.location.origin) {
|
|
3047
|
+
img.removeAttribute("src");
|
|
3048
|
+
img.removeAttribute("srcset");
|
|
3049
|
+
}
|
|
3050
|
+
} catch {
|
|
3051
|
+
}
|
|
3052
|
+
}
|
|
3053
|
+
for (const el of Array.from(clone.querySelectorAll("[style]"))) {
|
|
3054
|
+
const style = el.getAttribute("style") ?? "";
|
|
3055
|
+
if (/url\(["']?https?:\/\/(?!localhost)/.test(style)) {
|
|
3056
|
+
el.setAttribute("style", style.replace(/url\([^)]*\)/g, "none"));
|
|
3057
|
+
}
|
|
3058
|
+
}
|
|
2679
3059
|
for (const selector of privacy?.blockSelectors ?? []) {
|
|
2680
3060
|
for (const el of safeQueryAll(clone, selector)) {
|
|
2681
3061
|
el.remove();
|
|
@@ -2872,6 +3252,11 @@ function createElementSelector() {
|
|
|
2872
3252
|
e.stopPropagation();
|
|
2873
3253
|
const target = e.target;
|
|
2874
3254
|
if (target === overlay) return;
|
|
3255
|
+
const path = e.composedPath ? e.composedPath() : [];
|
|
3256
|
+
const hitsMushiHost = path.some(
|
|
3257
|
+
(node) => node instanceof Element && node.id === "mushi-mushi-widget"
|
|
3258
|
+
);
|
|
3259
|
+
if (hitsMushiHost) return;
|
|
2875
3260
|
const captured = captureElement(target);
|
|
2876
3261
|
finish(captured);
|
|
2877
3262
|
}
|
|
@@ -3586,7 +3971,7 @@ function createProactiveManager(config = {}) {
|
|
|
3586
3971
|
|
|
3587
3972
|
// src/version.ts
|
|
3588
3973
|
var MUSHI_SDK_PACKAGE = "@mushi-mushi/web";
|
|
3589
|
-
var MUSHI_SDK_VERSION = "1.
|
|
3974
|
+
var MUSHI_SDK_VERSION = "1.3.0" ;
|
|
3590
3975
|
|
|
3591
3976
|
// src/mushi.ts
|
|
3592
3977
|
var instance = null;
|
|
@@ -3791,8 +4176,21 @@ function createInstance(config) {
|
|
|
3791
4176
|
onScreenshotRequest: async () => {
|
|
3792
4177
|
if (!screenshotCap || activeConfig.capture?.screenshot === "off") return;
|
|
3793
4178
|
log.debug("Taking screenshot");
|
|
3794
|
-
|
|
3795
|
-
|
|
4179
|
+
widget.setScreenshotCapturing(true);
|
|
4180
|
+
const result = await screenshotCap.take();
|
|
4181
|
+
if (result.ok) {
|
|
4182
|
+
pendingScreenshot = result.dataUrl;
|
|
4183
|
+
widget.setScreenshotAttached(true);
|
|
4184
|
+
log.debug("Screenshot captured");
|
|
4185
|
+
} else {
|
|
4186
|
+
pendingScreenshot = null;
|
|
4187
|
+
if (result.reason !== "cancelled") {
|
|
4188
|
+
widget.setScreenshotError(true);
|
|
4189
|
+
log.debug("Screenshot failed", { reason: result.reason, message: result.message });
|
|
4190
|
+
} else {
|
|
4191
|
+
widget.setScreenshotCapturing(false);
|
|
4192
|
+
}
|
|
4193
|
+
}
|
|
3796
4194
|
},
|
|
3797
4195
|
onScreenshotRemove: () => {
|
|
3798
4196
|
log.debug("Screenshot attachment removed");
|
|
@@ -3802,11 +4200,19 @@ function createInstance(config) {
|
|
|
3802
4200
|
onElementSelectorRequest: async () => {
|
|
3803
4201
|
if (!elementSelector || activeConfig.capture?.elementSelector === false) return;
|
|
3804
4202
|
log.debug("Element selector activated");
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
4203
|
+
widget.setElementCapturing(true);
|
|
4204
|
+
widget.hidePanel();
|
|
4205
|
+
try {
|
|
4206
|
+
const el = await elementSelector.activate();
|
|
4207
|
+
if (el) {
|
|
4208
|
+
pendingElement = el;
|
|
4209
|
+
widget.setElementSelected(true);
|
|
4210
|
+
log.debug("Element selected", { tagName: el.tagName, xpath: el.xpath });
|
|
4211
|
+
} else {
|
|
4212
|
+
widget.setElementCapturing(false);
|
|
4213
|
+
}
|
|
4214
|
+
} finally {
|
|
4215
|
+
widget.showPanel();
|
|
3810
4216
|
}
|
|
3811
4217
|
},
|
|
3812
4218
|
async onReporterReportsRequest() {
|