makethisbetter 1.9.0 → 1.9.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.
@@ -7,6 +7,8 @@ interface ClarifyCardOptions {
7
7
  apiClient: ApiClient;
8
8
  messages: I18nMessages;
9
9
  onFinalize: () => Promise<void> | void;
10
+ element?: HTMLDivElement;
11
+ position?: 'left' | 'right';
10
12
  x?: number;
11
13
  y?: number;
12
14
  preloadedResult?: ClarifyStreamResult;
@@ -49,7 +51,7 @@ export declare class ClarifyCard {
49
51
  private stopPolling;
50
52
  private poll;
51
53
  private handleDone;
52
- private disableConversationInput;
54
+ private showFinalizeButton;
53
55
  private finalize;
54
56
  private showRetryButton;
55
57
  private renderConversation;
@@ -1 +1 @@
1
- {"version":3,"file":"clarify.d.ts","sourceRoot":"","sources":["../../src/popup/clarify.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,SAAS,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AASnE,UAAU,kBAAkB;IAC1B,mBAAmB,EAAE,MAAM,CAAA;IAC3B,eAAe,EAAE,MAAM,CAAA;IACvB,SAAS,EAAE,SAAS,CAAA;IACpB,QAAQ,EAAE,YAAY,CAAA;IACtB,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACtC,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,eAAe,CAAC,EAAE,mBAAmB,CAAA;IACrC,oBAAoB,CAAC,EAAE,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAA;CAC3D;AAKD,qBAAa,WAAW;IACtB,OAAO,CAAC,EAAE,CAAgB;IAC1B,OAAO,CAAC,UAAU,CAAiB;IACnC,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,SAAS,CAA8C;IAC/D,OAAO,CAAC,YAAY,CAAI;IACxB,OAAO,CAAC,eAAe,CAA8B;IACrD,OAAO,CAAC,mBAAmB,CAAQ;IACnC,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,SAAS,CAAW;IAC5B,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,IAAI,CAAc;IAC1B,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,IAAI,CAAQ;IACpB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,SAAS,CAAQ;IAEzB,OAAO,CAAC,eAAe,CAAC,CAAqB;IAC7C,OAAO,CAAC,oBAAoB,CAAC,CAAqC;gBAEtD,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,kBAAkB;IAwB7D,OAAO,CAAC,YAAY;IA0BpB,OAAO,CAAC,SAAS;IAmCjB,OAAO,CAAC,UAAU;YAuBJ,iBAAiB;YA8BjB,WAAW;YA+BX,cAAc;YAmBd,wBAAwB;YAgBxB,aAAa;IAY3B,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,WAAW;YAOL,IAAI;IAwBlB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,wBAAwB;YAKlB,QAAQ;IAgBtB,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,cAAc;IAItB,OAAO,IAAI,IAAI;CAKhB"}
1
+ {"version":3,"file":"clarify.d.ts","sourceRoot":"","sources":["../../src/popup/clarify.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,SAAS,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AASnE,UAAU,kBAAkB;IAC1B,mBAAmB,EAAE,MAAM,CAAA;IAC3B,eAAe,EAAE,MAAM,CAAA;IACvB,SAAS,EAAE,SAAS,CAAA;IACpB,QAAQ,EAAE,YAAY,CAAA;IACtB,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACtC,OAAO,CAAC,EAAE,cAAc,CAAA;IACxB,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IAC3B,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,eAAe,CAAC,EAAE,mBAAmB,CAAA;IACrC,oBAAoB,CAAC,EAAE,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAA;CAC3D;AAKD,qBAAa,WAAW;IACtB,OAAO,CAAC,EAAE,CAAgB;IAC1B,OAAO,CAAC,UAAU,CAAiB;IACnC,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,SAAS,CAA8C;IAC/D,OAAO,CAAC,YAAY,CAAI;IACxB,OAAO,CAAC,eAAe,CAA8B;IACrD,OAAO,CAAC,mBAAmB,CAAQ;IACnC,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,SAAS,CAAW;IAC5B,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,IAAI,CAAc;IAC1B,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,IAAI,CAAQ;IACpB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,SAAS,CAAQ;IAEzB,OAAO,CAAC,eAAe,CAAC,CAAqB;IAC7C,OAAO,CAAC,oBAAoB,CAAC,CAAqC;gBAEtD,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,kBAAkB;IA4B7D,OAAO,CAAC,YAAY;IA+BpB,OAAO,CAAC,SAAS;IAmCjB,OAAO,CAAC,UAAU;YAuBJ,iBAAiB;YA8BjB,WAAW;YA+BX,cAAc;YAmBd,wBAAwB;YAgBxB,aAAa;IAY3B,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,WAAW;YAOL,IAAI;IAwBlB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,kBAAkB;YAgBZ,QAAQ;IAgBtB,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,cAAc;IAItB,OAAO,IAAI,IAAI;CAKhB"}
@@ -10,6 +10,7 @@ interface PopupOptions {
10
10
  onClose: () => void;
11
11
  onMyFeedback?: () => void;
12
12
  messages: I18nMessages;
13
+ position?: 'left' | 'right';
13
14
  }
14
15
  export declare class CommentPopup {
15
16
  private el;
@@ -29,6 +30,7 @@ export declare class CommentPopup {
29
30
  private submit;
30
31
  setLoading(loading: boolean): void;
31
32
  setError(message: string): void;
33
+ releaseElement(): HTMLDivElement;
32
34
  destroy(): void;
33
35
  }
34
36
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"comment.d.ts","sourceRoot":"","sources":["../../src/popup/comment.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;AAG1C,UAAU,YAAY;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,QAAQ,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAA;IACzB,QAAQ,EAAE,YAAY,CAAA;CACvB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,EAAE,CAAgB;IAC1B,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,SAAS,CAAoB;IACrC,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,OAAO,CAAY;IAC3B,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,QAAQ,CAAc;gBAElB,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,YAAY;IAqBvD,OAAO,CAAC,SAAS;IA6CjB,OAAO,CAAC,aAAa;IAqCrB,OAAO,CAAC,UAAU;IA2BlB,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,MAAM;IAMd,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAclC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK/B,OAAO,IAAI,IAAI;CAGhB"}
1
+ {"version":3,"file":"comment.d.ts","sourceRoot":"","sources":["../../src/popup/comment.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;AAG1C,UAAU,YAAY;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,QAAQ,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAA;IACzB,QAAQ,EAAE,YAAY,CAAA;IACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAC5B;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,EAAE,CAAgB;IAC1B,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,SAAS,CAAoB;IACrC,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,OAAO,CAAY;IAC3B,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,QAAQ,CAAc;gBAElB,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,YAAY;IAqBvD,OAAO,CAAC,SAAS;IA6CjB,OAAO,CAAC,aAAa;IAwCrB,OAAO,CAAC,UAAU;IA2BlB,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,MAAM;IAMd,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAclC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK/B,cAAc,IAAI,cAAc;IAIhC,OAAO,IAAI,IAAI;CAGhB"}
@@ -1 +1 @@
1
- {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/widget/controller.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,oBAAoB,EAAqD,MAAM,UAAU,CAAA;AAYvG,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,GAAG,CAA2B;IACtC,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,GAAG,CAA0B;IACrC,OAAO,CAAC,KAAK,CAA4B;IACzC,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,iBAAiB,CAAqC;IAC9D,OAAO,CAAC,SAAS,CAAW;IAC5B,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,mBAAmB,CAAqB;IAChD,OAAO,CAAC,mBAAmB,CAAmC;IAC9D,OAAO,CAAC,QAAQ,CAAgC;IAChD,OAAO,CAAC,IAAI,CAAe;IAC3B,OAAO,CAAC,GAAG,CAAa;IACxB,OAAO,CAAC,iBAAiB,CAA0B;IACnD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,YAAY,CAAwC;IAC5D,OAAO,CAAC,gBAAgB,CAAgC;IACxD,OAAO,CAAC,gBAAgB,CAAyC;IACjE,OAAO,CAAC,iBAAiB,CAAI;IAC7B,OAAO,CAAC,WAAW,CAAyE;IAC5F,OAAO,CAAC,0BAA0B,CAAQ;gBAE9B,MAAM,EAAE,oBAAoB;IAoBxC,OAAO,CAAC,aAAa,CAuBpB;IAED,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,wBAAwB;IAKhC,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,uBAAuB;IA+B/B,OAAO,CAAC,gBAAgB,CAKvB;IAED,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,SAAS;IAwBjB,OAAO,CAAC,sBAAsB;YAYhB,YAAY;YAyCZ,kBAAkB;IA0ChC,OAAO,CAAC,oBAAoB;IAc5B,OAAO,CAAC,WAAW;YAuBL,kBAAkB;IAsBhC,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,wBAAwB;IAoBhC,OAAO,CAAC,OAAO;IA4Bf,OAAO,IAAI,IAAI;CAahB"}
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/widget/controller.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,oBAAoB,EAAqD,MAAM,UAAU,CAAA;AAYvG,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,GAAG,CAA2B;IACtC,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,GAAG,CAA0B;IACrC,OAAO,CAAC,KAAK,CAA4B;IACzC,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,iBAAiB,CAAqC;IAC9D,OAAO,CAAC,SAAS,CAAW;IAC5B,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,mBAAmB,CAAqB;IAChD,OAAO,CAAC,mBAAmB,CAAmC;IAC9D,OAAO,CAAC,QAAQ,CAAgC;IAChD,OAAO,CAAC,IAAI,CAAe;IAC3B,OAAO,CAAC,GAAG,CAAa;IACxB,OAAO,CAAC,iBAAiB,CAA0B;IACnD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,YAAY,CAAwC;IAC5D,OAAO,CAAC,gBAAgB,CAAgC;IACxD,OAAO,CAAC,gBAAgB,CAAyC;IACjE,OAAO,CAAC,iBAAiB,CAAI;IAC7B,OAAO,CAAC,WAAW,CAAyE;IAC5F,OAAO,CAAC,0BAA0B,CAAQ;gBAE9B,MAAM,EAAE,oBAAoB;IAoBxC,OAAO,CAAC,aAAa,CAuBpB;IAED,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,wBAAwB;IAKhC,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,uBAAuB;IA+B/B,OAAO,CAAC,gBAAgB,CAKvB;IAED,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,SAAS;IAyBjB,OAAO,CAAC,sBAAsB;YAYhB,YAAY;YAyCZ,kBAAkB;IAqChC,OAAO,CAAC,oBAAoB;IAgB5B,OAAO,CAAC,WAAW;YA0BL,kBAAkB;IAsBhC,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,wBAAwB;IAoBhC,OAAO,CAAC,OAAO;IA4Bf,OAAO,IAAI,IAAI;CAahB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "makethisbetter",
3
- "version": "1.9.0",
3
+ "version": "1.9.2",
4
4
  "description": "Make This Better JS Widget SDK — embed user feedback collection in any website",
5
5
  "type": "module",
6
6
  "main": "./dist/makethisbetter.cjs",
@@ -60,7 +60,7 @@
60
60
  "homepage": "https://makethisbetter.dev",
61
61
  "repository": {
62
62
  "type": "git",
63
- "url": "https://github.com/makethisbetter/makethisbetter-js.git"
63
+ "url": "git+https://github.com/makethisbetter/makethisbetter-js.git"
64
64
  },
65
65
  "license": "MIT"
66
66
  }
package/src/i18n/de.ts CHANGED
@@ -69,6 +69,7 @@ export default {
69
69
  thinking: 'Einen Moment...',
70
70
  placeholder: 'Antwort eingeben — oder Frage überspringen',
71
71
  send: 'Senden',
72
+ send_feedback: 'Feedback senden',
72
73
  skip: 'Überspringen & senden',
73
74
  retry: 'Erneut versuchen',
74
75
  },
package/src/i18n/en.ts CHANGED
@@ -69,6 +69,7 @@ export default {
69
69
  thinking: 'Thinking...',
70
70
  placeholder: 'Type your answer — or skip the question',
71
71
  send: 'Send',
72
+ send_feedback: 'Send feedback',
72
73
  skip: 'Skip & send',
73
74
  retry: 'Retry',
74
75
  },
package/src/i18n/es.ts CHANGED
@@ -69,6 +69,7 @@ export default {
69
69
  thinking: 'Pensando...',
70
70
  placeholder: 'Escribe tu respuesta — u omite la pregunta',
71
71
  send: 'Enviar',
72
+ send_feedback: 'Enviar comentario',
72
73
  skip: 'Omitir y enviar',
73
74
  retry: 'Reintentar',
74
75
  },
package/src/i18n/fr.ts CHANGED
@@ -69,6 +69,7 @@ export default {
69
69
  thinking: 'Réflexion...',
70
70
  placeholder: 'Saisissez votre réponse — ou ignorez la question',
71
71
  send: 'Envoyer',
72
+ send_feedback: 'Envoyer le retour',
72
73
  skip: 'Ignorer et envoyer',
73
74
  retry: 'Réessayer',
74
75
  },
package/src/i18n/ja.ts CHANGED
@@ -69,6 +69,7 @@ export default {
69
69
  thinking: '考え中...',
70
70
  placeholder: '回答を入力、または質問をスキップ',
71
71
  send: '送信',
72
+ send_feedback: 'フィードバックを送信',
72
73
  skip: 'スキップして送信',
73
74
  retry: '再試行',
74
75
  },
package/src/i18n/ko.ts CHANGED
@@ -69,6 +69,7 @@ export default {
69
69
  thinking: '생각 중...',
70
70
  placeholder: '답변을 입력하거나 질문을 건너뛰세요',
71
71
  send: '보내기',
72
+ send_feedback: '피드백 보내기',
72
73
  skip: '건너뛰고 보내기',
73
74
  retry: '재시도',
74
75
  },
package/src/i18n/zh-CN.ts CHANGED
@@ -69,6 +69,7 @@ export default {
69
69
  thinking: '思考中...',
70
70
  placeholder: '输入回答,或跳过问题',
71
71
  send: '发送',
72
+ send_feedback: '发送反馈',
72
73
  skip: '跳过并发送',
73
74
  retry: '重试',
74
75
  },
@@ -65,6 +65,38 @@ describe('ClarifyCard', () => {
65
65
  shadow.destroy()
66
66
  })
67
67
 
68
+ it('reuses the current popup element without moving or replaying its entrance', async () => {
69
+ const shadow = new ShadowContainer()
70
+ const element = shadow.el<HTMLDivElement>('div', 'mtb-popup')
71
+ element.style.left = '40px'
72
+ element.style.top = '60px'
73
+ shadow.append(element)
74
+
75
+ const apiClient = mockApiClient()
76
+ const card = new ClarifyCard(shadow, {
77
+ submissionSessionId: 'submission_123',
78
+ submissionToken: 'submission-secret',
79
+ apiClient,
80
+ messages: getMessages('en'),
81
+ onFinalize: vi.fn(),
82
+ element,
83
+ x: 400,
84
+ y: 300,
85
+ })
86
+
87
+ await vi.waitFor(() => {
88
+ expect(apiClient.startClarification).toHaveBeenCalled()
89
+ })
90
+ expect(shadow.root.querySelector('.mtb-clarify')).toBe(element)
91
+ expect(element.className).toBe('mtb-clarify mtb-clarify-continuation')
92
+ expect(element.style.left).toBe('40px')
93
+ expect(element.style.top).toBe('60px')
94
+ expect(shadow.root.children).toHaveLength(2)
95
+
96
+ card.destroy()
97
+ shadow.destroy()
98
+ })
99
+
68
100
  it('renders header with skip button', async () => {
69
101
  const { shadow, card, messages, apiClient } = setupCard()
70
102
  await vi.waitFor(() => {
@@ -98,7 +130,7 @@ describe('ClarifyCard', () => {
98
130
  const el = shadow.root.querySelector<HTMLDivElement>('.mtb-clarify')!
99
131
  const left = parseInt(el.style.left, 10)
100
132
  const top = parseInt(el.style.top, 10)
101
- expect(left + 346).toBeLessThanOrEqual(1024)
133
+ expect(left + 346).toBeLessThanOrEqual(1024 - 44)
102
134
  expect(top).toBeGreaterThanOrEqual(12)
103
135
  expect(top).toBeLessThanOrEqual(768 - 12)
104
136
 
@@ -106,6 +138,26 @@ describe('ClarifyCard', () => {
106
138
  shadow.destroy()
107
139
  })
108
140
 
141
+ it('leaves room for a left-side feedback tab', async () => {
142
+ const shadow = new ShadowContainer()
143
+ const card = new ClarifyCard(shadow, {
144
+ submissionSessionId: 'submission_123',
145
+ submissionToken: 'submission-secret',
146
+ apiClient: mockApiClient(),
147
+ messages: getMessages('en'),
148
+ onFinalize: vi.fn(),
149
+ position: 'left',
150
+ x: 0,
151
+ y: 300,
152
+ })
153
+ const element = shadow.root.querySelector<HTMLDivElement>('.mtb-clarify')!
154
+
155
+ expect(Number.parseFloat(element.style.left)).toBeGreaterThanOrEqual(44)
156
+
157
+ card.destroy()
158
+ shadow.destroy()
159
+ })
160
+
109
161
  it('renders the redesigned header title and subtitle', async () => {
110
162
  const { shadow, card, messages } = setupCard()
111
163
  expect(shadow.root.querySelector('.mtb-clarify-title')?.textContent).toBe(messages.clarify.title)
@@ -253,9 +305,12 @@ describe('ClarifyCard', () => {
253
305
  expect(startClarification).toHaveBeenCalledTimes(2)
254
306
  })
255
307
  expect(startClarification).toHaveBeenCalledWith('submission_123', 'submission-secret', 'Button does nothing')
308
+ expect(onFinalize).not.toHaveBeenCalled()
256
309
  await vi.waitFor(() => {
257
- expect(onFinalize).toHaveBeenCalled()
310
+ expect(shadow.root.querySelector('.mtb-clarify-send-feedback')).toBeTruthy()
258
311
  })
312
+ shadow.root.querySelector<HTMLButtonElement>('.mtb-clarify-send-feedback')!.click()
313
+ expect(onFinalize).toHaveBeenCalledOnce()
259
314
 
260
315
  card.destroy()
261
316
  shadow.destroy()
@@ -382,7 +437,7 @@ describe('ClarifyCard', () => {
382
437
  shadow.destroy()
383
438
  })
384
439
 
385
- it('auto-finalizes when done=true from start', async () => {
440
+ it('waits for Send feedback when done=true from start', async () => {
386
441
  const startClarification = vi.fn().mockResolvedValue({
387
442
  status: 'complete',
388
443
  messages: [{ role: 'assistant', content: 'All clear, thanks!' }],
@@ -395,15 +450,19 @@ describe('ClarifyCard', () => {
395
450
  })
396
451
  await vi.advanceTimersByTimeAsync(0)
397
452
 
398
- await vi.waitFor(() => {
399
- expect(onFinalize).toHaveBeenCalledOnce()
400
- })
453
+ expect(shadow.root.querySelector('.mtb-clarify-ai')?.textContent).toBe('All clear, thanks!')
454
+ expect(onFinalize).not.toHaveBeenCalled()
455
+
456
+ const sendFeedback = shadow.root.querySelector<HTMLButtonElement>('.mtb-clarify-send-feedback')!
457
+ expect(sendFeedback).toBeTruthy()
458
+ sendFeedback.click()
459
+ expect(onFinalize).toHaveBeenCalledOnce()
401
460
 
402
461
  card.destroy()
403
462
  shadow.destroy()
404
463
  })
405
464
 
406
- it('auto-completes when polling returns done=true', async () => {
465
+ it('waits for confirmation when polling returns done=true', async () => {
407
466
  const getClarification = vi.fn().mockResolvedValueOnce({
408
467
  status: 'complete',
409
468
  messages: [{ role: 'assistant', content: 'Done' }],
@@ -422,15 +481,17 @@ describe('ClarifyCard', () => {
422
481
  })
423
482
  await vi.advanceTimersByTimeAsync(0)
424
483
 
425
- await vi.waitFor(() => {
426
- expect(onFinalize).toHaveBeenCalledOnce()
427
- })
484
+ const sendFeedback = shadow.root.querySelector<HTMLButtonElement>('.mtb-clarify-send-feedback')!
485
+ expect(sendFeedback).toBeTruthy()
486
+ expect(onFinalize).not.toHaveBeenCalled()
487
+ sendFeedback.click()
488
+ expect(onFinalize).toHaveBeenCalledOnce()
428
489
 
429
490
  card.destroy()
430
491
  shadow.destroy()
431
492
  })
432
493
 
433
- it('auto-finalizes on startClarification error', async () => {
494
+ it('waits for confirmation on startClarification error', async () => {
434
495
  const startClarification = vi.fn().mockRejectedValue(new Error('Network error'))
435
496
 
436
497
  const { shadow, card, onFinalize } = setupCard({ startClarification })
@@ -439,9 +500,11 @@ describe('ClarifyCard', () => {
439
500
  })
440
501
  await vi.advanceTimersByTimeAsync(0)
441
502
 
442
- await vi.waitFor(() => {
443
- expect(onFinalize).toHaveBeenCalledOnce()
444
- })
503
+ const sendFeedback = shadow.root.querySelector<HTMLButtonElement>('.mtb-clarify-send-feedback')!
504
+ expect(sendFeedback).toBeTruthy()
505
+ expect(onFinalize).not.toHaveBeenCalled()
506
+ sendFeedback.click()
507
+ expect(onFinalize).toHaveBeenCalledOnce()
445
508
 
446
509
  card.destroy()
447
510
  shadow.destroy()
@@ -588,7 +651,7 @@ describe('ClarifyCard', () => {
588
651
  shadow.destroy()
589
652
  })
590
653
 
591
- it('completes via streaming done and stops without polling', async () => {
654
+ it('waits for confirmation after streaming completes without polling', async () => {
592
655
  const streamClarification = vi.fn().mockResolvedValue({
593
656
  messages: [{ role: 'assistant', content: 'All clear, thanks!' }],
594
657
  done: true,
@@ -603,15 +666,17 @@ describe('ClarifyCard', () => {
603
666
 
604
667
  await vi.advanceTimersByTimeAsync(2000)
605
668
  expect(getClarification).not.toHaveBeenCalled()
606
- await vi.waitFor(() => {
607
- expect(onFinalize).toHaveBeenCalledOnce()
608
- })
669
+ const sendFeedback = shadow.root.querySelector<HTMLButtonElement>('.mtb-clarify-send-feedback')!
670
+ expect(sendFeedback).toBeTruthy()
671
+ expect(onFinalize).not.toHaveBeenCalled()
672
+ sendFeedback.click()
673
+ expect(onFinalize).toHaveBeenCalledOnce()
609
674
 
610
675
  card.destroy()
611
676
  shadow.destroy()
612
677
  })
613
678
 
614
- it('auto-finalizes when polling exceeds the timeout with no reply', async () => {
679
+ it('waits for confirmation when polling exceeds the timeout with no reply', async () => {
615
680
  const getClarification = vi.fn().mockResolvedValue({
616
681
  status: 'pending',
617
682
  messages: [],
@@ -624,11 +689,13 @@ describe('ClarifyCard', () => {
624
689
  })
625
690
  await vi.advanceTimersByTimeAsync(0)
626
691
 
627
- // Poll past the 45s deadline; the card should give up and auto-finalize.
692
+ // Poll past the 45s deadline; the card should give up and let the reporter confirm.
628
693
  await vi.advanceTimersByTimeAsync(48000)
629
- await vi.waitFor(() => {
630
- expect(onFinalize).toHaveBeenCalledOnce()
631
- })
694
+ const sendFeedback = shadow.root.querySelector<HTMLButtonElement>('.mtb-clarify-send-feedback')!
695
+ expect(sendFeedback).toBeTruthy()
696
+ expect(onFinalize).not.toHaveBeenCalled()
697
+ sendFeedback.click()
698
+ expect(onFinalize).toHaveBeenCalledOnce()
632
699
 
633
700
  card.destroy()
634
701
  shadow.destroy()
@@ -15,6 +15,8 @@ interface ClarifyCardOptions {
15
15
  apiClient: ApiClient
16
16
  messages: I18nMessages
17
17
  onFinalize: () => Promise<void> | void
18
+ element?: HTMLDivElement
19
+ position?: 'left' | 'right'
18
20
  x?: number
19
21
  y?: number
20
22
  preloadedResult?: ClarifyStreamResult
@@ -22,7 +24,7 @@ interface ClarifyCardOptions {
22
24
  }
23
25
 
24
26
  const CARD_WIDTH = 346
25
- const CARD_HEIGHT = 320
27
+ const CARD_HEIGHT = 270
26
28
 
27
29
  export class ClarifyCard {
28
30
  private el: HTMLDivElement
@@ -55,10 +57,14 @@ export class ClarifyCard {
55
57
  this.preloadedResult = opts.preloadedResult
56
58
  this.pendingClarification = opts.pendingClarification
57
59
 
58
- this.el = shadow.el<HTMLDivElement>('div', 'mtb-clarify')
60
+ const existingElement = opts.element
61
+ this.el = existingElement ?? shadow.el<HTMLDivElement>('div', 'mtb-clarify')
62
+ this.el.className = existingElement ? 'mtb-clarify mtb-clarify-continuation' : 'mtb-clarify'
59
63
  this.el.innerHTML = this.buildHTML(opts.messages)
60
- shadow.append(this.el)
61
- this.positionCard(opts.x, opts.y)
64
+ if (!existingElement) {
65
+ shadow.append(this.el)
66
+ this.positionCard(opts.x, opts.y, opts.position ?? 'right')
67
+ }
62
68
 
63
69
  this.messagesEl = this.el.querySelector('.mtb-clarify-messages')!
64
70
  this.inputEl = this.el.querySelector('.mtb-clarify-input')!
@@ -70,15 +76,19 @@ export class ClarifyCard {
70
76
 
71
77
  // Anchors the card near the annotation point, clamped to the viewport so it
72
78
  // never overflows a screen edge (mirrors CommentPopup.positionPopup).
73
- private positionCard(x?: number, y?: number): void {
74
- const cardW = CARD_WIDTH
75
- const cardH = this.el.offsetHeight || CARD_HEIGHT
79
+ private positionCard(x: number | undefined, y: number | undefined, tabPosition: 'left' | 'right'): void {
76
80
  const vw = window.innerWidth
77
81
  const vh = window.innerHeight
78
82
  const margin = 12
83
+ const tabWidth = 32
84
+ const cardW = Math.min(CARD_WIDTH, vw - 2 * margin - tabWidth)
85
+ const cardH = this.el.offsetHeight || CARD_HEIGHT
86
+ const minLeft = margin + (tabPosition === 'left' ? tabWidth : 0)
87
+ const maxRight = vw - margin - (tabPosition === 'right' ? tabWidth : 0)
79
88
 
80
89
  if (x === undefined || y === undefined) {
81
- this.el.style.left = `${Math.max(margin, (vw - cardW) / 2)}px`
90
+ const centeredLeft = Math.max(minLeft, (vw - cardW) / 2)
91
+ this.el.style.left = `${Math.min(centeredLeft, maxRight - cardW)}px`
82
92
  this.el.style.top = `${Math.max(margin, (vh - cardH) / 2)}px`
83
93
  this.el.style.maxHeight = `${vh - 2 * margin}px`
84
94
  return
@@ -86,8 +96,9 @@ export class ClarifyCard {
86
96
 
87
97
  let left = x + 12
88
98
  let top = y + 12
89
- if (left + cardW > vw - margin) left = x - cardW - 12
90
- if (left < margin) left = margin
99
+ if (left + cardW > maxRight) left = x - cardW - 12
100
+ if (left + cardW > maxRight) left = maxRight - cardW
101
+ if (left < minLeft) left = minLeft
91
102
  if (top + cardH > vh - margin) top = vh - cardH - margin
92
103
  if (top < margin) top = margin
93
104
 
@@ -100,7 +111,7 @@ export class ClarifyCard {
100
111
  return `
101
112
  <div class="mtb-clarify-header">
102
113
  <span class="mtb-clarify-icon">
103
- <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round">
114
+ <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round">
104
115
  <path d="M12 3l1.6 5.4L19 10l-5.4 1.6L12 17l-1.6-5.4L5 10l5.4-1.6L12 3z"/>
105
116
  </svg>
106
117
  </span>
@@ -109,18 +120,18 @@ export class ClarifyCard {
109
120
  <div class="mtb-clarify-subtitle">${escapeHtml(m.clarify.subtitle)}</div>
110
121
  </div>
111
122
  <button class="mtb-clarify-close" type="button" title="${escapeHtml(m.clarify.skip)}" aria-label="${escapeHtml(m.clarify.skip)}">
112
- <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
123
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
113
124
  <path d="M18 6L6 18M6 6l12 12"/>
114
125
  </svg>
115
126
  </button>
116
127
  </div>
117
128
  <div class="mtb-clarify-messages"></div>
118
129
  <div class="mtb-clarify-footer">
119
- <textarea class="mtb-clarify-input" rows="2" placeholder="${escapeHtml(m.clarify.placeholder)}"></textarea>
130
+ <textarea class="mtb-clarify-input" rows="1" placeholder="${escapeHtml(m.clarify.placeholder)}"></textarea>
120
131
  <div class="mtb-clarify-actions">
121
132
  <button class="mtb-clarify-skip" type="button">${escapeHtml(m.clarify.skip)}</button>
122
133
  <button class="mtb-clarify-send" type="button" disabled>
123
- <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
134
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
124
135
  <line x1="22" y1="2" x2="11" y2="13"/>
125
136
  <polygon points="22 2 15 22 11 13 2 9 22 2"/>
126
137
  </svg>
@@ -331,13 +342,23 @@ export class ClarifyCard {
331
342
  this.done = true
332
343
  this.stopPolling()
333
344
  this.removeThinking()
334
- this.disableConversationInput()
335
- void this.finalize()
345
+ this.showFinalizeButton()
336
346
  }
337
347
 
338
- private disableConversationInput(): void {
339
- this.inputEl.disabled = true
340
- this.sendBtn.disabled = true
348
+ private showFinalizeButton(): void {
349
+ const footer = this.el.querySelector('.mtb-clarify-footer')!
350
+ footer.innerHTML = `
351
+ <button class="mtb-clarify-send-feedback" type="button">
352
+ <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
353
+ <line x1="22" y1="2" x2="11" y2="13"/>
354
+ <polygon points="22 2 15 22 11 13 2 9 22 2"/>
355
+ </svg>
356
+ <span>${escapeHtml(this.i18n.clarify.send_feedback)}</span>
357
+ </button>
358
+ `
359
+ footer.querySelector('.mtb-clarify-send-feedback')!.addEventListener('click', () => {
360
+ if (!this.destroyed) void this.finalize()
361
+ })
341
362
  }
342
363
 
343
364
  private async finalize(): Promise<void> {
@@ -406,4 +427,3 @@ export class ClarifyCard {
406
427
  this.el.remove()
407
428
  }
408
429
  }
409
-
@@ -127,4 +127,42 @@ describe('CommentPopup', () => {
127
127
  popup.destroy()
128
128
  shadow.destroy()
129
129
  })
130
+
131
+ it('leaves room for the right-side feedback tab', () => {
132
+ const shadow = new ShadowContainer()
133
+ const popup = new CommentPopup(shadow, {
134
+ targetName: 'Export PDF',
135
+ x: window.innerWidth,
136
+ y: 120,
137
+ messages: getMessages('en'),
138
+ onSubmit: vi.fn(),
139
+ onClose: vi.fn(),
140
+ position: 'right',
141
+ })
142
+ const element = shadow.root.querySelector<HTMLElement>('.mtb-popup')!
143
+
144
+ expect(Number.parseFloat(element.style.left) + 320).toBeLessThanOrEqual(window.innerWidth - 44)
145
+
146
+ popup.destroy()
147
+ shadow.destroy()
148
+ })
149
+
150
+ it('leaves room for the left-side feedback tab', () => {
151
+ const shadow = new ShadowContainer()
152
+ const popup = new CommentPopup(shadow, {
153
+ targetName: 'Export PDF',
154
+ x: 0,
155
+ y: 120,
156
+ messages: getMessages('en'),
157
+ onSubmit: vi.fn(),
158
+ onClose: vi.fn(),
159
+ position: 'left',
160
+ })
161
+ const element = shadow.root.querySelector<HTMLElement>('.mtb-popup')!
162
+
163
+ expect(Number.parseFloat(element.style.left)).toBeGreaterThanOrEqual(44)
164
+
165
+ popup.destroy()
166
+ shadow.destroy()
167
+ })
130
168
  })
@@ -12,6 +12,7 @@ interface PopupOptions {
12
12
  onClose: () => void
13
13
  onMyFeedback?: () => void
14
14
  messages: I18nMessages
15
+ position?: 'left' | 'right'
15
16
  }
16
17
 
17
18
  export class CommentPopup {
@@ -38,7 +39,7 @@ export class CommentPopup {
38
39
  this.textarea = this.el.querySelector('.mtb-textarea')!
39
40
  this.submitBtn = this.el.querySelector('.mtb-submit-btn')!
40
41
 
41
- this.positionPopup(opts.x, opts.y, opts.targetRect)
42
+ this.positionPopup(opts.x, opts.y, opts.targetRect, opts.position ?? 'right')
42
43
  this.bindEvents(opts.messages)
43
44
  if (opts.onMyFeedback) {
44
45
  this.el.querySelector('.mtb-my-feedback')!.addEventListener('click', opts.onMyFeedback)
@@ -91,13 +92,16 @@ export class CommentPopup {
91
92
 
92
93
 
93
94
 
94
- private positionPopup(x: number, y: number, targetRect?: TargetRect): void {
95
- const popupW = 320
96
- const popupH = this.el.offsetHeight || 260
95
+ private positionPopup(x: number, y: number, targetRect: TargetRect | undefined, tabPosition: 'left' | 'right'): void {
97
96
  const vw = window.innerWidth
98
97
  const vh = window.innerHeight
99
98
  const margin = 12
100
99
  const gap = 8
100
+ const tabWidth = 32
101
+ const popupW = Math.min(320, vw - 2 * margin - tabWidth)
102
+ const popupH = this.el.offsetHeight || 260
103
+ const minLeft = margin + (tabPosition === 'left' ? tabWidth : 0)
104
+ const maxRight = vw - margin - (tabPosition === 'right' ? tabWidth : 0)
101
105
 
102
106
  let left: number
103
107
  let top: number
@@ -117,10 +121,10 @@ export class CommentPopup {
117
121
  top = y + 12
118
122
  }
119
123
 
120
- if (left + popupW > vw - margin) {
121
- left = vw - popupW - margin
124
+ if (left + popupW > maxRight) {
125
+ left = maxRight - popupW
122
126
  }
123
- if (left < margin) left = margin
127
+ if (left < minLeft) left = minLeft
124
128
  if (top < margin) top = margin
125
129
 
126
130
  this.el.style.left = `${left}px`
@@ -188,6 +192,10 @@ export class CommentPopup {
188
192
  this.errorEl.hidden = false
189
193
  }
190
194
 
195
+ releaseElement(): HTMLDivElement {
196
+ return this.el
197
+ }
198
+
191
199
  destroy(): void {
192
200
  this.el.remove()
193
201
  }
@@ -199,4 +207,3 @@ function formatDuration(seconds: number): string {
199
207
  const ss = String(total % 60).padStart(2, '0')
200
208
  return `${mm}:${ss}`
201
209
  }
202
-