@ai-group/chat-sdk 3.7.0 → 3.7.1-alpha10

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 (235) hide show
  1. package/README.md +22 -0
  2. package/dist/cjs/components/FileGallery/index.js +59 -40
  3. package/dist/cjs/components/FileGallery/index.js.map +2 -2
  4. package/dist/cjs/components/FileGallery/styles.d.ts +7 -0
  5. package/dist/cjs/components/FileGallery/styles.js +78 -0
  6. package/dist/cjs/components/FileGallery/styles.js.map +2 -2
  7. package/dist/cjs/components/Sources/components/CarouselCard.d.ts +12 -0
  8. package/dist/cjs/components/Sources/components/CarouselCard.js +130 -0
  9. package/dist/cjs/components/Sources/components/CarouselCard.js.map +7 -0
  10. package/dist/cjs/components/Sources/index.d.ts +5 -0
  11. package/dist/cjs/components/Sources/index.js +162 -0
  12. package/dist/cjs/components/Sources/index.js.map +7 -0
  13. package/dist/cjs/components/Sources/styles.d.ts +59 -0
  14. package/dist/cjs/components/Sources/styles.js +179 -0
  15. package/dist/cjs/components/Sources/styles.js.map +7 -0
  16. package/dist/cjs/components/XAdkChatbot/components/MarkdownRender/index.d.ts +19 -1
  17. package/dist/cjs/components/XAdkChatbot/components/MarkdownRender/index.js +232 -22
  18. package/dist/cjs/components/XAdkChatbot/components/MarkdownRender/index.js.map +2 -2
  19. package/dist/cjs/components/XAdkChatbot/components/MarkdownRender/styles.d.ts +3 -0
  20. package/dist/cjs/components/XAdkChatbot/components/MarkdownRender/styles.js +83 -0
  21. package/dist/cjs/components/XAdkChatbot/components/MarkdownRender/styles.js.map +2 -2
  22. package/dist/cjs/components/XAdkChatbot/index.d.ts +2 -2
  23. package/dist/cjs/components/XAdkChatbot/index.js +75 -8
  24. package/dist/cjs/components/XAdkChatbot/index.js.map +2 -2
  25. package/dist/cjs/components/XAdkChatbot/styles.js +1 -1
  26. package/dist/cjs/components/XAdkChatbot/styles.js.map +1 -1
  27. package/dist/cjs/components/XAdkProvider/compound/DefaultLayout.d.ts +7 -2
  28. package/dist/cjs/components/XAdkProvider/compound/DefaultLayout.js +30 -12
  29. package/dist/cjs/components/XAdkProvider/compound/DefaultLayout.js.map +2 -2
  30. package/dist/cjs/components/XAdkProvider/compound/Sender.d.ts +3 -1
  31. package/dist/cjs/components/XAdkProvider/compound/Sender.js +81 -4
  32. package/dist/cjs/components/XAdkProvider/compound/Sender.js.map +3 -3
  33. package/dist/cjs/components/XAdkProvider/compound/styles.d.ts +1 -0
  34. package/dist/cjs/components/XAdkProvider/compound/styles.js +16 -0
  35. package/dist/cjs/components/XAdkProvider/compound/styles.js.map +2 -2
  36. package/dist/cjs/components/XAdkProvider/context/ChatSenderStateContext.d.ts +4 -0
  37. package/dist/cjs/components/XAdkProvider/context/ChatSenderStateContext.js.map +2 -2
  38. package/dist/cjs/components/XAdkProvider/context/DefaultLayoutContext.d.ts +9 -0
  39. package/dist/cjs/components/XAdkProvider/context/DefaultLayoutContext.js +34 -0
  40. package/dist/cjs/components/XAdkProvider/context/DefaultLayoutContext.js.map +7 -0
  41. package/dist/cjs/components/XAdkProvider/context/index.d.ts +5 -4
  42. package/dist/cjs/components/XAdkProvider/context/index.js +3 -1
  43. package/dist/cjs/components/XAdkProvider/context/index.js.map +2 -2
  44. package/dist/cjs/components/XAdkProvider/index.js +11 -10
  45. package/dist/cjs/components/XAdkProvider/index.js.map +2 -2
  46. package/dist/cjs/components/XAdkSender/InlineTagInput.d.ts +31 -0
  47. package/dist/cjs/components/XAdkSender/InlineTagInput.js +759 -0
  48. package/dist/cjs/components/XAdkSender/InlineTagInput.js.map +7 -0
  49. package/dist/cjs/components/XAdkSender/InputTags.d.ts +8 -0
  50. package/dist/cjs/components/XAdkSender/InputTags.js +51 -0
  51. package/dist/cjs/components/XAdkSender/InputTags.js.map +7 -0
  52. package/dist/cjs/components/XAdkSender/QuickList.d.ts +16 -0
  53. package/dist/cjs/components/XAdkSender/QuickList.js +105 -0
  54. package/dist/cjs/components/XAdkSender/QuickList.js.map +7 -0
  55. package/dist/cjs/components/XAdkSender/index.d.ts +1 -6
  56. package/dist/cjs/components/XAdkSender/index.js +422 -150
  57. package/dist/cjs/components/XAdkSender/index.js.map +3 -3
  58. package/dist/cjs/components/XAdkSender/styles.d.ts +19 -0
  59. package/dist/cjs/components/XAdkSender/styles.js +225 -5
  60. package/dist/cjs/components/XAdkSender/styles.js.map +2 -2
  61. package/dist/cjs/components/XAiConversations/styles.js +11 -1
  62. package/dist/cjs/components/XAiConversations/styles.js.map +2 -2
  63. package/dist/cjs/hooks/useADKChat.js +5 -1
  64. package/dist/cjs/hooks/useADKChat.js.map +2 -2
  65. package/dist/cjs/index.d.ts +8 -3
  66. package/dist/cjs/index.js +44 -10
  67. package/dist/cjs/index.js.map +3 -3
  68. package/dist/cjs/presets/base.d.ts +6 -0
  69. package/dist/cjs/presets/base.js +50 -0
  70. package/dist/cjs/presets/base.js.map +7 -0
  71. package/dist/cjs/presets/define.d.ts +11 -0
  72. package/dist/cjs/presets/define.js +58 -0
  73. package/dist/cjs/presets/define.js.map +7 -0
  74. package/dist/cjs/presets/index.d.ts +3 -0
  75. package/dist/cjs/presets/index.js +28 -0
  76. package/dist/cjs/presets/index.js.map +7 -0
  77. package/dist/cjs/presets/runtime.d.ts +22 -0
  78. package/dist/cjs/presets/runtime.js +75 -0
  79. package/dist/cjs/presets/runtime.js.map +7 -0
  80. package/dist/cjs/presets/xgroup/index.d.ts +5 -0
  81. package/dist/cjs/presets/xgroup/index.js +10 -0
  82. package/dist/cjs/presets/xgroup/index.js.map +2 -2
  83. package/dist/cjs/presets/xgroup/knowledgeReference.d.ts +17 -0
  84. package/dist/cjs/presets/xgroup/knowledgeReference.js +162 -0
  85. package/dist/cjs/presets/xgroup/knowledgeReference.js.map +7 -0
  86. package/dist/cjs/presets/xgroup/preset.d.ts +1 -13
  87. package/dist/cjs/presets/xgroup/preset.js +16 -37
  88. package/dist/cjs/presets/xgroup/preset.js.map +2 -2
  89. package/dist/cjs/presets/xgroup/strategies.d.ts +5 -4
  90. package/dist/cjs/presets/xgroup/strategies.js +11 -15
  91. package/dist/cjs/presets/xgroup/strategies.js.map +3 -3
  92. package/dist/cjs/presets/xgroup/webReference.d.ts +10 -0
  93. package/dist/cjs/presets/xgroup/webReference.js +85 -0
  94. package/dist/cjs/presets/xgroup/webReference.js.map +7 -0
  95. package/dist/cjs/types/ChatStrategies.d.ts +11 -2
  96. package/dist/cjs/types/ChatStrategies.js.map +1 -1
  97. package/dist/cjs/types/FileGallery.d.ts +3 -0
  98. package/dist/cjs/types/FileGallery.js.map +1 -1
  99. package/dist/cjs/types/Sources.d.ts +30 -0
  100. package/dist/cjs/types/Sources.js +18 -0
  101. package/dist/cjs/types/Sources.js.map +7 -0
  102. package/dist/cjs/types/XAdkChatbot.d.ts +33 -0
  103. package/dist/cjs/types/XAdkChatbot.js.map +1 -1
  104. package/dist/cjs/types/XAdkSender.d.ts +154 -8
  105. package/dist/cjs/types/XAdkSender.js.map +1 -1
  106. package/dist/cjs/types/index.d.ts +1 -0
  107. package/dist/cjs/types/index.js +3 -1
  108. package/dist/cjs/types/index.js.map +2 -2
  109. package/dist/cjs/utils/index.d.ts +1 -0
  110. package/dist/cjs/utils/index.js +3 -1
  111. package/dist/cjs/utils/index.js.map +2 -2
  112. package/dist/cjs/utils/markdownResource.d.ts +14 -0
  113. package/dist/cjs/utils/markdownResource.js +131 -0
  114. package/dist/cjs/utils/markdownResource.js.map +7 -0
  115. package/dist/esm/components/FileGallery/index.js +22 -16
  116. package/dist/esm/components/FileGallery/index.js.map +1 -1
  117. package/dist/esm/components/FileGallery/styles.d.ts +7 -0
  118. package/dist/esm/components/FileGallery/styles.js +24 -17
  119. package/dist/esm/components/FileGallery/styles.js.map +1 -1
  120. package/dist/esm/components/Sources/components/CarouselCard.d.ts +12 -0
  121. package/dist/esm/components/Sources/components/CarouselCard.js +107 -0
  122. package/dist/esm/components/Sources/components/CarouselCard.js.map +1 -0
  123. package/dist/esm/components/Sources/index.d.ts +5 -0
  124. package/dist/esm/components/Sources/index.js +127 -0
  125. package/dist/esm/components/Sources/index.js.map +1 -0
  126. package/dist/esm/components/Sources/styles.d.ts +59 -0
  127. package/dist/esm/components/Sources/styles.js +34 -0
  128. package/dist/esm/components/Sources/styles.js.map +1 -0
  129. package/dist/esm/components/XAdkChatbot/components/MarkdownRender/index.d.ts +19 -1
  130. package/dist/esm/components/XAdkChatbot/components/MarkdownRender/index.js +190 -11
  131. package/dist/esm/components/XAdkChatbot/components/MarkdownRender/index.js.map +1 -1
  132. package/dist/esm/components/XAdkChatbot/components/MarkdownRender/styles.d.ts +3 -0
  133. package/dist/esm/components/XAdkChatbot/components/MarkdownRender/styles.js +5 -2
  134. package/dist/esm/components/XAdkChatbot/components/MarkdownRender/styles.js.map +1 -1
  135. package/dist/esm/components/XAdkChatbot/index.d.ts +2 -2
  136. package/dist/esm/components/XAdkChatbot/index.js +55 -10
  137. package/dist/esm/components/XAdkChatbot/index.js.map +1 -1
  138. package/dist/esm/components/XAdkChatbot/styles.js +1 -1
  139. package/dist/esm/components/XAdkChatbot/styles.js.map +1 -1
  140. package/dist/esm/components/XAdkProvider/compound/DefaultLayout.d.ts +7 -2
  141. package/dist/esm/components/XAdkProvider/compound/DefaultLayout.js +40 -17
  142. package/dist/esm/components/XAdkProvider/compound/DefaultLayout.js.map +1 -1
  143. package/dist/esm/components/XAdkProvider/compound/Sender.d.ts +3 -1
  144. package/dist/esm/components/XAdkProvider/compound/Sender.js +70 -6
  145. package/dist/esm/components/XAdkProvider/compound/Sender.js.map +1 -1
  146. package/dist/esm/components/XAdkProvider/compound/styles.d.ts +1 -0
  147. package/dist/esm/components/XAdkProvider/compound/styles.js +3 -2
  148. package/dist/esm/components/XAdkProvider/compound/styles.js.map +1 -1
  149. package/dist/esm/components/XAdkProvider/context/ChatSenderStateContext.d.ts +4 -0
  150. package/dist/esm/components/XAdkProvider/context/ChatSenderStateContext.js.map +1 -1
  151. package/dist/esm/components/XAdkProvider/context/DefaultLayoutContext.d.ts +9 -0
  152. package/dist/esm/components/XAdkProvider/context/DefaultLayoutContext.js +9 -0
  153. package/dist/esm/components/XAdkProvider/context/DefaultLayoutContext.js.map +1 -0
  154. package/dist/esm/components/XAdkProvider/context/index.d.ts +5 -4
  155. package/dist/esm/components/XAdkProvider/context/index.js +1 -0
  156. package/dist/esm/components/XAdkProvider/context/index.js.map +1 -1
  157. package/dist/esm/components/XAdkProvider/index.js +7 -3
  158. package/dist/esm/components/XAdkProvider/index.js.map +1 -1
  159. package/dist/esm/components/XAdkSender/InlineTagInput.d.ts +31 -0
  160. package/dist/esm/components/XAdkSender/InlineTagInput.js +734 -0
  161. package/dist/esm/components/XAdkSender/InlineTagInput.js.map +1 -0
  162. package/dist/esm/components/XAdkSender/InputTags.d.ts +8 -0
  163. package/dist/esm/components/XAdkSender/InputTags.js +37 -0
  164. package/dist/esm/components/XAdkSender/InputTags.js.map +1 -0
  165. package/dist/esm/components/XAdkSender/QuickList.d.ts +16 -0
  166. package/dist/esm/components/XAdkSender/QuickList.js +96 -0
  167. package/dist/esm/components/XAdkSender/QuickList.js.map +1 -0
  168. package/dist/esm/components/XAdkSender/index.d.ts +1 -6
  169. package/dist/esm/components/XAdkSender/index.js +476 -143
  170. package/dist/esm/components/XAdkSender/index.js.map +1 -1
  171. package/dist/esm/components/XAdkSender/styles.d.ts +19 -0
  172. package/dist/esm/components/XAdkSender/styles.js +34 -12
  173. package/dist/esm/components/XAdkSender/styles.js.map +1 -1
  174. package/dist/esm/components/XAiConversations/styles.js +3 -3
  175. package/dist/esm/components/XAiConversations/styles.js.map +1 -1
  176. package/dist/esm/hooks/useADKChat.js +8 -2
  177. package/dist/esm/hooks/useADKChat.js.map +1 -1
  178. package/dist/esm/index.d.ts +8 -3
  179. package/dist/esm/index.js +7 -4
  180. package/dist/esm/index.js.map +1 -1
  181. package/dist/esm/presets/base.d.ts +6 -0
  182. package/dist/esm/presets/base.js +28 -0
  183. package/dist/esm/presets/base.js.map +1 -0
  184. package/dist/esm/presets/define.d.ts +11 -0
  185. package/dist/esm/presets/define.js +33 -0
  186. package/dist/esm/presets/define.js.map +1 -0
  187. package/dist/esm/presets/index.d.ts +3 -0
  188. package/dist/esm/presets/index.js +4 -0
  189. package/dist/esm/presets/index.js.map +1 -0
  190. package/dist/esm/presets/runtime.d.ts +22 -0
  191. package/dist/esm/presets/runtime.js +45 -0
  192. package/dist/esm/presets/runtime.js.map +1 -0
  193. package/dist/esm/presets/xgroup/index.d.ts +5 -0
  194. package/dist/esm/presets/xgroup/index.js +6 -0
  195. package/dist/esm/presets/xgroup/index.js.map +1 -1
  196. package/dist/esm/presets/xgroup/knowledgeReference.d.ts +17 -0
  197. package/dist/esm/presets/xgroup/knowledgeReference.js +95 -0
  198. package/dist/esm/presets/xgroup/knowledgeReference.js.map +1 -0
  199. package/dist/esm/presets/xgroup/preset.d.ts +1 -13
  200. package/dist/esm/presets/xgroup/preset.js +9 -29
  201. package/dist/esm/presets/xgroup/preset.js.map +1 -1
  202. package/dist/esm/presets/xgroup/strategies.d.ts +5 -4
  203. package/dist/esm/presets/xgroup/strategies.js +8 -20
  204. package/dist/esm/presets/xgroup/strategies.js.map +1 -1
  205. package/dist/esm/presets/xgroup/webReference.d.ts +10 -0
  206. package/dist/esm/presets/xgroup/webReference.js +46 -0
  207. package/dist/esm/presets/xgroup/webReference.js.map +1 -0
  208. package/dist/esm/types/ChatStrategies.d.ts +11 -2
  209. package/dist/esm/types/ChatStrategies.js.map +1 -1
  210. package/dist/esm/types/FileGallery.d.ts +3 -0
  211. package/dist/esm/types/FileGallery.js.map +1 -1
  212. package/dist/esm/types/Sources.d.ts +30 -0
  213. package/dist/esm/types/Sources.js +2 -0
  214. package/dist/esm/types/Sources.js.map +1 -0
  215. package/dist/esm/types/XAdkChatbot.d.ts +33 -0
  216. package/dist/esm/types/XAdkChatbot.js.map +1 -1
  217. package/dist/esm/types/XAdkSender.d.ts +154 -8
  218. package/dist/esm/types/XAdkSender.js.map +1 -1
  219. package/dist/esm/types/index.d.ts +1 -0
  220. package/dist/esm/types/index.js +1 -0
  221. package/dist/esm/types/index.js.map +1 -1
  222. package/dist/esm/utils/index.d.ts +1 -0
  223. package/dist/esm/utils/index.js +1 -0
  224. package/dist/esm/utils/index.js.map +1 -1
  225. package/dist/esm/utils/markdownResource.d.ts +14 -0
  226. package/dist/esm/utils/markdownResource.js +101 -0
  227. package/dist/esm/utils/markdownResource.js.map +1 -0
  228. package/dist/umd/chat-sdk.min.js +1 -1
  229. package/package.json +6 -1
  230. package/dist/cjs/components/XAdkSender/Switch.d.ts +0 -16
  231. package/dist/cjs/components/XAdkSender/Switch.js +0 -95
  232. package/dist/cjs/components/XAdkSender/Switch.js.map +0 -7
  233. package/dist/esm/components/XAdkSender/Switch.d.ts +0 -16
  234. package/dist/esm/components/XAdkSender/Switch.js +0 -53
  235. package/dist/esm/components/XAdkSender/Switch.js.map +0 -1
