@mushi-mushi/web 1.5.0 → 1.6.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 +0 -11
- package/dist/index.cjs +551 -148
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +99 -10
- package/dist/index.d.ts +99 -10
- package/dist/index.js +551 -148
- package/dist/index.js.map +1 -1
- package/package.json +16 -16
package/dist/index.d.cts
CHANGED
|
@@ -36,12 +36,27 @@ interface WidgetRewardsState {
|
|
|
36
36
|
/** Expected base points for a `report_submit` action (default 50). */
|
|
37
37
|
pointsForReport: number;
|
|
38
38
|
}
|
|
39
|
+
interface WidgetSubmitOutcome {
|
|
40
|
+
/** Server-confirmed report id. When `null` the report was queued
|
|
41
|
+
* offline / failed-and-queued for retry; the success step degrades
|
|
42
|
+
* gracefully (no "track on console" link, just the receipt stamp). */
|
|
43
|
+
reportId: string | null;
|
|
44
|
+
/** Convenience flag for the widget to decide whether to render the
|
|
45
|
+
* optimistic copy ("queued offline, we'll send it when you're back")
|
|
46
|
+
* versus the confirmed copy ("received — track at #abc12345"). */
|
|
47
|
+
queuedOffline?: boolean;
|
|
48
|
+
}
|
|
39
49
|
interface WidgetCallbacks {
|
|
50
|
+
/**
|
|
51
|
+
* Returns the outcome of the submission so the widget can render a
|
|
52
|
+
* real receipt (report id, deep link). Older callers that return
|
|
53
|
+
* `void` still work — the widget falls back to the legacy stamp.
|
|
54
|
+
*/
|
|
40
55
|
onSubmit(data: {
|
|
41
56
|
category: MushiReportCategory;
|
|
42
57
|
description: string;
|
|
43
58
|
intent?: string;
|
|
44
|
-
}): void
|
|
59
|
+
}): void | Promise<WidgetSubmitOutcome | void>;
|
|
45
60
|
onOpen(): void;
|
|
46
61
|
onClose(): void;
|
|
47
62
|
onScreenshotRequest(): void;
|
|
@@ -62,6 +77,13 @@ declare class MushiWidget {
|
|
|
62
77
|
private step;
|
|
63
78
|
private selectedCategory;
|
|
64
79
|
private selectedIntent;
|
|
80
|
+
/**
|
|
81
|
+
* True when the user took the "Feature request" shortcut. We track this
|
|
82
|
+
* separately from `selectedCategory='other'` so the Back button on the
|
|
83
|
+
* details step jumps straight back to the category picker instead of
|
|
84
|
+
* landing on the intent picker the user explicitly skipped.
|
|
85
|
+
*/
|
|
86
|
+
private viaFeatureRequest;
|
|
65
87
|
private screenshotAttached;
|
|
66
88
|
private screenshotCapturing;
|
|
67
89
|
private screenshotError;
|
|
@@ -99,14 +121,34 @@ declare class MushiWidget {
|
|
|
99
121
|
private successTimer;
|
|
100
122
|
private autoCloseTimer;
|
|
101
123
|
private rewardsState;
|
|
124
|
+
/** Server-confirmed id for the just-submitted report. Surfaces in
|
|
125
|
+
* the success step as a copyable receipt + optional deep link to
|
|
126
|
+
* the Mushi console (when `dashboardUrl` is configured). Cleared
|
|
127
|
+
* on every new `open()` so a re-opened widget never reuses a
|
|
128
|
+
* stale id from the previous session. */
|
|
129
|
+
private lastReportId;
|
|
130
|
+
/** True when the just-submitted report was queued offline (no
|
|
131
|
+
* network, or the API errored and went into the retry queue).
|
|
132
|
+
* Drives a different success copy so the user knows the report
|
|
133
|
+
* hasn't actually reached the console yet. */
|
|
134
|
+
private lastSubmitQueuedOffline;
|
|
102
135
|
constructor(config: MushiWidgetConfig | undefined, callbacks: WidgetCallbacks, sdkVersion?: string);
|
|
103
136
|
mount(): void;
|
|
104
137
|
getIsMounted(): boolean;
|
|
105
138
|
updateConfig(config?: MushiWidgetConfig): void;
|
|
106
139
|
open(options?: {
|
|
107
140
|
category?: MushiReportCategory;
|
|
141
|
+
featureRequest?: boolean;
|
|
108
142
|
}): void;
|
|
109
143
|
close(): void;
|
|
144
|
+
/**
|
|
145
|
+
* Briefly highlight the trigger button (a soft pulse + tooltip) without
|
|
146
|
+
* opening the full reporter panel. Use for first-session welcome nudges
|
|
147
|
+
* and other "by the way, this exists" prompts where forcing the panel
|
|
148
|
+
* open would feel aggressive. Honours `position: 'none'` (no-op when
|
|
149
|
+
* the trigger button is hidden).
|
|
150
|
+
*/
|
|
151
|
+
pulseTrigger(): void;
|
|
110
152
|
getIsOpen(): boolean;
|
|
111
153
|
showTrigger(): void;
|
|
112
154
|
hideTrigger(): void;
|
|
@@ -166,6 +208,19 @@ declare class MushiWidget {
|
|
|
166
208
|
*/
|
|
167
209
|
private renderStepIndicator;
|
|
168
210
|
private renderCategoryStep;
|
|
211
|
+
/**
|
|
212
|
+
* First-class "Feature request" entry rendered at the top of the
|
|
213
|
+
* category step. Beta apps consistently get more useful signal when
|
|
214
|
+
* the user has a no-friction path to say "I wish this did X" — burying
|
|
215
|
+
* it as an intent under the "Other" category drops feature submissions
|
|
216
|
+
* by ~40% in industry studies (Userpilot, Usersnap 2025).
|
|
217
|
+
*
|
|
218
|
+
* Wire format: still routes through the standard `other` category with
|
|
219
|
+
* a `user_category = 'Feature request'` stamp, so we don't need a DB
|
|
220
|
+
* migration. The admin console filters on that string to surface the
|
|
221
|
+
* Feature-request swimlane.
|
|
222
|
+
*/
|
|
223
|
+
private renderFeatureRequestEntry;
|
|
169
224
|
/** Collapsible "What's new" changelog row. Closes the reporter feedback loop. */
|
|
170
225
|
private renderBetaChangelog;
|
|
171
226
|
/**
|
|
@@ -188,6 +243,19 @@ declare class MushiWidget {
|
|
|
188
243
|
* frame instantly.
|
|
189
244
|
*/
|
|
190
245
|
private renderSuccessStep;
|
|
246
|
+
/**
|
|
247
|
+
* Two-way receipt block. Until the host's `onSubmit` resolves with a
|
|
248
|
+
* server-confirmed report id, we show a discreet "delivering..." pill so
|
|
249
|
+
* the user knows their submission is still in flight. Once we have the
|
|
250
|
+
* id, we surface a short monospaced id + a copy button + an optional
|
|
251
|
+
* "Track on Mushi" deep link to `dashboardUrl/reports/<id>` so the user
|
|
252
|
+
* can watch the status walk through queued -> classified -> fixed in
|
|
253
|
+
* real time (Peak-End rule: the last impression sticks). If we never
|
|
254
|
+
* get an id (offline retry queue), we say so explicitly rather than
|
|
255
|
+
* pretending everything is fine.
|
|
256
|
+
*/
|
|
257
|
+
private renderSuccessReceipt;
|
|
258
|
+
private renderSlaLine;
|
|
191
259
|
/**
|
|
192
260
|
* Reciprocity footer on the success step: closes the feedback loop by
|
|
193
261
|
* attributing where the report goes, sets a response expectation, and
|
|
@@ -238,20 +306,12 @@ interface NetworkCaptureOptions {
|
|
|
238
306
|
declare function createNetworkCapture(options?: NetworkCaptureOptions): NetworkCapture;
|
|
239
307
|
|
|
240
308
|
interface ScreenshotCapture {
|
|
241
|
-
take(): Promise<
|
|
309
|
+
take(): Promise<string | null>;
|
|
242
310
|
updateOptions(options: ScreenshotCaptureOptions): void;
|
|
243
311
|
}
|
|
244
312
|
interface ScreenshotCaptureOptions {
|
|
245
313
|
privacy?: MushiPrivacyConfig;
|
|
246
314
|
}
|
|
247
|
-
type ScreenshotResult = {
|
|
248
|
-
ok: true;
|
|
249
|
-
dataUrl: string;
|
|
250
|
-
} | {
|
|
251
|
-
ok: false;
|
|
252
|
-
reason: 'tainted' | 'load-error' | 'unsupported' | 'cancelled' | 'error';
|
|
253
|
-
message?: string;
|
|
254
|
-
};
|
|
255
315
|
declare function createScreenshotCapture(options?: ScreenshotCaptureOptions): ScreenshotCapture;
|
|
256
316
|
|
|
257
317
|
interface PerformanceCapture {
|
|
@@ -343,6 +403,35 @@ interface ProactiveTriggerConfig {
|
|
|
343
403
|
apiCascade?: boolean | MushiApiCascadeConfig;
|
|
344
404
|
apiEndpoint?: string;
|
|
345
405
|
errorBoundary?: boolean;
|
|
406
|
+
/**
|
|
407
|
+
* Beta-mode nudges. Fire when the user has been on the same route for
|
|
408
|
+
* `pageDwellMs` continuous milliseconds without filing any report. Default
|
|
409
|
+
* disabled because production apps usually don't want unsolicited prompts;
|
|
410
|
+
* recommended only when `betaMode.enabled` is true on the widget.
|
|
411
|
+
*
|
|
412
|
+
* Pass `true` to use the default 5-minute threshold, or a config object
|
|
413
|
+
* to override. Set to `false` (default) to disable entirely.
|
|
414
|
+
*/
|
|
415
|
+
pageDwell?: boolean | {
|
|
416
|
+
thresholdMs?: number;
|
|
417
|
+
excludeRoutes?: string[];
|
|
418
|
+
};
|
|
419
|
+
/**
|
|
420
|
+
* First-session welcome. Fires exactly once per user (tracked via
|
|
421
|
+
* `localStorage`) `delayMs` milliseconds after `Mushi.init`. Use to
|
|
422
|
+
* gently surface the bug button to new beta users so they know feedback
|
|
423
|
+
* is welcome. Default disabled.
|
|
424
|
+
*/
|
|
425
|
+
firstSession?: boolean | {
|
|
426
|
+
delayMs?: number;
|
|
427
|
+
storageKey?: string;
|
|
428
|
+
};
|
|
429
|
+
/**
|
|
430
|
+
* The project ID, used to namespace the `firstSession` localStorage key so
|
|
431
|
+
* multi-tenant single-page apps don't share first-session state across
|
|
432
|
+
* projects. Sourced from `MushiConfig.projectId` by the SDK.
|
|
433
|
+
*/
|
|
434
|
+
projectId?: string;
|
|
346
435
|
}
|
|
347
436
|
interface ProactiveTriggerCallbacks {
|
|
348
437
|
onTrigger: (type: string, context: Record<string, unknown>) => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -36,12 +36,27 @@ interface WidgetRewardsState {
|
|
|
36
36
|
/** Expected base points for a `report_submit` action (default 50). */
|
|
37
37
|
pointsForReport: number;
|
|
38
38
|
}
|
|
39
|
+
interface WidgetSubmitOutcome {
|
|
40
|
+
/** Server-confirmed report id. When `null` the report was queued
|
|
41
|
+
* offline / failed-and-queued for retry; the success step degrades
|
|
42
|
+
* gracefully (no "track on console" link, just the receipt stamp). */
|
|
43
|
+
reportId: string | null;
|
|
44
|
+
/** Convenience flag for the widget to decide whether to render the
|
|
45
|
+
* optimistic copy ("queued offline, we'll send it when you're back")
|
|
46
|
+
* versus the confirmed copy ("received — track at #abc12345"). */
|
|
47
|
+
queuedOffline?: boolean;
|
|
48
|
+
}
|
|
39
49
|
interface WidgetCallbacks {
|
|
50
|
+
/**
|
|
51
|
+
* Returns the outcome of the submission so the widget can render a
|
|
52
|
+
* real receipt (report id, deep link). Older callers that return
|
|
53
|
+
* `void` still work — the widget falls back to the legacy stamp.
|
|
54
|
+
*/
|
|
40
55
|
onSubmit(data: {
|
|
41
56
|
category: MushiReportCategory;
|
|
42
57
|
description: string;
|
|
43
58
|
intent?: string;
|
|
44
|
-
}): void
|
|
59
|
+
}): void | Promise<WidgetSubmitOutcome | void>;
|
|
45
60
|
onOpen(): void;
|
|
46
61
|
onClose(): void;
|
|
47
62
|
onScreenshotRequest(): void;
|
|
@@ -62,6 +77,13 @@ declare class MushiWidget {
|
|
|
62
77
|
private step;
|
|
63
78
|
private selectedCategory;
|
|
64
79
|
private selectedIntent;
|
|
80
|
+
/**
|
|
81
|
+
* True when the user took the "Feature request" shortcut. We track this
|
|
82
|
+
* separately from `selectedCategory='other'` so the Back button on the
|
|
83
|
+
* details step jumps straight back to the category picker instead of
|
|
84
|
+
* landing on the intent picker the user explicitly skipped.
|
|
85
|
+
*/
|
|
86
|
+
private viaFeatureRequest;
|
|
65
87
|
private screenshotAttached;
|
|
66
88
|
private screenshotCapturing;
|
|
67
89
|
private screenshotError;
|
|
@@ -99,14 +121,34 @@ declare class MushiWidget {
|
|
|
99
121
|
private successTimer;
|
|
100
122
|
private autoCloseTimer;
|
|
101
123
|
private rewardsState;
|
|
124
|
+
/** Server-confirmed id for the just-submitted report. Surfaces in
|
|
125
|
+
* the success step as a copyable receipt + optional deep link to
|
|
126
|
+
* the Mushi console (when `dashboardUrl` is configured). Cleared
|
|
127
|
+
* on every new `open()` so a re-opened widget never reuses a
|
|
128
|
+
* stale id from the previous session. */
|
|
129
|
+
private lastReportId;
|
|
130
|
+
/** True when the just-submitted report was queued offline (no
|
|
131
|
+
* network, or the API errored and went into the retry queue).
|
|
132
|
+
* Drives a different success copy so the user knows the report
|
|
133
|
+
* hasn't actually reached the console yet. */
|
|
134
|
+
private lastSubmitQueuedOffline;
|
|
102
135
|
constructor(config: MushiWidgetConfig | undefined, callbacks: WidgetCallbacks, sdkVersion?: string);
|
|
103
136
|
mount(): void;
|
|
104
137
|
getIsMounted(): boolean;
|
|
105
138
|
updateConfig(config?: MushiWidgetConfig): void;
|
|
106
139
|
open(options?: {
|
|
107
140
|
category?: MushiReportCategory;
|
|
141
|
+
featureRequest?: boolean;
|
|
108
142
|
}): void;
|
|
109
143
|
close(): void;
|
|
144
|
+
/**
|
|
145
|
+
* Briefly highlight the trigger button (a soft pulse + tooltip) without
|
|
146
|
+
* opening the full reporter panel. Use for first-session welcome nudges
|
|
147
|
+
* and other "by the way, this exists" prompts where forcing the panel
|
|
148
|
+
* open would feel aggressive. Honours `position: 'none'` (no-op when
|
|
149
|
+
* the trigger button is hidden).
|
|
150
|
+
*/
|
|
151
|
+
pulseTrigger(): void;
|
|
110
152
|
getIsOpen(): boolean;
|
|
111
153
|
showTrigger(): void;
|
|
112
154
|
hideTrigger(): void;
|
|
@@ -166,6 +208,19 @@ declare class MushiWidget {
|
|
|
166
208
|
*/
|
|
167
209
|
private renderStepIndicator;
|
|
168
210
|
private renderCategoryStep;
|
|
211
|
+
/**
|
|
212
|
+
* First-class "Feature request" entry rendered at the top of the
|
|
213
|
+
* category step. Beta apps consistently get more useful signal when
|
|
214
|
+
* the user has a no-friction path to say "I wish this did X" — burying
|
|
215
|
+
* it as an intent under the "Other" category drops feature submissions
|
|
216
|
+
* by ~40% in industry studies (Userpilot, Usersnap 2025).
|
|
217
|
+
*
|
|
218
|
+
* Wire format: still routes through the standard `other` category with
|
|
219
|
+
* a `user_category = 'Feature request'` stamp, so we don't need a DB
|
|
220
|
+
* migration. The admin console filters on that string to surface the
|
|
221
|
+
* Feature-request swimlane.
|
|
222
|
+
*/
|
|
223
|
+
private renderFeatureRequestEntry;
|
|
169
224
|
/** Collapsible "What's new" changelog row. Closes the reporter feedback loop. */
|
|
170
225
|
private renderBetaChangelog;
|
|
171
226
|
/**
|
|
@@ -188,6 +243,19 @@ declare class MushiWidget {
|
|
|
188
243
|
* frame instantly.
|
|
189
244
|
*/
|
|
190
245
|
private renderSuccessStep;
|
|
246
|
+
/**
|
|
247
|
+
* Two-way receipt block. Until the host's `onSubmit` resolves with a
|
|
248
|
+
* server-confirmed report id, we show a discreet "delivering..." pill so
|
|
249
|
+
* the user knows their submission is still in flight. Once we have the
|
|
250
|
+
* id, we surface a short monospaced id + a copy button + an optional
|
|
251
|
+
* "Track on Mushi" deep link to `dashboardUrl/reports/<id>` so the user
|
|
252
|
+
* can watch the status walk through queued -> classified -> fixed in
|
|
253
|
+
* real time (Peak-End rule: the last impression sticks). If we never
|
|
254
|
+
* get an id (offline retry queue), we say so explicitly rather than
|
|
255
|
+
* pretending everything is fine.
|
|
256
|
+
*/
|
|
257
|
+
private renderSuccessReceipt;
|
|
258
|
+
private renderSlaLine;
|
|
191
259
|
/**
|
|
192
260
|
* Reciprocity footer on the success step: closes the feedback loop by
|
|
193
261
|
* attributing where the report goes, sets a response expectation, and
|
|
@@ -238,20 +306,12 @@ interface NetworkCaptureOptions {
|
|
|
238
306
|
declare function createNetworkCapture(options?: NetworkCaptureOptions): NetworkCapture;
|
|
239
307
|
|
|
240
308
|
interface ScreenshotCapture {
|
|
241
|
-
take(): Promise<
|
|
309
|
+
take(): Promise<string | null>;
|
|
242
310
|
updateOptions(options: ScreenshotCaptureOptions): void;
|
|
243
311
|
}
|
|
244
312
|
interface ScreenshotCaptureOptions {
|
|
245
313
|
privacy?: MushiPrivacyConfig;
|
|
246
314
|
}
|
|
247
|
-
type ScreenshotResult = {
|
|
248
|
-
ok: true;
|
|
249
|
-
dataUrl: string;
|
|
250
|
-
} | {
|
|
251
|
-
ok: false;
|
|
252
|
-
reason: 'tainted' | 'load-error' | 'unsupported' | 'cancelled' | 'error';
|
|
253
|
-
message?: string;
|
|
254
|
-
};
|
|
255
315
|
declare function createScreenshotCapture(options?: ScreenshotCaptureOptions): ScreenshotCapture;
|
|
256
316
|
|
|
257
317
|
interface PerformanceCapture {
|
|
@@ -343,6 +403,35 @@ interface ProactiveTriggerConfig {
|
|
|
343
403
|
apiCascade?: boolean | MushiApiCascadeConfig;
|
|
344
404
|
apiEndpoint?: string;
|
|
345
405
|
errorBoundary?: boolean;
|
|
406
|
+
/**
|
|
407
|
+
* Beta-mode nudges. Fire when the user has been on the same route for
|
|
408
|
+
* `pageDwellMs` continuous milliseconds without filing any report. Default
|
|
409
|
+
* disabled because production apps usually don't want unsolicited prompts;
|
|
410
|
+
* recommended only when `betaMode.enabled` is true on the widget.
|
|
411
|
+
*
|
|
412
|
+
* Pass `true` to use the default 5-minute threshold, or a config object
|
|
413
|
+
* to override. Set to `false` (default) to disable entirely.
|
|
414
|
+
*/
|
|
415
|
+
pageDwell?: boolean | {
|
|
416
|
+
thresholdMs?: number;
|
|
417
|
+
excludeRoutes?: string[];
|
|
418
|
+
};
|
|
419
|
+
/**
|
|
420
|
+
* First-session welcome. Fires exactly once per user (tracked via
|
|
421
|
+
* `localStorage`) `delayMs` milliseconds after `Mushi.init`. Use to
|
|
422
|
+
* gently surface the bug button to new beta users so they know feedback
|
|
423
|
+
* is welcome. Default disabled.
|
|
424
|
+
*/
|
|
425
|
+
firstSession?: boolean | {
|
|
426
|
+
delayMs?: number;
|
|
427
|
+
storageKey?: string;
|
|
428
|
+
};
|
|
429
|
+
/**
|
|
430
|
+
* The project ID, used to namespace the `firstSession` localStorage key so
|
|
431
|
+
* multi-tenant single-page apps don't share first-session state across
|
|
432
|
+
* projects. Sourced from `MushiConfig.projectId` by the SDK.
|
|
433
|
+
*/
|
|
434
|
+
projectId?: string;
|
|
346
435
|
}
|
|
347
436
|
interface ProactiveTriggerCallbacks {
|
|
348
437
|
onTrigger: (type: string, context: Record<string, unknown>) => void;
|