makethisbetter 1.0.0 → 1.1.2

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.
Files changed (77) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +329 -62
  3. package/dist/annotate/session.d.ts +5 -0
  4. package/dist/annotate/session.d.ts.map +1 -1
  5. package/dist/api/client.d.ts +9 -3
  6. package/dist/api/client.d.ts.map +1 -1
  7. package/dist/context/error-source.d.ts +1 -0
  8. package/dist/context/error-source.d.ts.map +1 -1
  9. package/dist/context/frustration.d.ts +25 -1
  10. package/dist/context/frustration.d.ts.map +1 -1
  11. package/dist/i18n/de.d.ts +54 -0
  12. package/dist/i18n/de.d.ts.map +1 -0
  13. package/dist/i18n/en.d.ts +7 -0
  14. package/dist/i18n/en.d.ts.map +1 -1
  15. package/dist/i18n/es.d.ts +54 -0
  16. package/dist/i18n/es.d.ts.map +1 -0
  17. package/dist/i18n/fr.d.ts +54 -0
  18. package/dist/i18n/fr.d.ts.map +1 -0
  19. package/dist/i18n/index.d.ts.map +1 -1
  20. package/dist/i18n/ja.d.ts +54 -0
  21. package/dist/i18n/ja.d.ts.map +1 -0
  22. package/dist/i18n/ko.d.ts +54 -0
  23. package/dist/i18n/ko.d.ts.map +1 -0
  24. package/dist/i18n/zh-CN.d.ts +7 -0
  25. package/dist/i18n/zh-CN.d.ts.map +1 -1
  26. package/dist/makethisbetter.cjs.js +42 -27
  27. package/dist/makethisbetter.cjs.js.map +1 -1
  28. package/dist/makethisbetter.esm.js +1208 -636
  29. package/dist/makethisbetter.esm.js.map +1 -1
  30. package/dist/makethisbetter.js +42 -27
  31. package/dist/makethisbetter.js.map +1 -1
  32. package/dist/popup/clarify.d.ts +37 -0
  33. package/dist/popup/clarify.d.ts.map +1 -0
  34. package/dist/popup/clarify.test.d.ts +2 -0
  35. package/dist/popup/clarify.test.d.ts.map +1 -0
  36. package/dist/popup/success.d.ts +1 -1
  37. package/dist/popup/success.d.ts.map +1 -1
  38. package/dist/record/session.d.ts.map +1 -1
  39. package/dist/types.d.ts +17 -0
  40. package/dist/types.d.ts.map +1 -1
  41. package/dist/widget/controller.d.ts +3 -6
  42. package/dist/widget/controller.d.ts.map +1 -1
  43. package/dist/widget/recording-manager.d.ts +15 -0
  44. package/dist/widget/recording-manager.d.ts.map +1 -0
  45. package/dist/widget/recording-manager.test.d.ts +2 -0
  46. package/dist/widget/recording-manager.test.d.ts.map +1 -0
  47. package/dist/widget/tab.d.ts +1 -1
  48. package/dist/widget/tab.d.ts.map +1 -1
  49. package/package.json +13 -3
  50. package/src/annotate/session.test.ts +117 -5
  51. package/src/annotate/session.ts +27 -8
  52. package/src/api/client.test.ts +144 -4
  53. package/src/api/client.ts +56 -5
  54. package/src/context/error-source.test.ts +13 -0
  55. package/src/context/error-source.ts +9 -2
  56. package/src/context/frustration.test.ts +336 -1
  57. package/src/context/frustration.ts +237 -1
  58. package/src/i18n/de.ts +54 -0
  59. package/src/i18n/en.ts +7 -0
  60. package/src/i18n/es.ts +54 -0
  61. package/src/i18n/fr.ts +54 -0
  62. package/src/i18n/index.test.ts +1 -1
  63. package/src/i18n/index.ts +10 -0
  64. package/src/i18n/ja.ts +54 -0
  65. package/src/i18n/ko.ts +54 -0
  66. package/src/i18n/zh-CN.ts +7 -0
  67. package/src/popup/clarify.test.ts +419 -0
  68. package/src/popup/clarify.ts +215 -0
  69. package/src/popup/success.ts +11 -1
  70. package/src/record/session.ts +8 -1
  71. package/src/styles/widget.css +218 -0
  72. package/src/types.ts +20 -0
  73. package/src/widget/controller.test.ts +6 -4
  74. package/src/widget/controller.ts +59 -52
  75. package/src/widget/recording-manager.test.ts +136 -0
  76. package/src/widget/recording-manager.ts +51 -0
  77. package/src/widget/tab.ts +4 -2