@@ -0,0 +1,734 @@
1
+ import _createForOfIteratorHelper from "@babel/runtime/helpers/esm/createForOfIteratorHelper";
2
+ import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
3
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
4
+ import React, { forwardRef, useCallback, useEffect, useLayoutEffect, useImperativeHandle, useRef, useState } from "react";
5
+ import { createRoot } from "react-dom/client";
6
+ import { useStyles } from "./styles";
7
+ import { parseMarkdownResourceLinksAsParts } from "../../utils/markdownResource";
8
+ import { Fragment as _Fragment } from "react/jsx-runtime";
9
+ import { jsx as _jsx } from "react/jsx-runtime";
10
+ import { jsxs as _jsxs } from "react/jsx-runtime";
11
+ var MENTION_ATTR = "data-xadk-inline-mention-id";
12
+ // contenteditable 无法把光标放进 contenteditable=false 的 Mention 里,需用零宽字符承接“Mention 后方”的光标。
13
+ var CARET_TEXT = "\u200B";
14
+ var createTextNode = function createTextNode(text) {
15
+ return document.createTextNode(text);
16
+ };
17
+ var useIsomorphicLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
18
+ var normalizeText = function normalizeText(text) {
19
+ return text.replace(/\u200B/g, "").replace(/\u00a0/g, " ");
20
+ };
21
+ var getPlainLength = function getPlainLength(text) {
22
+ return normalizeText(text).length;
23
+ };
24
+ // DOM 文本里包含零宽光标锚点,快捷键替换和光标定位都要在“用户可见文本 offset”和 DOM raw offset 之间转换。
25
+ var toRawOffset = function toRawOffset(text, plainOffset) {
26
+ var current = 0;
27
+ for (var i = 0; i < text.length; i++) {
28
+ if (current >= plainOffset) return i;
29
+ if (text[i] !== CARET_TEXT) current += 1;
30
+ }
31
+ return text.length;
32
+ };
33
+
34
+ // 内联标签展示逻辑
35
+ var InlineTagInput = /*#__PURE__*/forwardRef(function (_ref, ref) {
36
+ var value = _ref.value,
37
+ mentions = _ref.mentions,
38
+ defaultInputParts = _ref.defaultInputParts,
39
+ placeholder = _ref.placeholder,
40
+ disabled = _ref.disabled,
41
+ onChange = _ref.onChange,
42
+ onMentionsChange = _ref.onMentionsChange,
43
+ onKeyDown = _ref.onKeyDown,
44
+ _onKeyUp = _ref.onKeyUp,
45
+ renderMention = _ref.renderMention;
46
+ var styles = useStyles();
47
+ var editorRef = useRef(null);
48
+ var latestMentionsRef = useRef(mentions);
49
+ var tagRootMapRef = useRef(new WeakMap());
50
+ var composingRef = useRef(false);
51
+ var lastInsertedCaretRef = useRef(null);
52
+ var savedRangeRef = useRef(null);
53
+ var defaultInputPartsAppliedRef = useRef(false);
54
+ var skipEmptyCleanupOnceRef = useRef(false);
55
+ var structuralCleanupFrameRef = useRef(null);
56
+ var _useState = useState(function () {
57
+ return Boolean(value || mentions.length);
58
+ }),
59
+ _useState2 = _slicedToArray(_useState, 2),
60
+ hasContent = _useState2[0],
61
+ setHasContent = _useState2[1];
62
+ var lastEmittedStateRef = useRef({
63
+ value: value,
64
+ mentionIds: mentions.map(function (mention) {
65
+ return mention.id;
66
+ }).join("|")
67
+ });
68
+ useEffect(function () {
69
+ latestMentionsRef.current = mentions;
70
+ }, [mentions]);
71
+ var getOrderedMentions = useCallback(function () {
72
+ var editor = editorRef.current;
73
+ if (!editor) return [];
74
+ var mentionMap = new Map(latestMentionsRef.current.map(function (mention) {
75
+ return [mention.id, mention];
76
+ }));
77
+ return Array.from(editor.querySelectorAll("[".concat(MENTION_ATTR, "]"))).map(function (node) {
78
+ return mentionMap.get(node.dataset.xadkInlineMentionId || "");
79
+ }).filter(Boolean);
80
+ }, []);
81
+
82
+ // 对外只暴露用户输入的纯文本,内部零宽锚点不进入 value。
83
+ var getPlainText = useCallback(function () {
84
+ var editor = editorRef.current;
85
+ if (!editor) return "";
86
+ var text = "";
87
+ editor.childNodes.forEach(function (node) {
88
+ if (node.nodeType === Node.TEXT_NODE) {
89
+ text += node.textContent || "";
90
+ }
91
+ });
92
+ return normalizeText(text);
93
+ }, []);
94
+
95
+ // 提交时需要保留文本与 Mention 的真实顺序;仅靠 value + mentions 无法区分 Mention 在句首、句中还是句尾。
96
+ var getParts = useCallback(function () {
97
+ var editor = editorRef.current;
98
+ if (!editor) return [];
99
+ var mentionMap = new Map(latestMentionsRef.current.map(function (mention) {
100
+ return [mention.id, mention];
101
+ }));
102
+ var parts = [];
103
+ editor.childNodes.forEach(function (node) {
104
+ if (node.nodeType === Node.TEXT_NODE) {
105
+ var text = normalizeText(node.textContent || "");
106
+ if (text) parts.push({
107
+ type: "text",
108
+ text: text
109
+ });
110
+ return;
111
+ }
112
+ if (node instanceof HTMLElement && node.hasAttribute(MENTION_ATTR)) {
113
+ var mentionId = node.dataset.xadkInlineMentionId || "";
114
+ var _mention = mentionMap.get(mentionId);
115
+ if (_mention) parts.push({
116
+ type: "mention",
117
+ mention: _mention
118
+ });
119
+ }
120
+ });
121
+ return parts;
122
+ }, []);
123
+ var emitChange = useCallback(function () {
124
+ var nextValue = getPlainText();
125
+ var nextMentions = getOrderedMentions();
126
+ setHasContent(Boolean(nextValue || nextMentions.length));
127
+ lastEmittedStateRef.current = {
128
+ value: nextValue,
129
+ mentionIds: nextMentions.map(function (mention) {
130
+ return mention.id;
131
+ }).join("|")
132
+ };
133
+ onChange(nextValue);
134
+ onMentionsChange(nextMentions);
135
+ }, [getOrderedMentions, getPlainText, onChange, onMentionsChange]);
136
+ var removeTextRange = useCallback(function (node, start, end) {
137
+ var text = node.textContent || "";
138
+ node.textContent = "".concat(text.slice(0, start)).concat(text.slice(end));
139
+ if (!node.textContent) node.remove();
140
+ }, []);
141
+ var removeMentionNode = useCallback(function (node) {
142
+ var _tagRootMapRef$curren;
143
+ var previous = node.previousSibling;
144
+ var next = node.nextSibling;
145
+ (_tagRootMapRef$curren = tagRootMapRef.current.get(node)) === null || _tagRootMapRef$curren === void 0 || _tagRootMapRef$curren.unmount();
146
+ node.remove();
147
+
148
+ // Mention 后会补一个不可见光标锚点;删除 Mention 时同步清理,避免留下冗余节点。
149
+ if ((next === null || next === void 0 ? void 0 : next.nodeType) === Node.TEXT_NODE) {
150
+ var _text$match;
151
+ var text = next.textContent || "";
152
+ var caretLength = ((_text$match = text.match(/^\u200B+/)) === null || _text$match === void 0 ? void 0 : _text$match[0].length) || 0;
153
+ if (caretLength > 0) {
154
+ removeTextRange(next, 0, caretLength);
155
+ return;
156
+ }
157
+ }
158
+ if ((previous === null || previous === void 0 ? void 0 : previous.nodeType) === Node.TEXT_NODE) {
159
+ var _text$match2;
160
+ var _text = previous.textContent || "";
161
+ var spaceLength = ((_text$match2 = _text.match(/\s+$/)) === null || _text$match2 === void 0 ? void 0 : _text$match2[0].length) || 0;
162
+ if (spaceLength > 0) {
163
+ removeTextRange(previous, _text.length - spaceLength, _text.length);
164
+ }
165
+ }
166
+ }, [removeTextRange]);
167
+ var removeMentionById = useCallback(function (id) {
168
+ var editor = editorRef.current;
169
+ var node = Array.from((editor === null || editor === void 0 ? void 0 : editor.querySelectorAll("[".concat(MENTION_ATTR, "]"))) || []).find(function (item) {
170
+ return item.dataset.xadkInlineMentionId === id;
171
+ });
172
+ if (node) {
173
+ removeMentionNode(node);
174
+ }
175
+ emitChange();
176
+ editor === null || editor === void 0 || editor.focus();
177
+ }, [emitChange, removeMentionNode]);
178
+
179
+ // Mention 节点本身不可编辑;删除入口通过 onRemove 回到组件内部统一维护 DOM 与 mentions。
180
+ var buildMentionNode = useCallback(function (mention) {
181
+ var span = document.createElement("span");
182
+ span.setAttribute("contenteditable", "false");
183
+ span.setAttribute(MENTION_ATTR, mention.id);
184
+ span.dataset.xadkInlineMentionId = mention.id;
185
+ span.dataset.xadkInlineMentionType = mention.type;
186
+ span.className = styles.inlineTag;
187
+ if (renderMention) {
188
+ var root = createRoot(span);
189
+ tagRootMapRef.current.set(span, root);
190
+ root.render( /*#__PURE__*/_jsx(_Fragment, {
191
+ children: renderMention(mention, {
192
+ onRemove: function onRemove() {
193
+ return removeMentionById(mention.id);
194
+ }
195
+ })
196
+ }));
197
+ } else {
198
+ var label = document.createElement("span");
199
+ label.className = "xadk-inline-tag-label";
200
+ label.textContent = mention.displayName || mention.label;
201
+ var close = document.createElement("span");
202
+ close.className = "xadk-inline-tag-close";
203
+ close.innerHTML = "×";
204
+ close.onclick = function (event) {
205
+ event.preventDefault();
206
+ event.stopPropagation();
207
+ removeMentionById(mention.id);
208
+ };
209
+ span.append(label, close);
210
+ }
211
+ return span;
212
+ }, [removeMentionById, renderMention, styles.inlineTag]);
213
+ var renderPartsToEditor = useCallback(function (parts) {
214
+ var editor = editorRef.current;
215
+ if (!editor) return;
216
+ editor.querySelectorAll("[".concat(MENTION_ATTR, "]")).forEach(function (node) {
217
+ var _tagRootMapRef$curren2;
218
+ (_tagRootMapRef$curren2 = tagRootMapRef.current.get(node)) === null || _tagRootMapRef$curren2 === void 0 || _tagRootMapRef$curren2.unmount();
219
+ });
220
+ editor.innerHTML = "";
221
+ parts.forEach(function (part) {
222
+ if (part.type === "text") {
223
+ if (part.text) editor.appendChild(createTextNode(part.text));
224
+ return;
225
+ }
226
+ var mention = part.type === "mention" ? part.mention : part.tag;
227
+ editor.append(buildMentionNode(mention), createTextNode(CARET_TEXT));
228
+ });
229
+ }, [buildMentionNode]);
230
+ var setCursorAtTextEnd = useCallback(function (node) {
231
+ var _node$textContent;
232
+ var range = document.createRange();
233
+ var selection = window.getSelection();
234
+ range.setStart(node, ((_node$textContent = node.textContent) === null || _node$textContent === void 0 ? void 0 : _node$textContent.length) || 0);
235
+ range.collapse(true);
236
+ selection === null || selection === void 0 || selection.removeAllRanges();
237
+ selection === null || selection === void 0 || selection.addRange(range);
238
+ savedRangeRef.current = range.cloneRange();
239
+ }, []);
240
+ var saveSelectionRange = useCallback(function () {
241
+ var editor = editorRef.current;
242
+ var selection = window.getSelection();
243
+ if (!editor || !selection || selection.rangeCount === 0) return;
244
+ var range = selection.getRangeAt(0);
245
+ if (!editor.contains(range.startContainer) || !editor.contains(range.endContainer)) {
246
+ return;
247
+ }
248
+ savedRangeRef.current = range.cloneRange();
249
+ }, []);
250
+ var restoreCursorAfterInsert = useCallback(function (node) {
251
+ var editor = editorRef.current;
252
+ if (!editor || !editor.contains(node)) return;
253
+ editor.focus();
254
+ setCursorAtTextEnd(node);
255
+ }, [setCursorAtTextEnd]);
256
+ var isMentionNode = function isMentionNode(node) {
257
+ return node instanceof HTMLElement && node.hasAttribute(MENTION_ATTR);
258
+ };
259
+ var isOnlyCaretText = function isOnlyCaretText(text) {
260
+ return normalizeText(text) === "";
261
+ };
262
+
263
+ // Backspace/Delete 需要跨过零宽锚点识别相邻 Mention,不能只看光标所在文本节点。
264
+ var getMentionBeforeRange = function getMentionBeforeRange(range) {
265
+ var container = range.startContainer;
266
+ if (container.nodeType === Node.TEXT_NODE) {
267
+ var text = container.textContent || "";
268
+ var beforeCursor = text.slice(0, range.startOffset);
269
+ if (isOnlyCaretText(beforeCursor) && isMentionNode(container.previousSibling)) {
270
+ return container.previousSibling;
271
+ }
272
+ }
273
+ if (container instanceof HTMLElement) {
274
+ var previous = container.childNodes[range.startOffset - 1];
275
+ if (isMentionNode(previous)) return previous;
276
+ if ((previous === null || previous === void 0 ? void 0 : previous.nodeType) === Node.TEXT_NODE && isOnlyCaretText(previous.textContent || "") && isMentionNode(previous.previousSibling)) {
277
+ return previous.previousSibling;
278
+ }
279
+ }
280
+ return null;
281
+ };
282
+ var getMentionAfterRange = function getMentionAfterRange(range) {
283
+ var container = range.startContainer;
284
+ if (container.nodeType === Node.TEXT_NODE) {
285
+ var text = container.textContent || "";
286
+ var afterCursor = text.slice(range.startOffset);
287
+ if (isOnlyCaretText(afterCursor) && isMentionNode(container.nextSibling)) {
288
+ return container.nextSibling;
289
+ }
290
+ }
291
+ if (container instanceof HTMLElement) {
292
+ var next = container.childNodes[range.startOffset];
293
+ if (isMentionNode(next)) return next;
294
+ if ((next === null || next === void 0 ? void 0 : next.nodeType) === Node.TEXT_NODE && isOnlyCaretText(next.textContent || "") && isMentionNode(next.nextSibling)) {
295
+ return next.nextSibling;
296
+ }
297
+ }
298
+ return null;
299
+ };
300
+ var moveCursorAroundMention = useCallback(function (mention, direction) {
301
+ var editor = editorRef.current;
302
+ var selection = window.getSelection();
303
+ if (!editor || !selection || !editor.contains(mention)) return;
304
+ var range = document.createRange();
305
+ if (direction === "before") {
306
+ var previous = mention.previousSibling;
307
+ if ((previous === null || previous === void 0 ? void 0 : previous.nodeType) === Node.TEXT_NODE) {
308
+ var _previous$textContent;
309
+ range.setStart(previous, ((_previous$textContent = previous.textContent) === null || _previous$textContent === void 0 ? void 0 : _previous$textContent.length) || 0);
310
+ } else {
311
+ range.setStartBefore(mention);
312
+ }
313
+ } else {
314
+ var next = mention.nextSibling;
315
+ if ((next === null || next === void 0 ? void 0 : next.nodeType) === Node.TEXT_NODE) {
316
+ var _match;
317
+ var leadingCaretLength = ((_match = (next.textContent || "").match(/^\u200B+/)) === null || _match === void 0 ? void 0 : _match[0].length) || 0;
318
+ range.setStart(next, leadingCaretLength);
319
+ } else {
320
+ range.setStartAfter(mention);
321
+ }
322
+ }
323
+ range.collapse(true);
324
+ selection.removeAllRanges();
325
+ selection.addRange(range);
326
+ savedRangeRef.current = range.cloneRange();
327
+ }, []);
328
+
329
+ // 读取光标在纯文本中的位置,供快捷键搜索词和 Mention 插入位置复用。
330
+ var getOffsetInEditor = useCallback(function () {
331
+ var editor = editorRef.current;
332
+ var selection = window.getSelection();
333
+ if (!editor || !selection || selection.rangeCount === 0) return 0;
334
+ var range = selection.getRangeAt(0);
335
+ var offset = 0;
336
+ var found = false;
337
+ var visit = function visit(node) {
338
+ if (found) return;
339
+ if (node === range.startContainer) {
340
+ if (node.nodeType === Node.TEXT_NODE) {
341
+ offset += getPlainLength((node.textContent || "").slice(0, range.startOffset));
342
+ }
343
+ found = true;
344
+ return;
345
+ }
346
+ if (node instanceof HTMLElement && node.hasAttribute(MENTION_ATTR)) return;
347
+ if (node.nodeType === Node.TEXT_NODE) {
348
+ offset += getPlainLength(node.textContent || "");
349
+ return;
350
+ }
351
+ node.childNodes.forEach(visit);
352
+ };
353
+ editor.childNodes.forEach(visit);
354
+ return offset;
355
+ }, []);
356
+ var getNodeIndex = function getNodeIndex(node) {
357
+ var index = 0;
358
+ var current = node;
359
+ while (current.previousSibling) {
360
+ index += 1;
361
+ current = current.previousSibling;
362
+ }
363
+ return index;
364
+ };
365
+
366
+ // 删除快捷键触发片段,例如把 “@文档” 替换成一个结构化 Mention,并返回删除位置对应的真实 DOM Range。
367
+ // 注意:纯文本 offset 不包含 Mention,Mention 前后可能都是 offset 0;插入 Mention 必须依赖真实 Range,不能再反推 offset。
368
+ var replaceTextRange = useCallback(function (start, end) {
369
+ var editor = editorRef.current;
370
+ if (!editor) return null;
371
+ var offset = 0;
372
+ var insertRange = null;
373
+ var nodes = Array.from(editor.childNodes);
374
+ nodes.forEach(function (node) {
375
+ if (node.nodeType !== Node.TEXT_NODE) return;
376
+ var text = node.textContent || "";
377
+ var nodeStart = offset;
378
+ var plainLength = getPlainLength(text);
379
+ var nodeEnd = offset + plainLength;
380
+ offset = nodeEnd;
381
+ if (nodeEnd <= start || nodeStart >= end) return;
382
+ var rawStart = toRawOffset(text, Math.max(0, start - nodeStart));
383
+ var rawEnd = toRawOffset(text, Math.max(0, end - nodeStart));
384
+ var keepLeft = text.slice(0, rawStart);
385
+ var keepRight = text.slice(rawEnd);
386
+ var parent = node.parentNode;
387
+ var nodeIndex = getNodeIndex(node);
388
+ node.textContent = "".concat(keepLeft).concat(keepRight);
389
+ if (!insertRange) {
390
+ insertRange = document.createRange();
391
+ if (node.textContent) {
392
+ insertRange.setStart(node, rawStart);
393
+ } else if (parent) {
394
+ insertRange.setStart(parent, nodeIndex);
395
+ }
396
+ insertRange.collapse(true);
397
+ }
398
+ if (!node.textContent) node.remove();
399
+ });
400
+ return insertRange;
401
+ }, []);
402
+
403
+ // 浏览器拆分 Range 后可能留下空文本节点;清理后才能保证后续 Mention 继续 append 在队尾。
404
+ var cleanupCaretTextNodes = useCallback(function () {
405
+ var editor = editorRef.current;
406
+ if (!editor) return;
407
+ Array.from(editor.childNodes).forEach(function (node) {
408
+ if (node.nodeType !== Node.TEXT_NODE) return;
409
+ var text = node.textContent || "";
410
+ if (!text) {
411
+ node.remove();
412
+ return;
413
+ }
414
+ if (text && normalizeText(text) === "") {
415
+ node.textContent = CARET_TEXT;
416
+ }
417
+ });
418
+ }, []);
419
+
420
+ // Chrome 会把标签前临时输入的文字包进块级节点;文字被删空后,可能留下
421
+ // <div><br></div>。它没有消息语义,却会在 contenteditable 中占据一整行。
422
+ var cleanupEmptyStructuralNodes = useCallback(function () {
423
+ var editor = editorRef.current;
424
+ var selection = window.getSelection();
425
+ if (!editor) return;
426
+ Array.from(editor.children).forEach(function (node) {
427
+ if (node.hasAttribute(MENTION_ATTR)) return;
428
+ if (node.querySelector("[".concat(MENTION_ATTR, "]"))) return;
429
+ if (normalizeText(node.textContent || "")) return;
430
+ var range = selection !== null && selection !== void 0 && selection.rangeCount ? selection.getRangeAt(0) : null;
431
+ var nodeIndex = getNodeIndex(node);
432
+ var containsCursor = Boolean(range && range.collapsed && (range.startContainer === node || node.contains(range.startContainer) || range.startContainer === editor && (range.startOffset === nodeIndex || range.startOffset === nodeIndex + 1)));
433
+ if (containsCursor && selection) {
434
+ // 光标紧邻 contenteditable=false 的 Mention 时,单纯删除 <br> 会让 Chrome
435
+ // 再次生成它。替换成零宽文本锚点,既能承接光标,也不会增加行高。
436
+ var caretNode = createTextNode(CARET_TEXT);
437
+ node.replaceWith(caretNode);
438
+ var nextRange = document.createRange();
439
+ nextRange.setStart(caretNode, CARET_TEXT.length);
440
+ nextRange.collapse(true);
441
+ selection.removeAllRanges();
442
+ selection.addRange(nextRange);
443
+ savedRangeRef.current = nextRange.cloneRange();
444
+ return;
445
+ }
446
+ node.remove();
447
+ });
448
+ }, []);
449
+ useEffect(function () {
450
+ var editor = editorRef.current;
451
+ if (!editor) return;
452
+
453
+ // 某些业务容器会截断 React 委托事件;直接监听编辑器的原生 input,确保删除事务结束后
454
+ // 仍能清理 Chrome 在不可编辑 Mention 前生成的占行 <br>。仅处理 delete*,不影响 Enter 换行。
455
+ var handleNativeDelete = function handleNativeDelete(event) {
456
+ if (!(event instanceof InputEvent)) return;
457
+ if (!event.inputType.startsWith("delete")) return;
458
+ if (structuralCleanupFrameRef.current !== null) {
459
+ window.cancelAnimationFrame(structuralCleanupFrameRef.current);
460
+ }
461
+ structuralCleanupFrameRef.current = window.requestAnimationFrame(function () {
462
+ structuralCleanupFrameRef.current = null;
463
+ cleanupEmptyStructuralNodes();
464
+ cleanupCaretTextNodes();
465
+ });
466
+ };
467
+ editor.addEventListener("input", handleNativeDelete);
468
+ return function () {
469
+ return editor.removeEventListener("input", handleNativeDelete);
470
+ };
471
+ }, [cleanupCaretTextNodes, cleanupEmptyStructuralNodes]);
472
+ var insertMention = useCallback(function (mention, replace) {
473
+ var editor = editorRef.current;
474
+ if (!editor) return;
475
+ // 工具栏/弹窗会先抢走焦点;必须在 focus 之前保存当前 Selection,
476
+ // 否则浏览器新建在输入框开头的 Range 会覆盖最后一次真实光标位置。
477
+ var selectionBeforeFocus = window.getSelection();
478
+ var activeRangeBeforeFocus = selectionBeforeFocus !== null && selectionBeforeFocus !== void 0 && selectionBeforeFocus.rangeCount && editor.contains(selectionBeforeFocus.getRangeAt(0).startContainer) ? selectionBeforeFocus.getRangeAt(0).cloneRange() : null;
479
+ var savedRangeBeforeFocus = savedRangeRef.current && editor.contains(savedRangeRef.current.startContainer) ? savedRangeRef.current.cloneRange() : null;
480
+ var rangeBeforeFocus = activeRangeBeforeFocus || savedRangeBeforeFocus;
481
+ editor.focus();
482
+ latestMentionsRef.current = [].concat(_toConsumableArray(latestMentionsRef.current.filter(function (item) {
483
+ return item.id !== mention.id;
484
+ })), [mention]);
485
+ var insertRange = null;
486
+ if (replace) {
487
+ insertRange = replaceTextRange(replace.start, replace.end);
488
+ cleanupCaretTextNodes();
489
+ }
490
+ // 浏览器会在空 contenteditable 中生成 <div><br> 等占位块。
491
+ // 空编辑器插入首个 Mention 前先清掉这些无语义节点,避免标签被放进第二个视觉行。
492
+ var isSemanticallyEmpty = !getPlainText() && !editor.querySelector("[".concat(MENTION_ATTR, "]"));
493
+ if (isSemanticallyEmpty) {
494
+ editor.innerHTML = "";
495
+ savedRangeRef.current = null;
496
+ insertRange = null;
497
+ }
498
+ var mentionNode = buildMentionNode(mention);
499
+ var caretNode = createTextNode(CARET_TEXT);
500
+ var range = insertRange || rangeBeforeFocus;
501
+ if (range && editor.contains(range.startContainer)) {
502
+ // 用 DocumentFragment 一次性插入,避免连续 insertNode 导致 mention/caret 顺序被浏览器 Range 状态打乱。
503
+ var fragment = document.createDocumentFragment();
504
+ fragment.append(mentionNode, caretNode);
505
+ range.insertNode(fragment);
506
+ } else {
507
+ editor.append(mentionNode, caretNode);
508
+ }
509
+ cleanupCaretTextNodes();
510
+ lastInsertedCaretRef.current = caretNode;
511
+ setCursorAtTextEnd(caretNode);
512
+ emitChange();
513
+
514
+ // 关闭快捷列表和父组件同步 mentions/value 会触发一次 React 更新;
515
+ // 下一帧再恢复到刚插入 Mention 后的零宽锚点,避免光标被 focus 或重渲染带回旧位置。
516
+ window.requestAnimationFrame(function () {
517
+ if (lastInsertedCaretRef.current === caretNode) {
518
+ restoreCursorAfterInsert(caretNode);
519
+ }
520
+ });
521
+ }, [buildMentionNode, cleanupCaretTextNodes, emitChange, getPlainText, replaceTextRange, restoreCursorAfterInsert, setCursorAtTextEnd]);
522
+ useEffect(function () {
523
+ document.addEventListener("selectionchange", saveSelectionRange);
524
+ return function () {
525
+ document.removeEventListener("selectionchange", saveSelectionRange);
526
+ };
527
+ }, [saveSelectionRange]);
528
+ useEffect(function () {
529
+ return function () {
530
+ if (structuralCleanupFrameRef.current !== null) {
531
+ window.cancelAnimationFrame(structuralCleanupFrameRef.current);
532
+ }
533
+ };
534
+ }, []);
535
+ useImperativeHandle(ref, function () {
536
+ return {
537
+ focus: function focus() {
538
+ var _editorRef$current;
539
+ return (_editorRef$current = editorRef.current) === null || _editorRef$current === void 0 ? void 0 : _editorRef$current.focus();
540
+ },
541
+ getText: getPlainText,
542
+ getParts: getParts,
543
+ getCursorOffset: getOffsetInEditor,
544
+ insertMention: insertMention,
545
+ insertTag: insertMention
546
+ };
547
+ }, [getOffsetInEditor, getParts, getPlainText, insertMention]);
548
+ useIsomorphicLayoutEffect(function () {
549
+ var editor = editorRef.current;
550
+ if (!editor) return;
551
+
552
+ // 默认片段只在空输入首次挂载时灌入,避免外部重新渲染覆盖用户正在编辑的内容。
553
+ if (!defaultInputPartsAppliedRef.current && defaultInputParts !== null && defaultInputParts !== void 0 && defaultInputParts.length && !value && mentions.length === 0) {
554
+ defaultInputPartsAppliedRef.current = true;
555
+ // emitChange 的受控回写要到下一次 render 才生效;跳过本轮紧随其后的空值清理,
556
+ // 避免刚渲染的默认 Mention 被旧的空 value/mentions 立即移除。
557
+ skipEmptyCleanupOnceRef.current = true;
558
+ renderPartsToEditor(defaultInputParts);
559
+ emitChange();
560
+ return;
561
+ }
562
+ var incomingMentionIds = mentions.map(function (mention) {
563
+ return mention.id;
564
+ }).join("|");
565
+ var lastEmittedState = lastEmittedStateRef.current;
566
+ var isInternalControlledEcho = value === lastEmittedState.value && incomingMentionIds === lastEmittedState.mentionIds;
567
+ if (isInternalControlledEcho && editor.childNodes.length > 0) return;
568
+ renderPartsToEditor([].concat(_toConsumableArray(value ? [{
569
+ type: "text",
570
+ text: value
571
+ }] : []), _toConsumableArray(mentions.map(function (mention) {
572
+ return {
573
+ type: "mention",
574
+ mention: mention
575
+ };
576
+ }))));
577
+ setHasContent(Boolean(value || mentions.length));
578
+
579
+ // 外部主动写入 value/mentions 后,需要在首帧绘制前同步 DOM;若输入区已有焦点,则把光标放在内容末尾。
580
+ var lastTextNode = Array.from(editor.childNodes).reverse().find(function (node) {
581
+ return node.nodeType === Node.TEXT_NODE;
582
+ });
583
+ if (document.activeElement === editor && lastTextNode) {
584
+ setCursorAtTextEnd(lastTextNode);
585
+ }
586
+ }, [defaultInputParts, emitChange, renderPartsToEditor, setCursorAtTextEnd, mentions, value]);
587
+ useIsomorphicLayoutEffect(function () {
588
+ var editor = editorRef.current;
589
+ if (!editor) return;
590
+ if (skipEmptyCleanupOnceRef.current) {
591
+ skipEmptyCleanupOnceRef.current = false;
592
+ return;
593
+ }
594
+ if (!value && mentions.length === 0 && editor.childNodes.length > 0) {
595
+ editor.querySelectorAll("[".concat(MENTION_ATTR, "]")).forEach(function (node) {
596
+ var _tagRootMapRef$curren3;
597
+ (_tagRootMapRef$curren3 = tagRootMapRef.current.get(node)) === null || _tagRootMapRef$curren3 === void 0 || _tagRootMapRef$curren3.unmount();
598
+ });
599
+ editor.innerHTML = "";
600
+ }
601
+ }, [mentions.length, value]);
602
+ var handleInput = function handleInput() {
603
+ if (!composingRef.current) {
604
+ cleanupEmptyStructuralNodes();
605
+ cleanupCaretTextNodes();
606
+ emitChange();
607
+
608
+ // Chrome 可能在 input 回调返回后才补上用于承接光标的 <br>;下一帧再归一化一次。
609
+ if (structuralCleanupFrameRef.current !== null) {
610
+ window.cancelAnimationFrame(structuralCleanupFrameRef.current);
611
+ }
612
+ structuralCleanupFrameRef.current = window.requestAnimationFrame(function () {
613
+ structuralCleanupFrameRef.current = null;
614
+ cleanupEmptyStructuralNodes();
615
+ cleanupCaretTextNodes();
616
+ });
617
+ }
618
+ };
619
+ var handlePaste = function handlePaste(event) {
620
+ event.preventDefault();
621
+ var editor = editorRef.current;
622
+ if (!editor) return;
623
+
624
+ // 始终按 text/plain 粘贴,避免消息气泡的背景色等 HTML 样式进入 contenteditable。
625
+ var text = event.clipboardData.getData("text/plain");
626
+ if (!text) return;
627
+ var parts = parseMarkdownResourceLinksAsParts(text);
628
+ var selection = window.getSelection();
629
+ var range = selection !== null && selection !== void 0 && selection.rangeCount && editor.contains(selection.getRangeAt(0).startContainer) ? selection.getRangeAt(0) : null;
630
+ var fragment = document.createDocumentFragment();
631
+ var lastTextNode = null;
632
+ var _iterator = _createForOfIteratorHelper(parts),
633
+ _step;
634
+ try {
635
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
636
+ var part = _step.value;
637
+ if (part.type === "text") {
638
+ lastTextNode = createTextNode(part.text);
639
+ fragment.append(lastTextNode);
640
+ continue;
641
+ }
642
+ latestMentionsRef.current = [].concat(_toConsumableArray(latestMentionsRef.current), [part.mention]);
643
+ fragment.append(buildMentionNode(part.mention));
644
+ lastTextNode = createTextNode(CARET_TEXT);
645
+ fragment.append(lastTextNode);
646
+ }
647
+ } catch (err) {
648
+ _iterator.e(err);
649
+ } finally {
650
+ _iterator.f();
651
+ }
652
+ if (range) {
653
+ range.deleteContents();
654
+ range.insertNode(fragment);
655
+ } else {
656
+ editor.append(fragment);
657
+ }
658
+ cleanupCaretTextNodes();
659
+ if (lastTextNode) setCursorAtTextEnd(lastTextNode);
660
+ emitChange();
661
+ };
662
+ var handleKeyDown = function handleKeyDown(event) {
663
+ if (event.key === "ArrowLeft" || event.key === "ArrowRight") {
664
+ var selection = window.getSelection();
665
+ if (selection !== null && selection !== void 0 && selection.rangeCount) {
666
+ var range = selection.getRangeAt(0);
667
+ if (range.collapsed) {
668
+ var targetMention = event.key === "ArrowLeft" ? getMentionBeforeRange(range) : getMentionAfterRange(range);
669
+ if (targetMention) {
670
+ event.preventDefault();
671
+ moveCursorAroundMention(targetMention, event.key === "ArrowLeft" ? "before" : "after");
672
+ return;
673
+ }
674
+ }
675
+ }
676
+ }
677
+ if (event.key === "Backspace" || event.key === "Delete") {
678
+ var _selection = window.getSelection();
679
+ if (_selection !== null && _selection !== void 0 && _selection.rangeCount) {
680
+ var _range = _selection.getRangeAt(0);
681
+ if (_range.collapsed) {
682
+ var _targetMention = event.key === "Backspace" ? getMentionBeforeRange(_range) : getMentionAfterRange(_range);
683
+ if (_targetMention) {
684
+ event.preventDefault();
685
+ removeMentionById(_targetMention.dataset.xadkInlineMentionId || "");
686
+ return;
687
+ }
688
+ }
689
+ }
690
+ }
691
+ onKeyDown === null || onKeyDown === void 0 || onKeyDown(event);
692
+ };
693
+
694
+ // placeholder 只由受控 value/mentions 派生,避免从 contenteditable DOM 读取导致外部插入 Mention 后状态滞后一帧。
695
+ var showPlaceholder = !hasContent;
696
+ return /*#__PURE__*/_jsxs("div", {
697
+ className: styles.inlineInputWrapper,
698
+ children: [showPlaceholder && placeholder && /*#__PURE__*/_jsx("div", {
699
+ className: styles.inlinePlaceholder,
700
+ children: placeholder
701
+ }), /*#__PURE__*/_jsx("div", {
702
+ ref: editorRef,
703
+ className: styles.inlineInput,
704
+ contentEditable: !disabled,
705
+ suppressContentEditableWarning: true,
706
+ role: "textbox",
707
+ "aria-multiline": "true",
708
+ onInput: handleInput,
709
+ onPaste: handlePaste,
710
+ onKeyDown: handleKeyDown,
711
+ onKeyUp: function onKeyUp(event) {
712
+ cleanupEmptyStructuralNodes();
713
+ cleanupCaretTextNodes();
714
+ saveSelectionRange();
715
+ _onKeyUp === null || _onKeyUp === void 0 || _onKeyUp(event);
716
+ },
717
+ onMouseUp: saveSelectionRange,
718
+ onFocus: saveSelectionRange,
719
+ onCompositionStart: function onCompositionStart() {
720
+ composingRef.current = true;
721
+ // 中文 IME 在 compositionend 前不会触发受控 value 更新;候选输入一出现就应隐藏 placeholder。
722
+ setHasContent(true);
723
+ },
724
+ onCompositionEnd: function onCompositionEnd() {
725
+ composingRef.current = false;
726
+ emitChange();
727
+ },
728
+ "data-cursor-offset": getOffsetInEditor()
729
+ })]
730
+ });
731
+ });
732
+ InlineTagInput.displayName = "InlineTagInput";
733
+ export default InlineTagInput;
734
+ //# sourceMappingURL=InlineTagInput.js.map