@opentiny/fluent-editor 4.0.0-beta.0 → 4.0.0-beta.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 (158) hide show
  1. package/es/config/i18n/en-us.es.js +0 -2
  2. package/es/config/i18n/en-us.es.js.map +1 -1
  3. package/es/config/i18n/zh-cn.es.js +0 -2
  4. package/es/config/i18n/zh-cn.es.js.map +1 -1
  5. package/es/fluent-editor.es.js +0 -6
  6. package/es/fluent-editor.es.js.map +1 -1
  7. package/es/index.es.js +0 -4
  8. package/es/index.es.js.map +1 -1
  9. package/es/modules/index.es.js +0 -4
  10. package/es/modules/index.es.js.map +1 -1
  11. package/es/modules/shortcut-key/index.es.js +0 -16
  12. package/es/modules/shortcut-key/index.es.js.map +1 -1
  13. package/es/ui/icons.config.es.js +0 -4
  14. package/es/ui/icons.config.es.js.map +1 -1
  15. package/es/ui/icons.es.js +2 -4
  16. package/es/ui/icons.es.js.map +1 -1
  17. package/lib/config/i18n/en-us.cjs.js +0 -2
  18. package/lib/config/i18n/en-us.cjs.js.map +1 -1
  19. package/lib/config/i18n/zh-cn.cjs.js +0 -2
  20. package/lib/config/i18n/zh-cn.cjs.js.map +1 -1
  21. package/lib/fluent-editor.cjs.js +2 -8
  22. package/lib/fluent-editor.cjs.js.map +1 -1
  23. package/lib/index.cjs.js +5 -9
  24. package/lib/index.cjs.js.map +1 -1
  25. package/lib/modules/index.cjs.js +5 -9
  26. package/lib/modules/index.cjs.js.map +1 -1
  27. package/lib/modules/shortcut-key/index.cjs.js +0 -16
  28. package/lib/modules/shortcut-key/index.cjs.js.map +1 -1
  29. package/lib/ui/icons.cjs.js +1 -3
  30. package/lib/ui/icons.cjs.js.map +1 -1
  31. package/lib/ui/icons.config.cjs.js +0 -4
  32. package/lib/ui/icons.config.cjs.js.map +1 -1
  33. package/package.json +1 -3
  34. package/types/config/i18n/en-us.d.ts +0 -2
  35. package/types/config/i18n/zh-cn.d.ts +0 -2
  36. package/types/config/types/editor-modules.interface.d.ts +0 -4
  37. package/types/modules/index.d.ts +0 -2
  38. package/types/ui/icons.config.d.ts +0 -2
  39. package/es/modules/ai/constants.es.js +0 -50
  40. package/es/modules/ai/constants.es.js.map +0 -1
  41. package/es/modules/ai/icons.es.js +0 -319
  42. package/es/modules/ai/icons.es.js.map +0 -1
  43. package/es/modules/ai/index.es.js +0 -670
  44. package/es/modules/ai/index.es.js.map +0 -1
  45. package/es/modules/flow-chart/config-utils.es.js +0 -102
  46. package/es/modules/flow-chart/config-utils.es.js.map +0 -1
  47. package/es/modules/flow-chart/formats/flow-chart-blot.es.js +0 -369
  48. package/es/modules/flow-chart/formats/flow-chart-blot.es.js.map +0 -1
  49. package/es/modules/flow-chart/i18n/en-us.es.js +0 -30
  50. package/es/modules/flow-chart/i18n/en-us.es.js.map +0 -1
  51. package/es/modules/flow-chart/i18n/index.es.js +0 -12
  52. package/es/modules/flow-chart/i18n/index.es.js.map +0 -1
  53. package/es/modules/flow-chart/i18n/zh-cn.es.js +0 -30
  54. package/es/modules/flow-chart/i18n/zh-cn.es.js.map +0 -1
  55. package/es/modules/flow-chart/icons.es.js +0 -27
  56. package/es/modules/flow-chart/icons.es.js.map +0 -1
  57. package/es/modules/flow-chart/index.es.js +0 -45
  58. package/es/modules/flow-chart/index.es.js.map +0 -1
  59. package/es/modules/flow-chart/modules/context-menu.es.js +0 -184
  60. package/es/modules/flow-chart/modules/context-menu.es.js.map +0 -1
  61. package/es/modules/flow-chart/modules/control-panel.es.js +0 -286
  62. package/es/modules/flow-chart/modules/control-panel.es.js.map +0 -1
  63. package/es/modules/flow-chart/modules/custom-resize-action.es.js +0 -150
  64. package/es/modules/flow-chart/modules/custom-resize-action.es.js.map +0 -1
  65. package/es/modules/mind-map/config-utils.es.js +0 -108
  66. package/es/modules/mind-map/config-utils.es.js.map +0 -1
  67. package/es/modules/mind-map/formats/mind-map-blot.es.js +0 -356
  68. package/es/modules/mind-map/formats/mind-map-blot.es.js.map +0 -1
  69. package/es/modules/mind-map/i18n/en-us.es.js +0 -29
  70. package/es/modules/mind-map/i18n/en-us.es.js.map +0 -1
  71. package/es/modules/mind-map/i18n/index.es.js +0 -12
  72. package/es/modules/mind-map/i18n/index.es.js.map +0 -1
  73. package/es/modules/mind-map/i18n/zh-cn.es.js +0 -29
  74. package/es/modules/mind-map/i18n/zh-cn.es.js.map +0 -1
  75. package/es/modules/mind-map/icons.es.js +0 -45
  76. package/es/modules/mind-map/icons.es.js.map +0 -1
  77. package/es/modules/mind-map/index.es.js +0 -56
  78. package/es/modules/mind-map/index.es.js.map +0 -1
  79. package/es/modules/mind-map/modules/context-menu.es.js +0 -128
  80. package/es/modules/mind-map/modules/context-menu.es.js.map +0 -1
  81. package/es/modules/mind-map/modules/control-panel.es.js +0 -425
  82. package/es/modules/mind-map/modules/control-panel.es.js.map +0 -1
  83. package/es/modules/mind-map/modules/custom-resize-action.es.js +0 -161
  84. package/es/modules/mind-map/modules/custom-resize-action.es.js.map +0 -1
  85. package/flow-chart.css +0 -185
  86. package/lib/modules/ai/constants.cjs.js +0 -50
  87. package/lib/modules/ai/constants.cjs.js.map +0 -1
  88. package/lib/modules/ai/icons.cjs.js +0 -319
  89. package/lib/modules/ai/icons.cjs.js.map +0 -1
  90. package/lib/modules/ai/index.cjs.js +0 -670
  91. package/lib/modules/ai/index.cjs.js.map +0 -1
  92. package/lib/modules/flow-chart/config-utils.cjs.js +0 -102
  93. package/lib/modules/flow-chart/config-utils.cjs.js.map +0 -1
  94. package/lib/modules/flow-chart/formats/flow-chart-blot.cjs.js +0 -369
  95. package/lib/modules/flow-chart/formats/flow-chart-blot.cjs.js.map +0 -1
  96. package/lib/modules/flow-chart/i18n/en-us.cjs.js +0 -30
  97. package/lib/modules/flow-chart/i18n/en-us.cjs.js.map +0 -1
  98. package/lib/modules/flow-chart/i18n/index.cjs.js +0 -12
  99. package/lib/modules/flow-chart/i18n/index.cjs.js.map +0 -1
  100. package/lib/modules/flow-chart/i18n/zh-cn.cjs.js +0 -30
  101. package/lib/modules/flow-chart/i18n/zh-cn.cjs.js.map +0 -1
  102. package/lib/modules/flow-chart/icons.cjs.js +0 -27
  103. package/lib/modules/flow-chart/icons.cjs.js.map +0 -1
  104. package/lib/modules/flow-chart/index.cjs.js +0 -45
  105. package/lib/modules/flow-chart/index.cjs.js.map +0 -1
  106. package/lib/modules/flow-chart/modules/context-menu.cjs.js +0 -184
  107. package/lib/modules/flow-chart/modules/context-menu.cjs.js.map +0 -1
  108. package/lib/modules/flow-chart/modules/control-panel.cjs.js +0 -286
  109. package/lib/modules/flow-chart/modules/control-panel.cjs.js.map +0 -1
  110. package/lib/modules/flow-chart/modules/custom-resize-action.cjs.js +0 -150
  111. package/lib/modules/flow-chart/modules/custom-resize-action.cjs.js.map +0 -1
  112. package/lib/modules/mind-map/config-utils.cjs.js +0 -108
  113. package/lib/modules/mind-map/config-utils.cjs.js.map +0 -1
  114. package/lib/modules/mind-map/formats/mind-map-blot.cjs.js +0 -356
  115. package/lib/modules/mind-map/formats/mind-map-blot.cjs.js.map +0 -1
  116. package/lib/modules/mind-map/i18n/en-us.cjs.js +0 -29
  117. package/lib/modules/mind-map/i18n/en-us.cjs.js.map +0 -1
  118. package/lib/modules/mind-map/i18n/index.cjs.js +0 -12
  119. package/lib/modules/mind-map/i18n/index.cjs.js.map +0 -1
  120. package/lib/modules/mind-map/i18n/zh-cn.cjs.js +0 -29
  121. package/lib/modules/mind-map/i18n/zh-cn.cjs.js.map +0 -1
  122. package/lib/modules/mind-map/icons.cjs.js +0 -45
  123. package/lib/modules/mind-map/icons.cjs.js.map +0 -1
  124. package/lib/modules/mind-map/index.cjs.js +0 -56
  125. package/lib/modules/mind-map/index.cjs.js.map +0 -1
  126. package/lib/modules/mind-map/modules/context-menu.cjs.js +0 -128
  127. package/lib/modules/mind-map/modules/context-menu.cjs.js.map +0 -1
  128. package/lib/modules/mind-map/modules/control-panel.cjs.js +0 -425
  129. package/lib/modules/mind-map/modules/control-panel.cjs.js.map +0 -1
  130. package/lib/modules/mind-map/modules/custom-resize-action.cjs.js +0 -161
  131. package/lib/modules/mind-map/modules/custom-resize-action.cjs.js.map +0 -1
  132. package/mind-map.css +0 -224
  133. package/types/modules/ai/constants.d.ts +0 -30
  134. package/types/modules/ai/icons.d.ts +0 -21
  135. package/types/modules/ai/index.d.ts +0 -96
  136. package/types/modules/ai/types.d.ts +0 -16
  137. package/types/modules/flow-chart/config-utils.d.ts +0 -10
  138. package/types/modules/flow-chart/formats/flow-chart-blot.d.ts +0 -43
  139. package/types/modules/flow-chart/i18n/en-us.d.ts +0 -26
  140. package/types/modules/flow-chart/i18n/index.d.ts +0 -1
  141. package/types/modules/flow-chart/i18n/zh-cn.d.ts +0 -26
  142. package/types/modules/flow-chart/icons.d.ts +0 -12
  143. package/types/modules/flow-chart/index.d.ts +0 -10
  144. package/types/modules/flow-chart/modules/context-menu.d.ts +0 -3
  145. package/types/modules/flow-chart/modules/control-panel.d.ts +0 -3
  146. package/types/modules/flow-chart/modules/custom-resize-action.d.ts +0 -22
  147. package/types/modules/flow-chart/options.d.ts +0 -29
  148. package/types/modules/mind-map/config-utils.d.ts +0 -12
  149. package/types/modules/mind-map/formats/mind-map-blot.d.ts +0 -44
  150. package/types/modules/mind-map/i18n/en-us.d.ts +0 -25
  151. package/types/modules/mind-map/i18n/index.d.ts +0 -1
  152. package/types/modules/mind-map/i18n/zh-cn.d.ts +0 -25
  153. package/types/modules/mind-map/icons.d.ts +0 -21
  154. package/types/modules/mind-map/index.d.ts +0 -10
  155. package/types/modules/mind-map/modules/context-menu.d.ts +0 -3
  156. package/types/modules/mind-map/modules/control-panel.d.ts +0 -3
  157. package/types/modules/mind-map/modules/custom-resize-action.d.ts +0 -23
  158. package/types/modules/mind-map/options.d.ts +0 -27