package/LICENSE CHANGED
@@ -3,7 +3,7 @@ Business Source License 1.1
3
3
  Parameters
4
4
 
5
5
  Licensor: Make This Better, Inc.
6
- Licensed Work: @makethisbetter/js
6
+ Licensed Work: makethisbetter
7
7
  The Licensed Work is (c) 2026 Make This Better, Inc.
8
8
  Additional Use Grant: You may make production use of the Licensed Work,
9
9
  provided your use does not include offering the Licensed
package/README.md CHANGED
@@ -1,113 +1,380 @@
1
- # @makethisbetter/js
1
+ <p align="center">
2
+ <img src="https://makethisbetter.dev/icon.svg" width="80" height="80" alt="Make This Better">
3
+ </p>
2
4
 
3
- The Make This Better Widget SDK — embed user feedback collection in any website.
5
+ <h1 align="center">makethisbetter</h1>
4
6
 
5
- One script. Click any element. Describe the issue. Done.
7
+ <p align="center">
8
+ From rage click to agent-ready fix.
9
+ </p>
6
10
 
7
- ## Quickstart
11
+ <p align="center">
12
+ <a href="https://makethisbetter.dev">makethisbetter.dev</a> &middot;
13
+ <a href="https://www.npmjs.com/package/makethisbetter"><img src="https://img.shields.io/npm/v/makethisbetter.svg" alt="npm version"></a>
14
+ <a href="https://www.npmjs.com/package/makethisbetter"><img src="https://img.shields.io/npm/dm/makethisbetter.svg" alt="npm downloads"></a>
15
+ <a href="https://bundlephobia.com/package/makethisbetter"><img src="https://img.shields.io/bundlephobia/minzip/makethisbetter" alt="bundle size"></a>
16
+ <a href="https://github.com/makethisbetter/makethisbetter-js/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-BUSL--1.1-blue.svg" alt="license"></a>
17
+ </p>
8
18
 
9
- ### Script tag (IIFE)
19
+ ---
20
+
21
+ ## Why
22
+
23
+ You ship with AI agents. Your users hit bugs you never see in dev. They leave. You never find out why.
24
+
25
+ This widget gives your users a way to report exactly what went wrong — annotated screenshot, console errors, DOM state, browser info — in two clicks. AI triage turns that into a structured task your coding agent (Claude Code, Cursor, Codex) picks up automatically. The agent ships the fix. The user gets notified.
26
+
27
+ No more "can you describe what happened?" No more lost screenshots in Slack. The full loop, from frustrated user to shipped fix, runs without you context-switching.
28
+
29
+ ## Quick Start
30
+
31
+ ### CDN (2 lines)
10
32
 
11
33
  ```html
12
- <script src="https://unpkg.com/@makethisbetter/js/dist/makethisbetter.iife.js"></script>
34
+ <script src="https://unpkg.com/makethisbetter@1"></script>
13
35
  <script>
14
- MakeThisBetter.init({ projectKey: 'mtb_proj_YOUR_KEY' });
36
+ MakeThisBetter.init({ projectKey: 'mtb_proj_YOUR_KEY' })
15
37
  </script>
16
38
  ```
17
39
 
18
- ### npm / ESM
40
+ ### npm
19
41
 
20
42
  ```bash
21
- npm install @makethisbetter/js
43
+ npm install makethisbetter
22
44
  ```
23
45
 
24
46
  ```js
25
- import { MakeThisBetter } from '@makethisbetter/js';
47
+ import { MakeThisBetter } from 'makethisbetter'
48
+
49
+ MakeThisBetter.init({ projectKey: 'mtb_proj_YOUR_KEY' })
50
+ ```
51
+
52
+ That's it. A feedback tab appears on your page.
53
+
54
+ ## How It Works
55
+
56
+ ```
57
+ User clicks feedback tab
58
+ -> Annotates the problem (click to pin, drag to draw)
59
+ -> Adds a comment
60
+ -> Submits
61
+ +-- Screenshot captured automatically
62
+ +-- Console errors collected
63
+ +-- Page context assembled (URL, browser, OS, selectors)
64
+ +-- Sent to Make This Better API
65
+ +-- AI asks a clarifying question if needed
66
+ -> Dashboard shows structured feedback
67
+ -> AI triage produces an agent-ready task
68
+ -> Your coding agent picks it up and ships the fix
69
+ -> User gets notified: the fix is live
70
+ ```
71
+
72
+ ## Framework Guides
73
+
74
+ <details>
75
+ <summary><strong>React / Next.js</strong></summary>
26
76
 
