hanbiro-react16-sdk 1.0.27 → 1.0.29

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 (69) hide show
  1. package/README.md +58 -5
  2. package/dist/components/ChatAIDraft/ChatInput.js +3 -1
  3. package/dist/components/ChatAIDraft/ChatList/LoadingDots.js +4 -3
  4. package/dist/components/ChatAIDraft/ChatList/MessageItem.js +7 -5
  5. package/dist/components/ChatAIDraft/CreatePanel/EmptyState.js +15 -15
  6. package/dist/components/ChatAIDraft/CreatePanel/index.js +3 -3
  7. package/dist/components/ChatAIDraft/ReplyPanel/BaseModal.d.ts +15 -0
  8. package/dist/components/ChatAIDraft/ReplyPanel/BaseModal.js +101 -0
  9. package/dist/components/ChatAIDraft/ReplyPanel/ContextPreviewModal.d.ts +13 -0
  10. package/dist/components/ChatAIDraft/ReplyPanel/ContextPreviewModal.js +65 -0
  11. package/dist/components/ChatAIDraft/ReplyPanel/EmptyState.d.ts +1 -8
  12. package/dist/components/ChatAIDraft/ReplyPanel/EmptyState.js +11 -227
  13. package/dist/components/ChatAIDraft/ReplyPanel/Header/SelectedChip.d.ts +10 -0
  14. package/dist/components/ChatAIDraft/ReplyPanel/Header/SelectedChip.js +79 -0
  15. package/dist/components/ChatAIDraft/ReplyPanel/Header/SourceCard.d.ts +8 -0
  16. package/dist/components/ChatAIDraft/ReplyPanel/Header/SourceCard.js +52 -0
  17. package/dist/components/ChatAIDraft/ReplyPanel/Header/index.d.ts +12 -0
  18. package/dist/components/ChatAIDraft/ReplyPanel/Header/index.js +139 -0
  19. package/dist/components/ChatAIDraft/ReplyPanel/MailListSelect.d.ts +1 -0
  20. package/dist/components/ChatAIDraft/ReplyPanel/MailListSelect.js +71 -155
  21. package/dist/components/ChatAIDraft/ReplyPanel/index.d.ts +5 -1
  22. package/dist/components/ChatAIDraft/ReplyPanel/index.js +42 -201
  23. package/dist/components/ChatAIDraft/SettingPopper/index.js +8 -6
  24. package/dist/components/ChatAIDraft/constants.d.ts +2 -2
  25. package/dist/components/ChatAIDraft/constants.js +16 -14
  26. package/dist/components/ChatAIDraft/index.d.ts +1 -0
  27. package/dist/components/ChatAIDraft/index.js +7 -1
  28. package/dist/components/Pagination/index.d.ts +20 -0
  29. package/dist/components/Pagination/index.js +133 -0
  30. package/dist/components/SummaryAIEmails/FilterTabs.d.ts +8 -0
  31. package/dist/components/SummaryAIEmails/FilterTabs.js +59 -0
  32. package/dist/components/SummaryAIEmails/LanguagePopover.d.ts +24 -0
  33. package/dist/components/SummaryAIEmails/LanguagePopover.js +110 -0
  34. package/dist/components/SummaryAIEmails/SummaryItem.d.ts +7 -0
  35. package/dist/components/SummaryAIEmails/SummaryItem.js +76 -0
  36. package/dist/components/SummaryAIEmails/TargetInfoBar.d.ts +9 -0
  37. package/dist/components/SummaryAIEmails/TargetInfoBar.js +81 -0
  38. package/dist/components/SummaryAIEmails/index.d.ts +35 -0
  39. package/dist/components/SummaryAIEmails/index.js +222 -0
  40. package/dist/components/SummaryAIEmails/types.d.ts +16 -0
  41. package/dist/components/SummaryAIEmails/utils.d.ts +12 -0
  42. package/dist/components/SummaryAIEmails/utils.js +47 -0
  43. package/dist/components/index.d.ts +2 -4
  44. package/dist/hanbiro-react16-sdk.style.css +7 -2
  45. package/dist/hanbiro-react16-sdk.umd.js +2169 -1033
  46. package/dist/index.js +13 -14
  47. package/dist/lang/en.d.ts +3 -0
  48. package/dist/lang/en.js +66 -0
  49. package/dist/lang/index.d.ts +4 -0
  50. package/dist/lang/index.js +18 -0
  51. package/dist/lang/keyLang.d.ts +62 -0
  52. package/dist/lang/keyLang.js +66 -0
  53. package/dist/lang/ko.d.ts +3 -0
  54. package/dist/lang/ko.js +66 -0
  55. package/dist/lang/vi.d.ts +3 -0
  56. package/dist/lang/vi.js +66 -0
  57. package/dist/node_modules/react-feather/dist/icons/arrow-down.js +73 -0
  58. package/dist/node_modules/react-feather/dist/icons/chevron-left.js +68 -0
  59. package/dist/node_modules/react-feather/dist/icons/chevron-right.js +68 -0
  60. package/dist/node_modules/react-feather/dist/icons/globe.js +77 -0
  61. package/dist/node_modules/react-feather/dist/icons/x.js +76 -0
  62. package/dist/utils/index.d.ts +1 -1
  63. package/dist/utils/lang.d.ts +1 -0
  64. package/dist/utils/lang.js +30 -0
  65. package/dist/utils/storage.d.ts +8 -0
  66. package/dist/utils/storage.js +19 -0
  67. package/dist/utils/url.d.ts +2 -0
  68. package/dist/utils/url.js +8 -15
  69. package/package.json +1 -1