@@ -1,670 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { REPLACE_SELECT, INSERT_SUB_CONTENT_TEXT, INSERT_TEXT, REGENERATE, CLOSE, RESULT_HEADER_TEXT, MENU_ID_MAP, MENU_TITLE_DATA, SELECT_PLACEHOLDER, INPUT_PLACEHOLDER, THINK_TEXT, STOP_ANSWER } from "./constants.es.js";
5
- import { REPLACE_SELECT_ICON, INSERT_ICON, REBUILD_ICON, MENU_CLOSE_ICON, EDITOR_ICON, CALL_ICON, ADJUST_ICON, REFRESH_ICON, COPY_ICON, RIGHT_ARROW_ICON, SEND_BTN_ICON, CLOSE_ICON, AI_ICON, THINK_ICON, STOP_ICON } from "./icons.es.js";
6
- class AI {
7
- constructor(quill, options) {
8
- __publicField(this, "toolbar");
9
- __publicField(this, "host");
10
- __publicField(this, "apiKey");
11
- __publicField(this, "model");
12
- __publicField(this, "message");
13
- __publicField(this, "isBreak", false);
14
- // 打断标记
15
- __publicField(this, "textNumber");
16
- // 文本字数限制
17
- __publicField(this, "_isSelectRangeMode", false);
18
- // 选择/点击模式
19
- __publicField(this, "_charCount", 0);
20
- // 文本字数
21
- __publicField(this, "_debounceTimer", null);
22
- __publicField(this, "_inputPlaceholder", "");
23
- __publicField(this, "_showOperationMenu", false);
24
- __publicField(this, "_isThinking", false);
25
- // 思考中
26
- __publicField(this, "_showResultPopupEl", false);
27
- // 结果弹窗
28
- __publicField(this, "selectedText", "");
29
- // 选择的文本
30
- __publicField(this, "inputValue", "");
31
- // 存储输入框的值
32
- __publicField(this, "resultMenuList", []);
33
- __publicField(this, "operationMenuList", []);
34
- __publicField(this, "_operationMenuItemList", []);
35
- __publicField(this, "alertEl", null);
36
- __publicField(this, "alertTimer", null);
37
- __publicField(this, "selectionBubbleEl", null);
38
- __publicField(this, "selectionRange", null);
39
- __publicField(this, "dialogContainerEl", null);
40
- __publicField(this, "wrapContainerEl", null);
41
- __publicField(this, "aiIconEl", null);
42
- __publicField(this, "inputContainerEl", null);
43
- __publicField(this, "inputEl", null);
44
- __publicField(this, "menuContainerEl", null);
45
- __publicField(this, "subMenuEl", null);
46
- __publicField(this, "subMenuEditorEl", null);
47
- __publicField(this, "subMenuToneEl", null);
48
- __publicField(this, "subMenuAdjustEl", null);
49
- __publicField(this, "inputRightEl", null);
50
- __publicField(this, "inputSendBtnEl", null);
51
- __publicField(this, "inputCloseBtnEl", null);
52
- __publicField(this, "thinkContainerEl", null);
53
- // 思考元素
54
- __publicField(this, "thinkBtnEl", null);
55
- __publicField(this, "resultPopupEl", null);
56
- __publicField(this, "resultPopupHeaderEl", null);
57
- __publicField(this, "resultPopupContentEl", null);
58
- __publicField(this, "resultPopupFooterEl", null);
59
- __publicField(this, "resultPopupFooterTextEl", null);
60
- __publicField(this, "resultRefreshBtnEl", null);
61
- __publicField(this, "resultCopyBtnEl", null);
62
- // 分享和朗读功能待放开
63
- // private resultShareBtnEl: HTMLSpanElement | null = null
64
- // private resultVoiceBtnEl: HTMLSpanElement | null = null
65
- __publicField(this, "actionMenuEl", null);
66
- this.quill = quill;
67
- this.options = options;
68
- this.quill = quill;
69
- this.toolbar = quill.getModule("toolbar");
70
- if (typeof this.toolbar !== "undefined") {
71
- this.toolbar.addHandler("ai", this.showAIInput.bind(this));
72
- }
73
- this.quill.on("selection-change", this.handleSelectionChange.bind(this));
74
- this.host = options.host || "https://api.deepseek.com/v1";
75
- this.apiKey = options.apiKey;
76
- this.model = options.model || "deepseek-chat";
77
- this.textNumber = options.contentMaxLength || 5e3;
78
- this.resultMenuList = [
79
- { text: REPLACE_SELECT, icon: REPLACE_SELECT_ICON },
80
- { text: INSERT_TEXT, icon: INSERT_ICON, selectText: INSERT_SUB_CONTENT_TEXT },
81
- { text: REGENERATE, icon: REBUILD_ICON },
82
- { text: CLOSE, icon: MENU_CLOSE_ICON }
83
- ];
84
- this.operationMenuList = [
85
- { id: "editor", text: "编辑调整内容", icon: EDITOR_ICON },
86
- { id: "tone", text: "改写口吻", icon: CALL_ICON },
87
- { id: "adjust", text: "整理选区内容", icon: ADJUST_ICON }
88
- ];
89
- }
90
- // 工具栏启动
91
- showAIInput() {
92
- this.create();
93
- this.selectionRange = this.quill.getSelection();
94
- if (this.selectionRange.length) {
95
- this.isSelectRangeMode = true;
96
- } else {
97
- this.isSelectRangeMode = false;
98
- }
99
- this.positionElements();
100
- const handleKeyDown = (e) => {
101
- if (e.key === "Escape") {
102
- this.closeAIPanel();
103
- this.quill.container.removeEventListener("keydown", handleKeyDown);
104
- }
105
- };
106
- this.quill.container.addEventListener("keydown", handleKeyDown);
107
- }
108
- // 气泡启动
109
- selectTextEvent() {
110
- if (!this.selectionRange) return;
111
- this.create();
112
- this.positionElements();
113
- this.isSelectRangeMode = true;
114
- }
115
- create() {
116
- this.createResultElement();
117
- this.createOperationMenuElements();
118
- this.createInputBoxElements();
119
- this.addInputEvent();
120
- this.addResultEvent();
121
- this.handleActionMenuDisplay();
122
- this.quill.container.appendChild(this.dialogContainerEl);
123
- }
124
- // 创建结果弹窗
125
- createResultElement() {
126
- if (!this.resultPopupEl) {
127
- this.resultPopupEl = document.createElement("div");
128
- this.resultPopupEl.className = "ql-ai-result";
129
- this.resultPopupHeaderEl = document.createElement("div");
130
- this.resultPopupHeaderEl.className = "ql-ai-result-header";
131
- this.resultPopupHeaderEl.textContent = RESULT_HEADER_TEXT;
132
- this.resultPopupContentEl = document.createElement("div");
133
- this.resultPopupContentEl.className = "ql-ai-result-content";
134
- this.resultPopupFooterEl = document.createElement("div");
135
- this.resultPopupFooterEl.className = "ql-ai-result-footer";
136
- this.resultPopupFooterTextEl = document.createElement("span");
137
- this.resultPopupFooterTextEl.className = "ql-ai-result-footer-text";
138
- this.resultPopupFooterTextEl.textContent = `0`;
139
- this.resultRefreshBtnEl = document.createElement("span");
140
- this.resultRefreshBtnEl.className = "ql-ai-result-footer-refresh";
141
- this.resultRefreshBtnEl.innerHTML = REFRESH_ICON;
142
- this.resultCopyBtnEl = document.createElement("span");
143
- this.resultCopyBtnEl.className = "ql-ai-result-footer-copy";
144
- this.resultCopyBtnEl.innerHTML = COPY_ICON;
145
- const resultFooterRightEl = document.createElement("div");
146
- resultFooterRightEl.className = "ql-ai-result-footer-right";
147
- resultFooterRightEl.appendChild(this.resultRefreshBtnEl);
148
- resultFooterRightEl.appendChild(this.resultCopyBtnEl);
149
- this.resultPopupFooterEl.appendChild(this.resultPopupFooterTextEl);
150
- this.resultPopupFooterEl.appendChild(resultFooterRightEl);
151
- this.resultPopupEl.appendChild(this.resultPopupHeaderEl);
152
- this.resultPopupEl.appendChild(this.resultPopupContentEl);
153
- this.resultPopupEl.appendChild(this.resultPopupFooterEl);
154
- }
155
- this.showResultPopupEl = false;
156
- }
157
- createOperationMenuElements() {
158
- if (!this.menuContainerEl) {
159
- this.menuContainerEl = document.createElement("div");
160
- this.menuContainerEl.className = "ql-ai-menu-container";
161
- const mainMenu = document.createElement("div");
162
- mainMenu.className = "ql-ai-main-menu";
163
- this.operationMenuList.forEach(({ text, icon, id }) => {
164
- const menuItem = document.createElement("div");
165
- menuItem.className = "ql-ai-menu-item";
166
- menuItem.innerHTML = `${icon}<span>${text}</span>${RIGHT_ARROW_ICON}`;
167
- menuItem.addEventListener("mouseenter", (e) => {
168
- e.stopPropagation();
169
- this.subMenuEl.style.display = "block";
170
- this.subMenuEl.className = `ql-ai-sub-menu ${id}`;
171
- this.createOperationMenuItem(id);
172
- });
173
- mainMenu.appendChild(menuItem);
174
- });
175
- if (!this.subMenuEl) {
176
- this.subMenuEl = document.createElement("div");
177
- this.subMenuEl.className = "ql-ai-sub-menu";
178
- this.subMenuEl.style.display = "none";
179
- }
180
- this.menuContainerEl.appendChild(mainMenu);
181
- this.menuContainerEl.appendChild(this.subMenuEl);
182
- }
183
- this.showOperationMenu = false;
184
- }
185
- createOperationMenuItem(id) {
186
- let menuItemBox = this[MENU_ID_MAP[id]];
187
- if (!menuItemBox) {
188
- menuItemBox = document.createElement("div");
189
- }
190
- while (this.subMenuEl.firstChild) {
191
- this.subMenuEl.removeChild(this.subMenuEl.firstChild);
192
- }
193
- MENU_TITLE_DATA[id].forEach(({ text, icon, id: id2 }) => {
194
- const menuItem = document.createElement("div");
195
- menuItem.className = "ql-ai-menu-item";
196
- menuItem.innerHTML = `${icon || ""}<span>${text}</span>`;
197
- menuItem.addEventListener("click", (e) => {
198
- e.stopPropagation();
199
- this.handleOperationMenuItemClick(text, id2);
200
- });
201
- menuItemBox.appendChild(menuItem);
202
- });
203
- this.subMenuEl.appendChild(menuItemBox);
204
- }
205
- createInputBoxElements() {
206
- if (!this.dialogContainerEl) {
207
- this.dialogContainerEl = document.createElement("div");
208
- this.dialogContainerEl.className = "ql-ai-dialog";
209
- this.wrapContainerEl = document.createElement("div");
210
- this.wrapContainerEl.className = "ql-ai-wrapper";
211
- this.wrapContainerEl.style.width = `${this.quill.container.clientWidth - 30}px`;
212
- this.createAIInputIcon();
213
- this.inputEl = document.createElement("input");
214
- this.inputEl.type = "text";
215
- this.inputPlaceholder = this._isSelectRangeMode ? SELECT_PLACEHOLDER : INPUT_PLACEHOLDER;
216
- this.inputSendBtnEl = document.createElement("span");
217
- this.inputSendBtnEl.className = "ql-ai-input-right-send";
218
- this.inputSendBtnEl.innerHTML = SEND_BTN_ICON;
219
- this.inputCloseBtnEl = document.createElement("span");
220
- this.inputCloseBtnEl.className = "ql-ai-input-right-close";
221
- this.inputCloseBtnEl.innerHTML = CLOSE_ICON;
222
- this.inputRightEl = document.createElement("div");
223
- this.inputRightEl.className = "ql-ai-input-right";
224
- this.inputContainerEl = document.createElement("div");
225
- this.inputContainerEl.className = "ql-ai-input";
226
- this.inputContainerEl.appendChild(this.aiIconEl);
227
- this.inputContainerEl.appendChild(this.inputEl);
228
- this.inputRightEl.appendChild(this.inputSendBtnEl);
229
- this.inputRightEl.appendChild(this.inputCloseBtnEl);
230
- this.inputContainerEl.appendChild(this.inputRightEl);
231
- this.wrapContainerEl.appendChild(this.resultPopupEl);
232
- this.wrapContainerEl.appendChild(this.inputContainerEl);
233
- this.wrapContainerEl.appendChild(this.menuContainerEl);
234
- this.dialogContainerEl.appendChild(this.wrapContainerEl);
235
- } else {
236
- this.dialogContainerEl.style.display = "block";
237
- }
238
- this.hiddenInputSendBtnEl();
239
- }
240
- hiddenInputSendBtnEl(display = "none") {
241
- if (this.inputEl && this.inputSendBtnEl) {
242
- this.inputSendBtnEl.style.display = display;
243
- }
244
- }
245
- copyResult() {
246
- if (!this.resultPopupContentEl) return;
247
- try {
248
- const textToCopy = this.resultPopupContentEl.textContent || "";
249
- navigator.clipboard.writeText(textToCopy).then(() => {
250
- this.showAlert("内容已复制到剪贴板");
251
- }).catch((err) => {
252
- this.showAlert(`复制失败:${err}`);
253
- });
254
- } catch (err) {
255
- this.showAlert(`复制失败:${err}`);
256
- const textarea = document.createElement("textarea");
257
- textarea.value = this.resultPopupContentEl.textContent || "";
258
- document.body.appendChild(textarea);
259
- textarea.select();
260
- document.execCommand("copy");
261
- document.body.removeChild(textarea);
262
- }
263
- }
264
- // 分享和朗读功能待放开
265
- // private shareResult() {
266
- // if (!this.resultPopupContentEl) return
267
- // const textToShare = this.resultPopupContentEl.textContent || ''
268
- // const title = 'AI生成内容分享'
269
- // if (navigator.share) {
270
- // navigator.share({
271
- // title,
272
- // text: textToShare,
273
- // })
274
- // .catch((err) => {
275
- // this.showAlert(`分享失败:${err}`)
276
- // })
277
- // }
278
- // else {
279
- // // 兼容不支持Web Share API的浏览器
280
- // const shareUrl = `mailto:?subject=${encodeURIComponent(title)}&body=${encodeURIComponent(textToShare)}`
281
- // window.open(shareUrl, '_blank')
282
- // }
283
- // }
284
- // private voiceResult() {
285
- // if (!this.resultPopupContentEl) return
286
- // const textToSpeak = this.resultPopupContentEl.textContent || ''
287
- // if ('speechSynthesis' in window) {
288
- // const utterance = new SpeechSynthesisUtterance(textToSpeak)
289
- // utterance.lang = 'zh-CN' // 设置中文语音
290
- // speechSynthesis.speak(utterance)
291
- // }
292
- // else {
293
- // this.showAlert('当前浏览器不支持语音合成API')
294
- // // 可以在这里添加不支持语音的提示
295
- // }
296
- // }
297
- addResultEvent() {
298
- if (this.resultRefreshBtnEl) {
299
- this.resultRefreshBtnEl.addEventListener("click", () => {
300
- this.regenerateResponse();
301
- });
302
- }
303
- if (this.resultCopyBtnEl) {
304
- this.resultCopyBtnEl.addEventListener("click", () => {
305
- this.copyResult();
306
- });
307
- }
308
- }
309
- // 显示选中文本的气泡
310
- showSelectionBubble() {
311
- if (!this.selectionBubbleEl) {
312
- this.selectionBubbleEl = document.createElement("div");
313
- this.selectionBubbleEl.className = "ql-ai-selection-bubble";
314
- const icon = AI_ICON.replaceAll("paint_linear_2", "paint_linear_bubble");
315
- this.selectionBubbleEl.innerHTML = `${icon}<span>AI 智能</span>`;
316
- this.selectionBubbleEl.addEventListener("click", () => this.selectTextEvent());
317
- document.body.appendChild(this.selectionBubbleEl);
318
- }
319
- const { left, top } = this.quill.getBounds(this.selectionRange.index);
320
- const { left: endLeft } = this.quill.getBounds(this.selectionRange.index + this.selectionRange.length);
321
- const width = (endLeft - left) / 2;
322
- const editorRect = this.quill.container.getBoundingClientRect();
323
- this.selectionBubbleEl.style.display = "flex";
324
- this.selectionBubbleEl.style.left = `${left + editorRect.left + width - 45}px`;
325
- this.selectionBubbleEl.style.top = `${top + editorRect.top - 40}px`;
326
- }
327
- // 隐藏选中文本的气泡
328
- hideSelectionBubble() {
329
- if (this.selectionBubbleEl) {
330
- this.selectionBubbleEl.style.display = "none";
331
- }
332
- }
333
- // 处理文本选中变化
334
- handleSelectionChange(range) {
335
- if (range && range.length > 0) {
336
- this.selectionRange = range;
337
- this.showSelectionBubble();
338
- this.selectedText = this.quill.getText(range.index, range.length);
339
- } else {
340
- if (range && range.index !== null) {
341
- this.selectedText = "";
342
- this.closeAIPanel();
343
- } else {
344
- this.hideSelectionBubble();
345
- }
346
- }
347
- }
348
- addInputEvent() {
349
- if (this.inputContainerEl) {
350
- this.inputContainerEl.addEventListener("click", () => {
351
- });
352
- }
353
- if (this.inputEl) {
354
- this.inputEl.addEventListener("input", () => {
355
- this.hiddenInputSendBtnEl(this.inputEl.value.trim() ? "flex" : "none");
356
- if (this.menuContainerEl && this._isSelectRangeMode) {
357
- this.showOperationMenu = !this.inputEl.value.trim() && !this._showResultPopupEl;
358
- }
359
- });
360
- }
361
- if (this.inputSendBtnEl) {
362
- this.inputSendBtnEl.addEventListener("click", async () => {
363
- await this.queryAI();
364
- });
365
- }
366
- this.inputEl.addEventListener("keydown", async (e) => {
367
- if (e.key === "Enter") {
368
- await this.queryAI();
369
- }
370
- });
371
- if (this.inputCloseBtnEl) {
372
- this.inputCloseBtnEl.addEventListener("click", () => {
373
- this.closeAIPanel();
374
- });
375
- }
376
- }
377
- positionElements() {
378
- if (!this.dialogContainerEl) return;
379
- const range = this.selectionRange;
380
- if (range) {
381
- const bounds = this.quill.getBounds(range.index);
382
- this.dialogContainerEl.style.position = "absolute";
383
- this.dialogContainerEl.style.top = `${bounds.top + bounds.height + 20}px`;
384
- }
385
- }
386
- // 添加创建alert元素的方法
387
- createAlertElement() {
388
- if (!this.alertEl) {
389
- this.alertEl = document.createElement("div");
390
- this.alertEl.className = "ql-ai-alert";
391
- this.alertEl.style.display = "none";
392
- document.body.appendChild(this.alertEl);
393
- }
394
- }
395
- // 添加显示alert的方法
396
- showAlert(message, duration = 3e3) {
397
- this.createAlertElement();
398
- if (!this.alertEl) return;
399
- if (this.alertTimer) {
400
- clearTimeout(this.alertTimer);
401
- this.alertTimer = null;
402
- }
403
- this.alertEl.textContent = message;
404
- this.alertEl.style.display = "block";
405
- this.alertTimer = setTimeout(() => {
406
- if (this.alertEl) {
407
- this.alertEl.style.display = "none";
408
- }
409
- this.alertTimer = null;
410
- }, duration);
411
- }
412
- createAIInputIcon() {
413
- if (!this.aiIconEl) {
414
- this.aiIconEl = document.createElement("span");
415
- this.aiIconEl.className = "ql-ai-input-pre-icon";
416
- const icon = AI_ICON.replaceAll("paint_linear_2", "paint_linear_ai_input");
417
- this.aiIconEl.innerHTML = icon;
418
- }
419
- }
420
- // 添加处理子菜单点击的方法
421
- handleOperationMenuItemClick(text, id = "") {
422
- let quetion = "";
423
- if (id.startsWith("1-") || id.startsWith("3-")) {
424
- quetion = `将目标文字${text},目标文字为:${this.selectedText}`;
425
- } else if (id.startsWith("2-")) {
426
- quetion = `改写目标文字的口吻,让其变得${text},目标文字为:${this.selectedText}`;
427
- }
428
- this.showOperationMenu = false;
429
- this.queryAI(quetion);
430
- }
431
- createActionMenu() {
432
- if (!this.actionMenuEl) {
433
- this.actionMenuEl = document.createElement("div");
434
- this.actionMenuEl.className = "ql-ai-actions";
435
- this.resultMenuList.forEach(({ text, icon }) => {
436
- const menuItem = document.createElement("div");
437
- menuItem.className = "ql-ai-action-item";
438
- menuItem.innerHTML = `${icon}<span class="ql-ai-result-menu-text">${text}</span>`;
439
- menuItem.addEventListener("click", () => this.handleAction(text));
440
- this.actionMenuEl.appendChild(menuItem);
441
- });
442
- this.wrapContainerEl.appendChild(this.actionMenuEl);
443
- }
444
- const secondMenuItemText = this.actionMenuEl.children[1].querySelector(".ql-ai-result-menu-text");
445
- const firstChild = this.actionMenuEl.firstChild;
446
- if (!this._isSelectRangeMode) {
447
- if (firstChild instanceof Element) {
448
- firstChild.classList.add("hidden");
449
- }
450
- secondMenuItemText.textContent = INSERT_TEXT;
451
- } else {
452
- if (firstChild instanceof Element) {
453
- firstChild.classList.remove("hidden");
454
- }
455
- secondMenuItemText.textContent = INSERT_SUB_CONTENT_TEXT;
456
- }
457
- this.isThinking = false;
458
- }
459
- handleActionMenuDisplay(value = "none") {
460
- if (this.actionMenuEl) {
461
- this.actionMenuEl.style.display = value;
462
- }
463
- }
464
- switchInputEl(showInput = true) {
465
- if (this.inputContainerEl) {
466
- this.inputContainerEl.style.display = showInput ? "flex" : "none";
467
- }
468
- this.handleActionMenuDisplay(showInput ? "block" : "none");
469
- if (this.thinkContainerEl) {
470
- this.thinkContainerEl.style.display = showInput ? "none" : "flex";
471
- }
472
- }
473
- // 创建思考元素
474
- createThinkElements() {
475
- if (!this.thinkContainerEl) {
476
- this.thinkContainerEl = document.createElement("div");
477
- this.thinkContainerEl.className = "ql-ai-input";
478
- this.thinkContainerEl.innerHTML = `<span class="ql-ai-input-pre-icon ql-ai-think-icon">${THINK_ICON}</span><span class="ql-ai-think-text">${THINK_TEXT}</span>`;
479
- this.thinkBtnEl = document.createElement("div");
480
- this.thinkBtnEl.className = "ql-ai-think-btn";
481
- this.thinkBtnEl.innerHTML = `${STOP_ICON}<span>${STOP_ANSWER}</span>`;
482
- this.thinkContainerEl.appendChild(this.thinkBtnEl);
483
- this.wrapContainerEl.appendChild(this.thinkContainerEl);
484
- this.thinkBtnEl.addEventListener("click", () => {
485
- this.isBreak = true;
486
- this.isThinking = false;
487
- });
488
- }
489
- this.isThinking = true;
490
- }
491
- // AI查询
492
- async queryAI(question) {
493
- this.createThinkElements();
494
- this.inputValue = question || this.inputEl.value;
495
- if (this.inputValue.trim() === "") {
496
- return;
497
- }
498
- this.isBreak = false;
499
- try {
500
- const response = await fetch(`${this.host}`, {
501
- method: "POST",
502
- headers: {
503
- "Content-Type": "application/json",
504
- "Authorization": `Bearer ${this.apiKey}`
505
- },
506
- body: JSON.stringify({
507
- model: this.model,
508
- prompt: this.inputValue,
509
- stream: true
510
- })
511
- });
512
- if (!response.ok) {
513
- throw new Error(`HTTP error! status: ${response.status}`);
514
- }
515
- const reader = response.body.getReader();
516
- const decoder = new TextDecoder();
517
- let content = "";
518
- while (true) {
519
- if (this.isBreak) {
520
- this.isBreak = false;
521
- break;
522
- }
523
- const { done, value } = await reader.read();
524
- if (done) break;
525
- const chunk = decoder.decode(value);
526
- const lines = chunk.split("\n").filter((line) => line.trim() !== "");
527
- for (const line of lines) {
528
- try {
529
- const data = JSON.parse(line);
530
- content += data.response || "";
531
- this.showAIResponse(content);
532
- } catch (e) {
533
- console.error("解析错误:", e);
534
- }
535
- }
536
- }
537
- this.createActionMenu();
538
- this.inputEl.value = "";
539
- this.hiddenInputSendBtnEl();
540
- return content;
541
- } catch (error) {
542
- console.error("AI查询失败:", error);
543
- return "AI查询失败,请重试";
544
- }
545
- }
546
- showAIResponse(response) {
547
- if (!this.resultPopupEl) return;
548
- if (this._charCount <= this.textNumber) {
549
- this.resultPopupContentEl.innerHTML = response;
550
- this.charCount = this.resultPopupContentEl.textContent.replace(/\s+/g, "").length;
551
- } else {
552
- this.isBreak = true;
553
- this.charCount = 0;
554
- }
555
- this.showResultPopupEl = true;
556
- }
557
- handleAction(action) {
558
- switch (action) {
559
- case REPLACE_SELECT:
560
- this.replaceSelectText();
561
- break;
562
- case INSERT_TEXT:
563
- this.insertAIResponse();
564
- break;
565
- case REGENERATE:
566
- this.regenerateResponse();
567
- break;
568
- case CLOSE:
569
- this.closeAIPanel();
570
- break;
571
- }
572
- }
573
- replaceSelectText() {
574
- if (!this.resultPopupContentEl) return;
575
- const range = this.quill.getSelection(true);
576
- if (range && range.length > 0) {
577
- this.quill.deleteText(range.index, range.length);
578
- this.quill.clipboard.dangerouslyPasteHTML(range.index, this.resultPopupContentEl.innerHTML);
579
- }
580
- this.closeAIPanel();
581
- }
582
- insertAIResponse() {
583
- if (!this.resultPopupContentEl) return;
584
- const range = this.quill.getSelection(true);
585
- if (range) {
586
- this.quill.clipboard.dangerouslyPasteHTML(range.index + range.length, this.resultPopupContentEl.innerHTML);
587
- }
588
- this.closeAIPanel();
589
- }
590
- async regenerateResponse() {
591
- await this.queryAI(this.inputValue);
592
- }
593
- closeAIPanel() {
594
- this.isBreak = true;
595
- if (this.dialogContainerEl) {
596
- this.dialogContainerEl.style.display = "none";
597
- }
598
- if (this.actionMenuEl) {
599
- this.actionMenuEl.style.display = "none";
600
- }
601
- this.showResultPopupEl = false;
602
- if (this.inputEl && this.inputEl.value.trim() !== "") {
603
- this.inputEl.value = "";
604
- }
605
- this.hideSelectionBubble();
606
- }
607
- set charCount(value) {
608
- if (this._debounceTimer) {
609
- clearTimeout(this._debounceTimer);
610
- }
611
- this._debounceTimer = setTimeout(() => {
612
- this._charCount = value;
613
- if (this.resultPopupFooterTextEl) {
614
- this.resultPopupFooterTextEl.textContent = `${this._charCount}/${this.textNumber}`;
615
- }
616
- clearTimeout(this._debounceTimer);
617
- this._debounceTimer = null;
618
- }, 210);
619
- }
620
- get charCount() {
621
- return this._charCount;
622
- }
623
- set inputPlaceholder(value) {
624
- this._inputPlaceholder = value;
625
- if (this.inputEl) {
626
- this.inputEl.placeholder = value;
627
- }
628
- }
629
- get inputPlaceholder() {
630
- return this._inputPlaceholder;
631
- }
632
- set showOperationMenu(value) {
633
- this._showOperationMenu = value;
634
- if (this.menuContainerEl) {
635
- this.menuContainerEl.style.display = value ? "flex" : "none";
636
- }
637
- }
638
- get showOperationMenu() {
639
- return this._showOperationMenu;
640
- }
641
- set isSelectRangeMode(value) {
642
- this._isSelectRangeMode = value;
643
- this.showOperationMenu = value;
644
- this.inputPlaceholder = value ? SELECT_PLACEHOLDER : INPUT_PLACEHOLDER;
645
- this.hideSelectionBubble();
646
- }
647
- get isSelectRangeMode() {
648
- return this._isSelectRangeMode;
649
- }
650
- set isThinking(value) {
651
- this._isThinking = value;
652
- this.switchInputEl(!value);
653
- }
654
- get isThinking() {
655
- return this._isThinking;
656
- }
657
- set showResultPopupEl(value) {
658
- this._showResultPopupEl = value;
659
- if (this.resultPopupEl) {
660
- this.resultPopupEl.style.display = value ? "block" : "none";
661
- }
662
- }
663
- get showResultPopupEl() {
664
- return this._showResultPopupEl;
665
- }
666
- }
667
- export {
668
- AI
669
- };
670
- //# sourceMappingURL=index.es.js.map