27
- MakeThisBetter.init({ projectKey: 'mtb_proj_YOUR_KEY' });
77
+ ```tsx
78
+ // app/providers.tsx (App Router) or pages/_app.tsx (Pages Router)
79
+ 'use client'
80
+ import { useEffect } from 'react'
81
+
82
+ export function FeedbackProvider() {
83
+ useEffect(() => {
84
+ import('makethisbetter').then(({ MakeThisBetter }) => {
85
+ MakeThisBetter.init({
86
+ projectKey: process.env.NEXT_PUBLIC_MTB_KEY!,
87
+ user: { id: userId, email }
88
+ })
89
+ })
90
+ return () => {
91
+ import('makethisbetter').then(({ MakeThisBetter }) => MakeThisBetter.destroy())
92
+ }
93
+ }, [])
94
+ return null
95
+ }
96
+ ```
97
+
98
+ </details>
99
+
100
+ <details>
101
+ <summary><strong>Vue / Nuxt</strong></summary>
102
+
103
+ ```ts
104
+ // plugins/makethisbetter.client.ts (Nuxt) or main.ts (Vue)
105
+ import { MakeThisBetter } from 'makethisbetter'
106
+
107
+ export default defineNuxtPlugin(() => {
108
+ MakeThisBetter.init({
109
+ projectKey: useRuntimeConfig().public.mtbKey,
110
+ })
111
+
112
+ return {
113
+ provide: { mtbDestroy: () => MakeThisBetter.destroy() }
114
+ }
115
+ })
28
116
  ```
29
117
 
