@mushi-mushi/web 1.7.2 → 1.7.6
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 +61 -1
- package/dist/index.cjs +279 -126
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +51 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.js +280 -127
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -265,9 +265,9 @@ function getWidgetStyles(theme) {
|
|
|
265
265
|
const inkFaint = isDark ? "#5A5650" : "#9A9489";
|
|
266
266
|
const rule = isDark ? "rgba(242,235,221,0.10)" : "rgba(14,13,11,0.10)";
|
|
267
267
|
const ruleStrong = isDark ? "rgba(242,235,221,0.18)" : "rgba(14,13,11,0.16)";
|
|
268
|
-
const
|
|
269
|
-
const
|
|
270
|
-
const
|
|
268
|
+
const widgetAccent = isDark ? "#FF5A47" : "#E03C2C";
|
|
269
|
+
const widgetAccentWash = isDark ? "rgba(255,90,71,0.12)" : "rgba(224,60,44,0.08)";
|
|
270
|
+
const widgetAccentInk = isDark ? "#FFE5E0" : "#7A1F15";
|
|
271
271
|
const fontDisplay = `'Iowan Old Style', 'Palatino Linotype', 'Palatino', 'Book Antiqua', 'Cambria', Georgia, 'Times New Roman', serif`;
|
|
272
272
|
const fontBody = `system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI Variable Display', 'Segoe UI', sans-serif`;
|
|
273
273
|
const fontMono = `ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, Consolas, 'Liberation Mono', monospace`;
|
|
@@ -283,6 +283,17 @@ function getWidgetStyles(theme) {
|
|
|
283
283
|
-moz-osx-font-smoothing: grayscale;
|
|
284
284
|
font-feature-settings: 'ss01', 'cv11'; /* nicer system-ui glyphs where supported */
|
|
285
285
|
--mushi-ok: ${isDark ? "#4ade80" : "#16a34a"};
|
|
286
|
+
/* SDK contract: the host element is always pass-through. Only the
|
|
287
|
+
interactive surfaces (.mushi-trigger, .mushi-banner, .mushi-panel)
|
|
288
|
+
opt back into pointer events so the widget never creates an
|
|
289
|
+
invisible touch blocker over host-app UI. */
|
|
290
|
+
pointer-events: none;
|
|
291
|
+
}
|
|
292
|
+
/* Only actual widget controls receive touch/mouse events. */
|
|
293
|
+
.mushi-trigger,
|
|
294
|
+
.mushi-banner,
|
|
295
|
+
.mushi-panel {
|
|
296
|
+
pointer-events: auto;
|
|
286
297
|
}
|
|
287
298
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
288
299
|
button { font-family: inherit; }
|
|
@@ -305,7 +316,7 @@ function getWidgetStyles(theme) {
|
|
|
305
316
|
box-shadow:
|
|
306
317
|
0 1px 0 ${rule},
|
|
307
318
|
0 6px 14px -8px rgba(14,13,11,0.35),
|
|
308
|
-
inset 0 -3px 0 ${
|
|
319
|
+
inset 0 -3px 0 ${widgetAccent};
|
|
309
320
|
transition: transform 200ms ${easeStamp}, box-shadow 200ms ${easeStamp};
|
|
310
321
|
overflow: visible;
|
|
311
322
|
isolation: isolate;
|
|
@@ -318,8 +329,8 @@ function getWidgetStyles(theme) {
|
|
|
318
329
|
width: 6px;
|
|
319
330
|
height: 6px;
|
|
320
331
|
border-radius: 50%;
|
|
321
|
-
background: ${
|
|
322
|
-
box-shadow: 0 0 0 0 ${
|
|
332
|
+
background: ${widgetAccent};
|
|
333
|
+
box-shadow: 0 0 0 0 ${widgetAccent};
|
|
323
334
|
animation: mushi-pulse 2.4s ${easeStamp} infinite;
|
|
324
335
|
}
|
|
325
336
|
.mushi-trigger:hover {
|
|
@@ -327,17 +338,17 @@ function getWidgetStyles(theme) {
|
|
|
327
338
|
box-shadow:
|
|
328
339
|
0 1px 0 ${rule},
|
|
329
340
|
0 14px 24px -10px rgba(14,13,11,0.45),
|
|
330
|
-
inset 0 -3px 0 ${
|
|
341
|
+
inset 0 -3px 0 ${widgetAccent};
|
|
331
342
|
}
|
|
332
343
|
.mushi-trigger:active {
|
|
333
344
|
transform: translateY(0) rotate(0);
|
|
334
345
|
box-shadow:
|
|
335
346
|
0 1px 0 ${rule},
|
|
336
347
|
0 2px 4px -2px rgba(14,13,11,0.35),
|
|
337
|
-
inset 0 -2px 0 ${
|
|
348
|
+
inset 0 -2px 0 ${widgetAccent};
|
|
338
349
|
}
|
|
339
350
|
.mushi-trigger:focus-visible {
|
|
340
|
-
outline: 2px solid ${
|
|
351
|
+
outline: 2px solid ${widgetAccent};
|
|
341
352
|
outline-offset: 3px;
|
|
342
353
|
}
|
|
343
354
|
/* First-session welcome pulse. Three soft halos at 800ms each, then
|
|
@@ -381,7 +392,7 @@ function getWidgetStyles(theme) {
|
|
|
381
392
|
box-shadow:
|
|
382
393
|
0 1px 0 ${rule},
|
|
383
394
|
0 10px 24px -14px rgba(14,13,11,0.45),
|
|
384
|
-
inset -3px 0 0 ${
|
|
395
|
+
inset -3px 0 0 ${widgetAccent};
|
|
385
396
|
}
|
|
386
397
|
.mushi-trigger.edge-tab.bottom-right,
|
|
387
398
|
.mushi-trigger.edge-tab.top-right {
|
|
@@ -394,7 +405,7 @@ function getWidgetStyles(theme) {
|
|
|
394
405
|
box-shadow:
|
|
395
406
|
0 1px 0 ${rule},
|
|
396
407
|
0 10px 24px -14px rgba(14,13,11,0.45),
|
|
397
|
-
inset 3px 0 0 ${
|
|
408
|
+
inset 3px 0 0 ${widgetAccent};
|
|
398
409
|
}
|
|
399
410
|
.mushi-trigger.shrunk {
|
|
400
411
|
width: 36px;
|
|
@@ -404,7 +415,7 @@ function getWidgetStyles(theme) {
|
|
|
404
415
|
}
|
|
405
416
|
|
|
406
417
|
@keyframes mushi-pulse {
|
|
407
|
-
0% { box-shadow: 0 0 0 0 ${
|
|
418
|
+
0% { box-shadow: 0 0 0 0 ${widgetAccent}; opacity: 1; }
|
|
408
419
|
70% { box-shadow: 0 0 0 8px rgba(224,60,44,0); opacity: 0.5; }
|
|
409
420
|
100% { box-shadow: 0 0 0 0 rgba(224,60,44,0); opacity: 1; }
|
|
410
421
|
}
|
|
@@ -451,9 +462,9 @@ function getWidgetStyles(theme) {
|
|
|
451
462
|
.mushi-outdated {
|
|
452
463
|
margin: 12px 14px 0;
|
|
453
464
|
padding: 10px 12px;
|
|
454
|
-
border: 1px solid ${
|
|
455
|
-
background: ${
|
|
456
|
-
color: ${
|
|
465
|
+
border: 1px solid ${widgetAccentWash};
|
|
466
|
+
background: ${widgetAccentWash};
|
|
467
|
+
color: ${widgetAccentInk};
|
|
457
468
|
font-family: ${fontBody};
|
|
458
469
|
font-size: 12px;
|
|
459
470
|
line-height: 1.4;
|
|
@@ -493,7 +504,7 @@ function getWidgetStyles(theme) {
|
|
|
493
504
|
width: 22px;
|
|
494
505
|
height: 22px;
|
|
495
506
|
border-radius: 3px;
|
|
496
|
-
background: ${
|
|
507
|
+
background: ${widgetAccent};
|
|
497
508
|
color: #FAF7F0;
|
|
498
509
|
font-family: ${fontDisplay};
|
|
499
510
|
font-size: 14px;
|
|
@@ -554,9 +565,9 @@ function getWidgetStyles(theme) {
|
|
|
554
565
|
border-radius: 3px;
|
|
555
566
|
transition: color 150ms ${easeStamp};
|
|
556
567
|
}
|
|
557
|
-
.mushi-close:hover, .mushi-back:hover { color: ${
|
|
568
|
+
.mushi-close:hover, .mushi-back:hover { color: ${widgetAccent}; }
|
|
558
569
|
.mushi-close:focus-visible, .mushi-back:focus-visible {
|
|
559
|
-
outline: 1.5px solid ${
|
|
570
|
+
outline: 1.5px solid ${widgetAccent};
|
|
560
571
|
outline-offset: 2px;
|
|
561
572
|
}
|
|
562
573
|
|
|
@@ -591,12 +602,12 @@ function getWidgetStyles(theme) {
|
|
|
591
602
|
position: relative;
|
|
592
603
|
}
|
|
593
604
|
.mushi-option-btn:last-child { border-bottom: none; }
|
|
594
|
-
.mushi-option-btn:hover { padding-left: 6px; color: ${
|
|
595
|
-
.mushi-option-btn:hover .mushi-option-arrow { opacity: 1; transform: translateX(0); color: ${
|
|
605
|
+
.mushi-option-btn:hover { padding-left: 6px; color: ${widgetAccent}; }
|
|
606
|
+
.mushi-option-btn:hover .mushi-option-arrow { opacity: 1; transform: translateX(0); color: ${widgetAccent}; }
|
|
596
607
|
.mushi-option-btn:focus-visible {
|
|
597
608
|
outline: none;
|
|
598
609
|
padding-left: 6px;
|
|
599
|
-
box-shadow: inset 2px 0 0 ${
|
|
610
|
+
box-shadow: inset 2px 0 0 ${widgetAccent};
|
|
600
611
|
}
|
|
601
612
|
.mushi-option-icon {
|
|
602
613
|
font-size: 18px;
|
|
@@ -638,7 +649,7 @@ function getWidgetStyles(theme) {
|
|
|
638
649
|
}
|
|
639
650
|
.mushi-feature-entry:hover,
|
|
640
651
|
.mushi-reports-entry:hover {
|
|
641
|
-
border-left-color: ${
|
|
652
|
+
border-left-color: ${widgetAccent};
|
|
642
653
|
padding-left: 14px;
|
|
643
654
|
}
|
|
644
655
|
.mushi-feature-entry .mushi-option-icon {
|
|
@@ -661,7 +672,7 @@ function getWidgetStyles(theme) {
|
|
|
661
672
|
.mushi-report-status {
|
|
662
673
|
font-family: ${fontMono};
|
|
663
674
|
font-size: 10px;
|
|
664
|
-
color: ${
|
|
675
|
+
color: ${widgetAccent};
|
|
665
676
|
text-transform: uppercase;
|
|
666
677
|
}
|
|
667
678
|
.mushi-report-title {
|
|
@@ -678,7 +689,7 @@ function getWidgetStyles(theme) {
|
|
|
678
689
|
.mushi-thread-summary span {
|
|
679
690
|
font-family: ${fontMono};
|
|
680
691
|
font-size: 10px;
|
|
681
|
-
color: ${
|
|
692
|
+
color: ${widgetAccent};
|
|
682
693
|
text-transform: uppercase;
|
|
683
694
|
}
|
|
684
695
|
.mushi-thread {
|
|
@@ -694,8 +705,8 @@ function getWidgetStyles(theme) {
|
|
|
694
705
|
background: ${isDark ? "rgba(242,235,221,0.04)" : "rgba(14,13,11,0.03)"};
|
|
695
706
|
}
|
|
696
707
|
.mushi-thread-comment.reporter {
|
|
697
|
-
border-color: ${
|
|
698
|
-
background: ${
|
|
708
|
+
border-color: ${widgetAccentWash};
|
|
709
|
+
background: ${widgetAccentWash};
|
|
699
710
|
}
|
|
700
711
|
.mushi-thread-comment strong {
|
|
701
712
|
display: block;
|
|
@@ -712,16 +723,16 @@ function getWidgetStyles(theme) {
|
|
|
712
723
|
color: ${inkMuted};
|
|
713
724
|
line-height: 1.45;
|
|
714
725
|
}
|
|
715
|
-
.mushi-error-inline { color: ${
|
|
726
|
+
.mushi-error-inline { color: ${widgetAccent}; }
|
|
716
727
|
|
|
717
728
|
.mushi-selected-category {
|
|
718
729
|
display: inline-flex;
|
|
719
730
|
align-items: center;
|
|
720
731
|
gap: 8px;
|
|
721
732
|
padding: 6px 10px 6px 12px;
|
|
722
|
-
border-left: 2px solid ${
|
|
723
|
-
background: ${
|
|
724
|
-
color: ${
|
|
733
|
+
border-left: 2px solid ${widgetAccent};
|
|
734
|
+
background: ${widgetAccentWash};
|
|
735
|
+
color: ${widgetAccentInk};
|
|
725
736
|
font-family: ${fontMono};
|
|
726
737
|
font-size: 11px;
|
|
727
738
|
letter-spacing: 0.12em;
|
|
@@ -761,12 +772,12 @@ function getWidgetStyles(theme) {
|
|
|
761
772
|
transition: opacity 220ms ${easeStamp}, transform 220ms ${easeStamp};
|
|
762
773
|
}
|
|
763
774
|
.mushi-intent-btn:last-child { border-bottom: none; }
|
|
764
|
-
.mushi-intent-btn:hover { padding-left: 6px; color: ${
|
|
765
|
-
.mushi-intent-btn:hover::after { opacity: 1; transform: translateX(0); color: ${
|
|
775
|
+
.mushi-intent-btn:hover { padding-left: 6px; color: ${widgetAccent}; }
|
|
776
|
+
.mushi-intent-btn:hover::after { opacity: 1; transform: translateX(0); color: ${widgetAccent}; }
|
|
766
777
|
.mushi-intent-btn:focus-visible {
|
|
767
778
|
outline: none;
|
|
768
779
|
padding-left: 6px;
|
|
769
|
-
box-shadow: inset 2px 0 0 ${
|
|
780
|
+
box-shadow: inset 2px 0 0 ${widgetAccent};
|
|
770
781
|
}
|
|
771
782
|
|
|
772
783
|
/* Example starter chips \u2014 reduce first-report activation energy */
|
|
@@ -794,7 +805,7 @@ function getWidgetStyles(theme) {
|
|
|
794
805
|
background: ${isDark ? "rgba(242,235,221,0.06)" : "rgba(14,13,11,0.04)"};
|
|
795
806
|
}
|
|
796
807
|
.mushi-example-chip:focus-visible {
|
|
797
|
-
outline: 2px solid ${
|
|
808
|
+
outline: 2px solid ${widgetAccent};
|
|
798
809
|
outline-offset: 2px;
|
|
799
810
|
}
|
|
800
811
|
|
|
@@ -833,7 +844,7 @@ function getWidgetStyles(theme) {
|
|
|
833
844
|
color: ${inkFaint};
|
|
834
845
|
font-style: italic;
|
|
835
846
|
}
|
|
836
|
-
.mushi-textarea:focus { border-bottom-color: ${
|
|
847
|
+
.mushi-textarea:focus { border-bottom-color: ${widgetAccent}; }
|
|
837
848
|
|
|
838
849
|
.mushi-attachments {
|
|
839
850
|
display: flex;
|
|
@@ -862,30 +873,30 @@ function getWidgetStyles(theme) {
|
|
|
862
873
|
border-color: ${ink};
|
|
863
874
|
}
|
|
864
875
|
.mushi-attach-btn.active {
|
|
865
|
-
color: ${
|
|
866
|
-
border-color: ${
|
|
867
|
-
background: ${
|
|
876
|
+
color: ${widgetAccent};
|
|
877
|
+
border-color: ${widgetAccent};
|
|
878
|
+
background: ${widgetAccentWash};
|
|
868
879
|
}
|
|
869
880
|
.mushi-attach-btn.danger {
|
|
870
|
-
color: ${
|
|
871
|
-
border-color: ${
|
|
881
|
+
color: ${widgetAccentInk};
|
|
882
|
+
border-color: ${widgetAccentWash};
|
|
872
883
|
background: transparent;
|
|
873
884
|
}
|
|
874
885
|
.mushi-attach-btn.danger:hover {
|
|
875
|
-
color: ${
|
|
876
|
-
border-color: ${
|
|
877
|
-
background: ${
|
|
886
|
+
color: ${widgetAccent};
|
|
887
|
+
border-color: ${widgetAccent};
|
|
888
|
+
background: ${widgetAccentWash};
|
|
878
889
|
}
|
|
879
890
|
.mushi-attach-btn.loading {
|
|
880
891
|
opacity: 0.7;
|
|
881
892
|
cursor: wait;
|
|
882
893
|
}
|
|
883
894
|
.mushi-attach-btn.error {
|
|
884
|
-
color: ${
|
|
885
|
-
border-color: ${
|
|
895
|
+
color: ${widgetAccent};
|
|
896
|
+
border-color: ${widgetAccentWash};
|
|
886
897
|
}
|
|
887
898
|
.mushi-attach-btn:focus-visible {
|
|
888
|
-
outline: 2px solid ${
|
|
899
|
+
outline: 2px solid ${widgetAccent};
|
|
889
900
|
outline-offset: 2px;
|
|
890
901
|
}
|
|
891
902
|
@keyframes mushi-spin {
|
|
@@ -926,9 +937,9 @@ function getWidgetStyles(theme) {
|
|
|
926
937
|
align-items: center;
|
|
927
938
|
gap: 8px;
|
|
928
939
|
padding: 10px 18px;
|
|
929
|
-
border: 1px solid ${
|
|
940
|
+
border: 1px solid ${widgetAccent};
|
|
930
941
|
border-radius: 3px;
|
|
931
|
-
background: ${
|
|
942
|
+
background: ${widgetAccent};
|
|
932
943
|
color: #FAF7F0;
|
|
933
944
|
font-family: ${fontMono};
|
|
934
945
|
font-size: 11px;
|
|
@@ -960,7 +971,7 @@ function getWidgetStyles(theme) {
|
|
|
960
971
|
opacity: 0.7;
|
|
961
972
|
}
|
|
962
973
|
.mushi-submit:focus-visible {
|
|
963
|
-
outline: 2px solid ${
|
|
974
|
+
outline: 2px solid ${widgetAccent};
|
|
964
975
|
outline-offset: 3px;
|
|
965
976
|
}
|
|
966
977
|
.mushi-submit-arrow {
|
|
@@ -999,7 +1010,7 @@ function getWidgetStyles(theme) {
|
|
|
999
1010
|
}
|
|
1000
1011
|
.mushi-step-num.done { color: ${inkMuted}; text-decoration: line-through; text-decoration-color: ${inkFaint}; }
|
|
1001
1012
|
.mushi-step-num.active {
|
|
1002
|
-
color: ${
|
|
1013
|
+
color: ${widgetAccent};
|
|
1003
1014
|
font-family: ${fontDisplay};
|
|
1004
1015
|
font-size: 14px;
|
|
1005
1016
|
font-weight: 600;
|
|
@@ -1028,7 +1039,7 @@ function getWidgetStyles(theme) {
|
|
|
1028
1039
|
}
|
|
1029
1040
|
.mushi-success-stamp circle {
|
|
1030
1041
|
fill: none;
|
|
1031
|
-
stroke: ${
|
|
1042
|
+
stroke: ${widgetAccent};
|
|
1032
1043
|
stroke-width: 3;
|
|
1033
1044
|
stroke-dasharray: 280;
|
|
1034
1045
|
stroke-dashoffset: 280;
|
|
@@ -1040,7 +1051,7 @@ function getWidgetStyles(theme) {
|
|
|
1040
1051
|
font-family: ${fontDisplay};
|
|
1041
1052
|
font-size: 18px;
|
|
1042
1053
|
font-weight: 600;
|
|
1043
|
-
color: ${
|
|
1054
|
+
color: ${widgetAccent};
|
|
1044
1055
|
letter-spacing: 0.04em;
|
|
1045
1056
|
transform: rotate(-6deg);
|
|
1046
1057
|
opacity: 0;
|
|
@@ -1108,8 +1119,8 @@ function getWidgetStyles(theme) {
|
|
|
1108
1119
|
.mushi-success-receipt-id:hover,
|
|
1109
1120
|
.mushi-success-receipt-id:focus-visible {
|
|
1110
1121
|
background: rgba(217, 65, 47, 0.06);
|
|
1111
|
-
border-color: ${
|
|
1112
|
-
color: ${
|
|
1122
|
+
border-color: ${widgetAccent};
|
|
1123
|
+
color: ${widgetAccent};
|
|
1113
1124
|
outline: none;
|
|
1114
1125
|
}
|
|
1115
1126
|
.mushi-success-receipt-copy {
|
|
@@ -1123,7 +1134,7 @@ function getWidgetStyles(theme) {
|
|
|
1123
1134
|
gap: 4px;
|
|
1124
1135
|
padding: 6px 10px;
|
|
1125
1136
|
border-radius: 4px;
|
|
1126
|
-
background: ${
|
|
1137
|
+
background: ${widgetAccent};
|
|
1127
1138
|
color: #fff;
|
|
1128
1139
|
font-family: ${fontMono};
|
|
1129
1140
|
font-size: 11px;
|
|
@@ -1142,7 +1153,7 @@ function getWidgetStyles(theme) {
|
|
|
1142
1153
|
height: 11px;
|
|
1143
1154
|
border-radius: 50%;
|
|
1144
1155
|
border: 1.5px solid ${rule};
|
|
1145
|
-
border-top-color: ${
|
|
1156
|
+
border-top-color: ${widgetAccent};
|
|
1146
1157
|
animation: mushi-receipt-spin 0.8s linear infinite;
|
|
1147
1158
|
}
|
|
1148
1159
|
@keyframes mushi-receipt-spin {
|
|
@@ -1153,7 +1164,7 @@ function getWidgetStyles(theme) {
|
|
|
1153
1164
|
font-style: italic;
|
|
1154
1165
|
}
|
|
1155
1166
|
.mushi-success-receipt-warn {
|
|
1156
|
-
color: ${
|
|
1167
|
+
color: ${widgetAccent};
|
|
1157
1168
|
}
|
|
1158
1169
|
.mushi-success-sla {
|
|
1159
1170
|
margin-top: 2px;
|
|
@@ -1180,8 +1191,8 @@ function getWidgetStyles(theme) {
|
|
|
1180
1191
|
.mushi-error {
|
|
1181
1192
|
margin-top: 10px;
|
|
1182
1193
|
padding: 8px 0 8px 10px;
|
|
1183
|
-
border-left: 2px solid ${
|
|
1184
|
-
color: ${
|
|
1194
|
+
border-left: 2px solid ${widgetAccent};
|
|
1195
|
+
color: ${widgetAccent};
|
|
1185
1196
|
font-size: 12px;
|
|
1186
1197
|
font-family: ${fontMono};
|
|
1187
1198
|
letter-spacing: 0.02em;
|
|
@@ -1221,7 +1232,7 @@ function getWidgetStyles(theme) {
|
|
|
1221
1232
|
.mushi-rewards-pts-earn {
|
|
1222
1233
|
font-family: ${fontMono};
|
|
1223
1234
|
font-size: 10px;
|
|
1224
|
-
color: ${
|
|
1235
|
+
color: ${widgetAccent};
|
|
1225
1236
|
letter-spacing: 0.04em;
|
|
1226
1237
|
white-space: nowrap;
|
|
1227
1238
|
}
|
|
@@ -1234,7 +1245,7 @@ function getWidgetStyles(theme) {
|
|
|
1234
1245
|
}
|
|
1235
1246
|
.mushi-tier-bar-fill {
|
|
1236
1247
|
height: 100%;
|
|
1237
|
-
background: ${
|
|
1248
|
+
background: ${widgetAccent};
|
|
1238
1249
|
border-radius: 2px;
|
|
1239
1250
|
transition: width 600ms ${easeStamp};
|
|
1240
1251
|
}
|
|
@@ -1257,7 +1268,7 @@ function getWidgetStyles(theme) {
|
|
|
1257
1268
|
font-family: ${fontMono};
|
|
1258
1269
|
font-size: 22px;
|
|
1259
1270
|
font-weight: 700;
|
|
1260
|
-
color: ${
|
|
1271
|
+
color: ${widgetAccent};
|
|
1261
1272
|
text-align: center;
|
|
1262
1273
|
letter-spacing: 0.06em;
|
|
1263
1274
|
margin-bottom: 10px;
|
|
@@ -1272,13 +1283,17 @@ function getWidgetStyles(theme) {
|
|
|
1272
1283
|
}
|
|
1273
1284
|
|
|
1274
1285
|
/* \u2500\u2500\u2500 Beta mode strip (category step) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
1286
|
+
/* Brand palette: widgetAccent (vermillion) + washi ink for the strip.
|
|
1287
|
+
The previous indigo (#6366f1) is the single most recognisable AI-template
|
|
1288
|
+
colour; replaced with the widget's own vermillion wash so the beta panel
|
|
1289
|
+
reads as a Mushi-native surface rather than a generic SaaS plug-in. */
|
|
1275
1290
|
|
|
1276
1291
|
.mushi-beta-strip {
|
|
1277
1292
|
margin: 0 16px 2px;
|
|
1278
1293
|
padding: 9px 12px;
|
|
1279
|
-
background:
|
|
1280
|
-
border: 1px solid rgba(
|
|
1281
|
-
border-radius:
|
|
1294
|
+
background: ${widgetAccentWash};
|
|
1295
|
+
border: 1px solid ${isDark ? "rgba(255,90,71,0.22)" : "rgba(224,60,44,0.16)"};
|
|
1296
|
+
border-radius: 4px;
|
|
1282
1297
|
display: flex;
|
|
1283
1298
|
flex-direction: column;
|
|
1284
1299
|
gap: 4px;
|
|
@@ -1294,38 +1309,30 @@ function getWidgetStyles(theme) {
|
|
|
1294
1309
|
display: inline-flex;
|
|
1295
1310
|
align-items: center;
|
|
1296
1311
|
padding: 1px 6px;
|
|
1297
|
-
border-radius:
|
|
1298
|
-
background:
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
font-family: var(--mushi-font-mono);
|
|
1312
|
+
border-radius: 3px;
|
|
1313
|
+
background: ${widgetAccent};
|
|
1314
|
+
color: #FAF7F0;
|
|
1315
|
+
font-family: ${fontMono};
|
|
1302
1316
|
font-size: 9px;
|
|
1303
1317
|
font-weight: 700;
|
|
1304
|
-
letter-spacing: 0.
|
|
1318
|
+
letter-spacing: 0.14em;
|
|
1305
1319
|
line-height: 1.6;
|
|
1306
1320
|
white-space: nowrap;
|
|
1307
1321
|
flex-shrink: 0;
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
@media (prefers-color-scheme: dark) {
|
|
1311
|
-
.mushi-beta-tag {
|
|
1312
|
-
background: rgba(245, 158, 11, 0.12);
|
|
1313
|
-
border-color: rgba(245, 158, 11, 0.28);
|
|
1314
|
-
color: #fbbf24;
|
|
1315
|
-
}
|
|
1322
|
+
text-transform: uppercase;
|
|
1316
1323
|
}
|
|
1317
1324
|
|
|
1318
1325
|
.mushi-beta-msg {
|
|
1319
1326
|
font-size: 11px;
|
|
1320
|
-
color:
|
|
1327
|
+
color: ${inkMuted};
|
|
1321
1328
|
line-height: 1.45;
|
|
1322
1329
|
}
|
|
1323
1330
|
|
|
1324
1331
|
.mushi-beta-contact-hint {
|
|
1325
1332
|
font-size: 10px;
|
|
1326
|
-
color:
|
|
1327
|
-
|
|
1328
|
-
|
|
1333
|
+
color: ${inkFaint};
|
|
1334
|
+
font-family: ${fontMono};
|
|
1335
|
+
letter-spacing: 0.06em;
|
|
1329
1336
|
}
|
|
1330
1337
|
|
|
1331
1338
|
.mushi-beta-perks {
|
|
@@ -1339,16 +1346,10 @@ function getWidgetStyles(theme) {
|
|
|
1339
1346
|
|
|
1340
1347
|
.mushi-beta-perks li {
|
|
1341
1348
|
font-size: 10.5px;
|
|
1342
|
-
color:
|
|
1349
|
+
color: ${widgetAccentInk};
|
|
1343
1350
|
font-weight: 500;
|
|
1344
1351
|
}
|
|
1345
1352
|
|
|
1346
|
-
@media (prefers-color-scheme: dark) {
|
|
1347
|
-
.mushi-beta-perks li {
|
|
1348
|
-
color: #818cf8;
|
|
1349
|
-
}
|
|
1350
|
-
}
|
|
1351
|
-
|
|
1352
1353
|
/* \u2500\u2500\u2500 Beta changelog (collapsible What's new) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
1353
1354
|
|
|
1354
1355
|
.mushi-changelog {
|
|
@@ -1397,9 +1398,9 @@ function getWidgetStyles(theme) {
|
|
|
1397
1398
|
.mushi-beta-success-footer {
|
|
1398
1399
|
margin-top: 14px;
|
|
1399
1400
|
padding: 10px 14px;
|
|
1400
|
-
background:
|
|
1401
|
-
border: 1px solid rgba(
|
|
1402
|
-
border-radius:
|
|
1401
|
+
background: ${widgetAccentWash};
|
|
1402
|
+
border: 1px solid ${isDark ? "rgba(255,90,71,0.18)" : "rgba(224,60,44,0.14)"};
|
|
1403
|
+
border-radius: 4px;
|
|
1403
1404
|
display: flex;
|
|
1404
1405
|
flex-direction: column;
|
|
1405
1406
|
gap: 3px;
|
|
@@ -1460,9 +1461,9 @@ function getWidgetStyles(theme) {
|
|
|
1460
1461
|
background: rgba(0,0,0,0.22);
|
|
1461
1462
|
}
|
|
1462
1463
|
|
|
1463
|
-
/* --- brand variant (
|
|
1464
|
+
/* --- brand variant (widgetAccent \u2014 editorial, app-quality) --- */
|
|
1464
1465
|
.mushi-banner.brand {
|
|
1465
|
-
background: ${
|
|
1466
|
+
background: ${widgetAccent};
|
|
1466
1467
|
color: #fff;
|
|
1467
1468
|
border-bottom: 1.5px solid ${isDark ? "#C4321E" : "#B52F1F"};
|
|
1468
1469
|
}
|
|
@@ -1479,23 +1480,29 @@ function getWidgetStyles(theme) {
|
|
|
1479
1480
|
background: rgba(255,255,255,0.28);
|
|
1480
1481
|
}
|
|
1481
1482
|
|
|
1482
|
-
/* --- subtle variant (
|
|
1483
|
+
/* --- subtle variant (frosted-glass, muted \u2014 least disruptive) ---
|
|
1484
|
+
Uses the widget's own paper colour at high opacity + backdrop-blur so
|
|
1485
|
+
it blends with the host app while remaining legible. The previous 4-6%
|
|
1486
|
+
opacity values were effectively invisible \u2014 users could not distinguish
|
|
1487
|
+
the banner from the page content below it. */
|
|
1483
1488
|
.mushi-banner.subtle {
|
|
1484
|
-
background: ${isDark ? "rgba(
|
|
1485
|
-
|
|
1486
|
-
|
|
1489
|
+
background: ${isDark ? "rgba(15,14,12,0.88)" : "rgba(248,244,237,0.92)"};
|
|
1490
|
+
backdrop-filter: blur(14px);
|
|
1491
|
+
-webkit-backdrop-filter: blur(14px);
|
|
1492
|
+
color: ${ink};
|
|
1493
|
+
border-bottom: 1px solid ${ruleStrong};
|
|
1487
1494
|
}
|
|
1488
1495
|
.mushi-banner.subtle.bottom {
|
|
1489
|
-
border-top: 1px solid ${
|
|
1496
|
+
border-top: 1px solid ${ruleStrong};
|
|
1490
1497
|
border-bottom: none;
|
|
1491
1498
|
}
|
|
1492
1499
|
.mushi-banner.subtle .mushi-banner-btn {
|
|
1493
|
-
background: ${isDark ? "rgba(242,235,221,0.10)" : "rgba(14,13,11,0.
|
|
1500
|
+
background: ${isDark ? "rgba(242,235,221,0.10)" : "rgba(14,13,11,0.08)"};
|
|
1494
1501
|
color: ${ink};
|
|
1495
|
-
border: 1px solid ${
|
|
1502
|
+
border: 1px solid ${ruleStrong};
|
|
1496
1503
|
}
|
|
1497
1504
|
.mushi-banner.subtle .mushi-banner-btn:hover {
|
|
1498
|
-
background: ${isDark ? "rgba(242,235,221,0.
|
|
1505
|
+
background: ${isDark ? "rgba(242,235,221,0.18)" : "rgba(14,13,11,0.14)"};
|
|
1499
1506
|
}
|
|
1500
1507
|
|
|
1501
1508
|
.mushi-banner-label {
|
|
@@ -1520,7 +1527,7 @@ function getWidgetStyles(theme) {
|
|
|
1520
1527
|
line-height: 1;
|
|
1521
1528
|
}
|
|
1522
1529
|
.mushi-banner-btn:focus-visible {
|
|
1523
|
-
outline: 2px solid ${
|
|
1530
|
+
outline: 2px solid ${widgetAccent};
|
|
1524
1531
|
outline-offset: 2px;
|
|
1525
1532
|
}
|
|
1526
1533
|
|
|
@@ -1631,7 +1638,8 @@ var MushiWidget = class _MushiWidget {
|
|
|
1631
1638
|
responseSlaLabel: config.responseSlaLabel ?? "",
|
|
1632
1639
|
featureRequestCard: config.featureRequestCard ?? true,
|
|
1633
1640
|
featureRequestLabel: config.featureRequestLabel ?? "",
|
|
1634
|
-
featureRequestDescription: config.featureRequestDescription ?? ""
|
|
1641
|
+
featureRequestDescription: config.featureRequestDescription ?? "",
|
|
1642
|
+
avoidSelectors: config.avoidSelectors ?? []
|
|
1635
1643
|
};
|
|
1636
1644
|
this.callbacks = callbacks;
|
|
1637
1645
|
this.locale = getLocale(this.config.locale === "auto" ? void 0 : this.config.locale);
|
|
@@ -1708,6 +1716,7 @@ var MushiWidget = class _MushiWidget {
|
|
|
1708
1716
|
bannerDismissed = false;
|
|
1709
1717
|
mount() {
|
|
1710
1718
|
if (this.host.isConnected) return;
|
|
1719
|
+
this.syncHostChromeState();
|
|
1711
1720
|
document.body.appendChild(this.host);
|
|
1712
1721
|
this.syncAttachedLaunchers();
|
|
1713
1722
|
this.syncSmartHide();
|
|
@@ -1748,6 +1757,7 @@ var MushiWidget = class _MushiWidget {
|
|
|
1748
1757
|
...config.featureRequestDescription !== void 0 ? { featureRequestDescription: config.featureRequestDescription } : {}
|
|
1749
1758
|
};
|
|
1750
1759
|
this.locale = getLocale(this.config.locale === "auto" ? void 0 : this.config.locale);
|
|
1760
|
+
if (this.host.isConnected) this.syncHostChromeState();
|
|
1751
1761
|
this.syncAttachedLaunchers();
|
|
1752
1762
|
this.syncSmartHide();
|
|
1753
1763
|
this.render();
|
|
@@ -1980,6 +1990,59 @@ var MushiWidget = class _MushiWidget {
|
|
|
1980
1990
|
this.removeBodyNudge();
|
|
1981
1991
|
this.host.remove();
|
|
1982
1992
|
}
|
|
1993
|
+
/* ── Host chrome contract ────────────────────────────────────────────────
|
|
1994
|
+
The host element must never create an invisible full-screen touch blocker.
|
|
1995
|
+
We own these inline styles — consumer CSS can only win with `!important`,
|
|
1996
|
+
which is explicitly banned by the SDK contract. Calling this at mount()
|
|
1997
|
+
and after every zIndex update is the only safe invariant. */
|
|
1998
|
+
/**
|
|
1999
|
+
* Apply the SDK-owned pass-through layout to the host element so it is
|
|
2000
|
+
* always zero-sized and click/touch-transparent. Only the shadow-root
|
|
2001
|
+
* internals (`.mushi-trigger`, `.mushi-banner`, `.mushi-panel`) opt back
|
|
2002
|
+
* into pointer events. This is idempotent and safe to call repeatedly.
|
|
2003
|
+
*/
|
|
2004
|
+
syncHostChromeState() {
|
|
2005
|
+
const s = this.host.style;
|
|
2006
|
+
s.setProperty("position", "fixed");
|
|
2007
|
+
s.setProperty("top", "0");
|
|
2008
|
+
s.setProperty("left", "0");
|
|
2009
|
+
s.setProperty("width", "0");
|
|
2010
|
+
s.setProperty("height", "0");
|
|
2011
|
+
s.setProperty("overflow", "visible");
|
|
2012
|
+
s.setProperty("pointer-events", "none");
|
|
2013
|
+
s.setProperty("z-index", String(this.config.zIndex));
|
|
2014
|
+
s.setProperty("margin", "0");
|
|
2015
|
+
s.setProperty("padding", "0");
|
|
2016
|
+
s.setProperty("border", "none");
|
|
2017
|
+
s.setProperty("background", "none");
|
|
2018
|
+
}
|
|
2019
|
+
/**
|
|
2020
|
+
* Returns true when a DOM element matching `hideOnSelector` is currently
|
|
2021
|
+
* present in the host document. Used by both the trigger and the banner
|
|
2022
|
+
* so a single selector consistently hides ALL SDK-injected launcher
|
|
2023
|
+
* surfaces. Invalid selectors are swallowed silently (non-fatal).
|
|
2024
|
+
*/
|
|
2025
|
+
isSuppressedByHost() {
|
|
2026
|
+
if (!this.config.hideOnSelector || typeof document === "undefined") return false;
|
|
2027
|
+
try {
|
|
2028
|
+
return Boolean(document.querySelector(this.config.hideOnSelector));
|
|
2029
|
+
} catch {
|
|
2030
|
+
return false;
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2033
|
+
/**
|
|
2034
|
+
* Returns a snapshot of the widget's host-layer health for use in
|
|
2035
|
+
* `Mushi.diagnose()`. Callers check this to know whether the widget
|
|
2036
|
+
* could ever block host-app UI without opening a browser devtools.
|
|
2037
|
+
*/
|
|
2038
|
+
getWidgetDiagnostics() {
|
|
2039
|
+
const s = this.host.style;
|
|
2040
|
+
const widgetHostPointerSafe = s.pointerEvents === "none" && (s.width === "0" || s.width === "0px") && (s.height === "0" || s.height === "0px");
|
|
2041
|
+
const widgetHostBounds = this.host.isConnected ? { width: this.host.offsetWidth, height: this.host.offsetHeight } : null;
|
|
2042
|
+
const widgetSuppressed = this.isSuppressedByHost() || this.isRouteHidden() || !this.triggerVisible;
|
|
2043
|
+
const bannerRendered = this.config.trigger === "banner" && !this.bannerDismissed && !this.isSuppressedByHost() && !this.isRouteHidden() && this.triggerVisible;
|
|
2044
|
+
return { widgetHostPointerSafe, widgetHostBounds, widgetSuppressed, bannerRendered };
|
|
2045
|
+
}
|
|
1983
2046
|
syncAttachedLaunchers() {
|
|
1984
2047
|
this.attachedLaunchers.forEach((cleanup) => cleanup());
|
|
1985
2048
|
this.attachedLaunchers = [];
|
|
@@ -2020,7 +2083,7 @@ var MushiWidget = class _MushiWidget {
|
|
|
2020
2083
|
}
|
|
2021
2084
|
if (this.isMobileSmartHidden()) return false;
|
|
2022
2085
|
if (this.isRouteHidden()) return false;
|
|
2023
|
-
if (this.
|
|
2086
|
+
if (this.isSuppressedByHost()) return false;
|
|
2024
2087
|
const action = this.config.environments[this.detectEnvironment()];
|
|
2025
2088
|
return action !== "never" && action !== "manual";
|
|
2026
2089
|
}
|
|
@@ -2069,6 +2132,10 @@ var MushiWidget = class _MushiWidget {
|
|
|
2069
2132
|
this.removeBodyNudge();
|
|
2070
2133
|
return;
|
|
2071
2134
|
}
|
|
2135
|
+
if (this.isSuppressedByHost()) {
|
|
2136
|
+
this.removeBodyNudge();
|
|
2137
|
+
return;
|
|
2138
|
+
}
|
|
2072
2139
|
const bc = this.config.bannerConfig ?? {};
|
|
2073
2140
|
const variant = bc.variant ?? "brand";
|
|
2074
2141
|
const position = bc.position ?? "top";
|
|
@@ -2187,6 +2254,32 @@ var MushiWidget = class _MushiWidget {
|
|
|
2187
2254
|
this.trapFocus(panel);
|
|
2188
2255
|
}
|
|
2189
2256
|
}
|
|
2257
|
+
/**
|
|
2258
|
+
* Queries each `avoidSelectors` element in the host document and returns
|
|
2259
|
+
* the minimum top-offset in px so that a top-anchored element clears all
|
|
2260
|
+
* of them by `gap` pixels. Returns `null` when no selectors are provided
|
|
2261
|
+
* or no matching elements have a non-zero bounding rect.
|
|
2262
|
+
*
|
|
2263
|
+
* Runs in the host document (not shadow DOM) so it can reach fixed headers,
|
|
2264
|
+
* sticky nav bars, and sign-in CTAs.
|
|
2265
|
+
*/
|
|
2266
|
+
computeAvoidTopPx(gap = 8) {
|
|
2267
|
+
const sels = this.config.avoidSelectors;
|
|
2268
|
+
if (!sels?.length) return null;
|
|
2269
|
+
let maxBottom = 0;
|
|
2270
|
+
for (const sel of sels) {
|
|
2271
|
+
try {
|
|
2272
|
+
const el = document.querySelector(sel);
|
|
2273
|
+
if (!el) continue;
|
|
2274
|
+
const r = el.getBoundingClientRect();
|
|
2275
|
+
if (r.bottom > maxBottom && r.width > 0 && r.height > 0) {
|
|
2276
|
+
maxBottom = r.bottom;
|
|
2277
|
+
}
|
|
2278
|
+
} catch {
|
|
2279
|
+
}
|
|
2280
|
+
}
|
|
2281
|
+
return maxBottom > 0 ? Math.ceil(maxBottom) + gap : null;
|
|
2282
|
+
}
|
|
2190
2283
|
applyInsetVars(el) {
|
|
2191
2284
|
const { anchor } = this.config;
|
|
2192
2285
|
if (anchor && Object.keys(anchor).length > 0) {
|
|
@@ -2195,20 +2288,27 @@ var MushiWidget = class _MushiWidget {
|
|
|
2195
2288
|
if (value !== void 0) el.style.setProperty(`--mushi-${edge}`, value);
|
|
2196
2289
|
});
|
|
2197
2290
|
el.style.setProperty("--mushi-safe-area", this.config.respectSafeArea ? "1" : "0");
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2291
|
+
} else {
|
|
2292
|
+
const { inset } = this.config;
|
|
2293
|
+
if (!this.config.respectSafeArea) {
|
|
2294
|
+
["top", "right", "bottom", "left"].forEach((edge) => {
|
|
2295
|
+
if (inset[edge] === void 0) el.style.setProperty(`--mushi-${edge}`, "24px");
|
|
2296
|
+
});
|
|
2297
|
+
}
|
|
2202
2298
|
["top", "right", "bottom", "left"].forEach((edge) => {
|
|
2203
|
-
|
|
2299
|
+
const value = inset[edge];
|
|
2300
|
+
if (value === void 0) return;
|
|
2301
|
+
el.style.setProperty(`--mushi-${edge}`, value === "auto" ? "auto" : `${value}px`);
|
|
2204
2302
|
});
|
|
2303
|
+
el.style.setProperty("--mushi-safe-area", this.config.respectSafeArea ? "1" : "0");
|
|
2304
|
+
}
|
|
2305
|
+
const isTopAnchored = anchor?.top !== void 0 || this.config.position?.startsWith("top") || !this.config.position && !anchor?.bottom;
|
|
2306
|
+
if (isTopAnchored) {
|
|
2307
|
+
const avoidPx = this.computeAvoidTopPx();
|
|
2308
|
+
if (avoidPx !== null) {
|
|
2309
|
+
el.style.setProperty("--mushi-top", `${avoidPx}px`);
|
|
2310
|
+
}
|
|
2205
2311
|
}
|
|
2206
|
-
["top", "right", "bottom", "left"].forEach((edge) => {
|
|
2207
|
-
const value = inset[edge];
|
|
2208
|
-
if (value === void 0) return;
|
|
2209
|
-
el.style.setProperty(`--mushi-${edge}`, value === "auto" ? "auto" : `${value}px`);
|
|
2210
|
-
});
|
|
2211
|
-
el.style.setProperty("--mushi-safe-area", this.config.respectSafeArea ? "1" : "0");
|
|
2212
2312
|
}
|
|
2213
2313
|
renderStep() {
|
|
2214
2314
|
switch (this.step) {
|
|
@@ -3042,6 +3142,15 @@ var optedIn = false;
|
|
|
3042
3142
|
var tierCache = null;
|
|
3043
3143
|
var tierCacheTime = 0;
|
|
3044
3144
|
var TIER_CACHE_TTL = 5 * 60 * 1e3;
|
|
3145
|
+
var rewardsApiBackoffUntil = 0;
|
|
3146
|
+
var REWARDS_4XX_BACKOFF_MS = 15 * 60 * 1e3;
|
|
3147
|
+
function isRewardsApiBackedOff() {
|
|
3148
|
+
return Date.now() < rewardsApiBackoffUntil;
|
|
3149
|
+
}
|
|
3150
|
+
function noteRewardsApiFailure(code) {
|
|
3151
|
+
if (!code?.startsWith("HTTP_4")) return;
|
|
3152
|
+
rewardsApiBackoffUntil = Date.now() + REWARDS_4XX_BACKOFF_MS;
|
|
3153
|
+
}
|
|
3045
3154
|
var seenRoutes = /* @__PURE__ */ new Set();
|
|
3046
3155
|
function getConsentKey(projectId) {
|
|
3047
3156
|
return `mushi_rewards_consent_${projectId}`;
|
|
@@ -3146,14 +3255,22 @@ async function flush(ctx) {
|
|
|
3146
3255
|
} catch {
|
|
3147
3256
|
}
|
|
3148
3257
|
}
|
|
3258
|
+
if (isRewardsApiBackedOff()) return;
|
|
3149
3259
|
const batch = pendingEvents.splice(0, 100);
|
|
3150
3260
|
try {
|
|
3151
|
-
await ctx.client.submitActivity(currentUserId, batch, {
|
|
3261
|
+
const result = await ctx.client.submitActivity(currentUserId, batch, {
|
|
3152
3262
|
userTraits: currentUserTraits ?? void 0,
|
|
3153
3263
|
reporterTokenHash: reporterTokenHash ?? void 0,
|
|
3154
3264
|
optedIn: true,
|
|
3155
3265
|
hostJwt: hostJwt ?? void 0
|
|
3156
3266
|
});
|
|
3267
|
+
if (!result.ok) {
|
|
3268
|
+
noteRewardsApiFailure(result.error?.code);
|
|
3269
|
+
const permanent = result.error?.code?.startsWith("HTTP_4");
|
|
3270
|
+
if (!permanent) {
|
|
3271
|
+
pendingEvents.unshift(...batch.slice(0, 50));
|
|
3272
|
+
}
|
|
3273
|
+
}
|
|
3157
3274
|
} catch {
|
|
3158
3275
|
pendingEvents.unshift(...batch.slice(0, 50));
|
|
3159
3276
|
}
|
|
@@ -3164,13 +3281,14 @@ async function getTier(userId) {
|
|
|
3164
3281
|
return fetchAndCacheTier(userId);
|
|
3165
3282
|
}
|
|
3166
3283
|
async function fetchAndCacheTier(userId) {
|
|
3167
|
-
if (!apiClient) return null;
|
|
3284
|
+
if (!apiClient || isRewardsApiBackedOff()) return null;
|
|
3168
3285
|
const res = await apiClient.getMyTier(userId);
|
|
3169
3286
|
if (res.ok && res.data) {
|
|
3170
3287
|
tierCache = res.data;
|
|
3171
3288
|
tierCacheTime = Date.now();
|
|
3172
3289
|
return tierCache;
|
|
3173
3290
|
}
|
|
3291
|
+
noteRewardsApiFailure(res.error?.code);
|
|
3174
3292
|
return null;
|
|
3175
3293
|
}
|
|
3176
3294
|
var routeObserver = null;
|
|
@@ -4598,6 +4716,7 @@ function recordApiFailure(failedRequests, callbacks) {
|
|
|
4598
4716
|
// src/proactive-manager.ts
|
|
4599
4717
|
var STORAGE_KEY_LAST_DISMISS = "mushi:lastDismiss";
|
|
4600
4718
|
var STORAGE_KEY_CONSEC_DISMISS = "mushi:consecDismiss";
|
|
4719
|
+
var STORAGE_KEY_LAST_SHOWN = "mushi:lastShown";
|
|
4601
4720
|
function readStorage(key) {
|
|
4602
4721
|
try {
|
|
4603
4722
|
return localStorage.getItem(key);
|
|
@@ -4615,20 +4734,30 @@ function createProactiveManager(config = {}) {
|
|
|
4615
4734
|
const maxPerSession = config.maxProactivePerSession ?? 2;
|
|
4616
4735
|
const cooldownHours = config.dismissCooldownHours ?? 24;
|
|
4617
4736
|
const suppressThreshold = config.suppressAfterDismissals ?? 3;
|
|
4737
|
+
const reshowCooldownMs = (config.reshowCooldownMinutes ?? 30) * 60 * 1e3;
|
|
4618
4738
|
let sessionPromptCount = 0;
|
|
4619
4739
|
const sessionTriggerTypes = /* @__PURE__ */ new Set();
|
|
4620
4740
|
function shouldShow(triggerType) {
|
|
4741
|
+
const now = Date.now();
|
|
4621
4742
|
const consecDismissals = parseInt(readStorage(STORAGE_KEY_CONSEC_DISMISS) ?? "0", 10);
|
|
4622
4743
|
if (consecDismissals >= suppressThreshold) return false;
|
|
4623
4744
|
const lastDismiss = readStorage(STORAGE_KEY_LAST_DISMISS);
|
|
4624
4745
|
if (lastDismiss) {
|
|
4625
|
-
const elapsed =
|
|
4746
|
+
const elapsed = now - parseInt(lastDismiss, 10);
|
|
4626
4747
|
if (elapsed < cooldownHours * 60 * 60 * 1e3) return false;
|
|
4627
4748
|
}
|
|
4749
|
+
if (reshowCooldownMs > 0 && sessionPromptCount === 0) {
|
|
4750
|
+
const lastShown = readStorage(STORAGE_KEY_LAST_SHOWN);
|
|
4751
|
+
if (lastShown) {
|
|
4752
|
+
const elapsed = now - parseInt(lastShown, 10);
|
|
4753
|
+
if (elapsed < reshowCooldownMs) return false;
|
|
4754
|
+
}
|
|
4755
|
+
}
|
|
4628
4756
|
if (sessionPromptCount >= maxPerSession) return false;
|
|
4629
4757
|
if (sessionTriggerTypes.has(triggerType)) return false;
|
|
4630
4758
|
sessionTriggerTypes.add(triggerType);
|
|
4631
4759
|
sessionPromptCount++;
|
|
4760
|
+
writeStorage(STORAGE_KEY_LAST_SHOWN, String(now));
|
|
4632
4761
|
return true;
|
|
4633
4762
|
}
|
|
4634
4763
|
function recordDismissal() {
|
|
@@ -4642,13 +4771,17 @@ function createProactiveManager(config = {}) {
|
|
|
4642
4771
|
function reset() {
|
|
4643
4772
|
sessionPromptCount = 0;
|
|
4644
4773
|
sessionTriggerTypes.clear();
|
|
4774
|
+
try {
|
|
4775
|
+
localStorage.removeItem(STORAGE_KEY_LAST_SHOWN);
|
|
4776
|
+
} catch {
|
|
4777
|
+
}
|
|
4645
4778
|
}
|
|
4646
4779
|
return { shouldShow, recordDismissal, recordSubmission, reset };
|
|
4647
4780
|
}
|
|
4648
4781
|
|
|
4649
4782
|
// src/version.ts
|
|
4650
4783
|
var MUSHI_SDK_PACKAGE = "@mushi-mushi/web";
|
|
4651
|
-
var MUSHI_SDK_VERSION = "1.7.
|
|
4784
|
+
var MUSHI_SDK_VERSION = "1.7.6" ;
|
|
4652
4785
|
|
|
4653
4786
|
// src/mushi.ts
|
|
4654
4787
|
var instance = null;
|
|
@@ -4829,15 +4962,26 @@ function createInstance(config) {
|
|
|
4829
4962
|
});
|
|
4830
4963
|
let detachAutoBreadcrumbs = null;
|
|
4831
4964
|
detachAutoBreadcrumbs = installAutoBreadcrumbs(breadcrumbs);
|
|
4965
|
+
async function autoCaptureScreenshot(when) {
|
|
4966
|
+
const mode = activeConfig.capture?.screenshot;
|
|
4967
|
+
if (!screenshotCap || mode === "off" || pendingScreenshot) return;
|
|
4968
|
+
if (when === "open" && mode !== "auto") return;
|
|
4969
|
+
if (when === "submit" && mode !== "on-report" && mode !== "auto") return;
|
|
4970
|
+
log.debug("Auto-capturing screenshot", { when, mode });
|
|
4971
|
+
pendingScreenshot = await screenshotCap.take();
|
|
4972
|
+
widget.setScreenshotAttached(pendingScreenshot !== null);
|
|
4973
|
+
}
|
|
4832
4974
|
widget = new MushiWidget(bootstrapConfig.widget, {
|
|
4833
4975
|
onSubmit: async ({ category, description, intent }) => {
|
|
4834
4976
|
log.info("Report submitted", { category, intent });
|
|
4835
4977
|
proactiveManager?.recordSubmission();
|
|
4978
|
+
await autoCaptureScreenshot("submit");
|
|
4836
4979
|
const outcome = await submitReport(category, description, intent);
|
|
4837
4980
|
return outcome ?? { reportId: null, queuedOffline: true };
|
|
4838
4981
|
},
|
|
4839
4982
|
onOpen: () => {
|
|
4840
4983
|
log.debug("Widget opened");
|
|
4984
|
+
void autoCaptureScreenshot("open");
|
|
4841
4985
|
emit("widget:opened");
|
|
4842
4986
|
},
|
|
4843
4987
|
onClose: () => {
|
|
@@ -5066,7 +5210,7 @@ function createInstance(config) {
|
|
|
5066
5210
|
...sentryCtx.tags ? { tags: scrubTagsForWire(sentryCtx.tags) } : {}
|
|
5067
5211
|
} : void 0;
|
|
5068
5212
|
const report = {
|
|
5069
|
-
id:
|
|
5213
|
+
id: core.newUuid(),
|
|
5070
5214
|
projectId: config.projectId,
|
|
5071
5215
|
category,
|
|
5072
5216
|
description: scrubbedDescription,
|
|
@@ -5244,7 +5388,8 @@ function createInstance(config) {
|
|
|
5244
5388
|
widgetMounted: widget.getIsMounted(),
|
|
5245
5389
|
runtimeConfigLoaded,
|
|
5246
5390
|
captureScreenshotAvailable: screenshotCap !== null,
|
|
5247
|
-
captureNetworkIntercepting: networkCap !== null
|
|
5391
|
+
captureNetworkIntercepting: networkCap !== null,
|
|
5392
|
+
widgetDiagnostics: widget.getWidgetDiagnostics()
|
|
5248
5393
|
});
|
|
5249
5394
|
},
|
|
5250
5395
|
destroy() {
|
|
@@ -5287,7 +5432,7 @@ function createInstance(config) {
|
|
|
5287
5432
|
...sentryCtx.tags ? { tags: scrubTagsForWire(sentryCtx.tags) } : {}
|
|
5288
5433
|
} : void 0;
|
|
5289
5434
|
const report = {
|
|
5290
|
-
id:
|
|
5435
|
+
id: core.newUuid(),
|
|
5291
5436
|
projectId: config.projectId,
|
|
5292
5437
|
category,
|
|
5293
5438
|
description,
|
|
@@ -5593,7 +5738,11 @@ async function runDiagnostics(options) {
|
|
|
5593
5738
|
runtimeConfigLoaded: options.runtimeConfigLoaded,
|
|
5594
5739
|
captureScreenshotAvailable: options.captureScreenshotAvailable,
|
|
5595
5740
|
captureNetworkIntercepting: options.captureNetworkIntercepting,
|
|
5596
|
-
sdkVersion: MUSHI_SDK_VERSION
|
|
5741
|
+
sdkVersion: MUSHI_SDK_VERSION,
|
|
5742
|
+
widgetHostPointerSafe: options.widgetDiagnostics?.widgetHostPointerSafe ?? false,
|
|
5743
|
+
widgetHostBounds: options.widgetDiagnostics?.widgetHostBounds ?? null,
|
|
5744
|
+
widgetSuppressed: options.widgetDiagnostics?.widgetSuppressed ?? false,
|
|
5745
|
+
bannerRendered: options.widgetDiagnostics?.bannerRendered ?? false
|
|
5597
5746
|
};
|
|
5598
5747
|
}
|
|
5599
5748
|
async function diagnoseWithoutInstance() {
|
|
@@ -5606,7 +5755,11 @@ async function diagnoseWithoutInstance() {
|
|
|
5606
5755
|
runtimeConfigLoaded: false,
|
|
5607
5756
|
captureScreenshotAvailable: false,
|
|
5608
5757
|
captureNetworkIntercepting: false,
|
|
5609
|
-
sdkVersion: MUSHI_SDK_VERSION
|
|
5758
|
+
sdkVersion: MUSHI_SDK_VERSION,
|
|
5759
|
+
widgetHostPointerSafe: false,
|
|
5760
|
+
widgetHostBounds: null,
|
|
5761
|
+
widgetSuppressed: false,
|
|
5762
|
+
bannerRendered: false
|
|
5610
5763
|
};
|
|
5611
5764
|
}
|
|
5612
5765
|
async function probeApiEndpoint(apiEndpoint) {
|