@@ -22,8 +22,13 @@ var __async = (__this, __arguments, generator) => {
22
22
  });
23
23
  };
24
24
  import * as React from "react";
25
+ import LoadingContainer from "../../LoadingContainer/index.js";
26
+ import LoadingCircular from "../../LoadingCircular/index.js";
27
+ import Pagination from "../../Pagination/index.js";
25
28
  import { fetchMailList } from "./helper.js";
29
+ import { t } from "../../../lang/index.js";
26
30
  import ArrowLeft from "../../../node_modules/react-feather/dist/icons/arrow-left.js";
31
+ import { LangKey } from "../../../lang/keyLang.js";
27
32
  import Paperclip from "../../../node_modules/react-feather/dist/icons/paperclip.js";
28
33
  const PAGE_SIZE = 6;
29
34
  const MAX_SELECTED = 5;
@@ -53,19 +58,16 @@ class MailListSelect extends React.Component {
53
58
  });
54
59
  __publicField(this, "toggleAll", () => {
55
60
  const { items, selectedMids } = this.state;
56
- const pageMids = items.map((it) => it.mid);
57
- const allSelected = pageMids.every((m) => selectedMids.includes(m));
58
- if (allSelected) {
59
- this.setState({
60
- selectedMids: selectedMids.filter((m) => !pageMids.includes(m))
61
- });
62
- } else {
63
- const merged = Array.from(/* @__PURE__ */ new Set([...selectedMids, ...pageMids])).slice(
64
- 0,
65
- MAX_SELECTED
66
- );
67
- this.setState({ selectedMids: merged });
61
+ if (selectedMids.length >= MAX_SELECTED) {
62
+ this.setState({ selectedMids: [] });
63
+ return;
68
64
  }
65
+ const pageMids = items.map((it) => it.mid);
66
+ const merged = Array.from(/* @__PURE__ */ new Set([...selectedMids, ...pageMids])).slice(
67
+ 0,
68
+ MAX_SELECTED
69
+ );
70
+ this.setState({ selectedMids: merged });
69
71
  });
70
72
  __publicField(this, "clearAll", () => {
71
73
  this.setState({ selectedMids: [] });
@@ -84,67 +86,20 @@ class MailListSelect extends React.Component {
84
86
  renderPagination() {
85
87
  const { page, total } = this.state;
86
88
  const totalPages = Math.max(1, Math.ceil(total / PAGE_SIZE));
87
- const pages = [];
88
- for (let i = 1; i <= totalPages; i++) pages.push(i);
89
89
  return /* @__PURE__ */ React.createElement(
90
- "div",
90
+ Pagination,
91
91
  {
92
- style: {
93
- display: "flex",
94
- alignItems: "center",
95
- justifyContent: "center",
96
- gap: 4,
97
- padding: "12px 0"
98
- }
99
- },
100
- /* @__PURE__ */ React.createElement(
101
- "button",
102
- {
103
- type: "button",
104
- onClick: () => page > 1 && this.loadPage(page - 1),
105
- disabled: page <= 1,
106
- className: "icon-button small"
107
- },
108
- "‹"
109
- ),
110
- pages.map((p) => /* @__PURE__ */ React.createElement(
111
- "button",
112
- {
113
- key: p,
114
- type: "button",
115
- onClick: () => p !== page && this.loadPage(p),
116
- style: {
117
- minWidth: 28,
118
- height: 28,
119
- borderRadius: 4,
120
- border: "none",
121
- background: p === page ? "var(--primary-main)" : "transparent",
122
- color: p === page ? "var(--primary-contrasttext)" : "var(--text-primary)",
123
- cursor: "pointer",
124
- fontSize: 12,
125
- fontFamily: "inherit",
126
- fontWeight: p === page ? 600 : 400
127
- }
128
- },
129
- p
130
- )),
131
- /* @__PURE__ */ React.createElement(
132
- "button",
133
- {
134
- type: "button",
135
- onClick: () => page < totalPages && this.loadPage(page + 1),
136
- disabled: page >= totalPages,
137
- className: "icon-button small"
138
- },
139
- "›"
140
- )
92
+ total,
93
+ page,
94
+ totalPages,
95
+ onChangePage: this.loadPage
96
+ }
141
97
  );
142
98
  }
143
99
  render() {
144
- const { onCancel, onConfirm } = this.props;
100
+ const { onCancel, onConfirm, isConfirming } = this.props;
145
101
  const { items, total, selectedMids, isLoading } = this.state;
146
- const pageMids = items.map((it) => it.mid);
147
- const allOnPageSelected = pageMids.length > 0 && pageMids.every((m) => selectedMids.includes(m));
102
+ const isFull = selectedMids.length >= MAX_SELECTED;
148
103
  return /* @__PURE__ */ React.createElement(
149
104
  "div",
150
105
  {
@@ -167,7 +122,8 @@ class MailListSelect extends React.Component {
167
122
  style: { alignSelf: "flex-start" }
168
123
  },
169
124
  /* @__PURE__ */ React.createElement(ArrowLeft, { size: 14 }),
170
- " Back"
125
+ " ",
126
+ t(LangKey.BACK)
171
127
  ),
172
128
  /* @__PURE__ */ React.createElement("div", { style: { marginTop: 8 } }, /* @__PURE__ */ React.createElement(
173
129
  "div",
@@ -178,7 +134,7 @@ class MailListSelect extends React.Component {
178
134
  color: "var(--text-primary)"
179
135
  }
180
136
  },
181
- "Add context from receive history"
137
+ t(LangKey.ADD_CONTEXT_TITLE)
182
138
  ), /* @__PURE__ */ React.createElement(
183
139
  "div",
184
140
  {
@@ -188,7 +144,7 @@ class MailListSelect extends React.Component {
188
144
  marginTop: 2
189
145
  }
190
146
  },
191
- "Select related emails to provide AI context."
147
+ t(LangKey.ADD_CONTEXT_DESC)
192
148
  )),
193
149
  /* @__PURE__ */ React.createElement(
194
150
  "div",
@@ -208,9 +164,9 @@ class MailListSelect extends React.Component {
208
164
  style: {
209
165
  display: "inline-flex",
210
166
  alignItems: "center",
211
- gap: 6,
167
+ gap: 8,
212
168
  fontSize: 12,
213
- color: "var(--text-primary)",
169
+ color: "var(--text-secondary)",
214
170
  cursor: "pointer"
215
171
  }
216
172
  },
@@ -218,13 +174,40 @@ class MailListSelect extends React.Component {
218
174
  "input",
219
175
  {
220
176
  type: "checkbox",
221
- checked: allOnPageSelected,
177
+ checked: isFull,
222
178
  onChange: this.toggleAll
223
179
  }
224
180
  ),
225
- /* @__PURE__ */ React.createElement("span", null, "Select all · ", total, " total")
181
+ /* @__PURE__ */ React.createElement(
182
+ "span",
183
+ {
184
+ style: {
185
+ background: "var(--primary-main)",
186
+ color: "var(--primary-contrasttext)",
187
+ padding: "2px 8px",
188
+ borderRadius: 999,
189
+ fontWeight: 600
190
+ }
191
+ },
192
+ selectedMids.length,
193
+ "/",
194
+ MAX_SELECTED
195
+ ),
196
+ /* @__PURE__ */ React.createElement("span", null, t(LangKey.SELECTED_UP_TO), " ", MAX_SELECTED),
197
+ selectedMids.length > 0 && /* @__PURE__ */ React.createElement(
198
+ "button",
199
+ {
200
+ type: "button",
201
+ onClick: (e) => {
202
+ e.preventDefault();
203
+ this.clearAll();
204
+ },
205
+ className: "text-button primary"
206
+ },
207
+ t(LangKey.CLEAR_ALL)
208
+ )
226
209
  ),
227
- /* @__PURE__ */ React.createElement("span", { style: { fontSize: 11, color: "var(--text-secondary)" } }, "Sort: latest")
210
+ /* @__PURE__ */ React.createElement("span", { style: { fontSize: 11, color: "var(--text-secondary)" } }, t(LangKey.SORT_LATEST))
228
211
  ),
229
212
  /* @__PURE__ */ React.createElement(
230
213
  "div",
@@ -237,7 +220,7 @@ class MailListSelect extends React.Component {
237
220
  marginRight: -8
238
221
  }
239
222
  },
240
- isLoading ? /* @__PURE__ */ React.createElement(
223
+ isLoading ? /* @__PURE__ */ React.createElement(LoadingContainer, { fullHeight: true, size: "small" }) : items.length === 0 ? /* @__PURE__ */ React.createElement(
241
224
  "div",
242
225
  {
243
226
  style: {
@@ -247,18 +230,7 @@ class MailListSelect extends React.Component {
247
230
  fontSize: 12
248
231
  }
249
232
  },
250
- "Loading..."
251
- ) : items.length === 0 ? /* @__PURE__ */ React.createElement(
252
- "div",
253
- {
254
- style: {
255
- padding: 24,
256
- textAlign: "center",
257
- color: "var(--text-secondary)",
258
- fontSize: 12
259
- }
260
- },
261
- "No emails found."
233
+ t(LangKey.NO_EMAILS_FOUND)
262
234
  ) : items.map((it) => {
263
235
  const isChecked = selectedMids.includes(it.mid);
264
236
  const disabled = !isChecked && selectedMids.length >= MAX_SELECTED;
@@ -361,65 +333,6 @@ class MailListSelect extends React.Component {
361
333
  }),
362
334
  !isLoading && items.length > 0 && this.renderPagination()
363
335
  ),
364
- /* @__PURE__ */ React.createElement(
365
- "div",
366
- {
367
- style: {
368
- display: "flex",
369
- alignItems: "center",
370
- justifyContent: "space-between",
371
- paddingTop: 12,
372
- borderTop: "1px solid var(--border-light)",
373
- marginTop: 8,
374
- gap: 8
375
- }
376
- },
377
- /* @__PURE__ */ React.createElement(
378
- "div",
379
- {
380
- style: {
381
- fontSize: 12,
382
- color: "var(--text-secondary)",
383
- display: "inline-flex",
384
- alignItems: "center",
385
- gap: 8
386
- }
387
- },
388
- /* @__PURE__ */ React.createElement(
389
- "span",
390
- {
391
- style: {
392
- background: "var(--primary-main)",
393
- color: "var(--primary-contrasttext)",
394
- padding: "2px 8px",
395
- borderRadius: 999,
396
- fontWeight: 600
397
- }
398
- },
399
- selectedMids.length,
400
- "/",
401
- MAX_SELECTED
402
- ),
403
- /* @__PURE__ */ React.createElement("span", null, "selected · up to ", MAX_SELECTED),
404
- selectedMids.length > 0 && /* @__PURE__ */ React.createElement(
405
- "button",
406
- {
407
- type: "button",
408
- onClick: this.clearAll,
409
- style: {
410
- border: "none",
411
- background: "transparent",
412
- color: "var(--primary-main)",
413
- cursor: "pointer",
414
- fontSize: 12,
415
- padding: 0,
416
- fontFamily: "inherit"
417
- }
418
- },
419
- "Clear all"
420
- )
421
- )
422
- ),
423
336
  /* @__PURE__ */ React.createElement(
424
337
  "div",
425
338
  {
@@ -446,30 +359,33 @@ class MailListSelect extends React.Component {
446
359
  fontFamily: "inherit"
447
360
  }
448
361
  },
449
- "Cancel"
362
+ t(LangKey.CANCEL)
450
363
  ),
451
364
  /* @__PURE__ */ React.createElement(
452
365
  "button",
453
366
  {
454
367
  type: "button",
455
- disabled: selectedMids.length === 0,
368
+ disabled: selectedMids.length === 0 || isConfirming,
456
369
  onClick: () => onConfirm(selectedMids),
457
370
  style: {
458
371
  flex: 2,
459
372
  padding: "10px 12px",
460
373
  borderRadius: 8,
461
374
  border: "none",
462
- background: selectedMids.length === 0 ? "var(--primary-lighter)" : "var(--primary-main)",
375
+ background: selectedMids.length === 0 || isConfirming ? "var(--primary-lighter)" : "var(--primary-main)",
463
376
  color: "var(--primary-contrasttext)",
464
- cursor: selectedMids.length === 0 ? "not-allowed" : "pointer",
377
+ cursor: selectedMids.length === 0 || isConfirming ? "not-allowed" : "pointer",
465
378
  fontSize: 13,
466
379
  fontWeight: 600,
467
- fontFamily: "inherit"
380
+ fontFamily: "inherit",
381
+ display: "inline-flex",
382
+ alignItems: "center",
383
+ justifyContent: "center",
384
+ gap: 8
468
385
  }
469
386
  },
470
- "Add ",
471
- selectedMids.length > 0 ? `${selectedMids.length} ` : "",
472
- "as context →"
387
+ isConfirming && /* @__PURE__ */ React.createElement(LoadingCircular, { size: 16, color: "var(--primary-contrasttext)" }),
388
+ /* @__PURE__ */ React.createElement("span", null, t(LangKey.ADD), " ", selectedMids.length > 0 ? `${selectedMids.length} ` : "", t(LangKey.ADD_AS_CONTEXT))
473
389
  )
474
390
  )
475
391
  );
@@ -1,3 +1,4 @@
1
+ import { PreviewState } from './ContextPreviewModal';
1
2
  import { LabelValue } from '../../../types';
2
3
  import { AIMessage, ChatType, ContextMail } from '../types';
3
4
  import * as React from "react";
@@ -18,6 +19,7 @@ interface ReplyPanelState {
18
19
  selectedMails: ContextMail[];
19
20
  isLoadingSource: boolean;
20
21
  isLoadingSelected: boolean;
22
+ preview: PreviewState | null;
21
23
  message: string;
22
24
  messages: AIMessage[];
23
25
  isSending: boolean;
@@ -35,12 +37,14 @@ declare class ReplyPanel extends React.Component<ReplyPanelProps, ReplyPanelStat
35
37
  handleListCancel: () => void;
36
38
  handleListConfirm: (mids: string[]) => Promise<void>;
37
39
  handleRemoveSelected: (mid: string) => void;
40
+ handlePreviewSelected: (mail: ContextMail) => void;
41
+ handlePreviewSource: (mail: ContextMail) => void;
42
+ handlePreviewClose: () => void;
38
43
  handleMessageChange: (value: string) => void;
39
44
  handleSubmit: () => Promise<void>;
40
45
  setLang: (lang: LabelValue | null) => void;
41
46
  setTone: (tone: LabelValue | null) => void;
42
47
  setLength: (length: LabelValue | null) => void;
43
- renderContextHeader(): React.JSX.Element;
44
48
  render(): React.JSX.Element;
45
49
  }
46
50
  export default ReplyPanel;
@@ -43,13 +43,15 @@ import { callAI } from "../helper.js";
43
43
  import ChatList from "../ChatList/index.js";
44
44
  import ChatInput from "../ChatInput.js";
45
45
  import EmptyState from "./EmptyState.js";
46
+ import ContextHeader from "./Header/index.js";
46
47
  import MailListSelect from "./MailListSelect.js";
48
+ import ContextPreviewModal from "./ContextPreviewModal.js";
47
49
  import { fetchMailView, fetchMailAiContext } from "./helper.js";
48
- import { LENGTH_OPTIONS, TONE_OPTIONS } from "../constants.js";
50
+ import { getLengthOptions, getToneOptions } from "../constants.js";
49
51
  import { AI_LANG_FLAGS } from "../../../constants/index.js";
52
+ import { t } from "../../../lang/index.js";
50
53
  import v4 from "../../../node_modules/uuid/dist/esm-browser/v4.js";
51
- import Lock from "../../../node_modules/react-feather/dist/icons/lock.js";
52
- import Plus from "../../../node_modules/react-feather/dist/icons/plus.js";
54
+ import { LangKey } from "../../../lang/keyLang.js";
53
55
  class ReplyPanel extends React.Component {
54
56
  constructor(props) {
55
57
  var _a;
@@ -98,6 +100,15 @@ class ReplyPanel extends React.Component {
98
100
  selectedMails: this.state.selectedMails.filter((m) => m.mid !== mid)
99
101
  });
100
102
  });
103
+ __publicField(this, "handlePreviewSelected", (mail) => {
104
+ this.setState({ preview: { mail, mode: "ai" } });
105
+ });
106
+ __publicField(this, "handlePreviewSource", (mail) => {
107
+ this.setState({ preview: { mail, mode: "html" } });
108
+ });
109
+ __publicField(this, "handlePreviewClose", () => {
110
+ this.setState({ preview: null });
111
+ });
101
112
  __publicField(this, "handleMessageChange", (value) => {
102
113
  this.setState({ message: value });
103
114
  });
@@ -177,201 +188,19 @@ class ReplyPanel extends React.Component {
177
188
  selectedMails: [],
178
189
  isLoadingSource: false,
179
190
  isLoadingSelected: false,
191
+ preview: null,
180
192
  message: "",
181
193
  messages: [],
182
194
  isSending: false,
183
195
  lang,
184
- tone: TONE_OPTIONS[2],
185
- length: LENGTH_OPTIONS[2],
196
+ tone: getToneOptions()[2],
197
+ length: getLengthOptions()[2],
186
198
  conversationId: ""
187
199
  };
188
200
  }
189
201
  componentDidMount() {
190
202
  this.loadSourceMail();
191
203
  }
192
- renderContextHeader() {
193
- const { sourceMail, selectedMails } = this.state;
194
- return /* @__PURE__ */ React.createElement(
195
- "div",
196
- {
197
- style: {
198
- display: "flex",
199
- flexDirection: "column",
200
- gap: 8,
201
- paddingBottom: 12,
202
- borderBottom: "1px solid var(--border-light)",
203
- marginBottom: 12
204
- }
205
- },
206
- sourceMail && /* @__PURE__ */ React.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 4 } }, /* @__PURE__ */ React.createElement(
207
- "div",
208
- {
209
- style: {
210
- display: "flex",
211
- alignItems: "center",
212
- gap: 6,
213
- fontSize: 12,
214
- fontWeight: 600,
215
- color: "var(--text-primary)"
216
- }
217
- },
218
- /* @__PURE__ */ React.createElement("span", null, "Source context"),
219
- /* @__PURE__ */ React.createElement(
220
- "span",
221
- {
222
- style: {
223
- background: "var(--primary-main)",
224
- color: "var(--primary-contrasttext)",
225
- fontSize: 10,
226
- padding: "1px 6px",
227
- borderRadius: 999
228
- }
229
- },
230
- "1"
231
- ),
232
- /* @__PURE__ */ React.createElement(
233
- "span",
234
- {
235
- style: {
236
- display: "inline-flex",
237
- alignItems: "center",
238
- gap: 2,
239
- fontSize: 11,
240
- color: "var(--text-secondary)"
241
- }
242
- },
243
- /* @__PURE__ */ React.createElement(Lock, { size: 11 }),
244
- " Auto"
245
- )
246
- ), /* @__PURE__ */ React.createElement(
247
- "div",
248
- {
249
- style: {
250
- fontSize: 12,
251
- color: "var(--text-secondary)",
252
- whiteSpace: "nowrap",
253
- overflow: "hidden",
254
- textOverflow: "ellipsis"
255
- }
256
- },
257
- sourceMail.subject,
258
- " ·",
259
- " ",
260
- /* @__PURE__ */ React.createElement("span", { style: { color: "var(--text-primary)" } }, sourceMail.from_name)
261
- )),
262
- /* @__PURE__ */ React.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 6 } }, /* @__PURE__ */ React.createElement(
263
- "div",
264
- {
265
- style: {
266
- display: "flex",
267
- alignItems: "center",
268
- justifyContent: "space-between"
269
- }
270
- },
271
- /* @__PURE__ */ React.createElement(
272
- "div",
273
- {
274
- style: {
275
- display: "flex",
276
- alignItems: "center",
277
- gap: 6,
278
- fontSize: 12,
279
- fontWeight: 600,
280
- color: "var(--text-primary)"
281
- }
282
- },
283
- /* @__PURE__ */ React.createElement("span", null, "Selected context"),
284
- /* @__PURE__ */ React.createElement(
285
- "span",
286
- {
287
- style: {
288
- background: "var(--background-softGrey)",
289
- color: "var(--text-primary)",
290
- fontSize: 10,
291
- padding: "1px 6px",
292
- borderRadius: 999
293
- }
294
- },
295
- selectedMails.length
296
- )
297
- ),
298
- /* @__PURE__ */ React.createElement(
299
- "button",
300
- {
301
- type: "button",
302
- onClick: this.handleAddClick,
303
- className: "text-button primary"
304
- },
305
- /* @__PURE__ */ React.createElement(Plus, { size: 12 }),
306
- " Add"
307
- )
308
- ), selectedMails.length > 0 && /* @__PURE__ */ React.createElement("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 } }, selectedMails.map((m, i) => /* @__PURE__ */ React.createElement(
309
- "div",
310
- {
311
- key: m.mid,
312
- style: {
313
- display: "inline-flex",
314
- alignItems: "center",
315
- gap: 6,
316
- padding: "4px 8px",
317
- borderRadius: 8,
318
- border: "1px solid var(--border-light)",
319
- background: "var(--primary-lighter)",
320
- fontSize: 11,
321
- maxWidth: 160
322
- }
323
- },
324
- /* @__PURE__ */ React.createElement(
325
- "span",
326
- {
327
- style: {
328
- width: 14,
329
- height: 14,
330
- borderRadius: "50%",
331
- background: "var(--primary-main)",
332
- color: "var(--primary-contrasttext)",
333
- fontSize: 9,
334
- fontWeight: 700,
335
- display: "inline-flex",
336
- alignItems: "center",
337
- justifyContent: "center",
338
- flexShrink: 0
339
- }
340
- },
341
- i + 1
342
- ),
343
- /* @__PURE__ */ React.createElement(
344
- "span",
345
- {
346
- style: {
347
- whiteSpace: "nowrap",
348
- overflow: "hidden",
349
- textOverflow: "ellipsis"
350
- }
351
- },
352
- m.subject || "(no subject)"
353
- ),
354
- /* @__PURE__ */ React.createElement(
355
- "button",
356
- {
357
- type: "button",
358
- onClick: () => this.handleRemoveSelected(m.mid),
359
- style: {
360
- border: "none",
361
- background: "transparent",
362
- cursor: "pointer",
363
- padding: 0,
364
- color: "var(--text-secondary)",
365
- display: "inline-flex",
366
- alignItems: "center",
367
- flexShrink: 0
368
- }
369
- },
370
- "×"
371
- )
372
- ))))
373
- );
374
- }
375
204
  render() {
376
205
  const { onApply, getEditorContent } = this.props;
377
206
  const {
@@ -385,7 +214,8 @@ class ReplyPanel extends React.Component {
385
214
  lang,
386
215
  tone,
387
216
  length,
388
- isLoadingSelected
217
+ isLoadingSelected,
218
+ preview
389
219
  } = this.state;
390
220
  if (view === "list") {
391
221
  return /* @__PURE__ */ React.createElement(
@@ -393,6 +223,7 @@ class ReplyPanel extends React.Component {
393
223
  {
394
224
  accountEmail,
395
225
  initialSelected: selectedMails.map((m) => m.mid),
226
+ isConfirming: isLoadingSelected,
396
227
  onCancel: this.handleListCancel,
397
228
  onConfirm: this.handleListConfirm
398
229
  }
@@ -412,22 +243,25 @@ class ReplyPanel extends React.Component {
412
243
  boxSizing: "border-box"
413
244
  }
414
245
  },
415
- view === "chat" ? /* @__PURE__ */ React.createElement(React.Fragment, null, this.renderContextHeader(), /* @__PURE__ */ React.createElement(
416
- ChatList,
417
- {
418
- items: messages,
419
- onApply,
420
- getEditorContent
421
- }
422
- )) : /* @__PURE__ */ React.createElement(
423
- EmptyState,
246
+ /* @__PURE__ */ React.createElement(
247
+ ContextHeader,
424
248
  {
425
249
  sourceMail,
426
250
  selectedMails,
427
251
  onAddClick: this.handleAddClick,
428
- onRemoveSelected: this.handleRemoveSelected
252
+ onSourceClick: this.handlePreviewSource,
253
+ onChipClick: this.handlePreviewSelected,
254
+ onRemoveChip: this.handleRemoveSelected
429
255
  }
430
256
  ),
257
+ view === "chat" ? /* @__PURE__ */ React.createElement(
258
+ ChatList,
259
+ {
260
+ items: messages,
261
+ onApply,
262
+ getEditorContent
263
+ }
264
+ ) : /* @__PURE__ */ React.createElement(EmptyState, null),
431
265
  isLoadingSelected && /* @__PURE__ */ React.createElement(
432
266
  "div",
433
267
  {
@@ -438,7 +272,7 @@ class ReplyPanel extends React.Component {
438
272
  textAlign: "center"
439
273
  }
440
274
  },
441
- "Loading context..."
275
+ t(LangKey.REPLY_LOADING_CONTEXT)
442
276
  ),
443
277
  /* @__PURE__ */ React.createElement(
444
278
  ChatInput,
@@ -454,7 +288,14 @@ class ReplyPanel extends React.Component {
454
288
  length,
455
289
  setLength: this.setLength,
456
290
  parentRef: this.rootRef,
457
- placeholder: "Type a message..."
291
+ placeholder: t(LangKey.CHAT_INPUT_PLACEHOLDER_REPLY)
292
+ }
293
+ ),
294
+ /* @__PURE__ */ React.createElement(
295
+ ContextPreviewModal,
296
+ {
297
+ preview,
298
+ onClose: this.handlePreviewClose
458
299
  }
459
300
  )
460
301
  );