118
+ </details>
119
+
120
+ <details>
121
+ <summary><strong>Astro</strong></summary>
122
+
123
+ ```astro
124
+ <!-- src/components/Feedback.astro -->
125
+ <script>
126
+ import { MakeThisBetter } from 'makethisbetter'
127
+ MakeThisBetter.init({ projectKey: import.meta.env.PUBLIC_MTB_KEY })
128
+ </script>
129
+ ```
130
+
131
+ </details>
132
+
133
+ <details>
134
+ <summary><strong>Rails</strong></summary>
135
+
136
+ ```erb
137
+ <%# app/views/layouts/application.html.erb %>
138
+ <% if current_user&.admin? %>
139
+ <script src="https://unpkg.com/makethisbetter@1"></script>
140
+ <script>
141
+ MakeThisBetter.init({
142
+ projectKey: '<%= Rails.application.credentials.mtb_project_key %>',
143
+ user: { id: '<%= current_user.id %>', email: '<%= current_user.email %>' }
144
+ })
145
+ </script>
146
+ <% end %>
147
+ ```
148
+
149
+ </details>
150
+
151
+ <details>
152
+ <summary><strong>Plain HTML / Static Sites</strong></summary>
153
+
154
+ ```html
155
+ <script src="https://unpkg.com/makethisbetter@1"></script>
156
+ <script>
157
+ MakeThisBetter.init({ projectKey: 'mtb_proj_YOUR_KEY' })
158
+ </script>
159
+ ```
160
+
161
+ </details>
162
+
163
+ ## Features
164
+
165
+ ### Annotation
166
+
167
+ Click any element to pin it, or drag to draw a freeform highlight. The SDK captures the element's CSS selector, text content, and position.
168
+
169
+ ### Screen Recording
170
+
171
+ Switch to **Record** mode in the toolbar to capture a screen recording (up to 60 seconds). Powered by [rrweb](https://github.com/rrweb-io/rrweb) with lazy loading — zero cost until the user hits Record.
172
+
173
+ ```bash
174
+ # Optional: install rrweb for npm users (CDN users get it automatically)
175
+ npm install rrweb
176
+ ```
177
+
178
+ ### Frustration Detection
179
+
180
+ The SDK watches for signals that a user is struggling and proactively offers to collect feedback:
181
+
182
+ | Signal | Trigger |
183
+ |--------|---------|
184
+ | Rage click | 3+ clicks on the same element within 1 second |
185
+ | Dead click | Click on a non-interactive element (with console errors) |
186
+ | Dead click (DOM) | Click on interactive-looking element with no DOM response |
187
+ | Rapid navigation | 3+ page navigations within 5 seconds |
188
+ | Form failure | Form submission with validation errors |
189
+ | Error page | Landing on a 404/500 error page |
190
+
191
+ Disable with `frustrationDetection: false`.
192
+
193
+ ### AI Clarification
194
+
195
+ After submitting feedback, an AI assistant may ask a short follow-up question to clarify the real need — avoiding [XY problems](https://xyproblem.info/) where users describe their attempted solution instead of the actual problem.
196
+
197
+ ### Auto-Collected Context
198
+
199
+ Every submission automatically includes:
200
+
201
+ - Page URL, browser, OS, screen resolution
202
+ - Console errors (via `window.onerror` and `window.onunhandledrejection`)
203
+ - Target element selector and text
204
+ - Annotated screenshot (via `html-to-image`)
205
+ - Annotation coordinates and draw paths
206
+
207
+ ### Internationalization
208
+
209
+ Built-in support for 7 languages:
210
+
211
+ | Code | Language |
212
+ |------|----------|
213
+ | `en` | English (default) |
214
+ | `zh-CN` | Chinese (Simplified) |
215
+ | `ja` | Japanese |
216
+ | `ko` | Korean |
217
+ | `es` | Spanish |
218
+ | `fr` | French |
219
+ | `de` | German |
220
+
30
221
  ## Configuration
31
222
 
32
223
  ```js
33
224
  MakeThisBetter.init({
34
- projectKey: 'mtb_proj_xxx', // required — your project API key
35
- locale: 'zh-CN', // optional — 'en' (default) or 'zh-CN'
36
- position: 'right', // optional — 'right' (default) or 'left'
37
- theme: 'auto', // optional — 'light' | 'dark' | 'auto'
38
- apiUrl: 'https://...', // optional — custom API endpoint
225
+ // Required
226
+ projectKey: 'mtb_proj_xxx',
227
+
228
+ // Optional
229
+ locale: 'en', // UI language
230
+ position: 'right', // Tab position: 'left' | 'right'
231
+ theme: 'auto', // 'light' | 'dark' | 'auto'
232
+ frustrationDetection: true, // Proactive frustration prompts
233
+ apiUrl: 'https://...', // Self-hosted API endpoint
234
+
235
+ // User identification (recommended)
39
236
  user: {
40
- id: 'usr_123', // optional — identify the user
41
- email: 'alex@company.co',
237
+ id: 'usr_123',
238
+ email: 'alex@example.com',
42
239
  name: 'Alex Chen',
43
240
  },
44
- });
241
+ })
45
242
  ```
46
243
 
47
- ## How it works
244
+ ### Identity Verification
48
245
 
49
- 1. A green **Feedback** tab appears on the right edge of the page
50
- 2. Clicking the tab enters **Mark up mode** — a toolbar appears at the top
51
- 3. Hover over any element to highlight it (blue outline + tooltip)
52
- 4. Click to place a **pin** annotation
53
- 5. Or drag to **draw** a free-form highlight
54
- 6. A **Comment popup** appears — describe the issue and hit Submit
55
- 7. The SDK captures a screenshot, collects page context (URL, browser, OS, console errors), and sends everything to the Make This Better API
56
- 8. Your dashboard shows the structured feedback with AI triage
246
+ Identity verification links feedback to authenticated users and lets them view their own submissions on the feedback board.
57
247
 
58
- ## What gets collected automatically
248
+ **Level 0 -- Anonymous** (default): No user token. Feedback is anonymous.
59
249
 
60
- - Page URL
61
- - Browser and OS
62
- - Screen resolution
63
- - Console errors (captured via `window.onerror`)
64
- - Target element CSS selector and text content
65
- - Page screenshot (via `html-to-image`, invisible to the user)
66
- - Annotation coordinates
250
+ ```js
251
+ MakeThisBetter.init({ projectKey: 'mtb_proj_xxx' })
252
+ ```
67
253
 
68
- ## Conditional loading
254
+ **Level 1 -- Static token**: Pass a pre-generated JWT. Simple, but the token may expire during long sessions.
69
255
 
70
- The Widget only loads when you call `MakeThisBetter.init()`. Control who sees it with your own logic:
256
+ ```js
257
+ MakeThisBetter.init({
258
+ projectKey: 'mtb_proj_xxx',
259
+ userToken: 'eyJhbGciOiJIUzI1NiIs...',
260
+ })
261
+ ```
262
+
263
+ **Level 2 -- Dynamic token (recommended)**: Pass an async function that returns a fresh JWT. The SDK calls it before each API request, so tokens never go stale.
71
264
 
72
265
  ```js
73
- // Only show to admins
74
- if (currentUser.isAdmin) {
75
- MakeThisBetter.init({ projectKey: 'mtb_proj_xxx', user: { id: currentUser.id } });
76
- }
266
+ MakeThisBetter.init({
267
+ projectKey: 'mtb_proj_xxx',
268
+ userTokenFn: async () => {
269
+ const res = await fetch('/api/mtb-token')
270
+ const { token } = await res.json()
271
+ return token
272
+ },
273
+ })
77
274
  ```
78
275
 
276
+ When `userToken` or `userTokenFn` is set, the widget sends an `X-User-Token` header with every request. After submitting feedback, a "View my feedback" link appears that opens the project board filtered to the user's submissions.
277
+
278
+ Generate tokens server-side using your project's HMAC secret (available in your project settings):
279
+
79
280
  ```ruby
80
281
  # Rails example
81
- <% if current_user&.admin? %>
82
- <script>
83
- MakeThisBetter.init({
84
- projectKey: '<%= Rails.application.credentials.mtb_project_key %>',
85
- user: { id: '<%= current_user.id %>', email: '<%= current_user.email %>' }
86
- });
87
- </script>
88
- <% end %>
282
+ payload = { sub: current_user.id, email: current_user.email, exp: 1.hour.from_now.to_i }
283
+ JWT.encode(payload, project.widget_secret, 'HS256')
89
284
  ```
90
285
 
286
+ ### Conditional Loading
287
+
288
+ ```js
289
+ // Only show to beta users
290
+ if (user.isBetaTester) {
291
+ MakeThisBetter.init({ projectKey: 'mtb_proj_xxx', user: { id: user.id } })
292
+ }
293
+ ```
294
+
295
+ ## Self-Hosting
296
+
297
+ The Widget works with any backend — not just makethisbetter.dev. Implement one API endpoint and point `apiUrl` at your server:
298
+
299
+ ```js
300
+ MakeThisBetter.init({
301
+ projectKey: 'your-key',
302
+ apiUrl: 'https://feedback.yoursite.com',
303
+ })
304
+ ```
305
+
306
+ Your backend needs to handle `POST /api/v1/widget/feedbacks` (multipart/form-data with description, screenshot, console errors, etc). The Widget takes care of everything else — annotation, recording, frustration detection, context collection.
307
+
308
+ The cloud platform at [makethisbetter.dev](https://makethisbetter.dev) adds AI triage, dashboard, GitHub/Linear sync, and email notifications on top.
309
+
310
+ ## API
311
+
312
+ ```ts
313
+ import { MakeThisBetter } from 'makethisbetter'
314
+
315
+ // Start the widget
316
+ MakeThisBetter.init(config: MakeThisBetterConfig): void
317
+
318
+ // Remove the widget and clean up all listeners
319
+ MakeThisBetter.destroy(): void
320
+ ```
321
+
322
+ ## Architecture
323
+
324
+ The widget runs inside a Shadow DOM container, isolating its styles from your page. No CSS conflicts, no z-index wars.
325
+
326
+ ```
327
+ Shadow DOM Host (#mtb-widget-host)
328
+ +-- Feedback Tab (entry point)
329
+ +-- Annotation Toolbar (Mark up / Record toggle)
330
+ +-- Annotation Session (pin + draw overlays)
331
+ +-- Comment Popup (description + submit)
332
+ +-- AI Clarification Card (follow-up conversation)
333
+ +-- Success Card (confirmation)
334
+ +-- Frustration Prompt (proactive trigger)
335
+ ```
336
+
337
+ ## Bundle Size
338
+
339
+ | Format | Size | gzip |
340
+ |--------|------|------|
341
+ | IIFE | ~80 KB | ~23 KB |
342
+ | ESM | ~94 KB | ~25 KB |
343
+
344
+ rrweb is loaded on demand and not included in these numbers.
345
+
91
346
  ## Development
92
347
 
93
348
  ```bash
349
+ git clone https://github.com/makethisbetter/makethisbetter-js.git
350
+ cd makethisbetter-js
94
351
  npm install
95
- npm run build # build dist/
96
- open demo/index.html # run the standalone demo
97
- npm run dev # optional: serve demo at localhost:5173
98
- npm test # run tests
99
- npm run type-check # TypeScript check
352
+ npm run dev # Dev server at localhost:5173
353
+ npm run build # Build all formats to dist/
354
+ npm test # Run tests
355
+ npm run type-check # TypeScript validation
100
356
  ```
101
357
 
102
- ## Bundle size
358
+ ## Related
103
359
 
104
- | Format | Size | gzip |
105
- |--------|--------|--------|
106
- | IIFE | 42 KB | 13.6 KB |
107
- | ESM | 50 KB | 14.7 KB |
360
+ | Package | What it does |
361
+ |---------|-------------|
362
+ | [Make This Better](https://makethisbetter.dev) | The platform — dashboard, AI triage, feedback board |
363
+ | [@makethisbetter/mcp](https://github.com/makethisbetter/mcp) | MCP server your coding agent reads feedback directly |
364
+ | [makethisbetter CLI](https://github.com/makethisbetter/cli) | Terminal tool for managing feedback |
365
+ | [makethisbetter Skills](https://github.com/makethisbetter/skills) | Claude Code skills — `/makethisbetter` in your editor |
108
366
 
109
367
  ## License
110
368
 
111
- [Business Source License 1.1](LICENSE) — free for non-competitive use, converts to MIT on 2029-01-01.
369
+ [Business Source License 1.1](LICENSE) — free for any use that does not compete with Make This Better's commercial offering. Converts to MIT on 2029-01-01.
370
+
371
+ ---
372
+
373
+ <details>
374
+ <summary><strong>GitHub repo settings</strong></summary>
375
+
376
+ - **Description**: Drop-in feedback widget — from rage click to agent-ready fix
377
+ - **Homepage**: https://makethisbetter.dev
378
+ - **Topics**: feedback, widget, ai, mcp, claude-code, cursor, vibe-coding
112
379
 
113
- Free to self-host. Cloud platform at [makethisbetter.dev](https://makethisbetter.dev).
380
+ </details>
@@ -10,9 +10,14 @@ export declare class AnnotationSession {
10
10
  private drawLayer;
11
11
  private pinCount;
12
12
  private interactionActive;
13
+ private pendingHighlightFrame;
14
+ private lastMoveX;
15
+ private lastMoveY;
13
16
  constructor(shadow: ShadowContainer, messages: I18nMessages, onReady: (annotation: Annotation, targetName: string) => void);
14
17
  private handleMouseDown;
15
18
  private handleMouseMove;
19
+ private updateHighlight;
20
+ private cancelPendingHighlight;
16
21
  private handleMouseUp;
17
22
  dismissInteraction(): void;
18
23
  destroy(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/annotate/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAQ1C,qBAAa,iBAAiB;IAU1B,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,OAAO;IAVjB,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,SAAS,CAAW;IAC5B,OAAO,CAAC,SAAS,CAAW;IAC5B,OAAO,CAAC,QAAQ,CAAI;IACpB,OAAO,CAAC,iBAAiB,CAAO;gBAG9B,MAAM,EAAE,eAAe,EACf,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI;IAkBvE,OAAO,CAAC,eAAe;IAKvB,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,aAAa;IAyBrB,kBAAkB,IAAI,IAAI;IAO1B,OAAO,IAAI,IAAI;CAKhB"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/annotate/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAQ1C,qBAAa,iBAAiB;IAa1B,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,OAAO;IAbjB,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,SAAS,CAAW;IAC5B,OAAO,CAAC,SAAS,CAAW;IAC5B,OAAO,CAAC,QAAQ,CAAI;IACpB,OAAO,CAAC,iBAAiB,CAAO;IAChC,OAAO,CAAC,qBAAqB,CAAsB;IACnD,OAAO,CAAC,SAAS,CAAI;IACrB,OAAO,CAAC,SAAS,CAAI;gBAGnB,MAAM,EAAE,eAAe,EACf,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI;IAmBvE,OAAO,CAAC,eAAe;IAKvB,OAAO,CAAC,eAAe;IAiBvB,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,sBAAsB;IAM9B,OAAO,CAAC,aAAa;IAyBrB,kBAAkB,IAAI,IAAI;IAQ1B,OAAO,IAAI,IAAI;CAKhB"}
@@ -1,10 +1,16 @@
1
- import type { FeedbackPayload } from '../types';
1
+ import type { FeedbackPayload, FeedbackResponse, ClarifyResponse } from '../types';
2
2
  export declare class ApiClient {
3
3
  private apiUrl;
4
4
  private projectKey;
5
5
  private retryDelayMs;
6
- constructor(projectKey: string, apiUrl?: string, retryDelayMs?: number);
7
- submitFeedback(payload: FeedbackPayload, screenshot: Blob | null): Promise<void>;
6
+ private userToken?;
7
+ private userTokenFn?;
8
+ constructor(projectKey: string, apiUrl?: string, retryDelayMs?: number, userToken?: string, userTokenFn?: () => Promise<string>);
9
+ resolveUserToken(): Promise<string | undefined>;
10
+ private authHeaders;
11
+ submitFeedback(payload: FeedbackPayload, screenshot: Blob | null): Promise<FeedbackResponse>;
12
+ startClarification(feedbackId: string, message?: string): Promise<ClarifyResponse>;
13
+ getClarification(feedbackId: string): Promise<ClarifyResponse>;
8
14
  private fetchWithRetry;
9
15
  }
10
16
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAI/C,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,YAAY,CAAQ;gBAEhB,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,YAAY,SAAO;IAM9D,cAAc,CAAC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,IAAI,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;YAqCxE,cAAc;CAmB7B"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAIlF,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,SAAS,CAAC,CAAQ;IAC1B,OAAO,CAAC,WAAW,CAAC,CAAuB;gBAE/B,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,YAAY,SAAO,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC;IAQvH,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;YAKvC,WAAW;IAQnB,cAAc,CAAC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,IAAI,GAAG,IAAI,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA2C5F,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAYlF,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;YAStD,cAAc;CAmB7B"}
@@ -9,6 +9,7 @@ type ErrorListener = (event: ErrorSourceEvent) => void;
9
9
  declare class ErrorSource {
10
10
  private listeners;
11
11
  private originalOnError;
12
+ private installedOnError;
12
13
  private rejectionHandler;
13
14
  private hooked;
14
15
  subscribe(listener: ErrorListener): () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"error-source.d.ts","sourceRoot":"","sources":["../../src/context/error-source.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAA;AAEtD,cAAM,WAAW;IACf,OAAO,CAAC,SAAS,CAA2B;IAC5C,OAAO,CAAC,eAAe,CAAmC;IAC1D,OAAO,CAAC,gBAAgB,CAAoD;IAC5E,OAAO,CAAC,MAAM,CAAQ;IAEtB,SAAS,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,IAAI;IAS9C,OAAO,CAAC,IAAI;IAoBZ,OAAO,CAAC,MAAM;IAWd,OAAO,CAAC,IAAI;CAGb;AAED,eAAO,MAAM,WAAW,aAAoB,CAAA"}
1
+ {"version":3,"file":"error-source.d.ts","sourceRoot":"","sources":["../../src/context/error-source.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAA;AAEtD,cAAM,WAAW;IACf,OAAO,CAAC,SAAS,CAA2B;IAC5C,OAAO,CAAC,eAAe,CAAmC;IAC1D,OAAO,CAAC,gBAAgB,CAAmC;IAC3D,OAAO,CAAC,gBAAgB,CAAoD;IAC5E,OAAO,CAAC,MAAM,CAAQ;IAEtB,SAAS,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,IAAI;IAS9C,OAAO,CAAC,IAAI;IAqBZ,OAAO,CAAC,MAAM;IAgBd,OAAO,CAAC,IAAI;CAGb;AAED,eAAO,MAAM,WAAW,aAAoB,CAAA"}
@@ -1,4 +1,4 @@
1
- export type FrustrationSignal = 'rage_click' | 'dead_click' | 'console_error';
1
+ export type FrustrationSignal = 'rage_click' | 'dead_click' | 'console_error' | 'rapid_navigation' | 'form_failure' | 'error_page' | 'dead_click_dom';
2
2
  export interface FrustrationEvent {
3
3
  signal: FrustrationSignal;
4
4
  target?: string;
@@ -15,10 +15,34 @@ export declare class FrustrationDetector {
15
15
  private deadClickCount;
16
16
  private cooldownUntil;
17
17
  private static readonly COOLDOWN_MS;
18
+ private navTimestamps;
19
+ private boundPopstateHandler;
20
+ private originalPushState;
21
+ private originalReplaceState;
22
+ private installedPushState;
23
+ private installedReplaceState;
24
+ private boundSubmitHandler;
25
+ private boundInvalidHandler;
26
+ private errorPageUrls;
27
+ private domObserver;
28
+ private pendingDomChecks;
29
+ private lastMutationAt;
18
30
  constructor(onFrustration: (event: FrustrationEvent) => void);
19
31
  start(): void;
20
32
  stop(): void;
33
+ private startNavigationTracking;
34
+ private stopNavigationTracking;
35
+ private startFormTracking;
36
+ private stopFormTracking;
21
37
  private handleClick;
38
+ private handleNavigation;
39
+ private handleFormSubmit;
40
+ private handleFormInvalid;
41
+ private checkErrorPage;
42
+ private checkDeadClickDom;
43
+ private ensureDomObserver;
44
+ private disconnectDomObserver;
45
+ private looksInteractive;
22
46
  private isInteractive;
23
47
  private isWidgetElement;
24
48
  private emitIfReady;
@@ -1 +1 @@
1
- {"version":3,"file":"frustration.d.ts","sourceRoot":"","sources":["../../src/context/frustration.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,YAAY,GAAG,eAAe,CAAA;AAE7E,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,iBAAiB,CAAA;IACzB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CAClB;AAmBD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,aAAa,CAAmC;IACxD,OAAO,CAAC,iBAAiB,CAAyB;IAClD,OAAO,CAAC,iBAAiB,CAA4B;IACrD,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,UAAU,CAAI;IACtB,OAAO,CAAC,cAAc,CAAI;IAC1B,OAAO,CAAC,aAAa,CAAI;IACzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAS;gBAEhC,aAAa,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI;IAK5D,KAAK,IAAI,IAAI;IASb,IAAI,IAAI,IAAI;IASZ,OAAO,CAAC,WAAW;IAqCnB,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,gBAAgB;CAIzB"}
1
+ {"version":3,"file":"frustration.d.ts","sourceRoot":"","sources":["../../src/context/frustration.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,iBAAiB,GACzB,YAAY,GACZ,YAAY,GACZ,eAAe,GACf,kBAAkB,GAClB,cAAc,GACd,YAAY,GACZ,gBAAgB,CAAA;AAEpB,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,iBAAiB,CAAA;IACzB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CAClB;AA6BD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,aAAa,CAAmC;IACxD,OAAO,CAAC,iBAAiB,CAAyB;IAClD,OAAO,CAAC,iBAAiB,CAA4B;IACrD,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,UAAU,CAAI;IACtB,OAAO,CAAC,cAAc,CAAI;IAC1B,OAAO,CAAC,aAAa,CAAI;IACzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAS;IAE5C,OAAO,CAAC,aAAa,CAAe;IACpC,OAAO,CAAC,oBAAoB,CAA4B;IACxD,OAAO,CAAC,iBAAiB,CAAoC;IAC7D,OAAO,CAAC,oBAAoB,CAAuC;IACnE,OAAO,CAAC,kBAAkB,CAAoC;IAC9D,OAAO,CAAC,qBAAqB,CAAuC;IACpE,OAAO,CAAC,kBAAkB,CAAoC;IAC9D,OAAO,CAAC,mBAAmB,CAAoC;IAC/D,OAAO,CAAC,aAAa,CAAoB;IACzC,OAAO,CAAC,WAAW,CAAgC;IACnD,OAAO,CAAC,gBAAgB,CAAI;IAC5B,OAAO,CAAC,cAAc,CAAK;gBAEf,aAAa,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI;IAK5D,KAAK,IAAI,IAAI;IAab,IAAI,IAAI,IAAI;IAeZ,OAAO,CAAC,uBAAuB;IAsB/B,OAAO,CAAC,sBAAsB;IAoB9B,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,gBAAgB;IAWxB,OAAO,CAAC,WAAW;IAuCnB,OAAO,CAAC,gBAAgB;IAiBxB,OAAO,CAAC,gBAAgB;IAiBxB,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,cAAc;IAmCtB,OAAO,CAAC,iBAAiB;IAqBzB,OAAO,CAAC,iBAAiB;IAazB,OAAO,CAAC,qBAAqB;IAK7B,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,gBAAgB;CAIzB"}
@@ -0,0 +1,54 @@
1
+ declare const _default: {
2
+ tab: string;
3
+ toolbar: {
4
+ markup: string;
5
+ record: string;
6
+ hint: string;
7
+ hintRecord: string;
8
+ exit: string;
9
+ };
10
+ popup: {
11
+ about: string;
12
+ placeholder: string;
13
+ submit: string;
14
+ cancel: string;
15
+ quickOptions: {
16
+ emoji: string;
17
+ label: string;
18
+ }[];
19
+ };
20
+ success: {
21
+ title: string;
22
+ message: string;
23
+ view_feedback: string;
24
+ close: string;
25
+ };
26
+ error: {
27
+ submit: string;
28
+ };
29
+ pet: {
30
+ bubble: string;
31
+ };
32
+ frustration: {
33
+ prompt: string;
34
+ action: string;
35
+ dismiss: string;
36
+ };
37
+ annotation: {
38
+ drawing: string;
39
+ element: string;
40
+ };
41
+ record: {
42
+ stop: string;
43
+ timer_label: string;
44
+ max_reached: string;
45
+ };
46
+ clarify: {
47
+ thinking: string;
48
+ placeholder: string;
49
+ send: string;
50
+ skip: string;
51
+ };
52
+ };
53
+ export default _default;
54
+ //# sourceMappingURL=de.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"de.d.ts","sourceRoot":"","sources":["../../src/i18n/de.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,wBAqDC"}
package/dist/i18n/en.d.ts CHANGED
@@ -20,6 +20,7 @@ declare const _default: {
20
20
  success: {
21
21
  title: string;
22
22
  message: string;
23
+ view_feedback: string;
23
24
  close: string;
24
25
  };
25
26
  error: {
@@ -42,6 +43,12 @@ declare const _default: {
42
43
  timer_label: string;
43
44
  max_reached: string;
44
45
  };
46
+ clarify: {
47
+ thinking: string;
48
+ placeholder: string;
49
+ send: string;
50
+ skip: string;
51
+ };
45
52
  };
46
53
  export default _default;
47
54
  //# sourceMappingURL=en.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/i18n/en.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,wBA8CC"}
1
+ {"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/i18n/en.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,wBAqDC"}