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